/*
 2020 CN-Consult GmbH
 @author Patrick Hausmann <patrick.hausmann@cn-consult.eu>
 2020 CN-Consult GmbH
 @author Nils Dehl <nils.dehl@dkd.de>
 2013 CN-Consult GmbH
 @author Jan-Victor Krille <jan-victor.krille@cn-consult.eu>
 2013 CN-Consult GmbH
 @author Daniel Haas <daniel.haas@cn-consult.eu>
 2018 CN-Consult GmbH
 @author Marcel Bohländer <marcel.bohlaender@cn-consult.eu>
 2018 CN-Consult GmbH
 @author Nils Dehl <nils.dehl@dkd.de>
 2019 CN-Consult GmbH
 @author Nils Dehl <nils.dehl@dkd.de>
 2014 CN-Consult GmbH
 @author Marcel Bohländer <marcel.bohlaender@cn-consult.eu>
 2021 CN-Consult GmbH
 @author Sebastian Alkemade <sa@linetco.com>
 2018 CN-Consult GmbH
 @author Daniel Haas <daniel.haas@cn-consult.eu>
 2016 CN-Consult GmbH
 @author Marcel Bohländer <marcel.bohlaender@cn-consult.eu>
 2019 CN-Consult GmbH
 @author Marcel Bohländer <marcel.bohlaender@cn-consult.eu>
 2023 CN-Consult GmbH
 @author Tim Schreindl <tim.schreindl@cn-consult.eu>
 2022 CN-Consult GmbH
 @author Nils Dehl <nils.dehl@dkd.de>
 2021 CN-Consult GmbH
 @author Dominik Helsper <dh@linetco.com>
 2021 CN-Consult GmbH
 @author Marouane Ferjani <marouane.ferjani@cn-consult.eu>
 2020 CN-Consult GmbH
 @author Nils Dehl
 2017 CN-Consult GmbH
 @author Marcel Bohländer <marcel.bohlaender@cn-consult.eu>
 2020 CN-Consult GmbH
 @author Marcel Bohländer <marcel.bohlaender@cn-consult.eu>
 2018 CN-Consult GmbH
 @author Nils Leistner <nils.leistner@cn-consult.eu>
 2018 CN-Consult GmbH
 @author Nils Leistner <nils.Leistner@cn-consult.eu>
 2018 CN-Consult GmbH
 @author Nils Leistner <nils.leistner@cn-consult.eu>, Pascal Stiemer <pascal.stiemer@cn-consult.eu>
 2022 CN-Consult GmbH
 @author Tim Schreindl <tim.schreindl@cn-consult.eu>
 2013 CN-Consult GmbH
 @author Marcel Bohländer <marcel.bohlaender@cn-consult.eu>
 2020 CN-Consult GmbH
 @author Nils Leistner <nils.leistner@cn-consult.eu>
 2020 CN-Consult GmbH
 @author Marouane Ferjani <marouane.ferjani@cn-consult.eu>
 2021 CN-Consult GmbH
 @author Tim Schreindl <tim.schreindl@cn-consult.eu>
 2024 CN-Consult GmbH
 @author Tim Schreindl <tim.schreindl@cn-consult.eu>
 2025 cn-mobility GmbH
 @author Tim Schreindl <tim.schreindl@cn-mobility.eu>
 2022 CN-Consult GmbH
 @author Nils Leistner <nils.leistner@cn-consult.eu>
 2024 cn-mobility GmbH
 @author Nils Leistner <nils.leistner@cn-mobility.eu>
 2024 cn-mobility GmbH
 @author Tim Schreindl <tim.schreindl@cn-mobility.eu>
 2022 CN-Consult GmbH
 @author Nils Leistner <nils.Leistner@cn-consult.eu>
*/
var $jscomp = $jscomp || {};
$jscomp.scope = {};
$jscomp.ASSUME_ES5 = false;
$jscomp.ASSUME_NO_NATIVE_MAP = false;
$jscomp.ASSUME_NO_NATIVE_SET = false;
$jscomp.defineProperty = $jscomp.ASSUME_ES5 || typeof Object.defineProperties == 'function' ? Object.defineProperty : function(target, property, descriptor) {
  descriptor = descriptor;
  if (target == Array.prototype || target == Object.prototype) {
    return;
  }
  target[property] = descriptor.value;
};
$jscomp.getGlobal = function(maybeGlobal) {
  return typeof window != 'undefined' && window === maybeGlobal ? maybeGlobal : typeof global != 'undefined' && global != null ? global : maybeGlobal;
};
$jscomp.global = $jscomp.getGlobal(this);
$jscomp.polyfill = function(target, polyfill, fromLang, toLang) {
  if (!polyfill) {
    return;
  }
  var obj = $jscomp.global;
  var split = target.split('.');
  for (var i = 0; i < split.length - 1; i++) {
    var key = split[i];
    if (!(key in obj)) {
      obj[key] = {};
    }
    obj = obj[key];
  }
  var property = split[split.length - 1];
  var orig = obj[property];
  var impl = polyfill(orig);
  if (impl == orig || impl == null) {
    return;
  }
  $jscomp.defineProperty(obj, property, {configurable:true, writable:true, value:impl});
};
$jscomp.polyfill('Array.prototype.copyWithin', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(target, start, opt_end) {
    var len = this.length;
    target = Number(target);
    start = Number(start);
    opt_end = Number(opt_end != null ? opt_end : len);
    if (target < start) {
      opt_end = Math.min(opt_end, len);
      while (start < opt_end) {
        if (start in this) {
          this[target++] = this[start++];
        } else {
          delete this[target++];
          start++;
        }
      }
    } else {
      opt_end = Math.min(opt_end, len + start - target);
      target += opt_end - start;
      while (opt_end > start) {
        if (--opt_end in this) {
          this[--target] = this[opt_end];
        } else {
          delete this[target];
        }
      }
    }
    return this;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.SYMBOL_PREFIX = 'jscomp_symbol_';
$jscomp.initSymbol = function() {
  $jscomp.initSymbol = function() {
  };
  if (!$jscomp.global['Symbol']) {
    $jscomp.global['Symbol'] = $jscomp.Symbol;
  }
};
$jscomp.Symbol = function() {
  var counter = 0;
  function Symbol(opt_description) {
    return $jscomp.SYMBOL_PREFIX + (opt_description || '') + counter++;
  }
  return Symbol;
}();
$jscomp.initSymbolIterator = function() {
  $jscomp.initSymbol();
  var symbolIterator = $jscomp.global['Symbol'].iterator;
  if (!symbolIterator) {
    symbolIterator = $jscomp.global['Symbol'].iterator = $jscomp.global['Symbol']('iterator');
  }
  if (typeof Array.prototype[symbolIterator] != 'function') {
    $jscomp.defineProperty(Array.prototype, symbolIterator, {configurable:true, writable:true, value:function() {
      return $jscomp.arrayIterator(this);
    }});
  }
  $jscomp.initSymbolIterator = function() {
  };
};
$jscomp.arrayIterator = function(array) {
  var index = 0;
  return $jscomp.iteratorPrototype(function() {
    if (index < array.length) {
      return {done:false, value:array[index++]};
    } else {
      return {done:true};
    }
  });
};
$jscomp.iteratorPrototype = function(next) {
  $jscomp.initSymbolIterator();
  var iterator = {next:next};
  iterator[$jscomp.global['Symbol'].iterator] = function() {
    return this;
  };
  return iterator;
};
$jscomp.iteratorFromArray = function(array, transform) {
  $jscomp.initSymbolIterator();
  if (array instanceof String) {
    array = array + '';
  }
  var i = 0;
  var iter = {next:function() {
    if (i < array.length) {
      var index = i++;
      return {value:transform(index, array[index]), done:false};
    }
    iter.next = function() {
      return {done:true, value:void 0};
    };
    return iter.next();
  }};
  $jscomp.initSymbol();
  $jscomp.initSymbolIterator();
  iter[Symbol.iterator] = function() {
    return iter;
  };
  return iter;
};
$jscomp.polyfill('Array.prototype.entries', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function() {
    return $jscomp.iteratorFromArray(this, function(i, v) {
      return [i, v];
    });
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Array.prototype.fill', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(value, opt_start, opt_end) {
    var length = this.length || 0;
    if (opt_start < 0) {
      opt_start = Math.max(0, length + opt_start);
    }
    if (opt_end == null || opt_end > length) {
      opt_end = length;
    }
    opt_end = Number(opt_end);
    if (opt_end < 0) {
      opt_end = Math.max(0, length + opt_end);
    }
    for (var i = Number(opt_start || 0); i < opt_end; i++) {
      this[i] = value;
    }
    return this;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.findInternal = function(array, callback, thisArg) {
  if (array instanceof String) {
    array = String(array);
  }
  var len = array.length;
  for (var i = 0; i < len; i++) {
    var value = array[i];
    if (callback.call(thisArg, value, i, array)) {
      return {i:i, v:value};
    }
  }
  return {i:-1, v:void 0};
};
$jscomp.polyfill('Array.prototype.find', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(callback, opt_thisArg) {
    return $jscomp.findInternal(this, callback, opt_thisArg).v;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Array.prototype.findIndex', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(callback, opt_thisArg) {
    return $jscomp.findInternal(this, callback, opt_thisArg).i;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Array.from', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(arrayLike, opt_mapFn, opt_thisArg) {
    $jscomp.initSymbolIterator();
    opt_mapFn = opt_mapFn != null ? opt_mapFn : function(x) {
      return x;
    };
    var result = [];
    $jscomp.initSymbol();
    $jscomp.initSymbolIterator();
    var iteratorFunction = arrayLike[Symbol.iterator];
    if (typeof iteratorFunction == 'function') {
      arrayLike = iteratorFunction.call(arrayLike);
      var next;
      var k = 0;
      while (!(next = arrayLike.next()).done) {
        result.push(opt_mapFn.call(opt_thisArg, next.value, k++));
      }
    } else {
      var len = arrayLike.length;
      for (var i = 0; i < len; i++) {
        result.push(opt_mapFn.call(opt_thisArg, arrayLike[i], i));
      }
    }
    return result;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Object.is', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(left, right) {
    if (left === right) {
      return left !== 0 || 1 / left === 1 / right;
    } else {
      return left !== left && right !== right;
    }
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Array.prototype.includes', function(orig) {
  if (orig) {
    return orig;
  }
  var includes = function(searchElement, opt_fromIndex) {
    var array = this;
    if (array instanceof String) {
      array = String(array);
    }
    var len = array.length;
    var i = opt_fromIndex || 0;
    if (i < 0) {
      i = Math.max(i + len, 0);
    }
    for (; i < len; i++) {
      var element = array[i];
      if (element === searchElement || Object.is(element, searchElement)) {
        return true;
      }
    }
    return false;
  };
  return includes;
}, 'es7', 'es3');
$jscomp.polyfill('Array.prototype.keys', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function() {
    return $jscomp.iteratorFromArray(this, function(i) {
      return i;
    });
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Array.of', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(var_args) {
    return Array.from(arguments);
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Array.prototype.values', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function() {
    return $jscomp.iteratorFromArray(this, function(k, v) {
      return v;
    });
  };
  return polyfill;
}, 'es8', 'es3');
$jscomp.makeIterator = function(iterable) {
  $jscomp.initSymbolIterator();
  $jscomp.initSymbol();
  $jscomp.initSymbolIterator();
  var iteratorFunction = iterable[Symbol.iterator];
  return iteratorFunction ? iteratorFunction.call(iterable) : $jscomp.arrayIterator(iterable);
};
$jscomp.FORCE_POLYFILL_PROMISE = false;
$jscomp.polyfill('Promise', function(NativePromise) {
  if (NativePromise && !$jscomp.FORCE_POLYFILL_PROMISE) {
    return NativePromise;
  }
  function AsyncExecutor() {
    this.batch_ = null;
  }
  AsyncExecutor.prototype.asyncExecute = function(f) {
    if (this.batch_ == null) {
      this.batch_ = [];
      this.asyncExecuteBatch_();
    }
    this.batch_.push(f);
    return this;
  };
  AsyncExecutor.prototype.asyncExecuteBatch_ = function() {
    var self = this;
    this.asyncExecuteFunction(function() {
      self.executeBatch_();
    });
  };
  var nativeSetTimeout = $jscomp.global['setTimeout'];
  AsyncExecutor.prototype.asyncExecuteFunction = function(f) {
    nativeSetTimeout(f, 0);
  };
  AsyncExecutor.prototype.executeBatch_ = function() {
    while (this.batch_ && this.batch_.length) {
      var executingBatch = this.batch_;
      this.batch_ = [];
      for (var i = 0; i < executingBatch.length; ++i) {
        var f = executingBatch[i];
        executingBatch[i] = null;
        try {
          f();
        } catch (error) {
          this.asyncThrow_(error);
        }
      }
    }
    this.batch_ = null;
  };
  AsyncExecutor.prototype.asyncThrow_ = function(exception) {
    this.asyncExecuteFunction(function() {
      throw exception;
    });
  };
  var PromiseState = {PENDING:0, FULFILLED:1, REJECTED:2};
  var PolyfillPromise = function(executor) {
    this.state_ = PromiseState.PENDING;
    this.result_ = undefined;
    this.onSettledCallbacks_ = [];
    var resolveAndReject = this.createResolveAndReject_();
    try {
      executor(resolveAndReject.resolve, resolveAndReject.reject);
    } catch (e) {
      resolveAndReject.reject(e);
    }
  };
  PolyfillPromise.prototype.createResolveAndReject_ = function() {
    var thisPromise = this;
    var alreadyCalled = false;
    function firstCallWins(method) {
      return function(x) {
        if (!alreadyCalled) {
          alreadyCalled = true;
          method.call(thisPromise, x);
        }
      };
    }
    return {resolve:firstCallWins(this.resolveTo_), reject:firstCallWins(this.reject_)};
  };
  PolyfillPromise.prototype.resolveTo_ = function(value) {
    if (value === this) {
      this.reject_(new TypeError('A Promise cannot resolve to itself'));
    } else {
      if (value instanceof PolyfillPromise) {
        this.settleSameAsPromise_(value);
      } else {
        if (isObject(value)) {
          this.resolveToNonPromiseObj_(value);
        } else {
          this.fulfill_(value);
        }
      }
    }
  };
  PolyfillPromise.prototype.resolveToNonPromiseObj_ = function(obj) {
    var thenMethod = undefined;
    try {
      thenMethod = obj.then;
    } catch (error) {
      this.reject_(error);
      return;
    }
    if (typeof thenMethod == 'function') {
      this.settleSameAsThenable_(thenMethod, obj);
    } else {
      this.fulfill_(obj);
    }
  };
  function isObject(value) {
    switch(typeof value) {
      case 'object':
        return value != null;
      case 'function':
        return true;
      default:
        return false;
    }
  }
  PolyfillPromise.prototype.reject_ = function(reason) {
    this.settle_(PromiseState.REJECTED, reason);
  };
  PolyfillPromise.prototype.fulfill_ = function(value) {
    this.settle_(PromiseState.FULFILLED, value);
  };
  PolyfillPromise.prototype.settle_ = function(settledState, valueOrReason) {
    if (this.state_ != PromiseState.PENDING) {
      throw new Error('Cannot settle(' + settledState + ', ' + valueOrReason + '): Promise already settled in state' + this.state_);
    }
    this.state_ = settledState;
    this.result_ = valueOrReason;
    this.executeOnSettledCallbacks_();
  };
  PolyfillPromise.prototype.executeOnSettledCallbacks_ = function() {
    if (this.onSettledCallbacks_ != null) {
      for (var i = 0; i < this.onSettledCallbacks_.length; ++i) {
        asyncExecutor.asyncExecute(this.onSettledCallbacks_[i]);
      }
      this.onSettledCallbacks_ = null;
    }
  };
  var asyncExecutor = new AsyncExecutor;
  PolyfillPromise.prototype.settleSameAsPromise_ = function(promise) {
    var methods = this.createResolveAndReject_();
    promise.callWhenSettled_(methods.resolve, methods.reject);
  };
  PolyfillPromise.prototype.settleSameAsThenable_ = function(thenMethod, thenable) {
    var methods = this.createResolveAndReject_();
    try {
      thenMethod.call(thenable, methods.resolve, methods.reject);
    } catch (error) {
      methods.reject(error);
    }
  };
  PolyfillPromise.prototype.then = function(onFulfilled, onRejected) {
    var resolveChild;
    var rejectChild;
    var childPromise = new PolyfillPromise(function(resolve, reject) {
      resolveChild = resolve;
      rejectChild = reject;
    });
    function createCallback(paramF, defaultF) {
      if (typeof paramF == 'function') {
        return function(x) {
          try {
            resolveChild(paramF(x));
          } catch (error) {
            rejectChild(error);
          }
        };
      } else {
        return defaultF;
      }
    }
    this.callWhenSettled_(createCallback(onFulfilled, resolveChild), createCallback(onRejected, rejectChild));
    return childPromise;
  };
  PolyfillPromise.prototype['catch'] = function(onRejected) {
    return this.then(undefined, onRejected);
  };
  PolyfillPromise.prototype.callWhenSettled_ = function(onFulfilled, onRejected) {
    var thisPromise = this;
    function callback() {
      switch(thisPromise.state_) {
        case PromiseState.FULFILLED:
          onFulfilled(thisPromise.result_);
          break;
        case PromiseState.REJECTED:
          onRejected(thisPromise.result_);
          break;
        default:
          throw new Error('Unexpected state: ' + thisPromise.state_);
      }
    }
    if (this.onSettledCallbacks_ == null) {
      asyncExecutor.asyncExecute(callback);
    } else {
      this.onSettledCallbacks_.push(callback);
    }
  };
  function resolvingPromise(opt_value) {
    if (opt_value instanceof PolyfillPromise) {
      return opt_value;
    } else {
      return new PolyfillPromise(function(resolve, reject) {
        resolve(opt_value);
      });
    }
  }
  PolyfillPromise['resolve'] = resolvingPromise;
  PolyfillPromise['reject'] = function(opt_reason) {
    return new PolyfillPromise(function(resolve, reject) {
      reject(opt_reason);
    });
  };
  PolyfillPromise['race'] = function(thenablesOrValues) {
    return new PolyfillPromise(function(resolve, reject) {
      var iterator = $jscomp.makeIterator(thenablesOrValues);
      for (var iterRec = iterator.next(); !iterRec.done; iterRec = iterator.next()) {
        resolvingPromise(iterRec.value).callWhenSettled_(resolve, reject);
      }
    });
  };
  PolyfillPromise['all'] = function(thenablesOrValues) {
    var iterator = $jscomp.makeIterator(thenablesOrValues);
    var iterRec = iterator.next();
    if (iterRec.done) {
      return resolvingPromise([]);
    } else {
      return new PolyfillPromise(function(resolveAll, rejectAll) {
        var resultsArray = [];
        var unresolvedCount = 0;
        function onFulfilled(i) {
          return function(ithResult) {
            resultsArray[i] = ithResult;
            unresolvedCount--;
            if (unresolvedCount == 0) {
              resolveAll(resultsArray);
            }
          };
        }
        do {
          resultsArray.push(undefined);
          unresolvedCount++;
          resolvingPromise(iterRec.value).callWhenSettled_(onFulfilled(resultsArray.length - 1), rejectAll);
          iterRec = iterator.next();
        } while (!iterRec.done);
      });
    }
  };
  return PolyfillPromise;
}, 'es6', 'es3');
$jscomp.polyfill('Promise.prototype.finally', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(onFinally) {
    return this.then(function(value) {
      var promise = Promise.resolve(onFinally());
      return promise.then(function() {
        return value;
      });
    }, function(reason) {
      var promise = Promise.resolve(onFinally());
      return promise.then(function() {
        throw reason;
      });
    });
  };
  return polyfill;
}, 'es9', 'es3');
$jscomp.underscoreProtoCanBeSet = function() {
  var x = {a:true};
  var y = {};
  try {
    y.__proto__ = x;
    return y.a;
  } catch (e) {
  }
  return false;
};
$jscomp.setPrototypeOf = typeof Object.setPrototypeOf == 'function' ? Object.setPrototypeOf : $jscomp.underscoreProtoCanBeSet() ? function(target, proto) {
  target.__proto__ = proto;
  if (target.__proto__ !== proto) {
    throw new TypeError(target + ' is not extensible');
  }
  return target;
} : null;
$jscomp.generator = {};
$jscomp.generator.ensureIteratorResultIsObject_ = function(result) {
  if (result instanceof Object) {
    return;
  }
  throw new TypeError('Iterator result ' + result + ' is not an object');
};
$jscomp.generator.Context = function() {
  this.isRunning_ = false;
  this.yieldAllIterator_ = null;
  this.yieldResult = undefined;
  this.nextAddress = 1;
  this.catchAddress_ = 0;
  this.finallyAddress_ = 0;
  this.abruptCompletion_ = null;
  this.finallyContexts_ = null;
};
$jscomp.generator.Context.prototype.start_ = function() {
  if (this.isRunning_) {
    throw new TypeError('Generator is already running');
  }
  this.isRunning_ = true;
};
$jscomp.generator.Context.prototype.stop_ = function() {
  this.isRunning_ = false;
};
$jscomp.generator.Context.prototype.jumpToErrorHandler_ = function() {
  this.nextAddress = this.catchAddress_ || this.finallyAddress_;
};
$jscomp.generator.Context.prototype.next_ = function(value) {
  this.yieldResult = value;
};
$jscomp.generator.Context.prototype.throw_ = function(e) {
  this.abruptCompletion_ = {exception:e, isException:true};
  this.jumpToErrorHandler_();
};
$jscomp.generator.Context.prototype['return'] = function(value) {
  this.abruptCompletion_ = {'return':value};
  this.nextAddress = this.finallyAddress_;
};
$jscomp.generator.Context.prototype.jumpThroughFinallyBlocks = function(nextAddress) {
  this.abruptCompletion_ = {jumpTo:nextAddress};
  this.nextAddress = this.finallyAddress_;
};
$jscomp.generator.Context.prototype.yield = function(value, resumeAddress) {
  this.nextAddress = resumeAddress;
  return {value:value};
};
$jscomp.generator.Context.prototype.yieldAll = function(iterable, resumeAddress) {
  var iterator = $jscomp.makeIterator(iterable);
  var result = iterator.next();
  $jscomp.generator.ensureIteratorResultIsObject_(result);
  if (result.done) {
    this.yieldResult = result.value;
    this.nextAddress = resumeAddress;
    return;
  }
  this.yieldAllIterator_ = iterator;
  return this.yield(result.value, resumeAddress);
};
$jscomp.generator.Context.prototype.jumpTo = function(nextAddress) {
  this.nextAddress = nextAddress;
};
$jscomp.generator.Context.prototype.jumpToEnd = function() {
  this.nextAddress = 0;
};
$jscomp.generator.Context.prototype.setCatchFinallyBlocks = function(catchAddress, finallyAddress) {
  this.catchAddress_ = catchAddress;
  if (finallyAddress != undefined) {
    this.finallyAddress_ = finallyAddress;
  }
};
$jscomp.generator.Context.prototype.setFinallyBlock = function(finallyAddress) {
  this.catchAddress_ = 0;
  this.finallyAddress_ = finallyAddress || 0;
};
$jscomp.generator.Context.prototype.leaveTryBlock = function(nextAddress, catchAddress) {
  this.nextAddress = nextAddress;
  this.catchAddress_ = catchAddress || 0;
};
$jscomp.generator.Context.prototype.enterCatchBlock = function(nextCatchBlockAddress) {
  this.catchAddress_ = nextCatchBlockAddress || 0;
  var exception = this.abruptCompletion_.exception;
  this.abruptCompletion_ = null;
  return exception;
};
$jscomp.generator.Context.prototype.enterFinallyBlock = function(nextCatchAddress, nextFinallyAddress, finallyDepth) {
  if (!finallyDepth) {
    this.finallyContexts_ = [this.abruptCompletion_];
  } else {
    this.finallyContexts_[finallyDepth] = this.abruptCompletion_;
  }
  this.catchAddress_ = nextCatchAddress || 0;
  this.finallyAddress_ = nextFinallyAddress || 0;
};
$jscomp.generator.Context.prototype.leaveFinallyBlock = function(nextAddress, finallyDepth) {
  var preservedContext = this.finallyContexts_.splice(finallyDepth || 0)[0];
  var abruptCompletion = this.abruptCompletion_ = this.abruptCompletion_ || preservedContext;
  if (abruptCompletion) {
    if (abruptCompletion.isException) {
      return this.jumpToErrorHandler_();
    }
    if (abruptCompletion.jumpTo != undefined && this.finallyAddress_ < abruptCompletion.jumpTo) {
      this.nextAddress = abruptCompletion.jumpTo;
      this.abruptCompletion_ = null;
    } else {
      this.nextAddress = this.finallyAddress_;
    }
  } else {
    this.nextAddress = nextAddress;
  }
};
$jscomp.generator.Context.prototype.forIn = function(object) {
  return new $jscomp.generator.Context.PropertyIterator(object);
};
$jscomp.generator.Context.PropertyIterator = function(object) {
  this.object_ = object;
  this.properties_ = [];
  for (var property in object) {
    this.properties_.push(property);
  }
  this.properties_.reverse();
};
$jscomp.generator.Context.PropertyIterator.prototype.getNext = function() {
  while (this.properties_.length > 0) {
    var property = this.properties_.pop();
    if (property in this.object_) {
      return property;
    }
  }
  return null;
};
$jscomp.generator.Engine_ = function(program) {
  this.context_ = new $jscomp.generator.Context;
  this.program_ = program;
};
$jscomp.generator.Engine_.prototype.next_ = function(value) {
  this.context_.start_();
  if (this.context_.yieldAllIterator_) {
    return this.yieldAllStep_(this.context_.yieldAllIterator_.next, value, this.context_.next_);
  }
  this.context_.next_(value);
  return this.nextStep_();
};
$jscomp.generator.Engine_.prototype.return_ = function(value) {
  this.context_.start_();
  var yieldAllIterator = this.context_.yieldAllIterator_;
  if (yieldAllIterator) {
    var returnFunction = 'return' in yieldAllIterator ? yieldAllIterator['return'] : function(v) {
      return {value:v, done:true};
    };
    return this.yieldAllStep_(returnFunction, value, this.context_['return']);
  }
  this.context_['return'](value);
  return this.nextStep_();
};
$jscomp.generator.Engine_.prototype.throw_ = function(exception) {
  this.context_.start_();
  if (this.context_.yieldAllIterator_) {
    return this.yieldAllStep_(this.context_.yieldAllIterator_['throw'], exception, this.context_.next_);
  }
  this.context_.throw_(exception);
  return this.nextStep_();
};
$jscomp.generator.Engine_.prototype.yieldAllStep_ = function(action, value, nextAction) {
  try {
    var result = action.call(this.context_.yieldAllIterator_, value);
    $jscomp.generator.ensureIteratorResultIsObject_(result);
    if (!result.done) {
      this.context_.stop_();
      return result;
    }
    var resultValue = result.value;
  } catch (e) {
    this.context_.yieldAllIterator_ = null;
    this.context_.throw_(e);
    return this.nextStep_();
  }
  this.context_.yieldAllIterator_ = null;
  nextAction.call(this.context_, resultValue);
  return this.nextStep_();
};
$jscomp.generator.Engine_.prototype.nextStep_ = function() {
  while (this.context_.nextAddress) {
    try {
      var yieldValue = this.program_(this.context_);
      if (yieldValue) {
        this.context_.stop_();
        return {value:yieldValue.value, done:false};
      }
    } catch (e) {
      this.context_.yieldResult = undefined;
      this.context_.throw_(e);
    }
  }
  this.context_.stop_();
  if (this.context_.abruptCompletion_) {
    var abruptCompletion = this.context_.abruptCompletion_;
    this.context_.abruptCompletion_ = null;
    if (abruptCompletion.isException) {
      throw abruptCompletion.exception;
    }
    return {value:abruptCompletion['return'], done:true};
  }
  return {value:undefined, done:true};
};
$jscomp.generator.Generator_ = function(engine) {
  this.next = function(opt_value) {
    return engine.next_(opt_value);
  };
  this['throw'] = function(exception) {
    return engine.throw_(exception);
  };
  this['return'] = function(value) {
    return engine.return_(value);
  };
  $jscomp.initSymbolIterator();
  $jscomp.initSymbol();
  $jscomp.initSymbolIterator();
  this[Symbol.iterator] = function() {
    return this;
  };
};
$jscomp.generator.createGenerator = function(generator, program) {
  var result = new $jscomp.generator.Generator_(new $jscomp.generator.Engine_(program));
  if ($jscomp.setPrototypeOf) {
    $jscomp.setPrototypeOf(result, generator.prototype);
  }
  return result;
};
$jscomp.asyncExecutePromiseGenerator = function(generator) {
  function passValueToGenerator(value) {
    return generator.next(value);
  }
  function passErrorToGenerator(error) {
    return generator['throw'](error);
  }
  return new Promise(function(resolve, reject) {
    function handleGeneratorRecord(genRec) {
      if (genRec.done) {
        resolve(genRec.value);
      } else {
        Promise.resolve(genRec.value).then(passValueToGenerator, passErrorToGenerator).then(handleGeneratorRecord, reject);
      }
    }
    handleGeneratorRecord(generator.next());
  });
};
$jscomp.asyncExecutePromiseGeneratorFunction = function(generatorFunction) {
  return $jscomp.asyncExecutePromiseGenerator(generatorFunction());
};
$jscomp.asyncExecutePromiseGeneratorProgram = function(program) {
  return $jscomp.asyncExecutePromiseGenerator(new $jscomp.generator.Generator_(new $jscomp.generator.Engine_(program)));
};
$jscomp.checkEs6ConformanceViaProxy = function() {
  try {
    var proxied = {};
    var proxy = Object.create(new $jscomp.global['Proxy'](proxied, {'get':function(target, key, receiver) {
      return target == proxied && key == 'q' && receiver == proxy;
    }}));
    return proxy['q'] === true;
  } catch (err) {
    return false;
  }
};
$jscomp.USE_PROXY_FOR_ES6_CONFORMANCE_CHECKS = false;
$jscomp.ES6_CONFORMANCE = $jscomp.USE_PROXY_FOR_ES6_CONFORMANCE_CHECKS && $jscomp.checkEs6ConformanceViaProxy();
$jscomp.owns = function(obj, prop) {
  return Object.prototype.hasOwnProperty.call(obj, prop);
};
$jscomp.polyfill('WeakMap', function(NativeWeakMap) {
  function isConformant() {
    if (!NativeWeakMap || !Object.seal) {
      return false;
    }
    try {
      var x = Object.seal({});
      var y = Object.seal({});
      var map = new NativeWeakMap([[x, 2], [y, 3]]);
      if (map.get(x) != 2 || map.get(y) != 3) {
        return false;
      }
      map['delete'](x);
      map.set(y, 4);
      return !map.has(x) && map.get(y) == 4;
    } catch (err) {
      return false;
    }
  }
  if ($jscomp.USE_PROXY_FOR_ES6_CONFORMANCE_CHECKS) {
    if (NativeWeakMap && $jscomp.ES6_CONFORMANCE) {
      return NativeWeakMap;
    }
  } else {
    if (isConformant()) {
      return NativeWeakMap;
    }
  }
  var prop = '$jscomp_hidden_' + Math.random();
  function insert(target) {
    if (!$jscomp.owns(target, prop)) {
      var obj = {};
      $jscomp.defineProperty(target, prop, {value:obj});
    }
  }
  function patch(name) {
    var prev = Object[name];
    if (prev) {
      Object[name] = function(target) {
        insert(target);
        return prev(target);
      };
    }
  }
  patch('freeze');
  patch('preventExtensions');
  patch('seal');
  var index = 0;
  var PolyfillWeakMap = function(opt_iterable) {
    this.id_ = (index += Math.random() + 1).toString();
    if (opt_iterable) {
      $jscomp.initSymbol();
      $jscomp.initSymbolIterator();
      var iter = $jscomp.makeIterator(opt_iterable);
      var entry;
      while (!(entry = iter.next()).done) {
        var item = entry.value;
        this.set(item[0], item[1]);
      }
    }
  };
  PolyfillWeakMap.prototype.set = function(key, value) {
    insert(key);
    if (!$jscomp.owns(key, prop)) {
      throw new Error('WeakMap key fail: ' + key);
    }
    key[prop][this.id_] = value;
    return this;
  };
  PolyfillWeakMap.prototype.get = function(key) {
    return $jscomp.owns(key, prop) ? key[prop][this.id_] : undefined;
  };
  PolyfillWeakMap.prototype.has = function(key) {
    return $jscomp.owns(key, prop) && $jscomp.owns(key[prop], this.id_);
  };
  PolyfillWeakMap.prototype['delete'] = function(key) {
    if (!$jscomp.owns(key, prop) || !$jscomp.owns(key[prop], this.id_)) {
      return false;
    }
    return delete key[prop][this.id_];
  };
  return PolyfillWeakMap;
}, 'es6', 'es3');
$jscomp.MapEntry = function() {
  this.previous;
  this.next;
  this.head;
  this.key;
  this.value;
};
$jscomp.polyfill('Map', function(NativeMap) {
  function isConformant() {
    if ($jscomp.ASSUME_NO_NATIVE_MAP || !NativeMap || typeof NativeMap != 'function' || !NativeMap.prototype.entries || typeof Object.seal != 'function') {
      return false;
    }
    try {
      NativeMap = NativeMap;
      var key = Object.seal({x:4});
      var map = new NativeMap($jscomp.makeIterator([[key, 's']]));
      if (map.get(key) != 's' || map.size != 1 || map.get({x:4}) || map.set({x:4}, 't') != map || map.size != 2) {
        return false;
      }
      var iter = map.entries();
      var item = iter.next();
      if (item.done || item.value[0] != key || item.value[1] != 's') {
        return false;
      }
      item = iter.next();
      if (item.done || item.value[0].x != 4 || item.value[1] != 't' || !iter.next().done) {
        return false;
      }
      return true;
    } catch (err) {
      return false;
    }
  }
  if ($jscomp.USE_PROXY_FOR_ES6_CONFORMANCE_CHECKS) {
    if (NativeMap && $jscomp.ES6_CONFORMANCE) {
      return NativeMap;
    }
  } else {
    if (isConformant()) {
      return NativeMap;
    }
  }
  $jscomp.initSymbol();
  $jscomp.initSymbolIterator();
  var idMap = new WeakMap;
  var PolyfillMap = function(opt_iterable) {
    this.data_ = {};
    this.head_ = createHead();
    this.size = 0;
    if (opt_iterable) {
      var iter = $jscomp.makeIterator(opt_iterable);
      var entry;
      while (!(entry = iter.next()).done) {
        var item = entry.value;
        this.set(item[0], item[1]);
      }
    }
  };
  PolyfillMap.prototype.set = function(key, value) {
    key = key === 0 ? 0 : key;
    var r = maybeGetEntry(this, key);
    if (!r.list) {
      r.list = this.data_[r.id] = [];
    }
    if (!r.entry) {
      r.entry = {next:this.head_, previous:this.head_.previous, head:this.head_, key:key, value:value};
      r.list.push(r.entry);
      this.head_.previous.next = r.entry;
      this.head_.previous = r.entry;
      this.size++;
    } else {
      r.entry.value = value;
    }
    return this;
  };
  PolyfillMap.prototype['delete'] = function(key) {
    var r = maybeGetEntry(this, key);
    if (r.entry && r.list) {
      r.list.splice(r.index, 1);
      if (!r.list.length) {
        delete this.data_[r.id];
      }
      r.entry.previous.next = r.entry.next;
      r.entry.next.previous = r.entry.previous;
      r.entry.head = null;
      this.size--;
      return true;
    }
    return false;
  };
  PolyfillMap.prototype.clear = function() {
    this.data_ = {};
    this.head_ = this.head_.previous = createHead();
    this.size = 0;
  };
  PolyfillMap.prototype.has = function(key) {
    return !!maybeGetEntry(this, key).entry;
  };
  PolyfillMap.prototype.get = function(key) {
    var entry = maybeGetEntry(this, key).entry;
    return entry && entry.value;
  };
  PolyfillMap.prototype.entries = function() {
    return makeIterator(this, function(entry) {
      return [entry.key, entry.value];
    });
  };
  PolyfillMap.prototype.keys = function() {
    return makeIterator(this, function(entry) {
      return entry.key;
    });
  };
  PolyfillMap.prototype.values = function() {
    return makeIterator(this, function(entry) {
      return entry.value;
    });
  };
  PolyfillMap.prototype.forEach = function(callback, opt_thisArg) {
    var iter = this.entries();
    var item;
    while (!(item = iter.next()).done) {
      var entry = item.value;
      callback.call(opt_thisArg, entry[1], entry[0], this);
    }
  };
  $jscomp.initSymbol();
  $jscomp.initSymbolIterator();
  PolyfillMap.prototype[Symbol.iterator] = PolyfillMap.prototype.entries;
  var maybeGetEntry = function(map, key) {
    var id = getId(key);
    var list = map.data_[id];
    if (list && $jscomp.owns(map.data_, id)) {
      for (var index = 0; index < list.length; index++) {
        var entry = list[index];
        if (key !== key && entry.key !== entry.key || key === entry.key) {
          return {id:id, list:list, index:index, entry:entry};
        }
      }
    }
    return {id:id, list:list, index:-1, entry:undefined};
  };
  var makeIterator = function(map, func) {
    var entry = map.head_;
    return $jscomp.iteratorPrototype(function() {
      if (entry) {
        while (entry.head != map.head_) {
          entry = entry.previous;
        }
        while (entry.next != entry.head) {
          entry = entry.next;
          return {done:false, value:func(entry)};
        }
        entry = null;
      }
      return {done:true, value:void 0};
    });
  };
  var createHead = function() {
    var head = {};
    head.previous = head.next = head.head = head;
    return head;
  };
  var mapIndex = 0;
  var getId = function(obj) {
    var type = obj && typeof obj;
    if (type == 'object' || type == 'function') {
      obj = obj;
      if (!idMap.has(obj)) {
        var id = '' + ++mapIndex;
        idMap.set(obj, id);
        return id;
      }
      return idMap.get(obj);
    }
    return 'p_' + obj;
  };
  return PolyfillMap;
}, 'es6', 'es3');
$jscomp.polyfill('Math.acosh', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    x = Number(x);
    return Math.log(x + Math.sqrt(x * x - 1));
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.asinh', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    x = Number(x);
    if (x === 0) {
      return x;
    }
    var y = Math.log(Math.abs(x) + Math.sqrt(x * x + 1));
    return x < 0 ? -y : y;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.log1p', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    x = Number(x);
    if (x < 0.25 && x > -0.25) {
      var y = x;
      var d = 1;
      var z = x;
      var zPrev = 0;
      var s = 1;
      while (zPrev != z) {
        y *= x;
        s *= -1;
        z = (zPrev = z) + s * y / ++d;
      }
      return z;
    }
    return Math.log(1 + x);
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.atanh', function(orig) {
  if (orig) {
    return orig;
  }
  var log1p = Math.log1p;
  var polyfill = function(x) {
    x = Number(x);
    return (log1p(x) - log1p(-x)) / 2;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.cbrt', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    if (x === 0) {
      return x;
    }
    x = Number(x);
    var y = Math.pow(Math.abs(x), 1 / 3);
    return x < 0 ? -y : y;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.clz32', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    x = Number(x) >>> 0;
    if (x === 0) {
      return 32;
    }
    var result = 0;
    if ((x & 4294901760) === 0) {
      x <<= 16;
      result += 16;
    }
    if ((x & 4278190080) === 0) {
      x <<= 8;
      result += 8;
    }
    if ((x & 4026531840) === 0) {
      x <<= 4;
      result += 4;
    }
    if ((x & 3221225472) === 0) {
      x <<= 2;
      result += 2;
    }
    if ((x & 2147483648) === 0) {
      result++;
    }
    return result;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.cosh', function(orig) {
  if (orig) {
    return orig;
  }
  var exp = Math.exp;
  var polyfill = function(x) {
    x = Number(x);
    return (exp(x) + exp(-x)) / 2;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.expm1', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    x = Number(x);
    if (x < .25 && x > -.25) {
      var y = x;
      var d = 1;
      var z = x;
      var zPrev = 0;
      while (zPrev != z) {
        y *= x / ++d;
        z = (zPrev = z) + y;
      }
      return z;
    }
    return Math.exp(x) - 1;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.hypot', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x, y, var_args) {
    x = Number(x);
    y = Number(y);
    var i, z, sum;
    var max = Math.max(Math.abs(x), Math.abs(y));
    for (i = 2; i < arguments.length; i++) {
      max = Math.max(max, Math.abs(arguments[i]));
    }
    if (max > 1e100 || max < 1e-100) {
      if (!max) {
        return max;
      }
      x = x / max;
      y = y / max;
      sum = x * x + y * y;
      for (i = 2; i < arguments.length; i++) {
        z = Number(arguments[i]) / max;
        sum += z * z;
      }
      return Math.sqrt(sum) * max;
    } else {
      sum = x * x + y * y;
      for (i = 2; i < arguments.length; i++) {
        z = Number(arguments[i]);
        sum += z * z;
      }
      return Math.sqrt(sum);
    }
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.imul', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(a, b) {
    a = Number(a);
    b = Number(b);
    var ah = a >>> 16 & 65535;
    var al = a & 65535;
    var bh = b >>> 16 & 65535;
    var bl = b & 65535;
    var lh = ah * bl + al * bh << 16 >>> 0;
    return al * bl + lh | 0;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.log10', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    return Math.log(x) / Math.LN10;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.log2', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    return Math.log(x) / Math.LN2;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.sign', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    x = Number(x);
    return x === 0 || isNaN(x) ? x : x > 0 ? 1 : -1;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.sinh', function(orig) {
  if (orig) {
    return orig;
  }
  var exp = Math.exp;
  var polyfill = function(x) {
    x = Number(x);
    if (x === 0) {
      return x;
    }
    return (exp(x) - exp(-x)) / 2;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.tanh', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    x = Number(x);
    if (x === 0) {
      return x;
    }
    var y = Math.exp(-2 * Math.abs(x));
    var z = (1 - y) / (1 + y);
    return x < 0 ? -z : z;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Math.trunc', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    x = Number(x);
    if (isNaN(x) || x === Infinity || x === -Infinity || x === 0) {
      return x;
    }
    var y = Math.floor(Math.abs(x));
    return x < 0 ? -y : y;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Number.EPSILON', function(orig) {
  return Math.pow(2, -52);
}, 'es6', 'es3');
$jscomp.polyfill('Number.MAX_SAFE_INTEGER', function() {
  return 9007199254740991;
}, 'es6', 'es3');
$jscomp.polyfill('Number.MIN_SAFE_INTEGER', function() {
  return -9007199254740991;
}, 'es6', 'es3');
$jscomp.polyfill('Number.isFinite', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    if (typeof x !== 'number') {
      return false;
    }
    return !isNaN(x) && x !== Infinity && x !== -Infinity;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Number.isInteger', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    if (!Number.isFinite(x)) {
      return false;
    }
    return x === Math.floor(x);
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Number.isNaN', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    return typeof x === 'number' && isNaN(x);
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Number.isSafeInteger', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(x) {
    return Number.isInteger(x) && Math.abs(x) <= Number.MAX_SAFE_INTEGER;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Number.parseFloat', function(orig) {
  return orig || parseFloat;
}, 'es6', 'es3');
$jscomp.polyfill('Number.parseInt', function(orig) {
  return orig || parseInt;
}, 'es6', 'es3');
$jscomp.assign = typeof Object.assign == 'function' ? Object.assign : function(target, var_args) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];
    if (!source) {
      continue;
    }
    for (var key in source) {
      if ($jscomp.owns(source, key)) {
        target[key] = source[key];
      }
    }
  }
  return target;
};
$jscomp.polyfill('Object.assign', function(orig) {
  return orig || $jscomp.assign;
}, 'es6', 'es3');
$jscomp.polyfill('Object.entries', function(orig) {
  if (orig) {
    return orig;
  }
  var entries = function(obj) {
    var result = [];
    for (var key in obj) {
      if ($jscomp.owns(obj, key)) {
        result.push([key, obj[key]]);
      }
    }
    return result;
  };
  return entries;
}, 'es8', 'es3');
$jscomp.polyfill('Object.getOwnPropertySymbols', function(orig) {
  if (orig) {
    return orig;
  }
  return function() {
    return [];
  };
}, 'es6', 'es5');
$jscomp.polyfill('Reflect.ownKeys', function(orig) {
  if (orig) {
    return orig;
  }
  var symbolPrefix = 'jscomp_symbol_';
  function isSymbol(key) {
    return key.substring(0, symbolPrefix.length) == symbolPrefix;
  }
  var polyfill = function(target) {
    var keys = [];
    var names = Object.getOwnPropertyNames(target);
    var symbols = Object.getOwnPropertySymbols(target);
    for (var i = 0; i < names.length; i++) {
      (isSymbol(names[i]) ? symbols : keys).push(names[i]);
    }
    return keys.concat(symbols);
  };
  return polyfill;
}, 'es6', 'es5');
$jscomp.polyfill('Object.getOwnPropertyDescriptors', function(orig) {
  if (orig) {
    return orig;
  }
  var getOwnPropertyDescriptors = function(obj) {
    var result = {};
    var keys = Reflect.ownKeys(obj);
    for (var i = 0; i < keys.length; i++) {
      result[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]);
    }
    return result;
  };
  return getOwnPropertyDescriptors;
}, 'es8', 'es5');
$jscomp.polyfill('Object.setPrototypeOf', function(orig) {
  return orig || $jscomp.setPrototypeOf;
}, 'es6', 'es5');
$jscomp.polyfill('Object.values', function(orig) {
  if (orig) {
    return orig;
  }
  var values = function(obj) {
    var result = [];
    for (var key in obj) {
      if ($jscomp.owns(obj, key)) {
        result.push(obj[key]);
      }
    }
    return result;
  };
  return values;
}, 'es8', 'es3');
$jscomp.polyfill('Reflect.apply', function(orig) {
  if (orig) {
    return orig;
  }
  var apply = Function.prototype.apply;
  var polyfill = function(target, thisArg, argList) {
    return apply.call(target, thisArg, argList);
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.objectCreate = $jscomp.ASSUME_ES5 || typeof Object.create == 'function' ? Object.create : function(prototype) {
  var ctor = function() {
  };
  ctor.prototype = prototype;
  return new ctor;
};
$jscomp.construct = function() {
  function reflectConstructWorks() {
    function Base() {
    }
    function Derived() {
    }
    new Base;
    Reflect.construct(Base, [], Derived);
    return new Base instanceof Base;
  }
  if (typeof Reflect != 'undefined' && Reflect.construct) {
    if (reflectConstructWorks()) {
      return Reflect.construct;
    }
    var brokenConstruct = Reflect.construct;
    var patchedConstruct = function(target, argList, opt_newTarget) {
      var out = brokenConstruct(target, argList);
      if (opt_newTarget) {
        Reflect.setPrototypeOf(out, opt_newTarget.prototype);
      }
      return out;
    };
    return patchedConstruct;
  }
  function construct(target, argList, opt_newTarget) {
    if (opt_newTarget === undefined) {
      opt_newTarget = target;
    }
    var proto = opt_newTarget.prototype || Object.prototype;
    var obj = $jscomp.objectCreate(proto);
    var apply = Function.prototype.apply;
    var out = apply.call(target, obj, argList);
    return out || obj;
  }
  return construct;
}();
$jscomp.polyfill('Reflect.construct', function(orig) {
  return $jscomp.construct;
}, 'es6', 'es3');
$jscomp.polyfill('Reflect.defineProperty', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(target, propertyKey, attributes) {
    try {
      Object.defineProperty(target, propertyKey, attributes);
      var desc = Object.getOwnPropertyDescriptor(target, propertyKey);
      if (!desc) {
        return false;
      }
      return desc.configurable === (attributes.configurable || false) && desc.enumerable === (attributes.enumerable || false) && ('value' in desc ? desc.value === attributes.value && desc.writable === (attributes.writable || false) : desc.get === attributes.get && desc.set === attributes.set);
    } catch (err) {
      return false;
    }
  };
  return polyfill;
}, 'es6', 'es5');
$jscomp.polyfill('Reflect.deleteProperty', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(target, propertyKey) {
    if (!$jscomp.owns(target, propertyKey)) {
      return true;
    }
    try {
      return delete target[propertyKey];
    } catch (err) {
      return false;
    }
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Reflect.getOwnPropertyDescriptor', function(orig) {
  return orig || Object.getOwnPropertyDescriptor;
}, 'es6', 'es5');
$jscomp.polyfill('Reflect.getPrototypeOf', function(orig) {
  return orig || Object.getPrototypeOf;
}, 'es6', 'es5');
$jscomp.findDescriptor = function(target, propertyKey) {
  var obj = target;
  while (obj) {
    var property = Reflect.getOwnPropertyDescriptor(obj, propertyKey);
    if (property) {
      return property;
    }
    obj = Reflect.getPrototypeOf(obj);
  }
  return undefined;
};
$jscomp.polyfill('Reflect.get', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(target, propertyKey, opt_receiver) {
    if (arguments.length <= 2) {
      return target[propertyKey];
    }
    var property = $jscomp.findDescriptor(target, propertyKey);
    if (property) {
      return property.get ? property.get.call(opt_receiver) : property.value;
    }
    return undefined;
  };
  return polyfill;
}, 'es6', 'es5');
$jscomp.polyfill('Reflect.has', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(target, propertyKey) {
    return propertyKey in target;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Reflect.isExtensible', function(orig) {
  if (orig) {
    return orig;
  }
  if ($jscomp.ASSUME_ES5 || typeof Object.isExtensible == 'function') {
    return Object.isExtensible;
  }
  return function() {
    return true;
  };
}, 'es6', 'es3');
$jscomp.polyfill('Reflect.preventExtensions', function(orig) {
  if (orig) {
    return orig;
  }
  if (!($jscomp.ASSUME_ES5 || typeof Object.preventExtensions == 'function')) {
    return function() {
      return false;
    };
  }
  var polyfill = function(target) {
    Object.preventExtensions(target);
    return !Object.isExtensible(target);
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('Reflect.set', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(target, propertyKey, value, opt_receiver) {
    var property = $jscomp.findDescriptor(target, propertyKey);
    if (!property) {
      if (Reflect.isExtensible(target)) {
        target[propertyKey] = value;
        return true;
      }
      return false;
    }
    if (property.set) {
      property.set.call(arguments.length > 3 ? opt_receiver : target, value);
      return true;
    } else {
      if (property.writable && !Object.isFrozen(target)) {
        target[propertyKey] = value;
        return true;
      }
    }
    return false;
  };
  return polyfill;
}, 'es6', 'es5');
$jscomp.polyfill('Reflect.setPrototypeOf', function(orig) {
  if (orig) {
    return orig;
  } else {
    if ($jscomp.setPrototypeOf) {
      var setPrototypeOf = $jscomp.setPrototypeOf;
      var polyfill = function(target, proto) {
        try {
          setPrototypeOf(target, proto);
          return true;
        } catch (e) {
          return false;
        }
      };
      return polyfill;
    } else {
      return null;
    }
  }
}, 'es6', 'es5');
$jscomp.polyfill('Set', function(NativeSet) {
  function isConformant() {
    if ($jscomp.ASSUME_NO_NATIVE_SET || !NativeSet || typeof NativeSet != 'function' || !NativeSet.prototype.entries || typeof Object.seal != 'function') {
      return false;
    }
    try {
      NativeSet = NativeSet;
      var value = Object.seal({x:4});
      var set = new NativeSet($jscomp.makeIterator([value]));
      if (!set.has(value) || set.size != 1 || set.add(value) != set || set.size != 1 || set.add({x:4}) != set || set.size != 2) {
        return false;
      }
      var iter = set.entries();
      var item = iter.next();
      if (item.done || item.value[0] != value || item.value[1] != value) {
        return false;
      }
      item = iter.next();
      if (item.done || item.value[0] == value || item.value[0].x != 4 || item.value[1] != item.value[0]) {
        return false;
      }
      return iter.next().done;
    } catch (err) {
      return false;
    }
  }
  if ($jscomp.USE_PROXY_FOR_ES6_CONFORMANCE_CHECKS) {
    if (NativeSet && $jscomp.ES6_CONFORMANCE) {
      return NativeSet;
    }
  } else {
    if (isConformant()) {
      return NativeSet;
    }
  }
  $jscomp.initSymbol();
  $jscomp.initSymbolIterator();
  var PolyfillSet = function(opt_iterable) {
    this.map_ = new Map;
    if (opt_iterable) {
      var iter = $jscomp.makeIterator(opt_iterable);
      var entry;
      while (!(entry = iter.next()).done) {
        var item = entry.value;
        this.add(item);
      }
    }
    this.size = this.map_.size;
  };
  PolyfillSet.prototype.add = function(value) {
    value = value === 0 ? 0 : value;
    this.map_.set(value, value);
    this.size = this.map_.size;
    return this;
  };
  PolyfillSet.prototype['delete'] = function(value) {
    var result = this.map_['delete'](value);
    this.size = this.map_.size;
    return result;
  };
  PolyfillSet.prototype.clear = function() {
    this.map_.clear();
    this.size = 0;
  };
  PolyfillSet.prototype.has = function(value) {
    return this.map_.has(value);
  };
  PolyfillSet.prototype.entries = function() {
    return this.map_.entries();
  };
  PolyfillSet.prototype.values = function() {
    return this.map_.values();
  };
  PolyfillSet.prototype.keys = PolyfillSet.prototype.values;
  $jscomp.initSymbol();
  $jscomp.initSymbolIterator();
  PolyfillSet.prototype[Symbol.iterator] = PolyfillSet.prototype.values;
  PolyfillSet.prototype.forEach = function(callback, opt_thisArg) {
    var set = this;
    this.map_.forEach(function(value) {
      return callback.call(opt_thisArg, value, value, set);
    });
  };
  return PolyfillSet;
}, 'es6', 'es3');
$jscomp.checkStringArgs = function(thisArg, arg, func) {
  if (thisArg == null) {
    throw new TypeError("The 'this' value for String.prototype." + func + ' must not be null or undefined');
  }
  if (arg instanceof RegExp) {
    throw new TypeError('First argument to String.prototype.' + func + ' must not be a regular expression');
  }
  return thisArg + '';
};
$jscomp.polyfill('String.prototype.codePointAt', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(position) {
    var string = $jscomp.checkStringArgs(this, null, 'codePointAt');
    var size = string.length;
    position = Number(position) || 0;
    if (!(position >= 0 && position < size)) {
      return void 0;
    }
    position = position | 0;
    var first = string.charCodeAt(position);
    if (first < 55296 || first > 56319 || position + 1 === size) {
      return first;
    }
    var second = string.charCodeAt(position + 1);
    if (second < 56320 || second > 57343) {
      return first;
    }
    return (first - 55296) * 1024 + second + 9216;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('String.prototype.endsWith', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(searchString, opt_position) {
    var string = $jscomp.checkStringArgs(this, searchString, 'endsWith');
    searchString = searchString + '';
    if (opt_position === void 0) {
      opt_position = string.length;
    }
    var i = Math.max(0, Math.min(opt_position | 0, string.length));
    var j = searchString.length;
    while (j > 0 && i > 0) {
      if (string[--i] != searchString[--j]) {
        return false;
      }
    }
    return j <= 0;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('String.fromCodePoint', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(var_args) {
    var result = '';
    for (var i = 0; i < arguments.length; i++) {
      var code = Number(arguments[i]);
      if (code < 0 || code > 1114111 || code !== Math.floor(code)) {
        throw new RangeError('invalid_code_point ' + code);
      }
      if (code <= 65535) {
        result += String.fromCharCode(code);
      } else {
        code -= 65536;
        result += String.fromCharCode(code >>> 10 & 1023 | 55296);
        result += String.fromCharCode(code & 1023 | 56320);
      }
    }
    return result;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('String.prototype.includes', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(searchString, opt_position) {
    var string = $jscomp.checkStringArgs(this, searchString, 'includes');
    return string.indexOf(searchString, opt_position || 0) !== -1;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.polyfill('String.prototype.repeat', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(copies) {
    var string = $jscomp.checkStringArgs(this, null, 'repeat');
    if (copies < 0 || copies > 1342177279) {
      throw new RangeError('Invalid count value');
    }
    copies = copies | 0;
    var result = '';
    while (copies) {
      if (copies & 1) {
        result += string;
      }
      if (copies >>>= 1) {
        string += string;
      }
    }
    return result;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.stringPadding = function(padString, padLength) {
  var padding = padString !== undefined ? String(padString) : ' ';
  if (!(padLength > 0) || !padding) {
    return '';
  }
  var repeats = Math.ceil(padLength / padding.length);
  return padding.repeat(repeats).substring(0, padLength);
};
$jscomp.polyfill('String.prototype.padEnd', function(orig) {
  if (orig) {
    return orig;
  }
  var padEnd = function(targetLength, opt_padString) {
    var string = $jscomp.checkStringArgs(this, null, 'padStart');
    var padLength = targetLength - string.length;
    return string + $jscomp.stringPadding(opt_padString, padLength);
  };
  return padEnd;
}, 'es8', 'es3');
$jscomp.polyfill('String.prototype.padStart', function(orig) {
  if (orig) {
    return orig;
  }
  var padStart = function(targetLength, opt_padString) {
    var string = $jscomp.checkStringArgs(this, null, 'padStart');
    var padLength = targetLength - string.length;
    return $jscomp.stringPadding(opt_padString, padLength) + string;
  };
  return padStart;
}, 'es8', 'es3');
$jscomp.polyfill('String.prototype.startsWith', function(orig) {
  if (orig) {
    return orig;
  }
  var polyfill = function(searchString, opt_position) {
    var string = $jscomp.checkStringArgs(this, searchString, 'startsWith');
    searchString = searchString + '';
    var strLen = string.length;
    var searchLen = searchString.length;
    var i = Math.max(0, Math.min(opt_position | 0, string.length));
    var j = 0;
    while (j < searchLen && i < strLen) {
      if (string[i++] != searchString[j++]) {
        return false;
      }
    }
    return j >= searchLen;
  };
  return polyfill;
}, 'es6', 'es3');
$jscomp.arrayFromIterator = function(iterator) {
  var i;
  var arr = [];
  while (!(i = iterator.next()).done) {
    arr.push(i.value);
  }
  return arr;
};
$jscomp.arrayFromIterable = function(iterable) {
  if (iterable instanceof Array) {
    return iterable;
  } else {
    return $jscomp.arrayFromIterator($jscomp.makeIterator(iterable));
  }
};
$jscomp.inherits = function(childCtor, parentCtor) {
  childCtor.prototype = $jscomp.objectCreate(parentCtor.prototype);
  childCtor.prototype.constructor = childCtor;
  if ($jscomp.setPrototypeOf) {
    var setPrototypeOf = $jscomp.setPrototypeOf;
    setPrototypeOf(childCtor, parentCtor);
  } else {
    for (var p in parentCtor) {
      if (p == 'prototype') {
        continue;
      }
      if (Object.defineProperties) {
        var descriptor = Object.getOwnPropertyDescriptor(parentCtor, p);
        if (descriptor) {
          Object.defineProperty(childCtor, p, descriptor);
        }
      } else {
        childCtor[p] = parentCtor[p];
      }
    }
  }
  childCtor.superClass_ = parentCtor.prototype;
};
$jscomp.polyfill('WeakSet', function(NativeWeakSet) {
  function isConformant() {
    if (!NativeWeakSet || !Object.seal) {
      return false;
    }
    try {
      var x = Object.seal({});
      var y = Object.seal({});
      var set = new NativeWeakSet([x]);
      if (!set.has(x) || set.has(y)) {
        return false;
      }
      set['delete'](x);
      set.add(y);
      return !set.has(x) && set.has(y);
    } catch (err) {
      return false;
    }
  }
  if ($jscomp.USE_PROXY_FOR_ES6_CONFORMANCE_CHECKS) {
    if (NativeWeakSet && $jscomp.ES6_CONFORMANCE) {
      return NativeWeakSet;
    }
  } else {
    if (isConformant()) {
      return NativeWeakSet;
    }
  }
  var PolyfillWeakSet = function(opt_iterable) {
    this.map_ = new WeakMap;
    if (opt_iterable) {
      $jscomp.initSymbol();
      $jscomp.initSymbolIterator();
      var iter = $jscomp.makeIterator(opt_iterable);
      var entry;
      while (!(entry = iter.next()).done) {
        var item = entry.value;
        this.add(item);
      }
    }
  };
  PolyfillWeakSet.prototype.add = function(elem) {
    this.map_.set(elem, true);
    return this;
  };
  PolyfillWeakSet.prototype.has = function(elem) {
    return this.map_.has(elem);
  };
  PolyfillWeakSet.prototype['delete'] = function(elem) {
    return this.map_['delete'](elem);
  };
  return PolyfillWeakSet;
}, 'es6', 'es3');
try {
  if (Array.prototype.values.toString().indexOf('[native code]') == -1) {
    delete Array.prototype.values;
  }
} catch (e) {
}
var Ext = Ext || {};
(function() {
  var global = this, objectPrototype = Object.prototype, toString = objectPrototype.toString, enumerables = ['valueOf', 'toLocaleString', 'toString', 'constructor'], emptyFn = Ext.fireIdle = function() {
  }, privateFn = function() {
  }, identityFn = function(o) {
    return o;
  }, callOverrideParent = function() {
    var method = callOverrideParent.caller.caller;
    return method.$owner.prototype[method.$name].apply(this, arguments);
  }, manifest = Ext.manifest || {}, iterableRe = /\[object\s*(?:Array|Arguments|\w*Collection|\w*List|HTML\s+document\.all\s+class)\]/, MSDateRe = /^\\?\/Date\(([-+])?(\d+)(?:[+-]\d{4})?\)\\?\/$/, elevateArgs, elevateFn, elevateRet, elevateScope, i;
  Ext.global = global;
  Ext.$nextIid = 0;
  Ext.now = Date.now || (Date.now = function() {
    return +new Date;
  });
  Ext.ticks = global.performance && global.performance.now ? function() {
    return performance.now();
  } : Ext.now;
  Ext._startTime = Ext.ticks();
  emptyFn.$nullFn = identityFn.$nullFn = emptyFn.$emptyFn = identityFn.$identityFn = privateFn.$nullFn = true;
  privateFn.$privacy = 'framework';
  emptyFn.$noClearOnDestroy = identityFn.$noClearOnDestroy = true;
  privateFn.$noClearOnDestroy = true;
  Ext['suspendLayouts'] = Ext['resumeLayouts'] = emptyFn;
  for (i in{toString:1}) {
    enumerables = null;
  }
  Ext.enumerables = enumerables;
  Ext.apply = function(object, config, defaults) {
    var i, j, k;
    if (object) {
      if (defaults) {
        Ext.apply(object, defaults);
      }
      if (config && typeof config === 'object') {
        for (i in config) {
          object[i] = config[i];
        }
        if (enumerables) {
          for (j = enumerables.length; j--;) {
            k = enumerables[j];
            if (config.hasOwnProperty(k)) {
              object[k] = config[k];
            }
          }
        }
      }
    }
    return object;
  };
  function addInstanceOverrides(target, owner, overrides) {
    var name, value;
    for (name in overrides) {
      if (overrides.hasOwnProperty(name)) {
        value = overrides[name];
        if (typeof value === 'function') {
          if (owner.$className) {
            value.name = owner.$className + '#' + name;
          }
          value.$name = name;
          value.$owner = owner;
          value.$previous = target.hasOwnProperty(name) ? target[name] : callOverrideParent;
        }
        target[name] = value;
      }
    }
  }
  Ext.buildSettings = Ext.apply({baseCSSPrefix:'x-'}, Ext.buildSettings || {});
  Ext.apply(Ext, {idSeed:0, idPrefix:'ext-', isRobot:false, isSecure:/^https/i.test(window.location.protocol), enableGarbageCollector:false, enableListenerCollection:true, name:Ext.sandboxName || 'Ext', privateFn:privateFn, emptyFn:emptyFn, identityFn:identityFn, frameStartTime:Ext.now(), manifest:manifest, debugConfig:Ext.debugConfig || manifest.debug || {hooks:{'*':true}}, enableAria:true, startsWithHashRe:/^#/, validIdRe:/^[a-z_][a-z0-9\-_]*$/i, BLANK_IMAGE_URL:'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw\x3d\x3d', 
  makeIdSelector:function(id) {
    if (!Ext.validIdRe.test(id)) {
      Ext.raise('Invalid id selector: "' + id + '"');
    }
    return '#' + id;
  }, id:function(o, prefix) {
    if (o && o.id) {
      return o.id;
    }
    var id = (prefix || Ext.idPrefix) + ++Ext.idSeed;
    if (o) {
      o.id = id;
    }
    return id;
  }, returnId:function(o) {
    return o.getId();
  }, returnTrue:function() {
    return true;
  }, emptyString:new String, emptyArray:Object.freeze ? Object.freeze([]) : [], baseCSSPrefix:Ext.buildSettings.baseCSSPrefix, $eventNameMap:{}, $vendorEventRe:/^(DOMMouse|Moz.+|MS.+|webkit.+)/, canonicalEventName:function(name) {
    return Ext.$eventNameMap[name] || (Ext.$eventNameMap[name] = Ext.$vendorEventRe.test(name) ? name : name.toLowerCase());
  }, applyIf:function(object, config) {
    var property;
    if (object && config && typeof config === 'object') {
      for (property in config) {
        if (object[property] === undefined) {
          object[property] = config[property];
        }
      }
    }
    return object;
  }, destroy:function() {
    var ln = arguments.length, i, arg;
    for (i = 0; i < ln; i++) {
      arg = arguments[i];
      if (arg) {
        if (Ext.isArray(arg)) {
          this.destroy.apply(this, arg);
        } else {
          if (Ext.isFunction(arg.destroy) && !arg.destroyed) {
            arg.destroy();
          }
        }
      }
    }
    return null;
  }, destroyMembers:function(object) {
    for (var ref, name, i = 1, a = arguments, len = a.length; i < len; i++) {
      ref = object[name = a[i]];
      if (ref != null) {
        object[name] = Ext.destroy(ref);
      }
    }
  }, override:function(target, overrides) {
    if (target.$isClass) {
      target.override(overrides);
    } else {
      if (typeof target === 'function') {
        Ext.apply(target.prototype, overrides);
      } else {
        var owner = target.self, privates;
        if (owner && owner.$isClass) {
          privates = overrides.privates;
          if (privates) {
            overrides = Ext.apply({}, overrides);
            delete overrides.privates;
            addInstanceOverrides(target, owner, privates);
          }
          addInstanceOverrides(target, owner, overrides);
        } else {
          Ext.apply(target, overrides);
        }
      }
    }
    return target;
  }, valueFrom:function(value, defaultValue, allowBlank) {
    return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
  }, isEmpty:function(value, allowEmptyString) {
    return value == null || (!allowEmptyString ? value === '' : false) || Ext.isArray(value) && value.length === 0;
  }, isArray:'isArray' in Array ? Array.isArray : function(value) {
    return toString.call(value) === '[object Array]';
  }, isDate:function(obj) {
    return toString.call(obj) === '[object Date]';
  }, isMSDate:function(value) {
    if (!Ext.isString(value)) {
      return false;
    }
    return MSDateRe.test(value);
  }, isObject:toString.call(null) === '[object Object]' ? function(value) {
    return value != null && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;
  } : function(value) {
    return toString.call(value) === '[object Object]';
  }, isSimpleObject:function(value) {
    return value instanceof Object && value.constructor === Object;
  }, isPrimitive:function(value) {
    var type = typeof value;
    return type === 'string' || type === 'number' || type === 'boolean';
  }, isFunction:typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function' ? function(value) {
    return !!value && toString.call(value) === '[object Function]';
  } : function(value) {
    return !!value && typeof value === 'function';
  }, isNumber:function(value) {
    return typeof value === 'number' && isFinite(value);
  }, isNumeric:function(value) {
    return !isNaN(parseFloat(value)) && isFinite(value);
  }, isString:function(value) {
    return typeof value === 'string';
  }, isBoolean:function(value) {
    return typeof value === 'boolean';
  }, isElement:function(value) {
    return value ? value.nodeType === 1 : false;
  }, isTextNode:function(value) {
    return value ? value.nodeName === '#text' : false;
  }, isDefined:function(value) {
    return typeof value !== 'undefined';
  }, isIterable:function(value) {
    if (!value || typeof value.length !== 'number' || typeof value === 'string' || Ext.isFunction(value)) {
      return false;
    }
    if (!value.propertyIsEnumerable) {
      return !!value.item;
    }
    if (value.hasOwnProperty('length') && !value.propertyIsEnumerable('length')) {
      return true;
    }
    return iterableRe.test(toString.call(value));
  }, isDebugEnabled:function(className, defaultEnabled) {
    var debugConfig = Ext.debugConfig.hooks;
    if (debugConfig.hasOwnProperty(className)) {
      return debugConfig[className];
    }
    var enabled = debugConfig['*'], prefixLength = 0;
    if (defaultEnabled !== undefined) {
      enabled = defaultEnabled;
    }
    if (!className) {
      return enabled;
    }
    for (var prefix in debugConfig) {
      var value = debugConfig[prefix];
      if (className.charAt(prefix.length) === '.') {
        if (className.substring(0, prefix.length) === prefix) {
          if (prefixLength < prefix.length) {
            prefixLength = prefix.length;
            enabled = value;
          }
        }
      }
    }
    return enabled;
  } || emptyFn, clone:function(item, cloneDom) {
    if (item == null) {
      return item;
    }
    if (cloneDom !== false && item.nodeType && item.cloneNode) {
      return item.cloneNode(true);
    }
    var type = toString.call(item), i, j, k, clone, key;
    if (type === '[object Date]') {
      return new Date(item.getTime());
    }
    if (type === '[object Array]') {
      i = item.length;
      clone = [];
      while (i--) {
        clone[i] = Ext.clone(item[i], cloneDom);
      }
    } else {
      if (type === '[object Object]' && item.constructor === Object) {
        clone = {};
        for (key in item) {
          clone[key] = Ext.clone(item[key], cloneDom);
        }
        if (enumerables) {
          for (j = enumerables.length; j--;) {
            k = enumerables[j];
            if (item.hasOwnProperty(k)) {
              clone[k] = item[k];
            }
          }
        }
      }
    }
    return clone || item;
  }, getUniqueGlobalNamespace:function() {
    var uniqueGlobalNamespace = this.uniqueGlobalNamespace, i;
    if (uniqueGlobalNamespace === undefined) {
      i = 0;
      do {
        uniqueGlobalNamespace = 'ExtBox' + ++i;
      } while (global[uniqueGlobalNamespace] !== undefined);
      global[uniqueGlobalNamespace] = Ext;
      this.uniqueGlobalNamespace = uniqueGlobalNamespace;
    }
    return uniqueGlobalNamespace;
  }, functionFactoryCache:{}, cacheableFunctionFactory:function() {
    var me = this, args = Array.prototype.slice.call(arguments), cache = me.functionFactoryCache, idx, fn, ln;
    if (Ext.isSandboxed) {
      ln = args.length;
      if (ln > 0) {
        ln--;
        args[ln] = 'var Ext\x3dwindow.' + Ext.name + ';' + args[ln];
      }
    }
    idx = args.join('');
    fn = cache[idx];
    if (!fn) {
      fn = Function.prototype.constructor.apply(Function.prototype, args);
      cache[idx] = fn;
    }
    return fn;
  }, functionFactory:function() {
    var args = Array.prototype.slice.call(arguments), ln;
    if (Ext.isSandboxed) {
      ln = args.length;
      if (ln > 0) {
        ln--;
        args[ln] = 'var Ext\x3dwindow.' + Ext.name + ';' + args[ln];
      }
    }
    return Function.prototype.constructor.apply(Function.prototype, args);
  }, Logger:{log:function(message, priority) {
    if (message && global.console) {
      if (!priority || !(priority in global.console)) {
        priority = 'log';
      }
      message = '[' + priority.toUpperCase() + '] ' + message;
      global.console[priority](message);
    }
  }, verbose:function(message) {
    this.log(message, 'verbose');
  }, info:function(message) {
    this.log(message, 'info');
  }, warn:function(message) {
    this.log(message, 'warn');
  }, error:function(message) {
    throw new Error(message);
  }, deprecate:function(message) {
    this.log(message, 'warn');
  }} || {verbose:emptyFn, log:emptyFn, info:emptyFn, warn:emptyFn, error:function(message) {
    throw new Error(message);
  }, deprecate:emptyFn}, ariaWarn:function(target, msg) {
    if (Ext.enableAria && !Ext.slicer) {
      if (!Ext.ariaWarn.first) {
        Ext.ariaWarn.first = true;
        Ext.log.warn('WAI-ARIA compatibility warnings can be suppressed ' + 'by adding the following to application startup code:');
        Ext.log.warn('    Ext.ariaWarn \x3d Ext.emptyFn;');
      }
      Ext.log.warn({msg:msg, dump:target});
    }
  }, getElementById:function(id) {
    return document.getElementById(id);
  }, splitAndUnescape:function() {
    var cache = {};
    return function(origin, delimiter) {
      if (!origin) {
        return [];
      } else {
        if (!delimiter) {
          return [origin];
        }
      }
      var replaceRe = cache[delimiter] || (cache[delimiter] = new RegExp('\\\\' + delimiter, 'g')), result = [], parts, part;
      parts = origin.split(delimiter);
      while ((part = parts.shift()) !== undefined) {
        while (part.charAt(part.length - 1) === '\\' && parts.length > 0) {
          part = part + delimiter + parts.shift();
        }
        part = part.replace(replaceRe, delimiter);
        result.push(part);
      }
      return result;
    };
  }(), doElevate:function() {
    var fn = elevateFn, args = elevateArgs, scope = elevateScope;
    elevateFn = elevateArgs = elevateScope = null;
    elevateRet = args ? fn.apply(scope, args) : fn.call(scope);
    Ext.fireIdle();
  }, elevate:function(fn, scope, args, timer) {
    var ret;
    if (args && !args.length) {
      args = null;
    }
    Ext._suppressIdle = false;
    if (timer) {
      timer.tick();
    }
    if (Ext.elevateFunction) {
      elevateFn = fn;
      elevateScope = scope;
      elevateArgs = args;
      Ext.elevateFunction(Ext.doElevate);
      ret = elevateRet;
      elevateRet = null;
    } else {
      ret = args ? fn.apply(scope, args) : fn.call(scope);
      Ext.fireIdle();
    }
    if (timer) {
      timer.tock();
    }
    return ret;
  }, Timer:{all:{}, track:false, captureStack:true, created:function(kind, id, info) {
    if (!Ext.Timer.track) {
      return null;
    }
    var timer = Ext.apply({kind:kind, id:id, done:false, firing:false, creator:Ext.Timer.captureStack ? (new Error).stack : null, tick:Ext.Timer.tick, tock:Ext.Timer.tock}, info);
    var timers = Ext.Timer.all[kind] || (Ext.Timer.all[kind] = {});
    timers[timer.id] = timer;
    if (Ext.Timer.hook) {
      Ext.Timer.hook(timer);
    }
    return timer;
  }, get:function(id, kind) {
    kind = kind || 'timeout';
    var timers = Ext.Timer.all[kind];
    return timers && timers[id] || null;
  }, cancel:function(kind, id) {
    var timers = Ext.Timer.all[kind], timer = timers && timers[id];
    if (timer) {
      timer.cancelled = true;
      timers[id] = null;
      delete timers[id];
    }
  }, tick:function() {
    if (Ext.Timer.firing) {
      Ext.log.error('Previous timer state not cleaned up properly: ' + Ext.Timer.firing.creator);
    }
    if (this.kind !== 'interval') {
      this.done = true;
      Ext.Timer.all[this.kind][this.id] = null;
      delete Ext.Timer.all[this.kind][this.id];
    }
    this.firing = true;
    Ext.Timer.firing = this;
  }, tock:function() {
    this.firing = false;
    if (Ext.Timer.firing === this) {
      Ext.Timer.firing = null;
    }
  }}, getExpando:function(target, id) {
    var expandos = target.$expandos;
    return expandos && expandos[id] || null;
  }, setExpando:function(target, id, value) {
    var expandos = target.$expandos;
    if (value !== undefined) {
      (expandos || (target.$expandos = {}))[id] = value;
    } else {
      if (expandos) {
        delete expandos[id];
      }
    }
    return value;
  }});
  Ext.returnTrue.$nullFn = Ext.returnId.$nullFn = true;
})();
Ext.platformTags.classic = !(Ext.platformTags.modern = Ext.isModern = true);
(function() {
  function toString() {
    var me = this, cls = me.sourceClass, method = me.sourceMethod, msg = me.msg;
    if (method) {
      if (msg) {
        method += '(): ';
        method += msg;
      } else {
        method += '()';
      }
    }
    if (cls) {
      method = method ? cls + '.' + method : cls;
    }
    return method || msg || '';
  }
  Ext.Error = function(config) {
    var error = new Error;
    if (Ext.isString(config)) {
      config = {msg:config};
    }
    Ext.apply(error, config);
    error.message = error.message || error.msg;
    error.toString = toString;
    return error;
  };
  Ext.apply(Ext.Error, {ignore:false, raise:function(err) {
    var me = this, method = me.raise.caller, msg, name;
    err = err || {};
    if (Ext.isString(err)) {
      err = {msg:err};
    }
    if (method === Ext.raise) {
      method = method.caller;
    }
    if (method) {
      if (!err.sourceMethod && (name = method.$name)) {
        err.sourceMethod = name;
      }
      if (!err.sourceClass && (name = method.$owner) && (name = name.$className)) {
        err.sourceClass = name;
      }
    }
    if (me.handle(err) !== true) {
      msg = toString.call(err);
      Ext.log({msg:msg, level:'error', dump:err, stack:true});
      throw new Ext.Error(err);
    }
  }, handle:function() {
    return this.ignore;
  }});
})();
Ext.deprecated = function(suggestion) {
  if (!suggestion) {
    suggestion = '';
  }
  function fail() {
    Ext.raise('The method "' + fail.$owner.$className + '.' + fail.$name + '" has been removed. ' + suggestion);
  }
  return fail;
  return Ext.emptyFn;
};
Ext.raise = function() {
  Ext.Error.raise.apply(Ext.Error, arguments);
};
(function(skipNotify) {
  if (skipNotify || typeof window === 'undefined') {
    return;
  }
  var last = 0, notify = function() {
    var cnt = Ext.log && Ext.log.counters, n = cnt && cnt.error + cnt.warn + cnt.info + cnt.log, msg;
    if (n && last !== n) {
      msg = [];
      if (cnt.error) {
        msg.push('Errors: ' + cnt.error);
      }
      if (cnt.warn) {
        msg.push('Warnings: ' + cnt.warn);
      }
      if (cnt.info) {
        msg.push('Info: ' + cnt.info);
      }
      if (cnt.log) {
        msg.push('Log: ' + cnt.log);
      }
      window.status = '*** ' + msg.join(' -- ');
      last = n;
    }
  };
  notify.$skipTimerCheck = true;
  setInterval(notify, 1000);
})(!!window.__UNIT_TESTING__);
Ext.Array = function() {
  var arrayPrototype = Array.prototype, slice = arrayPrototype.slice, supportsSplice = function() {
    var array = [], lengthBefore, j = 20;
    if (!array.splice) {
      return false;
    }
    while (j--) {
      array.push('A');
    }
    array.splice(15, 0, 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F');
    lengthBefore = array.length;
    array.splice(13, 0, 'XXX');
    if (lengthBefore + 1 !== array.length) {
      return false;
    }
    return true;
  }(), supportsIndexOf = 'indexOf' in arrayPrototype, supportsSliceOnNodeList = true;
  function stableSort(array, userComparator) {
    var len = array.length, indices = new Array(len), i;
    for (i = 0; i < len; i++) {
      indices[i] = i;
    }
    indices.sort(function(index1, index2) {
      return userComparator(array[index1], array[index2]) || index1 - index2;
    });
    for (i = 0; i < len; i++) {
      indices[i] = array[indices[i]];
    }
    for (i = 0; i < len; i++) {
      array[i] = indices[i];
    }
    return array;
  }
  try {
    if (typeof document !== 'undefined') {
      slice.call(document.getElementsByTagName('body'));
    }
  } catch (e$29) {
    supportsSliceOnNodeList = false;
  }
  var fixArrayIndex = function(array, index) {
    return index < 0 ? Math.max(0, array.length + index) : Math.min(array.length, index);
  }, replaceSim = function(array, index, removeCount, insert) {
    var add = insert ? insert.length : 0, length = array.length, pos = fixArrayIndex(array, index);
    if (pos === length) {
      if (add) {
        array.push.apply(array, insert);
      }
    } else {
      var remove = Math.min(removeCount, length - pos), tailOldPos = pos + remove, tailNewPos = tailOldPos + add - remove, tailCount = length - tailOldPos, lengthAfterRemove = length - remove, i;
      if (tailNewPos < tailOldPos) {
        for (i = 0; i < tailCount; ++i) {
          array[tailNewPos + i] = array[tailOldPos + i];
        }
      } else {
        if (tailNewPos > tailOldPos) {
          for (i = tailCount; i--;) {
            array[tailNewPos + i] = array[tailOldPos + i];
          }
        }
      }
      if (add && pos === lengthAfterRemove) {
        array.length = lengthAfterRemove;
        array.push.apply(array, insert);
      } else {
        array.length = lengthAfterRemove + add;
        for (i = 0; i < add; ++i) {
          array[pos + i] = insert[i];
        }
      }
    }
    return array;
  }, replaceNative = function(array, index, removeCount, insert) {
    if (insert && insert.length) {
      if (index === 0 && !removeCount) {
        array.unshift.apply(array, insert);
      } else {
        if (index < array.length) {
          array.splice.apply(array, [index, removeCount].concat(insert));
        } else {
          array.push.apply(array, insert);
        }
      }
    } else {
      array.splice(index, removeCount);
    }
    return array;
  }, eraseSim = function(array, index, removeCount) {
    return replaceSim(array, index, removeCount);
  }, eraseNative = function(array, index, removeCount) {
    array.splice(index, removeCount);
    return array;
  }, spliceSim = function(array, index, removeCount) {
    var len = arguments.length, pos = fixArrayIndex(array, index), removed;
    if (len < 3) {
      removeCount = array.length - pos;
    }
    removed = array.slice(index, fixArrayIndex(array, pos + removeCount));
    if (len < 4) {
      replaceSim(array, pos, removeCount);
    } else {
      replaceSim(array, pos, removeCount, slice.call(arguments, 3));
    }
    return removed;
  }, spliceNative = function(array) {
    return array.splice.apply(array, slice.call(arguments, 1));
  }, erase = supportsSplice ? eraseNative : eraseSim, replace = supportsSplice ? replaceNative : replaceSim, splice = supportsSplice ? spliceNative : spliceSim, ExtArray = {binarySearch:function(array, item, begin, end, compareFn) {
    var length = array.length, middle, comparison;
    if (begin instanceof Function) {
      compareFn = begin;
      begin = 0;
      end = length;
    } else {
      if (end instanceof Function) {
        compareFn = end;
        end = length;
      } else {
        if (begin === undefined) {
          begin = 0;
        }
        if (end === undefined) {
          end = length;
        }
        compareFn = compareFn || ExtArray.lexicalCompare;
      }
    }
    --end;
    while (begin <= end) {
      middle = begin + end >> 1;
      comparison = compareFn(item, array[middle]);
      if (comparison >= 0) {
        begin = middle + 1;
      } else {
        if (comparison < 0) {
          end = middle - 1;
        }
      }
    }
    return begin;
  }, defaultCompare:function(lhs, rhs) {
    return lhs < rhs ? -1 : lhs > rhs ? 1 : 0;
  }, lexicalCompare:function(lhs, rhs) {
    lhs = String(lhs);
    rhs = String(rhs);
    return lhs < rhs ? -1 : lhs > rhs ? 1 : 0;
  }, each:function(array, fn, scope, reverse) {
    var i, ln;
    array = ExtArray.from(array);
    ln = array.length;
    if (reverse !== true) {
      for (i = 0; i < ln; i++) {
        if (fn.call(scope || array[i], array[i], i, array) === false) {
          return i;
        }
      }
    } else {
      for (i = ln - 1; i > -1; i--) {
        if (fn.call(scope || array[i], array[i], i, array) === false) {
          return i;
        }
      }
    }
    return true;
  }, findInsertionIndex:function(item, items, comparatorFn, index) {
    var len = items.length, beforeCheck, afterCheck;
    comparatorFn = comparatorFn || ExtArray.lexicalCompare;
    if (0 <= index && index < len) {
      beforeCheck = index > 0 ? comparatorFn(item, items[index - 1]) : 0;
      afterCheck = index < len ? comparatorFn(item, items[index]) : 0;
      if (0 <= beforeCheck && afterCheck < 1) {
        return index;
      }
    }
    return ExtArray.binarySearch(items, item, comparatorFn);
  }, forEach:'forEach' in arrayPrototype ? function(array, fn, scope) {
    array.forEach(fn, scope);
  } : function(array, fn, scope) {
    var i, ln;
    for (i = 0, ln = array.length; i < ln; i++) {
      fn.call(scope, array[i], i, array);
    }
  }, indexOf:supportsIndexOf ? function(array, item, from) {
    return array ? arrayPrototype.indexOf.call(array, item, from) : -1;
  } : function(array, item, from) {
    var i, length = array ? array.length : 0;
    for (i = from < 0 ? Math.max(0, length + from) : from || 0; i < length; i++) {
      if (array[i] === item) {
        return i;
      }
    }
    return -1;
  }, contains:supportsIndexOf ? function(array, item) {
    return arrayPrototype.indexOf.call(array, item) !== -1;
  } : function(array, item) {
    var i, ln;
    for (i = 0, ln = array.length; i < ln; i++) {
      if (array[i] === item) {
        return true;
      }
    }
    return false;
  }, toArray:function(iterable, start, end) {
    var array = [], i;
    if (!iterable || !iterable.length) {
      return array;
    }
    if (typeof iterable === 'string') {
      iterable = iterable.split('');
    }
    if (supportsSliceOnNodeList) {
      return slice.call(iterable, start || 0, end || iterable.length);
    }
    start = start || 0;
    end = end ? end < 0 ? iterable.length + end : end : iterable.length;
    for (i = start; i < end; i++) {
      array.push(iterable[i]);
    }
    return array;
  }, pluck:function(array, propertyName) {
    var ret = [], i, ln, item;
    for (i = 0, ln = array.length; i < ln; i++) {
      item = array[i];
      ret.push(item[propertyName]);
    }
    return ret;
  }, map:'map' in arrayPrototype ? function(array, fn, scope) {
    Ext.Assert.isFunction(fn, 'Ext.Array.map must have a callback function passed as second argument.');
    return array.map(fn, scope);
  } : function(array, fn, scope) {
    Ext.Assert.isFunction(fn, 'Ext.Array.map must have a callback function passed as second argument.');
    var len = array.length, results = new Array(len), i;
    for (i = 0; i < len; i++) {
      results[i] = fn.call(scope, array[i], i, array);
    }
    return results;
  }, every:'every' in arrayPrototype ? function(array, fn, scope) {
    Ext.Assert.isFunction(fn, 'Ext.Array.every must have a callback function passed as second argument.');
    return array.every(fn, scope);
  } : function(array, fn, scope) {
    var i, ln;
    Ext.Assert.isFunction(fn, 'Ext.Array.every must have a callback function passed as second argument.');
    for (i = 0, ln = array.length; i < ln; ++i) {
      if (!fn.call(scope, array[i], i, array)) {
        return false;
      }
    }
    return true;
  }, some:'some' in arrayPrototype ? function(array, fn, scope) {
    Ext.Assert.isFunction(fn, 'Ext.Array.some must have a callback function passed as second argument.');
    return array.some(fn, scope);
  } : function(array, fn, scope) {
    var i, ln;
    Ext.Assert.isFunction(fn, 'Ext.Array.some must have a callback function passed as second argument.');
    for (i = 0, ln = array.length; i < ln; ++i) {
      if (fn.call(scope, array[i], i, array)) {
        return true;
      }
    }
    return false;
  }, equals:function(array1, array2) {
    var len1 = array1.length, len2 = array2.length, i;
    if (array1 === array2) {
      return true;
    }
    if (len1 !== len2) {
      return false;
    }
    for (i = 0; i < len1; ++i) {
      if (array1[i] !== array2[i]) {
        return false;
      }
    }
    return true;
  }, clean:function(array) {
    var results = [], i, ln, item;
    for (i = 0, ln = array.length; i < ln; i++) {
      item = array[i];
      if (!Ext.isEmpty(item)) {
        results.push(item);
      }
    }
    return results;
  }, unique:function(array) {
    var clone = [], i, ln, item;
    for (i = 0, ln = array.length; i < ln; i++) {
      item = array[i];
      if (ExtArray.indexOf(clone, item) === -1) {
        clone.push(item);
      }
    }
    return clone;
  }, filter:'filter' in arrayPrototype ? function(array, fn, scope) {
    Ext.Assert.isFunction(fn, 'Ext.Array.filter must have a filter function passed as second argument.');
    return array.filter(fn, scope);
  } : function(array, fn, scope) {
    var results = [], i, ln;
    Ext.Assert.isFunction(fn, 'Ext.Array.filter must have a filter function passed as second argument.');
    for (i = 0, ln = array.length; i < ln; i++) {
      if (fn.call(scope, array[i], i, array)) {
        results.push(array[i]);
      }
    }
    return results;
  }, findBy:function(array, fn, scope) {
    var i, len;
    for (i = 0, len = array.length; i < len; i++) {
      if (fn.call(scope || array, array[i], i)) {
        return array[i];
      }
    }
    return null;
  }, from:function(value, newReference) {
    var type;
    if (value === undefined || value === null) {
      return [];
    }
    if (Ext.isArray(value)) {
      return newReference ? slice.call(value) : value;
    }
    type = typeof value;
    if (value && value.length !== undefined && type !== 'string' && (type !== 'function' || !value.apply)) {
      return ExtArray.toArray(value);
    }
    return [value];
  }, remove:function(array, item) {
    var index = ExtArray.indexOf(array, item);
    if (index !== -1) {
      erase(array, index, 1);
    }
    return array;
  }, removeAt:function(array, index, count) {
    var len = array.length;
    if (index >= 0 && index < len) {
      count = count || 1;
      count = Math.min(count, len - index);
      erase(array, index, count);
    }
    return array;
  }, include:function(array, item) {
    if (!ExtArray.contains(array, item)) {
      array.push(item);
    }
  }, clone:function(array) {
    return slice.call(array);
  }, merge:function() {
    var args = slice.call(arguments), array = [], i, ln;
    for (i = 0, ln = args.length; i < ln; i++) {
      array = array.concat(args[i]);
    }
    return ExtArray.unique(array);
  }, intersect:function() {
    var intersection = [], arrays = slice.call(arguments), arraysLength, array, arrayLength, minArray, minArrayIndex, minArrayCandidate, minArrayLength, element, elementCandidate, elementCount, i, j, k;
    if (!arrays.length) {
      return intersection;
    }
    arraysLength = arrays.length;
    for (i = minArrayIndex = 0; i < arraysLength; i++) {
      minArrayCandidate = arrays[i];
      if (!minArray || minArrayCandidate.length < minArray.length) {
        minArray = minArrayCandidate;
        minArrayIndex = i;
      }
    }
    minArray = ExtArray.unique(minArray);
    erase(arrays, minArrayIndex, 1);
    minArrayLength = minArray.length;
    arraysLength = arrays.length;
    for (i = 0; i < minArrayLength; i++) {
      element = minArray[i];
      elementCount = 0;
      for (j = 0; j < arraysLength; j++) {
        array = arrays[j];
        arrayLength = array.length;
        for (k = 0; k < arrayLength; k++) {
          elementCandidate = array[k];
          if (element === elementCandidate) {
            elementCount++;
            break;
          }
        }
      }
      if (elementCount === arraysLength) {
        intersection.push(element);
      }
    }
    return intersection;
  }, difference:function(arrayA, arrayB) {
    var clone = slice.call(arrayA), ln = clone.length, i, j, lnB;
    for (i = 0, lnB = arrayB.length; i < lnB; i++) {
      for (j = 0; j < ln; j++) {
        if (clone[j] === arrayB[i]) {
          erase(clone, j, 1);
          j--;
          ln--;
        }
      }
    }
    return clone;
  }, reduce:Array.prototype.reduce ? function(array, reduceFn, initialValue) {
    if (arguments.length === 3) {
      return Array.prototype.reduce.call(array, reduceFn, initialValue);
    }
    return Array.prototype.reduce.call(array, reduceFn);
  } : function(array, reduceFn, initialValue) {
    array = Object(array);
    if (!Ext.isFunction(reduceFn)) {
      Ext.raise('Invalid parameter: expected a function.');
    }
    var index = 0, length = array.length >>> 0, reduced = initialValue;
    if (arguments.length < 3) {
      while (true) {
        if (index in array) {
          reduced = array[index++];
          break;
        }
        if (++index >= length) {
          throw new TypeError('Reduce of empty array with no initial value');
        }
      }
    }
    for (; index < length; ++index) {
      if (index in array) {
        reduced = reduceFn(reduced, array[index], index, array);
      }
    }
    return reduced;
  }, slice:[1, 2].slice(1, undefined).length ? function(array, begin, end) {
    return slice.call(array, begin, end);
  } : function(array, begin, end) {
    if (typeof begin === 'undefined') {
      return slice.call(array);
    }
    if (typeof end === 'undefined') {
      return slice.call(array, begin);
    }
    return slice.call(array, begin, end);
  }, sort:function(array, sortFn) {
    return stableSort(array, sortFn || ExtArray.lexicalCompare);
  }, flatten:function(array) {
    var worker = [];
    function rFlatten(a) {
      var i, ln, v;
      for (i = 0, ln = a.length; i < ln; i++) {
        v = a[i];
        if (Ext.isArray(v)) {
          rFlatten(v);
        } else {
          worker.push(v);
        }
      }
      return worker;
    }
    return rFlatten(array);
  }, min:function(array, comparisonFn) {
    var min = array[0], i, ln, item;
    for (i = 0, ln = array.length; i < ln; i++) {
      item = array[i];
      if (comparisonFn) {
        if (comparisonFn(min, item) === 1) {
          min = item;
        }
      } else {
        if (item < min) {
          min = item;
        }
      }
    }
    return min;
  }, max:function(array, comparisonFn) {
    var max = array[0], i, ln, item;
    for (i = 0, ln = array.length; i < ln; i++) {
      item = array[i];
      if (comparisonFn) {
        if (comparisonFn(max, item) === -1) {
          max = item;
        }
      } else {
        if (item > max) {
          max = item;
        }
      }
    }
    return max;
  }, mean:function(array) {
    return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
  }, sum:function(array) {
    var sum = 0, i, ln, item;
    for (i = 0, ln = array.length; i < ln; i++) {
      item = array[i];
      sum += item;
    }
    return sum;
  }, toMap:function(strings, getKey, scope) {
    var map, i;
    if (!strings) {
      return null;
    }
    map = {};
    i = strings.length;
    if (typeof strings === 'string') {
      map[strings] = 1;
    } else {
      if (!getKey) {
        while (i--) {
          map[strings[i]] = i + 1;
        }
      } else {
        if (typeof getKey === 'string') {
          while (i--) {
            map[strings[i][getKey]] = i + 1;
          }
        } else {
          while (i--) {
            map[getKey.call(scope, strings[i])] = i + 1;
          }
        }
      }
    }
    return map;
  }, toValueMap:function(array, getKey, scope, arrayify) {
    var map = {}, i = array.length, autoArray, alwaysArray, entry, fn, key, value;
    if (!getKey) {
      while (i--) {
        value = array[i];
        map[value] = value;
      }
    } else {
      if (!(fn = typeof getKey !== 'string')) {
        arrayify = scope;
      }
      alwaysArray = arrayify === 1;
      autoArray = arrayify === 2;
      while (i--) {
        value = array[i];
        key = fn ? getKey.call(scope, value) : value[getKey];
        if (alwaysArray) {
          if (key in map) {
            map[key].push(value);
          } else {
            map[key] = [value];
          }
        } else {
          if (autoArray && key in map) {
            if ((entry = map[key]) instanceof Array) {
              entry.push(value);
            } else {
              map[key] = [entry, value];
            }
          } else {
            map[key] = value;
          }
        }
      }
    }
    return map;
  }, _replaceSim:replaceSim, _spliceSim:spliceSim, erase:erase, insert:function(array, index, items) {
    return replace(array, index, 0, items);
  }, move:function(array, fromIdx, toIdx) {
    if (toIdx === fromIdx) {
      return;
    }
    var item = array[fromIdx], incr = toIdx > fromIdx ? 1 : -1, i;
    for (i = fromIdx; i !== toIdx; i += incr) {
      array[i] = array[i + incr];
    }
    array[toIdx] = item;
  }, replace:replace, splice:splice, push:function(target) {
    var args = arguments, len = args.length, i, newItem;
    if (target === undefined) {
      target = [];
    } else {
      if (!Ext.isArray(target)) {
        target = [target];
      }
    }
    for (i = 1; i < len; i++) {
      newItem = args[i];
      Array.prototype.push[Ext.isIterable(newItem) ? 'apply' : 'call'](target, newItem);
    }
    return target;
  }, numericSortFn:function(a, b) {
    return a - b;
  }};
  Ext.each = ExtArray.each;
  ExtArray.union = ExtArray.merge;
  Ext.min = ExtArray.min;
  Ext.max = ExtArray.max;
  Ext.sum = ExtArray.sum;
  Ext.mean = ExtArray.mean;
  Ext.flatten = ExtArray.flatten;
  Ext.clean = ExtArray.clean;
  Ext.unique = ExtArray.unique;
  Ext.pluck = ExtArray.pluck;
  Ext.toArray = function() {
    return ExtArray.toArray.apply(ExtArray, arguments);
  };
  return ExtArray;
}();
Ext.Assert = {falsey:function(b, msg) {
  if (b) {
    Ext.raise(msg || 'Expected a falsey value but was ' + b);
  }
}, falseyProp:function(object, property) {
  var b;
  Ext.Assert.truthy(object);
  b = object[property];
  if (b) {
    if (object.$className) {
      property = object.$className + '#' + property;
    }
    Ext.raise('Expected a falsey value for ' + property + ' but was ' + b);
  }
}, truthy:function(b, msg) {
  if (!b) {
    Ext.raise(msg || 'Expected a truthy value but was ' + typeof b);
  }
}, truthyProp:function(object, property) {
  var b;
  Ext.Assert.truthy(object);
  b = object[property];
  if (!b) {
    if (object.$className) {
      property = object.$className + '#' + property;
    }
    Ext.raise('Expected a truthy value for ' + property + ' but was ' + typeof b);
  }
}};
(function() {
  var name, kind;
  function makeAssert(name, kind) {
    var testFn = Ext[name], def;
    return function(value, msg) {
      if (!testFn(value)) {
        Ext.raise(msg || def || (def = 'Expected value to be ' + kind));
      }
    };
  }
  function makeAssertProp(name, kind) {
    var testFn = Ext[name], def;
    return function(object, prop) {
      Ext.Assert.truthy(object);
      if (!testFn(object[prop])) {
        Ext.raise(def || (def = 'Expected ' + (object.$className ? object.$className + '#' : '') + prop + ' to be ' + kind));
      }
    };
  }
  function makeNotAssert(name, kind) {
    var testFn = Ext[name], def;
    return function(value, msg) {
      if (testFn(value)) {
        Ext.raise(msg || def || (def = 'Expected value to NOT be ' + kind));
      }
    };
  }
  function makeNotAssertProp(name, kind) {
    var testFn = Ext[name], def;
    return function(object, prop) {
      Ext.Assert.truthy(object);
      if (testFn(object[prop])) {
        Ext.raise(def || (def = 'Expected ' + (object.$className ? object.$className + '#' : '') + prop + ' to NOT be ' + kind));
      }
    };
  }
  for (name in Ext) {
    if (name.substring(0, 2) === 'is' && Ext.isFunction(Ext[name])) {
      kind = name.substring(2);
      Ext.Assert[name] = makeAssert(name, kind);
      Ext.Assert[name + 'Prop'] = makeAssertProp(name, kind);
      Ext.Assert['isNot' + kind] = makeNotAssert(name, kind);
      Ext.Assert['isNot' + kind + 'Prop'] = makeNotAssertProp(name, kind);
    }
  }
})();
Ext.String = function() {
  var trimRegex = /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g, escapeRe = /('|\\)/g, escapeRegexRe = /([-.*+?\^${}()|\[\]\/\\])/g, basicTrimRe = /^\s+|\s+$/g, whitespaceRe = /\s+/, varReplace = /(^[^a-z]*|[^\w])/gi, charToEntity, entityToChar, charToEntityRegex, 
  entityToCharRegex, htmlEncodeReplaceFn = function(match, capture) {
    return charToEntity[capture];
  }, htmlDecodeReplaceFn = function(match, capture) {
    return capture in entityToChar ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
  }, boundsCheck = function(s, other) {
    if (s === null || s === undefined || other === null || other === undefined) {
      return false;
    }
    return other.length <= s.length;
  }, fromCharCode = String.fromCharCode, ExtString;
  return ExtString = {fromCodePoint:String.fromCodePoint || function() {
    var codePoint, result = '', codeUnits = [], index = -1, length = arguments.length;
    while (++index < length) {
      codePoint = Number(arguments[index]);
      if (!isFinite(codePoint) || codePoint < 0 || codePoint > 1114111 || Math.floor(codePoint) !== codePoint) {
        Ext.raise('Invalid code point: ' + codePoint);
      }
      if (codePoint <= 65535) {
        codeUnits.push(codePoint);
      } else {
        codePoint -= 65536;
        codeUnits.push((codePoint >> 10) + 55296, codePoint % 1024 + 56320);
      }
      if (index + 1 === length) {
        result += fromCharCode(codeUnits);
        codeUnits.length = 0;
      }
    }
    return result;
  }, insert:function(s, value, index) {
    var len;
    if (!s) {
      return value;
    }
    if (!value) {
      return s;
    }
    len = s.length;
    if (!index && index !== 0) {
      index = len;
    }
    if (index < 0) {
      index *= -1;
      if (index >= len) {
        index = 0;
      } else {
        index = len - index;
      }
    }
    if (index === 0) {
      s = value + s;
    } else {
      if (index >= s.length) {
        s += value;
      } else {
        s = s.substr(0, index) + value + s.substr(index);
      }
    }
    return s;
  }, startsWith:function(s, start, ignoreCase) {
    var result = boundsCheck(s, start);
    if (result) {
      if (ignoreCase) {
        s = s.toLowerCase();
        start = start.toLowerCase();
      }
      result = s.lastIndexOf(start, 0) === 0;
    }
    return result;
  }, endsWith:function(s, end, ignoreCase) {
    var result = boundsCheck(s, end);
    if (result) {
      if (ignoreCase) {
        s = s.toLowerCase();
        end = end.toLowerCase();
      }
      result = s.indexOf(end, s.length - end.length) !== -1;
    }
    return result;
  }, createVarName:function(s) {
    return s.replace(varReplace, '');
  }, htmlEncode:function(value) {
    return !value ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
  }, htmlDecode:function(value) {
    return !value ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
  }, hasHtmlCharacters:function(s) {
    return charToEntityRegex.test(s);
  }, addCharacterEntities:function(newEntities) {
    var charKeys = [], entityKeys = [], key, echar;
    for (key in newEntities) {
      echar = newEntities[key];
      entityToChar[key] = echar;
      charToEntity[echar] = key;
      charKeys.push(echar);
      entityKeys.push(key);
    }
    charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
    entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|\x26#[0-9]{1,5};' + ')', 'g');
  }, resetCharacterEntities:function() {
    charToEntity = {};
    entityToChar = {};
    this.addCharacterEntities({'\x26amp;':'\x26', '\x26gt;':'\x3e', '\x26lt;':'\x3c', '\x26quot;':'"', '\x26#39;':"'"});
  }, urlAppend:function(url, string) {
    if (!Ext.isEmpty(string)) {
      return url + (url.indexOf('?') === -1 ? '?' : '\x26') + string;
    }
    return url;
  }, trim:function(string) {
    if (string) {
      string = string.replace(trimRegex, '');
    }
    return string || '';
  }, capitalize:function(string) {
    if (string) {
      string = string.charAt(0).toUpperCase() + string.substr(1);
    }
    return string || '';
  }, uncapitalize:function(string) {
    if (string) {
      string = string.charAt(0).toLowerCase() + string.substr(1);
    }
    return string || '';
  }, ellipsis:function(value, length, word) {
    var vs, index;
    if (value && value.length > length) {
      if (word) {
        vs = value.substr(0, length - 2);
        index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
        if (index !== -1 && index >= length - 15) {
          return vs.substr(0, index) + '...';
        }
      }
      return value.substr(0, length - 3) + '...';
    }
    return value;
  }, escapeRegex:function(string) {
    return string.replace(escapeRegexRe, '\\$1');
  }, createRegex:function(value, startsWith, endsWith, ignoreCase) {
    var ret = value;
    if (value != null && !value.exec) {
      ret = ExtString.escapeRegex(String(value));
      if (startsWith !== false) {
        ret = '^' + ret;
      }
      if (endsWith !== false) {
        ret += '$';
      }
      ret = new RegExp(ret, ignoreCase !== false ? 'i' : '');
    }
    return ret;
  }, escape:function(string) {
    return string.replace(escapeRe, '\\$1');
  }, toggle:function(string, value, other) {
    return string === value ? other : value;
  }, leftPad:function(string, size, character) {
    var result = String(string);
    character = character || ' ';
    while (result.length < size) {
      result = character + result;
    }
    return result;
  }, repeat:function(pattern, count, sep) {
    var buf = [], i;
    if (count < 1) {
      count = 0;
    }
    for (i = count; i--;) {
      buf.push(pattern);
    }
    return buf.join(sep || '');
  }, splitWords:function(words) {
    if (words && typeof words === 'string') {
      return words.replace(basicTrimRe, '').split(whitespaceRe);
    }
    return words || [];
  }};
}();
Ext.String.resetCharacterEntities();
Ext.htmlEncode = Ext.String.htmlEncode;
Ext.htmlDecode = Ext.String.htmlDecode;
Ext.urlAppend = Ext.String.urlAppend;
Ext.Date = function() {
  var utilDate, nativeDate = Date, stripEscapeRe = /(\\.)/g, hourInfoRe = /([gGhHisucUOPZ]|MS)/, dateInfoRe = /([djzmnYycU]|MS)/, slashRe = /\\/gi, numberTokenRe = /\{(\d+)\}/g, MSFormatRe = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/'), datePartsRe = /^(?:(\d{1,4})|(\w{3,}))[/\-.\\\s](?:(\d{1,2})|(\w{3,}))[/\-.\\\s](\d{1,4})$/, pad = Ext.String.leftPad, dayInfo = {d:true, j:true}, monthInfo = {F:true, m:true, M:true, n:true}, yearInfo = {o:true, Y:true, y:true}, code = ['var me \x3d this, dt, y, m, d, h, i, s, ms, o, O, z, zz, u, v, W, year, jan4, week1monday, daysInMonth, dayMatched,', 
  'def \x3d me.defaults,', 'from \x3d Ext.Number.from,', 'results \x3d String(input).match(me.parseRegexes[{0}]);', 'if(results){', '{1}', 'if(u !\x3d null){', 'v \x3d new Date(u * 1000);', '}else{', 'dt \x3d me.clearTime(new Date);', 'y \x3d from(y, from(def.y, dt.getFullYear()));', 'm \x3d from(m, from(def.m - 1, dt.getMonth()));', 'dayMatched \x3d d !\x3d\x3d undefined;', 'd \x3d from(d, from(def.d, dt.getDate()));', 'if (!dayMatched) {', 'dt.setDate(1);', 'dt.setMonth(m);', 'dt.setFullYear(y);', 
  'daysInMonth \x3d me.getDaysInMonth(dt);', 'if (d \x3e daysInMonth) {', 'd \x3d daysInMonth;', '}', '}', 'h  \x3d from(h, from(def.h, dt.getHours()));', 'i  \x3d from(i, from(def.i, dt.getMinutes()));', 's  \x3d from(s, from(def.s, dt.getSeconds()));', 'ms \x3d from(ms, from(def.ms, dt.getMilliseconds()));', 'if(z \x3e\x3d 0 \x26\x26 y \x3e\x3d 0){', 'v \x3d me.add(new Date(y \x3c 100 ? 100 : y, 0, 1, h, i, s, ms), me.YEAR, y \x3c 100 ? y - 100 : 0);', 'v \x3d !strict? v : (strict \x3d\x3d\x3d true \x26\x26 (z \x3c\x3d 364 || (me.isLeapYear(v) \x26\x26 z \x3c\x3d 365))? me.add(v, me.DAY, z) : null);', 
  '}else if(strict \x3d\x3d\x3d true \x26\x26 !me.isValid(y, m + 1, d, h, i, s, ms)){', 'v \x3d null;', '}else{', 'if (W) {', 'year \x3d y || (new Date()).getFullYear();', 'jan4 \x3d new Date(year, 0, 4, 0, 0, 0);', 'd \x3d jan4.getDay();', 'week1monday \x3d new Date(jan4.getTime() - ((d \x3d\x3d\x3d 0 ? 6 : d - 1) * 86400000));', 'v \x3d Ext.Date.clearTime(new Date(week1monday.getTime() + ((W - 1) * 604800000 + 43200000)));', '} else {', 'v \x3d me.add(new Date(y \x3c 100 ? 100 : y, m, d, h, i, s, ms), me.YEAR, y \x3c 100 ? y - 100 : 0);', 
  '}', '}', '}', '}', 'if(v){', 'if(zz !\x3d null){', 'v \x3d me.add(v, me.SECOND, -v.getTimezoneOffset() * 60 - zz);', '}else if(o){', "v \x3d me.add(v, me.MINUTE, -v.getTimezoneOffset() + (sn \x3d\x3d '+'? -1 : 1) * (hr * 60 + mn));", '}', '}', 'return (v !\x3d null) ? v : null;'].join('\n');
  if (!Date.prototype.toISOString) {
    Date.prototype.toISOString = function() {
      var me = this;
      return pad(me.getUTCFullYear(), 4, '0') + '-' + pad(me.getUTCMonth() + 1, 2, '0') + '-' + pad(me.getUTCDate(), 2, '0') + 'T' + pad(me.getUTCHours(), 2, '0') + ':' + pad(me.getUTCMinutes(), 2, '0') + ':' + pad(me.getUTCSeconds(), 2, '0') + '.' + pad(me.getUTCMilliseconds(), 3, '0') + 'Z';
    };
  }
  function xf(format) {
    var args = Array.prototype.slice.call(arguments, 1);
    return format.replace(numberTokenRe, function(m, i) {
      return args[i];
    });
  }
  utilDate = {now:nativeDate.now, toString:function(date) {
    if (!date) {
      date = new nativeDate;
    }
    return date.getFullYear() + '-' + pad(date.getMonth() + 1, 2, '0') + '-' + pad(date.getDate(), 2, '0') + 'T' + pad(date.getHours(), 2, '0') + ':' + pad(date.getMinutes(), 2, '0') + ':' + pad(date.getSeconds(), 2, '0');
  }, getElapsed:function(dateA, dateB) {
    return Math.abs(dateA - (dateB || utilDate.now()));
  }, useStrict:false, formatCodeToRegex:function(character, currentGroup) {
    var p = utilDate.parseCodes[character];
    if (p) {
      p = typeof p === 'function' ? p() : p;
      utilDate.parseCodes[character] = p;
    }
    return p ? Ext.applyIf({c:p.c ? xf(p.c, currentGroup || '{0}') : p.c}, p) : {g:0, c:null, s:Ext.String.escapeRegex(character)};
  }, parseFunctions:{'MS':function(input, strict) {
    var r = (input || '').match(MSFormatRe);
    return r ? new nativeDate(((r[1] || '') + r[2]) * 1) : null;
  }, 'time':function(input, strict) {
    var num = parseInt(input, 10);
    if (num || num === 0) {
      return new nativeDate(num);
    }
    return null;
  }, 'timestamp':function(input, strict) {
    var num = parseInt(input, 10);
    if (num || num === 0) {
      return new nativeDate(num * 1000);
    }
    return null;
  }}, parseRegexes:[], formatFunctions:{'MS':function() {
    return '\\/Date(' + this.getTime() + ')\\/';
  }, 'time':function() {
    return this.getTime().toString();
  }, 'timestamp':function() {
    return utilDate.format(this, 'U');
  }}, y2kYear:50, MILLI:'ms', SECOND:'s', MINUTE:'mi', HOUR:'h', DAY:'d', MONTH:'mo', YEAR:'y', DAYS_IN_WEEK:7, MONTHS_IN_YEAR:12, MAX_DAYS_IN_MONTH:31, SUNDAY:0, MONDAY:1, TUESDAY:2, WEDNESDAY:3, THURSDAY:4, FRIDAY:5, SATURDAY:6, defaults:{}, dayNames:['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], monthNames:['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], monthNumbers:{January:0, Jan:0, February:1, 
  Feb:1, March:2, Mar:2, April:3, Apr:3, May:4, June:5, Jun:5, July:6, Jul:6, August:7, Aug:7, September:8, Sep:8, October:9, Oct:9, November:10, Nov:10, December:11, Dec:11}, defaultFormat:'m/d/Y', defaultTimeFormat:'h:i A', firstDayOfWeek:0, weekendDays:[0, 6], getShortMonthName:function(month) {
    return utilDate.monthNames[month].substring(0, 3);
  }, getShortDayName:function(day) {
    return utilDate.dayNames[day].substring(0, 3);
  }, getMonthNumber:function(name) {
    return utilDate.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
  }, formatContainsHourInfo:function(format) {
    return hourInfoRe.test(format.replace(stripEscapeRe, ''));
  }, formatContainsDateInfo:function(format) {
    return dateInfoRe.test(format.replace(stripEscapeRe, ''));
  }, isMonthFormat:function(format) {
    return !!monthInfo[format];
  }, isYearFormat:function(format) {
    return !!yearInfo[format];
  }, unescapeFormat:function(format) {
    return format.replace(slashRe, '');
  }, formatCodes:{d:"Ext.String.leftPad(m.getDate(), 2, '0')", D:'Ext.Date.getShortDayName(m.getDay())', j:'m.getDate()', l:'Ext.Date.dayNames[m.getDay()]', N:'(m.getDay() ? m.getDay() : 7)', S:'Ext.Date.getSuffix(m)', w:'m.getDay()', z:'Ext.Date.getDayOfYear(m)', W:"Ext.String.leftPad(Ext.Date.getWeekOfYear(m), 2, '0')", F:'Ext.Date.monthNames[m.getMonth()]', m:"Ext.String.leftPad(m.getMonth() + 1, 2, '0')", M:'Ext.Date.getShortMonthName(m.getMonth())', n:'(m.getMonth() + 1)', t:'Ext.Date.getDaysInMonth(m)', 
  L:'(Ext.Date.isLeapYear(m) ? 1 : 0)', o:'(m.getFullYear() + (Ext.Date.getWeekOfYear(m) \x3d\x3d 1 \x26\x26 m.getMonth() \x3e 0 ? +1 : (Ext.Date.getWeekOfYear(m) \x3e\x3d 52 \x26\x26 m.getMonth() \x3c 11 ? -1 : 0)))', Y:"Ext.String.leftPad(m.getFullYear(), 4, '0')", y:"('' + m.getFullYear()).substring(2, 4)", a:"(m.getHours() \x3c 12 ? 'am' : 'pm')", A:"(m.getHours() \x3c 12 ? 'AM' : 'PM')", g:'((m.getHours() % 12) ? m.getHours() % 12 : 12)', G:'m.getHours()', h:"Ext.String.leftPad((m.getHours() % 12) ? m.getHours() % 12 : 12, 2, '0')", 
  H:"Ext.String.leftPad(m.getHours(), 2, '0')", i:"Ext.String.leftPad(m.getMinutes(), 2, '0')", s:"Ext.String.leftPad(m.getSeconds(), 2, '0')", u:"Ext.String.leftPad(m.getMilliseconds(), 3, '0')", O:'Ext.Date.getGMTOffset(m)', P:'Ext.Date.getGMTOffset(m, true)', T:'Ext.Date.getTimezone(m)', Z:'(m.getTimezoneOffset() * -60)', c:function() {
    var c = 'Y-m-dTH:i:sP', code = [], l = c.length, i, e;
    for (i = 0; i < l; ++i) {
      e = c.charAt(i);
      code.push(e === 'T' ? "'T'" : utilDate.getFormatCode(e));
    }
    return code.join(' + ');
  }, C:function() {
    return 'm.toISOString()';
  }, U:'Math.round(m.getTime() / 1000)'}, isValid:function(year, month, day, hour, minute, second, millisecond) {
    var dt;
    hour = hour || 0;
    minute = minute || 0;
    second = second || 0;
    millisecond = millisecond || 0;
    dt = utilDate.add(new nativeDate(year < 100 ? 100 : year, month - 1, day, hour, minute, second, millisecond), utilDate.YEAR, year < 100 ? year - 100 : 0);
    return year === dt.getFullYear() && month === dt.getMonth() + 1 && day === dt.getDate() && hour === dt.getHours() && minute === dt.getMinutes() && second === dt.getSeconds() && millisecond === dt.getMilliseconds();
  }, parse:function(input, format, strict) {
    var p;
    if (!format) {
      return utilDate.flexParse(input);
    }
    p = utilDate.parseFunctions;
    if (p[format] == null) {
      utilDate.createParser(format);
    }
    return p[format].call(utilDate, input, Ext.isDefined(strict) ? strict : utilDate.useStrict);
  }, parseDate:function(input, format, strict) {
    return utilDate.parse(input, format, strict);
  }, getFormatCode:function(character) {
    var f = utilDate.formatCodes[character];
    if (f) {
      f = typeof f === 'function' ? f() : f;
      utilDate.formatCodes[character] = f;
    }
    return f || "'" + Ext.String.escape(character) + "'";
  }, createFormat:function(format) {
    var code = [], special = false, ch = '', i;
    for (i = 0; i < format.length; ++i) {
      ch = format.charAt(i);
      if (!special && ch === '\\') {
        special = true;
      } else {
        if (special) {
          special = false;
          code.push("'" + Ext.String.escape(ch) + "'");
        } else {
          if (ch === '\n') {
            code.push("'\\n'");
          } else {
            code.push(utilDate.getFormatCode(ch));
          }
        }
      }
    }
    utilDate.formatFunctions[format] = Ext.functionFactory('var m \x3d this; return ' + code.join('+'));
  }, createParser:function(format) {
    var regexNum = utilDate.parseRegexes.length, currentGroup = 1, calc = [], regex = [], special = false, ch = '', i = 0, len = format.length, atEnd = [], obj;
    for (; i < len; ++i) {
      ch = format.charAt(i);
      if (!special && ch === '\\') {
        special = true;
      } else {
        if (special) {
          special = false;
          regex.push(Ext.String.escape(ch));
        } else {
          obj = utilDate.formatCodeToRegex(ch, currentGroup);
          currentGroup += obj.g;
          regex.push(obj.s);
          if (obj.g && obj.c) {
            if (obj.calcAtEnd) {
              atEnd.push(obj.c);
            } else {
              calc.push(obj.c);
            }
          }
        }
      }
    }
    calc = calc.concat(atEnd);
    utilDate.parseRegexes[regexNum] = new RegExp('^' + regex.join('') + '$', 'i');
    utilDate.parseFunctions[format] = Ext.functionFactory('input', 'strict', xf(code, regexNum, calc.join('')));
  }, parseCodes:{d:{g:1, c:'d \x3d parseInt(results[{0}], 10);\n', s:'(3[0-1]|[1-2][0-9]|0[1-9])'}, j:{g:1, c:'d \x3d parseInt(results[{0}], 10);\n', s:'(3[0-1]|[1-2][0-9]|[1-9])'}, D:function() {
    var a = [], i;
    for (i = 0; i < 7; i++) {
      a.push(utilDate.getShortDayName(i));
    }
    return {g:0, c:null, s:'(?:' + a.join('|') + ')'};
  }, l:function() {
    return {g:0, c:null, s:'(?:' + utilDate.dayNames.join('|') + ')'};
  }, N:{g:0, c:null, s:'[1-7]'}, S:{g:0, c:null, s:'(?:st|nd|rd|th)'}, w:{g:0, c:null, s:'[0-6]'}, z:{g:1, c:'z \x3d parseInt(results[{0}], 10);\n', s:'(\\d{1,3})'}, W:{g:1, c:'W \x3d parseInt(results[{0}], 10);\n', s:'(\\d{2})'}, F:function() {
    return {g:1, c:'m \x3d parseInt(me.getMonthNumber(results[{0}]), 10);\n', s:'(' + utilDate.monthNames.join('|') + ')'};
  }, M:function() {
    var a = [], i;
    for (i = 0; i < 12; i++) {
      a.push(utilDate.getShortMonthName(i));
    }
    return Ext.applyIf({s:'(' + a.join('|') + ')'}, utilDate.formatCodeToRegex('F'));
  }, m:{g:1, c:'m \x3d parseInt(results[{0}], 10) - 1;\n', s:'(1[0-2]|0[1-9])'}, n:{g:1, c:'m \x3d parseInt(results[{0}], 10) - 1;\n', s:'(1[0-2]|[1-9])'}, t:{g:0, c:null, s:'(?:\\d{2})'}, L:{g:0, c:null, s:'(?:1|0)'}, o:{g:1, c:'y \x3d parseInt(results[{0}], 10);\n', s:'(\\d{4})'}, Y:{g:1, c:'y \x3d parseInt(results[{0}], 10);\n', s:'(\\d{4})'}, y:{g:1, c:'var ty \x3d parseInt(results[{0}], 10);\n' + 'y \x3d ty \x3e me.y2kYear ? 1900 + ty : 2000 + ty;\n', s:'(\\d{2})'}, a:{g:1, c:'if (/(am)/i.test(results[{0}])) {\n' + 
  'if (!h || h \x3d\x3d 12) { h \x3d 0; }\n' + '} else { if (!h || h \x3c 12) { h \x3d (h || 0) + 12; }}', s:'(am|pm|AM|PM)', calcAtEnd:true}, A:{g:1, c:'if (/(am)/i.test(results[{0}])) {\n' + 'if (!h || h \x3d\x3d 12) { h \x3d 0; }\n' + '} else { if (!h || h \x3c 12) { h \x3d (h || 0) + 12; }}', s:'(AM|PM|am|pm)', calcAtEnd:true}, g:{g:1, c:'h \x3d parseInt(results[{0}], 10);\n', s:'(1[0-2]|[1-9])'}, G:{g:1, c:'h \x3d parseInt(results[{0}], 10);\n', s:'(2[0-3]|1[0-9]|[0-9])'}, h:{g:1, c:'h \x3d parseInt(results[{0}], 10);\n', 
  s:'(1[0-2]|0[1-9])'}, H:{g:1, c:'h \x3d parseInt(results[{0}], 10);\n', s:'(2[0-3]|[0-1][0-9])'}, i:{g:1, c:'i \x3d parseInt(results[{0}], 10);\n', s:'([0-5][0-9])'}, s:{g:1, c:'s \x3d parseInt(results[{0}], 10);\n', s:'([0-5][0-9])'}, u:{g:1, c:'ms \x3d results[{0}]; ms \x3d parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n', s:'(\\d+)'}, O:{g:1, c:['o \x3d results[{0}];', 'var sn \x3d o.substring(0,1),', 'hr \x3d o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),', 'mn \x3d o.substring(3,5) % 60;', 
  "o \x3d ((-12 \x3c\x3d (hr*60 + mn)/60) \x26\x26 ((hr*60 + mn)/60 \x3c\x3d 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n"].join('\n'), s:'([+-]\\d{4})'}, P:{g:1, c:['o \x3d results[{0}];', 'var sn \x3d o.substring(0,1),', 'hr \x3d o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),', 'mn \x3d o.substring(4,6) % 60;', "o \x3d ((-12 \x3c\x3d (hr*60 + mn)/60) \x26\x26 ((hr*60 + mn)/60 \x3c\x3d 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n"].join('\n'), 
  s:'([+-]\\d{2}:\\d{2})'}, T:{g:0, c:null, s:'[A-Z]{1,5}'}, Z:{g:1, c:'zz \x3d results[{0}] * 1;\n' + 'zz \x3d (-43200 \x3c\x3d zz \x26\x26 zz \x3c\x3d 50400)? zz : null;\n', s:'([+-]?\\d{1,5})'}, c:function() {
    var calc = [], arr = [utilDate.formatCodeToRegex('Y', 1), utilDate.formatCodeToRegex('m', 2), utilDate.formatCodeToRegex('d', 3), utilDate.formatCodeToRegex('H', 4), utilDate.formatCodeToRegex('i', 5), utilDate.formatCodeToRegex('s', 6), {c:"ms \x3d results[7] || '0'; ms \x3d parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, {c:['if (results[8]) {', "if (results[8] \x3d\x3d 'Z') {", 'zz \x3d 0;', '}', "else if (results[8].indexOf(':') \x3e -1) {", utilDate.formatCodeToRegex('P', 8).c, '}', 'else {', 
    utilDate.formatCodeToRegex('O', 8).c, '}', '}'].join('\n')}], i, l;
    for (i = 0, l = arr.length; i < l; ++i) {
      calc.push(arr[i].c);
    }
    return {g:1, c:calc.join(''), s:[arr[0].s, '(?:', '-', arr[1].s, '(?:', '-', arr[2].s, '(?:', '(?:T| )?', arr[3].s, ':', arr[4].s, '(?::', arr[5].s, ')?', '(?:(?:\\.|,)(\\d+))?', '(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?', ')?', ')?', ')?'].join('')};
  }, U:{g:1, c:'u \x3d parseInt(results[{0}], 10);\n', s:'(-?\\d+)'}}, compare:function(d1, d2, includeTime) {
    var s1, s2;
    if (typeof d1 === 'string') {
      d1 = Ext.Date.parse(d1);
    }
    if (typeof d2 === 'string') {
      d2 = Ext.Date.parse(d2);
    }
    s1 = Ext.Date.format(d1, 'C');
    s2 = Ext.Date.format(d2, 'C');
    if (!includeTime) {
      s1 = s1.substr(0, 10);
      s2 = s2.substr(0, 10);
    }
    return s1 < s2 ? -1 : s2 < s1 ? 1 : 0;
  }, dateFormat:function(date, format) {
    return utilDate.format(date, format);
  }, isEqual:function(date1, date2) {
    if (date1 && date2) {
      return +date1 === +date2;
    }
    return !(date1 || date2);
  }, format:function(date, format) {
    var formatFunctions = utilDate.formatFunctions;
    if (!Ext.isDate(date)) {
      return '';
    }
    if (formatFunctions[format] == null) {
      utilDate.createFormat(format);
    }
    return formatFunctions[format].call(date) + '';
  }, getTimezone:function(date) {
    return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,5})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, '$1$2').replace(/[^A-Z]/g, '');
  }, getGMTOffset:function(date, colon) {
    var offset = date.getTimezoneOffset();
    return (offset > 0 ? '-' : '+') + Ext.String.leftPad(Math.floor(Math.abs(offset) / 60), 2, '0') + (colon ? ':' : '') + Ext.String.leftPad(Math.abs(offset % 60), 2, '0');
  }, getDayOfYear:function(date) {
    var num = 0, d = utilDate.clone(date), m = date.getMonth(), i;
    for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
      num += utilDate.getDaysInMonth(d);
    }
    return num + date.getDate() - 1;
  }, getWeekOfYear:function() {
    var ms1d = 86400000, ms7d = 7 * ms1d;
    return function(date) {
      var DC3 = nativeDate.UTC(date.getFullYear(), date.getMonth(), date.getDate() + 3) / ms1d, AWN = Math.floor(DC3 / 7), Wyr = (new nativeDate(AWN * ms7d)).getUTCFullYear();
      return AWN - Math.floor(nativeDate.UTC(Wyr, 0, 7) / ms7d) + 1;
    };
  }(), isLeapYear:function(date) {
    var year = date.getFullYear();
    return !!((year & 3) === 0 && (year % 100 || year % 400 === 0 && year));
  }, getFirstDayOfMonth:function(date) {
    var day = (date.getDay() - (date.getDate() - 1)) % 7;
    return day < 0 ? day + 7 : day;
  }, getLastDayOfMonth:function(date) {
    return utilDate.getLastDateOfMonth(date).getDay();
  }, getFirstDateOfMonth:function(date) {
    return new nativeDate(date.getFullYear(), date.getMonth(), 1);
  }, getLastDateOfMonth:function(date) {
    return new nativeDate(date.getFullYear(), date.getMonth(), utilDate.getDaysInMonth(date));
  }, getDaysInMonth:function() {
    var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    return function(date) {
      var m = date.getMonth();
      return m === 1 && utilDate.isLeapYear(date) ? 29 : daysInMonth[m];
    };
  }(), getSuffix:function(date) {
    switch(date.getDate()) {
      case 1:
      case 21:
      case 31:
        return 'st';
      case 2:
      case 22:
        return 'nd';
      case 3:
      case 23:
        return 'rd';
      default:
        return 'th';
    }
  }, clone:function(date) {
    return new nativeDate(date.getTime());
  }, isDST:function(date) {
    return (new nativeDate(date.getFullYear(), 0, 1)).getTimezoneOffset() !== date.getTimezoneOffset();
  }, clearTime:function(date, clone) {
    var d, hr, c;
    if (isNaN(date.getTime())) {
      return date;
    }
    if (clone) {
      return utilDate.clearTime(utilDate.clone(date));
    }
    d = date.getDate();
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);
    if (date.getDate() !== d) {
      for (hr = 1, c = utilDate.add(date, utilDate.HOUR, hr); c.getDate() !== d; hr++, c = utilDate.add(date, utilDate.HOUR, hr)) {
      }
      date.setDate(d);
      date.setHours(c.getHours());
    }
    return date;
  }, add:function(date, interval, value, preventDstAdjust) {
    var d = utilDate.clone(date), base = 0, day, decimalValue;
    if (!interval || value === 0) {
      return d;
    }
    decimalValue = value - parseInt(value, 10);
    value = parseInt(value, 10);
    if (value) {
      switch(interval.toLowerCase()) {
        case utilDate.MILLI:
          if (preventDstAdjust) {
            d.setMilliseconds(d.getMilliseconds() + value);
          } else {
            d.setTime(d.getTime() + value);
          }
          break;
        case utilDate.SECOND:
          if (preventDstAdjust) {
            d.setSeconds(d.getSeconds() + value);
          } else {
            d.setTime(d.getTime() + value * 1000);
          }
          break;
        case utilDate.MINUTE:
          if (preventDstAdjust) {
            d.setMinutes(d.getMinutes() + value);
          } else {
            d.setTime(d.getTime() + value * 60 * 1000);
          }
          break;
        case utilDate.HOUR:
          if (preventDstAdjust) {
            d.setHours(d.getHours() + value);
          } else {
            d.setTime(d.getTime() + value * 60 * 60 * 1000);
          }
          break;
        case utilDate.DAY:
          if (preventDstAdjust === false) {
            d.setTime(d.getTime() + value * 24 * 60 * 60 * 1000);
          } else {
            d.setDate(d.getDate() + value);
          }
          break;
        case utilDate.MONTH:
          day = date.getDate();
          if (day > 28) {
            day = Math.min(day, utilDate.getLastDateOfMonth(utilDate.add(utilDate.getFirstDateOfMonth(date), utilDate.MONTH, value)).getDate());
          }
          d.setDate(day);
          d.setMonth(date.getMonth() + value);
          break;
        case utilDate.YEAR:
          day = date.getDate();
          if (day > 28) {
            day = Math.min(day, utilDate.getLastDateOfMonth(utilDate.add(utilDate.getFirstDateOfMonth(date), utilDate.YEAR, value)).getDate());
          }
          d.setDate(day);
          d.setFullYear(date.getFullYear() + value);
          break;
      }
    }
    if (decimalValue) {
      switch(interval.toLowerCase()) {
        case utilDate.MILLI:
          base = 1;
          break;
        case utilDate.SECOND:
          base = 1000;
          break;
        case utilDate.MINUTE:
          base = 1000 * 60;
          break;
        case utilDate.HOUR:
          base = 1000 * 60 * 60;
          break;
        case utilDate.DAY:
          base = 1000 * 60 * 60 * 24;
          break;
        case utilDate.MONTH:
          day = utilDate.getDaysInMonth(d);
          base = 1000 * 60 * 60 * 24 * day;
          break;
        case utilDate.YEAR:
          day = utilDate.isLeapYear(d) ? 366 : 365;
          base = 1000 * 60 * 60 * 24 * day;
          break;
      }
      if (base) {
        d.setTime(d.getTime() + base * decimalValue);
      }
    }
    return d;
  }, subtract:function(date, interval, value, preventDstAdjust) {
    return utilDate.add(date, interval, -value, preventDstAdjust);
  }, between:function(date, start, end) {
    var t = date.getTime();
    return start.getTime() <= t && t <= end.getTime();
  }, isWeekend:function(date) {
    return Ext.Array.indexOf(this.weekendDays, date.getDay()) > -1;
  }, utcToLocal:function(d) {
    return new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
  }, localToUtc:function(d) {
    return utilDate.utc(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
  }, utc:function(year, month, day, hour, min, s, ms) {
    return new Date(Date.UTC(year, month, day, hour || 0, min || 0, s || 0, ms || 0));
  }, compat:function() {
    var p, statics = ['useStrict', 'formatCodeToRegex', 'parseFunctions', 'parseRegexes', 'formatFunctions', 'y2kYear', 'MILLI', 'SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH', 'YEAR', 'defaults', 'dayNames', 'monthNames', 'monthNumbers', 'getShortMonthName', 'getShortDayName', 'getMonthNumber', 'formatCodes', 'isValid', 'parseDate', 'getFormatCode', 'createFormat', 'createParser', 'parseCodes'], proto = ['dateFormat', 'format', 'getTimezone', 'getGMTOffset', 'getDayOfYear', 'getWeekOfYear', 'isLeapYear', 
    'getFirstDayOfMonth', 'getLastDayOfMonth', 'getDaysInMonth', 'getSuffix', 'clone', 'isDST', 'clearTime', 'add', 'between'], sLen = statics.length, pLen = proto.length, stat, prot, s;
    for (s = 0; s < sLen; s++) {
      stat = statics[s];
      nativeDate[stat] = utilDate[stat];
    }
    for (p = 0; p < pLen; p++) {
      prot = proto[p];
      nativeDate.prototype[prot] = function() {
        var args = Array.prototype.slice.call(arguments);
        args.unshift(this);
        return utilDate[prot].apply(utilDate, args);
      };
    }
  }, diff:function(min, max, unit) {
    var diff = +max - min, est;
    switch(unit) {
      case utilDate.MILLI:
        return diff;
      case utilDate.SECOND:
        return Math.floor(diff / 1000);
      case utilDate.MINUTE:
        return Math.floor(diff / 60000);
      case utilDate.HOUR:
        return Math.floor(diff / 3600000);
      case utilDate.DAY:
        return Math.floor(diff / 86400000);
      case 'w':
        return Math.floor(diff / 604800000);
      case utilDate.MONTH:
        est = max.getFullYear() * 12 + max.getMonth() - (min.getFullYear() * 12 + min.getMonth());
        if (utilDate.add(min, unit, est) > max) {
          return est - 1;
        }
        return est;
      case utilDate.YEAR:
        est = max.getFullYear() - min.getFullYear();
        if (utilDate.add(min, unit, est) > max) {
          return est - 1;
        } else {
          return est;
        }
    }
  }, align:function(date, unit, step) {
    var num = new nativeDate(+date);
    switch(unit.toLowerCase()) {
      case utilDate.MILLI:
        return num;
      case utilDate.SECOND:
        num.setUTCSeconds(num.getUTCSeconds() - num.getUTCSeconds() % step);
        num.setUTCMilliseconds(0);
        return num;
      case utilDate.MINUTE:
        num.setUTCMinutes(num.getUTCMinutes() - num.getUTCMinutes() % step);
        num.setUTCSeconds(0);
        num.setUTCMilliseconds(0);
        return num;
      case utilDate.HOUR:
        num.setUTCHours(num.getUTCHours() - num.getUTCHours() % step);
        num.setUTCMinutes(0);
        num.setUTCSeconds(0);
        num.setUTCMilliseconds(0);
        return num;
      case utilDate.DAY:
        if (step === 7 || step === 14) {
          num.setUTCDate(num.getUTCDate() - num.getUTCDay() + 1);
        }
        num.setUTCHours(0);
        num.setUTCMinutes(0);
        num.setUTCSeconds(0);
        num.setUTCMilliseconds(0);
        return num;
      case utilDate.MONTH:
        num.setUTCMonth(num.getUTCMonth() - (num.getUTCMonth() - 1) % step, 1);
        num.setUTCHours(0);
        num.setUTCMinutes(0);
        num.setUTCSeconds(0);
        num.setUTCMilliseconds(0);
        return num;
      case utilDate.YEAR:
        num.setUTCFullYear(num.getUTCFullYear() - num.getUTCFullYear() % step, 1, 1);
        num.setUTCHours(0);
        num.setUTCMinutes(0);
        num.setUTCSeconds(0);
        num.setUTCMilliseconds(0);
        return date;
    }
  }, flexParse:function(inDate, defaultFormat) {
    var parts = datePartsRe.exec(inDate), firstFormatToken, day, month, year, result;
    if (!parts) {
      return Ext.Date.parse(inDate, 'C');
    }
    if (!defaultFormat) {
      defaultFormat = Ext.Date.defaultFormat;
    }
    if (!(parts[2] || parts[4])) {
      firstFormatToken = defaultFormat[0];
      if (!yearInfo[firstFormatToken] && (dayInfo[firstFormatToken] || parts[1] > 12 && parts[3] < 13)) {
        day = parseInt(parts[1]);
        month = parseInt(parts[3]) - 1;
        year = parseInt(parts[5]);
      } else {
        if (!yearInfo[firstFormatToken] && (monthInfo[firstFormatToken] || parts[3] > 12 && parts[1] < 13)) {
          month = parseInt(parts[1]) - 1;
          day = parseInt(parts[3]);
          year = parseInt(parts[5]);
        } else {
          year = parseInt(parts[1]);
          month = parseInt(parts[3]) - 1;
          day = parseInt(parts[5]);
        }
      }
    } else {
      if (parts[2] && parts[4]) {
        return null;
      }
      if (parts[2]) {
        month = utilDate.monthNumbers[Ext.String.capitalize(parts[2].substr(0, 3))];
        day = parseInt(parts[3]);
        year = parseInt(parts[5]);
      } else {
        day = parseInt(parts[1]);
        month = utilDate.monthNumbers[Ext.String.capitalize(parts[4].substr(0, 3))];
        year = parseInt(parts[5]);
      }
    }
    if (isNaN(month) || (month < 0 || month > 11)) {
      return null;
    }
    if (year < utilDate.y2kYear) {
      year += 2000;
    }
    result = new Date(year, month, 1, 0, 0, 0);
    if (day < 1 || day > Ext.Date.getDaysInMonth(result)) {
      return null;
    }
    result.setDate(day);
    return result;
  }};
  utilDate.parseCodes.C = utilDate.parseCodes.c;
  return utilDate;
}();
Ext.Function = function() {
  var lastTime = 0, animFrameId, animFrameHandlers = [], animFrameNoArgs = [], idSource = 0, animFrameMap = {}, slice = Array.prototype.slice, win = window, global = Ext.global, hasImmediate = !Ext.disableImmediate && !!(global.setImmediate && global.clearImmediate), requestAnimFrame = win.requestAnimationFrame || win.webkitRequestAnimationFrame || win.mozRequestAnimationFrame || win.oRequestAnimationFrame || function(callback) {
    var currTime = Ext.now(), timeToCall = Math.max(0, 16 - (currTime - lastTime)), timerFn = function() {
      callback(currTime + timeToCall);
    }, id;
    timerFn.$origFn = callback.$origFn || callback;
    timerFn.$skipTimerCheck = timerFn.$origFn.$skipTimerCheck;
    id = win.setTimeout(timerFn, timeToCall);
    lastTime = currTime + timeToCall;
    return id;
  }, fireHandlers = function() {
    var len = animFrameHandlers.length, id, i, handler;
    animFrameId = null;
    var timer;
    for (i = 0; i < len; i++) {
      handler = animFrameHandlers[i];
      id = handler[3];
      if (animFrameMap[id]) {
        delete animFrameMap[id];
        timer = Ext.Timer.get(id, 'raf');
        if (timer) {
          timer.tick();
        }
        handler[0].apply(handler[1] || global, handler[2] || animFrameNoArgs);
        if (timer) {
          timer.tock();
        }
      }
    }
    animFrameHandlers = animFrameHandlers.slice(len);
  }, fireElevatedHandlers = function() {
    Ext.elevate(fireHandlers);
  }, ExtFunction = {flexSetter:function(setter) {
    return function(name, value) {
      var k, i;
      if (name !== null) {
        if (typeof name !== 'string') {
          for (k in name) {
            if (name.hasOwnProperty(k)) {
              setter.call(this, k, name[k]);
            }
          }
          if (Ext.enumerables) {
            for (i = Ext.enumerables.length; i--;) {
              k = Ext.enumerables[i];
              if (name.hasOwnProperty(k)) {
                setter.call(this, k, name[k]);
              }
            }
          }
        } else {
          setter.call(this, name, value);
        }
      }
      return this;
    };
  }, bind:function(fn, scope, args, appendArgs) {
    if (arguments.length <= 2) {
      return fn.bind(scope);
    }
    var method = fn;
    return function() {
      var callArgs = args || arguments;
      if (appendArgs === true) {
        callArgs = slice.call(arguments, 0);
        callArgs = callArgs.concat(args);
      } else {
        if (typeof appendArgs === 'number') {
          callArgs = slice.call(arguments, 0);
          Ext.Array.insert(callArgs, appendArgs, args);
        }
      }
      return method.apply(scope || global, callArgs);
    };
  }, bindCallback:function(callback, scope, args, delay, caller) {
    return function() {
      var a = slice.call(arguments);
      return Ext.callback(callback, scope, args ? args.concat(a) : a, delay, caller);
    };
  }, pass:function(fn, args, scope) {
    if (!Ext.isArray(args)) {
      if (Ext.isIterable(args)) {
        args = Ext.Array.clone(args);
      } else {
        args = args !== undefined ? [args] : [];
      }
    }
    return function() {
      var fnArgs = args.slice();
      fnArgs.push.apply(fnArgs, arguments);
      return fn.apply(scope || this, fnArgs);
    };
  }, alias:function(object, methodName) {
    return function() {
      return object[methodName].apply(object, arguments);
    };
  }, clone:function(method) {
    var newMethod, prop;
    newMethod = function() {
      return method.apply(this, arguments);
    };
    for (prop in method) {
      if (method.hasOwnProperty(prop)) {
        newMethod[prop] = method[prop];
      }
    }
    return newMethod;
  }, createInterceptor:function(origFn, newFn, scope, returnValue) {
    if (!Ext.isFunction(newFn)) {
      return origFn;
    } else {
      returnValue = Ext.isDefined(returnValue) ? returnValue : null;
      return function() {
        var me = this, args = arguments;
        return newFn.apply(scope || me || global, args) !== false ? origFn.apply(me || global, args) : returnValue;
      };
    }
  }, createDelayed:function(fn, delay, scope, args, appendArgs) {
    var boundFn = fn;
    if (scope || args) {
      boundFn = Ext.Function.bind(fn, scope, args, appendArgs);
    }
    return function() {
      var me = this, args = slice.call(arguments), timerFn, timerId;
      var timer;
      timerFn = function() {
        Ext.elevate(boundFn, me, args, timer);
      };
      timerId = setTimeout(timerFn, delay);
      timerFn.$origFn = fn.$origFn || fn;
      timerFn.$skipTimerCheck = timerFn.$origFn.$skipTimerCheck;
      timer = Ext.Timer.created('timeout', timerId, {type:'createDelayed', fn:fn, timerFn:timerFn});
    };
  }, defer:function(fn, millis, scope, args, appendArgs) {
    var timerId = 0, timerFn, boundFn;
    var timer;
    if (!scope && !args && !appendArgs) {
      boundFn = fn;
    } else {
      boundFn = Ext.Function.bind(fn, scope, args, appendArgs);
    }
    if (millis > 0) {
      timerFn = function() {
        Ext.elevate(boundFn, null, null, timer);
      };
      timerId = setTimeout(timerFn, millis);
      timerFn.$origFn = fn.$origFn || fn;
      timerFn.$skipTimerCheck = timerFn.$origFn.$skipTimerCheck;
      timer = Ext.Timer.created('timeout', timerId, {type:'defer', fn:fn, timerFn:timerFn});
    } else {
      boundFn();
    }
    return timerId;
  }, interval:function(fn, millis, scope, args, appendArgs) {
    var timerFn, timerId, boundFn;
    var timer;
    boundFn = Ext.Function.bind(fn, scope, args, appendArgs);
    timerFn = function() {
      Ext.elevate(boundFn, null, null, timer);
    };
    timerId = setInterval(timerFn, millis);
    timerFn.$origFn = boundFn.$origFn || fn;
    timerFn.$skipTimerCheck = timerFn.$origFn.$skipTimerCheck;
    timer = Ext.Timer.created('interval', timerId, {type:'interval', fn:fn, timerFn:timerFn});
    return timerId;
  }, createSequence:function(originalFn, newFn, scope) {
    if (!newFn) {
      return originalFn;
    } else {
      return function() {
        var result = originalFn.apply(this, arguments);
        newFn.apply(scope || this, arguments);
        return result;
      };
    }
  }, createBuffered:function(fn, buffer, scope, args) {
    var timerId, result = function() {
      var callArgs = args || slice.call(arguments, 0), me = scope || this, timerFn;
      var timer;
      if (timerId) {
        Ext.undefer(timerId);
      }
      timerFn = function() {
        Ext.elevate(fn, me, callArgs, timer);
      };
      result.timer = timerId = setTimeout(timerFn, buffer);
      timerFn.$origFn = fn.$origFn || fn;
      timerFn.$skipTimerCheck = timerFn.$origFn.$skipTimerCheck;
      timer = Ext.Timer.created('timeout', timerId, {type:'createBuffered', fn:fn, timerFn:timerFn});
    };
    return result;
  }, createAnimationFrame:function(fn, scope, args, queueStrategy) {
    var boundFn, timerId;
    queueStrategy = queueStrategy || 3;
    boundFn = function() {
      var timerFn, callArgs = args || slice.call(arguments, 0);
      scope = scope || this;
      if (queueStrategy === 3 && timerId) {
        ExtFunction.cancelAnimationFrame(timerId);
      }
      if (queueStrategy & 1 || !timerId) {
        timerFn = function() {
          timerId = boundFn.timerId = null;
          fn.apply(scope, callArgs);
        };
        timerFn.$origFn = fn.$origFn || fn;
        timerFn.$skipTimerCheck = timerFn.$origFn.$skipTimerCheck;
        timerId = boundFn.timerId = ExtFunction.requestAnimationFrame(timerFn);
      }
    };
    return boundFn;
  }, requestAnimationFrame:function(fn, scope, args) {
    var id = ++idSource, handler = slice.call(arguments, 0);
    handler[3] = id;
    animFrameMap[id] = 1;
    Ext.Timer.created('raf', id, {type:'raf', fn:fn});
    animFrameHandlers.push(handler);
    if (!animFrameId) {
      animFrameId = requestAnimFrame(fireElevatedHandlers);
    }
    return id;
  }, cancelAnimationFrame:function(id) {
    delete animFrameMap[id];
    Ext.Timer.cancel('raf', id);
  }, createThrottled:function(fn, interval, scope) {
    var lastCallTime = 0, elapsed, lastArgs, timerId, execute = function() {
      fn.apply(scope, lastArgs);
      lastCallTime = Ext.now();
      lastArgs = timerId = null;
    };
    execute.$origFn = fn.$origFn || fn;
    execute.$skipTimerCheck = execute.$origFn.$skipTimerCheck;
    return function() {
      if (!scope) {
        scope = this;
      }
      elapsed = Ext.now() - lastCallTime;
      lastArgs = Ext.Array.slice(arguments);
      if (elapsed >= interval) {
        Ext.undefer(timerId);
        execute();
      } else {
        if (!timerId) {
          timerId = Ext.defer(execute, interval - elapsed);
        }
      }
    };
  }, createBarrier:function(count, fn, scope) {
    var barrierFn = function() {
      if (!--count) {
        fn.apply(scope, arguments);
      }
    };
    barrierFn.$origFn = fn.$origFn || fn;
    barrierFn.$skipTimerCheck = barrierFn.$origFn.$skipTimerCheck;
    return barrierFn;
  }, interceptBefore:function(object, methodName, fn, scope) {
    var method = object[methodName] || Ext.emptyFn;
    return object[methodName] = function() {
      var ret = fn.apply(scope || this, arguments);
      method.apply(this, arguments);
      return ret;
    };
  }, interceptAfter:function(object, methodName, fn, scope) {
    var method = object[methodName] || Ext.emptyFn;
    return object[methodName] = function() {
      method.apply(this, arguments);
      return fn.apply(scope || this, arguments);
    };
  }, interceptAfterOnce:function(object, methodName, fn, scope) {
    var origMethod = object[methodName], newMethod;
    newMethod = function() {
      var ret;
      if (origMethod) {
        origMethod.apply(this, arguments);
      }
      ret = fn.apply(scope || this, arguments);
      object[methodName] = origMethod;
      object = methodName = fn = scope = origMethod = newMethod = null;
      return ret;
    };
    object[methodName] = newMethod;
    return newMethod;
  }, makeCallback:function(callback, scope) {
    if (!scope[callback]) {
      if (scope.$className) {
        Ext.raise('No method "' + callback + '" on ' + scope.$className);
      }
      Ext.raise('No method "' + callback + '"');
    }
    return function() {
      return scope[callback].apply(scope, arguments);
    };
  }, memoize:function(fn, scope, hashFn) {
    var memo = {}, isFunc = hashFn && Ext.isFunction(hashFn);
    return function(value) {
      var key = isFunc ? hashFn.apply(scope, arguments) : value;
      if (!(key in memo)) {
        memo[key] = fn.apply(scope, arguments);
      }
      return memo[key];
    };
  }, _stripCommentRe:/(\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/)|(\/\/.*)/g, toCode:function(fn) {
    var s = fn ? fn.toString() : '';
    s = s.replace(ExtFunction._stripCommentRe, '');
    return s;
  }, fireElevatedHandlers:function() {
    fireElevatedHandlers();
  }};
  Ext.asap = hasImmediate ? function(fn, scope, parameters) {
    var boundFn = fn, timerFn, timerId;
    var timer;
    if (scope != null || parameters != null) {
      boundFn = ExtFunction.bind(fn, scope, parameters);
    }
    timerFn = function() {
      Ext.elevate(boundFn, null, null, timer);
    };
    timerId = setImmediate(timerFn);
    timerFn.$origFn = fn.$origFn || fn;
    timerFn.$skipTimerCheck = timerFn.$origFn.$skipTimerCheck;
    timer = Ext.Timer.created('asap', timerId, {type:'asap', fn:fn, timerFn:timerFn});
    return timerId;
  } : function(fn, scope, parameters) {
    var boundFn = fn, timerFn, timerId;
    var timer;
    if (scope != null || parameters != null) {
      boundFn = ExtFunction.bind(fn, scope, parameters);
    }
    timerFn = function() {
      Ext.elevate(boundFn, null, null, timer);
    };
    timerId = setTimeout(timerFn, 0, true);
    timerFn.$origFn = fn.$origFn || fn;
    timerFn.$skipTimerCheck = timerFn.$origFn.$skipTimerCheck;
    timer = Ext.Timer.created('timeout', timerId, {type:'asap', fn:fn, timerFn:timerFn});
    return timerId;
  };
  Ext.unasap = hasImmediate ? function(id) {
    if (id) {
      clearImmediate(id);
      Ext.Timer.cancel('asap', id);
    }
    return null;
  } : function(id) {
    return Ext.undefer(id);
  };
  Ext.asapCancel = function(id) {
    return Ext.unasap(id);
  };
  Ext.defer = ExtFunction.defer;
  Ext.undefer = function(id) {
    if (id) {
      clearTimeout(id);
      Ext.Timer.cancel('timeout', id);
    }
    return null;
  };
  Ext.interval = ExtFunction.interval;
  Ext.uninterval = function(id) {
    if (id) {
      clearInterval(id);
      Ext.Timer.cancel('interval', id);
    }
    return null;
  };
  Ext.pass = ExtFunction.pass;
  Ext.bind = ExtFunction.bind;
  Ext.raf = function() {
    return ExtFunction.requestAnimationFrame.apply(ExtFunction, arguments);
  };
  Ext.unraf = function(id) {
    ExtFunction.cancelAnimationFrame(id);
  };
  return ExtFunction;
}();
Ext.Number = new function() {
  var ExtNumber = this, isToFixedBroken = (0.9).toFixed() !== '1', math = Math, ClipDefault = {count:false, inclusive:false, wrap:true};
  Number.MIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER || -(math.pow(2, 53) - 1);
  Number.MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || math.pow(2, 53) - 1;
  Ext.apply(ExtNumber, {MIN_SAFE_INTEGER:Number.MIN_SAFE_INTEGER, MAX_SAFE_INTEGER:Number.MAX_SAFE_INTEGER, MAX_32BIT_INTEGER:math.pow(2, 31) - 1, floatRe:/^[-+]?(?:\d+|\d*\.\d*)(?:[Ee][+-]?\d+)?$/, intRe:/^[-+]?\d+(?:[Ee]\+?\d+)?$/, Clip:{DEFAULT:ClipDefault, COUNT:Ext.applyIf({count:true}, ClipDefault), INCLUSIVE:Ext.applyIf({inclusive:true}, ClipDefault), NOWRAP:Ext.applyIf({wrap:false}, ClipDefault)}, parseFloat:function(value) {
    if (value === undefined) {
      value = null;
    }
    if (value !== null && typeof value !== 'number') {
      value = String(value);
      value = ExtNumber.floatRe.test(value) ? +value : null;
      if (isNaN(value)) {
        value = null;
      }
    }
    return value;
  }, parseInt:function(value) {
    if (value === undefined) {
      value = null;
    }
    if (typeof value === 'number') {
      value = Math.floor(value);
    } else {
      if (value !== null) {
        value = String(value);
        value = ExtNumber.intRe.test(value) ? +value : null;
      }
    }
    return value;
  }, binarySearch:function(array, value, begin, end) {
    var middle, midVal;
    if (begin === undefined) {
      begin = 0;
    }
    if (end === undefined) {
      end = array.length;
    }
    --end;
    while (begin <= end) {
      middle = begin + end >>> 1;
      midVal = array[middle];
      if (value === midVal) {
        return middle;
      }
      if (midVal < value) {
        begin = middle + 1;
      } else {
        end = middle - 1;
      }
    }
    return begin;
  }, bisectTuples:function(array, value, index, begin, end) {
    var middle, midVal;
    if (begin === undefined) {
      begin = 0;
    }
    if (end === undefined) {
      end = array.length;
    }
    --end;
    while (begin <= end) {
      middle = begin + end >>> 1;
      midVal = array[middle][index];
      if (value === midVal) {
        return middle;
      }
      if (midVal < value) {
        begin = middle + 1;
      } else {
        end = middle - 1;
      }
    }
    return begin;
  }, clipIndices:function(length, indices, options) {
    var defaultValue = 0, wrap, begin, end, i;
    options = options || ClipDefault;
    wrap = options.wrap;
    indices = indices || [];
    for (i = 0; i < 2; ++i) {
      begin = end;
      end = indices[i];
      if (end == null) {
        end = defaultValue;
      } else {
        if (i && options.count) {
          end += begin;
          end = end > length ? length : end;
        } else {
          if (wrap) {
            end = end < 0 ? length + end : end;
          }
          if (i && options.inclusive) {
            ++end;
          }
          end = end < 0 ? 0 : end > length ? length : end;
        }
      }
      defaultValue = length;
    }
    indices[0] = begin;
    indices[1] = end < begin ? begin : end;
    return indices;
  }, constrain:function(number, min, max) {
    var x = parseFloat(number);
    if (min === null) {
      min = number;
    }
    if (max === null) {
      max = number;
    }
    return x < min ? min : x > max ? max : x;
  }, snap:function(value, increment, minValue, maxValue) {
    var m;
    if (value === undefined || value < minValue) {
      return minValue || 0;
    }
    if (increment) {
      m = value % increment;
      if (m !== 0) {
        value -= m;
        if (m * 2 >= increment) {
          value += increment;
        } else {
          if (m * 2 < -increment) {
            value -= increment;
          }
        }
      }
    }
    return ExtNumber.constrain(value, minValue, maxValue);
  }, snapInRange:function(value, increment, minValue, maxValue) {
    var tween;
    minValue = minValue || 0;
    if (value === undefined || value < minValue) {
      return minValue;
    }
    if (increment && (tween = (value - minValue) % increment)) {
      value -= tween;
      tween *= 2;
      if (tween >= increment) {
        value += increment;
      }
    }
    if (maxValue !== undefined) {
      if (value > (maxValue = ExtNumber.snapInRange(maxValue, increment, minValue))) {
        value = maxValue;
      }
    }
    return value;
  }, roundToNearest:function(value, interval) {
    interval = interval || 1;
    return interval * math.round(value / interval);
  }, roundToPrecision:function(value, precision) {
    var factor = math.pow(10, precision || 1);
    return math.round(value * factor) / factor;
  }, truncateToPrecision:function(value, precision) {
    var factor = math.pow(10, precision || 1);
    return parseInt(value * factor, 10) / factor;
  }, sign:math.sign || function(x) {
    x = +x;
    if (x === 0 || isNaN(x)) {
      return x;
    }
    return x > 0 ? 1 : -1;
  }, log10:math.log10 || function(x) {
    return math.log(x) * math.LOG10E;
  }, isEqual:function(n1, n2, epsilon) {
    if (!(typeof n1 === 'number' && typeof n2 === 'number' && typeof epsilon === 'number')) {
      Ext.raise('All parameters should be valid numbers.');
    }
    return math.abs(n1 - n2) < epsilon;
  }, isFinite:Number.isFinite || function(value) {
    return typeof value === 'number' && isFinite(value);
  }, isInteger:Number.isInteger || function(value) {
    return ~~(value + 0) === value;
  }, toFixed:isToFixedBroken ? function(value, precision) {
    var pow;
    precision = precision || 0;
    pow = math.pow(10, precision);
    return (math.round(value * pow) / pow).toFixed(precision);
  } : function(value, precision) {
    return value.toFixed(precision);
  }, from:function(value, defaultValue) {
    if (isFinite(value)) {
      value = parseFloat(value);
    }
    return !isNaN(value) ? value : defaultValue;
  }, randomInt:function(from, to) {
    return math.floor(math.random() * (to - from + 1) + from);
  }, correctFloat:function(n) {
    return parseFloat(n.toPrecision(14));
  }});
  Ext.num = function() {
    return ExtNumber.from.apply(this, arguments);
  };
};
(function() {
  var TemplateClass = function() {
  }, queryRe = /^\?/, keyRe = /(\[):?([^\]]*)\]/g, nameRe = /^([^\[]+)/, plusRe = /\+/g, ExtObject;
  ExtObject = Ext.Object = {chain:Object.create || function(object) {
    var result;
    TemplateClass.prototype = object;
    result = new TemplateClass;
    TemplateClass.prototype = null;
    return result;
  }, clear:function(object) {
    var key;
    for (key in object) {
      delete object[key];
    }
    return object;
  }, freeze:Object.freeze ? function(obj, deep) {
    var name;
    if (obj && typeof obj === 'object' && !Object.isFrozen(obj)) {
      Object.freeze(obj);
      if (deep) {
        for (name in obj) {
          ExtObject.freeze(obj[name], deep);
        }
      }
    }
    return obj;
  } : Ext.identityFn, toQueryObjects:function(name, value, recursive) {
    var self = ExtObject.toQueryObjects, objects = [], i, ln;
    if (Ext.isArray(value)) {
      for (i = 0, ln = value.length; i < ln; i++) {
        if (recursive) {
          objects = objects.concat(self(name + '[' + i + ']', value[i], true));
        } else {
          objects.push({name:name, value:value[i]});
        }
      }
    } else {
      if (Ext.isObject(value)) {
        for (i in value) {
          if (value.hasOwnProperty(i)) {
            if (recursive) {
              objects = objects.concat(self(name + '[' + i + ']', value[i], true));
            } else {
              objects.push({name:name, value:value[i]});
            }
          }
        }
      } else {
        objects.push({name:name, value:value});
      }
    }
    return objects;
  }, toQueryString:function(object, recursive) {
    var paramObjects = [], params = [], i, j, ln, paramObject, value;
    for (i in object) {
      if (object.hasOwnProperty(i)) {
        paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
      }
    }
    for (j = 0, ln = paramObjects.length; j < ln; j++) {
      paramObject = paramObjects[j];
      value = paramObject.value;
      if (Ext.isEmpty(value)) {
        value = '';
      } else {
        if (Ext.isDate(value)) {
          value = Ext.Date.toString(value);
        }
      }
      params.push(encodeURIComponent(paramObject.name) + '\x3d' + encodeURIComponent(String(value)));
    }
    return params.join('\x26');
  }, fromQueryString:function(queryString, recursive) {
    var parts = queryString.replace(queryRe, '').split('\x26'), object = {}, temp, components, name, value, i, ln, part, j, subLn, matchedKeys, matchedName, keys, key, nextKey;
    for (i = 0, ln = parts.length; i < ln; i++) {
      part = parts[i];
      if (part.length > 0) {
        components = part.split('\x3d');
        name = components[0];
        name = name.replace(plusRe, '%20');
        name = decodeURIComponent(name);
        value = components[1];
        if (value !== undefined) {
          value = value.replace(plusRe, '%20');
          value = decodeURIComponent(value);
        } else {
          value = '';
        }
        if (!recursive) {
          if (object.hasOwnProperty(name)) {
            if (!Ext.isArray(object[name])) {
              object[name] = [object[name]];
            }
            object[name].push(value);
          } else {
            object[name] = value;
          }
        } else {
          matchedKeys = name.match(keyRe);
          matchedName = name.match(nameRe);
          if (!matchedName) {
            throw new Error('[Ext.Object.fromQueryString] Malformed query string given, failed parsing name from "' + part + '"');
          }
          name = matchedName[0];
          keys = [];
          if (matchedKeys === null) {
            object[name] = value;
            continue;
          }
          for (j = 0, subLn = matchedKeys.length; j < subLn; j++) {
            key = matchedKeys[j];
            key = key.length === 2 ? '' : key.substring(1, key.length - 1);
            keys.push(key);
          }
          keys.unshift(name);
          temp = object;
          for (j = 0, subLn = keys.length; j < subLn; j++) {
            key = keys[j];
            if (j === subLn - 1) {
              if (Ext.isArray(temp) && key === '') {
                temp.push(value);
              } else {
                temp[key] = value;
              }
            } else {
              if (temp[key] === undefined || typeof temp[key] === 'string') {
                nextKey = keys[j + 1];
                temp[key] = Ext.isNumeric(nextKey) || nextKey === '' ? [] : {};
              }
              temp = temp[key];
            }
          }
        }
      }
    }
    return object;
  }, each:function(object, fn, scope) {
    var enumerables = Ext.enumerables, i, property;
    if (object) {
      scope = scope || object;
      for (property in object) {
        if (object.hasOwnProperty(property)) {
          if (fn.call(scope, property, object[property], object) === false) {
            return;
          }
        }
      }
      if (enumerables) {
        for (i = enumerables.length; i--;) {
          if (object.hasOwnProperty(property = enumerables[i])) {
            if (fn.call(scope, property, object[property], object) === false) {
              return;
            }
          }
        }
      }
    }
  }, eachValue:function(object, fn, scope) {
    var enumerables = Ext.enumerables, i, property;
    scope = scope || object;
    for (property in object) {
      if (object.hasOwnProperty(property)) {
        if (fn.call(scope, object[property]) === false) {
          return;
        }
      }
    }
    if (enumerables) {
      for (i = enumerables.length; i--;) {
        if (object.hasOwnProperty(property = enumerables[i])) {
          if (fn.call(scope, object[property]) === false) {
            return;
          }
        }
      }
    }
  }, merge:function(destination) {
    var i = 1, args = arguments, ln = args.length, mergeFn = ExtObject.merge, cloneFn = Ext.clone, object, key, value, sourceKey;
    for (; i < ln; i++) {
      object = args[i];
      for (key in object) {
        value = object[key];
        if (value && value.constructor === Object) {
          sourceKey = destination[key];
          if (sourceKey && sourceKey.constructor === Object) {
            mergeFn(sourceKey, value);
          } else {
            destination[key] = cloneFn(value);
          }
        } else {
          destination[key] = value;
        }
      }
    }
    return destination;
  }, mergeIf:function(destination) {
    var i = 1, ln = arguments.length, cloneFn = Ext.clone, object, key, value;
    for (; i < ln; i++) {
      object = arguments[i];
      for (key in object) {
        if (!(key in destination)) {
          value = object[key];
          if (value && value.constructor === Object) {
            destination[key] = cloneFn(value);
          } else {
            destination[key] = value;
          }
        }
      }
    }
    return destination;
  }, getAllKeys:function(object) {
    var keys = [], property;
    for (property in object) {
      keys.push(property);
    }
    return keys;
  }, getKey:function(object, value) {
    var property;
    for (property in object) {
      if (object.hasOwnProperty(property) && object[property] === value) {
        return property;
      }
    }
    return null;
  }, getValues:function(object) {
    var values = [], property;
    for (property in object) {
      if (object.hasOwnProperty(property)) {
        values.push(object[property]);
      }
    }
    return values;
  }, getKeys:typeof Object.keys === 'function' ? function(object) {
    if (!object) {
      return [];
    }
    return Object.keys(object);
  } : function(object) {
    var keys = [], property;
    for (property in object) {
      if (object.hasOwnProperty(property)) {
        keys.push(property);
      }
    }
    return keys;
  }, getSize:function(object) {
    var size = 0, property;
    for (property in object) {
      if (object.hasOwnProperty(property)) {
        size++;
      }
    }
    return size;
  }, isEmpty:function(object) {
    var key;
    for (key in object) {
      if (object.hasOwnProperty(key)) {
        return false;
      }
    }
    return true;
  }, equals:function() {
    var check = function(o1, o2) {
      var key;
      for (key in o1) {
        if (o1.hasOwnProperty(key)) {
          if (o1[key] !== o2[key]) {
            return false;
          }
        }
      }
      return true;
    };
    return function(object1, object2) {
      if (object1 === object2) {
        return true;
      }
      if (object1 && object2) {
        return check(object1, object2) && check(object2, object1);
      } else {
        if (!object1 && !object2) {
          return object1 === object2;
        } else {
          return false;
        }
      }
    };
  }(), fork:function(obj) {
    var ret, key, value;
    if (obj && obj.constructor === Object) {
      ret = ExtObject.chain(obj);
      for (key in obj) {
        value = obj[key];
        if (value) {
          if (value.constructor === Object) {
            ret[key] = ExtObject.fork(value);
          } else {
            if (value instanceof Array) {
              ret[key] = Ext.Array.clone(value);
            }
          }
        }
      }
    } else {
      ret = obj;
    }
    return ret;
  }, defineProperty:'defineProperty' in Object ? Object.defineProperty : function(object, name, descriptor) {
    if (!Object.prototype.__defineGetter__) {
      return;
    }
    if (descriptor.get) {
      object.__defineGetter__(name, descriptor.get);
    }
    if (descriptor.set) {
      object.__defineSetter__(name, descriptor.set);
    }
  }, classify:function(object) {
    var prototype = object, objectProperties = [], propertyClassesMap = {}, objectClass, key, value;
    objectClass = function() {
      var property, i, ln;
      for (i = 0, ln = objectProperties.length; i < ln; i++) {
        property = objectProperties[i];
        this[property] = new propertyClassesMap[property];
      }
    };
    for (key in object) {
      if (object.hasOwnProperty(key)) {
        value = object[key];
        if (value && value.constructor === Object) {
          objectProperties.push(key);
          propertyClassesMap[key] = ExtObject.classify(value);
        }
      }
    }
    objectClass.prototype = prototype;
    return objectClass;
  }};
  Ext.merge = Ext.Object.merge;
  Ext.mergeIf = Ext.Object.mergeIf;
})();
Ext.apply(Ext, {_namedScopes:{'this':{isThis:1}, controller:{isController:1}, owner:{isOwner:1}, up:{isUp:1}, self:{isSelf:1}, 'self.controller':{isSelf:1, isController:1}}, scrollbar:{_size:null, size:function(force) {
  var scrollbar = Ext.scrollbar, size = scrollbar._size;
  if (!Ext.isDomReady) {
    Ext.raise('Ext.scrollbar.size() called before DomReady');
  }
  if (force || !size) {
    var db = document.body, div = document.createElement('div'), h, w;
    div.style.width = div.style.height = '100px';
    div.style.overflow = 'scroll';
    div.style.position = 'absolute';
    db.appendChild(div);
    scrollbar._size = size = {width:w = div.offsetWidth - div.clientWidth, height:h = div.offsetHeight - div.clientHeight};
    size.reservedWidth = w ? 'calc(100% - ' + w + 'px)' : '';
    size.reservedHeight = h ? 'calc(100% - ' + h + 'px)' : '';
    db.removeChild(div);
  }
  return size;
}, height:function(force) {
  return Ext.scrollbar.size(force).height;
}, width:function(force) {
  return Ext.scrollbar.size(force).width;
}}, escapeId:function() {
  var validIdRe = /^[a-zA-Z_][a-zA-Z0-9_\-]*$/i, escapeRx = /([\W]{1})/g, leadingNumRx = /^(\d)/g, escapeFn = function(match, capture) {
    return '\\' + capture;
  }, numEscapeFn = function(match, capture) {
    return '\\00' + capture.charCodeAt(0).toString(16) + ' ';
  };
  return function(id) {
    return validIdRe.test(id) ? id : id.replace(escapeRx, escapeFn).replace(leadingNumRx, numEscapeFn);
  };
}(), lookUpFn:function(from, fn) {
  if (!from || !Ext.isFunction(from.up)) {
    Ext.raise('Callback "up" syntax requires a caller with "up" method');
  }
  var controller, scope;
  for (scope = from.up(); scope && !scope[fn]; scope = scope.up()) {
    controller = scope.controller;
    if (controller && controller[fn]) {
      scope = controller;
      break;
    }
  }
  if (!scope || !Ext.isFunction(scope[fn])) {
    Ext.raise('No such method "' + fn + '" found up() from ' + (from.getId ? from.getId() : from.id));
  }
  return scope;
}, callback:function(callback, scope, args, delay, caller, defaultScope) {
  if (!callback) {
    return;
  }
  var namedScope = scope in Ext._namedScopes, ret;
  if (callback.charAt) {
    if (callback[2] === '.') {
      if (callback.substr(0, 2) !== 'up') {
        Ext.raise('Invalid callback method name "' + callback + '"');
      }
      if (scope) {
        Ext.raise('Callback "up" syntax is incompatible with scopes');
      }
      scope = Ext.lookUpFn(caller, callback = callback.substr(3));
    } else {
      if (caller) {
        if (namedScope && namedScope.isUp) {
          scope = Ext.lookUpFn(caller, callback);
        } else {
          if (!scope || namedScope) {
            scope = caller.resolveListenerScope(namedScope ? scope : defaultScope);
          }
        }
      }
    }
    if (!scope || !Ext.isObject(scope)) {
      Ext.raise('Named method "' + callback + '" requires a scope object');
    }
    if (!Ext.isFunction(scope[callback])) {
      Ext.raise('No method named "' + callback + '" on ' + (scope.$className || 'scope object'));
    }
    callback = scope[callback];
  } else {
    if (namedScope) {
      scope = defaultScope || caller;
    } else {
      if (!scope) {
        scope = caller;
      }
    }
  }
  if (callback && Ext.isFunction(callback)) {
    scope = scope || Ext.global;
    if (delay) {
      Ext.defer(callback, delay, scope, args);
    } else {
      ret = args ? callback.apply(scope, args) : callback.call(scope);
    }
  }
  return ret;
}, coerce:function(from, to) {
  var fromType = Ext.typeOf(from), toType = Ext.typeOf(to), isString = typeof from === 'string';
  if (fromType !== toType) {
    switch(toType) {
      case 'string':
        return String(from);
      case 'number':
        return Number(from);
      case 'boolean':
        return isString && (!from || from === 'false' || from === '0') ? false : Boolean(from);
      case 'null':
        return isString && (!from || from === 'null') ? null : false;
      case 'undefined':
        return isString && (!from || from === 'undefined') ? undefined : false;
      case 'date':
        return isString && isNaN(from) ? Ext.Date.parse(from, Ext.Date.defaultFormat) : Date(Number(from));
    }
  }
  return from;
}, copyTo:function(dest, source, names, usePrototypeKeys) {
  var name, i, n;
  if (typeof names === 'string') {
    names = names.split(Ext.propertyNameSplitRe);
  }
  for (i = 0, n = names ? names.length : 0; i < n; i++) {
    name = names[i];
    if (usePrototypeKeys || source.hasOwnProperty(name)) {
      dest[name] = source[name];
    }
  }
  return dest;
}, copy:function(dest, source, names, usePrototypeKeys) {
  var name, i, n;
  if (typeof names === 'string') {
    names = names.split(Ext.propertyNameSplitRe);
  }
  for (i = 0, n = names ? names.length : 0; i < n; i++) {
    name = names[i];
    if (source.hasOwnProperty(name) || usePrototypeKeys && name in source) {
      dest[name] = source[name];
    }
  }
  return dest;
}, propertyNameSplitRe:/[,;\s]+/, copyToIf:function(destination, source, names) {
  var name, i, n;
  if (typeof names === 'string') {
    names = names.split(Ext.propertyNameSplitRe);
  }
  for (i = 0, n = names ? names.length : 0; i < n; i++) {
    name = names[i];
    if (destination[name] === undefined) {
      destination[name] = source[name];
    }
  }
  return destination;
}, copyIf:function(destination, source, names) {
  var name, i, n;
  if (typeof names === 'string') {
    names = names.split(Ext.propertyNameSplitRe);
  }
  for (i = 0, n = names ? names.length : 0; i < n; i++) {
    name = names[i];
    if (!(name in destination) && name in source) {
      destination[name] = source[name];
    }
  }
  return destination;
}, extend:function() {
  var objectConstructor = Object.prototype.constructor, inlineOverrides = function(o) {
    var m;
    for (m in o) {
      if (!o.hasOwnProperty(m)) {
        continue;
      }
      this[m] = o[m];
    }
  };
  return function(subclass, superclass, overrides) {
    if (Ext.isObject(superclass)) {
      overrides = superclass;
      superclass = subclass;
      subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
        superclass.apply(this, arguments);
      };
    }
    if (!superclass) {
      Ext.raise({sourceClass:'Ext', sourceMethod:'extend', msg:'Attempting to extend from a class which has not been loaded on the page.'});
    }
    var F = function() {
    }, superclassProto = superclass.prototype, subclassProto;
    F.prototype = superclassProto;
    subclassProto = subclass.prototype = new F;
    subclassProto.constructor = subclass;
    subclass.superclass = superclassProto;
    if (superclassProto.constructor === objectConstructor) {
      superclassProto.constructor = superclass;
    }
    subclass.override = function(overrides) {
      Ext.override(subclass, overrides);
    };
    subclassProto.override = inlineOverrides;
    subclassProto.proto = subclassProto;
    subclass.override(overrides);
    subclass.extend = function(o) {
      return Ext.extend(subclass, o);
    };
    return subclass;
  };
}(), isOnline:function() {
  return Ext.global.navigator.onLine;
}, iterate:function(object, fn, scope) {
  if (Ext.isEmpty(object)) {
    return;
  }
  if (scope === undefined) {
    scope = object;
  }
  if (Ext.isIterable(object)) {
    Ext.Array.each.call(Ext.Array, object, fn, scope);
  } else {
    Ext.Object.each.call(Ext.Object, object, fn, scope);
  }
}, _resourcePoolRe:/^[<]([^<>@:]*)(?:[@]([^<>@:]+))?[>](.+)$/, resolveResource:function(url) {
  var ret = url, m;
  if (url && url.charAt(0) === '\x3c') {
    m = Ext._resourcePoolRe.exec(url);
    if (m) {
      ret = Ext.getResourcePath(m[3], m[1], m[2]);
    }
  }
  return ret;
}, urlEncode:function() {
  var args = Ext.Array.from(arguments), prefix = '';
  if (Ext.isString(args[1])) {
    prefix = args[1] + '\x26';
    args[1] = false;
  }
  return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);
}, urlDecode:function() {
  return Ext.Object.fromQueryString.apply(Ext.Object, arguments);
}, getScrollbarSize:function(force) {
  return Ext.scrollbar.size(force);
}, typeOf:function() {
  var nonWhitespaceRe = /\S/, toString = Object.prototype.toString, typeofTypes = {number:1, string:1, 'boolean':1, 'undefined':1}, toStringTypes = {'[object Array]':'array', '[object Date]':'date', '[object Boolean]':'boolean', '[object Number]':'number', '[object RegExp]':'regexp'};
  return function(value) {
    if (value === null) {
      return 'null';
    }
    var type = typeof value, ret, typeToString;
    if (typeofTypes[type]) {
      return type;
    }
    ret = toStringTypes[typeToString = toString.call(value)];
    if (ret) {
      return ret;
    }
    if (type === 'function') {
      return 'function';
    }
    if (type === 'object') {
      if (value.nodeType !== undefined) {
        if (value.nodeType === 3) {
          return nonWhitespaceRe.test(value.nodeValue) ? 'textnode' : 'whitespace';
        } else {
          return 'element';
        }
      }
      return 'object';
    }
    Ext.raise({sourceClass:'Ext', sourceMethod:'typeOf', msg:'Failed to determine the type of "' + value + '".'});
    return typeToString;
  };
}(), factory:function(config, classReference, instance, aliasNamespace) {
  var manager = Ext.ClassManager, newInstance;
  if (!config || config.isInstance) {
    if (instance && instance !== config) {
      instance.destroy();
    }
    return config;
  }
  if (aliasNamespace) {
    if (typeof config === 'string') {
      return manager.instantiateByAlias(aliasNamespace + '.' + config);
    } else {
      if (Ext.isObject(config) && 'type' in config) {
        return manager.instantiateByAlias(aliasNamespace + '.' + config.type, config);
      }
    }
  }
  if (config === true) {
    if (!instance && !classReference) {
      Ext.raise('[Ext.factory] Cannot determine type of class to create');
    }
    return instance || Ext.create(classReference);
  }
  if (!Ext.isObject(config)) {
    Ext.raise('Invalid config, must be a valid config object');
  }
  if ('xtype' in config) {
    newInstance = manager.instantiateByAlias('widget.' + config.xtype, config);
  } else {
    if ('xclass' in config) {
      newInstance = Ext.create(config.xclass, config);
    }
  }
  if (newInstance) {
    if (instance) {
      instance.destroy();
    }
    return newInstance;
  }
  if (instance) {
    return instance.setConfig(config);
  }
  return Ext.create(classReference, config);
}, convertKeyedItems:function(items, defaultProperty, functionProperty) {
  if (items && !items.isInstance && Ext.isObject(items)) {
    var obj = items, item, itemId, value;
    items = [];
    if (obj.xtype || obj.xclass || obj.itemId || obj.id) {
      items.push(obj);
    } else {
      for (itemId in obj) {
        item = obj[itemId];
        if (item) {
          if (item === true) {
            item = {};
          } else {
            if (typeof item === 'function') {
              if (!functionProperty) {
                Ext.raise('Function not expected here');
              }
              value = item;
              item = {};
              item[functionProperty] = value;
            } else {
              if (typeof item === 'string') {
                value = item;
                item = {};
                item[defaultProperty || 'xtype'] = value;
              } else {
                item = Ext.apply({}, item);
              }
            }
          }
          item.itemId = itemId;
          items.push(item);
        }
      }
    }
  }
  return items;
}, sortByWeight:function(items) {
  if (items) {
    Ext.Array.sort(items, Ext.weightSortFn);
  }
}, weightSortFn:function(lhs, rhs) {
  return (lhs.weight || 0) - (rhs.weight || 0);
}, concat:function(a, b) {
  var noB = b == null, E = Ext.emptyArray;
  return a == null ? noB ? a : E.concat(b) : noB ? E.concat(a) : E.concat(a, b);
}, log:function() {
  var primitiveRe = /string|number|boolean/;
  function dumpObject(object, level, maxLevel, withFunctions) {
    var member, type, value, name, prefix, suffix, members = [];
    if (Ext.isArray(object)) {
      prefix = '[';
      suffix = ']';
    } else {
      if (Ext.isObject(object)) {
        prefix = '{';
        suffix = '}';
      }
    }
    if (!maxLevel) {
      maxLevel = 3;
    }
    if (level > maxLevel) {
      return prefix + '...' + suffix;
    }
    level = level || 1;
    var spacer = (new Array(level)).join('    ');
    for (name in object) {
      if (object.hasOwnProperty(name)) {
        value = object[name];
        type = typeof value;
        if (type === 'function') {
          if (!withFunctions) {
            continue;
          }
          member = type;
        } else {
          if (type === 'undefined') {
            member = type;
          } else {
            if (value === null || primitiveRe.test(type) || Ext.isDate(value)) {
              member = Ext.encode(value);
            } else {
              if (Ext.isArray(value)) {
                member = dumpObject(value, level + 1, maxLevel, withFunctions);
              } else {
                if (Ext.isObject(value)) {
                  member = dumpObject(value, level + 1, maxLevel, withFunctions);
                } else {
                  member = type;
                }
              }
            }
          }
        }
        members.push(spacer + name + ': ' + member);
      }
    }
    if (members.length) {
      return prefix + '\n    ' + members.join(',\n    ') + '\n' + spacer + suffix;
    }
    return prefix + suffix;
  }
  function log(message) {
    var options, dump, con = Ext.global.console, level = 'log', indent = log.indent || 0, prefix, stack, fn, out, max;
    log.indent = indent;
    if (typeof message !== 'string') {
      options = message;
      message = options.msg || '';
      level = options.level || level;
      dump = options.dump;
      stack = options.stack;
      prefix = options.prefix;
      fn = options.fn;
      if (options.indent) {
        ++log.indent;
      } else {
        if (options.outdent) {
          log.indent = indent = Math.max(indent - 1, 0);
        }
      }
      if (dump && !(con && con.dir)) {
        message += dumpObject(dump);
        dump = null;
      }
    }
    if (arguments.length > 1) {
      message += Array.prototype.slice.call(arguments, 1).join('');
    }
    if (prefix) {
      message = prefix + ' - ' + message;
    }
    message = indent ? Ext.String.repeat(' ', log.indentSize * indent) + message : message;
    if (level !== 'log') {
      message = '[' + level.charAt(0).toUpperCase() + '] ' + message;
    }
    if (fn) {
      message += '\nCaller: ' + fn.toString();
    }
    if (con) {
      if (con[level]) {
        con[level](message);
      } else {
        con.log(message);
      }
      if (dump) {
        con.dir(dump);
      }
      if (stack && con.trace) {
        if (!con.firebug || level !== 'error') {
          con.trace();
        }
      }
    } else {
      if (Ext.isOpera) {
        opera.postError(message);
      } else {
        out = log.out;
        max = log.max;
        if (out.length >= max) {
          Ext.Array.erase(out, 0, out.length - 3 * Math.floor(max / 4));
        }
        out.push(message);
      }
    }
    ++log.count;
    ++log.counters[level];
  }
  function logx(level, args) {
    if (typeof args[0] === 'string') {
      args.unshift({});
    }
    args[0].level = level;
    log.apply(this, args);
  }
  log.error = function() {
    logx('error', Array.prototype.slice.call(arguments));
  };
  log.info = function() {
    logx('info', Array.prototype.slice.call(arguments));
  };
  log.warn = function() {
    logx('warn', Array.prototype.slice.call(arguments));
  };
  log.count = 0;
  log.counters = {error:0, warn:0, info:0, log:0};
  log.indentSize = 2;
  log.out = [];
  log.max = 750;
  return log;
}() || function() {
  var nullLog = function() {
  };
  nullLog.info = nullLog.warn = nullLog.error = Ext.emptyFn;
  return nullLog;
}()});
(function() {
  var checkVerTemp = [''], endOfVersionRe = /([^\d.])/, notDigitsRe = /[^\d]/g, plusMinusRe = /[-+]/g, stripRe = /\s/g, underscoreRe = /_/g, toolkitNames = {classic:1, modern:1}, Version;
  Ext.Version = Version = function(version, defaultMode) {
    var me = this, padModes = me.padModes, ch, i, pad, parts, release, releaseStartIndex, ver;
    if (version.isVersion) {
      version = version.version;
    }
    me.version = ver = String(version).toLowerCase().replace(underscoreRe, '.').replace(plusMinusRe, '');
    ch = ver.charAt(0);
    if (ch in padModes) {
      ver = ver.substring(1);
      pad = padModes[ch];
    } else {
      pad = defaultMode ? padModes[defaultMode] : 0;
    }
    me.pad = pad;
    releaseStartIndex = ver.search(endOfVersionRe);
    me.shortVersion = ver;
    if (releaseStartIndex !== -1) {
      me.release = release = ver.substr(releaseStartIndex, version.length);
      me.shortVersion = ver.substr(0, releaseStartIndex);
      release = Version.releaseValueMap[release] || release;
    }
    me.releaseValue = release || pad;
    me.shortVersion = me.shortVersion.replace(notDigitsRe, '');
    me.parts = parts = ver.split('.');
    for (i = parts.length; i--;) {
      parts[i] = parseInt(parts[i], 10);
    }
    if (pad === Infinity) {
      parts.push(pad);
    }
    me.major = parts[0] || pad;
    me.minor = parts[1] || pad;
    me.patch = parts[2] || pad;
    me.build = parts[3] || pad;
    return me;
  };
  Version.prototype = {isVersion:true, padModes:{'~':NaN, '^':Infinity}, release:'', compareTo:function(other) {
    var me = this, lhsPad = me.pad, lhsParts = me.parts, lhsLength = lhsParts.length, rhsVersion = other.isVersion ? other : new Version(other), rhsPad = rhsVersion.pad, rhsParts = rhsVersion.parts, rhsLength = rhsParts.length, length = Math.max(lhsLength, rhsLength), i, lhs, rhs;
    for (i = 0; i < length; i++) {
      lhs = i < lhsLength ? lhsParts[i] : lhsPad;
      rhs = i < rhsLength ? rhsParts[i] : rhsPad;
      if (lhs < rhs) {
        return -1;
      }
      if (lhs > rhs) {
        return 1;
      }
    }
    lhs = me.releaseValue;
    rhs = rhsVersion.releaseValue;
    if (lhs < rhs) {
      return -1;
    }
    if (lhs > rhs) {
      return 1;
    }
    return 0;
  }, toString:function() {
    return this.version;
  }, valueOf:function() {
    return this.version;
  }, getMajor:function() {
    return this.major;
  }, getMinor:function() {
    return this.minor;
  }, getPatch:function() {
    return this.patch;
  }, getBuild:function() {
    return this.build;
  }, getRelease:function() {
    return this.release;
  }, getReleaseValue:function() {
    return this.releaseValue;
  }, isGreaterThan:function(target) {
    return this.compareTo(target) > 0;
  }, isGreaterThanOrEqual:function(target) {
    return this.compareTo(target) >= 0;
  }, isLessThan:function(target) {
    return this.compareTo(target) < 0;
  }, isLessThanOrEqual:function(target) {
    return this.compareTo(target) <= 0;
  }, equals:function(target) {
    return this.compareTo(target) === 0;
  }, match:function(target) {
    target = String(target);
    return this.version.substr(0, target.length) === target;
  }, toArray:function() {
    var me = this;
    return [me.getMajor(), me.getMinor(), me.getPatch(), me.getBuild(), me.getRelease()];
  }, getShortVersion:function() {
    return this.shortVersion;
  }, gt:function(target) {
    return this.compareTo(target) > 0;
  }, lt:function(target) {
    return this.compareTo(target) < 0;
  }, gtEq:function(target) {
    return this.compareTo(target) >= 0;
  }, ltEq:function(target) {
    return this.compareTo(target) <= 0;
  }};
  Ext.apply(Version, {aliases:{from:{extjs:'ext', core:'core', touch:'modern'}, to:{ext:['extjs'], 'core':['core'], modern:['touch']}}, releaseValueMap:{dev:-6, alpha:-5, a:-5, beta:-4, b:-4, rc:-3, '#':-2, p:-1, pl:-1}, getComponentValue:function(value) {
    return !value ? 0 : isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10);
  }, compare:function(current, target) {
    var ver = current.isVersion ? current : new Version(current);
    return ver.compareTo(target);
  }, set:function(collection, packageName, version) {
    var aliases = Version.aliases.to[packageName], ver = version.isVersion ? version : new Version(version), i;
    collection[packageName] = ver;
    if (aliases) {
      for (i = aliases.length; i-- > 0;) {
        collection[aliases[i]] = ver;
      }
    }
    return ver;
  }});
  Ext.apply(Ext, {compatVersions:{}, versions:{}, lastRegisteredVersion:null, getCompatVersion:function(packageName) {
    var versions = Ext.compatVersions, compat;
    if (!packageName) {
      compat = versions.ext || versions.touch || versions.core;
    } else {
      compat = versions[Version.aliases.from[packageName] || packageName];
    }
    return compat || Ext.getVersion(packageName);
  }, setCompatVersion:function(packageName, version) {
    Version.set(Ext.compatVersions, packageName, version);
  }, setVersion:function(packageName, version) {
    if (packageName in toolkitNames) {
      Ext.toolkit = packageName;
    }
    Ext.lastRegisteredVersion = Version.set(Ext.versions, packageName, version);
    return this;
  }, getVersion:function(packageName) {
    var versions = Ext.versions;
    if (!packageName) {
      return versions.ext || versions.touch || versions.core;
    }
    return versions[Version.aliases.from[packageName] || packageName];
  }, checkVersion:function(specs, matchAll) {
    var isArray = Ext.isArray(specs), aliases = Version.aliases.from, compat = isArray ? specs : checkVerTemp, length = compat.length, versions = Ext.versions, frameworkVer = versions.ext || versions.touch, i, index, matches, minVer, maxVer, packageName, spec, range, ver;
    if (!isArray) {
      checkVerTemp[0] = specs;
    }
    for (i = 0; i < length; ++i) {
      if (!Ext.isString(spec = compat[i])) {
        matches = Ext.checkVersion(spec.and || spec.or, !spec.or);
        if (spec.not) {
          matches = !matches;
        }
      } else {
        if (spec.indexOf(' ') >= 0) {
          spec = spec.replace(stripRe, '');
        }
        index = spec.indexOf('@');
        if (index < 0) {
          range = spec;
          ver = frameworkVer;
        } else {
          packageName = spec.substring(0, index);
          if (!(ver = versions[aliases[packageName] || packageName])) {
            if (matchAll) {
              return false;
            }
            continue;
          }
          range = spec.substring(index + 1);
        }
        index = range.indexOf('-');
        if (index < 0) {
          if (range.charAt(index = range.length - 1) === '+') {
            minVer = range.substring(0, index);
            maxVer = null;
          } else {
            minVer = maxVer = range;
          }
        } else {
          if (index > 0) {
            minVer = range.substring(0, index);
            maxVer = range.substring(index + 1);
          } else {
            minVer = null;
            maxVer = range.substring(index + 1);
          }
        }
        matches = true;
        if (minVer) {
          minVer = new Version(minVer, '~');
          matches = minVer.ltEq(ver);
        }
        if (matches && maxVer) {
          maxVer = new Version(maxVer, '~');
          matches = maxVer.gtEq(ver);
        }
      }
      if (matches) {
        if (!matchAll) {
          return true;
        }
      } else {
        if (matchAll) {
          return false;
        }
      }
    }
    return !!matchAll;
  }, deprecate:function(packageName, since, closure, scope) {
    if (Version.compare(Ext.getVersion(packageName), since) < 1) {
      closure.call(scope);
    }
  }});
})();
(function(manifest) {
  var packages = manifest && manifest.packages || {}, compat = manifest && manifest.compatibility, name, pkg;
  for (name in packages) {
    pkg = packages[name];
    if (pkg && pkg.version) {
      Ext.setVersion(name, pkg.version);
    }
  }
  if (compat) {
    if (Ext.isString(compat)) {
      Ext.setCompatVersion('core', compat);
    } else {
      for (name in compat) {
        Ext.setCompatVersion(name, compat[name]);
      }
    }
  }
  if (!packages.ext && !packages.touch) {
    Ext.setVersion('ext', '7.3.1.27');
    Ext.setVersion('core', '7.3.1.27');
  }
})(Ext.manifest);
Ext.Config = function(name) {
  var me = this, capitalizedName = name.charAt(0).toUpperCase() + name.substr(1);
  me.name = name;
  me.names = {internal:'_' + name, initializing:'is' + capitalizedName + 'Initializing', apply:'apply' + capitalizedName, update:'update' + capitalizedName, get:'get' + capitalizedName, set:'set' + capitalizedName, initGet:'initGet' + capitalizedName, changeEvent:name.toLowerCase() + 'change'};
  me.root = me;
};
Ext.Config.map = {};
Ext.Config.get = function(name) {
  var map = Ext.Config.map, ret = map[name] || (map[name] = new Ext.Config(name));
  return ret;
};
Ext.Config.prototype = {self:Ext.Config, isConfig:true, combine:function(value, baseValue, instance, clone) {
  var cfg = this;
  if (cfg.merge) {
    value = cfg.merge(clone ? Ext.clone(value) : value, baseValue, instance);
  } else {
    if (value && value.constructor === Object && baseValue && baseValue.constructor === Object) {
      value = Ext.merge({}, baseValue, value);
    } else {
      if (clone && value) {
        value = Ext.clone(value);
      }
    }
  }
  return value;
}, equals:function(value1, value2) {
  return value1 === value2;
}, getGetter:function() {
  return this.getter || (this.root.getter = this.makeGetter());
}, getInitGetter:function() {
  return this.initGetter || (this.root.initGetter = this.makeInitGetter());
}, getSetter:function() {
  return this.setter || (this.root.setter = this.makeSetter());
}, getEventedSetter:function() {
  return this.eventedSetter || (this.root.eventedSetter = this.makeEventedSetter());
}, getInternalName:function(target) {
  return target.$configPrefixed ? this.names.internal : this.name;
}, mergeNew:function(newValue, oldValue, target, mixinClass) {
  var ret, key;
  if (!oldValue) {
    ret = newValue;
  } else {
    if (!newValue) {
      ret = oldValue;
    } else {
      ret = Ext.Object.chain(oldValue);
      for (key in newValue) {
        if (!mixinClass || !(key in ret)) {
          ret[key] = newValue[key];
        }
      }
    }
  }
  return ret;
}, mergeSets:function(newValue, oldValue, preserveExisting) {
  var ret = oldValue ? Ext.Object.chain(oldValue) : {}, i, val;
  if (newValue instanceof Array) {
    for (i = newValue.length; i--;) {
      val = newValue[i];
      if (!preserveExisting || !(val in ret)) {
        ret[val] = true;
      }
    }
  } else {
    if (newValue) {
      if (newValue.constructor === Object) {
        for (i in newValue) {
          val = newValue[i];
          if (!preserveExisting || !(i in ret)) {
            ret[i] = val;
          }
        }
      } else {
        if (!preserveExisting || !(newValue in ret)) {
          ret[newValue] = true;
        }
      }
    }
  }
  return ret;
}, makeGetter:function() {
  var name = this.name, prefixedName = this.names.internal;
  return function() {
    var internalName = this.$configPrefixed ? prefixedName : name;
    return this[internalName];
  };
}, makeInitGetter:function() {
  var name = this.name, names = this.names, setName = names.set, getName = names.get, initializingName = names.initializing;
  return function() {
    var me = this;
    me[initializingName] = true;
    delete me[getName];
    me[setName](me.config[name]);
    delete me[initializingName];
    return me[getName].apply(me, arguments);
  };
}, makeSetter:function() {
  var name = this.name, names = this.names, prefixedName = names.internal, getName = names.get, applyName = names.apply, updateName = names.update, setter;
  setter = function(value) {
    var me = this, internalName = me.$configPrefixed ? prefixedName : name, oldValue = me[internalName], watch;
    delete me[getName];
    if (!me[applyName] || (value = me[applyName](value, oldValue)) !== undefined) {
      if (value !== (oldValue = me[internalName])) {
        me[internalName] = value;
        if (me[updateName]) {
          me[updateName](value, oldValue);
        }
        watch = me.$configWatch;
        if (watch && !me.isConfiguring) {
          watch.fire(name, [me, name, me[internalName], oldValue]);
        }
      }
    }
    return me;
  };
  setter.$isDefault = true;
  return setter;
}, makeEventedSetter:function() {
  var name = this.name, names = this.names, prefixedName = names.internal, getName = names.get, applyName = names.apply, updateName = names.update, changeEventName = names.changeEvent, updateFn = function(me, value, oldValue, internalName) {
    me[internalName] = value;
    if (me[updateName]) {
      me[updateName](value, oldValue);
    }
    var watch = me.$configWatch;
    if (watch) {
      watch.fire(name, [me, name, value, oldValue]);
    }
  }, setter;
  setter = function(value) {
    var me = this, internalName = me.$configPrefixed ? prefixedName : name, oldValue = me[internalName];
    delete me[getName];
    if (!me[applyName] || (value = me[applyName](value, oldValue)) !== undefined) {
      if (value !== (oldValue = me[internalName])) {
        if (me.isConfiguring) {
          me[internalName] = value;
          if (me[updateName]) {
            me[updateName](value, oldValue);
          }
        } else {
          me.fireEventedAction(changeEventName, [me, value, oldValue], updateFn, me, [me, value, oldValue, internalName]);
        }
      }
    }
    return me;
  };
  setter.$isDefault = true;
  return setter;
}};
(function() {
  var ExtConfig = Ext.Config, configPropMap = ExtConfig.map, ExtObject = Ext.Object;
  Ext.Configurator = function(cls) {
    var me = this, prototype = cls.prototype, superCfg = cls.superclass ? cls.superclass.self.$config : null;
    me.cls = cls;
    me.superCfg = superCfg;
    if (superCfg) {
      me.configs = ExtObject.chain(superCfg.configs);
      me.cachedConfigs = ExtObject.chain(superCfg.cachedConfigs);
      me.initMap = ExtObject.chain(superCfg.initMap);
      me.values = ExtObject.chain(superCfg.values);
      me.needsFork = superCfg.needsFork;
      me.deprecations = ExtObject.chain(superCfg.deprecations);
    } else {
      me.configs = {};
      me.cachedConfigs = {};
      me.initMap = {};
      me.values = {};
      me.deprecations = {};
    }
    prototype.config = prototype.defaultConfig = me.values;
    cls.$config = me;
  };
  Ext.Configurator.prototype = {self:Ext.Configurator, needsFork:false, initList:null, add:function(config, mixinClass) {
    var me = this, Cls = me.cls, configs = me.configs, cachedConfigs = me.cachedConfigs, initMap = me.initMap, prototype = Cls.prototype, mixinConfigs = mixinClass && mixinClass.$config.configs, values = me.values, isObject, meta, isCached, merge, cfg, currentValue, name, names, s, value;
    for (name in config) {
      value = config[name];
      isObject = value && value.constructor === Object;
      meta = isObject && '$value' in value ? value : null;
      isCached = false;
      if (meta) {
        isCached = !!meta.cached;
        value = meta.$value;
        isObject = value && value.constructor === Object;
      }
      merge = meta && meta.merge;
      cfg = configs[name];
      if (cfg) {
        if (mixinClass) {
          merge = cfg.merge;
          if (!merge) {
            continue;
          }
          meta = null;
        } else {
          merge = merge || cfg.merge;
        }
        if (!mixinClass && isCached && !cachedConfigs[name]) {
          Ext.raise('Redefining config as cached: ' + name + ' in class: ' + Cls.$className);
        }
        currentValue = values[name];
        if (merge) {
          value = merge.call(cfg, value, currentValue, Cls, mixinClass);
        } else {
          if (isObject) {
            if (currentValue && currentValue.constructor === Object) {
              value = Ext.merge({}, currentValue, value);
            }
          }
        }
      } else {
        if (mixinConfigs) {
          cfg = mixinConfigs[name];
          meta = null;
        } else {
          cfg = ExtConfig.get(name);
        }
        configs[name] = cfg;
        if (cfg.cached || isCached) {
          cachedConfigs[name] = true;
        }
        names = cfg.names;
        if (!prototype[s = names.get]) {
          prototype[s] = cfg.getter || cfg.getGetter();
        }
        if (!prototype[s = names.set]) {
          prototype[s] = meta && meta.evented ? cfg.eventedSetter || cfg.getEventedSetter() : cfg.setter || cfg.getSetter();
        }
      }
      if (meta) {
        if (cfg.owner !== Cls) {
          configs[name] = cfg = Ext.Object.chain(cfg);
          cfg.owner = Cls;
        }
        Ext.apply(cfg, meta);
        delete cfg.$value;
      }
      if (!me.needsFork && value && (value.constructor === Object || value instanceof Array)) {
        me.needsFork = true;
      }
      if (value !== null) {
        initMap[name] = true;
      } else {
        if (prototype.$configPrefixed) {
          prototype[configs[name].names.internal] = null;
        } else {
          prototype[configs[name].name] = null;
        }
        if (name in initMap) {
          initMap[name] = false;
        }
      }
      values[name] = value;
    }
  }, addDeprecations:function(configs) {
    var me = this, deprecations = me.deprecations, className = (me.cls.$className || '') + '#', message, newName, oldName;
    for (oldName in configs) {
      newName = configs[oldName];
      if (!newName) {
        message = 'This config has been removed.';
      } else {
        if (!(message = newName.message)) {
          message = 'This config has been renamed to "' + newName + '"';
        }
      }
      deprecations[oldName] = className + oldName + ': ' + message;
    }
  }, configure:function(instance, instanceConfig) {
    var me = this, configs = me.configs, deprecations = me.deprecations, initMap = me.initMap, initListMap = me.initListMap, initList = me.initList, prototype = me.cls.prototype, values = me.values, remaining = 0, firstInstance = !initList, cachedInitList, cfg, getter, i, internalName, ln, names, name, value, isCached, valuesKey, field, transforms;
    values = me.needsFork ? ExtObject.fork(values) : ExtObject.chain(values);
    instance.isConfiguring = true;
    if (firstInstance) {
      me.initList = initList = [];
      me.initListMap = initListMap = {};
      instance.isFirstInstance = true;
      for (name in initMap) {
        cfg = configs[name];
        isCached = cfg.cached;
        if (initMap[name]) {
          names = cfg.names;
          value = values[name];
          if (!prototype[names.set].$isDefault || prototype[names.apply] || prototype[names.update] || typeof value === 'object') {
            if (isCached) {
              (cachedInitList || (cachedInitList = [])).push(cfg);
            } else {
              initList.push(cfg);
              initListMap[name] = true;
            }
            instance[names.get] = cfg.initGetter || cfg.getInitGetter();
          } else {
            prototype[cfg.getInternalName(prototype)] = value;
          }
        } else {
          if (isCached) {
            prototype[cfg.getInternalName(prototype)] = undefined;
          }
        }
      }
    }
    ln = cachedInitList && cachedInitList.length;
    if (ln) {
      for (i = 0; i < ln; ++i) {
        internalName = cachedInitList[i].getInternalName(prototype);
        instance[internalName] = null;
      }
      for (i = 0; i < ln; ++i) {
        names = (cfg = cachedInitList[i]).names;
        getter = names.get;
        if (instance.hasOwnProperty(getter)) {
          instance[names.set](values[cfg.name]);
          delete instance[getter];
        }
      }
      for (i = 0; i < ln; ++i) {
        internalName = cachedInitList[i].getInternalName(prototype);
        prototype[internalName] = instance[internalName];
        delete instance[internalName];
      }
    }
    if (instanceConfig && instanceConfig.platformConfig) {
      instanceConfig = me.resolvePlatformConfig(instance, instanceConfig);
    }
    if (firstInstance) {
      if (instance.afterCachedConfig && !instance.afterCachedConfig.$nullFn) {
        instance.afterCachedConfig(instanceConfig);
      }
    }
    instance.config = values;
    for (i = 0, ln = initList.length; i < ln; ++i) {
      cfg = initList[i];
      instance[cfg.names.get] = cfg.initGetter || cfg.getInitGetter();
    }
    if (!(transforms = instance.self.$configTransforms)) {
      instance.self.$configTransforms = transforms = [];
      ln = instance.$configTransforms;
      for (name in ln) {
        transforms.push([name, ln[name]]);
      }
      ln = transforms.length;
      if (ln > 1) {
        transforms.sort(me.transformSorter);
        for (i = 0; i < ln; ++i) {
          transforms[i] = transforms[i][0];
        }
      } else {
        if (ln) {
          transforms[0] = transforms[0][0];
        }
      }
    }
    for (i = 0; i < transforms.length; ++i) {
      name = transforms[i];
      if (instance[name]) {
        instanceConfig = instance[name](instanceConfig, me);
      }
    }
    if (instanceConfig) {
      for (name in instanceConfig) {
        value = instanceConfig[name];
        cfg = configs[name];
        if (deprecations[name]) {
          Ext.log.warn(deprecations[name]);
          if (!cfg) {
            continue;
          }
        }
        if (!cfg) {
          field = instance.self.prototype[name];
          if (instance.$configStrict && typeof field === 'function' && !field.$nullFn) {
            Ext.raise('Cannot override method ' + name + ' on ' + instance.$className + ' instance.');
          }
          instance[name] = value;
        } else {
          if (!cfg.lazy) {
            ++remaining;
          }
          if (!initListMap[name]) {
            instance[cfg.names.get] = cfg.initGetter || cfg.getInitGetter();
          }
          valuesKey = values[name];
          if (cfg.merge) {
            value = cfg.merge(value, valuesKey, instance);
          } else {
            if (value && value.constructor === Object) {
              if (valuesKey && valuesKey.constructor === Object) {
                value = Ext.merge(values[name], value);
              } else {
                value = Ext.clone(value, false);
              }
            }
          }
        }
        values[name] = value;
      }
    }
    if (instance.beforeInitConfig && !instance.beforeInitConfig.$nullFn) {
      if (instance.beforeInitConfig(instanceConfig) === false) {
        return;
      }
    }
    if (instanceConfig) {
      for (name in instanceConfig) {
        if (!remaining) {
          break;
        }
        cfg = configs[name];
        if (cfg && !cfg.lazy) {
          --remaining;
          names = cfg.names;
          getter = names.get;
          if (instance.hasOwnProperty(getter)) {
            instance[names.set](values[name]);
            delete instance[names.get];
          }
        }
      }
    }
    for (i = 0, ln = initList.length; i < ln; ++i) {
      cfg = initList[i];
      names = cfg.names;
      getter = names.get;
      if (!cfg.lazy && instance.hasOwnProperty(getter)) {
        instance[names.set](values[cfg.name]);
        delete instance[getter];
      }
    }
    delete instance.isConfiguring;
  }, getCurrentConfig:function(instance) {
    var defaultConfig = instance.defaultConfig, config = {}, name;
    for (name in defaultConfig) {
      config[name] = instance[configPropMap[name].names.get]();
    }
    return config;
  }, hoistConfigs:function(instance, instanceConfig, names) {
    var config = instance.config, configs = this.configs, initListMap = this.initListMap, ret = false, cfg, i, name;
    for (i = 0; i < names.length; ++i) {
      name = names[i];
      if (instanceConfig && name in instanceConfig) {
        cfg = configs[name];
        config[name] = cfg.combine(instanceConfig[name], config[name], instance);
        if (!initListMap[name]) {
          instance[cfg.names.get] = cfg.initGetter || cfg.getInitGetter();
        }
      }
      if (config[name] != null) {
        ret = true;
      }
    }
    return ret;
  }, merge:function(instance, baseConfig, config, clone) {
    var configs = this.configs, name, value, baseValue, cfg;
    if (clone) {
      baseConfig = Ext.clone(baseConfig, false);
    }
    for (name in config) {
      value = config[name];
      cfg = configs[name];
      if (cfg) {
        baseValue = baseConfig[name];
        if (cfg.merge) {
          value = cfg.merge(value, baseValue, instance);
        } else {
          if (value && value.constructor === Object) {
            if (baseValue && baseValue.constructor === Object) {
              value = Ext.merge(baseValue, value);
            } else {
              value = Ext.clone(value, false);
            }
          }
        }
      }
      baseConfig[name] = value;
    }
    return baseConfig;
  }, reconfigure:function(instance, instanceConfig, options) {
    var currentConfig = instance.config, configList = [], strict = instance.$configStrict && !(options && options.strict === false), configs = this.configs, defaults = options && options.defaults, cfg, getter, i, len, name, names, prop;
    for (name in instanceConfig) {
      cfg = configs[name];
      if (defaults && instance.hasOwnProperty(cfg && instance.$configPrefixed ? cfg.names.internal : name)) {
        continue;
      }
      currentConfig[name] = instanceConfig[name];
      if (this.deprecations[name]) {
        Ext.log.warn(this.deprecations[name]);
        if (!cfg) {
          continue;
        }
      }
      if (cfg) {
        instance[cfg.names.get] = cfg.initGetter || cfg.getInitGetter();
      } else {
        prop = instance.self.prototype[name];
        if (strict) {
          if (typeof prop === 'function' && !prop.$nullFn) {
            Ext.Error.raise('Cannot override method ' + name + ' on ' + instance.$className + ' instance.');
            continue;
          } else {
            if (name !== 'type') {
              Ext.log.warn('No such config "' + name + '" for class ' + instance.$className);
            }
          }
        }
      }
      configList.push(name);
    }
    for (i = 0, len = configList.length; i < len; i++) {
      name = configList[i];
      cfg = configs[name];
      if (cfg) {
        names = cfg.names;
        getter = names.get;
        if (instance.hasOwnProperty(getter)) {
          instance[names.set](instanceConfig[name]);
          delete instance[getter];
        }
      } else {
        cfg = configPropMap[name] || Ext.Config.get(name);
        names = cfg.names;
        if (instance[names.set]) {
          instance[names.set](instanceConfig[name]);
        } else {
          instance[name] = instanceConfig[name];
        }
      }
    }
  }, resolvePlatformConfig:function(instance, instanceConfig) {
    var platformConfig = instanceConfig && instanceConfig.platformConfig, ret = instanceConfig, i, keys, n;
    if (platformConfig) {
      keys = Ext.getPlatformConfigKeys(platformConfig);
      n = keys.length;
      if (n) {
        ret = Ext.merge({}, ret);
        for (i = 0, n = keys.length; i < n; ++i) {
          this.merge(instance, ret, platformConfig[keys[i]]);
        }
      }
    }
    return ret;
  }, transformSorter:function(a, b) {
    return a[1] - b[1];
  }};
})();
Ext.Base = function(flexSetter) {
  var noArgs = [], baseStaticMember, baseStaticMembers = [], makeDeprecatedMethod = function(oldName, newName, msg) {
    var message = '"' + oldName + '" is deprecated.';
    if (msg) {
      message += ' ' + msg;
    } else {
      if (newName) {
        message += ' Please use "' + newName + '" instead.';
      }
    }
    return function() {
      Ext.raise(message);
    };
  }, addDeprecatedProperty = function(object, oldName, newName, message) {
    if (!message) {
      message = '"' + oldName + '" is deprecated.';
    }
    if (newName) {
      message += ' Please use "' + newName + '" instead.';
    }
    if (message) {
      Ext.Object.defineProperty(object, oldName, {get:function() {
        Ext.raise(message);
      }, set:function(value) {
        Ext.raise(message);
      }, configurable:true});
    }
  }, getOwnObject = function(proto, name) {
    if (!proto.hasOwnProperty(name)) {
      proto[name] = Ext.Object.chain(getOwnObject(proto.superclass, name));
    }
    return proto[name];
  }, makeAliasFn = function(name) {
    return function() {
      return this[name].apply(this, arguments);
    };
  }, Version = Ext.Version, leadingDigitRe = /^\d/, oneMember = {}, aliasOneMember = {}, Base = function() {
  }, BasePrototype = Base.prototype, Reaper;
  Ext.Reaper = Reaper = {delay:100, queue:[], timer:null, add:function(obj) {
    if (!Reaper.timer) {
      Reaper.timer = Ext.defer(Reaper.tick, Reaper.delay);
    }
    Reaper.queue.push(obj);
  }, flush:function() {
    if (Reaper.timer) {
      Ext.undefer(Reaper.timer);
      Reaper.timer = null;
    }
    var queue = Reaper.queue, n = queue.length, i, obj;
    Reaper.queue = [];
    for (i = 0; i < n; ++i) {
      obj = queue[i];
      if (obj && obj.$reap) {
        obj.$reap();
      }
    }
  }, tick:function() {
    Reaper.timer = null;
    Reaper.flush();
  }};
  Ext.apply(Base, {$className:'Ext.Base', $isClass:true, create:function() {
    return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
  }, addConfigTransform:function(methodName, priority) {
    var transforms = getOwnObject(this.prototype, '$configTransforms');
    if (this.$configTransforms) {
      Ext.raise('Config transforms cannot be added after instances are created');
    }
    transforms[methodName] = priority;
  }, addDeprecations:function(deprecations) {
    var me = this, all = [], compatVersion = Ext.getCompatVersion(deprecations.name), configurator = me.getConfigurator(), displayName = (me.$className || '') + '#', deprecate, versionSpec, index, message, target, enabled, existing, fn, names, oldName, newName, member, statics, version;
    for (versionSpec in deprecations) {
      if (leadingDigitRe.test(versionSpec)) {
        version = new Ext.Version(versionSpec);
        version.deprecations = deprecations[versionSpec];
        all.push(version);
      }
    }
    all.sort(Version.compare);
    for (index = all.length; index--;) {
      deprecate = (version = all[index]).deprecations;
      target = me.prototype;
      statics = deprecate.statics;
      enabled = compatVersion && compatVersion.lt(version);
      if (!enabled) {
      } else {
        if (!enabled) {
          break;
        }
      }
      while (deprecate) {
        names = deprecate.methods;
        if (names) {
          for (oldName in names) {
            member = names[oldName];
            fn = null;
            if (!member) {
              Ext.Assert.isNotDefinedProp(target, oldName);
              fn = makeDeprecatedMethod(displayName + oldName);
            } else {
              if (Ext.isString(member)) {
                Ext.Assert.isNotDefinedProp(target, oldName);
                Ext.Assert.isDefinedProp(target, member);
                if (enabled) {
                  fn = makeAliasFn(member);
                } else {
                  fn = makeDeprecatedMethod(displayName + oldName, member);
                }
              } else {
                message = '';
                if (member.message || member.fn) {
                  message = member.message;
                  member = member.fn;
                }
                existing = target.hasOwnProperty(oldName) && target[oldName];
                if (enabled && member) {
                  member.$owner = me;
                  member.$name = oldName;
                  member.name = displayName + oldName;
                  if (existing) {
                    member.$previous = existing;
                  }
                  fn = member;
                } else {
                  if (!existing) {
                    fn = makeDeprecatedMethod(displayName + oldName, null, message);
                  }
                }
              }
            }
            if (fn) {
              target[oldName] = fn;
            }
          }
        }
        names = deprecate.configs;
        if (names) {
          configurator.addDeprecations(names);
        }
        names = deprecate.properties;
        if (names && !enabled) {
          for (oldName in names) {
            newName = names[oldName];
            if (Ext.isString(newName)) {
              addDeprecatedProperty(target, displayName + oldName, newName);
            } else {
              if (newName && newName.message) {
                addDeprecatedProperty(target, displayName + oldName, null, newName.message);
              } else {
                addDeprecatedProperty(target, displayName + oldName);
              }
            }
          }
        }
        deprecate = statics;
        statics = null;
        target = me;
      }
    }
  }, extend:function(parentClass) {
    var me = this, parentPrototype = parentClass.prototype, prototype, name, statics;
    prototype = me.prototype = Ext.Object.chain(parentPrototype);
    prototype.self = me;
    me.superclass = prototype.superclass = parentPrototype;
    if (!parentClass.$isClass) {
      for (name in BasePrototype) {
        if (name in prototype) {
          prototype[name] = BasePrototype[name];
        }
      }
    }
    statics = parentPrototype.$inheritableStatics;
    if (statics) {
      for (name in statics) {
        if (!me.hasOwnProperty(name)) {
          me[name] = parentClass[name];
        }
      }
    }
    if (parentClass.$onExtended) {
      me.$onExtended = parentClass.$onExtended.slice();
    }
    me.getConfigurator();
  }, $onExtended:[], triggerExtended:function() {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(this, 'Ext.Base#triggerExtended', arguments);
    }
    var callbacks = this.$onExtended, ln = callbacks.length, i, callback;
    if (ln > 0) {
      for (i = 0; i < ln; i++) {
        callback = callbacks[i];
        callback.fn.apply(callback.scope || this, arguments);
      }
    }
  }, onExtended:function(fn, scope) {
    this.$onExtended.push({fn:fn, scope:scope});
    return this;
  }, addStatics:function(members) {
    this.addMembers(members, true);
    return this;
  }, addInheritableStatics:function(members) {
    var me = this, proto = me.prototype, inheritableStatics = me.$inheritableStatics, name, member, current;
    if (!inheritableStatics) {
      inheritableStatics = Ext.apply({}, proto.$inheritableStatics);
      me.$inheritableStatics = proto.$inheritableStatics = inheritableStatics;
    }
    var className = Ext.getClassName(me) + '.';
    for (name in members) {
      if (members.hasOwnProperty(name)) {
        member = members[name];
        current = me[name];
        if (typeof member === 'function') {
          member.name = className + name;
        }
        if (typeof current === 'function' && !current.$isClass && !current.$nullFn) {
          member.$previous = current;
        }
        me[name] = member;
        inheritableStatics[name] = true;
      }
    }
    return me;
  }, addMembers:function(members, isStatic, privacy) {
    var me = this, cloneFunction = Ext.Function.clone, target = isStatic ? me : me.prototype, defaultConfig = !isStatic && target.defaultConfig, enumerables = Ext.enumerables, privates = members.privates, configs, i, ln, member, name, subPrivacy, privateStatics;
    var displayName = (me.$className || '') + '#';
    if (privates) {
      delete members.privates;
      if (!isStatic) {
        privateStatics = privates.statics;
        delete privates.statics;
      }
      subPrivacy = privates.privacy || privacy || 'framework';
      me.addMembers(privates, isStatic, subPrivacy);
      if (privateStatics) {
        me.addMembers(privateStatics, true, subPrivacy);
      }
    }
    for (name in members) {
      if (members.hasOwnProperty(name)) {
        member = members[name];
        if (privacy === true) {
          privacy = 'framework';
        }
        if (member && member.$nullFn && privacy !== member.$privacy) {
          Ext.raise('Cannot use stock function for private method ' + (me.$className ? me.$className + '#' : '') + name);
        }
        if (typeof member === 'function' && !member.$isClass && !member.$nullFn) {
          if (member.$owner) {
            member = cloneFunction(member);
          }
          if (target.hasOwnProperty(name)) {
            member.$previous = target[name];
          }
          member.$owner = me;
          member.$name = name;
          member.name = displayName + name;
          var existing = target[name];
          if (privacy) {
            member.$privacy = privacy;
            if (existing && existing.$privacy && existing.$privacy !== privacy) {
              Ext.privacyViolation(me, existing, member, isStatic);
            }
          } else {
            if (existing && existing.$privacy) {
              Ext.privacyViolation(me, existing, member, isStatic);
            }
          }
        } else {
          if (defaultConfig && name in defaultConfig && !target.config.hasOwnProperty(name)) {
            (configs || (configs = {}))[name] = member;
            continue;
          }
        }
        target[name] = member;
      }
    }
    if (configs) {
      me.addConfig(configs);
    }
    if (enumerables) {
      for (i = 0, ln = enumerables.length; i < ln; ++i) {
        if (members.hasOwnProperty(name = enumerables[i])) {
          member = members[name];
          if (member && !member.$nullFn) {
            if (member.$owner) {
              member = cloneFunction(member);
            }
            member.$owner = me;
            member.$name = name;
            member.name = displayName + name;
            if (target.hasOwnProperty(name)) {
              member.$previous = target[name];
            }
          }
          target[name] = member;
        }
      }
    }
    return this;
  }, addMember:function(name, member, privacy) {
    oneMember[name] = member;
    this.addMembers(oneMember, false, privacy);
    delete oneMember[name];
    return this;
  }, hookMember:function(name, member) {
    var existing = this.prototype[name];
    return this.addMember(name, member, existing && existing.$privacy);
  }, borrow:function(fromClass, members) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(this, 'Ext.Base#borrow', arguments);
    }
    var prototype = fromClass.prototype, membersObj = {}, i, ln, name;
    members = Ext.Array.from(members);
    for (i = 0, ln = members.length; i < ln; i++) {
      name = members[i];
      membersObj[name] = prototype[name];
    }
    return this.addMembers(membersObj);
  }, override:function(members) {
    var me = this, statics = members.statics, inheritableStatics = members.inheritableStatics, config = members.config, mixins = members.mixins, cachedConfig = members.cachedConfig;
    if (statics || inheritableStatics || config) {
      members = Ext.apply({}, members);
    }
    if (statics) {
      me.addMembers(statics, true);
      delete members.statics;
    }
    if (inheritableStatics) {
      me.addInheritableStatics(inheritableStatics);
      delete members.inheritableStatics;
    }
    if (members.platformConfig) {
      me.addPlatformConfig(members);
    }
    if (config) {
      me.addConfig(config);
      delete members.config;
    }
    if (cachedConfig) {
      me.addCachedConfig(cachedConfig);
      delete members.cachedConfig;
    }
    delete members.mixins;
    me.addMembers(members);
    if (mixins) {
      me.mixin(mixins);
    }
    return me;
  }, addPlatformConfig:function(data) {
    var me = this, prototype = me.prototype, platformConfigs = data.platformConfig, added, classConfigs, configs, configurator, keys, name, value, i, ln;
    delete prototype.platformConfig;
    if (platformConfigs instanceof Array) {
      throw new Error('platformConfigs must be specified as an object.');
    }
    configurator = me.getConfigurator();
    classConfigs = configurator.configs;
    keys = Ext.getPlatformConfigKeys(platformConfigs);
    for (i = 0, ln = keys.length; i < ln; ++i) {
      configs = platformConfigs[keys[i]];
      added = null;
      for (name in configs) {
        value = configs[name];
        if (name in classConfigs) {
          (added || (added = {}))[name] = value;
        } else {
          prototype[name] = value;
        }
      }
      if (added) {
        configurator.add(added);
      }
    }
  }, callParent:function(args) {
    var method;
    return (method = this.callParent.caller) && (method.$previous || (method = method.$owner ? method : method.caller) && method.$owner.superclass.self[method.$name]).apply(this, args || noArgs);
  }, callSuper:function(args) {
    var method;
    return (method = this.callSuper.caller) && ((method = method.$owner ? method : method.caller) && method.$owner.superclass.self[method.$name]).apply(this, args || noArgs);
  }, mixin:function(name, mixinClass) {
    var me = this, mixin, prototype, key, statics, i, ln, mixinName, mixinValue, mixins, mixinStatics, staticName;
    if (typeof name !== 'string') {
      mixins = name;
      if (mixins instanceof Array) {
        for (i = 0, ln = mixins.length; i < ln; i++) {
          mixin = mixins[i];
          me.mixin(mixin.prototype.mixinId || mixin.$className, mixin);
        }
      } else {
        for (mixinName in mixins) {
          me.mixin(mixinName, mixins[mixinName]);
        }
      }
      return;
    }
    mixin = mixinClass.prototype;
    prototype = me.prototype;
    if (mixin.onClassMixedIn) {
      mixin.onClassMixedIn.call(mixinClass, me);
    }
    if (!prototype.hasOwnProperty('mixins')) {
      if ('mixins' in prototype) {
        prototype.mixins = Ext.Object.chain(prototype.mixins);
      } else {
        prototype.mixins = {};
      }
    }
    for (key in mixin) {
      mixinValue = mixin[key];
      if (key === 'mixins') {
        Ext.applyIf(prototype.mixins, mixinValue);
      } else {
        if (!(key === 'mixinId' || key === 'config' || key === '$inheritableStatics') && prototype[key] === undefined) {
          prototype[key] = mixinValue;
        }
      }
    }
    statics = mixin.$inheritableStatics;
    if (statics) {
      mixinStatics = {};
      for (staticName in statics) {
        if (!me.hasOwnProperty(staticName)) {
          mixinStatics[staticName] = mixinClass[staticName];
        }
      }
      me.addInheritableStatics(mixinStatics);
    }
    if ('config' in mixin) {
      me.addConfig(mixin.config, mixinClass);
    }
    prototype.mixins[name] = mixin;
    if (mixin.afterClassMixedIn) {
      mixin.afterClassMixedIn.call(mixinClass, me);
    }
    return me;
  }, addConfig:function(config, mixinClass) {
    var cfg = this.$config || this.getConfigurator();
    cfg.add(config, mixinClass);
  }, addCachedConfig:function(config, isMixin) {
    var cached = {}, key;
    for (key in config) {
      cached[key] = {cached:true, $value:config[key]};
    }
    this.addConfig(cached, isMixin);
  }, getConfigurator:function() {
    return this.$config || new Ext.Configurator(this);
  }, getName:function() {
    return Ext.getClassName(this);
  }, createAlias:flexSetter(function(alias, origin) {
    aliasOneMember[alias] = function() {
      return this[origin].apply(this, arguments);
    };
    this.override(aliasOneMember);
    delete aliasOneMember[alias];
  })});
  for (baseStaticMember in Base) {
    if (Base.hasOwnProperty(baseStaticMember)) {
      baseStaticMembers.push(baseStaticMember);
    }
  }
  Base.$staticMembers = baseStaticMembers;
  Base.getConfigurator();
  Base.addMembers({$className:'Ext.Base', $configTransforms:{}, isInstance:true, $configPrefixed:true, $configStrict:true, isConfiguring:false, isFirstInstance:false, destroyed:false, clearPropertiesOnDestroy:true, clearPrototypeOnDestroy:false, statics:function() {
    var method = this.statics.caller, self = this.self;
    if (!method) {
      return self;
    }
    return method.$owner;
  }, callParent:function(args) {
    var method, superMethod = (method = this.callParent.caller) && (method.$previous || (method = method.$owner ? method : method.caller) && method.$owner.superclass[method.$name]);
    if (!superMethod) {
      method = this.callParent.caller;
      var parentClass, methodName;
      if (!method.$owner) {
        if (!method.caller) {
          throw new Error('Attempting to call a protected method from the ' + 'public scope, which is not allowed');
        }
        method = method.caller;
      }
      parentClass = method.$owner.superclass;
      methodName = method.$name;
      if (!(methodName in parentClass)) {
        throw new Error("this.callParent() was called but there's no such method (" + methodName + ') found in the parent class (' + (Ext.getClassName(parentClass) || 'Object') + ')');
      }
    }
    return superMethod.apply(this, args || noArgs);
  }, callSuper:function(args) {
    var method, superMethod = (method = this.callSuper.caller) && ((method = method.$owner ? method : method.caller) && method.$owner.superclass[method.$name]);
    if (!superMethod) {
      method = this.callSuper.caller;
      var parentClass, methodName;
      if (!method.$owner) {
        if (!method.caller) {
          throw new Error('Attempting to call a protected method from the ' + 'public scope, which is not allowed');
        }
        method = method.caller;
      }
      parentClass = method.$owner.superclass;
      methodName = method.$name;
      if (!(methodName in parentClass)) {
        throw new Error("this.callSuper() was called but there's no such method (" + methodName + ') found in the parent class (' + (Ext.getClassName(parentClass) || 'Object') + ')');
      }
    }
    return superMethod.apply(this, args || noArgs);
  }, self:Base, constructor:function() {
    return this;
  }, initConfig:function(instanceConfig) {
    var me = this, cfg = me.self.getConfigurator();
    me.initConfig = Ext.emptyFn;
    me.initialConfig = instanceConfig || {};
    cfg.configure(me, instanceConfig);
    return me;
  }, beforeInitConfig:Ext.emptyFn, getConfig:function(name, peek, ifInitialized) {
    var me = this, ret, cfg, propName;
    if (name) {
      cfg = me.self.$config.configs[name];
      if (cfg) {
        propName = me.$configPrefixed ? cfg.names.internal : name;
        if (ifInitialized) {
          ret = me.hasOwnProperty(propName) ? me[propName] : null;
        } else {
          if (peek) {
            ret = me.hasOwnProperty(propName) ? me[propName] : me.config[name];
          } else {
            ret = me[cfg.names.get]();
          }
        }
      } else {
        ret = me[name];
      }
    } else {
      ret = me.getCurrentConfig();
    }
    return ret;
  }, destroyMembers:function() {
    var me = this, configs = me.self.$config.configs, len = arguments.length, cfg, name, value, i;
    for (i = 0; i < len; i++) {
      name = arguments[i];
      cfg = configs[name];
      name = cfg && me.$configPrefixed ? cfg.names.internal : name;
      value = me.hasOwnProperty(name) && me[name];
      if (value) {
        Ext.destroy(value);
        me[name] = null;
      }
    }
  }, freezeConfig:function(name) {
    var me = this, config = Ext.Config.get(name), names = config.names, value = me[names.get]();
    me[names.set] = function(v) {
      if (v !== value) {
        Ext.raise('Cannot change frozen config "' + name + '"');
      }
      return me;
    };
    if (!Ext.isIE8) {
      Object.defineProperty(me, me.$configPrefixed ? names.internal : name, {get:function() {
        return value;
      }, set:function(v) {
        if (v !== value) {
          Ext.raise('Cannot change frozen config "' + name + '"');
        }
      }});
    }
  }, setConfig:function(name, value, options) {
    var me = this, configurator, config, prop;
    if (name) {
      configurator = me.self.getConfigurator();
      if (typeof name === 'string') {
        config = configurator.configs[name];
        if (!config) {
          if (me.$configStrict) {
            prop = me.self.prototype[name];
            if (typeof prop === 'function' && !prop.$nullFn) {
              Ext.Error.raise('Cannot override method ' + name + ' on ' + me.$className + ' instance.');
              return me;
            } else {
              if (name !== 'type') {
                Ext.log.warn('No such config "' + name + '" for class ' + me.$className);
              }
            }
          }
          config = Ext.Config.map[name] || Ext.Config.get(name);
        }
        if (me[config.names.set]) {
          me[config.names.set](value);
        } else {
          me[name] = value;
        }
      } else {
        configurator.reconfigure(me, name, options || value);
      }
    }
    return me;
  }, getConfigWatcher:function() {
    return this.$configWatch || (this.$configWatch = new Ext.mixin.Watchable);
  }, watchConfig:function(name, fn, scope) {
    var watcher = this.getConfigWatcher();
    return watcher.on.apply(watcher, arguments);
  }, $configWatch:null, getCurrentConfig:function() {
    var cfg = this.self.getConfigurator();
    return cfg.getCurrentConfig(this);
  }, hasConfig:function(name) {
    return name in this.defaultConfig;
  }, getInitialConfig:function(name) {
    var config = this.config;
    if (!name) {
      return config;
    }
    return config[name];
  }, $links:null, link:function(name, value) {
    var me = this, links = me.$links || (me.$links = {});
    links[name] = true;
    me[name] = value;
    return value;
  }, unlink:function(names) {
    var me = this, i, ln, link, value;
    if (!Ext.isArray(names)) {
      Ext.raise('Invalid argument - expected array of strings');
    }
    for (i = 0, ln = names.length; i < ln; i++) {
      link = names[i];
      value = me[link];
      if (value) {
        if (value.isInstance && !value.destroyed) {
          value.destroy();
        } else {
          if (value.parentNode && 'nodeType' in value) {
            value.parentNode.removeChild(value);
          }
        }
      }
      me[link] = null;
    }
    return me;
  }, $reap:function() {
    var me = this, keepers = me.$noClearOnDestroy, props, prop, val, t, i, len;
    props = Ext.Object.getKeys(me);
    for (i = 0, len = props.length; i < len; i++) {
      prop = props[i];
      val = me[prop];
      if (val && !(keepers && keepers[prop])) {
        t = typeof val;
        if (t === 'object' || t === 'function' && !val.$noClearOnDestroy) {
          me[prop] = null;
        }
      }
    }
    me.$nulled = true;
    if (Object.setPrototypeOf) {
      if (me.clearPrototypeOnDestroy && !me.$vetoClearingPrototypeOnDestroy) {
        props = me.$preservePrototypeProperties;
        if (props) {
          for (i = 0, len = props.length; i < len; i++) {
            prop = props[i];
            if (!me.hasOwnProperty(prop)) {
              me[prop] = me[prop];
            }
          }
        }
        Object.setPrototypeOf(me, null);
      }
    }
  }, destroy:function() {
    var me = this, links = me.$links, clearPropertiesOnDestroy = me.clearPropertiesOnDestroy;
    if (links) {
      me.$links = null;
      me.unlink(Ext.Object.getKeys(links));
    }
    me.destroy = Ext.emptyFn;
    me.isDestroyed = me.destroyed = true;
    if (clearPropertiesOnDestroy === true) {
      if (!me.isObservable) {
        me.$reap();
      }
    } else {
      if (clearPropertiesOnDestroy) {
        if (clearPropertiesOnDestroy !== 'async') {
          Ext.raise('Invalid value for clearPropertiesOnDestroy');
        }
        Reaper.add(me);
      }
    }
  }});
  BasePrototype.callOverridden = BasePrototype.callParent;
  Ext.privacyViolation = function(cls, existing, member, isStatic) {
    var name = member.$name, conflictCls = existing.$owner && existing.$owner.$className, s = isStatic ? 'static ' : '', msg = member.$privacy ? 'Private ' + s + member.$privacy + ' method "' + name + '"' : 'Public ' + s + 'method "' + name + '"';
    if (cls.$className) {
      msg = cls.$className + ': ' + msg;
    }
    if (!existing.$privacy) {
      msg += conflictCls ? ' hides public method inherited from ' + conflictCls : ' hides inherited public method.';
    } else {
      msg += conflictCls ? ' conflicts with private ' + existing.$privacy + ' method declared by ' + conflictCls : ' conflicts with inherited private ' + existing.$privacy + ' method.';
    }
    var compat = Ext.getCompatVersion(), ver = Ext.getVersion();
    if (ver && compat && compat.lt(ver)) {
      Ext.log.error(msg);
    } else {
      Ext.raise(msg);
    }
  };
  Ext.Reaper.tick.$skipTimerCheck = true;
  return Base;
}(Ext.Function.flexSetter);
(function(LRU, prototype) {
  (Ext.util || (Ext.util = {})).LRU = LRU = function(config) {
    var me = this, head;
    if (config) {
      Ext.apply(me, config);
    }
    me.head = head = {id:me.seed = 0, key:null, value:null};
    me.map = {};
    head.next = head.prev = head;
  };
  LRU.prototype = prototype = {count:0, add:function(key, value) {
    var me = this, map = me.map, entry = map[key];
    if (entry) {
      me.unlink(entry);
      --me.count;
    }
    map[key] = entry = {id:++me.seed, key:key, value:value};
    me.link(entry);
    ++me.count;
    return entry;
  }, clear:function(fn, scope) {
    var me = this, head = me.head, entry = head.next;
    head.next = head.prev = head;
    me.count = 0;
    if (fn && !fn.$nullFn) {
      for (; entry !== head; entry = entry.next) {
        fn.call(scope || me, entry.key, entry.value);
      }
    }
  }, each:function(fn, scope) {
    var head, ent;
    scope = scope || this;
    for (head = this.head, ent = head.next; ent !== head; ent = ent.next) {
      if (fn.call(scope, ent.key, ent.value)) {
        break;
      }
    }
  }, prune:function(fn, scope) {
    var me = this, entry = me.head.prev, ret;
    if (me.count) {
      ret = entry.value;
      me.unlink(entry);
      --me.count;
      if (fn) {
        fn.call(scope || me, entry.key, ret);
      }
    }
    return ret;
  }, remove:function(key) {
    var me = this, map = me.map, entry = map[key], value;
    if (entry) {
      me.unlink(entry);
      value = entry.value;
      delete map[key];
      --me.count;
    }
    return value;
  }, touch:function(key) {
    var me = this, head = me.head, entry = me.map[key];
    if (entry && entry.prev !== head) {
      me.unlink(entry);
      me.link(entry);
    }
  }, trim:function(size, fn, scope) {
    while (this.count > size) {
      this.prune(fn, scope);
    }
  }, link:function(entry) {
    var head = this.head, first = head.next;
    entry.next = first;
    entry.prev = head;
    head.next = entry;
    first.prev = entry;
  }, unlink:function(entry) {
    var next = entry.next, prev = entry.prev;
    prev.next = next;
    next.prev = prev;
  }};
  prototype.destroy = function() {
    this.clear.apply(this, arguments);
  };
})();
(function(LRU, fn, Cache) {
  Ext.util.Cache = Cache = function(config) {
    LRU.call(this, config);
  };
  fn.prototype = LRU.prototype;
  Cache.prototype = Ext.apply(new fn, {maxSize:100, clear:function() {
    LRU.prototype.clear.call(this, this.evict);
  }, get:function(key) {
    var me = this, entry = me.map[key], value;
    if (entry) {
      value = entry.value;
      me.touch(key);
    } else {
      value = me.miss.apply(me, arguments);
      me.add(key, value);
      me.trim(me.maxSize, me.evict);
    }
    return value;
  }, evict:Ext.emptyFn});
})(Ext.util.LRU, function() {
});
(function() {
  var ExtClass, Base = Ext.Base, baseStaticMembers = Base.$staticMembers, ruleKeySortFn = function(a, b) {
    return a.length - b.length || (a < b ? -1 : a > b ? 1 : 0);
  };
  function makeCtor(className) {
    function constructor() {
      return this.constructor.apply(this, arguments) || null;
    }
    if (className) {
      constructor.name = className;
    }
    return constructor;
  }
  Ext.Class = ExtClass = function(Class, data, onCreated) {
    if (typeof Class !== 'function') {
      onCreated = data;
      data = Class;
      Class = null;
    }
    if (!data) {
      data = {};
    }
    Class = ExtClass.create(Class, data);
    ExtClass.process(Class, data, onCreated);
    return Class;
  };
  Ext.apply(ExtClass, {makeCtor:makeCtor, onBeforeCreated:function(Class, data, hooks) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, '\x3e\x3e Ext.Class#onBeforeCreated', arguments);
    }
    Class.addMembers(data);
    hooks.onCreated.call(Class, Class);
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, '\x3c\x3c Ext.Class#onBeforeCreated', arguments);
    }
  }, create:function(Class, data) {
    var i = baseStaticMembers.length, name;
    if (!Class) {
      Class = makeCtor(data.$className);
    }
    while (i--) {
      name = baseStaticMembers[i];
      Class[name] = Base[name];
    }
    return Class;
  }, process:function(Class, data, onCreated) {
    var preprocessorStack = data.preprocessors || ExtClass.defaultPreprocessors, registeredPreprocessors = this.preprocessors, hooks = {onBeforeCreated:this.onBeforeCreated}, preprocessors = [], preprocessor, preprocessorsProperties, i, ln, j, subLn, preprocessorProperty;
    delete data.preprocessors;
    Class._classHooks = hooks;
    for (i = 0, ln = preprocessorStack.length; i < ln; i++) {
      preprocessor = preprocessorStack[i];
      if (typeof preprocessor === 'string') {
        preprocessor = registeredPreprocessors[preprocessor];
        preprocessorsProperties = preprocessor.properties;
        if (preprocessorsProperties === true) {
          preprocessors.push(preprocessor.fn);
        } else {
          if (preprocessorsProperties) {
            for (j = 0, subLn = preprocessorsProperties.length; j < subLn; j++) {
              preprocessorProperty = preprocessorsProperties[j];
              if (data.hasOwnProperty(preprocessorProperty)) {
                preprocessors.push(preprocessor.fn);
                break;
              }
            }
          }
        }
      } else {
        preprocessors.push(preprocessor);
      }
    }
    hooks.onCreated = onCreated ? onCreated : Ext.emptyFn;
    hooks.preprocessors = preprocessors;
    this.doProcess(Class, data, hooks);
  }, doProcess:function(Class, data, hooks) {
    var me = this, preprocessors = hooks.preprocessors, preprocessor = preprocessors.shift(), doProcess = me.doProcess;
    for (; preprocessor; preprocessor = preprocessors.shift()) {
      if (preprocessor.call(me, Class, data, hooks, doProcess) === false) {
        return;
      }
    }
    hooks.onBeforeCreated.apply(me, arguments);
  }, preprocessors:{}, registerPreprocessor:function(name, fn, properties, position, relativeTo) {
    if (!position) {
      position = 'last';
    }
    if (!properties) {
      properties = [name];
    }
    this.preprocessors[name] = {name:name, properties:properties || false, fn:fn};
    this.setDefaultPreprocessorPosition(name, position, relativeTo);
    return this;
  }, getPreprocessor:function(name) {
    return this.preprocessors[name];
  }, getPreprocessors:function() {
    return this.preprocessors;
  }, defaultPreprocessors:[], getDefaultPreprocessors:function() {
    return this.defaultPreprocessors;
  }, setDefaultPreprocessors:function(preprocessors) {
    this.defaultPreprocessors = Ext.Array.from(preprocessors);
    return this;
  }, setDefaultPreprocessorPosition:function(name, offset, relativeName) {
    var defaultPreprocessors = this.defaultPreprocessors, index;
    if (typeof offset === 'string') {
      if (offset === 'first') {
        defaultPreprocessors.unshift(name);
        return this;
      } else {
        if (offset === 'last') {
          defaultPreprocessors.push(name);
          return this;
        }
      }
      offset = offset === 'after' ? 1 : -1;
    }
    index = Ext.Array.indexOf(defaultPreprocessors, relativeName);
    if (index !== -1) {
      Ext.Array.splice(defaultPreprocessors, Math.max(0, index + offset), 0, name);
    }
    return this;
  }});
  ExtClass.registerPreprocessor('extend', function(Class, data, hooks) {
    var Base = Ext.Base, basePrototype = Base.prototype, extend = data.extend, Parent, parentPrototype, i;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, 'Ext.Class#extendPreProcessor', arguments);
    }
    delete data.extend;
    if (extend && extend !== Object) {
      Parent = extend;
    } else {
      Parent = Base;
    }
    parentPrototype = Parent.prototype;
    if (!Parent.$isClass) {
      for (i in basePrototype) {
        if (!parentPrototype[i]) {
          parentPrototype[i] = basePrototype[i];
        }
      }
    }
    Class.extend(Parent);
    Class.triggerExtended.apply(Class, arguments);
    if (data.onClassExtended) {
      Class.onExtended(data.onClassExtended, Class);
      delete data.onClassExtended;
    }
  }, true);
  ExtClass.registerPreprocessor('privates', function(Class, data) {
    var privates = data.privates, statics = privates.statics, privacy = privates.privacy || true;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, 'Ext.Class#privatePreprocessor', arguments);
    }
    delete data.privates;
    delete privates.statics;
    Class.addMembers(privates, false, privacy);
    if (statics) {
      Class.addMembers(statics, true, privacy);
    }
  });
  ExtClass.registerPreprocessor('statics', function(Class, data) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, 'Ext.Class#staticsPreprocessor', arguments);
    }
    Class.addStatics(data.statics);
    delete data.statics;
  });
  ExtClass.registerPreprocessor('inheritableStatics', function(Class, data) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, 'Ext.Class#inheritableStaticsPreprocessor', arguments);
    }
    Class.addInheritableStatics(data.inheritableStatics);
    delete data.inheritableStatics;
  });
  Ext.createRuleFn = function(code) {
    return new Function('$c', 'with($c) { try { return (' + code + '); } catch(e) { return false;}}');
  };
  Ext.expressionCache = new Ext.util.Cache({miss:Ext.createRuleFn});
  Ext.ruleKeySortFn = ruleKeySortFn;
  Ext.getPlatformConfigKeys = function(platformConfig) {
    var ret = [], platform, rule;
    for (platform in platformConfig) {
      rule = Ext.expressionCache.get(platform);
      if (rule(Ext.platformTags)) {
        ret.push(platform);
      }
    }
    ret.sort(ruleKeySortFn);
    return ret;
  };
  ExtClass.registerPreprocessor('config', function(Class, data) {
    if (data.hasOwnProperty('$configPrefixed')) {
      Class.prototype.$configPrefixed = data.$configPrefixed;
    }
    Class.addConfig(data.config);
    delete data.config;
  });
  ExtClass.registerPreprocessor('cachedConfig', function(Class, data) {
    if (data.hasOwnProperty('$configPrefixed')) {
      Class.prototype.$configPrefixed = data.$configPrefixed;
    }
    Class.addCachedConfig(data.cachedConfig);
    delete data.cachedConfig;
  });
  ExtClass.registerPreprocessor('mixins', function(Class, data, hooks) {
    var mixins = data.mixins, onCreated = hooks.onCreated;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, 'Ext.Class#mixinsPreprocessor', arguments);
    }
    delete data.mixins;
    hooks.onCreated = function() {
      if (Ext.classSystemMonitor) {
        Ext.classSystemMonitor(Class, 'Ext.Class#mixinsPreprocessor#beforeCreated', arguments);
      }
      hooks.onCreated = onCreated;
      Class.mixin(mixins);
      return hooks.onCreated.apply(this, arguments);
    };
  });
  Ext.extend = function(Class, Parent, members) {
    var cls, m;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, 'Ext.Class#extend-backwards-compatible', arguments);
    }
    if (arguments.length === 2 && Ext.isObject(Parent)) {
      members = Parent;
      Parent = Class;
      Class = null;
    }
    if (!Parent) {
      throw new Error('[Ext.extend] Attempting to extend from a class which has not ' + 'been loaded on the page.');
    }
    members.extend = Parent;
    members.preprocessors = ['extend', 'statics', 'inheritableStatics', 'mixins', 'config'];
    if (Class) {
      cls = new ExtClass(Class, members);
      cls.prototype.constructor = Class;
    } else {
      cls = new ExtClass(members);
    }
    cls.prototype.override = function(o) {
      for (m in o) {
        if (o.hasOwnProperty(m)) {
          this[m] = o[m];
        }
      }
    };
    return cls;
  };
})();
Ext.Inventory = function() {
  var me = this;
  me.names = [];
  me.paths = {};
  me.alternateToName = {};
  me.aliasToName = {};
  me.nameToAliases = {};
  me.nameToAlternates = {};
  me.nameToPrefix = {};
};
Ext.Inventory.prototype = {_array1:[0], prefixes:null, dotRe:/\./g, wildcardRe:/\*/g, addAlias:function(className, alias, update) {
  return this.addMapping(className, alias, this.aliasToName, this.nameToAliases, update);
}, addAlternate:function(className, alternate) {
  return this.addMapping(className, alternate, this.alternateToName, this.nameToAlternates);
}, addMapping:function(className, alternate, toName, nameTo, update) {
  var name = className.$className || className, mappings = name, array = this._array1, a, aliases, cls, i, length, nameMapping;
  if (Ext.isString(name)) {
    mappings = {};
    mappings[name] = alternate;
  }
  for (cls in mappings) {
    aliases = mappings[cls];
    if (Ext.isString(aliases)) {
      array[0] = aliases;
      aliases = array;
    }
    length = aliases.length;
    nameMapping = nameTo[cls] || (nameTo[cls] = []);
    for (i = 0; i < length; ++i) {
      if (!(a = aliases[i])) {
        continue;
      }
      if (toName[a] !== cls) {
        if (!update && toName[a] && 'Ext.Gadget' !== a) {
          Ext.log.warn("Overriding existing mapping: '" + a + "' From '" + toName[a] + "' to '" + cls + "'. Is this intentional?");
        }
        toName[a] = cls;
        nameMapping.push(a);
      }
    }
  }
}, getAliasesByName:function(name) {
  return this.nameToAliases[name] || null;
}, getAlternatesByName:function(name) {
  return this.nameToAlternates[name] || null;
}, getNameByAlias:function(alias) {
  return this.aliasToName[alias] || '';
}, getNameByAlternate:function(alternate) {
  return this.alternateToName[alternate] || '';
}, getNamesByExpression:function(expression, exclude, accumulate) {
  var me = this, aliasToName = me.aliasToName, alternateToName = me.alternateToName, nameToAliases = me.nameToAliases, nameToAlternates = me.nameToAlternates, map = accumulate ? exclude : {}, names = [], expressions = Ext.isString(expression) ? [expression] : expression, length = expressions.length, wildcardRe = me.wildcardRe, expr, i, list, match, n, name, regex;
  for (i = 0; i < length; ++i) {
    if ((expr = expressions[i]).indexOf('*') < 0) {
      if (!(name = aliasToName[expr])) {
        if (!(name = alternateToName[expr])) {
          name = expr;
        }
      }
      if (!(name in map) && !(exclude && name in exclude)) {
        map[name] = 1;
        names.push(name);
      }
    } else {
      regex = new RegExp('^' + expr.replace(wildcardRe, '(.*?)') + '$');
      for (name in nameToAliases) {
        if (!(name in map) && !(exclude && name in exclude)) {
          if (!(match = regex.test(name))) {
            n = (list = nameToAliases[name]).length;
            while (!match && n-- > 0) {
              match = regex.test(list[n]);
            }
            list = nameToAlternates[name];
            if (list && !match) {
              n = list.length;
              while (!match && n-- > 0) {
                match = regex.test(list[n]);
              }
            }
          }
          if (match) {
            map[name] = 1;
            names.push(name);
          }
        }
      }
    }
  }
  return names;
}, getPath:function(className) {
  var me = this, paths = me.paths, ret = '', prefix;
  if (className in paths) {
    ret = paths[className];
  } else {
    prefix = me.nameToPrefix[className] || (me.nameToPrefix[className] = me.getPrefix(className));
    if (prefix) {
      className = className.substring(prefix.length + 1);
      ret = paths[prefix];
      if (ret) {
        ret += '/';
      }
    }
    ret += className.replace(me.dotRe, '/') + '.js';
  }
  return ret;
}, getPrefix:function(className) {
  if (className in this.paths) {
    return className;
  } else {
    if (className in this.nameToPrefix) {
      return this.nameToPrefix[className];
    }
  }
  var prefixes = this.getPrefixes(), length = className.length, items, currChar, prefix, j, jlen;
  while (length-- > 0) {
    items = prefixes[length];
    if (items) {
      currChar = className.charAt(length);
      if (currChar !== '.') {
        continue;
      }
      for (j = 0, jlen = items.length; j < jlen; j++) {
        prefix = items[j];
        if (prefix === className.substring(0, length)) {
          return prefix;
        }
      }
    }
  }
  return '';
}, getPrefixes:function() {
  var me = this, prefixes = me.prefixes, names, name, nameLength, items, i, len;
  if (!prefixes) {
    names = me.names.slice(0);
    me.prefixes = prefixes = [];
    for (i = 0, len = names.length; i < len; i++) {
      name = names[i];
      nameLength = name.length;
      items = prefixes[nameLength] || (prefixes[nameLength] = []);
      items.push(name);
    }
  }
  return prefixes;
}, removeName:function(name) {
  var me = this, aliasToName = me.aliasToName, alternateToName = me.alternateToName, nameToAliases = me.nameToAliases, nameToAlternates = me.nameToAlternates, aliases = nameToAliases[name], alternates = nameToAlternates[name], i, a;
  delete nameToAliases[name];
  delete nameToAlternates[name];
  delete me.nameToPrefix[name];
  if (aliases) {
    for (i = aliases.length; i--;) {
      if (name === aliasToName[a = aliases[i]]) {
        delete aliasToName[a];
      }
    }
  }
  if (alternates) {
    for (i = alternates.length; i--;) {
      if (name === alternateToName[a = alternates[i]]) {
        delete alternateToName[a];
      }
    }
  }
}, resolveName:function(name) {
  var me = this, trueName;
  if (!(name in me.nameToAliases)) {
    if (!(trueName = me.aliasToName[name])) {
      trueName = me.alternateToName[name];
    }
  }
  return trueName || name;
}, select:function(receiver, scope) {
  var me = this, excludes = {}, ret = {excludes:excludes, exclude:function() {
    me.getNamesByExpression(arguments[0], excludes, true);
    return this;
  }}, name;
  for (name in receiver) {
    ret[name] = me.selectMethod(excludes, receiver[name], scope || receiver);
  }
  return ret;
}, selectMethod:function(excludes, fn, scope) {
  var me = this;
  return function(include) {
    var args = Ext.Array.slice(arguments, 1);
    args.unshift(me.getNamesByExpression(include, excludes));
    return fn.apply(scope, args);
  };
}, setPath:Ext.Function.flexSetter(function(name, path) {
  var me = this;
  me.paths[name] = path;
  me.names.push(name);
  me.prefixes = null;
  me.nameToPrefix = {};
  return me;
})};
Ext.ClassManager = function(Class, alias, arraySlice, arrayFrom, global) {
  var makeCtor = Ext.Class.makeCtor, nameLookupStack = [], namespaceCache = {Ext:{name:'Ext', value:Ext}}, Manager = Ext.apply(new Ext.Inventory, {classes:{}, classCount:0, classState:{}, existCache:{}, instantiators:[], isCreated:function(className) {
    if (typeof className !== 'string' || className.length < 1) {
      throw new Error('[Ext.ClassManager] Invalid classname, must be a string and ' + 'must not be empty');
    }
    if (Manager.classes[className] || Manager.existCache[className]) {
      return true;
    }
    if (!Manager.lookupName(className, false)) {
      return false;
    }
    Manager.triggerCreated(className);
    return true;
  }, createdListeners:[], nameCreatedListeners:{}, existsListeners:[], nameExistsListeners:{}, overrideMap:{}, triggerCreated:function(className, state) {
    Manager.existCache[className] = state || 1;
    Manager.classState[className] += 40;
    Manager.notify(className, Manager.createdListeners, Manager.nameCreatedListeners);
  }, onCreated:function(fn, scope, className) {
    Manager.addListener(fn, scope, className, Manager.createdListeners, Manager.nameCreatedListeners);
  }, notify:function(className, listeners, nameListeners) {
    var alternateNames = Manager.getAlternatesByName(className), names = [className], i, ln, j, subLn, listener, name;
    for (i = 0, ln = listeners.length; i < ln; i++) {
      listener = listeners[i];
      listener.fn.call(listener.scope, className);
    }
    while (names) {
      for (i = 0, ln = names.length; i < ln; i++) {
        name = names[i];
        listeners = nameListeners[name];
        if (listeners) {
          for (j = 0, subLn = listeners.length; j < subLn; j++) {
            listener = listeners[j];
            listener.fn.call(listener.scope, name);
          }
          delete nameListeners[name];
        }
      }
      names = alternateNames;
      alternateNames = null;
    }
  }, addListener:function(fn, scope, className, listeners, nameListeners) {
    var i;
    if (Ext.isArray(className)) {
      fn = Ext.Function.createBarrier(className.length, fn, scope);
      for (i = 0; i < className.length; i++) {
        this.addListener(fn, null, className[i], listeners, nameListeners);
      }
      return;
    }
    var listener = {fn:fn, scope:scope};
    if (className) {
      if (this.isCreated(className)) {
        fn.call(scope, className);
        return;
      }
      if (!nameListeners[className]) {
        nameListeners[className] = [];
      }
      nameListeners[className].push(listener);
    } else {
      listeners.push(listener);
    }
  }, $namespaceCache:namespaceCache, addRootNamespaces:function(namespaces) {
    var name;
    for (name in namespaces) {
      namespaceCache[name] = {name:name, value:namespaces[name]};
    }
  }, clearNamespaceCache:function() {
    var name;
    nameLookupStack.length = 0;
    for (name in namespaceCache) {
      if (!namespaceCache[name].value) {
        delete namespaceCache[name];
      }
    }
  }, getNamespaceEntry:function(namespace) {
    var entry, i;
    if (typeof namespace !== 'string') {
      return namespace;
    }
    entry = namespaceCache[namespace];
    if (!entry) {
      i = namespace.lastIndexOf('.');
      if (i < 0) {
        entry = {name:namespace};
      } else {
        entry = {name:namespace.substring(i + 1), parent:Manager.getNamespaceEntry(namespace.substring(0, i))};
      }
      namespaceCache[namespace] = entry;
    }
    return entry;
  }, lookupName:function(namespace, autoCreate) {
    var entry = Manager.getNamespaceEntry(namespace), scope = Ext.global, i = 0, e, parent;
    for (e = entry; e; e = e.parent) {
      nameLookupStack[i++] = e;
    }
    while (scope && i-- > 0) {
      e = nameLookupStack[i];
      parent = scope;
      scope = e.value || scope[e.name];
      if (!scope && autoCreate) {
        parent[e.name] = scope = {};
      }
    }
    return scope;
  }, setNamespace:function(namespace, value) {
    var entry = Manager.getNamespaceEntry(namespace), scope = Ext.global;
    if (entry.parent) {
      scope = Manager.lookupName(entry.parent, true);
    }
    scope[entry.name] = value;
    return value;
  }, setXType:function(cls, xtype) {
    var className = cls.$className, C = className ? cls : Manager.get(className = cls), proto = C.prototype, xtypes = proto.xtypes, xtypesChain = proto.xtypesChain, xtypesMap = proto.xtypesMap;
    if (!proto.hasOwnProperty('xtypes')) {
      proto.xtypes = xtypes = [];
      proto.xtypesChain = xtypesChain = xtypesChain ? xtypesChain.slice(0) : [];
      proto.xtypesMap = xtypesMap = Ext.apply({}, xtypesMap);
    }
    Manager.addAlias(className, 'widget.' + xtype, true);
    xtypes.push(xtype);
    xtypesChain.push(xtype);
    xtypesMap[xtype] = true;
  }, set:function(name, value) {
    var targetName = Manager.getName(value);
    Manager.classes[name] = Manager.setNamespace(name, value);
    Manager.classCount++;
    if (targetName && targetName !== name) {
      Manager.addAlternate(targetName, name);
    }
    return Manager;
  }, get:function(name) {
    return Manager.classes[name] || Manager.lookupName(name, false);
  }, addNameAliasMappings:function(aliases) {
    Manager.addAlias(aliases);
  }, addNameAlternateMappings:function(alternates) {
    Manager.addAlternate(alternates);
  }, getByAlias:function(alias) {
    return Manager.get(Manager.getNameByAlias(alias));
  }, getByConfig:function(config, aliasPrefix) {
    var xclass = config.xclass, name;
    if (xclass) {
      name = xclass;
    } else {
      name = config.xtype;
      if (name) {
        aliasPrefix = 'widget.';
      } else {
        name = config.type;
      }
      name = Manager.getNameByAlias(aliasPrefix + name);
    }
    return Manager.get(name);
  }, getName:function(object) {
    return object && object.$className || '';
  }, getClass:function(object) {
    return object && object.self || null;
  }, create:function(className, data, createdFn) {
    var ctor;
    if (className != null && typeof className !== 'string') {
      throw new Error("[Ext.define] Invalid class name '" + className + "' specified, must be a non-empty string");
    }
    ctor = makeCtor(className);
    if (typeof data === 'function') {
      data = data(ctor);
    }
    if (className) {
      if (Manager.classes[className]) {
        Ext.log.warn("[Ext.define] Duplicate class name '" + className + "' specified, must be a non-empty string");
      }
      ctor.name = className;
    }
    data.$className = className;
    return new Class(ctor, data, function() {
      var postprocessorStack = data.postprocessors || Manager.defaultPostprocessors, registeredPostprocessors = Manager.postprocessors, postprocessors = [], postprocessor, i, ln, j, subLn, postprocessorProperties, postprocessorProperty;
      delete data.postprocessors;
      for (i = 0, ln = postprocessorStack.length; i < ln; i++) {
        postprocessor = postprocessorStack[i];
        if (typeof postprocessor === 'string') {
          postprocessor = registeredPostprocessors[postprocessor];
          postprocessorProperties = postprocessor.properties;
          if (postprocessorProperties === true) {
            postprocessors.push(postprocessor.fn);
          } else {
            if (postprocessorProperties) {
              for (j = 0, subLn = postprocessorProperties.length; j < subLn; j++) {
                postprocessorProperty = postprocessorProperties[j];
                if (data.hasOwnProperty(postprocessorProperty)) {
                  postprocessors.push(postprocessor.fn);
                  break;
                }
              }
            }
          }
        } else {
          postprocessors.push(postprocessor);
        }
      }
      data.postprocessors = postprocessors;
      data.createdFn = createdFn;
      Manager.processCreate(className, this, data);
    });
  }, processCreate:function(className, cls, clsData) {
    var me = this, postprocessor = clsData.postprocessors.shift(), createdFn = clsData.createdFn;
    if (!postprocessor) {
      if (Ext.classSystemMonitor) {
        Ext.classSystemMonitor(className, 'Ext.ClassManager#classCreated', arguments);
      }
      if (className) {
        me.set(className, cls);
      }
      delete cls._classHooks;
      if (createdFn) {
        createdFn.call(cls, cls);
      }
      if (className) {
        me.triggerCreated(className);
      }
      return;
    }
    if (postprocessor.call(me, className, cls, clsData, me.processCreate) !== false) {
      me.processCreate(className, cls, clsData);
    }
  }, createOverride:function(className, data, createdFn) {
    var me = this, overriddenClassName = data.override, requires = data.requires, uses = data.uses, mixins = data.mixins, mixinsIsArray, compat = 1, dependenciesLoaded, classReady;
    classReady = function() {
      var cls, dependencies, i, key, temp;
      if (!dependenciesLoaded) {
        dependencies = requires ? requires.slice(0) : [];
        if (mixins) {
          if (!(mixinsIsArray = mixins instanceof Array)) {
            for (key in mixins) {
              if (Ext.isString(cls = mixins[key])) {
                dependencies.push(cls);
              }
            }
          } else {
            for (i = 0, temp = mixins.length; i < temp; ++i) {
              if (Ext.isString(cls = mixins[i])) {
                dependencies.push(cls);
              }
            }
          }
        }
        dependenciesLoaded = true;
        if (dependencies.length) {
          Ext.require(dependencies, classReady);
          return;
        }
      }
      if (mixinsIsArray) {
        for (i = 0, temp = mixins.length; i < temp; ++i) {
          if (Ext.isString(cls = mixins[i])) {
            mixins[i] = Ext.ClassManager.get(cls);
          }
        }
      } else {
        if (mixins) {
          for (key in mixins) {
            if (Ext.isString(cls = mixins[key])) {
              mixins[key] = Ext.ClassManager.get(cls);
            }
          }
        }
      }
      cls = overriddenClassName.$isClass ? overriddenClassName : me.get(overriddenClassName);
      delete data.override;
      delete data.compatibility;
      delete data.requires;
      delete data.uses;
      Ext.override(cls, data);
      Ext.Loader.history.push(className);
      if (uses) {
        Ext['Loader'].addUsedClasses(uses);
      }
      if (createdFn) {
        createdFn.call(cls, cls);
      }
    };
    if (className) {
      Manager.overrideMap[className] = true;
    }
    if ('compatibility' in data) {
      compat = data.compatibility;
      if (!compat) {
        compat = false;
      } else {
        if (typeof compat === 'number') {
          compat = true;
        } else {
          if (typeof compat !== 'boolean') {
            compat = Ext.checkVersion(compat);
          }
        }
      }
    }
    if (compat) {
      if (overriddenClassName.$isClass) {
        classReady();
      } else {
        me.onCreated(classReady, me, overriddenClassName);
      }
    }
    me.triggerCreated(className, 2);
    return me;
  }, instantiateByAlias:function() {
    var alias = arguments[0], args = arraySlice.call(arguments), className = this.getNameByAlias(alias);
    if (!className) {
      throw new Error('[Ext.createByAlias] Unrecognized alias: ' + alias);
    }
    args[0] = className;
    return Ext.create.apply(Ext, args);
  }, instantiate:function() {
    Ext.log.warn('Ext.ClassManager.instantiate() is deprecated. Use Ext.create() instead.');
    return Ext.create.apply(Ext, arguments);
  }, dynInstantiate:function(name, args) {
    args = arrayFrom(args, true);
    args.unshift(name);
    return Ext.create.apply(Ext, args);
  }, getInstantiator:function(length) {
    var instantiators = this.instantiators, instantiator, args, i;
    instantiator = instantiators[length];
    if (!instantiator) {
      i = length;
      args = [];
      for (i = 0; i < length; i++) {
        args.push('a[' + i + ']');
      }
      instantiator = instantiators[length] = new Function('c', 'a', 'return new c(' + args.join(',') + ')');
      instantiator.name = 'Ext.create' + length;
    }
    return instantiator;
  }, postprocessors:{}, defaultPostprocessors:[], registerPostprocessor:function(name, fn, properties, position, relativeTo) {
    if (!position) {
      position = 'last';
    }
    if (!properties) {
      properties = [name];
    }
    this.postprocessors[name] = {name:name, properties:properties || false, fn:fn};
    this.setDefaultPostprocessorPosition(name, position, relativeTo);
    return this;
  }, setDefaultPostprocessors:function(postprocessors) {
    this.defaultPostprocessors = arrayFrom(postprocessors);
    return this;
  }, setDefaultPostprocessorPosition:function(name, offset, relativeName) {
    var defaultPostprocessors = this.defaultPostprocessors, index;
    if (typeof offset === 'string') {
      if (offset === 'first') {
        defaultPostprocessors.unshift(name);
        return this;
      } else {
        if (offset === 'last') {
          defaultPostprocessors.push(name);
          return this;
        }
      }
      offset = offset === 'after' ? 1 : -1;
    }
    index = Ext.Array.indexOf(defaultPostprocessors, relativeName);
    if (index !== -1) {
      Ext.Array.splice(defaultPostprocessors, Math.max(0, index + offset), 0, name);
    }
    return this;
  }});
  Manager.registerPostprocessor('platformConfig', function(name, Class, data) {
    Class.addPlatformConfig(data);
  });
  Manager.registerPostprocessor('alias', function(name, cls, data) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(name, 'Ext.ClassManager#aliasPostProcessor', arguments);
    }
    var aliases = Ext.Array.from(data.alias), i, ln;
    for (i = 0, ln = aliases.length; i < ln; i++) {
      alias = aliases[i];
      this.addAlias(cls, alias);
    }
  }, ['xtype', 'alias']);
  Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(name, 'Ext.ClassManager#singletonPostProcessor', arguments);
    }
    if (data.singleton) {
      fn.call(this, name, new cls, data);
    } else {
      return true;
    }
    return false;
  });
  Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
    var alternates = data.alternateClassName, i, ln, alternate;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(name, 'Ext.ClassManager#alternateClassNamePostprocessor', arguments);
    }
    if (!(alternates instanceof Array)) {
      alternates = [alternates];
    }
    for (i = 0, ln = alternates.length; i < ln; i++) {
      alternate = alternates[i];
      if (typeof alternate !== 'string') {
        throw new Error("[Ext.define] Invalid alternate of: '" + alternate + "' for class: '" + name + "'; must be a valid string");
      }
      this.set(alternate, cls);
    }
  });
  Manager.registerPostprocessor('debugHooks', function(name, Class, data) {
    var target;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, 'Ext.Class#debugHooks', arguments);
    }
    if (Ext.isDebugEnabled(Class.$className, data.debugHooks.$enabled)) {
      delete data.debugHooks.$enabled;
      Ext.override(Class, data.debugHooks);
    }
    target = Class.isInstance ? Class.self : Class;
    delete target.prototype.debugHooks;
  });
  Manager.registerPostprocessor('deprecated', function(name, Class, data) {
    var target;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(Class, 'Ext.Class#deprecated', arguments);
    }
    target = Class.isInstance ? Class.self : Class;
    target.addDeprecations(data.deprecated);
    delete target.prototype.deprecated;
  });
  Ext.apply(Ext, {create:function() {
    var name = arguments[0], nameType = typeof name, args = arraySlice.call(arguments, 1), cls;
    if (nameType === 'function') {
      cls = name;
    } else {
      if (nameType !== 'string' && args.length === 0) {
        args = [name];
        if (!(name = name.xclass)) {
          name = args[0].xtype;
          if (name) {
            name = 'widget.' + name;
          }
        }
      }
      if (typeof name !== 'string' || name.length < 1) {
        throw new Error("[Ext.create] Invalid class name or alias '" + name + "' specified, must be a non-empty string");
      }
      name = Manager.resolveName(name);
      cls = Manager.get(name);
    }
    if (!cls) {
      Ext.syncRequire(name);
      cls = Manager.get(name);
    }
    if (!cls) {
      throw new Error('[Ext.create] Unrecognized class name / alias: ' + name);
    }
    if (typeof cls !== 'function') {
      throw new Error("[Ext.create] Singleton '" + name + "' cannot be instantiated.");
    }
    return Manager.getInstantiator(args.length)(cls, args);
  }, widget:function(name, config) {
    var xtype = name, alias, className, T;
    if (typeof xtype !== 'string') {
      config = name;
      xtype = config.xtype;
      className = config.xclass;
    } else {
      config = config || {};
    }
    if (config.isComponent) {
      return config;
    }
    if (!className) {
      alias = 'widget.' + xtype;
      className = Manager.getNameByAlias(alias);
    }
    if (className) {
      T = Manager.get(className);
    }
    if (!T) {
      return Ext.create(className || alias, config);
    }
    return new T(config);
  }, createByAlias:alias(Manager, 'instantiateByAlias'), define:function(className, data, createdFn) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(className, 'ClassManager#define', arguments);
    }
    if (data.override) {
      Manager.classState[className] = 20;
      return Manager.createOverride.apply(Manager, arguments);
    }
    Manager.classState[className] = 10;
    return Manager.create.apply(Manager, arguments);
  }, undefine:function(className) {
    var classes = Manager.classes;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(className, 'Ext.ClassManager#undefine', arguments);
    }
    if (classes[className]) {
      Manager.classCount--;
    }
    delete classes[className];
    delete Manager.existCache[className];
    delete Manager.classState[className];
    Manager.removeName(className);
    Ext.Factory.clearCaches();
    var entry = Manager.getNamespaceEntry(className), scope = entry.parent ? Manager.lookupName(entry.parent, false) : Ext.global, entryName;
    if (scope) {
      entryName = entry.name;
      try {
        delete scope[entryName];
      } catch (e$30) {
        scope[entryName] = undefined;
      }
    }
    return entryName;
  }, getClassName:alias(Manager, 'getName'), getDisplayName:function(object) {
    if (object) {
      if (object.displayName) {
        return object.displayName;
      }
      if (object.$name && object.$class) {
        return Ext.getClassName(object.$class) + '#' + object.$name;
      }
      if (object.$className) {
        return object.$className;
      }
    }
    return 'Anonymous';
  }, getClass:alias(Manager, 'getClass'), namespace:function() {
    var root = global, i;
    for (i = arguments.length; i-- > 0;) {
      root = Manager.lookupName(arguments[i], true);
    }
    return root;
  }});
  Ext.addRootNamespaces = Manager.addRootNamespaces;
  Ext.createWidget = Ext.widget;
  Ext.ns = Ext.namespace;
  Class.registerPreprocessor('className', function(cls, data) {
    if ('$className' in data) {
      cls.$className = data.$className;
      cls.displayName = cls.$className;
    }
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(cls, 'Ext.ClassManager#classNamePreprocessor', arguments);
    }
  }, true, 'first');
  Class.registerPreprocessor('alias', function(cls, data) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(cls, 'Ext.ClassManager#aliasPreprocessor', arguments);
    }
    var prototype = cls.prototype, xtypes = arrayFrom(data.xtype), aliases = arrayFrom(data.alias), widgetPrefix = 'widget.', widgetPrefixLength = widgetPrefix.length, xtypesChain = Array.prototype.slice.call(prototype.xtypesChain || []), xtypesMap = Ext.merge({}, prototype.xtypesMap || {}), i, ln, alias, xtype;
    for (i = 0, ln = aliases.length; i < ln; i++) {
      alias = aliases[i];
      if (typeof alias !== 'string' || alias.length < 1) {
        throw new Error("[Ext.define] Invalid alias of: '" + alias + "' for class: '" + name + "'; must be a valid string");
      }
      if (alias.substring(0, widgetPrefixLength) === widgetPrefix) {
        xtype = alias.substring(widgetPrefixLength);
        Ext.Array.include(xtypes, xtype);
      }
    }
    cls.xtype = data.xtype = xtypes[0];
    data.xtypes = xtypes;
    for (i = 0, ln = xtypes.length; i < ln; i++) {
      xtype = xtypes[i];
      if (!xtypesMap[xtype]) {
        xtypesMap[xtype] = true;
        xtypesChain.push(xtype);
      }
    }
    data.xtypesChain = xtypesChain;
    data.xtypesMap = xtypesMap;
    Ext.Function.interceptAfterOnce(cls, 'onClassCreated', function() {
      var cls = this, prototype = cls.prototype, mixins = prototype.mixins, key, mixin;
      if (Ext.classSystemMonitor) {
        Ext.classSystemMonitor(cls, 'Ext.ClassManager#aliasPreprocessor#afterClassCreated', arguments);
      }
      for (key in mixins) {
        if (mixins.hasOwnProperty(key)) {
          mixin = mixins[key];
          xtypes = mixin.xtypes;
          if (xtypes) {
            for (i = 0, ln = xtypes.length; i < ln; i++) {
              xtype = xtypes[i];
              if (!xtypesMap[xtype]) {
                xtypesMap[xtype] = true;
                xtypesChain.push(xtype);
              }
            }
          }
        }
      }
    });
    for (i = 0, ln = xtypes.length; i < ln; i++) {
      xtype = xtypes[i];
      if (typeof xtype !== 'string' || xtype.length < 1) {
        throw new Error("[Ext.define] Invalid xtype of: '" + xtype + "' for class: '" + name + "'; must be a valid non-empty string");
      }
      Ext.Array.include(aliases, widgetPrefix + xtype);
    }
    data.alias = aliases;
  }, ['xtype', 'alias']);
  if (Ext.manifest) {
    var manifest = Ext.manifest, classes = manifest.classes, paths = manifest.paths, aliases = {}, alternates = {}, className, obj, name, path, baseUrl;
    if (paths) {
      if (manifest.bootRelative) {
        baseUrl = Ext.Boot.baseUrl;
        for (path in paths) {
          if (paths.hasOwnProperty(path)) {
            paths[path] = baseUrl + paths[path];
          }
        }
      }
      Manager.setPath(paths);
    }
    if (classes) {
      for (className in classes) {
        alternates[className] = [];
        aliases[className] = [];
        obj = classes[className];
        if (obj.alias) {
          aliases[className] = obj.alias;
        }
        if (obj.alternates) {
          alternates[className] = obj.alternates;
        }
      }
    }
    Manager.addAlias(aliases);
    Manager.addAlternate(alternates);
  }
  return Manager;
}(Ext.Class, Ext.Function.alias, Array.prototype.slice, Ext.Array.from, Ext.global);
Ext.define('Ext.mixin.Watchable', {on:function(name, fn, scope) {
  return this._watchUpdate(false, '_watchAdd', name, fn, scope);
}, fire:function(event, args) {
  var me = this, watching = me.watching, watchers = watching && watching[event], fn, i, r, scope;
  if (watchers) {
    ++watchers.$firing;
    for (i = 0; i < watchers.length; ++i) {
      scope = watchers[i][0];
      fn = watchers[i][1];
      if (fn.charAt) {
        r = args ? scope[fn].apply(scope, args) : scope[fn]();
      } else {
        r = args ? fn.apply(scope, args) : fn.call(scope);
      }
      if (r === false) {
        return r;
      }
    }
    --watchers.$firing;
  }
}, fireEvent:function() {
  var args = Ext.Array.slice(arguments), event = args.shift();
  return this.fire(event, args);
}, un:function(name, fn, scope) {
  return this._watchUpdate(true, '_watchRemove', name, fn, scope);
}, privates:{watching:null, $watchOptions:{destroyable:1, scope:1}, _watchAdd:function(watching, name, fn, scope, destroyable) {
  if (typeof fn === 'string' && !scope[fn]) {
    Ext.raise('No such method "' + fn + '" on ' + scope.$className);
  }
  var watchers = watching[name], entry = [scope, fn], i, ent;
  if (!watchers) {
    watching[name] = watchers = [];
    watchers.$firing = 0;
  } else {
    for (i = watchers.length; i-- > 0;) {
      ent = watchers[i];
      if (fn === ent[1]) {
        if (scope ? ent[0] === scope : !ent[0]) {
          return;
        }
      }
    }
    if (watchers.$firing) {
      watching[name] = watchers = watchers.slice();
      watchers.$firing = 0;
    }
  }
  watchers.push(entry);
  if (destroyable) {
    entry.push(name);
    destroyable.items.push(entry);
  }
}, _watchRemove:function(watching, name, fn, scope) {
  var watchers = watching[name], i;
  if (watchers) {
    if (watchers.$firing) {
      watching[name] = watchers = watchers.slice();
      watchers.$firing = 0;
    }
    for (i = watchers.length; i-- > 0;) {
      if (watchers[i][0] === scope && watchers[i][1] === fn) {
        watchers.splice(i, 1);
      }
    }
  }
}, _watchUpdate:function(remove, process, name, fn, scope) {
  var me = this, watch = name, watching = me.watching, destroyable;
  if (!watching) {
    if (remove) {
      return;
    }
    me.watching = watching = {};
  }
  if (typeof name === 'string') {
    me[process](watching, name, fn, scope);
  } else {
    destroyable = watch.destroyable ? {owner:me, items:[], destroy:me._watcherDestroyer} : null;
    scope = watch.scope;
    for (name in watch) {
      if (!me.$watchOptions[name]) {
        me[process](watching, name, watch[name], scope, destroyable);
      }
    }
  }
  return destroyable;
}, _watcherDestroyer:function() {
  var me = this.owner, watching = me.watching, items = this.items, entry, i;
  for (i = 0; i < items.length; ++i) {
    entry = items[i];
    me._watchRemove(watching, entry[2], entry[1], entry[0]);
  }
}}});
(Ext.env || (Ext.env = {})).Browser = function(userAgent, publish) {
  var me = this, browserPrefixes = Ext.Boot.browserPrefixes, browserNames = Ext.Boot.browserNames, enginePrefixes = me.enginePrefixes, engineNames = me.engineNames, browserMatch = userAgent.match(new RegExp('((?:' + Ext.Object.getValues(browserPrefixes).join(')|(?:') + '))([\\w\\._]+)')), engineMatch = userAgent.match(new RegExp('((?:' + Ext.Object.getValues(enginePrefixes).join(')|(?:') + '))([\\w\\._]+)')), browserName = browserNames.other, engineName = engineNames.other, browserVersion = '', engineVersion = 
  '', majorVer = '', isWebView = false, edgeRE = /(Edge\/)([\w.]+)/, ripple = '', i, prefix, name;
  me.userAgent = userAgent;
  this.is = function(name) {
    return !!this.is[name];
  };
  if (/Edge\//.test(userAgent)) {
    browserMatch = userAgent.match(edgeRE);
    engineMatch = userAgent.match(edgeRE);
  }
  if (browserMatch) {
    browserName = browserNames[Ext.Object.getKey(browserPrefixes, browserMatch[1])];
    if (browserName === 'Safari' && /^Opera/.test(userAgent)) {
      browserName = 'Opera';
    }
    browserVersion = new Ext.Version(browserMatch[2]);
  }
  if (engineMatch) {
    engineName = engineNames[Ext.Object.getKey(enginePrefixes, engineMatch[1])];
    engineVersion = new Ext.Version(engineMatch[2]);
  }
  if (engineName === 'Trident' && browserName !== 'IE') {
    browserName = 'IE';
    var version = userAgent.match(/.*rv:(\d+.\d+)/);
    if (version && version.length) {
      version = version[1];
      browserVersion = new Ext.Version(version);
    }
  }
  if (browserName && browserVersion) {
    Ext.setVersion(browserName, browserVersion);
  }
  if (userAgent.match(/FB/) && browserName === 'Other') {
    browserName = browserNames.safari;
    engineName = engineNames.webkit;
  } else {
    if (userAgent.match(/Android.*Chrome/g)) {
      browserName = 'ChromeMobile';
    } else {
      browserMatch = userAgent.match(/OPR\/(\d+.\d+)/);
      if (browserMatch) {
        browserName = 'Opera';
        browserVersion = new Ext.Version(browserMatch[1]);
      }
    }
  }
  Ext.apply(this, {engineName:engineName, engineVersion:engineVersion, name:browserName, version:browserVersion});
  this.setFlag(browserName, true, publish);
  if (browserVersion) {
    majorVer = browserVersion.getMajor() || '';
    if (me.is.IE) {
      majorVer = document.documentMode || parseInt(majorVer, 10);
      for (i = 7; i <= 11; ++i) {
        prefix = 'isIE' + i;
        Ext[prefix] = majorVer === i;
        Ext[prefix + 'm'] = majorVer <= i;
        Ext[prefix + 'p'] = majorVer >= i;
      }
    }
    if (me.is.Opera && parseInt(majorVer, 10) <= 12) {
      Ext.isOpera12m = true;
    }
    Ext.chromeVersion = Ext.isChrome ? majorVer : 0;
    Ext.firefoxVersion = Ext.isFirefox ? majorVer : 0;
    Ext.ieVersion = Ext.isIE ? majorVer : 0;
    Ext.operaVersion = Ext.isOpera ? majorVer : 0;
    Ext.safariVersion = Ext.isSafari ? majorVer : 0;
    Ext.webKitVersion = Ext.isWebKit ? majorVer : 0;
    this.setFlag(browserName + majorVer, true, publish);
    this.setFlag(browserName + browserVersion.getShortVersion());
  }
  for (i in browserNames) {
    if (browserNames.hasOwnProperty(i)) {
      name = browserNames[i];
      this.setFlag(name, browserName === name);
    }
  }
  this.setFlag(name);
  if (engineVersion) {
    this.setFlag(engineName + (engineVersion.getMajor() || ''));
    this.setFlag(engineName + engineVersion.getShortVersion());
  }
  for (i in engineNames) {
    if (engineNames.hasOwnProperty(i)) {
      name = engineNames[i];
      this.setFlag(name, engineName === name, publish);
    }
  }
  this.setFlag('Standalone', !!navigator.standalone);
  try {
    ripple = window.top.ripple;
  } catch (e$31) {
  }
  this.setFlag('Ripple', !!document.getElementById('tinyhippos-injected') && !Ext.isEmpty(ripple));
  this.setFlag('WebWorks', !!window.blackberry);
  if (window.PhoneGap !== undefined || window.Cordova !== undefined || window.cordova !== undefined) {
    isWebView = true;
    this.setFlag('PhoneGap');
    this.setFlag('Cordova');
  }
  if (/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)(?!.*FBAN)/i.test(userAgent)) {
    isWebView = true;
  }
  this.setFlag('WebView', isWebView);
  this.isStrict = Ext.isStrict = document.compatMode === 'CSS1Compat';
  this.isSecure = Ext.isSecure;
  this.identity = browserName + majorVer + (this.isStrict ? 'Strict' : 'Quirks');
};
Ext.env.Browser.prototype = {constructor:Ext.env.Browser, engineNames:{edge:'Edge', webkit:'WebKit', gecko:'Gecko', presto:'Presto', trident:'Trident', other:'Other'}, enginePrefixes:{edge:'Edge/', webkit:'AppleWebKit/', gecko:'Gecko/', presto:'Presto/', trident:'Trident/'}, styleDashPrefixes:{WebKit:'-webkit-', Gecko:'-moz-', Trident:'-ms-', Presto:'-o-', Other:''}, stylePrefixes:{WebKit:'Webkit', Gecko:'Moz', Trident:'ms', Presto:'O', Other:''}, propertyPrefixes:{WebKit:'webkit', Gecko:'moz', Trident:'ms', 
Presto:'o', Other:''}, name:null, version:null, engineName:null, engineVersion:null, setFlag:function(name, value, publish) {
  if (value === undefined) {
    value = true;
  }
  this.is[name] = value;
  this.is[name.toLowerCase()] = value;
  if (publish) {
    Ext['is' + name] = value;
  }
  return this;
}, getStyleDashPrefix:function() {
  return this.styleDashPrefixes[this.engineName];
}, getStylePrefix:function() {
  return this.stylePrefixes[this.engineName];
}, getVendorProperyName:function(name) {
  var prefix = this.propertyPrefixes[this.engineName];
  if (prefix.length > 0) {
    return prefix + Ext.String.capitalize(name);
  }
  return name;
}};
(function(userAgent) {
  Ext.browser = new Ext.env.Browser(userAgent, true);
  Ext.userAgent = userAgent.toLowerCase();
  Ext.SSL_SECURE_URL = Ext.isSecure && Ext.isIE ? "javascript:''" : 'about:blank';
})(Ext.global.navigator.userAgent);
Ext.env.OS = function(userAgent, platform, browserScope) {
  var me = this, names = Ext.Boot.osNames, prefixes = Ext.Boot.osPrefixes, name, version = '', is = me.is, i, prefix, match, item, match1;
  browserScope = browserScope || Ext.browser;
  for (i in prefixes) {
    if (prefixes.hasOwnProperty(i)) {
      prefix = prefixes[i];
      match = userAgent.match(new RegExp('(?:' + prefix + ')([^\\s;]+)'));
      if (match) {
        name = names[i];
        match1 = match[1];
        if (match1 && match1 === 'HTC_') {
          version = new Ext.Version('2.3');
        } else {
          if (match1 && match1 === 'Silk/') {
            version = new Ext.Version('2.3');
          } else {
            version = new Ext.Version(match[match.length - 1]);
          }
        }
        break;
      }
    }
  }
  if (!name) {
    name = names[(userAgent.toLowerCase().match(/mac|win|linux/) || ['other'])[0]];
    version = new Ext.Version('');
  }
  this.name = name;
  this.version = version;
  if (userAgent.match(/ipad/i) || !userAgent.match(/iphone/i) && userAgent.match(/Mac/) && navigator.maxTouchPoints > 2) {
    name = 'iOS';
    platform = 'iPad';
  }
  if (platform) {
    this.setFlag(platform.replace(/ simulator$/i, ''));
  }
  this.setFlag(name);
  if (version) {
    this.setFlag(name + (version.getMajor() || ''));
    this.setFlag(name + version.getShortVersion());
  }
  for (i in names) {
    if (names.hasOwnProperty(i)) {
      item = names[i];
      if (!is.hasOwnProperty(name)) {
        this.setFlag(item, name === item);
      }
    }
  }
  if (this.name === 'iOS' && window.screen.height === 568) {
    this.setFlag('iPhone5');
  }
  if (browserScope.is.Safari || browserScope.is.Silk) {
    if (this.is.Android2 || this.is.Android3 || browserScope.version.shortVersion === 501) {
      browserScope.setFlag('AndroidStock');
    }
    if (this.is.Android4) {
      browserScope.setFlag('AndroidStock');
      browserScope.setFlag('AndroidStock4');
    }
  }
};
Ext.env.OS.prototype = {constructor:Ext.env.OS, is:function(name) {
  return !!this[name];
}, name:null, version:null, setFlag:function(name, value) {
  if (value === undefined) {
    value = true;
  }
  if (this.flags) {
    this.flags[name] = value;
  }
  this.is[name] = value;
  this.is[name.toLowerCase()] = value;
  return this;
}};
(function() {
  var navigation = Ext.global.navigator, userAgent = navigation.userAgent, OS = Ext.env.OS, is = Ext.is || (Ext.is = {}), osEnv, osName, deviceType;
  OS.prototype.flags = is;
  Ext.os = osEnv = new OS(userAgent, navigation.platform);
  osName = osEnv.name;
  Ext['is' + osName] = true;
  Ext.isMac = is.Mac = is.MacOS;
  Ext.isApple = Ext.isMac || Ext.isiOS;
  var search = window.location.search.match(/deviceType=(Tablet|Phone)/), nativeDeviceType = window.deviceType;
  if (search && search[1]) {
    deviceType = search[1];
  } else {
    if (nativeDeviceType === 'iPhone') {
      deviceType = 'Phone';
    } else {
      if (nativeDeviceType === 'iPad') {
        deviceType = 'Tablet';
      } else {
        if (!osEnv.is.Android && !osEnv.is.iOS && !osEnv.is.WindowsPhone && /Windows|Linux|MacOS|ChromeOS/.test(osName)) {
          deviceType = 'Desktop';
          Ext.browser.is.WebView = !!Ext.browser.is.Ripple;
        } else {
          if (osEnv.is.iPad || osEnv.is.RIMTablet || osEnv.is.Android3 || Ext.browser.is.Silk || osEnv.is.Android && userAgent.search(/mobile/i) === -1) {
            deviceType = 'Tablet';
          } else {
            deviceType = 'Phone';
          }
        }
      }
    }
  }
  if (deviceType === 'Tablet' && osName === 'MacOS') {
    Ext.isiOS = true;
    Ext.isiPadOS = true;
  }
  osEnv.setFlag(deviceType, true);
  osEnv.deviceType = deviceType;
  delete OS.prototype.flags;
})();
Ext.feature = {has:function(name) {
  return !!this.has[name];
}, testElements:{}, getTestElement:function(tag, createNew) {
  if (tag === undefined) {
    tag = 'div';
  } else {
    if (typeof tag !== 'string') {
      return tag;
    }
  }
  if (createNew) {
    return document.createElement(tag);
  }
  if (!this.testElements[tag]) {
    this.testElements[tag] = document.createElement(tag);
  }
  return this.testElements[tag];
}, isStyleSupported:function(name, tag) {
  var elementStyle = this.getTestElement(tag).style, cName = Ext.String.capitalize(name);
  if (typeof elementStyle[name] !== 'undefined' || typeof elementStyle[Ext.browser.getStylePrefix(name) + cName] !== 'undefined') {
    return true;
  }
  return false;
}, isStyleSupportedWithoutPrefix:function(name, tag) {
  var elementStyle = this.getTestElement(tag).style;
  if (typeof elementStyle[name] !== 'undefined') {
    return true;
  }
  return false;
}, isEventSupported:function(name, tag) {
  if (tag === undefined) {
    tag = window;
  }
  var element = this.getTestElement(tag), eventName = 'on' + name.toLowerCase(), isSupported = eventName in element;
  if (!isSupported) {
    if (element.setAttribute && element.removeAttribute) {
      element.setAttribute(eventName, '');
      isSupported = typeof element[eventName] === 'function';
      if (typeof element[eventName] !== 'undefined') {
        element[eventName] = undefined;
      }
      element.removeAttribute(eventName);
    }
  }
  return isSupported;
}, getStyle:function(element, styleName) {
  var view = element.ownerDocument.defaultView, style = view ? view.getComputedStyle(element, null) : element.currentStyle;
  return (style || element.style)[styleName];
}, getSupportedPropertyName:function(object, name) {
  var vendorName = Ext.browser.getVendorProperyName(name);
  if (vendorName in object) {
    return vendorName;
  } else {
    if (name in object) {
      return name;
    }
  }
  return null;
}, detect:function(isReady) {
  var me = this, doc = document, toRun = me.toRun || me.tests, n = toRun.length, div = doc.createElement('div'), notRun = [], supports = Ext.supports, has = me.has, name, names, test, vector, value;
  div.innerHTML = '\x3cdiv style\x3d"height:30px;width:50px;"\x3e' + '\x3cdiv style\x3d"height:20px;width:20px;"\x3e\x3c/div\x3e' + '\x3c/div\x3e' + '\x3cdiv style\x3d"width: 200px; height: 200px; position: relative; padding: 5px;"\x3e' + '\x3cdiv style\x3d"position: absolute; top: 0; left: 0; width: 100%; height: 100%;"\x3e\x3c/div\x3e' + '\x3c/div\x3e' + '\x3cdiv style\x3d"position: absolute; left: 10%; top: 10%;"\x3e\x3c/div\x3e' + '\x3cdiv style\x3d"float:left; background-color:transparent;"\x3e\x3c/div\x3e';
  if (isReady) {
    doc.body.appendChild(div);
  }
  vector = me.preDetected[Ext.browser.identity] || [];
  while (n--) {
    test = toRun[n];
    value = vector[n];
    name = test.name;
    names = test.names;
    if (value === undefined) {
      if (!isReady && test.ready) {
        notRun.push(test);
        continue;
      }
      value = test.fn.call(me, doc, div);
    }
    if (name) {
      supports[name] = has[name] = value;
    } else {
      if (names) {
        while (names.length) {
          name = names.pop();
          supports[name] = has[name] = value;
        }
      }
    }
  }
  if (isReady) {
    doc.body.removeChild(div);
  }
  me.toRun = notRun;
}, report:function() {
  var values = [], len = this.tests.length, i;
  for (i = 0; i < len; ++i) {
    values.push(this.has[this.tests[i].name] ? 1 : 0);
  }
  Ext.log(Ext.browser.identity + ': [' + values.join(',') + ']');
}, preDetected:{}, tests:[{name:'CloneNodeCopiesExpando', fn:function() {
  var el = document.createElement('div');
  el.expandoProp = {};
  return el.cloneNode().expandoProp === el.expandoProp;
}}, {name:'CSSPointerEvents', fn:function(doc) {
  return 'pointerEvents' in doc.documentElement.style;
}}, {name:'CSS3BoxShadow', fn:function(doc) {
  return 'boxShadow' in doc.documentElement.style || 'WebkitBoxShadow' in doc.documentElement.style || 'MozBoxShadow' in doc.documentElement.style;
}}, {name:'CSS3NegationSelector', fn:function(doc) {
  try {
    doc.querySelectorAll('foo:not(bar)');
  } catch (e$32) {
    return false;
  }
  return true;
}}, {name:'ClassList', fn:function(doc) {
  return !!doc.documentElement.classList;
}}, {name:'Canvas', fn:function() {
  var element = this.getTestElement('canvas');
  return !!(element && element.getContext && element.getContext('2d'));
}}, {name:'Svg', fn:function(doc) {
  return !!(doc.createElementNS && !!doc.createElementNS('http:/' + '/www.w3.org/2000/svg', 'svg').createSVGRect);
}}, {name:'Vml', fn:function() {
  var element = this.getTestElement(), ret = false;
  element.innerHTML = '\x3c!--[if vml]\x3e\x3cbr\x3e\x3c![endif]--\x3e';
  ret = element.childNodes.length === 1;
  element.innerHTML = '';
  return ret;
}}, {name:'Touch', fn:function() {
  var maxTouchPoints = navigator.msMaxTouchPoints || navigator.maxTouchPoints;
  if (Ext.browser.is.Chrome && Ext.browser.version.isLessThanOrEqual(39)) {
    return Ext.supports.TouchEvents && maxTouchPoints !== 1 || maxTouchPoints > 1;
  } else {
    return Ext.supports.TouchEvents || maxTouchPoints > 0;
  }
}}, {name:'PointerEvents', fn:function() {
  var pointerEvent = window.PointerEvent, nav = window.navigator, pointerEnabled = !!(pointerEvent && (nav.pointerEnabled || !Ext.isIE));
  return pointerEnabled && !Ext.supports.TouchEvents;
}}, {name:'MSPointerEvents', fn:function() {
  return Ext.isIE10;
}}, {name:'TouchEvents', fn:function() {
  return this.isEventSupported('touchend');
}}, {name:'TouchAction', ready:true, fn:function(doc, div) {
  if (!window.getComputedStyle) {
    return 0;
  }
  var values = ['pan-x', 'pan-y', 'pinch-zoom', 'double-tap-zoom'], flags = [1, 2, 4, 8], ln = values.length, flag = 0, i, value;
  for (i = 0; i < ln; i++) {
    value = values[i];
    div.style.touchAction = value;
    if (getComputedStyle(div).touchAction === value) {
      flag |= flags[i];
    }
  }
  return flag;
}}, {name:'Orientation', fn:function() {
  return 'orientation' in window && this.isEventSupported('orientationchange');
}}, {name:'OrientationChange', fn:function() {
  return this.isEventSupported('orientationchange');
}}, {name:'DeviceMotion', fn:function() {
  return this.isEventSupported('devicemotion');
}}, {names:['Geolocation', 'GeoLocation'], fn:function() {
  return 'geolocation' in window.navigator;
}}, {name:'SqlDatabase', fn:function() {
  return 'openDatabase' in window;
}}, {name:'WebSockets', fn:function() {
  return 'WebSocket' in window;
}}, {name:'Range', fn:function() {
  return !!document.createRange;
}}, {name:'CreateContextualFragment', fn:function() {
  var range = !!document.createRange ? document.createRange() : false;
  return range && !!range.createContextualFragment;
}}, {name:'History', fn:function() {
  return 'history' in window && 'pushState' in window.history;
}}, {name:'Css3dTransforms', fn:function() {
  return this.has('CssTransforms') && this.isStyleSupported('perspective');
}}, {name:'CssTransforms', fn:function() {
  return this.isStyleSupported('transform');
}}, {name:'CssTransformNoPrefix', fn:function() {
  return this.isStyleSupportedWithoutPrefix('transform');
}}, {name:'CssAnimations', fn:function() {
  return this.isStyleSupported('animationName');
}}, {names:['CssTransitions', 'Transitions'], fn:function() {
  return this.isStyleSupported('transitionProperty');
}}, {names:['Audio', 'AudioTag'], fn:function() {
  return !!this.getTestElement('audio').canPlayType;
}}, {name:'Video', fn:function() {
  return !!this.getTestElement('video').canPlayType;
}}, {name:'LocalStorage', fn:function() {
  try {
    if ('localStorage' in window && window['localStorage'] !== null) {
      localStorage.setItem('sencha-localstorage-test', 'test success');
      localStorage.removeItem('sencha-localstorage-test');
      return true;
    }
  } catch (e$33) {
  }
  return false;
}}, {name:'XmlQuerySelector', fn:function() {
  var xmlString = '\x3c?xml version\x3d"1.0" encoding\x3d"UTF-8" standalone\x3d"yes" ?\x3e\x3croot\x3e\x3c/root\x3e', xmlDoc;
  if (window.ActiveXObject) {
    xmlDoc = new ActiveXObject('Microsoft.xmlDOM');
    xmlDoc.async = false;
    xmlDoc.loadXML(xmlString);
  } else {
    if (window.DOMParser) {
      var parser = new DOMParser;
      xmlDoc = parser.parseFromString(xmlString, 'text/xml');
    }
  }
  return xmlDoc ? !!xmlDoc.lastChild.querySelector : false;
}}, {name:'XHR2', fn:function() {
  return window.ProgressEvent && window.FormData && window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest;
}}, {name:'XHRUploadProgress', fn:function() {
  var xhr;
  if (window.XMLHttpRequest && !Ext.browser.is.AndroidStock) {
    xhr = new XMLHttpRequest;
    return xhr && 'upload' in xhr && 'onprogress' in xhr.upload;
  }
  return false;
}}, {name:'NumericInputPlaceHolder', fn:function() {
  return !(Ext.browser.is.AndroidStock4 && Ext.os.version.getMinor() < 2);
}}, {name:'matchesSelector', fn:function() {
  var el = document.documentElement, w3 = 'matches', wk = 'webkitMatchesSelector', ms = 'msMatchesSelector', mz = 'mozMatchesSelector';
  return el[w3] ? w3 : el[wk] ? wk : el[ms] ? ms : el[mz] ? mz : null;
}}, {name:'RightMargin', ready:true, fn:function(doc, div) {
  var view = doc.defaultView;
  return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight !== '0px');
}}, {name:'DisplayChangeInputSelectionBug', fn:function() {
  var webKitVersion = Ext.webKitVersion;
  return 0 < webKitVersion && webKitVersion < 533;
}}, {name:'DisplayChangeTextAreaSelectionBug', fn:function() {
  var webKitVersion = Ext.webKitVersion;
  return 0 < webKitVersion && webKitVersion < 534.24;
}}, {name:'TransparentColor', ready:true, fn:function(doc, div, view) {
  view = doc.defaultView;
  return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor !== 'transparent');
}}, {name:'ComputedStyle', ready:true, fn:function(doc, div, view) {
  view = doc.defaultView;
  return !!(view && view.getComputedStyle);
}}, {name:'Float', fn:function(doc) {
  return 'cssFloat' in doc.documentElement.style;
}}, {name:'CSS3BorderRadius', ready:true, fn:function(doc) {
  var domPrefixes = ['borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius'], pass = false, i;
  for (i = 0; i < domPrefixes.length; i++) {
    if (doc.documentElement.style[domPrefixes[i]] !== undefined) {
      pass = true;
    }
  }
  return pass && !Ext.isIE9;
}}, {name:'CSS3LinearGradient', fn:function(doc, div) {
  var property = 'background-image:', webkit = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))', w3c = 'linear-gradient(left top, black, white)', moz = '-moz-' + w3c, ms = '-ms-' + w3c, opera = '-o-' + w3c, options = [property + webkit, property + w3c, property + moz, property + ms, property + opera];
  div.style.cssText = options.join(';');
  return ('' + div.style.backgroundImage).indexOf('gradient') !== -1 && !Ext.isIE9;
}}, {name:'MouseEnterLeave', fn:function(doc) {
  return 'onmouseenter' in doc.documentElement && 'onmouseleave' in doc.documentElement;
}}, {name:'MouseWheel', fn:function(doc) {
  return 'onmousewheel' in doc.documentElement;
}}, {name:'Opacity', fn:function(doc, div) {
  if (Ext.isIE8) {
    return false;
  }
  div.firstChild.style.cssText = 'opacity:0.73';
  return div.firstChild.style.opacity == '0.73';
}}, {name:'Placeholder', fn:function(doc) {
  return 'placeholder' in doc.createElement('input');
}}, {name:'Direct2DBug', fn:function(doc) {
  return Ext.isString(doc.documentElement.style.msTransformOrigin) && Ext.isIE9m;
}}, {name:'BoundingClientRect', fn:function(doc) {
  return 'getBoundingClientRect' in doc.documentElement;
}}, {name:'RotatedBoundingClientRect', ready:true, fn:function(doc) {
  var body = doc.body, supports = false, el = doc.createElement('div'), style = el.style;
  if (el.getBoundingClientRect) {
    style.position = 'absolute';
    style.top = '0';
    style.WebkitTransform = style.MozTransform = style.msTransform = style.OTransform = style.transform = 'rotate(90deg)';
    style.width = '100px';
    style.height = '30px';
    body.appendChild(el);
    supports = el.getBoundingClientRect().height !== 100;
    body.removeChild(el);
  }
  return supports;
}}, {name:'ChildContentClearedWhenSettingInnerHTML', ready:true, fn:function() {
  var el = this.getTestElement(), child;
  el.innerHTML = '\x3cdiv\x3ea\x3c/div\x3e';
  child = el.firstChild;
  el.innerHTML = '\x3cdiv\x3eb\x3c/div\x3e';
  return child.innerHTML !== 'a';
}}, {name:'IncludePaddingInWidthCalculation', ready:true, fn:function(doc, div) {
  return div.childNodes[1].firstChild.offsetWidth === 210;
}}, {name:'IncludePaddingInHeightCalculation', ready:true, fn:function(doc, div) {
  return div.childNodes[1].firstChild.offsetHeight === 210;
}}, {name:'TextAreaMaxLength', fn:function(doc) {
  return 'maxlength' in doc.createElement('textarea');
}}, {name:'GetPositionPercentage', ready:true, fn:function(doc, div) {
  return Ext.feature.getStyle(div.childNodes[2], 'left') === '10%';
}}, {name:'PercentageHeightOverflowBug', ready:true, fn:function(doc) {
  var hasBug = false, style, el;
  if (Ext.getScrollbarSize().height) {
    el = this.getTestElement('div', true);
    style = el.style;
    style.height = '50px';
    style.width = '50px';
    style.overflow = 'auto';
    style.position = 'absolute';
    el.innerHTML = ['\x3cdiv style\x3d"display:table;height:100%;"\x3e', '\x3cdiv style\x3d"width:51px;"\x3e\x3c/div\x3e', '\x3c/div\x3e'].join('');
    doc.body.appendChild(el);
    if (el.firstChild.offsetHeight === 50) {
      hasBug = true;
    }
    doc.body.removeChild(el);
  }
  return hasBug;
}}, {name:'xOriginBug', ready:true, fn:function(doc, div) {
  div.innerHTML = '\x3cdiv id\x3d"b1" style\x3d"height:100px;width:100px;direction:rtl;position:relative;overflow:scroll"\x3e' + '\x3cdiv id\x3d"b2" style\x3d"position:relative;width:100%;height:20px;"\x3e\x3c/div\x3e' + '\x3cdiv id\x3d"b3" style\x3d"position:absolute;width:20px;height:20px;top:0px;right:0px"\x3e\x3c/div\x3e' + '\x3c/div\x3e';
  var outerBox = document.getElementById('b1').getBoundingClientRect(), b2 = document.getElementById('b2').getBoundingClientRect(), b3 = document.getElementById('b3').getBoundingClientRect();
  return b2.left !== outerBox.left && b3.right !== outerBox.right;
}}, {name:'ScrollWidthInlinePaddingBug', ready:true, fn:function(doc) {
  var hasBug = false, style, el;
  el = doc.createElement('div');
  style = el.style;
  style.height = '50px';
  style.width = '50px';
  style.padding = '10px';
  style.overflow = 'hidden';
  style.position = 'absolute';
  el.innerHTML = '\x3cspan style\x3d"display:inline-block;zoom:1;height:60px;width:60px;"\x3e\x3c/span\x3e';
  doc.body.appendChild(el);
  if (el.scrollWidth === 70) {
    hasBug = true;
  }
  doc.body.removeChild(el);
  return hasBug;
}}, {name:'rtlVertScrollbarOnRight', ready:true, fn:function(doc, div) {
  div.innerHTML = '\x3cdiv style\x3d"height:100px;width:100px;direction:rtl;overflow:scroll"\x3e' + '\x3cdiv style\x3d"width:20px;height:200px;"\x3e\x3c/div\x3e' + '\x3c/div\x3e';
  var outerBox = div.firstChild, innerBox = outerBox.firstChild;
  return innerBox.offsetLeft + innerBox.offsetWidth !== outerBox.offsetLeft + outerBox.offsetWidth;
}}, {name:'rtlVertScrollbarOverflowBug', ready:true, fn:function(doc, div) {
  div.innerHTML = '\x3cdiv style\x3d"height:100px;width:100px;direction:rtl;overflow:auto"\x3e' + '\x3cdiv style\x3d"width:95px;height:200px;"\x3e\x3c/div\x3e' + '\x3c/div\x3e';
  var outerBox = div.firstChild, style = div.style, pos = style.position;
  style.position = 'absolute';
  outerBox.offsetHeight;
  style.position = pos;
  return outerBox.clientHeight === outerBox.offsetHeight;
}}, {identity:'defineProperty', fn:function() {
  if (Ext.isIE8m) {
    Ext.Object.defineProperty = Ext.emptyFn;
    return false;
  }
  return true;
}}, {identify:'nativeXhr', fn:function() {
  if (typeof XMLHttpRequest !== 'undefined') {
    return true;
  }
  XMLHttpRequest = function() {
    try {
      return new ActiveXObject('MSXML2.XMLHTTP.3.0');
    } catch (ex) {
      return null;
    }
  };
  return false;
}}, {name:'SpecialKeyDownRepeat', fn:function() {
  return Ext.isWebKit ? parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 : !(!(Ext.isGecko || Ext.isIE || Ext.isEdge) || Ext.isOpera && Ext.operaVersion < 12);
}}, {name:'EmulatedMouseOver', fn:function() {
  return Ext.os.is.iOS;
}}, {name:'Hashchange', fn:function() {
  var docMode = document.documentMode;
  return 'onhashchange' in window && (docMode === undefined || docMode > 7);
}}, {name:'FixedTableWidthBug', ready:true, fn:function() {
  if (Ext.isIE8) {
    return false;
  }
  var outer = document.createElement('div'), inner = document.createElement('div'), width;
  outer.setAttribute('style', 'display:table;table-layout:fixed;');
  inner.setAttribute('style', 'display:table-cell;min-width:50px;');
  outer.appendChild(inner);
  document.body.appendChild(outer);
  outer.offsetWidth;
  outer.style.width = '25px';
  width = outer.offsetWidth;
  document.body.removeChild(outer);
  return width === 50;
}}, {name:'FocusinFocusoutEvents', fn:function() {
  return !(Ext.isGecko && Ext.firefoxVersion < 52);
}}, {name:'AsyncFocusEvents', fn:function() {
  return Ext.asyncFocus = !!Ext.isIE;
}}, {name:'accessibility', ready:true, fn:function(doc) {
  var body = doc.body, div, img, style, supports, bgImg;
  function getColor(colorTxt) {
    var values = [], colorValue = 0, regex, match;
    if (colorTxt.indexOf('rgb(') !== -1) {
      values = colorTxt.replace('rgb(', '').replace(')', '').split(', ');
    } else {
      if (colorTxt.indexOf('#') !== -1) {
        regex = colorTxt.length === 7 ? /^#(\S\S)(\S\S)(\S\S)$/ : /^#(\S)(\S)(\S)$/;
        match = colorTxt.match(regex);
        if (match) {
          values = ['0x' + match[1], '0x' + match[2], '0x' + match[3]];
        }
      }
    }
    for (var i = 0; i < values.length; i++) {
      colorValue += parseInt(values[i]);
    }
    return colorValue;
  }
  div = doc.createElement('div');
  img = doc.createElement('img');
  style = div.style;
  Ext.apply(style, {width:'2px', position:'absolute', clip:'rect(1px,1px,1px,1px)', borderWidth:'1px', borderStyle:'solid', borderTopTolor:'#f00', borderRightColor:'#ff0', backgroundColor:'#fff', backgroundImage:'url(' + Ext.BLANK_IMAGE_URL + ')'});
  img.alt = '';
  img.src = Ext.BLANK_IMAGE_URL;
  div.appendChild(img);
  body.appendChild(div);
  style = div.currentStyle || div.style;
  bgImg = style.backgroundImage;
  supports = {Images:img.offsetWidth === 1 && img.readyState !== 'uninitialized', BackgroundImages:!(bgImg !== null && (bgImg === 'none' || bgImg === 'url(invalid-url:)')), BorderColors:style.borderTopColor !== style.borderRightColor, LightOnDark:getColor(style.color) - getColor(style.backgroundColor) > 0};
  Ext.supports.HighContrastMode = !supports.BackgroundImages;
  body.removeChild(div);
  div = img = null;
  return supports;
}}, {name:'ViewportUnits', ready:true, fn:function(doc) {
  if (Ext.isIE8) {
    return false;
  }
  var body = doc.body, div = document.createElement('div'), style = div.currentStyle || div.style, width, divWidth;
  body.appendChild(div);
  Ext.apply(style, {width:'50vw'});
  width = parseInt(window.innerWidth / 2, 10);
  divWidth = parseInt((window.getComputedStyle ? getComputedStyle(div, null) : div.currentStyle).width, 10);
  body.removeChild(div);
  div = null;
  return width === divWidth;
}}, {name:'CSSVariables', ready:false, fn:function() {
  if (!window.getComputedStyle) {
    return false;
  }
  return window.CSS && window.CSS.supports && window.CSS.supports('--test-var', 0);
}}, {name:'Selectors2', ready:false, fn:function(doc) {
  try {
    return !!doc.querySelectorAll(':scope');
  } catch (e$34) {
    return false;
  }
}}, {name:'CSSScrollSnap', ready:false, fn:function(doc) {
  var style = doc.documentElement.style;
  return 'scrollSnapType' in style || 'webkitScrollSnapType' in style || 'msScrollSnapType' in style;
}}, {name:'TranslateYCausesHorizontalScroll', ready:true, fn:function(doc, div) {
  div.innerHTML = '\x3cdiv style\x3d"position: relative; overflow: auto; height: 200px; width: 200px;"\x3e' + '\x3cdiv\x3e' + '\x3cdiv style\x3d"transform: translateY(260px); width: 50px;"\x3ea\x3c/div\x3e' + '\x3c/div\x3e' + '\x3c/div\x3e';
  return div.firstChild.scrollWidth > div.firstChild.clientWidth;
}}, {name:'FlexBoxBasisBug', ready:true, fn:function() {
  if (Ext.isIE11 || Ext.os.is.iOS && Ext.os.version.major <= 10 || Ext.isSafari && Ext.browser.version.isLessThan(11) || Ext.os.is.Android && Ext.os.version.isLessThan(6)) {
    return true;
  }
  return false;
}}, {name:'PercentageSizeFlexBug', ready:true, fn:function(doc, div) {
  if (Ext.isIE9m) {
    return false;
  }
  var style = div.style;
  style.display = 'flex';
  style.flexDirection = 'column';
  style.height = style.width = '100px';
  div.innerHTML = '\x3cdiv style\x3d"flex: 1 1;"\x3e\x3cdiv style\x3d"height:50%"\x3e\x3c/div\x3e\x3c/div\x3e';
  return div.firstChild.firstChild.offsetHeight !== 50;
}}, {name:'CannotScrollExactHeight', fn:function() {
  return Ext.isIE10p;
}}, {name:'WebKitInputTableBoxModelBug', ready:true, fn:function(doc, div) {
  var table = document.createElement('div'), cell = document.createElement('div'), input = document.createElement('input'), tableStyle = table.style, cellStyle = cell.style, inputStyle = input.style, body = doc.body, hasBug;
  input.type = 'text';
  tableStyle.display = 'table';
  tableStyle.height = '100px';
  cellStyle.display = 'table-cell';
  inputStyle.border = '0';
  inputStyle.padding = '10px';
  inputStyle.boxSizing = 'border-box';
  inputStyle.height = '100%';
  cell.appendChild(input);
  table.appendChild(cell);
  body.appendChild(table);
  hasBug = input.offsetHeight === 80;
  body.removeChild(table);
  return hasBug;
}}, {name:'PassiveEventListener', fn:function(doc, div) {
  var supportsPassive = false, options;
  try {
    options = Object.defineProperty({}, 'passive', {get:function() {
      supportsPassive = true;
    }});
    window.addEventListener('e', null, options);
    window.removeEventListener('e', null, options);
  } catch (e$35) {
  }
  return supportsPassive;
}}, {name:'CSSMinContent', ready:true, fn:function(doc, div) {
  div.innerHTML = '\x3cdiv style\x3d"height:4px;width:4px;min-height:-webkit-min-content;min-height:-moz-min-content;min-height:min-content"\x3e\x3cdiv style\x3d"height:8px;width:8px"\x3e\x3c/div\x3e\x3c/div\x3e';
  return div.firstChild.offsetHeight === 8;
}}, {name:'ComputedSizeIncludesPadding', ready:true, fn:function(doc, div) {
  var ret = false, bd = document.body, el, w;
  if (window.getComputedStyle) {
    el = document.createElement('div');
    el.style.cssText = 'width:10px;padding:2px;' + '-webkit-box-sizing:border-box;box-sizing:border-box;';
    bd.appendChild(el);
    w = window.getComputedStyle(el, null).width;
    ret = w === '10px';
    bd.removeChild(el);
  }
  return ret;
}}, {name:'inputEventData', ready:false, fn:function() {
  return !!(window.InputEvent && 'data' in new InputEvent('input'));
}}, 0]};
Ext.feature.tests.pop();
Ext.supports = {};
Ext.feature.detect();
Ext.env.Ready = {blocks:(location.search || '').indexOf('ext-pauseReadyFire') > 0 ? 1 : 0, bound:0, delay:1, events:[], firing:false, generation:0, listeners:[], nextId:0, sortGeneration:0, state:0, timer:null, bind:function() {
  var me = Ext.env.Ready, doc = document;
  if (!me.bound) {
    if (doc.readyState === 'complete') {
      me.onReadyEvent({type:doc.readyState || 'body'});
    } else {
      me.bound = 1;
      if (Ext.browser.is.PhoneGap && !Ext.os.is.Desktop) {
        me.bound = 2;
        doc.addEventListener('deviceready', me.onReadyEvent, false);
      }
      doc.addEventListener('DOMContentLoaded', me.onReadyEvent, false);
      window.addEventListener('load', me.onReadyEvent, false);
    }
  }
}, block:function() {
  ++this.blocks;
  Ext.isReady = false;
}, fireReady:function() {
  var me = Ext.env.Ready;
  if (!me.state) {
    Ext._readyTime = Ext.ticks();
    Ext.isDomReady = true;
    me.state = 1;
    Ext.feature.detect(true);
    if (!me.delay) {
      me.handleReady();
    } else {
      if (navigator.standalone) {
        me.timer = Ext.defer(function() {
          me.timer = null;
          me.handleReadySoon();
        }, 1);
      } else {
        me.handleReadySoon();
      }
    }
  }
}, handleReady:function() {
  var me = this;
  if (me.state === 1) {
    me.state = 2;
    Ext._beforeReadyTime = Ext.ticks();
    me.invokeAll();
    Ext._afterReadyTime = Ext.ticks();
  }
}, handleReadySoon:function(delay) {
  var me = this;
  if (!me.timer) {
    me.timer = Ext.defer(function() {
      me.timer = null;
      me.handleReady();
    }, delay || me.delay);
  }
}, invoke:function(listener) {
  var delay = listener.delay;
  if (delay) {
    Ext.defer(listener.fn, delay, listener.scope);
  } else {
    if (Ext.elevateFunction) {
      Ext.elevateFunction(listener.fn, listener.scope);
    } else {
      listener.fn.call(listener.scope);
    }
  }
}, invokeAll:function() {
  if (Ext.elevateFunction) {
    Ext.elevateFunction(this.doInvokeAll, this);
  } else {
    this.doInvokeAll();
  }
}, doInvokeAll:function() {
  var me = this, listeners = me.listeners, listener;
  if (!me.blocks) {
    Ext.isReady = true;
  }
  me.firing = true;
  while (listeners.length) {
    if (me.sortGeneration !== me.generation) {
      me.sortGeneration = me.generation;
      listeners.sort(me.sortFn);
    }
    listener = listeners.pop();
    if (me.blocks && !listener.dom) {
      listeners.push(listener);
      break;
    }
    me.invoke(listener);
  }
  me.firing = false;
}, makeListener:function(fn, scope, options) {
  var ret = {fn:fn, id:++this.nextId, scope:scope, dom:false, priority:0};
  if (options) {
    Ext.apply(ret, options);
  }
  ret.phase = ret.dom ? 0 : 1;
  return ret;
}, on:function(fn, scope, options) {
  var me = Ext.env.Ready, listener = me.makeListener(fn, scope, options);
  if (me.state === 2 && !me.firing && (listener.dom || !me.blocks)) {
    me.invoke(listener);
  } else {
    me.listeners.push(listener);
    ++me.generation;
    if (!me.bound) {
      me.bind();
    }
  }
}, onReadyEvent:function(ev) {
  var me = Ext.env.Ready;
  if (Ext.elevateFunction) {
    Ext.elevateFunction(me.doReadyEvent, me, arguments);
  } else {
    me.doReadyEvent(ev);
  }
}, doReadyEvent:function(ev) {
  var me = this;
  if (ev && ev.type) {
    me.events.push(ev);
  }
  if (me.bound > 0) {
    me.unbind();
    me.bound = -1;
  }
  if (!me.state) {
    me.fireReady();
  }
}, sortFn:function(a, b) {
  return -(a.phase - b.phase || b.priority - a.priority || a.id - b.id);
}, unblock:function() {
  var me = this;
  if (me.blocks) {
    if (!--me.blocks) {
      if (me.state === 2 && !me.firing) {
        me.invokeAll();
      }
    }
  }
}, unbind:function() {
  var me = this, doc = document;
  if (me.bound > 1) {
    doc.removeEventListener('deviceready', me.onReadyEvent, false);
  }
  doc.removeEventListener('DOMContentLoaded', me.onReadyEvent, false);
  window.removeEventListener('load', me.onReadyEvent, false);
}};
(function() {
  var Ready = Ext.env.Ready;
  if (Ext.isIE9m) {
    Ext.apply(Ready, {scrollTimer:null, readyStatesRe:/complete/i, pollScroll:function() {
      var scrollable = true;
      try {
        document.documentElement.doScroll('left');
      } catch (e$36) {
        scrollable = false;
      }
      if (scrollable && document.body) {
        Ready.onReadyEvent({type:'doScroll'});
      } else {
        Ready.scrollTimer = Ext.defer(Ready.pollScroll, 20);
      }
      return scrollable;
    }, bind:function() {
      var doc = document, topContext;
      if (Ready.bound) {
        return;
      }
      try {
        topContext = window.frameElement === undefined;
      } catch (e$37) {
      }
      if (!topContext || !doc.documentElement.doScroll) {
        Ready.pollScroll = Ext.emptyFn;
      } else {
        if (Ready.pollScroll()) {
          return;
        }
      }
      if (doc.readyState === 'complete') {
        Ready.onReadyEvent({type:'already ' + (doc.readyState || 'body')});
      } else {
        doc.attachEvent('onreadystatechange', Ready.onReadyStateChange);
        window.attachEvent('onload', Ready.onReadyEvent);
        Ready.bound = 1;
      }
    }, unbind:function() {
      document.detachEvent('onreadystatechange', Ready.onReadyStateChange);
      window.detachEvent('onload', Ready.onReadyEvent);
      if (Ext.isNumber(Ready.scrollTimer)) {
        Ext.undefer(Ready.scrollTimer);
        Ready.scrollTimer = null;
      }
    }, onReadyStateChange:function() {
      var state = document.readyState;
      if (Ready.readyStatesRe.test(state)) {
        Ready.onReadyEvent({type:state});
      }
    }});
  }
  Ext.onDocumentReady = function(fn, scope, options) {
    var opt = {dom:true};
    if (options) {
      Ext.apply(opt, options);
    }
    Ready.on(fn, scope, opt);
  };
  Ext.onReady = function(fn, scope, options) {
    Ready.on(fn, scope, options);
  };
  Ext.onInternalReady = function(fn, scope, options) {
    Ready.on(fn, scope, Ext.apply({priority:1000}, options));
  };
  Ready.bind();
})();
Ext.Loader = new function() {
  var Loader = this, Manager = Ext.ClassManager, Boot = Ext.Boot, Class = Ext.Class, Ready = Ext.env.Ready, alias = Ext.Function.alias, dependencyProperties = ['extend', 'mixins', 'requires'], isInHistory = {}, history = [], readyListeners = [], usedClasses = [], _requiresMap = {}, _config = {enabled:true, scriptChainDelay:false, disableCaching:true, disableCachingParam:'_dc', paths:Manager.paths, preserveScripts:true, scriptCharset:undefined}, delegatedConfigs = {disableCaching:true, disableCachingParam:true, 
  preserveScripts:true, scriptChainDelay:'loadDelay'};
  Ext.apply(Loader, {isInHistory:isInHistory, isLoading:false, history:history, config:_config, readyListeners:readyListeners, optionalRequires:usedClasses, requiresMap:_requiresMap, hasFileLoadError:false, scriptsLoading:0, classesLoading:{}, missingCount:0, missingQueue:{}, syncModeEnabled:false, init:function() {
    var scripts = document.getElementsByTagName('script'), src = scripts[scripts.length - 1].src, path = src.substring(0, src.lastIndexOf('/') + 1), meta = Ext._classPathMetadata, microloader = Ext.Microloader, manifest = Ext.manifest, loadOrder, baseUrl, loadlen, l, loadItem;
    if (src.indexOf('packages/core/src/') !== -1) {
      path = path + '../../';
    } else {
      if (src.indexOf('/core/src/class/') !== -1) {
        path = path + '../../../';
      }
    }
    if (!Manager.getPath('Ext')) {
      Manager.setPath('Ext', path + 'src');
    }
    if (meta) {
      Ext._classPathMetadata = null;
      Loader.addClassPathMappings(meta);
    }
    if (manifest) {
      loadOrder = manifest.loadOrder;
      baseUrl = Ext.Boot.baseUrl;
      if (loadOrder && manifest.bootRelative) {
        for (loadlen = loadOrder.length, l = 0; l < loadlen; l++) {
          loadItem = loadOrder[l];
          loadItem.path = baseUrl + loadItem.path;
          loadItem.canonicalPath = true;
        }
      }
    }
    if (microloader) {
      Ready.block();
      microloader.onMicroloaderReady(function() {
        Ready.unblock();
      });
    }
  }, setConfig:Ext.Function.flexSetter(function(name, value) {
    var delegated = delegatedConfigs[name];
    if (name === 'paths') {
      Loader.setPath(value);
    } else {
      _config[name] = value;
      if (delegated) {
        Boot.setConfig(delegated === true ? name : delegated, value);
      }
    }
    return Loader;
  }), getConfig:function(name) {
    return name ? _config[name] : _config;
  }, setPath:function() {
    Manager.setPath.apply(Manager, arguments);
    return Loader;
  }, addClassPathMappings:function(paths) {
    Manager.setPath(paths);
    return Loader;
  }, addBaseUrlClassPathMappings:function(pathConfig) {
    var name;
    for (name in pathConfig) {
      pathConfig[name] = Boot.baseUrl + pathConfig[name];
    }
    Ext.Loader.addClassPathMappings(pathConfig);
  }, getPath:function(className) {
    return Manager.getPath(className);
  }, require:function(expressions, fn, scope, excludes) {
    var classNames;
    if (excludes) {
      return Loader.exclude(excludes).require(expressions, fn, scope);
    }
    classNames = Manager.getNamesByExpression(expressions);
    return Loader.load(classNames, fn, scope);
  }, syncRequire:function() {
    var wasEnabled = Loader.syncModeEnabled, ret;
    Loader.syncModeEnabled = true;
    ret = Loader.require.apply(Loader, arguments);
    Loader.syncModeEnabled = wasEnabled;
    return ret;
  }, exclude:function(excludes) {
    var selector = Manager.select({require:function(classNames, fn, scope) {
      return Loader.load(classNames, fn, scope);
    }, syncRequire:function(classNames, fn, scope) {
      var wasEnabled = Loader.syncModeEnabled, ret;
      Loader.syncModeEnabled = true;
      ret = Loader.load(classNames, fn, scope);
      Loader.syncModeEnabled = wasEnabled;
      return ret;
    }});
    selector.exclude(excludes);
    return selector;
  }, load:function(classNames, callback, scope) {
    if (callback) {
      if (callback.length) {
        callback = Loader.makeLoadCallback(classNames, callback);
      }
      callback = callback.bind(scope || Ext.global);
    }
    var state = Manager.classState, missingClassNames = [], urls = [], urlByClass = {}, numClasses = classNames.length, className, i, numMissing;
    for (i = 0; i < numClasses; ++i) {
      className = Manager.resolveName(classNames[i]);
      if (!Manager.isCreated(className)) {
        missingClassNames.push(className);
        if (!state[className]) {
          urlByClass[className] = Loader.getPath(className);
          urls.push(urlByClass[className]);
        }
      }
    }
    numMissing = missingClassNames.length;
    if (numMissing) {
      Loader.missingCount += numMissing;
      Manager.onCreated(function() {
        if (callback) {
          Ext.callback(callback, scope, arguments);
        }
        Loader.checkReady();
      }, Loader, missingClassNames);
      if (!_config.enabled) {
        Ext.raise('Ext.Loader is not enabled, so dependencies cannot be resolved ' + 'dynamically. Missing required class' + (missingClassNames.length > 1 ? 'es' : '') + ': ' + missingClassNames.join(', '));
      }
      if (urls.length) {
        Loader.loadScripts({url:urls, _classNames:missingClassNames, _urlByClass:urlByClass});
      } else {
        Loader.checkReady();
      }
    } else {
      if (callback) {
        callback.call(scope);
      }
      Loader.checkReady();
    }
    if (Loader.syncModeEnabled) {
      if (numClasses === 1) {
        return Manager.get(classNames[0]);
      }
    }
    return Loader;
  }, makeLoadCallback:function(classNames, callback) {
    return function() {
      var classes = [], i = classNames.length;
      while (i-- > 0) {
        classes[i] = Manager.get(classNames[i]);
      }
      return callback.apply(this, classes);
    };
  }, onLoadFailure:function(request) {
    var options = this, entries = request.entries || [], onError = options.onError, error, entry, i;
    Loader.hasFileLoadError = true;
    --Loader.scriptsLoading;
    if (onError) {
      for (i = 0; i < entries.length; i++) {
        entry = entries[i];
        if (entry.error) {
          error = new Error('Failed to load: ' + entry.url);
          break;
        }
      }
      error = error || new Error('Failed to load');
      onError.call(options.userScope, options, error, request);
    } else {
      Ext.log.error('[Ext.Loader] Some requested files failed to load.');
    }
    Loader.checkReady();
  }, onLoadSuccess:function() {
    var options = this, onLoad = options.onLoad, classNames = options._classNames, urlByClass = options._urlByClass, state = Manager.classState, missingQueue = Loader.missingQueue, className, i, len;
    --Loader.scriptsLoading;
    if (onLoad) {
      onLoad.call(options.userScope, options);
    }
    for (i = 0, len = classNames.length; i < len; i++) {
      className = classNames[i];
      if (!state[className]) {
        missingQueue[className] = urlByClass[className];
      }
    }
    Loader.checkReady();
  }, reportMissingClasses:function() {
    var missingQueue = Loader.missingQueue, missingClasses = [], missingPaths = [], missingClassName;
    if (!Loader.syncModeEnabled && !Loader.scriptsLoading && Loader.isLoading && !Loader.hasFileLoadError) {
      for (missingClassName in missingQueue) {
        missingClasses.push(missingClassName);
        missingPaths.push(missingQueue[missingClassName]);
      }
      if (missingClasses.length) {
        throw new Error('The following classes are not declared even if their files ' + "have been loaded: '" + missingClasses.join("', '") + "'. Please check the source code of their " + "corresponding files for possible typos: '" + missingPaths.join("', '"));
      }
    }
  }, onReady:function(fn, scope, withDomReady, options) {
    var listener;
    if (withDomReady) {
      Ready.on(fn, scope, options);
    } else {
      listener = Ready.makeListener(fn, scope, options);
      if (Loader.isLoading) {
        readyListeners.push(listener);
      } else {
        Ready.invoke(listener);
      }
    }
  }, addUsedClasses:function(classes) {
    var cls, i, ln;
    if (classes) {
      classes = typeof classes === 'string' ? [classes] : classes;
      for (i = 0, ln = classes.length; i < ln; i++) {
        cls = classes[i];
        if (typeof cls === 'string' && !Ext.Array.contains(usedClasses, cls)) {
          usedClasses.push(cls);
        }
      }
    }
    return Loader;
  }, triggerReady:function() {
    var listener, refClasses = usedClasses;
    if (Loader.isLoading && refClasses.length) {
      usedClasses = [];
      Loader.require(refClasses);
    } else {
      Loader.isLoading = false;
      readyListeners.sort(Ready.sortFn);
      while (readyListeners.length && !Loader.isLoading) {
        listener = readyListeners.pop();
        Ready.invoke(listener);
      }
      Ready.unblock();
    }
  }, historyPush:function(className) {
    if (className && !isInHistory[className] && !Manager.overrideMap[className]) {
      isInHistory[className] = true;
      history.push(className);
    }
    return Loader;
  }, loadScripts:function(params) {
    var manifest = Ext.manifest, loadOrder = manifest && manifest.loadOrder, loadOrderMap = manifest && manifest.loadOrderMap, options;
    ++Loader.scriptsLoading;
    if (loadOrder && !loadOrderMap) {
      manifest.loadOrderMap = loadOrderMap = Boot.createLoadOrderMap(loadOrder);
    }
    Loader.checkReady();
    options = Ext.apply({loadOrder:loadOrder, loadOrderMap:loadOrderMap, charset:_config.scriptCharset, success:Loader.onLoadSuccess, failure:Loader.onLoadFailure, sync:Loader.syncModeEnabled, _classNames:[]}, params);
    options.userScope = options.scope;
    options.scope = options;
    Boot.load(options);
  }, loadScriptsSync:function(urls) {
    var syncwas = Loader.syncModeEnabled;
    Loader.syncModeEnabled = true;
    Loader.loadScripts({url:urls});
    Loader.syncModeEnabled = syncwas;
  }, loadScriptsSyncBasePrefix:function(urls) {
    var syncwas = Loader.syncModeEnabled;
    Loader.syncModeEnabled = true;
    Loader.loadScripts({url:urls, prependBaseUrl:true});
    Loader.syncModeEnabled = syncwas;
  }, loadScript:function(options) {
    var isString = typeof options === 'string', isArray = options instanceof Array, isObject = !isArray && !isString, url = isObject ? options.url : options, onError = isObject && options.onError, onLoad = isObject && options.onLoad, scope = isObject && options.scope, request = {url:url, scope:scope, onLoad:onLoad, onError:onError, _classNames:[]};
    Loader.loadScripts(request);
  }, checkMissingQueue:function() {
    var missingQueue = Loader.missingQueue, newQueue = {}, missing = 0, name;
    for (name in missingQueue) {
      if (!(Manager.classState[name] || Manager.isCreated(name))) {
        newQueue[name] = missingQueue[name];
        missing++;
      }
    }
    Loader.missingCount = missing;
    Loader.missingQueue = newQueue;
  }, checkReady:function() {
    var wasLoading = Loader.isLoading, isLoading;
    Loader.checkMissingQueue();
    isLoading = Loader.missingCount + Loader.scriptsLoading;
    if (isLoading && !wasLoading) {
      Ready.block();
      Loader.isLoading = !!isLoading;
    } else {
      if (!isLoading && wasLoading) {
        Loader.triggerReady();
      }
    }
    if (!Loader.scriptsLoading && Loader.missingCount) {
      Ext.defer(function() {
        var name;
        if (!Loader.scriptsLoading && Loader.missingCount) {
          Ext.log.error('[Loader] The following classes failed to load:');
          for (name in Loader.missingQueue) {
            Ext.log.error('[Loader] ' + name + ' from ' + Loader.missingQueue[name]);
          }
        }
      }, 1000);
    }
  }});
  Ext.require = alias(Loader, 'require');
  Ext.syncRequire = alias(Loader, 'syncRequire');
  Ext.exclude = alias(Loader, 'exclude');
  Class.registerPreprocessor('loader', function(cls, data, hooks, continueFn) {
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(cls, 'Ext.Loader#loaderPreprocessor', arguments);
    }
    var me = this, dependencies = [], dependency, className = Manager.getName(cls), i, j, ln, subLn, value, propertyName, propertyValue, requiredMap;
    for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
      propertyName = dependencyProperties[i];
      if (data.hasOwnProperty(propertyName)) {
        propertyValue = data[propertyName];
        if (typeof propertyValue === 'string') {
          dependencies.push(propertyValue);
        } else {
          if (propertyValue instanceof Array) {
            for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
              value = propertyValue[j];
              if (typeof value === 'string') {
                dependencies.push(value);
              }
            }
          } else {
            if (typeof propertyValue !== 'function') {
              for (j in propertyValue) {
                if (propertyValue.hasOwnProperty(j)) {
                  value = propertyValue[j];
                  if (typeof value === 'string') {
                    dependencies.push(value);
                  }
                }
              }
            }
          }
        }
      }
    }
    if (dependencies.length === 0) {
      return;
    }
    if (className) {
      _requiresMap[className] = dependencies;
    }
    var manifestClasses = Ext.manifest && Ext.manifest.classes, deadlockPath = [], detectDeadlock;
    if (className && (!manifestClasses || !manifestClasses[className])) {
      requiredMap = Loader.requiredByMap || (Loader.requiredByMap = {});
      for (i = 0, ln = dependencies.length; i < ln; i++) {
        dependency = dependencies[i];
        (requiredMap[dependency] || (requiredMap[dependency] = [])).push(className);
      }
      detectDeadlock = function(cls) {
        var requires = _requiresMap[cls], dep, i, ln;
        deadlockPath.push(cls);
        if (requires) {
          if (Ext.Array.contains(requires, className)) {
            Ext.Error.raise("Circular requirement detected! '" + className + "' and '" + deadlockPath[1] + "' mutually require each other. " + 'Path: ' + deadlockPath.join(' -\x3e ') + ' -\x3e ' + deadlockPath[0]);
          }
          for (i = 0, ln = requires.length; i < ln; i++) {
            dep = requires[i];
            if (!isInHistory[dep]) {
              detectDeadlock(requires[i]);
            }
          }
        }
      };
      detectDeadlock(className);
    }
    (className ? Loader.exclude(className) : Loader).require(dependencies, function() {
      var i, ln, j, subLn, k;
      for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
        propertyName = dependencyProperties[i];
        if (data.hasOwnProperty(propertyName)) {
          propertyValue = data[propertyName];
          if (typeof propertyValue === 'string') {
            data[propertyName] = Manager.get(propertyValue);
          } else {
            if (propertyValue instanceof Array) {
              for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
                value = propertyValue[j];
                if (typeof value === 'string') {
                  data[propertyName][j] = Manager.get(value);
                }
              }
            } else {
              if (typeof propertyValue !== 'function') {
                for (k in propertyValue) {
                  if (propertyValue.hasOwnProperty(k)) {
                    value = propertyValue[k];
                    if (typeof value === 'string') {
                      data[propertyName][k] = Manager.get(value);
                    }
                  }
                }
              }
            }
          }
        }
      }
      continueFn.call(me, cls, data, hooks);
    });
    return false;
  }, true, 'after', 'className');
  Manager.registerPostprocessor('uses', function(name, cls, data) {
    var uses = data.uses, classNames;
    if (Ext.classSystemMonitor) {
      Ext.classSystemMonitor(cls, 'Ext.Loader#usesPostprocessor', arguments);
    }
    if (uses) {
      classNames = Manager.getNamesByExpression(data.uses);
      Loader.addUsedClasses(classNames);
    }
  });
  Manager.onCreated(Loader.historyPush);
  Loader.init();
};
Ext._endTime = Ext.ticks();
if (Ext._beforereadyhandler) {
  Ext._beforereadyhandler();
}
Ext.define('Ext.Mixin', function(Mixin) {
  return {statics:{addHook:function(hookFn, targetClass, methodName, mixinClassPrototype) {
    var isFunc = Ext.isFunction(hookFn), hook = function() {
      var a = arguments, fn = isFunc ? hookFn : mixinClassPrototype[hookFn], result = this.callParent(a);
      fn.apply(this, a);
      return result;
    }, existingFn = targetClass.hasOwnProperty(methodName) && targetClass[methodName];
    if (isFunc) {
      hookFn.$previous = Ext.emptyFn;
    }
    hook.$name = methodName;
    hook.$owner = targetClass.self;
    if (existingFn) {
      hook.$previous = existingFn.$previous;
      existingFn.$previous = hook;
    } else {
      targetClass[methodName] = hook;
    }
  }}, onClassExtended:function(cls, data) {
    var mixinConfig = data.mixinConfig, hooks = data.xhooks, superclass = cls.superclass, onClassMixedIn = data.onClassMixedIn, afterClassMixedIn = data.afterClassMixedIn, afters, befores, configs, extended, mixed, parentMixinConfig;
    if (hooks) {
      delete data.xhooks;
      (mixinConfig || (data.mixinConfig = mixinConfig = {})).on = hooks;
    }
    if (mixinConfig) {
      parentMixinConfig = superclass.mixinConfig;
      if (parentMixinConfig) {
        data.mixinConfig = mixinConfig = Ext.merge({}, parentMixinConfig, mixinConfig);
      }
      data.mixinId = mixinConfig.id;
      if (mixinConfig.beforeHooks) {
        Ext.raise('Use of "beforeHooks" is deprecated - use "before" instead');
      }
      if (mixinConfig.hooks) {
        Ext.raise('Use of "hooks" is deprecated - use "after" instead');
      }
      if (mixinConfig.afterHooks) {
        Ext.raise('Use of "afterHooks" is deprecated - use "after" instead');
      }
      afters = mixinConfig.after;
      befores = mixinConfig.before;
      configs = mixinConfig.configs;
      extended = mixinConfig.extended;
      hooks = mixinConfig.on;
      mixed = mixinConfig.mixed;
    }
    if (afters || befores || hooks || extended) {
      data.onClassMixedIn = function(targetClass) {
        var mixin = this.prototype, targetProto = targetClass.prototype, key;
        if (befores) {
          Ext.Object.each(befores, function(key, value) {
            targetClass.hookMember(key, function() {
              if (mixin[value].apply(this, arguments) !== false) {
                return this.callParent(arguments);
              }
            });
          });
        }
        if (afters) {
          Ext.Object.each(afters, function(key, value) {
            targetClass.hookMember(key, function() {
              var ret = this.callParent(arguments);
              mixin[value].apply(this, arguments);
              return ret;
            });
          });
        }
        if (hooks) {
          for (key in hooks) {
            Mixin.addHook(hooks[key], targetProto, key, mixin);
          }
        }
        if (extended) {
          targetClass.onExtended(function() {
            var args = Ext.Array.slice(arguments, 0);
            args.unshift(targetClass);
            return extended.apply(this, args);
          }, this);
        }
        if (onClassMixedIn) {
          onClassMixedIn.apply(this, arguments);
        }
      };
    }
    if (configs || mixed) {
      data.afterClassMixedIn = function(targetClass) {
        if (configs) {
          var proto = targetClass.prototype, hoistable = this.$config.configs, cfg, name, hoist;
          for (name in proto) {
            cfg = hoistable[name];
            if (cfg && cfg.isConfig && proto.hasOwnProperty(name)) {
              (hoist || (hoist = {}))[name] = proto[name];
              delete proto[name];
            }
          }
          if (hoist) {
            targetClass.$config.add(hoist);
          }
        }
        if (afterClassMixedIn) {
          afterClassMixedIn.apply(this, arguments);
        }
        if (mixed) {
          mixed.apply(this, arguments);
        }
      };
    }
  }};
});
Ext.util = Ext.util || {};
Ext.util.DelayedTask = function(fn, scope, args, cancelOnDelay, fireIdleEvent) {
  var me = this, delay, call = function() {
    me.id = null;
    if (!(scope && scope.destroyed)) {
      if (args) {
        fn.apply(scope, args);
      } else {
        fn.call(scope);
      }
    }
    if (fireIdleEvent === false) {
      Ext._suppressIdle = true;
    }
  };
  if (fn) {
    call.$origFn = fn.$origFn || fn;
    call.$skipTimerCheck = call.$origFn.$skipTimerCheck;
  }
  cancelOnDelay = typeof cancelOnDelay === 'boolean' ? cancelOnDelay : true;
  me.id = null;
  me.delay = function(newDelay, newFn, newScope, newArgs) {
    if (cancelOnDelay) {
      me.cancel();
    }
    if (typeof newDelay === 'number') {
      delay = newDelay;
    }
    fn = newFn || fn;
    scope = newScope || scope;
    args = newArgs || args;
    me.delayTime = delay;
    if (fn) {
      call.$origFn = fn.$origFn || fn;
      call.$skipTimerCheck = call.$origFn.$skipTimerCheck;
    }
    if (!me.id) {
      if (delay === -1) {
        me.id = Ext.raf(call);
      } else {
        me.id = Ext.defer(call, delay || 1);
      }
    }
    return me.id;
  };
  me.cancel = function() {
    if (me.id) {
      if (me.delayTime === -1) {
        Ext.unraf(me.id);
      } else {
        Ext.undefer(me.id);
      }
      me.id = null;
    }
  };
  me.flush = function() {
    var was;
    if (me.id) {
      me.cancel();
      was = fireIdleEvent;
      fireIdleEvent = true;
      call();
      fireIdleEvent = was;
    }
  };
  me.stop = function(stopFn, stopScope) {
    if (stopFn && stopFn === fn && (!stopScope || stopScope === scope)) {
      me.cancel();
    }
  };
};
Ext.define('Ext.util.Event', function() {
  var arraySlice = Array.prototype.slice, arrayInsert = Ext.Array.insert, toArray = Ext.Array.toArray, fireArgs = {};
  return {isEvent:true, suspended:0, noOptions:{}, constructor:function(observable, name) {
    this.name = name;
    this.observable = observable;
    this.listeners = [];
  }, addListener:function(fn, scope, options, caller, manager) {
    var me = this, added = false, observable = me.observable, eventName = me.name, listeners, listener, priority, isNegativePriority, highestNegativePriorityIndex, hasNegativePriorityIndex, length, index, i, listenerPriority, managedListeners;
    if (scope && !Ext._namedScopes[scope] && typeof fn === 'string' && typeof scope[fn] !== 'function') {
      Ext.raise("No method named '" + fn + "' found on scope object");
    }
    if (me.findListener(fn, scope) === -1) {
      listener = me.createListener(fn, scope, options, caller, manager);
      if (me.firing) {
        me.listeners = me.listeners.slice(0);
      }
      listeners = me.listeners;
      index = length = listeners.length;
      priority = options && options.priority;
      highestNegativePriorityIndex = me._highestNegativePriorityIndex;
      hasNegativePriorityIndex = highestNegativePriorityIndex !== undefined;
      if (priority) {
        isNegativePriority = priority < 0;
        if (!isNegativePriority || hasNegativePriorityIndex) {
          for (i = isNegativePriority ? highestNegativePriorityIndex : 0; i < length; i++) {
            listenerPriority = listeners[i].o ? listeners[i].o.priority || 0 : 0;
            if (listenerPriority < priority) {
              index = i;
              break;
            }
          }
        } else {
          me._highestNegativePriorityIndex = index;
        }
      } else {
        if (hasNegativePriorityIndex) {
          index = highestNegativePriorityIndex;
        }
      }
      if (!isNegativePriority && index <= highestNegativePriorityIndex) {
        me._highestNegativePriorityIndex++;
      }
      if (index === length) {
        listeners[length] = listener;
      } else {
        arrayInsert(listeners, index, [listener]);
      }
      if (observable.isElement) {
        observable._getPublisher(eventName, options.translate === false).subscribe(observable, eventName, options.delegated !== false, options.capture);
      }
      if (manager) {
        managedListeners = manager.managedListeners || (manager.managedListeners = []);
        managedListeners.push({item:me.observable, ename:options && options.managedName || me.name, fn:fn, scope:scope, options:options});
      }
      added = true;
    }
    return added;
  }, createListener:function(fn, scope, o, caller, manager) {
    var me = this, namedScopes = Ext._namedScopes, namedScope = namedScopes[scope], listener = {fn:fn, scope:scope, ev:me, caller:caller, manager:manager, namedScope:namedScope, defaultScope:namedScope ? scope || me.observable : undefined, lateBound:typeof fn === 'string'}, handler = fn, wrapped = false, type;
    if (listener.lateBound && fn[2] === '.') {
      if (fn.substr(0, 2) !== 'up') {
        Ext.raise('Invalid listener method: ' + fn);
      }
      listener.defaultScope = null;
      listener.namedScope = namedScopes[listener.scope = scope = 'up'];
      listener.fn = handler = fn.substr(3);
    }
    if (o) {
      listener.o = o;
      if (o.single) {
        handler = me.createSingle(handler, listener, o, scope);
        wrapped = true;
      }
      if (o.target) {
        handler = me.createTargeted(handler, listener, o, scope, wrapped);
        wrapped = true;
      }
      if (o.onFrame) {
        handler = me.createAnimFrame(handler, listener, o, scope, wrapped);
        wrapped = true;
      }
      if (o.delay) {
        handler = me.createDelayed(handler, listener, o, scope, wrapped);
        wrapped = true;
      }
      if (o.buffer) {
        handler = me.createBuffered(handler, listener, o, scope, wrapped);
        wrapped = true;
      }
      if (me.observable.isElement) {
        type = o.type;
        if (type) {
          listener.type = type;
        }
      }
    }
    listener.fireFn = handler;
    listener.wrapped = wrapped;
    return listener;
  }, findListener:function(fn, scope) {
    var listeners = this.listeners, i = listeners.length, listener;
    while (i--) {
      listener = listeners[i];
      if (listener) {
        if (listener.fn === fn && listener.scope == scope) {
          return i;
        }
      }
    }
    return -1;
  }, removeListener:function(fn, scope, index) {
    var me = this, removed = false, observable = me.observable, eventName = me.name, listener, options, manager, managedListeners, managedListener, i;
    index = index != null ? index : me.findListener(fn, scope);
    if (index !== -1) {
      listener = me.listeners[index];
      if (me.firing) {
        me.listeners = me.listeners.slice(0);
      }
      me.listeners.splice(index, 1);
      if (me._highestNegativePriorityIndex) {
        if (index < me._highestNegativePriorityIndex) {
          me._highestNegativePriorityIndex--;
        } else {
          if (index === me._highestNegativePriorityIndex && index === me.listeners.length) {
            delete me._highestNegativePriorityIndex;
          }
        }
      }
      if (listener) {
        options = listener.o;
        if (listener.task) {
          listener.task.cancel();
          delete listener.task;
        }
        i = listener.tasks && listener.tasks.length;
        if (i) {
          while (i--) {
            listener.tasks[i].cancel();
          }
          delete listener.tasks;
        }
        listener.fireFn.timerId = Ext.undefer(listener.fireFn.timerId);
        manager = listener.manager;
        if (manager) {
          managedListeners = manager.managedListeners;
          if (managedListeners) {
            for (i = managedListeners.length; i--;) {
              managedListener = managedListeners[i];
              if (managedListener.item === me.observable && managedListener.ename === eventName && managedListener.fn === fn && managedListener.scope === scope) {
                managedListeners.splice(i, 1);
              }
            }
          }
        }
        if (observable.isElement) {
          observable._getPublisher(eventName, options.translate === false).unsubscribe(observable, eventName, options.delegated !== false, options.capture);
        }
      }
      removed = true;
    }
    return removed;
  }, clearListeners:function() {
    var listeners = this.listeners, i = listeners.length, listener;
    while (i--) {
      listener = listeners[i];
      this.removeListener(listener.fn, listener.scope);
    }
  }, suspend:function() {
    ++this.suspended;
  }, resume:function() {
    if (this.suspended) {
      --this.suspended;
    }
  }, isSuspended:function() {
    return this.suspended > 0;
  }, fireDelegated:function(firingObservable, args) {
    this.firingObservable = firingObservable;
    return this.fire.apply(this, args);
  }, fire:function() {
    var me = this, CQ = Ext.ComponentQuery, listeners = me.listeners, count = listeners.length, observable = me.observable, isElement = observable.isElement, isComponent = observable.isComponent, firingObservable = me.firingObservable, options, delegate, fireInfo, i, args, listener, len, delegateEl, currentTarget, type, chained, firingArgs, e, fireFn, fireScope;
    if (!me.suspended && count > 0) {
      me.firing = true;
      args = arguments.length ? arraySlice.call(arguments, 0) : [];
      len = args.length;
      if (isElement) {
        e = args[0];
      }
      for (i = 0; i < count; i++) {
        listener = listeners[i];
        if (!listener) {
          continue;
        }
        options = listener.o;
        if (isElement) {
          if (currentTarget) {
            e.setCurrentTarget(currentTarget);
          }
          type = listener.type;
          if (type) {
            chained = e;
            e = args[0] = chained.chain({type:type, isGesture:false});
          }
          Ext.EventObject = e;
        }
        firingArgs = args;
        if (options) {
          delegate = options.delegate;
          if (delegate) {
            if (isElement) {
              delegateEl = e.getTarget(typeof delegate === 'function' ? delegate : '#' + e.currentTarget.id + ' ' + delegate);
              if (delegateEl) {
                args[1] = delegateEl;
                currentTarget = e.currentTarget;
                e.setCurrentTarget(delegateEl);
              } else {
                continue;
              }
            } else {
              if (isComponent && !CQ.is(firingObservable, delegate, observable)) {
                continue;
              }
            }
          }
          if (isElement) {
            if (options.preventDefault) {
              e.preventDefault();
            }
            if (options.stopPropagation) {
              e.stopPropagation();
            }
            if (options.stopEvent) {
              e.stopEvent();
            }
          }
          args[len] = options;
          if (options.args) {
            firingArgs = options.args.concat(args);
          }
        }
        fireInfo = me.getFireInfo(listener);
        fireFn = fireInfo.fn;
        fireScope = fireInfo.scope;
        fireInfo.fn = fireInfo.scope = null;
        if (fireScope && fireScope.destroyed) {
          me.removeListener(fireFn, fireScope, i);
          fireFn = null;
          if (fireScope.$className !== 'Ext.container.Monitor') {
            (Ext.raiseOnDestroyed ? Ext.raise : Ext.log.warn)({msg:'Attempting to fire "' + me.name + '" event on destroyed ' + (fireScope.$className || 'object') + ' instance with id: ' + (fireScope.id || 'unknown'), instance:fireScope});
          }
        }
        if (fireFn && fireFn.apply(fireScope, firingArgs) === false) {
          Ext.EventObject = null;
          return me.firing = false;
        }
        if (options) {
          args.length--;
        }
        if (chained) {
          e = args[0] = chained;
          chained = null;
        }
        Ext.EventObject = null;
      }
    }
    me.firing = false;
    return true;
  }, getFireInfo:function(listener, fromWrapped) {
    var observable = this.observable, fireFn = listener.fireFn, scope = listener.scope, namedScope = listener.namedScope, fn, origin;
    if (!fromWrapped && listener.wrapped) {
      fireArgs.fn = fireFn;
      return fireArgs;
    }
    fn = fromWrapped ? listener.fn : fireFn;
    var name = fn;
    if (listener.lateBound) {
      origin = listener.caller || observable;
      if (namedScope && namedScope.isUp) {
        scope = Ext.lookUpFn(origin, fn);
      } else {
        if (!scope || namedScope) {
          scope = origin.resolveListenerScope(listener.defaultScope);
        }
      }
      if (!scope) {
        Ext.raise('Unable to dynamically resolve scope for "' + listener.ev.name + '" listener on ' + this.observable.id);
      }
      if (!Ext.isFunction(scope[fn])) {
        Ext.raise('No method named "' + fn + '" on ' + (scope.$className || 'scope object.'));
      }
      fn = scope[fn];
    } else {
      if (namedScope && namedScope.isController) {
        scope = (listener.caller || observable).resolveListenerScope(listener.defaultScope);
        if (!scope) {
          Ext.raise('Unable to dynamically resolve scope for "' + listener.ev.name + '" listener on ' + this.observable.id);
        }
      } else {
        if (!scope || namedScope) {
          scope = observable;
        }
      }
    }
    fireArgs.fn = fn;
    fireArgs.scope = scope;
    if (!fn) {
      Ext.raise('Unable to dynamically resolve method "' + name + '" on ' + this.observable.$className);
    }
    return fireArgs;
  }, createAnimFrame:function(handler, listener, o, scope, wrapped) {
    var fireInfo;
    if (!wrapped) {
      fireInfo = listener.ev.getFireInfo(listener, true);
      handler = fireInfo.fn;
      scope = fireInfo.scope;
      fireInfo.fn = fireInfo.scope = null;
    }
    return Ext.Function.createAnimationFrame(handler, scope, o.args);
  }, createTargeted:function(handler, listener, o, scope, wrapped) {
    return function() {
      var fireInfo;
      if (o.target === arguments[0]) {
        if (!wrapped) {
          fireInfo = listener.ev.getFireInfo(listener, true);
          handler = fireInfo.fn;
          scope = fireInfo.scope;
          fireInfo.fn = fireInfo.scope = null;
        }
        return handler.apply(scope, arguments);
      }
    };
  }, createBuffered:function(handler, listener, o, scope, wrapped) {
    listener.task = new Ext.util.DelayedTask;
    return function() {
      var fireInfo;
      if (listener.task) {
        if (Ext._unitTesting) {
          o.$delayedTask = listener.task;
        }
        if (!wrapped) {
          fireInfo = listener.ev.getFireInfo(listener, true);
          handler = fireInfo.fn;
          scope = fireInfo.scope;
          fireInfo.fn = fireInfo.scope = null;
        }
        listener.task.delay(o.buffer, handler, scope, toArray(arguments));
      }
    };
  }, createDelayed:function(handler, listener, o, scope, wrapped) {
    return function() {
      var task = new Ext.util.DelayedTask, fireInfo;
      if (!wrapped) {
        fireInfo = listener.ev.getFireInfo(listener, true);
        handler = fireInfo.fn;
        scope = fireInfo.scope;
        fireInfo.fn = fireInfo.scope = null;
      }
      if (!listener.tasks) {
        listener.tasks = [];
      }
      listener.tasks.push(task);
      if (Ext._unitTesting) {
        o.$delayedTask = task;
      }
      task.delay(o.delay || 10, handler, scope, toArray(arguments));
    };
  }, createSingle:function(handler, listener, o, scope, wrapped) {
    return function() {
      var event = listener.ev, observable = event.observable, fn = listener.fn, fireInfo;
      if (observable) {
        if (!observable.destroyed) {
          observable.removeListener(event.name, fn, scope);
        }
      } else {
        event.removeListener(fn, scope);
      }
      if (!wrapped) {
        fireInfo = event.getFireInfo(listener, true);
        handler = fireInfo.fn;
        scope = fireInfo.scope;
        fireInfo.fn = fireInfo.scope = null;
      }
      return handler.apply(scope, arguments);
    };
  }};
});
Ext.define('Ext.mixin.Identifiable', function(Identifiable) {
  return {isIdentifiable:true, mixinId:'identifiable', getId:function() {
    var me = this, id = me.id, cfg;
    if (!(id || id === 0)) {
      cfg = me.initialConfig;
      if (cfg && cfg.id) {
        id = cfg.id;
      } else {
        id = me.generateAutoId();
        me.autoGenId = true;
      }
      me.setId(id);
    }
    me.getId = Identifiable._getId;
    return id;
  }, setId:function(id) {
    this.id = this.id = id;
  }, privates:{statics:{_idCleanRe:/\.|[^\w-]/g, uniqueIds:{}, _getId:function() {
    return this.id;
  }}, defaultIdPrefix:'ext-', defaultIdSeparator:'-', id:null, autoGenId:false, generateAutoId:function() {
    var me = this, prototype = me.self.prototype, sep = me.defaultIdSeparator, uniqueIds = Identifiable.uniqueIds, cleanRe, defaultIdPrefix, prefix, xtype;
    if (!prototype.hasOwnProperty('identifiablePrefix')) {
      cleanRe = Identifiable._idCleanRe;
      defaultIdPrefix = me.defaultIdPrefix;
      xtype = me.xtype;
      if (xtype) {
        prefix = defaultIdPrefix + xtype.replace(cleanRe, sep) + sep;
      } else {
        if (!(prefix = prototype.$className)) {
          prefix = defaultIdPrefix + 'anonymous' + sep;
        } else {
          prefix = prefix.replace(cleanRe, sep).toLowerCase() + sep;
        }
      }
      prototype.identifiablePrefix = prefix;
    }
    prefix = me.identifiablePrefix;
    if (!uniqueIds.hasOwnProperty(prefix)) {
      uniqueIds[prefix] = 0;
    }
    return prefix + ++uniqueIds[prefix];
  }}};
});
Ext.define('Ext.mixin.Observable', function(Observable) {
  var emptyFn = Ext.emptyFn, emptyArray = [], arrayProto = Array.prototype, arraySlice = arrayProto.slice, ListenerRemover = function(observable) {
    if (observable instanceof ListenerRemover) {
      return observable;
    }
    this.observable = observable;
    if (arguments[1].isObservable) {
      this.managedListeners = true;
    }
    this.args = arraySlice.call(arguments, 1);
  }, protectedProps = ['events', 'hasListeners', 'managedListeners', 'eventedBeforeEventNames'];
  ListenerRemover.prototype.destroy = function() {
    var me = this, args = me.args, observable = me.observable, elementName = args[0].element || args[3] && args[3].element;
    if (elementName) {
      if (Ext.Array.indexOf(observable.referenceList, elementName) === -1) {
        Ext.Logger.error('Destroying event listener with an invalid element reference ' + "of '" + elementName + "' for this component. Available values are: '" + observable.referenceList.join("', '") + "'", observable);
      }
      observable = observable[elementName];
    }
    if (!observable.destroyed) {
      observable[me.managedListeners ? 'mun' : 'un'].apply(observable, me.args);
    }
    me.destroy = Ext.emptyFn;
  };
  return {extend:Ext.Mixin, mixinConfig:{id:'observable', after:{destroy:'destroyObservable'}}, mixins:[Ext.mixin.Identifiable], statics:{releaseCapture:function(o) {
    o.fireEventArgs = this.prototype.fireEventArgs;
  }, capture:function(o, fn, scope) {
    var newFn = function(eventName, args) {
      return fn.apply(scope, [eventName].concat(args));
    };
    this.captureArgs(o, newFn, scope);
  }, captureArgs:function(o, fn, scope) {
    o.fireEventArgs = Ext.Function.createInterceptor(o.fireEventArgs, fn, scope);
  }, observe:function(cls, listeners) {
    if (cls) {
      if (!cls.isObservable) {
        Ext.applyIf(cls, new this);
        this.captureArgs(cls.prototype, cls.fireEventArgs, cls);
      }
      if (Ext.isObject(listeners)) {
        cls.on(listeners);
      }
    }
    return cls;
  }, prepareClass:function(T, mixin, data) {
    var listeners = T.listeners = [], target = data || T.prototype, targetListeners = target.listeners, superListeners = mixin ? mixin.listeners : T.superclass.self.listeners, scope, namedScope, i, len;
    if (superListeners) {
      listeners.push(superListeners);
    }
    if (targetListeners) {
      scope = targetListeners.scope;
      if (!scope) {
        targetListeners.scope = 'self';
      } else {
        namedScope = Ext._namedScopes[scope];
        if (namedScope && namedScope.isController) {
          targetListeners.scope = 'self.controller';
        }
      }
      listeners.push(targetListeners);
      target.listeners = null;
    }
    if (!T.HasListeners) {
      var HasListeners = function() {
      }, SuperHL = T.superclass.HasListeners || mixin && mixin.HasListeners || Observable.HasListeners;
      T.prototype.HasListeners = T.HasListeners = HasListeners;
      HasListeners.prototype = T.hasListeners = new SuperHL;
    }
    scope = T.prototype.$noClearOnDestroy || {};
    for (i = 0, len = protectedProps.length; i < len; i++) {
      scope[protectedProps[i]] = true;
    }
    T.prototype.$noClearOnDestroy = scope;
  }}, isObservable:true, $vetoClearingPrototypeOnDestroy:true, eventsSuspended:0, constructor:function(config) {
    var me = this, self = me.self, declaredListeners, listeners, bubbleEvents, len, i;
    if (me.$observableInitialized) {
      return;
    }
    me.$observableInitialized = true;
    me.hasListeners = me.hasListeners = new me.HasListeners;
    me.eventedBeforeEventNames = {};
    me.events = me.events || {};
    declaredListeners = self.listeners;
    if (declaredListeners && !me._addDeclaredListeners(declaredListeners)) {
      self.listeners = null;
    }
    listeners = config && config.listeners || me.listeners;
    if (listeners) {
      if (listeners instanceof Array) {
        for (i = 0, len = listeners.length; i < len; ++i) {
          me.addListener(listeners[i]);
        }
      } else {
        me.addListener(listeners);
      }
    }
    bubbleEvents = config && config.bubbleEvents || me.bubbleEvents;
    if (bubbleEvents) {
      me.enableBubble(bubbleEvents);
    }
    if (me.$applyConfigs) {
      if (config) {
        Ext.apply(me, config);
      }
    } else {
      me.initConfig(config);
    }
    if (listeners) {
      me.listeners = null;
    }
  }, onClassExtended:function(T, data) {
    if (!T.HasListeners) {
      Observable.prepareClass(T, T.prototype.$observableMixedIn ? undefined : data);
    }
  }, $eventOptions:{scope:1, delay:1, buffer:1, onFrame:1, single:1, args:1, destroyable:1, priority:1, order:1}, $orderToPriority:{before:100, current:0, after:-100}, _addDeclaredListeners:function(listeners) {
    var me = this;
    if (listeners instanceof Array) {
      Ext.each(listeners, me._addDeclaredListeners, me);
    } else {
      me._addedDeclaredListeners = true;
      me.addListener(listeners);
    }
    return me._addedDeclaredListeners;
  }, addManagedListener:function(item, ename, fn, scope, options, noDestroy) {
    var me = this, config, passedOptions;
    me.managedListeners = me.managedListeners || [];
    if (typeof ename !== 'string') {
      passedOptions = arguments.length > 4 ? options : ename;
      options = ename;
      for (ename in options) {
        if (options.hasOwnProperty(ename)) {
          config = options[ename];
          if (!item.$eventOptions[ename]) {
            me.addManagedListener(item, ename, config.fn || config, config.scope || options.scope || scope, config.fn ? config : passedOptions, true);
          }
        }
      }
      if (options && options.destroyable) {
        return new ListenerRemover(me, item, options);
      }
    } else {
      if (fn !== emptyFn) {
        item.doAddListener(ename, fn, scope, options, null, me, me);
        if (!noDestroy && options && options.destroyable) {
          return new ListenerRemover(me, item, ename, fn, scope);
        }
      }
    }
  }, removeManagedListener:function(item, ename, fn, scope) {
    var me = this, options, config, managedListeners, length, i;
    if (item.$observableDestroyed) {
      return;
    }
    if (typeof ename !== 'string') {
      options = ename;
      for (ename in options) {
        if (options.hasOwnProperty(ename)) {
          config = options[ename];
          if (!item.$eventOptions[ename]) {
            me.removeManagedListener(item, ename, config.fn || config, config.scope || options.scope || scope);
          }
        }
      }
    } else {
      managedListeners = me.managedListeners ? me.managedListeners.slice() : [];
      ename = Ext.canonicalEventName(ename);
      for (i = 0, length = managedListeners.length; i < length; i++) {
        me.removeManagedListenerItem(false, managedListeners[i], item, ename, fn, scope);
      }
    }
  }, fireEvent:function(eventName) {
    return this.fireEventArgs(eventName, arraySlice.call(arguments, 1));
  }, resolveListenerScope:function(defaultScope) {
    var namedScope = Ext._namedScopes[defaultScope];
    if (namedScope) {
      if (namedScope.isController) {
        Ext.raise('scope: "controller" can only be specified on classes ' + 'that derive from Ext.Component or Ext.Widget');
      }
      if (namedScope.isSelf || namedScope.isThis) {
        defaultScope = null;
      }
    }
    return defaultScope || this;
  }, fireEventArgs:function(eventName, args) {
    var me = this, events = me.events, ret = true, event;
    eventName = Ext.canonicalEventName(eventName);
    event = events && events[eventName];
    if (me.hasListeners[eventName]) {
      ret = me.doFireEvent(eventName, args || emptyArray, event ? event.bubble : false);
    }
    return ret;
  }, fireAction:function(eventName, args, fn, scope, options, order) {
    if (typeof fn === 'string' && !scope) {
      fn = this[fn];
    }
    options = options ? Ext.Object.chain(options) : {};
    options.single = true;
    options.priority = order === 'after' ? -99.5 : 99.5;
    this.doAddListener(eventName, fn, scope, options);
    this.fireEventArgs(eventName, args);
  }, $eventedController:{_paused:1, pause:function() {
    ++this._paused;
  }, resume:function() {
    var me = this, fn = me.fn, scope = me.scope, fnArgs = me.fnArgs, args, ret;
    if (!--me._paused) {
      if (fn) {
        args = Ext.Array.slice(fnArgs || me.args);
        if (fnArgs === false) {
          args.shift();
        }
        me.fn = null;
        args.push(me);
        if (Ext.isFunction(fn)) {
          ret = fn.apply(scope, args);
        } else {
          if (scope && Ext.isString(fn) && Ext.isFunction(scope[fn])) {
            ret = scope[fn].apply(scope, args);
          }
        }
        if (ret === false) {
          return false;
        }
      }
      if (!me._paused) {
        return me.owner.fireEventArgs(me.eventName, me.args);
      }
    }
  }}, fireEventedAction:function(eventName, args, fn, scope, fnArgs) {
    var me = this, eventedBeforeEventNames = me.eventedBeforeEventNames, beforeEventName = eventedBeforeEventNames[eventName] || (eventedBeforeEventNames[eventName] = 'before' + eventName), controller = Ext.apply({owner:me, eventName:eventName, fn:fn, scope:scope, fnArgs:fnArgs, args:args}, me.$eventedController), value;
    args.push(controller);
    value = me.fireEventArgs(beforeEventName, args);
    args.pop();
    if (value === false) {
      return false;
    }
    return controller.resume();
  }, doFireEvent:function(eventName, args, bubbles) {
    var target = this, queue, event, ret = true;
    do {
      if (target.eventsSuspended) {
        if (queue = target.eventQueue) {
          queue.push([eventName, args]);
        }
        return ret;
      } else {
        event = target.events && target.events[eventName];
        if (event && event !== true) {
          if ((ret = event.fire.apply(event, args)) === false) {
            break;
          }
        }
      }
    } while (bubbles && (target = target.getBubbleParent()));
    return ret;
  }, getBubbleParent:function() {
    var me = this, parent = me.getBubbleTarget && me.getBubbleTarget();
    if (parent && parent.isObservable) {
      return parent;
    }
    return null;
  }, addListener:function(eventName, fn, scope, options, order, caller) {
    var me = this, namedScopes = Ext._namedScopes, config, namedScope, isClassListener, innerScope, eventOptions;
    if (typeof eventName !== 'string') {
      options = eventName;
      scope = options.scope;
      namedScope = scope && namedScopes[scope];
      isClassListener = namedScope && namedScope.isSelf;
      eventOptions = (me.isComponent || me.isWidget) && options.element ? me.$elementEventOptions : me.$eventOptions;
      for (eventName in options) {
        config = options[eventName];
        if (!eventOptions[eventName]) {
          innerScope = config.scope;
          if (innerScope && isClassListener) {
            namedScope = namedScopes[innerScope];
            if (namedScope && namedScope.isController) {
              innerScope = 'self.controller';
            }
          }
          me.doAddListener(eventName, config.fn || config, innerScope || scope, config.fn ? config : options, order, caller);
        }
      }
      if (options && options.destroyable) {
        return new ListenerRemover(me, options);
      }
    } else {
      me.doAddListener(eventName, fn, scope, options, order, caller);
      if (options && options.destroyable) {
        return new ListenerRemover(me, eventName, fn, scope, options);
      }
    }
    return me;
  }, removeListener:function(eventName, fn, scope, eventOptions) {
    var me = this, config, options;
    if (typeof eventName !== 'string') {
      options = eventName;
      eventOptions = eventOptions || me.$eventOptions;
      for (eventName in options) {
        if (options.hasOwnProperty(eventName)) {
          config = options[eventName];
          if (!me.$eventOptions[eventName]) {
            me.doRemoveListener(eventName, config.fn || config, config.scope || options.scope);
          }
        }
      }
    } else {
      me.doRemoveListener(eventName, fn, scope);
    }
    return me;
  }, onBefore:function(eventName, fn, scope, options) {
    return this.addListener(eventName, fn, scope, options, 'before');
  }, onAfter:function(eventName, fn, scope, options) {
    return this.addListener(eventName, fn, scope, options, 'after');
  }, unBefore:function(eventName, fn, scope, options) {
    return this.removeListener(eventName, fn, scope, options, 'before');
  }, unAfter:function(eventName, fn, scope, options) {
    return this.removeListener(eventName, fn, scope, options, 'after');
  }, addBeforeListener:function() {
    return this.onBefore.apply(this, arguments);
  }, addAfterListener:function() {
    return this.onAfter.apply(this, arguments);
  }, removeBeforeListener:function() {
    return this.unBefore.apply(this, arguments);
  }, removeAfterListener:function() {
    return this.unAfter.apply(this, arguments);
  }, clearListeners:function() {
    var me = this, events = me.events, hasListeners = me.hasListeners, event, key;
    if (events) {
      for (key in events) {
        if (events.hasOwnProperty(key)) {
          event = events[key];
          if (event.isEvent) {
            delete hasListeners[key];
            event.clearListeners();
          }
        }
      }
      me.events = null;
    }
    me.clearManagedListeners();
  }, purgeListeners:function() {
    if (Ext.global.console) {
      Ext.global.console.warn('Observable: purgeListeners has been deprecated. ' + 'Please use clearListeners.');
    }
    return this.clearListeners.apply(this, arguments);
  }, clearManagedListeners:function() {
    var me = this, managedListeners = me.managedListeners, i, len;
    if (managedListeners) {
      me.managedListeners = null;
      for (i = 0, len = managedListeners.length; i < len; i++) {
        me.removeManagedListenerItem(true, managedListeners[i]);
      }
      managedListeners.length = 0;
    }
    me.managedListeners = managedListeners;
  }, removeManagedListenerItem:function(isClear, managedListener, item, ename, fn, scope) {
    if (isClear || managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope)) {
      if (!managedListener.item.destroyed) {
        managedListener.item.doRemoveListener(managedListener.ename, managedListener.fn, managedListener.scope, managedListener.options);
      }
      if (!isClear) {
        Ext.Array.remove(this.managedListeners, managedListener);
      }
    }
  }, purgeManagedListeners:function() {
    if (Ext.global.console) {
      Ext.global.console.warn('Observable: purgeManagedListeners has been deprecated. ' + 'Please use clearManagedListeners.');
    }
    return this.clearManagedListeners.apply(this, arguments);
  }, hasListener:function(eventName) {
    eventName = Ext.canonicalEventName(eventName);
    return !!this.hasListeners[eventName];
  }, isSuspended:function(event) {
    var suspended = this.eventsSuspended > 0, events = this.events;
    if (!suspended && event && events) {
      event = events[event];
      if (event && event.isEvent) {
        return event.isSuspended();
      }
    }
    return suspended;
  }, suspendEvents:function(queueSuspended) {
    ++this.eventsSuspended;
    if (queueSuspended && !this.eventQueue) {
      this.eventQueue = [];
    }
  }, suspendEvent:function() {
    var me = this, events = me.events, len = arguments.length, i, event, ename;
    for (i = 0; i < len; i++) {
      ename = arguments[i];
      ename = Ext.canonicalEventName(ename);
      event = events[ename];
      if (!event || !event.isEvent) {
        event = me._initEvent(ename);
      }
      event.suspend();
    }
  }, resumeEvent:function() {
    var events = this.events || 0, len = events && arguments.length, i, event, ename;
    for (i = 0; i < len; i++) {
      ename = Ext.canonicalEventName(arguments[i]);
      event = events[ename];
      if (event && event.resume) {
        event.resume();
      }
    }
  }, resumeEvents:function(discardQueue) {
    var me = this, queued = me.eventQueue, qLen, q;
    if (me.eventsSuspended && !--me.eventsSuspended) {
      delete me.eventQueue;
      if (!discardQueue && queued) {
        qLen = queued.length;
        for (q = 0; q < qLen; q++) {
          me.fireEventArgs.apply(me, queued[q]);
        }
      }
    }
  }, relayEvents:function(origin, events, prefix) {
    var me = this, len = events.length, i = 0, oldName, newName, relayers = {};
    if (Ext.isObject(events)) {
      for (i in events) {
        newName = events[i];
        relayers[i] = me.createRelayer(newName);
      }
    } else {
      for (; i < len; i++) {
        oldName = events[i];
        relayers[oldName] = me.createRelayer(prefix ? prefix + oldName : oldName);
      }
    }
    me.mon(origin, relayers, null, null, undefined);
    return new ListenerRemover(me, origin, relayers);
  }, createRelayer:function(newName, beginEnd) {
    var me = this;
    return function() {
      return me.fireEventArgs.call(me, newName, beginEnd ? arraySlice.apply(arguments, beginEnd) : arguments);
    };
  }, enableBubble:function(eventNames) {
    if (eventNames) {
      var me = this, names = typeof eventNames === 'string' ? arguments : eventNames, events = me.events, length = events && names.length, ename, event, i;
      for (i = 0; i < length; ++i) {
        ename = names[i];
        ename = Ext.canonicalEventName(ename);
        event = events[ename];
        if (!event || !event.isEvent) {
          event = me._initEvent(ename);
        }
        me.hasListeners._incr_(ename);
        event.bubble = true;
      }
    }
  }, destroy:function() {
    this.clearListeners();
    this.callParent();
    this.destroyObservable(true);
  }, destroyObservable:function(skipClearListeners) {
    var me = this, clearPropertiesOnDestroy = me.clearPropertiesOnDestroy;
    if (me.$observableDestroyed) {
      return;
    }
    if (!skipClearListeners) {
      me.clearListeners();
    }
    if (me.destroyed) {
      if (clearPropertiesOnDestroy) {
        if (clearPropertiesOnDestroy === true && !me.$nulled) {
          me.$reap();
        }
        if (!me.clearPrototypeOnDestroy) {
          me.fireEvent = me.fireEventArgs = me.fireAction = me.fireEventedAction = Ext.emptyFn;
        }
        me.events = me.managedListeners = me.eventedBeforeEventNames = null;
        me.$observableDestroyed = true;
      }
      if (me.clearPrototypeOnDestroy && Object.setPrototypeOf && !me.$alreadyNulled) {
        Object.setPrototypeOf(me, null);
        me.$alreadyNulled = true;
      }
    }
  }, privates:{doAddListener:function(ename, fn, scope, options, order, caller, manager) {
    var me = this, ret = false, event, priority;
    order = order || options && options.order;
    if (order) {
      priority = options && options.priority;
      if (!priority) {
        options = options ? Ext.Object.chain(options) : {};
        options.priority = me.$orderToPriority[order];
      }
    }
    ename = Ext.canonicalEventName(ename);
    if (!fn) {
      Ext.raise("Cannot add '" + ename + "' listener to " + me.$className + ' instance.  No function specified.');
    }
    event = (me.events || (me.events = {}))[ename];
    if (!event || !event.isEvent) {
      event = me._initEvent(ename);
    }
    if (fn !== emptyFn) {
      if (!manager && (scope && scope.isObservable && scope !== me)) {
        manager = scope;
      }
      if (event.addListener(fn, scope, options, caller, manager)) {
        me.hasListeners._incr_(ename);
        ret = true;
      }
    }
    return ret;
  }, doRemoveListener:function(ename, fn, scope) {
    var me = this, ret = false, events = me.events, event;
    ename = Ext.canonicalEventName(ename);
    event = events && events[ename];
    if (!fn) {
      Ext.raise("Cannot remove '" + ename + "' listener to " + me.$className + ' instance.  No function specified.');
    }
    if (event && event.isEvent) {
      if (event.removeListener(fn, scope)) {
        me.hasListeners._decr_(ename);
        ret = true;
      }
    }
    return ret;
  }, _initEvent:function(eventName) {
    return this.events[eventName] = new Ext.util.Event(this, eventName);
  }}, deprecated:{'5.0':{methods:{addEvents:null}}}};
}, function() {
  var Observable = this, proto = Observable.prototype, HasListeners = function() {
  }, prepareMixin = function(T) {
    var proto = T.prototype;
    if (!T.HasListeners) {
      proto.$observableMixedIn = 1;
      Observable.prepareClass(T, this);
      T.onExtended(function(U, data) {
        if (Ext.classSystemMonitor) {
          Ext.classSystemMonitor('extend mixin', arguments);
        }
        Observable.prepareClass(U, null, data);
      });
      if (proto.onClassMixedIn) {
        Ext.override(T, {onClassMixedIn:function(U) {
          prepareMixin.call(this, U);
          this.callParent(arguments);
        }});
      } else {
        proto.onClassMixedIn = function(U) {
          prepareMixin.call(this, U);
        };
      }
    }
    superOnClassMixedIn.call(this, T);
  }, superOnClassMixedIn = proto.onClassMixedIn;
  HasListeners.prototype = {_decr_:function(ev, count) {
    if (count == null) {
      count = 1;
    }
    if (!(this[ev] -= count)) {
      delete this[ev];
    }
  }, _incr_:function(ev) {
    if (this.hasOwnProperty(ev)) {
      ++this[ev];
    } else {
      this[ev] = 1;
    }
  }};
  proto.HasListeners = Observable.HasListeners = HasListeners;
  Observable.createAlias({on:'addListener', un:'removeListener', mon:'addManagedListener', mun:'removeManagedListener', setListeners:'addListener'});
  Observable.observeClass = Observable.observe;
  function getMethodEvent(method) {
    var event = (this.methodEvents = this.methodEvents || {})[method], returnValue, v, cancel, me = this, makeCall;
    if (!event) {
      me.methodEvents[method] = event = {};
      event.originalFn = me[method];
      event.methodName = method;
      event.before = [];
      event.after = [];
      makeCall = function(fn, scope, args) {
        scope = scope || me;
        if (typeof fn === 'string') {
          fn = scope[fn];
        }
        if ((v = fn.apply(scope, args)) !== undefined) {
          if (typeof v === 'object') {
            if (v.returnValue !== undefined) {
              returnValue = v.returnValue;
            } else {
              returnValue = v;
            }
            cancel = !!v.cancel;
          } else {
            if (v === false) {
              cancel = true;
            } else {
              returnValue = v;
            }
          }
        }
      };
      me[method] = function() {
        var args = Array.prototype.slice.call(arguments, 0), argsLen = args.length, b, i, len;
        returnValue = v = undefined;
        cancel = false;
        for (i = 0, len = event.before.length; i < len; i++) {
          b = event.before[i];
          if (b.extraArgs) {
            args.push.apply(args, b.extraArgs);
          }
          makeCall(b.fn, b.scope, args);
          args.length = argsLen;
          if (cancel || b.preventDefault) {
            return returnValue;
          }
        }
        if ((v = event.originalFn.apply(me, args)) !== undefined) {
          returnValue = v;
        }
        for (i = 0, len = event.after.length; i < len; i++) {
          b = event.after[i];
          if (b.extraArgs) {
            args.push.apply(args, b.extraArgs);
          }
          makeCall(b.fn, b.scope, args);
          args.length = argsLen;
          if (cancel || b.preventDefault) {
            return returnValue;
          }
        }
        return returnValue;
      };
    }
    return event;
  }
  Ext.apply(proto, {onClassMixedIn:prepareMixin, beforeMethod:function(method, fn, scope, preventDefault, extraArgs) {
    getMethodEvent.call(this, method).before.push({fn:fn, scope:scope, extraArgs:extraArgs, preventDefault:preventDefault});
  }, afterMethod:function(method, fn, scope, preventDefault, extraArgs) {
    getMethodEvent.call(this, method).after.push({fn:fn, scope:scope, extraArgs:extraArgs, preventDefault:preventDefault});
  }, removeMethodListener:function(method, fn, scope) {
    var e = getMethodEvent.call(this, method), i, len;
    for (i = 0, len = e.before.length; i < len; i++) {
      if (e.before[i].fn == fn && e.before[i].scope == scope) {
        Ext.Array.erase(e.before, i, 1);
        return;
      }
    }
    for (i = 0, len = e.after.length; i < len; i++) {
      if (e.after[i].fn == fn && e.after[i].scope == scope) {
        Ext.Array.erase(e.after, i, 1);
        return;
      }
    }
  }, toggleEventLogging:function(toggle) {
    Ext.util.Observable[toggle ? 'capture' : 'releaseCapture'](this, function(en) {
      if (Ext.isDefined(Ext.global.console)) {
        Ext.global.console.log(en, arguments);
      }
    });
  }});
});
Ext.define('Ext.util.HashMap', {mixins:[Ext.mixin.Observable], generation:0, config:{keyFn:null}, constructor:function(config) {
  var me = this, fn;
  me.mixins.observable.constructor.call(me, config);
  me.clear(true);
  fn = me.getKeyFn();
  if (fn) {
    me.getKey = fn;
  }
}, getCount:function() {
  return this.length;
}, getData:function(key, value) {
  if (value === undefined) {
    value = key;
    key = this.getKey(value);
  }
  return [key, value];
}, getKey:function(o) {
  return o.id;
}, add:function(key, value) {
  var me = this;
  if (arguments.length === 1) {
    value = key;
    key = me.getKey(value);
  }
  if (me.containsKey(key)) {
    return me.replace(key, value);
  }
  me.map[key] = value;
  ++me.length;
  me.generation++;
  if (me.hasListeners.add) {
    me.fireEvent('add', me, key, value);
  }
  return value;
}, replace:function(key, value) {
  var me = this, map = me.map, old;
  if (arguments.length === 1) {
    value = key;
    key = me.getKey(value);
  }
  if (!me.containsKey(key)) {
    me.add(key, value);
  }
  old = map[key];
  map[key] = value;
  me.generation++;
  if (me.hasListeners.replace) {
    me.fireEvent('replace', me, key, value, old);
  }
  return value;
}, remove:function(o) {
  var key = this.findKey(o);
  if (key !== undefined) {
    return this.removeAtKey(key);
  }
  return false;
}, removeAtKey:function(key) {
  var me = this, value;
  if (me.containsKey(key)) {
    value = me.map[key];
    delete me.map[key];
    --me.length;
    me.generation++;
    if (me.hasListeners.remove) {
      me.fireEvent('remove', me, key, value);
    }
    return true;
  }
  return false;
}, get:function(key) {
  var map = this.map;
  return map.hasOwnProperty(key) ? map[key] : undefined;
}, clear:function(initial) {
  var me = this;
  if (initial || me.generation) {
    me.map = {};
    me.length = 0;
    me.generation = initial ? 0 : me.generation + 1;
  }
  if (initial !== true && me.hasListeners.clear) {
    me.fireEvent('clear', me);
  }
  return me;
}, containsKey:function(key) {
  var map = this.map;
  return map.hasOwnProperty(key) && map[key] !== undefined;
}, contains:function(value) {
  return this.containsKey(this.findKey(value));
}, getKeys:function() {
  return this.getArray(true);
}, getValues:function() {
  return this.getArray(false);
}, getArray:function(isKey) {
  var arr = [], key, map = this.map;
  for (key in map) {
    if (map.hasOwnProperty(key)) {
      arr.push(isKey ? key : map[key]);
    }
  }
  return arr;
}, each:function(fn, scope) {
  var items = Ext.apply({}, this.map), key, length = this.length;
  scope = scope || this;
  for (key in items) {
    if (items.hasOwnProperty(key)) {
      if (fn.call(scope, key, items[key], length) === false) {
        break;
      }
    }
  }
  return this;
}, clone:function() {
  var hash = new this.self(this.initialConfig), map = this.map, key;
  hash.suspendEvents();
  for (key in map) {
    if (map.hasOwnProperty(key)) {
      hash.add(key, map[key]);
    }
  }
  hash.resumeEvents();
  return hash;
}, findKey:function(value) {
  var key, map = this.map;
  for (key in map) {
    if (map.hasOwnProperty(key) && map[key] === value) {
      return key;
    }
  }
  return undefined;
}}, function(HashMap) {
  var prototype = HashMap.prototype;
  prototype.removeByKey = prototype.removeAtKey;
});
Ext.define('Ext.promise.Consequence', function(Consequence) {
  return {promise:null, deferred:null, onFulfilled:null, onRejected:null, onProgress:null, constructor:function(onFulfilled, onRejected, onProgress) {
    var me = this;
    me.onFulfilled = onFulfilled;
    me.onRejected = onRejected;
    me.onProgress = onProgress;
    me.deferred = new Ext.promise.Deferred;
    me.promise = me.deferred.promise;
  }, trigger:function(action, value) {
    var me = this, deferred = me.deferred;
    switch(action) {
      case 'fulfill':
        me.propagate(value, me.onFulfilled, deferred, deferred.resolve);
        break;
      case 'reject':
        me.propagate(value, me.onRejected, deferred, deferred.reject);
        break;
    }
  }, update:function(progress) {
    if (Ext.isFunction(this.onProgress)) {
      progress = this.onProgress(progress);
    }
    this.deferred.update(progress);
  }, propagate:function(value, callback, deferred, deferredMethod) {
    if (Ext.isFunction(callback)) {
      this.schedule(function() {
        try {
          deferred.resolve(callback(value));
        } catch (e$38) {
          deferred.reject(e$38);
        }
      });
    } else {
      deferredMethod.call(this.deferred, value);
    }
  }, schedule:function(callback) {
    var n = Consequence.queueSize++;
    Consequence.queue[n] = callback;
    if (!n) {
      Ext.asap(Consequence.dispatch);
    }
  }, statics:{queue:new Array(10000), queueSize:0, dispatch:function() {
    var queue = Consequence.queue, fn, i;
    for (i = 0; i < Consequence.queueSize; ++i) {
      fn = queue[i];
      queue[i] = null;
      fn();
    }
    Consequence.queueSize = 0;
  }}};
}, function(Consequence) {
  Consequence.dispatch.$skipTimerCheck = true;
});
Ext.define('Ext.promise.Deferred', {promise:null, consequences:[], completed:false, completionAction:null, completionValue:null, constructor:function() {
  var me = this;
  me.promise = new Ext.promise.Promise(me);
  me.consequences = [];
  me.completed = false;
  me.completionAction = null;
  me.completionValue = null;
}, then:function(onFulfilled, onRejected, onProgress) {
  var me = this, consequence = new Ext.promise.Consequence(onFulfilled, onRejected, onProgress);
  if (me.completed) {
    consequence.trigger(me.completionAction, me.completionValue);
  } else {
    me.consequences.push(consequence);
  }
  return consequence.promise;
}, resolve:function(value) {
  var me = this, isHandled, thenFn;
  if (me.completed) {
    return;
  }
  try {
    if (value === me.promise) {
      throw new TypeError('A Promise cannot be resolved with itself.');
    }
    if (value != null && (typeof value === 'object' || Ext.isFunction(value)) && Ext.isFunction(thenFn = value.then)) {
      isHandled = false;
      try {
        thenFn.call(value, function(value) {
          if (!isHandled) {
            isHandled = true;
            me.resolve(value);
          }
        }, function(error) {
          if (!isHandled) {
            isHandled = true;
            me.reject(error);
          }
        });
      } catch (e1) {
        if (!isHandled) {
          me.reject(e1);
        }
      }
    } else {
      me.complete('fulfill', value);
    }
  } catch (e2) {
    me.reject(e2);
  }
}, reject:function(reason) {
  if (this.completed) {
    return;
  }
  this.complete('reject', reason);
}, update:function(progress) {
  var consequences = this.consequences, consequence, i, len;
  if (this.completed) {
    return;
  }
  for (i = 0, len = consequences.length; i < len; i++) {
    consequence = consequences[i];
    consequence.update(progress);
  }
}, complete:function(action, value) {
  var me = this, consequences = me.consequences, consequence, i, len;
  me.completionAction = action;
  me.completionValue = value;
  me.completed = true;
  for (i = 0, len = consequences.length; i < len; i++) {
    consequence = consequences[i];
    consequence.trigger(me.completionAction, me.completionValue);
  }
  me.consequences = null;
}});
Ext.define('Ext.promise.Promise', function(ExtPromise) {
  var Deferred;
  return {statics:{CancellationError:Ext.global.CancellationError || Error, _ready:function() {
    Deferred = Ext.promise.Deferred;
  }, all:function(promisesOrValues) {
    if (!(Ext.isArray(promisesOrValues) || ExtPromise.is(promisesOrValues))) {
      Ext.raise('Invalid parameter: expected an Array or Promise of an Array.');
    }
    return ExtPromise.when(promisesOrValues).then(function(promisesOrValues) {
      var deferred = new Deferred, remainingToResolve = promisesOrValues.length, results = new Array(remainingToResolve), index, promiseOrValue, resolve, i, len;
      if (!remainingToResolve) {
        deferred.resolve(results);
      } else {
        resolve = function(item, index) {
          return ExtPromise.when(item).then(function(value) {
            results[index] = value;
            if (!--remainingToResolve) {
              deferred.resolve(results);
            }
            return value;
          }, function(reason) {
            return deferred.reject(reason);
          });
        };
        for (index = i = 0, len = promisesOrValues.length; i < len; index = ++i) {
          promiseOrValue = promisesOrValues[index];
          if (index in promisesOrValues) {
            resolve(promiseOrValue, index);
          } else {
            remainingToResolve--;
          }
        }
      }
      return deferred.promise;
    });
  }, is:function(value) {
    return value != null && (typeof value === 'object' || Ext.isFunction(value)) && Ext.isFunction(value.then);
  }, race:function(promises) {
    var deferred = new Deferred, len = promises.length, i;
    if (!Ext.isArray(promises)) {
      Ext.raise('Invalid parameter: expected an Array.');
    }
    for (i = 0; i < len; ++i) {
      deferred.resolve(promises[i]);
    }
    return deferred.promise;
  }, rethrowError:function(error) {
    Ext.asap(function() {
      throw error;
    });
  }, when:function(value) {
    var deferred = new Deferred;
    deferred.resolve(value);
    return deferred.promise;
  }}, owner:null, constructor:function(owner) {
    this.owner = owner;
  }, then:function(onFulfilled, onRejected, onProgress, scope) {
    var ref;
    if (arguments.length === 1 && Ext.isObject(arguments[0])) {
      ref = arguments[0];
      onFulfilled = ref.success;
      onRejected = ref.failure;
      onProgress = ref.progress;
      scope = ref.scope;
    }
    if (scope) {
      if (onFulfilled) {
        onFulfilled = onFulfilled.bind(scope);
      }
      if (onRejected) {
        onRejected = onRejected.bind(scope);
      }
      if (onProgress) {
        onProgress = onProgress.bind(scope);
      }
    }
    return this.owner.then(onFulfilled, onRejected, onProgress);
  }, 'catch':function(onRejected, scope) {
    var ref;
    if (arguments.length === 1 && Ext.isObject(arguments[0])) {
      ref = arguments[0];
      onRejected = ref.fn;
      scope = ref.scope;
    }
    if (scope != null) {
      onRejected = onRejected.bind(scope);
    }
    return this.owner.then(null, onRejected);
  }, otherwise:function(onRejected, scope) {
    return this['catch'].apply(this, arguments);
  }, always:function(onCompleted, scope) {
    var ref;
    if (arguments.length === 1 && Ext.isObject(arguments[0])) {
      ref = arguments[0];
      onCompleted = ref.fn;
      scope = ref.scope;
    }
    if (scope != null) {
      onCompleted = onCompleted.bind(scope);
    }
    return this.owner.then(function(value) {
      try {
        onCompleted();
      } catch (e$39) {
        ExtPromise.rethrowError(e$39);
      }
      return value;
    }, function(reason) {
      try {
        onCompleted();
      } catch (e$40) {
        ExtPromise.rethrowError(e$40);
      }
      throw reason;
    });
  }, done:function() {
    this.owner.then(null, ExtPromise.rethrowError);
  }, cancel:function(reason) {
    if (reason == null) {
      reason = null;
    }
    this.owner.reject(new this.self.CancellationError(reason));
  }, log:function(identifier) {
    if (identifier == null) {
      identifier = '';
    }
    return this.owner.then(function(value) {
      Ext.log('' + (identifier || 'Promise') + ' resolved with value: ' + value);
      return value;
    }, function(reason) {
      Ext.log('' + (identifier || 'Promise') + ' rejected with reason: ' + reason);
      throw reason;
    });
  }};
}, function(ExtPromise) {
  ExtPromise._ready();
});
Ext.define('Ext.Promise', function() {
  var Polyfiller;
  return {statics:{_ready:function() {
    Polyfiller = Ext.promise.Promise;
  }, all:function() {
    return Polyfiller.all.apply(Polyfiller, arguments);
  }, race:function() {
    return Polyfiller.race.apply(Polyfiller, arguments);
  }, reject:function(reason) {
    var deferred = new Ext.promise.Deferred;
    deferred.reject(reason);
    return deferred.promise;
  }, resolve:function(value) {
    var deferred = new Ext.promise.Deferred;
    deferred.resolve(value);
    return deferred.promise;
  }}, constructor:function(action) {
    var deferred = new Ext.promise.Deferred;
    action(deferred.resolve.bind(deferred), deferred.reject.bind(deferred));
    return deferred.promise;
  }};
}, function(ExtPromise) {
  var P = Ext.global.Promise;
  if (P && P.resolve && !Ext.useExtPromises) {
    Ext.Promise = P;
  } else {
    ExtPromise._ready();
  }
});
Ext.define('Ext.Deferred', function(Deferred) {
  var ExtPromise, rejected, resolved, when;
  return {extend:Ext.promise.Deferred, statics:{_ready:function() {
    ExtPromise = Ext.promise.Promise;
    when = Ext.Promise.resolve;
  }, all:function() {
    return ExtPromise.all.apply(ExtPromise, arguments);
  }, any:function(promisesOrValues) {
    if (!(Ext.isArray(promisesOrValues) || ExtPromise.is(promisesOrValues))) {
      Ext.raise('Invalid parameter: expected an Array or Promise of an Array.');
    }
    return Deferred.some(promisesOrValues, 1).then(function(array) {
      return array[0];
    }, function(error) {
      if (error instanceof Error && error.message === 'Too few Promises were resolved.') {
        Ext.raise('No Promises were resolved.');
      } else {
        throw error;
      }
    });
  }, delay:function(promiseOrValue, milliseconds) {
    var deferred;
    if (arguments.length === 1) {
      milliseconds = promiseOrValue;
      promiseOrValue = undefined;
    }
    milliseconds = Math.max(milliseconds, 1);
    deferred = new Deferred;
    deferred.timeoutId = Ext.defer(function() {
      delete deferred.timeoutId;
      deferred.resolve(promiseOrValue);
    }, milliseconds);
    return deferred.promise;
  }, getCachedRejected:function() {
    if (!rejected) {
      rejected = Ext.Promise.reject();
    }
    return rejected;
  }, getCachedResolved:function() {
    if (!resolved) {
      resolved = Ext.Promise.resolve();
    }
    return resolved;
  }, map:function(promisesOrValues, mapFn) {
    if (!(Ext.isArray(promisesOrValues) || ExtPromise.is(promisesOrValues))) {
      Ext.raise('Invalid parameter: expected an Array or Promise of an Array.');
    }
    if (!Ext.isFunction(mapFn)) {
      Ext.raise('Invalid parameter: expected a function.');
    }
    return Deferred.resolved(promisesOrValues).then(function(promisesOrValues) {
      var deferred, index, promiseOrValue, remainingToResolve, resolve, results, i, len;
      remainingToResolve = promisesOrValues.length;
      results = new Array(promisesOrValues.length);
      deferred = new Deferred;
      if (!remainingToResolve) {
        deferred.resolve(results);
      } else {
        resolve = function(item, index) {
          return Deferred.resolved(item).then(function(value) {
            return mapFn(value, index, results);
          }).then(function(value) {
            results[index] = value;
            if (!--remainingToResolve) {
              deferred.resolve(results);
            }
            return value;
          }, function(reason) {
            return deferred.reject(reason);
          });
        };
        for (index = i = 0, len = promisesOrValues.length; i < len; index = ++i) {
          promiseOrValue = promisesOrValues[index];
          if (index in promisesOrValues) {
            resolve(promiseOrValue, index);
          } else {
            remainingToResolve--;
          }
        }
      }
      return deferred.promise;
    });
  }, memoize:function(fn, scope, hashFn) {
    var memoizedFn = Ext.Function.memoize(fn, scope, hashFn);
    return function() {
      return Deferred.all(Ext.Array.slice(arguments)).then(function(values) {
        return memoizedFn.apply(scope, values);
      });
    };
  }, parallel:function(fns, scope) {
    var args;
    if (scope == null) {
      scope = null;
    }
    args = Ext.Array.slice(arguments, 2);
    return Deferred.map(fns, function(fn) {
      if (!Ext.isFunction(fn)) {
        throw new Error('Invalid parameter: expected a function.');
      }
      return fn.apply(scope, args);
    });
  }, pipeline:function(fns, initialValue, scope) {
    if (scope == null) {
      scope = null;
    }
    return Deferred.reduce(fns, function(value, fn) {
      if (!Ext.isFunction(fn)) {
        throw new Error('Invalid parameter: expected a function.');
      }
      return fn.call(scope, value);
    }, initialValue);
  }, race:function() {
    return ExtPromise.race.apply(ExtPromise, arguments);
  }, reduce:function(values, reduceFn, initialValue) {
    var initialValueSpecified;
    if (!(Ext.isArray(values) || ExtPromise.is(values))) {
      Ext.raise('Invalid parameter: expected an Array or Promise of an Array.');
    }
    if (!Ext.isFunction(reduceFn)) {
      Ext.raise('Invalid parameter: expected a function.');
    }
    initialValueSpecified = arguments.length === 3;
    return Deferred.resolved(values).then(function(promisesOrValues) {
      var reduceArguments = [promisesOrValues, function(previousValueOrPromise, currentValueOrPromise, currentIndex) {
        return Deferred.resolved(previousValueOrPromise).then(function(previousValue) {
          return Deferred.resolved(currentValueOrPromise).then(function(currentValue) {
            return reduceFn(previousValue, currentValue, currentIndex, promisesOrValues);
          });
        });
      }];
      if (initialValueSpecified) {
        reduceArguments.push(initialValue);
      }
      return Ext.Array.reduce.apply(Ext.Array, reduceArguments);
    });
  }, rejected:function(reason) {
    var deferred = new Ext.Deferred;
    deferred.reject(reason);
    return deferred.promise;
  }, resolved:function(promiseOrValue) {
    var deferred = new Ext.Deferred;
    deferred.resolve(promiseOrValue);
    return deferred.promise;
  }, sequence:function(fns, scope) {
    var args;
    if (scope == null) {
      scope = null;
    }
    args = Ext.Array.slice(arguments, 2);
    return Deferred.reduce(fns, function(results, fn) {
      if (!Ext.isFunction(fn)) {
        throw new Error('Invalid parameter: expected a function.');
      }
      return Deferred.resolved(fn.apply(scope, args)).then(function(result) {
        results.push(result);
        return results;
      });
    }, []);
  }, some:function(promisesOrValues, howMany) {
    if (!(Ext.isArray(promisesOrValues) || ExtPromise.is(promisesOrValues))) {
      Ext.raise('Invalid parameter: expected an Array or Promise of an Array.');
    }
    if (!Ext.isNumeric(howMany) || howMany <= 0) {
      Ext.raise('Invalid parameter: expected a positive integer.');
    }
    return Deferred.resolved(promisesOrValues).then(function(promisesOrValues) {
      var deferred, index, onReject, onResolve, promiseOrValue, remainingToReject, remainingToResolve, values, i, len;
      values = [];
      remainingToResolve = howMany;
      remainingToReject = promisesOrValues.length - remainingToResolve + 1;
      deferred = new Deferred;
      if (promisesOrValues.length < howMany) {
        deferred.reject(new Error('Too few Promises were resolved.'));
      } else {
        onResolve = function(value) {
          if (remainingToResolve > 0) {
            values.push(value);
          }
          remainingToResolve--;
          if (remainingToResolve === 0) {
            deferred.resolve(values);
          }
          return value;
        };
        onReject = function(reason) {
          remainingToReject--;
          if (remainingToReject === 0) {
            deferred.reject(new Error('Too few Promises were resolved.'));
          }
          return reason;
        };
        for (index = i = 0, len = promisesOrValues.length; i < len; index = ++i) {
          promiseOrValue = promisesOrValues[index];
          if (index in promisesOrValues) {
            Deferred.resolved(promiseOrValue).then(onResolve, onReject);
          }
        }
      }
      return deferred.promise;
    });
  }, timeout:function(promiseOrValue, milliseconds) {
    var deferred = new Deferred, timeoutId;
    timeoutId = Ext.defer(function() {
      if (timeoutId) {
        deferred.reject(new Error('Promise timed out.'));
      }
    }, milliseconds);
    Deferred.resolved(promiseOrValue).then(function(value) {
      Ext.undefer(timeoutId);
      timeoutId = null;
      deferred.resolve(value);
    }, function(reason) {
      Ext.undefer(timeoutId);
      timeoutId = null;
      deferred.reject(reason);
    });
    return deferred.promise;
  }}};
}, function(Deferred) {
  Deferred._ready();
});
Ext.Factory = function(type) {
  var me = this;
  me.aliasPrefix = type + '.';
  me.cache = {};
  me.name = type.replace(me.fixNameRe, me.fixNameFn);
  me.type = type;
  me.creator = 'create' + Ext.String.capitalize(me.name);
};
Ext.Factory.prototype = {defaultProperty:'type', instanceProp:'isInstance', typeProperty:'type', create:function(config, defaultType) {
  var me = this, Manager = Ext.ClassManager, cache = me.cache, typeProperty = me.typeProperty, alias, className, klass, suffix;
  if (config) {
    if (config[me.instanceProp]) {
      return config;
    }
    if (typeof config === 'string') {
      suffix = config;
      config = {};
      config[me.defaultProperty] = suffix;
    }
    className = config.xclass;
    suffix = config[typeProperty];
  }
  if (defaultType && defaultType.constructor === Object) {
    config = Ext.apply({}, config, defaultType);
    defaultType = defaultType[typeProperty];
  }
  if (className) {
    if (!(klass = Manager.get(className))) {
      return Manager.instantiate(className, config);
    }
  } else {
    if (!(suffix = suffix || defaultType || me.defaultType)) {
      klass = me.defaultClass;
    }
    if (!suffix && !klass) {
      Ext.raise('No type specified for ' + me.type + '.create');
    }
    if (!klass && !(klass = cache[suffix])) {
      alias = me.aliasPrefix + suffix;
      className = Manager.getNameByAlias(alias);
      if (!(klass = className && Manager.get(className))) {
        return Manager.instantiateByAlias(alias, config);
      }
      cache[suffix] = klass;
    }
  }
  return klass.isInstance ? klass : new klass(config);
}, fixNameRe:/\.[a-z]/ig, fixNameFn:function(match) {
  return match.substring(1).toUpperCase();
}, clearCache:function() {
  this.cache = {};
  this.instanceCache = {};
}, hook:function(fn) {
  var me = this, original = me.create;
  me.create = function(config, defaultType) {
    var ret = fn.call(me, original, config, defaultType);
    if (ret === undefined) {
      ret = original.call(me, config, defaultType);
    }
    return ret;
  };
}, update:function(instance, config, creator, creatorMethod, defaultsConfig) {
  var me = this, aliases, defaults, reuse, type;
  if (!config || config.isInstance) {
    if (config && !config[me.instanceProp]) {
      Ext.raise('Config instance failed ' + me.instanceProp + ' requirement');
    }
    if (instance && instance !== config) {
      instance.destroy();
    }
    return config;
  }
  if (typeof config === 'string') {
    type = config;
    config = {};
    config[me.defaultProperty] = type;
  }
  if (instance) {
    if (config === true) {
      return instance;
    }
    if (!(type = config.xclass)) {
      if (!(type = config.xtype)) {
        type = config[me.typeProperty];
        if (type) {
          type = me.aliasPrefix + type;
          aliases = instance.self.prototype;
          if (aliases.hasOwnProperty('alias')) {
            aliases = aliases.alias;
            if (aliases) {
              reuse = aliases === type || aliases.indexOf(type) > -1;
            }
          }
        }
      } else {
        reuse = instance.isXType(type, true);
      }
    } else {
      reuse = instance.$className === type;
    }
    if (reuse) {
      instance.setConfig(config);
      return instance;
    }
    instance.destroy();
  }
  if (config === true) {
    config = {};
  }
  if (creator) {
    if (defaultsConfig) {
      defaults = Ext.Config.map[defaultsConfig];
      defaults = creator[defaults.names.get]();
      if (defaults) {
        config = Ext.merge(Ext.clone(defaults), config);
      }
    }
    creatorMethod = creatorMethod || me.creator;
    if (creator[creatorMethod]) {
      config = creator[creatorMethod](config);
      if (!config) {
        Ext.raise('Missing return value from ' + creatorMethod + ' on class ' + creator.$className);
      }
    }
  }
  return me.create(config);
}};
Ext.Factory.define = function(type, config) {
  var Factory = Ext.Factory, cacheable = config && config.cacheable, defaultClass, factory, fn;
  if (type.constructor === Object) {
    Ext.Object.each(type, Factory.define, Factory);
  } else {
    factory = new Ext.Factory(type);
    if (config) {
      if (config.constructor === Object) {
        Ext.apply(factory, config);
        if (typeof(defaultClass = factory.xclass) === 'string') {
          factory.defaultClass = Ext.ClassManager.get(defaultClass);
        }
      } else {
        factory.defaultType = config;
      }
    }
    Factory[factory.name] = fn = function(config, defaultType) {
      return factory.create(config, defaultType);
    };
    if (cacheable) {
      factory.instanceCache = {};
      factory.hook(function(original, config, defaultType) {
        var cache = this.instanceCache, v;
        if (typeof config === 'string' && !(v = cache[config])) {
          v = original.call(this, config, defaultType);
          if (v.cacheable !== false) {
            cache[config] = v;
            Ext.Object.freeze(v);
          }
        }
        return v;
      });
    }
    fn.instance = factory;
    fn.update = function(instance, config, creator, creatorMethod, defaultsConfig) {
      return factory.update(instance, config, creator, creatorMethod, defaultsConfig);
    };
  }
  return fn;
};
Ext.Factory.clearCaches = function() {
  var Factory = Ext.Factory, key, item;
  for (key in Factory) {
    item = Factory[key];
    item = item.instance;
    if (item) {
      item.clearCache();
    }
  }
};
Ext.Factory.on = function(name, fn) {
  Ext.Factory[name].instance.hook(fn);
};
Ext.define('Ext.mixin.Factoryable', {mixinId:'factoryable', onClassMixedIn:function(targetClass) {
  var proto = targetClass.prototype, factoryConfig = proto.factoryConfig, alias = proto.alias, config = {}, dot, createFn;
  alias = alias && alias.length && alias[0];
  if (alias && (dot = alias.lastIndexOf('.')) > 0) {
    config.type = alias.substring(0, dot);
    config.defaultType = alias.substring(dot + 1);
  }
  if (factoryConfig) {
    delete proto.factoryConfig;
    Ext.apply(config, factoryConfig);
  }
  createFn = Ext.Factory.define(config.type, config);
  if (targetClass.create === Ext.Base.create) {
    targetClass.create = createFn;
  }
}});
Ext.define('Ext.data.request.Base', {mixins:[Ext.mixin.Factoryable], factoryConfig:{type:'request', defaultType:'ajax'}, result:null, success:null, timer:null, constructor:function(config) {
  var me = this;
  Ext.apply(me, config.options || {}, config.ownerConfig);
  me.id = ++Ext.data.Connection.requestId;
  me.owner = config.owner;
  me.options = config.options;
  me.requestOptions = config.requestOptions;
}, start:function() {
  var me = this, timeout = me.getTimeout();
  if (timeout && me.async) {
    me.timer = Ext.defer(me.onTimeout, timeout, me);
  }
}, abort:function() {
  var me = this;
  me.clearTimer();
  if (!me.timedout) {
    me.aborted = true;
  }
  me.abort = Ext.emptyFn;
}, createDeferred:function() {
  var me = this, result = me.result, d = new Ext.Deferred;
  if (me.completed) {
    if (me.success) {
      d.resolve(result);
    } else {
      d.reject(result);
    }
  }
  me.deferred = d;
  return d;
}, getDeferred:function() {
  return this.deferred || this.createDeferred();
}, getPromise:function() {
  return this.getDeferred().promise;
}, then:function() {
  var promise = this.getPromise();
  return promise.then.apply(promise, arguments);
}, onComplete:function() {
  var me = this, deferred = me.deferred, result = me.result;
  me.clearTimer();
  if (deferred) {
    if (me.success) {
      deferred.resolve(result);
    } else {
      deferred.reject(result);
    }
  }
  me.completed = true;
}, onTimeout:function() {
  var me = this;
  me.timedout = true;
  me.timer = null;
  me.abort(true);
}, getTimeout:function() {
  return this.timeout;
}, clearTimer:function() {
  this.timer = Ext.undefer(this.timer);
}, destroy:function() {
  var me = this;
  me.abort();
  me.owner = me.options = me.requestOptions = me.result = null;
  me.callParent();
}, privates:{createException:function() {
  var me = this, result;
  result = {request:me, requestId:me.id, status:me.aborted ? -1 : 0, statusText:me.aborted ? 'transaction aborted' : 'communication failure', getResponseHeader:me._getHeader, getAllResponseHeaders:me._getHeaders};
  if (me.aborted) {
    result.aborted = true;
  }
  if (me.timedout) {
    result.timedout = true;
  }
  return result;
}, _getHeader:function(name) {
  var headers = this.headers;
  return headers && headers[name.toLowerCase()];
}, _getHeaders:function() {
  return this.headers;
}}});
Ext.define('Ext.data.flash.BinaryXhr', {statics:{flashPluginActivated:function() {
  Ext.data.flash.BinaryXhr.flashPluginActive = true;
  Ext.data.flash.BinaryXhr.flashPlugin = document.getElementById('ext-flash-polyfill');
  Ext.GlobalEvents.fireEvent('flashready');
}, flashPluginActive:false, flashPluginInjected:false, connectionIndex:1, liveConnections:{}, flashPlugin:null, onFlashStateChange:function(javascriptId, state, data) {
  var connection;
  connection = this.liveConnections[Number(javascriptId)];
  if (connection) {
    connection.onFlashStateChange(state, data);
  } else {
    Ext.warn.log('onFlashStateChange for unknown connection ID: ' + javascriptId);
  }
}, registerConnection:function(conn) {
  var i = this.connectionIndex;
  this.conectionIndex = this.connectionIndex + 1;
  this.liveConnections[i] = conn;
  return i;
}, injectFlashPlugin:function() {
  var me = this, flashLoaderPath, flashObjectPath;
  me.flashPolyfillEl = Ext.getBody().appendChild({id:'ext-flash-polyfill', cn:[{tag:'p', html:'To view this page ensure that Adobe Flash Player version 11.1.0 or greater is installed.'}, {tag:'a', href:'http://www.adobe.com/go/getflashplayer', cn:[{tag:'img', src:window.location.protocol + '//www.adobe.com/images/shared/download_buttons/get_flash_player.gif', alt:'Get Adobe Flash player'}]}]});
  flashLoaderPath = [Ext.Loader.getPath('Ext.data.Connection'), '../../../plugins/flash/swfobject.js'].join('/');
  flashObjectPath = '/plugins/flash/FlashPlugin.swf';
  flashObjectPath = [Ext.Loader.getPath('Ext.data.Connection'), '../../plugins/flash/FlashPlugin.swf'].join('/');
  if (Ext.flashPluginPath) {
    flashObjectPath = Ext.flashPluginPath;
  }
  Ext.Loader.loadScript({url:flashLoaderPath, onLoad:function() {
    var swfVersionStr = '11.4.0', xiSwfUrlStr = 'playerProductInstall.swf', flashvars = {}, params = {}, attributes = {};
    params.quality = 'high';
    params.bgcolor = '#ffffff';
    params.allowscriptaccess = 'sameDomain';
    params.allowfullscreen = 'true';
    attributes.id = 'ext-flash-polyfill';
    attributes.name = 'polyfill';
    attributes.align = 'middle';
    swfobject.embedSWF(flashObjectPath, 'ext-flash-polyfill', '0', '0', swfVersionStr, xiSwfUrlStr, flashvars, params, attributes);
  }, onError:function() {
    Ext.raise('Could not load flash-loader file swfobject.js from ' + flashLoader);
  }, scope:me});
  Ext.data.flash.BinaryXhr.flashPluginInjected = true;
}}, readyState:0, status:0, statusText:'', responseBytes:null, javascriptId:null, constructor:function(config) {
  var me = this;
  if (!Ext.data.flash.BinaryXhr.flashPluginInjected) {
    Ext.data.flash.BinaryXhr.injectFlashPlugin();
  }
  Ext.apply(me, config);
  me.requestHeaders = {};
}, abort:function() {
  var me = this;
  if (me.readyState === 4) {
    Ext.warn.log("Aborting a connection that's completed its transfer: " + this.url);
    return;
  }
  me.aborted = true;
  if (!Ext.data.flash.BinaryXhr.flashPluginActive) {
    Ext.GlobalEvents.removeListener('flashready', me.onFlashReady, me);
    return;
  }
  Ext.data.flash.BinaryXhr.flashPlugin.abortRequest(me.javascriptId);
  delete Ext.data.flash.BinaryXhr.liveConnections[me.javascriptId];
}, getAllResponseHeaders:function() {
  var headers = [];
  Ext.Object.each(this.responseHeaders, function(name, value) {
    headers.push(name + ': ' + value);
  });
  return headers.join('\r\n');
}, getResponseHeader:function(header) {
  var headers = this.responseHeaders;
  return headers && headers[header] || null;
}, open:function(method, url, isAsync, user, password) {
  var me = this;
  me.method = method;
  me.url = url;
  me.async = isAsync !== false;
  me.user = user;
  me.password = password;
  if (!me.async) {
    Ext.raise('Binary posts are only supported in async mode: ' + url);
  }
  if (me.method !== 'POST') {
    Ext.log.warn('Binary data can only be sent as a POST request: ' + url);
  }
}, overrideMimeType:function(mimeType) {
  this.mimeType = mimeType;
}, send:function(body) {
  var me = this;
  me.body = body;
  if (!Ext.data.flash.BinaryXhr.flashPluginActive) {
    Ext.GlobalEvents.addListener('flashready', me.onFlashReady, me);
  } else {
    this.onFlashReady();
  }
}, onFlashReady:function() {
  var me = this, req;
  me.javascriptId = Ext.data.flash.BinaryXhr.registerConnection(me);
  req = {method:me.method, url:me.url, user:me.user, password:me.password, mimeType:me.mimeType, requestHeaders:me.requestHeaders, body:me.body, javascriptId:me.javascriptId};
  Ext.data.flash.BinaryXhr.flashPlugin.postBinary(req);
}, setReadyState:function(state) {
  var me = this;
  if (me.readyState !== state) {
    me.readyState = state;
    me.onreadystatechange();
  }
}, setRequestHeader:function(header, value) {
  this.requestHeaders[header] = value;
}, onreadystatechange:Ext.emptyFn, parseData:function(data) {
  var me = this;
  this.status = data.status || 0;
  me.responseHeaders = {};
  if (me.mimeType) {
    me.responseHeaders['content-type'] = me.mimeType;
  }
  if (data.reason === 'complete') {
    this.responseBytes = data.data;
    me.responseHeaders['content-length'] = data.data.length;
  } else {
    if (data.reason === 'error' || data.reason === 'securityError') {
      this.statusText = data.text;
      me.responseHeaders['content-length'] = 0;
    } else {
      Ext.raise('Unkown reason code in data: ' + data.reason);
    }
  }
}, onFlashStateChange:function(state, data) {
  var me = this;
  if (state === 4) {
    me.parseData(data);
    delete Ext.data.flash.BinaryXhr.liveConnections[me.javascriptId];
  }
  me.setReadyState(state);
}});
Ext.define('Ext.data.request.Ajax', {extend:Ext.data.request.Base, alias:'request.ajax', statics:{parseStatus:function(status, response) {
  var type, len, success, isException;
  if (response) {
    type = response.responseType;
    if (type === 'arraybuffer') {
      len = response.byteLength;
    } else {
      if (type === 'blob') {
        len = response.response.size;
      } else {
        if ((type === 'json' || type === 'document') && response.response) {
          len = 0;
        } else {
          if ((type === 'text' || type === '' || !type) && response.responseText) {
            len = response.responseText.length;
          }
        }
      }
    }
  }
  status = status === 1223 ? 204 : status;
  isException = false;
  success = status >= 200 && status < 300 || status === 304 || status === 0 && Ext.isNumber(len);
  if (!success) {
    switch(status) {
      case 12002:
      case 12029:
      case 12030:
      case 12031:
      case 12152:
      case 13030:
        isException = true;
        break;
    }
  }
  return {success:success, isException:isException};
}}, start:function(data) {
  var me = this, options = me.options, requestOptions = me.requestOptions, isXdr = me.isXdr, xhr;
  xhr = me.xhr = me.openRequest(options, requestOptions, me.async, me.username, me.password);
  if (!isXdr) {
    me.setupHeaders(xhr, options, requestOptions.data, requestOptions.params);
  }
  if (me.async) {
    if (!isXdr) {
      xhr.onreadystatechange = me.bindStateChange();
    }
  }
  if (isXdr) {
    me.processXdrRequest(me, xhr);
  }
  me.callParent([data]);
  xhr.send(data);
  if (!me.async) {
    return me.onComplete();
  }
  return me;
}, abort:function(force) {
  var me = this, xhr = me.xhr;
  if (force || me.isLoading()) {
    try {
      xhr.onreadystatechange = null;
    } catch (e$41) {
      xhr.onreadystatechange = Ext.emptyFn;
    }
    xhr.abort();
    me.callParent([force]);
    me.onComplete();
    me.cleanup();
  }
}, cleanup:function() {
  this.xhr = null;
  delete this.xhr;
}, isLoading:function() {
  var me = this, xhr = me.xhr, state = xhr && xhr.readyState, C = Ext.data.flash && Ext.data.flash.BinaryXhr;
  if (!xhr || me.aborted || me.timedout) {
    return false;
  }
  if (C && xhr instanceof C) {
    return state !== 4;
  }
  return state !== 0 && state !== 4;
}, openRequest:function(options, requestOptions, isAsync, username, password) {
  var me = this, xhr = me.newRequest(options);
  if (username) {
    xhr.open(requestOptions.method, requestOptions.url, isAsync, username, password);
  } else {
    if (me.isXdr) {
      xhr.open(requestOptions.method, requestOptions.url);
    } else {
      xhr.open(requestOptions.method, requestOptions.url, isAsync);
    }
  }
  if (options.binary || me.binary) {
    if (window.Uint8Array) {
      xhr.responseType = 'arraybuffer';
    } else {
      if (xhr.overrideMimeType) {
        xhr.overrideMimeType('text/plain; charset\x3dx-user-defined');
      } else {
        if (!Ext.isIE) {
          Ext.log.warn('Your browser does not support loading binary data using Ajax.');
        }
      }
    }
  }
  if (options.responseType) {
    xhr.responseType = options.responseType;
  }
  if (options.withCredentials || me.withCredentials) {
    xhr.withCredentials = true;
  }
  return xhr;
}, newRequest:function(options) {
  var me = this, xhr;
  if (options.binaryData) {
    if (window.Uint8Array) {
      xhr = me.getXhrInstance();
    } else {
      xhr = new Ext.data.flash.BinaryXhr;
    }
  } else {
    if (me.cors && Ext.isIE9m) {
      xhr = me.getXdrInstance();
      me.isXdr = true;
    } else {
      xhr = me.getXhrInstance();
      me.isXdr = false;
    }
  }
  return xhr;
}, setupHeaders:function(xhr, options, data, params) {
  var me = this, headers = Ext.apply({}, options.headers || {}, me.defaultHeaders), contentType = me.defaultPostHeader, jsonData = options.jsonData, xmlData = options.xmlData, type = 'Content-Type', useHeader = me.useDefaultXhrHeader, key, header;
  if (!headers.hasOwnProperty(type) && (data || params)) {
    if (data) {
      if (options.rawData) {
        contentType = 'text/plain';
      } else {
        if (xmlData && Ext.isDefined(xmlData)) {
          contentType = 'text/xml';
        } else {
          if (jsonData && Ext.isDefined(jsonData)) {
            contentType = 'application/json';
          }
        }
      }
    }
    headers[type] = contentType;
  }
  if (useHeader && !headers['X-Requested-With']) {
    headers['X-Requested-With'] = me.defaultXhrHeader;
  }
  if (headers[type] === undefined || headers[type] === null) {
    delete headers[type];
  }
  try {
    for (key in headers) {
      if (headers.hasOwnProperty(key)) {
        header = headers[key];
        xhr.setRequestHeader(key, header);
      }
    }
  } catch (e$42) {
    me.owner.fireEvent('exception', key, header);
  }
  return headers;
}, getXdrInstance:function() {
  var xdr;
  if (Ext.ieVersion >= 8) {
    xdr = new XDomainRequest;
  } else {
    Ext.raise({msg:'Your browser does not support CORS'});
  }
  return xdr;
}, getXhrInstance:function() {
  return new XMLHttpRequest;
}, processXdrRequest:function(request, xhr) {
  var me = this;
  delete request.headers;
  request.contentType = request.options.contentType || me.defaultXdrContentType;
  xhr.onload = me.bindStateChange(true);
  xhr.onerror = xhr.ontimeout = me.bindStateChange(false);
}, processXdrResponse:function(response, xhr) {
  response.getAllResponseHeaders = function() {
    return [];
  };
  response.getResponseHeader = function() {
    return '';
  };
  response.contentType = xhr.contentType || this.defaultXdrContentType;
}, bindStateChange:function(xdrResult) {
  var me = this;
  return function() {
    Ext.elevate(function() {
      me.onStateChange(xdrResult);
    });
  };
}, onStateChange:function(xdrResult) {
  var me = this, xhr = me.xhr;
  if (xhr && xhr.readyState === 4 || me.isXdr) {
    me.clearTimer();
    me.onComplete(xdrResult);
    me.cleanup();
  }
}, onComplete:function(xdrResult) {
  var me = this, owner = me.owner, options = me.options, xhr = me.xhr, failure = {success:false, isException:false}, result, success, response;
  if (!xhr || me.destroyed) {
    return me.result = failure;
  }
  try {
    result = Ext.data.request.Ajax.parseStatus(xhr.status, xhr);
    if (result.success) {
      result.success = xhr.readyState === 4;
    }
  } catch (e$43) {
    result = failure;
  }
  success = me.success = me.isXdr ? xdrResult : result.success;
  if (success) {
    response = me.createResponse(xhr);
    if (owner.hasListeners.requestcomplete) {
      owner.fireEvent('requestcomplete', owner, response, options);
    }
    if (options.success) {
      Ext.callback(options.success, options.scope, [response, options]);
    }
  } else {
    if (result.isException || me.aborted || me.timedout) {
      response = me.createException(xhr);
    } else {
      response = me.createResponse(xhr);
    }
    if (owner.hasListeners.requestexception) {
      owner.fireEvent('requestexception', owner, response, options);
    }
    if (options.failure) {
      Ext.callback(options.failure, options.scope, [response, options]);
    }
  }
  me.result = response;
  if (options.callback) {
    Ext.callback(options.callback, options.scope, [options, success, response]);
  }
  owner.onRequestComplete(me);
  me.callParent([xdrResult]);
  return response;
}, createResponse:function(xhr) {
  var me = this, isXdr = me.isXdr, headers = {}, lines = isXdr ? [] : xhr.getAllResponseHeaders().replace(/\r\n/g, '\n').split('\n'), count = lines.length, line, index, key, response;
  while (count--) {
    line = lines[count];
    index = line.indexOf(':');
    if (index >= 0) {
      key = line.substr(0, index).toLowerCase();
      if (line.charAt(index + 1) === ' ') {
        ++index;
      }
      headers[key] = line.substr(index + 1);
    }
  }
  response = {request:me, requestId:me.id, status:xhr.status, statusText:xhr.statusText, getResponseHeader:function(header) {
    return headers[header.toLowerCase()];
  }, getAllResponseHeaders:function() {
    return headers;
  }};
  if (isXdr) {
    me.processXdrResponse(response, xhr);
  }
  if (me.binary) {
    response.responseBytes = me.getByteArray(xhr);
  } else {
    if (xhr.responseType) {
      response.responseType = xhr.responseType;
    }
    if (xhr.responseType === 'blob') {
      response.responseBlob = xhr.response;
    } else {
      if (xhr.responseType === 'json') {
        response.responseJson = xhr.response;
      } else {
        if (xhr.responseType === 'document') {
          response.responseXML = xhr.response;
        } else {
          response.responseText = xhr.responseText;
          response.responseXML = xhr.responseXML;
        }
      }
    }
  }
  return response;
}, destroy:function() {
  this.xhr = null;
  this.callParent();
}, privates:{getByteArray:function(xhr) {
  var response = xhr.response, responseBody = xhr.responseBody, Cls = Ext.data.flash && Ext.data.flash.BinaryXhr, byteArray, responseText, len, i;
  if (xhr instanceof Cls) {
    byteArray = xhr.responseBytes;
  } else {
    if (window.Uint8Array) {
      byteArray = response ? new Uint8Array(response) : [];
    } else {
      if (Ext.isIE9p) {
        try {
          byteArray = (new VBArray(responseBody)).toArray();
        } catch (e$44) {
          byteArray = [];
        }
      } else {
        if (Ext.isIE) {
          if (!this.self.vbScriptInjected) {
            this.injectVBScript();
          }
          getIEByteArray(xhr.responseBody, byteArray = []);
        } else {
          byteArray = [];
          responseText = xhr.responseText;
          len = responseText.length;
          for (i = 0; i < len; i++) {
            byteArray.push(responseText.charCodeAt(i) & 255);
          }
        }
      }
    }
  }
  return byteArray;
}, injectVBScript:function() {
  var scriptTag = document.createElement('script');
  scriptTag.type = 'text/vbscript';
  scriptTag.text = ['Function getIEByteArray(byteArray, out)', 'Dim len, i', 'len \x3d LenB(byteArray)', 'For i \x3d 1 to len', 'out.push(AscB(MidB(byteArray, i, 1)))', 'Next', 'End Function'].join('\n');
  Ext.getHead().dom.appendChild(scriptTag);
  this.self.vbScriptInjected = true;
}}});
Ext.define('Ext.data.request.Form', {extend:Ext.data.request.Base, alias:'request.form', start:function(data) {
  var me = this, options = me.options, requestOptions = me.requestOptions;
  me.callParent([data]);
  me.form = me.upload(options.form, requestOptions.url, requestOptions.data, options);
  return me;
}, abort:function(force) {
  var me = this, frame;
  if (me.isLoading()) {
    try {
      frame = me.frame.dom;
      if (frame.stop) {
        frame.stop();
      } else {
        frame.document.execCommand('Stop');
      }
    } catch (e$45) {
    }
  }
  me.callParent([force]);
  me.onComplete();
  me.cleanup();
}, cleanup:function() {
  var me = this, frame = me.frame;
  if (frame) {
    frame.un('load', me.onComplete, me);
    Ext.removeNode(frame);
  }
  me.frame = me.form = null;
}, isLoading:function() {
  return !!this.frame;
}, upload:function(form, url, params, options) {
  form = Ext.getDom(form);
  options = options || {};
  var frameDom = document.createElement('iframe'), frame = Ext.get(frameDom), id = frame.id, hiddens = [], encoding = 'multipart/form-data', buf = {target:form.target, method:form.method, encoding:form.encoding, enctype:form.enctype, action:form.action}, addField = function(name, value) {
    hiddenItem = document.createElement('input');
    Ext.fly(hiddenItem).set({type:'hidden', value:value, name:name});
    form.appendChild(hiddenItem);
    hiddens.push(hiddenItem);
  }, hiddenItem, obj, value, name, vLen, v, hLen, h;
  frame.set({name:id, cls:Ext.baseCSSPrefix + 'hidden-display', src:Ext.SSL_SECURE_URL, tabIndex:-1});
  document.body.appendChild(frameDom);
  document.body.appendChild(form);
  if (document.frames) {
    document.frames[id].name = id;
  }
  Ext.fly(form).set({target:id, method:'POST', enctype:encoding, encoding:encoding, action:url || buf.action});
  if (params) {
    obj = Ext.Object.fromQueryString(params) || {};
    for (name in obj) {
      if (obj.hasOwnProperty(name)) {
        value = obj[name];
        if (Ext.isArray(value)) {
          vLen = value.length;
          for (v = 0; v < vLen; v++) {
            addField(name, value[v]);
          }
        } else {
          addField(name, value);
        }
      }
    }
  }
  this.frame = frame;
  frame.on({load:this.onComplete, scope:this, single:!Ext.isOpera});
  form.submit();
  document.body.removeChild(form);
  Ext.fly(form).set(buf);
  for (hLen = hiddens.length, h = 0; h < hLen; h++) {
    Ext.removeNode(hiddens[h]);
  }
  return form;
}, getDoc:function() {
  var frame = this.frame.dom;
  return frame && (frame.contentWindow.document || frame.contentDocument) || (window.frames[frame.id] || {}).document;
}, getTimeout:function() {
  return this.options.timeout;
}, onComplete:function() {
  var me = this, frame = me.frame, owner = me.owner, options = me.options, callback, doc, success, contentNode, response;
  if (!frame) {
    return;
  }
  if (me.aborted || me.timedout) {
    me.result = response = me.createException();
    response.responseXML = null;
    response.responseText = Ext.encode({success:false, message:Ext.String.trim(response.statusText)});
    response.request = me;
    callback = options.failure;
    success = false;
  } else {
    try {
      doc = me.getDoc();
      me.result = response = {responseText:'', responseXML:null, request:me};
      if (doc) {
        if (Ext.isOpera && doc.location === Ext.SSL_SECURE_URL) {
          return;
        }
        if (doc.body) {
          if ((contentNode = doc.body.firstChild) && /pre/i.test(contentNode.tagName)) {
            response.responseText = contentNode.textContent || contentNode.innerText;
          } else {
            if (contentNode = doc.getElementsByTagName('textarea')[0]) {
              response.responseText = contentNode.value;
            } else {
              response.responseText = doc.body.textContent || doc.body.innerText;
            }
          }
        }
        response.responseXML = doc.XMLDocument || doc;
        callback = options.success;
        success = true;
        response.status = 200;
      } else {
        Ext.raise('Could not acquire a suitable connection for the ' + 'file upload service.');
      }
    } catch (e$46) {
      me.result = response = me.createException();
      response.status = 400;
      response.statusText = (e$46.message || e$46.description) + '';
      response.responseText = Ext.encode({success:false, message:Ext.String.trim(response.statusText)});
      response.responseXML = null;
      callback = options.failure;
      success = false;
    }
  }
  me.frame = null;
  me.success = success;
  owner.fireEvent(success ? 'requestcomplete' : 'requestexception', owner, response, options);
  Ext.callback(callback, options.scope, [response, options]);
  Ext.callback(options.callback, options.scope, [options, success, response]);
  owner.onRequestComplete(me);
  Ext.asap(frame.destroy, frame);
  me.callParent();
}, destroy:function() {
  this.cleanup();
  this.callParent();
}});
Ext.define('Ext.data.Connection', {mixins:{observable:Ext.mixin.Observable}, statics:{requestId:0}, enctypeRe:/multipart\/form-data/i, config:{url:null, async:true, username:'', password:'', disableCaching:true, withCredentials:false, binary:false, cors:false, isXdr:false, defaultXdrContentType:'text/plain', disableCachingParam:'_dc', timeout:30000, extraParams:null, autoAbort:false, method:null, defaultHeaders:null, defaultPostHeader:'application/x-www-form-urlencoded; charset\x3dUTF-8', useDefaultXhrHeader:true, 
defaultXhrHeader:'XMLHttpRequest'}, constructor:function(config) {
  this.mixins.observable.constructor.call(this, config);
  this.requests = {};
}, request:function(options) {
  var me = this, requestOptions, request;
  options = options || {};
  if (me.fireEvent('beforerequest', me, options) !== false) {
    requestOptions = me.setOptions(options, options.scope || Ext.global);
    request = me.createRequest(options, requestOptions);
    return request.start(requestOptions.data);
  }
  request = {status:-1, statusText:'Request cancelled in beforerequest event handler'};
  Ext.callback(options.callback, options.scope, [options, false, request]);
  return Ext.Deferred.rejected([options, false, request]);
}, createRequest:function(options, requestOptions) {
  var me = this, type = options.type || requestOptions.type, request;
  if (!type) {
    type = me.isFormUpload(options) ? 'form' : 'ajax';
  }
  if (options.autoAbort || me.getAutoAbort()) {
    me.abort();
  }
  request = Ext.Factory.request({type:type, owner:me, options:options, requestOptions:requestOptions, ownerConfig:me.getConfig()});
  me.requests[request.id] = request;
  me.latestId = request.id;
  return request;
}, isFormUpload:function(options) {
  var form = this.getForm(options);
  if (form) {
    return options.isUpload || this.enctypeRe.test(form.getAttribute('enctype'));
  }
  return false;
}, getForm:function(options) {
  return Ext.getDom(options.form);
}, setOptions:function(options, scope) {
  var me = this, params = options.params || {}, extraParams = me.getExtraParams(), urlParams = options.urlParams, url = options.url || me.getUrl(), cors = options.cors, jsonData = options.jsonData, method, disableCache, data;
  if (cors !== undefined) {
    me.setCors(cors);
  }
  if (Ext.isFunction(params)) {
    params = params.call(scope, options);
  }
  if (Ext.isFunction(url)) {
    url = url.call(scope, options);
  }
  url = this.setupUrl(options, url);
  if (!url) {
    Ext.raise({options:options, msg:'No URL specified'});
  }
  data = options.rawData || options.binaryData || options.xmlData || jsonData || null;
  if (jsonData && !Ext.isPrimitive(jsonData)) {
    data = Ext.encode(data);
  }
  if (options.binaryData) {
    if (!Ext.isArray(options.binaryData)) {
      Ext.log.warn('Binary submission data must be an array of byte values! ' + 'Instead got ' + typeof options.binaryData);
    }
    if (me.nativeBinaryPostSupport()) {
      data = new Uint8Array(options.binaryData);
      if (Ext.isChrome && Ext.chromeVersion < 22 || Ext.isSafari || Ext.isGecko) {
        data = data.buffer;
      }
    }
  }
  if (Ext.isObject(params)) {
    params = Ext.Object.toQueryString(params);
  }
  if (Ext.isObject(extraParams)) {
    extraParams = Ext.Object.toQueryString(extraParams);
  }
  params = params + (extraParams ? (params ? '\x26' : '') + extraParams : '');
  urlParams = Ext.isObject(urlParams) ? Ext.Object.toQueryString(urlParams) : urlParams;
  params = this.setupParams(options, params);
  method = (options.method || me.getMethod() || (params || data ? 'POST' : 'GET')).toUpperCase();
  this.setupMethod(options, method);
  disableCache = options.disableCaching !== false ? options.disableCaching || me.getDisableCaching() : false;
  if (method === 'GET' && disableCache) {
    url = Ext.urlAppend(url, (options.disableCachingParam || me.getDisableCachingParam()) + '\x3d' + (new Date).getTime());
  }
  if ((method === 'GET' || data) && params) {
    url = Ext.urlAppend(url, params);
    params = null;
  }
  if (urlParams) {
    url = Ext.urlAppend(url, urlParams);
  }
  return {url:url, method:method, data:data || params || null};
}, setupUrl:function(options, url) {
  var form = this.getForm(options);
  if (form) {
    url = url || form.action;
  }
  return url;
}, setupParams:function(options, params) {
  var form = this.getForm(options), serializedForm;
  if (form && !this.isFormUpload(options)) {
    serializedForm = Ext.Element.serializeForm(form);
    params = params ? params + '\x26' + serializedForm : serializedForm;
  }
  return params;
}, setupMethod:function(options, method) {
  if (this.isFormUpload(options)) {
    return 'POST';
  }
  return method;
}, isLoading:function(request) {
  if (!request) {
    request = this.getLatest();
  }
  return request ? request.isLoading() : false;
}, abort:function(request) {
  if (!request) {
    request = this.getLatest();
  }
  if (request && request.isLoading()) {
    request.abort();
  }
}, abortAll:function() {
  var requests = this.requests, id;
  for (id in requests) {
    this.abort(requests[id]);
  }
}, getLatest:function() {
  var id = this.latestId, request;
  if (id) {
    request = this.requests[id];
  }
  return request || null;
}, clearTimeout:function(request) {
  if (!request) {
    request = this.getLatest();
  }
  if (request) {
    request.clearTimer();
  }
}, onRequestComplete:function(request) {
  delete this.requests[request.id];
}, nativeBinaryPostSupport:function() {
  return Ext.isChrome || Ext.isSafari && Ext.isDefined(window.Uint8Array) || Ext.isGecko && Ext.isDefined(window.Uint8Array);
}});
Ext.define('Ext.Ajax', {extend:Ext.data.Connection, singleton:true, autoAbort:false});
Ext.define('Ext.AnimationQueue', {singleton:true, constructor:function() {
  var me = this;
  me.queue = [];
  me.taskQueue = [];
  me.runningQueue = [];
  me.idleQueue = [];
  me.isRunning = false;
  me.isIdle = true;
  me.run = me.run.bind(me);
  if (Ext.os.is.iOS) {
    me.watch.$skipTimerCheck = true;
    me.watchdogTimer = Ext.interval(me.watch, 500, me);
  }
}, start:function(fn, scope, args) {
  var me = this;
  me.queue.push(arguments);
  if (!me.isRunning) {
    if (me.hasOwnProperty('idleTimer')) {
      Ext.undefer(me.idleTimer);
      delete me.idleTimer;
    }
    if (me.hasOwnProperty('idleQueueTimer')) {
      Ext.undefer(me.idleQueueTimer);
      delete me.idleQueueTimer;
    }
    me.isIdle = false;
    me.isRunning = true;
    me.startCountTime = Ext.now();
    me.count = 0;
    me.doStart();
  }
}, clear:function() {
  var me = this;
  Ext.undefer(me.idleTimer);
  Ext.undefer(me.idleQueueTimer);
  Ext.unraf(me.animationFrameId);
  me.idleTimer = me.idleQueueTimer = me.animationFrameId = null;
  me.queue.length = me.taskQueue.length = me.runningQueue.length = me.idleQueue.length = 0;
  me.isRunning = false;
  me.isIdle = true;
  me.startCountTime = Ext.now();
  me.count = 0;
}, watch:function() {
  if (this.isRunning && Ext.now() - this.lastRunTime >= 500) {
    this.run();
  }
}, run:function() {
  var me = this, queue = me.runningQueue, now, item, element, i, ln;
  me.animationFrameId = null;
  if (!me.isRunning) {
    return;
  }
  now = Ext.now();
  me.lastRunTime = now;
  me.frameStartTime = now;
  i = me.queue.length;
  while (i--) {
    item = me.queue[i];
    element = item[1] && item[1].getElement && item[1].getElement();
    if (element && element.destroyed) {
      me.queue.splice(i, 1);
    }
  }
  queue.push.apply(queue, me.queue);
  for (i = 0, ln = queue.length; i < ln; i++) {
    me.invoke(queue[i]);
  }
  queue.length = 0;
  var elapse = me.frameStartTime - me.startCountTime, count = ++me.count;
  if (elapse >= 200) {
    me.onFpsChanged(count * 1000 / elapse, count, elapse);
    me.startCountTime = me.frameStartTime;
    me.count = 0;
  }
  if (!me.queue.length) {
    me.stop();
  }
  if (me.isRunning) {
    me.doIterate();
  }
}, onFpsChanged:Ext.emptyFn, onStop:Ext.emptyFn, doStart:function() {
  if (!this.animationFrameId) {
    this.animationFrameId = Ext.raf(this.run);
  }
  this.lastRunTime = Ext.now();
}, doIterate:function() {
  if (!this.animationFrameId) {
    this.animationFrameId = Ext.raf(this.run);
  }
}, doStop:function() {
  if (this.animationFrameId) {
    Ext.unraf(this.animationFrameId);
  }
  this.animationFrameId = null;
}, stop:function(fn, scope, args) {
  var me = this, queue = me.queue, ln = queue.length, i, item;
  if (!me.isRunning) {
    return;
  }
  for (i = 0; i < ln; i++) {
    item = queue[i];
    if (item[0] === fn && item[1] === scope && item[2] === args) {
      queue.splice(i, 1);
      i--;
      ln--;
    }
  }
  if (ln === 0) {
    me.doStop();
    me.onStop();
    me.isRunning = false;
    if (me.idleQueue.length && !me.idleTimer) {
      me.idleTimer = Ext.defer(me.whenIdle, 100, me);
    }
  }
}, onIdle:function(fn, scope, args) {
  var me = this, listeners = me.idleQueue, i, ln, listener;
  for (i = 0, ln = listeners.length; i < ln; i++) {
    listener = listeners[i];
    if (fn === listener[0] && scope === listener[1] && args === listener[2]) {
      return;
    }
  }
  listeners.push(arguments);
  if (me.isIdle) {
    me.processIdleQueue();
  } else {
    if (!me.idleTimer) {
      me.idleTimer = Ext.defer(me.whenIdle, 100, me);
    }
  }
}, unIdle:function(fn, scope, args) {
  var me = this, listeners = me.idleQueue, i, ln, listener;
  for (i = 0, ln = listeners.length; i < ln; i++) {
    listener = listeners[i];
    if (fn === listener[0] && scope === listener[1] && args === listener[2]) {
      listeners.splice(i, 1);
      return true;
    }
  }
  if (!listeners.length && me.idleTimer) {
    Ext.undefer(me.idleTimer);
    delete me.idleTimer;
  }
  if (!listeners.length && me.idleQueueTimer) {
    Ext.undefer(me.idleQueueTimer);
    delete me.idleQueueTimer;
  }
  return false;
}, queueTask:function(fn, scope, args) {
  this.taskQueue.push(arguments);
  this.processTaskQueue();
}, dequeueTask:function(fn, scope, args) {
  var listeners = this.taskQueue, i, ln, listener;
  for (i = 0, ln = listeners.length; i < ln; i++) {
    listener = listeners[i];
    if (fn === listener[0] && scope === listener[1] && args === listener[2]) {
      listeners.splice(i, 1);
      i--;
      ln--;
    }
  }
}, invoke:function(listener) {
  var fn = listener[0], scope = listener[1], args = listener[2];
  fn = typeof fn === 'string' ? scope[fn] : fn;
  if (Ext.isArray(args)) {
    fn.apply(scope, args);
  } else {
    fn.call(scope, args);
  }
}, whenIdle:function() {
  delete this.idleTimer;
  this.isIdle = true;
  this.processIdleQueue();
}, processIdleQueue:function() {
  if (!this.hasOwnProperty('idleQueueTimer')) {
    this.idleQueueTimer = Ext.defer(this.processIdleQueueItem, 1, this);
  }
}, processIdleQueueItem:function() {
  var listeners = this.idleQueue, listener;
  delete this.idleQueueTimer;
  if (!this.isIdle) {
    return;
  }
  if (listeners.length > 0) {
    listener = listeners.shift();
    this.invoke(listener);
    this.processIdleQueue();
  }
}, processTaskQueue:function() {
  if (!this.hasOwnProperty('taskQueueTimer')) {
    this.taskQueueTimer = Ext.defer(this.processTaskQueueItem, 15, this);
  }
}, processTaskQueueItem:function() {
  var listeners = this.taskQueue, listener;
  delete this.taskQueueTimer;
  if (listeners.length > 0) {
    listener = listeners.shift();
    this.invoke(listener);
    this.processTaskQueue();
  }
}, showFps:function() {
  var styleTpl = {color:'white', 'background-color':'black', 'text-align':'center', 'font-family':'sans-serif', 'font-size':'8px', 'font-weight':'normal', 'font-style':'normal', 'line-height':'20px', '-webkit-font-smoothing':'antialiased', 'zIndex':100000, position:'absolute'};
  Ext.getBody().append([{style:Ext.applyIf({bottom:'50px', left:0, width:'50px', height:'20px'}, styleTpl), html:'Average'}, {style:Ext.applyIf({'background-color':'red', 'font-size':'18px', 'line-height':'50px', bottom:0, left:0, width:'50px', height:'50px'}, styleTpl), id:'__averageFps', html:'0'}, {style:Ext.applyIf({bottom:'50px', left:'50px', width:'50px', height:'20px'}, styleTpl), html:'Min (Last 1k)'}, {style:Ext.applyIf({'background-color':'orange', 'font-size':'18px', 'line-height':'50px', 
  bottom:0, left:'50px', width:'50px', height:'50px'}, styleTpl), id:'__minFps', html:'0'}, {style:Ext.applyIf({bottom:'50px', left:'100px', width:'50px', height:'20px'}, styleTpl), html:'Max (Last 1k)'}, {style:Ext.applyIf({'background-color':'maroon', 'font-size':'18px', 'line-height':'50px', bottom:0, left:'100px', width:'50px', height:'50px'}, styleTpl), id:'__maxFps', html:'0'}, {style:Ext.applyIf({bottom:'50px', left:'150px', width:'50px', height:'20px'}, styleTpl), html:'Current'}, {style:Ext.applyIf({'background-color':'green', 
  'font-size':'18px', 'line-height':'50px', bottom:0, left:'150px', width:'50px', height:'50px'}, styleTpl), id:'__currentFps', html:'0'}]);
  Ext.AnimationQueue.resetFps();
}, resetFps:function() {
  var currentFps = Ext.get('__currentFps'), averageFps = Ext.get('__averageFps'), minFps = Ext.get('__minFps'), maxFps = Ext.get('__maxFps'), min = 1000, max = 0, count = 0, sum = 0;
  if (!currentFps) {
    return;
  }
  Ext.AnimationQueue.onFpsChanged = function(fps) {
    count++;
    if (!(count % 10)) {
      min = 1000;
      max = 0;
    }
    sum += fps;
    min = Math.min(min, fps);
    max = Math.max(max, fps);
    currentFps.setHtml(Math.round(fps));
    averageFps.setHtml(Math.round(sum / count));
    minFps.setHtml(Math.round(min));
    maxFps.setHtml(Math.round(max));
  };
}}, function() {
  var paramsString = window.location.search.substr(1), paramsArray = paramsString.split('\x26');
  if (Ext.Array.contains(paramsArray, 'showfps')) {
    Ext.onReady(this.showFps.bind(this));
  }
});
Ext.define('Ext.mixin.Bufferable', function(Bufferable) {
  return {extend:Ext.Mixin, mixinConfig:{id:'bufferable', after:{destroy:'cancelAllCalls'}, before:{$reap:'cancelAllCalls'}, extended:function(baseClass, derivedClass, classBody) {
    var bufferableMethods = classBody.bufferableMethods;
    if (bufferableMethods) {
      delete classBody.bufferableMethods;
      Bufferable.processClass(derivedClass, bufferableMethods);
    }
  }}, afterClassMixedIn:function(targetClass) {
    Bufferable.processClass(targetClass);
  }, privates:{cancelAllCalls:function() {
    var bufferables = this.bufferables, name;
    if (bufferables) {
      for (name in bufferables) {
        bufferables[name].cancel();
        delete bufferables[name];
      }
    }
  }, cancelBufferedCall:function(name, invoke) {
    var bufferables = this.bufferables, timer = bufferables && bufferables[name];
    if (timer) {
      timer[invoke ? 'invoke' : 'cancel']();
    }
    return !!timer;
  }, flushBufferedCall:function(name) {
    return this.cancelBufferedCall(name, true);
  }, initBufferables:function() {
    var me = this, methods = me.hasOwnProperty('bufferableMethods') && me.bufferableMethods, classMethods;
    if (methods) {
      Bufferable._canonicalize(methods);
      classMethods = me.self.prototype.bufferableMethods;
      me.bufferableMethods = Ext.merge(Ext.clone(classMethods), methods);
    }
    return me.bufferables = {};
  }, isCallPending:function(name) {
    var bufferables = this.bufferables, timer = bufferables && bufferables[name];
    return !!timer;
  }, statics:{SINGLE:{single:true}, _canonicalize:function(methods) {
    var t, def, s, name;
    for (name in methods) {
      s = Ext.String.capitalize(name);
      def = methods[name];
      t = typeof def;
      if (t === 'number' || t === 'string') {
        methods[name] = def = {delay:def};
      }
      if (typeof(t = def.delay) === 'string') {
        def[t] = true;
        delete def.delay;
      }
      def.capitalized = s;
      def.name = name;
      if (!def.fn) {
        def.fn = 'do' + s;
      }
      if (!def.flag) {
        def.flag = 'is' + s + 'Pending';
      }
    }
  }, _canceller:function() {
    var timer = this, id = timer.id;
    if (id) {
      if (timer.delay) {
        Ext.undefer(id);
      } else {
        if (timer.asap) {
          Ext.unasap(id);
        } else {
          if (timer.idle) {
            Ext.un('idle', id, null, Bufferable.SINGLE);
          } else {
            if (timer.raf) {
              Ext.unraf(id);
            }
          }
        }
      }
      timer.id = null;
    }
    timer.args = null;
    timer.target[timer.flag] = false;
  }, _invoker:function() {
    var timer = this, args = timer.args || Ext.emptyArray, target = timer.target;
    ++timer.invokes;
    timer.cancel();
    target[timer.fn].apply(target, args);
  }, delayCall:function(target, def, args) {
    if (target.destroying) {
      return;
    }
    var bufferables = target.bufferables || target.initBufferables(), name = def.name, timer = bufferables[name] || (bufferables[name] = Ext.apply({calls:0, invokes:0, args:null, cancel:Bufferable._canceller, id:null, target:target, invoke:Bufferable._invoker}, def)), delay = def.delay, exec = function() {
      if (timer.id) {
        timer.id = null;
        timer.invoke();
      }
    };
    if (timer.id) {
      timer.cancel();
    }
    timer.args = args;
    ++timer.calls;
    target[timer.flag] = true;
    if (delay) {
      timer.id = Ext.defer(exec, delay);
    } else {
      if (def.asap) {
        timer.id = Ext.asap(exec);
      } else {
        if (def.idle) {
          timer.id = exec;
          Ext.on('idle', exec, null, Bufferable.SINGLE);
        } else {
          if (def.raf) {
            timer.id = Ext.raf(exec);
          } else {
            timer.invoke();
          }
        }
      }
    }
  }, processClass:function(cls, bufferableMethods) {
    var proto = cls.prototype, inherited = proto.bufferableMethods, def, name;
    if (bufferableMethods) {
      Bufferable._canonicalize(bufferableMethods);
      if (inherited) {
        inherited = Ext.merge(Ext.clone(inherited), bufferableMethods);
      }
      proto.bufferableMethods = inherited || bufferableMethods;
    } else {
      bufferableMethods = inherited;
      Bufferable._canonicalize(bufferableMethods);
      proto.bufferables = null;
    }
    if (bufferableMethods) {
      for (name in bufferableMethods) {
        if (!proto[name]) {
          def = bufferableMethods[name];
          Bufferable.processMethod(proto, def, Array.prototype.slice);
        }
      }
    }
  }, processMethod:function(proto, def, slice) {
    var name = def.name, cap = def.capitalized;
    proto[name] = function() {
      return Bufferable.delayCall(this, def, slice.call(arguments));
    };
    proto['cancel' + cap] = function() {
      return this.cancelBufferedCall(name);
    };
    proto['flush' + cap] = function() {
      return this.flushBufferedCall(name);
    };
  }}}};
});
Ext.define('Ext.ComponentManager', {alternateClassName:'Ext.ComponentMgr', singleton:true, mixins:[Ext.mixin.Bufferable], count:0, fixReferencesTimer:null, referenceRepairs:0, typeName:'xtype', bufferableMethods:{handleDocumentMouseDown:'asap'}, constructor:function(config) {
  var me = this;
  Ext.apply(me, config);
  me.all = {};
  me.byInstanceId = {};
  me.holders = {};
  me.onAvailableCallbacks = {};
}, create:function(config, defaultType) {
  if (typeof config === 'string') {
    return Ext.widget(config);
  }
  if (config.isComponent) {
    return config;
  }
  if ('xclass' in config) {
    return Ext.create(config.xclass, config);
  }
  return Ext.widget(config.xtype || defaultType, config);
}, get:function(id) {
  return this.all[id];
}, register:function(component) {
  var me = this, id = component.getId(), onAvailableCallbacks = me.onAvailableCallbacks;
  if (id === undefined) {
    Ext.raise('Component id is undefined. Please ensure the component has an id.');
  }
  if (id in me.all) {
    Ext.raise('Duplicate component id "' + id + '"');
  }
  if (component.$iid in me.byInstanceId) {
    Ext.raise('Duplicate component instance id "' + component.$iid + '"');
  }
  me.all[id] = component;
  me.byInstanceId[component.$iid] = component;
  if (component.nameHolder || component.referenceHolder) {
    me.holders[id] = component;
  }
  ++me.count;
  if (!me.hasFocusListener) {
    me.installFocusListener();
  }
  onAvailableCallbacks = onAvailableCallbacks && onAvailableCallbacks[id];
  if (onAvailableCallbacks && onAvailableCallbacks.length) {
    me.notifyAvailable(component);
  }
}, unregister:function(component) {
  var me = this, all = me.all, byInstanceId = me.byInstanceId, holders = me.holders, id = component.getId();
  if (id in holders) {
    holders[id] = null;
    delete holders[id];
  }
  all[id] = null;
  delete all[id];
  id = component.$iid;
  byInstanceId[id] = null;
  delete byInstanceId[id];
  --me.count;
}, markReferencesDirty:function() {
  var me = this, holders = me.holders, holder, id;
  if (!Ext.referencesDirty) {
    for (id in holders) {
      holder = holders[id];
      holder.refs = holder.nameRefs = null;
      if (holder.invalidateChildDirty) {
        holder.invalidateChildDirty();
      }
    }
    Ext.referencesDirty = true;
    me.fixReferencesTimer = Ext.asap(function() {
      me.fixReferencesTimer = null;
      me.fixReferences();
    });
  }
}, fixReferences:function() {
  var me = this, all = me.all, holders = me.holders, holder, id;
  if (Ext.referencesDirty) {
    me.fixReferencesTimer = Ext.unasap(me.fixReferencesTimer);
    Ext.referencesDirty = 0;
    ++me.referenceRepairs;
    for (id in holders) {
      holder = holders[id];
      if (holder.beginSyncChildDirty) {
        holder.beginSyncChildDirty();
      }
    }
    for (id in all) {
      all[id]._fixReference();
    }
    for (id in holders) {
      holder = holders[id];
      if (holder.finishSyncChildDirty) {
        holder.finishSyncChildDirty();
      }
    }
    Ext.referencesDirty = false;
  }
}, onAvailable:function(id, fn, scope) {
  var me = this, callbacks = me.onAvailableCallbacks, all = me.all, item;
  if (id in all) {
    item = all[id];
    fn.call(scope || item, item);
  } else {
    if (id) {
      if (!Ext.isArray(callbacks[id])) {
        callbacks[id] = [];
      }
      callbacks[id].push(function(item) {
        fn.call(scope || item, item);
      });
    }
  }
}, notifyAvailable:function(item) {
  var callbacks = this.onAvailableCallbacks[item && item.getId()] || [];
  while (callbacks.length) {
    callbacks.shift()(item);
  }
}, each:function(fn, scope) {
  Ext.Object.each(this.all, fn, scope);
}, getCount:function() {
  return this.count;
}, getAll:function() {
  return Ext.Object.getValues(this.all);
}, getActiveComponent:function() {
  return Ext.Component.from(Ext.dom.Element.getActiveElement());
}, onGlobalFocus:function(info) {
  var me = this, event = info.event.chain(), infoCopy = Ext.applyIf({event:event}, info), to, from, ancestor, target;
  to = event.toComponent = infoCopy.toComponent = Ext.Component.from(info.toElement);
  from = event.fromComponent = infoCopy.fromComponent = Ext.Component.from(info.fromElement);
  ancestor = me.getCommonAncestor(from, to);
  if (to !== from) {
    if (from && !from.destroyed && !from.isDestructing()) {
      if (from.handleBlurEvent) {
        from.handleBlurEvent(infoCopy);
      }
      for (target = from; target && target !== ancestor; target = target.getRefOwner()) {
        if (!(target.destroyed || target.destroying)) {
          event.type = 'focusleave';
          target.onFocusLeave(event);
        }
      }
    }
    if (to && !to.destroyed && !to.isDestructing()) {
      if (to.handleFocusEvent) {
        to.handleFocusEvent(infoCopy);
      }
      for (target = to; target && target !== ancestor; target = target.getRefOwner()) {
        event.type = 'focusenter';
        target.onFocusEnter(event);
      }
    }
  }
  for (target = ancestor; target; target = target.getRefOwner()) {
    if (!(target.destroying || target.destroyed)) {
      target.onFocusMove(infoCopy);
    }
  }
}, getCommonAncestor:function(compA, compB) {
  if (compA === compB) {
    return compA;
  }
  while (compA && !(compA.isAncestor(compB) || compA === compB)) {
    compA = compA.getRefOwner();
  }
  return compA;
}, privates:{doHandleDocumentMouseDown:function(e) {
  var floatedSelector = Ext.Widget.prototype.floatedSelector, targetFloated;
  if (floatedSelector) {
    targetFloated = Ext.Component.from(e.getTarget(floatedSelector, Ext.getBody()));
    if (targetFloated && !targetFloated.activeAnimation) {
      targetFloated.toFront(true);
    }
  }
}, installFocusListener:function() {
  var me = this;
  Ext.on('focus', me.onGlobalFocus, me);
  me.hasFocusListener = true;
}, clearAll:function() {
  var me = this;
  me.all = {};
  me.byInstanceId = {};
  me.holders = {};
  me.onAvailableCallbacks = {};
}, from:function(el, limit, selector) {
  var cache = this.all, depth = 0, target, topmost, cmpId, cmp;
  if (el && el.isEvent) {
    el = el.target;
  }
  target = Ext.getDom(el);
  if (typeof limit !== 'number') {
    topmost = Ext.getDom(limit);
    limit = Number.MAX_VALUE;
  }
  while (target && target.nodeType === 1 && depth < limit && target !== topmost) {
    cmpId = target.getAttribute('data-componentid') || target.id;
    if (cmpId) {
      cmp = cache[cmpId];
      if (cmp && (!selector || Ext.ComponentQuery.is(cmp, selector))) {
        return cmp;
      }
      depth++;
    }
    target = target.parentNode;
  }
  return null;
}}}, function(ComponentManager) {
  ComponentManager.fromElement = ComponentManager.from;
  Ext.referencesDirty = false;
  Ext.fixReferences = function() {
    ComponentManager.fixReferences();
  };
  Ext.markReferencesDirty = function() {
    ComponentManager.markReferencesDirty();
  };
  Ext.getCmp = function(id) {
    return ComponentManager.get(id);
  };
  Ext.iidToCmp = function(iid) {
    return ComponentManager.byInstanceId[iid] || null;
  };
  Ext.doEv = function(node, e) {
    var cmp, method, event;
    cmp = Ext.Component.from(e.target);
    if (cmp && !cmp.destroying && !cmp.destroyed && cmp.getEventHandlers) {
      method = cmp.getEventHandlers()[e.type];
      if (method && cmp[method]) {
        event = new Ext.event.Event(e);
        return cmp[method](event);
      }
    }
    return true;
  };
});
Ext.ns('Ext.util').Operators = {'\x3d':function(a, v) {
  return a == v;
}, '!\x3d':function(a, v) {
  return a != v;
}, '^\x3d':function(a, v) {
  return a && a.substr(0, v.length) == v;
}, '$\x3d':function(a, v) {
  return a && a.substr(a.length - v.length) == v;
}, '*\x3d':function(a, v) {
  return a && a.indexOf(v) !== -1;
}, '%\x3d':function(a, v) {
  return a % v === 0;
}, '|\x3d':function(a, v) {
  return a && (a == v || a.substr(0, v.length + 1) == v + '-');
}, '~\x3d':function(a, v) {
  return a && (' ' + a + ' ').indexOf(' ' + v + ' ') != -1;
}};
Ext.define('Ext.util.LruCache', {extend:Ext.util.HashMap, config:{maxSize:null}, add:function(key, newValue) {
  var me = this, entry, last;
  me.removeAtKey(key);
  last = me.last;
  entry = {prev:last, next:null, key:key, value:newValue};
  if (last) {
    last.next = entry;
  } else {
    me.first = entry;
  }
  me.last = entry;
  me.callParent([key, entry]);
  me.prune();
  return newValue;
}, insertBefore:function(key, newValue, sibling) {
  var me = this, existingKey, entry;
  if (sibling = this.map[this.findKey(sibling)]) {
    existingKey = me.findKey(newValue);
    if (existingKey) {
      me.unlinkEntry(entry = me.map[existingKey]);
    } else {
      entry = {prev:sibling.prev, next:sibling, key:key, value:newValue};
    }
    if (sibling.prev) {
      entry.prev.next = entry;
    } else {
      me.first = entry;
    }
    entry.next = sibling;
    sibling.prev = entry;
    me.prune();
    return newValue;
  } else {
    return me.add(key, newValue);
  }
}, get:function(key) {
  var entry = this.map[key];
  if (entry) {
    if (entry.next) {
      this.moveToEnd(entry);
    }
    return entry.value;
  }
}, removeAtKey:function(key) {
  this.unlinkEntry(this.map[key]);
  return this.callParent(arguments);
}, clear:function(initial) {
  this.first = this.last = null;
  return this.callParent([initial]);
}, unlinkEntry:function(entry) {
  if (entry) {
    if (entry.next) {
      entry.next.prev = entry.prev;
    } else {
      this.last = entry.prev;
    }
    if (entry.prev) {
      entry.prev.next = entry.next;
    } else {
      this.first = entry.next;
    }
    entry.prev = entry.next = null;
  }
}, moveToEnd:function(entry) {
  this.unlinkEntry(entry);
  if (entry.prev = this.last) {
    this.last.next = entry;
  } else {
    this.first = entry;
  }
  this.last = entry;
}, getArray:function(isKey) {
  var arr = [], entry = this.first;
  while (entry) {
    arr.push(isKey ? entry.key : entry.value);
    entry = entry.next;
  }
  return arr;
}, each:function(fn, scope, reverse) {
  var me = this, entry = reverse ? me.last : me.first, length = me.length;
  scope = scope || me;
  while (entry) {
    if (fn.call(scope, entry.key, entry.value, length) === false) {
      break;
    }
    entry = reverse ? entry.prev : entry.next;
  }
  return me;
}, findKey:function(value) {
  var key, map = this.map;
  for (key in map) {
    if (map.hasOwnProperty(key) && map[key].value === value) {
      return key;
    }
  }
  return undefined;
}, clone:function() {
  var newCache = new this.self(this.initialConfig), map = this.map, key;
  newCache.suspendEvents();
  for (key in map) {
    if (map.hasOwnProperty(key)) {
      newCache.add(key, map[key].value);
    }
  }
  newCache.resumeEvents();
  return newCache;
}, prune:function() {
  var me = this, max = me.getMaxSize(), purgeCount = max ? me.length - max : 0;
  if (purgeCount > 0) {
    for (; me.first && purgeCount; purgeCount--) {
      me.removeAtKey(me.first.key);
    }
  }
}});
Ext.define('Ext.ComponentQuery', {singleton:true}, function() {
  var cq = this, queryOperators = Ext.util.Operators, nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/, stripLeadingSpaceRe = /^(\s)+/, unescapeRe = /\\(.)/g, regexCache = new Ext.util.LruCache({maxSize:100}), filterFnPattern = ['var r \x3d [],', 'i \x3d 0,', 'it \x3d items,', 'l \x3d it.length,', 'c;', 'for (; i \x3c l; i++) {', 'c \x3d it[i];', 'if (c.{0}) {', 'r.push(c);', '}', '}', 'return r;'].join(''), filterItems = function(items, operation) {
    return operation.method.apply(this, [items].concat(operation.args));
  }, getItems = function(items, mode) {
    var result = [], i = 0, length = items.length, candidate, deep = mode !== '\x3e';
    for (; i < length; i++) {
      candidate = items[i];
      if (candidate.getRefItems) {
        result = result.concat(candidate.getRefItems(deep));
      }
    }
    return result;
  }, getAncestors = function(items) {
    var result = [], i = 0, length = items.length, candidate;
    for (; i < length; i++) {
      candidate = items[i];
      while (!!(candidate = candidate.getRefOwner())) {
        result.push(candidate);
      }
    }
    return result;
  }, filterByXType = function(items, xtype, shallow) {
    if (xtype === '*') {
      return items.slice();
    } else {
      var result = [], i = 0, length = items.length, candidate;
      for (; i < length; i++) {
        candidate = items[i];
        if (!candidate.destroyed && candidate.isXType(xtype, shallow)) {
          result.push(candidate);
        }
      }
      return result;
    }
  }, filterByAttribute = function(items, property, operator, compareTo) {
    var result = [], length = items.length, mustBeOwnProperty, presenceOnly, candidate, propValue, config, i, j, propLen;
    if (property.charAt(0) === '@') {
      mustBeOwnProperty = true;
      property = property.substr(1);
    }
    if (property.charAt(0) === '?') {
      mustBeOwnProperty = true;
      presenceOnly = true;
      property = property.substr(1);
    }
    for (i = 0; i < length; i++) {
      candidate = items[i];
      config = candidate.self && candidate.self.getConfigurator && candidate.self.$config.configs[property];
      if (config) {
        propValue = candidate[config.names.get]();
      } else {
        if (mustBeOwnProperty && !candidate.hasOwnProperty(property)) {
          continue;
        } else {
          propValue = candidate[property];
        }
      }
      if (presenceOnly) {
        result.push(candidate);
      } else {
        if (operator === '~\x3d') {
          if (propValue) {
            if (!Ext.isArray(propValue)) {
              propValue = propValue.split(' ');
            }
            for (j = 0, propLen = propValue.length; j < propLen; j++) {
              if (queryOperators[operator](Ext.coerce(propValue[j], compareTo), compareTo)) {
                result.push(candidate);
                break;
              }
            }
          }
        } else {
          if (operator === '/\x3d') {
            if (propValue != null && compareTo.test(propValue)) {
              result.push(candidate);
            }
          } else {
            if (!compareTo ? !!propValue : queryOperators[operator](Ext.coerce(propValue, compareTo), compareTo)) {
              result.push(candidate);
            }
          }
        }
      }
    }
    return result;
  }, filterById = function(items, id, idOnly) {
    var result = [], i = 0, length = items.length, candidate, check;
    for (; i < length; i++) {
      candidate = items[i];
      check = idOnly ? candidate.id : candidate.getItemId();
      if (check === id) {
        result.push(candidate);
      }
    }
    return result;
  }, filterByPseudo = function(items, name, value) {
    return cq.pseudos[name](items, value);
  }, modeRe = /^(\s?([>\^])\s?|\s|$)/, tokenRe = /^(#)?((?:\\\.|[\w\-])+|\*)(?:\((true|false)\))?/, matchers = [{re:/^\.((?:\\\.|[\w\-])+)(?:\((true|false)\))?/, method:filterByXType, argTransform:function(args) {
    var selector = args[0];
    Ext.log.warn('"' + selector + '" ComponentQuery selector style is deprecated,' + ' use "' + selector.replace(/^\./, '') + '" without the leading dot instead');
    if (args[1] !== undefined) {
      args[1] = args[1].replace(unescapeRe, '$1');
    }
    return args.slice(1);
  }}, {re:/^(?:\[((?:[@?$])?[\w\-]*)\s*(?:([\^$*~%!\/]?=)\s*(['"])?((?:\\\]|.)*?)\3)?(?!\\)\])/, method:filterByAttribute, argTransform:function(args) {
    var selector = args[0], property = args[1], operator = args[2], compareTo = args[4], compareRe;
    if (compareTo !== undefined) {
      compareTo = compareTo.replace(unescapeRe, '$1');
      var format = Ext.String.format, msg = "ComponentQuery selector '{0}' has an unescaped ({1}) character " + 'at the {2} of the attribute value pattern. Usually that indicates ' + 'an error where the opening quote is not followed by the closing ' + 'quote. If you need to match a ({1}) character at the {2} of the ' + 'attribute value, escape the quote character in your pattern: ' + '(\\{1})', match;
      if (match = /^(['"]).*?[^'"]$/.exec(compareTo)) {
        Ext.log.warn(format(msg, selector, match[1], 'beginning'));
      } else {
        if (match = /^[^'"].*?(['"])$/.exec(compareTo)) {
          Ext.log.warn(format(msg, selector, match[1], 'end'));
        }
      }
    }
    if (operator === '/\x3d') {
      compareRe = regexCache.get(compareTo);
      if (compareRe) {
        compareTo = compareRe;
      } else {
        compareTo = regexCache.add(compareTo, new RegExp(compareTo));
      }
    }
    return [property, operator, compareTo];
  }}, {re:/^#((?:\\\.|[\w\-])+)/, method:filterById}, {re:/^:([\w\-]+)(?:\(((?:\{[^\}]+\})|(?:(?!\{)[^\s>\/]*?(?!\})))\))?/, method:filterByPseudo, argTransform:function(args) {
    if (args[2] !== undefined) {
      args[2] = args[2].replace(unescapeRe, '$1');
    }
    return args.slice(1);
  }}, {re:/^(?:\{([^\}]+)\})/, method:filterFnPattern}];
  cq.Query = Ext.extend(Object, {constructor:function(cfg) {
    cfg = cfg || {};
    Ext.apply(this, cfg);
  }, execute:function(root) {
    var operations = this.operations, result = [], op, i, len;
    for (i = 0, len = operations.length; i < len; i++) {
      op = operations[i];
      result = result.concat(this._execute(root, op));
    }
    return result;
  }, _execute:function(root, operations) {
    var i = 0, length = operations.length, operation, workingItems;
    if (!root) {
      workingItems = Ext.ComponentManager.getAll();
    } else {
      if (Ext.isIterable(root)) {
        workingItems = root;
      } else {
        if (root.isMixedCollection) {
          workingItems = root.items;
        }
      }
    }
    for (; i < length; i++) {
      operation = operations[i];
      if (operation.mode === '^') {
        workingItems = getAncestors(workingItems || [root]);
      } else {
        if (operation.mode) {
          workingItems = getItems(workingItems || [root], operation.mode);
        } else {
          workingItems = filterItems(workingItems || getItems([root]), operation);
        }
      }
      if (i === length - 1) {
        return workingItems;
      }
    }
    return [];
  }, is:function(component, root) {
    var operations = this.operations, result = false, len = operations.length, op, i;
    if (len === 0) {
      return true;
    }
    for (i = 0; i < len; i++) {
      op = operations[i];
      result = this._is(component, root, op);
      if (result) {
        return result;
      }
    }
    return false;
  }, _is:function(component, root, operations) {
    var len = operations.length, active = [component], operation, i, j, mode, items, item;
    for (i = len - 1; i >= 0; --i) {
      operation = operations[i];
      mode = operation.mode;
      if (mode) {
        if (mode === '^') {
          active = getItems(active, ' ');
        } else {
          if (mode === '\x3e') {
            items = [];
            for (j = 0, len = active.length; j < len; ++j) {
              item = active[j].getRefOwner();
              if (item) {
                items.push(item);
              }
            }
            active = items;
          } else {
            active = getAncestors(active);
          }
        }
      } else {
        active = filterItems(active, operation);
      }
      if (active.length === 0) {
        return false;
      }
    }
    if (root) {
      if (!mode) {
        active = getAncestors(active);
      }
      if (active.length > 0) {
        active = filterItems(active, {method:filterById, args:[root.id, true]});
      }
      if (active.length === 0) {
        return false;
      }
    }
    return true;
  }, getMatches:function(components, operations) {
    var len = operations.length, i;
    for (i = 0; i < len; ++i) {
      components = filterItems(components, operations[i]);
      if (components.length === 0) {
        break;
      }
    }
    return components;
  }, isMultiMatch:function() {
    return this.operations.length > 1;
  }});
  Ext.apply(cq, {cache:new Ext.util.LruCache({maxSize:100}), pseudos:{not:function(components, selector) {
    var i = 0, length = components.length, results = [], index = -1, component;
    for (; i < length; ++i) {
      component = components[i];
      if (!cq.is(component, selector)) {
        results[++index] = component;
      }
    }
    return results;
  }, first:function(components) {
    var ret = [];
    if (components.length > 0) {
      ret.push(components[0]);
    }
    return ret;
  }, last:function(components) {
    var len = components.length, ret = [];
    if (len > 0) {
      ret.push(components[len - 1]);
    }
    return ret;
  }, focusable:function(cmps) {
    var len = cmps.length, results = [], i = 0, c;
    for (; i < len; i++) {
      c = cmps[i];
      if (c.isFocusable && c.isFocusable()) {
        results.push(c);
      }
    }
    return results;
  }, canfocus:function(cmps, value) {
    var len = cmps.length, results = [], i = 0, c;
    for (; i < len; i++) {
      c = cmps[i];
      if (c.canFocus && c.canFocus(false, value)) {
        results.push(c);
      }
    }
    return results;
  }, 'nth-child':function(c, a) {
    var result = [], m, f, i, len, n, nodeIndex;
    m = nthRe.exec(a === 'even' && '2n' || a === 'odd' && '2n+1' || !nthRe2.test(a) && 'n+' + a || a);
    f = (m[1] || 1) - 0;
    len = m[2] - 0;
    for (i = 0; n = c[i]; i++) {
      nodeIndex = i + 1;
      if (f === 1) {
        if (len === 0 || nodeIndex === len) {
          result.push(n);
        }
      } else {
        if ((nodeIndex + len) % f === 0) {
          result.push(n);
        }
      }
    }
    return result;
  }, scrollable:function(cmps) {
    var len = cmps.length, results = [], i = 0, c;
    for (; i < len; i++) {
      c = cmps[i];
      if (c.scrollable || c._scrollable) {
        results.push(c);
      }
    }
    return results;
  }, visible:function(cmps, deep) {
    var len = cmps.length, results = [], i = 0, c;
    deep = deep === 'true';
    for (; i < len; i++) {
      c = cmps[i];
      if (c.isVisible(deep)) {
        results.push(c);
      }
    }
    return results;
  }}, query:function(selector, root) {
    if (!selector) {
      return Ext.ComponentManager.getAll();
    }
    var results = [], noDupResults = [], dupMatcher = {}, query = cq.cache.get(selector), resultsLn, cmp, i;
    if (!query) {
      query = cq.cache.add(selector, cq.parse(selector));
    }
    results = query.execute(root);
    if (query.isMultiMatch()) {
      resultsLn = results.length;
      for (i = 0; i < resultsLn; i++) {
        cmp = results[i];
        if (!dupMatcher[cmp.id]) {
          noDupResults.push(cmp);
          dupMatcher[cmp.id] = true;
        }
      }
      results = noDupResults;
    }
    return results;
  }, visitPreOrder:function(selector, root, fn, scope, extraArgs) {
    cq._visit(true, selector, root, fn, scope, extraArgs);
  }, visitPostOrder:function(selector, root, fn, scope, extraArgs) {
    cq._visit(false, selector, root, fn, scope, extraArgs);
  }, _visit:function(preOrder, selector, root, fn, scope, extraArgs) {
    var query = cq.cache.get(selector), callArgs = [root], children, len = 0, i, rootMatch;
    if (!query) {
      query = cq.cache.add(selector, cq.parse(selector));
    }
    rootMatch = query.is(root);
    if (root.getRefItems) {
      children = root.getRefItems();
      len = children.length;
    }
    if (extraArgs) {
      Ext.Array.push(callArgs, extraArgs);
    }
    if (preOrder) {
      if (rootMatch) {
        if (fn.apply(scope || root, callArgs) === false) {
          return false;
        }
      }
    }
    for (i = 0; i < len; i++) {
      if (cq._visit.call(cq, preOrder, selector, children[i], fn, scope, extraArgs) === false) {
        return false;
      }
    }
    if (!preOrder) {
      if (rootMatch) {
        if (fn.apply(scope || root, callArgs) === false) {
          return false;
        }
      }
    }
  }, is:function(component, selector, root) {
    var query;
    if (!selector) {
      return true;
    }
    if (typeof selector === 'function') {
      return selector(component);
    } else {
      query = cq.cache.get(selector);
      if (!query) {
        query = cq.cache.add(selector, cq.parse(selector));
      }
      return query.is(component, root);
    }
  }, parse:function(selector) {
    var operations = [], selectors, sel, i, len;
    selectors = Ext.splitAndUnescape(selector, ',');
    for (i = 0, len = selectors.length; i < len; i++) {
      sel = Ext.String.trim(selectors[i]);
      if (sel === '') {
        Ext.raise('Invalid ComponentQuery selector: ""');
      }
      operations.push(cq._parse(sel));
    }
    return new cq.Query({operations:operations});
  }, _parse:function(selector) {
    var operations = [], trim = Ext.String.trim, length = matchers.length, lastSelector, tokenMatch, token, matchedChar, modeMatch, selectorMatch, transform, i, matcher, method, args;
    while (selector && lastSelector !== selector) {
      lastSelector = selector;
      tokenMatch = selector.match(tokenRe);
      if (tokenMatch) {
        matchedChar = tokenMatch[1];
        token = trim(tokenMatch[2]).replace(unescapeRe, '$1');
        if (matchedChar === '#') {
          operations.push({method:filterById, args:[token]});
        } else {
          operations.push({method:filterByXType, args:[token, Boolean(tokenMatch[3])]});
        }
        selector = selector.replace(tokenMatch[0], '').replace(stripLeadingSpaceRe, '$1');
      }
      while (!(modeMatch = selector.match(modeRe))) {
        for (i = 0; selector && i < length; i++) {
          matcher = matchers[i];
          selectorMatch = selector.match(matcher.re);
          method = matcher.method;
          transform = matcher.argTransform;
          if (selectorMatch) {
            if (transform) {
              args = transform(selectorMatch);
            } else {
              args = selectorMatch.slice(1);
            }
            operations.push({method:Ext.isString(matcher.method) ? Ext.functionFactory('items', Ext.String.format.apply(Ext.String, [method].concat(selectorMatch.slice(1)))) : matcher.method, args:args});
            selector = selector.replace(selectorMatch[0], '').replace(stripLeadingSpaceRe, '$1');
            break;
          }
          if (i === length - 1) {
            Ext.raise('Invalid ComponentQuery selector: "' + arguments[0] + '"');
          }
        }
      }
      if (modeMatch[1]) {
        operations.push({mode:modeMatch[2] || modeMatch[1]});
        selector = selector.replace(modeMatch[0], '').replace(stripLeadingSpaceRe, '');
      }
    }
    return operations;
  }});
  Ext.all = function() {
    return cq.query.apply(cq, arguments);
  };
  Ext.first = function() {
    var matches = cq.query.apply(cq, arguments);
    return matches && matches[0] || null;
  };
});
Ext.define('Ext.Evented', {alternateClassName:'Ext.EventedBase', mixins:[Ext.mixin.Observable], initialized:false, constructor:function(config) {
  this.callParent();
  this.mixins.observable.constructor.call(this, config);
  this.initialized = true;
}, onClassExtended:function(cls, data) {
  if (!data.hasOwnProperty('eventedConfig')) {
    return;
  }
  var config = data.config, eventedConfig = data.eventedConfig, name, cfg;
  if (config) {
    Ext.applyIf(config, eventedConfig);
  } else {
    cls.addConfig(eventedConfig);
  }
  for (name in eventedConfig) {
    if (eventedConfig.hasOwnProperty(name)) {
      cfg = Ext.Config.get(name);
      data[cfg.names.set] = cfg.eventedSetter || cfg.getEventedSetter();
    }
  }
}});
Ext.define('Ext.util.Positionable', {mixinId:'positionable', _positionTopLeft:['position', 'top', 'left'], clippedCls:Ext.baseCSSPrefix + 'clipped', afterSetPosition:Ext.emptyFn, getAnchorToXY:function() {
  Ext.raise('getAnchorToXY is not implemented in ' + this.$className);
}, getBorderPadding:function() {
  Ext.raise('getBorderPadding is not implemented in ' + this.$className);
}, getLocalX:function() {
  Ext.raise('getLocalX is not implemented in ' + this.$className);
}, getLocalXY:function() {
  Ext.raise('getLocalXY is not implemented in ' + this.$className);
}, getLocalY:function() {
  Ext.raise('getLocalY is not implemented in ' + this.$className);
}, getX:function() {
  Ext.raise('getX is not implemented in ' + this.$className);
}, getXY:function() {
  Ext.raise('getXY is not implemented in ' + this.$className);
}, getY:function() {
  Ext.raise('getY is not implemented in ' + this.$className);
}, setLocalX:function() {
  Ext.raise('setLocalX is not implemented in ' + this.$className);
}, setLocalXY:function() {
  Ext.raise('setLocalXY is not implemented in ' + this.$className);
}, setLocalY:function() {
  Ext.raise('setLocalY is not implemented in ' + this.$className);
}, setX:function() {
  Ext.raise('setX is not implemented in ' + this.$className);
}, setXY:function() {
  Ext.raise('setXY is not implemented in ' + this.$className);
}, setY:function() {
  Ext.raise('setY is not implemented in ' + this.$className);
}, adjustForConstraints:function(xy, parent) {
  var vector = this.getConstrainVector(parent, xy);
  if (vector) {
    xy[0] += vector[0];
    xy[1] += vector[1];
  }
  return xy;
}, alignTo:function(element, position, offsets, animate) {
  var me = this, el = me.el;
  return me.setXY(me.getAlignToXY(element, position, offsets), el.anim && !!animate ? el.anim(animate) : false);
}, calculateAnchorXY:function(anchor, extraX, extraY, size) {
  var region = this.getRegion();
  region.setPosition(0, 0);
  region.translateBy(extraX || 0, extraY || 0);
  if (size) {
    region.setWidth(size.width);
    region.setHeight(size.height);
  }
  return region.getAnchorPoint(anchor);
}, convertPositionSpec:function(posSpec) {
  return Ext.util.Region.getAlignInfo(posSpec);
}, getAlignToXY:function(alignToEl, position, offsets) {
  var newRegion = this.getAlignToRegion(alignToEl, position, offsets);
  return [newRegion.x, newRegion.y];
}, getAlignToRegion:function(alignToEl, posSpec, offset, minHeight) {
  var me = this, inside, newRegion, bodyScroll, oldOffset;
  alignToEl = Ext.fly(alignToEl.el || alignToEl);
  if (!alignToEl || !alignToEl.dom) {
    Ext.raise({sourceClass:'Ext.util.Positionable', sourceMethod:'getAlignToXY', msg:"Attempted to align an element that doesn't exist"});
  }
  posSpec = me.convertPositionSpec(posSpec);
  if (posSpec.constrain) {
    if (posSpec.constrain === '!') {
      inside = alignToEl;
    } else {
      inside = me.constrainTo || me.container || me.el.parent();
    }
    inside = Ext.fly(inside.el || inside).getConstrainRegion();
  }
  if (alignToEl === Ext.getBody()) {
    bodyScroll = alignToEl.getScroll();
    oldOffset = offset && offset.length === 2 ? offset : [0, 0];
    offset = [bodyScroll.left + oldOffset[0], bodyScroll.top + oldOffset[1]];
  }
  newRegion = me.getRegion().alignTo({target:alignToEl.getRegion(), inside:inside, minHeight:minHeight, offset:offset, align:posSpec, axisLock:true});
  return newRegion;
}, getAnchorXY:function(anchor, local, size) {
  var me = this, region = me.getRegion(), el = me.el, isViewport = el.dom.nodeName === 'BODY' || el.dom.nodeType === 9, scroll = el.getScroll();
  if (local) {
    region.setPosition(0, 0);
  } else {
    if (isViewport) {
      region.setPosition(scroll.left, scroll.top);
    }
  }
  if (size) {
    region.setWidth(size.width);
    region.setHeight(size.height);
  }
  return region.getAnchorPoint(anchor);
}, getBox:function(contentBox, local) {
  var me = this, xy = local ? me.getLocalXY() : me.getXY(), x = xy[0], y = xy[1], w, h, borderPadding, beforeX, beforeY;
  if (me.el.dom.nodeName === 'BODY' || me.el.dom.nodeType === 9) {
    w = Ext.Element.getViewportWidth();
    h = Ext.Element.getViewportHeight();
  } else {
    w = me.getWidth();
    h = me.getHeight();
  }
  if (contentBox) {
    borderPadding = me.getBorderPadding();
    beforeX = borderPadding.beforeX;
    beforeY = borderPadding.beforeY;
    x += beforeX;
    y += beforeY;
    w -= beforeX + borderPadding.afterX;
    h -= beforeY + borderPadding.afterY;
  }
  return {x:x, left:x, 0:x, y:y, top:y, 1:y, width:w, height:h, right:x + w, bottom:y + h};
}, calculateConstrainedPosition:function(constrainTo, proposedPosition, local, proposedSize) {
  var me = this, vector, fp = me.floatParent, parentNode = fp ? fp.getTargetEl() : null, parentOffset, borderPadding, proposedConstrainPosition, xy = false;
  if (local && fp) {
    parentOffset = parentNode.getXY();
    borderPadding = parentNode.getBorderPadding();
    parentOffset[0] += borderPadding.beforeX;
    parentOffset[1] += borderPadding.beforeY;
    if (proposedPosition) {
      proposedConstrainPosition = [proposedPosition[0] + parentOffset[0], proposedPosition[1] + parentOffset[1]];
    }
  } else {
    proposedConstrainPosition = proposedPosition;
  }
  constrainTo = constrainTo || me.constrainTo || parentNode || me.container || me.el.parent();
  if (local && proposedConstrainPosition) {
    proposedConstrainPosition = me.reverseTranslateXY(proposedConstrainPosition);
  }
  vector = (me.constrainHeader && me.header.rendered ? me.header : me).getConstrainVector(constrainTo, proposedConstrainPosition, proposedSize);
  if (vector) {
    xy = proposedPosition || me.getPosition(local);
    xy[0] += vector[0];
    xy[1] += vector[1];
  }
  return xy;
}, getConstrainRegion:function() {
  var me = this, el = me.el, isBody = el.dom.nodeName === 'BODY', dom = el.dom, borders = el.getBorders(), pos = el.getXY(), left = pos[0] + borders.beforeX, top = pos[1] + borders.beforeY, scroll, width, height;
  if (isBody) {
    scroll = el.getScroll();
    left = scroll.left;
    top = scroll.top;
    width = Ext.Element.getViewportWidth();
    height = Ext.Element.getViewportHeight();
  } else {
    width = dom.clientWidth;
    height = dom.clientHeight;
  }
  return new Ext.util.Region(top, left + width, top + height, left);
}, getConstrainVector:function(constrainTo, proposedPosition, proposedSize) {
  var me = this, thisRegion = me.getRegion(), vector = [0, 0], shadowSize = me.shadow && me.constrainShadow && !me.shadowDisabled ? me.el.shadow.getShadowSize() : undefined, overflowed = false, constraintInsets = me.constraintInsets;
  if (!(constrainTo instanceof Ext.util.Region)) {
    constrainTo = Ext.get(constrainTo.el || constrainTo);
    constrainTo = constrainTo.getConstrainRegion();
  }
  if (constraintInsets) {
    constraintInsets = Ext.isObject(constraintInsets) ? constraintInsets : Ext.Element.parseBox(constraintInsets);
    constrainTo.adjust(constraintInsets.top, constraintInsets.right, constraintInsets.bottom, constraintInsets.left);
  }
  if (proposedPosition) {
    thisRegion.translateBy(proposedPosition[0] - thisRegion.x, proposedPosition[1] - thisRegion.y);
  }
  if (proposedSize) {
    thisRegion.right = thisRegion.left + proposedSize[0];
    thisRegion.bottom = thisRegion.top + proposedSize[1];
  }
  if (shadowSize) {
    constrainTo.adjust(shadowSize[0], -shadowSize[1], -shadowSize[2], shadowSize[3]);
  }
  if (thisRegion.right > constrainTo.right) {
    overflowed = true;
    vector[0] = constrainTo.right - thisRegion.right;
  }
  if (thisRegion.left + vector[0] < constrainTo.left) {
    overflowed = true;
    vector[0] = constrainTo.left - thisRegion.left;
  }
  if (thisRegion.bottom > constrainTo.bottom) {
    overflowed = true;
    vector[1] = constrainTo.bottom - thisRegion.bottom;
  }
  if (thisRegion.top + vector[1] < constrainTo.top) {
    overflowed = true;
    vector[1] = constrainTo.top - thisRegion.top;
  }
  return overflowed ? vector : false;
}, getOffsetsTo:function(offsetsTo) {
  var o = this.getXY(), e = offsetsTo.isRegion ? [offsetsTo.x, offsetsTo.y] : Ext.fly(offsetsTo.el || offsetsTo).getXY();
  return [o[0] - e[0], o[1] - e[1]];
}, getRegion:function(contentBox, local) {
  var box = this.getBox(contentBox, local);
  return new Ext.util.Region(box.top, box.right, box.bottom, box.left);
}, getClientRegion:function() {
  var me = this, el = me.el, dom = el.dom, viewContentBox = me.getBox(true), scrollbarHeight = dom.offsetHeight > dom.clientHeight, scrollbarWidth = dom.offsetWidth > dom.clientWidth, padding, scrollSize, isRTL;
  if (scrollbarHeight || scrollbarWidth) {
    scrollSize = Ext.getScrollbarSize();
    if (scrollbarWidth) {
      scrollbarWidth = scrollSize.width;
      isRTL = el.getStyle('direction') === 'rtl' && !Ext.supports.rtlVertScrollbarOnRight;
      if (isRTL) {
        padding = el.getPadding('l');
        viewContentBox.left -= padding + Math.max(padding, scrollbarWidth);
      } else {
        padding = el.getPadding('r');
        viewContentBox.right += padding - Math.max(padding, scrollbarWidth);
      }
    }
    if (scrollbarHeight) {
      scrollbarHeight = scrollSize.height;
      padding = el.getPadding('b');
      viewContentBox.bottom += padding - Math.max(padding, scrollbarHeight);
    }
  }
  return new Ext.util.Region(viewContentBox.top, viewContentBox.right, viewContentBox.bottom, viewContentBox.left);
}, getViewRegion:function() {
  var me = this, el = me.el, isBody = el.dom.nodeName === 'BODY', borderPadding, scroll, pos, top, left, width, height;
  if (isBody) {
    scroll = el.getScroll();
    left = scroll.left;
    top = scroll.top;
    width = Ext.Element.getViewportWidth();
    height = Ext.Element.getViewportHeight();
  } else {
    borderPadding = me.getBorderPadding();
    pos = me.getXY();
    left = pos[0] + borderPadding.beforeX;
    top = pos[1] + borderPadding.beforeY;
    width = me.getWidth(true);
    height = me.getHeight(true);
  }
  return new Ext.util.Region(top, left + width, top + height, left);
}, move:function(direction, distance, animate) {
  var me = this, xy = me.getXY(), x = xy[0], y = xy[1], left = [x - distance, y], right = [x + distance, y], top = [x, y - distance], bottom = [x, y + distance], hash = {l:left, left:left, r:right, right:right, t:top, top:top, up:top, b:bottom, bottom:bottom, down:bottom};
  direction = direction.toLowerCase();
  me.setXY([hash[direction][0], hash[direction][1]], animate);
}, setBox:function(box) {
  var me = this, x, y;
  if (box.isRegion) {
    box = {x:box.left, y:box.top, width:box.right - box.left, height:box.bottom - box.top};
  }
  me.constrainBox(box);
  x = box.x;
  y = box.y;
  me.setXY([x, y]);
  me.setSize(box.width, box.height);
  me.afterSetPosition(x, y);
  return me;
}, constrainBox:function(box) {
  var me = this, constrainedPos, x, y;
  if (me.constrain || me.constrainHeader) {
    x = 'x' in box ? box.x : box.left;
    y = 'y' in box ? box.y : box.top;
    constrainedPos = me.calculateConstrainedPosition(null, [x, y], false, [box.width, box.height]);
    if (constrainedPos) {
      box.x = constrainedPos[0];
      box.y = constrainedPos[1];
    }
  }
}, translatePoints:function(x, y) {
  var pos = this.translateXY(x, y);
  return {left:pos.x, top:pos.y};
}, translateXY:function(x, y) {
  var me = this, el = me.el, styles = el.getStyle(me._positionTopLeft), relative = styles.position === 'relative', left = parseFloat(styles.left), top = parseFloat(styles.top), xy = me.getXY();
  if (Ext.isArray(x)) {
    y = x[1];
    x = x[0];
  }
  if (isNaN(left)) {
    left = relative ? 0 : el.dom.offsetLeft;
  }
  if (isNaN(top)) {
    top = relative ? 0 : el.dom.offsetTop;
  }
  left = typeof x === 'number' ? x - xy[0] + left : undefined;
  top = typeof y === 'number' ? y - xy[1] + top : undefined;
  return {x:left, y:top};
}, reverseTranslateXY:function(xy) {
  var coords = xy, el = this.el, dom = el.dom, offsetParent = dom.offsetParent, relative, offsetParentXY, x, y;
  if (offsetParent) {
    relative = el.isStyle('position', 'relative');
    offsetParentXY = Ext.fly(offsetParent).getXY();
    x = xy[0] + offsetParentXY[0] + offsetParent.clientLeft;
    y = xy[1] + offsetParentXY[1] + offsetParent.clientTop;
    if (relative) {
      x += el.getPadding('l');
      y += el.getPadding('t');
    }
    coords = [x, y];
  }
  return coords;
}, privates:{clipTo:function(clippingEl, sides) {
  var clippingRegion, el = this.el, floaterRegion = el.getRegion(), overflow, i, clipValues = [], clippedCls = this.clippedCls, clipStyle, clipped, shadow;
  if (clippingEl.isRegion) {
    clippingRegion = clippingEl;
  } else {
    clippingRegion = (clippingEl.isComponent ? clippingEl.el : Ext.fly(clippingEl)).getConstrainRegion();
  }
  if (!sides) {
    sides = 15;
  }
  if (sides & 1 && (overflow = clippingRegion.top - floaterRegion.top) > 0) {
    clipValues[0] = overflow;
    clipped = true;
  } else {
    clipValues[0] = -10000;
  }
  if (sides & 2 && (overflow = floaterRegion.right - clippingRegion.right) > 0) {
    clipValues[1] = Math.max(0, el.getWidth() - overflow);
    clipped = true;
  } else {
    clipValues[1] = 10000;
  }
  if (sides & 4 && (overflow = floaterRegion.bottom - clippingRegion.bottom) > 0) {
    clipValues[2] = Math.max(0, el.getHeight() - overflow);
    clipped = true;
  } else {
    clipValues[2] = 10000;
  }
  if (sides & 8 && (overflow = clippingRegion.left - floaterRegion.left) > 0) {
    clipValues[3] = overflow;
    clipped = true;
  } else {
    clipValues[3] = -10000;
  }
  clipStyle = 'rect(';
  for (i = 0; i < 4; ++i) {
    clipStyle += Ext.Element.addUnits(clipValues[i], 'px');
    clipStyle += i === 3 ? ')' : ',';
  }
  el.dom.style.clip = clipStyle;
  el.addCls(clippedCls);
  if ((shadow = el.shadow) && (el = shadow.el) && el.dom) {
    clipValues[2] -= shadow.offsets.y;
    clipValues[3] -= shadow.offsets.x;
    clipStyle = 'rect(';
    for (i = 0; i < 4; ++i) {
      clipStyle += Ext.Element.addUnits(clipValues[i], 'px');
      clipStyle += i === 3 ? ')' : ',';
    }
    el.dom.style.clip = clipStyle;
    if (clipped && !Ext.supports.CSS3BoxShadow) {
      el.dom.style.display = 'none';
    } else {
      el.dom.style.display = '';
      el.addCls(clippedCls);
    }
  }
}, clearClip:function() {
  var el = this.el, clippedCls = this.clippedCls;
  el.dom.style.clip = Ext.isIE8 ? 'auto' : '';
  el.removeCls(clippedCls);
  if (el.shadow && el.shadow.el && el.shadow.el.dom) {
    el.shadow.el.dom.style.clip = Ext.isIE8 ? 'auto' : '';
    if (!Ext.supports.CSS3BoxShadow) {
      el.dom.style.display = '';
      el.removeCls(clippedCls);
    }
  }
}}});
Ext.define('Ext.dom.UnderlayPool', {constructor:function(elementConfig) {
  this.elementConfig = elementConfig;
  this.cache = [];
}, checkOut:function() {
  var el = this.cache.shift();
  if (!el) {
    el = Ext.Element.create(this.elementConfig);
    el.setVisibilityMode(2);
    el.dom.setAttribute('data-sticky', true);
  }
  return el;
}, checkIn:function(el) {
  this.cache.push(el);
  Ext.getDetachedBody().dom.appendChild(el.dom);
}, reset:function() {
  var cache = this.cache, i = cache.length;
  while (i--) {
    cache[i].destroy();
  }
  this.cache = [];
}});
Ext.define('Ext.dom.Underlay', {constructor:function(config) {
  Ext.apply(this, config);
}, beforeShow:Ext.emptyFn, getInsertionTarget:function() {
  return this.target;
}, getPool:function() {
  return this.pool || (this.self.prototype.pool = new Ext.dom.UnderlayPool(this.elementConfig));
}, hide:function() {
  var me = this, el = me.el;
  if (el) {
    if (el.dom) {
      el.hide();
      me.getPool().checkIn(el);
    }
    me.el = null;
  }
  me.hidden = true;
}, realign:function(x, y, width, height) {
  var me = this, el = me.el, target = me.target, offsets = me.offsets, max = Math.max;
  if (el) {
    if (x == null) {
      x = target.getX();
    }
    if (y == null) {
      y = target.getY();
    }
    if (width == null) {
      width = target.getWidth();
    }
    if (height == null) {
      height = target.getHeight();
    }
    if (offsets) {
      x = x + offsets.x;
      y = y + offsets.y;
      width = max(width + offsets.w, 0);
      height = max(height + offsets.h, 0);
    }
    el.setXY([x, y]);
    el.setSize(width, height);
  }
}, setZIndex:function(zIndex) {
  this.zIndex = zIndex;
  if (this.el) {
    this.el.setStyle('z-index', zIndex);
  }
}, show:function() {
  var me = this, target = me.target, zIndex = me.zIndex, el = me.el, insertionTarget = me.getInsertionTarget().dom, dom;
  if (!el) {
    el = me.el = me.getPool().checkOut();
  }
  me.beforeShow();
  if (zIndex == null) {
    zIndex = parseInt(target.getStyle('z-index'), 10);
  }
  if (zIndex) {
    el.setStyle('z-index', zIndex);
  }
  el.setStyle('position', me.fixed ? 'fixed' : '');
  dom = el.dom;
  if (dom.nextSibling !== insertionTarget) {
    target.dom.parentNode.insertBefore(dom, insertionTarget);
  }
  el.show();
  me.realign();
  me.hidden = false;
}});
Ext.define('Ext.dom.Shadow', {extend:Ext.dom.Underlay, alternateClassName:'Ext.Shadow', mode:'drop', offset:4, cls:Ext.baseCSSPrefix + (!Ext.supports.CSS3BoxShadow ? 'ie' : 'css') + '-shadow', constructor:function(config) {
  var me = this, outerOffsets, offsets, offset, rad;
  me.callParent([config]);
  me.elementConfig = {cls:me.cls, role:'presentation'};
  offset = me.offset;
  rad = Math.floor(offset / 2);
  me.opacity = 50;
  switch(me.mode.toLowerCase()) {
    case 'drop':
      outerOffsets = {x:0, y:0, w:offset, h:offset};
      if (Ext.supports.CSS3BoxShadow) {
        offsets = {x:offset, y:offset, h:-offset, w:-offset};
      } else {
        offsets = {x:-rad, y:-rad, h:-rad, w:-rad};
      }
      break;
    case 'sides':
      outerOffsets = {x:-offset, y:0, w:offset * 2, h:offset};
      if (Ext.supports.CSS3BoxShadow) {
        offsets = {x:0, y:offset, h:-offset, w:0};
      } else {
        offsets = {x:1 + rad - 2 * offset, y:-(1 + rad), h:-1, w:rad - 1};
      }
      break;
    case 'frame':
      outerOffsets = {x:-offset, y:-offset, w:offset * 2, h:offset * 2};
      if (Ext.supports.CSS3BoxShadow) {
        offsets = {x:0, y:0, h:0, w:0};
      } else {
        offsets = {x:1 + rad - 2 * offset, y:1 + rad - 2 * offset, h:offset - rad - 1, w:offset - rad - 1};
      }
      break;
    case 'bottom':
      outerOffsets = {x:-offset, y:0, w:offset * 2, h:offset};
      if (Ext.supports.CSS3BoxShadow) {
        offsets = {x:0, y:offset, h:-offset, w:0};
      } else {
        offsets = {x:0, y:offset, h:0, w:0};
      }
      break;
  }
  me.offsets = offsets;
  me.outerOffsets = outerOffsets;
}, getShadowSize:function() {
  var me = this, offset = me.el ? me.offset : 0, result = [offset, offset, offset, offset], mode = me.mode.toLowerCase();
  if (me.el && mode !== 'frame') {
    result[0] = 0;
    if (mode === 'drop') {
      result[3] = 0;
    }
  }
  return result;
}, boxShadowProperty:function() {
  var property = 'boxShadow', style = document.documentElement.style;
  if (!('boxShadow' in style)) {
    if ('WebkitBoxShadow' in style) {
      property = 'WebkitBoxShadow';
    } else {
      if ('MozBoxShadow' in style) {
        property = 'MozBoxShadow';
      }
    }
  }
  return property;
}(), beforeShow:function() {
  var me = this, style = me.el.dom.style, shim = me.shim;
  if (Ext.supports.CSS3BoxShadow) {
    style[me.boxShadowProperty] = '0 0 ' + (me.offset + 2) + 'px #888';
  } else {
    style.filter = 'progid:DXImageTransform.Microsoft.alpha(opacity\x3d' + me.opacity + ') progid:DXImageTransform.Microsoft.Blur(pixelradius\x3d' + me.offset + ')';
  }
  if (shim) {
    shim.realign();
  }
}, setOpacity:function(opacity) {
  var el = this.el;
  if (el) {
    if (Ext.isIE && !Ext.supports.CSS3BoxShadow) {
      opacity = Math.floor(opacity * 100 / 2) / 100;
    }
    this.opacity = opacity;
    el.setOpacity(opacity);
  }
}});
Ext.define('Ext.dom.Shim', {extend:Ext.dom.Underlay, cls:Ext.baseCSSPrefix + 'shim', constructor:function(config) {
  this.callParent([config]);
  this.elementConfig = {tag:'iframe', cls:this.cls, role:'presentation', frameBorder:'0', src:Ext.SSL_SECURE_URL, tabindex:'-1'};
}, getInsertionTarget:function() {
  var shadow = this.shadow;
  return shadow && shadow.el || this.target;
}});
Ext.define('Ext.dom.ElementEvent', {extend:Ext.util.Event, addListener:function(fn, scope, options, caller, manager) {
  var me = this, added = false, name = me.name, isDirectEvent = Ext.event.publisher.Dom.instance.directEvents[name], captures, directs, directCaptures;
  options = options || {};
  if (options.delegated === false || isDirectEvent) {
    if (isDirectEvent && options.delegate) {
      options.capture = true;
    }
    if (options.capture) {
      directCaptures = me.directCaptures || (me.directCaptures = new Ext.util.Event(me.observable, name));
      added = directCaptures.addListener(fn, scope, options, caller, manager);
    } else {
      directs = me.directs || (me.directs = new Ext.util.Event(me.observable, name));
      added = directs.addListener(fn, scope, options, caller, manager);
    }
  } else {
    if (options.capture) {
      captures = me.captures || (me.captures = new Ext.util.Event(me.observable, name));
      added = captures.addListener(fn, scope, options, caller, manager);
    } else {
      added = me.callParent([fn, scope, options, caller, manager]);
    }
  }
  return added;
}, removeListener:function(fn, scope) {
  var me = this, captures = me.captures, directs = me.directs, directCaptures = me.directCaptures, removed = false, index = me.findListener(fn, scope);
  if (index !== -1) {
    removed = me.callParent([fn, scope, index]);
  } else {
    if (directs) {
      index = directs.findListener(fn, scope);
    }
    if (index !== -1) {
      removed = directs.removeListener(fn, scope, index);
    } else {
      if (captures) {
        index = captures.findListener(fn, scope);
      }
      if (index !== -1) {
        removed = captures.removeListener(fn, scope, index);
      } else {
        if (directCaptures) {
          index = directCaptures.findListener(fn, scope);
          if (index !== -1) {
            removed = directCaptures.removeListener(fn, scope, index);
          }
        }
      }
    }
  }
  return removed;
}, clearListeners:function() {
  var me = this, directCaptures = me.directCaptures, directs = me.directs, captures = me.captures;
  if (directCaptures) {
    directCaptures.clearListeners();
  }
  if (directs) {
    directs.clearListeners();
  }
  if (captures) {
    captures.clearListeners();
  }
  me.callParent();
}, suspend:function() {
  var me = this, directCaptures = me.directCaptures, directs = me.directs, captures = me.captures;
  if (directCaptures) {
    directCaptures.suspend();
  }
  if (directs) {
    directs.suspend();
  }
  if (captures) {
    captures.suspend();
  }
  me.callParent();
}, resume:function() {
  var me = this, directCaptures = me.directCaptures, directs = me.directs, captures = me.captures;
  if (directCaptures) {
    directCaptures.resume();
  }
  if (directs) {
    directs.resume();
  }
  if (captures) {
    captures.resume();
  }
  me.callParent();
}});
Ext.define('Ext.event.publisher.Publisher', {isEventPublisher:true, $vetoClearingPrototypeOnDestroy:true, handledEvents:[], statics:{publishers:{}, publishersByEvent:{}}, constructor:function() {
  var me = this, type = me.type;
  me.handles = {};
  if (!type) {
    Ext.raise("Event publisher '" + me.$className + "' defined without a 'type' property.");
  }
  if (me.self.instance) {
    Ext.raise("Cannot create multiple instances of '" + me.$className + "'. " + "Use '" + me.$className + ".instance' to retrieve the singleton instance.");
  }
  me.registerEvents();
  Ext.event.publisher.Publisher.publishers[type] = me;
}, registerEvents:function(events) {
  var me = this, publishersByEvent = Ext.event.publisher.Publisher.publishersByEvent, handledEvents = events || me.handledEvents, ln = handledEvents.length, eventName, i;
  for (i = 0; i < ln; i++) {
    eventName = handledEvents[i];
    me.handles[eventName] = 1;
    publishersByEvent[eventName] = me;
  }
}, subscribe:function() {
  Ext.raise("Ext.event.publisher.Publisher subclass '" + this.$className + '" has no subscribe method.');
}, unsubscribe:function() {
  Ext.raise("Ext.event.publisher.Publisher subclass '" + this.$className + '" has no unsubscribe method.');
}, fire:function(element, eventName, args) {
  var event;
  if (element.hasListeners[eventName]) {
    event = element.events[eventName];
    if (event) {
      event.fire.apply(event, args);
    }
  }
}});
Ext.define('Ext.util.Offset', {statics:{fromObject:function(obj) {
  if (obj instanceof this) {
    return obj;
  }
  if (typeof obj === 'number') {
    return new this(obj, obj);
  }
  if (obj.length) {
    return new this(obj[0], obj[1]);
  }
  return new this(obj.x, obj.y);
}}, constructor:function(x, y) {
  this.x = x != null && !isNaN(x) ? x : 0;
  this.y = y != null && !isNaN(y) ? y : 0;
  return this;
}, copy:function() {
  return new Ext.util.Offset(this.x, this.y);
}, copyFrom:function(p) {
  this.x = p.x;
  this.y = p.y;
}, toString:function() {
  return 'Offset[' + this.x + ',' + this.y + ']';
}, equals:function(offset) {
  if (!(offset instanceof this.statics())) {
    Ext.raise('Offset must be an instance of Ext.util.Offset');
  }
  return this.x === offset.x && this.y === offset.y;
}, add:function(offset) {
  if (!(offset instanceof this.statics())) {
    Ext.raise('Offset must be an instance of Ext.util.Offset');
  }
  this.x += offset.x;
  this.y += offset.y;
}, round:function(to) {
  var factor;
  if (!isNaN(to)) {
    factor = Math.pow(10, to);
    this.x = Math.round(this.x * factor) / factor;
    this.y = Math.round(this.y * factor) / factor;
  } else {
    this.x = Math.round(this.x);
    this.y = Math.round(this.y);
  }
}, isZero:function() {
  return this.x === 0 && this.y === 0;
}});
Ext.define('Ext.util.Region', function() {
  var ExtUtil = Ext.util, constrainRe = /([^\?!]*)(!|\?)?$/, alignRe = /^(?:(?:([trbl])(\d+))|(tl|t|tc|tr|l|c|r|bl|b|bc|br))(?:-(?:(?:([trbl])(\d+))|(tl|t|tc|tr|l|c|r|bl|b|bc|br)))?$/i, LTROffsetFactors = {l:0, r:100, t:0, b:100, c:50}, RTLOffsetFactors = {l:100, r:0, t:0, b:100, c:50}, relativePositions = {b:0, l:1, t:2, r:3}, alignMap = {'tl-tr':'l0-r0', 'tl-r':'l0-r50', 'bl-r':'l100-r50', 'bl-br':'l100-r100', 'tr-tl':'r0-l0', 'tr-l':'r0-l50', 'br-l':'r100-l50', 'br-bl':'r100-l100'}, rtlAlignMap = 
  {'tl-tr':'r0-l0', 'tl-r':'r0-l50', 'bl-r':'r100-l50', 'bl-br':'r100-l100', 'tr-tl':'l0-r0', 'tr-l':'l0-r50', 'br-l':'l100-r50', 'br-bl':'l100-r100'}, adjustParams = [], zeroOffset = new ExtUtil.Offset(0, 0), parseRegion = function(box) {
    var Region = ExtUtil.Region, type = typeof box, top, right, bottom, left;
    if (box == null) {
      return Region.EMPTY;
    }
    if (box.isRegion) {
      return box;
    }
    if (box.isElement || box.nodeType === 1) {
      return this.getRegion(box);
    }
    if (type === 'string') {
      box = box.split(' ');
      switch(box.length) {
        case 1:
          box[1] = box[2] = box[3] = box[0];
          break;
        case 2:
          box[2] = box[0];
          box[3] = box[1];
          break;
        case 3:
          box[3] = box[1];
      }
      top = parseInt(box[0], 10) || 0;
      right = parseInt(box[1], 10) || 0;
      bottom = parseInt(box[2], 10) || 0;
      left = parseInt(box[3], 10) || 0;
    } else {
      if (type === 'number') {
        top = right = bottom = left = box;
      } else {
        if (typeof box.x === 'number') {
          top = box.y;
          left = box.x;
          if (typeof box.right === 'number') {
            right = box.right;
            bottom = box.bottom;
          } else {
            right = left + box.width;
            bottom = top + box.height;
          }
        } else {
          Ext.raise('Not convertible to a Region: ' + box);
        }
      }
    }
    return new Region(top, right, bottom, left);
  }, magnitude = [-1, 1, 1, -1], addAnchorOffset = function(target, anchorSize, relativePosition) {
    if (relativePosition != null && anchorSize) {
      adjustParams[0] = adjustParams[1] = adjustParams[2] = adjustParams[3] = 0;
      adjustParams[relativePosition] = anchorSize.y * magnitude[relativePosition];
      target = ExtUtil.Region.from(target);
      target.adjust.apply(target, adjustParams);
    }
    return target;
  }, calculateAnchorPosition = function(target, result, relativePosition, anchorSize, inside) {
    var anchorWidth = Math.ceil(anchorSize.x), minOverlap = Math.ceil(anchorWidth / 2) + 3, min, max, anchorPos, isBefore, overlapLine, x, y;
    if (inside && !inside.intersect(target)) {
      return;
    }
    if (relativePosition != null) {
      if (relativePosition & 1) {
        if (result.getHeight() < anchorWidth + 4) {
          return;
        }
        min = target.top + minOverlap - result.height;
        max = target.bottom - minOverlap - 1;
        result.setPosition(result.x, Math.min(Math.max(result.y, min), max));
        min = result.top + 2;
        max = result.bottom - (anchorWidth + 2);
        isBefore = relativePosition === 3;
        x = isBefore ? result.right : result.left;
        overlapLine = new ExtUtil.Region(Math.max(result.top, target.top), x, Math.min(result.bottom, target.bottom), x);
        anchorPos = (new ExtUtil.Region(0, 0, 0, 0)).setWidth(anchorSize.y).setHeight(anchorWidth).alignTo({target:overlapLine, align:isBefore ? 'l-r' : 'r-l', overlap:true});
        anchorPos.setPosition(anchorPos.x, Math.min(Math.max(anchorPos.y, min), max));
        anchorPos.position = isBefore ? 'right' : 'left';
      } else {
        if (result.getWidth() < anchorWidth + 4) {
          return;
        }
        min = target.left + minOverlap - result.width;
        max = target.right - minOverlap - 1;
        result.setPosition(Math.min(Math.max(result.x, min), max), result.y);
        min = result.left + 2;
        max = result.right - (anchorWidth + 2);
        isBefore = relativePosition === 0;
        y = isBefore ? result.bottom : result.top;
        overlapLine = new ExtUtil.Region(y, Math.min(result.right, target.right), y, Math.max(result.left, target.left));
        anchorPos = (new ExtUtil.Region(0, 0, 0, 0)).setWidth(anchorWidth).setHeight(anchorSize.y).alignTo({target:overlapLine, align:isBefore ? 't-b' : 'b-t', overlap:true});
        anchorPos.setPosition(Math.min(Math.max(anchorPos.x, min), max), anchorPos.y);
        anchorPos.position = isBefore ? 'bottom' : 'top';
      }
      if (inside && !inside.contains(anchorPos)) {
        return;
      }
      result.anchor = anchorPos;
      result.anchor.align = relativePosition;
    }
  }, checkMinHeight = function(minHeight, result, target, inside) {
    var newHeight;
    if (minHeight && inside) {
      if (result.top >= target.bottom && result.bottom > inside.bottom) {
        result.setHeight(Math.max(result.getHeight() + inside.bottom - result.bottom, minHeight));
        result.constrainHeight = true;
      } else {
        if (result.bottom <= target.top && result.top < inside.top) {
          newHeight = Math.max(result.getHeight() + result.top - inside.top, minHeight);
          result.adjust(result.getHeight() - newHeight);
          result.constrainHeight = true;
        } else {
          if (result.getHeight() > inside.getHeight()) {
            result.setHeight(Math.max(minHeight, inside.getHeight()));
            result.setPosition(result.x, 0);
            result.constrainHeight = true;
          }
        }
      }
    }
  }, checkMinWidth = function(minWidth, result, target, inside) {
    var newWidth;
    if (minWidth && inside) {
      if (result.left >= target.right && result.right > inside.right) {
        result.setWidth(Math.max(result.getWidth() + inside.right - result.right, minWidth));
        result.constrainWidth = true;
      } else {
        if (result.right <= target.left && result.left < inside.left) {
          newWidth = Math.max(result.getWidth() + result.left - inside.left, minWidth);
          result.adjust(0, 0, 0, result.getWidth() - newWidth);
          result.constrainWidth = true;
        } else {
          if (result.getWidth() > inside.getWidth()) {
            result.setWidth(Math.max(minWidth, inside.getWidth()));
            result.setPosition(0, result.y);
            result.constrainWidth = true;
          }
        }
      }
    }
  };
  return {isRegion:true, statics:{getRegion:function(el) {
    return Ext.fly(el).getRegion();
  }, from:function(o) {
    return new this(o.top, o.right, o.bottom, o.left);
  }, getAlignInfo:function(align, rtl) {
    if (typeof align === 'object') {
      return align;
    }
    align = align ? align.indexOf('-') < 0 ? 'tl-' + align : align : 'tl-bl';
    constrain = constrainRe.exec(align);
    align = constrain[1];
    align = (rtl ? rtlAlignMap : alignMap)[align] || align;
    var offsetFactors = rtl ? RTLOffsetFactors : LTROffsetFactors, constrain, parts = alignRe.exec(align), result;
    if (!parts) {
      Ext.raise({sourceClass:'Ext.util.Region', sourceMethod:'getAlignInfo', position:align, msg:'Attempted to align an element with an invalid position: "' + align + '"'});
    }
    result = {myEdge:parts[1], myOffset:parts[2], otherEdge:parts[4], otherOffset:parts[5], constrain:constrain[2]};
    if (parts[3]) {
      result.myEdge = parts[3][0];
      result.myOffset = offsetFactors[parts[3][1]];
      if (result.myOffset == null) {
        result.myOffset = 50;
      }
    }
    if (parts[6]) {
      result.otherEdge = parts[6][0];
      result.otherOffset = offsetFactors[parts[6][1]];
      if (result.otherOffset == null) {
        result.otherOffset = 50;
      }
    }
    result.position = relativePositions[result.myEdge];
    return result;
  }}, constructor:function(top, right, bottom, left) {
    var me = this;
    me.y = me.top = me[1] = top;
    me.right = right;
    me.bottom = bottom;
    me.x = me.left = me[0] = left;
    me.height = me.bottom - me.top;
    me.width = me.right - me.left;
  }, setPosition:function(x, y) {
    if (arguments.length === 1) {
      y = x[1];
      x = x[0];
    }
    return this.translateBy(x - this.x, y - this.y);
  }, contains:function(region) {
    var me = this;
    return region.x >= me.x && (region.right || region.x) <= me.right && region.y >= me.y && (region.bottom || region.y) <= me.bottom;
  }, intersect:function(region) {
    var me = this, t = Math.max(me.y, region.y), r = Math.min(me.right, region.right), b = Math.min(me.bottom, region.bottom), l = Math.max(me.x, region.x);
    if (b > t && r > l) {
      return new this.self(t, r, b, l);
    } else {
      return false;
    }
  }, union:function(region) {
    var me = this, t = Math.min(me.y, region.y), r = Math.max(me.right, region.right), b = Math.max(me.bottom, region.bottom), l = Math.min(me.x, region.x);
    return new this.self(t, r, b, l);
  }, constrainTo:function(targetRegion) {
    var me = this, constrain = Ext.Number.constrain;
    me.top = me.y = constrain(me.top, targetRegion.y, targetRegion.bottom);
    me.bottom = constrain(me.bottom, targetRegion.y, targetRegion.bottom);
    me.left = me.x = constrain(me.left, targetRegion.x, targetRegion.right);
    me.right = constrain(me.right, targetRegion.x, targetRegion.right);
    me.height = me.bottom - me.top;
    me.width = me.right - me.left;
    return me;
  }, adjust:function(top, right, bottom, left) {
    var me = this;
    me.top = me.y += top || 0;
    me.left = me.x += left || 0;
    me.right += right || 0;
    me.bottom += bottom || 0;
    me.height = me.bottom - me.top;
    me.width = me.right - me.left;
    return me;
  }, getOutOfBoundOffset:function(axis, p) {
    var d;
    if (!Ext.isObject(axis)) {
      if (axis === 'x') {
        return this.getOutOfBoundOffsetX(p);
      } else {
        return this.getOutOfBoundOffsetY(p);
      }
    } else {
      p = axis;
      d = new ExtUtil.Offset;
      d.x = this.getOutOfBoundOffsetX(p.x);
      d.y = this.getOutOfBoundOffsetY(p.y);
      return d;
    }
  }, getOutOfBoundOffsetX:function(p) {
    if (p <= this.x) {
      return this.x - p;
    } else {
      if (p >= this.right) {
        return this.right - p;
      }
    }
    return 0;
  }, getOutOfBoundOffsetY:function(p) {
    if (p <= this.y) {
      return this.y - p;
    } else {
      if (p >= this.bottom) {
        return this.bottom - p;
      }
    }
    return 0;
  }, isOutOfBound:function(axis, p) {
    if (!Ext.isObject(axis)) {
      if (axis === 'x') {
        return this.isOutOfBoundX(p);
      } else {
        return this.isOutOfBoundY(p);
      }
    } else {
      p = axis;
      return this.isOutOfBoundX(p.x) || this.isOutOfBoundY(p.y);
    }
  }, isOutOfBoundX:function(p) {
    return p < this.x || p > this.right;
  }, isOutOfBoundY:function(p) {
    return p < this.y || p > this.bottom;
  }, restrict:function(axis, p, factor) {
    var newP;
    if (Ext.isObject(axis)) {
      factor = p;
      p = axis;
      if (p.copy) {
        newP = p.copy();
      } else {
        newP = {x:p.x, y:p.y};
      }
      newP.x = this.restrictX(p.x, factor);
      newP.y = this.restrictY(p.y, factor);
      return newP;
    } else {
      if (axis === 'x') {
        return this.restrictX(p, factor);
      } else {
        return this.restrictY(p, factor);
      }
    }
  }, restrictX:function(p, factor) {
    if (!factor) {
      factor = 1;
    }
    if (p <= this.x) {
      p -= (p - this.x) * factor;
    } else {
      if (p >= this.right) {
        p -= (p - this.right) * factor;
      }
    }
    return p;
  }, restrictY:function(p, factor) {
    if (!factor) {
      factor = 1;
    }
    if (p <= this.y) {
      p -= (p - this.y) * factor;
    } else {
      if (p >= this.bottom) {
        p -= (p - this.bottom) * factor;
      }
    }
    return p;
  }, alignTo:function(options) {
    var me = this, Region = me.self, Offset = ExtUtil.Offset, Element = Ext.Element, target = parseRegion(options.target), targetPlusAnchorOffset, rtl = options.rtl, overlap = options.overlap, align = options.align, anchorSize = options.anchorSize, offset = options.offset, inside = options.inside, position = options.position, allowXTranslate = options.allowXTranslate, allowYTranslate = options.allowYTranslate, wasConstrained, result, initialPosition, constrainedPosition;
    if (offset) {
      offset = Offset.fromObject(offset);
      if (!(offset instanceof Offset)) {
        Ext.raise('offset option must be an Ext.util.Offset');
      }
    }
    if (anchorSize) {
      anchorSize = Offset.fromObject(anchorSize);
      if (!(anchorSize instanceof Offset)) {
        Ext.raise('anchorSize option must be an Ext.util.Offset');
      }
    }
    if (inside && !inside.isRegion) {
      if (Ext.getDom(inside) === document.body) {
        inside = new Region(0, Element.getDocumentWidth(), Element.getDocumentHeight(), 0);
      } else {
        inside = Ext.fly(inside).getRegion();
      }
    }
    if (position) {
      if (position.length === 2) {
        position = new ExtUtil.Point(position[0], position[1]);
      }
      result = (new Region).copyFrom(me).setPosition(position.x, position.y);
    } else {
      align = me.getAlignInfo(align, rtl);
      if (inside) {
        if (target.x >= inside.right) {
          target.setPosition(inside.right - 1, target.y);
          if (align.position !== 3) {
            align = me.getAlignInfo('r-l', rtl);
          }
        } else {
          if (target.right < inside.x) {
            target.setPosition(inside.x - target.getWidth() + 1, target.y);
            if (align.position !== 1) {
              align = me.getAlignInfo('l-r', rtl);
            }
          }
        }
        if (target.y >= inside.bottom) {
          target.setPosition(target.x, inside.bottom - 1);
          if (align.position !== 0) {
            align = me.getAlignInfo('b-t', rtl);
          }
        } else {
          if (target.bottom < inside.y) {
            target.setPosition(target.x, inside.y - target.getHeight() + 1);
            if (align.position !== 2) {
              align = me.getAlignInfo('t-b', rtl);
            }
          }
        }
      }
      targetPlusAnchorOffset = anchorSize ? addAnchorOffset(target, anchorSize, align.position) : target;
      result = Region.from(me).translateBy(me.getAlignToVector(targetPlusAnchorOffset, align));
      overlap = !!result.intersect(targetPlusAnchorOffset);
      if (offset && (overlap || !anchorSize)) {
        result.translateBy(offset);
      }
      if (anchorSize) {
        calculateAnchorPosition(target, result, align.position, anchorSize, inside);
      }
    }
    if (inside) {
      initialPosition = result.copy();
      if (result.left < inside.left) {
        result.translateBy(inside.left - result.left, 0);
        wasConstrained = true;
      }
      if (result.right > inside.right && result.left > inside.left) {
        result.translateBy(inside.right - result.right, 0);
        wasConstrained = true;
      }
      if (result.top < inside.top) {
        result.translateBy(0, inside.top - result.top);
        wasConstrained = true;
      }
      if (result.bottom > inside.bottom && result.top > inside.top) {
        result.translateBy(0, inside.bottom - result.bottom);
        wasConstrained = true;
      }
      if (wasConstrained && !overlap) {
        result.anchor = null;
        if (options.axisLock) {
          if (align.position & 1) {
            allowYTranslate = false;
          } else {
            allowXTranslate = false;
          }
        }
        if (position) {
          if (result.contains(position)) {
            position.exclude(result, {inside:inside, centerOnSideChange:false});
          }
        } else {
          constrainedPosition = result.copy();
          if (result.intersect(targetPlusAnchorOffset)) {
            align.position = target.exclude(result, {initialPosition:initialPosition, defaultPosition:align.position, inside:inside, minHeight:options.minHeight, minWidth:options.minWidth, allowX:allowXTranslate, allowY:allowYTranslate, offset:offset, anchorHeight:anchorSize ? anchorSize.y : 0, centerOnSideChange:!!anchorSize});
          } else {
            if (options.minWidth && result.getWidth() > inside.getWidth()) {
              result.setPosition(0, result.y);
              result.setWidth(Math.max(inside.getWidth(), options.minWidth));
              result.constrainWidth = true;
            } else {
              if (options.minHeight && result.getHeight() > inside.getHeight()) {
                result.setPosition(result.x, 0);
                result.setHeight(Math.max(inside.getHeight(), options.minHeight));
                result.constrainHeight = true;
              }
            }
          }
          result.align = align;
          if (inside.contains(result)) {
            if (anchorSize) {
              calculateAnchorPosition(target, result, align.position, anchorSize, inside);
            }
          } else {
            result = constrainedPosition;
          }
        }
      }
    }
    return result;
  }, exclude:function(other, options) {
    options = options || {};
    var me = this, initialPosition = options.initialPosition || other, inside = options.inside, defaultPosition = options.defaultPosition, centerOnSideChange = options.centerOnSideChange, minHeight = options.minHeight, minWidth = options.minWidth, allowX = options.allowX !== false, allowY = options.allowY !== false, anchorHeight = options.anchorHeight, offset = options.offset, translations = [], testRegion, t, i, sizeConstrainedSolution, leastBadSolution, intersection, result;
    if (!offset) {
      offset = zeroOffset;
    }
    if (allowY) {
      translations.push([0, me.top - other.bottom - anchorHeight + offset.y, 'b-t', 0, Math.abs(me.top - initialPosition.bottom - anchorHeight + offset.y)]);
      translations.push([0, me.bottom - other.top + anchorHeight + offset.y, 't-b', 2, Math.abs(me.bottom - initialPosition.top + anchorHeight + offset.y)]);
    } else {
      centerOnSideChange = false;
    }
    if (allowX) {
      translations.push([me.left - other.right - anchorHeight + offset.x, 0, 'r-l', 3, Math.abs(me.left - initialPosition.right - anchorHeight + offset.x)]);
      translations.push([me.right - other.left + anchorHeight + offset.x, 0, 'l-r', 1, Math.abs(me.right - initialPosition.left + anchorHeight + offset.x)]);
    } else {
      centerOnSideChange = false;
    }
    Ext.Array.sort(translations, function(l, r) {
      var result = l[4] - r[4];
      if (!result) {
        if (l[3] === defaultPosition) {
          return -1;
        }
        if (r[3] === defaultPosition) {
          return 1;
        }
      }
      return result;
    });
    if (inside) {
      for (i = 0; i < translations.length; i++) {
        t = translations[i];
        testRegion = ExtUtil.Region.from(other);
        testRegion.translateBy.apply(testRegion, t);
        if (inside.contains(testRegion)) {
          other.copyFrom(testRegion);
          result = {align:t[2], position:t[3], distance:t[4]};
          break;
        }
        if (minHeight) {
          checkMinHeight(minHeight, testRegion, me, inside);
          if (inside.contains(testRegion)) {
            if (!sizeConstrainedSolution || testRegion.getArea() > sizeConstrainedSolution.region.getArea()) {
              sizeConstrainedSolution = {region:testRegion, align:t[2], position:t[3], distance:t[4]};
            }
          }
        }
        if (minWidth) {
          checkMinWidth(minWidth, testRegion, me, inside);
          if (inside.contains(testRegion)) {
            if (!sizeConstrainedSolution || testRegion.getArea() > sizeConstrainedSolution.region.getArea()) {
              sizeConstrainedSolution = {region:testRegion, align:t[2], position:t[3], distance:t[4]};
            }
          }
        }
        intersection = inside.intersect(testRegion);
        if (intersection) {
          intersection = intersection.getArea();
          if (!leastBadSolution || intersection && leastBadSolution.area < intersection) {
            leastBadSolution = {region:testRegion, align:t[2], position:t[3], distance:t[4], area:intersection};
          }
        }
      }
      if (!result) {
        if (sizeConstrainedSolution) {
          other.copyFrom(sizeConstrainedSolution.region);
          result = sizeConstrainedSolution;
          other.constrainWidth = sizeConstrainedSolution.region.constrainWidth;
          other.constrainHeight = sizeConstrainedSolution.region.constrainHeight;
        } else {
          if (leastBadSolution) {
            other.copyFrom(leastBadSolution.region);
            result = leastBadSolution;
          }
        }
      }
      if (result) {
        if ((result.position & 1) !== (defaultPosition & 1)) {
          if (result.distance && centerOnSideChange) {
            t = other.alignTo({align:result.align, target:me, anchorSize:anchorHeight, offset:offset, axisLock:true, inside:inside, minHeight:options.minHeight, minWidth:options.minWidth});
            if (inside.contains(t)) {
              other.setPosition(t.x, t.y);
            }
          }
        }
        return result.position;
      }
    } else {
      other.translateBy.apply(other, translations[0]);
      return translations[0][3];
    }
    return defaultPosition;
  }, getAlignToXY:function(target, align, rtl) {
    var alignVector = this.getAlignToVector(target, align, rtl);
    return [this.x + alignVector[0], this.y + alignVector[1]];
  }, getAnchorPoint:function(align, rtl) {
    align = typeof align === 'string' ? this.getAlignInfo(align + '-tl', rtl) : align;
    return this['getAnchorPoint_' + align.myEdge](align.myOffset);
  }, getAlignToVector:function(target, align, rtl) {
    align = typeof align === 'string' ? this.getAlignInfo(align, rtl) : align;
    var myAnchorPoint = this['getAnchorPoint_' + align.myEdge](align.myOffset), targetAnchorPoint = target['getAnchorPoint_' + align.otherEdge](align.otherOffset);
    return [targetAnchorPoint[0] - myAnchorPoint[0], targetAnchorPoint[1] - myAnchorPoint[1]];
  }, getAnchorPoint_t:function(offset) {
    return [this.x + Math.round(this.getWidth() * (offset / 100)), this.y];
  }, getAnchorPoint_b:function(offset) {
    return [this.x + Math.round(this.getWidth() * (offset / 100)), this.bottom];
  }, getAnchorPoint_l:function(offset) {
    return [this.x, this.y + Math.round(this.getHeight() * (offset / 100))];
  }, getAnchorPoint_r:function(offset) {
    return [this.right, this.y + Math.round(this.getHeight() * (offset / 100))];
  }, getAnchorPoint_c:function() {
    return [this.x + Math.round(this.getWidth() / 2), this.y + Math.round(this.getHeight() / 2)];
  }, getCenter:function() {
    return [this.x + this.width / 2, this.y + this.height / 2];
  }, getHeight:function() {
    return this.bottom - this.y;
  }, getWidth:function() {
    return this.right - this.x;
  }, getArea:function() {
    return this.getHeight() * this.getWidth();
  }, setHeight:function(h) {
    this.height = h;
    this.bottom = this.top + h;
    return this;
  }, setWidth:function(w) {
    this.width = w;
    this.right = this.left + w;
    return this;
  }, getSize:function() {
    return {width:this.right - this.x, height:this.bottom - this.y};
  }, setSize:function(w, h) {
    if (h === undefined) {
      h = w;
    }
    this.setWidth(w);
    return this.setHeight(h);
  }, copy:function() {
    return new this.self(this.y, this.right, this.bottom, this.x);
  }, copyFrom:function(p) {
    var me = this;
    me.top = me.y = me[1] = p.y;
    me.right = p.right;
    me.bottom = p.bottom;
    me.left = me.x = me[0] = p.x;
    return me;
  }, toString:function() {
    return 'Region[' + this.top + ',' + this.right + ',' + this.bottom + ',' + this.left + ']';
  }, translateBy:function(x, y) {
    var me = this;
    if (x.length) {
      y = x[1];
      x = x[0];
    } else {
      if (arguments.length === 1) {
        y = x.y;
        x = x.x;
      }
    }
    me.top = me.y += y;
    me.right += x;
    me.bottom += y;
    me.left = me.x += x;
    return me;
  }, round:function() {
    var me = this;
    me.top = me.y = Math.round(me.y);
    me.right = Math.round(me.right);
    me.bottom = Math.round(me.bottom);
    me.left = me.x = Math.round(me.x);
    return me;
  }, equals:function(region) {
    return this.top === region.top && this.right === region.right && this.bottom === region.bottom && this.left === region.left;
  }, getOffsetsTo:function(offsetsTo) {
    return {x:this.x - offsetsTo.x, y:this.y - offsetsTo.y};
  }, highlight:function() {
    var highlightEl = Ext.getBody().createChild({style:'background-color:#52a0db;opacity:0.4;position:absolute;z-index:9999999'});
    highlightEl.setBox(this);
    Ext.defer(function() {
      highlightEl.destroy();
    }, 5000);
    return highlightEl;
  }};
}, function(Region) {
  Region.prototype.getAlignInfo = Region.getAlignInfo;
  Region.EMPTY = new Region(0, 0, 0, 0);
  if (Object.freeze) {
    Object.freeze(Region.EMPTY);
  }
});
Ext.define('Ext.util.Point', {extend:Ext.util.Region, isPoint:true, radianToDegreeConstant:180 / Math.PI, origin:{x:0, y:0}, statics:{fromEvent:function(e) {
  var changedTouches = e.changedTouches, touch = changedTouches && changedTouches.length > 0 ? changedTouches[0] : e;
  return this.fromTouch(touch);
}, fromTouch:function(touch) {
  return new this(touch.pageX, touch.pageY);
}, from:function(object) {
  if (!object) {
    return new this(0, 0);
  }
  if (!(object instanceof this)) {
    return new this(object.x, object.y);
  }
  return object;
}}, constructor:function(x, y) {
  if (x == null) {
    x = 0;
  }
  if (y == null) {
    y = 0;
  }
  this.callParent([y, x, y, x]);
}, clone:function() {
  return new this.self(this.x, this.y);
}, copy:function() {
  return this.clone.apply(this, arguments);
}, copyFrom:function(point) {
  this.x = point.x;
  this.y = point.y;
  return this;
}, toString:function() {
  return 'Point[' + this.x + ',' + this.y + ']';
}, equals:function(point) {
  return this.x === point.x && this.y === point.y;
}, isCloseTo:function(point, threshold) {
  if (typeof threshold === 'number') {
    return this.getDistanceTo(point) <= threshold;
  }
  var x = point.x, y = point.y, thresholdX = threshold.x, thresholdY = threshold.y;
  return this.x <= x + thresholdX && this.x >= x - thresholdX && this.y <= y + thresholdY && this.y >= y - thresholdY;
}, isWithin:function() {
  return this.isCloseTo.apply(this, arguments);
}, isContainedBy:function(region) {
  if (!(region instanceof Ext.util.Region)) {
    region = Ext.get(region.el || region).getRegion();
  }
  return region.contains(this);
}, roundedEquals:function(point) {
  if (!point || typeof point !== 'object') {
    point = this.origin;
  }
  return Math.round(this.x) === Math.round(point.x) && Math.round(this.y) === Math.round(point.y);
}, getDistanceTo:function(point) {
  if (!point || typeof point !== 'object') {
    point = this.origin;
  }
  var deltaX = this.x - point.x, deltaY = this.y - point.y;
  return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
}, getAngleTo:function(point) {
  if (!point || typeof point !== 'object') {
    point = this.origin;
  }
  var deltaX = this.x - point.x, deltaY = this.y - point.y;
  return Math.atan2(deltaY, deltaX) * this.radianToDegreeConstant;
}}, function() {
  this.prototype.translate = this.prototype.translateBy;
});
Ext.define('Ext.event.Event', {alternateClassName:'Ext.EventObjectImpl', stopped:false, claimed:false, defaultPrevented:false, isEvent:true, geckoRelatedTargetEvents:{blur:1, dragenter:1, dragleave:1, focus:1}, statics:{resolveTextNode:function(node) {
  return node && node.nodeType === 3 ? node.parentNode : node;
}, gestureEvents:{}, pointerEvents:{pointerdown:1, pointermove:1, pointerup:1, pointercancel:1, pointerover:1, pointerout:1, pointerenter:1, pointerleave:1, MSPointerDown:1, MSPointerMove:1, MSPointerUp:1, MSPointerOver:1, MSPointerOut:1, MSPointerCancel:1, MSPointerEnter:1, MSPointerLeave:1}, mouseEvents:{mousedown:1, mousemove:1, mouseup:1, mouseover:1, mouseout:1, mouseenter:1, mouseleave:1}, clickEvents:{click:1, dblclick:1}, touchEvents:{touchstart:1, touchmove:1, touchend:1, touchcancel:1}, 
focusEvents:{focus:1, focusin:1, focusenter:1}, blurEvents:{blur:1, focusout:1, focusleave:1}, wheelEvents:{wheel:1}, pointerTypeMap:{2:'touch', 3:'pen', 4:'mouse', touch:'touch', pen:'pen', mouse:'mouse'}, keyEventRe:/^key/, keyFlags:{CTRL:'ctrlKey', CONTROL:'ctrlKey', ALT:'altKey', SHIFT:'shiftKey', CMD:'metaKey', COMMAND:'metaKey', CMDORCTRL:Ext.isMac ? 'metaKey' : 'ctrlKey', COMMANDORCONTROL:Ext.isMac ? 'metaKey' : 'ctrlKey', META:'metaKey'}, modifierGlyphs:{ctrlKey:'⌃', altKey:'⌥', metaKey:Ext.isMac ? 
'⌘' : '⊞', shiftKey:'⇧'}, specialKeyGlyphs:{BACKSPACE:'⌫', TAB:'⇥', ENTER:'⏎', RETURN:'⏎', SPACE:'␣', PAGE_UP:'⇞', PAGE_DOWN:'⇟', END:'⇲', HOME:'⌂', LEFT:'←', UP:'↑', RIGHT:'→', DOWN:'↓', PRINT_SCREEN:'⎙', INSERT:'⎀', DELETE:'⌦', CONTEXT_MENU:'☰'}, _hyphenRe:/^[a-z]+\-/i, getKeyId:function(keyName) {
  if (typeof keyName === 'number') {
    keyName = this.keyCodes[keyName];
  } else {
    keyName = keyName.toUpperCase();
  }
  var me = this, delim = me._hyphenRe.test(keyName) ? '-' : '+', parts = keyName === delim ? [delim] : keyName.split(delim), numModifiers = parts.length - 1, rawKey = parts[numModifiers], result = [], eventFlag, i;
  if (!Ext.event.Event[rawKey]) {
    Ext.raise('Invalid key name: "' + rawKey + '"');
  }
  for (i = 0; i < numModifiers; i++) {
    eventFlag = me.keyFlags[parts[i]];
    if (!eventFlag) {
      Ext.raise('Invalid key modifier: "' + parts[i] + '"');
    }
    result[eventFlag] = true;
  }
  if (result.ctrlKey) {
    result.push(me.modifierGlyphs.ctrlKey);
  }
  if (result.altKey) {
    result.push(me.modifierGlyphs.altKey);
  }
  if (result.shiftKey) {
    result.push(me.modifierGlyphs.shiftKey);
  }
  if (result.metaKey) {
    result.push(me.modifierGlyphs.metaKey);
  }
  result.push(this.specialKeyGlyphs[rawKey] || rawKey);
  return result.join('');
}, globalTabKeyDown:function(e) {
  if (e.keyCode === 9) {
    Ext.event.Event.forwardTab = !e.shiftKey;
  }
}, globalTabKeyUp:function(e) {
  if (e.keyCode === 9) {
    delete Ext.event.Event.forwardTab;
  }
}}, constructor:function(event) {
  var me = this, self = me.self, resolveTextNode = me.self.resolveTextNode, changedTouches = event.changedTouches, coordinateOwner = changedTouches ? changedTouches[0] : event, type = event.type, pointerType, relatedTarget;
  me.timeStamp = me.time = Ext.ticks();
  me.pageX = coordinateOwner.pageX;
  me.pageY = coordinateOwner.pageY;
  me.clientX = coordinateOwner.clientX;
  me.clientY = coordinateOwner.clientY;
  me.target = me.delegatedTarget = resolveTextNode(event.target);
  me.currentTarget = resolveTextNode(event.currentTarget);
  relatedTarget = event.relatedTarget;
  if (relatedTarget) {
    if (Ext.isGecko && me.geckoRelatedTargetEvents[type]) {
      try {
        me.relatedTarget = resolveTextNode(relatedTarget);
      } catch (e$47) {
        me.relatedTarget = null;
      }
    } else {
      me.relatedTarget = resolveTextNode(relatedTarget);
    }
  }
  me.browserEvent = me.event = event;
  me.type = type;
  me.button = event.button || 0;
  me.shiftKey = event.shiftKey;
  me.ctrlKey = event.ctrlKey || event.metaKey || false;
  me.altKey = event.altKey;
  me.charCode = event.charCode;
  me.keyCode = event.keyCode;
  me.buttons = event.buttons;
  if (me.button === 0 && me.buttons === 0) {
    me.buttons = 1;
  }
  if (self.focusEvents[type] || self.blurEvents[type]) {
    if (self.forwardTab !== undefined) {
      me.forwardTab = self.forwardTab;
    }
    if (self.focusEvents[type]) {
      me.fromElement = event.relatedTarget;
      me.toElement = event.target;
    } else {
      me.fromElement = event.target;
      me.toElement = event.relatedTarget;
    }
  } else {
    if (type !== 'keydown') {
      delete self.forwardTab;
    }
  }
  if (self.mouseEvents[type]) {
    pointerType = 'mouse';
  } else {
    if (self.clickEvents[type]) {
      pointerType = self.pointerTypeMap[event.pointerType] || (Ext.now() - Ext.event.publisher.Dom.lastTouchEndTime < 1000 ? 'touch' : 'mouse');
    } else {
      if (self.pointerEvents[type]) {
        pointerType = self.pointerTypeMap[event.pointerType] || 'mouse';
      } else {
        if (self.touchEvents[type]) {
          pointerType = 'touch';
        }
      }
    }
  }
  if (pointerType) {
    me.pointerType = pointerType;
  }
  me.isMultitouch = event.isPrimary === false || event.touches && event.touches.length > 1;
  if (self.wheelEvents[type]) {
    me.getWheelDeltas();
  }
}, chain:function(props) {
  var e = Ext.Object.chain(this);
  e.parentEvent = this;
  return Ext.apply(e, props);
}, correctWheelDelta:function(delta) {
  var me = this, deltaMode = me.browserEvent.deltaMode, correctedDelta = delta;
  if (deltaMode === 0) {
    correctedDelta = delta * me.WHEEL_PIXEL_SIZE;
  } else {
    if (deltaMode === 1) {
      correctedDelta = delta * me.WHEEL_LINE_SIZE;
    } else {
      if (deltaMode === 2) {
        correctedDelta = delta * me.WHEEL_PAGE_SIZE;
      }
    }
  }
  return Math.round(correctedDelta);
}, getChar:function() {
  var r = this.which();
  return String.fromCharCode(r);
}, getCharCode:function() {
  return this.charCode || this.keyCode;
}, getKey:function() {
  return this.keyCode || this.charCode;
}, getKeyName:function() {
  return this.type === 'keypress' ? String.fromCharCode(this.getCharCode()) : this.keyCodes[this.keyCode];
}, key:function() {
  return this.browserEvent.key;
}, which:function() {
  var me = this, e = me.browserEvent, r = e.which;
  if (r == null) {
    if (me.self.keyEventRe.test(e.type)) {
      r = e.charCode || e.keyCode;
    } else {
      if ((r = e.button) !== undefined) {
        r = r & 1 ? 1 : r & 4 ? 2 : r & 2 ? 3 : 0;
      }
    }
  }
  return r;
}, getClipboardData:function(type) {
  var clipboardData = this.browserEvent.clipboardData, clipIE = Ext.global.clipboardData, result = null, typeIE;
  type = type || 'text/plain';
  if (clipboardData && clipboardData.getData) {
    result = clipboardData.getData(type);
  } else {
    if (clipIE && clipIE.getData) {
      typeIE = this.ieMimeType[type];
      if (typeIE) {
        result = clipIE.getData(typeIE);
      }
    }
  }
  return result;
}, getPoint:function() {
  var me = this, point = me.point, xy;
  if (!point) {
    xy = me.getXY();
    point = me.point = new Ext.util.Point(xy[0], xy[1]);
  }
  return point;
}, getRelatedTarget:function(selector, maxDepth, returnEl) {
  var relatedTarget = this.relatedTarget, target = null;
  if (relatedTarget && relatedTarget.nodeType) {
    if (selector) {
      target = Ext.fly(relatedTarget).findParent(selector, maxDepth, returnEl);
    } else {
      target = returnEl ? Ext.get(relatedTarget) : relatedTarget;
    }
  }
  return target;
}, getTarget:function(selector, maxDepth, returnEl) {
  return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : returnEl ? Ext.get(this.target) : this.target;
}, getTime:function() {
  return this.time;
}, getWheelDelta:function() {
  var deltas = this.getWheelDeltas();
  return deltas.y;
}, getWheelDeltas:function() {
  var me = this, wheelDeltas = me.wheelDeltas, browserEvent, deltaX, deltaY;
  if (!wheelDeltas) {
    browserEvent = me.browserEvent;
    deltaX = me.correctWheelDelta(browserEvent.deltaX || 0);
    deltaY = browserEvent.deltaY;
    deltaY = me.correctWheelDelta(deltaY == null ? -browserEvent.wheelDelta : deltaY);
    me.deltaX = deltaX;
    me.deltaY = deltaY;
    me.wheelDeltas = wheelDeltas = {x:deltaX, y:deltaY};
  }
  return wheelDeltas;
}, getX:function() {
  return this.getXY()[0];
}, getXY:function() {
  var me = this, xy = me.xy;
  if (!xy) {
    xy = me.xy = [me.pageX, me.pageY];
    var x = xy[0], browserEvent, doc, docEl, body;
    if (!x && x !== 0) {
      browserEvent = me.browserEvent;
      doc = document;
      docEl = doc.documentElement;
      body = doc.body;
      xy[0] = browserEvent.clientX + (docEl && docEl.scrollLeft || body && body.scrollLeft || 0) - (docEl && docEl.clientLeft || body && body.clientLeft || 0);
      xy[1] = browserEvent.clientY + (docEl && docEl.scrollTop || body && body.scrollTop || 0) - (docEl && docEl.clientTop || body && body.clientTop || 0);
    }
  }
  return xy;
}, getLocalXY:function(clip) {
  var pageXY = this.getXY(), targetXY = Ext.fly(this.currentTarget).getXY(), localX = pageXY[0] - targetXY[0], localY = pageXY[1] - targetXY[1], size;
  if (clip) {
    size = Ext.fly(this.currentTarget).getSize();
    localX = Math.max(0, Math.min(localX, size.width));
    localY = Math.max(0, Math.min(localY, size.height));
  }
  return [localX, localY];
}, getY:function() {
  return this.getXY()[1];
}, hasModifier:function() {
  var me = this;
  return !!(me.ctrlKey || me.altKey || me.shiftKey || me.metaKey);
}, isNavKeyPress:function(scrollableOnly) {
  var me = this, k = me.keyCode, isKeyPress = me.type === 'keypress';
  return (!isKeyPress || Ext.isGecko) && k >= 33 && k <= 40 || !scrollableOnly && (k === me.RETURN || k === me.TAB || k === me.ESC);
}, isSpecialKey:function() {
  var me = this, k = me.keyCode, isGecko = Ext.isGecko, isKeyPress = me.type === 'keypress';
  return isGecko && isKeyPress && me.charCode === 0 || this.isNavKeyPress() || k === me.BACKSPACE || k === me.ENTER || k >= 16 && k <= 20 || (!isKeyPress || isGecko) && k >= 44 && k <= 46;
}, makeUnpreventable:function() {
  this.browserEvent.preventDefault = Ext.emptyFn;
}, preventDefault:function() {
  var me = this, parentEvent = me.parentEvent;
  me.defaultPrevented = true;
  if (parentEvent) {
    parentEvent.defaultPrevented = true;
  }
  me.browserEvent.preventDefault();
  return me;
}, setCurrentTarget:function(target) {
  this.currentTarget = this.delegatedTarget = target;
}, stopEvent:function() {
  return this.preventDefault().stopPropagation();
}, mousedownEvents:{mousedown:1, pointerdown:1, touchstart:1}, mouseupEvents:{mouseup:1, pointerup:1, touchend:1}, stopPropagation:function() {
  var me = this, browserEvent = me.browserEvent, parentEvent = me.parentEvent;
  if (me.mousedownEvents[me.type]) {
    Ext.GlobalEvents.fireMouseDown(me);
  }
  if (me.mouseupEvents[me.type]) {
    Ext.GlobalEvents.fireMouseUp(me);
  }
  me.stopped = true;
  if (parentEvent && !me.isGesture) {
    parentEvent.stopped = true;
  }
  if (!browserEvent.stopPropagation) {
    browserEvent.cancelBubble = true;
    return me;
  }
  browserEvent.stopPropagation();
  return me;
}, claimGesture:function() {
  var me = this, parentEvent = me.parentEvent;
  me.claimed = true;
  if (parentEvent && !me.isGesture) {
    parentEvent.claimGesture();
  } else {
    me.preventDefault();
  }
  return me;
}, within:function(el, related, allowEl) {
  var t;
  if (el) {
    t = related ? this.getRelatedTarget() : this.getTarget();
  }
  if (!t || allowEl === false && t === Ext.getDom(el)) {
    return false;
  }
  return Ext.fly(el).contains(t);
}, privates:{ieMimeType:{'text/plain':'Text'}}, deprecated:{'4.0':{methods:{getPageX:'getX', getPageY:'getY'}}}}, function(Event) {
  var constants = {BACKSPACE:8, TAB:9, NUM_CENTER:12, ENTER:13, RETURN:13, SHIFT:16, CTRL:17, ALT:18, PAUSE:19, CAPS_LOCK:20, ESC:27, SPACE:32, PAGE_UP:33, PAGE_DOWN:34, END:35, HOME:36, LEFT:37, UP:38, RIGHT:39, DOWN:40, PRINT_SCREEN:44, INSERT:45, DELETE:46, ZERO:48, ONE:49, TWO:50, THREE:51, FOUR:52, FIVE:53, SIX:54, SEVEN:55, EIGHT:56, NINE:57, A:65, B:66, C:67, D:68, E:69, F:70, G:71, H:72, I:73, J:74, K:75, L:76, M:77, N:78, O:79, P:80, Q:81, R:82, S:83, T:84, U:85, V:86, W:87, X:88, Y:89, 
  Z:90, META:91, CONTEXT_MENU:93, NUM_ZERO:96, NUM_ONE:97, NUM_TWO:98, NUM_THREE:99, NUM_FOUR:100, NUM_FIVE:101, NUM_SIX:102, NUM_SEVEN:103, NUM_EIGHT:104, NUM_NINE:105, NUM_MULTIPLY:106, NUM_PLUS:107, NUM_MINUS:109, NUM_PERIOD:110, NUM_DIVISION:111, F1:112, F2:113, F3:114, F4:115, F5:116, F6:117, F7:118, F8:119, F9:120, F10:121, F11:122, F12:123, WHEEL_PIXEL_SIZE:1, WHEEL_LINE_SIZE:20, WHEEL_PAGE_SIZE:600}, keyCodes = {}, gestureEvents = Event.gestureEvents, prototype = Event.prototype, i, keyName, 
  keyCode, keys;
  Ext.apply(gestureEvents, Event.mouseEvents);
  Ext.apply(gestureEvents, Event.pointerEvents);
  Ext.apply(gestureEvents, Event.touchEvents);
  Ext.apply(Event, constants);
  Ext.apply(prototype, constants);
  delete constants.RETURN;
  for (keyName in constants) {
    keyCode = constants[keyName];
    keyCodes[keyCode] = keyName;
  }
  Event.keyCodes = prototype.keyCodes = keyCodes;
  if (!Ext.isIE9m) {
    document.addEventListener('keydown', Event.globalTabKeyDown, true);
    document.addEventListener('keyup', Event.globalTabKeyUp, true);
  }
  prototype.getTrueXY = prototype.getXY;
  if (typeof KeyboardEvent !== 'undefined' && !('key' in KeyboardEvent.prototype)) {
    prototype._keys = keys = {3:'Cancel', 6:'Help', 8:'Backspace', 9:'Tab', 12:'Clear', 13:'Enter', 16:'Shift', 17:'Control', 18:'Alt', 19:'Pause', 20:'CapsLock', 27:'Escape', 28:'Convert', 29:'NonConvert', 30:'Accept', 31:'ModeChange', 32:' ', 33:'PageUp', 34:'PageDown', 35:'End', 36:'Home', 37:'ArrowLeft', 38:'ArrowUp', 39:'ArrowRight', 40:'ArrowDown', 41:'Select', 42:'Print', 43:'Execute', 44:'PrintScreen', 45:'Insert', 46:'Delete', 48:['0', ')'], 49:['1', '!'], 50:['2', '@'], 51:['3', '#'], 52:['4', 
    '$'], 53:['5', '%'], 54:['6', '^'], 55:['7', '\x26'], 56:['8', '*'], 57:['9', '('], 91:'OS', 93:'ContextMenu', 144:'NumLock', 145:'ScrollLock', 181:'VolumeMute', 182:'VolumeDown', 183:'VolumeUp', 186:[';', ':'], 187:['\x3d', '+'], 188:[',', '\x3c'], 189:['-', '_'], 190:['.', '\x3e'], 191:['/', '?'], 192:['`', '~'], 219:['[', '{'], 220:['\\', '|'], 221:[']', '}'], 222:["'", '"'], 224:'Meta', 225:'AltGraph', 246:'Attn', 247:'CrSel', 248:'ExSel', 249:'EraseEof', 250:'Play', 251:'ZoomOut'};
    for (i = 1; i < 25; ++i) {
      keys[i + 111] = 'F' + i;
    }
    for (i = 0; i < 26; ++i) {
      keys[i] = [String.fromCharCode(i + 97), String.fromCharCode(i + 65)];
    }
    prototype.key = function() {
      var k = keys[this.browserEvent.which || this.keyCode];
      if (k && typeof k !== 'string') {
        k = k[+this.shiftKey];
      }
      return k;
    };
  }
});
Ext.define('Ext.event.publisher.Dom', {extend:Ext.event.publisher.Publisher, type:'dom', handledDomEvents:[], reEnterCount:0, captureEvents:{animationstart:1, animationend:1, resize:1, focus:1, blur:1}, directEvents:{mouseenter:1, mouseleave:1, pointerenter:1, pointerleave:1, MSPointerEnter:1, MSPointerLeave:1, load:1, unload:1, beforeunload:1, error:1, DOMContentLoaded:1, DOMFrameContentLoaded:1, hashchange:1, scroll:1, online:1, offline:1}, blockedPointerEvents:{pointerover:1, pointerout:1, pointerenter:1, 
pointerleave:1, MSPointerOver:1, MSPointerOut:1, MSPointerEnter:1, MSPointerLeave:1}, blockedCompatibilityMouseEvents:{mouseenter:1, mouseleave:1}, constructor:function() {
  var me = this, supportsPassive = Ext.supports.PassiveEventListener;
  me.listenerOptions = supportsPassive ? {passive:false} : false;
  me.captureOptions = supportsPassive ? {passive:false, capture:true} : true;
  me.bubbleSubscribers = {};
  me.captureSubscribers = {};
  me.directSubscribers = {};
  me.directCaptureSubscribers = {};
  me.delegatedListeners = {};
  me.initHandlers();
  Ext.onInternalReady(me.onReady, me);
  me.callParent();
  me.registerDomEvents();
}, registerDomEvents:function() {
  var me = this, publishersByEvent = Ext.event.publisher.Publisher.publishersByEvent, domEvents = me.handledDomEvents, ln = domEvents.length, i, eventName;
  for (i = 0; i < ln; i++) {
    eventName = domEvents[i];
    me.handles[eventName] = 1;
    publishersByEvent[eventName] = me;
  }
}, onReady:function() {
  var me = this, domEvents = me.handledDomEvents, ln, i;
  if (domEvents) {
    for (i = 0, ln = domEvents.length; i < ln; i++) {
      me.addDelegatedListener(domEvents[i]);
    }
  }
  Ext.getWin().on('unload', me.destroy, me, {priority:-10000});
}, initHandlers:function() {
  var me = this;
  me.onDelegatedEvent = Ext.bind(me.onDelegatedEvent, me);
  me.onDirectEvent = Ext.bind(me.onDirectEvent, me);
  me.onDirectCaptureEvent = Ext.bind(me.onDirectCaptureEvent, me);
}, addDelegatedListener:function(eventName) {
  var me = this;
  me.delegatedListeners[eventName] = 1;
  me.target.addEventListener(eventName, me.onDelegatedEvent, me.captureEvents[eventName] ? me.captureOptions : me.listenerOptions);
}, removeDelegatedListener:function(eventName) {
  var me = this;
  delete me.delegatedListeners[eventName];
  me.target.removeEventListener(eventName, me.onDelegatedEvent, me.captureEvents[eventName] ? me.captureOptions : me.listenerOptions);
}, addDirectListener:function(eventName, element, capture) {
  var me = this;
  element.dom.addEventListener(eventName, capture ? me.onDirectCaptureEvent : me.onDirectEvent, capture ? me.captureOptions : me.listenerOptions);
}, removeDirectListener:function(eventName, element, capture) {
  var me = this;
  element.dom.removeEventListener(eventName, capture ? me.onDirectCaptureEvent : me.onDirectEvent, capture ? me.captureOptions : me.listenerOptions);
}, subscribe:function(element, eventName, delegated, capture) {
  var me = this, subscribers, id;
  if (delegated && !me.directEvents[eventName]) {
    subscribers = capture ? me.captureSubscribers : me.bubbleSubscribers;
    if (!me.handles[eventName] && !me.delegatedListeners[eventName]) {
      me.addDelegatedListener(eventName);
    }
    if (subscribers[eventName]) {
      ++subscribers[eventName];
    } else {
      subscribers[eventName] = 1;
    }
  } else {
    subscribers = capture ? me.directCaptureSubscribers : me.directSubscribers;
    id = element.id;
    subscribers = subscribers[eventName] || (subscribers[eventName] = {});
    if (subscribers[id]) {
      ++subscribers[id];
    } else {
      subscribers[id] = 1;
      me.addDirectListener(eventName, element, capture);
    }
  }
}, unsubscribe:function(element, eventName, delegated, capture) {
  var me = this, captureSubscribers, bubbleSubscribers, subscribers, id;
  if (delegated && !me.directEvents[eventName]) {
    captureSubscribers = me.captureSubscribers;
    bubbleSubscribers = me.bubbleSubscribers;
    subscribers = capture ? captureSubscribers : bubbleSubscribers;
    if (subscribers[eventName]) {
      --subscribers[eventName];
    }
    if (!me.handles[eventName] && !bubbleSubscribers[eventName] && !captureSubscribers[eventName]) {
      this.removeDelegatedListener(eventName);
    }
  } else {
    subscribers = capture ? me.directCaptureSubscribers : me.directSubscribers;
    id = element.id;
    subscribers = subscribers[eventName];
    if (subscribers[id]) {
      --subscribers[id];
    }
    if (!subscribers[id]) {
      delete subscribers[id];
      me.removeDirectListener(eventName, element, capture);
    }
  }
}, getPropagatingTargets:function(target) {
  var currentNode = target, targets = [], parentNode;
  while (currentNode) {
    targets.push(currentNode);
    parentNode = currentNode.parentNode;
    if (!parentNode) {
      parentNode = currentNode.defaultView;
    }
    currentNode = parentNode;
  }
  return targets;
}, publish:function(e, targets, claimed) {
  var me = this, hasCaptureSubscribers = false, hasBubbleSubscribers = false, events, type, target, el, i, ln, j, eLn;
  claimed = claimed || false;
  if (!targets) {
    if (e instanceof Array) {
      Ext.raise('Propagation targets must be supplied when publishing ' + 'an array of events.');
    }
    target = e.target;
    if (me.captureEvents[e.type]) {
      el = Ext.cache[target.id];
      targets = el ? [el] : [];
    } else {
      targets = me.getPropagatingTargets(target);
    }
  }
  events = Ext.Array.from(e);
  ln = targets.length;
  eLn = events.length;
  for (i = 0; i < eLn; i++) {
    type = events[i].type;
    if (!hasCaptureSubscribers && me.captureSubscribers[type]) {
      hasCaptureSubscribers = true;
    }
    if (!hasBubbleSubscribers && me.bubbleSubscribers[type]) {
      hasBubbleSubscribers = true;
    }
  }
  if (hasCaptureSubscribers) {
    for (i = ln; i--;) {
      el = Ext.cache[targets[i].id];
      if (el) {
        for (j = 0; j < eLn; j++) {
          e = events[j];
          me.fire(el, e.type, e, false, true);
          if (!claimed && e.claimed) {
            claimed = true;
            j = me.filterClaimed(events, e);
            eLn = events.length;
          }
          if (e.stopped) {
            events.splice(j, 1);
            j--;
            eLn--;
          }
        }
      }
    }
  }
  if (hasBubbleSubscribers && !e.stopped) {
    for (i = 0; i < ln; i++) {
      el = Ext.cache[targets[i].id];
      if (el) {
        for (j = 0; j < eLn; j++) {
          e = events[j];
          me.fire(el, e.type, e, false, false);
          if (!claimed && e.claimed && me.filterClaimed) {
            claimed = true;
            j = me.filterClaimed(events, e);
            eLn = events.length;
          }
          if (e.stopped) {
            events.splice(j, 1);
            j--;
            eLn--;
          }
        }
      }
    }
  }
}, publishDelegatedDomEvent:function(e) {
  this.publish(e);
}, fire:function(element, eventName, e, direct, capture) {
  var event;
  if (element.hasListeners[eventName]) {
    event = element.events[eventName];
    if (event) {
      if (capture && direct) {
        event = event.directCaptures;
      } else {
        if (capture) {
          event = event.captures;
        } else {
          if (direct) {
            event = event.directs;
          }
        }
      }
      if (event) {
        e.setCurrentTarget(element.dom);
        event.fire(e, e.target);
      }
    }
  }
}, onDelegatedEvent:function(e) {
  if (Ext.elevateFunction) {
    Ext.elevateFunction(this.doDelegatedEvent, this, [e]);
  } else {
    this.doDelegatedEvent(e);
  }
}, doDelegatedEvent:function(e) {
  var me = this, timeStamp;
  e = new Ext.event.Event(e);
  timeStamp = e.time;
  if (!me.isEventBlocked(e)) {
    me.beforeEvent(e);
    Ext.frameStartTime = timeStamp;
    me.reEnterCountAdjusted = false;
    me.reEnterCount++;
    me.publishDelegatedDomEvent(e);
    if (!me.reEnterCountAdjusted) {
      me.reEnterCount--;
    }
    me.afterEvent(e);
  }
}, onDirectEvent:function(e) {
  if (Ext.elevateFunction) {
    Ext.elevateFunction(this.doDirectEvent, this, [e, false]);
  } else {
    this.doDirectEvent(e, false);
  }
}, onDirectCaptureEvent:function(e) {
  if (Ext.elevateFunction) {
    Ext.elevateFunction(this.doDirectEvent, this, [e, true]);
  } else {
    this.doDirectEvent(e, true);
  }
}, doDirectEvent:function(e, capture) {
  var me = this, currentTarget = e.currentTarget, timeStamp, el;
  e = new Ext.event.Event(e);
  timeStamp = e.time;
  if (me.isEventBlocked(e)) {
    return;
  }
  me.beforeEvent(e);
  Ext.frameStartTime = timeStamp;
  el = Ext.cache[currentTarget.id];
  if (el) {
    me.reEnterCountAdjusted = false;
    me.reEnterCount++;
    me.fire(el, e.type, e, true, capture);
    if (!me.reEnterCountAdjusted) {
      me.reEnterCount--;
    }
  }
  me.afterEvent(e);
}, beforeEvent:function(e) {
  var browserEvent = e.browserEvent, self = Ext.event.publisher.Dom, touches, touch;
  if (browserEvent.type === 'touchstart') {
    touches = browserEvent.touches;
    if (touches.length === 1) {
      touch = touches[0];
      self.lastTouchStartX = touch.pageX;
      self.lastTouchStartY = touch.pageY;
    }
  }
}, afterEvent:function(e) {
  var browserEvent = e.browserEvent, type = browserEvent.type, self = Ext.event.publisher.Dom, GlobalEvents = Ext.GlobalEvents;
  if (e.self.pointerEvents[type] && e.pointerType !== 'mouse') {
    self.lastScreenPointerEventTime = Ext.now();
  }
  if (type === 'touchend') {
    self.lastTouchEndTime = Ext.now();
  }
  if (!this.reEnterCount && !GlobalEvents.idleEventMask[type]) {
    Ext.fireIdle();
  }
}, isEventBlocked:function(e) {
  var me = this, type = e.type, self = Ext.event.publisher.Dom, now = Ext.now();
  if (Ext.isGecko && e.type === 'click' && e.button === 2) {
    return true;
  }
  return me.blockedPointerEvents[type] && e.pointerType !== 'mouse' || me.blockedCompatibilityMouseEvents[type] && now - self.lastScreenPointerEventTime < 1000 || Ext.supports.TouchEvents && e.self.mouseEvents[e.type] && Math.abs(e.pageX - self.lastTouchStartX) < 15 && Math.abs(e.pageY - self.lastTouchStartY) < 15 && Ext.now() - self.lastTouchEndTime < 1000;
}, destroy:function() {
  var GC = Ext.dom['GarbageCollector'], eventName;
  for (eventName in this.delegatedListeners) {
    this.removeDelegatedListener(eventName);
  }
  Ext.Reaper.flush();
  if (GC) {
    GC.collect();
  }
  this.callParent();
}, reset:function() {
  var self = Ext.event.publisher.Dom;
  this.reEnterCount = 0;
  self.lastScreenPointerEventTime = self.lastTouchEndTime = self.lastTouchStartX = self.lastTouchStartY = undefined;
}}, function(Dom) {
  var doc = document, defaultView = doc.defaultView, prototype = Dom.prototype;
  if (Ext.os.is.iOS && window.self !== window.top || Ext.browser.is.AndroidStock || !(defaultView && defaultView.addEventListener)) {
    prototype.target = doc;
  } else {
    prototype.target = defaultView;
  }
  Dom.instance = new Dom;
});
Ext.define('Ext.event.publisher.Gesture', {extend:Ext.event.publisher.Dom, type:'gesture', isCancelEvent:{touchcancel:1, pointercancel:1, MSPointerCancel:1}, isEndEvent:{mouseup:1, touchend:1, pointerup:1, MSPointerUp:1}, handledEvents:[], handledDomEvents:[], constructor:function(config) {
  var me = this, handledDomEvents = me.handledDomEvents, supports = Ext.supports, supportsTouchEvents = supports.TouchEvents, onTouchStart = me.onTouchStart, onTouchMove = me.onTouchMove, onTouchEnd = me.onTouchEnd;
  me.handlers = {touchstart:onTouchStart, touchmove:onTouchMove, touchend:onTouchEnd, touchcancel:onTouchEnd, pointerdown:onTouchStart, pointermove:onTouchMove, pointerup:onTouchEnd, pointercancel:onTouchEnd, MSPointerDown:onTouchStart, MSPointerMove:onTouchMove, MSPointerUp:onTouchEnd, MSPointerCancel:onTouchEnd, mousedown:onTouchStart, mousemove:onTouchMove, mouseup:onTouchEnd};
  me.activeTouchesMap = {};
  me.activeTouches = [];
  me.changedTouches = [];
  me.recognizers = [];
  me.eventToRecognizer = {};
  me.cancelEvents = [];
  if (supportsTouchEvents) {
    me.onTargetTouchMove = me.onTargetTouchMove.bind(me);
    me.onTargetTouchEnd = me.onTargetTouchEnd.bind(me);
  }
  if (supports.PointerEvents) {
    handledDomEvents.push('pointerdown', 'pointermove', 'pointerup', 'pointercancel');
    me.mousePointerType = 'mouse';
  } else {
    if (supports.MSPointerEvents) {
      handledDomEvents.push('MSPointerDown', 'MSPointerMove', 'MSPointerUp', 'MSPointerCancel');
      me.mousePointerType = 4;
    } else {
      if (supportsTouchEvents) {
        handledDomEvents.push('touchstart', 'touchmove', 'touchend', 'touchcancel');
      }
    }
  }
  if (!handledDomEvents.length || supportsTouchEvents && Ext.os.is.Desktop) {
    handledDomEvents.push('mousedown', 'mousemove', 'mouseup');
  }
  me.initConfig(config);
  return me.callParent();
}, onReady:function() {
  this.callParent();
  Ext.Array.sort(this.recognizers, function(recognizerA, recognizerB) {
    var a = recognizerA.priority, b = recognizerB.priority;
    return a > b ? 1 : a < b ? -1 : 0;
  });
}, registerRecognizer:function(recognizer) {
  var me = this, handledEvents = recognizer.handledEvents, ln = handledEvents.length, eventName, i;
  recognizer.setOnRecognized(me.onRecognized);
  recognizer.setCallbackScope(me);
  for (i = 0; i < ln; i++) {
    eventName = handledEvents[i];
    me.handledEvents.push(eventName);
    me.eventToRecognizer[eventName] = recognizer;
  }
  me.registerEvents(handledEvents);
  me.recognizers.push(recognizer);
}, onRecognized:function(recognizer, eventName, e, info, isCancel) {
  var me = this, touches = e.touches, changedTouches = e.changedTouches, ln = changedTouches.length, events = me.events, queueWasEmpty = !events.length, cancelEvents = me.cancelEvents, targetGroups, targets, i, touch;
  info = info || {};
  info.type = eventName;
  info.target = changedTouches[0].target;
  info.stopped = false;
  info.claimed = false;
  info.isGesture = true;
  e = e.chain(info);
  if (!me.gestureTargets) {
    if (ln > 1) {
      targetGroups = [];
      for (i = 0; i < ln; i++) {
        touch = changedTouches[i];
        targetGroups.push(touch.targets);
      }
      targets = me.getCommonTargets(targetGroups);
    } else {
      targets = changedTouches[0].targets;
    }
    me.gestureTargets = targets;
  }
  if (isCancel && recognizer.isSingleTouch && touches.length > 1) {
    e.target = touches[0].target;
    cancelEvents.push(e);
  } else {
    events.push(e);
  }
  if (queueWasEmpty) {
    me.publishGestures();
  }
}, getCommonTargets:function(targetGroups) {
  var firstTargetGroup = targetGroups[0], ln = targetGroups.length, commonTargets = [], i = 1, target, targets, j;
  if (ln === 1) {
    return firstTargetGroup;
  }
  while (true) {
    target = firstTargetGroup[firstTargetGroup.length - i];
    if (!target) {
      return commonTargets;
    }
    for (j = 1; j < ln; j++) {
      targets = targetGroups[j];
      if (targets[targets.length - i] !== target) {
        return commonTargets;
      }
    }
    commonTargets.unshift(target);
    i++;
  }
  return commonTargets;
}, invokeRecognizers:function(methodName, e) {
  var recognizers = this.recognizers, ln = recognizers.length, i, recognizer;
  if (methodName === 'onStart') {
    for (i = 0; i < ln; i++) {
      recognizers[i].isActive = true;
    }
  }
  for (i = 0; i < ln; i++) {
    recognizer = recognizers[i];
    if (recognizer.isActive && recognizer[methodName].call(recognizer, e) === false) {
      recognizer.isActive = false;
    }
  }
}, filterClaimed:function(events, claimedEvent) {
  var me = this, eventToRecognizer = me.eventToRecognizer, claimedEventType = claimedEvent.type, claimedRecognizer = eventToRecognizer[claimedEventType], claimedEventIndex, recognizer, type, i;
  for (i = events.length; i--;) {
    type = events[i].type;
    if (type === claimedEventType) {
      claimedEventIndex = i;
    } else {
      recognizer = eventToRecognizer[type];
      if (!claimedRecognizer || recognizer && recognizer !== claimedRecognizer) {
        events.splice(i, 1);
        if (claimedEventIndex) {
          claimedEventIndex--;
        }
      }
    }
  }
  me.claimRecognizer(claimedRecognizer, events[0]);
  return claimedEventIndex;
}, claimRecognizer:function(claimedRecognizer, e) {
  var me = this, recognizers = me.recognizers, i, ln, recognizer;
  for (i = 0, ln = recognizers.length; i < ln; i++) {
    recognizer = recognizers[i];
    if (recognizer !== claimedRecognizer) {
      recognizer.isActive = false;
      recognizer.cancel(e);
    }
  }
  if (me.events.length) {
    me.publishGestures(true);
  }
}, publishGestures:function(claimed) {
  var me = this, cancelEvents = me.cancelEvents, events = me.events, gestureTargets = me.gestureTargets;
  if (cancelEvents.length) {
    me.cancelEvents = [];
    me.publish(cancelEvents, me.getPropagatingTargets(cancelEvents[0].target), true);
  }
  if (events.length) {
    me.events = [];
    me.gestureTargets = null;
    me.publish(events, gestureTargets || me.getPropagatingTargets(events[0].target), claimed);
  }
}, updateTouches:function(e) {
  var me = this, browserEvent = e.browserEvent, type = e.type, touchSources = browserEvent.changedTouches || [browserEvent], activeTouches = me.activeTouches, activeTouchesMap = me.activeTouchesMap, changedTouches = [], touchSource, identifier, touch, target, i, ln, x, y;
  for (i = 0, ln = touchSources.length; i < ln; i++) {
    touchSource = touchSources[i];
    if ('identifier' in touchSource) {
      identifier = touchSource.identifier;
    } else {
      if ('pointerId' in touchSource) {
        identifier = touchSource.pointerId;
      } else {
        identifier = 1;
      }
    }
    touch = activeTouchesMap[identifier];
    if (!touch) {
      target = Ext.event.Event.resolveTextNode(touchSource.target);
      touch = activeTouchesMap[identifier] = {identifier:identifier, target:target, targets:me.getPropagatingTargets(target)};
      activeTouches.push(touch);
    }
    if (me.isEndEvent[type] || me.isCancelEvent[type]) {
      delete activeTouchesMap[identifier];
      Ext.Array.remove(activeTouches, touch);
    }
    x = Math.round(touchSource.pageX);
    y = Math.round(touchSource.pageY);
    touch.pageX = x;
    touch.pageY = y;
    touch.point = new Ext.util.Point(x, y);
    changedTouches.push(touch);
  }
  e.touches = Ext.Array.clone(activeTouches);
  e.changedTouches = changedTouches;
}, publishDelegatedDomEvent:function(e) {
  var me = this;
  if (!e.button || e.button < 1) {
    me.events = [e];
    e.browserEvent.$extHandled = true;
    me.handlers[e.type].call(me, e);
  } else {
    me.callParent([e]);
  }
}, onTouchStart:function(e) {
  var me = this, target = e.target, touches = e.browserEvent.touches;
  if (e.browserEvent.type === 'touchstart') {
    target.addEventListener('touchmove', me.onTargetTouchMove);
    target.addEventListener('touchend', me.onTargetTouchEnd);
    target.addEventListener('touchcancel', me.onTargetTouchEnd);
  }
  if (touches && touches.length <= me.activeTouches.length) {
    me.removeGhostTouches(touches);
  }
  me.updateTouches(e);
  if (!me.isStarted) {
    if (Ext.enableGarbageCollector) {
      Ext.dom.GarbageCollector.pause();
    }
    me.isStarted = true;
    me.invokeRecognizers('onStart', e);
  }
  me.invokeRecognizers('onTouchStart', e);
  me.publishGestures();
}, onTouchMove:function(e) {
  var me = this, mousePointerType = me.mousePointerType, isStarted = me.isStarted;
  if (isStarted || e.pointerType !== 'mouse') {
    me.updateTouches(e);
  }
  if (isStarted) {
    if (mousePointerType && e.browserEvent.pointerType === mousePointerType && e.buttons === 0) {
      e.type = Ext.dom.Element.prototype.eventMap.touchend;
      e.button = 0;
      me.onTouchEnd(e);
      return;
    }
    if (e.changedTouches.length > 0) {
      me.invokeRecognizers('onTouchMove', e);
    }
  }
  me.publishGestures();
}, onTouchEnd:function(e) {
  var me = this, isStarted = me.isStarted, touchCount;
  if (isStarted || e.pointerType !== 'mouse') {
    me.updateTouches(e);
  }
  if (!isStarted) {
    me.publishGestures();
    return;
  }
  touchCount = me.activeTouches.length;
  try {
    me.invokeRecognizers(me.isCancelEvent[e.type] ? 'onTouchCancel' : 'onTouchEnd', e);
  } finally {
    try {
      if (!touchCount) {
        me.isStarted = false;
        me.invokeRecognizers('onEnd', e);
      }
    } finally {
      try {
        me.publishGestures();
      } finally {
        if (!touchCount) {
          if (Ext.enableGarbageCollector) {
            Ext.dom.GarbageCollector.resume();
          }
        }
        me.reEnterCountAdjusted = true;
        me.reEnterCount--;
      }
    }
  }
}, onTargetTouchMove:function(e) {
  if (Ext.elevateFunction) {
    Ext.elevateFunction(this.doTargetTouchMove, this, [e]);
  } else {
    this.doTargetTouchMove(e);
  }
}, doTargetTouchMove:function(e) {
  var me = this;
  if (!Ext.getBody().contains(e.target)) {
    me.reEnterCountAdjusted = false;
    me.reEnterCount++;
    this.onTouchMove(new Ext.event.Event(e));
    if (!me.reEnterCountAdjusted) {
      me.reEnterCount--;
    }
  }
}, onTargetTouchEnd:function(e) {
  if (Ext.elevateFunction) {
    Ext.elevateFunction(this.doTargetTouchEnd, this, [e]);
  } else {
    this.doTargetTouchEnd(e);
  }
}, doTargetTouchEnd:function(e) {
  var me = this, target = e.target;
  target.removeEventListener('touchmove', me.onTargetTouchMove);
  target.removeEventListener('touchend', me.onTargetTouchEnd);
  target.removeEventListener('touchcancel', me.onTargetTouchEnd);
  if (!Ext.getBody().contains(target)) {
    me.reEnterCountAdjusted = false;
    me.reEnterCount++;
    me.onTouchEnd(new Ext.event.Event(e));
    if (!me.reEnterCountAdjusted) {
      me.reEnterCount--;
    }
  }
}, reset:function() {
  var me = this, recognizers = me.recognizers, ln = recognizers.length, i, recognizer;
  me.activeTouchesMap = {};
  me.activeTouches = [];
  me.changedTouches = [];
  me.isStarted = false;
  me.gestureTargets = null;
  me.events = [];
  me.cancelEvents = [];
  for (i = 0; i < ln; i++) {
    recognizer = recognizers[i];
    recognizer.reset();
    recognizer.isActive = false;
  }
  this.callParent();
}, privates:{removeGhostTouches:function(touches) {
  var ids = {}, len = touches.length, activeTouches = this.activeTouches, map = this.activeTouchesMap, i, id, touch;
  for (i = 0; i < len; ++i) {
    ids[touches[i].identifier] = true;
  }
  i = activeTouches.length;
  while (i--) {
    touch = activeTouches[i];
    id = touch.identifier;
    if (!touches[id]) {
      Ext.Array.remove(activeTouches, touch);
      delete map[id];
    }
  }
}}}, function(Gesture) {
  var EventProto = Event.prototype, stopPropagation = EventProto.stopPropagation;
  if (stopPropagation) {
    EventProto.stopPropagation = function() {
      var me = this, publisher = Gesture.instance, type = me.type, e;
      if (!me.$extHandled && publisher.handles[type]) {
        e = new Ext.event.Event(me);
        publisher.updateTouches(e);
        publisher.invokeRecognizers('onTouchCancel', e);
        publisher.reset();
        publisher.reEnterCountAdjusted = true;
      }
      stopPropagation.apply(me, arguments);
    };
  }
  Gesture.instance = Ext.$gesturePublisher = new Gesture;
});
Ext.define('Ext.mixin.Templatable', {extend:Ext.Mixin, mixinConfig:{id:'templatable'}, referenceAttributeName:'reference', referenceSelector:'[reference]', getElementConfig:function() {
  return {reference:'element'};
}, getElementTemplate:function() {
  var elementTemplate = document.createDocumentFragment();
  elementTemplate.appendChild(Ext.Element.create(this.getElementConfig(), true));
  return elementTemplate;
}, initElement:function() {
  var prototype = this.self.prototype;
  prototype.elementTemplate = this.getElementTemplate();
  prototype.initElement = prototype.doInitElement;
  this.initElement.apply(this, arguments);
}, linkElement:function(reference, node) {
  this.link(reference, node);
}, doInitElement:function() {
  var referenceAttributeName = this.referenceAttributeName, renderElement, referenceNodes, i, ln, referenceNode, reference;
  renderElement = this.elementTemplate.cloneNode(true);
  referenceNodes = renderElement.querySelectorAll(this.referenceSelector);
  for (i = 0, ln = referenceNodes.length; i < ln; i++) {
    referenceNode = referenceNodes[i];
    reference = referenceNode.getAttribute(referenceAttributeName);
    referenceNode.removeAttribute(referenceAttributeName);
    this.linkElement(reference, referenceNode);
  }
}});
Ext.define('Ext.TaskQueue', {singleton:true, pending:false, mode:true, protectedReadQueue:[], protectedWriteQueue:[], readQueue:[], writeQueue:[], readRequestId:0, writeRequestId:0, timer:null, constructor:function() {
  var me = this;
  me.run = me.run.bind(me);
  me.runProtected = Ext.Function.bind(me.run, me, [me.protectedReadQueue, me.protectedWriteQueue, 'runProtected']);
  me.runProtected.$skipTimerCheck = true;
  if (Ext.os.is.iOS) {
    me.watch.$skipTimerCheck = true;
    me.watchdogTimer = Ext.interval(this.watch, 500, this);
  }
}, requestRead:function(fn, scope, args) {
  var request = {id:++this.readRequestId, fn:fn, scope:scope, args:args};
  if (arguments[3] === true) {
    this.protectedReadQueue.push(request);
    this.request(true, 'runProtected');
  } else {
    this.readQueue.push(request);
    this.request(true);
  }
  return request.id;
}, cancelRead:function(id) {
  this.cancelRequest(this.readQueue, id, true);
}, requestWrite:function(fn, scope, args) {
  var me = this, request = {id:++me.writeRequestId, fn:fn, scope:scope, args:args};
  if (arguments[3] === true) {
    me.protectedWriteQueue.push(request);
    me.request(false, 'runProtected');
  } else {
    me.writeQueue.push(request);
    me.request(false);
  }
  return request.id;
}, cancelWrite:function(id) {
  this.cancelRequest(this.writeQueue, id, false);
}, request:function(mode, method) {
  var me = this;
  var oldMode = me.mode;
  if (!me.pending) {
    me.pendingTime = Date.now();
    me.pending = true;
    me.mode = mode;
    if (mode) {
      me.timer = Ext.defer(me[method] || me.run, 1);
    } else {
      me.timer = Ext.raf(me[method] || me.run);
    }
  }
  if (me.mode === mode && me.timer) {
    if (oldMode) {
      Ext.undefer(me.timer);
    } else {
      Ext.unraf(me.timer);
    }
    if (mode) {
      me.timer = Ext.defer(me[method] || me.run, 1);
    } else {
      me.timer = Ext.raf(me[method] || me.run);
    }
  }
}, cancelRequest:function(queue, id, mode) {
  var i;
  for (i = 0; i < queue.length; i++) {
    if (queue[i].id === id) {
      queue.splice(i, 1);
      break;
    }
  }
  if (!queue.length && this.mode === mode && this.timer) {
    Ext.undefer(this.timer);
  }
}, watch:function() {
  if (this.pending && Date.now() - this.pendingTime >= 500) {
    this.run();
  }
}, run:function(readQueue, writeQueue, method) {
  var me = this, mode = null, queue, tasks, task, fn, scope, args, i, len;
  readQueue = readQueue || me.readQueue;
  writeQueue = writeQueue || me.writeQueue;
  me.pending = false;
  me.pending = me.timer = false;
  if (me.mode) {
    queue = readQueue;
    if (writeQueue.length > 0) {
      mode = false;
    }
  } else {
    queue = writeQueue;
    if (readQueue.length > 0) {
      mode = true;
    }
  }
  tasks = queue.slice();
  queue.length = 0;
  for (i = 0, len = tasks.length; i < len; i++) {
    task = tasks[i];
    fn = task.fn;
    scope = task.scope;
    args = task.args;
    if (scope && (scope.destroying || scope.destroyed)) {
      continue;
    }
    if (typeof fn === 'string') {
      fn = scope[fn];
    }
    if (args) {
      fn.apply(scope, args);
    } else {
      fn.call(scope);
    }
  }
  tasks.length = 0;
  if (mode !== null) {
    me.request(mode, method);
  }
}, clear:function() {
  var me = this, timer = me.timer;
  if (timer) {
    if (me.mode) {
      Ext.undefer(timer);
    } else {
      Ext.unraf(timer);
    }
  }
  me.readQueue.length = me.writeQueue.length = 0;
  me.pending = me.timer = false;
  me.mode = true;
}, privates:{flush:function() {
  var me = this, mode = me.mode;
  while (me.readQueue.length || me.writeQueue.length) {
    if (mode) {
      Ext.undefer(me.timer);
    } else {
      Ext.unraf(me.timer);
    }
    me.run();
  }
  me.mode = true;
}}});
Ext.define('Ext.util.sizemonitor.Abstract', {mixins:[Ext.mixin.Templatable], config:{element:null, callback:Ext.emptyFn, scope:null, args:[]}, width:null, height:null, contentWidth:null, contentHeight:null, constructor:function(config) {
  var me = this;
  me.refresh = me.refresh.bind(me);
  me.info = {width:0, height:0, contentWidth:0, contentHeight:0, flag:0};
  me.initElement();
  me.initConfig(config);
  me.bindListeners(true);
}, bindListeners:Ext.emptyFn, applyElement:function(element) {
  if (element) {
    return Ext.get(element);
  }
}, updateElement:function(element) {
  element.append(this.detectorsContainer, true);
  element.addCls(Ext.baseCSSPrefix + 'size-monitored');
}, applyArgs:function(args) {
  return args.concat([this.info]);
}, refreshMonitors:Ext.emptyFn, forceRefresh:function() {
  Ext.TaskQueue.requestRead('refresh', this);
}, getContentBounds:function() {
  return this.detectorsContainer.getBoundingClientRect();
}, getContentWidth:function() {
  return this.detectorsContainer.clientWidth;
}, getContentHeight:function() {
  return this.detectorsContainer.clientHeight;
}, refreshSize:function() {
  var element = this.getElement();
  if (!element || element.destroyed) {
    return false;
  }
  var me = this, size = element.measure(), width = size.width, height = size.height, contentWidth = me.getContentWidth(), contentHeight = me.getContentHeight(), currentContentWidth = me.contentWidth, currentContentHeight = me.contentHeight, info = me.info, resized = false, flag;
  me.width = width;
  me.height = height;
  me.contentWidth = contentWidth;
  me.contentHeight = contentHeight;
  flag = (currentContentWidth !== contentWidth ? 1 : 0) + (currentContentHeight !== contentHeight ? 2 : 0);
  if (flag > 0) {
    info.width = width;
    info.height = height;
    info.contentWidth = contentWidth;
    info.contentHeight = contentHeight;
    info.flag = flag;
    resized = true;
    me.getCallback().apply(me.getScope(), me.getArgs());
  }
  return resized;
}, refresh:function() {
  if (this.destroying || this.destroyed) {
    return;
  }
  this.refreshSize();
  Ext.TaskQueue.requestWrite('refreshMonitors', this);
}, destroy:function() {
  var me = this, element = me.getElement();
  me.bindListeners(false);
  if (element && !element.destroyed) {
    element.removeCls(Ext.baseCSSPrefix + 'size-monitored');
  }
  delete me._element;
  me.refresh = null;
  me.callParent();
}});
Ext.define('Ext.util.sizemonitor.Scroll', {extend:Ext.util.sizemonitor.Abstract, getElementConfig:function() {
  return {reference:'detectorsContainer', classList:[Ext.baseCSSPrefix + 'size-monitors', 'scroll'], children:[{reference:'expandMonitor', className:'expand'}, {reference:'shrinkMonitor', className:'shrink'}]};
}, constructor:function(config) {
  this.onScroll = this.onScroll.bind(this);
  this.callParent(arguments);
}, bindListeners:function(bind) {
  var method = bind ? 'addEventListener' : 'removeEventListener';
  this.expandMonitor[method]('scroll', this.onScroll, true);
  this.shrinkMonitor[method]('scroll', this.onScroll, true);
}, onScroll:function(e) {
  if (!this.destroyed) {
    if (this.hasExpandMonitorScrollChanged && e.target === this.expandMonitor) {
      delete this.hasExpandMonitorScrollChanged;
    } else {
      if (this.hasShrinkMonitorScrollChanged && e.target === this.shrinkMonitor) {
        delete this.hasShrinkMonitorScrollChanged;
      } else {
        Ext.TaskQueue.requestRead('refresh', this);
      }
    }
  }
}, refreshMonitors:function() {
  var expandMonitor = this.expandMonitor, shrinkMonitor = this.shrinkMonitor, end = 1000000;
  if (expandMonitor && !expandMonitor.destroyed) {
    if (Ext.isiOS) {
      this.hasExpandMonitorScrollChanged = true;
    }
    expandMonitor.scrollLeft = end;
    expandMonitor.scrollTop = end;
  }
  if (shrinkMonitor && !shrinkMonitor.destroyed) {
    if (Ext.isiOS) {
      this.hasShrinkMonitorScrollChanged = true;
    }
    shrinkMonitor.scrollLeft = end;
    shrinkMonitor.scrollTop = end;
  }
}, destroy:function() {
  this.onScroll = null;
  this.callParent();
}});
Ext.define('Ext.util.SizeMonitor', {constructor:function(config) {
  return new Ext.util.sizemonitor.Scroll(config);
}});
Ext.define('Ext.event.publisher.ElementSize', {extend:Ext.event.publisher.Publisher, type:'size', handledEvents:['resize'], constructor:function() {
  this.monitors = {};
  this.subscribers = {};
  this.callParent(arguments);
}, subscribe:function(element) {
  var id = element.id, subscribers = this.subscribers, monitors = this.monitors;
  if (subscribers[id]) {
    ++subscribers[id];
  } else {
    subscribers[id] = 1;
    monitors[id] = new Ext.util.SizeMonitor({element:element, callback:this.onElementResize, scope:this, args:[element]});
  }
  element.on('painted', 'forceRefresh', monitors[id]);
  return true;
}, unsubscribe:function(element) {
  var id = element.id, subscribers = this.subscribers, monitors = this.monitors, sizeMonitor;
  if (subscribers[id] && !--subscribers[id]) {
    delete subscribers[id];
    sizeMonitor = monitors[id];
    element.un('painted', 'forceRefresh', sizeMonitor);
    sizeMonitor.destroy();
    delete monitors[id];
  }
  if (element.activeRead) {
    Ext.TaskQueue.cancelRead(element.activeRead);
  }
}, fireElementResize:function(element, info) {
  delete element.activeRead;
  this.fire(element, 'resize', [element, info]);
}, onElementResize:function(element, info) {
  if (!element.activeRead) {
    element.activeRead = Ext.TaskQueue.requestRead('fireElementResize', this, [element, info], !!element.$skipResourceCheck);
  }
}, privates:{syncRefresh:function(elements) {
  var el, monitor, i, len;
  elements = Ext.Array.from(elements);
  for (i = 0, len = elements.length; i < len; ++i) {
    el = elements[i];
    if (typeof el !== 'string') {
      el = el.id;
    }
    monitor = this.monitors[el];
    if (monitor) {
      monitor.forceRefresh();
    }
  }
  Ext.TaskQueue.flush();
  Ext.Function.fireElevatedHandlers();
}}}, function(ElementSize) {
  ElementSize.instance = new ElementSize;
});
Ext.define('Ext.util.paintmonitor.Abstract', {config:{element:null, callback:Ext.emptyFn, scope:null, args:[]}, eventName:'', monitorClass:'', constructor:function(config) {
  this.onElementPainted = this.onElementPainted.bind(this);
  this.initConfig(config);
}, bindListeners:function(bind) {
  this.monitorElement[bind ? 'addEventListener' : 'removeEventListener'](this.eventName, this.onElementPainted, true);
}, applyElement:function(element) {
  if (element) {
    return Ext.get(element);
  }
}, updateElement:function(element) {
  this.monitorElement = Ext.Element.create({classList:[Ext.baseCSSPrefix + 'paint-monitor', this.monitorClass]}, true);
  element.appendChild(this.monitorElement, true);
  element.addCls(Ext.baseCSSPrefix + 'paint-monitored');
  this.bindListeners(true);
}, onElementPainted:function() {
}, destroy:function() {
  var me = this, monitorElement = me.monitorElement, parentNode = monitorElement.parentNode, element = me.getElement();
  me.bindListeners(false);
  delete me.monitorElement;
  if (element && !element.destroyed) {
    element.removeCls(Ext.baseCSSPrefix + 'paint-monitored');
    delete me._element;
  }
  if (parentNode) {
    parentNode.removeChild(monitorElement);
  }
  me.callParent();
}});
Ext.define('Ext.util.paintmonitor.CssAnimation', {extend:Ext.util.paintmonitor.Abstract, eventName:Ext.browser.is.WebKit ? 'webkitAnimationEnd' : 'animationend', monitorClass:'cssanimation', onElementPainted:function(e) {
  if (e.animationName === Ext.baseCSSPrefix + 'paint-monitor-helper') {
    this.getCallback().apply(this.getScope(), this.getArgs());
  }
}});
Ext.define('Ext.util.PaintMonitor', {constructor:function(config) {
  return new Ext.util.paintmonitor.CssAnimation(config);
}});
Ext.define('Ext.event.publisher.ElementPaint', {extend:Ext.event.publisher.Publisher, type:'paint', handledEvents:['painted'], constructor:function() {
  this.monitors = {};
  this.subscribers = {};
  this.callParent(arguments);
}, subscribe:function(element) {
  var me = this, id = element.id, subscribers = me.subscribers;
  if (subscribers[id]) {
    ++subscribers[id];
  } else {
    subscribers[id] = 1;
    me.monitors[id] = new Ext.util.PaintMonitor({element:element, callback:me.onElementPainted, scope:me, args:[element]});
  }
}, unsubscribe:function(element) {
  var id = element.id, subscribers = this.subscribers, monitors = this.monitors;
  if (subscribers[id] && !--subscribers[id]) {
    delete subscribers[id];
    monitors[id].destroy();
    delete monitors[id];
  }
  if (element.activeRead) {
    Ext.TaskQueue.cancelRead(element.activeRead);
  }
}, fireElementPainted:function(element) {
  delete element.activeRead;
  this.fire(element, 'painted', [element]);
}, onElementPainted:function(element) {
  if (!element.activeRead) {
    element.activeRead = Ext.TaskQueue.requestRead('fireElementPainted', this, [element], !!element.$skipResourceCheck);
  }
}}, function(ElementPaint) {
  ElementPaint.instance = new ElementPaint;
});
Ext.define('Ext.dom.Element', function(Element) {
  var WIN = window, DOC = document, docEl = DOC.documentElement, WIN_TOP = WIN.top, EMPTY = [], elementIdCounter, windowId, documentId, WIDTH = 'width', HEIGHT = 'height', MIN_WIDTH = 'min-width', MIN_HEIGHT = 'min-height', MAX_WIDTH = 'max-width', MAX_HEIGHT = 'max-height', TOP = 'top', RIGHT = 'right', BOTTOM = 'bottom', LEFT = 'left', VISIBILITY = 'visibility', HIDDEN = 'hidden', DISPLAY = 'display', NONE = 'none', ZINDEX = 'z-index', POSITION = 'position', RELATIVE = 'relative', STATIC = 'static', 
  wordsRe = /\w/g, spacesRe = /\s+/, classNameSplitRegex = /[\s]+/, transparentRe = /^(?:transparent|(?:rgba[(](?:\s*\d+\s*[,]){3}\s*0\s*[)]))$/i, endsQuestionRe = /\?$/, topRe = /top/i, empty = {}, borders = {t:'border-top-width', r:'border-right-width', b:'border-bottom-width', l:'border-left-width'}, paddings = {t:'padding-top', r:'padding-right', b:'padding-bottom', l:'padding-left'}, margins = {t:'margin-top', r:'margin-right', b:'margin-bottom', l:'margin-left'}, selectDir = {b:'backward', 
  back:'backward', f:'forward'}, paddingsTLRB = [paddings.l, paddings.r, paddings.t, paddings.b], bordersTLRB = [borders.l, borders.r, borders.t, borders.b], numberRe = /\d+$/, unitRe = /\d+(px|r?em|%|vh|vw|vmin|vmax|en|ch|ex|pt|in|cm|mm|pc)$/i, defaultUnit = 'px', msRe = /^-ms-/, camelRe = /(-[a-z])/gi, cssRe = /([a-z0-9\-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi, pxRe = /^\d+(?:\.\d*)?px$/i, relativeUnitRe = /(%|r?em|auto|vh|vw|vmin|vmax|ch|ex)$/i, propertyCache = {}, ORIGINALDISPLAY = 'originalDisplay', 
  camelReplaceFn = function(m, a) {
    return a.charAt(1).toUpperCase();
  }, clearData = function(node, deep) {
    var childNodes, i, len;
    if (node.nodeType === 1) {
      node._extData = null;
      if (deep) {
        childNodes = node.childNodes;
        for (i = 0, len = childNodes.length; i < len; ++i) {
          clearData(childNodes[i], deep);
        }
      }
    }
  }, toFloat = function(v) {
    return parseFloat(v) || 0;
  }, opacityCls = Ext.baseCSSPrefix + 'hidden-opacity', visibilityCls = Ext.baseCSSPrefix + 'hidden-visibility', displayCls = Ext.baseCSSPrefix + 'hidden-display', offsetsCls = Ext.baseCSSPrefix + 'hidden-offsets', clipCls = Ext.baseCSSPrefix + 'hidden-clip', lastFocusChange = 0, lastKeyboardClose = 0, editableHasFocus = false, isVirtualKeyboardOpen = false, inputTypeSelectionSupported = /text|password|search|tel|url/i, visFly, scrollFly, caFly, wrapFly, grannyFly, activeElFly;
  try {
    elementIdCounter = WIN_TOP.__elementIdCounter__;
    WIN_TOP.__elementIdCounter__ = elementIdCounter;
  } catch (e$48) {
    WIN_TOP = WIN;
  }
  WIN_TOP.__elementIdCounter__ = elementIdCounter = (WIN_TOP.__elementIdCounter__ || 0) + 1;
  windowId = 'ext-window-' + elementIdCounter;
  documentId = 'ext-document-' + elementIdCounter;
  if (Object.freeze) {
    Object.freeze(EMPTY);
  }
  return {alternateClassName:['Ext.Element'], mixins:[Ext.util.Positionable, Ext.mixin.Observable], observableType:'element', isElement:true, skipGarbageCollection:true, $applyConfigs:true, identifiablePrefix:'ext-element-', _selectDir:selectDir, styleHooks:{transform:{set:function(dom, value, el) {
    var result = '', prop;
    if (typeof value !== 'string') {
      for (prop in value) {
        if (result) {
          result += ' ';
        }
        if (prop.indexOf('translate') === 0) {
          result += prop + '(' + Element.addUnits(value[prop], 'px') + ')';
        } else {
          result += prop + '(' + value[prop] + ')';
        }
      }
      value = result;
    }
    dom.style.transform = value;
  }}}, validIdRe:Ext.validIdRe, blockedEvents:Ext.supports.EmulatedMouseOver ? {mouseover:1} : {}, longpressEvents:{longpress:1, taphold:1}, constructor:function(dom) {
    var me = this, id;
    if (typeof dom === 'string') {
      dom = DOC.getElementById(dom);
    }
    if (!dom) {
      Ext.raise('Invalid domNode reference or an id of an existing domNode: ' + dom);
      return null;
    }
    if (Ext.cache[dom.id]) {
      Ext.raise("Element cache already contains an entry for id '" + dom.id + "'.  Use Ext.get() to create or retrieve Element instances.");
    }
    me.dom = dom;
    if (!(id = dom.id)) {
      dom.id = id = me.generateAutoId();
    }
    me.id = id;
    if (!me.validIdRe.test(me.id)) {
      Ext.raise('Invalid Element "id": "' + me.id + '"');
    }
    me.el = me;
    Ext.cache[id] = me;
    me.longpressListenerCount = 0;
    me.mixins.observable.constructor.call(me);
  }, inheritableStatics:{cache:Ext.cache = {}, editableSelector:'input,textarea,[contenteditable\x3d"true"]', VISIBILITY:1, DISPLAY:2, OFFSETS:3, CLIP:4, OPACITY:5, minKeyboardHeight:100, unitRe:unitRe, useDelegatedEvents:true, validNodeTypes:{1:1, 9:1}, namespaceURIs:{html:'http://www.w3.org/1999/xhtml', svg:'http://www.w3.org/2000/svg'}, selectableCls:Ext.baseCSSPrefix + 'selectable', unselectableCls:Ext.baseCSSPrefix + 'unselectable', maxRippleDiameter:75, addUnits:function(size, units) {
    if (typeof size === 'number') {
      return size + (units || defaultUnit);
    }
    if (size === '' || size === 'auto' || size == null) {
      return size || '';
    }
    if (numberRe.test(size)) {
      return size + (units || defaultUnit);
    }
    if (!unitRe.test(size)) {
      if (!(Ext.isString(size) && size.indexOf('calc') === 0)) {
        Ext.Logger.warn('Warning, size detected (' + size + ') not a valid property value on Element.addUnits.');
      }
      return size || '';
    }
    return size;
  }, create:function(attributes, domNode, namespace) {
    var me = this, classes, element, elementStyle, tag, value, name, i, ln, tmp, ns;
    attributes = attributes || {};
    if (attributes.isElement) {
      return domNode ? attributes.dom : attributes;
    } else {
      if ('nodeType' in attributes) {
        return domNode ? attributes : Ext.get(attributes);
      }
    }
    if (typeof attributes === 'string') {
      return DOC.createTextNode(attributes);
    }
    tag = attributes.tag;
    if (!tag) {
      tag = 'div';
    }
    ns = attributes.namespace || namespace;
    if (ns) {
      element = DOC.createElementNS(me.namespaceURIs[ns] || ns, tag);
    } else {
      element = DOC.createElement(tag);
    }
    elementStyle = element.style;
    for (name in attributes) {
      if (name !== 'tag' && name !== 'namespace') {
        value = attributes[name];
        switch(name) {
          case 'style':
            if (typeof value === 'string') {
              element.setAttribute(name, value);
            } else {
              for (i in value) {
                elementStyle[i] = value[i];
              }
            }
            break;
          case 'className':
          case 'cls':
            tmp = value.split(spacesRe);
            classes = classes ? classes.concat(tmp) : tmp;
            break;
          case 'classList':
            classes = classes ? classes.concat(value) : value;
            break;
          case 'text':
            element.textContent = value;
            break;
          case 'html':
            element.innerHTML = value;
            break;
          case 'hidden':
            if (classes) {
              classes.push(displayCls);
            } else {
              classes = [displayCls];
            }
            break;
          case 'children':
            if (value != null) {
              for (i = 0, ln = value.length; i < ln; i++) {
                element.appendChild(me.create(value[i], true, ns));
              }
            }
            break;
          default:
            if (value != null) {
              element.setAttribute(name, value);
            }
        }
      }
    }
    if (classes) {
      element.className = classes.join(' ');
    }
    if (domNode) {
      return element;
    } else {
      return me.get(element);
    }
  }, fly:function(dom, named) {
    return Ext.fly(dom, named);
  }, fromPoint:function() {
    var elementFromPointBug;
    if (Ext.isIE || Ext.isEdge) {
      try {
        elementFromPointBug = window.self !== window.top;
      } catch (e$49) {
        elementFromPointBug = true;
      }
    }
    return function(x, y, asDom) {
      var el = null;
      el = DOC.elementFromPoint(x, y);
      if (!el && elementFromPointBug) {
        el = DOC.elementFromPoint(x, y);
      }
      return asDom ? el : Ext.get(el);
    };
  }(), fromPagePoint:function(x, y, asDom) {
    var scroll = Ext.getDoc().getScroll();
    return Element.fromPoint(x - scroll.left, y - scroll.top, asDom);
  }, get:function(el) {
    var me = this, cache = Ext.cache, nodeType, dom, id, entry, isDoc, isWin, isValidNodeType;
    if (!el) {
      return null;
    }
    function warnDuplicate(id) {
      Ext.raise('DOM element with id ' + id + ' in Element cache is not the same as element in the DOM. ' + 'Make sure to clean up Element instances using destroy()');
    }
    if (el.isFly) {
      el = el.dom;
    }
    if (typeof el === 'string') {
      id = el;
      if (cache.hasOwnProperty(id)) {
        entry = cache[id];
        if (entry.skipGarbageCollection || !Ext.isGarbage(entry.dom)) {
          dom = Ext.getElementById ? Ext.getElementById(id) : DOC.getElementById(id);
          if (dom && dom !== entry.dom) {
            warnDuplicate(id);
          }
          return entry;
        } else {
          entry.destroy();
        }
      }
      if (id === windowId) {
        return Element.get(WIN);
      } else {
        if (id === documentId) {
          return Element.get(DOC);
        }
      }
      dom = Ext.getElementById ? Ext.getElementById(id) : DOC.getElementById(id);
      if (dom) {
        return new Element(dom);
      }
    }
    nodeType = el.nodeType;
    if (nodeType) {
      isDoc = nodeType === 9;
      isValidNodeType = me.validNodeTypes[nodeType];
    } else {
      isWin = el.window == el;
    }
    if (isValidNodeType || isWin) {
      id = el.id;
      if (el === DOC) {
        el.id = id = documentId;
      } else {
        if (el == WIN) {
          el.id = id = windowId;
        }
      }
      if (cache.hasOwnProperty(id)) {
        entry = cache[id];
        if (entry.skipGarbageCollection || el === entry.dom || !Ext.isGarbage(entry.dom)) {
          if (el !== entry.dom) {
            warnDuplicate(id);
          }
          return entry;
        } else {
          entry.destroy();
        }
      }
      el = new Element(el);
      if (isWin || isDoc) {
        el.skipGarbageCollection = true;
      }
      return el;
    }
    if (el.isElement) {
      return el;
    }
    if (el.isComposite) {
      return el;
    }
    if (Ext.isIterable(el)) {
      return me.select(el);
    }
    return null;
  }, getActiveElement:function(asElement) {
    var active = DOC.activeElement;
    if (!active || !active.focus) {
      active = DOC.body;
    }
    return asElement ? Ext.get(active) : active;
  }, getDocumentHeight:function() {
    return Math.max(!Ext.isStrict ? DOC.body.scrollHeight : docEl.scrollHeight, this.getViewportHeight());
  }, getDocumentWidth:function() {
    return Math.max(!Ext.isStrict ? DOC.body.scrollWidth : docEl.scrollWidth, this.getViewportWidth());
  }, getOrientation:function() {
    if (Ext.supports.OrientationChange) {
      return WIN.orientation == 0 ? 'portrait' : 'landscape';
    }
    return WIN.innerHeight > WIN.innerWidth ? 'portrait' : 'landscape';
  }, getViewportHeight:function() {
    var viewportHeight = Element._viewportHeight;
    if (Ext.isIE9m) {
      return DOC.documentElement.clientHeight;
    }
    return viewportHeight != null ? viewportHeight : docEl.clientHeight;
  }, getViewportWidth:function() {
    var viewportWidth = Element._viewportWidth;
    if (Ext.isIE9m) {
      return DOC.documentElement.clientWidth;
    }
    return viewportWidth != null ? viewportWidth : docEl.clientWidth;
  }, getViewportScale:function() {
    var top = WIN_TOP;
    return (Ext.isiOS || Ext.isAndroid ? 1 : top.devicePixelRatio || top.screen.deviceXDPI / top.screen.logicalXDPI) * this.getViewportTouchScale();
  }, getViewportTouchScale:function(forceRead) {
    var scale = 1, top = WIN_TOP, cachedScale;
    if (!forceRead) {
      cachedScale = this._viewportTouchScale;
      if (cachedScale) {
        return cachedScale;
      }
    }
    if (Ext.isIE10p || Ext.isEdge || Ext.isiOS) {
      scale = docEl.offsetWidth / WIN.innerWidth;
    } else {
      if (Ext.isChromeMobile) {
        scale = top.outerWidth / top.innerWidth;
      }
    }
    return scale;
  }, getViewSize:function() {
    return {width:Element.getViewportWidth(), height:Element.getViewportHeight()};
  }, hasUnit:function(size) {
    return !!(size && unitRe.test(size));
  }, isRelativeUnit:function(size) {
    return !size || relativeUnitRe.test(size);
  }, maskIframes:function() {
    var iframes = document.getElementsByTagName('iframe'), fly = new Ext.dom.Fly;
    Ext.each(iframes, function(iframe) {
      var myMask;
      myMask = fly.attach(iframe.parentNode).mask();
      myMask.setStyle('background-color', 'transparent');
    });
  }, normalize:function(prop) {
    return propertyCache[prop] || (propertyCache[prop] = prop.replace(msRe, 'ms-').replace(camelRe, camelReplaceFn));
  }, _onWindowFocusChange:function(e) {
    if (Ext.fly(e.target).is(Element.editableSelector)) {
      lastFocusChange = new Date;
      editableHasFocus = e.type === 'focusin' || e.type === 'pointerup';
    }
  }, _onWindowResize:function() {
    var documentWidth = docEl.clientWidth, documentHeight = docEl.clientHeight, now = new Date, threshold = 1000, deltaX, deltaY;
    deltaX = documentWidth - Element._documentWidth;
    deltaY = documentHeight - Element._documentHeight;
    Element._documentWidth = documentWidth;
    Element._documentHeight = documentHeight;
    if (now - lastFocusChange < threshold || now - lastKeyboardClose < threshold) {
      if (deltaX === 0 && (editableHasFocus && deltaY <= -Element.minKeyboardHeight)) {
        isVirtualKeyboardOpen = true;
        return;
      }
    }
    if (isVirtualKeyboardOpen && deltaX === 0 && deltaY >= Element.minKeyboardHeight) {
      isVirtualKeyboardOpen = false;
      lastKeyboardClose = new Date;
    }
    if (isVirtualKeyboardOpen) {
      return;
    }
    Element._viewportWidth = documentWidth;
    Element._viewportHeight = documentHeight;
  }, parseBox:function(box) {
    var type, parts, ln;
    box = box || 0;
    type = typeof box;
    if (type === 'number') {
      return {top:box, right:box, bottom:box, left:box};
    } else {
      if (type !== 'string') {
        return box;
      }
    }
    parts = box.split(' ');
    ln = parts.length;
    if (ln === 1) {
      parts[1] = parts[2] = parts[3] = parts[0];
    } else {
      if (ln === 2) {
        parts[2] = parts[0];
        parts[3] = parts[1];
      } else {
        if (ln === 3) {
          parts[3] = parts[1];
        }
      }
    }
    return {top:parseFloat(parts[0]) || 0, right:parseFloat(parts[1]) || 0, bottom:parseFloat(parts[2]) || 0, left:parseFloat(parts[3]) || 0};
  }, parseStyles:function(styles) {
    var out = {}, matches;
    if (styles) {
      cssRe.lastIndex = 0;
      while (matches = cssRe.exec(styles)) {
        out[matches[1]] = matches[2] || '';
      }
    }
    return out;
  }, select:function(selector, composite, root) {
    return Ext.fly(root || DOC).select(selector, composite);
  }, query:function(selector, asDom, root) {
    return Ext.fly(root || DOC).query(selector, asDom);
  }, unitizeBox:function(box, units) {
    var me = this;
    box = me.parseBox(box);
    return me.addUnits(box.top, units) + ' ' + me.addUnits(box.right, units) + ' ' + me.addUnits(box.bottom, units) + ' ' + me.addUnits(box.left, units);
  }, unmaskIframes:function() {
    var iframes = document.getElementsByTagName('iframe'), fly = new Ext.dom.Fly;
    Ext.each(iframes, function(iframe) {
      fly.attach(iframe.parentNode).unmask();
    });
  }, serializeForm:function(form) {
    var fElements = form.elements || (DOC.forms[form] || Ext.getDom(form)).elements, hasSubmit = false, encoder = encodeURIComponent, data = '', eLen = fElements.length, element, name, type, options, hasValue, e, o, oLen, opt;
    for (e = 0; e < eLen; e++) {
      element = fElements[e];
      name = element.name;
      type = element.type;
      options = element.options;
      if (!element.disabled && name) {
        if (/select-(one|multiple)/i.test(type)) {
          oLen = options.length;
          for (o = 0; o < oLen; o++) {
            opt = options[o];
            if (opt.selected) {
              hasValue = opt.hasAttribute('value');
              data += Ext.String.format('{0}\x3d{1}\x26', encoder(name), encoder(hasValue ? opt.value : opt.text));
            }
          }
        } else {
          if (!/file|undefined|reset|button/i.test(type)) {
            if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type === 'submit' && hasSubmit)) {
              data += encoder(name) + '\x3d' + encoder(element.value) + '\x26';
              hasSubmit = /submit/i.test(type);
            }
          }
        }
      }
    }
    return data.substr(0, data.length - 1);
  }, getCommonAncestor:function(nodeA, nodeB, returnDom) {
    caFly = caFly || new Ext.dom.Fly;
    caFly.attach(Ext.getDom(nodeA));
    while (!caFly.isAncestor(nodeB)) {
      if (caFly.dom.parentNode) {
        caFly.attach(caFly.dom.parentNode);
      } else {
        caFly.attach(DOC.body);
        break;
      }
    }
    return returnDom ? caFly.dom : Ext.get(caFly);
  }}, selectable:function() {
    var me = this;
    me.dom.unselectable = '';
    me.removeCls(Element.unselectableCls);
    me.addCls(Element.selectableCls);
    return me;
  }, unselectable:function() {
    var me = this;
    if (Ext.isOpera) {
      me.dom.unselectable = 'on';
    }
    me.removeCls(Element.selectableCls);
    me.addCls(Element.unselectableCls);
    return me;
  }, statics:{tabbableSelector:Ext.supports.CSS3NegationSelector ? 'a[href],button,iframe,input,select,textarea,[tabindex]:not([tabindex\x3d"-1"]),[contenteditable\x3d"true"]' : 'a[href],button,iframe,input,select,textarea,[tabindex],[contenteditable\x3d"true"]', naturallyFocusableTags:{BUTTON:true, IFRAME:true, EMBED:true, INPUT:true, OBJECT:true, SELECT:true, TEXTAREA:true, HTML:Ext.isIE ? true : false, BODY:Ext.isIE ? false : true}, naturallyTabbableTags:{BUTTON:true, IFRAME:true, INPUT:true, 
  SELECT:true, TEXTAREA:true, OBJECT:Ext.isIE8m ? true : false}, inputTags:{INPUT:true, TEXTAREA:true}, tabbableSavedCounterAttribute:'data-tabindex-counter', tabbableSavedValueAttribute:'data-tabindex-value', splitCls:function(cls) {
    if (typeof cls === 'string') {
      cls = cls.split(spacesRe);
    }
    return cls;
  }}, _init:function(E) {
    E.tabbableSelector += ',[' + E.tabbableSavedCounterAttribute + ']';
  }, addCls:function(names, prefix, suffix) {
    return this.replaceCls(null, names, prefix, suffix);
  }, addClsOnClick:function(className, testFn, scope) {
    var me = this, hasTest = Ext.isFunction(testFn);
    me.on('mousedown', function() {
      if (hasTest && testFn.call(scope || me, me) === false) {
        return false;
      }
      me.addCls(className);
      Ext.getDoc().on({mouseup:function() {
        if (me.dom) {
          me.removeCls(className);
        }
      }, single:true});
    });
    return me;
  }, addClsOnFocus:function(className, testFn, scope) {
    var me = this, hasTest = Ext.isFunction(testFn);
    me.on('focus', function() {
      if (hasTest && testFn.call(scope || me, me) === false) {
        return false;
      }
      me.addCls(className);
    });
    me.on('blur', function() {
      if (me.dom) {
        me.removeCls(className);
      }
    });
    return me;
  }, addClsOnOver:function(className, testFn, scope) {
    var me = this, hasTest = Ext.isFunction(testFn);
    me.hover(function() {
      if (hasTest && testFn.call(scope || me, me) === false) {
        return;
      }
      me.addCls(className);
    }, function() {
      me.removeCls(className);
    });
    return me;
  }, addStyles:function(sides, styles) {
    var totalSize = 0, sidesArr = (sides || '').match(wordsRe), styleSides = [], len = sidesArr.length, side, i;
    if (len === 1) {
      totalSize = parseFloat(this.getStyle(styles[sidesArr[0]])) || 0;
    } else {
      if (len) {
        for (i = 0; i < len; i++) {
          side = sidesArr[i];
          styleSides.push(styles[side]);
        }
        styleSides = this.getStyle(styleSides);
        for (i = 0; i < len; i++) {
          side = sidesArr[i];
          totalSize += parseFloat(styleSides[styles[side]]) || 0;
        }
      }
    }
    return totalSize;
  }, addUnits:function(size, units) {
    return Element.addUnits(size, units);
  }, animate:function(animation) {
    animation = new Ext.fx.Animation(animation);
    animation.setElement(this);
    this._activeAnimation = animation;
    animation.on({animationend:this._onAnimationEnd, scope:this});
    Ext.Animator.run(animation);
    return animation;
  }, _onAnimationEnd:function() {
    this._activeAnimation = null;
  }, getActiveAnimation:function() {
    return this._activeAnimation;
  }, append:function() {
    return this.appendChild.apply(this, arguments);
  }, appendChild:function(el, returnDom) {
    var me = this, insertEl, eLen, e;
    if (el.nodeType || el.dom || typeof el === 'string') {
      el = Ext.getDom(el);
      me.dom.appendChild(el);
      return !returnDom ? Ext.get(el) : el;
    } else {
      if (el.length) {
        insertEl = Ext.fly(DOC.createDocumentFragment());
        eLen = el.length;
        for (e = 0; e < eLen; e++) {
          insertEl.appendChild(el[e], returnDom);
        }
        el = Ext.Array.toArray(insertEl.dom.childNodes);
        me.dom.appendChild(insertEl.dom);
        return returnDom ? el : new Ext.dom.CompositeElementLite(el);
      } else {
        return me.createChild(el, null, returnDom);
      }
    }
  }, appendTo:function(el) {
    Ext.getDom(el).appendChild(this.dom);
    return this;
  }, applyStyles:function(styles) {
    if (styles) {
      if (typeof styles === 'function') {
        styles = styles.call();
      }
      if (typeof styles === 'string') {
        styles = Element.parseStyles(styles);
      }
      if (typeof styles === 'object') {
        this.setStyle(styles);
      }
    }
    return this;
  }, blur:function() {
    var me = this, dom = me.dom;
    if (dom !== DOC.body) {
      try {
        dom.blur();
      } catch (e$50) {
      }
      return me;
    } else {
      return me.focus(undefined, dom);
    }
  }, cacheScrollValues:function() {
    var me = this, scrollValues = [], scrolledDescendants = [], descendants, descendant, i, len;
    scrollFly = scrollFly || new Ext.dom.Fly;
    descendants = me.query('*');
    for (i = 0, len = descendants.length; i < len; i++) {
      descendant = descendants[i];
      if (descendant.scrollTop > 0 || descendant.scrollLeft !== 0) {
        scrolledDescendants.push(descendant);
        scrollValues.push(scrollFly.attach(descendant).getScroll());
      }
    }
    return function() {
      var scroll, i, len;
      for (i = 0, len = scrolledDescendants.length; i < len; i++) {
        scroll = scrollValues[i];
        scrollFly.attach(scrolledDescendants[i]);
        scrollFly.setScrollLeft(scroll.left);
        scrollFly.setScrollTop(scroll.top);
      }
    };
  }, center:function(centerIn) {
    return this.alignTo(centerIn || DOC, 'c-c');
  }, child:function(selector, returnDom) {
    var me = this, id;
    if (Ext.supports.Selectors2) {
      return me.selectNode(':scope\x3e' + selector, !!returnDom);
    } else {
      id = me.id != null ? me.id : Ext.get(me).id;
      return me.selectNode(Ext.makeIdSelector(id) + ' \x3e ' + selector, !!returnDom);
    }
  }, clone:function(deep, returnDom) {
    var clone = this.dom.cloneNode(deep);
    if (Ext.supports.CloneNodeCopiesExpando) {
      clearData(clone, deep);
    }
    return returnDom ? clone : Ext.get(clone);
  }, constrainScrollLeft:function(left) {
    var dom = this.dom;
    return Math.max(Math.min(left, dom.scrollWidth - dom.clientWidth), 0);
  }, constrainScrollTop:function(top) {
    var dom = this.dom;
    return Math.max(Math.min(top, dom.scrollHeight - dom.clientHeight), 0);
  }, createChild:function(config, insertBefore, returnDom) {
    config = config || {tag:'div'};
    if (insertBefore) {
      return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
    } else {
      return Ext.DomHelper.append(this.dom, config, returnDom !== true);
    }
  }, contains:function(element) {
    if (!element) {
      return false;
    }
    var me = this, dom = Ext.getDom(element);
    return dom === me.dom || me.isAncestor(dom);
  }, destroy:function() {
    var me = this, dom = me.dom;
    if (me.destroyed) {
      Ext.Logger.warn('Cannot destroy Element "' + me.id + '". Already destroyed.');
      return;
    }
    if (me.resumeFocusEventsTimer) {
      Ext.unasap(me.resumeFocusEventsTimer);
      me.resumeFocusEventsTimer = null;
    }
    if (me.repaintTimer) {
      me.repaintTimer = Ext.undefer(me.repaintTimer);
    }
    if (me.deferFocusTimer) {
      me.deferFocusTimer = Ext.undefer(me.deferFocusTimer);
    }
    if (dom) {
      if (dom === DOC.body) {
        Ext.raise('Cannot destroy body element.');
      } else {
        if (dom === DOC) {
          Ext.raise('Cannot destroy document object.');
        } else {
          if (dom === WIN) {
            Ext.raise('Cannot destroy window object');
          }
        }
      }
    }
    if (dom && dom.parentNode) {
      dom.parentNode.removeChild(dom);
    }
    if (me.$ripples) {
      me.destroyAllRipples();
    }
    me.collect();
  }, detach:function() {
    var dom = this.dom, component = this.component;
    if (dom && dom.parentNode && dom.tagName !== 'BODY') {
      if (component) {
        component.revertFocus();
      }
      dom.parentNode.removeChild(dom);
    }
    return this;
  }, disableShadow:function() {
    var shadow = this.shadow;
    if (shadow) {
      shadow.hide();
      shadow.disabled = true;
    }
  }, disableShim:function() {
    var shim = this.shim;
    if (shim) {
      shim.hide();
      shim.disabled = true;
    }
  }, doReplaceWith:function(element) {
    var dom = this.dom;
    dom.parentNode.replaceChild(Ext.getDom(element), dom);
  }, doScrollIntoView:function(container, hscroll, animate, highlight, getScrollX, scrollTo) {
    scrollFly = scrollFly || new Ext.dom.Fly;
    var me = this, dom = me.dom, scrollX = scrollFly.attach(container)[getScrollX](), scrollY = container.scrollTop, position = me.getScrollIntoViewXY(container, scrollX, scrollY), newScrollX = position.x, newScrollY = position.y;
    if (highlight) {
      if (animate) {
        animate = Ext.apply({listeners:{afteranimate:function() {
          scrollFly.attach(dom).highlight();
        }}}, animate);
      } else {
        scrollFly.attach(dom).highlight();
      }
    }
    if (newScrollY !== scrollY) {
      scrollFly.attach(container).scrollTo('top', newScrollY, animate);
    }
    if (hscroll !== false && newScrollX !== scrollX) {
      scrollFly.attach(container)[scrollTo]('left', newScrollX, animate);
    }
    return me;
  }, down:function(selector, returnDom) {
    return this.selectNode(selector, !!returnDom);
  }, enableShadow:function(options, isVisible) {
    var me = this, shadow = me.shadow || (me.shadow = new Ext.dom.Shadow(Ext.apply({target:me}, options))), shim = me.shim;
    if (shim) {
      shim.offsets = shadow.outerOffsets;
      shim.shadow = shadow;
      shadow.shim = shim;
    }
    if (isVisible === true || isVisible !== false && me.isVisible()) {
      shadow.show();
    } else {
      shadow.hide();
    }
    shadow.disabled = false;
  }, enableShim:function(options, isVisible) {
    var me = this, shim = me.shim || (me.shim = new Ext.dom.Shim(Ext.apply({target:me}, options))), shadow = me.shadow;
    if (shadow) {
      shim.offsets = shadow.outerOffsets;
      shim.shadow = shadow;
      shadow.shim = shim;
    }
    if (isVisible === true || isVisible !== false && me.isVisible()) {
      shim.show();
    } else {
      shim.hide();
    }
    shim.disabled = false;
    return shim;
  }, findParent:function(simpleSelector, limit, returnEl) {
    var me = this, target = me.dom, topmost = docEl, depth = 0;
    if (limit || limit === 0) {
      if (typeof limit !== 'number') {
        topmost = Ext.getDom(limit);
        limit = Number.MAX_VALUE;
      }
    } else {
      limit = 50;
    }
    while (target && target.nodeType === 1 && depth < limit && target !== topmost) {
      if (Ext.fly(target).is(simpleSelector)) {
        return returnEl ? Ext.get(target) : target;
      }
      depth++;
      target = target.parentNode;
    }
    return null;
  }, findParentNode:function(simpleSelector, limit, returnEl) {
    var p = Ext.fly(this.dom.parentNode);
    return p ? p.findParent(simpleSelector, limit, returnEl) : null;
  }, first:function(selector, returnDom) {
    return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
  }, focus:function(defer, dom) {
    var me = this;
    dom = dom || me.dom;
    if (Number(defer)) {
      Ext.defer(me.focus, defer, me, [null, dom]);
    } else {
      Ext.fireEvent('beforefocus', dom);
      dom.focus();
    }
    return me;
  }, collect:function() {
    var me = this, dom = me.dom, shadow = me.shadow, shim = me.shim;
    if (!me.isFly) {
      me.mixins.observable.destroy.call(me);
      delete Ext.cache[me.id];
      me.el = null;
    }
    if (dom) {
      dom._extData = me.dom = null;
    }
    if (shadow) {
      shadow.hide();
      me.shadow = null;
    }
    if (shim) {
      shim.hide();
      me.shim = null;
    }
  }, getAnchorToXY:function(el, anchor, local, mySize) {
    return el.getAnchorXY(anchor, local, mySize);
  }, getAttribute:function(name, namespace) {
    var dom = this.dom;
    return namespace ? dom.getAttributeNS(namespace, name) || dom.getAttribute(namespace + ':' + name) : dom.getAttribute(name) || dom[name] || null;
  }, getAttributes:function() {
    var attributes = this.dom.attributes, result = {}, attr, i, len;
    for (i = 0, len = attributes.length; i < len; i++) {
      attr = attributes[i];
      result[attr.name] = attr.value;
    }
    return result;
  }, getBottom:function(local) {
    return (local ? this.getLocalY() : this.getY()) + this.getHeight();
  }, getById:function(id, asDom) {
    var dom = DOC.getElementById(id) || this.dom.querySelector(Ext.makeIdSelector(id));
    return asDom ? dom : dom ? Ext.get(dom) : null;
  }, getBorderPadding:function() {
    var paddingWidth = this.getStyle(paddingsTLRB), bordersWidth = this.getStyle(bordersTLRB);
    return {beforeX:(parseFloat(bordersWidth[borders.l]) || 0) + (parseFloat(paddingWidth[paddings.l]) || 0), afterX:(parseFloat(bordersWidth[borders.r]) || 0) + (parseFloat(paddingWidth[paddings.r]) || 0), beforeY:(parseFloat(bordersWidth[borders.t]) || 0) + (parseFloat(paddingWidth[paddings.t]) || 0), afterY:(parseFloat(bordersWidth[borders.b]) || 0) + (parseFloat(paddingWidth[paddings.b]) || 0)};
  }, getBorders:function() {
    var bordersWidth = this.getStyle(bordersTLRB);
    return {beforeX:parseFloat(bordersWidth[borders.l]) || 0, afterX:parseFloat(bordersWidth[borders.r]) || 0, beforeY:parseFloat(bordersWidth[borders.t]) || 0, afterY:parseFloat(bordersWidth[borders.b]) || 0};
  }, getBorderWidth:function(side) {
    return this.addStyles(side, borders);
  }, getClassMap:function(clone) {
    var data = this.getData();
    if (data) {
      data = data.classMap;
      if (clone !== false) {
        data = Ext.apply({}, data);
      }
    }
    return data;
  }, getData:function(sync) {
    var dom = this.dom, data;
    if (dom) {
      data = dom._extData || (dom._extData = {});
      if (sync !== false && !data.isSynchronized) {
        this.synchronize();
      }
    }
    return data || null;
  }, getFirstChild:function() {
    return Ext.get(this.dom.firstElementChild);
  }, getLastChild:function() {
    return Ext.get(this.dom.lastElementChild);
  }, getHeight:function(contentHeight, preciseHeight) {
    var me = this, dom = me.dom, hidden = me.isStyle('display', 'none'), height, floating;
    if (hidden) {
      return 0;
    }
    if (dom.nodeName === 'BODY') {
      height = Element.getViewportHeight();
    } else {
      if (preciseHeight) {
        height = dom.getBoundingClientRect().height;
      } else {
        height = dom.offsetHeight;
        if (height == null) {
          height = dom.getBoundingClientRect().height;
        }
      }
    }
    if (Ext.supports.Direct2DBug) {
      floating = me.adjustDirect2DDimension(HEIGHT);
      if (preciseHeight) {
        height += floating;
      } else {
        if (floating > 0 && floating < 0.5) {
          height++;
        }
      }
    }
    if (contentHeight) {
      height -= me.getBorderWidth('tb') + me.getPadding('tb');
    }
    return height < 0 ? 0 : height;
  }, getHtml:function() {
    return this.dom ? this.dom.innerHTML : '';
  }, getLeft:function(local) {
    return local ? this.getLocalX() : this.getX();
  }, getLocalX:function() {
    var me = this, offsetParent, x = me.getStyle('left');
    if (!x || x === 'auto') {
      x = 0;
    } else {
      if (pxRe.test(x)) {
        x = parseFloat(x);
      } else {
        x = me.getX();
        offsetParent = me.dom.offsetParent;
        if (offsetParent) {
          x -= Ext.fly(offsetParent).getX();
        }
      }
    }
    return x;
  }, getLocalXY:function() {
    var me = this, offsetParent, style = me.getStyle(['left', 'top']), x = style.left, y = style.top;
    if (!x || x === 'auto') {
      x = 0;
    } else {
      if (pxRe.test(x)) {
        x = parseFloat(x);
      } else {
        x = me.getX();
        offsetParent = me.dom.offsetParent;
        if (offsetParent) {
          x -= Ext.fly(offsetParent).getX();
        }
      }
    }
    if (!y || y === 'auto') {
      y = 0;
    } else {
      if (pxRe.test(y)) {
        y = parseFloat(y);
      } else {
        y = me.getY();
        offsetParent = me.dom.offsetParent;
        if (offsetParent) {
          y -= Ext.fly(offsetParent).getY();
        }
      }
    }
    return [x, y];
  }, getLocalY:function() {
    var me = this, offsetParent, y = me.getStyle('top');
    if (!y || y === 'auto') {
      y = 0;
    } else {
      if (pxRe.test(y)) {
        y = parseFloat(y);
      } else {
        y = me.getY();
        offsetParent = me.dom.offsetParent;
        if (offsetParent) {
          y -= Ext.fly(offsetParent).getY();
        }
      }
    }
    return y;
  }, getMargin:function() {
    var hash = {t:'top', l:'left', r:'right', b:'bottom'}, allMargins = ['margin-top', 'margin-left', 'margin-right', 'margin-bottom'];
    return function(side) {
      var me = this, style, key, o;
      if (!side) {
        style = me.getStyle(allMargins);
        o = {};
        if (style && typeof style === 'object') {
          o = {};
          for (key in margins) {
            o[key] = o[hash[key]] = parseFloat(style[margins[key]]) || 0;
          }
        }
      } else {
        o = me.addStyles(side, margins);
      }
      return o;
    };
  }(), getPadding:function(side) {
    return this.addStyles(side, paddings);
  }, getParent:function() {
    return Ext.get(this.dom.parentNode);
  }, getRight:function(local) {
    return (local ? this.getLocalX() : this.getX()) + this.getWidth();
  }, getScroll:function() {
    var me = this, dom = me.dom, docElement = docEl, left, top, body = DOC.body;
    if (dom === DOC || dom === body) {
      left = docElement.scrollLeft || (body ? body.scrollLeft : 0);
      top = docElement.scrollTop || (body ? body.scrollTop : 0);
    } else {
      left = dom.scrollLeft;
      top = dom.scrollTop;
    }
    return {left:left, top:top};
  }, getScrollIntoViewXY:function(container, scrollX, scrollY, align) {
    var me = this, dom = me.dom, offsets, clientWidth, clientHeight;
    align = align || empty;
    if (container.isRegion) {
      clientHeight = container.height;
      clientWidth = container.width;
    } else {
      container = Ext.getDom(container);
      clientHeight = container.clientHeight;
      clientWidth = container.clientWidth;
    }
    offsets = me.getOffsetsTo(container);
    return {y:me.calcScrollPos(offsets[1] + scrollY, dom.offsetHeight, scrollY, clientHeight, align.y), x:me.calcScrollPos(offsets[0] + scrollX, dom.offsetWidth, scrollX, clientWidth, align.x)};
  }, calcScrollPos:function(start, size, viewStart, viewSize, align) {
    var end = start + size, viewEnd = viewStart + viewSize, force = align && !endsQuestionRe.test(align), ret = viewStart;
    if (!force) {
      if (align) {
        align = align.slice(0, -1);
      }
      if (size > viewSize || start < viewStart) {
        align = align || 'start';
        force = true;
      } else {
        if (end > viewEnd) {
          align = align || 'end';
          force = true;
        }
      }
    }
    if (force) {
      if (align === 'start') {
        ret = start;
      } else {
        if (align === 'center') {
          ret = Math.max(0, start - Math.floor(viewSize / 2));
        } else {
          if (align === 'end') {
            ret = Math.max(0, end - viewSize);
          }
        }
      }
    }
    return ret;
  }, getScrollLeft:function() {
    var dom = this.dom;
    if (dom === DOC || dom === DOC.body) {
      return this.getScroll().left;
    } else {
      return dom.scrollLeft;
    }
  }, getScrollTop:function() {
    var dom = this.dom;
    if (dom === DOC || dom === DOC.body) {
      return this.getScroll().top;
    } else {
      return dom.scrollTop;
    }
  }, getSize:function(contentSize) {
    return {width:this.getWidth(contentSize), height:this.getHeight(contentSize)};
  }, getStyle:function(property, inline) {
    var me = this, dom = me.dom, multiple = typeof property !== 'string', hooks = me.styleHooks, prop = property, props = prop, len = 1, domStyle, camel, values, hook, out, style, i;
    if (multiple) {
      values = {};
      prop = props[0];
      i = 0;
      if (!(len = props.length)) {
        return values;
      }
    }
    if (!dom || dom.documentElement) {
      return values || '';
    }
    domStyle = dom.style;
    if (inline) {
      style = domStyle;
    } else {
      style = dom.ownerDocument.defaultView.getComputedStyle(dom, null);
      if (!style) {
        inline = true;
        style = domStyle;
      }
    }
    do {
      hook = hooks[prop];
      if (!hook) {
        hooks[prop] = hook = {name:Element.normalize(prop)};
      }
      if (hook.get) {
        out = hook.get(dom, me, inline, style);
      } else {
        camel = hook.name;
        out = style[camel];
      }
      if (!multiple) {
        return out;
      }
      values[prop] = out;
      prop = props[++i];
    } while (i < len);
    return values;
  }, getStyleValue:function(name) {
    return this.dom.style.getPropertyValue(name);
  }, getCaretPos:function() {
    var dom = this.dom, pos, selection;
    if (inputTypeSelectionSupported.test(dom.type)) {
      pos = dom.selectionStart;
      selection = typeof pos !== 'number' && this.getTextSelection();
      if (selection) {
        pos = selection[0];
      }
    } else {
      Ext.raise('Input type of "' + dom.type + '" does not support selectionStart');
    }
    return pos;
  }, setCaretPos:function(pos) {
    this.selectText(pos, pos);
  }, getTextSelection:function() {
    var dom = this.dom;
    if (inputTypeSelectionSupported.test(dom.type)) {
      return [dom.selectionStart, dom.selectionEnd, dom.selectionDirection];
    } else {
      Ext.raise('Input type of "' + this.dom.type + '" does not support selectionStart, selectionEnd and selectionDirection');
      return [];
    }
  }, selectText:function(start, end, direction) {
    var me = this, range, dom = me.dom, len;
    if (dom && inputTypeSelectionSupported.test(dom.type)) {
      start = start || 0;
      len = dom.value.length;
      if (end === undefined) {
        end = len;
      }
      direction = selectDir[direction] || direction || 'forward';
      if (dom.setSelectionRange) {
        dom.setSelectionRange(start, end, direction);
      } else {
        if (dom.createTextRange) {
          if (start > end) {
            start = end;
          }
          range = dom.createTextRange();
          range.moveStart('character', start);
          range.moveEnd('character', -(len - end));
          range.select();
        }
      }
    } else {
      if (!inputTypeSelectionSupported.test(dom.type)) {
        Ext.raise('Input type of "' + dom.type + '" does not support setSelectionRange');
      }
    }
    return me;
  }, getTop:function(local) {
    return local ? this.getLocalY() : this.getY();
  }, getTouchAction:function() {
    return Ext.dom.TouchAction.get(this.dom);
  }, getValue:function(asNumber) {
    var value = this.dom.value;
    return asNumber ? parseInt(value, 10) : value;
  }, getViewSize:function() {
    var dom = this.dom;
    if (dom === DOC || dom === DOC.body) {
      return {width:Element.getViewportWidth(), height:Element.getViewportHeight()};
    } else {
      return {width:dom.clientWidth, height:dom.clientHeight};
    }
  }, getVisibilityMode:function() {
    var me = this, data = me.getData(), mode = data.visibilityMode;
    if (mode === undefined) {
      data.visibilityMode = mode = Element.DISPLAY;
    }
    return mode;
  }, getWidth:function(contentWidth, preciseWidth) {
    var me = this, dom = me.dom, hidden = me.isStyle('display', 'none'), rect, width, floating;
    if (hidden) {
      return 0;
    }
    if (Ext.supports.BoundingClientRect) {
      rect = dom.getBoundingClientRect();
      width = me.vertical && !Ext.supports.RotatedBoundingClientRect ? rect.bottom - rect.top : rect.right - rect.left;
      width = preciseWidth ? width : Math.ceil(width);
    } else {
      width = dom.offsetWidth;
    }
    if (Ext.supports.Direct2DBug && !me.vertical) {
      floating = me.adjustDirect2DDimension(WIDTH);
      if (preciseWidth) {
        width += floating;
      } else {
        if (floating > 0 && floating < 0.5) {
          width++;
        }
      }
    }
    if (contentWidth) {
      width -= me.getBorderWidth('lr') + me.getPadding('lr');
    }
    return width < 0 ? 0 : width;
  }, getX:function() {
    return this.getXY()[0];
  }, getXY:function() {
    var round = Math.round, dom = this.dom, body = DOC.body, x = 0, y = 0, bodyRect, rect;
    if (dom !== DOC && dom !== body) {
      try {
        bodyRect = body.getBoundingClientRect();
        rect = dom.getBoundingClientRect();
        x = rect.left - bodyRect.left;
        y = rect.top - bodyRect.top;
      } catch (ex) {
      }
    }
    return [round(x), round(y)];
  }, getY:function() {
    return this.getXY()[1];
  }, getZIndex:function() {
    return parseInt(this.getStyle('z-index'), 10);
  }, hasCls:function(name) {
    var classMap = this.getClassMap();
    return classMap.hasOwnProperty(name);
  }, hide:function() {
    return this.setVisible(false);
  }, hover:function(overFn, outFn, scope, options) {
    var me = this;
    me.on('mouseenter', overFn, scope || me.dom, options);
    me.on('mouseleave', outFn, scope || me.dom, options);
    return me;
  }, indexOf:function(childEl) {
    var children = this.dom, c = childEl && Ext.getDom(childEl);
    children = children && children.childNodes;
    return c && children ? Array.prototype.indexOf.call(children, c) : -1;
  }, insertAfter:function(el) {
    el = Ext.getDom(el);
    el.parentNode.insertBefore(this.dom, el.nextSibling);
    return this;
  }, insertBefore:function(el) {
    el = Ext.getDom(el);
    el.parentNode.insertBefore(this.dom, el);
    return this;
  }, insertFirst:function(el, returnDom) {
    el = el || {};
    if (el.nodeType || el.dom || typeof el === 'string') {
      el = Ext.getDom(el);
      this.dom.insertBefore(el, this.dom.firstChild);
      return !returnDom ? Ext.get(el) : el;
    } else {
      return this.createChild(el, this.dom.firstChild, returnDom);
    }
  }, insertHtml:function(where, html, returnEl) {
    var el = Ext.DomHelper.insertHtml(where, this.dom, html);
    return returnEl ? Ext.get(el) : el;
  }, insertSibling:function(el, where, returnDom) {
    var me = this, DomHelper = Ext.DomHelper, isAfter = (where || 'before').toLowerCase() === 'after', rt, insertEl, eLen, e;
    if (Ext.isIterable(el)) {
      eLen = el.length;
      insertEl = Ext.fly(DOC.createDocumentFragment());
      if (Ext.isArray(el)) {
        for (e = 0; e < eLen; e++) {
          rt = insertEl.appendChild(el[e], returnDom);
        }
      } else {
        for (e = 0; e < eLen; e++) {
          insertEl.dom.appendChild(rt = el[0]);
        }
        if (returnDom === false) {
          rt = Ext.get(rt);
        }
      }
      me.dom.parentNode.insertBefore(insertEl.dom, isAfter ? me.dom.nextSibling : me.dom);
      return rt;
    }
    el = el || {};
    if (el.nodeType || el.dom) {
      rt = me.dom.parentNode.insertBefore(Ext.getDom(el), isAfter ? me.dom.nextSibling : me.dom);
      if (!returnDom) {
        rt = Ext.get(rt);
      }
    } else {
      if (isAfter && !me.dom.nextSibling) {
        rt = DomHelper.append(me.dom.parentNode, el, !returnDom);
      } else {
        rt = DomHelper[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
      }
    }
    return rt;
  }, is:function(selector) {
    var dom = this.dom, is;
    if (!selector) {
      is = true;
    } else {
      if (!dom.tagName) {
        is = false;
      } else {
        if (Ext.isFunction(selector)) {
          is = selector(dom);
        } else {
          is = dom[Ext.supports.matchesSelector](selector);
        }
      }
    }
    return is;
  }, isAncestor:function(el) {
    var ret = false, dom = this.dom, child = Ext.getDom(el);
    if (dom && child) {
      if (!child.nodeType) {
        return false;
      }
      if (dom.contains) {
        return dom.contains(child);
      } else {
        if (dom.compareDocumentPosition) {
          return !!(dom.compareDocumentPosition(child) & 16);
        } else {
          while (child = child.parentNode) {
            ret = child === dom || ret;
          }
        }
      }
    }
    return ret;
  }, isPainted:function() {
    return !Ext.browser.is.IE ? function() {
      var dom = this.dom;
      return Boolean(dom && dom.offsetParent);
    } : function() {
      var dom = this.dom;
      return Boolean(dom && (dom.offsetHeight !== 0 || dom.offsetWidth !== 0));
    };
  }(), isScrollable:function() {
    var dom = this.dom;
    return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
  }, isStyle:function(style, val) {
    return this.getStyle(style) === val;
  }, isVisible:function(deep, mode) {
    var dom = this.dom, visible = true, end;
    if (!dom) {
      return false;
    }
    mode = mode || 3;
    if (!visFly) {
      visFly = new Ext.dom.Fly;
    }
    for (end = dom.ownerDocument.documentElement; dom !== end; dom = dom.parentNode) {
      if (!dom || dom.nodeType === 11) {
        visible = false;
      }
      if (visible) {
        visFly.attach(dom);
        if (mode & 1) {
          visible = !visFly.isStyle(DISPLAY, NONE);
        }
        if (visible && mode & 2) {
          visible = !visFly.isStyle(VISIBILITY, HIDDEN);
        }
      }
      if (!visible || !deep) {
        break;
      }
    }
    return visible;
  }, last:function(selector, returnDom) {
    return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
  }, matchNode:function(dir, start, selector, returnDom) {
    var dom = this.dom, n;
    if (!dom) {
      return null;
    }
    n = dom[start];
    while (n) {
      if (n.nodeType === 1 && (!selector || Ext.fly(n, '_matchNode').is(selector))) {
        return !returnDom ? Ext.get(n) : n;
      }
      n = n[dir];
    }
    return null;
  }, measure:function(dimension) {
    var me = this, dom = me.dom, includeWidth = dimension !== 'h', includeHeight = dimension !== 'w', width = 0, height = 0, addPadding = !Ext.supports.ComputedSizeIncludesPadding, style, rect, offsetParent;
    if (dom.nodeName === 'BODY') {
      height = includeHeight && Element.getViewportHeight();
      width = includeWidth && Element.getViewportWidth();
    } else {
      offsetParent = dom.offsetParent;
      style = dom.ownerDocument.defaultView.getComputedStyle(dom, null);
      addPadding |= style.boxSizing === 'content-box';
      if (offsetParent !== null || style.position === 'fixed') {
        if (includeHeight) {
          height = toFloat(style.height);
          if (addPadding) {
            height += toFloat(style.paddingTop) + toFloat(style.paddingBottom) + toFloat(style.borderTopWidth) + toFloat(style.borderBottomWidth);
          }
        }
        if (includeWidth) {
          width = toFloat(style.width);
          if (addPadding) {
            width += toFloat(style.paddingLeft) + toFloat(style.paddingRight) + toFloat(style.borderLeftWidth) + toFloat(style.borderRightWidth);
          }
        }
      }
    }
    rect = dimension ? null : {width:width, height:height};
    return dimension ? includeWidth ? width : height : rect;
  }, measureContent:function(dimension) {
    var me = this, includeWidth = dimension !== 'h', size = me.measure(dimension), h = dimension ? size : size.height, w = dimension ? size : size.width;
    if (dimension !== 'w') {
      h -= me.getBorderWidth('tb') + me.getPadding('tb');
    }
    if (includeWidth) {
      w -= me.getBorderWidth('lr') + me.getPadding('lr');
    }
    return dimension ? includeWidth ? w : h : {width:w, height:h};
  }, monitorMouseLeave:function(delay, handler, scope) {
    var me = this, timer, listeners = {mouseleave:function(e) {
      if (Ext.isIE9m) {
        e.enableIEAsync();
      }
      timer = Ext.defer(handler, delay, scope || me, [e]);
    }, mouseenter:function() {
      Ext.undefer(timer);
    }, destroy:function() {
      Ext.undefer(timer);
      if (!me.destroyed) {
        me.un(listeners);
      }
    }};
    me.on(listeners);
    return listeners;
  }, next:function(selector, returnDom) {
    return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
  }, parent:function(selector, returnDom) {
    return this.matchNode('parentNode', 'parentNode', selector, returnDom);
  }, peekData:function() {
    var dom = this.dom;
    return dom && dom._extData || null;
  }, position:function(pos, zIndex, x, y) {
    var me = this;
    if (me.dom.tagName !== 'BODY') {
      if (!pos && me.isStyle(POSITION, STATIC)) {
        me.setStyle(POSITION, RELATIVE);
      } else {
        if (pos) {
          me.setStyle(POSITION, pos);
        }
      }
      if (zIndex) {
        me.setStyle(ZINDEX, zIndex);
      }
      if (x || y) {
        me.setXY([x || false, y || false]);
      }
    }
  }, prev:function(selector, returnDom) {
    return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
  }, query:function(selector, asDom, single) {
    var dom = this.dom, results, len, nlen, node, nodes, i, j;
    if (!dom) {
      return null;
    }
    asDom = asDom !== false;
    selector = selector.split(',');
    if (!single) {
      results = [];
    }
    for (i = 0, len = selector.length; i < len; i++) {
      if (typeof selector[i] === 'string') {
        if (single) {
          node = dom.querySelector(selector[i]);
          return asDom ? node : Ext.get(node);
        }
        nodes = dom.querySelectorAll(selector[i]);
        for (j = 0, nlen = nodes.length; j < nlen; j++) {
          results.push(asDom ? nodes[j] : Ext.get(nodes[j]));
        }
      }
    }
    return results;
  }, radioCls:function(className) {
    var cn = this.dom.parentNode.childNodes, v, i, len;
    className = Ext.isArray(className) ? className : [className];
    for (i = 0, len = cn.length; i < len; i++) {
      v = cn[i];
      if (v && v.nodeType === 1) {
        Ext.fly(v).removeCls(className);
      }
    }
    return this.addCls(className);
  }, redraw:function() {
    var dom = this.dom, domStyle = dom.style;
    domStyle.display = 'none';
    dom.offsetHeight;
    domStyle.display = '';
  }, remove:function() {
    this.destroy();
  }, removeChild:function(element) {
    this.dom.removeChild(Ext.getDom(element));
    return this;
  }, removeCls:function(names, prefix, suffix) {
    return this.replaceCls(names, null, prefix, suffix);
  }, repaint:function(cls, state) {
    var me = this, off, on;
    if (!cls) {
      cls = Ext.baseCSSPrefix + 'repaint';
      on = !(off = false);
    } else {
      if (state != null) {
        on = state;
        off = !state;
      }
    }
    me.toggleCls(cls, on);
    if (!me.repaintTimer) {
      me.repaintTimer = Ext.defer(function() {
        me.repaintTimer = null;
        if (me.dom) {
          me.toggleCls(cls, off);
        }
      }, 1);
    }
    return me;
  }, replace:function(el, destroy) {
    el = Ext.getDom(el);
    var parentNode = el.parentNode, id = el.id, dom = this.dom;
    if (!parentNode) {
      Ext.raise('Cannot replace element "' + id + '". It is not attached to a parent node.');
    }
    if (destroy !== false && id && Ext.cache[id]) {
      parentNode.insertBefore(dom, el);
      Ext.get(el).destroy();
    } else {
      parentNode.replaceChild(dom, el);
    }
    return this;
  }, replaceCls:function(remove, add, prefix, suffix) {
    var me = this, dom = me.dom, added = 0, removed = 0, rem = remove, data = (add || remove) && me.getData(), list, map, i, n, name;
    if (data) {
      list = data.classList;
      map = data.classMap;
      add = add ? typeof add === 'string' ? add.split(spacesRe) : add : EMPTY;
      rem = rem ? typeof rem === 'string' ? rem.split(spacesRe) : rem : EMPTY;
      prefix = prefix || '';
      if (prefix && prefix[prefix.length - 1] !== '-') {
        prefix += '-';
      }
      suffix = suffix || '';
      if (suffix && suffix[0] !== '-') {
        suffix = '-' + suffix;
      }
      for (i = 0, n = rem.length; i < n; i++) {
        if (!(name = rem[i])) {
          continue;
        }
        name = prefix + name + suffix;
        if (spacesRe.test(name)) {
          Ext.raise('Class names in arrays must not contain spaces');
        }
        if (map[name]) {
          delete map[name];
          ++removed;
        }
      }
      for (i = 0, n = add.length; i < n; i++) {
        if (!(name = add[i])) {
          continue;
        }
        name = prefix + name + suffix;
        if (spacesRe.test(name)) {
          Ext.raise('Class names in arrays must not contain spaces');
        }
        if (!map[name]) {
          map[name] = true;
          if (!removed) {
            list.push(name);
            ++added;
          }
        }
      }
      if (removed) {
        me.setClassMap(map, true);
      } else {
        if (added) {
          list = list.join(' ');
          if (!Ext.isIE8 && dom instanceof SVGElement) {
            dom.setAttribute('class', list);
          } else {
            dom.className = list;
          }
        }
      }
    }
    return me;
  }, replaceWith:function(el) {
    var me = this, dom = me.dom, parent = dom.parentNode, cache = Ext.cache, newDom;
    me.clearListeners();
    if (el.nodeType || el.dom || typeof el === 'string') {
      el = Ext.get(el);
      newDom = parent.insertBefore(el.dom, dom);
    } else {
      newDom = Ext.DomHelper.insertBefore(dom, el);
    }
    parent.removeChild(dom);
    me.dom = newDom;
    if (!me.isFly) {
      delete cache[me.id];
      cache[me.id = Ext.id(newDom)] = me;
    }
    return me;
  }, resolveListenerScope:function(defaultScope) {
    var component = this.component;
    return component ? component.resolveListenerScope(defaultScope) : this;
  }, scroll:function(direction, distance, animate) {
    if (!this.isScrollable()) {
      return false;
    }
    direction = direction.charAt(0);
    var me = this, dom = me.dom, side = direction === 'r' || direction === 'l' ? 'left' : 'top', scrolled = false, currentScroll, constrainedScroll;
    if (direction === 'l' || direction === 't' || direction === 'u') {
      distance = -distance;
    }
    if (side === 'left') {
      currentScroll = dom.scrollLeft;
      constrainedScroll = me.constrainScrollLeft(currentScroll + distance);
    } else {
      currentScroll = dom.scrollTop;
      constrainedScroll = me.constrainScrollTop(currentScroll + distance);
    }
    if (constrainedScroll !== currentScroll) {
      this.scrollTo(side, constrainedScroll, animate);
      scrolled = true;
    }
    return scrolled;
  }, scrollBy:function(deltaX, deltaY, animate) {
    var me = this, dom = me.dom;
    if (deltaX.length) {
      animate = deltaY;
      deltaY = deltaX[1];
      deltaX = deltaX[0];
    } else {
      if (typeof deltaX !== 'number') {
        animate = deltaY;
        deltaY = deltaX.y;
        deltaX = deltaX.x;
      }
    }
    if (deltaX) {
      me.scrollTo('left', me.constrainScrollLeft(dom.scrollLeft + deltaX), animate);
    }
    if (deltaY) {
      me.scrollTo('top', me.constrainScrollTop(dom.scrollTop + deltaY), animate);
    }
    return me;
  }, scrollChildIntoView:function(child, hscroll) {
    Ext.fly(child).scrollIntoView(this, hscroll);
  }, scrollIntoView:function(container, hscroll, animate, highlight) {
    container = Ext.getDom(container) || Ext.getBody().dom;
    return this.doScrollIntoView(container, hscroll, animate, highlight, 'getScrollLeft', 'scrollTo');
  }, scrollTo:function(side, value, animate) {
    var top = topRe.test(side), me = this, prop = top ? 'scrollTop' : 'scrollLeft', dom = me.dom, animCfg;
    if (!animate || !me.anim) {
      dom[prop] = value;
      dom[prop] = value;
    } else {
      animCfg = {to:{}};
      animCfg.to[prop] = value;
      if (Ext.isObject(animate)) {
        Ext.applyIf(animCfg, animate);
      }
      me.animate(animCfg);
    }
    return me;
  }, select:function(selector, composite) {
    var isElementArray, elements;
    if (typeof selector === 'string') {
      elements = this.query(selector, !composite);
    } else {
      if (selector.length === undefined) {
        Ext.raise('Invalid selector specified: ' + selector);
      } else {
        elements = selector;
        isElementArray = true;
      }
    }
    return composite ? new Ext.CompositeElement(elements, !isElementArray) : new Ext.CompositeElementLite(elements, true);
  }, selectNode:function(selector, asDom) {
    return this.query(selector, asDom, true);
  }, set:function(attributes, useSet) {
    var me = this, dom = me.dom, attribute, value;
    for (attribute in attributes) {
      if (attributes.hasOwnProperty(attribute)) {
        value = attributes[attribute];
        if (attribute === 'style') {
          me.applyStyles(value);
        } else {
          if (attribute === 'cls') {
            dom.className = value;
          } else {
            if (useSet !== false) {
              if (value === undefined) {
                dom.removeAttribute(attribute);
              } else {
                dom.setAttribute(attribute, value);
              }
            } else {
              dom[attribute] = value;
            }
          }
        }
      }
    }
    return me;
  }, setBottom:function(bottom) {
    this.dom.style[BOTTOM] = Element.addUnits(bottom);
    return this;
  }, setClassMap:function(classMap, keep) {
    var data = this.getData(false), classList;
    if (data) {
      classMap = keep && classMap || Ext.apply({}, classMap);
      data.classMap = classMap;
      data.classList = classList = Ext.Object.getKeys(classMap);
      data.isSynchronized = true;
      this.dom.className = classList.join(' ');
    }
  }, setCls:function(className) {
    var me = this, elementData = me.getData(false), i, ln, map, classList;
    if (typeof className === 'string') {
      className = className.split(spacesRe);
    }
    elementData.classList = classList = className.slice();
    elementData.classMap = map = {};
    for (i = 0, ln = classList.length; i < ln; i++) {
      map[classList[i]] = true;
    }
    me.dom.className = classList.join(' ');
  }, setDisplayed:function(value) {
    var me = this;
    if (typeof value === 'boolean') {
      value = value ? me._getDisplay() : NONE;
    }
    me.setStyle(DISPLAY, value);
    if (me.shadow || me.shim) {
      me.setUnderlaysVisible(value !== NONE);
    }
    return me;
  }, setHeight:function(height) {
    var me = this;
    me.dom.style[HEIGHT] = Element.addUnits(height);
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setHtml:function(html) {
    if (this.dom) {
      this.dom.innerHTML = html;
    }
    return this;
  }, setId:function(id) {
    var me = this, currentId = me.id, cache = Ext.cache;
    if (currentId) {
      delete cache[currentId];
    }
    me.dom.id = id;
    me.id = id;
    cache[id] = me;
    return me;
  }, setLeft:function(left) {
    var me = this;
    me.dom.style[LEFT] = Element.addUnits(left);
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setLocalX:function(x) {
    var me = this, style = me.dom.style;
    style.right = '';
    style.left = x === null ? 'auto' : x + 'px';
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setLocalXY:function(x, y) {
    var me = this, style = me.dom.style;
    style.right = '';
    if (x && x.length) {
      y = x[1];
      x = x[0];
    }
    if (x === null) {
      style.left = 'auto';
    } else {
      if (x !== undefined) {
        style.left = x + 'px';
      }
    }
    if (y === null) {
      style.top = 'auto';
    } else {
      if (y !== undefined) {
        style.top = y + 'px';
      }
    }
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setLocalY:function(y) {
    var me = this;
    me.dom.style.top = y === null ? 'auto' : y + 'px';
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setMargin:function(margin) {
    var me = this, domStyle = me.dom.style;
    if (margin || margin === 0) {
      margin = me.self.unitizeBox(margin === true ? 5 : margin);
      domStyle.setProperty('margin', margin, 'important');
    } else {
      domStyle.removeProperty('margin-top');
      domStyle.removeProperty('margin-right');
      domStyle.removeProperty('margin-bottom');
      domStyle.removeProperty('margin-left');
    }
  }, setMaxHeight:function(height) {
    this.dom.style[MAX_HEIGHT] = Element.addUnits(height);
    return this;
  }, setMaxWidth:function(width) {
    this.dom.style[MAX_WIDTH] = Element.addUnits(width);
    return this;
  }, setMinHeight:function(height) {
    this.dom.style[MIN_HEIGHT] = Element.addUnits(height);
    return this;
  }, setMinWidth:function(width) {
    this.dom.style[MIN_WIDTH] = Element.addUnits(width);
    return this;
  }, setOpacity:function(opacity) {
    var me = this;
    if (me.dom) {
      me.setStyle('opacity', opacity);
    }
    return me;
  }, setPadding:function(padding) {
    var me = this, domStyle = me.dom.style;
    if (padding || padding === 0) {
      padding = me.self.unitizeBox(padding === true ? 5 : padding);
      domStyle.setProperty('padding', padding, 'important');
    } else {
      domStyle.removeProperty('padding-top');
      domStyle.removeProperty('padding-right');
      domStyle.removeProperty('padding-bottom');
      domStyle.removeProperty('padding-left');
    }
  }, setRight:function(right) {
    this.dom.style[RIGHT] = Element.addUnits(right);
    return this;
  }, setScrollLeft:function(left) {
    this.dom.scrollLeft = left;
    return this;
  }, setScrollTop:function(top) {
    this.dom.scrollTop = top;
    return this;
  }, setSize:function(width, height) {
    var me = this, style = me.dom.style;
    if (Ext.isObject(width)) {
      height = width.height;
      width = width.width;
    }
    if (width !== undefined) {
      style.width = Element.addUnits(width);
    }
    if (height !== undefined) {
      style.height = Element.addUnits(height);
    }
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setStyle:function(prop, value) {
    var me = this, dom = me.dom, hooks = me.styleHooks, style = dom.style, name = prop, hook;
    if (typeof name === 'string') {
      hook = hooks[name];
      if (!hook) {
        hooks[name] = hook = {name:Element.normalize(name)};
      }
      value = value == null ? '' : value;
      if (hook.set) {
        hook.set(dom, value, me);
      } else {
        style[hook.name] = value;
      }
      if (hook.afterSet) {
        hook.afterSet(dom, value, me);
      }
    } else {
      for (name in prop) {
        hook = hooks[name];
        if (!hook) {
          hooks[name] = hook = {name:Element.normalize(name)};
        }
        value = prop[name];
        value = value == null ? '' : value;
        if (hook.set) {
          hook.set(dom, value, me);
        } else {
          style[hook.name] = value;
        }
        if (hook.afterSet) {
          hook.afterSet(dom, value, me);
        }
      }
    }
    return me;
  }, setText:function(text) {
    this.dom.textContent = text;
  }, getText:function() {
    return this.dom.textContent;
  }, setTop:function(top) {
    var me = this;
    me.dom.style[TOP] = Element.addUnits(top);
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setTouchAction:function(touchAction) {
    Ext.dom.TouchAction.set(this.dom, touchAction);
  }, setUnderlaysVisible:function(visible) {
    var shadow = this.shadow, shim = this.shim;
    if (shadow && !shadow.disabled) {
      if (visible) {
        shadow.show();
      } else {
        shadow.hide();
      }
    }
    if (shim && !shim.disabled) {
      if (visible) {
        shim.show();
      } else {
        shim.hide();
      }
    }
  }, setVisibility:function(isVisible) {
    var domStyle = this.dom.style;
    if (isVisible) {
      domStyle.removeProperty('visibility');
    } else {
      domStyle.setProperty('visibility', 'hidden', 'important');
    }
  }, setVisibilityMode:function(mode) {
    if (mode !== 1 && mode !== 2 && mode !== 3 && mode !== 4 && mode !== 5) {
      Ext.raise('visibilityMode must be one of the following: ' + 'Ext.Element.DISPLAY, Ext.Element.VISIBILITY, Ext.Element.OFFSETS, ' + 'Ext.Element.CLIP, or Element.OPACITY');
    }
    this.getData().visibilityMode = mode;
    return this;
  }, setVisible:function(visible) {
    var me = this, mode = me.getVisibilityMode(), addOrRemove = visible ? 'removeCls' : 'addCls';
    switch(mode) {
      case Element.DISPLAY:
        me.removeCls([visibilityCls, offsetsCls, clipCls, opacityCls]);
        me[addOrRemove](displayCls);
        break;
      case Element.VISIBILITY:
        me.removeCls([displayCls, offsetsCls, clipCls, opacityCls]);
        me[addOrRemove](visibilityCls);
        break;
      case Element.OFFSETS:
        me.removeCls([visibilityCls, displayCls, clipCls, opacityCls]);
        me[addOrRemove](offsetsCls);
        break;
      case Element.CLIP:
        me.removeCls([visibilityCls, displayCls, offsetsCls, opacityCls]);
        me[addOrRemove](clipCls);
        break;
      case Element.OPACITY:
        me.removeCls([visibilityCls, displayCls, offsetsCls, clipCls]);
        me[addOrRemove](opacityCls);
        break;
    }
    if (me.shadow || me.shim) {
      me.setUnderlaysVisible(visible);
    }
    if (!visible && me.$ripples) {
      me.destroyAllRipples();
    }
    return me;
  }, setWidth:function(width) {
    var me = this;
    me.dom.style[WIDTH] = Element.addUnits(width);
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setX:function(x) {
    return this.setXY([x, false]);
  }, setXY:function(xy) {
    var me = this, pts = me.translatePoints(xy), style = me.dom.style, pos;
    me.position();
    style.right = '';
    for (pos in pts) {
      if (!isNaN(pts[pos])) {
        style[pos] = pts[pos] + 'px';
      }
    }
    if (me.shadow || me.shim) {
      me.syncUnderlays();
    }
    return me;
  }, setY:function(y) {
    return this.setXY([false, y]);
  }, setZIndex:function(zindex) {
    var me = this;
    if (me.shadow) {
      me.shadow.setZIndex(zindex);
    }
    if (me.shim) {
      me.shim.setZIndex(zindex);
    }
    return me.setStyle('z-index', zindex);
  }, show:function() {
    return this.setVisible(true);
  }, swallowEvent:function(eventName, preventDefault) {
    var me = this, e, eLen, listeners = {destroyable:true}, fn = function(e) {
      e.stopPropagation();
      if (preventDefault) {
        e.preventDefault();
      }
    };
    if (Ext.isArray(eventName)) {
      eLen = eventName.length;
      for (e = 0; e < eLen; e++) {
        listeners[eventName[e]] = fn;
      }
    } else {
      listeners[eventName] = fn;
    }
    return me.on(listeners);
  }, swapCls:function(firstClass, secondClass, flag, prefix) {
    if (flag === undefined) {
      flag = true;
    }
    var me = this, addedClass = flag ? firstClass : secondClass, removedClass = flag ? secondClass : firstClass;
    if (removedClass) {
      me.removeCls(prefix ? prefix + '-' + removedClass : removedClass);
    }
    if (addedClass) {
      me.addCls(prefix ? prefix + '-' + addedClass : addedClass);
    }
    return me;
  }, synchronize:function() {
    var me = this, dom = me.dom, hasClassMap = {}, className = dom.className, classList, i, ln, name, elementData = me.getData(false);
    if (className && className.length > 0) {
      classList = dom.className.split(classNameSplitRegex);
      for (i = 0, ln = classList.length; i < ln; i++) {
        name = classList[i];
        hasClassMap[name] = true;
      }
    } else {
      classList = [];
    }
    elementData.classList = classList;
    elementData.classMap = hasClassMap;
    elementData.isSynchronized = true;
    return me;
  }, syncUnderlays:function() {
    var me = this, shadow = me.shadow, shim = me.shim, dom = me.dom, xy, x, y, w, h;
    if (me.isVisible()) {
      xy = me.getXY();
      x = xy[0];
      y = xy[1];
      w = dom.offsetWidth;
      h = dom.offsetHeight;
      if (shadow && !shadow.hidden) {
        shadow.realign(x, y, w, h);
      }
      if (shim && !shim.hidden) {
        shim.realign(x, y, w, h);
      }
    }
  }, toggleCls:function(className, state) {
    if (state == null) {
      state = !this.hasCls(className);
    }
    return state ? this.addCls(className) : this.removeCls(className);
  }, toggle:function() {
    this.setVisible(!this.isVisible());
    return this;
  }, translate:function() {
    var transformStyleName = 'webkitTransform' in DOC.createElement('div').style ? 'webkitTransform' : 'transform';
    return function(x, y, z) {
      x = Math.round(x);
      y = Math.round(y);
      z = Math.round(z);
      this.dom.style[transformStyleName] = 'translate3d(' + (x || 0) + 'px, ' + (y || 0) + 'px, ' + (z || 0) + 'px)';
    };
  }(), unwrap:function() {
    var dom = this.dom, parentNode = dom.parentNode, activeElement = (activeElFly || (activeElFly = new Ext.dom.Fly)).attach(Ext.Element.getActiveElement()), grandparentNode, cached, resumeFocus, tabIndex;
    grannyFly = grannyFly || new Ext.dom.Fly;
    cached = Ext.cache[activeElement.dom.id];
    if (cached) {
      activeElement = cached;
    }
    if (this.contains(activeElement)) {
      if (cached) {
        cached.suspendFocusEvents();
      }
      resumeFocus = true;
    }
    if (parentNode) {
      grandparentNode = parentNode.parentNode;
      if (resumeFocus) {
        tabIndex = grandparentNode.getAttribute('tabIndex');
        grannyFly.attach(grandparentNode);
        grannyFly.set({tabIndex:-1});
        grannyFly.suspendFocusEvents();
        grannyFly.focus();
      }
      grandparentNode.insertBefore(dom, parentNode);
      grandparentNode.removeChild(parentNode);
    } else {
      grandparentNode = DOC.createDocumentFragment();
      grandparentNode.appendChild(dom);
    }
    if (resumeFocus) {
      if (cached) {
        cached.focus();
        cached.resumeFocusEvents();
      } else {
        activeElement.focus();
      }
      if (grannyFly) {
        grannyFly.resumeFocusEvents();
        grannyFly.set({tabIndex:tabIndex});
      }
    }
    return this;
  }, up:function(simpleSelector, limit, returnDom) {
    return this.findParentNode(simpleSelector, limit, !returnDom);
  }, update:function(html) {
    return this.setHtml(html);
  }, wrap:function(config, returnDom, selector) {
    var me = this, dom = me.dom, result = Ext.DomHelper.insertBefore(dom, config || {tag:'div'}, !returnDom), newEl = (wrapFly || (wrapFly = new Ext.dom.Fly)).attach(Ext.getDom(result)), target = newEl, activeElement = (activeElFly || (activeElFly = new Ext.dom.Fly)).attach(Ext.Element.getActiveElement()), cached, resumeFocus, tabIndex;
    cached = Ext.cache[activeElement.dom.id];
    if (cached) {
      activeElement = cached;
    }
    if (selector) {
      target = newEl.selectNode(selector, returnDom);
    }
    if (me.contains(activeElement)) {
      if (cached) {
        cached.suspendFocusEvents();
      }
      tabIndex = Ext.getDom(newEl).getAttribute('tabIndex');
      newEl.set({tabIndex:-1});
      newEl.suspendFocusEvents();
      newEl.focus();
      resumeFocus = true;
    }
    (target.dom || target).appendChild(dom);
    if (resumeFocus) {
      if (cached) {
        cached.focus();
        cached.resumeFocusEvents();
      } else {
        activeElement.focus();
      }
      newEl.resumeFocusEvents();
      newEl.set({tabIndex:tabIndex});
    }
    return result;
  }, isFocusable:function(skipVisibility) {
    var dom = this.dom, focusable = false, nodeName;
    if (dom && !dom.disabled) {
      nodeName = dom.nodeName;
      focusable = !!Ext.Element.naturallyFocusableTags[nodeName] || (nodeName === 'A' || nodeName === 'LINK') && !!dom.href || dom.getAttribute('tabIndex') != null || dom.contentEditable === 'true';
      if (Ext.isIE8 && nodeName === 'INPUT' && dom.type === 'hidden') {
        focusable = false;
      }
      focusable = focusable && (skipVisibility || this.isVisible(true));
    }
    return focusable;
  }, isInputField:function() {
    var dom = this.dom, contentEditable = dom.contentEditable;
    if (Ext.Element.inputTags[dom.tagName] && dom.type !== 'button' || (contentEditable === '' || contentEditable === 'true')) {
      return true;
    }
    return false;
  }, isTabbable:function(includeHidden) {
    var dom = this.dom, tabbable = false, nodeName, hasIndex, tabIndex;
    if (dom && !dom.disabled) {
      nodeName = dom.nodeName;
      tabIndex = dom.getAttribute('tabIndex');
      hasIndex = tabIndex != null;
      tabIndex -= 0;
      if (nodeName === 'A' || nodeName === 'LINK') {
        if (dom.href) {
          tabbable = hasIndex && tabIndex < 0 ? false : true;
        } else {
          if (dom.contentEditable === 'true') {
            tabbable = !hasIndex || hasIndex && tabIndex >= 0 ? true : false;
          } else {
            tabbable = hasIndex && tabIndex >= 0 ? true : false;
          }
        }
      } else {
        if (dom.contentEditable === 'true' || Ext.Element.naturallyTabbableTags[nodeName]) {
          tabbable = hasIndex && tabIndex < 0 ? false : true;
        } else {
          if (hasIndex && tabIndex >= 0) {
            tabbable = true;
          }
        }
      }
      if (Ext.isIE8 && nodeName === 'INPUT' && dom.type === 'hidden') {
        tabbable = false;
      }
      tabbable = tabbable && (includeHidden || (!this.component || this.component.isVisible(true)) && this.isVisible(true));
    }
    return tabbable;
  }, ripplingCls:Ext.baseCSSPrefix + 'rippling', ripplingTransitionCls:Ext.baseCSSPrefix + 'ripple-transition', ripplingUnboundCls:Ext.baseCSSPrefix + 'rippling-unbound', rippleBubbleCls:Ext.baseCSSPrefix + 'ripple-bubble', rippleContainerCls:Ext.baseCSSPrefix + 'ripple-container', rippleWrapperCls:Ext.baseCSSPrefix + 'ripple-wrapper', noRippleDisplayMap:{table:1, 'table-row':1, 'table-row-group':1}, noRippleTagMap:{TABLE:1, TR:1, TBODY:1}, ripple:function(event, options) {
    if (options === true || !options) {
      options = {};
    } else {
      if (Ext.isString(options)) {
        options = {color:options};
      }
    }
    var me = this, rippleParent = Ext.isString(options.delegate) ? me.down(options.delegate) : me, rippleMeasureEl = Ext.isString(options.measureSelector) ? me.down(options.measureSelector) : null, color = window.getComputedStyle(rippleParent.dom).color, unbound = options.bound === false, position = options.position, ripplingCls = me.ripplingCls, ripplingTransitionCls = me.ripplingTransitionCls, ripplingUnboundCls = me.ripplingUnboundCls, rippleBubbleCls = me.rippleBubbleCls, rippleContainerCls = 
    me.rippleContainerCls, rippleWrapperCls = me.rippleWrapperCls, offset, width, height, rippleDiameter, center, measureElWidth, measureElHeight, rippleSize, pos, posX, posY, rippleWrapper, rippleContainer, rippleBubble, rippleDestructor, rippleClearFn, rippleDestructionTimer, rippleBox, unboundEl, unboundElData, timeout;
    if (rippleParent) {
      offset = rippleParent.getXY();
      width = rippleParent.getWidth();
      height = rippleParent.getHeight();
      timeout = rippleParent.$rippleClearTimeout;
      if (timeout) {
        rippleParent.$rippleClearTimeout = Ext.undefer(timeout);
      }
      if (rippleMeasureEl) {
        measureElWidth = rippleMeasureEl.getWidth();
        measureElHeight = rippleMeasureEl.getHeight();
        rippleDiameter = Math.max(measureElWidth, measureElHeight);
      } else {
        rippleDiameter = width > height ? width : height;
      }
      if (options.diameterLimit === undefined || options.diameterLimit === true) {
        rippleDiameter = Math.min(rippleDiameter, Element.maxRippleDiameter);
      } else {
        if (options.diameterLimit && options.diameterLimit !== false && options.diameterLimit !== 0) {
          rippleDiameter = Math.min(rippleDiameter, options.diameterLimit);
        }
      }
      center = [offset[0] + width / 2, offset[1] + height / 2];
      if (unbound) {
        if (options.fit !== false) {
          rippleSize = rippleDiameter * 2.15;
          rippleBox = rippleParent.getRegion();
          rippleBox.setPosition(rippleBox.getCenter()).setSize(rippleSize).translateBy(-rippleSize / 2, -rippleSize / 2);
          unboundEl = me.up(function(candidate) {
            var fly = Ext.fly(candidate, 'ripple');
            return !(candidate.tagName in me.noRippleTagMap) && !(fly.getStyle('display') in me.noRippleDisplayMap) && fly.getRegion().contains(rippleBox);
          }) || Ext.getBody();
        } else {
          unboundEl = rippleParent;
        }
      }
      if (Ext.isString(event)) {
        options.color = event;
        event = null;
      } else {
        if (event && !event.isEvent) {
          event = new Ext.event.Event(event);
        }
      }
      if (event && event.isEvent) {
        if (event.browserEvent.$preventRipple) {
          return;
        }
        position = event.getXY();
        event.browserEvent.$preventRipple = true;
      }
      pos = !unbound && !options.centered && position || center;
      posX = pos[0] - offset[0] - rippleDiameter / 2;
      posY = pos[1] - offset[1] - rippleDiameter / 2;
      rippleParent.addCls(ripplingTransitionCls);
      if (!unbound) {
        rippleParent.addCls(ripplingCls);
        rippleContainer = rippleParent.child('.' + rippleContainerCls);
      } else {
        unboundElData = unboundEl.getData();
        rippleWrapper = unboundElData.rippleWrapper;
        if (!rippleWrapper) {
          unboundElData.rippleWrapper = rippleWrapper = unboundEl.insertFirst({style:'position: absolute; top: 0; left: 0', cls:rippleWrapperCls + ' ' + ripplingCls + ' ' + ripplingUnboundCls});
        }
      }
      if (!rippleContainer) {
        if (unbound) {
          rippleContainer = rippleWrapper.append({cls:rippleContainerCls});
          rippleContainer.setXY(offset);
        } else {
          rippleContainer = rippleParent.append({cls:rippleContainerCls});
        }
      }
      rippleBubble = rippleContainer.append({cls:rippleBubbleCls});
      if (options.color !== 'default') {
        rippleBubble.setStyle('backgroundColor', options.color || color);
      }
      rippleBubble.setWidth(rippleDiameter);
      rippleBubble.setHeight(rippleDiameter);
      rippleBubble.setTop(posY);
      rippleBubble.setLeft(posX);
      rippleClearFn = function() {
        if (!rippleParent.destroyed) {
          rippleParent.$rippleClearTimeout = Ext.defer(function() {
            rippleParent.removeCls([ripplingCls, ripplingTransitionCls]);
            rippleParent.$rippleClearTimeout = null;
          }, 50);
        }
      };
      rippleDestructor = function() {
        var ripple, timeout;
        rippleBubble.destroy();
        if (me.$ripples) {
          delete me.$ripples[rippleBubble.id];
        }
        timeout = rippleParent.$rippleClearTimeout;
        if (timeout) {
          rippleParent.$rippleClearTimeout = Ext.undefer(timeout);
        }
        if (unbound) {
          rippleContainer.destroy();
          ripple = rippleWrapper.child('.' + rippleContainerCls);
          if (!ripple) {
            unboundElData.rippleWrapper = null;
            rippleWrapper.destroy();
            rippleClearFn();
          }
        } else {
          ripple = rippleContainer.child('.' + rippleBubbleCls);
          if (!ripple) {
            rippleContainer.destroy();
            rippleClearFn();
          }
        }
      };
      rippleDestructionTimer = Ext.defer(rippleDestructor, options.destroyTime || 1000, me);
      if (!me.$ripples) {
        me.$ripples = {};
      }
      me.$ripples[rippleBubble.id] = {timerId:rippleDestructionTimer, destructor:rippleDestructor};
      rippleBubble.addCls(Ext.baseCSSPrefix + 'ripple');
    }
  }, destroyAllRipples:function() {
    var me = this, rippleEl, ripple;
    for (rippleEl in me.$ripples) {
      ripple = me.$ripples[rippleEl];
      Ext.undefer(ripple.timerId);
      if (ripple.destructor) {
        ripple.destructor();
      }
    }
    me.$ripples = null;
  }, privates:{findTabbableElements:function(options) {
    var skipSelf, skipChildren, excludeRoot, includeSaved, includeHidden, dom = this.dom, cAttr = Ext.Element.tabbableSavedCounterAttribute, selection = [], idx = 0, nodes, node, fly, i, len, tabIndex;
    if (!dom) {
      return selection;
    }
    if (options) {
      skipSelf = options.skipSelf;
      skipChildren = options.skipChildren;
      excludeRoot = options.excludeRoot;
      includeSaved = options.includeSaved;
      includeHidden = options.includeHidden;
    }
    excludeRoot = excludeRoot && Ext.getDom(excludeRoot);
    if (excludeRoot && excludeRoot.contains(dom)) {
      return selection;
    }
    if (!skipSelf && (includeSaved && dom.hasAttribute(cAttr) || this.isTabbable(includeHidden))) {
      selection[idx++] = dom;
    }
    if (skipChildren) {
      return selection;
    }
    nodes = dom.querySelectorAll(Ext.Element.tabbableSelector);
    len = nodes.length;
    if (!len) {
      return selection;
    }
    fly = new Ext.dom.Fly;
    for (i = 0; i < len; i++) {
      node = nodes[i];
      tabIndex = +node.getAttribute('tabIndex');
      if ((includeSaved && node.hasAttribute(cAttr) || !(tabIndex < 0) && fly.attach(node).isTabbable(includeHidden)) && !(excludeRoot && (excludeRoot === node || excludeRoot.contains(node)))) {
        selection[idx++] = node;
      }
    }
    return selection;
  }, saveTabbableState:function(options) {
    var counterAttr = Ext.Element.tabbableSavedCounterAttribute, savedAttr = Ext.Element.tabbableSavedValueAttribute, counter, nodes, node, i, len;
    if (!options || options.includeSaved == null) {
      options = Ext.Object.chain(options || null);
      options.includeSaved = true;
    }
    nodes = this.findTabbableElements(options);
    for (i = 0, len = nodes.length; i < len; i++) {
      node = nodes[i];
      counter = +node.getAttribute(counterAttr);
      if (counter > 0) {
        node.setAttribute(counterAttr, ++counter);
      } else {
        if (node.hasAttribute('tabIndex')) {
          node.setAttribute(savedAttr, node.getAttribute('tabIndex'));
        } else {
          node.setAttribute(savedAttr, 'none');
        }
        node.setAttribute('tabIndex', '-1');
        node.setAttribute(counterAttr, '1');
      }
    }
    return nodes;
  }, restoreTabbableState:function(options) {
    var dom = this.dom, counterAttr = Ext.Element.tabbableSavedCounterAttribute, savedAttr = Ext.Element.tabbableSavedValueAttribute, nodes = [], skipSelf = options && options.skipSelf, skipChildren = options && options.skipChildren, reset = options && options.reset, idx, counter, node, i, len;
    if (!dom) {
      return this;
    }
    if (!skipChildren) {
      nodes = Ext.Array.from(dom.querySelectorAll('[' + counterAttr + ']'));
    }
    if (!skipSelf) {
      nodes.unshift(dom);
    }
    for (i = 0, len = nodes.length; i < len; i++) {
      node = nodes[i];
      if (!node.hasAttribute(counterAttr) || !node.hasAttribute(savedAttr)) {
        continue;
      }
      counter = +node.getAttribute(counterAttr);
      if (!reset && counter > 1) {
        node.setAttribute(counterAttr, --counter);
        continue;
      }
      idx = node.getAttribute(savedAttr);
      if (idx === 'none') {
        node.removeAttribute('tabIndex');
      } else {
        node.setAttribute('tabIndex', idx);
      }
      node.removeAttribute(savedAttr);
      node.removeAttribute(counterAttr);
    }
    return nodes;
  }, setTabIndex:function(tabIndex) {
    var dom = this.dom, savedAttr = Ext.Element.tabbableSavedValueAttribute;
    if (dom.hasAttribute(savedAttr)) {
      if (tabIndex == null) {
        dom.setAttribute(savedAttr, 'none');
        dom.removeAttribute('tabIndex');
      } else {
        dom.setAttribute(savedAttr, tabIndex);
      }
    } else {
      if (tabIndex == null) {
        dom.removeAttribute('tabIndex');
      } else {
        dom.setAttribute('tabIndex', tabIndex);
      }
    }
  }, doAddListener:function(eventName, fn, scope, options, order, caller, manager) {
    var me = this, originalName = eventName, observableDoAddListener, additiveEventName, translatedEventName;
    eventName = Ext.canonicalEventName(eventName);
    if (!me.blockedEvents[eventName]) {
      observableDoAddListener = me.mixins.observable.doAddListener;
      options = options || {};
      if (Element.useDelegatedEvents === false) {
        options.delegated = options.delegated || false;
      }
      if (options.translate !== false) {
        additiveEventName = me.additiveEvents[eventName];
        if (additiveEventName) {
          options.type = eventName;
          eventName = additiveEventName;
          observableDoAddListener.call(me, eventName, fn, scope, options, order, caller, manager);
        }
        translatedEventName = me.eventMap[eventName];
        if (translatedEventName) {
          options.type = options.type || eventName;
          if (manager) {
            options.managedName = originalName;
          }
          eventName = translatedEventName;
        }
      }
      if (observableDoAddListener.call(me, eventName, fn, scope, options, order, caller, manager)) {
        if (me.longpressEvents[eventName] && ++me.longpressListenerCount === 1) {
          me.on('MSHoldVisual', 'preventMsHoldVisual', me);
        }
      }
      if (manager && translatedEventName) {
        delete options.managedName;
      }
      delete options.type;
    }
  }, doRemoveListener:function(eventName, fn, scope) {
    var me = this, observableDoRemoveListener, translatedEventName, additiveEventName, removed;
    eventName = Ext.canonicalEventName(eventName);
    if (!me.blockedEvents[eventName]) {
      observableDoRemoveListener = me.mixins.observable.doRemoveListener;
      additiveEventName = me.additiveEvents[eventName];
      if (additiveEventName) {
        eventName = additiveEventName;
        observableDoRemoveListener.call(me, eventName, fn, scope);
      }
      translatedEventName = me.eventMap[eventName];
      if (translatedEventName) {
        removed = observableDoRemoveListener.call(me, translatedEventName, fn, scope);
      }
      removed = observableDoRemoveListener.call(me, eventName, fn, scope) || removed;
      if (removed) {
        if (me.longpressEvents[eventName] && !--me.longpressListenerCount) {
          me.un('MSHoldVisual', 'preventMsHoldVisual', me);
        }
      }
    }
  }, _initEvent:function(eventName) {
    return this.events[eventName] = new Ext.dom.ElementEvent(this, eventName);
  }, _getDisplay:function() {
    var data = this.getData(), display = data[ORIGINALDISPLAY];
    if (display === undefined) {
      data[ORIGINALDISPLAY] = display = '';
    }
    return display;
  }, _getPublisher:function(eventName, noTranslate) {
    var Publisher = Ext.event.publisher.Publisher, publisher = Publisher.publishersByEvent[eventName], isNative = noTranslate && !Ext.event.Event.gestureEvents[eventName];
    if (isNative || !publisher || this.dom === window && eventName === 'resize') {
      publisher = Publisher.publishers.dom;
    }
    return publisher;
  }, isFocusSuspended:function() {
    var data = this.peekData();
    return data && data.suspendFocusEvents;
  }, preventMsHoldVisual:function(e) {
    e.preventDefault();
  }, suspendFocusEvents:function() {
    if (!this.isFly) {
      this.suspendEvent('focus', 'blur');
    }
    this.getData().suspendFocusEvents = true;
  }, resumeFocusEvents:function() {
    function resumeFn() {
      var data;
      if (!this.destroyed) {
        data = this.getData();
        if (data) {
          data.suspendFocusEvents = false;
        }
        if (!this.isFly) {
          this.resumeEvent('focus', 'blur');
        }
      }
    }
    if (!this.destroyed && this.getData().suspendFocusEvents) {
      if (Ext.isIE && !this.isFly) {
        this.resumeFocusEventsTimer = Ext.asap(resumeFn, this);
      } else {
        resumeFn.call(this);
      }
    }
  }}, deprecated:{'5.0':{methods:{getHTML:'getHtml', getPageBox:function(getRegion) {
    var me = this, dom = me.dom, isDoc = dom.nodeName === 'BODY', w = isDoc ? Element.getViewportWidth() : dom.offsetWidth, h = isDoc ? Element.getViewportHeight() : dom.offsetHeight, xy = me.getXY(), t = xy[1], r = xy[0] + w, b = xy[1] + h, l = xy[0];
    if (getRegion) {
      return new Ext.util.Region(t, r, b, l);
    } else {
      return {left:l, top:t, width:w, height:h, right:r, bottom:b};
    }
  }, isTransparent:function(prop) {
    var value = this.getStyle(prop);
    return value ? transparentRe.test(value) : false;
  }, purgeAllListeners:'clearListeners', removeAllListeners:'clearListeners', setHTML:'setHtml'}}}};
}, function(Element) {
  var DOC = document, docEl = DOC.documentElement, prototype = Element.prototype, supports = Ext.supports, pointerdown = 'pointerdown', pointermove = 'pointermove', pointerup = 'pointerup', pointercancel = 'pointercancel', MSPointerDown = 'MSPointerDown', MSPointerMove = 'MSPointerMove', MSPointerUp = 'MSPointerUp', MSPointerCancel = 'MSPointerCancel', mousedown = 'mousedown', mousemove = 'mousemove', mouseup = 'mouseup', mouseover = 'mouseover', mouseout = 'mouseout', mouseenter = 'mouseenter', 
  mouseleave = 'mouseleave', touchstart = 'touchstart', touchmove = 'touchmove', touchend = 'touchend', touchcancel = 'touchcancel', click = 'click', dblclick = 'dblclick', tap = 'tap', doubletap = 'doubletap', eventMap = prototype.eventMap = {}, additiveEvents = prototype.additiveEvents = {}, oldId = Ext.id, eventOptions;
  prototype._init(Element);
  delete prototype._init;
  Ext.id = function(obj, prefix) {
    var el = obj && Ext.getDom(obj, true), sandboxPrefix, id;
    if (!el) {
      id = oldId(obj, prefix);
    } else {
      if (!(id = el.id)) {
        id = oldId(null, prefix || Element.prototype.identifiablePrefix);
        if (Ext.isSandboxed) {
          sandboxPrefix = Ext.sandboxPrefix || (Ext.sandboxPrefix = Ext.sandboxName.toLowerCase() + '-');
          id = sandboxPrefix + id;
        }
        el.id = id;
      }
    }
    return id;
  };
  if (supports.PointerEvents) {
    eventMap[mousedown] = pointerdown;
    eventMap[mousemove] = pointermove;
    eventMap[mouseup] = pointerup;
    eventMap[touchstart] = pointerdown;
    eventMap[touchmove] = pointermove;
    eventMap[touchend] = pointerup;
    eventMap[touchcancel] = pointercancel;
    eventMap[mouseover] = 'pointerover';
    eventMap[mouseout] = 'pointerout';
    eventMap[mouseenter] = 'pointerenter';
    if (!Ext.isIE11) {
      eventMap[mouseleave] = 'pointerleave';
    }
  } else {
    if (supports.MSPointerEvents) {
      eventMap[pointerdown] = MSPointerDown;
      eventMap[pointermove] = MSPointerMove;
      eventMap[pointerup] = MSPointerUp;
      eventMap[pointercancel] = MSPointerCancel;
      eventMap[mousedown] = MSPointerDown;
      eventMap[mousemove] = MSPointerMove;
      eventMap[mouseup] = MSPointerUp;
      eventMap[touchstart] = MSPointerDown;
      eventMap[touchmove] = MSPointerMove;
      eventMap[touchend] = MSPointerUp;
      eventMap[touchcancel] = MSPointerCancel;
      eventMap[mouseover] = 'MSPointerOver';
      eventMap[mouseout] = 'MSPointerOut';
    } else {
      if (supports.TouchEvents) {
        eventMap[pointerdown] = touchstart;
        eventMap[pointermove] = touchmove;
        eventMap[pointerup] = touchend;
        eventMap[pointercancel] = touchcancel;
        eventMap[mousedown] = touchstart;
        eventMap[mousemove] = touchmove;
        eventMap[mouseup] = touchend;
        eventMap[click] = tap;
        eventMap[dblclick] = doubletap;
        if (Ext.os.is.Desktop) {
          eventMap[touchstart] = mousedown;
          eventMap[touchmove] = mousemove;
          eventMap[touchend] = mouseup;
          eventMap[touchcancel] = mouseup;
          additiveEvents[mousedown] = mousedown;
          additiveEvents[mousemove] = mousemove;
          additiveEvents[mouseup] = mouseup;
          additiveEvents[touchstart] = touchstart;
          additiveEvents[touchmove] = touchmove;
          additiveEvents[touchend] = touchend;
          additiveEvents[touchcancel] = touchcancel;
          additiveEvents[pointerdown] = mousedown;
          additiveEvents[pointermove] = mousemove;
          additiveEvents[pointerup] = mouseup;
          additiveEvents[pointercancel] = mouseup;
        }
      } else {
        eventMap[pointerdown] = mousedown;
        eventMap[pointermove] = mousemove;
        eventMap[pointerup] = mouseup;
        eventMap[pointercancel] = mouseup;
        eventMap[touchstart] = mousedown;
        eventMap[touchmove] = mousemove;
        eventMap[touchend] = mouseup;
        eventMap[touchcancel] = mouseup;
      }
    }
  }
  if (Ext.isWebKit) {
    eventMap.transitionend = Ext.browser.getVendorProperyName('transitionEnd');
    eventMap.animationstart = Ext.browser.getVendorProperyName('animationStart');
    eventMap.animationend = Ext.browser.getVendorProperyName('animationEnd');
  }
  if (!Ext.supports.MouseWheel && !Ext.isOpera) {
    eventMap.mousewheel = 'DOMMouseScroll';
  }
  eventOptions = prototype.$eventOptions = Ext.Object.chain(prototype.$eventOptions);
  eventOptions.translate = eventOptions.capture = eventOptions.delegate = eventOptions.delegated = eventOptions.stopEvent = eventOptions.preventDefault = eventOptions.stopPropagation = eventOptions.element = 1;
  prototype.styleHooks.opacity = {name:'opacity', afterSet:function(dom, value, el) {
    var shadow = el.shadow;
    if (shadow) {
      shadow.setOpacity(value);
    }
  }};
  prototype.getTrueXY = prototype.getXY;
  Ext.getViewportHeight = Element.getViewportHeight;
  Ext.getViewportWidth = Element.getViewportWidth;
  Ext.select = Element.select;
  Ext.query = Element.query;
  Ext.apply(Ext, {get:function(element) {
    return Element.get(element);
  }, getDom:function(el) {
    if (!el || !DOC) {
      return null;
    }
    return typeof el === 'string' ? Ext.getElementById(el) : 'dom' in el ? el.dom : el;
  }, getBody:function() {
    if (!Ext._bodyEl) {
      if (!DOC.body) {
        throw new Error('[Ext.getBody] document.body does not yet exist');
      }
      Ext._bodyEl = Ext.get(DOC.body);
      Ext._bodyEl.skipGarbageCollection = true;
    }
    return Ext._bodyEl;
  }, getHead:function() {
    if (!Ext._headEl) {
      Ext._headEl = Ext.get(DOC.head || DOC.getElementsByTagName('head')[0]);
      Ext._headEl.skipGarbageCollection = true;
    }
    return Ext._headEl;
  }, getDoc:function() {
    if (!Ext._docEl) {
      Ext._docEl = Ext.get(DOC);
      Ext._docEl.skipGarbageCollection = true;
    }
    return Ext._docEl;
  }, getWin:function() {
    if (!Ext._winEl) {
      Ext._winEl = Ext.get(window);
      Ext._winEl.skipGarbageCollection = true;
    }
    return Ext._winEl;
  }, removeNode:function(node) {
    node = node.dom || node;
    var id = node && node.id, el = Ext.cache[id], parent;
    if (el) {
      el.destroy();
    } else {
      if (node && (node.nodeType === 3 || node.tagName.toUpperCase() !== 'BODY')) {
        parent = node.parentNode;
        if (parent) {
          parent.removeChild(node);
        }
      }
    }
  }});
  Ext.isGarbage = function(dom) {
    return dom && dom.nodeType === 1 && dom.tagName !== 'BODY' && dom.tagName !== 'HTML' && (!dom.parentNode || dom.offsetParent === null && (Ext.isIE8 ? DOC.all[dom.id] : DOC.getElementById(dom.id)) !== dom && !(Ext.detachedBodyEl && Ext.detachedBodyEl.isAncestor(dom)));
  };
  Ext.onInternalReady(function() {
    var bodyCls = [], theme;
    Ext.getDoc().on('selectstart', function(ev, dom) {
      var selectableCls = Element.selectableCls, unselectableCls = Element.unselectableCls, tagName = dom && dom.tagName, el = new Ext.dom.Fly;
      tagName = tagName && tagName.toLowerCase();
      if (tagName === 'input' || tagName === 'textarea') {
        return;
      }
      while (dom && dom.nodeType === 1 && dom !== DOC.documentElement) {
        el.attach(dom);
        if (el.hasCls(selectableCls)) {
          return;
        }
        if (el.hasCls(unselectableCls)) {
          ev.stopEvent();
          return;
        }
        dom = dom.parentNode;
      }
    });
    if (Ext.os.is.Android || Ext.os.is.Windows && Ext.supports.Touch) {
      var win = Ext.getWin();
      Element._documentWidth = Element._viewportWidth = docEl.clientWidth;
      Element._documentHeight = Element._viewportHeight = docEl.clientHeight;
      win.on({focusin:'_onWindowFocusChange', focusout:'_onWindowFocusChange', pointerup:'_onWindowFocusChange', capture:true, delegated:false, delay:1, scope:Element});
      win.on({resize:'_onWindowResize', priority:2000, scope:Element});
    }
    if (supports.Touch) {
      bodyCls.push(Ext.baseCSSPrefix + 'touch');
    }
    if (Ext.isIE && Ext.isIE9m) {
      bodyCls.push(Ext.baseCSSPrefix + 'ie', Ext.baseCSSPrefix + 'ie9m');
      bodyCls.push(Ext.baseCSSPrefix + 'ie8p');
      if (Ext.isIE8) {
        bodyCls.push(Ext.baseCSSPrefix + 'ie8');
      } else {
        bodyCls.push(Ext.baseCSSPrefix + 'ie9', Ext.baseCSSPrefix + 'ie9p');
      }
      if (Ext.isIE8m) {
        bodyCls.push(Ext.baseCSSPrefix + 'ie8m');
      }
    }
    if (Ext.isIE10) {
      bodyCls.push(Ext.baseCSSPrefix + 'ie10');
    }
    if (Ext.isIE10p) {
      bodyCls.push(Ext.baseCSSPrefix + 'ie10p');
    }
    if (Ext.isIE11) {
      bodyCls.push(Ext.baseCSSPrefix + 'ie11');
    }
    if (Ext.isEdge) {
      bodyCls.push(Ext.baseCSSPrefix + 'edge');
    }
    if (Ext.isGecko) {
      bodyCls.push(Ext.baseCSSPrefix + 'gecko');
    }
    if (Ext.isOpera) {
      bodyCls.push(Ext.baseCSSPrefix + 'opera');
    }
    if (Ext.isOpera12m) {
      bodyCls.push(Ext.baseCSSPrefix + 'opera12m');
    }
    if (Ext.isWebKit) {
      bodyCls.push(Ext.baseCSSPrefix + 'webkit');
    }
    if (Ext.isSafari) {
      bodyCls.push(Ext.baseCSSPrefix + 'safari');
    }
    if (Ext.isSafari9) {
      bodyCls.push(Ext.baseCSSPrefix + 'safari9');
    }
    if (Ext.isSafari10) {
      bodyCls.push(Ext.baseCSSPrefix + 'safari10');
    }
    if (Ext.isSafari) {
      if (Ext.browser.version.isLessThan(11)) {
        bodyCls.push(Ext.baseCSSPrefix + 'safari10m');
      }
      if (Ext.browser.version.isLessThan(9)) {
        bodyCls.push(Ext.baseCSSPrefix + 'safari8m');
      }
    }
    if (Ext.isChrome) {
      bodyCls.push(Ext.baseCSSPrefix + 'chrome');
    }
    if (Ext.isChromeMobile) {
      bodyCls.push(Ext.baseCSSPrefix + 'chromemobile');
    }
    if (Ext.isMac) {
      bodyCls.push(Ext.baseCSSPrefix + 'mac');
    }
    if (Ext.isWindows) {
      bodyCls.push(Ext.baseCSSPrefix + 'windows');
    }
    if (Ext.isLinux) {
      bodyCls.push(Ext.baseCSSPrefix + 'linux');
    }
    if (!supports.CSS3BorderRadius) {
      bodyCls.push(Ext.baseCSSPrefix + 'nbr');
    }
    if (!supports.CSS3LinearGradient) {
      bodyCls.push(Ext.baseCSSPrefix + 'nlg');
    }
    if (supports.Touch) {
      bodyCls.push(Ext.baseCSSPrefix + 'touch');
    }
    if (Ext.os.deviceType) {
      bodyCls.push(Ext.baseCSSPrefix + Ext.os.deviceType.toLowerCase());
    }
    if (Ext.os.is.BlackBerry) {
      bodyCls.push(Ext.baseCSSPrefix + 'bb');
      if (Ext.browser.userAgent.match(/Kbd/gi)) {
        bodyCls.push(Ext.baseCSSPrefix + 'bb-keyboard');
      }
    }
    if (Ext.os.is.iOS && Ext.isSafari) {
      bodyCls.push(Ext.baseCSSPrefix + 'mobile-safari');
    }
    if (Ext.os.is.iOS && Ext.browser.is.WebView && !Ext.browser.is.Standalone) {
      bodyCls.push(Ext.baseCSSPrefix + 'ios-native');
    }
    if (Ext.supports.FlexBoxBasisBug) {
      bodyCls.push(Ext.baseCSSPrefix + 'has-flexbasis-bug');
    }
    Ext.getBody().addCls(bodyCls);
    theme = Ext.theme;
    if (theme && theme.getDocCls) {
      Ext.fly(document.documentElement).addCls(theme.getDocCls());
    }
  }, null, {priority:1500});
});
Ext.define('Ext.overrides.dom.Element', {override:'Ext.dom.Element', _positionTopLeft:['position', 'top', 'left'], setX:function(x, animate) {
  return this.setXY([x, this.getY()], animate);
}, setXY:function(xy, animate) {
  var me = this;
  if (!animate) {
    me.callParent([xy]);
  } else {
    if (!Ext.isObject(animate)) {
      animate = {};
    }
    me.animate(Ext.applyIf({to:{x:xy[0], y:xy[1]}}, animate));
  }
  return this;
}, setY:function(y, animate) {
  return this.setXY([this.getX(), y], animate);
}, translateXY:function(x, y) {
  var me = this, el = me.el, styles = el.getStyle(me._positionTopLeft), relative = styles.position === 'relative', left = parseFloat(styles.left), top = parseFloat(styles.top), xy = me.getXY();
  if (Ext.isArray(x)) {
    y = x[1];
    x = x[0];
  }
  if (isNaN(left)) {
    left = relative ? 0 : el.dom.offsetLeft;
  }
  if (isNaN(top)) {
    top = relative ? 0 : el.dom.offsetTop;
  }
  left = typeof x === 'number' ? x - xy[0] + left : undefined;
  top = typeof y === 'number' ? y - xy[1] + top : undefined;
  return {x:left, y:top};
}, visit:function(options) {
  var me = this, dom = me.dom, skipSelf = options.skipSelf, excludeRoot = options.excludeRoot, callback = options.callback || options.fn, scope = options.scope || this, reverse = options.reverse, selector = options.selector, whatToShow = options.include || NodeFilter.SHOW_ELEMENT, treeWalker = document.createTreeWalker(dom, whatToShow, null, false), result = null, node = dom;
  if (reverse) {
    for (node = dom.lastElementChild; node.lastElementChild; node = node.lastElementChild) {
    }
    treeWalker.currentNode = node;
  }
  for (; result !== false && node; node = reverse ? treeWalker.previousNode() : treeWalker.nextNode()) {
    if (!(excludeRoot && excludeRoot.contains(node))) {
      if (!(node === dom && skipSelf)) {
        if (!(selector && !node[Ext.supports.matchesSelector](selector))) {
          result = Ext.callback(callback, scope, [node]);
        }
      }
    }
  }
  return result;
}});
Ext.define('Ext.overrides.dom.Element', {override:'Ext.dom.Element', rippleShowTimeout:300});
Ext.define('Ext.GlobalEvents', {extend:Ext.mixin.Observable, alternateClassName:'Ext.globalEvents', observableType:'global', singleton:true, resizeBuffer:100, idleEventMask:{mousemove:1, touchmove:1, pointermove:1, MSPointerMove:1, unload:1}, windowListeners:{resize:{fn:'fireResize'}}, constructor:function() {
  var me = this;
  me.callParent();
  Ext.onInternalReady(function() {
    me.attachListeners();
  });
}, setPressedComponent:function(component, e) {
  var me = this, pressedComponent = me.pressedComponent;
  if (pressedComponent && pressedComponent.onRelease) {
    pressedComponent.onRelease(e);
  }
  me.pressedComponent = component;
  if (component) {
    me.pressedScrollStart = Ext.on({scrollstart:function() {
      me.setPressedComponent(null, e);
    }, destroyable:true});
  } else {
    me.pressedScrollStart = Ext.destroy(me.pressedScrollStart);
  }
}, attachListeners:function() {
  var me = this, win = Ext.getWin(), winListeners = me.windowListeners;
  me.onlineState = Ext.isOnline();
  me.curHeight = Ext.Element.getViewportHeight();
  me.curWidth = Ext.Element.getViewportWidth();
  win.on({scope:me, online:'handleOnlineChange', offline:'handleOnlineChange'});
  me.fireResize.$skipTimerCheck = true;
  if (winListeners) {
    winListeners.scope = me;
    if (Ext.isModern) {
      winListeners.resize.onFrame = true;
    } else {
      winListeners.resize.buffer = me.resizeBuffer;
    }
    win.on(winListeners);
  }
  Ext.getDoc().on({touchstart:'fireMouseDown', mousedown:'fireMouseDown', mouseup:'fireMouseUp', touchend:'fireMouseUp', drop:'fireMouseUp', dragend:'fireMouseUp', scope:me});
}, fireMouseDown:function(e) {
  this.fireEvent('mousedown', e);
  Ext.ComponentManager.handleDocumentMouseDown(e);
}, fireMouseUp:function(e) {
  this.fireEvent('mouseup', e);
  this.setPressedComponent(null, e);
}, fireResize:function() {
  var me = this, Element = Ext.Element, w = Element.getViewportWidth(), h = Element.getViewportHeight();
  if (me.curHeight !== h || me.curWidth !== w) {
    me.curHeight = h;
    me.curWidth = w;
    if (me.hasListeners.resize) {
      me.fireEvent('resize', w, h);
    }
  }
}, handleOnlineChange:function() {
  var online = Ext.isOnline();
  if (online !== this.onlineState) {
    this.onlineState = online;
    this.fireEvent('onlinechange', online);
  }
}}, function(GlobalEvents) {
  Ext.hasListeners = GlobalEvents.hasListeners;
  Ext.on = function() {
    return GlobalEvents.addListener.apply(GlobalEvents, arguments);
  };
  Ext.un = function() {
    return GlobalEvents.removeListener.apply(GlobalEvents, arguments);
  };
  Ext.fireEvent = function() {
    return GlobalEvents.fireEvent.apply(GlobalEvents, arguments);
  };
  Ext.fireIdle = function() {
    if (GlobalEvents.hasListeners.idle && !Ext._suppressIdle) {
      GlobalEvents.fireEventArgs('idle');
    }
    Ext._suppressIdle = false;
  };
  Ext._suppressIdle = false;
});
Ext.USE_NATIVE_JSON = true;
Ext.JSON = new function() {
  var me = this, hasNative = window.JSON && JSON.toString() === '[object JSON]', useHasOwn = !!{}.hasOwnProperty, pad = function(n) {
    return n < 10 ? '0' + n : n;
  }, doDecode = function(json) {
    return eval('(' + json + ')');
  }, doEncode = function(o, newline) {
    if (o === null || o === undefined) {
      return 'null';
    } else {
      if (Ext.isDate(o)) {
        return me.encodeDate(o);
      } else {
        if (Ext.isString(o)) {
          if (Ext.isMSDate(o)) {
            return me.encodeMSDate(o);
          } else {
            return me.encodeString(o);
          }
        } else {
          if (typeof o === 'number') {
            return isFinite(o) ? String(o) : 'null';
          } else {
            if (Ext.isBoolean(o)) {
              return String(o);
            } else {
              if (typeof o.toJSON === 'function') {
                return doEncode(o.toJSON());
              } else {
                if (Ext.isArray(o)) {
                  return encodeArray(o, newline);
                } else {
                  if (Ext.isObject(o)) {
                    return encodeObject(o, newline);
                  } else {
                    if (typeof o === 'function') {
                      return 'null';
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    return 'undefined';
  }, m = {'\b':'\\b', '\t':'\\t', '\n':'\\n', '\f':'\\f', '\r':'\\r', '"':'\\"', '\\':'\\\\', '\x0B':'\\u000b'}, charToReplace = /[\\"\x00-\x1f\x7f-\uffff]/g, encodeString = function(s) {
    return '"' + s.replace(charToReplace, function(a) {
      var c = m[a];
      return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
    }) + '"';
  }, encodeMSDate = function(o) {
    return '"' + o + '"';
  }, encodeArrayPretty = function(o, newline) {
    var len = o.length, cnewline = newline + '   ', sep = ',' + cnewline, a = ['[', cnewline], i;
    for (i = 0; i < len; i += 1) {
      a.push(me.encodeValue(o[i], cnewline), sep);
    }
    a[a.length - 1] = newline + ']';
    return a.join('');
  }, encodeObjectPretty = function(o, newline) {
    var cnewline = newline + '   ', sep = ',' + cnewline, a = ['{', cnewline], i, val;
    for (i in o) {
      val = o[i];
      if (!useHasOwn || o.hasOwnProperty(i)) {
        if (typeof val === 'function' || val === undefined || val.isInstance) {
          continue;
        }
        a.push(me.encodeValue(i) + ': ' + me.encodeValue(val, cnewline), sep);
      }
    }
    a[a.length - 1] = newline + '}';
    return a.join('');
  }, encodeArray = function(o, newline) {
    if (newline) {
      return encodeArrayPretty(o, newline);
    }
    var a = ['[', ''], len = o.length, i;
    for (i = 0; i < len; i += 1) {
      a.push(me.encodeValue(o[i]), ',');
    }
    a[a.length - 1] = ']';
    return a.join('');
  }, encodeObject = function(o, newline) {
    if (newline) {
      return encodeObjectPretty(o, newline);
    }
    var a = ['{', ''], i, val;
    for (i in o) {
      val = o[i];
      if (!useHasOwn || o.hasOwnProperty(i)) {
        if (typeof val === 'function' || val === undefined) {
          continue;
        }
        a.push(me.encodeValue(i), ':', me.encodeValue(val), ',');
      }
    }
    a[a.length - 1] = '}';
    return a.join('');
  };
  me.encodeString = encodeString;
  me.encodeValue = doEncode;
  me.encodeDate = function(o) {
    return '"' + o.getFullYear() + '-' + pad(o.getMonth() + 1) + '-' + pad(o.getDate()) + 'T' + pad(o.getHours()) + ':' + pad(o.getMinutes()) + ':' + pad(o.getSeconds()) + '"';
  };
  me.encode = function(o) {
    if (hasNative && Ext.USE_NATIVE_JSON) {
      return JSON.stringify(o);
    }
    return me.encodeValue(o);
  };
  me.decode = function(json, safe) {
    try {
      if (hasNative && Ext.USE_NATIVE_JSON) {
        return JSON.parse(json);
      }
      return doDecode(json);
    } catch (e$51) {
      if (safe) {
        return null;
      }
      Ext.raise({sourceClass:'Ext.JSON', sourceMethod:'decode', msg:"You're trying to decode an invalid JSON String: " + json});
    }
  };
  me.encodeMSDate = encodeMSDate;
  if (!Ext.util) {
    Ext.util = {};
  }
  Ext.util.JSON = me;
  Ext.encode = me.encode;
  Ext.decode = me.decode;
};
Ext.define('Ext.mixin.Inheritable', {extend:Ext.Mixin, mixinConfig:{id:'inheritable'}, getInherited:function(inner) {
  var me = this, inheritedState = inner && me.inheritedStateInner || me.inheritedState, ownerCt = me.getRefOwner(), isContainer = me.isContainer, parent, inheritedStateInner, getInner, ownerLayout;
  if (!inheritedState || inheritedState.invalid) {
    parent = me.getRefOwner();
    ownerLayout = me.ownerLayout;
    if (ownerCt) {
      getInner = ownerLayout ? ownerLayout === ownerCt.layout : true;
    }
    me.inheritedState = inheritedState = Ext.Object.chain(parent ? parent.getInherited(getInner) : Ext.rootInheritedState);
    if (isContainer) {
      me.inheritedStateInner = inheritedStateInner = Ext.Object.chain(inheritedState);
    }
    me.initInheritedState(inheritedState, inheritedStateInner);
    inheritedState = isContainer && inner ? me.inheritedStateInner : me.inheritedState;
  }
  return inheritedState;
}, getInheritedConfig:function(property, skipThis) {
  var state = this.inheritedState, old, ret;
  if (!state || state.invalid) {
    state = this.getInherited();
  }
  ret = state[property];
  if (skipThis && state.hasOwnProperty(property)) {
    old = ret;
    delete state[property];
    ret = state[property];
    state[property] = old;
  }
  return ret;
}, resolveListenerScope:function(defaultScope, skipThis) {
  var me = this, hasSkipThis = typeof skipThis === 'boolean', namedScope = Ext._namedScopes[defaultScope], ret;
  if (!namedScope) {
    ret = me.getInheritedConfig('defaultListenerScope', hasSkipThis ? skipThis : true) || defaultScope || me;
  } else {
    if (namedScope.isController) {
      ret = me.getInheritedConfig('controller', hasSkipThis ? skipThis : !namedScope.isSelf);
    } else {
      if (namedScope.isOwner) {
        ret = me.getRefOwner();
      } else {
        if (namedScope.isSelf) {
          ret = me.getInheritedConfig('defaultListenerScope', hasSkipThis && skipThis) || me;
        } else {
          if (namedScope.isThis) {
            ret = me;
          }
        }
      }
    }
  }
  return ret || null;
}, resolveSatelliteListenerScope:function(satellite, defaultScope) {
  var me = this, namedScope = Ext._namedScopes[defaultScope], ret;
  if (!namedScope) {
    ret = me.getInheritedConfig('defaultListenerScope') || defaultScope || me;
  } else {
    if (namedScope.isController) {
      ret = me.getInheritedConfig('controller');
    } else {
      if (namedScope.isSelf) {
        ret = me.getInheritedConfig('defaultListenerScope') || satellite;
      } else {
        if (namedScope.isThis) {
          ret = satellite;
        }
      }
    }
  }
  return ret || null;
}, lookupNameHolder:function(skipThis) {
  return this.getInheritedConfig('nameHolder', skipThis !== false) || null;
}, lookupReferenceHolder:function(skipThis) {
  return this.getInheritedConfig('referenceHolder', skipThis !== false) || null;
}, getRefOwner:function() {
  var me = this;
  return me.ownerCmp || me.ownerCt || me.parent || me.$initParent || me.floatParent;
}, bubble:function(fn, scope, args) {
  var target;
  for (target = this; target; target = target.getRefOwner()) {
    if (fn.apply(scope || target, args || [target]) === false) {
      break;
    }
  }
}, isDescendantOf:function(ancestor) {
  return ancestor ? ancestor.isAncestor(this) : false;
}, isAncestor:function(possibleDescendant) {
  while (possibleDescendant) {
    if (possibleDescendant.getRefOwner() === this) {
      return true;
    }
    possibleDescendant = possibleDescendant.getRefOwner();
  }
  return false;
}, invalidateInheritedState:function() {
  var inheritedState = this.inheritedState;
  if (inheritedState) {
    inheritedState.invalid = true;
    delete this.inheritedState;
  }
}, privates:{_fixReference:function() {
  var me = this, holder;
  if (me.name && me.nameable) {
    holder = me.lookupNameHolder();
    if (holder && !holder.destroyed) {
      holder.attachNameRef(me);
    }
  }
  if (me.reference) {
    holder = me.lookupReferenceHolder();
    if (holder && !holder.destroyed) {
      holder.attachReference(me);
    }
  }
}, onInheritedAdd:function(parent, instanced) {
  var me = this;
  if (me.inheritedState && instanced) {
    me.invalidateInheritedState();
  }
  Ext.ComponentManager.markReferencesDirty();
}, onInheritedRemove:function(destroying) {
  var me = this;
  Ext.ComponentManager.markReferencesDirty();
  if (me.inheritedState && !destroying) {
    me.invalidateInheritedState();
  }
}}}, function() {
  Ext.rootInheritedState = {};
});
Ext.define('Ext.mixin.Bindable', {mixinId:'bindable', config:{bind:{$value:null, lazy:true}, controller:null, defaultListenerScope:false, publishes:{$value:null, lazy:true, merge:function(newValue, oldValue) {
  return this.mergeSets(newValue, oldValue);
}}, session:{$value:null, lazy:true}, twoWayBindable:{$value:null, lazy:true, merge:function(newValue, oldValue) {
  return this.mergeSets(newValue, oldValue);
}}, viewModel:{$value:null, lazy:true}}, defaultBindProperty:null, nameable:false, shareableName:false, reference:null, validRefRe:/^[a-z_][a-z0-9_]*$/i, getReference:function() {
  return this.reference;
}, initInheritedState:function(inheritedState) {
  var me = this, reference = me.reference, controller = me.getController(), viewModel = me.getConfig('viewModel', true), session = me.getConfig('session', true), defaultListenerScope = me.getDefaultListenerScope();
  if (controller) {
    inheritedState.controller = controller;
  }
  if (defaultListenerScope) {
    inheritedState.defaultListenerScope = me;
  } else {
    if (controller) {
      inheritedState.defaultListenerScope = controller;
    }
  }
  if (viewModel) {
    if (!viewModel.isViewModel) {
      viewModel = me;
    }
    inheritedState.viewModel = viewModel;
  }
  if (session) {
    if (!session.isSession) {
      session = me;
    }
    inheritedState.session = session;
  }
  if (reference) {
    me.referenceKey = (inheritedState.referencePath || '') + reference;
    me.viewModelKey = (inheritedState.viewModelPath || '') + reference;
  }
}, isBound:function(name) {
  var bind = this.getBind();
  return !!(bind && bind[name || this.defaultBindProperty]);
}, lookupController:function(skipThis) {
  return this.getInheritedConfig('controller', skipThis) || null;
}, lookupSession:function(skipThis) {
  var ret = skipThis ? null : this.getSession();
  if (!ret) {
    ret = this.getInheritedConfig('session', skipThis);
    if (ret && !ret.isSession) {
      ret = ret.getInherited().session = ret.getSession();
    }
  }
  return ret || null;
}, lookupViewModel:function(skipThis) {
  var ret = skipThis ? null : this.getViewModel();
  if (!ret) {
    ret = this.getInheritedConfig('viewModel', skipThis);
    if (ret && !ret.isViewModel) {
      ret = ret.getInherited().viewModel = ret.getViewModel();
    }
  }
  return ret || null;
}, publishState:function(property, value) {
  var me = this, state = me.publishedState, binds = me.getBind(), binding = binds && property && binds[property], count = 0, name, publishes, vm, path;
  if (!(arguments.length === 0 || arguments.length === 2)) {
    Ext.raise('publishState must either be called with no args, or with both name ' + 'AND value passed');
  }
  if (binding && !binding.syncing && !binding.isReadOnly()) {
    if (binding.calls || !(value == null || value === me.getInitialConfig()[property])) {
      binding.setValue(value);
    }
  }
  if (!(publishes = me.getPublishes())) {
    return;
  }
  if (!(vm = me.lookupViewModel())) {
    return;
  }
  if (!(path = me.viewModelKey)) {
    return;
  }
  state = state || (me.publishedState = {});
  if (property) {
    if (!publishes[property]) {
      return;
    }
    if (!(value && value.constructor === Object) && !(value instanceof Array)) {
      if (state[property] === value) {
        return;
      }
    }
    path += '.';
    path += property;
  } else {
    for (name in publishes) {
      ++count;
      state[name] = me.getConfig(name);
    }
    if (!count) {
      return;
    }
    value = state;
  }
  vm.set(path, value);
}, privates:{applyBind:function(binds, currentBindings) {
  if (!binds) {
    return currentBindings;
  }
  var me = this, viewModel = me.lookupViewModel(), twoWayable = me.getTwoWayBindable(), getBindTemplateScope = me._getBindTemplateScope, b, watch, property, descriptor;
  if (!viewModel) {
    Ext.raise('Cannot use bind config without a viewModel');
  }
  if (typeof binds === 'string') {
    if (!me.defaultBindProperty) {
      Ext.raise(me.$className + ' has no defaultBindProperty - ' + 'Please specify a bind object');
    }
    b = binds;
    binds = {};
    binds[me.defaultBindProperty] = b;
  }
  for (property in binds) {
    descriptor = binds[property];
    b = currentBindings && currentBindings[property];
    if (b) {
      b.destroy();
      delete currentBindings[property];
    }
    if (descriptor) {
      if (!b && twoWayable && twoWayable[property]) {
        (watch || (watch = {}))[property] = '_onConfigPropChange';
      }
      b = viewModel.bind(descriptor, me.onBindNotify, me);
      b._config = Ext.Config.get(property);
      b.getTemplateScope = getBindTemplateScope;
      if (!me[b._config.names.set]) {
        Ext.raise('Cannot bind ' + property + ' on ' + me.$className + ' - missing a ' + b._config.names.set + ' method.');
      }
      (currentBindings || (currentBindings = {}))[property] = b;
    }
  }
  if (watch) {
    watch.scope = me;
    me.watchConfig(watch);
  }
  me.$bindings = currentBindings;
  return currentBindings;
}, applyController:function(controller) {
  if (controller) {
    controller = Ext.Factory.controller(controller);
    controller.setView(this);
  }
  this.controller = controller;
  return controller;
}, updatePublishes:function(all) {
  var me = this, property, watch;
  if (all && me.lookupViewModel()) {
    for (property in all) {
      if (all[property]) {
        (watch || (watch = {}))[property] = '_onConfigPropChange';
      }
    }
    if (watch) {
      watch.scope = me;
      me.watchConfig(watch);
    }
  }
  return all;
}, applySession:function(session) {
  var parentSession, config;
  if (!session) {
    return null;
  }
  if (!session.isSession) {
    parentSession = this.lookupSession(true);
    config = session === true ? {} : session;
    if (parentSession) {
      session = parentSession.spawn(config);
    } else {
      session = new Ext.data['Session'](config);
    }
  }
  return session;
}, applyViewModel:function(viewModel) {
  var me = this, config, session;
  if (!viewModel) {
    return null;
  }
  if (!viewModel.isViewModel) {
    config = {parent:me.lookupViewModel(true), view:me};
    config.session = me.getSession();
    if (!session && !config.parent) {
      config.session = me.lookupSession();
    }
    if (viewModel) {
      if (viewModel.constructor === Object) {
        Ext.apply(config, viewModel);
      } else {
        if (typeof viewModel === 'string') {
          config.type = viewModel;
        }
      }
    }
    viewModel = Ext.Factory.viewModel(config);
  }
  return viewModel;
}, _getBindTemplateScope:function() {
  return this.scope.resolveListenerScope();
}, destroyBindable:function() {
  var me = this, viewModel = me.getConfig('viewModel', true), session = me.getConfig('session', true), controller = me.getController();
  if (viewModel && viewModel.isViewModel) {
    viewModel.destroy();
    me.setViewModel(null);
  }
  if (session && session.isSession) {
    if (session.getAutoDestroy()) {
      session.destroy();
    }
    me.setSession(null);
  }
  if (controller) {
    me.setController(null);
    controller.destroy();
  }
}, initBindable:function() {
  var me = this, controller = me.controller;
  me.initBindable = Ext.emptyFn;
  me.getBind();
  me.getPublishes();
  if (!me.viewModel) {
    me.getViewModel();
  }
  if (controller) {
    controller.initBindings();
  }
  if (me.reference) {
    me.publishState();
  }
}, isSyncing:function(name) {
  var bindings = this.getBind(), ret = false, binding;
  if (bindings) {
    binding = bindings[name];
    if (binding) {
      ret = binding.syncing > 0;
    }
  }
  return ret;
}, notifyIf:function(skipThis) {
  var vm = this.lookupViewModel(skipThis);
  if (vm) {
    vm.notify();
  }
}, onBindNotify:function(value, oldValue, binding) {
  binding.syncing = binding.syncing + 1 || 1;
  this[binding._config.names.set](value);
  --binding.syncing;
}, _onConfigPropChange:function(me, name, value) {
  me.publishState(name, value);
}, removeBindings:function() {
  var me = this, bindings = me.$bindings, b, key;
  if (bindings) {
    for (key in bindings) {
      b = bindings[key];
      if (b) {
        b.destroy();
        b._config = b.getTemplateScope = null;
        bindings[key] = null;
      }
    }
  }
}, updateSession:function(session) {
  var state = this.getInherited();
  if (session) {
    state.session = session;
  } else {
    delete state.session;
  }
}, updateViewModel:function(viewModel, oldViewModel) {
  var me = this, state = me.getInherited(), controller = me.getController();
  if (viewModel) {
    me.hasVM = true;
    state.viewModel = viewModel;
    viewModel.setView(me);
    if (controller) {
      controller.initViewModel(viewModel);
    }
  } else {
    delete state.viewModel;
  }
  me.viewModel = viewModel;
}}});
Ext.define('Ext.mixin.ComponentDelegation', {extend:Ext.Mixin, mixinConfig:{id:'componentDelegation'}, privates:{addDelegatedListener:function(eventName, fn, scope, options, order, caller, manager) {
  var me = this, delegatedEvents, event, priority;
  eventName = Ext.canonicalEventName(eventName);
  order = order || options.order;
  if (order) {
    priority = options && options.priority;
    if (!priority) {
      options = options ? Ext.Object.chain(options) : {};
      options.priority = me.$orderToPriority[order];
    }
  }
  if (options.target) {
    Ext.raise("Cannot add '" + eventName + "' listener to component: '" + me.id + "' - 'delegate' and 'target' event options are incompatible.");
  }
  delegatedEvents = me.$delegatedEvents || (me.$delegatedEvents = {});
  event = delegatedEvents[eventName] || (delegatedEvents[eventName] = new Ext.util.Event(me, eventName));
  if (event.addListener(fn, scope, options, caller, manager)) {
    me.$hasDelegatedListeners._incr_(eventName);
  }
}, clearDelegatedListeners:function() {
  var me = this, delegatedEvents = me.$delegatedEvents, eventName, event, listenerCount;
  if (delegatedEvents) {
    for (eventName in delegatedEvents) {
      event = delegatedEvents[eventName];
      listenerCount = event.listeners.length;
      event.clearListeners();
      me.$hasDelegatedListeners._decr_(eventName, listenerCount);
      delete delegatedEvents[eventName];
    }
  }
}, doFireDelegatedEvent:function(eventName, args) {
  var me = this, ret = true, owner, delegatedEvents, event;
  if (me.$hasDelegatedListeners[eventName]) {
    owner = me.getRefOwner();
    while (owner) {
      delegatedEvents = owner.$delegatedEvents;
      if (delegatedEvents) {
        event = delegatedEvents[eventName];
        if (event) {
          ret = event.fireDelegated(me, args);
          if (ret === false) {
            break;
          }
        }
      }
      owner = owner.getRefOwner();
    }
  }
  return ret;
}, removeDelegatedListener:function(eventName, fn, scope) {
  var me = this, delegatedEvents = me.$delegatedEvents, event;
  if (delegatedEvents) {
    event = delegatedEvents[eventName];
    if (event && event.removeListener(fn, scope)) {
      me.$hasDelegatedListeners._decr_(eventName);
      if (event.listeners.length === 0) {
        delete delegatedEvents[eventName];
      }
    }
  }
}, destroyComponentDelegation:function() {
  if (this.clearPropertiesOnDestroy) {
    this.$delegatedEvents = null;
  }
}}, onClassMixedIn:function(T) {
  function HasListeners() {
  }
  T.prototype.HasListeners = T.HasListeners = HasListeners;
  HasListeners.prototype = T.hasListeners = new Ext.mixin.ComponentDelegation.HasDelegatedListeners;
}}, function(ComponentDelegation) {
  function HasDelegatedListeners() {
  }
  ComponentDelegation.HasDelegatedListeners = HasDelegatedListeners;
  HasDelegatedListeners.prototype = ComponentDelegation.prototype.$hasDelegatedListeners = new Ext.mixin.Observable.HasListeners;
});
Ext.define('Ext.plugin.Abstract', {alternateClassName:'Ext.AbstractPlugin', mixins:[Ext.mixin.Identifiable], isPlugin:true, constructor:function(config) {
  if (config) {
    this.cmp = config.cmp;
    this.pluginConfig = config;
    this.initConfig(config);
  }
}, init:Ext.emptyFn, destroy:function() {
  var me = this;
  me.destroy = Ext.emptyFn;
  me.destroying = true;
  me.cmp = me.pluginConfig = null;
  me.doDestroy();
  me.callParent();
}, doDestroy:Ext.emptyFn, clonePlugin:function(overrideCfg) {
  return new this.self(Ext.apply({}, overrideCfg, this.pluginConfig));
}, getCmp:function() {
  return this.cmp;
}, setCmp:function(host) {
  this.cmp = host;
}, getStatefulOwner:function() {
  return [this.cmp, 'plugins'];
}, onClassExtended:function(cls, data, hooks) {
  var alias = data.alias, prototype = cls.prototype;
  if (alias && !data.ptype) {
    if (Ext.isArray(alias)) {
      alias = alias[0];
    }
    prototype.ptype = alias.split('plugin.')[1];
  }
}, resolveListenerScope:function(defaultScope) {
  var me = this, cmp = me.getCmp(), scope;
  if (cmp) {
    scope = cmp.resolveSatelliteListenerScope(me, defaultScope);
  }
  return scope || me.mixins.observable.resolveListenerScope.call(me, defaultScope);
}, statics:{decode:function(plugins, typeProp, include) {
  if (plugins) {
    var type = Ext.typeOf(plugins), entry, key, obj, value;
    if (type === 'string') {
      obj = {};
      obj[typeProp] = plugins;
      plugins = [obj];
    } else {
      if (plugins.isInstance) {
        plugins = [plugins];
      } else {
        if (type === 'object') {
          if (plugins[typeProp]) {
            plugins = [plugins];
          } else {
            obj = include ? Ext.merge(Ext.clone(include), plugins) : plugins;
            plugins = [];
            for (key in obj) {
              if (!(value = obj[key])) {
                continue;
              }
              entry = {id:key};
              entry[typeProp] = key;
              Ext.apply(entry, value);
              plugins.push(entry);
            }
            Ext.sortByWeight(plugins);
          }
        } else {
          if (type !== 'array') {
            Ext.raise('Invalid value for "plugins" config ("' + type + '"');
          } else {
            plugins = plugins.slice();
          }
        }
      }
    }
  }
  return plugins;
}}});
Ext.define('Ext.mixin.Pluggable', function(Pluggable) {
  return {mixinId:'pluggable', config:{plugins:null}, addPlugin:function(plugin) {
    var me = this, plugins = me.getPlugins();
    if (plugins) {
      plugin = me.createPlugin(plugin);
      plugin.init(me);
      plugins.push(plugin);
    } else {
      me.setPlugins(plugin);
      plugin = me.getPlugins()[0];
    }
    return plugin;
  }, destroyPlugin:function(plugin) {
    return this.removePlugin(plugin, true);
  }, findPlugin:function(type) {
    var plugins = this.getPlugins(), n = plugins && plugins.length, i, plugin, ret;
    for (i = 0; i < n && !ret; i++) {
      plugin = plugins[i];
      if (plugin.type === type || plugin.ptype === type) {
        ret = plugin;
      }
    }
    return ret || null;
  }, getPlugin:function(id) {
    var plugins = this.getPlugins(), n = plugins && plugins.length, i, plugin, ret;
    for (i = 0; i < n && !ret; i++) {
      plugin = plugins[i];
      if (plugin.id === id || plugin.pluginId === id) {
        ret = plugin;
      }
    }
    return ret || null;
  }, removePlugin:function(plugin, destroy) {
    var plugins = this.getPlugins(), i = plugins && plugins.length || 0, p;
    while (i-- > 0) {
      p = plugins[i];
      if (p === plugin || p.id === plugin) {
        plugins.splice(i, 1);
        if (destroy) {
          if (p.destroy) {
            p.destroy();
          }
        } else {
          if (p.detachCmp) {
            p.detachCmp();
            if (p.setCmp) {
              p.setCmp(null);
            }
          }
        }
        break;
      }
      p = null;
    }
    return p;
  }, privates:{statics:{idSeed:0}, activatePlugin:function(type) {
    var me = this, config = me.initialConfig, plugins = config && config.plugins, ret = null, i, include, p;
    if (plugins) {
      include = me.config.plugins;
      include = include && typeof include === 'object' ? include : null;
      plugins = Ext.plugin.Abstract.decode(plugins, 'type', include);
      for (i = plugins.length; i-- > 0;) {
        p = plugins[i];
        if (p === type || p.type === type) {
          me.initialConfig = config = Ext.apply({}, config);
          config.plugins = plugins;
          plugins[i] = ret = me.createPlugin(p);
          break;
        }
      }
    }
    return ret;
  }, applyPlugins:function(plugins, oldPlugins) {
    var me = this, oldCount = oldPlugins && oldPlugins.length || 0, count, i, plugin;
    if (plugins) {
      plugins = Ext.plugin.Abstract.decode(plugins, 'type');
    }
    for (i = 0; i < oldCount; ++i) {
      oldPlugins[i].$dead = true;
    }
    count = plugins && plugins.length || 0;
    for (i = 0; i < count; ++i) {
      plugins[i] = me.createPlugin(plugins[i]);
    }
    for (i = 0; i < count; ++i) {
      plugin = plugins[i];
      if (plugin.$dead) {
        delete plugin.$dead;
      } else {
        plugin.init(me);
      }
    }
    for (i = 0; i < oldCount; ++i) {
      if ((plugin = oldPlugins[i]).$dead) {
        delete plugin.$dead;
        Ext.destroy(plugin);
      }
    }
    return plugins;
  }, createPlugin:function(config) {
    var ret;
    if (typeof config === 'string') {
      config = {type:config};
    }
    ret = config;
    if (!config.isInstance) {
      config.cmp = this;
      ret = Ext.factory(config, null, null, 'plugin');
      delete config.cmp;
    }
    if (!ret.id) {
      ret.id = ++Pluggable.idSeed;
    }
    if (ret.setCmp) {
      ret.setCmp(this);
    }
    return ret;
  }}};
});
Ext.define('Ext.mixin.Keyboard', function(Keyboard) {
  return {extend:Ext.Mixin, mixinConfig:{id:'keyboard'}, config:{keyMap:{$value:null, cached:true, merge:function(value, baseValue, cls, mixin) {
    var ret, key, ucKey, v, vs;
    if (value === null) {
      return value;
    }
    ret = baseValue && !cls.isInstance ? Ext.Object.chain(baseValue) : {};
    for (key in value) {
      if (key !== 'scope') {
        ucKey = key.toUpperCase();
        if (!mixin || ret[ucKey] === undefined) {
          v = value[key];
          if (v) {
            if (typeof v === 'string' || typeof v === 'function') {
              v = {handler:v};
            } else {
              v = Ext.apply({handler:v.fn}, v);
            }
            vs = v.scope || value.scope || 'self';
            v.scope = vs === 'controller' ? 'self.controller' : vs;
          }
          ret[ucKey] = v;
        }
      }
    }
    return ret;
  }}, keyMapEnabled:null}, keyMapTarget:'el', applyKeyMap:function(keyMap, existingKeyMap) {
    var me = this, own = me.hasOwnProperty('config');
    if (own && existingKeyMap && existingKeyMap.$owner !== me) {
      existingKeyMap = Ext.apply({}, existingKeyMap);
    }
    keyMap = keyMap ? Keyboard.combineKeyMaps(existingKeyMap, keyMap, own && me) : null;
    if (me._keyMapReady) {
      me.setKeyMapListener(keyMap && me.getKeyMapEnabled());
    }
    return keyMap;
  }, initKeyMap:function() {
    var me = this, enabled = me.getKeyMapEnabled();
    me._keyMapReady = true;
    if (enabled === null) {
      me.setKeyMapEnabled(true);
    } else {
      me.setKeyMapListener(enabled && me.getKeyMap());
    }
  }, disableKeyMapGroup:function(group) {
    this.setKeyMapGroupEnabled(group, false);
  }, enableKeyMapGroup:function(group) {
    this.setKeyMapGroupEnabled(group, true);
  }, setKeyMapGroupEnabled:function(group, state) {
    var me = this, disabledGroups = me.disabledKeyMapGroups || (me.disabledKeyMapGroups = {});
    disabledGroups[group] = !state;
  }, updateKeyMapEnabled:function(enabled) {
    this.setKeyMapListener(enabled && this._keyMapReady && this.getKeyMap());
  }, privates:{_keyMapListenCount:0, _keyMapReady:false, comparePriorities:function(lhs, rhs) {
    return (rhs.priority || 0) - (lhs.priority || 0);
  }, findKeyMapEntries:function(e) {
    var me = this, disabledGroups = me.disabledKeyMapGroups, keyMap = me.getKeyMap(), entries = keyMap && Keyboard.getKeyName(e), result = [], entry, len, i;
    entries = entries && keyMap[entries];
    if (entries) {
      if (!entries.sorted) {
        Ext.Array.sort(entries, me.comparePriorities);
        entries.sorted = true;
      }
      len = entries.length;
      for (i = 0; i < len; i++) {
        entry = entries[i];
        if (!disabledGroups || !disabledGroups[entry.group]) {
          if (Keyboard.matchEntry(entry, e)) {
            result.push(entry);
          }
        }
      }
    }
    return result;
  }, onKeyMapEvent:function(e) {
    var me = this, entries = me.getKeyMapEnabled() ? me.findKeyMapEntries(e) : null, len = entries && entries.length, i, entry, result;
    me.lastKeyMapEvent = e;
    for (i = 0; i < len && result !== false; i++) {
      entry = entries[i];
      result = Ext.callback(entry.handler, entry.scope, [e, this], 0, this);
    }
    return result;
  }, setKeyMapListener:function(enabled) {
    var me = this, listener = me._keyMapListener, eventSource;
    if (listener) {
      listener.destroy();
      listener = null;
    }
    if (enabled) {
      ++me._keyMapListenCount;
      if (enabled) {
        eventSource = me[me.keyMapTarget];
        if (typeof eventSource === 'function') {
          eventSource = eventSource.call(me);
        }
        listener = eventSource.on({destroyable:true, scope:me, keydown:'onKeyMapEvent', keypress:'onKeyMapEvent'});
      }
    }
    me._keyMapListener = listener || null;
  }, statics:{_charCodeRe:/^#([\d]+)$/, _keySpecRe:/^(?:(?:(\*)[\+\-])|(?:([a-z\+\-]*)[\+\-]))?(?:([a-z0-9_]+|[\+\-]|(?:#?\d+))(?::([a-z]+))?)$/i, _delimiterRe:/-|\+/, _keyMapEvents:{charCode:'keypress', keyCode:'keydown'}, combineKeyMaps:function(existingKeyMap, keyMap, owner) {
    var defaultScope = keyMap.scope || 'controller', entry, key, mapping, existingMapping;
    for (key in keyMap) {
      if (key === 'scope') {
        continue;
      }
      if (!(mapping = keyMap[key])) {
        if (mapping === undefined) {
          Ext.raise('keyMap entry "' + key + '" is undefined');
        }
        if (!existingKeyMap) {
          continue;
        }
      } else {
        if (typeof mapping === 'string' || typeof mapping === 'function') {
          mapping = {handler:mapping, scope:defaultScope};
        } else {
          if (mapping) {
            mapping = Ext.apply({handler:mapping.fn, scope:defaultScope}, mapping);
          }
        }
        existingKeyMap = existingKeyMap || {};
      }
      if (Keyboard.parseEntry(key, entry = mapping || {})) {
        existingMapping = existingKeyMap[entry.name];
        if (existingMapping) {
          if (owner && existingMapping.$owner !== owner) {
            existingKeyMap[entry.name] = existingMapping = existingMapping.slice();
            existingMapping.$owner = owner;
          }
          existingMapping.push(mapping);
          existingMapping.sorted = false;
        } else {
          existingMapping = existingKeyMap[entry.name] = [mapping];
          existingMapping.$owner = owner;
          existingMapping.sorted = true;
        }
      } else {
        Ext.raise('Invalid keyMap key specification "' + key + '"');
      }
    }
    if (existingKeyMap && owner) {
      existingKeyMap.$owner = owner;
    }
    return existingKeyMap || null;
  }, getKeyName:function(event) {
    var keyCode;
    if (event.isEvent) {
      keyCode = event.keyCode || event.charCode;
      event = event.browserEvent;
      if (keyCode === 229 && 'code' in event) {
        if (Ext.String.startsWith(event.code, 'Key')) {
          return event.key.substr(3);
        }
        if (Ext.String.startsWith(event.code, 'Digit')) {
          return event.key.substr(5);
        }
      }
    } else {
      keyCode = event;
    }
    return Ext.event.Event.keyCodes[keyCode] || String.fromCharCode(keyCode);
  }, matchEntry:function(entry, e) {
    var ev = e.browserEvent, code;
    if (e.type !== entry.event) {
      return false;
    }
    if (!(code = entry.charCode)) {
      if (entry.keyCode !== e.keyCode || !entry.ignoreModifiers && !entry.shiftKey !== !ev.shiftKey) {
        return false;
      }
    } else {
      if (e.getCharCode() !== code) {
        return false;
      }
    }
    return entry.ignoreModifiers || !entry.ctrlKey === !ev.ctrlKey && !entry.altKey === !ev.altKey && !entry.metaKey === !ev.metaKey && !entry.shiftKey === !ev.shiftKey;
  }, parseEntry:function(key, entry) {
    key = key.toUpperCase();
    var me = this, Event = Ext.event.Event, keyFlags = Event.keyFlags, parts = me._keySpecRe.exec(key), type = 'keyCode', name, code, i, match, n;
    if (parts) {
      name = parts[3];
      if (parts[4]) {
        entry.group = parts[4];
      }
      if (!(entry.ignoreModifiers = !!parts[1]) && parts[2]) {
        parts = parts[2].split(me._delimiterRe);
        n = parts.length;
        for (i = 0; i < n; i++) {
          if (!keyFlags[parts[i]]) {
            return false;
          }
          entry[keyFlags[parts[i]]] = true;
        }
      }
      entry.name = name;
      if (isNaN(code = Event[name])) {
        if (!(match = me._charCodeRe.exec(name))) {
          if (name.length === 1) {
            code = name.charCodeAt(0);
          }
        } else {
          code = +match[1];
        }
        if (code) {
          type = 'charCode';
        } else {
          code = +name;
        }
        entry.name = Keyboard.getKeyName(code);
      }
      entry.event = entry.event || me._keyMapEvents[type];
      return !isNaN(code) && (entry[type] = code);
    }
  }}}};
});
Ext.define('Ext.mixin.Focusable', {mixinId:'focusable', $isFocusableEntity:true, focusable:false, hasFocus:false, containsFocus:false, focusCls:Ext.baseCSSPrefix + 'focused', focusEl:'el', getFocusEl:function() {
  var focusEl = this.focusEl;
  return focusEl && focusEl.dom ? focusEl : null;
}, getFocusClsEl:function() {
  return this.getFocusEl();
}, initFocusable:Ext.emptyFn, initFocusableEvents:function(force) {
  this.initFocusableElement(force);
}, enableFocusable:Ext.emptyFn, disableFocusable:function() {
  var me = this;
  if (me.hasFocus) {
    me.revertFocus();
  }
  me.removeFocusCls();
}, destroyFocusable:function() {
  var me = this;
  Ext.destroy(me.focusListeners);
  me.focusListeners = me.focusEnterEvent = me.focusTask = null;
  me.focusEl = me.ariaEl = null;
}, isFocusable:function(deep) {
  var me = this, focusEl;
  if (!me.focusable && (!me.isContainer || !deep)) {
    return false;
  }
  focusEl = me.getFocusEl();
  if (focusEl && me.canFocus()) {
    return focusEl && !focusEl.destroyed && focusEl.isFocusable(deep);
  }
  return false;
}, isDestructing:function() {
  var c;
  for (c = this; c; c = c.getRefOwner()) {
    if (c.destroying || c.destroyed) {
      return true;
    }
  }
  return false;
}, canFocus:function(skipVisibility, includeFocusTarget) {
  var me = this, ownerFC = me.ownerFocusableContainer, focusableIfDisabled = ownerFC && ownerFC.allowFocusingDisabledChildren, canFocus;
  canFocus = !me.destroyed && me.rendered && !me.isDestructing() && (me.isContainer || me.focusable) && (!me.isDisabled() || focusableIfDisabled) && (skipVisibility || me.isVisible(true));
  return canFocus || includeFocusTarget && !!me.findFocusTarget();
}, focus:function(selectText) {
  var me = this, focusTarget, focusElDom;
  if (!me.focusable && !me.isContainer || me.destroyed || me.destroying) {
    return false;
  }
  if (me.canFocus() && (focusTarget = me.getFocusEl())) {
    if (focusTarget.$isFocusableEntity) {
      return focusTarget.focus.apply(focusTarget, arguments);
    }
    focusElDom = focusTarget.dom;
    if (focusElDom) {
      focusTarget.focus();
      if (selectText && (me.selectText || focusElDom.select)) {
        if (me.selectText) {
          if (Ext.isArray(selectText)) {
            me.selectText.apply(me, selectText);
          } else {
            me.selectText();
          }
        } else {
          focusElDom.select();
        }
      }
    } else {
      if (focusTarget.focus) {
        focusTarget.focus();
      } else {
        return false;
      }
    }
  } else {
    focusTarget = me.findFocusTarget();
    if (focusTarget && focusTarget !== me) {
      return focusTarget.focus.apply(focusTarget, arguments);
    } else {
      return false;
    }
  }
  return true;
}, onBlur:function(e) {
  var me = this, container = me.ownerFocusableContainer;
  me.hasFocus = false;
  if (me.beforeBlur && !me.beforeBlur.$emptyFn) {
    me.beforeBlur(e);
  }
  if (container) {
    container.beforeFocusableChildBlur(me, e);
  }
  me.removeFocusCls(e);
  if (me.hasListeners.blur) {
    me.fireEvent('blur', me, e);
  }
  if (me.postBlur && !me.postBlur.$emptyFn) {
    me.postBlur(e);
  }
  if (container) {
    container.afterFocusableChildBlur(me, e);
  }
}, onFocus:function(e) {
  var me = this, container = me.ownerFocusableContainer;
  if (me.canFocus()) {
    if (me.beforeFocus && !me.beforeFocus.$emptyFn) {
      me.beforeFocus(e);
    }
    if (container) {
      container.beforeFocusableChildFocus(me, e);
    }
    me.addFocusCls(e);
    if (!me.hasFocus) {
      me.hasFocus = true;
      me.fireEvent('focus', me, e);
    }
    if (me.postFocus && !me.postFocus.$emptyFn) {
      me.postFocus(e);
    }
    if (container) {
      container.afterFocusableChildFocus(me, e);
    }
  }
}, getTabIndex:function() {
  var me = this, el, index;
  if (!me.focusable) {
    return;
  }
  el = me.getFocusEl();
  if (el) {
    if (el.$isFocusableEntity) {
      index = el.getTabIndex();
    } else {
      if (el.isElement && el.dom) {
        index = el.dom.getAttribute('tabIndex');
        if (index !== null) {
          index -= 0;
        }
      } else {
        return;
      }
    }
  }
  if (typeof index !== 'number') {
    index = me.tabIndex;
  }
  return index;
}, setTabIndex:function(newTabIndex, focusEl) {
  var me = this, ownerFC = me.ownerFocusableContainer, focusableIfDisabled = ownerFC && ownerFC.allowFocusingDisabledChildren, wasFocusable = me.focusable, el;
  if (!wasFocusable && !(me.forceTabIndex || newTabIndex == null)) {
    return;
  }
  me.tabIndex = newTabIndex;
  if (me.destroying || me.destroyed || me.isDisabled() && !focusableIfDisabled) {
    return;
  }
  me.focusable = true;
  el = focusEl || me.getFocusEl();
  me.focusable = wasFocusable;
  if (el) {
    if (el.$isFocusableEntity) {
      el.setTabIndex(newTabIndex);
    } else {
      if (el.isElement && el.dom) {
        el.setTabIndex(newTabIndex);
      }
    }
  }
}, onFocusEnter:function(e) {
  var me = this;
  if (me.destroying || me.destroyed) {
    return;
  }
  me.focusEnterEvent = e;
  me.containsFocus = true;
  if (me.hasListeners.focusenter) {
    me.fireEvent('focusenter', me, e);
  }
}, onFocusLeave:function(e) {
  var me = this;
  if (me.destroying || me.destroyed) {
    return;
  }
  me.focusEnterEvent = null;
  me.containsFocus = false;
  if (me.hasListeners.focusleave) {
    me.fireEvent('focusleave', me, e);
  }
}, onFocusMove:Ext.emptyFn, privates:{forceTabIndex:false, revertFocus:function() {
  var me = this, focusEvent = me.focusEnterEvent, activeElement = Ext.Element.getActiveElement(), focusTarget, fromComponent, reverted;
  if (focusEvent && !me.preventRefocus && me.el.contains(activeElement)) {
    fromComponent = focusEvent.fromComponent;
    if (fromComponent && (fromComponent.destroyed || fromComponent.isDestructing())) {
      focusTarget = document.body;
    } else {
      focusTarget = focusEvent.relatedTarget;
    }
    if (focusTarget === document.body) {
      fromComponent = me.findFocusTarget();
      if (fromComponent) {
        focusTarget = fromComponent.getFocusEl();
      }
    }
    if (focusTarget && focusTarget.$isFocusableEntity) {
      if (!focusTarget.destroyed && focusTarget.isFocusable()) {
        focusTarget.focus();
      }
    } else {
      if (Ext.getDoc().contains(focusTarget) && Ext.fly(focusTarget).isFocusable()) {
        fromComponent = Ext.Component.from(focusTarget);
        if (fromComponent) {
          fromComponent.revertFocusTo(focusTarget);
        } else {
          focusTarget.focus();
        }
      } else {
        if (focusEvent.fromComponent && focusEvent.fromComponent.focus) {
          reverted = focusEvent.fromComponent.focus();
          if (!reverted) {
            activeElement.blur();
          }
        }
      }
    }
  }
}, revertFocusTo:function(target) {
  target.focus();
}, findFocusTarget:function() {
  var me = this, parentAxis, candidate, len, i, focusTargets, focusIndex;
  if (me.preventRefocus) {
    return null;
  }
  for (parentAxis = [], candidate = me.getRefOwner(); candidate; candidate = candidate.getRefOwner()) {
    if (!candidate.isDisabled()) {
      parentAxis.unshift(candidate);
    }
  }
  for (i = 0, len = parentAxis.length; i < len; i++) {
    candidate = parentAxis[i];
    if (candidate.destroying || !candidate.isVisible()) {
      parentAxis.length = i;
      break;
    }
  }
  for (i = parentAxis.length - 1; i >= 0; i--) {
    candidate = parentAxis[i];
    focusTargets = Ext.ComponentQuery.query(':canfocus()', candidate);
    if (focusTargets.length) {
      focusIndex = Ext.Array.indexOf(focusTargets, Ext.ComponentManager.getActiveComponent());
      return focusTargets[focusIndex + 1] || focusTargets[focusIndex - 1] || focusTargets[0];
    }
    if (candidate.isFocusable && candidate.isFocusable()) {
      return candidate;
    }
  }
}, initFocusableElement:function(force) {
  var me = this, tabIndex = me.getTabIndex(), focusEl = me.getFocusEl();
  if (focusEl && !focusEl.$isFocusableEntity) {
    if (tabIndex != null && (force || me.canFocus(true))) {
      me.setTabIndex(tabIndex, focusEl);
    }
    if (!focusEl.dom.hasAttribute('data-componentid')) {
      focusEl.dom.setAttribute('data-componentid', me.id);
    }
  }
}, addFocusCls:function(e) {
  var focusCls = this.focusCls, el;
  el = this.getFocusClsEl();
  if (focusCls) {
    el = this.getFocusClsEl(e);
    if (el) {
      el.addCls(focusCls);
    }
  }
}, removeFocusCls:function(e) {
  var focusCls = this.focusCls, el;
  if (focusCls) {
    el = this.getFocusClsEl(e);
    if (el) {
      el.removeCls(focusCls);
    }
  }
}, handleFocusEvent:function(info) {
  var me = this, event;
  if (!me.focusable || me.destroying || me.destroyed) {
    return;
  }
  if (me.isFocusing(info)) {
    event = new Ext.event.Event(info.event);
    event.type = 'focus';
    event.relatedTarget = info.fromElement;
    event.target = info.toElement;
    me.onFocus(event);
  }
}, handleBlurEvent:function(info) {
  var me = this, event;
  if (!me.focusable || me.destroying || me.destroyed) {
    return;
  }
  if (info.toElement === document.body || me.isBlurring(info)) {
    event = new Ext.event.Event(info.event);
    event.type = 'blur';
    event.target = info.fromElement;
    event.relatedTarget = info.toElement;
    me.onBlur(event);
  }
}, isFocusing:function(e) {
  var focusEl = this.getFocusEl();
  if (focusEl) {
    if (focusEl.isFocusing) {
      return focusEl.isFocusing(e);
    } else {
      return focusEl.dom === document.activeElement && e.toElement === focusEl.dom && e.fromElement !== e.toElement;
    }
  }
  return false;
}, isBlurring:function(e) {
  var focusEl = this.getFocusEl();
  if (focusEl) {
    if (focusEl.isFocusing) {
      return focusEl.isBlurring(e);
    } else {
      return focusEl.dom !== document.activeElement && e.fromElement === focusEl.dom && e.fromElement !== e.toElement;
    }
  }
  return false;
}, blur:function() {
  var me = this, focusEl;
  if (!me.focusable || !me.canFocus()) {
    return;
  }
  focusEl = me.getFocusEl();
  if (focusEl) {
    me.blurring = true;
    focusEl.blur();
    delete me.blurring;
  }
}, isTabbable:function() {
  var me = this, focusEl;
  if (me.focusable) {
    focusEl = me.getFocusEl();
    if (focusEl && focusEl.isTabbable()) {
      return focusEl.isTabbable();
    }
  }
  return false;
}, disableTabbing:function() {
  var me = this, el = me.el, focusEl;
  if (me.destroying || me.destroyed) {
    return;
  }
  if (el) {
    el.saveTabbableState();
  }
  focusEl = me.getFocusEl();
  if (focusEl) {
    if (focusEl.$isFocusableEntity) {
      focusEl.disableTabbing();
    } else {
      if (focusEl.isElement && el && !el.contains(focusEl)) {
        focusEl.saveTabbableState();
      }
    }
  }
}, enableTabbing:function(reset) {
  var me = this, el = me.el, focusEl;
  if (me.destroying || me.destroyed) {
    return;
  }
  focusEl = me.getFocusEl();
  if (focusEl) {
    if (focusEl.$isFocusableEntity) {
      focusEl.enableTabbing();
    } else {
      if (focusEl.isElement && el && !el.contains(focusEl)) {
        focusEl.restoreTabbableState();
      }
    }
  }
  if (el) {
    el.restoreTabbableState({reset:reset});
  }
}}}, function() {
  var keyboardModeCls = Ext.baseCSSPrefix + 'keyboard-mode', keyboardMode = false;
  Ext.enableKeyboardMode = Ext.isModern || !Ext.os.is.Desktop;
  Ext.setKeyboardMode = Ext.setKeyboardMode || function(keyboardMode) {
    Ext.keyboardMode = keyboardMode;
    Ext.getBody().toggleCls(keyboardModeCls, keyboardMode);
  };
  Ext.isTouchMode = function() {
    return Ext.now() - Ext.lastTouchTime < 500;
  };
  Ext.syncKeyboardMode = function(e) {
    var type;
    if (!Ext.enableKeyboardMode) {
      return;
    }
    type = e.type;
    if (type === 'pointermove') {
      keyboardMode = false;
    } else {
      keyboardMode = type === 'keydown';
      Ext.lastTouchTime = e.pointerType === 'touch' && Ext.now();
      Ext.setKeyboardMode(keyboardMode);
    }
  };
  function keyboardModeFocusHandler() {
    if (keyboardMode !== Ext.getBody().hasCls(keyboardModeCls)) {
      Ext.setKeyboardMode(keyboardMode);
    }
  }
  Ext.getEnableKeyboardMode = function() {
    return Ext.enableKeyboardMode;
  };
  Ext.setEnableKeyboardMode = function(enable) {
    var listeners = {pointerdown:Ext.syncKeyboardMode, pointermove:Ext.syncKeyboardMode, keydown:Ext.syncKeyboardMode, capture:true, delegated:false};
    Ext.enableKeyboardMode = !!enable;
    if (Ext.enableKeyboardMode) {
      Ext.getWin().on(listeners);
      Ext.on('focus', keyboardModeFocusHandler);
    } else {
      Ext.getWin().un(listeners);
      Ext.un('focus', keyboardModeFocusHandler);
    }
  };
  Ext.onReady(function() {
    if (!Ext.enableKeyboardMode) {
      Ext.getBody().addCls(keyboardModeCls);
    }
    Ext.setEnableKeyboardMode(Ext.enableKeyboardMode);
  });
});
Ext.define('Ext.mixin.Accessible', {extend:Ext.Mixin, mixinConfig:{id:'accessible'}, config:{ariaAttributes:{$value:null, lazy:true}}, ariaEl:'el', privates:{getAriaLabelEl:function(reference) {
  var ids = [], refHolder, i, len, cmp;
  if (reference) {
    if (Ext.isFunction(reference)) {
      return reference.call(this);
    } else {
      if (!Ext.isArray(reference)) {
        reference = [reference];
      }
      refHolder = this.lookupReferenceHolder();
      if (refHolder) {
        for (i = 0, len = reference.length; i < len; i++) {
          cmp = refHolder.lookupReference(reference[i]);
          if (cmp) {
            ids.push(cmp.ariaEl.id);
          }
        }
      }
    }
  }
  return ids.length ? ids.join(' ') : null;
}}});
Ext.define('Ext.Widget', {extend:Ext.Evented, xtype:'widget', alternateClassName:'Ext.Gadget', mixins:[Ext.mixin.Inheritable, Ext.mixin.Bindable, Ext.mixin.ComponentDelegation, Ext.mixin.Pluggable, Ext.mixin.Keyboard, Ext.mixin.Factoryable, Ext.mixin.Focusable, Ext.mixin.Accessible], isWidget:true, factoryConfig:{creator:null, defaultProperty:'xtype', defaultType:'component', typeProperty:'xtype'}, element:{reference:'element'}, observableType:'component', cachedConfig:{cls:null, margin:null, style:null, 
border:null, touchAction:null, eventHandlers:{focus:'handleFocusEvent', blur:'handleBlurEvent'}}, name:null, config:{renderTo:null, ui:null, userCls:null, ripple:null, hideMode:null, instanceCls:null}, eventedConfig:{width:null, height:null, hidden:null, disabled:null}, template:[], baseCls:null, classCls:null, classClsRoot:true, classClsList:[], clearPropertiesOnDestroy:'async', focusEl:'element', ariaEl:'element', spaceRe:/\s+/, noBorderCls:Ext.baseCSSPrefix + 'noborder-trbl', borderedCls:Ext.baseCSSPrefix + 
'bordered', disabledCls:Ext.baseCSSPrefix + 'disabled', heightedCls:Ext.baseCSSPrefix + 'heighted', widthedCls:Ext.baseCSSPrefix + 'widthed', constructor:function(config) {
  var me = this, baseCls = me.baseCls, renderTo = config && config.renderTo, controller;
  me.$iid = ++Ext.$nextIid;
  if (baseCls == null || baseCls === true) {
    me.baseCls = me.classCls || Ext.baseCSSPrefix + me.xtype;
  }
  if (config && 'baseCls' in config) {
    Ext.raise('baseCls cannot be used as an instance config. It must be specified ' + 'at class definition time.');
  }
  if (config && config.controller || me.config.controller) {
    me.referenceHolder = true;
  }
  me.initId(config);
  me.initElement();
  if (renderTo) {
    config = Ext.apply({}, config);
    delete config.renderTo;
  }
  me.mixins.observable.constructor.call(me, config);
  if (me.focusable) {
    me.initFocusableEvents(true);
  }
  me.syncUiCls();
  Ext.ComponentManager.register(me);
  controller = me.getController();
  if (controller) {
    controller.init(me);
  }
  if (renderTo) {
    me.setRenderTo(renderTo);
  }
}, afterCachedConfig:function() {
  var me = this, prototype = me.self.prototype, referenceList = me.referenceList, renderElement = me.renderElement, renderTemplate, element, i, ln, reference, elements;
  prototype.renderTemplate = renderTemplate = document.createDocumentFragment();
  renderTemplate.appendChild(renderElement.clone(true, true));
  elements = renderTemplate.querySelectorAll('[id]');
  for (i = 0, ln = elements.length; i < ln; i++) {
    element = elements[i];
    element.removeAttribute('id');
  }
  for (i = 0, ln = referenceList.length; i < ln; i++) {
    reference = referenceList[i];
    me[reference].dom.removeAttribute('reference');
  }
}, applyHidden:function(hidden) {
  return !!hidden;
}, applyDisabled:function(disabled) {
  return !!disabled;
}, updateDisabled:function(disabled) {
  var me = this, container = me.ownerFocusableContainer;
  if (container) {
    if (disabled) {
      if (!container.beforeFocusableChildDisable.$nullFn) {
        container.beforeFocusableChildDisable(me);
      }
    } else {
      if (!container.beforeFocusableChildEnable.$nullFn) {
        container.beforeFocusableChildEnable(me);
      }
    }
  }
  me.element.toggleCls(me.disabledCls, disabled);
  if (me.focusable) {
    if (disabled) {
      me.disableFocusable();
    } else {
      me.enableFocusable();
    }
  }
  if (container) {
    if (disabled) {
      if (!container.onFocusableChildDisable.$nullFn) {
        container.onFocusableChildDisable(me);
      }
    } else {
      if (!container.onFocusableChildEnable.$nullFn) {
        container.onFocusableChildEnable(me);
      }
    }
  }
}, disable:function() {
  this.setDisabled(true);
}, enable:function() {
  this.setDisabled(false);
}, isDisabled:function() {
  return this.getDisabled();
}, isEnabled:function() {
  return !this.getDisabled();
}, applyTouchAction:function(touchAction, oldTouchAction) {
  if (oldTouchAction != null) {
    touchAction = Ext.merge({}, oldTouchAction, touchAction);
  }
  return touchAction;
}, applyWidth:function(width) {
  return this.filterLengthValue(width);
}, applyHeight:function(height) {
  return this.filterLengthValue(height);
}, updateBorder:function(border) {
  var me = this;
  border = border || border === null;
  me.toggleCls(me.noBorderCls, !border);
  me.toggleCls(me.borderedCls, !!border);
}, clearListeners:function() {
  var me = this;
  me.mixins.observable.clearListeners.call(me);
  me.mixins.componentDelegation.clearDelegatedListeners.call(me);
}, destroy:function() {
  var me = this;
  me.isDestroying = me.destroying = true;
  me.destroy = Ext.emptyFn;
  me.doDestroy();
  me.clearListeners();
  me.mixins.componentDelegation.destroyComponentDelegation.call(me);
  me.callParent();
}, doDestroy:function() {
  var me = this, referenceList = me.referenceList, container = me.ownerFocusableContainer, i, ln, reference;
  me.ownerCmp = null;
  if (container && !container.onFocusableChildDestroy.$nullFn) {
    container.onFocusableChildDestroy(me);
  }
  for (i = 0, ln = referenceList.length; i < ln; i++) {
    reference = referenceList[i];
    if (me.hasOwnProperty(reference)) {
      me[reference].destroy();
      me[reference] = null;
    }
  }
  me.destroyBindable();
  Ext.ComponentManager.unregister(me);
}, doFireEvent:function(eventName, args, bubbles) {
  var me = this, ev, ret;
  ret = me.mixins.observable.doFireEvent.call(me, eventName, args, bubbles);
  if (ret !== false && !me.destroyed) {
    ev = me.events[eventName];
    if (!ev || !ev.suspended) {
      ret = me.mixins.componentDelegation.doFireDelegatedEvent.call(me, eventName, args);
    }
  }
  return ret;
}, getBubbleTarget:function() {
  return this.getRefOwner();
}, getElementConfig:function() {
  var me = this, el = me.element;
  if (!('children' in el)) {
    el = Ext.apply({children:me.getTemplate()}, el);
  }
  return el;
}, getSize:function() {
  return this.el.getSize();
}, getTemplate:function() {
  return Ext.clone(this.template);
}, getClassCls:function() {
  var proto = this.self.prototype, prototype = proto, classes, classCls, i, ln;
  while (prototype) {
    classCls = prototype.hasOwnProperty('classCls') ? prototype.classCls : null;
    if (classCls) {
      if (classCls instanceof Array) {
        for (i = 0, ln = classCls.length; i < ln; i++) {
          (classes || (classes = [])).push(classCls[i]);
        }
      } else {
        (classes || (classes = [])).push(classCls);
      }
    }
    if (prototype.classClsRoot && prototype.hasOwnProperty('classClsRoot')) {
      break;
    }
    prototype = prototype.superclass;
  }
  if (classes) {
    proto.classClsList = classes;
  }
  return classes;
}, hide:function() {
  this.setHidden(true);
}, initElement:function() {
  var me = this, prototype = me.self.prototype, id = me.getId(), referenceList = me.referenceList = me.referenceList = [], isFirstInstance = !prototype.hasOwnProperty('renderTemplate'), uiReferences = prototype.hasOwnProperty('uiReferences') ? prototype.uiReferences : prototype.uiReferences = {element:''}, renderTemplate, renderElement, renderConfig, element, referenceNodes, i, ln, referenceNode, reference, classCls, uiCls, baseCls, referenceElement;
  if (isFirstInstance) {
    renderTemplate = document.createDocumentFragment();
    renderConfig = me.processElementConfig.call(prototype);
    renderElement = Ext.Element.create(renderConfig, true);
    renderTemplate.appendChild(renderElement);
    referenceNodes = renderTemplate.querySelectorAll('[uiCls]');
    for (i = 0, ln = referenceNodes.length; i < ln; i++) {
      referenceNode = referenceNodes[i];
      reference = referenceNode.getAttribute('reference');
      uiCls = referenceNode.getAttribute('uiCls');
      if (!reference) {
        Ext.raise('Cannot render element with uiCls\x3d"' + uiCls + '". uiCls is only allowed on elements that have a reference name.');
      }
      uiReferences[reference] = uiCls;
      referenceNode.removeAttribute('uiCls');
    }
  } else {
    renderTemplate = me.renderTemplate.cloneNode(true);
    renderElement = renderTemplate.firstChild;
  }
  referenceNodes = renderTemplate.querySelectorAll('[reference]');
  for (i = 0, ln = referenceNodes.length; i < ln; i++) {
    referenceNode = referenceNodes[i];
    reference = referenceNode.getAttribute('reference');
    if (!isFirstInstance) {
      referenceNode.removeAttribute('reference');
    }
    if (reference === 'element') {
      if (element) {
        Ext.raise("Duplicate 'element' reference detected in '" + me.$className + "' template.");
      }
      referenceNode.id = id;
      element = me.el = me.addElementReference(reference, referenceNode);
      element.dom.setAttribute('data-componentid', id);
      if (isFirstInstance) {
        classCls = me.getClassCls();
        if (classCls) {
          element.addCls(classCls);
        }
        baseCls = me.baseCls;
        if (baseCls && baseCls !== me.classCls) {
          element.addCls(baseCls);
        }
      }
    } else {
      uiCls = uiReferences[reference];
      if (uiCls && isFirstInstance) {
        referenceElement = me.addElementReference(reference, referenceNode);
        me.initUiReference(reference, uiCls, false);
      } else {
        me.addElementReferenceOnDemand(reference, referenceNode);
      }
    }
    if (reference === me.focusEl) {
      me.addElementReference('focusEl', referenceNode);
    }
    if (reference === me.ariaEl) {
      me.addElementReferenceOnDemand('ariaEl', referenceNode);
    }
    referenceList.push(reference);
  }
  if (!element) {
    Ext.raise("No 'element' reference found in '" + me.$className + "' template.");
  }
  if (renderElement === element.dom) {
    me.renderElement = element;
  } else {
    me.addElementReferenceOnDemand('renderElement', renderElement);
  }
  renderElement.setAttribute(me.dataXid, me.$iid);
}, dataXid:'data-' + Ext.baseCSSPrefix.substr(0, Ext.baseCSSPrefix.length - 1) + 'id', is:function(selector) {
  return Ext.ComponentQuery.is(this, selector);
}, isHidden:function(deep) {
  var hidden = !!this.getHidden(), owner;
  if (!hidden && deep) {
    owner = this.getRefOwner();
    while (owner && owner !== deep && !hidden) {
      hidden = !!owner.getHidden();
      owner = owner.getRefOwner();
    }
  }
  return hidden;
}, isVisible:function(deep) {
  return this.rendered && !this.destroyed && !this.isHidden(deep);
}, isXType:function(xtype, shallow) {
  return shallow ? Ext.Array.indexOf(this.xtypes, xtype) !== -1 : !!this.xtypesMap[xtype];
}, lookupTpl:function(name) {
  return Ext.XTemplate.getTpl(this, name);
}, owns:function(element) {
  var result = false, cmp;
  if (element.isEvent) {
    element = element.target;
  } else {
    if (element.isElement) {
      element = element.dom;
    }
  }
  cmp = Ext.Component.from(element);
  if (cmp) {
    result = cmp === this || !!cmp.up(this);
  }
  return result;
}, render:function(container, insertBeforeElement) {
  if (container && container.isWidget) {
    container = container.el;
  }
  var dom = this.renderElement.dom, containerDom = Ext.getDom(container), insertBeforeChildDom;
  if (Ext.isNumber(insertBeforeChildDom)) {
    insertBeforeElement = containerDom.childNodes[insertBeforeElement];
  }
  insertBeforeChildDom = Ext.getDom(insertBeforeElement);
  if (containerDom) {
    if (insertBeforeChildDom) {
      containerDom.insertBefore(dom, insertBeforeChildDom);
    } else {
      containerDom.appendChild(dom);
    }
    this.setRendered(Ext.getBody().contains(dom), true);
  }
}, toggleCls:function(className, state) {
  this.element.toggleCls(className, state);
  return this;
}, resolveListenerScope:function(defaultScope, skipThis) {
  return this.mixins.inheritable.resolveListenerScope.call(this, defaultScope, skipThis);
}, setSize:function(width, height) {
  if (width && typeof width === 'object') {
    return this.setSize(width.width, width.height);
  }
  if (width !== undefined) {
    this.setWidth(width);
  }
  if (height !== undefined) {
    this.setHeight(height);
  }
}, show:function() {
  this.setHidden(false);
}, addCls:function(cls, prefix, suffix) {
  if (!this.destroyed) {
    this.el.replaceCls(null, cls, prefix, suffix);
  }
}, applyCls:function(cls) {
  return cls && Ext.dom.Element.splitCls(cls);
}, applyUi:function(ui) {
  return this.parseUi(ui, true);
}, removeCls:function(cls, prefix, suffix) {
  if (!this.destroyed) {
    this.el.replaceCls(cls, null, prefix, suffix);
  }
}, replaceCls:function(oldCls, newCls, prefix, suffix) {
  if (!this.destroyed) {
    this.el.replaceCls(oldCls, newCls, prefix, suffix);
  }
}, hasCls:function(className) {
  return this.el.hasCls(className);
}, updateCls:function(newCls, oldCls) {
  this.element.replaceCls(oldCls, newCls);
}, updateHidden:function(hidden) {
  var me = this, element = me.renderElement, container = me.ownerFocusableContainer;
  if (container) {
    if (hidden) {
      if (!container.beforeFocusableChildHide.$nullFn) {
        container.beforeFocusableChildHide(me);
      }
    } else {
      if (!container.beforeFocusableChildShow.$nullFn) {
        container.beforeFocusableChildShow(me);
      }
    }
  } else {
    if (hidden) {
      me.revertFocus();
    }
  }
  if (element && !element.destroyed) {
    if (hidden) {
      element.hide();
    } else {
      element.show();
    }
  }
  if (me.focusableContainer && me.activateFocusableContainer) {
    me.activateFocusableContainer(!hidden);
  }
  if (container) {
    if (hidden) {
      if (!container.onFocusableChildHide.$nullFn) {
        container.onFocusableChildHide(me);
      }
    } else {
      if (!container.onFocusableChildShow.$nullFn) {
        container.onFocusableChildShow(me);
      }
    }
  }
}, updateMargin:function(margin) {
  this.element.setMargin(margin);
}, updateRipple:function(ripple) {
  var me = this, el = me.el;
  if (el) {
    el.un('touchstart', 'onRippleStart', me);
    el.un('touchend', 'onRippleStart', me);
    el.destroyAllRipples();
    if (ripple.release) {
      el.on('touchend', 'onRippleStart', me);
    } else {
      el.on('touchstart', 'onRippleStart', me);
    }
  }
}, shouldRipple:function(e) {
  var me = this, disabled = me.getDisabled && me.getDisabled(), el = me.el, ripple = !disabled && me.getRipple(), target;
  if (ripple && e) {
    target = e.getTarget(me.noRippleSelector);
    if (target) {
      if (el.dom === target || el.contains(target)) {
        ripple = null;
      }
    }
  }
  return ripple;
}, onRippleStart:function(e) {
  var ripple = this.shouldRipple(e);
  if (e.button === 0 && ripple) {
    this.el.ripple(e, ripple);
  }
}, applyStyle:function(style, oldStyle) {
  if (oldStyle && style === oldStyle && Ext.isObject(oldStyle)) {
    style = Ext.apply({}, style);
  }
  this.element.applyStyles(style);
  return null;
}, getStyle:function() {
  Ext.Error.raise("'style' is a write-only config. To query element styles use " + 'the Ext.dom.Element API.');
}, updateRenderTo:function(newContainer) {
  this.render(newContainer);
}, updateTouchAction:function(touchAction) {
  var name, childEl, value, hasRootActions;
  for (name in touchAction) {
    childEl = this[name];
    value = touchAction[name];
    if (childEl && childEl.isElement) {
      childEl.setTouchAction(value);
    } else {
      hasRootActions = true;
    }
  }
  if (hasRootActions) {
    this.el.setTouchAction(touchAction);
  }
}, updateUi:function() {
  if (!this.isConfiguring) {
    this.syncUiCls();
  }
}, updateWidth:function(width) {
  var el = this.el;
  el.setWidth(width);
  el.toggleCls(this.widthedCls, width != null && width !== 'auto');
}, updateHeight:function(height) {
  var el = this.el;
  el.setHeight(height);
  el.toggleCls(this.heightedCls, height != null && height !== 'auto');
}, isWidthed:function() {
  var width = this.getWidth();
  return width != null && width !== 'auto';
}, isHeighted:function() {
  var height = this.getHeight();
  return height != null && height !== 'auto';
}, up:function(selector, limit) {
  var result = this.getRefOwner(), limitSelector = typeof limit === 'string', limitCount = typeof limit === 'number', limitComponent = limit && limit.isComponent, steps = 0;
  if (selector) {
    for (; result; result = result.getRefOwner()) {
      if (result.destroyed) {
        return null;
      }
      steps++;
      if (selector.isComponent || selector.isWidget) {
        if (result === selector) {
          return result;
        }
      } else {
        if (Ext.ComponentQuery.is(result, selector)) {
          return result;
        }
      }
      if (limitSelector && result.is(limit)) {
        return;
      }
      if (limitCount && steps === limit) {
        return;
      }
      if (limitComponent && result === limit) {
        return;
      }
    }
  }
  return result;
}, updateLayout:Ext.emptyFn, updateInstanceCls:function(instanceCls, oldInstanceCls) {
  var me = this, el = me.el, classClsList = me.classClsList, Array = Ext.Array, uiReferences = me.uiReferences, referenceName, referenceElement, i, ln, cls, uiCls;
  if (oldInstanceCls) {
    el.removeCls(oldInstanceCls);
    oldInstanceCls = Array.from(oldInstanceCls);
    for (i = 0, ln = oldInstanceCls.length; i < ln; i++) {
      cls = oldInstanceCls[i];
      Array.remove(classClsList, cls);
      for (referenceName in uiReferences) {
        referenceElement = me[referenceName];
        uiCls = uiReferences[referenceName];
        referenceElement.removeCls(cls + '-' + uiCls);
      }
    }
  }
  if (instanceCls) {
    el.addCls(instanceCls);
    instanceCls = Array.from(instanceCls);
    me.classClsList = classClsList.concat(instanceCls);
    for (i = 0, ln = instanceCls.length; i < ln; i++) {
      cls = instanceCls[i];
      for (referenceName in uiReferences) {
        referenceElement = me[referenceName];
        uiCls = uiReferences[referenceName];
        referenceElement.addCls(cls + '-' + uiCls);
      }
    }
  }
  if (!me.isConfiguring) {
    me.syncUiCls();
  }
}, getBaseCls:function() {
  return this.baseCls;
}, setBaseCls:function() {
  Ext.raise('baseCls cannot be reconfigured. It must be specified at class definition time.');
}, onClassExtended:function(Class, members) {
  if (members.config && members.config.baseCls) {
    Ext.raise('baseCls must be declared directly on the class body. Please move it ' + 'outside of the config block.');
  }
}, privates:{_hideModes:{clip:'CLIP', display:'DISPLAY', offsets:'OFFSETS', opacity:'OPACITY', visibility:'VISIBILITY'}, noRippleSelector:'.' + Ext.baseCSSPrefix + 'no-ripple', addElementReferenceOnDemand:function(name, domNode) {
  if (this._elementListeners[name]) {
    this.addElementReference(name, domNode);
  } else {
    Ext.Object.defineProperty(this, name, {get:function() {
      if (this.destroyed) {
        return null;
      }
      delete this[name];
      return this.addElementReference(name, domNode);
    }, configurable:true});
  }
}, addElementReference:function(name, domNode) {
  var me = this, referenceEl = me[name] = Ext.get(domNode), listeners = me._elementListeners[name], eventName, listener;
  referenceEl.skipGarbageCollection = true;
  referenceEl.component = me;
  if (listeners) {
    listeners = Ext.clone(listeners);
    for (eventName in listeners) {
      listener = listeners[eventName];
      if (typeof listener === 'object') {
        listener.scope = me;
      }
    }
    listeners.scope = me;
    referenceEl.on(listeners);
  }
  return referenceEl;
}, detachFromBody:function() {
  Ext.getDetachedBody().appendChild(this.element, true);
  this.isDetached = true;
}, reattachToBody:function() {
  var detachedBody;
  if (this.isDetached) {
    detachedBody = Ext.getDetachedBody();
    if (detachedBody.contains(this.element)) {
      Ext.getBody().appendChild(this.element, true);
    }
  }
  this.isDetached = false;
}, doAddListener:function(name, fn, scope, options, order, caller, manager) {
  var me = this, elementName = options && options.element, delegate = options && options.delegate, listeners, eventOptions, option;
  if (elementName) {
    if (Ext.Array.indexOf(me.referenceList, elementName) === -1) {
      Ext.Logger.error("Adding event listener with an invalid element reference of '" + elementName + "' for this component. Available values are: '" + me.referenceList.join("', '") + "'", me);
    }
    listeners = {};
    listeners[name] = fn;
    if (scope) {
      listeners.scope = scope;
    }
    eventOptions = Ext.Element.prototype.$eventOptions;
    for (option in options) {
      if (eventOptions[option]) {
        listeners[option] = options[option];
      }
    }
    me.mon(me[elementName], listeners);
    return;
  } else {
    if (delegate) {
      me.mixins.componentDelegation.addDelegatedListener.call(me, name, fn, scope, options, order, caller, manager);
      return;
    }
  }
  me.callParent([name, fn, scope, options, order, caller, manager]);
}, doRemoveListener:function(eventName, fn, scope) {
  var me = this;
  me.mixins.observable.doRemoveListener.call(me, eventName, fn, scope);
  me.mixins.componentDelegation.removeDelegatedListener.call(me, eventName, fn, scope);
}, filterLengthValue:function(value) {
  if (!value && value !== 0) {
    return null;
  }
  return value;
}, hasHiddenContent:function() {
  return this.getHidden();
}, initElementListeners:function(elementConfig) {
  var prototype = this, superPrototype = prototype.self.superclass, superElementListeners = superPrototype._elementListeners, reference = elementConfig.reference, children = elementConfig.children, elementListeners, listeners, superListeners, ln, i;
  if (prototype.hasOwnProperty('_elementListeners')) {
    elementListeners = prototype._elementListeners;
  } else {
    elementListeners = prototype._elementListeners = superElementListeners ? Ext.Object.chain(superElementListeners) : {};
  }
  if (reference) {
    listeners = elementConfig.listeners;
    if (listeners) {
      if (superElementListeners) {
        superListeners = superElementListeners[reference];
        if (superListeners) {
          listeners = Ext.Object.chain(superListeners);
          Ext.apply(listeners, elementConfig.listeners);
        }
      }
      elementListeners[reference] = listeners;
      elementConfig.listeners = null;
    }
  }
  if (children) {
    for (i = 0, ln = children.length; i < ln; i++) {
      prototype.initElementListeners(children[i]);
    }
  }
}, initId:function(config) {
  var me = this, defaultConfig = me.config, id = config && config.id || defaultConfig && defaultConfig.id;
  if (id) {
    me.setId(id);
    me.id = id;
  } else {
    me.getId();
  }
}, measure:function(dimension) {
  return this.element.measure(dimension);
}, processElementConfig:function() {
  var prototype = this, superPrototype = prototype.self.superclass, elementConfig;
  if (prototype.hasOwnProperty('_elementConfig')) {
    elementConfig = prototype._elementConfig;
  } else {
    elementConfig = prototype._elementConfig = prototype.getElementConfig();
    if (superPrototype.isWidget) {
      prototype.processElementConfig.call(superPrototype);
    }
    prototype.initElementListeners(elementConfig);
  }
  return elementConfig;
}, parseUi:function(ui, asString) {
  ui = Ext.String.splitWords(ui);
  if (asString) {
    ui = ui.join(' ');
  }
  return ui;
}, addUi:function(ui) {
  this.setUi(this.doAddUi(ui, this.getUi()));
}, doAddUi:function(ui, oldUi) {
  var me = this, newUi = null, i, u, len;
  if (ui) {
    ui = me.parseUi(ui);
    len = ui.length;
    oldUi = me.parseUi(oldUi);
    for (i = 0; i < len; i++) {
      u = ui[i];
      if (Ext.Array.indexOf(oldUi, u) === -1) {
        oldUi.push(u);
      }
    }
    newUi = oldUi.join(' ');
  }
  return newUi;
}, removeUi:function(ui) {
  this.setUi(this.doRemoveUi(ui, this.getUi()));
}, doRemoveUi:function(ui, oldUi) {
  var me = this, newUi = null, i, u, index, len;
  if (ui) {
    ui = me.parseUi(ui);
    len = ui.length;
    oldUi = me.parseUi(oldUi);
    for (i = 0; i < len; i++) {
      u = ui[i];
      index = Ext.Array.indexOf(oldUi, u);
      if (index !== -1) {
        oldUi.splice(index, 1);
      }
    }
    newUi = oldUi.join(' ');
  }
  return newUi;
}, initUiReference:function(referenceName, uiCls, isInstance) {
  var me = this, referenceElement = me[referenceName], baseCls = me.baseCls, classClsList = me.classClsList, cls = [], i, n;
  isInstance = isInstance !== false;
  if (isInstance) {
    if (!me.hasOwnProperty('uiReferences')) {
      me.uiReferences = Ext.clone(me.uiReferences);
    }
    me.uiReferences[referenceName] = uiCls;
  }
  uiCls = '-' + uiCls;
  if (baseCls && baseCls !== me.classCls) {
    cls.push(baseCls + uiCls);
  }
  if (classClsList) {
    for (i = 0, n = classClsList.length; i < n; i++) {
      cls.push(classClsList[i] + uiCls);
    }
  }
  referenceElement.addCls(cls);
  if (isInstance && !me.isConfiguring) {
    me.syncUiCls();
  }
}, syncUiCls:function(refs) {
  var me = this, ui = me.getUi(), currentUiCls = me.currentUiCls || (me.currentUiCls = {}), baseCls = me.baseCls, uiReferences = refs || me.uiReferences, classClsList = me.classClsList, classClsListLen = classClsList ? classClsList.length : 0, uiCls, uiLen, refName, refEl, cls, suffix, uiSuffix, i, j;
  if (ui) {
    ui = me.parseUi(ui);
    uiLen = ui.length;
  }
  for (refName in uiReferences) {
    refEl = me[refName];
    uiCls = [];
    if (refEl) {
      cls = currentUiCls[refName];
      if (cls) {
        refEl.removeCls(cls);
      }
      if (ui) {
        suffix = uiReferences[refName];
        suffix = suffix ? '-' + suffix : '';
        for (i = 0; i < uiLen; i++) {
          uiSuffix = '-' + ui[i] + suffix;
          if (baseCls && baseCls !== me.classCls) {
            uiCls.push(baseCls + uiSuffix);
          }
          if (classClsList) {
            for (j = 0; j < classClsListLen; j++) {
              uiCls.push(classClsList[j] + uiSuffix);
            }
          }
        }
        refEl.addCls(uiCls);
        currentUiCls[refName] = uiCls;
      }
    }
  }
}, applyHideMode:function(mode) {
  return mode || 'display';
}, updateHideMode:function(mode) {
  var me = this, el = me.el, shouldToggle = me.getHidden();
  if (!me._hideModes[mode]) {
    Ext.raise('Invalid hideMode: "' + mode + '" (must be one of: "' + Object.keys(me._hideModes).join('", "') + '")');
  }
  if (shouldToggle) {
    el.show();
  }
  me.renderElement.setVisibilityMode(Ext.Element[me._hideModes[mode]]);
  if (shouldToggle) {
    el.hide();
  }
}, updateUserCls:function(newCls, oldCls) {
  this.element.replaceCls(oldCls, newCls);
}}}, function(Widget) {
  var prototype = Widget.prototype;
  (prototype.$elementEventOptions = Ext.Object.chain(Ext.Element.prototype.$eventOptions)).element = 1;
  (prototype.$eventOptions = Ext.Object.chain(prototype.$eventOptions)).delegate = 1;
  Ext.updateWidget = Ext.Factory.widget.update;
});
Ext.define('Ext.mixin.Traversable', {extend:Ext.Mixin, mixinConfig:{id:'traversable'}, setParent:function(parent) {
  this.parent = parent;
  return this;
}, hasParent:function() {
  return Boolean(this.getParent());
}, is:function() {
  return true;
}, getParent:function() {
  return this.parent || this.$initParent;
}, getAncestors:function() {
  var ancestors = [], parent = this.getParent();
  while (parent) {
    ancestors.push(parent);
    parent = parent.getParent();
  }
  return ancestors;
}, getAncestorIds:function() {
  var ancestorIds = [], parent = this.getParent();
  while (parent) {
    ancestorIds.push(parent.getId());
    parent = parent.getParent();
  }
  return ancestorIds;
}, previousNode:function(selector, includeSelf) {
  var node = this, parent = node.getRefOwner(), result, it, i, sibling;
  if (includeSelf && node.is(selector)) {
    return node;
  }
  if (parent) {
    for (it = parent.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
      sibling = it[i];
      if (sibling.query) {
        result = sibling.query(selector);
        result = result[result.length - 1];
        if (result) {
          return result;
        }
      }
      if (!selector || sibling.is(selector)) {
        return sibling;
      }
    }
    return parent.previousNode(selector, true);
  }
  return null;
}, previousSibling:function(selector) {
  var parent = this.getRefOwner(), it, idx, sibling;
  if (parent) {
    it = parent.items;
    idx = it.indexOf(this);
    if (idx !== -1) {
      if (selector) {
        for (--idx; idx >= 0; idx--) {
          if ((sibling = it.getAt(idx)).is(selector)) {
            return sibling;
          }
        }
      } else {
        if (idx) {
          return it.getAt(--idx);
        }
      }
    }
  }
  return null;
}, nextNode:function(selector, includeSelf) {
  var node = this, parent = node.getRefOwner(), result, it, len, i, sibling;
  if (includeSelf && node.is(selector)) {
    return node;
  }
  if (parent) {
    for (it = parent.items.items, i = Ext.Array.indexOf(it, node) + 1, len = it.length; i < len; i++) {
      sibling = it[i];
      if (!selector || sibling.is(selector)) {
        return sibling;
      }
      if (sibling.down) {
        result = sibling.down(selector);
        if (result) {
          return result;
        }
      }
    }
    return parent.nextNode(selector);
  }
  return null;
}, nextSibling:function(selector) {
  var parent = this.getRefOwner(), it, last, idx, sibling;
  if (parent) {
    it = parent.items;
    idx = it.indexOf(this) + 1;
    if (idx) {
      if (selector) {
        for (last = it.getCount(); idx < last; idx++) {
          if ((sibling = it.getAt(idx)).is(selector)) {
            return sibling;
          }
        }
      } else {
        if (idx < it.getCount()) {
          return it.getAt(idx);
        }
      }
    }
  }
  return null;
}});
Ext.define('Ext.fx.easing.Abstract', {config:{startTime:0, startValue:0}, isEasing:true, isEnded:false, constructor:function(config) {
  this.initConfig(config);
  return this;
}, applyStartTime:function(startTime) {
  if (!startTime) {
    startTime = Ext.Date.now();
  }
  return startTime;
}, updateStartTime:function(startTime) {
  this.reset();
}, reset:function() {
  this.isEnded = false;
}, getValue:Ext.emptyFn});
Ext.define('Ext.fx.easing.Linear', {extend:Ext.fx.easing.Abstract, alias:'easing.linear', config:{duration:0, endValue:0}, updateStartValue:function(startValue) {
  this.distance = this.getEndValue() - startValue;
}, updateEndValue:function(endValue) {
  this.distance = endValue - this.getStartValue();
}, getValue:function() {
  var deltaTime = Ext.Date.now() - this.getStartTime(), duration = this.getDuration();
  if (deltaTime > duration) {
    this.isEnded = true;
    return this.getEndValue();
  } else {
    return this.getStartValue() + deltaTime / duration * this.distance;
  }
}});
Ext.define('Ext.util.translatable.Abstract', {extend:Ext.Evented, mixins:[Ext.mixin.Factoryable], factoryConfig:{type:'translatable', defaultType:'csstransform'}, config:{easing:null, easingX:{duration:300}, easingY:{duration:300}, offsetX:0, offsetY:0}, x:0, y:0, activeEasingX:null, activeEasingY:null, isAnimating:false, isTranslatable:true, constructor:function(config) {
  this.callParent([config]);
  this.position = {x:0, y:0};
}, factoryEasing:function(easing) {
  return Ext.factory(easing, Ext.fx.easing.Linear, null, 'easing');
}, applyEasing:function(easing) {
  if (!this.getEasingX()) {
    this.setEasingX(this.factoryEasing(easing));
  }
  if (!this.getEasingY()) {
    this.setEasingY(this.factoryEasing(easing));
  }
}, applyEasingX:function(easing) {
  return this.factoryEasing(easing);
}, applyEasingY:function(easing) {
  return this.factoryEasing(easing);
}, updateOffsetX:function() {
  var me = this;
  if (!me.isConfiguring && !me.isAnimating) {
    me.translateXY(me.x, me.y);
  }
}, updateOffsetY:function() {
  var me = this;
  if (!me.isConfiguring && !me.isAnimating) {
    me.translateXY(me.x, me.y);
  }
}, translate:function(x, y, animation) {
  var me = this;
  if (animation) {
    return me.translateAnimated(x, y, animation);
  }
  if (me.isAnimating) {
    me.stopAnimation();
  }
  if (!isNaN(x) && typeof x === 'number') {
    me.x = x;
  } else {
    x = me.x;
  }
  if (!isNaN(y) && typeof y === 'number') {
    me.y = y;
  } else {
    y = me.y;
  }
  me.translateXY(x, y);
}, translateXY:function(x, y) {
  var me = this;
  if (!me.destroyed) {
    me.doTranslate(x + me.getOffsetX(), y + me.getOffsetY());
    if (me.hasListeners.translate) {
      me.fireEvent('translate', me, x, y);
    }
  }
}, translateAxis:function(axis, value, animation) {
  var x, y;
  if (axis === 'x') {
    x = value;
  } else {
    y = value;
  }
  return this.translate(x, y, animation);
}, getPosition:function() {
  var me = this, position = me.position;
  position.x = -me.x;
  position.y = -me.y;
  return position;
}, animate:function(easingX, easingY) {
  var me = this;
  me.activeEasingX = easingX;
  me.activeEasingY = easingY;
  me.isAnimating = true;
  if (me.ownerCmp) {
    me.ownerCmp.isTranslating = true;
  }
  me.lastX = null;
  me.lastY = null;
  Ext.AnimationQueue.start(me.doAnimationFrame, me);
  me.fireEvent('animationstart', me, me.x, me.y);
  return me;
}, translateAnimated:function(x, y, animation) {
  var me = this, now, easing, easingX, easingY;
  if (!Ext.isObject(animation)) {
    animation = {};
  }
  if (me.isAnimating) {
    me.stopAnimation();
  }
  me.callback = animation.callback;
  me.callbackScope = animation.scope;
  now = Ext.Date.now();
  easing = animation.easing;
  easingX = typeof x === 'number' ? animation.easingX || easing || me.getEasingX() || true : null;
  easingY = typeof y === 'number' ? animation.easingY || easing || me.getEasingY() || true : null;
  if (easingX) {
    easingX = me.factoryEasing(easingX);
    easingX.setStartTime(now);
    easingX.setStartValue(me.x);
    easingX.setEndValue(x);
    if ('duration' in animation) {
      easingX.setDuration(animation.duration);
    }
  }
  if (easingY) {
    easingY = me.factoryEasing(easingY);
    easingY.setStartTime(now);
    easingY.setStartValue(me.y);
    easingY.setEndValue(y);
    if ('duration' in animation) {
      easingY.setDuration(animation.duration);
    }
  }
  return me.animate(easingX, easingY);
}, doAnimationFrame:function() {
  var me = this, easingX = me.activeEasingX, easingY = me.activeEasingY, now = Date.now(), x, y;
  if (!me.isAnimating) {
    return;
  }
  me.lastRun = now;
  if (easingX === null && easingY === null) {
    me.stopAnimation();
    return;
  }
  if (easingX !== null) {
    me.x = x = Math.round(easingX.getValue());
    if (easingX.isEnded) {
      me.activeEasingX = null;
      me.fireEvent('axisanimationend', me, 'x', x);
    }
  } else {
    x = me.x;
  }
  if (easingY !== null) {
    me.y = y = Math.round(easingY.getValue());
    if (easingY.isEnded) {
      me.activeEasingY = null;
      me.fireEvent('axisanimationend', me, 'y', y);
    }
  } else {
    y = me.y;
  }
  if (me.lastX !== x || me.lastY !== y) {
    me.translateXY(x, y);
    me.lastX = x;
    me.lastY = y;
  }
  me.fireEvent('animationframe', me, x, y);
}, stopAnimation:function() {
  var me = this;
  if (!me.isAnimating) {
    return;
  }
  me.activeEasingX = null;
  me.activeEasingY = null;
  me.isAnimating = false;
  if (me.ownerCmp) {
    me.ownerCmp.isTranslating = false;
  }
  Ext.AnimationQueue.stop(me.doAnimationFrame, me);
  me.fireEvent('animationend', me, me.x, me.y);
  if (me.callback) {
    me.callback.call(me.callbackScope);
    me.callback = null;
  }
}, refresh:function() {
  this.translate(this.x, this.y);
}, resolveListenerScope:function() {
  var ownerCmp = this.ownerCmp, a = arguments;
  if (ownerCmp) {
    return ownerCmp.resolveListenerScope.apply(ownerCmp, a);
  }
  return this.callParent(a);
}, destroy:function() {
  var me = this;
  me.destroying = true;
  if (me.isAnimating) {
    me.stopAnimation();
  }
  me.callParent();
  me.destroyed = true;
}});
Ext.define('Ext.overrides.Widget', {override:'Ext.Widget', mixins:[Ext.mixin.Traversable], statics:{floatInset:8, onModalMaskTap:function(e) {
  var top = this.topModal;
  if (top && top.onModalMaskTap && top.onModalMaskTap(e)) {
    this.topModal = null;
  }
}, range:document.createRange()}, config:{flex:{evented:true, $value:null}, itemId:undefined, floated:null, relative:null, x:null, y:null, shadow:null, shim:null, alwaysOnTop:null, toFrontOnShow:true, translatable:{lazy:true, $value:null}, constrainAlign:null, alignSelf:null}, inheritUi:false, floatedCls:Ext.baseCSSPrefix + 'floated', floatedSelector:'.' + Ext.baseCSSPrefix + 'floated', shadowCls:Ext.baseCSSPrefix + 'shadow', noShadowCls:Ext.baseCSSPrefix + 'no-shadow', floatWrapCls:Ext.baseCSSPrefix + 
'float-wrap', shimCls:Ext.baseCSSPrefix + 'shim', rootCls:Ext.baseCSSPrefix + 'root', isInner:true, clearPropertiesOnDestroy:'async', beforeHide:Ext.emptyFn, afterHide:function() {
  var me = this, parent = me.getParent();
  if (parent && parent.afterItemHide) {
    parent.afterItemHide(me);
  }
  if (me.getFloated()) {
    me.syncShim();
  }
}, beforeShow:Ext.emptyFn, afterShow:function() {
  var me = this, parent = me.getParent();
  if (parent && parent.afterItemShow) {
    parent.afterItemShow(me);
  }
}, applyItemId:function(itemId) {
  return itemId || this.getId();
}, doDestroy:function() {
  var me = this, parent = me.getParent(), fw = me.floatWrap;
  if (parent && parent.remove) {
    parent.remove(me, false);
  }
  me.setShim(false);
  Ext.destroy(me.getTranslatable());
  if (fw) {
    me.un('resize', 'syncFloatWrap', me);
    fw.destroy();
    me.floatWrap = null;
  }
  me.removeBindings();
  me.callParent();
}, isInnerItem:function() {
  return this.isInner;
}, isCentered:function() {
  return false;
}, isDocked:function() {
  return Boolean(this.getDocked());
}, isPositioned:function() {
  return false;
}, getDocked:function() {
  return this._docked;
}, isHidden:function(deep) {
  var me = this, hidden;
  if (me.isConfiguring) {
    hidden = me.getConfig('hidden', true);
    if (me.getConfig('floated', true)) {
      return hidden !== false;
    } else {
      return !!hidden;
    }
  }
  return me.callParent([deep]);
}, onAdded:function(parent, instanced) {
  var me = this, currentParent = me.parent;
  if (currentParent && currentParent !== parent) {
    currentParent.remove(me, false);
  }
  me.parent = parent;
  me.onInheritedAdd(parent, instanced);
  me.isDetached = false;
  if (me.getFloated()) {
    me.findFloatParent();
  }
  if (me.inheritUi) {
    me.doInheritUi();
  }
}, onRemoved:function(destroying) {
  var me = this;
  if (me.inheritUi && !destroying) {
    me.doUninheritUi();
  }
  me.onInheritedRemove(destroying);
  me.parent = null;
}, setIsInner:function(isInner) {
  var parent;
  if (isInner !== this.isInner) {
    this.isInner = isInner;
    parent = this.initialized && this.getParent();
    if (parent) {
      parent.onItemInnerStateChange(this, isInner);
    }
  }
}, refreshInnerState:function() {
  this.setIsInner(!this.getFloated() && !this.isCentered() && !this.isPositioned() && !this.isDocked());
}, toFront:function(fromMousedown) {
  var me = this, floatParent;
  if (!this.getFloated()) {
    Ext.raise('Cannot use toFront on a non-floated component');
  }
  floatParent = me.getFloatParent();
  if (!me.hasListeners.beforetofront || me.fireEvent('beforetofront', me) !== false) {
    me.syncAlwaysOnTop(fromMousedown);
    if (floatParent && floatParent.getFloated()) {
      floatParent.toFront(fromMousedown);
    }
    if (me.hasListeners.tofront) {
      me.fireEvent('tofront', me);
    }
  }
  return me;
}, applyTranslatable:function(config, translatable) {
  return Ext.Factory.translatable.update(translatable, config, this, 'createTranslatable');
}, createTranslatable:function(config) {
  var me = this, listeners = config.listeners;
  config = Ext.apply({type:'cssposition', ownerCmp:me, element:me.renderElement}, config);
  if (listeners && listeners.scope === 'this') {
    config.listeners = listeners = Ext.apply({}, listeners);
    listeners.scope = me;
  }
  return config;
}, ensureTranslatable:function() {
  var me = this, translatable = me.getTranslatable();
  if (!translatable) {
    me.setTranslatable(true);
    translatable = me.getTranslatable();
  }
  return translatable;
}, translate:function() {
  var translatable = this.ensureTranslatable();
  translatable.translate.apply(translatable, arguments);
}, getAlignmentInfo:function(component, alignment) {
  var me = this, alignToBox = component.isRegion ? component : (component.isWidget ? component.renderElement : Ext.fly(component)).getBox(), element = me.renderElement, box = element.getBox(), stats = {alignToBox:alignToBox, alignment:alignment, top:alignToBox.top, left:alignToBox.left, alignToWidth:alignToBox.width || 0, alignToHeight:alignToBox.height || 0, width:box.width, height:box.height, anchor:!!(me.getAnchor && me.getAnchor())}, currentAlignmentInfo = me.getCurrentAlignmentInfo(), isAligned = 
  true;
  if (!Ext.isEmpty(currentAlignmentInfo)) {
    Ext.Object.each(stats, function(key, value) {
      if (!Ext.isObject(value) && currentAlignmentInfo[key] !== value) {
        isAligned = false;
        return false;
      }
      return true;
    });
  } else {
    isAligned = false;
  }
  return {isAligned:isAligned, stats:stats};
}, getCurrentAlignmentInfo:function() {
  return this.$currentAlignmentInfo;
}, setCurrentAlignmentInfo:function(alignmentInfo) {
  this.$currentAlignmentInfo = Ext.isEmpty(alignmentInfo) ? null : Ext.merge({}, alignmentInfo.stats ? alignmentInfo.stats : alignmentInfo);
}, alignTo:function(component, alignment, options) {
  var me = this, alignmentInfo = me.getAlignmentInfo(component, alignment), config = me.initialConfig, positioned = !me.getFloated(), setX = positioned ? me.setLeft : me.setX, setY = positioned ? me.setTop : me.setY, oldHeight, resultRegion;
  if (alignmentInfo.isAligned) {
    return;
  }
  if ('unconstrainedWidth' in me) {
    me.setWidth(me.unconstrainedWidth);
  }
  if ('unconstrainedHeight' in me) {
    me.setHeight(me.unconstrainedHeight);
  }
  resultRegion = me.getAlignRegion(component, alignment, options);
  setX.call(me, resultRegion.x);
  setY.call(me, resultRegion.y);
  if (resultRegion.constrainWidth) {
    me.unconstrainedWidth = config.width || me.self.prototype.width;
    oldHeight = me.el.getHeight();
    me.setWidth(alignmentInfo.stats.width = resultRegion.getWidth());
    if (resultRegion.align.position === 0) {
      setY.call(me, resultRegion.y + (oldHeight - me.el.getHeight()));
    }
  }
  if (resultRegion.constrainHeight) {
    me.unconstrainedHeight = config.height || me.self.prototype.height;
    me.setHeight(alignmentInfo.stats.height = resultRegion.getHeight());
  }
  me.alignToArgs = [component, alignment, options];
  me.setCurrentAlignmentInfo(alignmentInfo);
}, realign:function(component, alignment, options) {
  var args = this.alignToArgs;
  if (this.isVisible()) {
    this.alignTo.call(this, component || args[0], alignment || args[1], options || args[2]);
  }
}, getAlignRegion:function(component, alignment, options) {
  var me = this, alignmentInfo = me.getAlignmentInfo(component, alignment), constrainModifier, inside, alignToBox, constrainBox, height, width;
  if (alignmentInfo.isAligned) {
    return;
  }
  alignToBox = alignmentInfo.stats.alignToBox;
  constrainBox = me.getConstrainAlignRegion();
  height = alignmentInfo.stats.height;
  width = alignmentInfo.stats.width;
  if (constrainBox && (!alignment || alignment === 'auto')) {
    if (constrainBox.bottom - alignToBox.bottom < height) {
      if (alignToBox.top - constrainBox.top < height) {
        if (alignToBox.left - constrainBox.left < width) {
          alignment = 'l-r?';
        } else {
          alignment = 'r-l?';
        }
      } else {
        alignment = 'b-t?';
      }
    } else {
      alignment = 't-b?';
    }
  }
  constrainModifier = alignment[alignment.length - 1];
  if (constrainModifier === '!') {
    inside = component.isRegion ? component : (component.isWidget ? component.renderElement : Ext.fly(component)).getBox();
    alignment = alignment.substr(0, alignment.length - 1);
  } else {
    inside = constrainBox;
    if (constrainModifier === '?') {
      alignment = alignment.substr(0, alignment.length - 1);
    }
  }
  return me.el.getRegion().alignTo(Ext.apply({target:Ext.util.Region.from(alignmentInfo.stats.alignToBox), align:alignment, inside:inside, minWidth:me.getMinWidth && me.getMinWidth(), minHeight:me.getMinHeight && me.getMinHeight()}, options));
}, render:function(container, insertBeforeElement) {
  if (this.getFloated()) {
    Ext.raise('floated: true components cannot be rendered. ' + 'They render themselves on first show');
    return;
  }
  this.callParent([container, insertBeforeElement]);
}, afterRender:Ext.emptyFn, onRender:Ext.emptyFn, applyFloated:function(floated) {
  return Boolean(floated);
}, updateFloated:function(floated, oldFloated) {
  var me = this, fw = me.floatWrap, modal, sibling;
  if (floated) {
    me.refreshInnerState = Ext.emptyFn;
    if (me.isPositioned()) {
      me.resetPositioned();
    }
    if (me.isDocked()) {
      me.setDocked(false);
    }
    delete me.refreshInnerState;
  } else {
    if (fw) {
      fw.dom.removeChild(me.el.dom);
      me.un('resize', 'syncFloatWrap', me);
      fw.destroy();
      me.floatWrap = null;
      me.setRendered(false);
    }
  }
  me.refreshInnerState();
  me.el.toggleCls(me.floatedCls, floated);
  if (me.hasOwnProperty('_modal')) {
    modal = me.getModal && me.getModal();
    if (modal) {
      me.setModal(false);
      if (floated) {
        Ext.destroy(modal);
        if (me.isVisible()) {
          me.showModalMask();
        }
      } else {
        sibling = me.getModalSibling();
        if (sibling) {
          sibling.showModalMask();
        } else {
          me.hideModalMask();
        }
      }
      me.setModal(true);
    }
    if (me.getHideOnMaskTap && me.getHideOnMaskTap()) {
      me.setHideOnMaskTap(false);
      me.setHideOnMaskTap(true);
    }
  }
  me.syncFloatedState(floated, oldFloated, me.rendered && oldFloated === false);
}, applyUi:function(ui) {
  var me = this, inheritedUi = me._inheritedUi;
  ui = me.callParent([ui]);
  if (inheritedUi) {
    ui = me.doAddUi(inheritedUi, ui);
  }
  return ui;
}, updateUi:function(ui, oldUi) {
  var me = this, item, refItems, i, n;
  me.callParent([ui, oldUi]);
  if (me.$inheritUiCount && !me.destroying) {
    refItems = me.getRefItems();
    for (i = 0, n = refItems.length; i < n; i++) {
      item = refItems[i];
      if (item.inheritUi) {
        item.doUninheritUi();
        item.doInheritUi();
      }
    }
  }
}, updateHidden:function(hidden, oldHidden) {
  var globals = Ext.GlobalEvents, event = hidden ? 'hide' : 'show';
  this.callParent([hidden, oldHidden]);
  if (!this.isConfiguring && globals.hasListeners[event]) {
    globals.fireEvent(event, this);
  }
}, updateAlignSelf:function(align) {
  this.el.setStyle({'align-self':align});
}, privates:{setRendered:function(rendered, root) {
  var me = this, afterRenderQueue, item, items, ln, i;
  if (!rendered && me.rendered && me.getFloated()) {
    me.floatWrap.dom.parentNode.removeChild(me.floatWrap.dom);
  }
  me.rendered = rendered;
  if (!me.destroying && !me.destroyed) {
    if (rendered && me.onRender) {
      me.initBindable();
      me.initKeyMap();
      if (!me.onRender.$nullFn) {
        me.onRender();
      }
      me.onRender = null;
      if (!me.afterRender.$nullFn) {
        (Ext._afterRenderQueue || (Ext._afterRenderQueue = [])).push(me);
      }
    }
    items = me.getRefItems && me.getRefItems();
    ln = items && items.length;
    for (i = 0; i < ln; i++) {
      item = items[i];
      if (item.setRendered) {
        me.setChildRendered(rendered, item);
      }
    }
    if (me.focusableContainer && me.initFocusableContainer) {
      me.initFocusableContainer();
    }
    if (root) {
      afterRenderQueue = Ext._afterRenderQueue;
      if (afterRenderQueue) {
        while (afterRenderQueue.length) {
          item = afterRenderQueue.pop();
          if (!item.destroyed) {
            item.afterRender();
          }
        }
      }
    }
  }
}, setChildRendered:function(rendered, item) {
  if (!rendered || !item.getFloated()) {
    item.setRendered(rendered);
  }
}, hideFromModal:function() {
  this.hide();
}, owns:function(element) {
  var result = false, cmp;
  if (element.isEvent) {
    element = element.target;
  } else {
    if (element.isElement) {
      element = element.dom;
    }
  }
  cmp = Ext.Component.from(element);
  if (cmp) {
    result = cmp === this || !!cmp.up(this);
  }
  return result;
}, doInheritUi:function() {
  var me = this, owner, ownerUi;
  if (me.inheritUi) {
    me._ownUi = me.getUi();
    owner = me.getRefOwner();
    ownerUi = owner.getUi();
    if (ownerUi) {
      me.addUi(ownerUi);
      me._inheritedUi = ownerUi;
    }
    owner.$inheritUiCount = (owner.$inheritUiCount || 0) + 1;
  }
}, doUninheritUi:function() {
  var me = this, inheritUi = me.inheritUi, ownUi, owner;
  if (inheritUi) {
    owner = me.getRefOwner();
    ownUi = me._ownUi;
    me._ownUi = null;
    me._inheritedUi = null;
    me.setUi(ownUi || null);
    if (owner.$inheritUiCount) {
      --owner.$inheritUiCount;
    }
  }
}, getBubbleTarget:function() {
  return this.getParent();
}, getConstrainAlignRegion:function() {
  var me = this, isFloated = me.getFloated(), constrainAlign = me.getConstrainAlign(), parent, isViewport, docInsets;
  if (constrainAlign !== false) {
    if (typeof constrainAlign === 'string') {
      constrainAlign = parent = me.up(constrainAlign);
    }
    if (me.floatParentNode.destroyed && !me.destroyed) {
      me.findFloatParent();
    }
    if (!constrainAlign) {
      parent = isFloated ? me.floatParentNode.getData().component : me.getParent();
    }
    if (parent) {
      if (parent.getFloated() && !parent.getRelative()) {
        constrainAlign = Ext.getBody();
        isViewport = true;
      } else {
        constrainAlign = parent.getRenderTarget ? parent.getRenderTarget() : parent.bodyElement || parent.element;
        isViewport = parent.isViewport;
      }
    } else {
      if (!constrainAlign) {
        if (isFloated) {
          isViewport = true;
          constrainAlign = Ext.getBody();
        } else {
          constrainAlign = me.element.parent();
        }
      }
    }
    if (!constrainAlign.isRegion) {
      constrainAlign = Ext.fly(constrainAlign).getConstrainRegion();
      if (isViewport) {
        docInsets = Math.round(Ext.Widget.floatInset);
        constrainAlign.adjust(docInsets, -docInsets, -docInsets, docInsets);
      }
    }
    return constrainAlign;
  }
}, getFloatParent:function() {
  var result = this.floatParentNode.getData().component;
  return result && result.getFloated() ? result : null;
}, syncFloatedState:function(floated, oldFloated, rendered) {
  var me = this, isHidden = me.isHidden();
  if (floated) {
    if (rendered) {
      if (me.isCentered()) {
        me.getWidth();
        me.getHeight();
        me.center();
      } else {
        me.syncXYPosition();
      }
      if (!isHidden) {
        me.showModalMask();
      }
    } else {
      if (!isHidden) {
        me.findFloatParent();
      } else {
        me.setHidden(true);
      }
    }
  } else {
    me.translate(0, 0, 0);
  }
}, findFloatParent:function(needsShow) {
  var me = this, parent = me.getRefOwner();
  while (parent && !parent.getFloated()) {
    parent = parent.getRefOwner();
  }
  if (!parent) {
    me.floatParentNode = Ext.getFloatRoot();
  } else {
    me.floatParentNode = parent.getFloatWrap();
  }
  me.insertFloatedDom(needsShow);
}, getFloatWrap:function() {
  var me = this, fw = me.floatWrap;
  if (!fw) {
    me.floatWrap = fw = Ext.get(Ext.DomHelper.createDom({cls:me.floatWrapCls, id:me.id + '-floatWrap', 'data-componentId':me.id}));
    me.on('resize', 'syncFloatWrap', me);
    fw.getData().component = me;
    if (me.isContainer && (!me.isWidthed() || !me.isHeighted())) {
      me.setAutoSize(true);
    }
    fw.dom.appendChild(me.element.dom);
    fw.getData().alwaysOnTop = me.element.getData().alwaysOnTop;
    me.syncFloatWrap();
  }
  return fw;
}, applyRenderTo:function(renderTo) {
  if (renderTo && this.getFloated()) {
    Ext.raise('floated: true components cannot be rendered. ' + 'They render themselves on first show');
    return;
  }
  return renderTo;
}, syncFloatWrap:function() {
  var me = this, floatWrap = me.floatWrap, mySize = me.el.getSize(), mask;
  if (me.getRelative()) {
    floatWrap.setSize(mySize);
  } else {
    mask = floatWrap.getData().modalMask;
    if (mask) {
      mask.setSize(mySize);
    }
  }
}, insertFloatedDom:function(needsShow) {
  var me = this, fw = me.getFloatWrap(), floatParentNode = me.floatParentNode;
  if (fw.dom.parentNode !== floatParentNode.dom) {
    floatParentNode.dom.appendChild(me.getFloatWrap().dom);
    if (needsShow) {
      me.setVisibility(true);
      me._hidden = false;
    }
    me.setRendered(true, true);
    me.syncXYPosition();
  }
}, applyShim:function(shim) {
  if (shim && !this.getFloated()) {
    Ext.raise('Cannot use setShim on a non-floated component');
  }
  if (shim) {
    return Ext.getBody().createChild(Ext.apply({cls:this.shimCls}, shim));
  } else {
    Ext.destroy(this.shim);
    return null;
  }
}, updateShim:function(shim, oldShim) {
  var me = this;
  if (shim) {
    me.syncShim();
    if (!oldShim) {
      me.on('resize', 'syncShim', me);
    }
  } else {
    if (oldShim) {
      me.un('resize', 'syncShim', me);
    }
  }
}, hideModalMask:function() {
  var me = this, floatRoot = Ext.getFloatRoot(), floatParentNode = me.floatParentNode, data, mask;
  if (floatParentNode) {
    data = floatParentNode.getData();
    if (floatParentNode !== floatRoot && !data.component.getRelative()) {
      data = floatRoot.getData();
    }
    mask = data.modalMask;
    if (mask && mask.dom.parentNode) {
      mask = mask.dom;
      Ext.getDetachedBody().appendChild(mask);
    }
  }
  if (Ext.Viewport) {
    Ext.Viewport.enableTabbing();
  }
}, showModalMask:function() {
  var me = this, Widget = Ext.Widget, floatRoot = Ext.getFloatRoot(), positionEl = me.getFloatWrap(), parent = me.getParent(), floatParentNode = me.floatParentNode, data = floatParentNode.getData(), mask;
  if (me.getFloated() && me.getModal && me.getModal()) {
    if (floatParentNode !== floatRoot && !data.component.getRelative()) {
      data = floatRoot.getData();
    }
    mask = data.modalMask;
    if (mask) {
      if (positionEl.dom.parentElement === floatParentNode.dom) {
        floatParentNode.dom.insertBefore(mask.dom, positionEl.dom);
      } else {
        floatParentNode.dom.appendChild(mask.dom);
      }
    } else {
      mask = data.modalMask = floatParentNode.createChild({cls:'x-mask'}, positionEl);
      mask.on({tap:Widget.onModalMaskTap, scope:Widget});
      if (Ext.isiOS && floatParentNode === floatRoot) {
        mask.on({touchmove:function(e) {
          e.preventDefault();
        }});
      }
    }
    Widget.topModal = me;
    if (parent && parent.getFloated() && !parent.getRelative()) {
      parent.syncXYPosition();
    }
    if (Ext.Viewport) {
      Ext.Viewport.disableTabbing();
    }
  }
}, syncShim:function() {
  var me = this, shim = me.getShim();
  if (shim) {
    if (me.isVisible(true)) {
      shim.show();
      me.getFloatWrap().dom.insertBefore(shim.dom, me.el.dom);
      shim.setSize(me.getSize());
    } else {
      shim.hide();
    }
  }
}, updateAlwaysOnTop:function(alwaysOnTop) {
  var me = this;
  me.getFloatWrap().getData().alwaysOnTop = Number(alwaysOnTop);
  if (!me.floatParentNode) {
    me.findFloatParent();
  }
  if (!me.isConfiguring) {
    me.syncAlwaysOnTop();
  }
}, syncAlwaysOnTop:function(fromMousedown) {
  var me = this, positionEl = me.getFloatWrap().dom, parentEl = me.floatParentNode, nodes = parentEl.dom.childNodes, len = nodes.length, alwaysOnTop = Number(me.getAlwaysOnTop()), range = me.statics().range, maskCls = Ext.Mask.prototype.baseCls, i, startIdx, nodeEl, refNode, isTopModal, currentAlwaysOnTop;
  startIdx = parentEl === Ext.floatRoot ? 0 : 1;
  isTopModal = me.getModal && me.getModal() && positionEl.previousSibling && Ext.fly(positionEl.previousSibling).hasCls(maskCls);
  if (positionEl.nextSibling) {
    for (i = len - 1; i >= startIdx; i--) {
      nodeEl = Ext.fly(nodes[i]);
      if (!nodeEl.hasCls(me.shimCls) && !nodeEl.hasCls(maskCls) && nodes[i] !== positionEl) {
        if (alwaysOnTop >= (Ext.get(nodes[i]).getData().alwaysOnTop || 0)) {
          refNode = nodes[i].nextSibling;
          break;
        }
      }
    }
    if (refNode === positionEl) {
      return;
    }
    if (i < startIdx) {
      refNode = nodes[0];
    }
    if (me.containsFocus || fromMousedown) {
      range.setStartAfter(positionEl);
      range.setEndAfter(refNode || nodes[len - 1]);
      parentEl.dom.insertBefore(range.extractContents(), positionEl);
    } else {
      parentEl.dom.insertBefore(positionEl, refNode);
    }
  } else {
    if (positionEl.previousSibling) {
      for (i = len - 2; i >= startIdx; i--) {
        if (!Ext.fly(nodes[i]).is('.' + me.shimCls) && nodes[i] !== positionEl) {
          currentAlwaysOnTop = Ext.get(nodes[i]).getData().alwaysOnTop;
          if (alwaysOnTop < currentAlwaysOnTop) {
            refNode = nodes[i];
            parentEl.dom.insertBefore(refNode, null);
            if (nodes[i - 1] && Ext.fly(nodes[i - 1]).hasCls(maskCls)) {
              parentEl.dom.insertBefore(nodes[i - 1], refNode);
              i -= 1;
            }
            alwaysOnTop = currentAlwaysOnTop;
          }
        }
      }
    }
  }
  if (isTopModal) {
    me.showModalMask();
  }
  me.syncShim();
  if (refNode && !Ext.fly(refNode).hasCls(maskCls)) {
    Ext.Component.from(refNode).syncShim();
  } else {
    return true;
  }
}, updateRelative:function() {
  this.syncXYPosition();
}, updateShadow:function(shadow) {
  this.el.toggleCls(this.shadowCls, shadow);
  this.el.toggleCls(this.noShadowCls, shadow === false);
}, updateX:function() {
  if (!this.getFloated()) {
    Ext.raise('Cannot use setX on a non-floated component');
  }
  if (!this.$updatingXY) {
    this.syncXYPosition();
  }
}, updateY:function() {
  if (!this.getFloated()) {
    Ext.raise('Cannot use setY on a non-floated component');
  }
  if (!this.$updatingXY) {
    this.syncXYPosition();
  }
}, syncXYPosition:function(animation) {
  var me = this, floatWrap = me.getFloatWrap(), maskAnim = animation, mask, x = me.getX() || 0, y = me.getY() || 0;
  if (me.getRelative()) {
    floatWrap.translate(x, y, animation);
    floatWrap.setWidth(me.el.getWidth());
    floatWrap.setHeight(me.el.getHeight());
    me.translate(0, 0);
    mask = floatWrap.getData().modalMask;
    if (mask) {
      mask.translate(0, 0);
    }
  } else {
    me.translate(x, y, animation);
    mask = floatWrap.getData().modalMask;
    if (mask) {
      if (maskAnim) {
        maskAnim = Ext.apply({}, maskAnim);
        delete maskAnim.callback;
      }
      mask.translate(x, y, maskAnim);
    }
  }
  me.syncShim();
}}}, function(Widget) {
  this.borrow(Ext.util.Positionable, ['clipTo', 'clearClip']);
  Widget.createAlias({prev:'previousSibling', next:'nextSibling'});
  Ext.getFloatRoot = function() {
    var fp = Ext.floatRoot, prototype = Widget.prototype, range = Widget.range;
    if (fp) {
      if (fp.el.dom.nextSibling) {
        if (fp.el.contains(document.activeElement)) {
          range.setStartBefore(fp.el.dom.nextSibling);
          range.setEndAfter(fp.el.dom.parentNode.lastChild);
          fp.el.dom.parentNode.insertBefore(range.extractContents(), fp.el.dom);
        } else {
          fp.el.dom.parentNode.appendChild(fp.dom);
        }
      }
    } else {
      fp = Ext.getBody().createChild({cls:prototype.floatWrapCls + ' ' + prototype.rootCls, id:'ext-global-floatWrap', 'data-sticky':true});
      fp.$skipResourceCheck = true;
      Ext.floatRoot = fp;
    }
    return fp;
  };
});
Ext.define('Ext.util.Bag', {isBag:true, constructor:function() {
  this.items = [];
  this.map = {};
}, generation:0, length:0, beginUpdate:Ext.emptyFn, endUpdate:Ext.emptyFn, add:function(item) {
  var me = this, items = me.items, map = me.map, n = 1, old, i, idx, id, it, ret, was;
  if (Ext.isArray(item)) {
    old = ret = [];
    n = item.length;
  }
  for (i = 0; i < n; i++) {
    id = me.getKey(it = old ? item[i] : item);
    idx = map[id];
    if (idx === undefined) {
      items.push(it);
      map[id] = me.length++;
      if (old) {
        old.push(it);
      } else {
        ret = it;
      }
    } else {
      was = items[idx];
      if (old) {
        old.push(was);
      } else {
        ret = was;
      }
      items[idx] = it;
    }
  }
  ++me.generation;
  return ret;
}, clear:function() {
  var me = this, needsClear = me.generation || me.length, ret = needsClear ? me.items : [];
  if (needsClear) {
    me.items = [];
    me.length = 0;
    me.map = {};
    ++me.generation;
  }
  return ret;
}, clone:function() {
  var me = this, ret = new me.self, len = me.length;
  if (len) {
    Ext.apply(ret.map, me.map);
    ret.items = me.items.slice();
    ret.length = me.length;
  }
  return ret;
}, contains:function(item) {
  var ret = false, map = this.map, key;
  if (item != null) {
    key = this.getKey(item);
    if (key in map) {
      ret = this.items[map[key]] === item;
    }
  }
  return ret;
}, containsKey:function(key) {
  return key in this.map;
}, destroy:function() {
  this.items = this.map = null;
  this.callParent();
}, each:function(fn, scope) {
  var items = this.items, len = items.length, i, ret;
  if (len) {
    scope = scope || this;
    items = items.slice(0);
    for (i = 0; i < len; i++) {
      ret = fn.call(scope, items[i], i, len);
      if (ret === false) {
        break;
      }
    }
  }
  return ret;
}, getAt:function(index) {
  var out = null;
  if (index < this.length) {
    out = this.items[index];
  }
  return out;
}, get:function(key) {
  return this.getByKey(key);
}, getByKey:function(key) {
  var map = this.map, ret = key in map ? this.items[map[key]] : null;
  return ret;
}, indexOfKey:function(key) {
  var map = this.map, ret = key in map ? map[key] : -1;
  return ret;
}, last:function() {
  return this.items[this.length - 1];
}, updateKey:function(item, oldKey) {
  var me = this, map = me.map, newKey;
  if (!item || !oldKey) {
    return;
  }
  if ((newKey = me.getKey(item)) !== oldKey) {
    if (me.getAt(map[oldKey]) === item && !(newKey in map)) {
      me.generation++;
      map[newKey] = map[oldKey];
      delete map[oldKey];
    }
  } else {
    if (newKey in map && me.getAt(map[newKey]) !== item) {
      Ext.raise('Duplicate newKey "' + newKey + '" for item with oldKey "' + oldKey + '"');
    }
    if (oldKey in map && me.getAt(map[oldKey]) !== item) {
      Ext.raise('Incorrect oldKey "' + oldKey + '" for item with newKey "' + newKey + '"');
    }
  }
}, getCount:function() {
  return this.length;
}, getKey:function(item) {
  return item.id || item.getId();
}, getRange:function(begin, end) {
  var items = this.items, length = items.length, range;
  if (!length) {
    range = [];
  } else {
    range = Ext.Number.clipIndices(length, [begin, end]);
    range = items.slice(range[0], range[1]);
  }
  return range;
}, remove:function(item) {
  var me = this, map = me.map, items = me.items, ret = null, n = 1, changed, old, i, idx, id, last, was;
  if (Ext.isArray(item)) {
    n = item.length;
    old = ret = [];
  }
  if (me.length) {
    for (i = 0; i < n; i++) {
      idx = map[id = me.getKey(old ? item[i] : item)];
      if (idx !== undefined) {
        delete map[id];
        was = items[idx];
        if (old) {
          old.push(was);
        } else {
          ret = was;
        }
        last = items.pop();
        if (idx < --me.length) {
          items[idx] = last;
          map[me.getKey(last)] = idx;
        }
        changed = true;
      }
    }
    if (changed) {
      ++me.generation;
    }
  }
  return ret;
}, removeByKey:function(key) {
  var item = this.getByKey(key);
  if (item) {
    this.remove(item);
  }
  return item || null;
}, replace:function(item) {
  this.add(item);
  return item;
}, sort:function(fn) {
  var me = this, items = me.items, n = items.length, item;
  if (n) {
    Ext.Array.sort(items, fn);
    me.map = {};
    while (n-- > 0) {
      item = items[n];
      me.map[me.getKey(item)] = n;
    }
    ++me.generation;
  }
}});
Ext.define('Ext.state.Provider', function(Provider) {
  return {mixins:[Ext.mixin.Bufferable], statics:{get:function() {
    return Provider._default;
  }, register:function(provider) {
    var was = Provider._default;
    if (was !== provider) {
      Provider._default = provider;
      if (provider) {
        provider.global = true;
      }
      if (was) {
        was.global = false;
      }
      if (Ext.hasListeners.stateproviderchange) {
        Ext.fireEvent('stateproviderchange', provider, was);
      }
    }
  }}, bufferableMethods:{saveState:50}, constructor:function(config) {
    this.queue = new Ext.util.Bag;
    this.state = {};
    this.initConfig(config);
  }, clear:function() {
    var me = this;
    me.cancelSaveState();
    me.queue.clear();
    me.state = {};
  }, get:function(name, defaultValue) {
    var ret = this.state[name];
    return ret === undefined ? defaultValue : ret;
  }, remove:function(name) {
    return this.set(name, null);
  }, set:function(name, value) {
    var me = this, state = me.state, looper = name;
    if (typeof name === 'string') {
      looper = {};
      looper[name] = value;
    }
    for (name in looper) {
      value = looper[name];
      if (value == null) {
        delete state[name];
        value = null;
      } else {
        state[name] = value;
      }
    }
  }, decodeValue:function(value) {
    return Ext.decode(value);
  }, encodeValue:function(value) {
    return Ext.encode(value);
  }, privates:{doSave:function(stateful) {
    stateful.$saveStatePending = false;
    stateful.persistState();
  }, doSaveState:function() {
    var me = this, queue = me.queue;
    queue.each(me.doSave, me);
    queue.clear();
  }, save:function(stateful) {
    if (stateful.destroyed || stateful.destroying) {
      Ext.raise('Cannot save state of instance during or after destroy');
    }
    stateful.$saveStatePending = true;
    this.queue.add(stateful);
    this.saveState();
  }}};
}, function(Provider) {
  Provider.register(new Provider);
});
Ext.define('Ext.state.Stateful', function(Stateful) {
  return {extend:Ext.Mixin, mixinConfig:{id:'state', configs:true, before:{destroy:'_flushStateful'}, mixed:function(targetClass) {
    targetClass.addConfigTransform('transformStatefulConfig', 20);
  }}, isStateful:true, config:{stateful:{$value:null, merge:function(newValue, oldValue) {
    if (newValue === true) {
      return oldValue || newValue;
    }
    if (!newValue) {
      return false;
    }
    return this.mergeSets(newValue, oldValue);
  }}, statefulDefaults:{$value:null, cached:true, merge:function(newValue, oldValue) {
    return this.mergeSets(newValue, oldValue);
  }}, stateId:null}, getStatefulOwner:Ext.emptyFn, loadState:function(state, stateful) {
    var props = stateful && state.data, name, ret;
    props = props && props.$;
    if (props) {
      for (name in stateful) {
        if (stateful[name] && name in props) {
          (ret || (ret = {}))[name] = props[name];
        }
      }
    }
    return ret;
  }, saveState:function(state, stateful) {
    var me = this, name;
    if (stateful) {
      for (name in stateful) {
        state.save(me, name);
      }
    }
  }, applyStateful:function(stateful, was) {
    var me = this, ret = false, handler = 'onStatefulChange', watcher = (stateful || was) && me.getConfigWatcher(), defaults = me.isConfiguring, name, on;
    if (stateful) {
      if (stateful === true) {
        ret = {};
        defaults = true;
      } else {
        if (typeof stateful === 'string') {
          ret = {};
          ret[stateful] = true;
        } else {
          if (Ext.isObject(stateful)) {
            ret = stateful;
          } else {
            ret = Ext.Array.toMap(stateful);
          }
        }
      }
      defaults = defaults && me.getStatefulDefaults();
      if (defaults) {
        ret = Ext.merge({}, defaults, ret);
      }
      was = was || {};
      for (name in ret) {
        on = ret[name];
        if (!on !== !was[name]) {
          watcher[on ? 'on' : 'un'](name, handler, me);
          if (on) {
            was[name] = true;
          } else {
            delete was[name];
          }
        }
      }
      ret = Ext.Object.isEmpty(was) ? false : was;
    } else {
      if (was) {
        for (name in was) {
          watcher.un(name, handler, me);
        }
      }
    }
    return ret;
  }, privates:{statics:{_configNames:['stateful', 'stateId']}, _flushStateful:function() {
    if (this.$saveStatePending) {
      var provider = Ext.state.Provider.get();
      if (provider && provider.isSaveStatePending) {
        provider.flushSaveState();
      }
    }
  }, getStateBuilder:function(cache) {
    var me = this, id = me._getStateId(), ret = cache && me.$state || null, provider = id && Ext.state.Provider.get(), n, owner, statefulOwner;
    if (provider && !ret) {
      if (!(statefulOwner = me.getStatefulOwner())) {
        ret = new Ext.state.Builder;
        if (cache) {
          ret.data = provider.get(id);
        }
      } else {
        if (!(owner = statefulOwner).isStateful) {
          owner = statefulOwner[0];
          n = 1;
        }
        ret = owner.getStateBuilder(cache);
        if (ret) {
          for (; n && n < statefulOwner.length; ++n) {
            ret = ret.child(statefulOwner[n]);
          }
          ret = ret.child(id);
        }
      }
      if (ret) {
        ret.owner = me;
        ret.id = id;
      }
      me.$state = cache ? ret : null;
    }
    return ret;
  }, _getStateId:function() {
    var me = this, id = me.getStateId();
    me._getStateId = me.getStateId;
    if (!id) {
      id = me.id || me.getId();
      if (me.autoGenId) {
        id = null;
      } else {
        me.setStateId(id);
      }
    }
    return id;
  }, onStatefulChange:function() {
    var me = this;
    if (!me.destroying && me._getStateId()) {
      Ext.state.Provider.get().save(me);
    }
  }, persistState:function() {
    var me = this, state = me.getStateBuilder(), id, provider, root;
    if (state) {
      provider = Ext.state.Provider.get();
      root = state.root;
      id = root.id;
      if (state.parent) {
        root.data = provider.get(id);
        state.clear();
      }
      me.saveState(state, me.getStateful());
      provider.set(id, root.data);
    }
  }, readStateObject:function() {
    var me = this, state = me.getStateBuilder(true), ret;
    if (state) {
      state.getData();
      ret = me.loadState(state, me.getStateful());
    }
    return ret || null;
  }, transformStatefulConfig:function(instanceConfig, configurator) {
    var me = this, ret = instanceConfig, saved, name, state, stateful;
    if (configurator.hoistConfigs(me, instanceConfig, Stateful._configNames)) {
      state = me.readStateObject();
      if (state) {
        stateful = me.getStateful();
        saved = {};
        for (name in state) {
          if (stateful[name]) {
            saved[name] = true;
          } else {
            delete state[name];
          }
        }
        state = Ext.Object.isEmpty(state) ? null : state;
        me.$statefulConfigs = state && saved;
      }
      if (state) {
        ret = configurator.merge(me, ret, state, true);
      } else {
        ret = Ext.apply({}, ret);
      }
      delete ret.stateful;
      delete ret.stateId;
    }
    return ret;
  }}};
});
Ext.define('Ext.util.Format', function() {
  var me;
  return {singleton:true, defaultDateFormat:'m/d/Y', thousandSeparator:',', decimalSeparator:'.', currencyPrecision:2, currencySign:'$', currencySpacer:'', percentSign:'%', currencyAtEnd:false, stripTagsRe:/<\/?[^>]+>/gi, stripScriptsRe:/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, nl2brRe:/\r?\n/g, hashRe:/#+$/, allHashes:/^#+$/, formatPattern:/[\d,.#]+/, formatCleanRe:/[^\d.#]/g, I18NFormatCleanRe:null, formatFns:{}, constructor:function() {
    me = this;
  }, nbsp:function(value, strict) {
    strict = strict !== false;
    if (strict ? value === '' || value == null : !value) {
      value = ' ';
    }
    return value;
  }, undef:function(value) {
    return value !== undefined ? value : '';
  }, defaultValue:function(value, defaultValue) {
    return value !== undefined && value !== '' ? value : defaultValue;
  }, substr:'ab'.substr(-1) !== 'b' ? function(value, start, length) {
    var str = String(value);
    return start < 0 ? str.substr(Math.max(str.length + start, 0), length) : str.substr(start, length);
  } : function(value, start, length) {
    return String(value).substr(start, length);
  }, lowercase:function(value) {
    return String(value).toLowerCase();
  }, uppercase:function(value) {
    return String(value).toUpperCase();
  }, usMoney:function(value) {
    return me.currency(value, '$', 2);
  }, currency:function(value, currencySign, decimals, end, currencySpacer) {
    var negativeSign = '', format = ',0', i = 0;
    value = value - 0;
    if (value < 0) {
      value = -value;
      negativeSign = '-';
    }
    decimals = Ext.isDefined(decimals) ? decimals : me.currencyPrecision;
    format += decimals > 0 ? '.' : '';
    for (; i < decimals; i++) {
      format += '0';
    }
    value = me.number(value, format);
    if (currencySpacer == null) {
      currencySpacer = me.currencySpacer;
    }
    if ((end || me.currencyAtEnd) === true) {
      return Ext.String.format('{0}{1}{2}{3}', negativeSign, value, currencySpacer, currencySign || me.currencySign);
    } else {
      return Ext.String.format('{0}{1}{2}{3}', negativeSign, currencySign || me.currencySign, currencySpacer, value);
    }
  }, date:function(value, format) {
    if (!value) {
      return '';
    }
    if (!Ext.isDate(value)) {
      value = new Date(Date.parse(value));
    }
    return Ext.Date.dateFormat(value, format || Ext.Date.defaultFormat);
  }, dateRenderer:function(format) {
    return function(v) {
      return me.date(v, format);
    };
  }, hex:function(value, digits) {
    var s = parseInt(value || 0, 10).toString(16);
    if (digits) {
      if (digits < 0) {
        digits = -digits;
        if (s.length > digits) {
          s = s.substring(s.length - digits);
        }
      }
      while (s.length < digits) {
        s = '0' + s;
      }
    }
    return s;
  }, or:function(value, orValue) {
    return value || orValue;
  }, pick:function(value, firstValue, secondValue) {
    var ret;
    if (Ext.isNumber(value)) {
      ret = arguments[value + 1];
      if (ret) {
        return ret;
      }
    }
    return value ? secondValue : firstValue;
  }, lessThanElse:function(value, threshold, below, above, equal) {
    var v = Ext.Number.from(value, 0), t = Ext.Number.from(threshold, 0), missing = !Ext.isDefined(equal);
    return v < t ? below : v > t ? above : missing ? above : equal;
  }, sign:function(value, negative, positive, zero) {
    if (zero === undefined) {
      zero = positive;
    }
    return me.lessThanElse(value, 0, negative, positive, zero);
  }, stripTags:function(value) {
    return !value ? value : String(value).replace(me.stripTagsRe, '');
  }, stripScripts:function(value) {
    return !value ? value : String(value).replace(me.stripScriptsRe, '');
  }, fileSize:function() {
    var byteLimit = 1024, kbLimit = 1048576, mbLimit = 1073741824;
    return function(size) {
      var out;
      if (size < byteLimit) {
        if (size === 1) {
          out = '1 byte';
        } else {
          out = size + ' bytes';
        }
      } else {
        if (size < kbLimit) {
          out = Math.round(size * 10 / byteLimit) / 10 + ' KB';
        } else {
          if (size < mbLimit) {
            out = Math.round(size * 10 / kbLimit) / 10 + ' MB';
          } else {
            out = Math.round(size * 10 / mbLimit) / 10 + ' GB';
          }
        }
      }
      return out;
    };
  }(), math:function() {
    var fns = {};
    return function(v, a) {
      if (!fns[a]) {
        fns[a] = Ext.functionFactory('v', 'return v ' + a + ';');
      }
      return fns[a](v);
    };
  }(), round:function(value, precision) {
    var result = Number(value);
    if (typeof precision === 'number') {
      precision = Math.pow(10, precision);
      result = Math.round(value * precision) / precision;
    } else {
      if (precision === undefined) {
        result = Math.round(result);
      }
    }
    return result;
  }, number:function(v, formatString) {
    var formatFn;
    if (!formatString) {
      return v;
    }
    if (isNaN(v)) {
      return '';
    }
    formatFn = me.formatFns[formatString];
    if (!formatFn) {
      var originalFormatString = formatString, comma = me.thousandSeparator, decimalSeparator = me.decimalSeparator, precision = 0, trimPart = '', hasComma, splitFormat, extraChars, trimTrailingZeroes, code, len;
      if (formatString.substr(formatString.length - 2) === '/i') {
        if (!me.I18NFormatCleanRe || me.lastDecimalSeparator !== decimalSeparator) {
          me.I18NFormatCleanRe = new RegExp('[^\\d\\' + decimalSeparator + '#]', 'g');
          me.lastDecimalSeparator = decimalSeparator;
        }
        formatString = formatString.substr(0, formatString.length - 2);
        hasComma = formatString.indexOf(comma) !== -1;
        splitFormat = formatString.replace(me.I18NFormatCleanRe, '').split(decimalSeparator);
      } else {
        hasComma = formatString.indexOf(',') !== -1;
        splitFormat = formatString.replace(me.formatCleanRe, '').split('.');
      }
      extraChars = formatString.replace(me.formatPattern, '');
      if (splitFormat.length > 2) {
        Ext.raise({sourceClass:'Ext.util.Format', sourceMethod:'number', value:v, formatString:formatString, msg:'Invalid number format, should have no more than 1 decimal'});
      } else {
        if (splitFormat.length === 2) {
          precision = splitFormat[1].length;
          trimTrailingZeroes = splitFormat[1].match(me.hashRe);
          if (trimTrailingZeroes) {
            len = trimTrailingZeroes[0].length;
            trimPart = 'trailingZeroes\x3dnew RegExp(Ext.String.escapeRegex(utilFormat.decimalSeparator) + "*0{0,' + len + '}$")';
          }
        }
      }
      code = ['var utilFormat\x3dExt.util.Format,extNumber\x3dExt.Number,neg,absVal,fnum,parts' + (hasComma ? ',thousandSeparator,thousands\x3d[],j,n,i' : '') + (extraChars ? ',formatString\x3d"' + formatString + '",formatPattern\x3d/[\\d,\\.#]+/' : '') + ',trailingZeroes;' + 'return function(v){' + 'if(typeof v!\x3d\x3d"number"\x26\x26isNaN(v\x3dextNumber.from(v,NaN)))return"";' + 'neg\x3dv\x3c0;', 'absVal\x3dMath.abs(v);', 'fnum\x3dExt.Number.toFixed(absVal, ' + precision + ');', trimPart, ';'];
      if (hasComma) {
        if (precision) {
          code[code.length] = 'parts\x3dfnum.split(".");';
          code[code.length] = 'fnum\x3dparts[0];';
        }
        code[code.length] = 'if(absVal\x3e\x3d1000) {';
        code[code.length] = 'thousandSeparator\x3dutilFormat.thousandSeparator;' + 'thousands.length\x3d0;' + 'j\x3dfnum.length;' + 'n\x3dfnum.length%3||3;' + 'for(i\x3d0;i\x3cj;i+\x3dn){' + 'if(i!\x3d\x3d0){' + 'n\x3d3;' + '}' + 'thousands[thousands.length]\x3dfnum.substr(i,n);' + '}' + 'fnum\x3dthousands.join(thousandSeparator);' + '}';
        if (precision) {
          code[code.length] = 'fnum +\x3d utilFormat.decimalSeparator+parts[1];';
        }
      } else {
        if (precision) {
          code[code.length] = 'if(utilFormat.decimalSeparator!\x3d\x3d"."){' + 'parts\x3dfnum.split(".");' + 'fnum\x3dparts[0]+utilFormat.decimalSeparator+parts[1];' + '}';
        }
      }
      code[code.length] = 'if(neg\x26\x26fnum!\x3d\x3d"' + (precision ? '0.' + Ext.String.repeat('0', precision) : '0') + '") { fnum\x3d"-"+fnum; }';
      if (trimTrailingZeroes) {
        code[code.length] = 'if(fnum.indexOf("e+") \x3d\x3d\x3d -1)' + 'fnum\x3dfnum.replace(trailingZeroes,"");';
      }
      code[code.length] = 'return ';
      if (extraChars) {
        code[code.length] = 'formatString.replace(formatPattern, fnum);';
      } else {
        code[code.length] = 'fnum;';
      }
      code[code.length] = '};';
      formatFn = me.formatFns[originalFormatString] = Ext.functionFactory('Ext', code.join(''))(Ext);
    }
    return formatFn(v);
  }, numberRenderer:function(format) {
    return function(v) {
      return me.number(v, format);
    };
  }, percent:function(value, formatString) {
    return me.number(value * 100, formatString || '0') + me.percentSign;
  }, repeat:function(value, text, sep) {
    return Ext.String.repeat(text, value, sep);
  }, attributes:function(attributes) {
    var result, name;
    if (typeof attributes === 'object') {
      result = [];
      for (name in attributes) {
        if (attributes.hasOwnProperty(name)) {
          result.push(name, '\x3d"', name === 'style' ? Ext.DomHelper.generateStyles(attributes[name], null, true) : Ext.htmlEncode(attributes[name]), '" ');
        }
      }
      attributes = result.join('');
    }
    return attributes || '';
  }, plural:function(value, singular, plural) {
    return value + ' ' + (value === 1 ? singular : plural ? plural : singular + 's');
  }, nl2br:function(v) {
    return Ext.isEmpty(v) ? '' : v.replace(me.nl2brRe, '\x3cbr/\x3e');
  }, capitalize:Ext.String.capitalize, uncapitalize:Ext.String.uncapitalize, ellipsis:Ext.String.ellipsis, escape:Ext.String.escape, escapeRegex:Ext.String.escapeRegex, htmlDecode:Ext.String.htmlDecode, htmlEncode:Ext.String.htmlEncode, leftPad:Ext.String.leftPad, toggle:Ext.String.toggle, trim:Ext.String.trim, parseBox:function(box) {
    box = box || 0;
    if (typeof box === 'number') {
      return {top:box, right:box, bottom:box, left:box};
    }
    var parts = box.split(' '), ln = parts.length;
    if (ln === 1) {
      parts[1] = parts[2] = parts[3] = parts[0];
    } else {
      if (ln === 2) {
        parts[2] = parts[0];
        parts[3] = parts[1];
      } else {
        if (ln === 3) {
          parts[3] = parts[1];
        }
      }
    }
    return {top:parseInt(parts[0], 10) || 0, right:parseInt(parts[1], 10) || 0, bottom:parseInt(parts[2], 10) || 0, left:parseInt(parts[3], 10) || 0};
  }, resource:function(url, prefix) {
    prefix = prefix || '';
    return Ext.resolveResource(prefix + url);
  }, uri:function(value) {
    return encodeURI(value);
  }, uriCmp:function(value) {
    return encodeURIComponent(value);
  }, wordBreakRe:/[\W\s]+/, word:function(value, index, sep) {
    var re = sep ? typeof sep === 'string' ? new RegExp(sep) : sep : me.wordBreakRe, parts = (value || '').split(re);
    return parts[index || 0] || '';
  }};
});
Ext.define('Ext.Template', {inheritableStatics:{from:function(el, config) {
  el = Ext.getDom(el);
  return new this(el.value || el.innerHTML, config || '');
}}, useEval:Ext.isGecko, constructor:function(html) {
  var me = this, args = arguments, buffer = [], length = args.length, i, value;
  me.initialConfig = {};
  if (length === 1 && Ext.isArray(html)) {
    args = html;
    length = args.length;
  }
  if (length > 1) {
    for (i = 0; i < length; i++) {
      value = args[i];
      if (typeof value === 'object') {
        Ext.apply(me.initialConfig, value);
        Ext.apply(me, value);
      } else {
        buffer.push(value);
      }
    }
  } else {
    buffer.push(html);
  }
  me.html = buffer.join('');
}, isTemplate:true, disableFormats:false, tokenRe:/\{(?:(?:(\d+)|([a-z_$][\w\-$]*))(?::([a-z_.]+)(?:\(([^)]*?)?\))?)?)\}/gi, apply:function(values) {
  var me = this;
  if (me.compiled) {
    if (!me.fn) {
      me.compile();
    }
    return me.fn(values).join('');
  }
  return me.evaluate(values);
}, evaluate:function(values) {
  var me = this, useFormat = !me.disableFormats, fm = Ext.util.Format, tpl = me;
  function fn(match, index, name, formatFn, args) {
    if (name == null || name === '') {
      name = index;
    }
    if (formatFn && useFormat) {
      if (args) {
        args = [values[name]].concat(Ext.functionFactory('return [' + args + '];')());
      } else {
        args = [values[name]];
      }
      if (formatFn.substr(0, 5) === 'this.') {
        return tpl[formatFn.substr(5)].apply(tpl, args);
      } else {
        if (fm[formatFn]) {
          return fm[formatFn].apply(fm, args);
        } else {
          return match;
        }
      }
    } else {
      return values[name] !== undefined ? values[name] : '';
    }
  }
  return me.html.replace(me.tokenRe, fn);
}, applyOut:function(values, out) {
  var me = this;
  if (me.compiled) {
    if (!me.fn) {
      me.compile();
    }
    out.push.apply(out, me.fn(values));
  } else {
    out.push(me.apply(values));
  }
  return out;
}, applyTemplate:function() {
  return this.apply.apply(this, arguments);
}, set:function(html, compile) {
  var me = this;
  me.html = html;
  me.compiled = !!compile;
  me.fn = null;
  return me;
}, compileARe:/\\/g, compileBRe:/(\r\n|\n)/g, compileCRe:/'/g, compile:function() {
  var me = this, code;
  code = me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.tokenRe, me.regexReplaceFn.bind(me));
  code = (this.disableFormats !== true ? 'var fm\x3dExt.util.Format;' : '') + (me.useEval ? '$\x3d' : 'return') + " function(v){return ['" + code + "'];};";
  me.fn = me.useEval ? me.evalCompiled(code) : (new Function('Ext', code))(Ext);
  me.compiled = true;
  return me;
}, evalCompiled:function($) {
  eval($);
  return $;
}, regexReplaceFn:function(match, index, name, formatFn, args) {
  if (index == null || index === '') {
    index = '"' + name + '"';
  } else {
    if (this.stringFormat) {
      index = parseInt(index) + 1;
    }
  }
  if (formatFn && this.disableFormats !== true) {
    args = args ? ',' + args : '';
    if (formatFn.substr(0, 5) === 'this.') {
      formatFn = formatFn + '(';
    } else {
      if (Ext.util.Format[formatFn]) {
        formatFn = 'fm.' + formatFn + '(';
      } else {
        return match;
      }
    }
    return "'," + formatFn + 'v[' + index + ']' + args + "),'";
  } else {
    return "',v[" + index + "] \x3d\x3d undefined ? '' : v[" + index + "],'";
  }
}, insertFirst:function(el, values, returnElement) {
  return this.doInsert('afterBegin', el, values, returnElement);
}, insertBefore:function(el, values, returnElement) {
  return this.doInsert('beforeBegin', el, values, returnElement);
}, insertAfter:function(el, values, returnElement) {
  return this.doInsert('afterEnd', el, values, returnElement);
}, append:function(el, values, returnElement) {
  return this.doInsert('beforeEnd', el, values, returnElement);
}, doInsert:function(where, el, values, returnElement) {
  var newNode = Ext.DomHelper.insertHtml(where, Ext.getDom(el), this.apply(values));
  return returnElement ? Ext.get(newNode) : newNode;
}, overwrite:function(el, values, returnElement) {
  var newNode = Ext.DomHelper.overwrite(Ext.getDom(el), this.apply(values));
  return returnElement ? Ext.get(newNode) : newNode;
}}, function(Template) {
  var formatRe = /\{\d+\}/, generateFormatFn = function(format) {
    if (formatRe.test(format)) {
      format = new Template(format, formatTplConfig);
      return function() {
        return format.apply(arguments);
      };
    } else {
      return function() {
        return format;
      };
    }
  }, formatTplConfig = {useFormat:false, compiled:true, stringFormat:true}, formatFns = {};
  Ext.String.format = Ext.util.Format.format = function(format) {
    var formatFn = formatFns[format] || (formatFns[format] = generateFormatFn(format));
    return formatFn.apply(this, arguments);
  };
  Ext.String.formatEncode = function() {
    return Ext.String.htmlEncode(Ext.String.format.apply(this, arguments));
  };
});
Ext.define('Ext.util.XTemplateParser', {constructor:function(config) {
  Ext.apply(this, config);
}, doTpl:Ext.emptyFn, parse:function(str) {
  var me = this, len = str.length, aliases = {elseif:'elif'}, topRe = me.topRe, actionsRe = me.actionsRe, index, stack, s, m, t, prev, frame, subMatch, begin, end, actions, prop, expectTplNext;
  me.level = 0;
  me.stack = stack = [];
  for (index = 0; index < len; index = end) {
    topRe.lastIndex = index;
    m = topRe.exec(str);
    if (!m) {
      me.doText(str.substring(index, len));
      break;
    }
    begin = m.index;
    end = topRe.lastIndex;
    if (index < begin) {
      s = str.substring(index, begin);
      if (!(expectTplNext && Ext.String.trim(s) === '')) {
        me.doText(s);
      }
    }
    expectTplNext = false;
    if (m[1]) {
      end = str.indexOf('%}', begin + 2);
      me.doEval(str.substring(begin + 2, end));
      end += 2;
    } else {
      if (m[2]) {
        end = str.indexOf(']}', begin + 2);
        me.doExpr(str.substring(begin + 2, end));
        end += 2;
      } else {
        if (m[3]) {
          me.doTag(m[3]);
        } else {
          if (m[4]) {
            actions = null;
            while ((subMatch = actionsRe.exec(m[4])) !== null) {
              s = subMatch[2] || subMatch[3];
              if (s) {
                s = Ext.String.htmlDecode(s);
                t = subMatch[1];
                t = aliases[t] || t;
                actions = actions || {};
                prev = actions[t];
                if (typeof prev === 'string') {
                  actions[t] = [prev, s];
                } else {
                  if (prev) {
                    actions[t].push(s);
                  } else {
                    actions[t] = s;
                  }
                }
              }
            }
            if (!actions) {
              if (me.elseRe.test(m[4])) {
                me.doElse();
              } else {
                if (me.defaultRe.test(m[4])) {
                  me.doDefault();
                } else {
                  me.doTpl();
                  stack.push({type:'tpl'});
                }
              }
            } else {
              if (actions['if']) {
                me.doIf(actions['if'], actions);
                stack.push({type:'if'});
              } else {
                if (actions['switch']) {
                  me.doSwitch(actions['switch'], actions);
                  stack.push({type:'switch'});
                  expectTplNext = true;
                } else {
                  if (actions['case']) {
                    me.doCase(actions['case'], actions);
                  } else {
                    if (actions['elif']) {
                      me.doElseIf(actions['elif'], actions);
                    } else {
                      if (actions['for']) {
                        ++me.level;
                        if (prop = me.propRe.exec(m[4])) {
                          actions.propName = prop[1] || prop[2];
                        }
                        me.doFor(actions['for'], actions);
                        stack.push({type:'for', actions:actions});
                      } else {
                        if (actions['foreach']) {
                          ++me.level;
                          if (prop = me.propRe.exec(m[4])) {
                            actions.propName = prop[1] || prop[2];
                          }
                          me.doForEach(actions['foreach'], actions);
                          stack.push({type:'foreach', actions:actions});
                        } else {
                          if (actions.exec) {
                            me.doExec(actions.exec, actions);
                            stack.push({type:'exec', actions:actions});
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          } else {
            if (m[0].length === 5) {
              stack.push({type:'tpl'});
            } else {
              frame = stack.pop();
              me.doEnd(frame.type, frame.actions);
              if (frame.type === 'for' || frame.type === 'foreach') {
                --me.level;
              }
            }
          }
        }
      }
    }
  }
}, topRe:/(?:(\{%)|(\{\[)|\{([^{}]+)\})|(?:<tpl([^>]*)>)|(?:<\/tpl>)/g, actionsRe:/\s*(elif|elseif|if|for|foreach|exec|switch|case|eval|between)\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)'))\s*/g, propRe:/prop=(?:(?:"([^"]*)")|(?:'([^']*)'))/, defaultRe:/^\s*default\s*$/, elseRe:/^\s*else\s*$/});
Ext.define('Ext.util.XTemplateCompiler', {extend:Ext.util.XTemplateParser, useEval:Ext.isGecko, useIndex:Ext.isIE8m, useFormat:true, propNameRe:/^[\w\d$]*$/, compile:function(tpl) {
  var me = this, code = me.generate(tpl);
  return me.useEval ? me.evalTpl(code) : (new Function('Ext', code))(Ext);
}, generate:function(tpl) {
  var me = this, definitions = 'var fm\x3dExt.util.Format,ts\x3dObject.prototype.toString;', code;
  me.maxLevel = 0;
  me.body = ['var c0\x3dvalues, a0\x3d' + me.createArrayTest(0) + ', p0\x3dparent, n0\x3dxcount, i0\x3dxindex, k0, v;\n'];
  if (me.definitions) {
    if (typeof me.definitions === 'string') {
      me.definitions = [me.definitions, definitions];
    } else {
      me.definitions.push(definitions);
    }
  } else {
    me.definitions = [definitions];
  }
  me.switches = [];
  me.parse(tpl);
  me.definitions.push((me.useEval ? '$\x3d' : 'return') + ' function (' + me.fnArgs + ') {', me.body.join(''), '}');
  code = me.definitions.join('\n');
  me.definitions.length = me.body.length = me.switches.length = 0;
  me.definitions = me.body = me.switches = 0;
  return code;
}, doText:function(text) {
  var me = this, out = me.body;
  text = text.replace(me.aposRe, "\\'").replace(me.newLineRe, '\\n');
  if (me.useIndex) {
    out.push("out[out.length]\x3d'", text, "'\n");
  } else {
    out.push("out.push('", text, "')\n");
  }
}, doExpr:function(expr) {
  var out = this.body;
  out.push('if ((v\x3d' + expr + ') !\x3d null) out');
  if (this.useIndex) {
    out.push('[out.length]\x3dv\n');
  } else {
    out.push('.push(v)\n');
  }
}, doTag:function(tag) {
  var expr = this.parseTag(tag);
  if (expr) {
    this.doExpr(expr);
  } else {
    this.doText('{' + tag + '}');
  }
}, doElse:function() {
  this.body.push('} else {\n');
}, doEval:function(text) {
  this.body.push(text, '\n');
}, doIf:function(action, actions) {
  var me = this;
  if (action === '.') {
    me.body.push('if (values) {\n');
  } else {
    if (me.propNameRe.test(action)) {
      me.body.push('if (', me.parseTag(action), ') {\n');
    } else {
      me.body.push('if (', me.addFn(action), me.callFn, ') {\n');
    }
  }
  if (actions.exec) {
    me.doExec(actions.exec);
  }
}, doElseIf:function(action, actions) {
  var me = this;
  if (action === '.') {
    me.body.push('else if (values) {\n');
  } else {
    if (me.propNameRe.test(action)) {
      me.body.push('} else if (', me.parseTag(action), ') {\n');
    } else {
      me.body.push('} else if (', me.addFn(action), me.callFn, ') {\n');
    }
  }
  if (actions.exec) {
    me.doExec(actions.exec);
  }
}, doSwitch:function(action) {
  var me = this, key;
  if (action === '.' || action === '#') {
    key = action === '.' ? 'values' : 'xindex';
    me.body.push('switch (', key, ') {\n');
  } else {
    if (me.propNameRe.test(action)) {
      me.body.push('switch (', me.parseTag(action), ') {\n');
    } else {
      me.body.push('switch (', me.addFn(action), me.callFn, ') {\n');
    }
  }
  me.switches.push(0);
}, doCase:function(action) {
  var me = this, cases = Ext.isArray(action) ? action : [action], n = me.switches.length - 1, match, i;
  if (me.switches[n]) {
    me.body.push('break;\n');
  } else {
    me.switches[n]++;
  }
  for (i = 0, n = cases.length; i < n; ++i) {
    match = me.intRe.exec(cases[i]);
    cases[i] = match ? match[1] : "'" + cases[i].replace(me.aposRe, "\\'") + "'";
  }
  me.body.push('case ', cases.join(': case '), ':\n');
}, doDefault:function() {
  var me = this, n = me.switches.length - 1;
  if (me.switches[n]) {
    me.body.push('break;\n');
  } else {
    me.switches[n]++;
  }
  me.body.push('default:\n');
}, doEnd:function(type, actions) {
  var me = this, L = me.level - 1;
  if (type === 'for' || type === 'foreach') {
    if (actions.exec) {
      me.doExec(actions.exec);
    }
    me.body.push('}\n');
    me.body.push('parent\x3dp', L, ';values\x3dr', L + 1, ';xcount\x3dn' + L + ';xindex\x3di', L, '+1;xkey\x3dk', L, ';\n');
  } else {
    if (type === 'if' || type === 'switch') {
      me.body.push('}\n');
    }
  }
}, doFor:function(action, actions) {
  var me = this, s, L = me.level, up = L - 1, parentAssignment;
  if (action === '.') {
    s = 'values';
  } else {
    if (me.propNameRe.test(action)) {
      s = me.parseTag(action);
    } else {
      s = me.addFn(action) + me.callFn;
    }
  }
  if (me.maxLevel < L) {
    me.maxLevel = L;
    me.body.push('var ');
  }
  if (action === '.') {
    parentAssignment = 'c' + L;
  } else {
    parentAssignment = 'a' + up + '?c' + up + '[i' + up + ']:c' + up;
  }
  me.body.push('i', L, '\x3d0,n', L, '\x3d0,c', L, '\x3d', s, ',a', L, '\x3d', me.createArrayTest(L), ',r', L, '\x3dvalues,p', L, ',k', L, ';\n', 'p', L, '\x3dparent\x3d', parentAssignment, '\n', 'if (c', L, '){if(a', L, '){n', L, '\x3dc', L, '.length;}else if (c', L, '.isMixedCollection){c', L, '\x3dc', L, '.items;n', L, '\x3dc', L, '.length;}else if(c', L, '.isStore){c', L, '\x3dc', L, '.data.items;n', L, '\x3dc', L, '.length;}else{c', L, '\x3d[c', L, '];n', L, '\x3d1;}}\n', 'for (xcount\x3dn', 
  L, ';i', L, '\x3cn' + L + ';++i', L, '){\n', 'values\x3dc', L, '[i', L, ']');
  if (actions.propName) {
    me.body.push('.', actions.propName);
  }
  me.body.push('\n', 'xindex\x3di', L, '+1\n');
  if (actions.between) {
    me.body.push('if(xindex\x3e1){ out.push("', actions.between, '"); } \n');
  }
}, doForEach:function(action, actions) {
  var me = this, L = me.level, up = L - 1, s, parentAssignment;
  if (action === '.') {
    s = 'values';
  } else {
    if (me.propNameRe.test(action)) {
      s = me.parseTag(action);
    } else {
      s = me.addFn(action) + me.callFn;
    }
  }
  if (me.maxLevel < L) {
    me.maxLevel = L;
    me.body.push('var ');
  }
  if (action === '.') {
    parentAssignment = 'c' + L;
  } else {
    parentAssignment = 'a' + up + '?c' + up + '[i' + up + ']:c' + up;
  }
  me.body.push('i', L, '\x3d-1,n', L, '\x3d0,c', L, '\x3d', s, ',a', L, '\x3d', me.createArrayTest(L), ',r', L, '\x3dvalues,p', L, ',k', L, ';\n', 'p', L, '\x3dparent\x3d', parentAssignment, '\n', 'for(k', L, ' in c', L, '){\n', 'xindex\x3d++i', L, '+1;\n', 'xkey\x3dk', L, ';\n', 'values\x3dc', L, '[k', L, '];');
  if (actions.propName) {
    me.body.push('.', actions.propName);
  }
  if (actions.between) {
    me.body.push('if(xindex\x3e1){ out.push("', actions.between, '"); } \n');
  }
}, createArrayTest:'isArray' in Array ? function(L) {
  return 'Array.isArray(c' + L + ')';
} : function(L) {
  return 'ts.call(c' + L + ')\x3d\x3d\x3d"[object Array]"';
}, doExec:function(action, actions) {
  var me = this, name = 'f' + me.definitions.length, guards = me.guards[me.strict ? 0 : 1];
  me.definitions.push('function ' + name + '(' + me.fnArgs + ') {', guards.doTry, ' var $v \x3d values; with($v) {', '  ' + action, ' }', guards.doCatch, '}');
  me.body.push(name + me.callFn + '\n');
}, guards:[{doTry:'', doCatch:''}, {doTry:'try { ', doCatch:' } catch(e) {\n' + 'Ext.log.warn("XTemplate evaluation exception: " + e.message);\n' + '}'}], addFn:function(body) {
  var me = this, name = 'f' + me.definitions.length, guards = me.guards[me.strict ? 0 : 1];
  if (body === '.') {
    me.definitions.push('function ' + name + '(' + me.fnArgs + ') {', ' return values', '}');
  } else {
    if (body === '..') {
      me.definitions.push('function ' + name + '(' + me.fnArgs + ') {', ' return parent', '}');
    } else {
      me.definitions.push('function ' + name + '(' + me.fnArgs + ') {', guards.doTry, ' var $v \x3d values; with($v) {', '  return(' + body + ')', ' }', guards.doCatch, '}');
    }
  }
  return name;
}, parseTag:function(tag) {
  var me = this, m = me.tagRe.exec(tag), name, format, args, math, v;
  if (!m) {
    return null;
  }
  name = m[1];
  format = m[2];
  args = m[3];
  math = m[4];
  if (name === '.') {
    if (!me.validTypes) {
      me.definitions.push('var validTypes\x3d{string:1,number:1,boolean:1};');
      me.validTypes = true;
    }
    v = 'validTypes[typeof values] || ts.call(values) \x3d\x3d\x3d "[object Date]" ? values : ""';
  } else {
    if (name === '#') {
      v = 'xindex';
    } else {
      if (name === '$') {
        v = 'xkey';
      } else {
        if (name.substr(0, 7) === 'parent.') {
          v = name;
        } else {
          if (isNaN(name) && name.indexOf('-') === -1 && name.indexOf('.') !== -1) {
            v = 'values.' + name;
          } else {
            v = "values['" + name + "']";
          }
        }
      }
    }
  }
  if (math) {
    v = '(' + v + math + ')';
  }
  if (format && me.useFormat) {
    args = args ? ',' + args : '';
    if (format.substr(0, 5) !== 'this.') {
      format = 'fm.' + format + '(';
    } else {
      format += '(';
    }
  } else {
    return v;
  }
  return format + v + args + ')';
}, evalTpl:function($) {
  eval($);
  return $;
}, newLineRe:/\r\n|\r|\n/g, aposRe:/[']/g, intRe:/^\s*(\d+)\s*$/, tagRe:/^([\w-\.#\$]+)(?::([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?$/}, function() {
  var proto = this.prototype;
  proto.fnArgs = 'out,values,parent,xindex,xcount,xkey';
  proto.callFn = '.call(this,' + proto.fnArgs + ')';
});
Ext.define('Ext.XTemplate', {extend:Ext.Template, isXTemplate:true, emptyObj:{}, fn:null, strict:false, apply:function(values, parent, xindex, xcount) {
  var buffer = this.applyOut(values, [], parent, xindex, xcount);
  return buffer.length === 1 ? buffer[0] : buffer.join('');
}, applyOut:function(values, out, parent, xindex, xcount) {
  var me = this, compiler;
  if (!me.fn) {
    compiler = new Ext.util.XTemplateCompiler({useFormat:me.disableFormats !== true, definitions:me.definitions, strict:me.strict});
    me.fn = compiler.compile(me.html);
  }
  xindex = xindex || 1;
  xcount = xcount || 1;
  if (me.strict) {
    me.fn(out, values, parent || me.emptyObj, xindex, xcount);
  } else {
    try {
      me.fn(out, values, parent || me.emptyObj, xindex, xcount);
    } catch (e$52) {
      Ext.log.warn('XTemplate evaluation exception: ' + e$52.message);
    }
  }
  return out;
}, compile:function() {
  return this;
}, statics:{get:function(config, source, defaultTpl) {
  var ret = config;
  if (config == null) {
    if (source && defaultTpl) {
      ret = this.getTpl(source, defaultTpl);
    }
  } else {
    if ((config || config === '') && !config.isTemplate) {
      ret = new this(config);
    }
  }
  return ret;
}, getTpl:function(instance, name) {
  var tpl = instance[name], owner;
  if (tpl) {
    if (!tpl.isTemplate) {
      tpl = Ext.XTemplate.get(tpl);
    }
    if (!tpl.owner) {
      if (instance.hasOwnProperty(name)) {
        owner = instance;
      } else {
        for (owner = instance.self.prototype; owner && !owner.hasOwnProperty(name); owner = owner.superclass) {
        }
      }
      owner[name] = tpl;
      tpl.owner = owner;
    }
  }
  return tpl || null;
}}});
Ext.define('Ext.util.translatable.Dom', {extend:Ext.util.translatable.Abstract, alias:'translatable.dom', config:{element:null}, applyElement:function(element) {
  if (!element) {
    return;
  }
  return Ext.get(element);
}, updateElement:function() {
  this.refresh();
}, translateXY:function(x, y) {
  var element = this.getElement();
  if (element && !element.destroyed) {
    this.callParent([x, y]);
  }
}});
Ext.define('Ext.util.translatable.CssPosition', {extend:Ext.util.translatable.Dom, alias:'translatable.cssposition', doTranslate:function(x, y) {
  var domStyle = this.getElement().dom.style;
  if (typeof x === 'number') {
    domStyle.left = x + 'px';
  }
  if (typeof y === 'number') {
    domStyle.top = y + 'px';
  }
}, syncPosition:function() {
  var domStyle = this.getElement().dom.style;
  return [this.x = parseFloat(domStyle.left), this.y = parseFloat(domStyle.top)];
}, destroy:function() {
  var domStyle = this.getElement().dom.style;
  domStyle.left = null;
  domStyle.top = null;
  this.callParent();
}});
Ext.define('Ext.util.translatable.CssTransform', {extend:Ext.util.translatable.Dom, alias:'translatable.csstransform', isCssTransform:true, posRegex:/(\d+)px[^\d]*(\d+)px/, doTranslate:function(x, y) {
  this.getElement().translate(x, y);
}, syncPosition:function() {
  var pos = this.posRegex.exec(this.getElement().dom.style.tranform);
  if (pos) {
    this.x = parseFloat(pos[1]);
    this.y = parseFloat(pos[2]);
  }
  return [this.x, this.y];
}, destroy:function() {
  var element = this.getElement();
  if (element && !element.destroyed) {
    element.dom.style.webkitTransform = null;
  }
  this.callParent();
}});
Ext.define('Ext.scroll.Scroller', {extend:Ext.Evented, alias:'scroller.scroller', mixins:[Ext.mixin.Factoryable, Ext.mixin.Bufferable], isScroller:true, factoryConfig:{defaultType:'native'}, bufferableMethods:{onScrollEnd:100}, config:{direction:undefined, element:null, size:null, x:true, y:true, touchAction:null, translatable:'scrollposition'}, constructor:function(config) {
  var me = this;
  me.position = {x:0, y:0};
  me.configuredSize = {x:false, y:false};
  me.callParent([config]);
}, destroy:function() {
  var me = this;
  me.destroying = true;
  me.destroy = Ext.emptyFn;
  me.doDestroy();
  me.callParent();
}, doDestroy:function() {
  var me = this, partners, id;
  me.component = null;
  partners = me._partners;
  if (partners) {
    for (id in partners) {
      me.removePartner(partners[id].scroller);
    }
  }
  me._partners = null;
  me.setElement(null);
  me.setTranslatable(null);
}, addPartner:function(partner, axis) {
  var me = this, partners = me._partners || (me._partners = {}), otherPartners = partner._partners || (partner._partners = {});
  axis = me.axisConfigs[axis || 'both'];
  partners[partner.getId()] = {scroller:partner, axes:axis, called:false, calledPrimary:false};
  otherPartners[me.getId()] = {scroller:me, axes:axis, called:false, calledPrimary:false};
}, convertX:function(x) {
  return x;
}, ensureVisible:function(el, options) {
  var me = this, position = me.getPosition(), highlight, newPosition, ret;
  if (el) {
    if (el && el.element && !el.isElement) {
      options = el;
      el = options.element;
    }
    options = options || {};
    highlight = options.highlight;
    newPosition = me.getEnsureVisibleXY(el, options);
    if (newPosition.y !== position.y || newPosition.x !== position.x) {
      if (highlight) {
        me.on({scrollend:'doHighlight', scope:me, single:true, args:[el, highlight]});
      }
      ret = me.doScrollTo(newPosition.x, newPosition.y, options.animation);
    } else {
      if (highlight) {
        me.doHighlight(el, highlight);
      }
      ret = Ext.Deferred.getCachedResolved();
    }
  } else {
    ret = Ext.Deferred.getCachedRejected();
  }
  return ret;
}, getPosition:function() {
  return this.position;
}, isInView:function(el, contains) {
  var me = this, c = me.component, result = {x:false, y:false}, myEl = me.getElement(), elRegion, myElRegion;
  if (el && (contains === false || myEl.contains(el) || c && c.owns(el))) {
    myElRegion = myEl.getRegion();
    elRegion = Ext.fly(el).getRegion();
    result.x = elRegion.right > myElRegion.left && elRegion.left < myElRegion.right;
    result.y = elRegion.bottom > myElRegion.top && elRegion.top < myElRegion.bottom;
  }
  return result;
}, refresh:function() {
  this.fireEvent('refresh', this);
  return this;
}, removePartner:function(partner) {
  var partners = this._partners, otherPartners = partner._partners;
  if (partners) {
    delete partners[partner.getId()];
  }
  if (otherPartners) {
    delete otherPartners[this.getId()];
  }
}, scrollBy:function(deltaX, deltaY, animate) {
  var position = this.getPosition();
  if (deltaX) {
    if (deltaX.length) {
      animate = deltaY;
      deltaY = deltaX[1];
      deltaX = deltaX[0];
    } else {
      if (typeof deltaX !== 'number') {
        animate = deltaY;
        deltaY = deltaX.y;
        deltaX = deltaX.x;
      }
    }
  }
  deltaX = typeof deltaX === 'number' ? deltaX + position.x : null;
  deltaY = typeof deltaY === 'number' ? deltaY + position.y : null;
  return this.doScrollTo(deltaX, deltaY, animate);
}, scrollIntoView:function(el, hscroll, animate, highlight) {
  return this.ensureVisible(el, {animation:animate, highlight:highlight, x:hscroll});
}, scrollTo:function(x, y, animation) {
  var me = this, maxPosition;
  if (x) {
    if (Ext.isArray(x)) {
      animation = y;
      y = x[1];
      x = x[0];
    } else {
      if (typeof x !== 'number') {
        animation = y;
        y = x.y;
        x = x.x;
      }
    }
  }
  if (x < 0 || y < 0) {
    maxPosition = me.getMaxPosition();
    if (x < 0) {
      x += maxPosition.x;
    }
    if (y < 0) {
      y += maxPosition.y;
    }
  }
  return me.doScrollTo(x, y, animation);
}, applyElement:function(element) {
  if (element) {
    if (typeof element === 'string' && !Ext.get(element)) {
      Ext.raise('Cannot create Ext.scroll.Scroller instance. ' + "Element with id '" + element + "' not found.");
    }
    if (!element.isElement) {
      element = Ext.get(element);
    }
  }
  return element;
}, updateElement:function(element, oldElement) {
  var me = this, scrollerCls = me.scrollerCls, touchAction;
  if (oldElement && !oldElement.destroyed) {
    oldElement.removeCls(scrollerCls);
  }
  if (element) {
    if (!this.isConfiguring) {
      touchAction = this.getTouchAction();
      if (touchAction) {
        element.setTouchAction(touchAction);
      }
    }
    element.addCls(scrollerCls);
  }
}, updateDirection:function(direction) {
  var me = this, x, y;
  if (!direction) {
    x = me.getX();
    y = me.getY();
    if (x && y) {
      direction = y === 'scroll' && x === 'scroll' ? 'both' : 'auto';
    } else {
      if (y) {
        direction = 'vertical';
      } else {
        if (x) {
          direction = 'horizontal';
        }
      }
    }
    me._direction = direction;
  } else {
    if (direction === 'auto') {
      x = true;
      y = true;
    } else {
      if (direction === 'vertical') {
        x = false;
        y = true;
      } else {
        if (direction === 'horizontal') {
          x = true;
          y = false;
        } else {
          if (direction === 'both') {
            x = 'scroll';
            y = 'scroll';
          }
        }
      }
    }
    me.setX(x);
    me.setY(y);
  }
}, applySize:function(size, oldSize) {
  var num = 'number', configuredSize = this.configuredSize, x, y;
  if (size == null || typeof size === num) {
    x = y = size;
  } else {
    if (size) {
      x = size.x;
      y = size.y;
    }
  }
  if (typeof x === num) {
    configuredSize.x = true;
  } else {
    if (x === null) {
      configuredSize.x = false;
    }
  }
  if (typeof y === num) {
    configuredSize.y = true;
  } else {
    if (y === null) {
      configuredSize.y = false;
    }
  }
  if (x === undefined) {
    x = oldSize ? oldSize.x : null;
  }
  if (y === undefined) {
    y = oldSize ? oldSize.y : null;
  }
  return oldSize && x === oldSize.x && y === oldSize.y ? oldSize : {x:x, y:y};
}, updateTouchAction:function(touchAction) {
  var element = this.getElement();
  if (element) {
    element.setTouchAction(touchAction);
  }
}, statics:{create:function(config, type) {
  return Ext.Factory.scroller(config, type);
}, getScrollingElement:function() {
  return Ext.get(document.scrollingElement || document.documentElement);
}}, privates:{scrollerCls:Ext.baseCSSPrefix + 'scroller', axisConfigs:{x:{x:1, y:0}, y:{x:0, y:1}, both:{x:1, y:1}}, callPartners:function(method, scrollX, scrollY) {
  var me = this, partners = me._partners, axes, id, partner, pos, scroller, x, y;
  if (!me.suspendSync) {
    for (id in partners) {
      partner = partners[id];
      scroller = partner.scroller;
      if (!scroller.isPrimary && !partner.called) {
        partner.called = true;
        axes = partners[id].axes;
        pos = scroller.position;
        x = !axes.x || scrollX === undefined ? pos.x : scrollX;
        y = !axes.y || scrollY === undefined ? pos.y : scrollY;
        scroller[method](x, y, x - pos.x || 0, y - pos.y || 0);
        scroller.callPartners(method, x, y);
        partner.called = false;
      }
    }
  }
}, contains:function(component) {
  var el = this.getElement(), owner = component;
  while (owner && owner !== Ext.Viewport) {
    if (el.contains(owner.el)) {
      return true;
    }
    owner = owner.getRefOwner();
  }
  return false;
}, fireScrollStart:function(x, y, deltaX, deltaY) {
  var me = this, component = me.component;
  me.startX = x - deltaX;
  me.startY = y - deltaY;
  if (me.hasListeners.scrollstart) {
    me.fireEvent('scrollstart', me, x, y);
  }
  if (component && component.onScrollStart) {
    component.onScrollStart(x, y);
  }
  Ext.GlobalEvents.fireEvent('scrollstart', me, x, y);
}, fireScroll:function(x, y, deltaX, deltaY) {
  var me = this, component = me.component;
  if (me.hasListeners.scroll) {
    me.fireEvent('scroll', me, x, y, deltaX, deltaY);
  }
  if (component && component.onScrollMove) {
    component.onScrollMove(x, y, deltaX, deltaY);
  }
  Ext.fireEvent('scroll', me, x, y, deltaX, deltaY);
}, fireScrollEnd:function(x, y) {
  var me = this, component = me.component, deltaX = x - me.startX, deltaY = y - me.startY;
  if (me.hasListeners.scrollend) {
    me.fireEvent('scrollend', me, x, y, deltaX, deltaY);
  }
  if (component && component.onScrollEnd) {
    component.onScrollEnd(x, y, deltaX, deltaY);
  }
  Ext.fireEvent('scrollend', me, x, y, deltaX, deltaY);
}, getEnsureVisibleXY:function(el, options) {
  var position = this.getPosition(), viewport = this.component ? this.component.getScrollableClientRegion() : this.getElement(), newPosition, align;
  if (el && el.element && !el.isElement) {
    options = el;
    el = options.element;
  }
  options = options || {};
  align = options.align;
  if (align) {
    if (Ext.isString(align)) {
      align = {x:options.x === false ? null : align, y:options.y === false ? null : align};
    } else {
      if (Ext.isObject(align)) {
        if (align.x && options.x === false) {
          align.x = null;
        }
        if (align.y && options.y === false) {
          align.y = null;
        }
      }
    }
  }
  newPosition = Ext.fly(el).getScrollIntoViewXY(viewport, position.x, position.y, align);
  newPosition.x = options.x === false ? position.x : newPosition.x;
  newPosition.y = options.y === false ? position.y : newPosition.y;
  return newPosition;
}, onPartnerScroll:function(x, y) {
  this.doScrollTo(x, y);
}, onPartnerScrollStart:function(x, y, deltaX, deltaY) {
  this.isScrolling = true;
  if (deltaX || deltaY) {
    this.doScrollTo(x, y);
  }
}, onPartnerScrollEnd:function() {
  this.isScrolling = false;
}, restoreState:Ext.privateFn, resumePartnerSync:function(syncNow) {
  var me = this, position, x, y;
  if (me.suspendSync) {
    me.suspendSync--;
  }
  if (!me.suspendSync && syncNow) {
    position = me.position;
    x = position.x;
    y = position.y;
    me.callPartners('onPartnerScrollStart', undefined, undefined);
    me.callPartners('fireScrollStart', undefined, undefined);
    me.callPartners('onPartnerScroll', x, y);
    me.callPartners('fireScroll', x, y);
    me.callPartners('onPartnerScrollEnd');
    me.callPartners('fireScrollEnd', x, y);
  }
}, setPrimary:function(isPrimary) {
  var me = this, partners = me._partners, partner, scroller, id;
  if (isPrimary) {
    for (id in partners) {
      partner = partners[id];
      scroller = partner.scroller;
      if (!partner.calledPrimary) {
        partner.calledPrimary = true;
        scroller.setPrimary(false);
        partner.calledPrimary = false;
      }
    }
    me.isScrolling = Ext.isScrolling = true;
  } else {
    if (me.isScrolling) {
      me.cancelOnScrollEnd();
      me.doOnScrollEnd();
    }
  }
  me.isPrimary = isPrimary;
}, suspendPartnerSync:function() {
  this.suspendSync = (this.suspendSync || 0) + 1;
}, syncWithPartners:function() {
  var me = this, partners = me._partners, position = me.position, id, axes, xAxis, yAxis, partner, partnerPosition, x, y, deltaX, deltaY;
  for (id in partners) {
    axes = partners[id].axes;
    xAxis = axes.x;
    yAxis = axes.y;
    partner = partners[id].scroller;
    partnerPosition = partner.position;
    partner.setPrimary(true);
    x = xAxis ? position.x : null;
    y = yAxis ? position.y : null;
    deltaX = deltaY = 0;
    me.onPartnerScrollStart(x, y, 0, 0);
    me.fireScrollStart(x, y, 0, 0);
    x = xAxis ? partnerPosition.x : null;
    y = yAxis ? partnerPosition.y : null;
    deltaX = x === null ? 0 : x - position.x;
    deltaY = y === null ? 0 : y - position.y;
    me.onPartnerScroll(x, y);
    me.fireScroll(x, y, deltaX, deltaY);
    me.onPartnerScrollEnd();
    me.fireScrollEnd(x, y);
    partner.setPrimary(null);
  }
}, applyTranslatable:function(translatable, oldTranslatable) {
  return Ext.Factory.translatable.update(oldTranslatable, translatable, this, 'createTranslatable');
}}, deprecated:{5:{methods:{getScroller:function() {
  return this;
}}}, '5.1.0':{methods:{scrollToTop:function(animate) {
  return this.scrollTo(0, 0, animate);
}, scrollToEnd:function(animate) {
  return this.scrollTo(Infinity, Infinity, animate);
}}}}});
Ext.define('Ext.Component', {extend:Ext.Widget, mixins:[Ext.state.Stateful], alternateClassName:['Ext.lib.Component', 'Ext.Gadget'], xtype:'component', cachedConfig:{padding:null, tabIndex:null}, eventedConfig:{left:null, top:null, right:null, bottom:null, minWidth:null, minHeight:null, maxWidth:null, maxHeight:null, scrollable:null, docked:null, centered:{lazy:true, $value:null}}, config:{displayed:null, html:null, draggable:null, zIndex:null, tpl:null, enterAnimation:null, exitAnimation:null, showAnimation:null, 
hideAnimation:null, tplWriteMode:'overwrite', data:null, contentEl:null, record:null, tooltip:null, axisLock:null, modal:{lazy:true, $value:null}, hideOnMaskTap:null, weight:null, userSelectable:null}, modelValidation:null, defaultBindProperty:'html', isComponent:true, positioned:false, rendered:false, activeAnimation:null, dockPositions:{top:true, right:true, bottom:true, left:true}, bodyElement:null, classCls:Ext.baseCSSPrefix + 'component', floatingCls:Ext.baseCSSPrefix + 'floating', hiddenCls:Ext.baseCSSPrefix + 
'hidden', _scrollableCfg:{x:{x:true, y:false}, y:{x:false, y:true}, horizontal:{x:true, y:false}, vertical:{x:false, y:true}, both:{x:true, y:true}, 'true':{x:true, y:true}, 'false':{x:false, y:false}}, statics:{from:function(el, limit, selector) {
  return Ext.ComponentManager.from(el, limit, selector);
}, fromElement:function(el, limit, selector) {
  return Ext.ComponentManager.from(el, limit, selector);
}}, initialConfig:null, $initParent:null, userSelectableClsMap:{'true':Ext.baseCSSPrefix + 'user-selectable-auto', 'false':Ext.baseCSSPrefix + 'user-selectable-none', all:Ext.baseCSSPrefix + 'user-selectable-all', auto:Ext.baseCSSPrefix + 'user-selectable-auto', text:Ext.baseCSSPrefix + 'user-selectable-text', none:Ext.baseCSSPrefix + 'user-selectable-none'}, constructor:function(config) {
  var me = this, VP = Ext['Viewport'], renderTo = config && config.renderTo, hasListeners, hasResize, el;
  me.lastSize = {};
  me.onInitializedListeners = [];
  if (config) {
    me.initialConfig = config;
    me.$initParent = config.$initParent;
  }
  if (renderTo) {
    config = Ext.apply({}, config);
    delete config.renderTo;
  }
  me.callParent([config]);
  el = me.el;
  if (!me.getRefOwner()) {
    el.addCls(me.rootCls);
  }
  me.refreshPositioned = me.doRefreshPositioned;
  if (me.refreshPositionedOnInitialized) {
    me.refreshPositioned();
  }
  me.initialize();
  me.triggerInitialized();
  if (me.isCentered()) {
    me.center();
  }
  hasListeners = me.hasListeners;
  hasResize = hasListeners.resize;
  if (me.hasListeners.painted) {
    el.on('painted', 'handleElementPainted', me);
  }
  if ((hasResize || me.onResize) && !me.isViewport) {
    if (!hasResize) {
      hasListeners._incr_('resize');
    }
    el.on({scope:me, resize:'handleElementResize', priority:1000});
  }
  if (me.fullscreen && VP) {
    VP.setItemFullScreen(me);
  }
  me.fireEvent('initialize', me);
  if (renderTo) {
    me.setRenderTo(renderTo);
  }
}, beforeInitConfig:function(config) {
  this.beforeInitialize.apply(this, arguments);
}, beforeInitialize:Ext.emptyFn, initialize:Ext.emptyFn, center:function() {
  var me = this, parent = me.getParent(), parentBox, translateXY, xy, size;
  if ((!parent || parent.rendered) && me.shouldRecenter()) {
    translateXY = !!parent;
    parent = parent ? parent.bodyElement : Ext.getBody();
    parentBox = parent.getConstrainRegion();
    size = me.measure();
    xy = [(parentBox.getWidth() - size.width) / 2, (parentBox.getHeight() - size.height) / 2];
    me.needsCenter = false;
    me._centering = true;
    if (me.getFloated()) {
      if (translateXY) {
        xy = parent.reverseTranslateXY(xy);
      }
      me.setXY(xy);
    } else {
      me.setLeft(xy[0]);
      me.setTop(xy[1]);
    }
    me._centering = false;
  } else {
    me.needsCenter = true;
  }
  return me;
}, shouldRecenter:function() {
  return this.rendered && !this.$isShowing && (this.el.isVisible() || this.el.getVisibilityMode() !== Ext.Element.DISPLAY);
}, getModalSibling:function() {
  var me = this, floatRoot = Ext.getFloatRoot().dom, parentWrap, parentContainer, childNodes, c, i;
  for (parentWrap = me.floatParentNode && me.floatParentNode.dom; parentWrap; parentWrap = parentWrap === floatRoot || parentContainer.getRelative() ? null : parentWrap.parentNode) {
    parentContainer = Ext.fly(parentWrap).getData().component;
    childNodes = parentWrap.childNodes;
    for (i = childNodes ? childNodes.length : 0; i-- > 0;) {
      c = Ext.fly(childNodes[i]);
      if (c.hasCls(me.floatWrapCls)) {
        c = c.getData().component;
        if (c && c !== me && c.isVisible() && c.getModal()) {
          return c;
        }
      }
    }
  }
  return null;
}, triggerInitialized:function() {
  var listeners = this.onInitializedListeners, ln = listeners.length, listener, fn, scope, args, i;
  if (!this.initialized) {
    this.initialized = true;
    if (ln > 0) {
      for (i = 0; i < ln; i++) {
        listener = listeners[i];
        fn = listener.fn;
        scope = listener.scope;
        args = listener.args;
        if (typeof fn === 'string') {
          scope[fn].apply(scope, args);
        } else {
          fn.apply(scope, args);
        }
      }
      listeners.length = 0;
    }
  }
}, onInitialized:function(fn, scope, args) {
  var me = this, listeners = me.onInitializedListeners;
  if (!scope) {
    scope = me;
  }
  if (args) {
    args = args.slice();
    args.unshift(me);
  } else {
    args = [me];
  }
  if (me.initialized) {
    if (typeof fn === 'string') {
      scope[fn].apply(scope, args);
    } else {
      fn.apply(scope, args);
    }
  } else {
    listeners.push({fn:fn, scope:scope, args:args});
  }
}, initElement:function() {
  var me = this;
  me.callParent();
  if (!me.bodyElement) {
    me.bodyElement = me.element;
  }
  me.innerElement = me.innerElement || me.bodyElement;
}, initInheritedState:function(inheritedState) {
  var me = this;
  if (me.modelValidation !== null) {
    inheritedState.modelValidation = me.modelValidation;
  }
  me.callParent([inheritedState]);
}, applyScrollable:function(scrollable, oldScrollable) {
  var me = this;
  if (typeof scrollable === 'boolean' || typeof scrollable === 'string') {
    if (!me._scrollableCfg[scrollable]) {
      Ext.raise("'" + scrollable + "' is not a valid value for 'scrollable'");
    }
    scrollable = me._scrollableCfg[scrollable];
  }
  return Ext.Factory.scroller.update(oldScrollable, scrollable, this, 'createScrollable');
}, applyHidden:function(hidden) {
  if (!hidden && this.isConfiguring && this.getFloated()) {
    this.preprocessShow();
  }
  return !!hidden;
}, createScrollable:function(defaults) {
  return Ext.apply({component:this, element:this.getScrollerTarget()}, defaults);
}, getScrollerTarget:function() {
  return this.bodyElement;
}, getScrollableClientRegion:function() {
  var me = this, region = me.getScrollerTarget().getClientRegion(), scroller = me.getScrollable(), scrollbarSize;
  if (scroller && scroller.isVirtualScroller) {
    scrollbarSize = scroller.getScrollbarSize();
    region.adjust(0, -scrollbarSize.width, -scrollbarSize.height, 0);
  }
  return region;
}, updatePadding:function(padding) {
  this.bodyElement.setPadding(padding);
}, updateWeight:function(weight, oldWeight) {
  var me = this, owner = !me.isConfiguring && me.getRefOwner();
  me.weight = weight;
  if (owner && owner.onItemWeightChange) {
    owner.onItemWeightChange(me, weight, oldWeight);
  }
}, applyContentEl:function(contentEl) {
  if (contentEl) {
    return Ext.get(contentEl);
  }
}, updateContentEl:function(newContentEl, oldContentEl) {
  if (oldContentEl) {
    oldContentEl.hide();
    Ext.getBody().append(oldContentEl);
  }
  if (newContentEl) {
    this.setHtml(newContentEl.dom);
    newContentEl.show();
  }
}, createTranslatable:function(config) {
  var me = this, ret = me.callParent([config]);
  if (config && !config.type && me.getFloated()) {
    ret.type = 'csstransform';
  }
  return ret;
}, isCentered:function() {
  return Boolean(this.getCentered());
}, isPositioned:function() {
  return this.positioned;
}, isDocked:function() {
  return Boolean(this.getDocked());
}, applyTop:function(top) {
  return this.filterLengthValue(top);
}, applyRight:function(right) {
  return this.filterLengthValue(right);
}, applyBottom:function(bottom) {
  return this.filterLengthValue(bottom);
}, applyLeft:function(left) {
  return this.filterLengthValue(left);
}, applyMinWidth:function(width) {
  return this.filterLengthValue(width);
}, applyMinHeight:function(height) {
  return this.filterLengthValue(height);
}, applyMaxWidth:function(width) {
  return this.filterLengthValue(width);
}, applyMaxHeight:function(height) {
  return this.filterLengthValue(height);
}, updateTop:function(top) {
  if (!this.$updatingXY) {
    this.element.setTop(top);
  }
  this.refreshPositioned();
}, updateRight:function(right) {
  if (!this.$updatingXY) {
    this.element.setRight(right);
  }
  this.refreshPositioned();
}, updateBottom:function(bottom) {
  if (!this.$updatingXY) {
    this.element.setBottom(bottom);
  }
  this.refreshPositioned();
}, updateLeft:function(left) {
  if (!this.$updatingXY) {
    this.element.setLeft(left);
  }
  this.refreshPositioned();
}, onResize:null, updateMinWidth:function(width) {
  this.element.setMinWidth(width);
}, updateMinHeight:function(height) {
  this.element.setMinHeight(height);
}, updateMaxWidth:function(width) {
  this.element.setMaxWidth(width);
}, updateMaxHeight:function(height) {
  this.element.setMaxHeight(height);
}, applyCentered:function(centered) {
  var me = this, doCenter = me.getLeft() === null && me.getRight() === null && me.getTop() === null && me.getBottom() === null;
  if (doCenter) {
    return !!centered;
  }
}, updateCentered:function(centered) {
  var me = this, resizeParent;
  if (me.getFloated()) {
    if (centered) {
      me.center();
      if (!me.centerResizeListener && !me.needsCenter) {
        resizeParent = me.floatParentNode;
        resizeParent = resizeParent === Ext.floatRoot ? Ext : resizeParent;
        me.centerResizeListener = resizeParent.on({resize:'center', scope:me, destroyable:true});
      }
    } else {
      me.centerResizeListener = Ext.destroy(me.centerResizeListener);
    }
  } else {
    me.el.toggleCls(me.floatingCls, centered);
    if (centered) {
      me.refreshInnerState = Ext.emptyFn;
      if (me.isContainer && (!me.isWidthed() || !me.isHeighted())) {
        me.setAutoSize(true);
      }
      if (me.isPositioned()) {
        me.resetPositioned();
      }
      if (me.isDocked()) {
        me.setDocked(false);
      }
      me.setIsInner(false);
      delete me.refreshInnerState;
    } else {
      me.refreshInnerState();
    }
  }
}, applyDocked:function(docked) {
  var me = this;
  if (!docked) {
    return null;
  }
  if (!/^(top|right|bottom|left)$/.test(docked)) {
    Ext.Logger.error("Invalid docking position of '" + docked.position + "', must be either 'top', 'right', 'bottom', " + "'left' or `null` (for no docking)", me);
    return;
  }
  me.refreshInnerState = Ext.emptyFn;
  if (me.isPositioned()) {
    me.resetPositioned();
  }
  if (me.isCentered()) {
    me.setCentered(false);
  }
  me.setIsInner(false);
  delete me.refreshInnerState;
  return docked;
}, getDisplayed:function() {
  return !this.getHidden();
}, setDisplayed:function(displayed) {
  var me = this, hidden = me.getHidden() !== false;
  if (displayed === hidden) {
    me._displayed = displayed;
    me.updateDisplayed(displayed, !displayed);
  }
  return me;
}, updateDisplayed:function(displayed) {
  this[displayed ? 'show' : 'hide']();
}, updateDocked:function(docked, oldDocked) {
  var me = this;
  if (!me.isConfiguring) {
    me.fireEvent('afterdockedchange', me, docked, oldDocked);
    if (!docked) {
      me.refreshInnerState();
    }
  }
}, updateUserSelectable:function(newSelectable, oldSelectable) {
  var me = this, map = me.userSelectableClsMap, el = me.el, name, childEl;
  if (typeof oldSelectable === 'boolean' || typeof oldSelectable === 'string') {
    el.removeCls(map[oldSelectable]);
  } else {
    for (name in oldSelectable) {
      childEl = me[name];
      if (!childEl || !childEl.isElement) {
        Ext.raise('Element not found: "' + name + '"');
      }
      childEl.removeCls(map[oldSelectable[name]]);
    }
  }
  if (typeof newSelectable === 'boolean' || typeof newSelectable === 'string') {
    el.addCls(map[newSelectable]);
  } else {
    for (name in newSelectable) {
      childEl = me[name];
      if (!childEl || !childEl.isElement) {
        Ext.raise('Element not found: "' + name + '"');
      }
      childEl.addCls(map[newSelectable[name]]);
    }
  }
}, resetPositioned:function() {
  var me = this;
  me.setTop(null);
  me.setRight(null);
  me.setBottom(null);
  me.setLeft(null);
}, refreshPositioned:function() {
  this.refreshPositionedOnInitialized = true;
}, doRefreshPositioned:function() {
  var me = this, positioned = !me.getConfig('floated', false, true) && (me.getTop() !== null || me.getBottom() !== null || me.getRight() !== null || me.getLeft() !== null);
  if (positioned !== this.positioned) {
    me.positioned = positioned;
    if (positioned) {
      me.refreshInnerState = Ext.emptyFn;
      if (me.isContainer && (!me.isWidthed() || !me.isHeighted())) {
        me.setAutoSize(true);
      }
      if (me.isCentered()) {
        me.setCentered(false);
      }
      if (me.isDocked()) {
        me.setDocked(false);
      }
      me.setIsInner(false);
      delete me.refreshInnerState;
    }
    me.element.toggleCls(me.floatingCls, positioned);
    if (me.initialized) {
      me.fireEvent('floatingchange', me, positioned);
      me.fireEvent('positionedchange', me, positioned);
    }
    if (!positioned) {
      me.refreshInnerState();
    }
  }
}, applyZIndex:function(zIndex) {
  if (!zIndex && zIndex !== 0) {
    zIndex = null;
  }
  if (zIndex !== null) {
    zIndex = Number(zIndex);
    if (isNaN(zIndex)) {
      zIndex = null;
    }
  }
  return zIndex;
}, updateZIndex:function(zIndex) {
  var element = this.element, modal = !this.getFloated() && this.getModal(), domStyle;
  if (element && !element.destroyed) {
    domStyle = element.dom.style;
    if (zIndex !== null) {
      domStyle.setProperty('z-index', zIndex, 'important');
    } else {
      domStyle.removeProperty('z-index');
    }
  }
  if (modal && !modal.destroyed) {
    modal.setZIndex(zIndex - 1);
  }
}, getInnerHtmlElement:function() {
  var me = this, innerHtmlElement = me.innerHtmlElement;
  if (!innerHtmlElement || !innerHtmlElement.dom || !innerHtmlElement.dom.parentNode) {
    me.innerHtmlElement = innerHtmlElement = Ext.Element.create({cls:Ext.baseCSSPrefix + 'innerhtml'});
    me.getRenderTarget().appendChild(innerHtmlElement);
  }
  return innerHtmlElement;
}, updateHtml:function(html) {
  var innerHtmlElement;
  if (!this.destroyed) {
    innerHtmlElement = this.getInnerHtmlElement();
    if (Ext.isElement(html)) {
      innerHtmlElement.setHtml('');
      innerHtmlElement.append(html);
    } else {
      innerHtmlElement.setHtml(html);
    }
  }
}, updateHidden:function(hidden, oldHidden) {
  var me = this, element = me.renderElement, modal = me.getModal(), name;
  if (me.rendered) {
    if (modal && !modal.destroyed) {
      if (me.getFloated()) {
        if (hidden) {
          modal = me.getModalSibling();
          if (modal) {
            modal.showModalMask();
          } else {
            me.hideModalMask();
          }
        } else {
          me.showModalMask();
        }
      } else {
        if (modal !== true) {
          modal.setZIndex(me.getZIndex() - 1);
          if (modal.getHidden() !== hidden) {
            modal.setHidden(hidden);
          }
        }
      }
    }
    if (!me.destroying && element && !element.destroyed) {
      element.toggleCls(me.hiddenCls, hidden);
    }
    me.callParent([hidden, oldHidden]);
  } else {
    element.toggleCls(me.hiddenCls, hidden);
    me.callParent([hidden, oldHidden]);
  }
  if (!me.isConfiguring && !me.destroying) {
    name = hidden ? 'hide' : 'show';
    if (me.hasListeners[name]) {
      me.fireEvent(name, me);
    }
    me[hidden ? 'afterHide' : 'afterShow'](me);
  }
}, hide:function(animation) {
  var me = this, activeAnim = me.activeAnimation, modal;
  if (me.isVisible()) {
    if (me.hasListeners.beforehide && me.fireEvent('beforehide', me) === false) {
      return;
    }
    if (me.beforeHide() === false) {
      return;
    }
    me.viewportResizeListener = Ext.destroy(me.viewportResizeListener);
    me.setCurrentAlignmentInfo(null);
    if (activeAnim) {
      activeAnim.on({animationend:function() {
        me.hide(animation);
      }, single:true});
      return me;
    }
    if (!me.getHidden()) {
      if (animation === undefined || animation && !Ext.isObject(animation)) {
        animation = me.getHideAnimation();
      }
      if (animation) {
        me.on({beforehiddenchange:'onBeforeHiddenChange', scope:me, single:true, args:[animation]});
      }
      me.setHidden(true);
    }
    if (!me.getFloated()) {
      modal = me.getModal();
      if (modal && modal !== true && !modal.destroyed) {
        modal.setHidden(true);
      }
    }
  } else {
    me.setHidden(true);
  }
  return me;
}, preprocessShow:function(component, alignment, options) {
  var me = this, hideMode = me.getHideMode(), hidden;
  if (me.isContainer) {
    me.getItems();
  }
  me.getHtml();
  if (me.getFloated()) {
    hidden = (!hideMode || hideMode === 'display') && me.getHidden();
    if (me.rendered) {
      if (hidden) {
        me.setVisibility(true);
        me._hidden = false;
      }
    } else {
      hidden = hidden !== false;
      me.findFloatParent(hidden);
    }
    if (component) {
      me.notifyIf();
      me.alignTo(component, alignment, options);
    } else {
      if (me.isCentered()) {
        me.notifyIf();
        me.updateCentered(true);
      } else {
        me.syncXYPosition();
      }
    }
    if (me.getModal()) {
      me.showModalMask();
    }
    if (me.getToFrontOnShow()) {
      me.toFront();
    } else {
      me.syncAlwaysOnTop();
    }
    if (hidden) {
      me.setVisibility(false);
      me._hidden = true;
    }
  }
}, showBy:function(component, alignment, options) {
  var me = this, offset;
  if (Ext.isArray(options)) {
    offset = options;
    options = {offset:offset};
  }
  if (me.isVisible()) {
    me.alignTo(component, alignment, options);
  } else {
    if (!me.getFloated()) {
      if (!me.getParent()) {
        me.setFloated(true);
      } else {
        me.positioned = true;
      }
    }
    me.alignToArgs = [component, alignment, options];
    me.show({animation:true, alignment:{component:component, alignment:alignment, options:options}});
  }
}, show:function(animation, options) {
  var me = this, hidden = me.getHidden(), floated = me.getFloated(), alignment, modal;
  if (animation && typeof animation === 'object' && 'animation' in animation) {
    options = animation;
    animation = options.animation;
  } else {
    options = Ext.apply({animation:animation}, options);
  }
  if (me.hasListeners.beforeshow && me.fireEvent('beforeshow', me, options) === false) {
    return false;
  }
  if (me.beforeShow(options) === false) {
    return;
  }
  alignment = options.alignment || {};
  me.preprocessShow(alignment.component, alignment.alignment, alignment.options);
  if (me.activeAnimation) {
    if (!me.$isShowing) {
      me.activeAnimation.on({animationend:function() {
        if (!me.destroying && !me.destroyed) {
          me.show(animation, options);
        }
      }, single:true});
    }
    return me;
  }
  if (hidden || hidden === null) {
    if (animation === undefined || animation && !Ext.isObject(animation)) {
      animation = me.getShowAnimation();
    }
    if (animation && !me.isConfiguring) {
      me.on({beforehiddenchange:'onBeforeHiddenChange', scope:me, single:true, args:[animation]});
    }
    me.setHidden(false);
  }
  if (!floated) {
    modal = me.getModal();
    if (modal && modal.setHidden) {
      modal.setHidden(false);
    }
  }
  return me;
}, onAnimationStart:function(hidden, animation, data) {
  var me = this, element = me.element, fromTransform = data.from.transform, toTransform = data.to.transform;
  if (!hidden) {
    me.renderElement.show();
    element.removeCls(me.hiddenCls);
    if (me.needsCenter) {
      me.center();
    }
  }
  me.$isShowing = true;
  if (me.getFloated() && fromTransform && toTransform && !(fromTransform.translateX | toTransform.translateX | fromTransform.translateY | toTransform.translateY)) {
    fromTransform.translateX = toTransform.translateX = null;
    fromTransform.translateY = toTransform.translateY = null;
  }
}, onBeforeHiddenChange:function(animation, component, hidden, oldHidden, controller) {
  var me = this;
  if (animation && (!hidden || hidden && me.isPainted())) {
    if (!animation.isAnimation) {
      animation = hidden ? me.createHideAnimation(animation) : me.createShowAnimation(animation);
      animation = Ext.Factory.animation(animation);
    }
    me.activeAnimation = animation;
    animation.on({animationstart:'onAnimationStart', scope:me, single:true, args:[hidden]});
    if (!Ext.isEmpty(hidden)) {
      animation.setOnEnd(function() {
        me.activeAnimation = null;
        me.$isShowing = false;
        if (!me.destroyed) {
          controller.resume();
          if (me.destroying || me.destroyed) {
            return;
          }
          if (me.getFloated()) {
            me.syncXYPosition();
          }
        }
      });
      if (!hidden) {
        me._hidden = false;
      }
      controller.pause();
    }
    Ext.Animator.run(animation);
  }
}, setVisibility:function(isVisible) {
  this.renderElement.setVisible(isVisible);
}, isRendered:function() {
  return this.rendered;
}, isPainted:function() {
  return this.renderElement.isPainted();
}, applyTpl:function(tpl) {
  return Ext.XTemplate.get(tpl);
}, updateTpl:function(tpl) {
  if (!this.isConfiguring) {
    if (tpl) {
      this.doUpdateTpl();
    } else {
      this.getInnerHtmlElement().setHtml('');
    }
  }
}, applyData:function(data) {
  if (Ext.isObject(data)) {
    return Ext.apply({}, data);
  } else {
    if (!data) {
      data = {};
    }
  }
  return data;
}, updateData:function(newData) {
  var me = this;
  if (newData) {
    me.doUpdateTpl(newData);
    if (!me.isConfiguring) {
      me.fireEvent('updatedata', me, newData);
    }
  }
}, applyRecord:function(config) {
  if (config && Ext.isObject(config) && config.isModel) {
    return config;
  }
  return null;
}, updateRecord:function(newRecord, oldRecord) {
  var me = this;
  if (oldRecord) {
    oldRecord.unjoin(me);
  }
  if (!newRecord) {
    me.updateData('');
  } else {
    newRecord.join(me);
    me.doUpdateTpl(newRecord.getData(true));
  }
}, afterEdit:function() {
  this.updateRecord(this.getRecord());
}, afterErase:function() {
  this.setRecord(null);
}, getXTypes:function() {
  return this.xtypesChain.join('/');
}, applyDraggable:function(draggable, existing) {
  if (existing) {
    if (draggable) {
      existing.setConfig(draggable);
    } else {
      existing.destroy();
    }
  } else {
    if (draggable) {
      draggable = this.createDraggable(draggable);
      draggable = new Ext.drag.Source(draggable);
      if (this.initDragConstraints) {
        draggable.on('initdragconstraints', 'initDragConstraints', this);
      }
    }
  }
  return draggable;
}, createDraggable:function(draggable) {
  var me = this, listeners = draggable.listeners;
  draggable = Ext.apply({autoDestroy:false, component:me, ownerCmp:me, local:true}, draggable);
  if (listeners && listeners.scope === 'this') {
    draggable.listeners = listeners = Ext.apply({}, listeners);
    listeners.scope = me;
  }
  return draggable;
}, updateDraggable:function(dragger, existing) {
  if (existing) {
    if (dragger) {
      existing.setConfig(dragger);
    } else {
      existing.destroy();
    }
  }
}, onModalMaskTap:function(e) {
  if (this.getHideOnMaskTap()) {
    this.hide();
  }
}, translateAxis:function(axis, value, animation) {
  var x, y;
  if (axis === 'x') {
    x = value;
  } else {
    y = value;
  }
  return this.translate(x, y, animation);
}, alignTo:function(component, alignment, options) {
  var me = this;
  if (!me.viewportResizeListener) {
    me.viewportResizeListener = Ext.on({resize:'onViewportResize', scope:me, destroyable:true});
  }
  me.aligning = true;
  me.callParent([component, alignment, Ext.apply({axisLock:me.getAxisLock()}, options)]);
  me.aligning = false;
}, onViewportResize:function() {
  if (this.isVisible()) {
    this.realign();
  }
}, showAt:function(x, y) {
  var me = this;
  if (me.getFloated() || me.isPositioned()) {
    if (arguments.length === 1) {
      if (x.x) {
        y = x.y;
        x = x.x;
      } else {
        y = x[1];
        x = x[0];
      }
    }
    me.show();
    if (me.isPositioned()) {
      me.setLeft(x);
      me.setTop(y);
    } else {
      me.setX(x);
      me.setY(y);
    }
  }
  return me;
}, onAdded:function(parent, instanced) {
  var me = this, modal;
  me.callParent([parent, instanced]);
  if (!me.getFloated()) {
    modal = me.getModal();
    if (modal) {
      parent.insertBefore(modal, me);
      modal.setZIndex(me.getZIndex() - 1);
    }
  }
  me.el.removeCls(me.rootCls);
}, onRemoved:function(destroying) {
  if (!destroying) {
    this.el.addCls(this.rootCls);
  }
  this.callParent([destroying]);
}, applyTooltip:function(tooltip) {
  if (tooltip) {
    if (tooltip.isInstance) {
      tooltip.setTarget(this);
      return tooltip;
    } else {
      if (typeof tooltip === 'string') {
        tooltip = {html:tooltip};
      } else {
        tooltip = Ext.merge({}, tooltip);
      }
    }
    if (tooltip.autoCreate || tooltip.autoHide === false) {
      delete tooltip.autoCreate;
      tooltip.target = this;
      tooltip.xtype = tooltip.xtype || 'tooltip';
      tooltip = Ext.create(tooltip);
    } else {
      delete tooltip.xtype;
    }
  }
  return tooltip;
}, updateTooltip:function(tooltip, oldTooltip) {
  var el = this.el, data, manager, target, tip;
  if (oldTooltip) {
    if (oldTooltip.isInstance) {
      Ext.destroy(oldTooltip);
    } else {
      target = Ext.fly(oldTooltip.target);
      data = target && target.peekData();
      if (data) {
        delete data.qtip;
      }
    }
  }
  if (tooltip && !tooltip.isInstance) {
    el.getData().qtip = tooltip;
    manager = Ext['tip'];
    manager = manager && manager.Manager;
    manager = manager && manager.instance;
    if (manager) {
      tip = manager.tip;
      if (tip.currentTarget.dom === el.dom) {
        manager.onBeforeShow(tip);
      }
    }
  }
}, applyModal:function(modal, currentModal) {
  var isVisible;
  if (this.getFloated()) {
    return !!modal;
  }
  isVisible = this.isVisible();
  if (modal === false) {
    modal = true;
    isVisible = false;
  }
  currentModal = Ext.factory(modal, Ext['Mask'], typeof currentModal === 'boolean' ? null : currentModal);
  if (currentModal) {
    currentModal.setVisibility(isVisible);
    currentModal.on('tap', 'onModalMaskTap', this);
  }
  return currentModal;
}, updateModal:function(modal) {
  var me = this, parent = me.getParent(), positionEl = (me.floatWrap || me.element).dom, topModal;
  if (me.getFloated()) {
    if (modal) {
      if (me.isVisible() && !positionEl.nextSibling) {
        me.showModalMask();
      }
    } else {
      topModal = me.getModalSibling();
      if (topModal) {
        topModal.showModalMask();
      } else {
        me.hideModalMask();
      }
    }
  } else {
    if (parent) {
      if (modal) {
        parent.insertBefore(modal, me);
        modal.setZIndex(me.getZIndex() - 1);
      } else {
        parent.remove(modal);
      }
    }
  }
}, applyHideAnimation:function(hideAnimation, oldHideAnimation) {
  return Ext.Factory.animation.update(oldHideAnimation, hideAnimation, this, 'createHideAnimation');
}, createHideAnimation:function(defaults) {
  return Ext.apply({type:'fadeOut', element:this.element}, defaults);
}, applyShowAnimation:function(showAnimation, oldShowAnimation) {
  return Ext.Factory.animation.update(oldShowAnimation, showAnimation, this, 'createShowAnimation');
}, createShowAnimation:function(defaults) {
  return Ext.apply({type:'fadeIn', element:this.element}, defaults);
}, doDestroy:function() {
  var me = this, sibling;
  if (me.isVisible()) {
    me.revertFocus();
    if (me.getModal() && me.getFloated()) {
      sibling = me.getModalSibling();
      if (sibling) {
        sibling.showModalMask();
      } else {
        me.hideModalMask();
      }
    }
  }
  if (me.hasListeners.destroy) {
    me.fireEvent('destroy', me);
  }
  me.destroyMembers('modal', 'innerHtmlElement', 'scrollerElement', 'scrollable', 'showAnimation', 'hideAnimation', 'centerResizeListener', 'visibleListener');
  me.setPlugins(null);
  me.setRecord(null);
  me.setTooltip(null);
  me.callParent();
}, privates:{preciseWidth:false, clearWhenVisible:function(fn) {
  var me = this, pending = me.pendingVisible;
  if (pending) {
    delete pending[fn];
    if (Ext.Object.isEmpty(pending)) {
      me.pendingVisible = null;
      me.visibleListener = Ext.destroy(me.visibleListener);
    }
  }
}, convertToLocalXY:function(xy) {
  var me = this, pageXY = me.element.getXY(), x = 0, y = 0;
  if (me.isPositioned()) {
    x = me.getLeft() || 0;
    y = me.getTop() || 0;
  } else {
    x = me.getX() || 0;
    y = me.getY() || 0;
  }
  return [xy[0] - pageXY[0] + x, xy[1] - pageXY[1] + y];
}, doAddListener:function(name, fn, scope, options, order, caller, manager) {
  var me = this, el = me.element;
  if (me.initialized) {
    if (name === 'painted') {
      if (!me.hasListeners.painted) {
        el.on('painted', 'handleElementPainted', me);
      }
    } else {
      if (name === 'resize' && !me.isViewport) {
        if (!me.hasListeners.resize) {
          el.on({scope:me, resize:'handleElementResize', priority:1000});
        }
      }
    }
  }
  return me.callParent([name, fn, scope, options, order, caller, manager]);
}, doRemoveListener:function(name, fn, scope) {
  var me = this, el = me.element, ret = me.callParent([name, fn, scope]);
  if (ret && me.initialized) {
    if (name === 'painted') {
      if (!me.hasListeners.painted) {
        el.un('painted', 'handleElementPainted', me);
      }
    } else {
      if (name === 'resize' && !me.isViewport) {
        if (!me.hasListeners.resize) {
          el.un('resize', 'handleElementResize', me);
        }
      }
    }
  }
  return ret;
}, doUpdateTpl:function(data) {
  var me = this, tpl = me.getTpl(), writeMode;
  if (tpl) {
    writeMode = me.getTplWriteMode();
    data = data || me.getData() || {};
    tpl[writeMode](me.getInnerHtmlElement(), data);
  }
}, getRenderTarget:function() {
  var scroller = this.getScrollable();
  return scroller && scroller.isVirtualScroller ? scroller.getInnerElement() : this.bodyElement;
}, handleElementPainted:function(el) {
  this.fireEvent('painted', this, el);
}, handleElementResize:function(el, info) {
  var me = this, ceil = Math.ceil, lastSize = me.lastSize, oldWidth = lastSize.width || null, oldHeight = lastSize.height || null, w, h;
  if (info.flag) {
    w = info.width;
    h = info.height;
    if (w === 0 && h === 0) {
      return;
    }
    if (!me.preciseWidth) {
      w = ceil(w);
      h = ceil(h);
    }
    lastSize.width = w;
    lastSize.height = h;
    if (me.onResize) {
      me.onResize(w, h, oldWidth, oldHeight, info);
    }
    if (me.isCentered()) {
      me.center();
    }
    me.fireEvent('resize', this, w, h, oldWidth, oldHeight, info);
  }
}, handleGlobalShow:function(c) {
  this.maybeRunWhenVisible(c);
}, handleGlobalExpand:function(c) {
  this.maybeRunWhenVisible(c);
}, maybeRunWhenVisible:function(c) {
  var me = this;
  if ((c === me || me.isDescendantOf(c)) && me.canLayoutChildren()) {
    me.runWhenVisible();
  }
}, canLayoutChildren:function() {
  var current = this;
  while (current) {
    if (!current.isVisible() || current.hasHiddenContent()) {
      return false;
    }
    current = current.getRefOwner();
  }
  return true;
}, runWhenVisible:function() {
  var me = this, pending = me.pendingVisible, key;
  me.pendingVisible = null;
  me.visibleListener = Ext.destroy(me.visibleListener);
  for (key in pending) {
    me[key].apply(me, pending[key]);
  }
}, whenVisible:function(fn, args) {
  var me = this, listener = me.visibleListener, pending = me.pendingVisible, visible = me.canLayoutChildren();
  args = args || Ext.emptyArray;
  if (!visible && !listener) {
    me.visibleListener = Ext.on({scope:me, show:'handleGlobalShow', expand:'handleGlobalExpand', destroyable:true});
  }
  if (visible) {
    if (pending) {
      pending[fn] = args;
      me.runWhenVisible();
    } else {
      me[fn].apply(me, args);
    }
  } else {
    if (!pending) {
      me.pendingVisible = pending = {};
    }
    pending[fn] = args;
  }
  return visible;
}, setXY:function(x, y, animation) {
  var me = this, floated = me.getFloated();
  if (typeof x !== 'number') {
    animation = y;
    y = x[1];
    x = x[0];
  }
  me.$updatingXY = true;
  if (floated) {
    if (x != null) {
      me.setX(x);
    }
    if (y != null) {
      me.setY(y);
    }
  } else {
    if (x != null) {
      me.setLeft(x);
    }
    if (y != null) {
      me.setTop(y);
    }
  }
  me.$updatingXY = false;
  if (floated) {
    me.syncXYPosition(animation);
  } else {
    me.translate(x, y, animation);
  }
}, syncXYPosition:function(animation) {
  var me = this;
  if (!me.aligning) {
    me.viewportResizeListener = Ext.destroy(me.viewportResizeListener);
  }
  me.callParent([animation]);
}}, deprecated:{'6.2.0':{methods:{resetFloating:'resetPositioned'}}, '6.5':{configs:{styleHtmlCls:null, styleHtmlContent:null}}}}, function(Cls) {
  if (!document.querySelector('meta[name\x3dviewport]')) {
    Ext.log.warn('Ext JS requires a viewport meta tag in order to function correctly on mobile ' + 'devices. Please add the following tag to the \x3chead\x3e of your html page: \n ' + '\x3cmeta name\x3d"viewport" content\x3d"width\x3ddevice-width, initial-scale\x3d1, ' + 'maximum-scale\x3d10, user-scalable\x3dyes"\x3e');
  }
});
Ext.define('Ext.mixin.Responsive', function(Responsive) {
  return {extend:Ext.Mixin, mixinConfig:{id:'responsive', after:{destroy:'destroy'}}, config:{responsiveConfig:{$value:undefined, merge:function(newValue, oldValue, target, mixinClass) {
    var marker, entry, ret, rule;
    if (!newValue) {
      return oldValue;
    }
    ret = oldValue ? Ext.Object.chain(oldValue) : {};
    marker = Responsive.context;
    for (rule in newValue) {
      if (!mixinClass || !(rule in ret)) {
        entry = newValue[rule];
        if (entry.fn !== marker) {
          entry = {fn:marker, config:entry};
        }
        ret[rule] = entry;
      }
    }
    return ret;
  }}, responsiveFormulas:{$value:null, merge:function(newValue, oldValue, target, mixinClass) {
    return this.mergeNew(newValue, oldValue, target, mixinClass);
  }}}, destroy:function() {
    Responsive.unregister(this);
  }, privates:{statics:{active:false, all:{}, _configNames:['responsiveConfig', 'responsiveFormulas'], context:Ext.Object.chain(Ext.platformTags), count:0, nextId:0, activate:function() {
    Responsive.active = true;
    Responsive.updateContext();
    Ext.on('resize', Responsive.onResize, Responsive);
  }, deactivate:function() {
    Responsive.active = false;
    Ext.un('resize', Responsive.onResize, Responsive);
  }, notify:function() {
    var all = Responsive.all, context = Responsive.context, timer = Responsive.timer, id;
    if (timer) {
      Responsive.timer = Ext.unasap(timer);
    }
    Responsive.updateContext();
    Ext.suspendLayouts();
    Ext.fireEvent('beforeresponsiveupdate', context);
    for (id in all) {
      all[id].setupResponsiveContext();
    }
    Ext.fireEvent('beginresponsiveupdate', context);
    for (id in all) {
      all[id].updateResponsiveState();
    }
    Ext.fireEvent('responsiveupdate', context);
    Ext.resumeLayouts(true);
  }, onResize:function() {
    if (!Responsive.timer) {
      Responsive.timer = Ext.asap(Responsive.onTimer);
    }
  }, onTimer:function() {
    Responsive.timer = null;
    Responsive.notify();
  }, register:function(responder) {
    var id = responder.$responsiveId;
    if (!id) {
      responder.$responsiveId = id = ++Responsive.nextId;
      Responsive.all[id] = responder;
      if (++Responsive.count === 1) {
        Responsive.activate();
      }
    }
  }, unregister:function(responder) {
    var id = responder.$responsiveId;
    if (id in Responsive.all) {
      responder.$responsiveId = null;
      delete Responsive.all[id];
      if (--Responsive.count === 0) {
        Responsive.deactivate();
      }
    }
  }, updateContext:function() {
    var El = Ext.Element, width = El.getViewportWidth(), height = El.getViewportHeight(), context = Responsive.context;
    context.width = width;
    context.height = height;
    context.tall = width < height;
    context.wide = !context.tall;
    context.landscape = context.portrait = false;
    if (!context.platform) {
      context.platform = Ext.platformTags;
    }
    context[Ext.dom.Element.getOrientation()] = true;
  }}, afterClassMixedIn:function(targetClass) {
    var proto = targetClass.prototype, responsiveConfig = proto.responsiveConfig, responsiveFormulas = proto.responsiveFormulas, config;
    if (responsiveConfig || responsiveFormulas) {
      config = {};
      if (responsiveConfig) {
        delete proto.responsiveConfig;
        config.responsiveConfig = responsiveConfig;
      }
      if (responsiveFormulas) {
        delete proto.responsiveFormulas;
        config.responsiveFormulas = responsiveFormulas;
      }
      targetClass.getConfigurator().add(config);
    }
    targetClass.addConfigTransform('transformResponsiveConfig', 10);
  }, applyResponsiveConfig:function(rules) {
    var rule;
    for (rule in rules) {
      rules[rule].fn = Ext.createRuleFn(rule);
    }
    return rules;
  }, applyResponsiveFormulas:function(formulas) {
    var fn, name, ret;
    if (formulas) {
      ret = {};
      for (name in formulas) {
        if (Ext.isString(fn = formulas[name])) {
          fn = Ext.createRuleFn(fn);
        }
        ret[name] = fn;
      }
    }
    return ret;
  }, getResponsiveState:function() {
    var context = Responsive.context, rules = this.getResponsiveConfig(), entry, ret, rule;
    if (rules) {
      ret = {};
      for (rule in rules) {
        entry = rules[rule];
        if (entry.fn.call(this, context)) {
          Ext.merge(ret, entry.config);
        }
      }
    }
    return ret;
  }, setupResponsiveContext:function() {
    var formulas = this.getResponsiveFormulas(), context = Responsive.context, name;
    if (formulas) {
      for (name in formulas) {
        context[name] = formulas[name].call(this, context);
      }
    }
  }, transformResponsiveConfig:function(instanceConfig, configurator) {
    var me = this, ret = instanceConfig, state;
    if (configurator.hoistConfigs(me, instanceConfig, Responsive._configNames)) {
      Responsive.register(me);
      me.setupResponsiveContext();
      state = me.getResponsiveState();
      if (state) {
        ret = Ext.merge({}, instanceConfig, state);
        delete ret.responsiveConfig;
        delete ret.responsiveFormulas;
      }
    }
    return ret;
  }, updateResponsiveState:function() {
    var config = this.getResponsiveState();
    this.setConfig(config);
  }}};
});
Ext.define('Ext.Responsive', {override:'Ext.Widget', mixins:[Ext.mixin.Responsive]});
Ext.define('Ext.theme.material.Widget', {override:'Ext.Widget', statics:{floatInset:16 / (window.devicePixelRatio || 1)}});
Ext.define('Ext.ProgressBase', {mixinId:'progressbase', config:{value:0, textTpl:null}, applyTextTpl:function(textTpl) {
  if (!textTpl.isTemplate) {
    textTpl = new Ext.XTemplate(textTpl);
  }
  return textTpl;
}, applyValue:function(value) {
  return value || 0;
}});
Ext.define('Ext.Progress', {extend:Ext.Gadget, xtype:['progress', 'progressbarwidget'], alternateClassName:'Ext.ProgressBarWidget', mixins:[Ext.ProgressBase], config:{text:null, animate:false}, cachedConfig:{textCls:Ext.baseCSSPrefix + 'progress-text', cls:null}, baseCls:Ext.baseCSSPrefix + 'progress', template:[{reference:'backgroundEl'}, {reference:'barEl', cls:Ext.baseCSSPrefix + 'progress-bar', children:[{reference:'textEl'}]}], defaultBindProperty:'value', updateCls:function(cls, oldCls) {
  var el = this.element;
  if (oldCls) {
    el.removeCls(oldCls);
  }
  if (cls) {
    el.addCls(cls);
  }
}, updateUi:function(ui, oldUi) {
  var element = this.element, barEl = this.barEl, baseCls = this.baseCls + '-';
  this.callParent([ui, oldUi]);
  if (oldUi) {
    element.removeCls(baseCls + oldUi);
    barEl.removeCls(baseCls + 'bar-' + oldUi);
  }
  element.addCls(baseCls + ui);
  barEl.addCls(baseCls + 'bar-' + ui);
}, updateTextCls:function(textCls) {
  this.backgroundEl.addCls(textCls + ' ' + textCls + '-back');
  this.textEl.addCls(textCls);
}, updateValue:function(value, oldValue) {
  var me = this, textTpl = me.getTextTpl();
  if (textTpl) {
    me.setText(textTpl.apply({value:value, percent:Math.round(value * 100)}));
  }
  if (!me.isConfiguring && me.getAnimate()) {
    me.stopBarAnimation();
    me.startBarAnimation(Ext.apply({from:{width:oldValue * 100 + '%'}, to:{width:value * 100 + '%'}}, me.animate));
  } else {
    me.barEl.setStyle('width', value * 100 + '%');
  }
}, updateText:function(text) {
  this.backgroundEl.setHtml(text);
  this.textEl.setHtml(text);
}, doDestroy:function() {
  this.stopBarAnimation();
  this.callParent();
}, privates:{startBarAnimation:Ext.privateFn, stopBarAnimation:Ext.privateFn}});
Ext.define('Ext.fx.State', {isAnimatable:{'background-color':true, 'background-image':true, 'background-position':true, 'border-bottom-color':true, 'border-bottom-width':true, 'border-color':true, 'border-left-color':true, 'border-left-width':true, 'border-right-color':true, 'border-right-width':true, 'border-spacing':true, 'border-top-color':true, 'border-top-width':true, 'border-width':true, 'bottom':true, 'color':true, 'crop':true, 'font-size':true, 'font-weight':true, 'height':true, 'left':true, 
'letter-spacing':true, 'line-height':true, 'margin-bottom':true, 'margin-left':true, 'margin-right':true, 'margin-top':true, 'max-height':true, 'max-width':true, 'min-height':true, 'min-width':true, 'opacity':true, 'outline-color':true, 'outline-offset':true, 'outline-width':true, 'padding-bottom':true, 'padding-left':true, 'padding-right':true, 'padding-top':true, 'right':true, 'text-indent':true, 'text-shadow':true, 'top':true, 'vertical-align':true, 'visibility':true, 'width':true, 'word-spacing':true, 
'z-index':true, 'zoom':true, 'transform':true}, constructor:function(data) {
  this.data = {};
  this.set(data);
}, setConfig:function(data) {
  this.set(data);
  return this;
}, setRaw:function(data) {
  this.data = data;
  return this;
}, clear:function() {
  return this.setRaw({});
}, setTransform:function(name, value) {
  var data = this.data, isArray = Ext.isArray(value), transform = data.transform, ln, key;
  if (!transform) {
    transform = data.transform = {translateX:0, translateY:0, translateZ:0, scaleX:1, scaleY:1, scaleZ:1, rotate:0, rotateX:0, rotateY:0, rotateZ:0, skewX:0, skewY:0};
  }
  if (typeof name === 'string') {
    switch(name) {
      case 'translate':
        if (isArray) {
          ln = value.length;
          if (ln === 0) {
            break;
          }
          transform.translateX = value[0];
          if (ln === 1) {
            break;
          }
          transform.translateY = value[1];
          if (ln === 2) {
            break;
          }
          transform.translateZ = value[2];
        } else {
          transform.translateX = value;
        }
        break;
      case 'rotate':
        if (isArray) {
          ln = value.length;
          if (ln === 0) {
            break;
          }
          transform.rotateX = value[0];
          if (ln === 1) {
            break;
          }
          transform.rotateY = value[1];
          if (ln === 2) {
            break;
          }
          transform.rotateZ = value[2];
        } else {
          transform.rotate = value;
        }
        break;
      case 'scale':
        if (isArray) {
          ln = value.length;
          if (ln === 0) {
            break;
          }
          transform.scaleX = value[0];
          if (ln === 1) {
            break;
          }
          transform.scaleY = value[1];
          if (ln === 2) {
            break;
          }
          transform.scaleZ = value[2];
        } else {
          transform.scaleX = value;
          transform.scaleY = value;
        }
        break;
      case 'skew':
        if (isArray) {
          ln = value.length;
          if (ln === 0) {
            break;
          }
          transform.skewX = value[0];
          if (ln === 1) {
            break;
          }
          transform.skewY = value[1];
        } else {
          transform.skewX = value;
        }
        break;
      default:
        transform[name] = value;
    }
  } else {
    for (key in name) {
      if (name.hasOwnProperty(key)) {
        value = name[key];
        this.setTransform(key, value);
      }
    }
  }
}, set:function(name, value) {
  var data = this.data, key;
  if (typeof name !== 'string') {
    for (key in name) {
      value = name[key];
      if (key === 'transform') {
        this.setTransform(value);
      } else {
        data[key] = value;
      }
    }
  } else {
    if (name === 'transform') {
      this.setTransform(value);
    } else {
      data[name] = value;
    }
  }
  return this;
}, unset:function(name) {
  var data = this.data;
  if (data.hasOwnProperty(name)) {
    delete data[name];
  }
  return this;
}, getData:function() {
  return this.data;
}});
Ext.define('Ext.fx.animation.Abstract', {extend:Ext.Evented, mixins:[Ext.mixin.Factoryable], factoryConfig:{type:'animation'}, isAnimation:true, config:{name:'', element:null, before:null, from:{}, to:{}, after:null, states:{}, duration:300, easing:'linear', iteration:1, direction:'normal', delay:0, onBeforeStart:null, callback:null, onEnd:null, onBeforeEnd:null, scope:null, reverse:null, preserveEndState:false, replacePrevious:true}, STATE_FROM:'0%', STATE_TO:'100%', DIRECTION_UP:'up', DIRECTION_TOP:'top', 
DIRECTION_DOWN:'down', DIRECTION_BOTTOM:'bottom', DIRECTION_LEFT:'left', DIRECTION_RIGHT:'right', stateNameRegex:/^(?:[\d.]+)%$/, constructor:function() {
  this.states = {};
  this.callParent(arguments);
  return this;
}, applyElement:function(element) {
  return Ext.get(element);
}, applyBefore:function(before, current) {
  if (before) {
    return Ext.factory(before, Ext.fx.State, current);
  }
}, applyAfter:function(after, current) {
  if (after) {
    return Ext.factory(after, Ext.fx.State, current);
  }
}, setFrom:function(from) {
  return this.setState(this.STATE_FROM, from);
}, setTo:function(to) {
  return this.setState(this.STATE_TO, to);
}, getFrom:function() {
  return this.getState(this.STATE_FROM);
}, getTo:function() {
  return this.getState(this.STATE_TO);
}, setStates:function(states) {
  var validNameRegex = this.stateNameRegex, name;
  for (name in states) {
    if (validNameRegex.test(name)) {
      this.setState(name, states[name]);
    }
  }
  return this;
}, getStates:function() {
  return this.states;
}, updateCallback:function(callback) {
  if (callback) {
    this.setOnEnd(callback);
  }
}, end:function() {
  this.stop();
}, stop:function() {
  this.fireEvent('stop', this);
}, destroy:function() {
  this.destroying = true;
  this.stop();
  this.callParent();
  this.destroying = false;
  this.destroyed = true;
}, setState:function(name, state) {
  var states = this.getStates(), stateInstance;
  stateInstance = Ext.factory(state, Ext.fx.State, states[name]);
  if (stateInstance) {
    states[name] = stateInstance;
  } else {
    if (name === this.STATE_TO) {
      Ext.Logger.error("Setting and invalid '100%' / 'to' state of: " + state);
    }
  }
  return this;
}, getState:function(name) {
  return this.getStates()[name];
}, getData:function() {
  var me = this, states = me.getStates(), statesData = {}, before = me.getBefore(), after = me.getAfter(), from = states[me.STATE_FROM], to = states[me.STATE_TO], fromData = from.getData(), toData = to.getData(), data, name, state;
  for (name in states) {
    if (states.hasOwnProperty(name)) {
      state = states[name];
      data = state.getData();
      statesData[name] = data;
    }
  }
  return {before:before ? before.getData() : {}, after:after ? after.getData() : {}, states:statesData, from:fromData, to:toData, duration:me.getDuration(), iteration:me.getIteration(), direction:me.getDirection(), easing:me.getEasing(), delay:me.getDelay(), onEnd:me.getOnEnd(), onBeforeEnd:me.getOnBeforeEnd(), onBeforeStart:me.getOnBeforeStart(), scope:me.getScope(), preserveEndState:me.getPreserveEndState(), replacePrevious:me.getReplacePrevious()};
}});
Ext.define('Ext.fx.animation.Slide', {extend:Ext.fx.animation.Abstract, alternateClassName:'Ext.fx.animation.SlideIn', alias:['animation.slide', 'animation.slideIn'], config:{direction:'left', out:false, offset:0, easing:'auto', containerBox:'auto', elementBox:'auto', isElementBoxFit:true, useCssTransform:true}, reverseDirectionMap:{up:'down', top:'down', down:'up', bottom:'up', left:'right', right:'left'}, applyEasing:function(easing) {
  if (easing === 'auto') {
    return 'ease-' + (this.getOut() ? 'in' : 'out');
  }
  return easing;
}, getContainerBox:function() {
  var box = this._containerBox;
  if (box === 'auto') {
    box = this.getElement().getParent().getBox();
  }
  return box;
}, getElementBox:function() {
  var box = this._elementBox;
  if (this.getIsElementBoxFit()) {
    return this.getContainerBox();
  }
  if (box === 'auto') {
    box = this.getElement().getBox();
  }
  return box;
}, getData:function() {
  var elementBox = this.getElementBox(), containerBox = this.getContainerBox(), box = elementBox ? elementBox : containerBox, from = this.getFrom(), to = this.getTo(), out = this.getOut(), offset = this.getOffset(), direction = this.getDirection(), useCssTransform = this.getUseCssTransform(), reverse = this.getReverse(), translateX = 0, translateY = 0, offsetPct, fromX, fromY, toX, toY;
  if (typeof offset === 'string') {
    offsetPct = true;
    offset = parseFloat(offset);
  }
  if (reverse) {
    direction = this.reverseDirectionMap[direction];
  }
  switch(direction) {
    case this.DIRECTION_UP:
    case this.DIRECTION_TOP:
      if (offsetPct) {
        offset = box.height * offset / 100;
      }
      if (out) {
        translateY = containerBox.top - box.top - box.height - offset;
      } else {
        translateY = containerBox.bottom - box.bottom + box.height + offset;
      }
      break;
    case this.DIRECTION_DOWN:
    case this.DIRECTION_BOTTOM:
      if (offsetPct) {
        offset = box.height * offset / 100;
      }
      if (out) {
        translateY = containerBox.bottom - box.bottom + box.height + offset;
      } else {
        translateY = containerBox.top - box.height - box.top - offset;
      }
      break;
    case this.DIRECTION_RIGHT:
      if (offsetPct) {
        offset = box.width * offset / 100;
      }
      if (out) {
        translateX = containerBox.right - box.right + box.width + offset;
      } else {
        translateX = containerBox.left - box.left - box.width - offset;
      }
      break;
    case this.DIRECTION_LEFT:
      if (offsetPct) {
        offset = box.width * offset / 100;
      }
      if (out) {
        translateX = containerBox.left - box.left - box.width - offset;
      } else {
        translateX = containerBox.right - box.right + box.width + offset;
      }
      break;
  }
  fromX = out ? 0 : translateX;
  fromY = out ? 0 : translateY;
  if (useCssTransform) {
    from.setTransform({translateX:fromX, translateY:fromY});
  } else {
    from.set('left', fromX);
    from.set('top', fromY);
  }
  toX = out ? translateX : 0;
  toY = out ? translateY : 0;
  if (useCssTransform) {
    to.setTransform({translateX:toX, translateY:toY});
  } else {
    to.set('left', toX);
    to.set('top', toY);
  }
  return this.callParent(arguments);
}});
Ext.define('Ext.fx.animation.SlideOut', {extend:Ext.fx.animation.Slide, alias:['animation.slideOut'], config:{out:true}});
Ext.define('Ext.fx.animation.Fade', {extend:Ext.fx.animation.Abstract, alternateClassName:'Ext.fx.animation.FadeIn', alias:['animation.fade', 'animation.fadeIn'], config:{out:false, before:{display:null, opacity:0}, after:{opacity:null}, reverse:null}, updateOut:function(newOut) {
  var to = this.getTo(), from = this.getFrom();
  if (newOut) {
    from.set('opacity', 1);
    to.set('opacity', 0);
  } else {
    from.set('opacity', 0);
    to.set('opacity', 1);
  }
}});
Ext.define('Ext.fx.animation.FadeOut', {extend:Ext.fx.animation.Fade, alias:'animation.fadeOut', config:{out:true, before:{}}});
Ext.define('Ext.fx.animation.Flip', {extend:Ext.fx.animation.Abstract, alias:'animation.flip', config:{easing:'ease-in', direction:'right', half:false, out:null}, getData:function() {
  var me = this, from = me.getFrom(), to = me.getTo(), direction = me.getDirection(), out = me.getOut(), half = me.getHalf(), rotate = half ? 90 : 180, fromScale = 1, toScale = 1, fromRotateX = 0, fromRotateY = 0, toRotateX = 0, toRotateY = 0;
  if (out) {
    toScale = 0.8;
  } else {
    fromScale = 0.8;
  }
  switch(direction) {
    case this.DIRECTION_UP:
    case this.DIRECTION_TOP:
      if (out) {
        toRotateX = rotate;
      } else {
        fromRotateX = -rotate;
      }
      break;
    case this.DIRECTION_DOWN:
    case this.DIRECTION_BOTTOM:
      if (out) {
        toRotateX = -rotate;
      } else {
        fromRotateX = rotate;
      }
      break;
    case this.DIRECTION_RIGHT:
      if (out) {
        toRotateY = rotate;
      } else {
        fromRotateY = -rotate;
      }
      break;
    case this.DIRECTION_LEFT:
      if (out) {
        toRotateY = -rotate;
      } else {
        fromRotateY = rotate;
      }
      break;
  }
  from.setTransform({rotateX:fromRotateX, rotateY:fromRotateY, scale:fromScale});
  to.setTransform({rotateX:toRotateX, rotateY:toRotateY, scale:toScale});
  return this.callParent();
}});
Ext.define('Ext.fx.animation.Pop', {extend:Ext.fx.animation.Abstract, alias:['animation.pop', 'animation.popIn'], alternateClassName:'Ext.fx.animation.PopIn', config:{out:false, before:{display:null, opacity:0}, after:{opacity:null}}, getData:function() {
  var to = this.getTo(), from = this.getFrom(), out = this.getOut();
  if (out) {
    from.set('opacity', 1);
    from.setTransform({scale:1});
    to.set('opacity', 0);
    to.setTransform({scale:0});
  } else {
    from.set('opacity', 0);
    from.setTransform({scale:0});
    to.set('opacity', 1);
    to.setTransform({scale:1});
  }
  return this.callParent(arguments);
}});
Ext.define('Ext.fx.animation.PopOut', {extend:Ext.fx.animation.Pop, alias:'animation.popOut', config:{out:true, before:{}}});
Ext.define('Ext.fx.Animation', {constructor:function(config) {
  var defaultClass = Ext.fx.animation.Abstract, type;
  if (typeof config === 'string') {
    type = config;
    config = {};
  } else {
    if (config && config.type) {
      type = config.type;
    }
  }
  if (type) {
    defaultClass = Ext.ClassManager.getByAlias('animation.' + type);
    if (!defaultClass) {
      Ext.Logger.error("Invalid animation type of: '" + type + "'");
    }
  }
  return Ext.factory(config, defaultClass);
}});
Ext.define('Ext.overrides.Progress', {override:'Ext.Progress', initialize:function() {
  this.callParent();
  this.on('painted', 'onPainted', this);
}, onPainted:function() {
  this.syncWidth();
}, onResize:function(width) {
  this.syncWidth(width);
}, syncWidth:function(width) {
  var me = this;
  if (width == null) {
    width = me.element.getWidth();
  }
  me.backgroundEl.setWidth(width);
  me.textEl.setWidth(width);
}, privates:{startBarAnimation:function(o) {
  var me = this;
  me.barAnim = new Ext.fx.Animation(Ext.apply(o, {element:me.barEl, preserveEndState:true, callback:function() {
    delete me.barAnim;
  }}));
  Ext.Animator.run(me.barAnim);
}, stopBarAnimation:function() {
  var barAnim = this.barAnim;
  if (barAnim) {
    barAnim.destroy();
  }
  this.barAnim = null;
}}});
Ext.define('Ext.app.EventDomain', {statics:{instances:{}}, isEventDomain:true, isInstance:false, constructor:function() {
  var me = this;
  if (!me.isInstance) {
    Ext.app.EventDomain.instances[me.type] = me;
  }
  me.bus = {};
  me.monitoredClasses = [];
}, dispatch:function(target, ev, args) {
  ev = Ext.canonicalEventName(ev);
  var me = this, bus = me.bus, selectors = bus[ev], selector, controllers, id, info, events, len, i, event;
  if (!selectors) {
    return true;
  }
  for (selector in selectors) {
    if (selectors.hasOwnProperty(selector) && me.match(target, selector, me.controller)) {
      controllers = selectors[selector];
      for (id in controllers) {
        if (controllers.hasOwnProperty(id)) {
          info = controllers[id];
          if (info.controller.isActive()) {
            events = info.list;
            len = events.length;
            for (i = 0; i < len; i++) {
              event = events[i];
              if (event.fire.apply(event, args) === false) {
                return false;
              }
            }
          }
        }
      }
    }
  }
  return true;
}, listen:function(selectors, controller) {
  var me = this, bus = me.bus, idProperty = me.idProperty, monitoredClasses = me.monitoredClasses, monitoredClassesCount = monitoredClasses.length, controllerId = controller.getId(), isComponentDomain = me.type === 'component', refMap = isComponentDomain ? controller.getRefMap() : null, i, tree, info, selector, options, listener, scope, event, listeners, ev, classHasListeners;
  for (selector in selectors) {
    listeners = selectors[selector];
    if (isComponentDomain) {
      selector = refMap[selector] || selector;
    }
    if (listeners) {
      if (idProperty) {
        if (!/^[*#]/.test(selector)) {
          Ext.raise('Selectors containing id should begin with #');
        }
        selector = selector === '*' ? selector : selector.substring(1);
      }
      for (ev in listeners) {
        options = null;
        listener = listeners[ev];
        scope = controller;
        ev = Ext.canonicalEventName(ev);
        event = new Ext.util.Event(controller, ev);
        if (Ext.isObject(listener)) {
          options = listener;
          listener = options.fn;
          scope = options.scope || controller;
          delete options.fn;
          delete options.scope;
        }
        if ((!options || !options.scope) && typeof listener === 'string') {
          if (!scope[listener]) {
            Ext.raise('Cannot resolve "' + listener + '" on controller.');
          }
          scope = null;
        } else {
          if (typeof listener === 'string') {
            listener = scope[listener];
          }
        }
        event.addListener(listener, scope, options);
        for (i = 0; i < monitoredClassesCount; ++i) {
          classHasListeners = monitoredClasses[i].hasListeners;
          if (classHasListeners) {
            classHasListeners._incr_(ev);
          }
        }
        tree = bus[ev] || (bus[ev] = {});
        tree = tree[selector] || (tree[selector] = {});
        info = tree[controllerId] || (tree[controllerId] = {controller:controller, list:[]});
        info.list.push(event);
      }
    }
  }
}, match:function(target, selector) {
  var idProperty = this.idProperty;
  if (idProperty) {
    return selector === '*' || target[idProperty] === selector;
  }
  return false;
}, monitor:function(observable) {
  var domain = this, prototype = observable.isInstance ? observable : observable.prototype, doFireEvent = prototype.doFireEvent;
  domain.monitoredClasses.push(observable);
  prototype.doFireEvent = function(ev, args) {
    var me = this, ret;
    ret = doFireEvent.apply(me, arguments);
    if (ret !== false && !me.destroyed && !me.isSuspended(ev)) {
      ret = domain.dispatch(me, ev, args);
    }
    return ret;
  };
}, unlisten:function(controllerId) {
  var bus = this.bus, id = controllerId, monitoredClasses = this.monitoredClasses, monitoredClassesCount = monitoredClasses.length, controllers, ev, events, len, item, selector, selectors, i, j, info, classHasListeners;
  if (controllerId.isController) {
    id = controllerId.getId();
  }
  for (ev in bus) {
    ev = Ext.canonicalEventName(ev);
    if (bus.hasOwnProperty(ev) && (selectors = bus[ev])) {
      for (selector in selectors) {
        controllers = selectors[selector];
        info = controllers[id];
        if (info) {
          events = info.list;
          if (events) {
            for (i = 0, len = events.length; i < len; ++i) {
              item = events[i];
              item.clearListeners();
              for (j = 0; j < monitoredClassesCount; ++j) {
                classHasListeners = monitoredClasses[j].hasListeners;
                if (classHasListeners) {
                  classHasListeners._decr_(item.name);
                }
              }
            }
            delete controllers[id];
          }
        }
      }
    }
  }
}, destroy:function() {
  this.monitoredClasses = this.bus = null;
  this.callParent();
}});
Ext.define('Ext.app.domain.Component', {extend:Ext.app.EventDomain, singleton:true, type:'component', constructor:function() {
  this.callParent();
  this.monitor(Ext.Widget);
}, dispatch:function(target, ev, args) {
  var controller = target.lookupController(false), domain, view;
  while (controller) {
    domain = controller.compDomain;
    if (domain) {
      if (domain.dispatch(target, ev, args) === false) {
        return false;
      }
    }
    view = controller.getView();
    controller = view ? view.lookupController(true) : null;
  }
  return this.callParent([target, ev, args]);
}, match:function(target, selector) {
  return target.is(selector);
}});
Ext.define('Ext.app.EventBus', {singleton:true, constructor:function() {
  var me = this, domains = Ext.app.EventDomain.instances;
  me.callParent();
  me.domains = domains;
  me.bus = domains.component.bus;
}, control:function(selectors, controller) {
  return this.domains.component.listen(selectors, controller);
}, listen:function(to, controller) {
  var domains = this.domains, domain;
  for (domain in to) {
    if (to.hasOwnProperty(domain)) {
      domains[domain].listen(to[domain], controller);
    }
  }
}, unlisten:function(controllerId) {
  var domains = Ext.app.EventDomain.instances, domain;
  for (domain in domains) {
    domains[domain].unlisten(controllerId);
  }
}});
Ext.define('Ext.app.domain.Global', {extend:Ext.app.EventDomain, singleton:true, type:'global', constructor:function() {
  var me = this;
  me.callParent();
  me.monitor(Ext.GlobalEvents);
}, listen:function(listeners, controller) {
  this.callParent([{global:listeners}, controller]);
}, match:Ext.returnTrue});
Ext.define('Ext.route.Handler', {lazy:false, statics:{fromRouteConfig:function(config, scope) {
  var handler = {action:config.action, before:config.before, lazy:config.lazy, exit:config.exit, scope:scope, single:config.single};
  return new this(handler);
}}, constructor:function(config) {
  Ext.apply(this, config);
}});
Ext.define('Ext.route.Action', {config:{actions:null, befores:null, urlParams:[]}, started:false, stopped:false, constructor:function(config) {
  var me = this;
  me.deferred = new Ext.Deferred;
  me.resume = me.resume.bind(me);
  me.stop = me.stop.bind(me);
  me.initConfig(config);
  me.callParent([config]);
}, applyActions:function(actions) {
  if (actions) {
    actions = Ext.Array.from(actions);
  }
  return actions;
}, applyBefores:function(befores) {
  if (befores) {
    befores = Ext.Array.from(befores);
  }
  return befores;
}, destroy:function() {
  this.deferred = null;
  this.setBefores(null).setActions(null).setUrlParams(null);
  this.callParent();
}, resume:function() {
  return this.next();
}, stop:function() {
  this.stopped = true;
  return this.done();
}, next:function() {
  var me = this, actions = me.getActions(), befores = me.getBefores(), urlParams = me.getUrlParams(), config, ret, args;
  if (Ext.isArray(urlParams)) {
    args = urlParams.slice();
  } else {
    args = [urlParams];
  }
  if (me.stopped || (befores ? !befores.length : true) && (actions ? !actions.length : true)) {
    me.done();
  } else {
    if (befores && befores.length) {
      config = befores.shift();
      args.push(me);
      ret = Ext.callback(config.fn, config.scope, args);
      if (ret && ret.then) {
        ret.then(function(arg) {
          me.resume(arg);
        }, function(arg) {
          me.stop(arg);
        });
      }
    } else {
      if (actions && actions.length) {
        config = actions.shift();
        Ext.callback(config.fn, config.scope, args);
        me.next();
      } else {
        me.next();
      }
    }
  }
  return me;
}, run:function() {
  var deferred = this.deferred;
  if (!this.started) {
    this.next();
    this.started = true;
  }
  return deferred.promise;
}, done:function() {
  var deferred = this.deferred;
  if (this.stopped) {
    deferred.reject();
  } else {
    deferred.resolve();
  }
  this.destroy();
  return this;
}, before:function(first, fn, scope) {
  if (!Ext.isBoolean(first)) {
    scope = fn;
    fn = first;
    first = false;
  }
  var befores = this.getBefores(), config = {fn:fn, scope:scope};
  if (this.destroyed) {
    Ext.raise('This action has has already resolved and therefore will never ' + 'execute this function.');
    return;
  }
  if (befores) {
    if (first) {
      befores.unshift(config);
    } else {
      befores.push(config);
    }
  } else {
    this.setBefores(config);
  }
  return this;
}, action:function(first, fn, scope) {
  if (!Ext.isBoolean(first)) {
    scope = fn;
    fn = first;
    first = false;
  }
  var actions = this.getActions(), config = {fn:fn, scope:scope};
  if (this.destroyed) {
    Ext.raise('This action has has already resolved and therefore will never ' + 'execute this function.');
    return;
  }
  if (actions) {
    if (first) {
      actions.unshift(config);
    } else {
      actions.push(config);
    }
  } else {
    this.setActions(config);
  }
  return this;
}, then:function(resolve, reject) {
  if (this.destroyed) {
    Ext.raise('This action has has already resolved and therefore will never ' + 'execute either function.');
    return;
  }
  return this.deferred.then(resolve, reject);
}});
Ext.define('Ext.route.Route', {config:{name:null, url:null, allowInactive:false, conditions:{}, caseInsensitive:false, handlers:[], types:{cached:true, $value:{alpha:{re:'([a-zA-Z]+)'}, alphanum:{re:'([a-zA-Z0-9]+|[0-9]+(?:\\.[0-9]+)?|[0-9]*(?:\\.[0-9]+){1})', parse:function(value) {
  var test;
  if (value && this.numRe.test(value)) {
    test = parseFloat(value);
    if (!isNaN(test)) {
      value = test;
    }
  }
  return value;
}}, num:{re:'([0-9]+(?:\\.[0-9]+)?|[0-9]*(?:\\.[0-9]+){1})', parse:function(value) {
  if (value) {
    value = parseFloat(value);
  }
  return value;
}}, '...':{re:'(.+)?', split:'/', parse:function(values) {
  var length, i, value;
  if (values) {
    length = values.length;
    for (i = 0; i < length; i++) {
      value = parseFloat(values[i]);
      if (!isNaN(value)) {
        values[i] = value;
      }
    }
  }
  return values;
}}}}}, defaultMatcher:'([%a-zA-Z0-9\\-\\_\\s,]+)', numRe:/^[0-9]*(?:\.[0-9]*)?$/, typeParamRegex:/:{([0-9A-Za-z_]+)(?::?([0-9A-Za-z_]+|.{3})?)}/g, optionalGroupRegex:/\((.+?)\)/g, paramMatchingRegex:/:([0-9A-Za-z_]+)/g, isRoute:true, constructor:function(config) {
  var me = this, url;
  this.initConfig(config);
  url = me.getUrl().replace(me.optionalGroupRegex, function(match, middle) {
    return '(?:' + middle + ')?';
  });
  if (url.match(me.typeParamRegex)) {
    me.handleNamedPattern(url);
  } else {
    me.handlePositionalPattern(url);
  }
}, handlePositionalPattern:function(url) {
  var me = this;
  me.paramsInMatchString = url.match(me.paramMatchingRegex) || [];
  me.matcherRegex = me.createMatcherRegex(url);
  me.mode = 'positional';
}, handleNamedPattern:function(url) {
  var me = this, typeParamRegex = me.typeParamRegex, conditions = me.getConditions(), types = me.getTypes(), defaultMatcher = me.defaultMatcher, params = {}, re = url.replace(typeParamRegex, function(match, param, typeMatch) {
    var type = typeMatch && types[typeMatch], matcher = conditions[param] || type || defaultMatcher;
    if (params[param]) {
      Ext.raise('"' + param + '" already defined in route "' + url + '"');
    }
    if (typeMatch && !type) {
      Ext.raise('Unknown parameter type "' + typeMatch + '" in route "' + url + '"');
    }
    if (Ext.isObject(matcher)) {
      matcher = matcher.re;
    }
    params[param] = {matcher:matcher, type:typeMatch};
    return matcher;
  });
  if (re.search(me.paramMatchingRegex) !== -1) {
    Ext.raise('URL parameter mismatch. Positional url parameter found ' + 'while in named mode.');
  }
  me.paramsInMatchString = params;
  me.matcherRegex = new RegExp('^' + re + '$', me.getCaseInsensitive() ? 'i' : '');
  me.mode = 'named';
}, recognize:function(url) {
  var me = this, recognized = me.recognizes(url), handlers, length, hasHandler, handler, matches, urlParams, i;
  if (recognized) {
    handlers = me.getHandlers();
    length = handlers.length;
    for (i = 0; i < length; i++) {
      handler = handlers[i];
      if (handler.lastToken !== url) {
        hasHandler = true;
        break;
      }
    }
    if (!hasHandler && url === me.lastToken) {
      return true;
    }
    matches = me.matchesFor(url);
    urlParams = me.getUrlParams(url);
    return Ext.applyIf(matches, {historyUrl:url, urlParams:urlParams});
  }
  return false;
}, getUrlParams:function(url) {
  if (this.mode === 'named') {
    return this.getNamedUrlParams(url);
  } else {
    return this.getPositionalUrlParams(url);
  }
}, getPositionalUrlParams:function(url) {
  var params = [], conditions = this.getConditions(), keys = this.paramsInMatchString, values = url.match(this.matcherRegex), length = keys.length, i, key, type, value;
  values.shift();
  for (i = 0; i < length; i++) {
    key = keys[i];
    value = values[i];
    if (conditions[key]) {
      type = conditions[key];
    } else {
      if (key[0] === ':') {
        key = key.substr(1);
        if (conditions[key]) {
          type = conditions[key];
        }
      }
    }
    value = this.parseValue(value, type);
    if (Ext.isDefined(value) && value !== '') {
      if (Ext.isArray(value)) {
        params.push.apply(params, value);
      } else {
        params.push(value);
      }
    }
  }
  return params;
}, getNamedUrlParams:function(url) {
  var conditions = this.getConditions(), types = this.getTypes(), params = {}, keys = this.paramsInMatchString, values = url.match(this.matcherRegex), name, obj, value, type, condition;
  values.shift();
  for (name in keys) {
    obj = keys[name];
    value = values.shift();
    condition = conditions[name];
    type = types[obj.type];
    if (condition || type) {
      type = Ext.merge({}, condition, types[obj.type]);
    }
    params[name] = this.parseValue(value, type);
  }
  return params;
}, parseValue:function(value, type) {
  if (type) {
    if (value && type.split) {
      value = value.split(type.split);
      if (!value[0]) {
        value.shift();
      }
      if (!value[value.length - 1]) {
        value.pop();
      }
    }
    if (type.parse) {
      value = type.parse.call(this, value);
    }
  }
  if (!value && Ext.isString(value)) {
    value = undefined;
  }
  return value;
}, recognizes:function(url) {
  return this.matcherRegex.test(url);
}, execute:function(token, argConfig) {
  var me = this, allowInactive = me.getAllowInactive(), handlers = me.getHandlers(), queue = Ext.route.Router.getQueueRoutes(), length = handlers.length, urlParams = argConfig && argConfig.urlParams || [], i, handler, scope, action, promises, single, remover;
  me.lastToken = token;
  if (!queue) {
    promises = [];
  }
  return new Ext.Promise(function(resolve, reject) {
    if (argConfig === false) {
      reject();
    } else {
      if (queue) {
        action = new Ext.route.Action({urlParams:urlParams});
      }
      for (i = 0; i < length; i++) {
        handler = handlers[i];
        if (token != null && handler.lastToken === token) {
          continue;
        }
        scope = handler.scope;
        handler.lastToken = token;
        if (!allowInactive && scope.isActive && !scope.isActive()) {
          continue;
        }
        if (!queue) {
          action = new Ext.route.Action({urlParams:urlParams});
        }
        single = handler.single;
        if (handler.before) {
          action.before(handler.before, scope);
        }
        if (handler.action) {
          action.action(handler.action, scope);
        }
        if (single) {
          remover = Ext.bind(me.removeHandler, me, [null, handler]);
          if (single === true) {
            if (handler.action) {
              action.action(remover, me);
            } else {
              action.before(function() {
                remover();
                return Ext.Promise.resolve();
              }, me);
            }
          } else {
            action.before(single === 'before', function() {
              remover();
              return Ext.Promise.resolve();
            }, me);
          }
        }
        if (!queue) {
          if (Ext.fireEvent('beforeroute', action, me) === false) {
            action.destroy();
          } else {
            promises.push(action.run());
          }
        }
      }
      if (queue) {
        if (Ext.fireEvent('beforeroute', action, me) === false) {
          action.destroy();
          reject();
        } else {
          action.run().then(resolve, reject);
        }
      } else {
        Ext.Promise.all(promises).then(resolve, reject);
      }
    }
  });
}, matchesFor:function(url) {
  var params = {}, keys = this.mode === 'named' ? Ext.Object.getKeys(this.paramsInMatchString) : this.paramsInMatchString, values = url.match(this.matcherRegex), length = keys.length, i;
  values.shift();
  for (i = 0; i < length; i++) {
    params[keys[i].replace(':', '')] = values[i];
  }
  return params;
}, createMatcherRegex:function(url) {
  var me = this, paramsInMatchString = me.paramsInMatchString, conditions = me.getConditions(), defaultMatcher = me.defaultMatcher, length = paramsInMatchString.length, modifiers = me.getCaseInsensitive() ? 'i' : '', i, param, matcher;
  if (url === '*') {
    url = url.replace('*', '\\*');
  } else {
    for (i = 0; i < length; i++) {
      param = paramsInMatchString[i];
      if (conditions[param]) {
        matcher = conditions[param];
      } else {
        if (param[0] === ':' && conditions[param.substr(1)]) {
          matcher = conditions[param.substr(1)];
        } else {
          matcher = defaultMatcher;
        }
      }
      if (Ext.isObject(matcher)) {
        matcher = matcher.re;
      }
      url = url.replace(new RegExp(param), matcher || defaultMatcher);
    }
  }
  return new RegExp('^' + url + '$', modifiers);
}, addHandler:function(handler) {
  var handlers = this.getHandlers();
  if (!handler.isInstance) {
    handler = new Ext.route.Handler(handler);
  }
  handlers.push(handler);
  return handler.route = this;
}, removeHandler:function(scope, handler) {
  var handlers = this.getHandlers(), length = handlers.length, newHandlers = [], i, item;
  for (i = 0; i < length; i++) {
    item = handlers[i];
    if (handler) {
      if (item !== handler) {
        newHandlers.push(item);
      }
    } else {
      if (item.scope !== scope) {
        newHandlers.push(item);
      }
    }
  }
  this.setHandlers(newHandlers);
  return this;
}, clearLastTokens:function() {
  var handlers = this.getHandlers(), length = handlers.length, i;
  for (i = 0; i < length; i++) {
    handlers[i].lastToken = null;
  }
  this.lastToken = null;
}, onExit:function() {
  var me = this, handlers = me.getHandlers(), allowInactive = me.getAllowInactive(), length = handlers.length, action = new Ext.route.Action({urlParams:[me.lastToken]}), i, handler, scope;
  me.clearLastTokens();
  for (i = 0; i < length; i++) {
    handler = handlers[i];
    if (handler.exit) {
      scope = handler.scope;
      if (!allowInactive && scope.isActive && !scope.isActive()) {
        continue;
      }
      action.action(handler.exit, scope);
    }
  }
  if (Ext.fireEvent('beforerouteexit', action, me) === false) {
    action.destroy();
  } else {
    action.run();
  }
}});
Ext.define('Ext.util.Observable', {extend:Ext.mixin.Observable, $applyConfigs:true}, function(Observable) {
  var Super = Ext.mixin.Observable;
  Observable.releaseCapture = Super.releaseCapture;
  Observable.capture = Super.capture;
  Observable.captureArgs = Super.captureArgs;
  Observable.observe = Observable.observeClass = Super.observe;
});
Ext.define('Ext.util.History', {singleton:true, alternateClassName:'Ext.History', mixins:{observable:Ext.util.Observable}, useTopWindow:false, hashRe:/^(#?!?)/, constructor:function() {
  var me = this;
  me.ready = false;
  me.currentToken = null;
  me.mixins.observable.constructor.call(me);
}, getHash:function() {
  return (this.win.location.hash || '').replace(this.hashRe, '');
}, setHash:function(hash, replace) {
  var me = this, hashRe = me.hashRe, loc = me.win.location;
  hash = hash.replace(hashRe, me.hashbang ? '#!' : '#');
  try {
    if (replace) {
      loc.replace(hash);
    } else {
      loc.hash = hash;
    }
    me.currentToken = hash.replace(hashRe, '');
  } catch (e$53) {
  }
}, handleStateChange:function(token) {
  token = token.replace(this.hashRe, '');
  this.fireEvent('change', this.currentToken = token);
}, startUp:function() {
  var me = this;
  me.currentToken = me.getHash();
  Ext.get(me.win).on('hashchange', me.onHashChange, me);
  me.ready = true;
  me.fireEvent('ready', me);
}, onHashChange:function() {
  var me = this, newHash = me.getHash();
  if (newHash !== me.hash) {
    me.hash = newHash;
    me.handleStateChange(newHash);
  }
}, init:function(onReady, scope) {
  var me = this;
  if (me.ready) {
    Ext.callback(onReady, scope, [me]);
    return;
  }
  if (!Ext.isReady) {
    Ext.onInternalReady(function() {
      me.init(onReady, scope);
    });
    return;
  }
  me.win = me.useTopWindow ? window.top : window;
  me.hash = me.getHash();
  if (onReady) {
    me.on('ready', onReady, scope, {single:true});
  }
  me.startUp();
}, add:function(token, preventDuplicates) {
  var me = this, set = false;
  if (preventDuplicates === false || me.getToken() !== token) {
    me.setHash(token);
    set = true;
  }
  return set;
}, replace:function(token, preventDuplicates) {
  var me = this, set = false;
  if (preventDuplicates === false || me.getToken() !== token) {
    this.setHash(token, true);
    set = true;
  }
  return set;
}, back:function() {
  this.win.history.go(-1);
}, forward:function() {
  this.win.history.go(1);
}, getToken:function() {
  return this.ready ? this.currentToken : this.getHash();
}});
Ext.define('Ext.route.Router', {singleton:true, config:{hashbang:null, multipleToken:'|', queueRoutes:true}, constructor:function() {
  var History = Ext.util.History;
  if (!History.ready) {
    History.init();
  }
  History.on('change', this.onStateChange, this);
  this.initConfig();
  this.clear();
}, updateHashbang:function(hashbang) {
  Ext.util.History.hashbang = hashbang;
}, onStateChange:function(token) {
  var me = this, tokens = token.split(me.getMultipleToken()), queue, i, length;
  if (me.isSuspended) {
    queue = me.suspendedQueue;
    i = 0;
    length = tokens.length;
    if (queue) {
      for (; i < length; i++) {
        token = tokens[i];
        if (!Ext.Array.contains(queue, token)) {
          queue.push(token);
        }
      }
    }
  } else {
    me.handleBefore(tokens);
  }
}, handleBefore:function(tokens) {
  var me = this, action = new Ext.route.Action;
  if (Ext.fireEvent('beforeroutes', action, tokens) === false) {
    action.destroy();
  } else {
    action.run().then(me.handleBeforeRoute.bind(me, tokens), Ext.emptyFn);
  }
}, handleBeforeRoute:function(tokens) {
  var me = this, beforeRoute = me.getByName('*');
  if (beforeRoute) {
    beforeRoute.execute().then(me.doRun.bind(me, tokens), Ext.emptyFn);
  } else {
    me.doRun(tokens);
  }
}, doRun:function(tokens) {
  var me = this, app = me.application, routes = me.routes, i = 0, length = tokens.length, matched = {}, unmatched = [], token, found, name, route, recognize;
  for (; i < length; i++) {
    token = tokens[i];
    found = false;
    for (name in routes) {
      route = routes[name];
      recognize = route.recognize(token);
      if (recognize) {
        found = true;
        if (recognize !== true) {
          route.execute(token, recognize).then(null, Ext.bind(me.onRouteRejection, me, [route], 0));
        }
        Ext.Array.remove(unmatched, route);
        if (!matched[name]) {
          matched[name] = 1;
        }
      } else {
        if (!matched[name]) {
          unmatched.push(route);
        }
      }
    }
    if (!found) {
      if (app) {
        app.fireEvent('unmatchedroute', token);
      }
      Ext.fireEvent('unmatchedroute', token);
    }
  }
  i = 0;
  length = unmatched.length;
  for (; i < length; i++) {
    unmatched[i].onExit();
  }
}, onRouteRejection:function(route, error) {
  Ext.fireEvent('routereject', route, error);
  if (error) {
    Ext.raise(error);
  }
}, connect:function(url, config, instance) {
  var routes = this.routes, delimiter = this.getMultipleToken(), name = config.name || url, version = Ext.getVersion().parts.slice(0, 3).join('.'), handler, route;
  if (url[0] === '!') {
    if (!Ext.util.History.hashbang) {
      Ext.log({level:'error', msg:'Route found with "!" ("' + url + '"). Should use new hashbang functionality instead. ' + 'Please see the router guide for more: https://docs.sencha.com/extjs/' + version + '/guides/application_architecture/router.html'});
    }
    url = url.substr(1);
    this.setHashbang(true);
  }
  if (Ext.isString(config)) {
    config = {action:config};
  }
  handler = Ext.route.Handler.fromRouteConfig(config, instance);
  route = routes[name];
  if (!route) {
    config.name = name;
    config.url = url;
    route = routes[name] = new Ext.route.Route(config);
  }
  route.addHandler(handler);
  if (handler.lazy) {
    var currentHash = Ext.util.History.getToken(), tokens = currentHash.split(delimiter), length = tokens.length, matched = [], i, token;
    for (i = 0; i < length; i++) {
      token = tokens[i];
      if (Ext.Array.indexOf(matched, token) === -1 && route.recognize(token)) {
        matched.push(token);
      }
    }
    this.onStateChange(matched.join(delimiter));
  }
  return handler;
}, disconnect:function(instance, config) {
  var routes = this.routes, route, name;
  if (config) {
    route = config.route || this.getByName(config.name || config.url);
    if (route) {
      route.removeHandler(instance, config);
    }
  } else {
    for (name in routes) {
      route = routes[name];
      route.removeHandler(instance);
    }
  }
}, recognize:function(url) {
  var routes = this.routes, matches = [], name, arr, i, length, route, urlParams;
  for (name in routes) {
    arr = routes[name];
    length = arr && arr.length;
    if (length) {
      i = 0;
      for (; i < length; i++) {
        route = arr[i];
        urlParams = route.recognize(url);
        if (urlParams) {
          matches.push({route:route, urlParams:urlParams});
        }
      }
    }
  }
  return matches.length ? matches : false;
}, draw:function(fn) {
  fn.call(this, this);
}, clear:function() {
  this.routes = {};
}, clearLastTokens:function(token) {
  var routes = this.routes, name, route;
  for (name in routes) {
    route = routes[name];
    if (!token || route.recognize(token)) {
      route.clearLastTokens();
    }
  }
}, getByName:function(name) {
  var routes = this.routes;
  if (routes) {
    return routes[name];
  }
}, suspend:function(trackTokens) {
  this.isSuspended = true;
  if (!this.suspendedQueue && trackTokens !== false) {
    this.suspendedQueue = [];
  }
}, resume:function(discardQueue) {
  var me = this, queue = me.suspendedQueue, token;
  if (me.isSuspended) {
    me.isSuspended = false;
    me.suspendedQueue = null;
    if (!discardQueue && queue) {
      token = queue.join(me.getMultipleToken());
      me.onStateChange(token);
    }
  }
}});
Ext.define('Ext.route.Mixin', {extend:Ext.Mixin, mixinConfig:{id:'routerable', before:{destroy:'destroyRouterable'}}, config:{routes:null}, destroyRouterable:function() {
  Ext.route.Router.disconnect(this);
}, applyRoutes:function(routes, oldRoutes) {
  var Router = Ext.route.Router, url;
  if (routes) {
    for (url in routes) {
      routes[url] = Router.connect(url, routes[url], this);
    }
  }
  if (oldRoutes) {
    for (url in oldRoutes) {
      Router.disconnect(this, oldRoutes[url]);
    }
  }
  return routes;
}, redirectTo:function(hash, opt) {
  var currentHash = Ext.util.History.getToken(), Router = Ext.route.Router, delimiter = Router.getMultipleToken(), tokens = currentHash ? currentHash.split(delimiter) : [], length = tokens.length, force, i, name, obj, route, token, match;
  if (hash === -1) {
    return Ext.util.History.back();
  } else {
    if (hash === 1) {
      return Ext.util.History.forward();
    } else {
      if (hash.isModel) {
        hash = hash.toUrl();
      } else {
        if (Ext.isObject(hash)) {
          for (name in hash) {
            obj = hash[name];
            if (!Ext.isObject(obj)) {
              obj = {token:obj};
            }
            if (length) {
              route = Router.getByName(name);
              if (route) {
                match = false;
                for (i = 0; i < length; i++) {
                  token = tokens[i];
                  if (route.matcherRegex.test(token)) {
                    match = true;
                    if (obj.token) {
                      if (obj.fn && obj.fn.call(this, token, tokens, obj) === false) {
                        continue;
                      }
                      tokens[i] = obj.token;
                      if (obj.force) {
                        route.lastToken = null;
                      }
                    } else {
                      tokens.splice(i, 1);
                      i--;
                      length--;
                      route.lastToken = null;
                    }
                  }
                }
                if (obj && obj.token && !match) {
                  tokens.push(obj.token);
                }
              }
            } else {
              if (obj && obj.token) {
                tokens.push(obj.token);
              }
            }
          }
          hash = tokens.join(delimiter);
        }
      }
    }
  }
  if (opt === true) {
    force = opt;
    opt = null;
  } else {
    if (opt) {
      force = opt.force;
    }
  }
  length = tokens.length;
  if (force && length) {
    for (i = 0; i < length; i++) {
      token = tokens[i];
      Router.clearLastTokens(token);
    }
  }
  if (currentHash === hash) {
    if (force) {
      Router.onStateChange(hash);
    }
    return false;
  }
  if (opt && opt.replace) {
    Ext.util.History.replace(hash);
  } else {
    Ext.util.History.add(hash);
  }
  return true;
}, privates:{afterClassMixedIn:function(targetClass) {
  var proto = targetClass.prototype, routes = proto.routes;
  if (routes) {
    delete proto.routes;
    targetClass.getConfigurator().add({routes:routes});
  }
}}});
Ext.define('Ext.app.BaseController', {mixins:[Ext.mixin.Observable, Ext.route.Mixin], isController:true, config:{id:undefined, control:null, listen:null}, constructor:function(config) {
  var me = this;
  Ext.apply(me, config);
  delete me.control;
  delete me.listen;
  me.eventbus = Ext.app.EventBus;
  me.mixins.observable.constructor.call(me, config);
}, updateId:function(id) {
  this.id = id;
}, applyListen:function(listen) {
  if (Ext.isObject(listen)) {
    listen = Ext.clone(listen);
  }
  return listen;
}, applyControl:function(control) {
  if (Ext.isObject(control)) {
    control = Ext.clone(control);
  }
  return control;
}, updateControl:function(control) {
  this.getId();
  if (control) {
    this.control(control);
  }
}, updateListen:function(listen) {
  this.getId();
  if (listen) {
    this.listen(listen);
  }
}, isActive:function() {
  return true;
}, control:function(selectors, listeners, controller) {
  var me = this, ctrl = controller, obj;
  if (Ext.isString(selectors)) {
    obj = {};
    obj[selectors] = listeners;
  } else {
    obj = selectors;
    ctrl = listeners;
  }
  me.eventbus.control(obj, ctrl || me);
}, listen:function(to, controller) {
  this.eventbus.listen(to, controller || this);
}, destroy:function() {
  var me = this, bus = me.eventbus;
  if (bus) {
    bus.unlisten(me);
    me.eventbus = null;
  }
  me.callParent();
}});
Ext.define('Ext.app.Util', {}, function() {
  Ext.apply(Ext.app, {namespaces:{Ext:{}}, addNamespaces:function(namespace) {
    var namespaces = Ext.app.namespaces, i, l;
    if (!Ext.isArray(namespace)) {
      namespace = [namespace];
    }
    for (i = 0, l = namespace.length; i < l; i++) {
      namespaces[namespace[i]] = true;
    }
  }, clearNamespaces:function() {
    Ext.app.namespaces = {};
  }, getNamespace:function(className) {
    var namespaces = Ext.apply({}, Ext.ClassManager.paths, Ext.app.namespaces), deepestPrefix = '', prefix;
    for (prefix in namespaces) {
      if (namespaces.hasOwnProperty(prefix) && prefix.length > deepestPrefix.length && prefix + '.' === className.substring(0, prefix.length + 1)) {
        deepestPrefix = prefix;
      }
    }
    return deepestPrefix === '' ? undefined : deepestPrefix;
  }, setupPaths:function(appName, appFolder, paths) {
    var manifestPaths = Ext.manifest, ns;
    if (appName && appFolder !== null) {
      manifestPaths = manifestPaths && manifestPaths.paths;
      if (!manifestPaths || appFolder !== undefined) {
        Ext.Loader.setPath(appName, appFolder === undefined ? 'app' : appFolder);
      }
    }
    if (paths) {
      for (ns in paths) {
        if (paths.hasOwnProperty(ns)) {
          Ext.Loader.setPath(ns, paths[ns]);
        }
      }
    }
  }});
  Ext.getNamespace = Ext.app.getNamespace;
});
Ext.define('Ext.util.BasicFilter', {isFilter:true, config:{id:null, disabled:false, serializer:null}, generation:0, constructor:function(config) {
  this.initConfig(config);
}, updateDisabled:function() {
  if (!this.isConfiguring) {
    ++this.generation;
  }
}});
Ext.define('Ext.util.Filter', {extend:Ext.util.BasicFilter, config:{property:null, root:null, value:null, filterFn:null, anyMatch:false, exactMatch:false, caseSensitive:false, disableOnEmpty:false, operator:null, convert:null}, scope:null, $configStrict:false, statics:{createFilterFn:function(filters) {
  if (!filters) {
    return Ext.returnTrue;
  }
  return function(candidate) {
    var items = filters.isCollection ? filters.items : filters, length = items.length, match = true, i, filter;
    for (i = 0; match && i < length; i++) {
      filter = items[i];
      if (!filter.getDisabled()) {
        match = filter.filter(candidate);
      }
    }
    return match;
  };
}, isEqual:function(filter1, filter2) {
  if (filter1.getProperty() !== filter2.getProperty()) {
    return false;
  }
  if (filter1.getOperator() !== filter2.getOperator()) {
    return false;
  }
  if (filter1.getValue() === filter2.getValue()) {
    return true;
  }
  if (Ext.isArray(filter1) && Ext.isArray(filter2)) {
    return Ext.Array.equals(filter1, filter2);
  }
  return false;
}, isInvalid:function(cfg) {
  if (!cfg.filterFn) {
    if (!cfg.property) {
      return 'A Filter requires either a property or a filterFn to be set';
    }
    if (!cfg.hasOwnProperty('value') && !cfg.operator) {
      return 'A Filter requires either a property and value, or a filterFn to be set';
    }
  }
  return false;
}}, constructor:function(config) {
  var warn = Ext.util.Filter.isInvalid(config);
  if (warn) {
    Ext.log.warn(warn);
  }
  this.callParent([config]);
}, preventConvert:{'in':1, notin:1}, filter:function(item) {
  var me = this, filterFn = me._filterFn || me.getFilterFn(), convert = me.getConvert(), value = me._value;
  me._filterValue = value;
  me.isDateValue = Ext.isDate(value);
  if (me.isDateValue) {
    me.dateValue = value.getTime();
  }
  if (convert && !me.preventConvert[me.getOperator()]) {
    me._filterValue = convert.call(me.scope || me, value);
  }
  return filterFn.call(me.scope || me, item);
}, getId:function() {
  var me = this, id = me._id;
  if (!id) {
    id = me.getProperty();
    if (!id) {
      id = Ext.id(null, 'ext-filter-');
    }
    me._id = id;
  }
  return id;
}, getFilterFn:function() {
  var me = this, filterFn = me._filterFn, operator;
  if (!filterFn) {
    operator = me.getOperator();
    if (operator) {
      filterFn = me.operatorFns[operator];
    } else {
      filterFn = me.createRegexFilter();
    }
    me._filterFn = filterFn;
    me.generatedFilterFn = true;
  }
  return filterFn;
}, createRegexFilter:function() {
  var me = this, anyMatch = !!me.getAnyMatch(), exact = !!me.getExactMatch(), value = me.getValue(), matcher = Ext.String.createRegex(value, !anyMatch, !anyMatch && exact, !me.getCaseSensitive());
  return function(item) {
    var val = me.getPropertyValue(item);
    return matcher ? matcher.test(val) : val == null;
  };
}, getPropertyValue:function(item) {
  var root = this._root, value = root == null ? item : item[root];
  return value[this._property];
}, getState:function() {
  var config = this.getInitialConfig(), result = {}, name;
  for (name in config) {
    if (config.hasOwnProperty(name)) {
      result[name] = config[name];
    }
  }
  delete result.root;
  result.value = this.getValue();
  return result;
}, getScope:function() {
  return this.scope;
}, serialize:function() {
  var result = this.getState(), serializer = this.getSerializer(), serialized;
  delete result.id;
  delete result.serializer;
  if (serializer) {
    serialized = serializer.call(this, result);
    if (serialized) {
      result = serialized;
    }
  }
  return result;
}, serializeTo:function(out) {
  var me = this, primitive, serialized;
  me.getFilterFn();
  if (me.generatedFilterFn) {
    out.push(serialized = me.serialize());
    primitive = me.primitiveRe.test(typeof serialized);
  }
  return !primitive;
}, updateOperator:function() {
  this.onConfigMutation();
}, updateConvert:function() {
  this.onConfigMutation();
}, updateProperty:function() {
  this.onConfigMutation();
}, updateAnyMatch:function() {
  this.onConfigMutation();
}, updateExactMatch:function() {
  this.onConfigMutation();
}, updateCaseSensitive:function() {
  this.onConfigMutation();
}, updateValue:function(value) {
  this.onConfigMutation();
  if (this.getDisableOnEmpty()) {
    this.setDisabled(Ext.isEmpty(value));
  }
}, updateFilterFn:function(filterFn) {
  delete this.generatedFilterFn;
}, onConfigMutation:function() {
  this.generation++;
  if (this.generatedFilterFn) {
    this._filterFn = null;
  }
}, updateDisableOnEmpty:function(disableOnEmpty) {
  if (disableOnEmpty) {
    this.setDisabled(Ext.isEmpty(this.getValue()));
  }
}, privates:{primitiveRe:/string|number|boolean/, getCandidateValue:function(candidate, v, preventCoerce) {
  var me = this, convert = me._convert, result = me.getPropertyValue(candidate);
  if (convert) {
    result = convert.call(me.scope || me, result);
  } else {
    if (!preventCoerce) {
      result = Ext.coerce(result, v);
    }
  }
  return result;
}}}, function(Filter) {
  var prototype = Filter.prototype, operatorFns = prototype.operatorFns = {'\x3c':function(candidate) {
    var v = this._filterValue;
    return this.getCandidateValue(candidate, v) < v;
  }, '\x3c\x3d':function(candidate) {
    var v = this._filterValue;
    return this.getCandidateValue(candidate, v) <= v;
  }, '\x3d':function(candidate) {
    var me = this, v = me._filterValue;
    candidate = me.getCandidateValue(candidate, v);
    if (me.isDateValue && candidate instanceof Date) {
      candidate = candidate.getTime();
      v = me.dateValue;
    }
    return candidate == v;
  }, '\x3d\x3d\x3d':function(candidate) {
    var me = this, v = me._filterValue;
    candidate = me.getCandidateValue(candidate, v, true);
    if (me.isDateValue && candidate instanceof Date) {
      candidate = candidate.getTime();
      v = me.dateValue;
    }
    return candidate === v;
  }, '\x3e\x3d':function(candidate) {
    var v = this._filterValue;
    return this.getCandidateValue(candidate, v) >= v;
  }, '\x3e':function(candidate) {
    var v = this._filterValue;
    return this.getCandidateValue(candidate, v) > v;
  }, '!\x3d':function(candidate) {
    var me = this, v = me._filterValue;
    candidate = me.getCandidateValue(candidate, v);
    if (me.isDateValue && candidate instanceof Date) {
      candidate = candidate.getTime();
      v = me.dateValue;
    }
    return candidate != v;
  }, '!\x3d\x3d':function(candidate) {
    var me = this, v = me._filterValue;
    candidate = me.getCandidateValue(candidate, v, true);
    if (me.isDateValue && candidate instanceof Date) {
      candidate = candidate.getTime();
      v = me.dateValue;
    }
    return candidate !== v;
  }, 'in':function(candidate) {
    var v = this._filterValue;
    return Ext.Array.contains(v, this.getCandidateValue(candidate, v));
  }, notin:function(candidate) {
    var v = this._filterValue;
    return !Ext.Array.contains(v, this.getCandidateValue(candidate, v));
  }, like:function(candidate) {
    var v = this._filterValue;
    return v && this.getCandidateValue(candidate, v).toLowerCase().indexOf(v.toLowerCase()) > -1;
  }, '/\x3d':function(candidate) {
    var me = this, v = me._filterValue;
    candidate = me.getCandidateValue(candidate, v);
    if (v !== me.lastRegExpSource) {
      me.lastRegExpSource = v;
      try {
        me.regex = new RegExp(v, 'i');
      } catch (e$54) {
        me.regex = null;
      }
    }
    return me.regex ? me.regex.test(candidate) : false;
  }};
  operatorFns['\x3d\x3d'] = operatorFns['\x3d'];
  operatorFns.gt = operatorFns['\x3e'];
  operatorFns.ge = operatorFns['\x3e\x3d'];
  operatorFns.lt = operatorFns['\x3c'];
  operatorFns.le = operatorFns['\x3c\x3d'];
  operatorFns.eq = operatorFns['\x3d'];
  operatorFns.ne = operatorFns['!\x3d'];
});
Ext.define('Ext.util.AbstractMixedCollection', {mixins:{observable:Ext.util.Observable}, isMixedCollection:true, generation:0, indexGeneration:0, constructor:function(allowFunctions, keyFn) {
  var me = this;
  if (arguments.length === 1 && Ext.isObject(allowFunctions)) {
    me.initialConfig = allowFunctions;
    Ext.apply(me, allowFunctions);
  } else {
    me.allowFunctions = allowFunctions === true;
    if (keyFn) {
      me.getKey = keyFn;
    }
    me.initialConfig = {allowFunctions:me.allowFunctions, getKey:me.getKey};
  }
  me.items = [];
  me.map = {};
  me.keys = [];
  me.indexMap = {};
  me.length = 0;
  me.mixins.observable.constructor.call(me);
}, destroy:function() {
  var me = this;
  me.items = me.map = me.keys = me.indexMap = null;
  me.callParent();
}, allowFunctions:false, add:function(key, obj) {
  var len = this.length, out;
  if (arguments.length === 1) {
    out = this.insert(len, key);
  } else {
    out = this.insert(len, key, obj);
  }
  return out;
}, getKey:function(item) {
  return item.id;
}, replace:function(key, o) {
  var me = this, old, index;
  if (arguments.length === 1) {
    o = arguments[0];
    key = me.getKey(o);
  }
  old = me.map[key];
  if (typeof key === 'undefined' || key === null || typeof old === 'undefined') {
    return me.add(key, o);
  }
  me.generation++;
  index = me.indexOfKey(key);
  me.items[index] = o;
  me.map[key] = o;
  if (me.hasListeners.replace) {
    me.fireEvent('replace', key, old, o);
  }
  return o;
}, reorder:function(mapping) {
  var me = this, items = me.items, index = 0, length = items.length, order = [], remaining = [], oldIndex;
  me.suspendEvents();
  for (oldIndex in mapping) {
    order[mapping[oldIndex]] = items[oldIndex];
  }
  for (index = 0; index < length; index++) {
    if (mapping[index] == undefined) {
      remaining.push(items[index]);
    }
  }
  for (index = 0; index < length; index++) {
    if (order[index] == undefined) {
      order[index] = remaining.shift();
    }
  }
  me.clear();
  me.addAll(order);
  me.resumeEvents();
}, updateKey:function(oldKey, newKey) {
  var me = this, map = me.map, index = me.indexOfKey(oldKey), indexMap = me.indexMap, item;
  if (index > -1) {
    item = map[oldKey];
    delete map[oldKey];
    delete indexMap[oldKey];
    map[newKey] = item;
    indexMap[newKey] = index;
    me.keys[index] = newKey;
    me.indexGeneration = ++me.generation;
  }
}, addAll:function(objs) {
  var me = this, key;
  if (arguments.length > 1 || Ext.isArray(objs)) {
    me.insert(me.length, arguments.length > 1 ? arguments : objs);
  } else {
    for (key in objs) {
      if (objs.hasOwnProperty(key)) {
        if (me.allowFunctions || typeof objs[key] !== 'function') {
          me.add(key, objs[key]);
        }
      }
    }
  }
}, each:function(fn, scope) {
  var items = Ext.Array.push([], this.items), i = 0, len = items.length, item;
  for (; i < len; i++) {
    item = items[i];
    if (fn.call(scope || item, item, i, len) === false) {
      break;
    }
  }
}, eachKey:function(fn, scope) {
  var keys = this.keys, items = this.items, i = 0, len = keys.length;
  for (; i < len; i++) {
    fn.call(scope || window, keys[i], items[i], i, len);
  }
}, findBy:function(fn, scope) {
  var keys = this.keys, items = this.items, i = 0, len = items.length;
  for (; i < len; i++) {
    if (fn.call(scope || window, items[i], keys[i])) {
      return items[i];
    }
  }
  return null;
}, insert:function(index, key, obj) {
  var out;
  if (Ext.isIterable(key)) {
    out = this.doInsert(index, key, obj);
  } else {
    if (arguments.length > 2) {
      out = this.doInsert(index, [key], [obj]);
    } else {
      out = this.doInsert(index, [key]);
    }
    out = out[0];
  }
  return out;
}, doInsert:function(index, keys, objects) {
  var me = this, itemKey, removeIndex, i, len = keys.length, deDupedLen = len, fireAdd = me.hasListeners.add, syncIndices, newKeys = {}, passedDuplicates, oldKeys, oldObjects;
  if (objects != null) {
    me.useLinearSearch = true;
  } else {
    objects = keys;
    keys = new Array(len);
    for (i = 0; i < len; i++) {
      keys[i] = this.getKey(objects[i]);
    }
  }
  me.suspendEvents();
  for (i = 0; i < len; i++) {
    itemKey = keys[i];
    removeIndex = me.indexOfKey(itemKey);
    if (removeIndex !== -1) {
      if (removeIndex < index) {
        index--;
      }
      me.removeAt(removeIndex);
    }
    if (itemKey != null) {
      if (newKeys[itemKey] != null) {
        passedDuplicates = true;
        deDupedLen--;
      }
      newKeys[itemKey] = i;
    }
  }
  me.resumeEvents();
  if (passedDuplicates) {
    oldKeys = keys;
    oldObjects = objects;
    keys = new Array(deDupedLen);
    objects = new Array(deDupedLen);
    i = 0;
    for (itemKey in newKeys) {
      keys[i] = oldKeys[newKeys[itemKey]];
      objects[i] = oldObjects[newKeys[itemKey]];
      i++;
    }
    len = deDupedLen;
  }
  syncIndices = index === me.length && me.indexGeneration === me.generation;
  Ext.Array.insert(me.items, index, objects);
  Ext.Array.insert(me.keys, index, keys);
  me.length += len;
  me.generation++;
  if (syncIndices) {
    me.indexGeneration = me.generation;
  }
  for (i = 0; i < len; i++, index++) {
    itemKey = keys[i];
    if (itemKey != null) {
      me.map[itemKey] = objects[i];
      if (syncIndices) {
        me.indexMap[itemKey] = index;
      }
    }
    if (fireAdd) {
      me.fireEvent('add', index, objects[i], itemKey);
    }
  }
  return objects;
}, remove:function(o) {
  var me = this, removeKey, index;
  if (!me.useLinearSearch && (removeKey = me.getKey(o))) {
    index = me.indexOfKey(removeKey);
  } else {
    index = Ext.Array.indexOf(me.items, o);
  }
  return index === -1 ? false : me.removeAt(index);
}, removeAll:function(items) {
  var me = this, i;
  if (items || me.hasListeners.remove) {
    if (items) {
      for (i = items.length - 1; i >= 0; --i) {
        me.remove(items[i]);
      }
    } else {
      while (me.length) {
        me.removeAt(0);
      }
    }
  } else {
    me.length = me.items.length = me.keys.length = 0;
    me.map = {};
    me.indexMap = {};
    me.generation++;
    me.indexGeneration = me.generation;
  }
}, removeAt:function(index) {
  var me = this, o, key;
  if (index < me.length && index >= 0) {
    me.length--;
    o = me.items[index];
    Ext.Array.erase(me.items, index, 1);
    key = me.keys[index];
    if (typeof key !== 'undefined') {
      delete me.map[key];
    }
    Ext.Array.erase(me.keys, index, 1);
    if (me.hasListeners.remove) {
      me.fireEvent('remove', o, key);
    }
    me.generation++;
    return o;
  }
  return false;
}, removeRange:function(index, removeCount) {
  var me = this, o, key, i, limit, syncIndices, trimming;
  if (index < me.length && index >= 0) {
    if (!removeCount) {
      removeCount = 1;
    }
    limit = Math.min(index + removeCount, me.length);
    removeCount = limit - index;
    trimming = limit === me.length;
    syncIndices = trimming && me.indexGeneration === me.generation;
    for (i = index; i < limit; i++) {
      key = me.keys[i];
      if (key != null) {
        delete me.map[key];
        if (syncIndices) {
          delete me.indexMap[key];
        }
      }
    }
    o = me.items[i - 1];
    me.length -= removeCount;
    me.generation++;
    if (syncIndices) {
      me.indexGeneration = me.generation;
    }
    if (trimming) {
      me.items.length = me.keys.length = me.length;
    } else {
      me.items.splice(index, removeCount);
      me.keys.splice(index, removeCount);
    }
    return o;
  }
  return false;
}, removeAtKey:function(key) {
  var me = this, keys = me.keys, i;
  if (key == null) {
    for (i = keys.length - 1; i >= 0; i--) {
      if (keys[i] == null) {
        me.removeAt(i);
      }
    }
  } else {
    return me.removeAt(me.indexOfKey(key));
  }
}, getCount:function() {
  return this.length;
}, indexOf:function(o) {
  var me = this, key;
  if (o != null) {
    if (!me.useLinearSearch && (key = me.getKey(o))) {
      return this.indexOfKey(key);
    }
    return Ext.Array.indexOf(me.items, o);
  }
  return -1;
}, indexOfKey:function(key) {
  if (!this.map.hasOwnProperty(key)) {
    return -1;
  }
  if (this.indexGeneration !== this.generation) {
    this.rebuildIndexMap();
  }
  return this.indexMap[key];
}, rebuildIndexMap:function() {
  var me = this, indexMap = me.indexMap = {}, keys = me.keys, len = keys.length, i;
  for (i = 0; i < len; i++) {
    indexMap[keys[i]] = i;
  }
  me.indexGeneration = me.generation;
}, get:function(key) {
  var me = this, mk = me.map[key], item = mk !== undefined ? mk : typeof key === 'number' ? me.items[key] : undefined;
  return typeof item !== 'function' || me.allowFunctions ? item : null;
}, getAt:function(index) {
  return this.items[index];
}, getByKey:function(key) {
  return this.map[key];
}, contains:function(o) {
  var me = this, key;
  if (o != null) {
    if (!me.useLinearSearch && (key = me.getKey(o))) {
      return this.map[key] != null;
    }
    return Ext.Array.indexOf(this.items, o) !== -1;
  }
  return false;
}, containsKey:function(key) {
  return this.map.hasOwnProperty(key);
}, clear:function() {
  var me = this;
  if (me.generation) {
    me.length = 0;
    me.items = [];
    me.keys = [];
    me.map = {};
    me.indexMap = {};
    me.generation++;
    me.indexGeneration = me.generation;
  }
  if (me.hasListeners.clear) {
    me.fireEvent('clear');
  }
}, first:function() {
  return this.items[0];
}, last:function() {
  return this.items[this.length - 1];
}, sum:function(property, root, start, end) {
  var values = this.extractValues(property, root), length = values.length, sum = 0, i;
  start = start || 0;
  end = end || end === 0 ? end : length - 1;
  for (i = start; i <= end; i++) {
    sum += values[i];
  }
  return sum;
}, collect:function(property, root, allowNull) {
  var values = this.extractValues(property, root), length = values.length, hits = {}, unique = [], value, strValue, i;
  for (i = 0; i < length; i++) {
    value = values[i];
    strValue = String(value);
    if ((allowNull || !Ext.isEmpty(value)) && !hits[strValue]) {
      hits[strValue] = true;
      unique.push(value);
    }
  }
  return unique;
}, extractValues:function(property, root) {
  var values = this.items;
  if (root) {
    values = Ext.Array.pluck(values, root);
  }
  return Ext.Array.pluck(values, property);
}, hasRange:function(start, end) {
  return end < this.length;
}, getRange:function(start, end) {
  var me = this, items = me.items, range = [], len = items.length, tmp, reverse;
  if (len < 1) {
    return range;
  }
  if (start > end) {
    reverse = true;
    tmp = start;
    start = end;
    end = tmp;
  }
  if (start < 0) {
    start = 0;
  }
  if (end == null || end >= len) {
    end = len - 1;
  }
  range = items.slice(start, end + 1);
  if (reverse && range.length) {
    range.reverse();
  }
  return range;
}, filter:function(property, value, anyMatch, caseSensitive) {
  var filters = [];
  if (Ext.isString(property)) {
    filters.push(new Ext.util.Filter({property:property, value:value, anyMatch:anyMatch, caseSensitive:caseSensitive}));
  } else {
    if (Ext.isArray(property) || property instanceof Ext.util.Filter) {
      filters = filters.concat(property);
    }
  }
  return this.filterBy(Ext.util.Filter.createFilterFn(filters));
}, filterBy:function(fn, scope) {
  var me = this, newMC = new me.self(me.initialConfig), keys = me.keys, items = me.items, length = items.length, i;
  newMC.getKey = me.getKey;
  for (i = 0; i < length; i++) {
    if (fn.call(scope || me, items[i], keys[i])) {
      newMC.add(keys[i], items[i]);
    }
  }
  newMC.useLinearSearch = me.useLinearSearch;
  return newMC;
}, findIndex:function(property, value, start, anyMatch, caseSensitive) {
  if (Ext.isEmpty(value, false)) {
    return -1;
  }
  value = this.createValueMatcher(value, anyMatch, caseSensitive);
  return this.findIndexBy(function(o) {
    return o && value.test(o[property]);
  }, null, start);
}, findIndexBy:function(fn, scope, start) {
  var me = this, keys = me.keys, items = me.items, i = start || 0, len = items.length;
  for (; i < len; i++) {
    if (fn.call(scope || me, items[i], keys[i])) {
      return i;
    }
  }
  return -1;
}, createValueMatcher:function(value, anyMatch, caseSensitive, exactMatch) {
  var er;
  if (!value.exec) {
    er = Ext.String.escapeRegex;
    value = String(value);
    if (anyMatch === true) {
      value = er(value);
    } else {
      value = '^' + er(value);
      if (exactMatch === true) {
        value += '$';
      }
    }
    value = new RegExp(value, caseSensitive ? '' : 'i');
  }
  return value;
}, clone:function() {
  var me = this, copy = new me.self(me.initialConfig);
  copy.add(me.keys, me.items);
  copy.useLinearSearch = me.useLinearSearch;
  return copy;
}});
Ext.define('Ext.util.Sorter', {isSorter:true, config:{property:null, sorterFn:null, root:null, transform:null, direction:'ASC', id:undefined}, statics:{createComparator:function(sorters, nextFn) {
  nextFn = nextFn || 0;
  return function(lhs, rhs) {
    var items = sorters.isCollection ? sorters.items : sorters, n = items.length, comp, i;
    for (i = 0; i < n; ++i) {
      comp = items[i].sort(lhs, rhs);
      if (comp) {
        return comp;
      }
    }
    return nextFn && nextFn(lhs, rhs);
  };
}}, multiplier:1, constructor:function(config) {
  if (config && !this.isGrouper) {
    if (!config.property === !config.sorterFn) {
      Ext.raise('A Sorter requires either a property or a sorterFn.');
    }
  }
  this.initConfig(config);
}, getId:function() {
  var id = this._id;
  if (!id) {
    id = this.getProperty();
    if (!id) {
      id = Ext.id(null, 'ext-sorter-');
    }
    this._id = id;
  }
  return id;
}, sort:function(lhs, rhs) {
  return this.multiplier * this.sortFn(lhs, rhs);
}, sortFn:function(item1, item2) {
  var me = this, transform = me._transform, root = me._root, property = me._property, lhs, rhs;
  if (root) {
    item1 = item1[root];
    item2 = item2[root];
  }
  lhs = item1[property];
  rhs = item2[property];
  if (transform) {
    lhs = transform(lhs);
    rhs = transform(rhs);
  }
  return lhs > rhs ? 1 : lhs < rhs ? -1 : 0;
}, applyDirection:function(direction) {
  return direction ? direction : 'ASC';
}, updateDirection:function(direction) {
  this.multiplier = direction.toUpperCase() === 'DESC' ? -1 : 1;
}, updateProperty:function(property) {
  if (property) {
    delete this.sortFn;
  }
}, updateSorterFn:function(sorterFn) {
  this.sortFn = sorterFn;
}, toggle:function() {
  this.setDirection(Ext.String.toggle(this.getDirection(), 'ASC', 'DESC'));
}, getState:function() {
  var me = this, result = {root:me.getRoot(), property:me.getProperty(), direction:me.getDirection()};
  if (me._id) {
    result.id = me._id;
  }
  return result;
}, serialize:function() {
  return {property:this.getProperty(), direction:this.getDirection()};
}});
Ext.define('Ext.util.Sortable', {isSortable:true, $configPrefixed:false, $configStrict:false, config:{sorters:null}, defaultSortDirection:'ASC', multiSortLimit:3, statics:{createComparator:function(sorters) {
  return sorters && sorters.length ? function(r1, r2) {
    var result = sorters[0].sort(r1, r2), length = sorters.length, i = 1;
    for (; !result && i < length; i++) {
      result = sorters[i].sort.call(sorters[i], r1, r2);
    }
    return result;
  } : function() {
    return 0;
  };
}}, applySorters:function(sorters) {
  var me = this, sortersCollection;
  sortersCollection = me.getSorters() || new Ext.util.MixedCollection(false, Ext.returnId);
  if (sorters) {
    sortersCollection.addAll(me.decodeSorters(sorters));
  }
  return sortersCollection;
}, sort:function(sorters, direction, insertionPosition, doSort) {
  var me = this, sorter, overFlow, currentSorters = me.getSorters();
  if (!currentSorters) {
    me.setSorters(null);
    currentSorters = me.getSorters();
  }
  if (Ext.isArray(sorters)) {
    doSort = insertionPosition;
    insertionPosition = direction;
  } else {
    if (Ext.isObject(sorters)) {
      sorters = [sorters];
      doSort = insertionPosition;
      insertionPosition = direction;
    } else {
      if (Ext.isString(sorters)) {
        sorter = currentSorters.get(sorters);
        if (!sorter) {
          sorter = {property:sorters, direction:direction};
        } else {
          if (direction == null) {
            sorter.toggle();
          } else {
            sorter.setDirection(direction);
          }
        }
        sorters = [sorter];
      }
    }
  }
  if (sorters && sorters.length) {
    sorters = me.decodeSorters(sorters);
    switch(insertionPosition) {
      case 'multi':
        currentSorters.insert(0, sorters[0]);
        overFlow = currentSorters.getCount() - me.multiSortLimit;
        if (overFlow > 0) {
          currentSorters.removeRange(me.multiSortLimit, overFlow);
        }
        break;
      case 'prepend':
        currentSorters.insert(0, sorters);
        break;
      case 'append':
        currentSorters.addAll(sorters);
        break;
      case undefined:
      case null:
      case 'replace':
        currentSorters.clear();
        currentSorters.addAll(sorters);
        break;
      default:
        Ext.raise('Sorter insertion point must be "multi", "prepend", ' + '"append" or "replace"');
    }
  }
  if (doSort !== false) {
    me.fireEvent('beforesort', me, sorters);
    me.onBeforeSort(sorters);
    if (me.getSorterCount()) {
      me.doSort(me.generateComparator());
    }
  }
  return sorters;
}, getSorterCount:function() {
  return this.getSorters().items.length;
}, generateComparator:function() {
  var sorters = this.getSorters().getRange();
  return sorters.length ? this.createComparator(sorters) : this.emptyComparator;
}, emptyComparator:function() {
  return 0;
}, onBeforeSort:Ext.emptyFn, decodeSorters:function(sorters) {
  if (!Ext.isArray(sorters)) {
    if (sorters === undefined) {
      sorters = [];
    } else {
      sorters = [sorters];
    }
  }
  var length = sorters.length, Sorter = Ext.util.Sorter, model = this.getModel ? this.getModel() : this.model, field, config, i;
  for (i = 0; i < length; i++) {
    config = sorters[i];
    if (!(config instanceof Sorter)) {
      if (Ext.isString(config)) {
        config = {property:config};
      }
      Ext.applyIf(config, {root:this.sortRoot, direction:'ASC'});
      if (config.fn) {
        config.sorterFn = config.fn;
      }
      if (typeof config === 'function') {
        config = {sorterFn:config};
      }
      if (model && !config.transform) {
        field = model.getField(config.property);
        config.transform = field && field.sortType !== Ext.identityFn ? field.sortType : undefined;
      }
      sorters[i] = new Ext.util.Sorter(config);
    }
  }
  return sorters;
}, getFirstSorter:function() {
  var sorters = this.getSorters().items, len = sorters.length, i = 0, sorter;
  for (; i < len; ++i) {
    sorter = sorters[i];
    if (!sorter.isGrouper) {
      return sorter;
    }
  }
  return null;
}}, function() {
  this.prototype.createComparator = this.createComparator;
});
Ext.define('Ext.util.MixedCollection', {extend:Ext.util.AbstractMixedCollection, mixins:{sortable:Ext.util.Sortable}, constructor:function() {
  this.initConfig();
  this.callParent(arguments);
}, doSort:function(sorterFn) {
  this.sortBy(sorterFn);
}, _sort:function(property, dir, fn) {
  var me = this, i, len, dsc = String(dir).toUpperCase() === 'DESC' ? -1 : 1, c = [], keys = me.keys, items = me.items, o;
  fn = fn || function(a, b) {
    return a - b;
  };
  for (i = 0, len = items.length; i < len; i++) {
    c[c.length] = {key:keys[i], value:items[i], index:i};
  }
  Ext.Array.sort(c, function(a, b) {
    return fn(a[property], b[property]) * dsc || (a.index < b.index ? -1 : 1);
  });
  for (i = 0, len = c.length; i < len; i++) {
    o = c[i];
    items[i] = o.value;
    keys[i] = o.key;
    me.indexMap[o.key] = i;
  }
  me.generation++;
  me.indexGeneration = me.generation;
  me.fireEvent('sort', me);
}, sortBy:function(sorterFn) {
  var me = this, items = me.items, item, keys = me.keys, key, length = items.length, i;
  for (i = 0; i < length; i++) {
    items[i].$extCollectionIndex = i;
  }
  Ext.Array.sort(items, function(a, b) {
    return sorterFn(a, b) || (a.$extCollectionIndex < b.$extCollectionIndex ? -1 : 1);
  });
  for (i = 0; i < length; i++) {
    item = items[i];
    key = me.getKey(item);
    keys[i] = key;
    me.indexMap[key] = i;
    delete item.$extCollectionIndex;
  }
  me.generation++;
  me.indexGeneration = me.generation;
  me.fireEvent('sort', me, items, keys);
}, findInsertionIndex:function(newItem, sorterFn) {
  var me = this, items = me.items, start = 0, end = items.length - 1, middle, comparison;
  if (!sorterFn) {
    sorterFn = me.generateComparator();
  }
  while (start <= end) {
    middle = start + end >> 1;
    comparison = sorterFn(newItem, items[middle]);
    if (comparison >= 0) {
      start = middle + 1;
    } else {
      if (comparison < 0) {
        end = middle - 1;
      }
    }
  }
  return start;
}, reorder:function(mapping) {
  this.callParent([mapping]);
  this.fireEvent('sort', this);
}, sortByKey:function(dir, fn) {
  this._sort('key', dir, fn || function(a, b) {
    var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
    return v1 > v2 ? 1 : v1 < v2 ? -1 : 0;
  });
}});
Ext.define('Ext.util.CollectionKey', {mixins:[Ext.mixin.Identifiable], isCollectionKey:true, observerPriority:-200, config:{collection:null, keyFn:null, property:null, rootProperty:null, unique:true}, generation:0, map:null, mapRebuilds:0, constructor:function(config) {
  this.initConfig(config);
  if (!Ext.isFunction(this.getKey)) {
    Ext.raise('CollectionKey requires a keyFn or property config');
  }
}, get:function(key) {
  var map = this.map || this.getMap();
  return map[key] || null;
}, clear:function() {
  this.map = null;
}, getRootProperty:function() {
  var me = this, root = this.callParent();
  return root !== null ? root : me.getCollection().getRootProperty();
}, indexOf:function(key, startAt) {
  var map = this.map || this.getMap(), item = map[key], collection = this.getCollection(), length = collection.length, i, index, items, n;
  if (!item) {
    return -1;
  }
  if (startAt === undefined) {
    startAt = -1;
  }
  if (item instanceof Array) {
    items = item;
    index = length;
    for (n = items.length; n-- > 0;) {
      i = collection.indexOf(items[n]);
      if (i < index && i > startAt) {
        index = i;
      }
    }
    if (index === length) {
      return -1;
    }
  } else {
    index = collection.indexOf(item);
  }
  return index > startAt ? index : -1;
}, updateKey:function(item, oldKey) {
  var me = this, map = me.map, bucket, index;
  if (map) {
    bucket = map[oldKey];
    if (bucket instanceof Array) {
      index = Ext.Array.indexOf(bucket, item);
      if (index >= 0) {
        if (bucket.length > 2) {
          bucket.splice(index, 1);
        } else {
          map[oldKey] = bucket[1 - index];
        }
      }
    } else {
      if (bucket) {
        if (me.getUnique() && bucket !== item) {
          Ext.raise('Incorrect oldKey "' + oldKey + '" for item with newKey "' + me.getKey(item) + '"');
        }
        delete map[oldKey];
      }
    }
    me.add([item]);
  }
}, onCollectionAdd:function(collection, add) {
  if (this.map) {
    this.add(add.items);
  }
}, onCollectionItemChange:function(collection, details) {
  this.map = null;
}, onCollectionRefresh:function() {
  this.map = null;
}, onCollectionRemove:function(collection, remove) {
  var me = this, map = me.map, items = remove.items, length = items.length, i, key;
  if (map) {
    if (me.getUnique() && length < collection.length / 2) {
      for (i = 0; i < length; ++i) {
        key = me.getKey(items[i]);
        delete map[key];
      }
    } else {
      me.map = null;
    }
  }
}, add:function(items) {
  var me = this, map = me.map, bucket, i, item, key, length, unique;
  length = items.length;
  unique = me.getUnique();
  for (i = 0; i < length; ++i) {
    key = me.getKey(item = items[i]);
    if (unique || !(key in map)) {
      map[key] = item;
    } else {
      if (!((bucket = map[key]) instanceof Array)) {
        map[key] = bucket = [bucket];
      }
      bucket.push(item);
    }
  }
}, applyKeyFn:function(keyFn) {
  if (Ext.isString(keyFn)) {
    this.getKey = function(item) {
      return item[keyFn]();
    };
  } else {
    this.getKey = keyFn;
  }
}, updateProperty:function(property) {
  var root = this.getRootProperty();
  this.getKey = function(item) {
    return (root ? item[root] : item)[property];
  };
}, getMap:function() {
  var me = this, map = me.map;
  if (!map) {
    me.map = map = {};
    me.keysByItemKey = {};
    ++me.mapRebuilds;
    me.add(me.getCollection().items);
  }
  return map;
}, updateCollection:function(collection, oldCollection) {
  if (collection) {
    collection.addObserver(this);
  }
  if (oldCollection) {
    oldCollection.removeObserver(this);
  }
}, clone:function() {
  return new Ext.util.CollectionKey(this.getCurrentConfig());
}, destroy:function() {
  this.clear();
  this.getCollection().removeObserver(this);
  this.destroyed = true;
}});
Ext.define('Ext.util.Grouper', {extend:Ext.util.Sorter, isGrouper:true, config:{groupFn:null, sortProperty:null}, constructor:function(config) {
  if (config) {
    if (config.getGroupString) {
      Ext.raise('Cannot set getGroupString - use groupFn instead');
    }
  }
  this.callParent(arguments);
}, getGroupString:function(item) {
  return item.$collapsedGroupPlaceholder ? item.$groupKey : this.getGroupValue(item).toString();
}, getGroupValue:function(item) {
  var groupValue = item.$collapsedGroupPlaceholder ? item.$groupValue : this._groupFn(item);
  return groupValue != null ? groupValue : '';
}, sortFn:function(item1, item2) {
  var me = this, lhs = me.getGroupValue(item1), rhs = me.getGroupValue(item2), property = me._sortProperty, root = me._root, sorterFn = me._sorterFn, transform = me._transform;
  if (lhs === rhs || Ext.Date.isEqual(lhs, rhs)) {
    return 0;
  }
  if (property || sorterFn) {
    if (sorterFn) {
      return sorterFn.call(this, item1, item2);
    }
    if (root) {
      item1 = item1[root];
      item2 = item2[root];
    }
    lhs = item1[property];
    rhs = item2[property];
    if (transform) {
      lhs = transform(lhs);
      rhs = transform(rhs);
    }
  }
  return lhs > rhs ? 1 : lhs < rhs ? -1 : 0;
}, standardGroupFn:function(item) {
  var root = this._root;
  return (root ? item[root] : item)[this._property];
}, updateSorterFn:function() {
}, updateProperty:function() {
  if (!this.getGroupFn()) {
    this.setGroupFn(this.standardGroupFn);
  }
}});
Ext.define('Ext.util.Collection', {mixins:[Ext.mixin.Observable], isCollection:true, config:{autoFilter:true, autoSort:true, autoGroup:true, decoder:null, extraKeys:null, filters:null, grouper:null, groups:null, groupConfig:null, rootProperty:null, sorters:null, multiSortLimit:3, defaultSortDirection:'ASC', source:null, trackGroups:true}, generation:0, indices:null, indexRebuilds:0, updating:0, grouped:false, sorted:false, filtered:false, $endUpdatePriority:1001, manageSorters:true, constructor:function(config) {
  var me = this;
  me.callParent([config]);
  me.items = [];
  me.map = {};
  me.length = 0;
  if (config && config.keyFn) {
    me.getKey = config.keyFn;
  }
  me.mixins.observable.constructor.call(me, config);
}, destroy:function() {
  var me = this, filters = me._filters, sorters = me._sorters, groups = me._groups;
  if (filters) {
    filters.destroy();
    me._filters = null;
  }
  if (sorters) {
    me.grouped = me.sorted = false;
    me.setSorters(null);
    if (me.manageSorters) {
      sorters.destroy();
    }
  }
  if (groups) {
    groups.destroy();
    me._groups = null;
  }
  me.setSource(null);
  me.observers = me.items = me.map = null;
  me.callParent();
}, add:function(item) {
  var me = this, items = me.decodeItems(arguments, 0), ret = items;
  if (items.length) {
    me.splice(me.length, 0, items);
    ret = items.length === 1 ? items[0] : items;
  }
  return ret;
}, replaceAll:function() {
  var me = this, ret, items;
  items = me.decodeItems(arguments, 0);
  ret = items;
  if (items.length) {
    me.splice(0, me.length, items);
    ret = items.length === 1 ? items[0] : items;
  } else {
    me.removeAll();
  }
  return ret;
}, aggregate:function(property, operation, begin, end, scope) {
  var me = this, args = Ext.Array.slice(arguments);
  args.unshift(me.items);
  return me.aggregateItems.apply(me, args);
}, aggregateByGroup:function(property, operation, scope) {
  var groups = this.getGroups();
  return this.aggregateGroups(groups, property, operation, scope);
}, aggregateItems:function(items, property, operation, begin, end, scope) {
  var me = this, range = Ext.Number.clipIndices(items.length, [begin, end]), subsetRequested = begin !== 0 && end !== items.length, i, j, rangeLen, root, value, values, valueItems;
  begin = range[0];
  end = range[1];
  if (!Ext.isFunction(operation)) {
    operation = me._aggregators[operation];
    return operation.call(me, items, begin, end, property, me.getRootProperty());
  }
  root = me.getRootProperty();
  values = new Array(rangeLen);
  valueItems = subsetRequested ? new Array(rangeLen) : items;
  for (i = begin, j = 0; i < end; ++i, j++) {
    if (subsetRequested) {
      valueItems[j] = value = items[i];
    }
    values[j] = (root ? value[root] : value)[property];
  }
  return operation.call(scope || me, items, values, 0);
}, aggregateGroups:function(groups, property, operation, scope) {
  var items = groups.items, len = items.length, callDirect = !Ext.isFunction(operation), out = {}, i, group, result;
  for (i = 0; i < len; ++i) {
    group = items[i];
    if (!callDirect) {
      result = this.aggregateItems(group.items, property, operation, null, null, scope);
    } else {
      result = group[operation](property);
    }
    out[group.getGroupKey()] = result;
  }
  return out;
}, beginUpdate:function() {
  if (!this.updating++) {
    this.notify('beginupdate');
  }
}, clear:function() {
  var me = this, generation = me.generation, ret = generation ? me.items : [], extraKeys, indexName;
  if (generation) {
    me.items.length = me.length = 0;
    me.map = {};
    me.indices = {};
    me.generation++;
    extraKeys = me.getExtraKeys();
    if (extraKeys) {
      for (indexName in extraKeys) {
        extraKeys[indexName].clear();
      }
    }
  }
  return ret;
}, clone:function() {
  var me = this, copy = new me.self(me.initialConfig);
  copy.add(me.items);
  return copy;
}, collect:function(property, root, allowNull) {
  var items = this.items, length = items.length, map = {}, ret = [], i, strValue, value;
  for (i = 0; i < length; ++i) {
    value = items[i];
    value = (root ? value[root] : value)[property];
    strValue = String(value);
    if ((allowNull || !Ext.isEmpty(value)) && !map[strValue]) {
      map[strValue] = 1;
      ret.push(value);
    }
  }
  return ret;
}, contains:function(item) {
  var ret = false, key;
  if (item != null) {
    key = this.getKey(item);
    ret = this.map[key] === item;
  }
  return ret;
}, containsAll:function(items) {
  var all = Ext.isArray(items) ? items : arguments, i;
  for (i = all.length; i-- > 0;) {
    if (!this.contains(all[i])) {
      return false;
    }
  }
  return true;
}, containsKey:function(key) {
  return key in this.map;
}, createFiltered:function(property, value, anyMatch, caseSensitive, exactMatch) {
  var me = this, ret = new me.self(Ext.applyIf({source:null}, me.initialConfig)), root = me.getRootProperty(), items = me.items, length, i, filters, fn, scope;
  if (Ext.isFunction(property)) {
    fn = property;
    scope = value;
  } else {
    if (Ext.isString(property)) {
      filters = [new Ext.util.Filter({property:property, value:value, root:root, anyMatch:anyMatch, caseSensitive:caseSensitive, exactMatch:exactMatch})];
    } else {
      if (property instanceof Ext.util.Filter) {
        filters = [property];
        property.setRoot(root);
      } else {
        if (Ext.isArray(property)) {
          filters = property.slice(0);
          for (i = 0, length = filters.length; i < length; ++i) {
            filters[i].setRoot(root);
          }
        }
      }
    }
    fn = Ext.util.Filter.createFilterFn(filters);
  }
  scope = scope || me;
  for (i = 0, length = items.length; i < length; i++) {
    if (fn.call(scope, items[i])) {
      ret.add(items[i]);
    }
  }
  return ret;
}, filterBy:function(fn, scope) {
  return this.createFiltered(fn, scope);
}, each:function(fn, scope) {
  var items = this.items, len = items.length, i, ret;
  if (len) {
    scope = scope || this;
    items = items.slice(0);
    for (i = 0; i < len; i++) {
      ret = fn.call(scope, items[i], i, len);
      if (ret === false) {
        break;
      }
    }
  }
  return ret;
}, eachKey:function(fn, scope) {
  var me = this, items = me.items, len = items.length, i, item, key, ret;
  if (len) {
    scope = scope || me;
    items = items.slice(0);
    for (i = 0; i < len; i++) {
      key = me.getKey(item = items[i]);
      ret = fn.call(scope, key, item, i, len);
      if (ret === false) {
        break;
      }
    }
  }
  return ret;
}, endUpdate:function() {
  if (!--this.updating) {
    this.notify('endupdate');
  }
}, find:function(property, value, start, startsWith, endsWith, ignoreCase) {
  var regex, root;
  if (Ext.isEmpty(value, false)) {
    return null;
  }
  regex = Ext.String.createRegex(value, startsWith, endsWith, ignoreCase);
  root = this.getRootProperty();
  return this.findBy(function(item) {
    return item && regex.test((root ? item[root] : item)[property]);
  }, null, start);
}, findBy:function(fn, scope, start) {
  var me = this, items = me.items, len = items.length, i, item, key;
  scope = scope || me;
  for (i = start || 0; i < len; i++) {
    key = me.getKey(item = items[i]);
    if (fn.call(scope, item, key)) {
      return items[i];
    }
  }
  return null;
}, findIndex:function(property, value, start, startsWith, endsWith, ignoreCase) {
  var item = this.find(property, value, start, startsWith, endsWith, ignoreCase);
  return item ? this.indexOf(item) : -1;
}, findIndexBy:function(fn, scope, start) {
  var item = this.findBy(fn, scope, start);
  return item ? this.indexOf(item) : -1;
}, first:function(grouped) {
  var groups = grouped ? this.getGroups() : undefined;
  return groups ? this.aggregateGroups(groups, null, 'first') : this.items[0];
}, last:function(grouped) {
  var groups = grouped ? this.getGroups() : undefined;
  return groups ? this.aggregateGroups(groups, null, 'last') : this.items[this.length - 1];
}, get:function(key) {
  return this.map[key];
}, getAt:function(index) {
  return this.items[index];
}, getByKey:function(key) {
  return this.map[key];
}, getCount:function() {
  return this.length;
}, getKey:function(item) {
  var id = item.id;
  return id === 0 || id ? id : (id = item._id) === 0 || id ? id : item.getId();
}, getRange:function(begin, end) {
  var items = this.items, length = items.length, range;
  if (begin > end) {
    Ext.raise('Inverted range passed to Collection.getRange: [' + begin + ',' + end + ']');
  }
  if (!length) {
    range = [];
  } else {
    range = Ext.Number.clipIndices(length, [begin, end]);
    range = items.slice(range[0], range[1]);
  }
  return range;
}, getValues:function(property, root, start, end) {
  var items = this.items, range = Ext.Number.clipIndices(items.length, [start, end]), ret = [], i, value;
  for (i = range[0], end = range[1]; i < end; ++i) {
    value = items[i];
    value = (root ? value[root] : value)[property];
    ret.push(value);
  }
  return ret;
}, indexOf:function(item) {
  var key;
  if (!item) {
    return -1;
  }
  key = this.getKey(item);
  return this.indexOfKey(key);
}, indexOfKey:function(key) {
  var me = this, indices = me.indices;
  if (key in me.map) {
    if (!indices) {
      indices = me.getIndices();
    }
    return indices[key];
  }
  return -1;
}, insert:function(index, item) {
  var me = this, items = me.decodeItems(arguments, 1), ret = items;
  if (items.length) {
    me.splice(index, 0, items);
    ret = items.length === 1 ? items[0] : items;
  }
  return ret;
}, itemChanged:function(item, modified, oldKey, meta) {
  var me = this, keyChanged = oldKey !== undefined, filtered = me.filtered && me.getAutoFilter(), filterChanged = false, itemMovement = 0, items = me.items, last = me.length - 1, sorted = me.sorted && last > 0 && me.getAutoSort(), source = me.getSource(), toRemove = 0, itemFiltered = false, wasFiltered = false, details, newKey, sortFn, toAdd, index, newIndex;
  if (source && !source.updating) {
    me.sourceUpdating = true;
    source.itemChanged(item, modified, oldKey, meta);
    me.sourceUpdating = false;
  } else {
    newKey = me.getKey(item);
    if (filtered) {
      index = me.indexOfKey(keyChanged ? oldKey : newKey);
      wasFiltered = index < 0;
      itemFiltered = me.isItemFiltered(item);
      filterChanged = wasFiltered !== itemFiltered;
    }
    if (filterChanged) {
      if (itemFiltered) {
        toRemove = [item];
        newIndex = -1;
      } else {
        toAdd = [item];
        newIndex = me.length;
      }
    } else {
      if (sorted && !itemFiltered) {
        if (!filtered) {
          index = me.indexOfKey(keyChanged ? oldKey : newKey);
        }
        sortFn = me.getSortFn();
        if (index !== -1) {
          if (index && sortFn(items[index - 1], items[index]) > 0) {
            itemMovement = -1;
            newIndex = Ext.Array.binarySearch(items, item, 0, index, sortFn);
          } else {
            if (index < last && sortFn(items[index], items[index + 1]) > 0) {
              itemMovement = 1;
              newIndex = Ext.Array.binarySearch(items, item, index + 1, sortFn);
            }
          }
          if (itemMovement) {
            toAdd = [item];
          }
        }
      }
    }
    details = {item:item, key:newKey, index:newIndex, filterChanged:filterChanged, keyChanged:keyChanged, indexChanged:!!itemMovement, filtered:itemFiltered, oldIndex:index, newIndex:newIndex, wasFiltered:wasFiltered, meta:meta};
    if (keyChanged) {
      details.oldKey = oldKey;
    }
    if (modified) {
      details.modified = modified;
    }
    ++me.generation;
    me.beginUpdate();
    me.notify('beforeitemchange', [details]);
    if (keyChanged) {
      me.updateKey(item, oldKey, details);
    }
    if (toAdd || toRemove) {
      me.splice(newIndex, toRemove, toAdd);
    }
    if (itemMovement > 0) {
      details.newIndex--;
    } else {
      if (itemMovement < 0) {
        details.oldIndex++;
      }
    }
    me.notify(itemFiltered ? 'filtereditemchange' : 'itemchange', [details]);
    me.endUpdate();
  }
}, remove:function(item) {
  var me = this, items = me.decodeRemoveItems(arguments, 0), length = me.length;
  me.splice(0, items);
  return length - me.length;
}, removeAll:function() {
  var me = this, length = me.length;
  if (me.generation && length) {
    me.splice(0, length);
  }
  return me;
}, removeAt:function(index, count) {
  var me = this, length = me.length, Num = Ext.Number, range = Num.clipIndices(length, [index, count === undefined ? 1 : count], Num.Clip.COUNT), n = range[0], removeCount = range[1] - n, item = removeCount === 1 && me.getAt(n), removed;
  me.splice(n, removeCount);
  removed = me.length - length;
  return item && removed ? item : removed;
}, removeByKey:function(key) {
  var item = this.getByKey(key);
  if (!item || !this.remove(item)) {
    return false;
  }
  return item;
}, replace:function(item) {
  var index = this.indexOf(item);
  if (index === -1) {
    this.add(item);
  } else {
    this.insert(index, item);
  }
}, splice:function(index, toRemove, toAdd) {
  var me = this, autoSort = me.sorted && me.getAutoSort(), map = me.map, items = me.items, length = me.length, removeItems = toRemove instanceof Array ? me.decodeRemoveItems(toRemove) : null, isRemoveCount = !removeItems, Num = Ext.Number, range = Num.clipIndices(length, [index, isRemoveCount ? toRemove : 0], Num.Clip.COUNT), begin = range[0], end = range[1], removeCount = end - begin, newItems = me.decodeItems(arguments, 2), newCount = newItems ? newItems.length : 0, addItems, newItemsMap, removeMap, 
  insertAt = begin, indices = me.indices || (newCount || removeItems ? me.getIndices() : null), adds = null, removes = removeCount ? [begin] : null, newKeys = null, source = me.getSource(), chunk, chunkItems, chunks, i, item, itemIndex, k, key, keys, n, duplicates, sorters;
  if (source && !source.updating) {
    if (isRemoveCount) {
      removeItems = [];
      for (i = 0; i < removeCount; ++i) {
        removeItems.push(items[begin + i]);
      }
    }
    if (begin < length) {
      i = source.indexOf(items[begin]);
    } else {
      i = source.length;
    }
    me.requestedIndex = index;
    source.splice(i, removeItems, newItems);
    delete me.requestedIndex;
    return me;
  }
  if (newCount) {
    addItems = newItems;
    newKeys = [];
    newItemsMap = {};
    if (autoSort) {
      sorters = me.getSorters();
      if (newCount > 1) {
        if (!addItems.$cloned) {
          newItems = addItems = addItems.slice(0);
        }
        me.sortData(addItems);
      }
    }
    for (i = 0; i < newCount; ++i) {
      key = me.getKey(item = newItems[i]);
      if ((k = newItemsMap[key]) !== undefined) {
        (duplicates || (duplicates = {}))[k] = 1;
      } else {
        itemIndex = indices[key];
        if (itemIndex < begin || end <= itemIndex) {
          (removes || (removes = [])).push(itemIndex);
        }
      }
      newItemsMap[key] = i;
      newKeys.push(key);
    }
    if (duplicates) {
      keys = newKeys;
      addItems = [];
      newKeys = [];
      addItems.$cloned = true;
      for (i = 0; i < newCount; ++i) {
        if (!duplicates[i]) {
          item = newItems[i];
          addItems.push(item);
          newKeys.push(keys[i]);
        }
      }
      newCount = addItems.length;
    }
    adds = {items:addItems, keys:newKeys};
  }
  for (i = removeItems ? removeItems.length : 0; i-- > 0;) {
    key = me.getKey(removeItems[i]);
    if ((itemIndex = indices[key]) !== undefined) {
      (removes || (removes = [])).push(itemIndex);
    }
  }
  if (!adds && !removes) {
    return me;
  }
  me.beginUpdate();
  if (removes) {
    chunk = null;
    chunks = [];
    removeMap = {};
    if (removes.length > 1) {
      removes.sort(Ext.Array.numericSortFn);
    }
    for (i = 0, n = removes.length; i < n; ++i) {
      key = me.getKey(item = items[itemIndex = removes[i]]);
      if (!(key in map)) {
        continue;
      }
      delete map[key];
      if (!chunk || itemIndex > chunk.at + chunkItems.length) {
        chunks.push(chunk = {at:itemIndex, items:chunkItems = [], keys:keys = [], map:removeMap, next:chunk, replacement:adds});
        if (adds) {
          adds.replaced = chunk;
        }
      }
      chunkItems.push(removeMap[key] = item);
      keys.push(key);
      if (itemIndex < insertAt) {
        --insertAt;
      }
      if (removeCount > 1 && itemIndex === begin) {
        --removeCount;
        removes[i--] = ++begin;
      }
    }
    if (adds) {
      adds.at = insertAt;
    }
    for (k = chunks.length; k-- > 0;) {
      chunk = chunks[k];
      i = chunk.at;
      n = chunk.items.length;
      if (i + n < length) {
        me.indices = indices = null;
      }
      me.length = length -= n;
      items.splice(i, n);
      if (indices) {
        keys = chunk.keys;
        for (i = 0; i < n; ++i) {
          delete indices[keys[i]];
        }
      }
      ++me.generation;
      me.notify('remove', [chunk]);
    }
  }
  if (adds) {
    if (autoSort && newCount > 1 && length) {
      me.spliceMerge(addItems, newKeys);
    } else {
      if (autoSort) {
        if (newCount > 1) {
          insertAt = 0;
          me.indices = indices = null;
        } else {
          insertAt = sorters.findInsertionIndex(adds.items[0], items, me.getSortFn(), index);
        }
      }
      if (insertAt === length) {
        end = insertAt;
        for (i = addItems.length - 1; i >= 0; --i) {
          items[end + i] = addItems[i];
        }
        indices = me.indices;
        if (indices) {
          for (i = 0; i < newCount; ++i) {
            indices[newKeys[i]] = insertAt + i;
          }
        }
      } else {
        me.indices = null;
        Ext.Array.insert(items, insertAt, addItems);
      }
      for (i = 0; i < newCount; ++i) {
        map[newKeys[i]] = addItems[i];
      }
      me.length += newCount;
      adds.at = insertAt;
      adds.atItem = insertAt === 0 ? null : items[insertAt - 1];
      ++me.generation;
      me.notify('add', [adds]);
    }
  }
  me.endUpdate();
  return me;
}, update:function(fn, scope) {
  var me = this;
  me.beginUpdate();
  try {
    return fn.call(scope || me, me);
  } catch (e$55) {
    Ext.log.error(this.$className + ': Unhandled Exception: ', e$55.description || e$55.message);
    throw e$55;
  } finally {
    me.endUpdate();
  }
}, updateKey:function(item, oldKey, details) {
  var me = this, map = me.map, indices = me.indices, source = me.getSource(), newKey;
  if (source && !source.updating) {
    source.updateKey(item, oldKey);
  } else {
    if ((newKey = me.getKey(item)) !== oldKey) {
      if (map[oldKey] === item && !(newKey in map)) {
        delete map[oldKey];
        me.updating++;
        me.generation++;
        map[newKey] = item;
        if (indices) {
          indices[newKey] = indices[oldKey];
          delete indices[oldKey];
        }
        me.notify('updatekey', [Ext.apply({item:item, newKey:newKey, oldKey:oldKey}, details)]);
        me.updating--;
      } else {
        if (newKey in map && map[newKey] !== item) {
          Ext.raise('Duplicate newKey "' + newKey + '" for item with oldKey "' + oldKey + '"');
        }
        if (oldKey in map && map[oldKey] !== item) {
          Ext.raise('Incorrect oldKey "' + oldKey + '" for item with newKey "' + newKey + '"');
        }
      }
    }
  }
}, findInsertIndex:function(item, defaultIndex) {
  var source = this.getSource(), sourceItems = source.items, i = source.indexOf(item) - 1, sourceItem, index;
  while (i > -1) {
    sourceItem = sourceItems[i];
    index = this.indexOf(sourceItem);
    if (index > -1) {
      return index + 1;
    }
    --i;
  }
  return defaultIndex;
}, onCollectionAdd:function(source, details) {
  var me = this, atItem = details.atItem, items = me.transformItems(details.items), requestedIndex = me.requestedIndex, filtered, index, copy, i, item, n;
  if (requestedIndex !== undefined) {
    index = requestedIndex;
  } else {
    item = atItem || source.items[1];
    index = item ? me.indexOf(item) : -1;
    if (index > -1) {
      if (atItem) {
        ++index;
      }
    } else {
      if (!me.sorted) {
        index = me.findInsertIndex(items[0], details.at ? me.length : 0);
      }
    }
  }
  if (me.getAutoFilter() && me.filtered) {
    for (i = 0, n = items.length; i < n; ++i) {
      item = items[i];
      if (me.isItemFiltered(item)) {
        if (!copy) {
          copy = items.slice(0, i);
        }
        if (!filtered) {
          filtered = [];
        }
        filtered.push(item);
      } else {
        if (copy) {
          copy.push(item);
        }
      }
    }
  }
  me.splice(index < 0 ? me.length : index, 0, copy || items);
  if (filtered) {
    me.notify('filteradd', [filtered]);
  }
}, onCollectionBeforeItemChange:function(source, details) {
  var me = this;
  me.onCollectionUpdateKey = null;
  if (!me.sourceUpdating) {
    me.notify('beforeitemchange', [details]);
  }
}, onCollectionBeginUpdate:function() {
  this.beginUpdate();
}, onCollectionEndUpdate:function() {
  this.endUpdate();
}, onCollectionItemChange:function(source, details) {
  delete this.onCollectionUpdateKey;
  this.itemChanged(details.item, details.modified, details.oldKey, details.meta);
}, onCollectionFilteredItemChange:function() {
  delete this.onCollectionUpdateKey;
}, onCollectionRefresh:function(source) {
  var me = this, map = {}, indices = {}, items = me.items, sourceItems = me.transformItems(source.items), filterFn = me.getFilterFn(), i, item, key, length, newLength;
  if (me.filtered && me.getAutoFilter()) {
    for (i = 0, newLength = 0, length = sourceItems.length; i < length; i++) {
      if (filterFn(sourceItems[i])) {
        items[newLength++] = sourceItems[i];
      }
    }
    items.length = newLength;
  } else {
    items.length = 0;
    items.push.apply(items, sourceItems);
  }
  if (me.sorted) {
    me.sortData(items);
  }
  me.length = length = items.length;
  me.map = map;
  me.indices = indices;
  for (i = 0; i < length; ++i) {
    key = me.getKey(item = items[i]);
    map[key] = item;
    indices[key] = i;
  }
  ++me.generation;
  me.notify('refresh');
}, onCollectionRemove:function(source, details) {
  this.splice(0, details.items);
}, onCollectionUpdateKey:function(source, details) {
  this.updateKey(details.item, details.oldKey, details);
}, _aggregators:{average:function(items, begin, end, property, root) {
  var n = end - begin;
  return n && this._aggregators.sum.call(this, items, begin, end, property, root) / n;
}, bounds:function(items, begin, end, property, root) {
  var value, max, min, i;
  for (i = begin; i < end; ++i) {
    value = items[i];
    value = (root ? value[root] : value)[property];
    if (!(value < max)) {
      max = value;
    }
    if (!(value > min)) {
      min = value;
    }
  }
  return [min, max];
}, count:function(items) {
  return items.length;
}, extremes:function(items, begin, end, property, root) {
  var most = null, least = null, i, item, max, min, value;
  for (i = begin; i < end; ++i) {
    item = items[i];
    value = (root ? item[root] : item)[property];
    if (!(value < max)) {
      max = value;
      most = item;
    }
    if (!(value > min)) {
      min = value;
      least = item;
    }
  }
  return [least, most];
}, max:function(items, begin, end, property, root) {
  var b = this._aggregators.bounds.call(this, items, begin, end, property, root);
  return b[1];
}, maxItem:function(items, begin, end, property, root) {
  var b = this._aggregators.extremes.call(this, items, begin, end, property, root);
  return b[1];
}, min:function(items, begin, end, property, root) {
  var b = this._aggregators.bounds.call(this, items, begin, end, property, root);
  return b[0];
}, minItem:function(items, begin, end, property, root) {
  var b = this._aggregators.extremes.call(this, items, begin, end, property, root);
  return b[0];
}, sum:function(items, begin, end, property, root) {
  var value, sum, i;
  for (sum = 0, i = begin; i < end; ++i) {
    value = items[i];
    value = (root ? value[root] : value)[property];
    sum += value;
  }
  return sum;
}}, _eventToMethodMap:{add:'onCollectionAdd', beforeitemchange:'onCollectionBeforeItemChange', beginupdate:'onCollectionBeginUpdate', endupdate:'onCollectionEndUpdate', itemchange:'onCollectionItemChange', filtereditemchange:'onCollectionFilteredItemChange', refresh:'onCollectionRefresh', remove:'onCollectionRemove', beforesort:'beforeCollectionSort', sort:'onCollectionSort', filter:'onCollectionFilter', filteradd:'onCollectionFilterAdd', updatekey:'onCollectionUpdateKey'}, addObserver:function(observer) {
  var me = this, observers = me.observers;
  if (!observers) {
    me.observers = observers = [];
  }
  if (Ext.Array.contains(observers, observer)) {
    Ext.Error.raise('Observer already added');
  }
  if (me.notifying) {
    me.observers = observers = observers.slice(0);
  }
  observers.push(observer);
  if (observers.length > 1) {
    Ext.Array.sort(observers, me.prioritySortFn);
  }
}, prioritySortFn:function(o1, o2) {
  var a = o1.observerPriority || 0, b = o2.observerPriority || 0;
  return a - b;
}, applyExtraKeys:function(extraKeys, oldExtraKeys) {
  var me = this, ret = oldExtraKeys || {}, config, name, value;
  for (name in extraKeys) {
    value = extraKeys[name];
    if (!value.isCollectionKey) {
      config = {collection:me};
      if (Ext.isString(value)) {
        config.property = value;
      } else {
        config = Ext.apply(config, value);
      }
      value = new Ext.util.CollectionKey(config);
    } else {
      value.setCollection(me);
    }
    ret[name] = me[name] = value;
    value.name = name;
  }
  return ret;
}, applyGrouper:function(grouper) {
  if (grouper) {
    grouper = this.getSorters().decodeSorter(grouper, Ext.util.Grouper);
  }
  return grouper;
}, decodeItems:function(args, index) {
  var me = this, ret = index === undefined ? args : args[index], cloned, decoder, i;
  if (!ret || !ret.$cloned) {
    cloned = args.length > index + 1 || !Ext.isIterable(ret);
    if (cloned) {
      ret = Ext.Array.slice(args, index);
      if (ret.length === 1 && ret[0] === undefined) {
        ret.length = 0;
      }
    }
    decoder = me.getDecoder();
    if (decoder) {
      if (!cloned) {
        ret = ret.slice(0);
        cloned = true;
      }
      for (i = ret.length; i-- > 0;) {
        if ((ret[i] = decoder.call(me, ret[i])) === false) {
          ret.splice(i, 1);
        }
      }
    }
    if (cloned) {
      ret.$cloned = true;
    }
  }
  return ret;
}, getIndices:function() {
  var me = this, indices = me.indices, items = me.items, n = items.length, i, key;
  if (!indices) {
    me.indices = indices = {};
    ++me.indexRebuilds;
    for (i = 0; i < n; ++i) {
      key = me.getKey(items[i]);
      indices[key] = i;
    }
  }
  return indices;
}, notify:function(eventName, args) {
  var me = this, observers = me.observers, methodName = me._eventToMethodMap[eventName], added = 0, index, length, method, observer;
  args = args || [];
  if (observers && methodName) {
    me.notifying = true;
    for (index = 0, length = observers.length; index < length; ++index) {
      method = (observer = observers[index])[methodName];
      if (method) {
        if (!added++) {
          args.unshift(me);
        }
        method.apply(observer, args);
      }
    }
    me.notifying = false;
  }
  if (!me.hasListeners) {
    return;
  }
  if (me.hasListeners[eventName]) {
    if (!added) {
      args.unshift(me);
    }
    me.fireEventArgs(eventName, args);
  }
}, getFilterFn:function() {
  return this.getFilters().getFilterFn();
}, getFilters:function(autoCreate) {
  var ret = this._filters;
  if (!ret && autoCreate !== false) {
    ret = new Ext.util.FilterCollection({id:this.getId() + '-filters' + (this.generation || '')});
    this.setFilters(ret);
  }
  return ret;
}, isItemFiltered:function(item) {
  return !this.getFilters().filterFn(item);
}, onFilterChange:function(filters) {
  var me = this, source = me.getSource(), extraKeys, newKeys, key;
  if (!source) {
    extraKeys = me.getExtraKeys();
    if (extraKeys) {
      newKeys = {};
      for (key in extraKeys) {
        newKeys[key] = extraKeys[key].clone(me);
      }
    }
    source = new Ext.util.Collection({keyFn:me.getKey, extraKeys:newKeys, rootProperty:me.getRootProperty()});
    if (me.length) {
      source.add(me.items);
    }
    me.setSource(source);
    me.autoSource = source;
  } else {
    if (source.destroyed) {
      return;
    }
    if (source.length || me.length) {
      me.onCollectionRefresh(source);
    }
  }
  me.notify('filter');
}, applyFilters:function(filters, collection) {
  if (!filters || filters.isFilterCollection) {
    return filters;
  }
  if (filters) {
    if (!collection) {
      collection = this.getFilters();
    }
    collection.splice(0, collection.length, filters);
  }
  return collection;
}, updateFilters:function(newFilters, oldFilters) {
  var me = this;
  if (oldFilters) {
    oldFilters.un('endupdate', 'onEndUpdateFilters', me);
  }
  if (newFilters) {
    newFilters.on({endupdate:'onEndUpdateFilters', scope:me, priority:me.$endUpdatePriority});
    newFilters.$filterable = me;
  }
  me.onEndUpdateFilters(newFilters);
}, onEndUpdateFilters:function(filters) {
  var me = this, was = me.filtered, is = !!filters && filters.getFilterCount() > 0;
  if (was || is) {
    me.filtered = is;
    me.onFilterChange(filters);
  }
}, getSortFn:function() {
  return this._sortFn || this.createSortFn();
}, getSorters:function(autoCreate) {
  var ret = this._sorters;
  if (!ret && autoCreate !== false) {
    ret = new Ext.util.SorterCollection({id:this.getId() + '-sorters' + (this.generation || '')});
    this.setSorters(ret);
  }
  return ret;
}, onSortChange:function() {
  if (this.sorted) {
    this.sortItems();
  }
}, sort:function(property, direction, mode) {
  var sorters = this.getSorters();
  sorters.addSort.apply(sorters, arguments);
  return this;
}, sortData:function(data) {
  Ext.Array.sort(data, this.getSortFn());
  return data;
}, sortItems:function(sortFn) {
  var me = this;
  if (me.sorted) {
    if (sortFn) {
      Ext.raise('Collections with sorters cannot resorted');
    }
    sortFn = me.getSortFn();
  }
  me.indices = null;
  me.notify('beforesort', [me.getSorters(false)]);
  if (me.length) {
    Ext.Array.sort(me.items, sortFn);
  }
  me.notify('sort');
}, sortBy:function(sortFn) {
  return this.sortItems(sortFn);
}, findInsertionIndex:function(item, items, comparatorFn, index) {
  return Ext.Array.findInsertionIndex(item, items || this.items, comparatorFn || this.getSortFn(), index);
}, applySorters:function(sorters, collection) {
  if (!sorters || sorters.isSorterCollection) {
    return sorters;
  }
  if (sorters) {
    if (!collection) {
      collection = this.getSorters();
    }
    collection.splice(0, collection.length, sorters);
  }
  return collection;
}, createSortFn:function() {
  var me = this, grouper = me.getGrouper(), sorters = me.getSorters(false), sorterFn = sorters ? sorters.getSortFn() : null;
  if (!grouper) {
    return sorterFn;
  }
  return function(lhs, rhs) {
    var ret = grouper.sort(lhs, rhs);
    if (!ret && sorterFn) {
      ret = sorterFn(lhs, rhs);
    }
    return ret;
  };
}, updateGrouper:function(grouper) {
  var me = this, groups = me.getGroups(), sorters = me.getSorters(), populate;
  me.onSorterChange();
  me.grouped = !!grouper;
  if (grouper) {
    if (me.getTrackGroups()) {
      if (!groups) {
        groups = new Ext.util.GroupCollection({id:me.getId() + '-groups' + (me.generation || ''), itemRoot:me.getRootProperty(), groupConfig:me.getGroupConfig()});
        groups.$groupable = me;
        me.setGroups(groups);
      }
      groups.setGrouper(grouper);
      populate = true;
    }
  } else {
    if (groups) {
      me.removeObserver(groups);
      groups.destroy();
    }
    me.setGroups(null);
  }
  if (!sorters.updating) {
    me.onEndUpdateSorters(sorters);
  }
  if (populate) {
    groups.onCollectionRefresh(me);
  }
}, updateSorters:function(newSorters, oldSorters) {
  var me = this;
  if (oldSorters && !oldSorters.destroyed) {
    oldSorters.un('endupdate', 'onEndUpdateSorters', me);
  }
  if (newSorters) {
    newSorters.on({endupdate:'onEndUpdateSorters', scope:me, priority:me.$endUpdatePriority});
    if (me.manageSorters) {
      newSorters.$sortable = me;
    }
  }
  me.onSorterChange();
  me.onEndUpdateSorters(newSorters);
}, onSorterChange:function() {
  this._sortFn = null;
}, onEndUpdateSorters:function(sorters) {
  var me = this, was = me.sorted, is = me.grouped && me.getAutoGroup() || sorters && sorters.length > 0;
  if (was || is) {
    me.sorted = !!is;
    me.onSortChange(sorters);
  }
}, removeObserver:function(observer) {
  var observers = this.observers;
  if (observers) {
    Ext.Array.remove(observers, observer);
  }
}, spliceMerge:function(newItems, newKeys) {
  var me = this, map = me.map, newLength = newItems.length, oldIndex = 0, oldItems = me.items, oldLength = oldItems.length, adds = [], count = 0, items = [], sortFn = me.getSortFn(), addItems, end, i, newItem, oldItem, newIndex;
  me.items = items;
  for (newIndex = 0; newIndex < newLength; newIndex = end) {
    newItem = newItems[newIndex];
    for (; oldIndex < oldLength; ++oldIndex) {
      if (sortFn(newItem, oldItem = oldItems[oldIndex]) < 0) {
        break;
      }
      items.push(oldItem);
    }
    if (oldIndex === oldLength) {
      adds[count++] = {at:items.length, itemAt:items[items.length - 1], items:addItems = []};
      if (count > 1) {
        adds[count - 2].next = adds[count - 1];
      }
      for (; newIndex < newLength; ++newIndex) {
        addItems.push(newItem = newItems[newIndex]);
        items.push(newItem);
      }
      break;
    }
    adds[count++] = {at:items.length, itemAt:items[items.length - 1], items:addItems = [newItem]};
    if (count > 1) {
      adds[count - 2].next = adds[count - 1];
    }
    items.push(newItem);
    for (end = newIndex + 1; end < newLength; ++end) {
      if (sortFn(newItem = newItems[end], oldItem) >= 0) {
        break;
      }
      items.push(newItem);
      addItems.push(newItem);
    }
  }
  for (; oldIndex < oldLength; ++oldIndex) {
    items.push(oldItems[oldIndex]);
  }
  for (i = 0; i < newLength; ++i) {
    map[newKeys[i]] = newItems[i];
  }
  me.length = items.length;
  ++me.generation;
  me.indices = null;
  for (i = 0; i < count; ++i) {
    me.notify('add', [adds[i]]);
  }
}, transformItems:Ext.identityFn, getGroups:function() {
  return this.callParent() || null;
}, updateAutoGroup:function(autoGroup) {
  var groups = this.getGroups();
  if (groups) {
    groups.setAutoGroup(autoGroup);
  }
  this.onEndUpdateSorters(this._sorters);
}, updateGroups:function(newGroups, oldGroups) {
  if (oldGroups) {
    this.removeObserver(oldGroups);
  }
  if (newGroups) {
    this.addObserver(newGroups);
  }
}, updateSource:function(newSource, oldSource) {
  var me = this, auto = me.autoSource;
  if (oldSource) {
    if (!oldSource.destroyed) {
      oldSource.removeObserver(me);
    }
    if (oldSource === auto) {
      auto.destroy();
      me.autoSource = null;
    }
  }
  if (newSource) {
    newSource.addObserver(me);
    if (newSource.length || me.length) {
      me.onCollectionRefresh(newSource);
    }
  }
}}, function() {
  var prototype = this.prototype;
  prototype.removeAtKey = prototype.removeByKey;
  prototype.decodeRemoveItems = prototype.decodeItems;
  Ext.Object.each(prototype._aggregators, function(name) {
    prototype[name] = function(property, begin, end) {
      return this.aggregate(property, name, begin, end);
    };
    prototype[name + 'ByGroup'] = function(property) {
      return this.aggregateByGroup(property, name);
    };
  });
});
Ext.define('Ext.data.Range', {isDataRange:true, begin:0, buffer:0, end:0, length:0, store:null, waitTimeout:10000, activeWait:null, constructor:function(config) {
  var me = this, activeRanges, store;
  Ext.apply(me, config);
  store = me.store;
  if (!(activeRanges = store.activeRanges)) {
    store.activeRanges = activeRanges = [];
  }
  activeRanges.push(me);
  me.refresh();
  if ('begin' in config) {
    me.begin = me.end = 0;
    me['goto'](config.begin, config.end)['catch'](function() {
    });
  }
}, destroy:function() {
  var me = this, store = me.store, activeRanges = store && store.activeRanges;
  Ext.destroy(me.storeListeners);
  if (activeRanges) {
    Ext.Array.remove(activeRanges, me);
  }
  me.cancelActiveWait();
  me.callParent();
}, 'goto':function(begin, end) {
  var me = this, buffer = me.buffer, task = me.task, promise;
  me.begin = begin;
  me.end = end;
  me.length = end - begin;
  me.cancelActiveWait();
  me.activeWait = me.setupWait(begin, end);
  promise = me.activeWait.promise;
  me.resolveWaitIfSatisfied();
  if (buffer > 0) {
    if (!task) {
      me.task = task = new Ext.util.DelayedTask(me.doGoto, me);
    }
    task.delay(buffer);
  } else {
    me.doGoto();
  }
  return promise;
}, privates:{lastBegin:0, lastEnd:0, cancelActiveWait:function() {
  this.resolveWait(null);
}, doGoto:Ext.privateFn, refresh:function() {
  this.records = this.store.getData().items;
}, resolveWait:function(value) {
  var wait = this.activeWait;
  if (wait) {
    wait.deferred.resolve(value);
    this.activeWait = null;
  }
  return value;
}, resolveWaitIfSatisfied:function() {
  this.resolveWait(this);
}, setupWait:function(begin, end) {
  var me = this, timeout = me.waitTimeout, deferred = new Ext.Deferred, promise = deferred.promise;
  if (timeout) {
    promise = Ext.Deferred.timeout(promise, timeout)['catch'](function() {
      return me.resolveWait(null);
    });
  }
  return {deferred:deferred, promise:promise};
}}});
Ext.define('Ext.util.ObjectTemplate', {isObjectTemplate:true, excludeProperties:{}, valueRe:/^[{][a-z.]+[}]$/i, statics:{create:function(template, options) {
  if (!Ext.isObject(template)) {
    Ext.raise('The template is not an Object');
  }
  return template.isObjectTemplate ? template : new Ext.util.ObjectTemplate(template, options);
}}, constructor:function(template, options) {
  Ext.apply(this, options);
  this.template = template;
}, apply:function(context) {
  var me = this;
  delete me.apply;
  me.apply = me.compile(me.template);
  return me.apply(context);
}, privates:{compile:function(template) {
  var me = this, exclude = me.excludeProperties, compiled, i, len, fn;
  if (Ext.isString(template)) {
    if (template.indexOf('{') < 0) {
      fn = function() {
        return template;
      };
    } else {
      if (me.valueRe.test(template)) {
        template = template.substring(1, template.length - 1).split('.');
        fn = function(context) {
          var v, i;
          for (v = context, i = 0; v && i < template.length; ++i) {
            v = v[template[i]];
          }
          return v;
        };
      } else {
        template = new Ext.XTemplate(template);
        fn = function(context) {
          return template.apply(context);
        };
      }
    }
  } else {
    if (!template || Ext.isPrimitive(template) || Ext.isFunction(template)) {
      fn = function() {
        return template;
      };
    } else {
      if (template instanceof Array) {
        compiled = [];
        for (i = 0, len = template.length; i < len; ++i) {
          compiled[i] = me.compile(template[i]);
        }
        fn = function(context) {
          var ret = [], i;
          for (i = 0; i < len; ++i) {
            ret[i] = compiled[i](context);
          }
          return ret;
        };
      } else {
        compiled = {};
        for (i in template) {
          if (!exclude[i]) {
            compiled[i] = me.compile(template[i]);
          }
        }
        fn = function(context) {
          var ret = {}, i, v;
          for (i in template) {
            v = exclude[i] ? template[i] : compiled[i](context);
            if (v !== undefined) {
              ret[i] = v;
            }
          }
          return ret;
        };
      }
    }
  }
  return fn;
}}});
Ext.define('Ext.data.schema.Role', {isRole:true, left:true, owner:false, side:'left', isMany:false, defaultReaderType:'json', _internalReadOptions:{recordsOnly:true, asRoot:true}, constructor:function(association, config) {
  var me = this, extra = config.extra;
  Ext.apply(me, config);
  if (extra) {
    extra = Ext.apply({}, extra);
    delete extra.type;
    Ext.apply(me, extra);
    delete me.extra;
  }
  me.association = association;
  if (association.owner === me.side) {
    association.owner = me;
    me.owner = true;
  }
}, processUpdate:function() {
  Ext.raise('Only the "many" for an association may be processed. "' + this.role + '" is not valid.');
}, processLoad:function(store, associatedEntity, records, session) {
  return records;
}, checkMembership:Ext.emptyFn, adoptAssociated:function(record, session) {
  var other = this.getAssociatedItem(record);
  if (other) {
    session.adopt(other);
  }
}, $roleFilterId:'$associationRoleFilter', createAssociationStore:function(session, from, records, isComplete) {
  var me = this, association = me.association, foreignKeyName = association.getFieldName(), isMany = association.isManyToMany, storeConfig = me.storeConfig, id = from.getId(), config = {asynchronousLoad:false, model:me.cls, role:me, session:session, associatedEntity:from, disableMetaChangeEvent:true, pageSize:null, remoteFilter:true, trackRemoved:!session}, store;
  if (isMany) {
    config.filters = [{id:me.$roleFilterId, property:me.inverse.field, value:id, exactMatch:true}];
  } else {
    if (foreignKeyName) {
      config.filters = [{id:me.$roleFilterId, property:foreignKeyName, value:id, exactMatch:true}];
      config.foreignKeyName = foreignKeyName;
    }
  }
  if (storeConfig) {
    Ext.apply(config, storeConfig);
  }
  store = Ext.Factory.store(config);
  me.onStoreCreate(store, session, id);
  if (!isMany || session) {
    store.on({scope:me, add:'onAddToMany', remove:'onRemoveFromMany', clear:'onRemoveFromMany'});
  }
  if (records) {
    store.loadData(records);
  }
  store.complete = !!isComplete;
  return store;
}, onStoreCreate:Ext.emptyFn, getAssociatedStore:function(inverseRecord, options, scope, records, allowInfer) {
  var me = this, storeName = me.getStoreName(), store = inverseRecord[storeName], hadStore = store, session = inverseRecord.session, load = options && options.reload, source = inverseRecord.$source, isComplete = false, phantom = false, hadSourceStore, args, i, len, raw, rec, sourceStore, hadRecords, isLoading;
  if (!store) {
    if (session) {
      if (source) {
        phantom = source.phantom;
      }
      if (!records && source) {
        sourceStore = source[storeName];
        if (sourceStore && !sourceStore.isLoading()) {
          records = [];
          raw = sourceStore.getData().items;
          for (i = 0, len = raw.length; i < len; ++i) {
            rec = raw[i];
            records.push(session.getRecord(rec.self, rec.id));
          }
          isComplete = !!sourceStore.complete;
          hadSourceStore = true;
        }
      }
      if (!hadSourceStore) {
        hadRecords = !!records;
        records = me.findRecords(session, inverseRecord, records, allowInfer);
        if (!hadRecords && (!records || !records.length)) {
          records = null;
        }
        isComplete = phantom || hadRecords;
      }
    } else {
      isComplete = !!records;
    }
    store = me.createAssociationStore(session, inverseRecord, records, isComplete || inverseRecord.phantom);
    store.$source = sourceStore;
    if (!records && (me.autoLoad || options)) {
      load = true;
    }
    inverseRecord[storeName] = store;
  }
  if (options) {
    if (load || store.isLoading()) {
      store.on('load', function(store, records, success, operation) {
        args = [store, operation];
        scope = scope || options.scope || inverseRecord;
        if (success) {
          Ext.callback(options.success, scope, args);
        } else {
          Ext.callback(options.failure, scope, args);
        }
        args.push(success);
        Ext.callback(options, scope, args);
        Ext.callback(options.callback, scope, args);
      }, null, {single:true});
    } else {
      args = [store, null];
      scope = scope || options.scope || inverseRecord;
      Ext.callback(options.success, scope, args);
      args.push(true);
      Ext.callback(options, scope, args);
      Ext.callback(options.callback, scope, args);
    }
  }
  isLoading = store.isLoading();
  if (load) {
    if (!isLoading) {
      store.load();
    }
  } else {
    if (hadStore && records && !isLoading) {
      store.loadData(records);
    }
  }
  return store;
}, getAssociatedItem:function(rec) {
  var key = this.isMany ? this.getStoreName() : this.getInstanceName();
  return rec[key] || null;
}, onDrop:Ext.emptyFn, onIdChanged:Ext.emptyFn, getReaderRoot:function() {
  var me = this;
  return me.associationKey || (me.associationKey = me.association.schema.getNamer().readerRoot(me.role));
}, getReader:function() {
  var me = this, reader = me.reader, Model = me.cls, useSimpleAccessors = !me.associationKey, root = this.getReaderRoot();
  if (reader && !reader.isReader) {
    if (Ext.isString(reader)) {
      reader = {type:reader};
    }
    Ext.applyIf(reader, {model:Model, rootProperty:root, useSimpleAccessors:useSimpleAccessors, type:me.defaultReaderType});
    reader = me.reader = Ext.createByAlias('reader.' + reader.type, reader);
  }
  return reader;
}, getInstanceName:function() {
  var me = this;
  return me.instanceName || (me.instanceName = me.association.schema.getNamer().instanceName(me.role));
}, getOldInstanceName:function() {
  return this.oldInstanceName || (this.oldInstanceName = '$old' + this.getInstanceName());
}, getStoreName:function() {
  var me = this;
  return me.storeName || (me.storeName = me.association.schema.getNamer().storeName(me.role));
}, constructReader:function(fromReader) {
  var me = this, reader = me.getReader(), Model = me.cls, useSimpleAccessors = !me.associationKey, root = me.getReaderRoot(), proxyReader, proxy;
  if (!reader) {
    proxy = Model.getProxy();
    if (proxy) {
      proxyReader = proxy.getReader();
      reader = new proxyReader.self;
      reader.copyFrom(proxyReader);
      reader.setRootProperty(root);
    } else {
      reader = new fromReader.self({model:Model, useSimpleAccessors:useSimpleAccessors, rootProperty:root});
    }
    me.reader = reader;
  }
  return reader;
}, read:function(record, data, fromReader, readOptions) {
  var reader = this.constructReader(fromReader), root = reader.getRoot(data);
  if (root) {
    return reader.readRecords(root, readOptions, this._internalReadOptions);
  }
}, getCallbackOptions:function(options, scope, defaultScope) {
  if (typeof options === 'function') {
    options = {callback:options, scope:scope || defaultScope};
  } else {
    if (options) {
      options = Ext.apply({}, options);
      options.scope = scope || options.scope || defaultScope;
    }
  }
  return options;
}, doGetFK:function(leftRecord, options, scope) {
  var me = this, cls = me.cls, foreignKey = me.association.getFieldName(), instanceName = me.getInstanceName(), rightRecord = leftRecord[instanceName], reload = options && options.reload, done = rightRecord !== undefined && !reload, session = leftRecord.session, foreignKeyId, args;
  if (!done) {
    if (session) {
      foreignKeyId = leftRecord.get(foreignKey);
      if (foreignKeyId || foreignKeyId === 0) {
        done = session.peekRecord(cls, foreignKeyId, true) && !reload;
        rightRecord = session.getRecord(cls, foreignKeyId, false);
      } else {
        done = true;
        leftRecord[instanceName] = rightRecord = null;
      }
    } else {
      if (foreignKey) {
        foreignKeyId = leftRecord.get(foreignKey);
        if (!foreignKeyId && foreignKeyId !== 0) {
          done = true;
          leftRecord[instanceName] = rightRecord = null;
        } else {
          if (!rightRecord) {
            rightRecord = cls.createWithId(foreignKeyId);
          }
        }
      } else {
        done = true;
        rightRecord = null;
      }
    }
  } else {
    if (rightRecord) {
      done = !rightRecord.isLoading();
    }
  }
  if (done) {
    if (options) {
      args = [rightRecord, null];
      scope = scope || options.scope || leftRecord;
      Ext.callback(options.success, scope, args);
      args.push(true);
      Ext.callback(options, scope, args);
      Ext.callback(options.callback, scope, args);
    }
  } else {
    leftRecord[instanceName] = rightRecord;
    options = me.getCallbackOptions(options, scope, leftRecord);
    rightRecord.load(options);
  }
  return rightRecord;
}, doSetFK:function(leftRecord, rightRecord, options, scope) {
  var me = this, foreignKey = me.association.getFieldName(), instanceName = me.getInstanceName(), current = leftRecord[instanceName], inverse = me.inverse, inverseSetter = inverse.setterName, modified, oldInstanceName;
  if (rightRecord && rightRecord.isEntity) {
    if (current !== rightRecord) {
      oldInstanceName = me.getOldInstanceName();
      leftRecord[oldInstanceName] = current;
      leftRecord[instanceName] = rightRecord;
      if (current && current.isEntity) {
        current[inverse.getInstanceName()] = undefined;
      }
      if (foreignKey) {
        leftRecord.set(foreignKey, rightRecord.getId());
      }
      delete leftRecord[oldInstanceName];
      leftRecord.onAssociatedRecordSet(rightRecord, me);
      if (inverseSetter) {
        rightRecord[inverseSetter](leftRecord);
      }
    }
  } else {
    if (!foreignKey) {
      Ext.raise('No foreignKey specified for "' + me.association.left.role + '" by ' + leftRecord.$className);
    }
    modified = leftRecord.changingKey && !inverse.isMany || leftRecord.set(foreignKey, rightRecord);
    if (modified && current && current.isEntity && !current.isEqual(current.getId(), rightRecord)) {
      leftRecord[instanceName] = undefined;
      if (!inverse.isMany) {
        current[inverse.getInstanceName()] = undefined;
      }
    }
  }
  if (options) {
    if (Ext.isFunction(options)) {
      options = {callback:options, scope:scope || leftRecord};
    }
    return leftRecord.save(options);
  }
}});
Ext.define('Ext.data.schema.Association', {isOneToOne:false, isManyToOne:false, isManyToMany:false, owner:null, field:null, constructor:function(config) {
  var me = this, left, right;
  Ext.apply(me, config);
  me.left = left = new me.Left(me, me.left);
  me.right = right = new me.Right(me, me.right);
  left.inverse = right;
  right.inverse = left;
}, hasField:function() {
  return !!this.field;
}, getFieldName:function() {
  var field = this.field;
  return field ? field.name : '';
}});
Ext.define('Ext.data.schema.OneToOne', {extend:Ext.data.schema.Association, isOneToOne:true, isToOne:true, kind:'one-to-one', Left:Ext.define(null, {extend:'Ext.data.schema.Role', onDrop:function(rightRecord, session) {
  var leftRecord = this.getAssociatedItem(rightRecord);
  rightRecord[this.getInstanceName()] = null;
  if (leftRecord) {
    leftRecord[this.inverse.getInstanceName()] = null;
  }
}, onIdChanged:function(rightRecord, oldId, newId) {
  var leftRecord = this.getAssociatedItem(rightRecord), fieldName = this.association.getFieldName();
  if (!rightRecord.session && leftRecord && fieldName) {
    leftRecord.set(fieldName, newId);
  }
}, createGetter:function() {
  var me = this;
  return function() {
    return me.doGet(this);
  };
}, createSetter:function() {
  var me = this;
  return function(value) {
    return me.doSet(this, value);
  };
}, doGet:function(rightRecord) {
  var instanceName = this.getInstanceName(), ret = rightRecord[instanceName], session = rightRecord.session;
  if (!ret && session) {
  }
  return ret || null;
}, doSet:function(rightRecord, leftRecord) {
  var instanceName = this.getInstanceName(), ret = rightRecord[instanceName], inverseSetter = this.inverse.setterName;
  if (ret !== leftRecord) {
    rightRecord[instanceName] = leftRecord;
    if (inverseSetter) {
      leftRecord[inverseSetter](rightRecord);
    }
    rightRecord.onAssociatedRecordSet(leftRecord, this);
  }
  return ret;
}, read:function(rightRecord, node, fromReader, readOptions) {
  var me = this, leftRecords = me.callParent([rightRecord, node, fromReader, readOptions]), leftRecord;
  if (leftRecords) {
    leftRecord = leftRecords[0];
    if (leftRecord) {
      leftRecord[me.inverse.getInstanceName()] = rightRecord;
      rightRecord[me.getInstanceName()] = leftRecord;
      delete rightRecord.data[me.role];
    }
  }
}}), Right:Ext.define(null, {extend:'Ext.data.schema.Role', left:false, side:'right', createGetter:function() {
  var me = this;
  return function(options, scope) {
    return me.doGetFK(this, options, scope);
  };
}, createSetter:function() {
  var me = this;
  return function(value, options, scope) {
    return me.doSetFK(this, value, options, scope);
  };
}, onDrop:function(leftRecord, session) {
  var me = this, field = me.association.field, rightRecord = me.getAssociatedItem(leftRecord), id;
  if (me.inverse.owner) {
    if (session && field) {
      id = leftRecord.get(field.name);
      if (id || id === 0) {
        rightRecord = session.getEntry(me.cls, id).record;
        if (rightRecord) {
          rightRecord.drop();
        }
      }
    } else {
      if (rightRecord) {
        rightRecord.drop();
      }
    }
  }
  if (field) {
    leftRecord.set(field.name, null);
  }
  leftRecord[me.getInstanceName()] = null;
  if (rightRecord) {
    rightRecord[me.inverse.getInstanceName()] = null;
  }
}, onValueChange:function(leftRecord, session, newValue) {
  var me = this, rightRecord = leftRecord[me.getOldInstanceName()] || me.getAssociatedItem(leftRecord), hasNewValue = newValue || newValue === 0, instanceName = me.getInstanceName(), cls = me.cls;
  leftRecord.changingKey = true;
  me.doSetFK(leftRecord, newValue);
  if (!hasNewValue) {
    leftRecord[instanceName] = null;
  } else {
    if (session && cls) {
      leftRecord[instanceName] = session.peekRecord(cls, newValue) || undefined;
    }
  }
  if (me.inverse.owner && rightRecord) {
    me.association.schema.queueKeyCheck(rightRecord, me);
  }
  leftRecord.changingKey = false;
}, checkKeyForDrop:function(rightRecord) {
  var leftRecord = this.inverse.getAssociatedItem(rightRecord);
  if (!leftRecord) {
    rightRecord.drop();
  }
}, read:function(leftRecord, node, fromReader, readOptions) {
  var me = this, rightRecords = me.callParent([leftRecord, node, fromReader, readOptions]), rightRecord, field, fieldName, session, refs, id, oldId, setKey, data;
  if (rightRecords) {
    rightRecord = rightRecords[0];
    field = me.association.field;
    if (field) {
      fieldName = field.name;
    }
    session = leftRecord.session;
    data = leftRecord.data;
    if (rightRecord) {
      if (session) {
        refs = session.getRefs(rightRecord, this.inverse, true);
        setKey = refs && refs[leftRecord.id] || data[fieldName] === undefined;
      } else {
        setKey = true;
      }
      if (setKey) {
        if (field) {
          oldId = data[fieldName];
          id = rightRecord.id;
          if (oldId !== id) {
            data[fieldName] = id;
            if (session) {
              session.updateReference(leftRecord, field, id, oldId);
            }
          }
        }
        rightRecord[me.inverse.getInstanceName()] = leftRecord;
        leftRecord[me.getInstanceName()] = rightRecord;
      }
      delete data[me.role];
    }
  }
}})});
Ext.define('Ext.data.schema.ManyToOne', {extend:Ext.data.schema.Association, isManyToOne:true, isToOne:true, kind:'many-to-one', Left:Ext.define(null, {extend:'Ext.data.schema.Role', isMany:true, onDrop:function(rightRecord, session) {
  var me = this, store = me.getAssociatedItem(rightRecord), leftRecords, len, i, id;
  if (store) {
    leftRecords = store.removeAll();
    if (leftRecords && me.inverse.owner) {
      for (i = 0, len = leftRecords.length; i < len; ++i) {
        leftRecords[i].drop();
      }
    }
    store.destroy();
    rightRecord[me.getStoreName()] = null;
  } else {
    if (session) {
      leftRecords = session.getRefs(rightRecord, me);
      if (leftRecords) {
        for (id in leftRecords) {
          leftRecords[id].drop();
        }
      }
    }
  }
}, onIdChanged:function(rightRecord, oldId, newId) {
  var fieldName = this.association.getFieldName(), store = this.getAssociatedItem(rightRecord), leftRecords, i, len, filter;
  if (store) {
    filter = store.getFilters().get(this.$roleFilterId);
    if (filter) {
      filter.setValue(newId);
    }
    if (!rightRecord.session && fieldName) {
      leftRecords = store.getDataSource().items;
      for (i = 0, len = leftRecords.length; i < len; ++i) {
        leftRecords[i].set(fieldName, newId);
      }
    }
  }
}, processUpdate:function(session, associationData) {
  var me = this, entityType = me.inverse.cls, items = associationData.R, id, rightRecord, store, leftRecords;
  if (items) {
    for (id in items) {
      rightRecord = session.peekRecord(entityType, id);
      if (rightRecord) {
        leftRecords = session.getEntityList(me.cls, items[id]);
        store = me.getAssociatedItem(rightRecord);
        if (store) {
          store.loadData(leftRecords);
          store.complete = true;
        } else {
          rightRecord[me.getterName](null, null, leftRecords);
        }
      } else {
        session.onInvalidAssociationEntity(entityType, id);
      }
    }
  }
}, findRecords:function(session, rightRecord, leftRecords, allowInfer) {
  var ret = leftRecords, refs = session.getRefs(rightRecord, this, true), field = this.association.field, fieldName, leftRecord, id, i, len, seen;
  if (field && (refs || allowInfer)) {
    fieldName = field.name;
    ret = [];
    if (leftRecords) {
      seen = {};
      for (i = 0, len = leftRecords.length; i < len; ++i) {
        leftRecord = leftRecords[i];
        id = leftRecord.id;
        if (refs && refs[id]) {
          ret.push(leftRecord);
        } else {
          if (allowInfer && leftRecord.data[fieldName] === undefined) {
            ret.push(leftRecord);
            leftRecord.data[fieldName] = rightRecord.id;
            session.updateReference(leftRecord, field, rightRecord.id, undefined);
          }
        }
        seen[id] = true;
      }
    }
    if (refs) {
      for (id in refs) {
        if (!seen || !seen[id]) {
          ret.push(refs[id]);
        }
      }
    }
  }
  return ret;
}, processLoad:function(store, rightRecord, leftRecords, session) {
  var ret = leftRecords;
  if (session) {
    ret = this.findRecords(session, rightRecord, leftRecords, true);
  }
  this.onLoadMany(rightRecord, ret, session);
  return ret;
}, adoptAssociated:function(rightRecord, session) {
  var store = this.getAssociatedItem(rightRecord), leftRecords, i, len;
  if (store) {
    store.setSession(session);
    leftRecords = store.getData().items;
    for (i = 0, len = leftRecords.length; i < len; ++i) {
      session.adopt(leftRecords[i]);
    }
  }
}, createGetter:function() {
  var me = this;
  return function(options, scope, leftRecords) {
    return me.getAssociatedStore(this, options, scope, leftRecords, true);
  };
}, createSetter:null, onAddToMany:function(store, leftRecords) {
  var rightRecord = store.getAssociatedEntity();
  if (this.association.field) {
    this.syncFK(leftRecords, rightRecord, false);
  } else {
    this.setInstances(rightRecord, leftRecords);
  }
}, onLoadMany:function(rightRecord, leftRecords, session) {
  this.setInstances(rightRecord, leftRecords, session);
}, onRemoveFromMany:function(store, leftRecords) {
  if (this.association.field) {
    this.syncFK(leftRecords, store.getAssociatedEntity(), true);
  } else {
    this.setInstances(null, leftRecords);
  }
}, read:function(rightRecord, node, fromReader, readOptions) {
  var me = this, instanceName = me.inverse.getInstanceName(), leftRecords = me.callParent([rightRecord, node, fromReader, readOptions]), store, len, i;
  if (leftRecords) {
    store = rightRecord[me.getterName](null, null, leftRecords);
    delete rightRecord.data[me.role];
    leftRecords = store.getData().items;
    for (i = 0, len = leftRecords.length; i < len; ++i) {
      leftRecords[i][instanceName] = rightRecord;
    }
  }
}, setInstances:function(rightRecord, leftRecords, session) {
  var instanceName = this.inverse.getInstanceName(), id = rightRecord ? rightRecord.getId() : null, field = this.association.field, len = leftRecords.length, i, leftRecord, oldId, data, name;
  for (i = 0; i < len; ++i) {
    leftRecord = leftRecords[i];
    leftRecord[instanceName] = rightRecord;
    if (field) {
      name = field.name;
      data = leftRecord.data;
      oldId = data[name];
      if (oldId !== id) {
        data[name] = id;
        if (session) {
          session.updateReference(leftRecord, field, id, oldId);
        }
      }
    }
  }
}, syncFK:function(leftRecords, rightRecord, clearing) {
  var foreignKeyName = this.association.getFieldName(), inverse = this.inverse, setter = inverse.setterName, instanceName = inverse.getInstanceName(), i = leftRecords.length, id = rightRecord.getId(), different, leftRecord, val;
  while (i-- > 0) {
    leftRecord = leftRecords[i];
    different = !leftRecord.isEqual(id, leftRecord.get(foreignKeyName));
    val = clearing ? null : rightRecord;
    if (different !== clearing) {
      leftRecord.changingKey = true;
      leftRecord[setter](val);
      leftRecord.changingKey = false;
    } else {
      leftRecord[instanceName] = val;
    }
  }
}}), Right:Ext.define(null, {extend:'Ext.data.schema.Role', left:false, side:'right', onDrop:function(leftRecord, session) {
  var field = this.association.field;
  if (field) {
    leftRecord.set(field.name, null);
  }
  leftRecord[this.getInstanceName()] = null;
}, createGetter:function() {
  var me = this;
  return function(options, scope) {
    return me.doGetFK(this, options, scope);
  };
}, createSetter:function() {
  var me = this;
  return function(rightRecord, options, scope) {
    return me.doSetFK(this, rightRecord, options, scope);
  };
}, checkMembership:function(session, leftRecord) {
  var field = this.association.field, store;
  if (field) {
    store = this.getSessionStore(session, leftRecord.get(field.name));
    if (store && !store.contains(leftRecord)) {
      store.add(leftRecord);
    }
  }
}, onValueChange:function(leftRecord, session, newValue, oldValue) {
  var me = this, instanceName = me.getInstanceName(), cls = me.cls, hasNewValue, joined, store, i, associated, rightRecord;
  if (!leftRecord.changingKey) {
    hasNewValue = newValue || newValue === 0;
    if (!hasNewValue) {
      leftRecord[instanceName] = null;
    }
    if (session) {
      store = me.getSessionStore(session, oldValue);
      if (store) {
        store.remove(leftRecord);
      }
      if (hasNewValue) {
        store = me.getSessionStore(session, newValue);
        if (store && !store.isLoading()) {
          store.add(leftRecord);
        }
        if (cls) {
          rightRecord = session.peekRecord(cls, newValue);
        }
        leftRecord[instanceName] = rightRecord || undefined;
      }
    } else {
      joined = leftRecord.joined;
      if (joined) {
        for (i = joined.length - 1; i >= 0; i--) {
          store = joined[i];
          if (store.isStore) {
            associated = store.getAssociatedEntity();
            if (associated && associated.self === me.cls && associated.getId() === oldValue) {
              store.remove(leftRecord);
            }
          }
        }
      }
    }
  }
  if (me.owner && newValue === null) {
    me.association.schema.queueKeyCheck(leftRecord, me);
  }
}, checkKeyForDrop:function(leftRecord) {
  var field = this.association.field;
  if (leftRecord.get(field.name) === null) {
    leftRecord.drop();
  }
}, getSessionStore:function(session, value) {
  var cls = this.cls, rec;
  if (cls) {
    rec = session.peekRecord(cls, value);
    if (rec) {
      return this.inverse.getAssociatedItem(rec);
    }
  }
}, read:function(leftRecord, node, fromReader, readOptions) {
  var rightRecords = this.callParent([leftRecord, node, fromReader, readOptions]), rightRecord;
  if (rightRecords) {
    rightRecord = rightRecords[0];
    if (rightRecord) {
      leftRecord[this.getInstanceName()] = rightRecord;
      delete leftRecord.data[this.role];
    }
  }
}})});
Ext.define('Ext.data.schema.ManyToMany', {extend:Ext.data.schema.Association, isManyToMany:true, isToMany:true, kind:'many-to-many', Left:Ext.define(null, {extend:'Ext.data.schema.Role', isMany:true, digitRe:/^\d+$/, findRecords:function(session, rightRecord, leftRecords) {
  var slice = session.getMatrixSlice(this.inverse, rightRecord.id), members = slice.members, ret = [], cls = this.cls, seen, i, len, id, member, leftRecord;
  if (leftRecords) {
    seen = {};
    for (i = 0, len = leftRecords.length; i < len; ++i) {
      leftRecord = leftRecords[i];
      id = leftRecord.id;
      member = members[id];
      if (!(member && member[2] === -1)) {
        ret.push(leftRecord);
      }
      seen[id] = true;
    }
  }
  for (id in members) {
    member = members[id];
    if (!seen || !seen[id] && (member && member[2] !== -1)) {
      leftRecord = session.peekRecord(cls, id);
      if (leftRecord) {
        ret.push(leftRecord);
      }
    }
  }
  return ret;
}, onIdChanged:function(rightRecord, oldId, newId) {
  var store = this.getAssociatedItem(rightRecord);
  if (store) {
    store.getFilters().get(this.$roleFilterId).setValue(newId);
  }
}, processLoad:function(store, rightRecord, leftRecords, session) {
  var ret = leftRecords;
  if (session) {
    ret = this.findRecords(session, rightRecord, leftRecords);
    this.onAddToMany(store, ret, true);
  }
  return ret;
}, processUpdate:function(session, associationData) {
  var me = this, entityType = me.inverse.cls, items = associationData.R, id, rightRecord, store, leftRecords;
  if (items) {
    for (id in items) {
      rightRecord = session.peekRecord(entityType, id);
      if (rightRecord) {
        leftRecords = session.getEntityList(me.cls, items[id]);
        store = me.getAssociatedItem(rightRecord);
        if (store) {
          store.loadData(leftRecords);
          store.complete = true;
        } else {
          rightRecord[me.getterName](null, null, leftRecords);
        }
      } else {
        session.onInvalidAssociationEntity(entityType, id);
      }
    }
  }
  me.processMatrixBlock(session, associationData.C, 1);
  me.processMatrixBlock(session, associationData.D, -1);
}, checkMembership:function(session, rightRecord) {
  var matrix = session.getMatrix(this.association, true), side, entityType, inverse, slice, slices, id, members, member, leftRecord, store;
  if (!matrix) {
    return;
  }
  side = this.left ? matrix.right : matrix.left;
  entityType = side.inverse.role.cls;
  inverse = this.inverse;
  slices = side.slices;
  if (slices) {
    slice = slices[rightRecord.id];
    if (slice) {
      members = slice.members;
      for (id in members) {
        member = members[id];
        if (member[2] !== -1) {
          leftRecord = session.peekRecord(entityType, id);
          if (leftRecord) {
            store = inverse.getAssociatedItem(leftRecord);
            if (store) {
              store.matrixUpdate = 1;
              store.add(rightRecord);
              store.matrixUpdate = 0;
            }
          }
        }
      }
    }
  }
}, onStoreCreate:function(store, session, id) {
  var me = this, matrix;
  if (session) {
    matrix = session.getMatrixSlice(me.inverse, id);
    matrix.attach(store);
    matrix.notify = me.onMatrixUpdate;
    matrix.scope = me;
  }
}, processMatrixBlock:function(session, leftKeys, state) {
  var inverse = this.inverse, digitRe = this.digitRe, slice, id;
  if (leftKeys) {
    for (id in leftKeys) {
      if (digitRe.test(id)) {
        id = parseInt(id, 10);
      }
      slice = session.getMatrixSlice(inverse, id);
      slice.update(leftKeys[id], state);
    }
  }
}, createGetter:function() {
  var me = this;
  return function(options, scope, leftRecords) {
    return me.getAssociatedStore(this, options, scope, leftRecords, false);
  };
}, onAddToMany:function(store, leftRecords, load) {
  if (!store.matrixUpdate) {
    store.matrixUpdate = 1;
    store.matrix.update(leftRecords, load === true ? 0 : 1);
    store.matrixUpdate = 0;
  }
}, onRemoveFromMany:function(store, records) {
  if (!store.matrixUpdate) {
    store.matrixUpdate = 1;
    store.matrix.update(records, -1);
    store.matrixUpdate = 0;
  }
}, read:function(rightRecord, node, fromReader, readOptions) {
  var me = this, leftRecords = me.callParent([rightRecord, node, fromReader, readOptions]);
  if (leftRecords) {
    rightRecord[me.getterName](null, null, leftRecords);
    delete rightRecord.data[me.role];
  }
}, onMatrixUpdate:function(matrixSlice, id, state) {
  var store = matrixSlice.store, index, leftRecord, entry;
  if (store && !store.loading && !store.matrixUpdate) {
    store.matrixUpdate = 1;
    index = store.indexOfId(id);
    if (state < 0) {
      if (index >= 0) {
        store.remove([index]);
      }
    } else {
      if (index < 0) {
        entry = store.getSession().getEntry(this.type, id);
        leftRecord = entry && entry.record;
        if (leftRecord) {
          store.add(leftRecord);
        }
      }
    }
    store.matrixUpdate = 0;
  }
}, adoptAssociated:function(record, session) {
  var store = this.getAssociatedItem(record), records, i, len;
  if (store) {
    store.setSession(session);
    this.onStoreCreate(store, session, record.getId());
    records = store.getData().items;
    for (i = 0, len = records.length; i < len; ++i) {
      session.adopt(records[i]);
    }
  }
}}, function() {
  var Left = this;
  Ext.ClassManager.onCreated(function() {
    Ext.data.schema.ManyToMany.prototype.Right = Ext.define(null, {extend:Left, left:false, side:'right'});
  }, null, 'Ext.data.schema.ManyToMany');
})});
Ext.define('Ext.util.Inflector', {singleton:true, plurals:[[/(quiz)$/i, '$1zes'], [/^(ox)$/i, '$1en'], [/([m|l])ouse$/i, '$1ice'], [/(matr|vert|ind)ix|ex$/i, '$1ices'], [/(x|ch|ss|sh)$/i, '$1es'], [/([^aeiouy]|qu)y$/i, '$1ies'], [/(hive)$/i, '$1s'], [/(?:([^f])fe|([lr])f)$/i, '$1$2ves'], [/sis$/i, 'ses'], [/([ti])um$/i, '$1a'], [/(buffal|tomat|potat)o$/i, '$1oes'], [/(bu)s$/i, '$1ses'], [/(alias|status|sex)$/i, '$1es'], [/(octop|vir)us$/i, '$1i'], [/(ax|test)is$/i, '$1es'], [/^(p)erson$/i, '$1eople'], 
[/^(m)an$/i, '$1en'], [/(.*)(child)(ren)?$/i, '$1$2ren'], [/s$/i, 's'], [/$/, 's']], singulars:[[/(address)$/i, '$1'], [/(quiz)zes$/i, '$1'], [/(matr)ices$/i, '$1ix'], [/(vert|ind)ices$/i, '$1ex'], [/^(ox)en/i, '$1'], [/(alias|status)es$/i, '$1'], [/(octop|vir)i$/i, '$1us'], [/(cris|ax|test)es$/i, '$1is'], [/(shoe)s$/i, '$1'], [/(o)es$/i, '$1'], [/(bus)es$/i, '$1'], [/([m|l])ice$/i, '$1ouse'], [/(x|ch|ss|sh)es$/i, '$1'], [/(m)ovies$/i, '$1ovie'], [/(s)eries$/i, '$1eries'], [/([^aeiouy]|qu)ies$/i, 
'$1y'], [/([lr])ves$/i, '$1f'], [/(tive)s$/i, '$1'], [/(hive)s$/i, '$1'], [/([^f])ves$/i, '$1fe'], [/(^analy)ses$/i, '$1sis'], [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '$1$2sis'], [/([ti])a$/i, '$1um'], [/(n)ews$/i, '$1ews'], [/(p)eople$/i, '$1erson'], [/s$/i, '']], uncountable:['sheep', 'fish', 'series', 'species', 'money', 'rice', 'information', 'equipment', 'grass', 'mud', 'offspring', 'deer', 'means'], singular:function(matcher, replacer) {
  this.singulars.unshift([matcher, replacer]);
}, plural:function(matcher, replacer) {
  this.plurals.unshift([matcher, replacer]);
}, clearSingulars:function() {
  this.singulars = [];
}, clearPlurals:function() {
  this.plurals = [];
}, isTransnumeral:function(word) {
  return Ext.Array.indexOf(this.uncountable, word) !== -1;
}, pluralize:function(word) {
  if (this.isTransnumeral(word)) {
    return word;
  }
  var plurals = this.plurals, length = plurals.length, tuple, regex, i;
  for (i = 0; i < length; i++) {
    tuple = plurals[i];
    regex = tuple[0];
    if (regex == word || regex.test && regex.test(word)) {
      return word.replace(regex, tuple[1]);
    }
  }
  return word;
}, singularize:function(word) {
  if (this.isTransnumeral(word)) {
    return word;
  }
  var singulars = this.singulars, length = singulars.length, tuple, regex, i;
  for (i = 0; i < length; i++) {
    tuple = singulars[i];
    regex = tuple[0];
    if (regex == word || regex.test && regex.test(word)) {
      return word.replace(regex, tuple[1]);
    }
  }
  return word;
}, classify:function(word) {
  return Ext.String.capitalize(this.singularize(word));
}, ordinalize:function(number) {
  var parsed = parseInt(number, 10), mod10 = parsed % 10, mod100 = parsed % 100;
  if (11 <= mod100 && mod100 <= 13) {
    return number + 'th';
  } else {
    switch(mod10) {
      case 1:
        return number + 'st';
      case 2:
        return number + 'nd';
      case 3:
        return number + 'rd';
      default:
        return number + 'th';
    }
  }
}}, function() {
  var singular, irregulars = {alumnus:'alumni', cactus:'cacti', focus:'foci', nucleus:'nuclei', radius:'radii', stimulus:'stimuli', ellipsis:'ellipses', paralysis:'paralyses', oasis:'oases', appendix:'appendices', index:'indexes', beau:'beaux', bureau:'bureaux', tableau:'tableaux', woman:'women', child:'children', man:'men', corpus:'corpora', criterion:'criteria', curriculum:'curricula', genus:'genera', memorandum:'memoranda', phenomenon:'phenomena', foot:'feet', goose:'geese', tooth:'teeth', antenna:'antennae', 
  formula:'formulae', nebula:'nebulae', vertebra:'vertebrae', vita:'vitae'};
  for (singular in irregulars) {
    if (irregulars.hasOwnProperty(singular)) {
      this.plural(singular, irregulars[singular]);
      this.singular(irregulars[singular], singular);
    }
  }
});
Ext.define('Ext.data.schema.Namer', {mixins:[Ext.mixin.Factoryable], alias:'namer.default', isNamer:true, capitalize:function(name) {
  return Ext.String.capitalize(name);
}, fieldRole:function(name) {
  var match = name.match(this.endsWithIdRe, '');
  if (match) {
    name = name.substr(0, name.length - (match[1] || match[2]).length);
  }
  return this.apply('uncapitalize', name);
}, idField:function(name) {
  return this.apply('uncapitalize,singularize', name) + 'Id';
}, instanceName:function(roleName) {
  return this.apply('underscore', roleName);
}, multiRole:function(name) {
  return this.apply('undotted,uncapitalize,pluralize', name);
}, pluralize:function(name) {
  return Ext.util.Inflector.pluralize(name);
}, readerRoot:function(roleName) {
  return this.apply('uncapitalize', roleName);
}, singularize:function(name) {
  return Ext.util.Inflector.singularize(name);
}, storeName:function(roleName) {
  return this.apply('underscore', roleName);
}, uncapitalize:function(name) {
  return Ext.String.uncapitalize(name);
}, underscore:function(name) {
  return '_' + name;
}, uniRole:function(name) {
  return this.apply('undotted,uncapitalize,singularize', name);
}, undotted:function(name) {
  var parts, index;
  if (name.indexOf('.') < 0) {
    return name;
  }
  parts = name.split('.');
  index = parts.length;
  while (index-- > 1) {
    parts[index] = this.apply('capitalize', parts[index]);
  }
  return parts.join('');
}, getterName:function(role) {
  var name = role.role;
  if (role && role.isMany) {
    return name;
  }
  return 'get' + this.apply('capitalize', name);
}, inverseFieldRole:function(leftType, unique, rightRole, rightType) {
  var me = this, leftRole = me.apply(unique ? 'uniRole' : 'multiRole', leftType), s1 = me.apply('pluralize', rightRole), s2 = me.apply('undotted,pluralize', rightType);
  if (s1.toLowerCase() !== s2.toLowerCase()) {
    leftRole = rightRole + me.apply('capitalize', leftRole);
  }
  return leftRole;
}, manyToMany:function(relation, leftType, rightType) {
  var me = this, ret = me.apply('undotted,capitalize,singularize', leftType) + me.apply('undotted,capitalize,pluralize', rightType);
  if (relation) {
    ret = me.apply('capitalize', relation + ret);
  }
  return ret;
}, manyToOne:function(leftType, leftRole, rightType, rightRole) {
  return this.apply('capitalize,singularize', rightType) + this.apply('capitalize', leftRole);
}, matrixRole:function(relation, entityType) {
  var ret = this.apply(relation ? 'multiRole,capitalize' : 'multiRole', entityType);
  return relation ? relation + ret : ret;
}, oneToOne:function(leftType, leftRole, rightType, rightRole) {
  return this.apply('undotted,capitalize,singularize', rightType) + this.apply('capitalize', leftRole);
}, setterName:function(role) {
  return 'set' + this.apply('capitalize', role.role);
}, endsWithIdRe:/(?:(_id)|[^A-Z](Id))$/, cache:{}, apply:function(operation, name) {
  var me = this, cache = me.cache, entry = cache[name] || (cache[name] = {}), ret = entry[operation], i, length, operations;
  if (!ret) {
    if (operation.indexOf(',') < 0) {
      ret = me[operation](name);
    } else {
      length = (operations = operation.split(',')).length;
      ret = name;
      for (i = 0; i < length; ++i) {
        ret = me.apply(operations[i], ret);
      }
    }
    entry[operation] = ret;
  }
  return ret;
}});
Ext.define('Ext.data.schema.Schema', {mixins:[Ext.mixin.Factoryable], alias:'schema.default', aliasPrefix:'schema.', isSchema:true, type:'default', statics:{instances:{}, clearInstance:function(id) {
  var schema = this.instances[id];
  delete this.instances[id];
  if (schema) {
    schema.clear(true);
    schema.destroy();
  }
}, get:function(config) {
  var Schema = this, cache = Schema.instances, id = 'default', isString = config && Ext.isString(config), instance, newConfig;
  if (config) {
    if (config.isSchema) {
      return config;
    }
    id = isString ? config : config.id || id;
  }
  if (!(instance = cache[id])) {
    cache[id] = instance = Schema.create(config);
    instance.id = id;
  } else {
    if (config && !isString) {
      if (id !== 'default') {
        Ext.raise('Only the default Schema instance can be reconfigured');
      }
      newConfig = Ext.merge({}, instance.config);
      Ext.merge(newConfig, config);
      instance.setConfig(newConfig);
      instance.config = newConfig;
      instance.setConfig = function() {
        Ext.raise('The schema can only be reconfigured once');
      };
    }
  }
  return instance;
}, lookupEntity:function(entity) {
  var ret = null, instances = this.instances, match, name, schema;
  if (entity) {
    if (entity.isEntity) {
      ret = entity.self;
    } else {
      if (Ext.isFunction(entity)) {
        ret = entity;
      } else {
        if (Ext.isString(entity)) {
          ret = Ext.ClassManager.get(entity);
          if (ret && (!ret.prototype || !ret.prototype.isEntity)) {
            ret = null;
          }
          if (!ret) {
            for (name in instances) {
              schema = instances[name];
              match = schema.getEntity(entity);
              if (match) {
                if (ret) {
                  Ext.raise('Ambiguous entity name "' + entity + '". Defined by schema "' + ret.schema.type + '" and "' + name + '"');
                }
                ret = match;
              }
            }
          }
          if (!ret) {
            Ext.raise('No such Entity "' + entity + '".');
          }
        }
      }
    }
  }
  return ret;
}}, assocCount:0, entityCount:0, config:{defaultIdentifier:null, keyCheckDelay:10, namer:'default', namespace:null, proxy:{type:'ajax', url:'{prefix}/{entityName}'}, urlPrefix:''}, onClassExtended:function(cls, data) {
  var alias = data.alias;
  if (alias && !data.type) {
    if (!Ext.isString(alias)) {
      alias = alias[0];
    }
    cls.prototype.type = alias.substring(this.prototype.aliasPrefix.length);
  }
}, constructor:function(config) {
  this.initConfig(config);
  this.clear();
}, applyDefaultIdentifier:function(identifier) {
  return identifier && Ext.Factory.dataIdentifier(identifier);
}, applyNamer:function(namer) {
  var ret = Ext.data.schema.Namer.create(namer);
  ret.schema = this;
  return ret;
}, applyNamespace:function(namespace) {
  var end;
  if (namespace) {
    end = namespace.length - 1;
    if (namespace.charAt(end) !== '.') {
      namespace += '.';
    }
  }
  return namespace;
}, applyProxy:function(proxy) {
  return Ext.util.ObjectTemplate.create(proxy);
}, eachAssociation:function(fn, scope) {
  var associations = this.associations, name;
  for (name in associations) {
    if (associations.hasOwnProperty(name)) {
      if (fn.call(scope, name, associations[name]) === false) {
        break;
      }
    }
  }
}, eachEntity:function(fn, scope) {
  var entities = this.entities, name;
  for (name in entities) {
    if (entities.hasOwnProperty(name)) {
      if (fn.call(scope, name, entities[name].cls) === false) {
        break;
      }
    }
  }
}, getAssociation:function(name) {
  var entry = this.associations[name];
  return entry || null;
}, getEntity:function(name) {
  var entry = this.entityClasses[name] || this.entities[name];
  return entry && entry.cls || null;
}, getEntityName:function(cls) {
  var ns = this.getNamespace(), index, name;
  if (typeof cls === 'string') {
    name = cls;
  } else {
    name = cls.$className || null;
  }
  if (name) {
    if (ns) {
      index = ns.length;
      if (name.substring(0, index) !== ns) {
        return name;
      }
    }
    if (index) {
      name = name.substring(index);
    }
  }
  return name;
}, hasAssociations:function(name) {
  name = name.entityName || name;
  return !!this.associationEntityMap[name];
}, hasEntity:function(entity) {
  var name = this.getEntityName(entity);
  return !!(this.entities[name] || this.entityClasses[name]);
}, addMatrix:function(entityType, matrixName, relation, left, right) {
  var me = this, namer = me.getNamer(), associations = me.associations, entities = me.entities, leftType = left.type, rightType = right.type, leftField = left.field || namer.apply('idField', leftType), rightField = right.field || namer.apply('idField', rightType), leftRole = left.role || namer.matrixRole(relation, leftType), rightRole = right.role || namer.matrixRole(relation, rightType), matrix, leftEntry, rightEntry;
  leftEntry = entities[leftType] || (entities[leftType] = {cls:null, name:leftType, associations:{}});
  rightEntry = entities[rightType] || (entities[rightType] = {cls:null, name:rightType, associations:{}});
  ++me.assocCount;
  associations[matrixName] = matrix = new Ext.data.schema.ManyToMany({name:matrixName, schema:me, definedBy:entityType, left:{cls:leftEntry.cls, type:leftType, role:leftRole, field:leftField, associationKey:left.associationKey}, right:{cls:rightEntry.cls, type:rightType, role:rightRole, field:rightField, associationKey:right.associationKey}});
  leftEntry.associations[matrix.right.role] = matrix.right;
  rightEntry.associations[matrix.left.role] = matrix.left;
  if (leftEntry.cls) {
    me.associationEntityMap[leftEntry.cls.entityName] = true;
  }
  if (rightEntry.cls) {
    me.associationEntityMap[rightEntry.cls.entityName] = true;
  }
  me.decorateModel(matrix);
}, addReference:function(entityType, referenceField, descr, unique, dupeCheck) {
  var me = this, namer = me.getNamer(), entities = me.entities, associations = me.associations, entityName = entityType.entityName, association = descr.association, child = descr.child, parent = descr.parent, rightRole = descr.role, rightType = descr.type || parent || child, leftVal = descr.inverse, left = Ext.isString(leftVal) ? {role:leftVal} : leftVal, leftRole = left && left.role, entry, T;
  if (!rightRole) {
    if (!referenceField || descr.legacy) {
      rightRole = namer.apply('uncapitalize', rightType);
    } else {
      rightRole = namer.apply('fieldRole', referenceField.name);
    }
  }
  if (!leftRole) {
    leftRole = namer.inverseFieldRole(entityName, unique, rightRole, rightType);
  }
  if (!association) {
    if (unique) {
      association = namer.oneToOne(entityType, leftRole, rightType, rightRole);
    } else {
      association = namer.manyToOne(entityType, leftRole, rightType, rightRole);
    }
  }
  if (dupeCheck && association in associations) {
    if (dupeCheck(associations[association], association, leftRole, rightRole) !== false) {
      return;
    }
  }
  if (association in associations) {
    Ext.raise('Duplicate association: "' + association + '" declared by ' + entityName + (referenceField ? '.' + referenceField.name : '') + ' (collides with ' + associations[association].definedBy.entityName + ')');
  }
  if (referenceField && referenceField.definedBy === entities[rightType]) {
    Ext.raise('ForeignKey reference should not be owned by the target model');
  }
  entry = entities[rightType] || (entities[rightType] = {cls:null, name:rightType, associations:{}});
  T = unique ? Ext.data.schema.OneToOne : Ext.data.schema.ManyToOne;
  association = new T({name:association, owner:child ? 'left' : parent ? 'right' : null, definedBy:entityType, schema:me, field:referenceField, nullable:referenceField ? !!referenceField.allowBlank : true, left:{cls:entityType, type:entityName, role:leftRole, extra:left}, right:{cls:entry.cls, type:rightType, role:rightRole, extra:descr}, meta:descr});
  entityType.associations[rightRole] = association.right;
  entry.associations[leftRole] = association.left;
  if (referenceField) {
    referenceField.reference = association.right;
    entityType.references.push(referenceField);
  }
  ++me.assocCount;
  me.associationEntityMap[entityName] = true;
  if (entry.cls) {
    me.associationEntityMap[entry.cls.entityName] = true;
  }
  associations[association.name] = association;
  if (association.right.cls) {
    me.decorateModel(association);
  }
}, privates:{addEntity:function(entityType) {
  var me = this, entities = me.entities, entityName = entityType.entityName, entry = entities[entityName], fields = entityType.fields, associations, field, i, length, name;
  if (!entry) {
    entities[entityName] = entry = {name:entityName, associations:{}};
  } else {
    if (entry.cls) {
      Ext.raise('Duplicate entity name "' + entityName + '": ' + entry.cls.$className + ' and ' + entityType.$className);
    } else {
      associations = entry.associations;
      for (name in associations) {
        associations[name].inverse.cls = entityType;
        me.associationEntityMap[entityName] = true;
        me.decorateModel(associations[name].association);
      }
    }
  }
  entry.cls = entityType;
  entityType.prototype.associations = entityType.associations = entry.associations;
  me.entityClasses[entityType.$className] = entry;
  ++me.entityCount;
  for (i = 0, length = fields.length; i < length; ++i) {
    field = fields[i];
    if (field.reference) {
      me.addReferenceDescr(entityType, field);
    }
  }
}, addMatrices:function(entityType, matrices) {
  var me = this, i, length, matrixName;
  if (Ext.isString(matrices)) {
    me.addMatrixDescr(entityType, null, matrices);
  } else {
    if (matrices[0]) {
      for (i = 0, length = matrices.length; i < length; ++i) {
        me.addMatrixDescr(entityType, null, matrices[i]);
      }
    } else {
      for (matrixName in matrices) {
        me.addMatrixDescr(entityType, matrixName, matrices[matrixName]);
      }
    }
  }
}, addMatrixDescr:function(entityType, matrixName, matrixDef) {
  var me = this, entityName = entityType.entityName, associations = me.associations, namer = me.getNamer(), left = matrixDef.left, right = matrixDef.right, last, relation;
  if (Ext.isString(matrixDef)) {
    if (matrixDef.charAt(0) === '#') {
      left = {type:entityName};
      right = {type:matrixDef.substring(1)};
    } else {
      if (matrixDef.charAt(last = matrixDef.length - 1) === '#') {
        left = {type:matrixDef.substring(0, last)};
        right = {type:entityName};
      } else {
        if (namer.apply('multiRole', entityName) < namer.apply('multiRole', matrixDef)) {
          left = {type:entityName};
          right = {type:matrixDef};
        } else {
          left = {type:matrixDef};
          right = {type:entityName};
        }
      }
    }
  } else {
    Ext.Assert.isString(matrixDef.type, 'No "type" for manyToMany in ' + entityName);
    relation = matrixDef.relation;
    if (left || !right && namer.apply('multiRole', entityName) < namer.apply('multiRole', matrixDef.type)) {
      if (!left || left === true) {
        left = {type:entityName};
      } else {
        left = Ext.apply({type:entityName}, left);
      }
      right = matrixDef;
    } else {
      if (!right || right === true) {
        right = {type:entityName};
      } else {
        right = Ext.apply({type:entityName}, right);
      }
      left = matrixDef;
    }
  }
  if (!matrixName) {
    matrixName = namer.manyToMany(relation, left.type, right.type);
  }
  if (!(matrixName in associations)) {
    me.addMatrix(entityType, matrixName, relation, left, right);
  } else {
    var entry = associations[matrixName], before = [entry.kind, entry.left.type, entry.left.role, entry.left.field, entry.right.type, entry.right.role, entry.right.field].join('|'), after;
    delete associations[matrixName];
    me.addMatrix(entityType, matrixName, relation, left, right);
    after = associations[matrixName];
    associations[matrixName] = entry;
    entry.left.cls.associations[entry.right.role] = entry.right;
    entry.right.cls.associations[entry.left.role] = entry.left;
    --me.assocCount;
    after = [after.kind, after.left.type, after.left.role, after.left.field, after.right.type, after.right.role, after.right.field].join('|');
    if (before != after) {
      Ext.log.warn(matrixName + '(' + entry.definedBy.entityName + '): ' + before);
      Ext.log.warn(matrixName + '(' + entityName + '): ' + after);
      Ext.raise('Conflicting association: "' + matrixName + '" declared by ' + entityName + ' was previously declared by ' + entry.definedBy.entityName);
    }
  }
}, addReferenceDescr:function(entityType, referenceField) {
  var me = this, descr = referenceField.$reference;
  if (Ext.isString(descr)) {
    descr = {type:descr};
  } else {
    descr = Ext.apply({}, descr);
  }
  me.addReference(entityType, referenceField, descr, referenceField.unique);
}, addBelongsTo:function(entityType, assoc) {
  this.addKeylessSingle(entityType, assoc, false);
}, addHasOne:function(entityType, assoc) {
  this.addKeylessSingle(entityType, assoc, true);
}, addKeylessSingle:function(entityType, assoc, unique) {
  var foreignKey, referenceField;
  assoc = Ext.apply({}, this.checkLegacyAssociation(entityType, assoc));
  assoc.type = this.getEntityName(assoc.child || assoc.parent || assoc.type);
  foreignKey = assoc.foreignKey || assoc.type.toLowerCase() + '_id';
  referenceField = entityType.getField(foreignKey);
  assoc.fromSingle = true;
  if (referenceField) {
    referenceField.$reference = assoc;
    referenceField.unique = true;
    assoc.legacy = true;
    Ext.log.warn('Using foreignKey is deprecated, use a keyed association. ' + 'See Ext.data.field.Field.reference');
  }
  this.addReference(entityType, referenceField, assoc, unique);
}, addHasMany:function(entityType, assoc) {
  var me = this, entities = me.entities, pending = me.pending, cls, name, referenceField, target, foreignKey, inverseOptions, child, declaredInverse;
  assoc = Ext.apply({}, this.checkLegacyAssociation(entityType, assoc));
  assoc.type = this.getEntityName(assoc.child || assoc.parent || assoc.type);
  name = assoc.type;
  target = entities[name];
  cls = target && target.cls;
  if (cls) {
    name = entityType.entityName;
    foreignKey = assoc.foreignKey || name.toLowerCase() + '_id';
    delete assoc.foreignKey;
    declaredInverse = Ext.apply({}, assoc.inverse);
    delete assoc.inverse;
    inverseOptions = Ext.apply({}, assoc);
    delete inverseOptions.type;
    assoc = Ext.apply({type:name, inverse:inverseOptions}, declaredInverse);
    child = inverseOptions.child;
    if (child) {
      delete inverseOptions.child;
      assoc.parent = name;
    }
    referenceField = cls.getField(foreignKey);
    if (referenceField) {
      referenceField.$reference = assoc;
      assoc.legacy = true;
      Ext.log.warn('Using foreignKey is deprecated, use a keyed association. ' + 'See Ext.data.field.Field.reference');
    }
    me.addReference(cls, referenceField, assoc, false, function(association, name, leftRole, rightRole) {
      var result = !!association.meta.fromSingle && cls === association.left.cls, l, r;
      if (result) {
        l = cls.entityName;
        r = entityType.entityName;
        Ext.raise('hasMany ("' + r + '") and belongsTo ("' + l + '") should not be used in conjunction to declare ' + 'a relationship. Use only one.');
      }
      return result;
    });
  } else {
    if (!pending[name]) {
      pending[name] = [];
    }
    pending[name].push([entityType, assoc]);
  }
}, checkLegacyAssociation:function(entityType, assoc) {
  var name;
  if (Ext.isString(assoc)) {
    assoc = {type:assoc};
  } else {
    assoc = Ext.apply({}, assoc);
  }
  if (assoc.model) {
    assoc.type = assoc.model;
    delete assoc.model;
  }
  name = assoc.associatedName || assoc.name;
  if (name) {
    delete assoc.associatedName;
    delete assoc.name;
    assoc.role = name;
  }
  return assoc;
}, afterKeylessAssociations:function(cls) {
  var pending = this.pending, name = cls.entityName, mine = pending[name], i, len;
  if (mine) {
    for (i = 0, len = mine.length; i < len; ++i) {
      this.addHasMany.apply(this, mine[i]);
    }
    delete pending[name];
  }
}, clear:function(clearNamespace) {
  var me = this, timer = me.timer;
  delete me.setConfig;
  if (timer) {
    window.clearTimeout(timer);
    me.timer = null;
  }
  me.associations = {};
  me.associationEntityMap = {};
  me.entities = {};
  me.entityClasses = {};
  me.pending = {};
  me.assocCount = me.entityCount = 0;
  if (clearNamespace) {
    me.setNamespace(null);
  }
}, constructProxy:function(Model) {
  var me = this, data = Ext.Object.chain(Model), proxy = me.getProxy();
  data.schema = me;
  data.prefix = me.getUrlPrefix();
  return proxy.apply(data);
}, applyDecoration:function(role) {
  var me = this, cls = role.inverse.cls, namer = me.getNamer(), getterName, setterName, proto;
  if (cls && !role.decorated) {
    role.decorated = true;
    proto = cls.prototype;
    if (!(getterName = role.getterName)) {
      role.getterName = getterName = namer.getterName(role);
    }
    proto[getterName] = role.createGetter();
    if (role.createSetter) {
      if (!(setterName = role.setterName)) {
        role.setterName = setterName = namer.setterName(role);
      }
      proto[setterName] = role.createSetter();
    }
  }
}, decorateModel:function(association) {
  this.applyDecoration(association.left);
  this.applyDecoration(association.right);
}, processKeyChecks:function(processAll) {
  var me = this, keyCheckQueue = me.keyCheckQueue, timer = me.timer, len, i, item;
  if (timer) {
    window.clearTimeout(timer);
    me.timer = null;
  }
  if (!keyCheckQueue) {
    return;
  }
  do {
    keyCheckQueue = me.keyCheckQueue;
    me.keyCheckQueue = [];
    for (i = 0, len = keyCheckQueue.length; i < len; ++i) {
      item = keyCheckQueue[i];
      item.role.checkKeyForDrop(item.record);
    }
  } while (processAll && me.keyCheckQueue.length);
}, queueKeyCheck:function(record, role) {
  var me = this, keyCheckQueue = me.keyCheckQueue, timer = me.timer;
  if (!keyCheckQueue) {
    me.keyCheckQueue = keyCheckQueue = [];
  }
  keyCheckQueue.push({record:record, role:role});
  if (!timer) {
    me.timer = timer = Ext.defer(me.processKeyChecks, me.getKeyCheckDelay(), me);
  }
}, rankEntities:function() {
  var me = this, entities = me.entities, entityNames = Ext.Object.getKeys(entities), length = entityNames.length, entityType, i;
  me.nextRank = 1;
  entityNames.sort();
  for (i = 0; i < length; ++i) {
    entityType = entities[entityNames[i]].cls;
    if (!entityType.rank) {
      me.rankEntity(entityType);
    }
  }
  me.topoStack = null;
}, rankEntity:function(entityType) {
  var associations = entityType.associations, associatedType, role, roleName;
  var topoStack = this.topoStack || (this.topoStack = []), entityName = entityType.entityName;
  topoStack.push(entityName);
  if (entityType.rank === 0) {
    Ext.raise(entityName + ' has circular foreign-key references: ' + topoStack.join(' --\x3e '));
  }
  entityType.rank = 0;
  for (roleName in associations) {
    role = associations[roleName];
    if (!role.left && role.association.field) {
      associatedType = role.cls;
      if (!associatedType.rank) {
        this.rankEntity(associatedType);
      }
    }
  }
  entityType.rank = this.nextRank++;
  topoStack.pop();
}}});
Ext.define('Ext.data.AbstractStore', {mixins:[Ext.mixin.Observable, Ext.mixin.Factoryable], factoryConfig:{defaultType:'store', type:'store'}, $configPrefixed:false, $configStrict:false, config:{filters:null, autoDestroy:undefined, storeId:null, statefulFilters:false, sorters:null, remoteSort:{lazy:true, $value:false}, remoteFilter:{lazy:true, $value:false}, groupField:undefined, groupDir:'ASC', grouper:null, pageSize:25, autoSort:null, reloadOnClearSorters:false}, currentPage:1, loading:false, isStore:true, 
updating:0, constructor:function(config) {
  var me = this, storeId;
  me.callParent([config]);
  me.isInitializing = true;
  me.mixins.observable.constructor.call(me, config);
  me.isInitializing = false;
  storeId = me.getStoreId();
  if (!storeId && (config && config.id)) {
    me.setStoreId(storeId = config.id);
  }
  if (storeId) {
    Ext.data.StoreManager.register(me);
  }
}, createActiveRange:function(config) {
  var range = Ext.apply({store:this}, config);
  return new Ext.data.Range(range);
}, syncActiveRanges:function() {
  var activeRanges = this.activeRanges, len = activeRanges && activeRanges.length, i;
  for (i = 0; i < len; i++) {
    activeRanges[i].refresh();
  }
}, getCount:function() {
  var data = this.getData();
  return data ? data.getCount() : 0;
}, rangeCached:function(start, end) {
  return this.getData().getCount() >= Math.max(start, end);
}, find:function(property, value, startIndex, anyMatch, caseSensitive, exactMatch) {
  var startsWith = !anyMatch, endsWith = !!(startsWith && exactMatch);
  return this.getData().findIndex(property, value, startIndex, startsWith, endsWith, !caseSensitive);
}, findRecord:function() {
  var me = this, index = me.find.apply(me, arguments);
  return index !== -1 ? me.getAt(index) : null;
}, findExact:function(fieldName, value, startIndex) {
  return this.getData().findIndexBy(function(rec) {
    return rec.isEqual(rec.get(fieldName), value);
  }, this, startIndex);
}, findBy:function(fn, scope, start) {
  return this.getData().findIndexBy(fn, scope, start);
}, getAt:function(index) {
  return this.getData().getAt(index) || null;
}, getRange:function(start, end, options) {
  var result = this.getData().getRange(start, Ext.isNumber(end) ? end + 1 : end);
  if (options && options.callback) {
    options.callback.call(options.scope || this, result, start, end, options);
  }
  return result;
}, getFilters:function(autoCreate) {
  var me = this, result = me.callParent();
  if (!result && autoCreate !== false) {
    me.setFilters([]);
    result = me.callParent();
  }
  return result;
}, applyFilters:function(filters, filtersCollection) {
  var me = this, created = !filtersCollection;
  if (created) {
    filtersCollection = me.createFiltersCollection();
  }
  if (filters !== filtersCollection) {
    if (filters && filters.isCollection) {
      filters = filters.items.slice();
    }
    filtersCollection.add(filters);
    if (created) {
      me.onRemoteFilterSet(filtersCollection, me.getRemoteFilter());
    }
  }
  return filtersCollection;
}, getSorters:function(autoCreate) {
  var me = this, result = me.callParent();
  if (!result && autoCreate !== false) {
    me.setSorters([]);
    result = me.callParent();
  }
  return result;
}, applySorters:function(sorters, sortersCollection) {
  var me = this, created;
  if (!sortersCollection) {
    sortersCollection = me.createSortersCollection();
    created = true;
  }
  sortersCollection.add(sorters);
  if (created) {
    me.onRemoteSortSet(sortersCollection, me.getRemoteSort());
  }
  return sortersCollection;
}, filter:function(filters, value, suppressEvent) {
  if (Ext.isString(filters)) {
    filters = {property:filters, value:value};
  }
  this.suppressNextFilter = !!suppressEvent;
  this.getFilters().add(filters);
  this.suppressNextFilter = false;
}, removeFilter:function(toRemove, suppressEvent) {
  var me = this, filters = me.getFilters();
  me.suppressNextFilter = !!suppressEvent;
  if (toRemove instanceof Ext.util.Filter) {
    filters.remove(toRemove);
  } else {
    filters.removeByKey(toRemove);
  }
  me.suppressNextFilter = false;
}, updateAutoSort:function(autoSort) {
  this.getData().setAutoSort(autoSort);
}, updateRemoteSort:function(remoteSort) {
  this.onRemoteSortSet(this.getSorters(false), remoteSort);
}, updateRemoteFilter:function(remoteFilter) {
  this.onRemoteFilterSet(this.getFilters(false), remoteFilter);
}, addFilter:function(filters, suppressEvent) {
  this.suppressNextFilter = !!suppressEvent;
  this.getFilters().add(filters);
  this.suppressNextFilter = false;
}, filterBy:function(fn, scope) {
  this.getFilters().add({filterFn:fn, scope:scope || this});
}, clearFilter:function(suppressEvent) {
  var me = this, filters = me.getFilters(false);
  if (!filters || filters.getCount() === 0) {
    return;
  }
  me.suppressNextFilter = !!suppressEvent;
  filters.removeAll();
  me.suppressNextFilter = false;
}, isFiltered:function() {
  return this.getFilters().getCount() > 0;
}, isSorted:function() {
  var sorters = this.getSorters(false);
  return !!(sorters && sorters.length > 0) || this.isGrouped();
}, addFieldTransform:function(sorter) {
  if (sorter.getTransform()) {
    return;
  }
  var fieldName = sorter.getProperty(), Model = this.getModel(), field, sortType;
  if (Model) {
    field = Model.getField(fieldName);
    sortType = field ? field.getSortType() : null;
  }
  if (sortType && sortType !== Ext.identityFn) {
    sorter.setTransform(sortType);
  }
}, beginUpdate:function() {
  if (!this.updating++ && this.hasListeners.beginupdate) {
    this.fireEvent('beginupdate');
  }
}, endUpdate:function() {
  if (this.updating && !--this.updating) {
    if (this.hasListeners.endupdate) {
      this.fireEvent('endupdate');
    }
    this.onEndUpdate();
  }
}, getState:function() {
  var me = this, sorters = [], filters = me.getFilters(), grouper = me.getGrouper(), filterState, hasState, result;
  me.getSorters().each(function(s) {
    sorters[sorters.length] = s.getState();
    hasState = true;
  });
  if (me.statefulFilters && me.saveStatefulFilters) {
    hasState = true;
    filterState = [];
    filters.each(function(f) {
      filterState[filterState.length] = f.getState();
    });
  }
  if (grouper) {
    hasState = true;
  }
  if (hasState) {
    result = {};
    if (sorters.length) {
      result.sorters = sorters;
    }
    if (filterState) {
      result.filters = filterState;
    }
    if (grouper) {
      result.grouper = grouper.getState();
    }
  }
  return result;
}, applyState:function(state) {
  var me = this, stateSorters = state.sorters, stateFilters = state.filters, stateGrouper = state.grouper;
  if (stateSorters) {
    me.getSorters().replaceAll(stateSorters);
  }
  if (stateFilters) {
    me.saveStatefulFilters = true;
    me.getFilters().replaceAll(stateFilters);
  }
  if (stateGrouper) {
    me.setGrouper(stateGrouper);
  }
}, hasPendingLoad:Ext.emptyFn, isLoaded:Ext.emptyFn, isLoading:Ext.emptyFn, destroy:function() {
  var me = this;
  if (me.hasListeners.beforedestroy) {
    me.fireEvent('beforedestroy', me);
  }
  me.destroying = true;
  if (me.getStoreId()) {
    Ext.data.StoreManager.unregister(me);
  }
  me.doDestroy();
  if (me.hasListeners.destroy) {
    me.fireEvent('destroy', me);
  }
  me.callParent();
}, doDestroy:Ext.emptyFn, sort:function(field, direction, mode) {
  var me = this;
  if (arguments.length === 0) {
    if (me.getRemoteSort()) {
      me.load();
    } else {
      me.forceLocalSort();
    }
  } else {
    me.getSorters().addSort(field, direction, mode);
  }
}, onBeforeCollectionSort:function(store, sorters) {
  if (sorters) {
    this.fireEvent('beforesort', this, sorters.getRange());
  }
}, onSorterEndUpdate:function() {
  var me = this, fireSort = true, sorters = me.getSorters(false), sorterCount;
  if (me.settingGroups || !sorters) {
    return;
  }
  sorters = sorters.getRange();
  sorterCount = sorters.length;
  if (me.getRemoteSort()) {
    if (sorters.length || me.getReloadOnClearSorters()) {
      fireSort = false;
      me.load({callback:function() {
        me.fireEvent('sort', me, sorters);
      }});
    }
  } else {
    if (sorterCount) {
      me.fireEvent('datachanged', me);
      me.fireEvent('refresh', me);
    }
  }
  if (fireSort) {
    me.fireEvent('sort', me, sorters);
  }
}, onFilterEndUpdate:function() {
  var me = this, suppressNext = me.suppressNextFilter, filters = me.getFilters(false);
  if (!filters) {
    return;
  }
  if (me.getRemoteFilter()) {
    me.getFilters().each(function(filter) {
      if (filter.getInitialConfig().filterFn) {
        Ext.raise('Unable to use a filtering function in conjunction with ' + 'remote filtering.');
      }
    });
    me.currentPage = 1;
    if (!suppressNext) {
      me.load();
    }
  } else {
    if (!suppressNext) {
      me.fireEvent('datachanged', me);
      me.fireEvent('refresh', me);
    }
  }
  if (me.trackStateChanges) {
    me.saveStatefulFilters = true;
  }
  me.fireEvent('filterchange', me, me.getFilters().getRange());
}, updateGroupField:function(field) {
  if (field) {
    this.setGrouper({property:field, direction:this.getGroupDir()});
  } else {
    this.setGrouper(null);
  }
}, getGrouper:function() {
  return this.getData().getGrouper();
}, group:function(grouper, direction) {
  var me = this, sorters = me.getSorters(false), change = grouper || sorters && sorters.length, data = me.getData();
  if (grouper && typeof grouper === 'string') {
    grouper = {property:grouper, direction:direction || me.getGroupDir()};
  }
  me.settingGroups = true;
  if (grouper === data.getGrouper()) {
    data.updateGrouper(grouper);
  } else {
    data.setGrouper(grouper);
  }
  delete me.settingGroups;
  if (change) {
    if (me.getRemoteSort()) {
      if (!me.isInitializing) {
        me.load({scope:me, callback:function() {
          me.fireGroupChange();
        }});
      }
    } else {
      me.fireEvent('datachanged', me);
      me.fireEvent('refresh', me);
      me.fireGroupChange();
    }
  } else {
    me.fireGroupChange();
  }
}, fireGroupChange:function(grouper) {
  var me = this;
  if (!me.isConfiguring && !me.destroying && !me.destroyed) {
    me.fireGroupChangeEvent(grouper || me.getGrouper());
  }
}, fireGroupChangeEvent:function(grouper) {
  this.fireEvent('groupchange', this, grouper);
}, clearGrouping:function() {
  this.group(null);
}, getGroupField:function() {
  var grouper = this.getGrouper(), group = '';
  if (grouper) {
    group = grouper.getProperty();
  }
  return group;
}, isGrouped:function() {
  return !!this.getGrouper();
}, applyGrouper:function(grouper) {
  this.group(grouper);
  return this.getData().getGrouper();
}, getGroups:function() {
  return this.getData().getGroups();
}, onEndUpdate:Ext.emptyFn, privates:{_metaProperties:{count:'getCount', first:'first', last:'last', loading:'hasPendingLoad', totalCount:'getTotalCount'}, interpret:function(name) {
  var me = this, accessor = me._metaProperties[name];
  return accessor && me[accessor]();
}, loadsSynchronously:Ext.privateFn, onRemoteFilterSet:function(filters, remoteFilter) {
  if (filters) {
    filters[remoteFilter ? 'on' : 'un']('endupdate', 'onFilterEndUpdate', this);
  }
}, onRemoteSortSet:function(sorters, remoteSort) {
  var me = this, data;
  if (sorters) {
    sorters[remoteSort ? 'on' : 'un']('endupdate', 'onSorterEndUpdate', me);
    data = me.getData();
    if (data) {
      data[remoteSort ? 'un' : 'on']('beforesort', 'onBeforeCollectionSort', me);
    }
  }
}}, deprecated:{5:{methods:{destroyStore:function() {
  this.destroy();
}}}}});
Ext.define('Ext.data.Error', {isError:true, $configPrefixed:false, config:{field:null, message:''}, constructor:function(config) {
  this.initConfig(config);
  this.msg = this.message;
}});
Ext.define('Ext.data.ErrorCollection', {extend:Ext.util.MixedCollection, alternateClassName:'Ext.data.Errors', init:function(record) {
  var me = this, fields = record.fields, data = record.data, before, field, i, len, msg, val, name;
  for (i = 0, len = fields.length; i < len; ++i) {
    field = fields[i];
    name = field.name;
    val = data[name];
    if (field.validate && !field.validate.$nullFn) {
      before = me.length;
      msg = field.validate(val, null, me, record);
      if (before === me.length && msg !== true) {
        me.add(name, msg);
      }
    }
  }
  return me;
}, add:function(key, value) {
  var me = this, defaultMessage = Ext.data.field.Field.defaultInvalidMessage, obj = key, current;
  if (Ext.isString(key)) {
    obj = new Ext.data.Error({field:key, message:value || defaultMessage});
  } else {
    if (!obj.isError) {
      obj = new Ext.data.Error({field:obj.field || obj.name, message:obj.error || obj.message || obj.msg || defaultMessage});
    }
    key = obj.field;
  }
  current = me.get(key);
  if (current) {
    if (Ext.isArray(current)) {
      current.push(obj);
      return current;
    }
    me.removeAtKey(key);
    obj = [current, obj];
    obj.field = key;
    obj = [obj];
  }
  return me.callParent([obj]);
}, getKey:function(item) {
  return item.field;
}, isValid:function() {
  return this.length === 0;
}, getByField:function(fieldName) {
  var values = this.get(fieldName);
  if (values && !Ext.isArray(values)) {
    values = [values];
  }
  return values || [];
}});
Ext.define('Ext.data.operation.Operation', {alternateClassName:'Ext.data.Operation', isOperation:true, config:{synchronous:false, url:'', params:undefined, callback:undefined, scope:undefined, resultSet:null, response:null, request:null, records:null, id:undefined, proxy:null, batch:null, recordCreator:null, internalCallback:null, internalScope:null}, order:0, foreignKeyDirection:1, started:false, running:false, complete:false, success:undefined, exception:false, error:undefined, idPrefix:'ext-operation-', 
constructor:function(config) {
  var scope = config && config.scope;
  this.initConfig(config);
  if (config) {
    config.scope = scope;
  }
  if (scope) {
    this.setScope(scope);
    this.initialConfig.scope = scope;
  }
  this._internalId = Ext.id(this, this.idPrefix);
}, getAction:function() {
  return this.action;
}, execute:function() {
  var me = this, request;
  delete me.error;
  delete me.success;
  me.complete = me.exception = false;
  me.setStarted();
  me.request = request = me.doExecute();
  if (request) {
    request.setOperation(me);
  }
  return request;
}, doExecute:Ext.emptyFn, abort:function() {
  var me = this, request = me.request, proxy;
  me.aborted = true;
  if (me.running && request) {
    proxy = me.getProxy();
    if (proxy && !proxy.destroyed) {
      proxy.abort(request);
    }
    me.request = null;
  }
  me.running = false;
}, process:function(resultSet, request, response, autoComplete) {
  var me = this;
  autoComplete = autoComplete !== false;
  me.setResponse(response);
  me.setResultSet(resultSet);
  if (resultSet.getSuccess()) {
    me.doProcess(resultSet, request, response);
    me.setSuccessful(autoComplete);
  } else {
    if (autoComplete) {
      me.setException(resultSet.getMessage());
    }
  }
}, _commitSetOptions:{convert:true, commit:true}, doProcess:function(resultSet, request, response) {
  var me = this, commitSetOptions = me._commitSetOptions, clientRecords = me.getRecords(), clientLen = clientRecords.length, clientIdProperty = clientRecords[0].clientIdProperty, serverRecords = resultSet.getRecords(), serverLen = serverRecords ? serverRecords.length : 0, clientMap, serverRecord, clientRecord, i;
  if (serverLen && clientIdProperty) {
    clientMap = Ext.Array.toValueMap(clientRecords, 'id');
    for (i = 0; i < serverLen; ++i) {
      serverRecord = serverRecords[i];
      clientRecord = clientMap[serverRecord[clientIdProperty]];
      if (clientRecord) {
        delete clientMap[clientRecord.id];
        delete serverRecord[clientIdProperty];
        clientRecord.set(serverRecord, commitSetOptions);
      } else {
        Ext.log.warn('Ignoring server record: ' + Ext.encode(serverRecord));
      }
    }
    for (i in clientMap) {
      clientMap[i].commit();
    }
  } else {
    for (i = 0; i < clientLen; ++i) {
      clientRecord = clientRecords[i];
      if (serverLen === 0 || !(serverRecord = serverRecords[i])) {
        clientRecord.commit();
      } else {
        clientRecord.set(serverRecord, commitSetOptions);
      }
    }
  }
}, setStarted:function() {
  this.started = this.running = true;
}, setCompleted:function() {
  var me = this, proxy;
  me.complete = true;
  me.running = false;
  if (!me.destroying) {
    me.triggerCallbacks();
  }
  if (me.destroyed) {
    return;
  }
  proxy = me.getProxy();
  if (proxy && !proxy.destroyed) {
    proxy.completeOperation(me);
  }
}, setSuccessful:function(complete) {
  this.success = true;
  if (complete) {
    this.setCompleted();
  }
}, setException:function(error) {
  var me = this;
  me.exception = true;
  me.success = me.running = false;
  me.error = error;
  me.setCompleted();
}, triggerCallbacks:function() {
  var me = this, callback = me.getInternalCallback();
  if (callback) {
    callback.call(me.getInternalScope() || me, me);
    if (me.destroyed) {
      return;
    }
    me.setInternalCallback(null);
    me.setInternalScope(null);
  }
  callback = me.getCallback();
  if (callback) {
    callback.call(me.getScope() || me, me.getRecords(), me, me.wasSuccessful());
    if (me.destroyed) {
      return;
    }
    me.setCallback(null);
    me.setScope(null);
  }
}, hasException:function() {
  return this.exception;
}, getError:function() {
  return this.error;
}, getRecords:function() {
  var resultSet;
  return this._records || ((resultSet = this.getResultSet()) ? resultSet.getRecords() : null);
}, isStarted:function() {
  return this.started;
}, isRunning:function() {
  return this.running;
}, isComplete:function() {
  return this.complete;
}, wasSuccessful:function() {
  return this.isComplete() && this.success === true;
}, allowWrite:function() {
  return true;
}, destroy:function() {
  var me = this;
  me.destroying = true;
  if (me.running) {
    me.abort();
  }
  me._params = me._callback = me._scope = me._resultSet = me._response = null;
  me.request = me._request = me._records = me._proxy = me._batch = null;
  me._recordCreator = me._internalCallback = me._internalScope = null;
  me.callParent();
}});
Ext.define('Ext.data.operation.Create', {extend:Ext.data.operation.Operation, alias:'data.operation.create', action:'create', isCreateOperation:true, order:10, config:{recordCreator:Ext.identityFn}, doExecute:function() {
  return this.getProxy().create(this);
}});
Ext.define('Ext.data.operation.Destroy', {extend:Ext.data.operation.Operation, alias:'data.operation.destroy', action:'destroy', isDestroyOperation:true, order:30, foreignKeyDirection:-1, doProcess:function() {
  var clientRecords = this.getRecords(), clientLen = clientRecords.length, i;
  for (i = 0; i < clientLen; ++i) {
    clientRecords[i].setErased();
  }
}, doExecute:function() {
  return this.getProxy().erase(this);
}, getRecordData:function(record, operation) {
  var data = {}, idField = record.idField, nameProperty = this.getNameProperty() || 'name';
  data[idField[nameProperty]] = record.id;
  return data;
}});
Ext.define('Ext.data.operation.Read', {extend:Ext.data.operation.Operation, alias:'data.operation.read', action:'read', isReadOperation:true, config:{filters:undefined, sorters:undefined, grouper:undefined, start:undefined, limit:undefined, page:undefined, addRecords:false}, doExecute:function() {
  return this.getProxy().read(this);
}, doProcess:Ext.emptyFn, allowWrite:function() {
  return false;
}});
Ext.define('Ext.data.operation.Update', {extend:Ext.data.operation.Operation, alias:'data.operation.update', action:'update', isUpdateOperation:true, order:20, config:{recordCreator:Ext.identityFn}, doExecute:function() {
  return this.getProxy().update(this);
}});
Ext.define('Ext.data.SortTypes', function() {
  var me;
  return {singleton:true, constructor:function() {
    me = this;
  }, none:Ext.identityFn, stripCommasRe:/,/g, stripTagsRE:/<\/?[^>]+>/gi, asText:function(s) {
    return s != null ? String(s).replace(me.stripTagsRE, '') : '\x00';
  }, asUCText:function(s) {
    return s != null ? String(s).toUpperCase().replace(me.stripTagsRE, '') : '\x00';
  }, asUCString:function(s) {
    return s != null ? String(s).toUpperCase() : '\x00';
  }, asDate:function(s) {
    if (!s) {
      return 0;
    }
    if (Ext.isDate(s)) {
      return s.getTime();
    }
    return Date.parse(String(s));
  }, asFloat:function(s) {
    var val = parseFloat(String(s).replace(me.stripCommasRe, ''));
    return isNaN(val) ? 0 : val;
  }, asInt:function(s) {
    var val = parseInt(String(s).replace(me.stripCommasRe, ''), 10);
    return isNaN(val) ? 0 : val;
  }};
});
Ext.define('Ext.data.validator.Validator', {mixins:[Ext.mixin.Factoryable], alias:'data.validator.base', isValidator:true, factoryConfig:{cacheable:true}, type:'base', constructor:function(config) {
  if (typeof config === 'function') {
    this.fnOnly = true;
    this.validate = config;
  } else {
    this.initConfig(config);
  }
}, validate:function() {
  return true;
}, clone:function() {
  var me = this;
  if (me.fnOnly) {
    return new Ext.data.validator.Validator(me.validate);
  }
  return new me.self(me.getCurrentConfig());
}}, function(Validator) {
  Ext.Factory.validator = Ext.Factory.dataValidator;
});
Ext.define('Ext.data.field.Field', {mixins:[Ext.mixin.Factoryable], alternateClassName:'Ext.data.Field', alias:'data.field.auto', aliasPrefix:'data.field.', type:'auto', factoryConfig:{defaultProperty:'name'}, isDataField:true, isField:true, allowBlank:true, allowNull:false, critical:false, defaultInvalidMessage:'This field is invalid', defaultValue:undefined, definedBy:null, depends:null, dependents:null, mapping:null, name:null, ordinal:undefined, persist:null, reference:null, summary:null, summaryField:'', 
unique:false, rank:null, stripRe:/[$,%]/g, calculated:false, evil:false, identifier:false, onClassExtended:function(cls, data) {
  var sortType = data.sortType, proto = cls.prototype, superValidators = proto.validators, validators = data.validators, alias = data.alias;
  if (alias) {
    if (typeof alias !== 'string') {
      alias = alias[0];
    }
    if (alias) {
      proto.type = alias.substr(alias.lastIndexOf('.') + 1);
    }
  }
  if (sortType && Ext.isString(sortType)) {
    proto.sortType = Ext.data.SortTypes[sortType];
  }
  if (validators) {
    if (!Ext.isArray(validators)) {
      validators = [validators];
    }
    delete data.validators;
    if (superValidators) {
      validators = superValidators.concat(validators);
    }
    proto.validators = validators;
  }
}, argumentNamesRe:/^function\s*\(\s*([^,\)\s]+)/, calculateRe:/[^.a-z0-9_]([a-z_][a-z_0-9]*)\.([a-z_][a-z_0-9]*)/gi, constructor:function(config) {
  var me = this, calculateRe = me.calculateRe, calculate, calculated, defaultValue, sortType, depends, map, match, dataProp, str, fld, validators;
  if (config) {
    if (Ext.isString(config)) {
      me.name = config;
    } else {
      validators = config.validators;
      if (validators) {
        delete config.validators;
        me.instanceValidators = validators;
      }
      Ext.apply(me, config);
    }
  }
  if (!me.allowNull) {
    me.allowNull = !!me.reference;
  }
  calculate = me.calculate;
  depends = me.depends;
  if (calculate) {
    me.convert = me.doCalculate;
    if (!depends) {
      if (!(depends = calculate.$depends)) {
        map = {};
        str = Ext.Function.toCode(calculate);
        calculate.$depends = depends = [];
        match = me.argumentNamesRe.exec(str);
        dataProp = match ? match[1] : 'data';
        while (match = calculateRe.exec(str)) {
          if (dataProp === match[1] && !map[fld = match[2]]) {
            map[fld] = 1;
            depends.push(fld);
          }
        }
      }
      me.depends = depends;
    }
  }
  defaultValue = me.defaultValue;
  if (me.convert) {
    me.calculated = calculated = me.convert.length > 1;
    me.evil = calculated && !depends;
  }
  if (me.persist === null) {
    me.persist = !calculate;
  }
  sortType = me.sortType;
  if (!me.sortType) {
    me.sortType = Ext.data.SortTypes.none;
  } else {
    if (Ext.isString(sortType)) {
      me.sortType = Ext.data.SortTypes[sortType];
    }
  }
  if (depends && typeof depends === 'string') {
    me.depends = [depends];
  }
  me.cloneDefaultValue = defaultValue !== undefined && (Ext.isDate(defaultValue) || Ext.isArray(defaultValue) || Ext.isObject(defaultValue));
}, setModelValidators:function(modelValidators) {
  this._validators = null;
  this.modelValidators = modelValidators;
}, constructValidators:function(validators) {
  var all, length, i, item, validator, presence;
  if (validators) {
    if (!(validators instanceof Array)) {
      validators = [validators];
    }
    all = this._validators;
    for (i = 0, length = validators.length; i < length; ++i) {
      item = validators[i];
      if (item.fn) {
        item = item.fn;
      }
      validator = Ext.Factory.dataValidator(item);
      if (!validator.isPresence) {
        all.push(validator);
      } else {
        presence = validator;
      }
    }
    if (presence) {
      this.presence = [presence];
    }
  }
}, collate:function(value1, value2) {
  var me = this, lhs = value1, rhs = value2;
  if (me.sortType) {
    lhs = me.sortType(lhs);
    rhs = me.sortType(rhs);
  }
  return lhs === rhs ? 0 : lhs < rhs ? -1 : 1;
}, compare:function(value1, value2) {
  return value1 === value2 ? 0 : value1 < value2 ? -1 : 1;
}, isEqual:function(value1, value2) {
  return this.compare(value1, value2) === 0;
}, convert:null, serialize:null, validate:function(value, separator, errors, record) {
  var me = this, validators = me.getValidators(), result, presence;
  presence = this.presence;
  if (presence && (value == null || value === '')) {
    result = me.validateGroup(presence, value, separator, errors, record);
    if (result !== true) {
      return result;
    }
  }
  return me.validateGroup(validators, value, separator, errors, record);
}, validateGroup:function(validators, value, separator, errors, record) {
  var ret = '', validator, length, i, result;
  for (i = 0, length = validators.length; i < length; ++i) {
    validator = validators[i];
    result = validator.validate(value, record);
    if (result !== true) {
      result = result || this.defaultInvalidMessage;
      if (errors) {
        if (errors.isMixedCollection) {
          errors.add(this.name, result);
        } else {
          if (errors.isCollection) {
            errors.add(result);
          } else {
            errors.push(result);
          }
        }
        ret = ret || result;
      } else {
        if (separator) {
          if (ret) {
            ret += separator;
          }
          ret += result;
        } else {
          ret = result;
          break;
        }
      }
    }
  }
  return ret || true;
}, doCalculate:function(v, rec) {
  return rec ? this.calculate(rec.data) : v;
}, getName:function() {
  return this.name;
}, getAllowBlank:function() {
  return this.allowBlank;
}, getAllowNull:function() {
  return this.allowNull;
}, getConvert:function() {
  return this.convert;
}, getDefaultValue:function() {
  return this.defaultValue;
}, getDepends:function() {
  return this.depends;
}, getMapping:function() {
  return this.mapping;
}, hasMapping:function() {
  var map = this.mapping;
  return !!(map || map === 0);
}, getPersist:function() {
  return this.persist;
}, getSortType:function() {
  return this.sortType;
}, getSummary:function() {
  var me = this, doneSummary = me.doneSummary, summary = me.summary;
  if (!doneSummary) {
    me.doneSummary = true;
    if (summary) {
      me.summary = summary = Ext.Factory.dataSummary(summary);
    }
  }
  return summary || null;
}, getType:function() {
  return 'auto';
}, privates:{getValidators:function() {
  var me = this, validators = me._validators;
  if (!validators) {
    me._validators = validators = [];
    me.constructValidators(me.validators);
    me.constructValidators(me.modelValidators);
    me.constructValidators(me.instanceValidators);
  }
  return validators;
}}, deprecated:{'5.1':{methods:{getSortDir:function() {
  return this.sortDir;
}}}}});
Ext.define('Ext.data.field.Array', {extend:Ext.data.field.Field, alias:'data.field.array', isArrayField:true, itemType:{type:'auto'}, getType:function() {
  return 'array';
}, collate:function(v1, v2) {
  return this.collateOrCompare(v1, v2, 'collate');
}, compare:function(v1, v2) {
  return this.collateOrCompare(v1, v2, 'compare');
}, convert:function(v) {
  return this.doForEach((v || v === 0) && !Ext.isArray(v) ? [v] : v, 'convert');
}, serialize:function(value) {
  return this.doForEach(value, 'serialize');
}, getItemField:function() {
  var me = this, t = me.itemType;
  if (!me.itemField) {
    if (typeof t === 'string') {
      t = {type:t};
    } else {
      if (!(t && t.isDataField)) {
        t = Ext.apply({type:'auto'}, t);
      }
    }
    me.itemField = Ext.data.field.Field.create(t);
  }
  return me.itemField;
}, doForEach:function(v, fn) {
  if (!v) {
    return this.allowNull ? null : [];
  }
  var len = v.length, ret = Array(len), field = this.getItemField(), i;
  for (i = 0; i < len; ++i) {
    ret[i] = field[fn] ? field[fn](v[i]) : v[i];
  }
  return ret;
}, collateOrCompare:function(v1, v2, fn) {
  var field = this.getItemField(), i, len1, len2, len, result;
  if (!v1 && !v2 || v1 === v2) {
    return 0;
  }
  if (!v1 || !v2) {
    return v1 ? 1 : -1;
  }
  len1 = v1.length;
  len2 = v2.length;
  len = Math.min(len1, len2);
  for (i = 0; i < len; ++i) {
    result = field[fn](v1[i], v2[i]);
    if (result !== 0) {
      return result;
    }
  }
  return len1 === len2 ? 0 : len1 < len2 ? -1 : 1;
}});
Ext.define('Ext.data.field.Boolean', {extend:Ext.data.field.Field, alias:['data.field.bool', 'data.field.boolean'], isBooleanField:true, trueRe:/^\s*(?:true|yes|on|1)\s*$/i, convert:function(v) {
  if (typeof v === 'boolean') {
    return v;
  }
  if (this.allowNull && (v === undefined || v === null || v === '')) {
    return null;
  }
  return this.trueRe.test(String(v));
}, getType:function() {
  return 'bool';
}});
Ext.define('Ext.data.field.Date', {extend:Ext.data.field.Field, alias:'data.field.date', sortType:'asDate', isDateField:true, dateFormat:null, dateReadFormat:null, dateWriteFormat:null, compare:function(lhs, rhs) {
  var lhsIsDate = lhs instanceof Date, rhsIsDate = rhs instanceof Date, result;
  if (rhsIsDate && lhsIsDate) {
    result = lhs.getTime() - rhs.getTime();
    if (result === 0) {
      result = 0;
    } else {
      result = result < 0 ? -1 : 1;
    }
  } else {
    if (lhsIsDate === rhsIsDate) {
      result = 0;
    } else {
      result = lhsIsDate ? 1 : -1;
    }
  }
  return result;
}, convert:function(v) {
  if (!v) {
    return null;
  }
  if (v instanceof Date) {
    return v;
  }
  var dateFormat = this.dateReadFormat || this.dateFormat, parsed;
  if (dateFormat) {
    return Ext.Date.parse(v, dateFormat, this.useStrict);
  }
  parsed = Date.parse(v);
  return parsed ? new Date(parsed) : null;
}, serialize:function(value) {
  var result = null, format;
  if (Ext.isDate(value)) {
    format = this.getDateWriteFormat();
    result = format ? Ext.Date.format(value, format) : value;
  }
  return result;
}, getDateFormat:function() {
  return this.dateFormat;
}, getDateReadFormat:function() {
  return this.dateReadFormat;
}, getDateWriteFormat:function() {
  var me = this;
  if (me.hasOwnProperty('dateWriteFormat')) {
    return me.dateWriteFormat;
  }
  if (me.hasOwnProperty('dateFormat')) {
    return me.dateFormat;
  }
  return me.dateWriteFormat || me.dateFormat || 'timestamp';
}, getType:function() {
  return 'date';
}});
Ext.define('Ext.data.field.Integer', {extend:Ext.data.field.Field, alias:['data.field.int', 'data.field.integer'], isNumeric:true, isIntegerField:true, numericType:'int', convert:function(v) {
  if (typeof v === 'number') {
    return this.getNumber(v);
  }
  var empty = v == null || v === '', allowNull = this.allowNull, out;
  if (empty) {
    out = allowNull ? null : 0;
  } else {
    out = this.parse(v);
    if (allowNull && isNaN(out)) {
      out = null;
    }
  }
  return out;
}, getNumber:function(v) {
  return parseInt(v, 10);
}, getType:function() {
  return this.numericType;
}, parse:function(v) {
  return parseInt(String(v).replace(this.stripRe, ''), 10);
}, sortType:function(s) {
  if (s == null) {
    s = Infinity;
  }
  return s;
}});
Ext.define('Ext.data.field.Number', {extend:Ext.data.field.Integer, alias:['data.field.float', 'data.field.number'], isIntegerField:false, isNumberField:true, numericType:'float', getNumber:Ext.identityFn, parse:function(v) {
  return parseFloat(String(v).replace(this.stripRe, ''));
}});
Ext.define('Ext.data.field.String', {extend:Ext.data.field.Field, alias:'data.field.string', sortType:'asUCString', isStringField:true, convert:function(v) {
  var defaultValue = this.allowNull ? null : '';
  return v === undefined || v === null ? defaultValue : String(v);
}, getType:function() {
  return 'string';
}});
Ext.define('Ext.data.identifier.Generator', {'abstract':true, mixins:[Ext.mixin.Factoryable], alias:'data.identifier.default', factoryConfig:{defaultType:'sequential'}, isGenerator:true, config:{id:null}, constructor:function(config) {
  var me = this, id;
  me.initConfig(config);
  id = me.getId();
  if (id) {
    Ext.data.identifier.Generator.all[id] = me;
  }
}, privates:{clone:function(config) {
  var cfg = this.getInitialConfig();
  cfg = config ? Ext.apply({}, config, cfg) : cfg;
  return new this.self(cfg);
}, statics:{all:{}}}}, function() {
  var Generator = this, Factory = Ext.Factory, factory = Factory.dataIdentifier;
  Factory.dataIdentifier = function(config) {
    var id = Ext.isString(config) ? config : config && config.id, existing = id && Generator.all[id];
    return existing || factory(config);
  };
});
Ext.define('Ext.data.identifier.Sequential', {extend:Ext.data.identifier.Generator, alias:'data.identifier.sequential', config:{increment:1, prefix:null, seed:1}, generate:function() {
  var me = this, seed = me._seed, prefix = me._prefix;
  me._seed += me._increment;
  return prefix !== null ? prefix + seed : seed;
}});
Ext.define('Ext.data.Model', {alternateClassName:'Ext.data.Record', isEntity:true, isModel:true, validIdRe:null, erasing:false, loadOperation:null, loadCount:0, observableType:'record', crudState:'R', crudStateWas:null, constructor:function(data, session, skipStoreAddition) {
  var me = this, cls = me.self, identifier = cls.identifier, Model = Ext.data.Model, modelIdentifier = Model.identifier, idProperty = me.idField.name, array, id, initializeFn, internalId, len, i, fields;
  me.data = me.data = data || (data = {});
  me.internalId = internalId = modelIdentifier.generate();
  var dataId = data[idProperty];
  if (session && !session.isSession) {
    Ext.raise('Bad Model constructor argument 2 - "session" is not a Session');
  }
  if ((array = data) instanceof Array) {
    me.data = data = {};
    fields = me.getFields();
    len = Math.min(fields.length, array.length);
    for (i = 0; i < len; ++i) {
      data[fields[i].name] = array[i];
    }
  }
  if (!(initializeFn = cls.initializeFn)) {
    cls.initializeFn = initializeFn = Model.makeInitializeFn(cls);
  }
  if (!initializeFn.$nullFn) {
    cls.initializeFn(me);
  }
  if (!me.isSummaryModel) {
    if (!(me.id = id = data[idProperty]) && id !== 0) {
      if (dataId) {
        Ext.raise('The model ID configured in data ("' + dataId + '") has been rejected by the ' + me.fieldsMap[idProperty].type + ' field converter for the ' + idProperty + ' field');
      }
      if (session) {
        identifier = session.getIdentifier(cls);
        id = identifier.generate();
      } else {
        if (modelIdentifier === identifier) {
          id = internalId;
        } else {
          id = identifier.generate();
        }
      }
      data[idProperty] = me.id = id;
      me.phantom = true;
      me.crudState = 'C';
    }
    if (session && !skipStoreAddition) {
      session.add(me);
    }
    if (me.phantom) {
      me.crudStateWas = 'C';
    }
  }
  if (me.init && Ext.isFunction(me.init)) {
    me.init();
  }
}, editing:false, dirty:false, session:null, dropped:false, erased:false, clientIdProperty:null, evented:false, phantom:false, idProperty:'id', manyToMany:null, identifier:null, previousValues:undefined, proxy:undefined, schema:'default', summary:null, versionProperty:null, generation:1, validationSeparator:null, convertOnSet:true, beginEdit:function() {
  var me = this, modified = me.modified, previousValues = me.previousValues;
  if (!me.editing) {
    me.editing = true;
    me.editMemento = {dirty:me.dirty, data:Ext.apply({}, me.data), generation:me.generation, modified:modified && Ext.apply({}, modified), previousValues:previousValues && Ext.apply({}, previousValues)};
  }
}, calculateSummary:function(records) {
  var fields = this.getFields(), len = fields.length, recLen = records.length, i, result, summary, prop, name, field;
  for (i = 0; i < len; ++i) {
    field = fields[i];
    summary = field.getSummary();
    if (summary) {
      result = result || {};
      name = field.name;
      prop = field.summaryField || name;
      result[name] = summary.calculate(records, prop, 'data', 0, recLen);
    }
  }
  if (result) {
    this.set(result, this._commitOptions);
  }
}, cancelEdit:function() {
  var me = this, editMemento = me.editMemento, validation = me.validation;
  if (editMemento) {
    me.editing = false;
    Ext.apply(me, editMemento);
    me.editMemento = null;
    if (validation && validation.syncGeneration !== me.generation) {
      validation.syncGeneration = 0;
    }
  }
}, endEdit:function(silent, modifiedFieldNames) {
  var me = this, editMemento = me.editMemento;
  if (editMemento) {
    me.editing = false;
    me.editMemento = null;
    me.previousValues = editMemento.previousValues;
    if (!silent) {
      if (!modifiedFieldNames) {
        modifiedFieldNames = me.getModifiedFieldNames(editMemento.data);
      }
      if (me.dirty || modifiedFieldNames && modifiedFieldNames.length) {
        me.callJoined('afterEdit', [modifiedFieldNames]);
      }
    }
  }
}, getField:function(name) {
  return this.self.getField(name);
}, getFields:function() {
  return this.self.getFields();
}, getFieldsMap:function() {
  return this.fieldsMap;
}, getIdProperty:function() {
  return this.idProperty;
}, getId:function() {
  return this.id;
}, getObservableId:function() {
  return this.internalId;
}, setId:function(id, options) {
  this.set(this.idProperty, id, options);
}, getPrevious:function(fieldName) {
  var previousValues = this.previousValues;
  return previousValues && previousValues[fieldName];
}, isModified:function(fieldName) {
  var modified = this.modified;
  return !!(modified && modified.hasOwnProperty(fieldName));
}, getModified:function(fieldName) {
  var out;
  if (this.isModified(fieldName)) {
    out = this.modified[fieldName];
  }
  return out;
}, get:function(fieldName) {
  return this.data[fieldName];
}, _singleProp:{}, _rejectOptions:{convert:false, silent:true}, set:function(fieldName, newValue, options) {
  var me = this, cls = me.self, data = me.data, modified = me.modified, prevVals = me.previousValues, session = me.session, single = Ext.isString(fieldName), opt = single ? options : newValue, convertOnSet = opt ? opt.convert !== false : me.convertOnSet, fieldsMap = me.fieldsMap, silent = opt && opt.silent, commit = opt && opt.commit, updateRefs = !(opt && opt.refs === false) && session, dirty = !(opt && opt.dirty === false && !commit), modifiedFieldNames = null, dirtyRank = 0, associations = me.associations, 
  currentValue, field, idChanged, key, name, oldId, comparator, dep, dependents, i, numFields, newId, rankedFields, reference, value, values, roleName;
  if (single) {
    values = me._singleProp;
    values[fieldName] = newValue;
  } else {
    values = fieldName;
  }
  if (!(rankedFields = cls.rankedFields)) {
    rankedFields = cls.rankFields();
  }
  numFields = rankedFields.length;
  do {
    for (name in values) {
      value = values[name];
      currentValue = data[name];
      comparator = me;
      field = fieldsMap[name];
      if (field) {
        if (convertOnSet && field.convert) {
          value = field.convert(value, me);
        }
        comparator = field;
        reference = field.reference;
      } else {
        reference = null;
      }
      if (comparator.isEqual(currentValue, value)) {
        continue;
      }
      data[name] = value;
      (modifiedFieldNames || (modifiedFieldNames = [])).push(name);
      (prevVals || (me.previousValues = prevVals = {}))[name] = currentValue;
      if (reference && reference.cls) {
        if (updateRefs) {
          session.updateReference(me, field, value, currentValue);
        }
        reference.onValueChange(me, session, value, currentValue);
      }
      i = (dependents = field && field.dependents) && dependents.length;
      while (i-- > 0) {
        (dep = dependents[i]).dirty = true;
        dirtyRank = dirtyRank ? Math.min(dirtyRank, dep.rank) : dep.rank;
      }
      if (!field || field.persist) {
        if (modified && modified.hasOwnProperty(name)) {
          if (!dirty || comparator.isEqual(modified[name], value)) {
            delete modified[name];
            me.dirty = -1;
          }
        } else {
          if (dirty) {
            if (!modified) {
              me.modified = modified = {};
            }
            me.dirty = true;
            modified[name] = currentValue;
          }
        }
      }
      if (name === me.idField.name) {
        idChanged = true;
        oldId = currentValue;
        newId = value;
      }
    }
    if (!dirtyRank) {
      break;
    }
    field = rankedFields[dirtyRank - 1];
    field.dirty = false;
    if (single) {
      delete values[fieldName];
    } else {
      values = me._singleProp;
      single = true;
    }
    fieldName = field.name;
    values[fieldName] = data[fieldName];
    convertOnSet = true;
    for (; dirtyRank < numFields; ++dirtyRank) {
      if (rankedFields[dirtyRank].dirty) {
        break;
      }
    }
    if (dirtyRank < numFields) {
      ++dirtyRank;
    } else {
      dirtyRank = 0;
    }
  } while (1);
  if (me.dirty < 0) {
    me.dirty = false;
    for (key in modified) {
      if (modified.hasOwnProperty(key)) {
        me.dirty = true;
        break;
      }
    }
  }
  if (single) {
    delete values[fieldName];
  }
  ++me.generation;
  if (idChanged) {
    me.id = newId;
    me.onIdChanged(newId, oldId);
    me.callJoined('onIdChanged', [oldId, newId]);
    if (associations) {
      for (roleName in associations) {
        associations[roleName].onIdChanged(me, oldId, newId);
      }
    }
  }
  if (commit) {
    me.commit(silent, modifiedFieldNames);
  } else {
    if (!silent && !me.editing && modifiedFieldNames) {
      me.callJoined('afterEdit', [modifiedFieldNames]);
    }
  }
  return modifiedFieldNames;
}, reject:function(silent) {
  var me = this, modified = me.modified;
  if (me.erased) {
    Ext.raise('Cannot reject once a record has been erased.');
  }
  if (modified) {
    me.set(modified, me._rejectOptions);
  }
  me.dropped = false;
  me.clearState();
  if (!silent) {
    me.callJoined('afterReject');
  }
}, commit:function(silent, modifiedFieldNames) {
  var me = this, versionProperty = me.versionProperty, data = me.data, erased;
  me.clearState();
  if (versionProperty && !me.phantom && !isNaN(data[versionProperty])) {
    ++data[versionProperty];
  }
  me.phantom = false;
  if (me.dropped) {
    me.erased = erased = true;
  }
  if (!silent) {
    if (erased) {
      me.callJoined('afterErase');
    } else {
      me.callJoined('afterCommit', [modifiedFieldNames]);
    }
  }
}, clearState:function() {
  var me = this;
  me.dirty = me.editing = false;
  me.editMemento = me.modified = null;
}, drop:function(cascade) {
  var me = this, associations = me.associations, session = me.session, roleName;
  if (me.erased || me.dropped) {
    return;
  }
  me.dropped = true;
  if (associations && cascade !== false) {
    for (roleName in associations) {
      associations[roleName].onDrop(me, session);
    }
  }
  me.callJoined('afterDrop');
  if (me.phantom) {
    me.setErased();
  }
}, join:function(owner) {
  var me = this, joined = me.joined;
  if (!joined) {
    joined = me.joined = [owner];
  } else {
    if (!joined.length) {
      joined[0] = owner;
    } else {
      Ext.Array.include(joined, owner);
    }
  }
  if (owner.isStore && !me.store) {
    me.store = owner;
  }
}, unjoin:function(owner) {
  var me = this, joined = me.joined, len = joined && joined.length, store = me.store, i;
  if (owner === me.session) {
    me.session = null;
  } else {
    if (len === 1 && joined[0] === owner) {
      joined.length = 0;
    } else {
      if (len) {
        Ext.Array.remove(joined, owner);
      }
    }
    if (store === owner) {
      store = null;
      if (joined) {
        for (i = 0, len = joined.length; i < len; ++i) {
          owner = joined[i];
          if (owner.isStore) {
            store = owner;
            break;
          }
        }
      }
      me.store = store;
    }
  }
}, clone:function(session) {
  var me = this, modified = me.modified, ret = me.copy(me.id, session);
  if (modified) {
    ret.modified = Ext.apply({}, modified);
  }
  ret.dirty = me.dirty;
  ret.dropped = me.dropped;
  ret.phantom = me.phantom;
  return ret;
}, copy:function(newId, session) {
  var me = this, data = Ext.apply({}, me.data), idProperty = me.idProperty, T = me.self;
  if (newId || newId === 0) {
    data[idProperty] = newId;
  } else {
    if (newId === null) {
      delete data[idProperty];
    }
  }
  return new T(data, session);
}, getProxy:function() {
  return this.self.getProxy();
}, getValidation:function(refresh) {
  var me = this, ret = me.validation;
  if (!ret) {
    me.validation = ret = new Ext.data.Validation;
    ret.attach(me);
  }
  if (refresh === true || refresh !== false && ret.syncGeneration !== me.generation) {
    ret.refresh(refresh);
  }
  return ret;
}, validate:function() {
  return (new Ext.data.ErrorCollection).init(this);
}, isValid:function() {
  return this.getValidation().isValid();
}, toUrl:function() {
  var pieces = this.$className.split('.'), name = pieces[pieces.length - 1].toLowerCase();
  return name + '/' + this.getId();
}, erase:function(options) {
  var me = this;
  me.erasing = true;
  me.drop();
  me.erasing = false;
  return me.save(options);
}, setErased:function() {
  this.erased = true;
  this.callJoined('afterErase');
}, getChanges:function() {
  return this.getData(this._getChangesOptions);
}, getCriticalFields:function() {
  var cls = this.self, ret = cls.criticalFields;
  if (!ret) {
    cls.rankFields();
    ret = cls.criticalFields;
  }
  return ret;
}, getAssociatedData:function(result, options) {
  var me = this, associations = me.associations, deep, i, item, items, itemData, length, record, role, roleName, opts, clear, associated;
  result = result || {};
  me.$gathering = 1;
  if (options) {
    options = Ext.apply({}, options);
  }
  for (roleName in associations) {
    role = associations[roleName];
    item = role.getAssociatedItem(me);
    if (!item || item.$gathering) {
      continue;
    }
    if (item.isStore) {
      item.$gathering = 1;
      items = item.getData().items;
      length = items.length;
      itemData = [];
      for (i = 0; i < length; ++i) {
        record = items[i];
        deep = !record.$gathering;
        record.$gathering = 1;
        if (options) {
          associated = options.associated;
          if (associated === undefined) {
            options.associated = deep;
            clear = true;
          } else {
            if (!deep) {
              options.associated = false;
              clear = true;
            }
          }
          opts = options;
        } else {
          opts = deep ? me._getAssociatedOptions : me._getNotAssociatedOptions;
        }
        itemData.push(record.getData(opts));
        if (clear) {
          options.associated = associated;
          clear = false;
        }
        delete record.$gathering;
      }
      delete item.$gathering;
    } else {
      opts = options || me._getAssociatedOptions;
      if (options && options.associated === undefined) {
        opts.associated = true;
      }
      itemData = item.getData(opts);
    }
    result[roleName] = itemData;
  }
  delete me.$gathering;
  return result;
}, getData:function(options) {
  var me = this, ret = {}, opts = options === true ? me._getAssociatedOptions : options || ret, data = me.data, associated = opts.associated, changes = opts.changes, critical = changes && opts.critical, content = changes ? me.modified : data, fieldsMap = me.fieldsMap, persist = opts.persist, serialize = opts.serialize, criticalFields, field, n, name, value;
  if (content) {
    for (name in content) {
      value = data[name];
      field = fieldsMap[name];
      if (field) {
        if (persist && !field.persist) {
          continue;
        }
        if (serialize && field.serialize) {
          value = field.serialize(value, me);
        }
      }
      ret[name] = value;
    }
  }
  if (critical) {
    criticalFields = me.self.criticalFields || me.getCriticalFields();
    for (n = criticalFields.length; n-- > 0;) {
      name = (field = criticalFields[n]).name;
      if (!(name in ret)) {
        value = data[name];
        if (serialize && field.serialize) {
          value = field.serialize(value, me);
        }
        ret[name] = value;
      }
    }
  }
  if (associated) {
    if (typeof associated === 'object') {
      me.getNestedData(opts, ret);
    } else {
      me.getAssociatedData(ret, opts);
    }
  }
  return ret;
}, getNestedData:function(options, result) {
  var me = this, associations = me.associations, graph = options.associated, i, item, items, itemData, length, record, role, roleName, opts;
  result = result || {};
  for (roleName in graph) {
    role = associations[roleName];
    opts = graph[roleName];
    if (opts === true) {
      delete options.associated;
    } else {
      options.associated = opts;
    }
    item = role.getAssociatedItem(me);
    if (!item) {
      continue;
    }
    if (item.isStore) {
      items = item.getData().items;
      length = items.length;
      itemData = [];
      for (i = 0; i < length; ++i) {
        record = items[i];
        itemData.push(record.getData(options));
      }
    } else {
      itemData = item.getData(options);
    }
    result[roleName] = itemData;
  }
  options.associated = graph;
  return result;
}, getTransientFields:function() {
  var cls = this.self, ret = cls.transientFields;
  if (!ret) {
    cls.rankFields();
    ret = cls.transientFields;
  }
  return ret;
}, isLoading:function() {
  return !!this.loadOperation;
}, abort:function() {
  var operation = this.loadOperation;
  if (operation) {
    operation.abort();
  }
}, load:function(options) {
  options = Ext.apply({}, options);
  var me = this, scope = options.scope || me, proxy = me.getProxy(), callback = options.callback, operation = me.loadOperation, id = me.getId(), extras;
  if (operation) {
    extras = operation.extraCalls;
    if (!extras) {
      extras = operation.extraCalls = [];
    }
    extras.push(options);
    return operation;
  }
  var doIdCheck = true;
  if (me.phantom) {
    doIdCheck = false;
  }
  options.id = id;
  options.recordCreator = function(data, type, readOptions) {
    var session = me.session;
    if (readOptions) {
      readOptions.recordCreator = session ? session.recordCreator : null;
    }
    me.set(data, me._commitOptions);
    if (doIdCheck && me.getId() !== id) {
      Ext.raise('Invalid record id returned for ' + id + '@' + me.entityName);
    }
    return me;
  };
  options.internalCallback = function(operation) {
    var success = operation.wasSuccessful() && operation.getRecords().length > 0, op = me.loadOperation, extras = op.extraCalls, successFailArgs = [me, operation], callbackArgs = [me, operation, success], i, len;
    me.loadOperation = null;
    ++me.loadCount;
    if (success) {
      Ext.callback(options.success, scope, successFailArgs);
    } else {
      Ext.callback(options.failure, scope, successFailArgs);
    }
    Ext.callback(callback, scope, callbackArgs);
    if (extras) {
      for (i = 0, len = extras.length; i < len; ++i) {
        options = extras[i];
        if (success) {
          Ext.callback(options.success, scope, successFailArgs);
        } else {
          Ext.callback(options.failure, scope, successFailArgs);
        }
        Ext.callback(options.callback, scope, callbackArgs);
      }
    }
    me.callJoined('afterLoad');
  };
  delete options.callback;
  me.loadOperation = operation = proxy.createOperation('read', options);
  operation.execute();
  return operation;
}, mergeData:function(data) {
  if (!this.dirty) {
    this.set(data, this._commitOptions);
  }
}, save:function(options) {
  options = Ext.apply({}, options);
  var me = this, phantom = me.phantom, dropped = me.dropped, action = dropped ? 'destroy' : phantom ? 'create' : 'update', scope = options.scope || me, callback = options.callback, proxy = me.getProxy(), operation;
  options.records = [me];
  options.internalCallback = function(operation) {
    var args = [me, operation], success = operation.wasSuccessful();
    if (success) {
      Ext.callback(options.success, scope, args);
    } else {
      Ext.callback(options.failure, scope, args);
    }
    args.push(success);
    Ext.callback(callback, scope, args);
  };
  delete options.callback;
  operation = proxy.createOperation(action, options);
  if (dropped && phantom) {
    operation.setResultSet(Ext.data.reader.Reader.prototype.nullResultSet);
    me.setErased();
    operation.setSuccessful(true);
  } else {
    operation.execute();
  }
  return operation;
}, statics:{defaultProxy:'memory'}, inheritableStatics:{_associatedReadOptions:{recordsOnly:true, asRoot:true}, loadData:function(data, session) {
  var rec;
  if (data) {
    rec = this.getProxy().getReader().readRecords([data], session ? {recordCreator:session.recordCreator} : undefined, this._associatedReadOptions)[0];
  } else {
    rec = new this(data, session);
  }
  return rec;
}, getSummaryModel:function() {
  var me = this, proto = me.prototype, summaryModel = me.summaryModel;
  if (!summaryModel) {
    summaryModel = Ext.define(null, {extend:me, fields:proto.summaryFields || [], isSummaryModel:true});
    summaryModel.isSummaryModel = true;
    me.summaryModel = proto.summaryModel = summaryModel;
  }
  return summaryModel || null;
}, addFields:function(newFields) {
  this.replaceFields(newFields);
}, replaceFields:function(newFields, removeFields) {
  var me = this, proto = me.prototype, Field = Ext.data.field.Field, fields = me.fields, fieldsMap = me.fieldsMap, ordinals = me.fieldOrdinals, field, i, idField, len, name, ordinal, cleared;
  if (removeFields === true) {
    fields.length = 0;
    me.fieldsMap = fieldsMap = {};
    me.fieldOrdinals = ordinals = {};
    cleared = true;
  } else {
    if (removeFields) {
      for (i = removeFields.length; i-- > 0;) {
        name = removeFields[i];
        if (name in ordinals) {
          delete ordinals[name];
          delete fieldsMap[name];
        }
      }
      for (i = 0, len = fields.length; i < len; ++i) {
        name = (field = fields[i]).name;
        if (name in ordinals) {
          ordinals[name] = i;
        } else {
          fields.splice(i, 1);
          --i;
          --len;
        }
      }
    }
  }
  for (i = 0, len = newFields ? newFields.length : 0; i < len; i++) {
    name = (field = newFields[i]).name;
    if (!(name in ordinals)) {
      ordinals[name] = ordinal = fields.length;
      fields.push(field = Field.create(field));
      fieldsMap[name] = field;
      field.ordinal = ordinal;
      field.definedBy = field.owner = this;
    }
  }
  if (!cleared) {
    for (i = 0, len = fields.length; i < len; ++i) {
      fields[i].rank = null;
    }
  }
  me.idField = proto.idField = idField = fieldsMap[proto.idProperty];
  if (idField) {
    idField.allowNull = idField.critical = idField.identifier = true;
    idField.defaultValue = null;
  }
  me.initializeFn = me.rankedFields = me.transientFields = me.criticalFields = null;
}, removeFields:function(removeFields) {
  this.replaceFields(null, removeFields);
}, getIdFromData:function(data) {
  var T = this, idField = T.idField, id = idField.calculated ? (new T(data)).id : data[idField.name];
  return id;
}, createWithId:function(id, data, session) {
  var d = data, T = this;
  if (id || id === 0) {
    d = {};
    if (data) {
      Ext.apply(d, data);
    }
    d[T.idField.name] = id;
  }
  return new T(d, session);
}, getFields:function() {
  return this.fields;
}, getFieldsMap:function() {
  return this.fieldsMap;
}, getField:function(name) {
  return this.fieldsMap[name] || null;
}, getProxy:function() {
  var me = this, proxy = me.proxy, defaultProxy = me.defaultProxy, defaults;
  if (!proxy) {
    proxy = me.proxyConfig;
    if (!proxy && defaultProxy) {
      proxy = defaultProxy;
    }
    if (!proxy || !proxy.isProxy) {
      if (typeof proxy === 'string') {
        proxy = {type:proxy};
      }
      defaults = Ext.merge(me.schema.constructProxy(me), proxy);
      if (proxy && proxy.type) {
        proxy = proxy.schema === false ? proxy : defaults;
      } else {
        proxy = defaults;
      }
    }
    proxy = me.setProxy(proxy);
  }
  return proxy;
}, setProxy:function(proxy) {
  var me = this, model;
  if (proxy) {
    if (!proxy.isProxy) {
      proxy = Ext.Factory.proxy(proxy);
    } else {
      model = proxy.getModel();
      if (model && model !== me) {
        proxy = proxy.clone();
      }
    }
    proxy.setModel(me);
  }
  return me.prototype.proxy = me.proxy = proxy;
}, load:function(id, options, session) {
  var data = {}, rec;
  if (session) {
    rec = session.peekRecord(this, id);
  }
  if (!rec) {
    data[this.prototype.idProperty] = id;
    rec = new this(data, session);
  }
  rec.load(options);
  return rec;
}}, deprecated:{5:{methods:{hasId:null, markDirty:null, setDirty:null, eachStore:function(callback, scope) {
  var me = this, stores = me.stores, len = stores.length, i;
  for (i = 0; i < len; ++i) {
    callback.call(scope, stores[i]);
  }
}, join:function(item) {
  var me = this, stores = me.stores, joined = me.joined;
  if (!joined) {
    joined = me.joined = [item];
  } else {
    joined.push(item);
  }
  if (item.isStore) {
    me.store = me.store || item;
    if (!stores) {
      stores = me.stores = [];
    }
    stores.push(item);
  }
}, unjoin:function(item) {
  var me = this, stores = me.stores, joined = me.joined;
  if (joined.length === 1) {
    joined.length = 0;
  } else {
    Ext.Array.remove(joined, item);
  }
  if (item.isStore) {
    Ext.Array.remove(stores, item);
    me.store = stores[0] || null;
  }
}}, properties:{persistenceProperty:null}, inheritableStatics:{methods:{setFields:null}}}}, privates:{_commitOptions:{commit:true}, _getChangesOptions:{changes:true}, _getAssociatedOptions:{associated:true}, _getNotAssociatedOptions:{associated:false}, _metaProperties:{dirty:'isDirty', phantom:'isPhantom', valid:'isValid'}, copyFrom:function(sourceRecord) {
  var me = this, fields = me.fields, fieldCount = fields.length, modifiedFieldNames = [], idProperty = me.idProperty, i = 0, field, myData, sourceData, name, value;
  if (sourceRecord) {
    myData = me.data;
    sourceData = sourceRecord.data;
    for (; i < fieldCount; i++) {
      field = fields[i];
      name = field.name;
      if (name !== idProperty) {
        value = sourceData[name];
        if (value !== undefined && !me.isEqual(myData[name], value)) {
          myData[name] = value;
          modifiedFieldNames.push(name);
        }
      }
    }
    if (me.phantom && !sourceRecord.phantom) {
      me.beginEdit();
      me.setId(sourceRecord.getId());
      me.endEdit(true);
      me.commit(true);
    }
  }
  return modifiedFieldNames;
}, callJoined:function(funcName, args) {
  var me = this, joined = me.joined, session = me.session, state = me.dropped ? 'D' : me.phantom ? 'C' : me.dirty ? 'U' : 'R', i, len, fn, item;
  me.crudState = state;
  if (joined || session) {
    if (args) {
      args.unshift(me);
    } else {
      args = [me];
    }
    fn = session && session[funcName];
    if (fn) {
      fn.apply(session, args);
    }
    if (joined) {
      for (i = 0, len = joined.length; i < len; ++i) {
        item = joined[i];
        if (item && (fn = item[funcName])) {
          fn.apply(item, args);
        }
      }
    }
  }
  me.crudStateWas = state;
}, hasPendingLoad:function() {
  return this.isLoading();
}, interpret:function(name) {
  var me = this, accessor = me._metaProperties[name];
  if (!accessor) {
    accessor = me.associations;
    accessor = accessor && accessor[name] && accessor[name].getterName;
  }
  if (accessor) {
    return me[accessor]();
  }
  return me.data[name];
}, isDirty:function() {
  return this.dirty;
}, isPhantom:function() {
  return this.phantom;
}, onAssociatedRecordSet:function(record, role) {
  this.callJoined('afterAssociatedRecordSet', [record, role]);
}, onIdChanged:Ext.privateFn, setSession:function(session) {
  if (session) {
    if (this.session) {
      Ext.raise('This model already belongs to a session.');
    }
    if (!this.id) {
      Ext.raise('The model must have an id to participate in a session.');
    }
  }
  this.session = session;
  if (session) {
    session.add(this);
  }
}, getModifiedFieldNames:function(old) {
  var me = this, data = me.data, modified = [], oldData = old || me.editMemento.data, key;
  for (key in data) {
    if (data.hasOwnProperty(key)) {
      if (!me.isEqual(data[key], oldData[key], key)) {
        modified.push(key);
      }
    }
  }
  return modified;
}, isEqual:function(lhs, rhs, field) {
  var f;
  if (field) {
    f = field.isField ? field : this.fieldsMap[field];
    if (f) {
      return f.isEqual(lhs, rhs);
    }
  }
  if (lhs instanceof Date && rhs instanceof Date) {
    return lhs.getTime() === rhs.getTime();
  }
  return lhs === rhs;
}, statics:{EDIT:'edit', REJECT:'reject', COMMIT:'commit', rankFields:function() {
  var cls = this, prototype = cls.prototype, fields = cls.fields, length = fields.length, rankedFields = [], criticalFields = [], transientFields = [], evilFields, field, i;
  cls.rankedFields = prototype.rankedFields = rankedFields;
  cls.criticalFields = prototype.criticalFields = criticalFields;
  cls.transientFields = prototype.transientFields = transientFields;
  for (i = 0; i < length; ++i) {
    field = fields[i];
    if (field.critical) {
      criticalFields.push(field);
    }
    if (!field.persist) {
      transientFields.push(field);
    }
    if (field.evil) {
      (evilFields || (evilFields = [])).push(field);
    } else {
      if (!field.depends) {
        rankedFields.push(field);
        field.rank = rankedFields.length;
      }
    }
  }
  for (i = 0; i < length; ++i) {
    if (!(field = fields[i]).rank && !field.evil) {
      cls.topoAdd(field);
    }
  }
  if (evilFields) {
    for (i = 0, length = evilFields.length; i < length; ++i) {
      rankedFields.push(field = evilFields[i]);
      field.rank = rankedFields.length;
    }
  }
  cls.topoStack = null;
  return rankedFields;
}, topoAdd:function(field) {
  var cls = this, dep = field.depends, dependsLength = dep ? dep.length : 0, rankedFields = cls.rankedFields, i, targetField;
  var topoStack = cls.topoStack || (cls.topoStack = []);
  topoStack.push(field.name);
  if (field.rank === 0) {
    Ext.raise(cls.$className + ' has circular field dependencies: ' + topoStack.join(' --\x3e '));
  }
  if (topoStack.length && field.evil) {
    Ext.raise(cls.$className + ': Field ' + topoStack[topoStack.length - 1] + ' cannot depend on depends-less field ' + field.name);
  }
  field.rank = 0;
  for (i = 0; i < dependsLength; ++i) {
    targetField = cls.fieldsMap[dep[i]];
    if (!targetField) {
      Ext.raise(cls.$className + ': Field ' + field.name + ' depends on undefined field ' + dep[i]);
    }
    (targetField.dependents || (targetField.dependents = [])).push(field);
    if (!targetField.rank) {
      cls.topoAdd(targetField);
    }
  }
  rankedFields.push(field);
  field.rank = rankedFields.length;
  topoStack.pop();
}, initFields:function(data, cls, proto) {
  var Field = Ext.data.field.Field, fieldDefs = data.fields, fields = [], fieldOrdinals = {}, fieldsMap = {}, references = [], superFields = proto.fields, versionProperty = data.versionProperty || proto.versionProperty, idProperty = cls.idProperty, idField, field, i, length, name, ordinal, reference, superIdField, superIdFieldName, superIdDeclared, idDeclared;
  cls.fields = proto.fields = fields;
  cls.fieldOrdinals = proto.fieldOrdinals = fieldOrdinals;
  cls.fieldsMap = proto.fieldsMap = fieldsMap;
  cls.references = proto.references = references;
  if (superFields) {
    for (i = 0, length = superFields.length; i < length; ++i) {
      fields[i] = field = Ext.Object.chain(superFields[i]);
      field.dependents = null;
      field.owner = cls;
      fieldOrdinals[name = field.name] = i;
      fieldsMap[name] = field;
      field.rank = null;
      if (field.generated) {
        superIdField = field;
        superIdFieldName = field.name;
      }
    }
  }
  delete data.fields;
  if (fieldDefs) {
    for (i = 0, length = fieldDefs.length; i < length; ++i) {
      field = fieldDefs[i];
      reference = field.reference;
      if (reference && typeof reference !== 'string') {
        reference = Ext.merge({}, reference);
      }
      field.$reference = reference;
      field = Field.create(fieldDefs[i]);
      name = field.name;
      ordinal = fieldOrdinals[name];
      if (ordinal === undefined) {
        fieldOrdinals[name] = ordinal = fields.length;
      }
      fieldsMap[name] = field;
      fields[ordinal] = field;
      field.definedBy = field.owner = cls;
      field.ordinal = ordinal;
      if (name === idProperty) {
        idDeclared = field;
      }
      if (name === superIdFieldName) {
        superIdDeclared = true;
      }
    }
  }
  idField = fieldsMap[idProperty];
  if (!idField) {
    if (superIdField && superIdField.generated) {
      ordinal = superIdField.ordinal;
    } else {
      ordinal = fields.length;
    }
    delete fieldsMap[superIdFieldName];
    delete fieldOrdinals[superIdFieldName];
    idField = new Field(idProperty);
    fields[ordinal] = idField;
    fieldOrdinals[idProperty] = ordinal;
    fieldsMap[idProperty] = idField;
    idField.definedBy = cls;
    idField.ordinal = ordinal;
    idField.generated = true;
  } else {
    if (idDeclared && !superIdDeclared && superIdField && superIdField.generated) {
      Ext.Array.remove(fields, superIdField);
      delete fieldsMap[superIdFieldName];
      delete fieldOrdinals[superIdFieldName];
      fieldsMap[idProperty] = idDeclared;
      for (i = 0, length = fields.length; i < length; ++i) {
        field = fields[i];
        fields.ordinal = i;
        fieldOrdinals[field.name] = i;
      }
    }
  }
  idField.allowNull = idField.critical = idField.identifier = true;
  idField.defaultValue = null;
  cls.idField = proto.idField = idField;
  if (versionProperty) {
    field = fieldsMap[versionProperty];
    if (!field) {
      ordinal = fields.length;
      field = new Field({name:versionProperty, type:'int'});
      fields[ordinal] = field;
      fieldOrdinals[versionProperty] = ordinal;
      fieldsMap[versionProperty] = field;
      field.definedBy = cls;
      field.ordinal = ordinal;
      field.generated = true;
    }
    field.defaultValue = 1;
    field.critical = true;
  }
}, initSummaries:function(data, cls, proto) {
  var summaryDefs = data.summary, fields = proto.fields, superSummaryFields = proto.summaryFields, field, fieldName, i, index, inlineDefs, len, name, summaryFields, summaryFieldMap, summaryField, type;
  if (superSummaryFields) {
    summaryFields = [];
    summaryFieldMap = {};
    for (i = 0, len = superSummaryFields.length; i < len; ++i) {
      summaryField = superSummaryFields[i];
      summaryFields.push(summaryField);
      summaryFieldMap[summaryField.name] = i;
    }
  }
  for (i = 0, len = fields.length; i < len; ++i) {
    field = fields[i];
    if (field.summary && field.definedBy === cls) {
      inlineDefs = inlineDefs || {};
      inlineDefs[field.name] = field.summary;
    }
  }
  if (inlineDefs) {
    summaryDefs = Ext.apply(inlineDefs, summaryDefs);
  }
  if (summaryDefs) {
    delete data.summary;
    summaryFields = summaryFields || [];
    summaryFieldMap = summaryFieldMap || {};
    for (name in summaryDefs) {
      type = typeof(summaryField = summaryDefs[name]);
      if (type === 'function' || type === 'string') {
        summaryField = {summary:summaryField};
      }
      index = summaryFieldMap[name];
      summaryField = Ext.apply({name:name}, summaryField);
      field = summaryField.field;
      if (field) {
        delete summaryField.field;
        summaryField.summaryField = field;
      }
      fieldName = summaryField.summaryField;
      field = proto.fieldsMap[fieldName || name];
      if (field && !summaryField.type) {
        summaryField.type = field.type;
      }
      if (index === undefined) {
        index = summaryFields.length;
        summaryFieldMap[name] = index;
      }
      summaryFields[index] = summaryField;
    }
  }
  if (summaryFields) {
    proto.summaryFields = summaryFields;
  }
}, initValidators:function(data, cls, proto) {
  var superValidators = proto.validators, validators, field, copy, validatorDefs, i, length, fieldValidator, name, validator, item;
  if (superValidators) {
    validators = {};
    for (field in superValidators) {
      validators[field] = Ext.Array.clone(superValidators[field]);
    }
  }
  validatorDefs = data.validators || data.validations;
  if (data.validations) {
    delete data.validations;
    Ext.log.warn((cls.$className || 'Ext.data.Model') + ': validations has been deprecated. Please use validators ' + 'instead.');
  }
  if (validatorDefs) {
    delete data.validators;
    validators = validators || {};
    if (Ext.isArray(validatorDefs)) {
      copy = {};
      for (i = 0, length = validatorDefs.length; i < length; ++i) {
        item = validatorDefs[i];
        name = item.field;
        if (!copy[name]) {
          copy[name] = [];
        }
        item = item.fn || item;
        copy[name].push(item);
      }
      validatorDefs = copy;
    }
    for (name in validatorDefs) {
      fieldValidator = validatorDefs[name];
      if (!Ext.isArray(fieldValidator)) {
        fieldValidator = [fieldValidator];
      }
      validator = validators[name];
      if (validator) {
        Ext.Array.push(validator, fieldValidator);
      } else {
        validators[name] = fieldValidator;
      }
    }
  }
  if (validators) {
    for (name in validators) {
      field = cls.getField(name);
      if (field) {
        field.setModelValidators(validators[name]);
      }
    }
  }
  cls.validators = proto.validators = validators;
}, initAssociations:function(schema, data, cls) {
  var associations = data.associations, belongsTo = data.belongsTo, hasMany = data.hasMany, hasOne = data.hasOne, matrices = data.manyToMany, i, length, assoc, o;
  delete data.associations;
  delete data.belongsTo;
  delete data.hasMany;
  delete data.hasOne;
  delete data.manyToMany;
  if (matrices) {
    schema.addMatrices(cls, matrices);
  }
  if (associations) {
    associations = Ext.isArray(associations) ? associations : [associations];
    for (i = 0, length = associations.length; i < length; ++i) {
      assoc = associations[i];
      o = Ext.apply({}, assoc);
      delete o.type;
      switch(assoc.type) {
        case 'belongsTo':
          schema.addBelongsTo(cls, o);
          break;
        case 'hasMany':
          schema.addHasMany(cls, o);
          break;
        case 'hasOne':
          schema.addHasOne(cls, o);
          break;
        default:
          Ext.raise('Invalid association type: "' + assoc.type + '"');
      }
    }
  }
  if (belongsTo) {
    belongsTo = Ext.isArray(belongsTo) ? belongsTo : [belongsTo];
    for (i = 0, length = belongsTo.length; i < length; ++i) {
      schema.addBelongsTo(cls, belongsTo[i]);
    }
  }
  if (hasMany) {
    hasMany = Ext.isArray(hasMany) ? hasMany : [hasMany];
    for (i = 0, length = hasMany.length; i < length; ++i) {
      schema.addHasMany(cls, hasMany[i]);
    }
  }
  if (hasOne) {
    hasOne = Ext.isArray(hasOne) ? hasOne : [hasOne];
    for (i = 0, length = hasOne.length; i < length; ++i) {
      schema.addHasOne(cls, hasOne[i]);
    }
  }
  schema.afterKeylessAssociations(cls);
}, initIdentifier:function(data, cls, proto) {
  var identifier = data.identifier || data.idgen, superIdent = proto.identifier || cls.schema._defaultIdentifier, generatorPrefix;
  if (data.idgen) {
    Ext.log.warn('Ext.data.Model: idgen has been deprecated. Please use ' + 'identifier instead.');
  }
  if (identifier) {
    delete data.identifier;
    delete data.idgen;
    identifier = Ext.Factory.dataIdentifier(identifier);
  } else {
    if (superIdent) {
      if (superIdent.clone && !superIdent.getId()) {
        identifier = superIdent.clone();
      } else {
        if (superIdent.isGenerator) {
          identifier = superIdent;
        } else {
          identifier = Ext.Factory.dataIdentifier(superIdent);
        }
      }
    }
  }
  cls.identifier = proto.identifier = identifier;
  if (!identifier) {
    generatorPrefix = cls.entityName;
    if (!generatorPrefix) {
      generatorPrefix = Ext.id(null, 'extModel');
    }
    cls.identifier = Ext.Factory.dataIdentifier({type:'sequential', prefix:generatorPrefix + '-'});
  }
}, findValidator:function(validators, name, cfg) {
  var type = cfg.type || cfg, field = validators[name], len, i, item;
  if (field) {
    for (i = 0, len = field.length; i < len; ++i) {
      item = field[i];
      if (item.type === type) {
        return item;
      }
    }
  }
  return null;
}, makeInitializeFn:function(cls) {
  var code = ['var '], body = ['\nreturn function (e) {\n    var data \x3d e.data, v;\n'], work = 0, bc, ec, convert, expr, factory, field, fields, fs, hasDefValue, i, length;
  if (!(fields = cls.rankedFields)) {
    fields = cls.rankFields();
  }
  for (i = 0, length = fields.length; i < length; ++i) {
    field = fields[i];
    fs = 'f' + i;
    convert = field.convert;
    if (i) {
      code.push(',  \n    ');
    }
    code.push(fs, ' \x3d $fields[' + i + ']');
    code.push('  /*  ', field.name, '  */');
    if ((hasDefValue = field.defaultValue !== undefined) || convert) {
      expr = 'data["' + field.name + '"]';
      ++work;
      bc = ec = '';
      if (field.cloneDefaultValue) {
        bc = 'Ext.clone(';
        ec = ')';
      }
      body.push('\n');
      if (convert && hasDefValue) {
        body.push('    v \x3d ', expr, ';\n' + '    if (v !\x3d\x3d undefined) {\n' + '        v \x3d ', fs, '.convert(v, e);\n' + '    }\n' + '    if (v \x3d\x3d\x3d undefined) {\n' + '        v \x3d ', bc, fs, '.defaultValue', ec, ';\n' + '    }\n' + '    ', expr, ' \x3d v;');
      } else {
        if (convert) {
          body.push('    v \x3d ', fs, '.convert(', expr, ',e);\n' + '    if (v !\x3d\x3d undefined) {\n' + '        ', expr, ' \x3d v;\n' + '    }\n');
        } else {
          if (hasDefValue) {
            body.push('    if (', expr, ' \x3d\x3d\x3d undefined) {\n' + '        ', expr, ' \x3d ', bc, fs, '.defaultValue', ec, ';\n' + '    }\n');
          }
        }
      }
    }
  }
  if (!work) {
    return Ext.emptyFn;
  }
  code.push(';\n');
  code.push.apply(code, body);
  code.push('}');
  code = code.join('');
  factory = new Function('$fields', 'Ext', code);
  return factory(fields, Ext);
}}}}, function() {
  var Model = this, proto = Model.prototype, Schema = Ext.data.schema.Schema, defaultSchema;
  Model.proxyConfig = proto.proxy;
  delete proto.proxy;
  Model.fields = [];
  Model.fieldsMap = proto.fieldsMap = {};
  Model.schema = proto.schema = Schema.get(proto.schema);
  proto.idField = new Ext.data.field.Field(proto.idProperty);
  Model.identifier = new Ext.data.identifier.Sequential;
  Model.onExtended(function(cls, data) {
    var proto = cls.prototype, schemaName = data.schema, superCls = proto.superclass.self, schema, entityName, proxy;
    cls.idProperty = data.idProperty || proto.idProperty;
    if (schemaName) {
      delete data.schema;
      schema = Schema.get(schemaName);
    } else {
      if (!(schema = proto.schema)) {
        schema = defaultSchema || (defaultSchema = Schema.get('default'));
      }
    }
    cls.rankFields = Model.rankFields;
    cls.topoAdd = Model.topoAdd;
    proto.schema = cls.schema = schema;
    if (!(entityName = data.entityName)) {
      proto.entityName = entityName = schema.getEntityName(cls);
      if (!entityName) {
        if (data.associations) {
          Ext.raise('Anonymous entities cannot specify "associations"');
        }
        if (data.belongsTo) {
          Ext.raise('Anonymous entities cannot specify "belongsTo"');
        }
        if (data.hasMany) {
          Ext.raise('Anonymous entities cannot specify "hasMany"');
        }
        if (data.hasOne) {
          Ext.raise('Anonymous entities cannot specify "hasOne"');
        }
        if (data.matrices) {
          Ext.raise('Anonymous entities cannot specify "manyToMany"');
        }
      }
    }
    cls.entityName = entityName;
    cls.fieldExtractors = {};
    Model.initIdentifier(data, cls, proto);
    Model.initFields(data, cls, proto);
    Model.initValidators(data, cls, proto);
    if (!data.isSummaryModel) {
      Model.initSummaries(data, cls, proto);
    }
    cls.fields.items = cls.fields;
    if (entityName) {
      schema.addEntity(cls);
      Model.initAssociations(schema, data, cls);
    }
    proxy = data.proxy;
    if (proxy) {
      delete data.proxy;
    } else {
      if (superCls !== Model) {
        proxy = superCls.proxyConfig || superCls.proxy;
      }
    }
    cls.proxyConfig = proxy;
  });
});
Ext.define('Ext.data.ResultSet', {isResultSet:true, $configPrefixed:false, config:{loaded:true, count:null, total:null, remoteTotal:null, success:false, records:null, message:null, metadata:null, groupData:null, summaryData:null}, constructor:function(config) {
  this.initConfig(config);
}, getCount:function() {
  var count = this.callParent(), records;
  if (!count) {
    records = this.getRecords();
    if (records) {
      count = records.length;
    }
  }
  return count;
}});
Ext.define('Ext.data.reader.Reader', {alternateClassName:['Ext.data.Reader', 'Ext.data.DataReader'], mixins:[Ext.mixin.Observable, Ext.mixin.Factoryable], alias:'reader.base', factoryConfig:{defaultType:null}, config:{groupRootProperty:'', implicitIncludes:true, keepRawData:null, messageProperty:'', model:null, proxy:null, readRecordsOnFailure:true, rootProperty:'', successProperty:'success', summaryRootProperty:'', totalProperty:'total', transform:null, typeProperty:''}, isReader:true, constructor:function(config) {
  var me = this;
  if (config && config.hasOwnProperty('root')) {
    config = Ext.apply({}, config);
    config.rootProperty = config.root;
    delete config.root;
    Ext.log.error('Ext.data.reader.Reader: Using the deprecated "root" configuration. ' + 'Use "rootProperty" instead.');
  }
  me.duringInit = 1;
  me.mixins.observable.constructor.call(me, config);
  --me.duringInit;
  me.buildExtractors();
}, forceBuildExtractors:function() {
  if (!this.duringInit) {
    this.buildExtractors(true);
  }
}, updateGroupRootProperty:function() {
  this.forceBuildExtractors();
}, updateMessageProperty:function() {
  this.forceBuildExtractors();
}, applyModel:function(model) {
  return Ext.data.schema.Schema.lookupEntity(model);
}, updateSuccessProperty:function() {
  this.forceBuildExtractors();
}, updateSummaryRootProperty:function() {
  this.forceBuildExtractors();
}, updateTotalProperty:function() {
  this.forceBuildExtractors();
}, applyTransform:function(transform) {
  if (transform) {
    if (Ext.isFunction(transform)) {
      transform = {fn:transform};
    } else {
      if (transform.charAt) {
        transform = {fn:this[transform]};
      }
    }
    return transform.fn.bind(transform.scope || this);
  }
  return transform;
}, read:function(response, readOptions) {
  var data, result, responseText;
  if (response) {
    responseText = response.responseText;
    if (response.responseType || responseText) {
      result = this.getResponseData(response);
      if (result && result.__$isError) {
        return new Ext.data.ResultSet({total:0, count:0, records:[], success:false, message:result.msg});
      } else {
        data = this.readRecords(result, readOptions);
      }
    } else {
      if (responseText !== '') {
        data = this.readRecords(response, readOptions);
      }
    }
  }
  return data || this.nullResultSet;
}, getNullResultSet:function() {
  return this.nullResultSet;
}, createReadError:function(msg) {
  return {__$isError:true, msg:msg};
}, readRecords:function(data, readOptions, internalReadOptions) {
  var me = this, recordsOnly = internalReadOptions && internalReadOptions.recordsOnly, asRoot = internalReadOptions && internalReadOptions.asRoot, groupData = null, summaryData = null, success, recordCount, records, root, remoteTotal, total, value, message, transform, meta, summaryOptions;
  meta = me.getMeta ? me.getMeta(data) : data.metaData;
  if (meta) {
    me.onMetaChange(meta);
  }
  transform = me.getTransform();
  if (transform) {
    data = transform(data);
  }
  me.buildExtractors();
  if (me.getKeepRawData()) {
    me.rawData = data;
  }
  if (me.hasListeners.rawdata) {
    me.fireEventArgs('rawdata', [data]);
  }
  data = me.getData(data);
  success = true;
  recordCount = 0;
  records = [];
  if (me.getSuccessProperty()) {
    value = me.getSuccess(data);
    if (value === false || value === 'false') {
      success = false;
    }
  }
  if (me.getMessageProperty()) {
    message = me.getMessage(data);
  }
  if (success || me.getReadRecordsOnFailure()) {
    root = asRoot || Ext.isArray(data) ? data : me.getRoot(data);
    if (root) {
      total = root.length;
    }
    if (me.getTotalProperty()) {
      value = parseInt(me.getTotal(data), 10);
      if (!isNaN(value)) {
        remoteTotal = total = value;
      }
    }
    if (root) {
      records = me.extractData(root, readOptions);
      recordCount = records.length;
    }
    if (me.getGroupRootProperty()) {
      root = me.getGroupRoot(data);
      if (root) {
        summaryOptions = {includes:false, model:me.getModel().getSummaryModel()};
        groupData = me.extractData(root, summaryOptions) || null;
      }
    }
    if (me.getSummaryRootProperty()) {
      root = me.getSummaryRoot(data);
      if (root) {
        summaryOptions = summaryOptions || {includes:false, model:me.getModel().getSummaryModel()};
        summaryData = me.extractData(root, summaryOptions) || null;
        if (summaryData) {
          summaryData = summaryData[0];
        }
      }
    }
  }
  return recordsOnly ? records : new Ext.data.ResultSet({total:total || recordCount, remoteTotal:remoteTotal, metadata:meta, count:recordCount, records:records, success:success, message:message, groupData:groupData, summaryData:summaryData});
}, extractData:function(root, readOptions) {
  var me = this, entityType = readOptions && readOptions.model ? Ext.data.schema.Schema.lookupEntity(readOptions.model) : me.getModel(), schema = entityType.schema, includes = readOptions && 'includes' in readOptions ? readOptions.includes : schema.hasAssociations(entityType) && me.getImplicitIncludes(), fieldExtractorInfo = me.getFieldExtractorInfo(entityType), length = root.length, records = new Array(length), typeProperty = me.getTypeProperty(), reader, node, nodeType, record, i;
  if (!length && Ext.isObject(root)) {
    root = [root];
    length = 1;
  }
  for (i = 0; i < length; i++) {
    record = root[i];
    if (!record.isModel) {
      node = record;
      if (typeProperty && (nodeType = me.getChildType(schema, node, typeProperty))) {
        reader = nodeType.getProxy().getReader();
        record = reader.extractRecord(node, readOptions, nodeType, schema.hasAssociations(nodeType) && reader.getImplicitIncludes(), reader.getFieldExtractorInfo(nodeType));
      } else {
        record = me.extractRecord(node, readOptions, entityType, includes, fieldExtractorInfo);
      }
      if (record.isModel && record.isNode) {
        record.raw = node;
      }
    }
    if (record.onLoad) {
      record.onLoad();
    }
    records[i] = record;
  }
  return records;
}, getChildType:function(schema, rawNode, typeProperty) {
  var namespace;
  switch(typeof typeProperty) {
    case 'string':
      return schema.getEntity(rawNode[typeProperty]);
    case 'object':
      namespace = typeProperty.namespace;
      return schema.getEntity((namespace ? namespace + '.' : '') + rawNode[typeProperty.name]);
    case 'function':
      return schema.getEntity(typeProperty(rawNode));
  }
}, extractRecordData:function(node, readOptions) {
  var entityType = readOptions && readOptions.model ? Ext.data.schema.Schema.lookupEntity(readOptions.model) : this.getModel(), fieldExtractorInfo = this.getFieldExtractorInfo(entityType);
  return this.extractRecord(node, readOptions, entityType, false, fieldExtractorInfo);
}, extractRecord:function(node, readOptions, entityType, includes, fieldExtractorInfo) {
  var me = this, creatorFn = readOptions && readOptions.recordCreator || me.defaultRecordCreator, modelData, record;
  modelData = me.extractModelData(node, fieldExtractorInfo);
  record = creatorFn.call(me, modelData, entityType || me.getModel(), readOptions);
  if (includes && record.isModel) {
    me.readAssociated(record, node, readOptions);
  }
  return record;
}, getFieldExtractorInfo:function(entityType) {
  var extractors = entityType.fieldExtractors, type, extractor;
  if (!extractors) {
    return;
  }
  type = this.$className;
  extractor = extractors[type];
  if (extractor === undefined) {
    extractors[type] = extractor = this.buildFieldExtractors(entityType);
  }
  return extractor;
}, buildFieldExtractors:function(entityType) {
  var fields = entityType.getFields(), len = fields.length, buffer = [], extractors = [], out = null, cnt = 0, field, name, i, extractor;
  for (i = 0; i < len; ++i) {
    field = fields[i];
    extractor = this.createFieldAccessor(field);
    if (extractor) {
      name = field.name;
      buffer.push('val \x3d extractors[' + cnt + "](raw, self); if (val !\x3d\x3d undefined) { data['" + name + "'] \x3d val; }");
      extractors.push(extractor);
      ++cnt;
    }
  }
  if (buffer.length) {
    out = {extractors:extractors, fn:new Function('raw', 'data', 'extractors', 'self', 'var val;' + buffer.join('\n'))};
  }
  return out;
}, defaultRecordCreator:function(data, Model) {
  return new Model(data);
}, defaultRecordCreatorFromServer:function(data, Model) {
  var record = new Model(data);
  record.phantom = false;
  return record;
}, getModelData:function(raw) {
  return {};
}, extractModelData:function(raw, fieldExtractorInfo) {
  var data = this.getModelData(raw), fn;
  if (fieldExtractorInfo) {
    fn = fieldExtractorInfo.fn;
    fn(raw, data, fieldExtractorInfo.extractors, this);
  }
  return data;
}, readAssociated:function(record, data, readOptions) {
  var me = this, roles = record.associations, key, role;
  for (key in roles) {
    if (roles.hasOwnProperty(key)) {
      role = roles[key];
      if (!record.phantom && readOptions && !readOptions.recordCreator) {
        Ext.apply(readOptions, {recordCreator:me.defaultRecordCreatorFromServer});
      }
      if (role.cls) {
        role.read(record, data, me, readOptions);
      }
    }
  }
}, getData:Ext.identityFn, getRoot:Ext.identityFn, getResponseData:function(response) {
  Ext.raise('getResponseData must be implemented in the Ext.data.reader.Reader subclass');
}, onMetaChange:function(meta) {
  var me = this, fields = meta.fields, model, newModel, clientIdProperty, proxy;
  me.metaData = meta;
  if (meta.root) {
    me.setRootProperty(meta.root);
  }
  if (meta.totalProperty) {
    me.setTotalProperty(meta.totalProperty);
  }
  if (meta.successProperty) {
    me.setSuccessProperty(meta.successProperty);
  }
  if (meta.messageProperty) {
    me.setMessageProperty(meta.messageProperty);
  }
  clientIdProperty = meta.clientIdProperty;
  if (fields) {
    newModel = Ext.define(null, {extend:'Ext.data.Model', fields:fields, clientIdProperty:clientIdProperty});
    me.setModel(newModel);
    proxy = me.getProxy();
    if (proxy) {
      proxy.setModel(newModel);
    }
  } else {
    if (clientIdProperty) {
      model = me.getModel();
      if (model) {
        model.self.prototype.clientIdProperty = clientIdProperty;
      }
    }
  }
}, buildExtractors:function(force) {
  var me = this, totalProp, successProp, messageProp;
  if (force || !me.hasExtractors) {
    totalProp = me.getTotalProperty();
    successProp = me.getSuccessProperty();
    messageProp = me.getMessageProperty();
    if (totalProp) {
      me.getTotal = me.getAccessor(totalProp);
    }
    if (successProp) {
      me.getSuccess = me.getAccessor(successProp);
    }
    if (messageProp) {
      me.getMessage = me.getAccessor(messageProp);
    }
    me.hasExtractors = true;
    return true;
  }
}, getAccessor:function(prop) {
  var me = this, cache = me.extractorCache, ret, key;
  if (typeof prop === 'string') {
    key = me.getAccessorKey(prop);
    if (key) {
      ret = cache.get(key);
    }
    if (!ret) {
      ret = me.createAccessor(prop);
      if (key) {
        cache.add(key, ret);
      }
    }
  } else {
    ret = me.createAccessor(prop);
  }
  return ret;
}, getAccessorKey:function(prop) {
  var className = this.$className;
  return className ? className + prop : '';
}, createAccessor:Ext.emptyFn, createFieldAccessor:Ext.emptyFn, destroy:function() {
  var me = this;
  me.model = me.getTotal = me.getSuccess = me.getMessage = me.rawData = null;
  me.onMetaChange = null;
  me.transform = null;
  me.callParent();
}, privates:{copyFrom:function(reader) {
  var me = this;
  reader.buildExtractors();
  me.getTotal = reader.getTotal;
  me.getSuccess = reader.getSuccess;
  me.getMessage = reader.getMessage;
  ++me.duringInit;
  me.setConfig(reader.getConfig());
  --me.duringInit;
  me.hasExtractors = true;
}}}, function(Cls) {
  var proto = Cls.prototype;
  Ext.apply(proto, {nullResultSet:new Ext.data.ResultSet({total:0, count:0, records:[], success:true, message:''})});
  proto.extractorCache = new Ext.util.LruCache;
});
Ext.define('Ext.data.writer.Writer', {alias:'writer.base', alternateClassName:['Ext.data.DataWriter', 'Ext.data.Writer'], mixins:[Ext.mixin.Factoryable], factoryConfig:{defaultType:null}, isWriter:true, config:{clientIdProperty:null, allDataOptions:{persist:true}, partialDataOptions:{changes:true, critical:true}, writeAllFields:false, dateFormat:null, nameProperty:'name', writeRecordId:true, transform:null}, constructor:function(config) {
  this.initConfig(config);
}, applyTransform:function(transform) {
  if (transform) {
    if (Ext.isFunction(transform)) {
      transform = {fn:transform};
    }
    return transform.fn.bind(transform.scope || this);
  }
  return transform;
}, write:function(request) {
  var operation = request.getOperation(), records = operation.getRecords() || [], len = records.length, data = [], i;
  for (i = 0; i < len; i++) {
    data.push(this.getRecordData(records[i], operation));
  }
  return this.writeRecords(request, data);
}, writeRecords:Ext.emptyFn, getRecordData:function(record, operation) {
  var me = this, nameProperty = me.getNameProperty(), mapping = nameProperty !== 'name', idField = record.self.idField, key = idField ? idField[nameProperty] || idField.name : 'id', value = record.id, writeAll = me.getWriteAllFields(), ret, dateFormat, phantom, options, clientIdProperty, fieldsMap, data, field;
  if (idField && idField.serialize) {
    value = idField.serialize(value);
  }
  if (!writeAll && operation && operation.isDestroyOperation) {
    ret = {};
    ret[key] = value;
  } else {
    dateFormat = me.getDateFormat();
    phantom = record.phantom;
    options = phantom || writeAll ? me.getAllDataOptions() : me.getPartialDataOptions();
    clientIdProperty = phantom && me.getClientIdProperty();
    fieldsMap = record.getFieldsMap();
    options.serialize = false;
    data = record.getData(options);
    ret = mapping ? {} : data;
    if (clientIdProperty) {
      ret[clientIdProperty] = value;
      delete data[key];
    } else {
      if (!me.getWriteRecordId()) {
        delete data[key];
      }
    }
    for (key in data) {
      value = data[key];
      if (!(field = fieldsMap[key])) {
        if (mapping) {
          ret[key] = value;
        }
      } else {
        if (field.isDateField && dateFormat && Ext.isDate(value)) {
          value = Ext.Date.format(value, dateFormat);
        } else {
          if (field.serialize) {
            value = field.serialize(value, record);
          }
        }
        if (mapping) {
          key = field[nameProperty] || key;
        }
        ret[key] = value;
      }
    }
  }
  return ret;
}});
Ext.define('Ext.data.proxy.Proxy', {mixins:[Ext.mixin.Factoryable, Ext.mixin.Observable], $configPrefixed:false, alias:'proxy.proxy', alternateClassName:['Ext.data.DataProxy', 'Ext.data.Proxy'], config:{batchOrder:'create,update,destroy', batchActions:true, model:undefined, reader:{type:'json'}, writer:{type:'json'}}, isProxy:true, isSynchronous:false, constructor:function(config) {
  this.mixins.observable.constructor.call(this, config);
  this.pendingOperations = {};
}, applyModel:function(model) {
  return Ext.data.schema.Schema.lookupEntity(model);
}, updateModel:function(model) {
  var reader;
  if (model) {
    reader = this.getReader();
    if (reader && !reader.getModel()) {
      reader.setModel(model);
    }
  }
}, applyReader:function(reader) {
  if (this.isSynchronous) {
    reader = reader || {};
    reader.keepRawData = true;
  }
  return Ext.Factory.reader(reader);
}, updateReader:function(reader) {
  var me = this, model;
  if (reader) {
    model = me.getModel();
    if (!model) {
      model = reader.getModel();
      if (model) {
        me.setModel(model);
      }
    } else {
      reader.setModel(model);
    }
    if (reader.responseType != null) {
      me.responseType = reader.responseType;
    }
  }
}, applyWriter:function(writer) {
  var reader = this.getReader();
  writer = Ext.Factory.writer(writer);
  if (writer.getRecord && !writer.getRecord() && reader && reader.getRecord) {
    reader = reader.getRecord();
    if (reader) {
      writer.setRecord(reader);
    }
  }
  return writer;
}, abort:Ext.emptyFn, onMetaChange:function(meta) {
  this.fireEvent('metachange', this, meta);
}, create:Ext.emptyFn, read:Ext.emptyFn, update:Ext.emptyFn, erase:Ext.emptyFn, batch:function(options, listeners) {
  var me = this, useBatch = me.getBatchActions(), batch, records, actions, aLen, action, a, r, rLen, record;
  if (options.operations === undefined) {
    options = {operations:options, listeners:listeners};
  }
  if (options.batch) {
    if (Ext.isDefined(options.batch.runOperation)) {
      batch = Ext.applyIf(options.batch, {proxy:me, listeners:{}});
    }
  } else {
    options.batch = {proxy:me, listeners:options.listeners || {}};
  }
  if (!batch) {
    batch = new Ext.data.Batch(options.batch);
  }
  batch.on('complete', Ext.bind(me.onBatchComplete, me, [options], 0), null, {single:true, priority:1000});
  batch.$destroyOwner = options.$destroyOwner;
  actions = me.getBatchOrder().split(',');
  aLen = actions.length;
  for (a = 0; a < aLen; a++) {
    action = actions[a];
    records = options.operations[action];
    if (records) {
      if (useBatch) {
        batch.add(me.createOperation(action, {records:records, params:options.params}));
      } else {
        rLen = records.length;
        for (r = 0; r < rLen; r++) {
          record = records[r];
          batch.add(me.createOperation(action, {records:[record], params:options.params}));
        }
      }
    }
  }
  batch.start();
  return batch;
}, onBatchComplete:function(batchOptions, batch) {
  var scope = batchOptions.scope || this;
  if (batch.hasException()) {
    if (Ext.isFunction(batchOptions.failure)) {
      Ext.callback(batchOptions.failure, scope, [batch, batchOptions]);
    }
  } else {
    if (Ext.isFunction(batchOptions.success)) {
      Ext.callback(batchOptions.success, scope, [batch, batchOptions]);
    }
  }
  if (Ext.isFunction(batchOptions.callback)) {
    Ext.callback(batchOptions.callback, scope, [batch, batchOptions]);
  }
  if (!batch.$destroyOwner) {
    batch.destroy();
  }
}, createOperation:function(action, config) {
  var operation = Ext.createByAlias('data.operation.' + action, config);
  operation.setProxy(this);
  this.pendingOperations[operation._internalId] = operation;
  return operation;
}, completeOperation:function(operation) {
  delete this.pendingOperations[operation._internalId];
}, clone:function() {
  return new this.self(this.getInitialConfig());
}, destroy:function() {
  var ops = this.pendingOperations, opId, op;
  for (opId in ops) {
    op = ops[opId];
    if (op && op.isRunning()) {
      op.abort();
    }
    op.destroy();
  }
  this.pendingOperations = null;
  this.callParent();
}});
Ext.define('Ext.data.proxy.Client', {extend:Ext.data.proxy.Proxy, alternateClassName:'Ext.data.ClientProxy', isSynchronous:true, clear:function() {
  Ext.raise('The Ext.data.proxy.Client subclass that you are using has not defined ' + "a 'clear' function. See src/data/ClientProxy.js for details.");
}});
Ext.define('Ext.data.proxy.Memory', {extend:Ext.data.proxy.Client, alias:'proxy.memory', alternateClassName:'Ext.data.MemoryProxy', isMemoryProxy:true, config:{enablePaging:null, data:{$value:null, merge:function(newValue, currentValue, target, mixinClass) {
  return newValue ? Ext.clone(newValue) : newValue;
}}, clearOnRead:null}, finishOperation:function(operation) {
  var recs = operation.getRecords(), len = recs.length, i;
  for (i = 0; i < len; i++) {
    recs[i].dropped = !!operation.isDestroyOperation;
    recs[i].commit();
  }
  operation.setSuccessful(true);
}, create:function(operation) {
  this.finishOperation(operation);
}, update:function(operation) {
  this.finishOperation(operation);
}, erase:function(operation) {
  this.finishOperation(operation);
}, read:function(operation) {
  var me = this, reader = me.getReader(), resultSet = reader.read(me.getData(), {recordCreator:reader.defaultRecordCreatorFromServer}), records = resultSet.getRecords(), sorters = operation.getSorters(), grouper = operation.getGrouper(), filters = operation.getFilters(), start = operation.getStart(), limit = operation.getLimit(), meta;
  if (operation.process(resultSet, null, null, false) !== false) {
    if (operation.success && me.getClearOnRead()) {
      this.setData(null);
    }
    if (filters && filters.length) {
      resultSet.setRecords(records = Ext.Array.filter(records, Ext.util.Filter.createFilterFn(filters)));
      resultSet.setTotal(records.length);
    }
    if (grouper) {
      sorters = sorters ? sorters.concat(grouper) : sorters;
    }
    if (sorters && sorters.length) {
      resultSet.setRecords(records = Ext.Array.sort(records, Ext.util.Sortable.createComparator(sorters)));
    }
    if (me.getEnablePaging() && start !== undefined && limit !== undefined) {
      if (start >= resultSet.getTotal()) {
        resultSet.setConfig({success:false, records:[], total:0});
      } else {
        resultSet.setRecords(Ext.Array.slice(records, start, start + limit));
      }
    }
    operation.setCompleted();
    meta = resultSet.getMetadata();
    if (meta) {
      me.onMetaChange(meta);
    }
  }
}, clear:Ext.emptyFn});
Ext.define('Ext.data.ProxyStore', {extend:Ext.data.AbstractStore, config:{model:undefined, fields:null, proxy:undefined, autoLoad:undefined, autoSync:false, batchUpdateMode:'operation', sortOnLoad:true, trackRemoved:true, asynchronousLoad:undefined}, onClassExtended:function(cls, data, hooks) {
  var model = data.model, onBeforeClassCreated;
  if (typeof model === 'string') {
    onBeforeClassCreated = hooks.onBeforeCreated;
    hooks.onBeforeCreated = function() {
      var me = this, args = arguments;
      Ext.require(model, function() {
        onBeforeClassCreated.apply(me, args);
      });
    };
  }
}, implicitModel:'Ext.data.Model', autoSyncSuspended:0, removed:null, constructor:function(config) {
  var me = this;
  var configModel = me.model;
  me.callParent(arguments);
  if (me.getAsynchronousLoad() === false) {
    me.flushLoad();
  }
  if (!me.getModel() && me.useModelWarning !== false && me.getStoreId() !== 'ext-empty-store') {
    var logMsg = [Ext.getClassName(me) || 'Store', ' created with no model.'];
    if (typeof configModel === 'string') {
      logMsg.push(" The name '", configModel, "'", ' does not correspond to a valid model.');
    }
    Ext.log.warn(logMsg.join(''));
  }
}, doDestroy:function() {
  var me = this, proxy = me.getProxy();
  me.clearLoadTask();
  Ext.destroy(me.getData());
  me.data = null;
  me.setProxy(null);
  if (proxy.autoCreated) {
    proxy.destroy();
  }
  me.setModel(null);
  me.callParent();
}, applyAsynchronousLoad:function(asynchronousLoad) {
  if (asynchronousLoad == null) {
    asynchronousLoad = !this.loadsSynchronously();
  }
  return asynchronousLoad;
}, updateAutoLoad:function(autoLoad) {
  this.getData();
  if (autoLoad) {
    this.load(Ext.isObject(autoLoad) ? autoLoad : undefined);
  }
}, getTotalCount:function() {
  return this.totalCount || 0;
}, applyFields:function(fields) {
  if (fields) {
    this.createImplicitModel(fields);
  }
}, applyModel:function(model) {
  if (model) {
    model = Ext.data.schema.Schema.lookupEntity(model);
  } else {
    if (!this.destroying) {
      this.getFields();
      model = this.getModel() || this.createImplicitModel();
    }
  }
  return model;
}, applyProxy:function(proxy) {
  var model = this.getModel();
  if (proxy !== null) {
    if (proxy) {
      if (proxy.isProxy) {
        proxy.setModel(model);
      } else {
        if (Ext.isString(proxy)) {
          proxy = {type:proxy, model:model};
        } else {
          if (!proxy.model) {
            proxy = Ext.apply({model:model}, proxy);
          }
        }
        proxy = Ext.createByAlias('proxy.' + proxy.type, proxy);
        proxy.autoCreated = true;
      }
    } else {
      if (model) {
        proxy = model.getProxy();
        this.useModelProxy = true;
      }
    }
    if (!proxy) {
      proxy = Ext.createByAlias('proxy.memory');
      proxy.autoCreated = true;
    }
  }
  return proxy;
}, applyState:function(state) {
  var me = this;
  me.callParent([state]);
  if ((me.getAutoLoad() || me.isLoaded()) && (me.getRemoteSort() || me.getRemoteFilter())) {
    me.load();
  }
}, updateProxy:function(proxy, oldProxy) {
  this.proxyListeners = Ext.destroy(this.proxyListeners);
}, updateTrackRemoved:function(track) {
  this.cleanRemoved();
  this.removed = track ? [] : null;
}, onMetaChange:function(proxy, meta) {
  this.fireEvent('metachange', this, meta);
}, create:function(data, options) {
  var me = this, Model = me.getModel(), instance = new Model(data), operation;
  options = Ext.apply({}, options);
  if (!options.records) {
    options.records = [instance];
  }
  options.internalScope = me;
  options.internalCallback = me.onProxyWrite;
  operation = me.createOperation('create', options);
  return operation.execute();
}, read:function() {
  return this.load.apply(this, arguments);
}, update:function(options) {
  var me = this, operation;
  options = Ext.apply({}, options);
  if (!options.records) {
    options.records = me.getUpdatedRecords();
  }
  options.internalScope = me;
  options.internalCallback = me.onProxyWrite;
  operation = me.createOperation('update', options);
  return operation.execute();
}, onProxyWrite:function(operation) {
  var me = this, success = operation.wasSuccessful(), records = operation.getRecords();
  switch(operation.getAction()) {
    case 'create':
      me.onCreateRecords(records, operation, success);
      break;
    case 'update':
      me.onUpdateRecords(records, operation, success);
      break;
    case 'destroy':
      me.onDestroyRecords(records, operation, success);
      break;
  }
  if (success) {
    me.fireEvent('write', me, operation);
    me.fireEvent('datachanged', me);
  }
}, onCreateRecords:Ext.emptyFn, onUpdateRecords:Ext.emptyFn, onDestroyRecords:function(records, operation, success) {
  if (success) {
    this.cleanRemoved();
  }
}, erase:function(options) {
  var me = this, operation;
  options = Ext.apply({}, options);
  if (!options.records) {
    options.records = me.getRemovedRecords();
  }
  options.internalScope = me;
  options.internalCallback = me.onProxyWrite;
  operation = me.createOperation('destroy', options);
  return operation.execute();
}, onBatchOperationComplete:function(batch, operation) {
  return this.onProxyWrite(operation);
}, onBatchComplete:function(batch, operation) {
  var me = this, operations = batch.operations, length = operations.length, i;
  if (me.batchUpdateMode !== 'operation') {
    me.suspendEvents();
    for (i = 0; i < length; i++) {
      me.onProxyWrite(operations[i]);
    }
    me.resumeEvents();
  }
  me.isSyncing = false;
  if (batch.$destroyOwner === me) {
    batch.destroy();
  }
  me.fireEvent('datachanged', me);
}, onBatchException:function(batch, operation) {
}, filterNew:function(item) {
  return item.phantom && item.isValid();
}, getNewRecords:function() {
  return [];
}, getUpdatedRecords:function() {
  return [];
}, getModifiedRecords:function() {
  return [].concat(this.getNewRecords(), this.getUpdatedRecords());
}, filterUpdated:function(item) {
  return item.dirty && !item.phantom && item.isValid();
}, getRemovedRecords:function() {
  var removed = this.getRawRemovedRecords();
  return removed ? Ext.Array.clone(removed) : [];
}, sync:function(options) {
  var me = this, operations = {}, toCreate = me.getNewRecords(), toUpdate = me.getUpdatedRecords(), toDestroy = me.getRemovedRecords(), needsSync = false;
  if (me.isSyncing) {
    Ext.log.warn('Sync called while a sync operation is in progress. ' + 'Consider configuring autoSync as false.');
  }
  me.needsSync = false;
  if (toCreate.length > 0) {
    operations.create = toCreate;
    needsSync = true;
  }
  if (toUpdate.length > 0) {
    operations.update = toUpdate;
    needsSync = true;
  }
  if (toDestroy.length > 0) {
    operations.destroy = toDestroy;
    needsSync = true;
  }
  if (needsSync && me.fireEvent('beforesync', operations) !== false) {
    me.isSyncing = true;
    options = options || {};
    me.proxy.batch(Ext.apply(options, {operations:operations, listeners:me.getBatchListeners(), $destroyOwner:me}));
  }
  return me;
}, getBatchListeners:function() {
  var me = this, listeners = {scope:me, exception:me.onBatchException, complete:me.onBatchComplete};
  if (me.batchUpdateMode === 'operation') {
    listeners.operationcomplete = me.onBatchOperationComplete;
  }
  return listeners;
}, save:function() {
  return this.sync.apply(this, arguments);
}, load:function(options) {
  var me = this;
  if (typeof options === 'function') {
    options = {callback:options};
  } else {
    options = options ? Ext.Object.chain(options) : {};
  }
  me.pendingLoadOptions = options;
  if (me.getAsynchronousLoad()) {
    if (!me.loadTimer) {
      me.loadTimer = Ext.asap(me.flushLoad, me);
    }
  } else {
    me.flushLoad();
  }
  return me;
}, flushLoad:function() {
  var me = this, options = me.pendingLoadOptions, operation;
  if (me.destroying || me.destroyed) {
    return;
  }
  me.clearLoadTask();
  if (!options) {
    return;
  }
  me.setLoadOptions(options);
  if (me.getRemoteSort() && options.sorters) {
    me.fireEvent('beforesort', me, options.sorters);
  }
  operation = Ext.apply({internalScope:me, internalCallback:me.onProxyLoad, scope:me}, options);
  me.lastOptions = operation;
  operation = me.createOperation('read', operation);
  if (me.fireEvent('beforeload', me, operation) !== false) {
    me.onBeforeLoad(operation);
    me.loading = true;
    if (me.hasListeners.beginload) {
      me.fireEvent('beginload', me, operation);
    }
    operation.execute();
  } else {
    if (me.getAsynchronousLoad()) {
      operation.abort();
    }
    operation.setCompleted();
  }
}, reload:function(options) {
  return this.load(Ext.apply({}, options, this.lastOptions));
}, onEndUpdate:function() {
  var me = this;
  if (me.needsSync && me.autoSync && !me.autoSyncSuspended) {
    me.sync();
  }
}, afterReject:function(record) {
  var me = this;
  if (me.contains(record)) {
    me.onUpdate(record, Ext.data.Model.REJECT, null);
    me.fireEvent('update', me, record, Ext.data.Model.REJECT, null);
    me.fireEvent('datachanged', me);
  }
}, afterCommit:function(record, modifiedFieldNames) {
  var me = this;
  if (!modifiedFieldNames) {
    modifiedFieldNames = null;
  }
  if (me.contains(record)) {
    me.onUpdate(record, Ext.data.Model.COMMIT, modifiedFieldNames);
    me.fireEvent('update', me, record, Ext.data.Model.COMMIT, modifiedFieldNames);
    me.fireEvent('datachanged', me);
  }
}, afterErase:function(record) {
  this.onErase(record);
}, onErase:Ext.emptyFn, onUpdate:Ext.emptyFn, hasPendingLoad:function() {
  return !!this.pendingLoadOptions || this.isLoading();
}, isLoading:function() {
  return !!this.loading;
}, isLoaded:function() {
  return this.loadCount > 0;
}, suspendAutoSync:function() {
  ++this.autoSyncSuspended;
}, resumeAutoSync:function(syncNow) {
  var me = this;
  if (!me.autoSyncSuspended) {
    Ext.log.warn('Mismatched call to resumeAutoSync - auto synchronization ' + 'is currently not suspended.');
  }
  if (me.autoSyncSuspended && !--me.autoSyncSuspended) {
    if (syncNow) {
      me.sync();
    }
  }
}, removeAll:Ext.emptyFn, clearData:Ext.emptyFn, privates:{getRawRemovedRecords:function() {
  return this.removed;
}, onExtraParamsChanged:function() {
}, clearLoadTask:function() {
  this.pendingLoadOptions = this.loadTimer = Ext.unasap(this.loadTimer);
}, cleanRemoved:function() {
  var removed = this.getRawRemovedRecords(), len, i;
  if (removed) {
    for (i = 0, len = removed.length; i < len; ++i) {
      removed[i].unjoin(this);
    }
    removed.length = 0;
  }
}, createOperation:function(type, options) {
  var me = this, proxy = me.getProxy(), listeners;
  if (!me.proxyListeners) {
    listeners = {scope:me, destroyable:true, beginprocessresponse:me.beginUpdate, endprocessresponse:me.endUpdate};
    if (!me.disableMetaChangeEvent) {
      listeners.metachange = me.onMetaChange;
    }
    me.proxyListeners = proxy.on(listeners);
  }
  return proxy.createOperation(type, options);
}, createImplicitModel:function(fields) {
  var me = this, modelCfg = {extend:me.implicitModel, statics:{defaultProxy:'memory'}}, proxy, model;
  if (fields) {
    modelCfg.fields = fields;
  }
  model = Ext.define(null, modelCfg);
  me.setModel(model);
  proxy = me.getProxy();
  if (proxy) {
    model.setProxy(proxy);
  } else {
    me.setProxy(model.getProxy());
  }
}, loadsSynchronously:function() {
  return this.getProxy().isSynchronous;
}, onBeforeLoad:Ext.privateFn, removeFromRemoved:function(record) {
  var removed = this.getRawRemovedRecords();
  if (removed) {
    Ext.Array.remove(removed, record);
    record.unjoin(this);
  }
}, setLoadOptions:function(options) {
  var me = this, filters, sorters;
  if (me.getRemoteFilter()) {
    filters = me.getFilters(false);
    if (filters && filters.getCount()) {
      options.filters = filters.getRange();
    }
  }
  if (me.getRemoteSort()) {
    sorters = me.getSorters(false);
    if (sorters && sorters.getCount()) {
      options.sorters = sorters.getRange();
    }
  }
}}});
Ext.define('Ext.util.Group', {extend:Ext.util.Collection, isGroup:true, config:{groupKey:null, groupValue:null}, $endUpdatePriority:2001, manageSorters:false});
Ext.define('Ext.data.Group', {extend:Ext.util.Group, isDataGroup:true, store:null, getSummaryRecord:function() {
  var me = this, summaryRecord = me.summaryRecord, store = me.store, generation = store.getData().generation, M, T;
  if (!summaryRecord) {
    M = store.getModel();
    T = M.getSummaryModel();
    me.summaryRecord = summaryRecord = new T;
  }
  if (!summaryRecord.isRemote && summaryRecord.summaryGeneration !== generation) {
    summaryRecord.calculateSummary(me.items);
    summaryRecord.summaryGeneration = generation;
  }
  return summaryRecord;
}});
Ext.define('Ext.data.LocalStore', {extend:Ext.Mixin, mixinConfig:{id:'localstore', after:{fireGroupChangeEvent:'onGrouperChange'}}, config:{extraKeys:null}, applyExtraKeys:function(extraKeys) {
  var indexName, data = this.getData();
  data.setExtraKeys(extraKeys);
  extraKeys = data.getExtraKeys();
  for (indexName in extraKeys) {
    this[indexName] = extraKeys[indexName];
  }
}, add:function(record) {
  return this.insert(this.getCount(), arguments.length === 1 ? record : arguments);
}, constructDataCollection:function() {
  var result = new Ext.util.Collection({id:this.getId() + '-data', rootProperty:'data', groupConfig:{xclass:'Ext.data.Group', store:this}});
  result.addObserver(this);
  return result;
}, createModel:function(record) {
  var session = this.getSession(), Model;
  if (!record.isModel) {
    Model = this.getModel();
    record = new Model(record, session);
  }
  return record;
}, createFiltersCollection:function() {
  return this.getData().getFilters();
}, createSortersCollection:function() {
  var sorters = this.getData().getSorters();
  sorters.setSorterConfigure(this.addFieldTransform, this);
  return sorters;
}, getSummaryRecord:function() {
  var me = this, summaryRecord = me.summaryRecord, data = me.getData(), generation = data.generation, T;
  if (!summaryRecord) {
    T = me.getModel().getSummaryModel();
    me.summaryRecord = summaryRecord = new T;
  }
  if (!summaryRecord.isRemote && summaryRecord.summaryGeneration !== generation) {
    summaryRecord.calculateSummary(data.items);
    summaryRecord.summaryGeneration = generation;
  }
  return summaryRecord;
}, onCollectionBeginUpdate:function() {
  this.beginUpdate();
}, onCollectionEndUpdate:function() {
  this.endUpdate();
}, onCollectionSort:function() {
  this.onSorterEndUpdate();
}, onCollectionFilter:function() {
  this.onFilterEndUpdate();
}, onGrouperChange:function(grouper) {
  this.callObservers('GrouperChange', [grouper]);
}, notifySorterChange:function() {
  this.getData().onSorterChange();
}, forceLocalSort:function() {
  var sorters = this.getSorters();
  sorters.beginUpdate();
  sorters.endUpdate();
}, contains:function(record) {
  return this.indexOf(record) > -1;
}, each:function(fn, scope, includeOptions) {
  var data = this.getData(), bypassFilters = includeOptions, len, record, i;
  if (typeof includeOptions === 'object') {
    bypassFilters = includeOptions.filtered;
  }
  if (bypassFilters && data.filtered) {
    data = data.getSource();
  }
  data = data.items.slice(0);
  len = data.length;
  for (i = 0; i < len; ++i) {
    record = data[i];
    if (fn.call(scope || record, record, i, len) === false) {
      break;
    }
  }
}, collect:function(property, includeOptions, filtered) {
  var me = this, allowNull = includeOptions, data = me.getData();
  if (typeof includeOptions === 'object') {
    filtered = includeOptions.filtered;
    allowNull = includeOptions.allowNull;
  }
  if (filtered && data.filtered) {
    data = data.getSource();
  }
  return data.collect(property, 'data', allowNull);
}, getById:function(id) {
  var data = this.getData();
  if (data.filtered) {
    data = data.getSource();
  }
  return data.get(id) || null;
}, getByInternalId:function(internalId) {
  var data = this.getData(), keyCfg;
  if (data.filtered) {
    if (!data.$hasExtraKeys) {
      keyCfg = this.makeInternalKeyCfg();
      data.setExtraKeys(keyCfg);
      data.$hasExtraKeys = true;
    }
    data = data.getSource();
  }
  if (!data.$hasExtraKeys) {
    data.setExtraKeys(keyCfg || this.makeInternalKeyCfg());
    data.$hasExtraKeys = true;
  }
  return data.byInternalId.get(internalId) || null;
}, getDataSource:function() {
  var data = this.getData();
  return data.getSource() || data;
}, indexOf:function(record) {
  return this.getData().indexOf(record);
}, indexOfId:function(id) {
  return this.indexOf(this.getById(id));
}, insert:function(index, records) {
  var me = this, len, i;
  if (records) {
    if (!Ext.isIterable(records)) {
      records = [records];
    } else {
      records = Ext.Array.clone(records);
    }
    len = records.length;
  }
  if (!len) {
    return [];
  }
  for (i = 0; i < len; ++i) {
    records[i] = me.createModel(records[i]);
  }
  me.getData().insert(index, records);
  return records;
}, queryBy:function(fn, scope) {
  var data = this.getData();
  return (data.getSource() || data).createFiltered(fn, scope);
}, query:function(property, value, anyMatch, caseSensitive, exactMatch) {
  var data = this.getData();
  return (data.getSource() || data).createFiltered(property, value, anyMatch, caseSensitive, exactMatch);
}, first:function(grouped) {
  return this.getData().first(grouped) || null;
}, last:function(grouped) {
  return this.getData().last(grouped) || null;
}, sum:function(field, grouped) {
  var data = this.getData();
  return grouped && this.isGrouped() ? data.sumByGroup(field) : data.sum(field);
}, count:function(grouped) {
  var data = this.getData();
  return grouped && this.isGrouped() ? data.countByGroup() : data.count();
}, min:function(field, grouped) {
  var data = this.getData();
  return grouped && this.isGrouped() ? data.minByGroup(field) : data.min(field);
}, max:function(field, grouped) {
  var data = this.getData();
  return grouped && this.isGrouped() ? data.maxByGroup(field) : data.max(field);
}, average:function(field, grouped) {
  var data = this.getData();
  return grouped && this.isGrouped() ? data.averageByGroup(field) : data.average(field);
}, aggregate:function(fn, scope, grouped, field) {
  var me = this, groups, len, out, group, i;
  if (grouped && me.isGrouped()) {
    groups = me.getGroups().items;
    len = groups.length;
    out = {};
    for (i = 0; i < len; ++i) {
      group = groups[i];
      out[group.getGroupKey()] = me.getAggregate(fn, scope || me, group.items, field);
    }
    return out;
  } else {
    return me.getAggregate(fn, scope, me.getData().items, field);
  }
}, getAggregate:function(fn, scope, records, field) {
  var values = [], len = records.length, i;
  for (i = 0; i < len; ++i) {
    values[i] = records[i].get(field);
  }
  return fn.call(scope || this, records, values);
}, addObserver:function(observer) {
  var observers = this.observers;
  if (!observers) {
    this.observers = observers = new Ext.util.Collection;
  }
  observers.add(observer);
}, removeObserver:function(observer) {
  var observers = this.observers;
  if (observers) {
    observers.remove(observer);
  }
}, callObservers:function(action, args) {
  var observers = this.observers, len, items, i, methodName, item;
  if (observers) {
    items = observers.items;
    if (args) {
      args.unshift(this);
    } else {
      args = [this];
    }
    for (i = 0, len = items.length; i < len; ++i) {
      item = items[i];
      methodName = 'onSource' + action;
      if (item[methodName]) {
        item[methodName].apply(item, args);
      }
    }
  }
}, queryRecordsBy:function(fn, scope) {
  var data = this.getData(), matches = [], len, i, record;
  data = (data.getSource() || data).items;
  scope = scope || this;
  for (i = 0, len = data.length; i < len; ++i) {
    record = data[i];
    if (fn.call(scope, record) === true) {
      matches.push(record);
    }
  }
  return matches;
}, queryRecords:function(field, value) {
  var data = this.getData(), matches = [], len, i, record;
  data = (data.getSource() || data).items;
  for (i = 0, len = data.length; i < len; ++i) {
    record = data[i];
    if (record.get(field) === value) {
      matches.push(record);
    }
  }
  return matches;
}, privates:{isLast:function(record) {
  return record === this.last();
}, makeInternalKeyCfg:function() {
  return {byInternalId:{property:'internalId', rootProperty:''}};
}}});
Ext.define('Ext.data.proxy.Server', {extend:Ext.data.proxy.Proxy, alias:'proxy.server', alternateClassName:'Ext.data.ServerProxy', isRemote:true, config:{url:'', pageParam:'page', startParam:'start', limitParam:'limit', groupParam:'group', groupDirectionParam:'groupDir', sortParam:'sort', filterParam:'filter', directionParam:'dir', idParam:'id', simpleSortMode:false, simpleGroupMode:false, noCache:true, cacheString:'_dc', timeout:30000, api:{create:undefined, read:undefined, update:undefined, destroy:undefined}, 
extraParams:{}}, create:function() {
  return this.doRequest.apply(this, arguments);
}, read:function() {
  return this.doRequest.apply(this, arguments);
}, update:function() {
  return this.doRequest.apply(this, arguments);
}, erase:function() {
  return this.doRequest.apply(this, arguments);
}, setExtraParam:function(name, value) {
  var extraParams = this.getExtraParams();
  extraParams[name] = value;
  this.fireEvent('extraparamschanged', extraParams);
}, updateExtraParams:function(newExtraParams, oldExtraParams) {
  this.fireEvent('extraparamschanged', newExtraParams);
}, buildRequest:function(operation) {
  var me = this, initialParams = Ext.apply({}, operation.getParams()), params = Ext.applyIf(initialParams, me.getExtraParams() || {}), request, operationId, idParam;
  Ext.applyIf(params, me.getParams(operation));
  operationId = operation.getId();
  idParam = me.getIdParam();
  if (operationId !== undefined && params[idParam] === undefined) {
    params[idParam] = operationId;
  }
  request = new Ext.data.Request({params:params, action:operation.getAction(), records:operation.getRecords(), url:operation.getUrl(), operation:operation, proxy:me});
  request.setUrl(me.buildUrl(request));
  operation.setRequest(request);
  return request;
}, processResponse:function(success, operation, request, response) {
  var me = this, exception, reader, resultSet, meta, destroyOp;
  if (me.destroying || me.destroyed) {
    return;
  }
  me.fireEvent('beginprocessresponse', me, response, operation);
  if (success === true) {
    reader = me.getReader();
    if (response.status === 204) {
      resultSet = reader.getNullResultSet();
    } else {
      resultSet = reader.read(me.extractResponseData(response), {recordCreator:operation.getRecordCreator() || reader.defaultRecordCreatorFromServer});
    }
    if (!operation.$destroyOwner) {
      operation.$destroyOwner = me;
      destroyOp = true;
    }
    operation.process(resultSet, request, response);
    exception = !operation.wasSuccessful();
  } else {
    me.setException(operation, response);
    exception = true;
  }
  if (me.destroyed) {
    if (!operation.destroyed && destroyOp && operation.$destroyOwner === me) {
      operation.destroy();
    }
    return;
  }
  if (exception) {
    me.fireEvent('exception', me, response, operation);
  } else {
    meta = resultSet.getMetadata();
    if (meta) {
      me.onMetaChange(meta);
    }
  }
  if (me.destroyed) {
    if (!operation.destroyed && destroyOp && operation.$destroyOwner === me) {
      operation.destroy();
    }
    return;
  }
  me.afterRequest(request, success);
  me.fireEvent('endprocessresponse', me, response, operation);
  if (!operation.destroyed && destroyOp && operation.$destroyOwner === me) {
    operation.destroy();
  }
}, setException:function(operation, response) {
  operation.setException({status:response.status, statusText:response.statusText, response:response});
}, extractResponseData:Ext.identityFn, applyEncoding:function(value) {
  return Ext.encode(value);
}, encodeSorters:function(sorters, preventArray) {
  var out = [], length = sorters.length, i;
  for (i = 0; i < length; i++) {
    out[i] = sorters[i].serialize();
  }
  return this.applyEncoding(preventArray ? out[0] : out);
}, encodeFilters:function(filters) {
  var out = [], length = filters.length, encode, i;
  for (i = 0; i < length; i++) {
    encode |= filters[i].serializeTo(out);
  }
  return encode ? this.applyEncoding(out) : out;
}, getParams:function(operation) {
  if (!operation.isReadOperation) {
    return {};
  }
  var me = this, params = {}, grouper = operation.getGrouper(), sorters = operation.getSorters(), filters = operation.getFilters(), page = operation.getPage(), start = operation.getStart(), limit = operation.getLimit(), simpleSortMode = me.getSimpleSortMode(), simpleGroupMode = me.getSimpleGroupMode(), pageParam = me.getPageParam(), startParam = me.getStartParam(), limitParam = me.getLimitParam(), groupParam = me.getGroupParam(), groupDirectionParam = me.getGroupDirectionParam(), sortParam = me.getSortParam(), 
  filterParam = me.getFilterParam(), directionParam = me.getDirectionParam(), hasGroups, index;
  if (pageParam && page) {
    params[pageParam] = page;
  }
  if (startParam && (start || start === 0)) {
    params[startParam] = start;
  }
  if (limitParam && limit) {
    params[limitParam] = limit;
  }
  hasGroups = groupParam && grouper;
  if (hasGroups) {
    if (simpleGroupMode) {
      params[groupParam] = grouper.getProperty();
      if (groupDirectionParam === groupParam) {
        params[groupParam] += ' ' + grouper.getDirection();
      } else {
        params[groupDirectionParam] = grouper.getDirection();
      }
    } else {
      params[groupParam] = me.encodeSorters([grouper], true);
    }
  }
  if (sortParam && sorters && sorters.length > 0) {
    if (simpleSortMode) {
      for (index = sorters.length > 1 && hasGroups ? 1 : 0; index < sorters.length; index++) {
        if (directionParam === sortParam) {
          params[sortParam] = Ext.Array.push(params[sortParam] || [], sorters[index].getProperty() + ' ' + sorters[index].getDirection());
        } else {
          params[sortParam] = Ext.Array.push(params[sortParam] || [], sorters[index].getProperty());
          params[directionParam] = Ext.Array.push(params[directionParam] || [], sorters[index].getDirection());
        }
      }
    } else {
      params[sortParam] = me.encodeSorters(sorters);
    }
  }
  if (filterParam && filters && filters.length > 0) {
    params[filterParam] = me.encodeFilters(filters);
  }
  return params;
}, buildUrl:function(request) {
  var me = this, url = me.getUrl(request);
  if (!url) {
    Ext.raise('You are using a ServerProxy but have not supplied it with a url.');
  }
  if (me.getNoCache()) {
    url = Ext.urlAppend(url, Ext.String.format('{0}\x3d{1}', me.getCacheString(), Ext.Date.now()));
  }
  return url;
}, getUrl:function(request) {
  var url;
  if (request) {
    url = request.getUrl() || this.getApi()[request.getAction()];
  }
  return url ? url : this.callParent();
}, doRequest:function(operation, callback, scope) {
  Ext.raise('The doRequest function has not been implemented on your ' + 'Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details');
}, afterRequest:Ext.emptyFn, destroy:function() {
  var me = this;
  me.destroying = true;
  me.reader = me.writer = Ext.destroy(me.reader, me.writer);
  me.callParent();
  me.destroyed = true;
}});
Ext.define('Ext.data.proxy.Ajax', {extend:Ext.data.proxy.Server, alias:'proxy.ajax', alternateClassName:['Ext.data.HttpProxy', 'Ext.data.AjaxProxy'], isAjaxProxy:true, defaultActionMethods:{create:'POST', read:'GET', update:'POST', destroy:'POST'}, config:{binary:false, headers:undefined, paramsAsJson:false, withCredentials:false, useDefaultXhrHeader:true, username:null, password:null, actionMethods:{create:'POST', read:'GET', update:'POST', destroy:'POST'}}, doRequest:function(operation) {
  var me = this, writer = me.getWriter(), request = me.buildRequest(operation), method = me.getMethod(request), jsonData, params;
  if (writer && operation.allowWrite()) {
    request = writer.write(request);
  }
  request.setConfig({binary:me.getBinary(), headers:me.getHeaders(), timeout:me.getTimeout(), scope:me, callback:me.createRequestCallback(request, operation), method:method, useDefaultXhrHeader:me.getUseDefaultXhrHeader(), disableCaching:false});
  if (me.responseType != null && Ext.supports.XHR2) {
    request.setResponseType(me.responseType);
  }
  if (method.toUpperCase() !== 'GET' && me.getParamsAsJson()) {
    params = request.getParams();
    if (params) {
      jsonData = request.getJsonData();
      if (jsonData) {
        jsonData = Ext.Object.merge({}, jsonData, params);
      } else {
        jsonData = params;
      }
      request.setJsonData(jsonData);
      request.setParams(undefined);
    }
  }
  if (me.getWithCredentials()) {
    request.setWithCredentials(true);
    request.setUsername(me.getUsername());
    request.setPassword(me.getPassword());
  }
  return me.sendRequest(request);
}, sendRequest:function(request) {
  request.setRawRequest(Ext.Ajax.request(request.getCurrentConfig()));
  this.lastRequest = request;
  return request;
}, abort:function(request) {
  request = request || this.lastRequest;
  if (request) {
    Ext.Ajax.abort(request.getRawRequest());
  }
}, getMethod:function(request) {
  var actions = this.getActionMethods(), action = request.getAction(), method;
  if (actions) {
    method = actions[action];
  }
  return method || this.defaultActionMethods[action];
}, createRequestCallback:function(request, operation) {
  return function(options, success, response) {
    var me = this;
    if (request === me.lastRequest) {
      me.lastRequest = null;
    }
    if (!me.destroying && !me.destroyed) {
      me.processResponse(success, operation, request, response);
    }
  };
}, destroy:function() {
  this.lastRequest = null;
  this.callParent();
}});
Ext.define('Ext.data.reader.Json', {extend:Ext.data.reader.Reader, alternateClassName:'Ext.data.JsonReader', alias:'reader.json', config:{record:null, metaProperty:'metaData', useSimpleAccessors:false, preserveRawData:false}, responseType:'json', updateRootProperty:function() {
  this.forceBuildExtractors();
}, updateMetaProperty:function() {
  this.forceBuildExtractors();
}, getResponseData:function(response) {
  var error;
  if (typeof response.responseJson === 'object') {
    return response.responseJson;
  }
  try {
    return Ext.decode(response.responseText);
  } catch (ex) {
    error = this.createReadError(ex.message);
    Ext.Logger.warn('Unable to parse the JSON returned by the server');
    this.fireEvent('exception', this, response, error);
    return error;
  }
}, buildExtractors:function(force) {
  var me = this, emptyFn = Ext.emptyFn;
  if (me.callParent([force])) {
    me.getRoot = me.setupExtractor(me.getRootProperty(), Ext.identityFn);
    me.getGroupRoot = me.setupExtractor(me.getGroupRootProperty(), emptyFn);
    me.getSummaryRoot = me.setupExtractor(me.getSummaryRootProperty(), emptyFn);
    me.getMeta = me.setupExtractor(me.getMetaProperty(), emptyFn);
  }
}, extractData:function(root, readOptions) {
  var recordName = this.getRecord(), data = [], length, i;
  if (recordName) {
    length = root.length;
    if (!length && Ext.isObject(root)) {
      length = 1;
      root = [root];
    }
    for (i = 0; i < length; i++) {
      data[i] = root[i][recordName];
    }
  } else {
    data = root;
  }
  return this.callParent([data, readOptions]);
}, getModelData:function(raw) {
  return this.getPreserveRawData() ? Ext.apply({}, raw) : raw;
}, createAccessor:function() {
  var re = /[\[\.]/;
  return function(expr) {
    var simple = this.getUseSimpleAccessors(), operatorIndex, result, current, parts, part, inExpr, isDot, isLeft, isRight, special, c, i, bracketed, len;
    if (!(expr || expr === 0)) {
      return;
    }
    if (typeof expr === 'function') {
      return expr;
    }
    if (!simple) {
      operatorIndex = String(expr).search(re);
    }
    if (simple === true || operatorIndex < 0) {
      result = function(raw) {
        return raw == null ? null : raw[expr];
      };
    } else {
      current = 'raw';
      parts = [];
      part = '';
      inExpr = 0;
      len = expr.length;
      for (i = 0; i <= len; ++i) {
        c = expr[i];
        isDot = c === '.';
        isLeft = c === '[';
        isRight = c === ']';
        special = isDot || isLeft || isRight || !c;
        if (!special || inExpr > 1 || inExpr && !isRight) {
          part += c;
        } else {
          if (special) {
            bracketed = false;
            if (isLeft) {
              ++inExpr;
            } else {
              if (isRight) {
                --inExpr;
                bracketed = true;
              }
            }
            if (part) {
              if (bracketed) {
                part = '[' + part + ']';
              } else {
                part = '.' + part;
              }
              current += part;
              parts.push('' + current);
              part = '';
            }
          }
        }
      }
      result = parts.join(' \x26\x26 ');
      result = Ext.functionFactory('raw', 'return ' + result);
    }
    return result;
  };
}(), createFieldAccessor:function(field) {
  var me = this, mapping = field.mapping, hasMap = mapping || mapping === 0, map = hasMap ? mapping : field.name;
  if (hasMap) {
    if (typeof map === 'function') {
      return function(raw, self) {
        return field.mapping(raw, self);
      };
    } else {
      return me.createAccessor(map);
    }
  }
}, getAccessorKey:function(prop) {
  var simple = this.getUseSimpleAccessors() ? 'simple' : '';
  return this.callParent([simple + prop]);
}, privates:{copyFrom:function(reader) {
  this.callParent([reader]);
  this.getRoot = reader.getRoot;
}, getGroupRoot:function(data) {
  this.buildExtractors();
  return this.getGroupRoot(data);
}, getSummaryRoot:function(data) {
  this.buildExtractors();
  return this.getSummaryRoot(data);
}, setupExtractor:function(prop, defaultFn) {
  return prop ? this.getAccessor(prop) : defaultFn;
}}});
Ext.define('Ext.data.writer.Json', {extend:Ext.data.writer.Writer, alternateClassName:'Ext.data.JsonWriter', alias:'writer.json', config:{rootProperty:undefined, encode:false, allowSingle:true, expandData:false}, constructor:function(config) {
  if (config && config.hasOwnProperty('root')) {
    config = Ext.apply({}, config);
    config.rootProperty = config.root;
    delete config.root;
    Ext.log.warn('Ext.data.writer.Json: Using the deprecated "root" configuration. ' + 'Use "rootProperty" instead.');
  }
  this.callParent([config]);
}, getExpandedData:function(data) {
  var dataLength = data.length, i = 0, item, prop, nameParts, j, tempObj, toObject;
  toObject = function(name, value) {
    var o = {};
    o[name] = value;
    return o;
  };
  for (; i < dataLength; i++) {
    item = data[i];
    for (prop in item) {
      if (item.hasOwnProperty(prop)) {
        nameParts = prop.split('.');
        j = nameParts.length - 1;
        if (j > 0) {
          tempObj = item[prop];
          for (; j > 0; j--) {
            tempObj = toObject(nameParts[j], tempObj);
          }
          item[nameParts[0]] = item[nameParts[0]] || {};
          Ext.Object.merge(item[nameParts[0]], tempObj);
          delete item[prop];
        }
      }
    }
  }
  return data;
}, writeRecords:function(request, data) {
  var me = this, root = me.getRootProperty(), json, single, transform;
  if (me.getExpandData()) {
    data = me.getExpandedData(data);
  }
  if (me.getAllowSingle() && data.length === 1) {
    data = data[0];
    single = true;
  }
  transform = this.getTransform();
  if (transform) {
    data = transform(data, request);
  }
  if (me.getEncode()) {
    if (root) {
      request.setParam(root, Ext.encode(data));
    } else {
      Ext.raise('Must specify a root when using encode');
    }
  } else {
    if (single || data && data.length) {
      json = request.getJsonData() || {};
      if (root) {
        json[root] = data;
      } else {
        json = data;
      }
      request.setJsonData(json);
    }
  }
  return request;
}});
Ext.define('Ext.util.SorterCollection', {extend:Ext.util.Collection, isSorterCollection:true, $sortable:null, sortFn:null, config:{sorterOptionsFn:null, sorterOptionsScope:null}, constructor:function(config) {
  var me = this;
  me.sortFn = Ext.util.Sorter.createComparator(me);
  me.callParent([config]);
  me.setDecoder(me.decodeSorter);
}, addSort:function(property, direction, mode) {
  var me = this, count, index, limit, options, primary, sorter, sorters;
  if (!property) {
    me.beginUpdate();
    me.endUpdate();
  } else {
    options = me.getOptions();
    if (property instanceof Array) {
      sorters = property;
      mode = direction;
      direction = null;
    } else {
      if (Ext.isString(property)) {
        if (!(sorter = me.get(property))) {
          sorters = [{property:property, direction:direction || options.getDefaultSortDirection()}];
        } else {
          sorters = [sorter];
        }
      } else {
        if (Ext.isFunction(property)) {
          sorters = [{sorterFn:property, direction:direction || options.getDefaultSortDirection()}];
        } else {
          if (!Ext.isObject(property)) {
            Ext.raise('Invalid sort descriptor: ' + property);
          }
          sorters = [property];
          mode = direction;
          direction = null;
        }
      }
    }
    if (mode && !me._sortModes[mode]) {
      Ext.raise('Sort mode should be "multi", "append", "prepend" or "replace", not "' + mode + '"');
    }
    mode = me._sortModes[mode || 'replace'];
    primary = me.getAt(0);
    count = me.length;
    index = mode.append ? count : 0;
    me.beginUpdate();
    me.splice(index, mode.replace ? count : 0, sorters);
    if (mode.multi) {
      count = me.length;
      limit = options.getMultiSortLimit();
      if (count > limit) {
        me.removeAt(limit, count);
      }
    }
    if (sorter && direction) {
      sorter.setDirection(direction);
    } else {
      if (index === 0 && primary && primary === me.getAt(0)) {
        primary.toggle();
      }
    }
    me.endUpdate();
  }
}, clear:function() {
  this.beginUpdate();
  this.callParent();
  this.endUpdate(this.items);
}, getSortFn:function() {
  return this.sortFn;
}, getByProperty:function(prop) {
  var items = this.items, len = items.length, i, item;
  for (i = 0; i < len; ++i) {
    item = items[i];
    if (item.getProperty() === prop) {
      return item;
    }
  }
  return null;
}, _sortModes:{append:{append:1}, multi:{multi:1}, prepend:{prepend:1}, replace:{replace:1}}, decodeSorter:function(sorter, xclass) {
  var me = this, options = me.getOptions(), root = options.getRootProperty(), sorterOptionsFn = me.getSorterOptionsFn(), currentSorter, sorterConfig, type;
  if (sorter.isSorter) {
    if (!sorter.getRoot()) {
      sorter.setRoot(root);
    }
  } else {
    sorterConfig = {direction:options.getDefaultSortDirection(), root:root};
    type = typeof sorter;
    if (type === 'string') {
      currentSorter = me.get(sorter);
      if (currentSorter) {
        return currentSorter;
      }
      sorterConfig.property = sorter;
    } else {
      if (type === 'function') {
        sorterConfig.sorterFn = sorter;
      } else {
        if (!Ext.isObject(sorter)) {
          Ext.raise('Invalid sorter specified: ' + sorter);
        }
        sorterConfig = Ext.apply(sorterConfig, sorter);
        if (sorterConfig.fn) {
          sorterConfig.sorterFn = sorterConfig.fn;
          delete sorterConfig.fn;
        }
      }
    }
    sorter = Ext.create(xclass || Ext.util.Sorter, sorterConfig);
  }
  if (sorterOptionsFn) {
    sorterOptionsFn.call(me.getSorterOptionsScope() || me, sorter);
  }
  return sorter;
}, setSorterConfigure:function(fn, scope) {
  this.setSorterOptionsFn(fn);
  this.setSorterOptionsScope(scope);
}, decodeRemoveItems:function(args, index) {
  var me = this, ret = index === undefined ? args : args[index];
  if (!ret || !ret.$cloned) {
    if (args.length > index + 1 || !Ext.isIterable(ret)) {
      ret = Ext.Array.slice(args, index);
    }
    var currentSorters = me.items, ln = ret.length, remove = [], i, item, n, sorter, type;
    for (i = 0; i < ln; i++) {
      sorter = ret[i];
      if (sorter && sorter.isSorter) {
        remove.push(sorter);
      } else {
        type = typeof sorter;
        if (type === 'string') {
          sorter = me.get(sorter);
          if (sorter) {
            remove.push(sorter);
          }
        } else {
          if (type === 'function') {
            for (n = currentSorters.length; n-- > 0;) {
              item = currentSorters[n];
              if (item.getSorterFn() === sorter) {
                remove.push(item);
              }
            }
          } else {
            Ext.raise('Invalid sorter specification: ' + sorter);
          }
        }
      }
    }
    ret = remove;
    ret.$cloned = true;
  }
  return ret;
}, getOptions:function() {
  return this.$sortable || this;
}});
Ext.define('Ext.util.FilterCollection', {extend:Ext.util.Collection, isFilterCollection:true, $filterable:null, filterFn:null, constructor:function(config) {
  var me = this;
  me.filterFn = Ext.util.Filter.createFilterFn(me);
  me.callParent([config]);
  me.setDecoder(me.decodeFilter);
}, filterData:function(data) {
  return this.filtered ? Ext.Array.filter(data, this.filterFn) : data;
}, getFilterFn:function() {
  return this.filterFn;
}, isItemFiltered:function(item) {
  return !this.filterFn(item);
}, getFilterCount:function() {
  var filters = this.items, len = filters.length, i;
  for (i = len - 1; i >= 0; i--) {
    if (filters[i].getDisabled()) {
      len--;
    }
  }
  return len;
}, decodeFilter:function(filter) {
  var options = this.getOptions(), filterRoot = options.getRootProperty(), filterConfig;
  if (filter.isFilter) {
    if (filter.setRoot && !filter.getRoot()) {
      filter.setRoot(filterRoot);
    }
  } else {
    filterConfig = {root:filterRoot};
    if (Ext.isFunction(filter)) {
      filterConfig.filterFn = filter;
    } else {
      if (!Ext.isObject(filter)) {
        Ext.raise('Invalid filter specified: ' + filter);
      }
      filterConfig = Ext.apply(filterConfig, filter);
      if (filterConfig.fn) {
        filterConfig.filterFn = filterConfig.fn;
        delete filterConfig.fn;
      }
      if (Ext.util.Filter.isInvalid(filterConfig)) {
        return false;
      }
    }
    filter = new Ext.util.Filter(filterConfig);
  }
  return filter;
}, decodeRemoveItems:function(args, index) {
  var me = this, ret = index === undefined ? args : args[index];
  if (!ret.$cloned) {
    if (args.length > index + 1 || !Ext.isIterable(ret)) {
      ret = Ext.Array.slice(args, index);
    }
    var currentFilters = me.items, ln = ret.length, remove = [], filter, i, isFunction, isProp, isString, item, match, n, type;
    for (i = 0; i < ln; i++) {
      filter = ret[i];
      if (filter && filter.isFilter) {
        remove.push(filter);
      } else {
        type = typeof filter;
        isFunction = type === 'function';
        isProp = filter.property !== undefined && filter.value !== undefined;
        isString = type === 'string';
        if (!isFunction && !isProp && !isString) {
          Ext.raise('Invalid filter specification: ' + filter);
        }
        for (n = currentFilters.length; n-- > 0;) {
          item = currentFilters[n];
          match = false;
          if (isString) {
            match = item.getProperty() === filter;
          } else {
            if (isFunction) {
              match = item.getFilterFn() === filter;
            } else {
              if (isProp) {
                match = item.getProperty() === filter.property && item.getValue() === filter.value;
              }
            }
          }
          if (match) {
            remove.push(item);
          }
        }
      }
    }
    ret = remove;
    ret.$cloned = true;
  }
  return ret;
}, getOptions:function() {
  return this.$filterable || this;
}});
Ext.define('Ext.util.GroupCollection', {extend:Ext.util.Collection, isGroupCollection:true, config:{grouper:null, groupConfig:null, itemRoot:null}, observerPriority:-100, emptyGroupRetainTime:300000, constructor:function(config) {
  this.emptyGroups = {};
  this.callParent([config]);
  this.on('remove', 'onGroupRemove', this);
}, getItemGroup:function(item) {
  var key = this.getGrouper().getGroupString(item);
  return this.get(key);
}, onCollectionAdd:function(source, details) {
  if (!this.isConfiguring) {
    this.addItemsToGroups(source, details.items, details.at);
  }
}, onCollectionBeforeItemChange:function(source, details) {
  this.changeDetails = details;
}, onCollectionBeginUpdate:function() {
  this.beginUpdate();
}, onCollectionEndUpdate:function() {
  this.endUpdate();
}, onCollectionItemChange:function(source, details) {
  if (!details.indexChanged) {
    this.syncItemGrouping(source, details);
  }
  this.changeDetails = null;
}, onCollectionRefresh:function(source) {
  if (source.generation) {
    var me = this, itemGroupKeys = me.itemGroupKeys = {}, groupData = me.createEntries(source, source.items), entries = groupData.entries, groupKey, i, len, entry, j;
    for (i = 0, len = entries.length; i < len; ++i) {
      entry = entries[i];
      entry.group.splice(0, 1.0E99, entry.items);
      for (j = 0; j < entry.items.length; j++) {
        itemGroupKeys[source.getKey(entry.items[j])] = entry.group;
      }
    }
    entries = null;
    for (groupKey in me.map) {
      if (!(groupKey in groupData.groups)) {
        (entries || (entries = [])).push(me.map[groupKey]);
      }
    }
    if (entries) {
      me.remove(entries);
    }
    me.sortItems();
  }
}, onCollectionRemove:function(source, details) {
  var me = this, changeDetails = me.changeDetails, itemGroupKeys = me.itemGroupKeys || (me.itemGroupKeys = {}), entries, entry, group, i, n, j, removeGroups, item;
  if (source.getCount()) {
    if (changeDetails) {
      item = changeDetails.item || changeDetails.items[0];
      entries = me.createEntries(source, [item], false).entries;
      entries[0].group = itemGroupKeys['oldKey' in details ? details.oldKey : source.getKey(item)];
    } else {
      entries = me.createEntries(source, details.items, false).entries;
    }
    for (i = 0, n = entries.length; i < n; ++i) {
      group = (entry = entries[i]).group;
      if (group) {
        group.remove(entry.items);
      }
      for (j = 0; j < entry.items.length; j++) {
        delete itemGroupKeys[source.getKey(entry.items[j])];
      }
      if (group && !group.length) {
        (removeGroups || (removeGroups = [])).push(group);
      }
    }
  } else {
    me.itemGroupKeys = {};
    removeGroups = me.items;
    for (i = 0, n = removeGroups.length; i < n; ++i) {
      removeGroups[i].clear();
    }
  }
  if (removeGroups) {
    me.remove(removeGroups);
  }
}, onCollectionSort:function(source) {
  var me = this, sorters = source.getSorters(false), items, length, i, group;
  if (sorters) {
    items = me.items;
    length = me.length;
    for (i = 0; i < length; ++i) {
      group = items[i];
      if (group.getSorters() === sorters) {
        group.sortItems();
      } else {
        group.setSorters(sorters);
      }
    }
  }
}, onCollectionUpdateKey:function(source, details) {
  if (!details.indexChanged) {
    details.oldIndex = source.indexOf(details.item);
    this.syncItemGrouping(source, details);
  }
}, addItemsToGroups:function(source, items, at, oldIndex) {
  var me = this, itemGroupKeys = me.itemGroupKeys || (me.itemGroupKeys = {}), entries = me.createEntries(source, items).entries, index = -1, sourceStartIndex, entry, i, len, j, group, firstIndex, item;
  for (i = 0, len = entries.length; i < len; ++i) {
    entry = entries[i];
    group = entry.group;
    if (oldIndex || oldIndex === 0) {
      item = items[0];
      if (group.getCount() > 0 && source.getSorters().getCount() === 0) {
        firstIndex = source.indexOf(group.items[0]);
        if (oldIndex < firstIndex) {
          index = 0;
        } else {
          index = oldIndex - firstIndex;
        }
      }
      if (index === -1) {
        group.add(item);
      } else {
        group.insert(index, item);
      }
    } else {
      if (me.length > 1 && at) {
        sourceStartIndex = source.indexOf(entries[0].group.getAt(0));
        at = Math.max(at - sourceStartIndex, 0);
      }
      entry.group.insert(at != null ? at : group.items.length, entry.items);
      for (j = 0; j < entry.items.length; j++) {
        itemGroupKeys[source.getKey(entry.items[j])] = entry.group;
      }
    }
  }
  me.sortItems();
}, createEntries:function(source, items, createGroups) {
  var me = this, groups = {}, entries = [], grouper = me.getGrouper(), entry, group, groupKey, groupValue, i, item, len;
  for (i = 0, len = items.length; i < len; ++i) {
    groupKey = grouper.getGroupString(item = items[i]);
    groupValue = grouper.getGroupValue(item);
    if (!(entry = groups[groupKey])) {
      group = me.getGroup(source, groupKey, groupValue, createGroups);
      entries.push(groups[groupKey] = entry = {group:group, items:[]});
    }
    entry.items.push(item);
  }
  return {groups:groups, entries:entries};
}, syncItemGrouping:function(source, details) {
  var me = this, itemGroupKeys = me.itemGroupKeys || (me.itemGroupKeys = {}), item = details.item, grouper = me.getGrouper(), oldKey, itemKey, oldGroup, group;
  itemKey = source.getKey(item);
  oldKey = 'oldKey' in details ? details.oldKey : itemKey;
  oldGroup = itemGroupKeys[oldKey];
  group = me.getGroup(source, grouper.getGroupString(item), grouper.getGroupValue(item));
  details.group = group;
  details.oldGroup = oldGroup;
  if (!(details.groupChanged = group !== oldGroup)) {
    oldGroup.itemChanged(item, details.modified, details.oldKey, details);
  } else {
    if (oldGroup) {
      oldGroup.updateKey(item, oldKey, itemKey);
      oldGroup.remove(item);
      if (!oldGroup.length) {
        me.remove(oldGroup);
      }
    }
    me.addItemsToGroups(source, [item], null, details.oldIndex);
  }
  delete itemGroupKeys[oldKey];
  itemGroupKeys[itemKey] = group;
}, getGroup:function(source, key, value, createGroups) {
  var me = this, group = me.get(key), autoSort = me.getAutoSort();
  if (group) {
    group.setSorters(source.getSorters());
  } else {
    if (createGroups !== false) {
      group = me.emptyGroups[key] || Ext.create(Ext.apply({xclass:'Ext.util.Group', id:me.getId() + '-group-' + key, groupKey:key, groupValue:value, rootProperty:me.getItemRoot(), sorters:source.getSorters()}, me.getGroupConfig()));
      group.ejectTime = null;
      me.setAutoSort(false);
      me.add(group);
      me.setAutoSort(autoSort);
    }
  }
  return group;
}, getKey:function(item) {
  return item.getGroupKey();
}, createSortFn:function() {
  var me = this, grouper = me.getGrouper(), sorterFn = me.getSorters().getSortFn();
  if (!grouper) {
    return sorterFn;
  }
  return function(lhs, rhs) {
    return grouper.sort(lhs.items[0], rhs.items[0]) || sorterFn(lhs, rhs);
  };
}, updateGrouper:function(grouper) {
  var me = this;
  me.grouped = !!(grouper && me.$groupable.getAutoGroup());
  me.onSorterChange();
  me.onEndUpdateSorters(me.getSorters());
}, destroy:function() {
  var me = this;
  me.$groupable = null;
  me.destroyGroups(me.items);
  Ext.undefer(me.checkRemoveQueueTimer);
  me.callParent();
}, privates:{destroyGroups:function(groups) {
  var len = groups.length, i;
  for (i = 0; i < len; ++i) {
    groups[i].destroy();
  }
}, onGroupRemove:function(collection, info) {
  var me = this, groups = info.items, emptyGroups = me.emptyGroups, len, group, i;
  groups = Ext.Array.from(groups);
  for (i = 0, len = groups.length; i < len; i++) {
    group = groups[i];
    group.setSorters(null);
    emptyGroups[group.getGroupKey()] = group;
    group.ejectTime = Ext.now();
  }
  me.checkRemoveQueue();
}, checkRemoveQueue:function() {
  var me = this, emptyGroups = me.emptyGroups, groupKey, group, reschedule;
  for (groupKey in emptyGroups) {
    group = emptyGroups[groupKey];
    if (!group.getCount() && Ext.now() - group.ejectTime > me.emptyGroupRetainTime) {
      Ext.destroy(group);
      delete emptyGroups[groupKey];
    } else {
      reschedule = true;
    }
  }
  if (reschedule) {
    Ext.undefer(me.checkRemoveQueueTimer);
    me.checkRemoveQueueTimer = Ext.defer(me.checkRemoveQueue, me.emptyGroupRetainTime, me);
  }
}}});
Ext.define('Ext.data.Store', {extend:Ext.data.ProxyStore, alias:'store.store', mixins:[Ext.data.LocalStore], config:{data:undefined, clearRemovedOnLoad:true, clearOnPageLoad:true, associatedEntity:null, role:null, session:null}, addRecordsOptions:{addRecords:true}, loadCount:0, complete:false, moveMapCount:0, constructor:function(config) {
  var me = this, data;
  if (config) {
    if (config.buffered) {
      if (this.self !== Ext.data.Store) {
        Ext.raise('buffered config not supported on derived Store classes. ' + 'Please derive from Ext.data.BufferedStore.');
      }
      return new Ext.data['BufferedStore'](config);
    }
    if (config.remoteGroup) {
      Ext.log.warn('Ext.data.Store: remoteGroup has been removed. ' + 'Use remoteSort instead.');
    }
  }
  me.callParent([config]);
  data = me.inlineData;
  if (data) {
    delete me.inlineData;
    me.loadInlineData(data);
  }
}, applyData:function(data, dataCollection) {
  var me = this;
  me.getFields();
  me.getModel();
  if (data && data.isCollection) {
    data.setRootProperty('data');
    dataCollection = data;
    dataCollection.addObserver(this);
    if (data.getCount()) {
      me.afterLoadRecords(data.items);
      if (me.hasListeners.load) {
        me.fireEvent('load', me, data.items, true);
      }
    }
  } else {
    if (!dataCollection) {
      dataCollection = me.constructDataCollection();
    }
    if (data) {
      if (me.isInitializing) {
        me.inlineData = data;
      } else {
        me.loadData(data);
      }
    }
  }
  return dataCollection;
}, loadInlineData:function(data) {
  var me = this, proxy = me.getProxy();
  if (proxy && proxy.isMemoryProxy) {
    proxy.setData(data);
    me.suspendEvents();
    me.read();
    me.resumeEvents();
  } else {
    me.removeAll(true);
    me.suspendEvents();
    me.loadData(data);
    me.resumeEvents();
  }
}, onCollectionAdd:function(collection, info) {
  this.loadCount = this.loadCount || 1;
  this.onCollectionAddItems(collection, info.items, info);
}, onCollectionFilterAdd:function(collection, items) {
  this.onCollectionAddItems(collection, items);
}, onCollectionAddItems:function(collection, records, info) {
  var me = this, len = records.length, lastChunk = info ? !info.next : false, removed = me.removed, ignoreAdd = me.ignoreCollectionAdd, session = me.getSession(), replaced = info && info.replaced, i, sync, record, replacedItems;
  if (me.activeRanges) {
    me.syncActiveRanges();
  }
  for (i = 0; i < len; ++i) {
    record = records[i];
    if (session) {
      session.adopt(record);
    }
    if (!ignoreAdd) {
      record.join(me);
      if (removed && removed.length) {
        Ext.Array.remove(removed, record);
      }
      sync = sync || record.phantom || record.dirty;
    }
  }
  if (ignoreAdd) {
    return;
  }
  if (replaced) {
    replacedItems = [];
    do {
      Ext.Array.push(replacedItems, replaced.items);
      replaced = replaced.next;
    } while (replaced);
    me.setMoving(replacedItems, true);
  }
  if (info) {
    if (info.replaced) {
      if (lastChunk) {
        me.fireEvent('datachanged', me);
        me.fireEvent('refresh', me);
      }
    } else {
      me.fireEvent('add', me, records, info.at);
      if (lastChunk) {
        me.fireEvent('datachanged', me);
      }
    }
  }
  if (replacedItems) {
    me.setMoving(replacedItems, false);
  }
  me.needsSync = me.needsSync || sync;
}, onCollectionBeforeItemChange:function(collection, info) {
  var record = info.item, modifiedFieldNames = info.modified || null, type = info.meta;
  this.fireEvent('beforeupdate', this, record, type, modifiedFieldNames, info);
}, onCollectionFilteredItemChange:function() {
  this.onCollectionItemChange.apply(this, arguments);
}, onCollectionItemChange:function(collection, info) {
  var me = this, record = info.item, modifiedFieldNames = info.modified || null, type = info.meta;
  if (me.fireChangeEvent(record)) {
    me.onUpdate(record, type, modifiedFieldNames, info);
    me.fireEvent('update', me, record, type, modifiedFieldNames, info);
    me.fireEvent('datachanged', me);
  }
}, afterChange:function(record, modifiedFieldNames, type) {
  this.getData().itemChanged(record, modifiedFieldNames || null, undefined, type);
}, afterCommit:function(record, modifiedFieldNames) {
  this.afterChange(record, modifiedFieldNames, Ext.data.Model.COMMIT);
}, afterEdit:function(record, modifiedFieldNames) {
  this.needsSync = this.needsSync || record.dirty;
  this.afterChange(record, modifiedFieldNames, Ext.data.Model.EDIT);
}, afterReject:function(record) {
  this.afterChange(record, null, Ext.data.Model.REJECT);
}, afterDrop:function(record) {
  this.getData().remove(record);
}, afterErase:function(record) {
  this.removeFromRemoved(record);
}, addSorted:function(record) {
  var me = this, remote = me.getRemoteSort(), data = me.getData(), index;
  if (remote) {
    data.setSorters(me.getSorters());
  }
  index = data.findInsertionIndex(record);
  if (remote) {
    data.setSorters(null);
  }
  return me.insert(index, record);
}, remove:function(records, isMove, silent) {
  var me = this, data = me.getDataSource(), len, i, toRemove, record;
  if (records) {
    if (records.isModel) {
      if (data.indexOf(records) > -1) {
        toRemove = [records];
        len = 1;
      } else {
        len = 0;
      }
    } else {
      toRemove = [];
      for (i = 0, len = records.length; i < len; ++i) {
        record = records[i];
        if (record && record.isEntity) {
          if (!data.contains(record)) {
            continue;
          }
        } else {
          if (!(record = data.getAt(record))) {
            continue;
          }
        }
        toRemove.push(record);
      }
      len = toRemove.length;
    }
  }
  if (!len) {
    return [];
  }
  me.removeIsMove = isMove === true;
  me.removeIsSilent = silent;
  data.remove(toRemove);
  me.removeIsSilent = false;
  return toRemove;
}, onCollectionRemove:function(collection, info) {
  var me = this, removed = me.removed, records = info.items, len = records.length, index = info.at, replacement = info.replacement, isMove = me.removeIsMove || replacement && Ext.Array.equals(records, replacement.items), silent = me.removeIsSilent, lastChunk = !info.next, data = me.getDataSource(), i, record;
  if (me.ignoreCollectionRemove) {
    return;
  }
  if (replacement) {
    me.setMoving(replacement.items, true);
  }
  for (i = len - 1; i >= 0; i--) {
    record = records[i];
    if (!data.contains(record)) {
      if (removed && !isMove && !record.phantom && !record.erasing) {
        record.removedFrom = index + i;
        removed.push(record);
        me.needsSync = true;
      } else {
        record.unjoin(me);
      }
    }
  }
  if (!silent) {
    if (!replacement || !replacement.items.length) {
      me.fireEvent('remove', me, records, index, isMove);
      if (lastChunk) {
        me.fireEvent('datachanged', me);
      }
    }
  }
  if (replacement) {
    me.setMoving(replacement.items, false);
  }
}, onFilterEndUpdate:function() {
  var me = this;
  if (me.destroying || me.destroyed) {
    return;
  }
  if (me.activeRanges) {
    me.syncActiveRanges();
  }
  me.callParent(arguments);
  me.callObservers('Filter');
}, removeAt:function(index, count) {
  var data = this.getData();
  index = Math.max(index, 0);
  if (index < data.length) {
    if (arguments.length === 1) {
      count = 1;
    } else {
      if (!count) {
        return;
      }
    }
    data.removeAt(index, count);
  }
}, removeAll:function(silent) {
  var me = this, data = me.getData(), records = data.getRange();
  if (data.length) {
    me.removeIsSilent = true;
    me.callObservers('BeforeRemoveAll');
    data.removeAll();
    me.removeIsSilent = false;
    if (!silent) {
      me.fireEvent('clear', me, records);
      me.fireEvent('datachanged', me);
    }
    me.callObservers('AfterRemoveAll', [!!silent]);
  }
  return records;
}, setRecords:function(records) {
  var count = this.getCount();
  ++this.loadCount;
  if (count) {
    this.getData().splice(0, count, records);
  } else {
    this.add(records);
  }
}, splice:function(index, toRemove, toAdd) {
  return this.getData().splice(index, toRemove, toAdd);
}, onProxyLoad:function(operation) {
  var me = this, resultSet = operation.getResultSet(), records = operation.getRecords(), successful = operation.wasSuccessful();
  if (me.destroyed) {
    return;
  }
  if (resultSet) {
    me.totalCount = resultSet.getTotal();
  }
  if (successful) {
    records = me.processAssociation(records);
    me.loadRecords(records, operation.getAddRecords() ? {addRecords:true} : undefined);
    me.attachSummaryRecord(resultSet);
  } else {
    me.loading = false;
  }
  if (me.hasListeners.load) {
    me.fireEvent('load', me, records, successful, operation);
  }
  me.callObservers('AfterLoad', [records, successful, operation]);
}, onProxyWrite:function(operation) {
  if (operation.wasSuccessful()) {
    this.attachSummaryRecord(operation.getResultSet());
  }
  this.callParent([operation]);
}, filterDataSource:function(fn) {
  var source = this.getDataSource(), items = source.items, len = items.length, ret = [], i;
  for (i = 0; i < len; i++) {
    if (fn.call(source, items[i])) {
      ret.push(items[i]);
    }
  }
  return ret;
}, getNewRecords:function() {
  return this.filterDataSource(this.filterNew);
}, getRejectRecords:function() {
  return this.filterDataSource(this.filterRejects);
}, getUpdatedRecords:function() {
  return this.filterDataSource(this.filterUpdated);
}, loadData:function(data, append) {
  var me = this, length = data.length, newData = [], i;
  for (i = 0; i < length; i++) {
    newData.push(me.createModel(data[i]));
  }
  newData = me.processAssociation(newData);
  me.loadRecords(newData, append ? me.addRecordsOptions : undefined);
}, loadRawData:function(data, append) {
  var me = this, session = me.getSession(), result, records, success;
  result = me.getProxy().getReader().read(data, session ? {recordCreator:session.recordCreator} : undefined);
  records = result.getRecords();
  success = result.getSuccess();
  if (success) {
    me.totalCount = result.getTotal();
    me.loadRecords(records, append ? me.addRecordsOptions : undefined);
  }
  return success;
}, loadRecords:function(records, options) {
  var me = this, data = me.getData(), addRecords, skipSort;
  if (options) {
    addRecords = options.addRecords;
  }
  if (!me.getRemoteSort() && !me.getSortOnLoad()) {
    skipSort = true;
    data.setAutoSort(false);
  }
  if (!addRecords) {
    me.clearData(true);
  }
  me.loading = false;
  me.ignoreCollectionAdd = true;
  me.callObservers('BeforePopulate');
  data.add(records);
  me.ignoreCollectionAdd = false;
  if (skipSort) {
    data.setAutoSort(true);
  }
  me.afterLoadRecords(records);
}, afterLoadRecords:function(records) {
  var me = this, length = records.length, i;
  for (i = 0; i < length; i++) {
    records[i].join(me);
  }
  if (!me.isEmptyStore) {
    ++me.loadCount;
    me.complete = true;
  }
  if (me.hasListeners.datachanged) {
    me.fireEvent('datachanged', me);
  }
  if (me.hasListeners.refresh) {
    me.fireEvent('refresh', me);
  }
  me.callObservers('AfterPopulate');
}, loadPage:function(page, options) {
  var me = this, size = me.getPageSize();
  me.currentPage = page;
  options = Ext.apply({page:page, start:(page - 1) * size, limit:size, addRecords:!me.getClearOnPageLoad()}, options);
  me.read(options);
}, nextPage:function(options) {
  this.loadPage(this.currentPage + 1, options);
}, previousPage:function(options) {
  this.loadPage(this.currentPage - 1, options);
}, clearData:function(isLoad) {
  var me = this, removed = me.removed, data = me.getDataSource(), clearRemovedOnLoad = me.getClearRemovedOnLoad(), needsUnjoinCheck = removed && isLoad && !clearRemovedOnLoad, records, record, i, len;
  if (data) {
    records = data.items;
    for (i = 0, len = records.length; i < len; ++i) {
      record = records[i];
      if (needsUnjoinCheck && Ext.Array.contains(removed, record)) {
        continue;
      }
      record.unjoin(me);
    }
    me.ignoreCollectionRemove = true;
    me.callObservers('BeforeClear');
    data.removeAll();
    me.ignoreCollectionRemove = false;
    me.callObservers('AfterClear');
  }
  if (removed && (!isLoad || clearRemovedOnLoad)) {
    removed.length = 0;
  }
}, onIdChanged:function(rec, oldId, newId) {
  this.getData().updateKey(rec, oldId);
  this.fireEvent('idchanged', this, rec, oldId, newId);
}, commitChanges:function() {
  var me = this, recs = me.getModifiedRecords(), len = recs.length, i = 0;
  Ext.suspendLayouts();
  me.beginUpdate();
  for (; i < len; i++) {
    recs[i].commit();
  }
  me.cleanRemoved();
  me.endUpdate();
  Ext.resumeLayouts(true);
  me.fireEvent('commit', me);
}, filterNewOnly:function(item) {
  return item.phantom === true;
}, filterRejects:function(item) {
  return item.phantom || item.dirty;
}, rejectChanges:function() {
  var me = this, recs = me.getRejectRecords(), len = recs.length, i, rec, toRemove, sorted, data, currentAutoSort;
  Ext.suspendLayouts();
  me.beginUpdate();
  for (i = 0; i < len; i++) {
    rec = recs[i];
    if (rec.phantom) {
      toRemove = toRemove || [];
      toRemove.push(rec);
    } else {
      rec.reject();
    }
  }
  if (toRemove) {
    me.remove(toRemove);
    for (i = 0, len = toRemove.length; i < len; ++i) {
      toRemove[i].reject();
    }
  }
  recs = me.getRawRemovedRecords();
  if (recs) {
    len = recs.length;
    sorted = !me.getRemoteSort() && me.isSorted();
    if (sorted) {
      data = me.getData();
      currentAutoSort = data.getAutoSort();
      data.setAutoSort(false);
    }
    for (i = len - 1; i >= 0; i--) {
      rec = recs[i];
      rec.reject();
      if (!sorted) {
        me.insert(rec.removedFrom || 0, rec);
      }
    }
    if (sorted) {
      data.setAutoSort(currentAutoSort);
      me.add(recs);
    }
    recs.length = 0;
  }
  me.endUpdate();
  Ext.resumeLayouts(true);
  me.fireEvent('reject', me);
}, doDestroy:function() {
  var me = this, task = me.loadTask, data = me.getData(), source = data.getSource();
  me.clearData();
  me.setSession(null);
  me.observers = null;
  if (task) {
    task.cancel();
    me.loadTask = null;
  }
  if (source) {
    source.destroy();
  }
  me.callParent();
}, privates:{commitOptions:{commit:true}, attachSummaryRecord:function(resultSet) {
  if (!resultSet) {
    return;
  }
  var me = this, summary = resultSet.getSummaryData(), grouper = me.getGrouper(), current = me.summaryRecord, commitOptions = me.commitOptions, groups, len, i, rec, group;
  if (summary) {
    if (current) {
      current.set(summary.data, commitOptions);
    } else {
      me.summaryRecord = summary;
      summary.isRemote = true;
    }
  }
  if (grouper) {
    summary = resultSet.getGroupData();
    if (summary) {
      groups = me.getGroups();
      for (i = 0, len = summary.length; i < len; ++i) {
        rec = summary[i];
        group = groups.getItemGroup(rec);
        if (group) {
          current = group.summaryRecord;
          if (current) {
            current.set(rec.data, commitOptions);
          } else {
            group.summaryRecord = rec;
            rec.isRemote = true;
          }
        }
      }
    }
  }
}, fetch:function(options) {
  var operation;
  options = Ext.apply({}, options);
  this.setLoadOptions(options);
  operation = this.createOperation('read', options);
  operation.execute();
}, fireChangeEvent:function(record) {
  return this.getDataSource().contains(record);
}, onBeforeLoad:function(operation) {
  this.callObservers('BeforeLoad', [operation]);
}, onRemoteFilterSet:function(filters, remoteFilter) {
  if (filters) {
    this.getData().setFilters(remoteFilter ? null : filters);
  }
  this.callParent([filters, remoteFilter]);
}, onRemoteSortSet:function(sorters, remoteSort) {
  var data = this.getData();
  if (sorters) {
    data.setSorters(remoteSort ? null : sorters);
  }
  data.setAutoGroup(!remoteSort);
  this.callParent([sorters, remoteSort]);
}, isMoving:function(records, getMap) {
  var map = this.moveMap, moving = 0, len, i;
  if (map) {
    if (records) {
      if (Ext.isArray(records)) {
        for (i = 0, len = records.length; i < len; ++i) {
          moving += map[records[i].id] ? 1 : 0;
        }
      } else {
        if (map[records.id]) {
          ++moving;
        }
      }
    } else {
      moving = getMap ? map : this.moveMapCount;
    }
  }
  return moving;
}, setLoadOptions:function(options) {
  var me = this, pageSize = me.getPageSize(), session, grouper;
  if (me.getRemoteSort() && !options.grouper) {
    grouper = me.getGrouper();
    if (grouper) {
      options.grouper = grouper;
    }
  }
  if (pageSize || 'start' in options || 'limit' in options || 'page' in options) {
    options.page = options.page != null ? options.page : me.currentPage;
    options.start = options.start !== undefined ? options.start : (options.page - 1) * pageSize;
    options.limit = options.limit != null ? options.limit : pageSize;
    me.currentPage = options.page;
  }
  options.addRecords = options.addRecords || false;
  if (!options.recordCreator) {
    session = me.getSession();
    if (session) {
      options.recordCreator = session.recordCreator;
    }
  }
  me.callParent([options]);
}, setMoving:function(records, isMoving) {
  var me = this, map = me.moveMap || (me.moveMap = {}), len = records.length, i, id;
  for (i = 0; i < len; ++i) {
    id = records[i].id;
    if (isMoving) {
      if (map[id]) {
        ++map[id];
      } else {
        map[id] = 1;
        ++me.moveMapCount;
      }
    } else {
      if (--map[id] === 0) {
        delete map[id];
        --me.moveMapCount;
      }
    }
  }
  if (me.moveMapCount === 0) {
    me.moveMap = null;
  }
}, processAssociation:function(records) {
  var me = this, associatedEntity = me.getAssociatedEntity();
  if (associatedEntity) {
    records = me.getRole().processLoad(me, associatedEntity, records, me.getSession());
  }
  return records;
}}});
Ext.define('Ext.data.reader.Array', {extend:Ext.data.reader.Json, alternateClassName:'Ext.data.ArrayReader', alias:'reader.array', config:{totalProperty:undefined, successProperty:undefined}, createFieldAccessor:function(field) {
  var oldMap = field.mapping, index = field.hasMapping() ? oldMap : field.ordinal, result;
  field.mapping = index;
  result = this.callParent(arguments);
  field.mapping = oldMap;
  return result;
}, getModelData:function(raw) {
  return {};
}});
Ext.define('Ext.data.ArrayStore', {extend:Ext.data.Store, alias:'store.array', alternateClassName:['Ext.data.SimpleStore'], config:{proxy:{type:'memory', reader:'array'}}, loadData:function(data, append) {
  if (this.expandData) {
    var r = [], i = 0, ln = data.length;
    for (; i < ln; i++) {
      r[r.length] = [data[i]];
    }
    data = r;
  }
  this.callParent([data, append]);
}});
Ext.define('Ext.data.StoreManager', {extend:Ext.util.MixedCollection, alternateClassName:['Ext.StoreMgr', 'Ext.data.StoreMgr', 'Ext.StoreManager'], singleton:true, register:function() {
  var i, s;
  for (i = 0; s = arguments[i]; i++) {
    this.add(s);
  }
}, unregister:function() {
  var i, s;
  for (i = 0; s = arguments[i]; i++) {
    this.remove(this.lookup(s));
  }
}, lookup:function(store, defaultType) {
  var first, data, arrays, fields, i, len;
  if (Ext.isArray(store)) {
    first = store[0];
    data = store;
    if (Ext.isObject(first)) {
      store = {data:data};
    } else {
      arrays = Ext.isArray(first);
      fields = ['field1'];
      if (arrays) {
        for (i = 2, len = first.length; i <= len; ++i) {
          fields.push('field' + i);
        }
      } else {
        data = [];
        for (i = 0, len = store.length; i < len; ++i) {
          data.push([store[i]]);
        }
      }
      return new Ext.data.ArrayStore({data:data, fields:fields, autoDestroy:true, autoCreated:true, expanded:!arrays});
    }
  }
  if (Ext.isString(store)) {
    return this.get(store);
  } else {
    return Ext.Factory.store(store, defaultType);
  }
}, getKey:function(o) {
  return o.storeId;
}, addEmptyStore:function() {
  var emptyStore = this.$emptyStore, destoryable = {destroy:Ext.emptyFn};
  if (!emptyStore) {
    emptyStore = this.$emptyStore = Ext.regStore('ext-empty-store', {proxy:'memory', useModelWarning:false});
    emptyStore.ignoreLeaked = true;
    emptyStore.isEmptyStore = true;
    emptyStore.on = emptyStore.addListener = function() {
      return destoryable;
    };
    emptyStore.un = emptyStore.removeListener = Ext.emptyFn;
    emptyStore.add = emptyStore.remove = emptyStore.insert = emptyStore.destroy = emptyStore.loadData = function() {
      Ext.raise('Cannot modify ext-empty-store');
    };
  }
  this.add(emptyStore);
}, clear:function() {
  this.callParent();
  this.addEmptyStore();
}}, function() {
  Ext.regStore = function(id, config) {
    var store;
    if (Ext.isObject(id)) {
      config = id;
    } else {
      if (Ext.data.StoreManager.containsKey(id)) {
        return Ext.data.StoreManager.lookup(id);
      }
      config.storeId = id;
    }
    if (config instanceof Ext.data.Store) {
      store = config;
    } else {
      store = new Ext.data.Store(config);
    }
    Ext.data.StoreManager.register(store);
    return store;
  };
  Ext.getStore = function(name) {
    return Ext.data.StoreManager.lookup(name);
  };
  Ext.data.StoreManager.addEmptyStore();
});
Ext.define('Ext.app.domain.Store', {extend:Ext.app.EventDomain, singleton:true, type:'store', prefix:'store.', idMatchRe:/^#/, constructor:function() {
  var me = this;
  me.callParent();
  me.monitor(Ext.data.AbstractStore);
}, match:function(target, selector) {
  var result = false, alias = target.alias;
  if (selector === '*') {
    result = true;
  } else {
    if (this.idMatchRe.test(selector)) {
      result = target.getStoreId() === selector.substring(1);
    } else {
      if (alias) {
        result = Ext.Array.indexOf(alias, this.prefix + selector) > -1;
      }
    }
  }
  return result;
}});
Ext.define('Ext.app.Controller', {extend:Ext.app.BaseController, statics:{strings:{model:{getter:'getModel', upper:'Model'}, view:{getter:'getView', upper:'View'}, controller:{getter:'getController', upper:'Controller'}, store:{getter:'getStore', upper:'Store'}, profile:{getter:'getProfile', upper:'Profiles'}}, controllerRegex:/^(.*)\.controller\./, profileRegex:/^(.*)\.profile\./, createGetter:function(baseGetter, name) {
  return function() {
    return this[baseGetter](name);
  };
}, getGetterName:function(name, kindUpper) {
  var fn = 'get', parts = name.split('.'), numParts = parts.length, index;
  for (index = 0; index < numParts; index++) {
    fn += Ext.String.capitalize(parts[index]);
  }
  fn += kindUpper;
  return fn;
}, resolveNamespace:function(cls, data) {
  var Controller = Ext.app.Controller, namespaceRe, className, namespace, match;
  namespaceRe = cls.prototype.isProfile ? Controller.profileRegex : Controller.controllerRegex;
  className = Ext.getClassName(cls);
  namespace = data.$namespace || data.namespace || Ext.app.getNamespace(className) || (match = namespaceRe.exec(className)) && match[1];
  if (!namespace) {
    Ext.log.warn('Missing namespace for ' + className + ', please define it ' + 'in namespaces property of your Application class.');
  }
  return namespace;
}, processDependencies:function(cls, requires, namespace, kind, names, profileName) {
  if (!names || !names.length) {
    return;
  }
  var me = this, strings = me.strings[kind], o, absoluteName, shortName, name, j, subLn, getterName, getter;
  if (!Ext.isArray(names)) {
    names = [names];
  }
  for (j = 0, subLn = names.length; j < subLn; j++) {
    name = names[j];
    o = me.getFullName(name, kind, namespace, profileName);
    names[j] = absoluteName = o.absoluteName;
    shortName = o.shortName;
    requires.push(absoluteName);
    getterName = me.getGetterName(shortName, strings.upper);
    if (!cls[getterName]) {
      cls[getterName] = getter = me.createGetter(strings.getter, name);
    } else {
      if (getterName === 'getMainView') {
        Ext.log.warn("Cannot have a view named 'Main' - getter conflicts " + 'with mainView config.');
      }
    }
    if (getter && kind !== 'controller') {
      getter['Ext.app.getter'] = true;
    }
  }
}, getFullName:function(name, kind, namespace, profileName) {
  var shortName = name, sep, absoluteName;
  if ((sep = name.indexOf('@')) > 0) {
    shortName = name.substring(0, sep);
    absoluteName = name.substring(sep + 1) + '.' + shortName;
  } else {
    if (name.indexOf('.') > 0 && (Ext.ClassManager.isCreated(name) || this.hasRegisteredPrefix(name))) {
      absoluteName = name;
      shortName = name.replace(namespace + '.' + kind + '.', '');
    } else {
      if (!namespace) {
        Ext.log.warn('Cannot find namespace for ' + kind + ' ' + name + ', ' + 'assuming it is fully qualified class name');
      }
      if (namespace) {
        absoluteName = namespace + '.' + kind + '.' + (profileName ? profileName + '.' + name : name);
        shortName = name;
      } else {
        absoluteName = name;
      }
    }
  }
  return {absoluteName:absoluteName, shortName:shortName};
}, hasRegisteredPrefix:function(className) {
  var inventory = Ext.ClassManager, prefix = inventory.getPrefix(className);
  return prefix && prefix !== className;
}}, models:null, views:null, stores:null, controllers:null, config:{application:null, refs:null, active:true, moduleClassName:null}, onClassExtended:function(cls, data, hooks) {
  var onBeforeClassCreated = hooks.onBeforeCreated;
  hooks.onBeforeCreated = function(cls, data) {
    var Controller = Ext.app.Controller, requires = [], namespace, proto;
    proto = cls.prototype;
    namespace = Controller.resolveNamespace(cls, data);
    if (namespace) {
      proto.$namespace = namespace;
    }
    Controller.processDependencies(proto, requires, namespace, 'model', data.models);
    Controller.processDependencies(proto, requires, namespace, 'view', data.views);
    Controller.processDependencies(proto, requires, namespace, 'store', data.stores);
    Controller.processDependencies(proto, requires, namespace, 'controller', data.controllers);
    Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this));
  };
}, constructor:function(config) {
  this.initAutoGetters();
  this.callParent([config]);
}, normalizeRefs:function(refs) {
  var me = this, newRefs = [];
  if (refs) {
    if (Ext.isObject(refs)) {
      Ext.Object.each(refs, function(key, value) {
        if (Ext.isString(value)) {
          value = {selector:value};
        }
        value.ref = key;
        newRefs.push(value);
      });
    } else {
      if (Ext.isArray(refs)) {
        newRefs = Ext.Array.merge(newRefs, refs);
      }
    }
  }
  refs = me.refs;
  if (refs) {
    me.refs = null;
    refs = me.normalizeRefs(refs);
    if (refs) {
      newRefs = Ext.Array.merge(newRefs, refs);
    }
  }
  return newRefs;
}, getRefMap:function() {
  var me = this, refMap = me._refMap, refs, ref, ln, i;
  if (!refMap) {
    refs = me.getRefs();
    refMap = me._refMap = {};
    if (refs) {
      for (i = 0, ln = refs.length; i < ln; i++) {
        ref = refs[i];
        refMap[ref.ref] = ref.selector;
      }
    }
  }
  return refMap;
}, applyId:function(id) {
  return id || Ext.app.Controller.getFullName(this.$className, 'controller', this.$namespace).shortName;
}, applyRefs:function(refs) {
  return this.normalizeRefs(Ext.clone(refs));
}, updateRefs:function(refs) {
  if (refs) {
    this.ref(refs);
  }
}, initAutoGetters:function() {
  var proto = this.self.prototype, prop, fn;
  for (prop in proto) {
    fn = proto[prop];
    if (fn && fn['Ext.app.getter']) {
      fn.call(this);
    }
  }
}, doInit:function(app) {
  var me = this;
  if (!me._initialized) {
    me.init(app);
    me._initialized = true;
  }
}, finishInit:function(app) {
  var me = this, controllers = me.controllers, controller, i, l;
  if (me._initialized && controllers && controllers.length) {
    for (i = 0, l = controllers.length; i < l; i++) {
      controller = me.getController(controllers[i]);
      controller.finishInit(app);
    }
  }
}, init:Ext.emptyFn, onLaunch:Ext.emptyFn, activate:function() {
  this.setActive(true);
}, deactivate:function() {
  this.setActive(false);
}, isActive:function() {
  return this.getActive();
}, ref:function(refs) {
  var me = this, i = 0, length = refs.length, info, ref, fn;
  refs = Ext.Array.from(refs);
  me.references = me.references || [];
  for (; i < length; i++) {
    info = refs[i];
    ref = info.ref;
    fn = 'get' + Ext.String.capitalize(ref);
    if (!me[fn]) {
      me[fn] = Ext.Function.pass(me.getRef, [ref, info], me);
    }
    me.references.push(ref.toLowerCase());
  }
}, addRef:function(refs) {
  this.ref(refs);
}, getRef:function(ref, info, config) {
  var me = this, refCache = me.refCache || (me.refCache = {}), cached = refCache[ref];
  info = info || {};
  config = config || {};
  Ext.apply(info, config);
  if (info.forceCreate) {
    return Ext.ComponentManager.create(info, 'component');
  }
  if (!cached) {
    if (info.selector) {
      refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0];
    }
    if (!cached && info.autoCreate) {
      refCache[ref] = cached = Ext.ComponentManager.create(info, 'component');
    }
    if (cached) {
      cached.on('destroy', function() {
        refCache[ref] = null;
      });
    }
  }
  return cached;
}, hasRef:function(ref) {
  var references = this.references;
  return references && Ext.Array.indexOf(references, ref.toLowerCase()) !== -1;
}, getController:function(id) {
  var app = this.getApplication();
  if (id === this.getId()) {
    return this;
  }
  return app && app.getController(id);
}, getStore:function(name) {
  var storeId, store;
  storeId = name.indexOf('@') === -1 ? name : name.split('@')[0];
  store = Ext.StoreManager.get(storeId);
  if (!store) {
    name = Ext.app.Controller.getFullName(name, 'store', this.$namespace);
    if (name) {
      store = Ext.create(name.absoluteName, {id:storeId});
    }
  }
  return store;
}, getModel:function(modelName) {
  var name = Ext.app.Controller.getFullName(modelName, 'model', this.$namespace), ret = Ext.ClassManager.get(name.absoluteName);
  if (!ret) {
    ret = Ext.data.schema.Schema.lookupEntity(modelName);
  }
  return ret;
}, getProfile:function(name) {
  name = Ext.app.Controller.getFullName(name, 'profile', this.$namespace);
  return name;
}, getView:function(view) {
  var name = Ext.app.Controller.getFullName(view, 'view', this.$namespace);
  return name && Ext.ClassManager.get(name.absoluteName);
}, destroy:function(destroyRefs, fromApp) {
  var me = this, app = me.application, refCache, ref;
  if (!fromApp && app) {
    app.unregister(me);
  }
  me.application = null;
  if (destroyRefs) {
    refCache = me.refCache;
    for (ref in refCache) {
      if (refCache.hasOwnProperty(ref)) {
        Ext.destroy(refCache[ref]);
      }
    }
  }
  me.callParent();
}});
Ext.define('Ext.app.Application', {extend:Ext.app.Controller, isApplication:true, scope:undefined, namespaces:[], paths:null, config:{name:'', appProperty:'app', profiles:[], currentProfile:null, mainView:{$value:null, lazy:true}, defaultToken:null, glyphFontFamily:null, quickTips:true, router:null}, onClassExtended:function(cls, data, hooks) {
  var Controller = Ext.app.Controller, proto = cls.prototype, requires = [], onBeforeClassCreated, namespace;
  namespace = data.name || cls.superclass.name;
  if (namespace) {
    data.$namespace = namespace;
    Ext.app.addNamespaces(namespace);
  }
  if (data.namespaces) {
    Ext.app.addNamespaces(data.namespaces);
  }
  if (data['paths processed']) {
    delete data['paths processed'];
  } else {
    Ext.app.setupPaths(namespace, 'appFolder' in data ? data.appFolder : cls.superclass.appFolder, data.paths);
  }
  Controller.processDependencies(proto, requires, namespace, 'profile', data.profiles);
  proto.getDependencies(cls, data, requires);
  if (requires.length) {
    onBeforeClassCreated = hooks.onBeforeCreated;
    hooks.onBeforeCreated = function(cls, data) {
      var args = Ext.Array.clone(arguments);
      if (data.__handleRequires) {
        data.__handleRequires.call(this, requires, Ext.bind(function() {
          return onBeforeClassCreated.apply(this, args);
        }, this));
        return;
      }
      Ext.require(requires, function() {
        return onBeforeClassCreated.apply(this, args);
      });
    };
  }
}, getDependencies:Ext.emptyFn, constructor:function(config) {
  var me = this, App = Ext.app.Application;
  Ext.route.Router.application = me;
  if (!App.instance) {
    App.instance = me;
  }
  me.callParent([config]);
  if (Ext.isEmpty(me.getName())) {
    Ext.raise('[Ext.app.Application] Name property is required');
  }
  me.doInit(me);
  Ext.on('appupdate', me.onAppUpdate, me, {single:true});
  Ext.Loader.setConfig({enabled:true});
  this.onProfilesReady();
}, applyId:function(id) {
  return id || this.$className;
}, updateRouter:function(cfg) {
  if (cfg) {
    Ext.route.Router.setConfig(cfg);
  }
}, onAppUpdate:Ext.emptyFn, onProfilesReady:function() {
  var me = this, profiles = me.getProfiles(), length = profiles.length, current, i, instance;
  for (i = 0; i < length; i++) {
    instance = Ext.create(profiles[i], {application:me});
    if (instance.isActive() && !current) {
      current = instance;
      me.setCurrentProfile(current);
    }
  }
  if (current) {
    current.init();
  }
  me.initControllers();
  me.onBeforeLaunch();
  me.finishInitControllers();
  Ext.fireEvent('applaunch', me);
}, doInit:function(app) {
  this.initNamespace(app);
  this.callParent([app]);
}, initNamespace:function(me) {
  var appProperty = me.getAppProperty(), ns = Ext.namespace(me.getName());
  if (ns) {
    ns.getApplication = function() {
      return me;
    };
    if (appProperty) {
      if (!ns[appProperty]) {
        ns[appProperty] = me;
      } else {
        if (ns[appProperty] !== me) {
          Ext.log.warn('An existing reference is being overwritten for ' + name + '.' + appProperty + '. See the appProperty config.');
        }
      }
    }
  }
}, initControllers:function() {
  var me = this, controllers = Ext.Array.from(me.controllers), profile = me.getCurrentProfile(), i, ln;
  me.controllers = new Ext.util.MixedCollection;
  for (i = 0, ln = controllers.length; i < ln; i++) {
    me.getController(controllers[i]);
  }
  if (profile) {
    controllers = profile.getControllers();
    for (i = 0, ln = controllers.length; i < ln; i++) {
      me.getController(controllers[i]);
    }
  }
}, finishInitControllers:function() {
  var me = this, controllers, i, l;
  controllers = me.controllers.getRange();
  for (i = 0, l = controllers.length; i < l; i++) {
    controllers[i].finishInit(me);
  }
}, launch:Ext.emptyFn, onBeforeLaunch:function() {
  var me = this, History = Ext.util.History, defaultToken = me.getDefaultToken(), currentProfile = me.getCurrentProfile(), controllers, c, cLen, controller, token;
  me.initMainView();
  if (currentProfile) {
    currentProfile.launch();
  }
  me.launch.call(me.scope || me);
  me.launched = true;
  me.fireEvent('launch', me);
  controllers = me.controllers.items;
  cLen = controllers.length;
  for (c = 0; c < cLen; c++) {
    controller = controllers[c];
    controller.onLaunch(me);
  }
  if (!History.ready) {
    History.init();
  }
  token = History.getToken();
  if (token || token === defaultToken) {
    Ext.route.Router.onStateChange(token);
  } else {
    if (defaultToken) {
      History.replace(defaultToken);
    }
  }
  if (Ext.Microloader && Ext.Microloader.appUpdate && Ext.Microloader.appUpdate.updated) {
    Ext.Microloader.fireAppUpdate();
  }
  if (!me.cnsTimer) {
    me.cnsTimer = Ext.defer(Ext.ClassManager.clearNamespaceCache, 2000, Ext.ClassManager);
  }
}, getModuleClassName:function(name, kind) {
  return Ext.app.Controller.getFullName(name, kind, this.getName()).absoluteName;
}, initMainView:function() {
  var me = this, currentProfile = me.getCurrentProfile(), mainView;
  if (currentProfile) {
    mainView = currentProfile.getMainView();
  }
  if (mainView) {
    me.setMainView(mainView);
  } else {
    me.getMainView();
  }
}, applyMainView:function(value) {
  var view = this.getView(value);
  return view.create({$initParent:this.viewport});
}, createController:function(name) {
  return this.getController(name);
}, destroyController:function(controller) {
  if (typeof controller === 'string') {
    controller = this.getController(controller, true);
  }
  Ext.destroy(controller);
}, getController:function(name, preventCreate) {
  var me = this, controllers = me.controllers, className, controller, len, i, c, all;
  controller = controllers.get(name);
  if (!controller) {
    all = controllers.items;
    for (i = 0, len = all.length; i < len; ++i) {
      c = all[i];
      className = c.getModuleClassName();
      if (className && className === name) {
        controller = c;
        break;
      }
    }
  }
  if (!controller && !preventCreate) {
    className = me.getModuleClassName(name, 'controller');
    controller = Ext.create(className, {application:me, moduleClassName:className});
    controllers.add(controller);
    if (me._initialized) {
      controller.doInit(me);
    }
  }
  return controller;
}, unregister:function(controller) {
  this.controllers.remove(controller);
}, getApplication:function() {
  return this;
}, destroy:function(destroyRefs) {
  var me = this, controllers = me.controllers, ns = Ext.namespace(me.getName()), appProp = me.getAppProperty();
  Ext.undefer(me.cnsTimer);
  Ext.un('appupdate', me.onAppUpdate, me);
  Ext.destroy(me.viewport);
  if (controllers) {
    controllers.each(function(controller) {
      controller.destroy(destroyRefs, true);
    });
  }
  me.controllers = null;
  me.callParent([destroyRefs, true]);
  if (ns && ns[appProp] === me) {
    delete ns[appProp];
  }
  if (Ext.route.Router.application === me) {
    Ext.route.Router.application = null;
  }
  if (Ext.app.Application.instance === me) {
    Ext.app.Application.instance = null;
  }
}, updateGlyphFontFamily:function(fontFamily) {
  Ext.setGlyphFontFamily(fontFamily);
}, applyProfiles:function(profiles) {
  var me = this;
  return Ext.Array.map(profiles, function(profile) {
    return me.getModuleClassName(profile, 'profile');
  });
}}, function() {
  Ext.getApplication = function() {
    return Ext.app.Application.instance;
  };
});
Ext.application = function(config) {
  var createApp = function(App) {
    Ext.onReady(function() {
      var Viewport = Ext.viewport;
      Viewport = Viewport && Viewport['Viewport'];
      if (Viewport && Viewport.setup) {
        Viewport.setup(App.prototype.config.viewport);
      }
      Ext.app.Application.instance = new App;
    });
  };
  if (typeof config === 'string') {
    Ext.require(config, function() {
      createApp(Ext.ClassManager.get(config));
    });
  } else {
    config = Ext.apply({extend:'Ext.app.Application'}, config);
    Ext.app.setupPaths(config.name, config.appFolder, config.paths);
    config['paths processed'] = true;
    Ext.define(config.name + '.$application', config, function() {
      createApp(this);
    });
  }
};
Ext.define('Ext.util.ItemCollection', {extend:Ext.util.MixedCollection, alternateClassName:'Ext.ItemCollection', getKey:function(item) {
  return item.getItemId && item.getItemId();
}, has:function(item) {
  return this.map.hasOwnProperty(item.getId());
}});
Ext.define('Ext.mixin.Queryable', {mixinId:'queryable', isQueryable:true, query:function(selector) {
  selector = selector || '*';
  return Ext.ComponentQuery.query(selector, this.getQueryRoot());
}, queryBy:function(fn, scope) {
  var out = [], items = this.getQueryRoot().getRefItems(true), i = 0, len = items.length, item;
  for (; i < len; ++i) {
    item = items[i];
    if (fn.call(scope || item, item) !== false) {
      out.push(item);
    }
  }
  return out;
}, queryById:function(id) {
  return this.down(Ext.makeIdSelector(id));
}, child:function(selector) {
  var children = this.getQueryRoot().getRefItems();
  if (selector && selector.isComponent) {
    return this.matchById(children, selector.getItemId());
  }
  if (selector) {
    children = Ext.ComponentQuery.query(selector, children);
  }
  if (children.length) {
    return children[0];
  }
  return null;
}, down:function(selector) {
  if (selector && selector.isComponent) {
    return this.matchById(this.getRefItems(true), selector.getItemId());
  }
  selector = selector || '';
  return this.query(selector)[0] || null;
}, visitPreOrder:function(selector, fn, scope, extraArgs) {
  Ext.ComponentQuery._visit(true, selector, this.getQueryRoot(), fn, scope, extraArgs);
}, visitPostOrder:function(selector, fn, scope, extraArgs) {
  Ext.ComponentQuery._visit(false, selector, this.getQueryRoot(), fn, scope, extraArgs);
}, getRefItems:function() {
  return [];
}, getQueryRoot:function() {
  return this;
}, privates:{matchById:function(items, id) {
  var len = items.length, i, item;
  for (i = 0; i < len; ++i) {
    item = items[i];
    if (item.getItemId() === id) {
      return item;
    }
  }
  return null;
}}});
Ext.define('Ext.mixin.Container', {extend:Ext.Mixin, mixinConfig:{id:'container'}, isContainer:true, nameHolder:false, referenceHolder:false, getNamedItems:function() {
  if (Ext.referencesDirty) {
    Ext.fixReferences();
  }
  return this.nameRefs || null;
}, getReferences:function() {
  if (Ext.referencesDirty) {
    Ext.fixReferences();
  }
  return this.refs || null;
}, lookup:function(ref) {
  var refs = this.getReferences();
  return refs && refs[ref] || null;
}, lookupName:function(name) {
  var items = this.getNamedItems();
  return items && items[name] || null;
}, lookupReference:function(ref) {
  return this.lookup(ref);
}, privates:{attachNameRef:function(component) {
  var me = this, key = component.name || component._name, entry, nameRefs;
  if (key && !me.destroying && !me.destroyed) {
    nameRefs = me.nameRefs || (me.nameRefs = {});
    entry = nameRefs[key];
    if (!entry) {
      entry = component.shareableName ? [component] : component;
    } else {
      if (!entry.isInstance) {
        entry.push(component);
      } else {
        Ext.raise('Duplicate name: "' + key + '" on ' + me.id + ' between ' + entry.id + ' and ' + component.id);
      }
    }
    nameRefs[key] = entry;
  }
}, attachReference:function(component) {
  var me = this, key, refs;
  if (!me.destroying && !me.destroyed) {
    refs = me.refs || (me.refs = {});
    key = component.referenceKey;
    if (refs[key] && refs[key] !== component) {
      Ext.log.warn('Duplicate reference: "' + key + '" on ' + me.id);
    }
    refs[key] = component;
  }
}, containerOnAdded:function(component, instanced) {
  Ext.ComponentManager.markReferencesDirty();
}, containerOnRemoved:function(destroying) {
  if (!destroying) {
    Ext.ComponentManager.markReferencesDirty();
  }
}, initContainerInheritedState:function(inheritedState, inheritedStateInner) {
  var me = this, controller = me.getController(), session = me.getSession(), viewModel = me.getConfig('viewModel', true), reference = me.reference, referenceHolder = me.referenceHolder;
  if (me.nameHolder) {
    inheritedState.nameHolder = me;
  }
  if (controller) {
    inheritedState.referenceHolder = controller;
    referenceHolder = true;
  } else {
    if (referenceHolder) {
      inheritedState.referenceHolder = me;
    }
  }
  if (referenceHolder) {
    inheritedState.referencePath = '';
  } else {
    if (reference && me.isParentReference) {
      inheritedState.referencePath = me.referenceKey + '.';
    }
  }
  if (session) {
    inheritedState.session = session;
  }
  if (viewModel) {
    inheritedState.viewModelPath = '';
  } else {
    if (reference && me.isParentReference) {
      inheritedState.viewModelPath = me.viewModelKey + '.';
    }
  }
}, setupReference:function(reference) {
  var len;
  if (reference && reference.charAt(len = reference.length - 1) === '\x3e') {
    this.isParentReference = true;
    reference = reference.substring(0, len);
  }
  if (reference && !Ext.validIdRe.test(reference)) {
    Ext.Error.raise('Invalid reference "' + reference + '" for ' + this.getId() + ' - not a valid identifier');
  }
  return reference;
}}});
Ext.define('Ext.util.KeyMap', {alternateClassName:'Ext.KeyMap', eventName:'keydown', constructor:function(config) {
  var me = this;
  if (arguments.length !== 1 || typeof config === 'string' || config.dom || config.tagName || config === document || config.isComponent) {
    Ext.raise('Legacy multi-argument KeyMap constructor is removed. ' + 'Use a config object instead.');
  }
  Ext.apply(me, config);
  me.bindings = [];
  if (!me.target.isComponent) {
    me.target = Ext.get(me.target);
  }
  if (me.binding) {
    me.addBinding(me.binding);
  } else {
    if (config.key) {
      me.addBinding(config);
    }
  }
  me.enable();
}, addBinding:function(binding) {
  var me = this, keyCode = binding.key, i, len;
  if (me.processing) {
    me.bindings = me.bindings.slice(0);
  }
  if (Ext.isArray(binding)) {
    for (i = 0, len = binding.length; i < len; i++) {
      me.addBinding(binding[i]);
    }
    return;
  }
  me.bindings.push(Ext.apply({keyCode:me.processKeys(keyCode)}, binding));
}, removeBinding:function(binding) {
  var me = this, bindings = me.bindings, len = bindings.length, i, item, keys;
  if (me.processing) {
    me.bindings = bindings.slice(0);
  }
  keys = me.processKeys(binding.key);
  for (i = 0; i < len; i++) {
    item = bindings[i];
    if ((item.fn || item.handler) === (binding.fn || binding.handler) && item.scope === binding.scope) {
      if (binding.alt === item.alt && binding.ctrl === item.ctrl && binding.shift === item.shift) {
        if (Ext.Array.equals(item.keyCode, keys)) {
          Ext.Array.erase(me.bindings, i, 1);
          return;
        }
      }
    }
  }
}, processKeys:function(keyCode) {
  var processed = false, key, keys, keyString, len, i;
  if (keyCode.test) {
    return keyCode;
  }
  if (Ext.isString(keyCode)) {
    keys = [];
    keyString = keyCode.toUpperCase();
    for (i = 0, len = keyString.length; i < len; i++) {
      keys.push(keyString.charCodeAt(i));
    }
    keyCode = keys;
    processed = true;
  }
  if (!Ext.isArray(keyCode)) {
    keyCode = [keyCode];
  }
  if (!processed) {
    for (i = 0, len = keyCode.length; i < len; i++) {
      key = keyCode[i];
      if (Ext.isString(key)) {
        keyCode[i] = key.toUpperCase().charCodeAt(0);
      }
    }
  }
  return keyCode;
}, handleTargetEvent:function(event) {
  var me = this, bindings, i, len, result;
  if (me.enabled) {
    bindings = me.bindings;
    event = me.processEvent.apply(me.processEventScope || me, arguments);
    if (event) {
      me.lastKeyEvent = event;
      if (me.ignoreInputFields && Ext.fly(event.target).isInputField()) {
        return;
      }
      if (!event.getKey) {
        return event;
      }
      me.processing = true;
      for (i = 0, len = bindings.length; i < len; i++) {
        result = me.processBinding(bindings[i], event);
        if (result === false) {
          me.processing = false;
          return result;
        }
      }
      me.processing = false;
    }
  }
}, processEvent:Ext.identityFn, processBinding:function(binding, event) {
  if (this.checkModifiers(binding, event)) {
    var key = event.getKey(), handler = binding.fn || binding.handler, scope = binding.scope || this, keyCode = binding.keyCode, defaultEventAction = binding.defaultEventAction, i, len, result;
    if (keyCode.test) {
      if (keyCode.test(String.fromCharCode(event.getCharCode()))) {
        result = handler.call(scope, key, event);
        if (result !== true && defaultEventAction) {
          event[defaultEventAction]();
        }
        if (result === false) {
          return result;
        }
      }
    } else {
      if (keyCode.length) {
        for (i = 0, len = keyCode.length; i < len; i++) {
          if (key === keyCode[i]) {
            result = handler.call(scope, key, event);
            if (result !== true && defaultEventAction) {
              event[defaultEventAction]();
            }
            if (result === false) {
              return result;
            }
            break;
          }
        }
      }
    }
  }
}, checkModifiers:function(binding, event) {
  var keys = ['shift', 'ctrl', 'alt'], i, len, val, key;
  for (i = 0, len = keys.length; i < len; i++) {
    key = keys[i];
    val = binding[key];
    if (!(val === undefined || val === event[key + 'Key'])) {
      return false;
    }
  }
  return true;
}, on:function(key, fn, scope) {
  var keyCode, shift, ctrl, alt;
  if (Ext.isObject(key) && !Ext.isArray(key)) {
    keyCode = key.key;
    shift = key.shift;
    ctrl = key.ctrl;
    alt = key.alt;
  } else {
    keyCode = key;
  }
  this.addBinding({key:keyCode, shift:shift, ctrl:ctrl, alt:alt, fn:fn, scope:scope});
}, un:function(key, fn, scope) {
  var keyCode, shift, ctrl, alt;
  if (Ext.isObject(key) && !Ext.isArray(key)) {
    keyCode = key.key;
    shift = key.shift;
    ctrl = key.ctrl;
    alt = key.alt;
  } else {
    keyCode = key;
  }
  this.removeBinding({key:keyCode, shift:shift, ctrl:ctrl, alt:alt, fn:fn, scope:scope});
}, isEnabled:function() {
  return !!this.enabled;
}, enable:function() {
  var me = this;
  if (!me.enabled) {
    me.target.on(me.eventName, me.handleTargetEvent, me, {capture:me.capture, priority:me.priority});
    me.enabled = true;
  }
}, disable:function() {
  var me = this;
  if (me.enabled) {
    if (!me.target.destroyed) {
      me.target.removeListener(me.eventName, me.handleTargetEvent, me);
    }
    me.enabled = false;
  }
}, setDisabled:function(disabled) {
  if (disabled) {
    this.disable();
  } else {
    this.enable();
  }
}, destroy:function(removeTarget) {
  var me = this, target = me.target;
  me.bindings = [];
  me.disable();
  me.target = null;
  if (removeTarget) {
    target.destroy();
    Ext.raise('Using removeTarget argument in KeyMap destructor is not supported.');
  }
  me.callParent();
}});
Ext.define('Ext.util.KeyNav', {alternateClassName:'Ext.KeyNav', disabled:false, defaultEventAction:false, forceKeyDown:false, eventName:'keypress', statics:{keyOptions:{left:37, right:39, up:38, down:40, space:32, pageUp:33, pageDown:34, del:46, backspace:8, home:36, end:35, enter:13, esc:27, tab:9}}, constructor:function(config) {
  var me = this, keymapCfg, map;
  if (arguments.length === 2) {
    Ext.raise('2-argument KeyNav constructor is removed. Use a config object instead.');
  }
  config = config || {};
  keymapCfg = {target:config.target, ignoreInputFields:config.ignoreInputFields, eventName:me.getKeyEvent('forceKeyDown' in config ? config.forceKeyDown : me.forceKeyDown, config.eventName), capture:config.capture};
  if (me.map) {
    me.map.destroy();
  }
  me.initConfig(config);
  if (config.processEvent) {
    keymapCfg.processEvent = config.processEvent;
    keymapCfg.processEventScope = config.processEventScope || me;
  }
  if (config.priority) {
    keymapCfg.priority = config.priority;
  }
  if (config.keyMap) {
    map = me.map = config.keyMap;
  } else {
    map = me.map = new Ext.util.KeyMap(keymapCfg);
    me.destroyKeyMap = true;
  }
  me.addBindings(config);
  map.disable();
  if (!config.disabled) {
    map.enable();
  }
}, addBindings:function(bindings) {
  var me = this, map = me.map, keyCodes = Ext.util.KeyNav.keyOptions, Event = Ext.event.Event, defaultScope = bindings.scope || me, binding, keyName, keyCode;
  for (keyName in bindings) {
    binding = bindings[keyName];
    keyCode = keyName.length === 1 ? keyName.charCodeAt(0) : keyCodes[keyName] || Event[keyName.toUpperCase()];
    if (keyCode != null) {
      keyName = keyCode;
    }
    if (binding && (keyName.length === 1 || !isNaN(keyName = parseInt(keyName, 10)))) {
      if (typeof binding === 'function') {
        binding = {handler:binding, defaultEventAction:bindings.defaultEventAction !== undefined ? bindings.defaultEventAction : me.defaultEventAction};
      }
      map.addBinding({key:keyName, ctrl:binding.ctrl, shift:binding.shift, alt:binding.alt, handler:Ext.Function.bind(me.handleEvent, binding.scope || defaultScope, [binding.handler || binding.fn, me], true), defaultEventAction:binding.defaultEventAction !== undefined ? binding.defaultEventAction : me.defaultEventAction});
    }
  }
}, handleEvent:function(keyCode, event, handler, keyNav) {
  keyNav.lastKeyEvent = event;
  return handler.call(this, event);
}, destroy:function(removeEl) {
  var me = this;
  if (removeEl) {
    Ext.raise('removeEl argument in KeyNav destructor is not supported anymore.');
  }
  if (me.destroyKeyMap) {
    me.map.destroy(removeEl);
  }
  me.map = null;
  me.callParent();
}, enable:function() {
  if (this.map) {
    this.map.enable();
    this.disabled = false;
  }
}, disable:function() {
  if (this.map) {
    this.map.disable();
  }
  this.disabled = true;
}, setDisabled:function(disabled) {
  this.map.setDisabled(disabled);
  this.disabled = disabled;
}, isEnabled:function() {
  return !this.disabled;
}, getKeyEvent:function(forceKeyDown, configuredEventName) {
  if (forceKeyDown || Ext.supports.SpecialKeyDownRepeat && !configuredEventName) {
    return 'keydown';
  } else {
    return configuredEventName || this.eventName;
  }
}});
Ext.define('Ext.mixin.FocusableContainer', {extend:Ext.Mixin, mixinConfig:{id:'focusablecontainer'}, isFocusableContainer:true, focusableContainer:false, resetFocusPosition:false, activeChildTabIndex:0, inactiveChildTabIndex:-1, allowFocusingDisabledChildren:false, focusableContainerEl:'el', privates:{initFocusableContainer:function(clearChildren) {
  var items, i, len;
  if (this.focusableContainer) {
    clearChildren = clearChildren != null ? clearChildren : true;
    this.doInitFocusableContainer(clearChildren);
  } else {
    items = this.getFocusables();
    for (i = 0, len = items.length; i < len; i++) {
      items[i].ownerFocusableContainer = null;
    }
  }
}, doInitFocusableContainer:function(clearChildren) {
  var me = this, el = me.focusableContainerEl, child;
  if (!el.isElement) {
    el = me.focusableContainerEl = me[el];
  }
  if (me.initFocusableContainerKeyNav) {
    me.initFocusableContainerKeyNav(el);
  }
  if (clearChildren) {
    me.clearFocusables();
    if (!me.isDisabled()) {
      child = me.findNextFocusableChild({step:1}) || me.findNextFocusableChild({beforeRender:true});
      if (child) {
        me.activateFocusable(child);
      }
    }
  }
  child = me.findNextFocusableChild({firstTabbable:true});
  me.activateFocusableContainer(!!child && !me.isDisabled());
}, initFocusableContainerKeyNav:function(el) {
  var me = this;
  if (!me.focusableKeyNav) {
    el = el || me.focusableContainerEl;
    me.focusableKeyNav = new Ext.util.KeyNav({target:el, disabled:true, eventName:'keydown', processEvent:me.processFocusableContainerKeyEvent, processEventScope:me, scope:me, tab:me.onFocusableContainerTabKey, enter:{handler:me.onFocusableContainerEnterKey, ctrl:false, shift:false, alt:false}, space:{handler:me.onFocusableContainerSpaceKey, ctrl:false, shift:false, alt:false}, up:{handler:me.onFocusableContainerUpKey, ctrl:false, shift:false, alt:false}, down:{handler:me.onFocusableContainerDownKey, 
    ctrl:false, shift:false, alt:false}, left:{handler:me.onFocusableContainerLeftKey, ctrl:false, shift:false, alt:false}, right:{handler:me.onFocusableContainerRightKey, ctrl:false, shift:false, alt:false}});
  }
}, destroyFocusableContainer:function() {
  this.focusableKeyNav = Ext.destroy(this.focusableKeyNav);
}, activateFocusableContainer:function(enable) {
  var keyNav = this.focusableKeyNav;
  if (keyNav) {
    keyNav.setDisabled(!enable);
  }
}, isFocusableContainerActive:function() {
  var keyNav = this.focusableKeyNav;
  return keyNav ? !keyNav.disabled : false;
}, getFocusables:function() {
  return this.items.items;
}, initDefaultFocusable:function() {
  var me = this, haveFocusable = false, items, item, i, len;
  items = me.getFocusables();
  len = items.length;
  if (!len) {
    return;
  }
  for (i = 0; i < len; i++) {
    item = items[i];
    if (!item.isDisabled() && item.isFocusable()) {
      haveFocusable = true;
      break;
    }
  }
  if (!haveFocusable) {
    return;
  }
  item = me.findNextFocusableChild({items:items, step:true});
  if (item) {
    me.activateFocusable(item);
  }
  return item;
}, clearFocusables:function(skipFocused) {
  var me = this, items = me.getFocusables(), len = items.length, item, i;
  for (i = 0; i < len; i++) {
    item = items[i];
    if (!item.destroyed && item.focusable && item.isTabbable()) {
      me.deactivateFocusable(item);
    }
  }
}, processFocusableContainerKeyEvent:function(e) {
  if (!Ext.fly(e.target).isInputField()) {
    return e;
  }
}, activateFocusable:function(child) {
  child.setTabIndex(this.activeChildTabIndex);
}, deactivateFocusable:function(child) {
  child.setTabIndex(this.inactiveChildTabIndex);
}, onFocusableContainerTabKey:function() {
  return true;
}, onFocusableContainerEnterKey:function() {
  return true;
}, onFocusableContainerSpaceKey:function() {
  return true;
}, onFocusableContainerUpKey:function(e) {
  e.preventDefault();
  return this.moveChildFocus(e, false);
}, onFocusableContainerDownKey:function(e) {
  e.preventDefault();
  return this.moveChildFocus(e, true);
}, onFocusableContainerLeftKey:function(e) {
  e.preventDefault();
  return this.moveChildFocus(e, false);
}, onFocusableContainerRightKey:function(e) {
  e.preventDefault();
  return this.moveChildFocus(e, true);
}, getFocusableFromEvent:function(e) {
  var child = Ext.Component.from(e);
  if (!child) {
    Ext.raise('No focusable child found for keyboard event!');
  }
  return child;
}, moveChildFocus:function(e, forward) {
  var child = this.getFocusableFromEvent(e);
  return this.focusChild(child, forward, e);
}, focusChild:function(child, forward) {
  var nextChild = this.findNextFocusableChild({child:child, step:forward});
  if (nextChild) {
    nextChild.focus();
  }
  return nextChild;
}, findNextFocusableChild:function(options) {
  var beforeRender = options.beforeRender, firstTabbable = options.firstTabbable, items, item, child, step, idx, i, len, allowDisabled;
  items = options.items || this.getFocusables();
  step = options.step != null ? options.step : 1;
  child = options.child;
  allowDisabled = !!this.allowFocusingDisabledChildren;
  idx = Ext.Array.indexOf(items, child);
  step = step === true ? 1 : step === false ? -1 : step;
  len = items.length;
  i = step > 0 ? idx < len ? idx + step : 0 : idx > 0 ? idx + step : len - 1;
  for (;; i += step) {
    if (idx < 0 && (i >= len || i < 0)) {
      return null;
    } else {
      if (i >= len) {
        i = -1;
        continue;
      } else {
        if (i < 0) {
          i = len;
          continue;
        } else {
          if (i === idx) {
            return null;
          }
        }
      }
    }
    item = items[i];
    if (!item || !item.focusable || item.isDisabled() && !allowDisabled) {
      continue;
    }
    if (firstTabbable) {
      if (item.isTabbable && item.isTabbable()) {
        return item;
      }
    } else {
      if (beforeRender || item.isFocusable && item.isFocusable()) {
        return item;
      }
    }
  }
  return null;
}, onFocusEnter:function(e) {
  var me = this, target = e.toComponent, child;
  if (target === me) {
    child = me.initDefaultFocusable();
    if (child) {
      child.focus();
    }
  }
  me.activateFocusableContainer(true);
}, onFocusLeave:function(e) {
  var me = this;
  if (me.resetFocusPosition) {
    me.clearFocusables();
    me.initDefaultFocusable();
  }
}, beforeFocusableChildBlur:Ext.privateFn, afterFocusableChildBlur:Ext.privateFn, beforeFocusableChildFocus:function(child) {
  var me = this;
  if (!me.focusableContainer || me.destroying || me.destroyed) {
    return;
  }
  me.clearFocusables();
  me.activateFocusable(child);
}, afterFocusableChildFocus:function(child) {
  var me = this;
  if (!me.focusableContainer || me.destroying || me.destroyed) {
    return;
  }
  me.lastFocusedChild = child;
}, onFocusableChildAdd:function(child) {
  var me = this;
  if (child.focusable) {
    child.ownerFocusableContainer = me;
  }
}, onFocusableChildRemove:function(child) {
  var me = this, next;
  child.ownerFocusableContainer = null;
  if (child === me.lastFocusedChild) {
    me.lastFocusedChild = null;
    next = me.initDefaultFocusable();
    if (child.hasFocus) {
      next = next || child.findFocusTarget();
      if (next) {
        next.focus();
      }
    }
  }
  child = next || me.findNextFocusableChild({step:1, beforeRender:true});
  if (!child) {
    me.activateFocusableContainer(false);
  }
}, beforeFocusableChildEnable:Ext.privateFn, onFocusableChildEnable:function(child) {
  var me = this, active;
  if (!me.focusableContainer || me.destroying || me.destroyed) {
    return;
  }
  if (me.containsFocus) {
    active = Ext.ComponentManager.getActiveComponent();
    me.clearFocusables();
    me.activateFocusable(active);
  } else {
    if (me.resetFocusPosition || me.lastFocusedChild == null) {
      me.clearFocusables();
      if (child.hasFocus) {
        me.activateFocusable(child);
        active = child;
      }
    } else {
      me.deactivateFocusable(child);
      if (child === me.lastFocusedChild) {
        me.clearFocusables();
        me.activateFocusable(child);
      }
      active = me.findNextFocusableChild({firstTabbable:true});
    }
  }
  if (!active) {
    me.initDefaultFocusable();
  }
  me.activateFocusableContainer(true);
}, beforeFocusableChildDisable:function(child) {
  var me = this, next;
  if (!me.focusableContainer || me.destroying || me.destroyed) {
    return;
  }
  if (child.hasFocus) {
    next = me.findNextFocusableChild({child:child}) || child.findFocusTarget();
    if (next) {
      next.focus();
    }
  }
}, onFocusableChildDisable:function(child) {
  var me = this, next;
  if (!me.focusableContainer || me.destroying || me.destroyed) {
    return;
  }
  next = me.findNextFocusableChild({firstTabbable:true});
  if (!next) {
    next = me.initDefaultFocusable();
  }
  if (!next) {
    me.activateFocusableContainer(false);
  }
}, beforeFocusableChildHide:function(child) {
  return this.beforeFocusableChildDisable(child);
}, onFocusableChildHide:function(child) {
  return this.onFocusableChildDisable(child);
}, beforeFocusableChildShow:function(child) {
  return this.beforeFocusableChildEnable(child);
}, onFocusableChildShow:function(child) {
  return this.onFocusableChildEnable(child);
}, onFocusableChildMasked:Ext.privateFn, onFocusableChildDestroy:Ext.privateFn, onFocusableChildUpdate:Ext.privateFn}, deprecated:{7:{configs:{enableFocusableContainer:'focusableContainer'}}}});
Ext.define('Ext.Container', {extend:Ext.Component, alternateClassName:['Ext.lib.Container', 'Ext.container.Container'], xtype:'container', isContainer:true, mixins:[Ext.mixin.Queryable, Ext.mixin.Container, Ext.mixin.FocusableContainer], eventedConfig:{activeItem:0}, config:{activeItemIndex:null, autoSize:null, bodyCls:null, layout:'auto', control:null, defaults:null, items:null, autoDestroy:true, defaultType:null, defaultFocus:{$value:null, lazy:true}, innerCls:null, masked:null}, weighted:false, 
manageBorders:false, classCls:Ext.baseCSSPrefix + 'container', managedBordersCls:Ext.baseCSSPrefix + 'managed-borders', template:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', uiCls:'body-el'}], constructor:function(config) {
  var me = this;
  me._items = me.items = new Ext.util.ItemCollection;
  me.innerItems = [];
  me.getReferences = me.getFirstReferences;
  me.onItemAdd = me.onFirstItemAdd;
  me.callParent(arguments);
  delete me.getReferences;
}, initialize:function() {
  var me = this;
  me.reference = me.setupReference(me.reference);
  me.callParent();
  if (me.manageBorders) {
    me.addCls(me.managedBordersCls);
  }
  me.getLayout();
}, applyMasked:function(masked) {
  var isVisible = true, currentMask;
  if (masked === false) {
    masked = true;
    isVisible = false;
  } else {
    if (Ext.isString(masked)) {
      masked = {xtype:'loadmask', message:masked};
    } else {
      if (masked && !masked.isComponent && masked.hidden) {
        isVisible = false;
      }
    }
  }
  currentMask = Ext.factory(masked, Ext['Mask'], this.getMasked());
  if (currentMask) {
    currentMask.sender = this;
    currentMask.setHidden(!isVisible);
    currentMask.render(this.el);
  }
  return currentMask;
}, mask:function(mask) {
  this.setMasked(mask || true);
}, unmask:function() {
  this.setMasked(false);
}, initInheritedState:function(inheritedState, inheritedStateInner) {
  this.callParent([inheritedState, inheritedStateInner]);
  this.initContainerInheritedState(inheritedState, inheritedStateInner);
}, onAdded:function(parent, instanced) {
  this.callParent([parent, instanced]);
  this.containerOnAdded(parent, instanced);
}, onRemoved:function(destroying) {
  this.containerOnRemoved(destroying);
  this.callParent([destroying]);
}, afterItemShow:function(item) {
  var layout;
  if (item.getDocked()) {
    layout = this.getLayout();
    this.items.generation++;
    layout.handleDockedItemBorders();
  }
}, afterItemHide:function(item) {
  var layout;
  if (item.getDocked()) {
    layout = this.getLayout();
    this.items.generation++;
    layout.handleDockedItemBorders();
  }
}, applyBodyCls:function(cls) {
  return cls && Ext.dom.Element.splitCls(cls);
}, updateBodyCls:function(newCls, oldCls) {
  this.bodyElement.replaceCls(oldCls, newCls);
}, applyItems:function(items, collection) {
  var me = this, activeItem;
  if (items) {
    me.getDefaultType();
    me.getDefaults();
    if (me.initialized && collection.length > 0) {
      me.removeAll();
    }
    if (me.weighted && !items.isWidget && !items.xtype) {
      items = Ext.convertKeyedItems(items);
    }
    me.add(items);
    if (me.initialized) {
      activeItem = me.initialConfig.activeItem || me.config.activeItem || 0;
      me.setActiveItem(activeItem);
    }
  }
}, applyControl:function(selectors) {
  var selector, key, listener, listeners;
  for (selector in selectors) {
    listeners = selectors[selector];
    for (key in listeners) {
      listener = listeners[key];
      if (Ext.isObject(listener)) {
        listener.delegate = selector;
      }
    }
    listeners.delegate = selector;
    this.addListener(listeners);
  }
  return selectors;
}, updateDisabled:function(disabled) {
  var me = this;
  me.callParent([disabled]);
  if (me.focusableContainer) {
    me.getItems();
    if (disabled) {
      me.element.saveTabbableState();
    } else {
      me.element.restoreTabbableState();
    }
    me.activateFocusableContainer(!disabled);
    if (!disabled) {
      me.initDefaultFocusable();
    }
  }
}, onFirstItemAdd:function(item) {
  var me = this;
  delete me.onItemAdd;
  if (item.isInner && me.innerHtmlElement && !me.getHtml() && !me.getTpl()) {
    me.innerHtmlElement.destroy();
    delete me.innerHtmlElement;
  }
  return me.onItemAdd.apply(me, arguments);
}, applyLayout:function(layout, oldLayout) {
  if (typeof layout === 'string') {
    layout = {type:layout};
  }
  if (oldLayout) {
    if (layout) {
      if (!layout.isLayout) {
        oldLayout.setConfig(layout);
      } else {
        Ext.raise('Cannot change layout instances on ' + this.$className);
      }
    }
    return oldLayout;
  }
  if (!(layout && layout.isLayout)) {
    layout = Ext.Factory.layout(Ext.apply({container:this}, layout), Ext.layout.Auto);
  }
  this.link('layout', layout);
  return layout;
}, updateDefaultType:function(defaultType) {
  this.defaultItemClass = Ext.ClassManager.getByAlias('widget.' + defaultType);
  if (!this.defaultItemClass) {
    Ext.Logger.error("Invalid defaultType of: '" + defaultType + "', must be a valid component xtype");
  }
}, factoryItem:function(item) {
  var me = this;
  if (!item) {
    Ext.Logger.error('Invalid item given: ' + item + ', must be either the config object to factory a ' + 'new item, or an existing component instance');
  }
  item = me.applyItemDefaults(item);
  if (!item.isComponent) {
    if (!me.$hasCachedDefaultItemClass) {
      me.getDefaultType();
      me.$hasCachedDefaultItemClass = true;
    }
    item = Ext.factory(item, me.defaultItemClass);
  }
  return item;
}, add:function(newItems) {
  var me = this, items = me.getItems(), weighted = me.weighted, addingArray = true, addedItems = [], doWeightedInsert, i, ln, item, instanced;
  if (!Ext.isArray(newItems)) {
    newItems = [newItems];
    addingArray = false;
  }
  if (weighted) {
    if (items.length) {
      doWeightedInsert = true;
    } else {
      Ext.sortByWeight(newItems);
    }
  }
  for (i = 0, ln = newItems.length; i < ln; i++) {
    item = newItems[i];
    if (item) {
      instanced = item.isWidget;
      if (!instanced) {
        item.$initParent = me;
      }
      item = me.factoryItem(item);
      if (doWeightedInsert) {
        me.doInsert(items.findInsertionIndex(item, Ext.weightSortFn), item, instanced);
      } else {
        me.doAdd(item, instanced);
      }
      delete item.$initParent;
      if (me.focusableContainer) {
        me.onFocusableChildAdd(item);
      }
      addedItems.push(item);
    } else {
      if (item !== null) {
        Ext.raise('Invalid item passed to add');
      }
    }
  }
  if ((me.isConfiguring || !me.getActiveItem()) && me.innerItems.length > 0) {
    me.setActiveItem(me.initialConfig.activeItem || 0);
  }
  if (me.rendered && ln && me.focusableContainer) {
    me.initFocusableContainer();
  }
  return addingArray ? addedItems : addedItems[0];
}, onItemWeightChange:function(item) {
  var items = this.getItems(), oldIndex = items.indexOf(item), index;
  items.remove(item);
  index = items.findInsertionIndex(item, Ext.weightSortFn);
  items.insert(index, item);
  this.insertInner(item, index);
  this.onItemMove(item, index, oldIndex);
}, doAdd:function(item, instanced) {
  var me = this, items = me.getItems(), index;
  if (!items.has(item)) {
    index = items.length;
    items.add(item);
    if (item.isInnerItem()) {
      me.insertInner(item, index);
    }
    item.onAdded(me, !!instanced);
    if (me.focusableContainer) {
      me.onFocusableChildAdd(item);
    }
    me.onItemAdd(item, index);
  }
}, remove:function(which, destroy) {
  var me = this, component = me.getComponent(which), activeItem, index, innerItems, item, wasActive;
  if (destroy === undefined) {
    destroy = me.getAutoDestroy();
  }
  if (!component) {
    if (!Ext.isArray(which)) {
      Ext.raise('Invalid first argument to Ext.Container#remove() - ', Ext.typeOf(which));
    }
    activeItem = me.getActiveItem();
    for (index = 0; index < which.length; ++index) {
      item = me.getComponent(which[index]);
      if (item === activeItem) {
        wasActive = true;
      } else {
        if (item) {
          me.remove(item, destroy);
        }
      }
    }
    if (wasActive) {
      me.remove(activeItem, destroy);
    }
    return which;
  }
  index = me.indexOf(component);
  innerItems = me.getInnerItems();
  if (index !== -1) {
    if (!me.removingAll && innerItems.length > 1 && component === me.getActiveItem()) {
      me.on({activeitemchange:'doRemove', scope:me, single:true, order:'after', args:[component, index, destroy]});
      me.doResetActiveItem(innerItems.indexOf(component));
    } else {
      me.doRemove(component, index, destroy);
      if (innerItems.length === 0) {
        me.setActiveItem(null);
      }
    }
  }
  return component;
}, doResetActiveItem:function(innerIndex) {
  if (innerIndex === 0) {
    this.setActiveItem(1);
  } else {
    this.setActiveItem(0);
  }
}, doRemove:function(item, index, destroy) {
  var me = this;
  if (!me.destroying) {
    me.items.remove(item);
    if (item.isInnerItem()) {
      me.removeInner(item);
    }
    me.onItemRemove(item, index, destroy);
  }
  if (!item.destroyed) {
    item.onRemoved(item.destroying || destroy);
  }
  if (me.focusableContainer && !me.destroying && !me.destroyed) {
    me.onFocusableChildRemove(item, destroy);
  }
  if (destroy && !item.destroyed) {
    item.destroy();
  }
}, removeAll:function(destroy, everything) {
  var me = this, destroying = me.destroying, items = me.items, removed = destroying ? null : [], ln = items.length, i, item;
  if (typeof destroy !== 'boolean') {
    destroy = this.getAutoDestroy();
  }
  me.removingAll = true;
  for (i = 0; i < ln; i++) {
    item = items.getAt(i);
    if (item && (everything || item.isInnerItem())) {
      me.doRemove(item, i, destroy);
      if (!destroying) {
        i--;
        ln--;
      }
    }
    if (removed) {
      removed.push(item);
    }
  }
  if (!destroying) {
    me.setActiveItem(null);
  }
  me.removingAll = false;
  return removed;
}, getAt:function(index) {
  return this.items.getAt(index);
}, getInnerAt:function(index) {
  return this.innerItems[index];
}, removeAt:function(index, destroy) {
  var item = this.getAt(index);
  if (item) {
    this.remove(item, destroy);
  }
  return item;
}, removeInnerAt:function(index) {
  var item = this.getInnerItems()[index];
  if (item) {
    this.remove(item);
  }
  return item;
}, has:function(item) {
  return this.getItems().indexOf(item) !== -1;
}, hasInnerItem:function(item) {
  return this.innerItems.indexOf(item) !== -1;
}, indexOf:function(item) {
  return this.getItems().indexOf(item);
}, innerIndexOf:function(item) {
  return this.innerItems.indexOf(item);
}, insertInner:function(item, index) {
  var items = this.getItems().items, innerItems = this.innerItems, currentInnerIndex = innerItems.indexOf(item), newInnerIndex = -1, nextSibling;
  if (currentInnerIndex !== -1) {
    innerItems.splice(currentInnerIndex, 1);
  }
  if (typeof index === 'number') {
    do {
      nextSibling = items[++index];
    } while (nextSibling && !nextSibling.isInnerItem());
    if (nextSibling) {
      newInnerIndex = innerItems.indexOf(nextSibling);
      innerItems.splice(newInnerIndex, 0, item);
    }
  }
  if (newInnerIndex === -1) {
    innerItems.push(item);
    newInnerIndex = innerItems.length - 1;
  }
  if (currentInnerIndex !== -1) {
    this.onInnerItemMove(item, newInnerIndex, currentInnerIndex);
  }
  return this;
}, onInnerItemMove:Ext.emptyFn, removeInner:function(item) {
  Ext.Array.remove(this.innerItems, item);
  return this;
}, insert:function(index, item) {
  var me = this, instanced, i;
  if (typeof index !== 'number') {
    Ext.Logger.error("Invalid index of '" + index + "', must be a valid number");
  }
  if (Ext.isArray(item)) {
    for (i = item.length - 1; i >= 0; i--) {
      me.insert(index, item[i]);
    }
    return me;
  }
  instanced = item.isWidget;
  if (!instanced) {
    item.$initParent = me;
  }
  item = me.factoryItem(item);
  me.doInsert(index, item, instanced);
  delete item.$initParent;
  return item;
}, doInsert:function(index, item, instanced) {
  var me = this, items = me.items, itemsLength = items.length, currentIndex, isInnerItem;
  isInnerItem = item.isInnerItem();
  if (index > itemsLength) {
    index = itemsLength;
  }
  if (items[index - 1] === item) {
    return;
  }
  currentIndex = me.indexOf(item);
  if (currentIndex !== -1) {
    items.removeAt(currentIndex);
  }
  items.insert(index, item);
  if (currentIndex === -1) {
    item.onAdded(me, !!instanced);
  }
  if (isInnerItem) {
    me.insertInner(item, index);
  }
  if (currentIndex !== -1) {
    me.onItemMove(item, index, currentIndex);
  } else {
    me.onItemAdd(item, index);
  }
}, insertFirst:function(item) {
  return this.insert(0, item);
}, insertLast:function(item) {
  return this.insert(this.getItems().length, item);
}, insertBefore:function(item, relativeToItem) {
  var items = this.getItems(), ret, index, itemIndex;
  if (relativeToItem === null) {
    ret = this.add(item);
  } else {
    index = items.indexOf(relativeToItem);
    if (index === -1) {
      Ext.raise('Item does not exist in the container');
    }
    itemIndex = items.indexOf(item);
    if (itemIndex !== -1 && itemIndex < index) {
      --index;
    }
    ret = this.insert(index, item);
  }
  return ret;
}, insertAfter:function(item, relativeToItem) {
  var index = this.indexOf(relativeToItem);
  if (index !== -1) {
    this.insert(index + 1, item);
  }
  return this;
}, onItemAdd:function(item, index) {
  var me = this;
  me.doItemLayoutAdd(item, index);
  if (me.initialized) {
    if (item.hasListeners.added) {
      item.fireEvent('added', item, me, index);
    }
    if (me.hasListeners.add) {
      me.fireEvent('add', me, item, index);
    }
  }
}, doItemLayoutAdd:function(item, index) {
  var layout = this.getLayout();
  if (this.rendered && !item.rendered) {
    item.fireAction('renderedchange', [this, item, true], 'onItemAdd', layout, {args:[item, index]});
  } else {
    layout.onItemAdd(item, index);
  }
}, onItemRemove:function(item, index, destroying) {
  var me = this;
  me.doItemLayoutRemove(item, index, destroying);
  if (item.hasListeners.removed) {
    item.fireEvent('removed', item, me, index);
  }
  if (me.hasListeners.remove) {
    me.fireEvent('remove', me, item, index);
  }
}, doItemLayoutRemove:function(item, index, destroying) {
  var layout = this.getLayout();
  if (item.rendered) {
    item.setRendered(false);
    item.fireAction('renderedchange', [this, item, false], 'onItemRemove', layout, {args:[item, index, destroying]});
  } else {
    layout.onItemRemove(item, index, destroying);
  }
}, onItemMove:function(item, toIndex, fromIndex) {
  var me = this;
  me.doItemLayoutMove(item, toIndex, fromIndex);
  if (item.hasListeners.moved) {
    item.fireEvent('moved', item, me, toIndex, fromIndex);
  }
  if (me.hasListeners.move) {
    me.fireEvent('move', me, item, toIndex, fromIndex);
  }
}, doItemLayoutMove:function(item, toIndex, fromIndex) {
  this.getLayout().onItemMove(item, toIndex, fromIndex);
}, onItemInnerStateChange:function(item, isInner) {
  var layout = this.getLayout();
  if (isInner) {
    this.insertInner(item, this.items.indexOf(item));
  } else {
    this.removeInner(item);
  }
  layout.onItemInnerStateChange.apply(layout, arguments);
}, onItemFloatedChange:function(item, floated) {
  var layout = this.getLayout();
  layout.onItemFloatedChange(item, floated);
}, getInnerItems:function() {
  return this.innerItems;
}, getDockedItems:function() {
  var items = this.getItems().items, dockedItems = [], ln = items.length, item, i;
  for (i = 0; i < ln; i++) {
    item = items[i];
    if (item.isDocked()) {
      dockedItems.push(item);
    }
  }
  return dockedItems;
}, applyActiveItem:function(activeItem, currentActiveItem) {
  var me = this, innerItems = me.getInnerItems(), initialConfig = me.initialConfig, initialActive = initialConfig.activeItem || activeItem, item;
  me.getItems();
  if (me.isConfiguring && !initialConfig.activeItem) {
    activeItem = initialActive;
  }
  if (!activeItem && innerItems.length === 0) {
    return 0;
  } else {
    if (typeof activeItem === 'number') {
      activeItem = Math.max(0, Math.min(activeItem, innerItems.length - 1));
      activeItem = innerItems[activeItem];
      if (activeItem) {
        return activeItem;
      } else {
        if (currentActiveItem) {
          return null;
        }
      }
    } else {
      if (activeItem) {
        if (typeof activeItem === 'string') {
          item = me.child(activeItem);
        } else {
          if (activeItem.isComponent) {
            item = activeItem;
          } else {
            activeItem = Ext.apply({$initParent:me}, activeItem);
            item = me.factoryItem(activeItem);
          }
        }
        if (!item) {
          return null;
        }
        me.pendingActiveItem = item;
        if (!item.isInnerItem()) {
          Ext.Logger.error('Setting activeItem to be a non-inner item');
        }
        if (!me.has(item)) {
          me.add(item);
        }
        delete item.$initParent;
        return item;
      }
    }
  }
}, animateActiveItem:function(activeItem, animation) {
  var layout = this.getLayout(), defaultAnimation;
  if (this.activeItemAnimation) {
    this.activeItemAnimation.destroy();
  }
  this.activeItemAnimation = animation = new Ext.Factory.layoutCardFx(animation);
  if (animation && layout.isCard) {
    animation.setLayout(layout);
    defaultAnimation = layout.getAnimation();
    if (defaultAnimation) {
      defaultAnimation.disable();
    }
    animation.on('animationend', function() {
      if (defaultAnimation) {
        defaultAnimation.enable();
      }
      animation.destroy();
    }, this);
  }
  return this.setActiveItem(activeItem);
}, updateActiveItem:function(newActiveItem, oldActiveItem) {
  delete this.pendingActiveItem;
  if (oldActiveItem && !oldActiveItem.destroyed) {
    oldActiveItem.fireEvent('deactivate', oldActiveItem, this, newActiveItem);
  }
  if (newActiveItem) {
    newActiveItem.fireEvent('activate', newActiveItem, this, oldActiveItem);
  }
  this.setActiveItemIndex(this.innerItems.indexOf(newActiveItem));
}, updateActiveItemIndex:function(index) {
  this.setActiveItem(this.innerItems[index]);
}, getRefItems:function(deep) {
  var items = this.getItems().items, result, ln, i, item;
  if (items) {
    if (deep) {
      result = [];
      for (i = 0, ln = items.length; i < ln; i++) {
        item = items[i];
        result[result.length] = item;
        if (item.getRefItems) {
          result.push.apply(result, item.getRefItems(true));
        }
      }
    } else {
      result = items.slice();
    }
  }
  return result || [];
}, getComponent:function(component) {
  if (typeof component === 'number') {
    return this.getItems().getAt(component);
  }
  if (Ext.isObject(component)) {
    component = component.getItemId();
  }
  return this.getItems().get(component);
}, getDockedComponent:function(component) {
  var dockedItems, ln, item, i;
  if (Ext.isObject(component)) {
    component = component.getItemId();
  }
  dockedItems = this.getDockedItems();
  ln = dockedItems.length;
  if (Ext.isNumber(component)) {
    return dockedItems[component];
  }
  for (i = 0; i < ln; i++) {
    item = dockedItems[i];
    if (item.id === component) {
      return item;
    }
  }
  return false;
}, doDestroy:function() {
  var me = this;
  if (me.focusableContainer) {
    me.destroyFocusableContainer();
  }
  me.removeAll(true, true);
  Ext.destroy(me.items, me.getMasked());
  me.items = null;
  if (me._layout) {
    me._layout = Ext.destroy(me._layout);
  }
  me.callParent();
}, getFocusEl:function() {
  var delegate = this.findDefaultFocus();
  if (delegate) {
    return delegate.isWidget ? delegate.getFocusEl() : delegate;
  } else {
    if (this.focusable) {
      return this.focusEl;
    }
  }
  return undefined;
}, findDefaultFocus:function() {
  var result = this.getDefaultFocus();
  if (result && !result.isWidget) {
    result = this.down(result);
    if (result && !result.canFocus()) {
      return;
    }
  }
  return result;
}, onFocusEnter:function(e) {
  var me = this;
  me.callParent([e]);
  if (me.focusableContainer && !me.destroying && !me.destroyed) {
    me.mixins.focusablecontainer.onFocusEnter.call(me, e);
  }
}, onFocusLeave:function(e) {
  var me = this;
  me.callParent([e]);
  if (me.focusableContainer && !me.destroying && !me.destroyed) {
    me.mixins.focusablecontainer.onFocusLeave.call(me, e);
  }
}, updateInnerCls:function(innerCls, old) {
  var el = this.getRenderTarget();
  el.replaceCls(old, innerCls);
}, updateAutoSize:function(autoSize) {
  var me = this, bodySizerElement = me.bodySizerElement;
  if (autoSize === false) {
    if (!bodySizerElement) {
      me.bodySizerElement = me.bodyElement.wrap({cls:Ext.baseCSSPrefix + 'body-sizer-el'});
    }
  } else {
    if (bodySizerElement) {
      me.bodyElement.unwrap();
      bodySizerElement.destroy();
      me.bodySizerElement = null;
    }
  }
}, updateMaxHeight:function(maxHeight, oldMaxHeight) {
  var me = this;
  me.callParent([maxHeight, oldMaxHeight]);
  if (Ext.isIE11 && maxHeight != null && me.getAutoSize() !== false) {
    me.getMaxHeightElement().setMaxHeight(maxHeight);
    me.addCls(Ext.baseCSSPrefix + 'max-height-wrapped');
  }
}, privates:{getFirstReferences:function() {
  var me = this;
  delete me.getReferences;
  me.getItems();
  return me.getReferences.apply(me, arguments);
}, getPositionedItemTarget:function() {
  return this.getRenderTarget();
}, applyItemDefaults:function(item) {
  var defaults = this.getDefaults();
  if (defaults && !item.ignoreDefaults) {
    if (item.isComponent) {
      if (item.isInnerItem() && !this.has(item)) {
        if (Ext.isFunction(defaults)) {
          defaults = defaults(item);
        }
        item.setConfig(defaults, null, {defaults:true});
      }
    } else {
      if (Ext.isFunction(defaults)) {
        defaults = defaults(item);
      }
      item = Ext.merge({}, defaults, item);
    }
  }
  return item;
}, setChildRendered:function(rendered, item) {
  if (item.isInnerItem()) {
    this.getLayout().renderInnerItem(item);
  } else {
    if (!rendered || !item.getFloated()) {
      item.setRendered(rendered);
    }
  }
}, getMaxHeightElement:function() {
  var el = this.el, maxHeightElement = this.maxHeightElement, selector = '.x-dock,.x-panelheader,.x-body-el,.x-body-wrap-el,.x-tab-guard-el', childNodes, node, i, ln;
  if (!maxHeightElement) {
    this.maxHeightElement = maxHeightElement = el.insertFirst({cls:Ext.baseCSSPrefix + 'max-height-el'});
    childNodes = Ext.Array.clone(el.dom.childNodes);
    for (i = 1, ln = childNodes.length; i < ln; i++) {
      node = childNodes[i];
      if (Ext.fly(node).is(selector)) {
        maxHeightElement.appendChild(node);
      }
    }
  }
  return maxHeightElement;
}}}, function() {
  this.prototype.defaultItemClass = this;
});
Ext.define('Ext.mixin.Hookable', {extend:Ext.Mixin, mixinConfig:{id:'hookable'}, bindHook:function(instance, boundMethod, bindingMethod, preventDefault, extraArgs) {
  instance.afterMethod(boundMethod, bindingMethod || boundMethod, this, preventDefault, extraArgs);
  return this;
}, unbindHook:function(instance, boundMethod, bindingMethod) {
  instance.removeMethodListener(boundMethod, bindingMethod || boundMethod, this);
  return this;
}});
Ext.define('Ext.util.Wrapper', {mixins:[Ext.mixin.Hookable], constructor:function(elementConfig, wrappedElement) {
  var element = this.link('element', Ext.Element.create(elementConfig));
  if (wrappedElement) {
    element.insertBefore(wrappedElement);
    this.wrap(wrappedElement);
  }
}, bindSize:function(sizeName) {
  var wrappedElement = this.wrappedElement, boundMethodName;
  this.boundSizeName = sizeName;
  this.boundMethodName = boundMethodName = sizeName === 'width' ? 'setWidth' : 'setHeight';
  this.bindHook(wrappedElement, boundMethodName, 'onBoundSizeChange');
  wrappedElement[boundMethodName].call(wrappedElement, wrappedElement.getStyleValue(sizeName));
}, onBoundSizeChange:function(size, args) {
  var element = this.element;
  if (typeof size === 'string' && size.substr(-1) === '%') {
    args[0] = '100%';
  } else {
    size = '';
  }
  element[this.boundMethodName].call(element, size);
}, wrap:function(wrappedElement) {
  var element = this.element, innerDom;
  this.wrappedElement = wrappedElement;
  innerDom = element.dom;
  while (innerDom.firstElementChild !== null) {
    innerDom = innerDom.firstElementChild;
  }
  innerDom.appendChild(wrappedElement.dom);
}, destroy:function() {
  var me = this, element = me.element, dom = element.dom, wrappedElement = me.wrappedElement, boundMethodName = me.boundMethodName, parentNode = dom.parentNode, size;
  if (boundMethodName) {
    me.unbindHook(wrappedElement, boundMethodName, 'onBoundSizeChange');
    size = element.getStyle(me.boundSizeName);
    if (size) {
      wrappedElement[boundMethodName].call(wrappedElement, size);
    }
  }
  if (parentNode) {
    if (!wrappedElement.destroyed) {
      parentNode.replaceChild(dom.firstElementChild, dom);
    }
    delete me.wrappedElement;
  }
  me.callParent();
}});
Ext.define('Ext.layout.wrapper.BoxDock', {config:{direction:'horizontal', element:{className:Ext.baseCSSPrefix + 'dock'}, innerWrapper:null, container:null, manageBorders:null}, positionMap:{top:'start', left:'start', bottom:'end', right:'end'}, managedBordersCls:Ext.baseCSSPrefix + 'managed-borders', constructor:function(config) {
  this.items = {start:[], end:[]};
  this.itemsCount = 0;
  this.initConfig(config);
}, addItems:function(items) {
  var i, ln, item;
  for (i = 0, ln = items.length; i < ln; i++) {
    item = items[i];
    this.addItem(item);
  }
}, addItem:function(item) {
  var docked = item.getDocked(), position = this.positionMap[docked], wrapper = item.$dockWrapper, container = this.getContainer(), index = container.indexOf(item), element = item.element, items = this.items, sideItems = items[position], i, ln, sibling, referenceElement, siblingIndex;
  if (wrapper) {
    wrapper.removeItem(item);
  }
  item.$dockWrapper = this;
  item.addCls(Ext.baseCSSPrefix + 'dock-item');
  item.addCls(Ext.baseCSSPrefix + 'docked-' + docked);
  for (i = 0, ln = sideItems.length; i < ln; i++) {
    sibling = sideItems[i];
    siblingIndex = container.indexOf(sibling);
    if (siblingIndex > index) {
      referenceElement = sibling.element;
      sideItems.splice(i, 0, item);
      break;
    }
  }
  if (!referenceElement) {
    sideItems.push(item);
    referenceElement = this.getInnerWrapper().getElement();
  }
  this.itemsCount++;
  if (position === 'start') {
    element.insertBefore(referenceElement);
  } else {
    element.insertAfter(referenceElement);
  }
}, removeItem:function(item, oldDocked) {
  var me = this, position = oldDocked || item.getDocked(), items = me.items[me.positionMap[position]];
  Ext.Array.remove(items, item);
  item.element.detach();
  delete item.$dockWrapper;
  item.removeCls(Ext.baseCSSPrefix + 'dock-item');
  item.removeCls(Ext.baseCSSPrefix + 'docked-' + position);
  if (--me.itemsCount === 0) {
    me.destroy();
  }
}, getItemsSlice:function(index) {
  var container = this.getContainer(), items = this.items, slice = [], sideItems, i, ln, item;
  for (sideItems = items.start, i = 0, ln = sideItems.length; i < ln; i++) {
    item = sideItems[i];
    if (container.indexOf(item) > index) {
      slice.push(item);
    }
  }
  for (sideItems = items.end, i = 0, ln = sideItems.length; i < ln; i++) {
    item = sideItems[i];
    if (container.indexOf(item) > index) {
      slice.push(item);
    }
  }
  return slice;
}, applyElement:function(element) {
  return Ext.Element.create(element);
}, updateElement:function(element) {
  element.addCls(Ext.baseCSSPrefix + 'dock-' + this.getDirection());
}, updateInnerWrapper:function(innerWrapper, oldInnerWrapper) {
  if (oldInnerWrapper) {
    innerWrapper.getElement().replace(oldInnerWrapper.getElement(), false);
    oldInnerWrapper.$outerWrapper = null;
  } else {
    this.getElement().append(innerWrapper.getElement());
  }
  innerWrapper.setManageBorders(this.getManageBorders());
  innerWrapper.$outerWrapper = this;
}, updateManageBorders:function(manageBorders) {
  var me = this, innerWrapper = me.getInnerWrapper();
  me.getElement().toggleCls(me.managedBordersCls, manageBorders);
  if (innerWrapper) {
    innerWrapper.setManageBorders(manageBorders);
  }
}, destroy:function() {
  var me = this, innerWrapper = me.getInnerWrapper(), outerWrapper = me.$outerWrapper, innerWrapperElement;
  if (innerWrapper) {
    if (outerWrapper) {
      outerWrapper.setInnerWrapper(innerWrapper);
    } else {
      innerWrapperElement = innerWrapper.getElement();
      if (!innerWrapperElement.destroyed) {
        innerWrapperElement.replace(me.getElement());
      }
      delete innerWrapper.$outerWrapper;
    }
  }
  delete me.$outerWrapper;
  me.unlink(['_element']);
  me.callParent();
}});
Ext.define('Ext.layout.wrapper.Inner', {config:{container:null, manageBorders:null}, constructor:function(config) {
  this.initConfig(config);
}, getElement:function() {
  var container = this.getContainer();
  return container.boxScrollerElement || container.bodySizerElement || container.bodyElement;
}, setInnerWrapper:Ext.emptyFn, getInnerWrapper:Ext.emptyFn});
Ext.define('Ext.layout.Auto', {alias:['layout.default', 'layout.auto'], alternateClassName:'Ext.layout.Default', mixins:[Ext.mixin.Observable, Ext.mixin.Factoryable], factoryConfig:{type:'layout', defaultType:'auto', instanceProp:'isLayout'}, isLayout:true, config:{animation:null, container:null}, centerCls:Ext.baseCSSPrefix + 'center', cls:Ext.baseCSSPrefix + 'layout-auto', itemCls:Ext.baseCSSPrefix + 'layout-auto-item', spaceRe:/\s+/, positionMap:{top:'start', left:'start', middle:'center', bottom:'end', 
right:'end'}, positionDirectionMap:{top:'vertical', bottom:'vertical', left:'horizontal', right:'horizontal'}, constructor:function(config) {
  this.mixins.observable.constructor.call(this, config);
}, updateContainer:function(container, oldContainer) {
  var me = this;
  me.dockedItems = [];
  container.getRenderTarget().addCls(me.cls);
  if (container.initialized) {
    me.onContainerInitialized(container);
  } else {
    container.onInitialized('onContainerInitialized', me);
  }
}, onContainerInitialized:function(container) {
  var me = this;
  me.handleDockedItemBorders();
  container.on({delegate:'\x3e component', beforecenteredchange:'onItemCenteredChange', positionedchange:'onItemPositionedChange', afterdockedchange:'onAfterItemDockedChange', scope:me});
}, onItemAdd:function(item) {
  var me = this, container = me.getContainer(), floated = item.getFloated();
  if (item.getDocked() != null) {
    me.dockItem(item);
  } else {
    if (item.isCentered()) {
      me.onItemCenteredChange(item, true);
    } else {
      if (item.isPositioned()) {
        me.onItemPositionedChange(item, true);
      } else {
        if (!floated) {
          me.onItemInnerStateChange(item, true);
        }
      }
    }
  }
  if (container.rendered && !floated) {
    if (item.isInnerItem()) {
      me.renderInnerItem(item, true);
    } else {
      item.setRendered(true, true);
    }
  }
}, onItemInnerStateChange:function(item, isInner, destroying) {
  var itemCls = this.itemCls;
  if (isInner) {
    this.insertInnerItem(item, this.getContainer().innerIndexOf(item));
    item.addCls(itemCls);
  } else {
    this.removeInnerItem(item);
    item.removeCls(itemCls);
  }
}, insertInnerItem:function(item, index) {
  var itemDom = item.element.dom, container = this.getContainer(), renderTarget = container.getRenderTarget(item), nextSibling = null;
  if (index !== -1) {
    if (renderTarget === container.getRenderTarget()) {
      nextSibling = container.getInnerAt(index + 1);
      nextSibling = nextSibling ? nextSibling.element.dom : null;
    } else {
      nextSibling = renderTarget.dom.childNodes[index];
    }
  }
  renderTarget.dom.insertBefore(itemDom, nextSibling);
}, insertPositionedItem:function(item) {
  var me = this, renderTarget = me.getContainer().getPositionedItemTarget(item).dom;
  if (item.getZIndex() === null) {
    item.setZIndex((me.getContainer().indexOf(item) + 1) * 2);
  }
  renderTarget.insertBefore(item.element.dom, renderTarget.firstChild);
  return me;
}, removeInnerItem:function(item) {
  item.element.detach();
}, removePositionedItem:function(item) {
  item.setZIndex(null);
  item.element.detach();
}, onItemRemove:function(item, index, destroying) {
  var me = this;
  if (item.getDocked()) {
    me.undockItem(item);
  } else {
    if (item.isCentered()) {
      me.onItemCenteredChange(item, false);
    } else {
      if (item.isPositioned()) {
        me.onItemPositionedChange(item, false);
      } else {
        if (!item.getFloated()) {
          me.onItemInnerStateChange(item, false, destroying);
        }
      }
    }
  }
}, onItemMove:function(item, toIndex, fromIndex) {
  if (item.isCentered() || item.isPositioned()) {
    item.setZIndex((toIndex + 1) * 2);
  } else {
    if (item.isInnerItem()) {
      this.insertInnerItem(item, this.getContainer().innerIndexOf(item));
    } else {
      this.undockItem(item);
      this.dockItem(item);
    }
  }
}, onItemCenteredChange:function(item, centered) {
  var wrapperName = '$centerWrapper';
  if (item.getFloated()) {
    item.center();
  } else {
    if (centered) {
      this.insertPositionedItem(item);
      item.link(wrapperName, new Ext.util.Wrapper({className:this.centerCls}, item.element));
    } else {
      item.unlink([wrapperName]);
      this.removePositionedItem(item);
    }
  }
}, onItemPositionedChange:function(item, positioned) {
  if (positioned) {
    this.insertPositionedItem(item);
  } else {
    this.removePositionedItem(item);
  }
}, onAfterItemDockedChange:function(item, docked, oldDocked) {
  if (item.initialized) {
    if (oldDocked) {
      this.undockItem(item, oldDocked);
    }
    if (docked) {
      this.dockItem(item);
    }
  }
}, dockItem:function(item) {
  var me = this, BoxDock = Ext.layout.wrapper.BoxDock, dockedItems = me.dockedItems, ln = dockedItems.length, container = me.getContainer(), itemIndex = container.indexOf(item), positionDirectionMap = me.positionDirectionMap, direction = positionDirectionMap[item.getDocked()], dockInnerWrapper = me.dockInnerWrapper, needsInnerWrapper = !dockInnerWrapper, referenceDirection, i, dockedItem, index, previousItem, slice, referenceItem, referenceDocked, referenceWrapper, newWrapper, nestedWrapper, oldInnerWrapper;
  if (needsInnerWrapper) {
    dockInnerWrapper = new Ext.layout.wrapper.Inner({container:container});
  }
  if (ln === 0) {
    dockedItems.push(item);
    newWrapper = new BoxDock({container:container, direction:direction, manageBorders:container.manageBorders});
    newWrapper.getElement().replace(dockInnerWrapper.getElement(), false);
    newWrapper.setInnerWrapper(dockInnerWrapper);
    newWrapper.addItem(item);
  } else {
    for (i = 0; i < ln; i++) {
      dockedItem = dockedItems[i];
      index = container.indexOf(dockedItem);
      if (index > itemIndex) {
        referenceItem = previousItem || dockedItems[0];
        dockedItems.splice(i, 0, item);
        break;
      }
      previousItem = dockedItem;
    }
    if (!referenceItem) {
      referenceItem = dockedItems[ln - 1];
      dockedItems.push(item);
    }
    referenceDocked = referenceItem.getDocked();
    referenceWrapper = referenceItem.$dockWrapper;
    referenceDirection = positionDirectionMap[referenceDocked];
    if (direction === referenceDirection) {
      referenceWrapper.addItem(item);
    } else {
      slice = referenceWrapper.getItemsSlice(itemIndex);
      newWrapper = new BoxDock({container:container, direction:direction});
      if (slice.length > 0) {
        if (slice.length === referenceWrapper.itemsCount) {
          nestedWrapper = referenceWrapper;
          newWrapper.getElement().replace(nestedWrapper.getElement(), false);
          newWrapper.setInnerWrapper(nestedWrapper);
        } else {
          nestedWrapper = new BoxDock({container:container, direction:referenceDirection});
          oldInnerWrapper = referenceWrapper.getInnerWrapper();
          newWrapper.setInnerWrapper(nestedWrapper);
          referenceWrapper.setInnerWrapper(newWrapper);
          nestedWrapper.setInnerWrapper(oldInnerWrapper);
          nestedWrapper.addItems(slice);
        }
      } else {
        oldInnerWrapper = referenceWrapper.getInnerWrapper();
        referenceWrapper.setInnerWrapper(newWrapper);
        newWrapper.setInnerWrapper(oldInnerWrapper);
      }
      newWrapper.addItem(item);
    }
  }
  if (newWrapper) {
    me.link('dockOuterWrapper', newWrapper);
  }
  if (needsInnerWrapper) {
    me.link('dockInnerWrapper', dockInnerWrapper);
  }
  if (container.initialized) {
    me.handleDockedItemBorders();
  }
}, getDockWrapper:function() {
  var dockedItems = this.dockedItems;
  if (dockedItems.length > 0) {
    return dockedItems[0].$dockWrapper;
  }
  return null;
}, undockItem:function(item, oldDocked) {
  var me = this, dockedItems = me.dockedItems, lastBorderMask, lastBorderCollapse, dockWrapper = item.$dockWrapper;
  if (dockWrapper) {
    dockWrapper.removeItem(item, oldDocked);
  }
  if (me.getContainer().initialized) {
    lastBorderMask = item.lastBorderMask;
    lastBorderCollapse = item.lastBorderCollapse;
    if (lastBorderMask) {
      item.lastBorderMask = 0;
      item.removeCls(me.noBorderClassTable[lastBorderMask]);
    }
    if (lastBorderCollapse) {
      item.lastBorderCollapse = 0;
      item.removeCls(me.getBorderCollapseTable()[lastBorderCollapse]);
    }
    me.handleDockedItemBorders();
  }
  Ext.Array.remove(dockedItems, item);
}, destroy:function() {
  this.dockedItems = null;
  Ext.destroy(this.getAnimation());
  this.callParent();
}, noBorderClassTable:[0, Ext.baseCSSPrefix + 'noborder-l', Ext.baseCSSPrefix + 'noborder-b', Ext.baseCSSPrefix + 'noborder-bl', Ext.baseCSSPrefix + 'noborder-r', Ext.baseCSSPrefix + 'noborder-rl', Ext.baseCSSPrefix + 'noborder-rb', Ext.baseCSSPrefix + 'noborder-rbl', Ext.baseCSSPrefix + 'noborder-t', Ext.baseCSSPrefix + 'noborder-tl', Ext.baseCSSPrefix + 'noborder-tb', Ext.baseCSSPrefix + 'noborder-tbl', Ext.baseCSSPrefix + 'noborder-tr', Ext.baseCSSPrefix + 'noborder-trl', Ext.baseCSSPrefix + 'noborder-trb', 
Ext.baseCSSPrefix + 'noborder-trbl'], edgeMasks:{top:8, right:4, bottom:2, left:1}, handleDockedItemBorders:function(force) {
  var me = this, edges = 0, maskT = 8, maskR = 4, maskB = 2, maskL = 1, container = me.getContainer(), bodyBorder = container.getBodyBorder && container.getBodyBorder(), containerBorder = container.getBorder(), collapsed = me.collapsed, edgeMasks = me.edgeMasks, noBorderCls = me.noBorderClassTable, dockedItemsGen = container.items.generation, bodyClsEl = container.boxScrollerElement || container.bodyElement, b, borderCls, docked, edgesTouched, i, ln, item, dock, lastValue, mask, addCls, removeCls, 
  header;
  if (!force && me.initializedBorders === dockedItemsGen || !container.manageBorders) {
    return;
  }
  addCls = [];
  removeCls = [];
  borderCls = me.getBorderCollapseTable();
  noBorderCls = me.getBorderClassTable ? me.getBorderClassTable() : noBorderCls;
  me.initializedBorders = dockedItemsGen;
  me.collapsed = false;
  docked = container.getDockedItems();
  me.collapsed = collapsed;
  header = container.getHeader && container.getHeader();
  if (header) {
    docked = [header].concat(docked);
  }
  for (i = 0, ln = docked.length; i < ln; i++) {
    item = docked[i];
    if (item.getHidden()) {
      continue;
    }
    dock = item.isPanelHeader ? item.getPosition() : item.getDocked();
    mask = edgesTouched = 0;
    addCls.length = 0;
    removeCls.length = 0;
    if (dock !== 'bottom') {
      if (edges & maskT) {
        b = item.border;
      } else {
        b = containerBorder;
        if (b !== false) {
          edgesTouched += maskT;
        }
      }
      if (b === false) {
        mask += maskT;
      }
    }
    if (dock !== 'left') {
      if (edges & maskR) {
        b = item.border;
      } else {
        b = containerBorder;
        if (b !== false) {
          edgesTouched += maskR;
        }
      }
      if (b === false) {
        mask += maskR;
      }
    }
    if (dock !== 'top') {
      if (edges & maskB) {
        b = item.border;
      } else {
        b = containerBorder;
        if (b !== false) {
          edgesTouched += maskB;
        }
      }
      if (b === false) {
        mask += maskB;
      }
    }
    if (dock !== 'right') {
      if (edges & maskL) {
        b = item.border;
      } else {
        b = containerBorder;
        if (b !== false) {
          edgesTouched += maskL;
        }
      }
      if (b === false) {
        mask += maskL;
      }
    }
    if ((lastValue = item.lastBorderMask) !== mask) {
      item.lastBorderMask = mask;
      if (lastValue) {
        removeCls[0] = noBorderCls[lastValue];
      }
      if (mask) {
        addCls[0] = noBorderCls[mask];
      }
    }
    if ((lastValue = item.lastBorderCollapse) !== edgesTouched) {
      item.lastBorderCollapse = edgesTouched;
      if (lastValue) {
        removeCls.push.apply(removeCls, borderCls[lastValue]);
      }
      if (edgesTouched) {
        addCls.push.apply(addCls, borderCls[edgesTouched]);
      }
    }
    if (removeCls.length) {
      item.removeCls(removeCls);
    }
    if (addCls.length) {
      item.addCls(addCls);
    }
    edges |= edgeMasks[dock];
  }
  mask = edgesTouched = 0;
  addCls.length = 0;
  removeCls.length = 0;
  if (edges & maskT) {
    b = bodyBorder;
  } else {
    b = containerBorder;
    if (b !== false) {
      edgesTouched += maskT;
    }
  }
  if (b === false) {
    mask += maskT;
  }
  if (edges & maskR) {
    b = bodyBorder;
  } else {
    b = containerBorder;
    if (b !== false) {
      edgesTouched += maskR;
    }
  }
  if (b === false) {
    mask += maskR;
  }
  if (edges & maskB) {
    b = bodyBorder;
  } else {
    b = containerBorder;
    if (b !== false) {
      edgesTouched += maskB;
    }
  }
  if (b === false) {
    mask += maskB;
  }
  if (edges & maskL) {
    b = bodyBorder;
  } else {
    b = containerBorder;
    if (b !== false) {
      edgesTouched += maskL;
    }
  }
  if (b === false) {
    mask += maskL;
  }
  if ((lastValue = me.lastBodyBorderMask) !== mask) {
    me.lastBodyBorderMask = mask;
    if (lastValue) {
      removeCls[0] = noBorderCls[lastValue];
    }
    if (mask) {
      addCls[0] = noBorderCls[mask];
    }
  }
  if ((lastValue = me.lastBodyBorderCollapse) !== edgesTouched) {
    me.lastBodyBorderCollapse = edgesTouched;
    if (lastValue) {
      removeCls.push.apply(removeCls, borderCls[lastValue]);
    }
    if (edgesTouched) {
      addCls.push.apply(addCls, borderCls[edgesTouched]);
    }
  }
  if (removeCls.length) {
    bodyClsEl.removeCls(removeCls);
  }
  if (addCls.length) {
    bodyClsEl.addCls(addCls);
  }
}, borderCollapseMap:{}, getBorderCollapseTable:function() {
  var me = this, map = me.borderCollapseMap, container = me.getContainer(), classCls = container.classCls, ui = container.getUi(), uiKey = ui || 'default', uiList, table, classClsList, baseCls, uiCls, i, ln, j, uiLen;
  map = map[classCls] || (map[classCls] = {});
  table = map[uiKey];
  if (!table) {
    classClsList = container.classClsList;
    map[uiKey] = table = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []];
    uiList = [0];
    if (ui) {
      uiList = uiList.concat(ui.split(me.spaceRe));
    }
    uiLen = uiList.length;
    for (i = 0, ln = classClsList.length; i < ln; i++) {
      classCls = classClsList[i];
      for (j = 0; j < uiLen; j++) {
        ui = uiList[j];
        uiCls = ui ? '-' + ui : '';
        baseCls = classCls + uiCls + '-outer-border-';
        table[1].push(baseCls + 'l');
        table[2].push(baseCls + 'b');
        table[3].push(baseCls + 'bl');
        table[4].push(baseCls + 'r');
        table[5].push(baseCls + 'rl');
        table[6].push(baseCls + 'rb');
        table[7].push(baseCls + 'rbl');
        table[8].push(baseCls + 't');
        table[9].push(baseCls + 'tl');
        table[10].push(baseCls + 'tb');
        table[11].push(baseCls + 'tbl');
        table[12].push(baseCls + 'tr');
        table[13].push(baseCls + 'trl');
        table[14].push(baseCls + 'trb');
        table[15].push(baseCls + 'trbl');
      }
    }
  }
  return table;
}, setConfig:function(name, value, options) {
  var config = name, alias = this.alias, type = config.type;
  if (name) {
    if (typeof name === 'string') {
      config = {};
      config[name] = value;
    } else {
      options = value;
    }
    if (!type || alias && alias.indexOf('layout.' + type) > -1) {
      this.callParent([config, options]);
    } else {
      Ext.raise('Cannot change layout from ' + this.$className + ' to "' + type + '"');
    }
  }
  return this;
}, privates:{renderInnerItem:function(item, asRoot) {
  item.setRendered(true, asRoot);
}}});
Ext.define('Ext.Indicator', {extend:Ext.Component, xtype:'indicator', config:{activeIndex:null, count:null, direction:'horizontal', tapMode:'direction'}, activeCls:Ext.baseCSSPrefix + 'indicator-active', baseCls:Ext.baseCSSPrefix + 'indicator', itemCls:Ext.baseCSSPrefix + 'indicator-item', defaultBindProperty:'activeIndex', twoWayBindable:['activeIndex'], isIndicator:true, constructor:function(config) {
  this.indicators = [];
  this.callParent([config]);
}, initialize:function() {
  this.callParent();
  this.element.on({tap:'onTap', scope:this});
}, doDestroy:function() {
  Ext.destroy(this.indicators);
  this.callParent();
}, applyActiveIndex:function(index) {
  var indicators = this.indicators, max = indicators.length - 1;
  if (index > max) {
    Ext.raise('Cannot set the active index greater than the number of indicators');
  }
  return index;
}, updateActiveIndex:function(index, oldIndex) {
  var activeCls = this.activeCls, indicators = this.indicators, currentActiveItem = indicators[oldIndex], activeItem = indicators[index];
  if (currentActiveItem) {
    currentActiveItem.removeCls(activeCls);
  }
  if (activeItem) {
    activeItem.addCls(activeCls);
  }
}, updateCount:function(count) {
  var indicators = this.indicators;
  while (indicators.length < count) {
    this.doAdd();
  }
  while (indicators.length > count) {
    this.doRemove();
  }
}, applyDirection:function(direction) {
  if (direction !== 'vertical' && direction !== 'horizontal') {
    Ext.raise('Invalid indicator direction provided: ' + direction);
    direction = 'horizontal';
  }
  return direction;
}, updateDirection:function(newDirection, oldDirection) {
  this.element.replaceCls(oldDirection, newDirection, this.baseCls);
}, sync:function(count, activeIndex) {
  if (Ext.isNumber(count)) {
    this.setCount(count);
  }
  if (Ext.isNumber(activeIndex)) {
    this.setActiveIndex(activeIndex);
  }
  return this;
}, add:function() {
  var count = this.getCount();
  return this.setCount(++count);
}, removeAll:function() {
  return this.setCount(0);
}, remove:function() {
  var count = this.getCount();
  return this.setCount(--count);
}, doAdd:function() {
  var indicators = this.indicators;
  indicators.push(this.element.createChild({tag:'span', cls:this.itemCls}));
  return this;
}, doRemove:function() {
  var indicators = this.indicators, indicator = indicators.pop();
  if (indicator) {
    indicator.destroy();
  }
  return this;
}, onTap:function(e) {
  var mode = this.getTapMode();
  if (mode === 'item') {
    this.onTapItem(e);
  } else {
    this.onTapDirection(e);
  }
}, onTapItem:function(e) {
  var me = this, item = e.getTarget('.' + me.itemCls, 1, true), index;
  if (item) {
    index = me.indicators.indexOf(item);
    if (index !== -1) {
      me.fireEvent('indicatortap', me, index, item);
    }
  } else {
    me.onTapDirection(e);
  }
}, onTapDirection:function(e) {
  var me = this, direction = me.getDirection(), touch = e.touch, box = me.element.getBox(), centerX = box.left + box.width / 2, centerY = box.top + box.height / 2, event = direction === 'horizontal' && touch.pageX >= centerX || direction === 'vertical' && touch.pageY >= centerY ? 'next' : 'previous';
  me.fireEvent(event, me);
}});
Ext.define('Ext.layout.card.fx.Abstract', {extend:Ext.Evented, mixins:[Ext.mixin.Factoryable], alias:'layout.card.fx.abstract', isAnimation:true, config:{direction:null, duration:null, reverse:null, layout:null}, updateLayout:function(layout) {
  if (layout) {
    this.enable();
  }
}, enable:function() {
  var layout = this.getLayout();
  if (layout) {
    layout.on('beforeactiveitemchange', 'onActiveItemChange', this);
  }
}, disable:function() {
  var layout = this.getLayout();
  if (this.isAnimating) {
    this.stopAnimation();
  }
  if (layout) {
    layout.un('beforeactiveitemchange', 'onActiveItemChange', this);
  }
}, onActiveItemChange:Ext.emptyFn, destroy:function() {
  var me = this, layout = me.getLayout();
  if (me.isAnimating) {
    me.stopAnimation();
  }
  if (layout) {
    layout.un('beforeactiveitemchange', 'onActiveItemChange', this);
  }
  me.setLayout(null);
  if (me.observableId) {
    me.fireEvent('destroy', this);
  }
  me.callParent();
}});
Ext.define('Ext.layout.card.fx.Style', {extend:Ext.layout.card.fx.Abstract, config:{inAnimation:{before:{visibility:null}, preserveEndState:false, replacePrevious:true}, outAnimation:{preserveEndState:false, replacePrevious:true}}, isAnimating:false, constructor:function(config) {
  var inAnimation, outAnimation;
  this.callParent([config]);
  this.endAnimationCounter = 0;
  inAnimation = this.getInAnimation();
  outAnimation = this.getOutAnimation();
  inAnimation.on('animationend', 'incrementEnd', this);
  outAnimation.on('animationend', 'incrementEnd', this);
}, updateDirection:function(direction) {
  this.getInAnimation().setDirection(direction);
  this.getOutAnimation().setDirection(direction);
}, updateDuration:function(duration) {
  this.getInAnimation().setDuration(duration);
  this.getOutAnimation().setDuration(duration);
}, updateReverse:function(reverse) {
  this.getInAnimation().setReverse(reverse);
  this.getOutAnimation().setReverse(reverse);
}, incrementEnd:function() {
  this.endAnimationCounter++;
  if (this.endAnimationCounter > 1) {
    this.endAnimationCounter = 0;
    this.fireEvent('animationend', this);
  }
}, applyInAnimation:function(animation, inAnimation) {
  return Ext.factory(animation, Ext.fx.Animation, inAnimation);
}, applyOutAnimation:function(animation, outAnimation) {
  return Ext.factory(animation, Ext.fx.Animation, outAnimation);
}, updateInAnimation:function(animation) {
  animation.setScope(this);
}, updateOutAnimation:function(animation) {
  animation.setScope(this);
}, onActiveItemChange:function(cardLayout, newItem, oldItem, controller) {
  var me = this, inElement, outElement, inAnimation, outAnimation;
  if (newItem && oldItem && oldItem.isPainted()) {
    inAnimation = me.getInAnimation();
    outAnimation = me.getOutAnimation();
    inElement = newItem.renderElement;
    outElement = oldItem.renderElement;
    inAnimation.setElement(inElement);
    outAnimation.setElement(outElement);
    outAnimation.setOnEnd(function() {
      me.isAnimating = false;
      controller.resume();
    });
    inElement.dom.style.setProperty('visibility', 'hidden', 'important');
    newItem.show();
    cardLayout.renderInnerItem(newItem, true);
    me.isAnimating = true;
    Ext.Animator.run([outAnimation, inAnimation]);
    controller.pause();
  }
}, destroy:function() {
  Ext.destroy(this.getInAnimation(), this.getOutAnimation());
  this.callParent();
}});
Ext.define('Ext.layout.card.fx.Cover', {extend:Ext.layout.card.fx.Style, alias:'layout.card.fx.cover', config:{reverse:null, inAnimation:{before:{'z-index':100}, after:{'z-index':0}, type:'slide', easing:'ease-out'}, outAnimation:{easing:'ease-out', from:{opacity:0.99}, to:{opacity:1}, out:true}}});
Ext.define('Ext.layout.card.fx.Cube', {extend:Ext.layout.card.fx.Style, alias:'layout.card.fx.cube', config:{reverse:null, inAnimation:{type:'cube'}, outAnimation:{type:'cube', out:true}}});
Ext.define('Ext.layout.card.fx.Serial', {extend:Ext.layout.card.fx.Style, duration:500, updateDuration:function(duration) {
  var halfDuration = duration / 2, inAnimation = this.getInAnimation(), outAnimation = this.getOutAnimation();
  inAnimation.setDelay(halfDuration);
  inAnimation.setDuration(halfDuration);
  outAnimation.setDuration(halfDuration);
}});
Ext.define('Ext.layout.card.fx.Fade', {extend:Ext.layout.card.fx.Serial, alias:'layout.card.fx.fade', config:{reverse:null, inAnimation:{type:'fade', easing:'ease-out'}, outAnimation:{type:'fade', easing:'ease-out', out:true}}});
Ext.define('Ext.layout.card.fx.Flip', {extend:Ext.layout.card.fx.Serial, alias:'layout.card.fx.flip', config:{inAnimation:{type:'flip', half:true, easing:'ease-out', before:{'backface-visibility':'hidden'}, after:{'backface-visibility':null}}, outAnimation:{type:'flip', half:true, easing:'ease-in', before:{'backface-visibility':'hidden'}, after:{'backface-visibility':null}, out:true}}, onActiveItemChange:function(cardLayout, newItem, oldItem, controller) {
  var parent = newItem.element.getParent();
  parent.addCls(Ext.baseCSSPrefix + 'layout-card-perspective');
  this.on('animationend', function() {
    parent.removeCls(Ext.baseCSSPrefix + 'layout-card-perspective');
  }, this, {single:true});
  this.callParent(arguments);
}});
Ext.define('Ext.layout.card.fx.Pop', {extend:Ext.layout.card.fx.Serial, alias:'layout.card.fx.pop', config:{inAnimation:{type:'pop', easing:'ease-out'}, outAnimation:{type:'pop', easing:'ease-in', out:true}}});
Ext.define('Ext.layout.card.fx.Reveal', {extend:Ext.layout.card.fx.Style, alias:'layout.card.fx.reveal', config:{inAnimation:{easing:'ease-out', from:{opacity:0.99}, to:{opacity:1}}, outAnimation:{before:{'z-index':100}, after:{'z-index':0}, type:'slide', easing:'ease-out', out:true}}});
Ext.define('Ext.layout.card.fx.Scroll', {extend:Ext.layout.card.fx.Abstract, alias:'layout.card.fx.scroll', config:{duration:150}, getEasing:function() {
  var easing = this.easing;
  if (!easing) {
    this.easing = easing = new Ext.fx.easing.Linear;
  }
  return easing;
}, updateDuration:function(duration) {
  this.getEasing().setDuration(duration);
}, onActiveItemChange:function(cardLayout, newItem, oldItem, controller) {
  var direction = this.getDirection(), easing = this.getEasing(), containerElement, inElement, outElement, containerWidth, containerHeight, reverse;
  if (newItem && oldItem) {
    if (this.isAnimating) {
      this.stopAnimation();
    }
    newItem.setWidth('100%');
    newItem.setHeight('100%');
    containerElement = this.getLayout().container.bodyElement;
    containerWidth = containerElement.getWidth();
    containerHeight = containerElement.getHeight();
    inElement = newItem.renderElement;
    outElement = oldItem.renderElement;
    this.oldItem = oldItem;
    this.newItem = newItem;
    this.containerElement = containerElement;
    this.currentEventController = controller;
    this.isReverse = reverse = this.getReverse();
    newItem.show();
    if (direction === 'right') {
      direction = 'left';
      this.isReverse = reverse = !reverse;
    } else {
      if (direction === 'down') {
        direction = 'up';
        this.isReverse = reverse = !reverse;
      }
    }
    if (direction === 'left') {
      if (reverse) {
        easing.setConfig({startValue:containerWidth, endValue:0});
        containerElement.dom.scrollLeft = containerWidth;
        outElement.setLeft(containerWidth);
      } else {
        easing.setConfig({startValue:0, endValue:containerWidth});
        inElement.setLeft(containerWidth);
      }
    } else {
      if (reverse) {
        easing.setConfig({startValue:containerHeight, endValue:0});
        containerElement.dom.scrollTop = containerHeight;
        outElement.setTop(containerHeight);
      } else {
        easing.setConfig({startValue:0, endValue:containerHeight});
        inElement.setTop(containerHeight);
      }
    }
    this.startAnimation();
    controller.pause();
  }
}, startAnimation:function() {
  this.isAnimating = true;
  this.getEasing().setStartTime(Date.now());
  Ext.AnimationQueue.start(this.doAnimationFrame, this);
}, doAnimationFrame:function() {
  var easing = this.getEasing(), direction = this.getDirection(), scroll = 'scrollTop', value;
  if (direction === 'left' || direction === 'right') {
    scroll = 'scrollLeft';
  }
  if (easing.isEnded) {
    this.stopAnimation();
  } else {
    value = easing.getValue();
    this.containerElement.dom[scroll] = value;
  }
}, stopAnimation:function() {
  var me = this, direction = me.getDirection(), scroll = 'setTop', oldItem = me.oldItem, newItem = me.newItem;
  if (direction === 'left' || direction === 'right') {
    scroll = 'setLeft';
  }
  me.currentEventController.resume();
  if (me.isReverse && oldItem && oldItem.renderElement && oldItem.renderElement.dom) {
    oldItem.renderElement[scroll](null);
  } else {
    if (newItem && newItem.renderElement && newItem.renderElement.dom) {
      newItem.renderElement[scroll](null);
    }
  }
  Ext.AnimationQueue.stop(this.doAnimationFrame, this);
  me.isAnimating = false;
  me.fireEvent('animationend', me);
}});
Ext.define('Ext.layout.card.fx.ScrollCover', {extend:Ext.layout.card.fx.Scroll, alias:'layout.card.fx.scrollcover', onActiveItemChange:function(cardLayout, inItem, outItem, controller) {
  var containerElement, containerSize, xy, animConfig, inTranslate, outTranslate;
  this.currentEventController = controller;
  this.inItem = inItem;
  if (inItem && outItem) {
    containerElement = this.getLayout().container.bodyElement;
    containerSize = containerElement.getSize();
    xy = this.calculateXY(containerSize);
    animConfig = {easing:this.getEasing(), duration:this.getDuration()};
    inItem.renderElement.dom.style.setProperty('visibility', 'hidden', 'important');
    inTranslate = inItem.setTranslatable(true).getTranslatable();
    outTranslate = outItem.setTranslatable(true).getTranslatable();
    outTranslate.translate({x:0, y:0});
    inTranslate.translate({x:xy.left, y:xy.top});
    inTranslate.getWrapper().dom.style.setProperty('z-index', '100', 'important');
    inItem.show();
    inTranslate.on({animationstart:'onInAnimationStart', animationend:'onInAnimationEnd', scope:this});
    inTranslate.translateAnimated({x:0, y:0}, animConfig);
    controller.pause();
  }
}, onInAnimationStart:function() {
  this.inItem.renderElement.dom.style.removeProperty('visibility');
}, onInAnimationEnd:function() {
  var wrapper;
  if (!this.destroyed) {
    wrapper = this.inItem.getTranslatable().getWrapper();
    wrapper.dom.style.removeProperty('z-index');
    this.currentEventController.resume();
  }
}});
Ext.define('Ext.layout.card.fx.ScrollReveal', {extend:Ext.layout.card.fx.Scroll, alias:'layout.card.fx.scrollreveal', onActiveItemChange:function(cardLayout, inItem, outItem, controller) {
  var containerElement, containerSize, xy, animConfig, outTranslate, inTranslate;
  this.currentEventController = controller;
  this.outItem = outItem;
  this.inItem = inItem;
  if (inItem && outItem) {
    containerElement = this.getLayout().container.bodyElement;
    containerSize = containerElement.getSize();
    xy = this.calculateXY(containerSize);
    animConfig = {easing:this.getEasing(), duration:this.getDuration()};
    outTranslate = outItem.setTranslatable(true).getTranslatable();
    inTranslate = inItem.setTranslatable(true).getTranslatable();
    outTranslate.getWrapper().dom.style.setProperty('z-index', '100', 'important');
    outTranslate.translate({x:0, y:0});
    inTranslate.translate({x:0, y:0});
    inItem.show();
    outTranslate.on({animationend:'onOutAnimationEnd', scope:this});
    outTranslate.translateAnimated({x:xy.x, y:xy.y}, animConfig);
    controller.pause();
  }
}, onOutAnimationEnd:function() {
  var wrapper;
  if (!this.destroyed) {
    wrapper = this.outItem.getTranslatable().getWrapper();
    wrapper.dom.style.removeProperty('z-index');
    this.currentEventController.resume();
  }
}});
Ext.define('Ext.layout.card.fx.Slide', {extend:Ext.layout.card.fx.Style, alias:'layout.card.fx.slide', config:{inAnimation:{type:'slide', easing:'ease-out'}, outAnimation:{type:'slide', easing:'ease-out', out:true}}});
Ext.define('Ext.layout.Card', {extend:Ext.layout.Auto, alias:'layout.card', type:'card', isCard:true, config:{indicator:{lazy:true, $value:{xtype:'indicator', flex:1}}}, deferRender:true, cls:Ext.baseCSSPrefix + 'layout-card', itemCls:Ext.baseCSSPrefix + 'layout-card-item', applyAnimation:function(animation) {
  return animation ? new Ext.Factory.layoutCardFx(animation) : null;
}, updateAnimation:function(animation, oldAnimation) {
  var me = this, direction;
  me.autoDirection = null;
  if (animation && animation.isAnimation) {
    animation.setLayout(me);
    direction = animation.getDirection();
    if (!direction || me.autoDirectionMap[direction]) {
      me.autoDirection = direction || 'horizontal';
      animation.setDirection(null);
    }
  }
  if (oldAnimation) {
    oldAnimation.destroy();
  }
}, applyIndicator:function(indicator, currentIndicator) {
  return Ext.updateWidget(currentIndicator, indicator, this, 'createIndicator');
}, createIndicator:function(indicator) {
  return Ext.apply({ownerCmp:this.getContainer()}, indicator);
}, updateIndicator:function(indicator) {
  var container, innerItems, activeItem;
  if (indicator) {
    container = this.getContainer();
    innerItems = container.getInnerItems();
    activeItem = container.getActiveItem();
    indicator.sync(innerItems.length, innerItems.indexOf(activeItem)).on({indicatortap:'onIndicatorTap', next:'next', previous:'previous', scope:this});
  }
}, onContainerInitialized:function(container) {
  var me = this, firstItem = container.getInnerAt(0), activeItem = container.getActiveItem(), minHeight = container.getMinHeight();
  if (Ext.isIE && minHeight != null && container.getHeight() == null) {
    container.setHeight(minHeight);
  }
  me.callParent([container]);
  if (activeItem) {
    activeItem.show();
    if (firstItem && firstItem !== activeItem) {
      firstItem.hide();
    }
  }
  container.on('activeitemchange', 'onContainerActiveItemChange', me);
}, onContainerActiveItemChange:function(container, newItem, oldItem) {
  var me = this, innerItems = container.getInnerItems(), newIndex = innerItems.indexOf(newItem), oldIndex = innerItems.indexOf(oldItem), animation = me.getAnimation(), autoDirection = me.autoDirection, horizontal = autoDirection && autoDirection === 'horizontal', direction;
  if (autoDirection && newIndex !== -1 && oldIndex !== -1) {
    if (newIndex < oldIndex) {
      direction = horizontal ? 'right' : 'up';
    } else {
      direction = horizontal ? 'left' : 'down';
    }
    animation.setDirection(direction);
  }
  me.fireEventedAction('activeitemchange', [me, newItem, oldItem], 'doActiveItemChange', me);
}, onItemInnerStateChange:function(item, isInner, destroying) {
  var container, activeItem;
  this.callParent([item, isInner, destroying]);
  container = this.getContainer();
  activeItem = container.getActiveItem();
  if (isInner) {
    if (activeItem !== container.innerIndexOf(item) && activeItem !== item && item !== container.pendingActiveItem) {
      item.hide();
    }
  } else {
    if (!destroying && !item.destroyed && item.destroying !== true) {
      item.show();
    }
  }
}, doActiveItemChange:function(me, newActiveItem, oldActiveItem) {
  var indicator = me.getConfig('indicator', null, true), container, innerItems;
  if (oldActiveItem && !oldActiveItem.destroyed) {
    oldActiveItem.hide();
  }
  if (newActiveItem && !newActiveItem.destroyed) {
    me.showItem(newActiveItem);
    if (indicator) {
      container = this.getContainer();
      innerItems = container.getInnerItems();
      indicator.setActiveIndex(innerItems.indexOf(newActiveItem));
    }
  }
}, onItemAdd:function(item, index) {
  var indicator, style;
  this.callParent([item, index]);
  if (item.isInnerItem()) {
    indicator = this.getConfig('indicator', null, true);
    if (indicator) {
      indicator.add();
    }
    style = item.element.dom.style;
    style.width = style.height = '';
  }
}, onItemRemove:function(item, index, destroying) {
  var indicator, w, h;
  this.callParent([item, index, destroying]);
  if (item.isInnerItem()) {
    indicator = this.getConfig('indicator', null, true);
    if (indicator) {
      indicator.remove();
    }
    w = item.getWidth();
    h = item.getHeight();
    item.setWidth(null).setWidth(w);
    item.setHeight(null).setHeight(h);
  }
}, next:function() {
  var container = this.getContainer(), activeItem = container.getActiveItem(), innerItems = container.getInnerItems(), index = innerItems.indexOf(activeItem);
  activeItem = innerItems[index + 1];
  if (activeItem) {
    container.setActiveItem(activeItem);
  }
}, previous:function() {
  var container = this.getContainer(), activeItem = container.getActiveItem(), innerItems = container.getInnerItems(), index = innerItems.indexOf(activeItem);
  activeItem = innerItems[index - 1];
  if (activeItem) {
    container.setActiveItem(activeItem);
  }
}, onIndicatorTap:function(indicator, index) {
  var container = this.getContainer();
  container.setActiveItem(index);
}, destroy:function() {
  Ext.destroy(this.getAnimation(), this.getIndicator());
  this.callParent();
}, privates:{autoDirectionMap:{horizontal:1, vertical:1}, renderInnerItem:function(item, asRoot) {
  if (!this.deferRender || this.getContainer().getActiveItem() === item) {
    this.callParent([item, asRoot]);
  }
}, showItem:function(item) {
  item.show();
  if (this.getContainer().rendered) {
    item.setRendered(true, true);
  }
}}});
Ext.define('Ext.util.InputBlocker', {singleton:true, blockInputs:function() {
  if (Ext.browser.is.ie) {
    Ext.select('.x-field-text .x-input:not(.x-item-disabled) .x-input-el, .x-field-textarea ' + '.x-input:not(.x-item-disabled) .x-input-el, .x-field-search ' + '.x-input:not(.x-item-disabled) .x-input-el').each(function(item) {
      if (item.dom.offsetWidth > 0) {
        item.dom.setAttribute('disabled', true);
        item.dom.setAttribute('overlayfix', true);
      }
    });
  }
}, unblockInputs:function() {
  if (Ext.browser.is.ie) {
    Ext.select('[overlayfix]').each(function(item) {
      item.dom.removeAttribute('disabled');
      item.dom.removeAttribute('overlayfix');
    });
  }
}});
Ext.define('Ext.viewport.Default', function() {
  var TOP = 1, RIGHT = 2, BOTTOM = 4, LEFT = 8, sideMap = {top:TOP, right:RIGHT, bottom:BOTTOM, left:LEFT}, oppositeSide = {1:BOTTOM, 2:LEFT, 4:TOP, 8:RIGHT}, oppositeSideNames = {left:'right', right:'left', top:'bottom', bottom:'top', up:'bottom', down:'top'};
  return {extend:Ext.Container, xtype:'viewport', PORTRAIT:'portrait', LANDSCAPE:'landscape', nameHolder:true, config:{autoMaximize:false, autoBlurInput:true, preventZooming:false, autoRender:true, layout:'card', width:'100%', height:'100%', menus:{}, orientation:null, swipeThreshold:30}, classCls:Ext.baseCSSPrefix + 'viewport', getTemplate:function() {
    var template = this.callParent();
    if (!Ext.feature.has.MatchMedia) {
      template.unshift({reference:'orientationElement', className:Ext.baseCSSPrefix + 'orientation-inspector', children:[{className:Ext.baseCSSPrefix + 'orientation-inspector-landscape'}]});
    }
    return template;
  }, isReady:false, isViewport:true, isMaximizing:false, id:'ext-viewport', isInputRegex:/^(input|textarea|select|a)$/i, isInteractiveWebComponentRegEx:/^(audio|video)$/i, notScalableRe:/user-scalable=no/, focusable:false, focusEl:null, ariaEl:null, allSidesCls:[Ext.baseCSSPrefix + 'top', Ext.baseCSSPrefix + 'right', Ext.baseCSSPrefix + 'bottom', Ext.baseCSSPrefix + 'left'], sideClsMap:{top:Ext.baseCSSPrefix + 'top', right:Ext.baseCSSPrefix + 'right', bottom:Ext.baseCSSPrefix + 'bottom', left:Ext.baseCSSPrefix + 
  'left'}, hasViewportCls:Ext.baseCSSPrefix + 'has-viewport', fixedCls:Ext.baseCSSPrefix + 'fixed-viewport', fullscreenItemCls:Ext.baseCSSPrefix + 'fullscreen', constructor:function(config) {
    var me = this, scroller;
    me.doPreventPanning = me.doPreventPanning.bind(me);
    me.doPreventZooming = me.doPreventZooming.bind(me);
    me.maximizeOnEvents = ['ready', 'orientationchange'];
    window.devicePixelRatio = window.devicePixelRatio || 1;
    me.callParent([config]);
    me.updateSize();
    me.windowOuterHeight = me.getWindowOuterHeight();
    scroller = me.getScrollable();
    if (!scroller) {
      scroller = Ext.getViewportScroller().setConfig({x:false, y:false});
      scroller.component = me;
    }
    Ext.setViewportScroller(scroller);
    Ext.getBody().setStyle('overflow', 'hidden');
    Ext.get(document.documentElement).addCls(me.hasViewportCls);
    me.stretchHeights = me.stretchHeights || {};
    if (Ext.feature.has.OrientationChange) {
      me.addWindowListener('orientationchange', me.onOrientationChange.bind(me));
    }
    if (!Ext.os.is.iOS || !me.isScalable()) {
      Ext.get(document.documentElement).addCls(me.fixedCls);
    }
    Ext.GlobalEvents.on('resize', 'onWindowResize', me, {priority:1000});
    Ext.onDocumentReady(me.onDomReady, me);
    return me;
  }, initialize:function() {
    var me = this;
    me.addMeta('apple-mobile-web-app-capable', 'yes');
    me.addMeta('apple-touch-fullscreen', 'yes');
    me.callParent();
  }, getRefItems:function(deep) {
    var menus = this.getMenus(), result = this.callParent([deep]), side, menu;
    for (side in menus) {
      menu = menus[side];
      if (menu) {
        Ext.Array.include(result, menu);
      }
    }
    return result;
  }, initInheritedState:function(inheritedState, inheritedStateInner) {
    var me = this, root = Ext.rootInheritedState;
    if (inheritedState !== root) {
      me.initInheritedState(me.inheritedState = root, me.inheritedStateInner = Ext.Object.chain(root));
    } else {
      me.callParent([inheritedState, inheritedStateInner]);
    }
  }, onAppLaunch:function() {
    var me = this;
    if (!me.isReady) {
      me.onDomReady();
    }
  }, onDomReady:function() {
    var me = this;
    if (me.isReady) {
      return;
    }
    me.isReady = true;
    me.updateSize();
    me.onReady();
    me.fireEvent('ready', me);
    Ext.GlobalEvents.fireEvent('viewportready', me);
  }, onReady:function() {
    if (this.getAutoRender()) {
      this.render();
    }
  }, render:function() {
    var me = this, body = Ext.getBody();
    if (!me.rendered) {
      me.callParent([body, Ext.floatRoot]);
      me.setOrientation(me.determineOrientation());
      Ext.getBody().addCls(Ext.baseCSSPrefix + me.getOrientation());
    }
  }, applyAutoMaximize:function(autoMaximize) {
    return Ext.browser.is.WebView ? false : autoMaximize;
  }, updateAutoMaximize:function(autoMaximize) {
    var me = this;
    if (autoMaximize) {
      me.on('ready', 'doAutoMaximizeOnReady', me, {single:true});
      me.on('orientationchange', 'doAutoMaximizeOnOrientationChange', me);
    } else {
      me.un('ready', 'doAutoMaximizeOnReady', me);
      me.un('orientationchange', 'doAutoMaximizeOnOrientationChange', me);
    }
  }, updatePreventPanning:function(preventPanning) {
    this.toggleWindowListener(preventPanning, 'touchmove', this.doPreventPanning, false);
  }, updatePreventZooming:function(preventZooming) {
    var touchstart = Ext.feature.has.TouchEvents ? 'touchstart' : 'mousedown';
    this.toggleWindowListener(preventZooming, touchstart, this.doPreventZooming, false);
  }, doAutoMaximizeOnReady:function() {
    var me = this;
    me.isMaximizing = true;
    me.on('maximize', function() {
      me.isMaximizing = false;
      me.updateSize();
      me.fireEvent('ready', me);
    }, me, {single:true});
    me.maximize();
  }, doAutoMaximizeOnOrientationChange:function() {
    var me = this;
    me.isMaximizing = true;
    me.on('maximize', function() {
      me.isMaximizing = false;
      me.updateSize();
    }, me, {single:true});
    me.maximize();
  }, doPreventPanning:function(e) {
    var me = this, target = e.target, touch;
    if (me.isInteractiveWebComponentRegEx.test(target.tagName) && e.touches && e.touches.length > 0) {
      touch = e.touches[0];
      if (touch && touch.target && me.isInputRegex.test(touch.target.tagName)) {
        return;
      }
    }
    if (target && target.nodeType === 1 && !me.isInputRegex.test(target.tagName)) {
      e.preventDefault();
    }
  }, doPreventZooming:function(e) {
    if ('button' in e && e.button !== 0) {
      return;
    }
    var target = e.target, inputRe = this.isInputRegex, touch;
    if (this.isInteractiveWebComponentRegEx.test(target.tagName) && e.touches && e.touches.length > 0) {
      touch = e.touches[0];
      if (touch && touch.target && inputRe.test(touch.target.tagName)) {
        return;
      }
    }
    if (target && target.nodeType === 1 && !inputRe.test(target.tagName)) {
      e.preventDefault();
    }
  }, addWindowListener:function(eventName, fn, capturing) {
    window.addEventListener(eventName, fn, Boolean(capturing));
  }, removeWindowListener:function(eventName, fn, capturing) {
    window.removeEventListener(eventName, fn, Boolean(capturing));
  }, supportsOrientation:function() {
    return Ext.feature.has.Orientation;
  }, supportsMatchMedia:function() {
    return Ext.feature.has.MatchMedia;
  }, onOrientationChange:function() {
    this.setOrientation(this.determineOrientation());
  }, determineOrientation:function() {
    var me = this, orientationElement = me.orientationElement, nativeOrientation, visible;
    if (me.supportsOrientation()) {
      nativeOrientation = me.getWindowOrientation();
      if (Math.abs(nativeOrientation) === 90 || nativeOrientation === 270) {
        return me.LANDSCAPE;
      }
      return me.PORTRAIT;
    }
    if (me.supportsMatchMedia()) {
      return window.matchMedia('(orientation : landscape)').matches ? me.LANDSCAPE : me.PORTRAIT;
    }
    if (orientationElement) {
      visible = orientationElement.first().isVisible();
      return visible ? me.LANDSCAPE : me.PORTRAIT;
    }
    return null;
  }, updateOrientation:function(newValue, oldValue) {
    if (oldValue) {
      this.fireOrientationChangeEvent(newValue, oldValue);
    }
  }, fireOrientationChangeEvent:function(newOrientation, oldOrientation) {
    var me = this, newSize = me.updateSize();
    Ext.getBody().replaceCls(Ext.baseCSSPrefix + oldOrientation, Ext.baseCSSPrefix + newOrientation);
    me.fireEvent('orientationchange', me, newOrientation, newSize.width, newSize.height);
  }, onWindowResize:function(width, height) {
    var me = this, oldWidth = me.lastSize.width, oldHeight = me.lastSize.height;
    me.updateSize(width, height);
    me.setOrientation(me.determineOrientation());
    if (width != null) {
      me.fireEvent('resize', this, width, height, oldWidth, oldHeight);
    }
  }, updateSize:function(width, height) {
    var lastSize = this.lastSize;
    lastSize.width = width !== undefined ? width : this.getWindowWidth();
    lastSize.height = height !== undefined ? height : this.getWindowHeight();
    return lastSize;
  }, waitUntil:function(condition, onSatisfied, onTimeout, delay, timeoutDuration) {
    var scope = this, elapse = 0;
    if (!delay) {
      delay = 50;
    }
    if (!timeoutDuration) {
      timeoutDuration = 2000;
    }
    Ext.defer(function repeat() {
      elapse += delay;
      if (condition.call(scope) === true) {
        if (onSatisfied) {
          onSatisfied.call(scope);
        }
      } else {
        if (elapse >= timeoutDuration) {
          if (onTimeout) {
            onTimeout.call(scope);
          }
        } else {
          Ext.defer(repeat, delay);
        }
      }
    }, delay);
  }, maximize:function() {
    this.fireMaximizeEvent();
  }, fireMaximizeEvent:function() {
    this.updateSize();
    this.fireEvent('maximize', this);
  }, updateHeight:function(height, oldHeight) {
    Ext.getBody().setHeight(height);
    this.callParent([height, oldHeight]);
  }, updateWidth:function(width, oldWidth) {
    Ext.getBody().setWidth(width);
    this.callParent([width, oldWidth]);
  }, scrollToTop:function() {
    window.scrollTo(0, -1);
  }, getWindowWidth:function() {
    return window.innerWidth;
  }, getWindowHeight:function() {
    return window.innerHeight;
  }, getWindowOuterHeight:function() {
    return window.outerHeight;
  }, getWindowOrientation:function() {
    return window.orientation;
  }, getSize:function() {
    return this.lastSize;
  }, setItemFullScreen:function(item) {
    item.addCls(this.fullscreenItemCls);
    item.setTop(0);
    item.setRight(0);
    item.setBottom(0);
    item.setLeft(0);
    this.add(item);
  }, setMenu:function(menu, config) {
    var me = this, side, menus, oldMenu;
    config = config || {};
    if (config.reveal && config.cover) {
      Ext.raise('[Ext.Viewport] setMenu(): Only one of reveal or cover is allowed');
    }
    if (Ext.os.is.iOS && !me.hasiOSOrientationFix) {
      me.hasiOSOrientationFix = true;
      me.on('orientationchange', function() {
        window.scrollTo(0, 0);
      }, me);
    }
    if (!menu) {
      Ext.raise('You must specify a menu configuration.');
    }
    menus = me.getMenus();
    if (!me.addedSwipeListener) {
      me.attachSwipeListeners();
      me.addedSwipeListener = true;
    }
    menu = me.configureMenu(menu, config);
    side = menu.getSide();
    oldMenu = menus[side];
    if (oldMenu && !oldMenu.destroyed && oldMenu !== menu) {
      me.hideMenu(side);
      oldMenu.setSide(null);
    }
    menus[side] = menu;
    me.setMenus(menus);
    return menu;
  }, attachSwipeListeners:function() {
    var me = this;
    me.element.on({tap:me.onTap, swipestart:me.onSwipeStart, edgeswipestart:me.onEdgeSwipeStart, edgeswipe:me.onEdgeSwipe, edgeswipeend:me.onEdgeSwipeEnd, scope:me});
  }, configureMenu:function(menu, config) {
    var isInstanced = menu.isComponent, reveal = isInstanced && !('reveal' in config) ? menu.getReveal() : !!config.reveal, cover = (isInstanced && !('cover' in config) ? menu.getCover() : config.cover) !== false && !reveal, side = isInstanced && !('side' in config) ? menu.getSide() : config.side, wasFloated;
    if (!side) {
      Ext.raise('You must specify a side to dock the menu.');
    }
    if (!sideMap[side]) {
      Ext.raise('Invalid side; must left, right, top or bottom.');
    }
    config = {hideAnimation:null, showAnimation:null, hidden:true, floated:cover, zIndex:cover ? null : 5, reveal:reveal, cover:cover, side:side};
    config[oppositeSideNames[side]] = null;
    if (isInstanced) {
      wasFloated = menu.getFloated();
      if (config.floated !== wasFloated) {
        if (menu.rendered) {
          if (wasFloated) {
            this.remove(menu, false);
          } else {
            menu.el.dom.parentNode.removeChild(menu.el.dom);
            menu.setRendered(false);
          }
        }
        menu.setConfig({top:null, right:null, bottom:null, left:null});
      }
      menu.setConfig(config, null, {strict:false});
    } else {
      config.xtype = 'actionsheet';
      menu = Ext.create(Ext.apply(config, menu));
    }
    config = {left:0, right:0, top:0, bottom:0};
    config[oppositeSideNames[side]] = null;
    menu.setConfig(config);
    menu.toggleCls(menu.floatingCls, !menu.getFloated());
    menu.removeCls(this.getLayout().itemCls);
    menu.toggleCls(Ext.baseCSSPrefix + 'menu-cover', cover);
    menu.toggleCls(Ext.baseCSSPrefix + 'menu-reveal', reveal);
    menu.replaceCls(this.allSidesCls, this.sideClsMap[side]);
    menu.isViewportMenu = true;
    return menu;
  }, removeMenu:function(side, animation) {
    var me = this, menus = me.getMenus() || {}, menu = menus[side];
    if (menu) {
      me.hideMenu(side, animation);
      menu.removeCls(me.sideClsMap[side]);
    }
    delete menus[side];
    me.setMenus(menus);
  }, showMenu:function(side, animation) {
    var me = this, sideValue = sideMap[side], menu = me.getMenus()[side], viewportAfter = {translateX:0, translateY:0}, size;
    if (!menu || !menu.isHidden()) {
      return;
    }
    if (animation === false) {
      menu.show(false, {side:null});
      return;
    }
    me.beforeMenuAnimate(menu);
    size = menu.element.measure(sideValue & (LEFT | RIGHT) ? 'w' : 'h');
    if (sideValue === LEFT) {
      viewportAfter.translateX = size;
    } else {
      if (sideValue === RIGHT) {
        viewportAfter.translateX = -size;
      } else {
        if (sideValue === TOP) {
          viewportAfter.translateY = size;
        } else {
          if (sideValue === BOTTOM) {
            viewportAfter.translateY = -size;
          }
        }
      }
    }
    menu.translate(0, 0, {duration:200});
    if (!menu.getFloated()) {
      me.translate(viewportAfter.translateX, viewportAfter.translateY, {duration:200});
    }
  }, hideMenu:function(side, animation) {
    var me = this, sideValue = sideMap[side], menu = me.getMenus()[side], after = {translateX:0, translateY:0}, size;
    animation = animation !== false;
    if (!menu || menu.isHidden()) {
      return;
    }
    size = menu.element.measure(sideValue & (LEFT | RIGHT) ? 'w' : 'h');
    if (sideValue === LEFT) {
      after.translateX = -size;
    } else {
      if (sideValue === RIGHT) {
        after.translateX = size;
      } else {
        if (sideValue === TOP) {
          after.translateY = -size;
        } else {
          if (sideValue === BOTTOM) {
            after.translateY = size;
          }
        }
      }
    }
    if (animation) {
      menu.revertFocus();
      menu.translate(after.translateX, after.translateY, {duration:200, callback:function() {
        if (!menu.destroyed) {
          menu.translate(0, 0);
          menu.setHidden(true);
        }
      }});
    } else {
      menu.getTranslatable().stopAnimation();
      menu.setHidden(true);
    }
    if (!menu.getFloated()) {
      me.translate(0, 0, animation ? {duration:200} : null);
    }
  }, hideAllMenus:function(animation) {
    var menus = this.getMenus(), side;
    for (side in menus) {
      this.hideMenu(side, animation);
    }
  }, hideOtherMenus:function(side, animate) {
    var menus = this.getMenus(), menu;
    for (menu in menus) {
      if (side !== menu) {
        this.hideMenu(menu, animate);
      }
    }
  }, toggleMenu:function(side) {
    var menus = this.getMenus(), menu;
    if (menus[side]) {
      menu = menus[side];
      menu.setDisplayed(menu.isHidden());
    }
  }, applyScrollable:function(scrollable) {
    return this.callParent([scrollable, Ext.getViewportScroller()]);
  }, doDestroy:function() {
    var me = this, docEl = Ext.get(document.documentElement), scroller = me._scrollable;
    docEl.removeCls(me.hasViewportCls);
    docEl.removeCls(me.fixedCls);
    if (scroller) {
      scroller.setConfig({x:true, y:true});
      me._scrollable = null;
    }
    Ext.un('resize', 'onWindowResize', me);
    me.callParent();
    Ext.Viewport = null;
  }, privates:{addMeta:function(name, content) {
    var meta = document.createElement('meta');
    meta.setAttribute('name', name);
    meta.setAttribute('content', content);
    Ext.getHead().append(meta);
  }, beforeMenuAnimate:function(menu) {
    var me = this, side = menu.getSide(), sideValue = sideMap[side], before = {translateX:0, translateY:0}, size, modal;
    me.hideOtherMenus(side);
    if (menu.getFloated()) {
      me.add(menu);
    } else {
      Ext.getBody().insertFirst(menu.element);
      if (!menu.rendered) {
        menu.setRendered(true);
      }
      modal = menu.getModal();
      if (modal) {
        Ext.getBody().insertFirst(modal.element);
        if (!modal.rendered) {
          modal.setRendered(true);
        }
      }
      me.translate(0, 0);
    }
    menu.removeCls(me.getLayout().itemCls);
    menu.show(false, {side:null});
    size = menu.element.measure(sideValue & (LEFT | RIGHT) ? 'w' : 'h');
    if (sideValue === LEFT) {
      before.translateX = -size;
    } else {
      if (sideValue === RIGHT) {
        before.translateX = size;
      } else {
        if (sideValue === TOP) {
          before.translateY = -size;
        } else {
          if (sideValue === BOTTOM) {
            before.translateY = size;
          }
        }
      }
    }
    menu.translate(before.translateX, before.translateY);
  }, disableTabbing:function() {
    if (this.tabbingDisabled) {
      return;
    }
    this.tabbingDisabled = true;
    this.callParent();
  }, enableTabbing:function(reset) {
    if (!this.tabbingDisabled) {
      return;
    }
    this.tabbingDisabled = false;
    this.callParent([reset]);
  }, doAddListener:function(eventName, fn, scope, options, order, caller, manager) {
    var me = this;
    if (eventName === 'ready' && me.isReady && !me.isMaximizing) {
      fn.call(scope);
      return me;
    }
    me.callParent([eventName, fn, scope, options, order, caller, manager]);
  }, isScalable:function() {
    var me = this, metas = document.querySelectorAll('meta[name\x3d"viewport"]'), meta = metas.length && metas[metas.length - 1], scalable = true, content;
    if (meta) {
      content = meta.getAttribute('content');
      scalable = !(content && me.notScalableRe.test(content));
    }
    return scalable;
  }, onTap:function(e) {
  }, onSwipeStart:function(e) {
    var side = this.sideForSwipeDirection(e.direction), menu = this.getMenus()[side];
    if (menu && !menu.owns(e)) {
      this.hideMenu(side);
    }
  }, onEdgeSwipeStart:function(e) {
    var me = this, menus = me.getMenus(), menu = menus[oppositeSideNames[e.direction]], menuSide, checkMenu;
    if (!menu || !menu.isHidden()) {
      return;
    }
    e.claimGesture();
    for (menuSide in menus) {
      checkMenu = menus[menuSide];
      if (checkMenu.isVisible()) {
        return;
      }
    }
    me.$swiping = true;
    me.beforeMenuAnimate(menu);
  }, onEdgeSwipe:function(e) {
    var me = this, side = me.sideForDirection(e.direction), menu = me.getMenus()[oppositeSideNames[e.direction]], size, after, viewportAfter, movement, viewportMovement;
    if (!menu || !me.$swiping) {
      return;
    }
    e.claimGesture();
    if (e.distance !== me.lastSwipeDistance) {
      me.reverseSwiping = e.distance < me.lastSwipeDistance;
    }
    me.lastSwipeDistance = e.distance;
    size = menu.element.measure(side & (LEFT | RIGHT) ? 'w' : 'h');
    movement = Math.min(e.distance - size, 0);
    viewportMovement = Math.min(e.distance, size);
    after = {translateX:0, translateY:0};
    viewportAfter = {translateX:0, translateY:0};
    if (side === LEFT) {
      after.translateX = movement;
      viewportAfter.translateX = viewportMovement;
    } else {
      if (side === RIGHT) {
        after.translateX = -movement;
        viewportAfter.translateX = -viewportMovement;
      } else {
        if (side === TOP) {
          after.translateY = movement;
          viewportAfter.translateY = viewportMovement;
        } else {
          if (side === BOTTOM) {
            after.translateY = -movement;
            viewportAfter.translateY = -viewportMovement;
          }
        }
      }
    }
    menu.translate(after.translateX, after.translateY);
    if (!menu.getFloated()) {
      me.translate(viewportAfter.translateX, viewportAfter.translateY);
    }
  }, onEdgeSwipeEnd:function(e) {
    var me = this, side = me.sideForDirection(e.direction), menu = me.getMenus()[oppositeSideNames[e.direction]], shouldRevert = me.reverseSwiping || e.distance < me.getSwipeThreshold(), after = {translateX:0, translateY:0}, viewportAfter = {translateX:0, translateY:0}, size, velocity, movement, viewportMovement;
    if (!menu) {
      return;
    }
    size = menu.element.measure(side & (LEFT | RIGHT) ? 'w' : 'h');
    velocity = e.flick ? e.flick.velocity : 0;
    if (side === RIGHT) {
      if (velocity.x > 0) {
        shouldRevert = true;
      }
    } else {
      if (side === LEFT) {
        if (velocity.x < 0) {
          shouldRevert = true;
        }
      } else {
        if (side === TOP) {
          if (velocity.y < 0) {
            shouldRevert = true;
          }
        } else {
          if (side === BOTTOM) {
            if (velocity.y > 0) {
              shouldRevert = true;
            }
          }
        }
      }
    }
    movement = shouldRevert ? size : 0;
    viewportMovement = shouldRevert ? 0 : -size;
    if (side === LEFT) {
      after.translateX = -movement;
      viewportAfter.translateX = -viewportMovement;
    } else {
      if (side === RIGHT) {
        after.translateX = movement;
        viewportAfter.translateX = viewportMovement;
      } else {
        if (side === TOP) {
          after.translateY = -movement;
          viewportAfter.translateY = -viewportMovement;
        } else {
          if (side === BOTTOM) {
            after.translateY = movement;
            viewportAfter.translateY = viewportMovement;
          }
        }
      }
    }
    menu.translate(after.translateX, after.translateY, {duration:200, callback:function() {
      if (shouldRevert) {
        menu.setHidden(true);
      }
    }});
    if (!menu.getFloated()) {
      me.translate(viewportAfter.translateX, viewportAfter.translateY, {duration:200});
    }
    me.$swiping = false;
  }, sideForDirection:function(direction) {
    if (direction === 'up') {
      direction = 'top';
    } else {
      if (direction === 'down') {
        direction = 'bottom';
      }
    }
    return oppositeSide[sideMap[direction]];
  }, sideForSwipeDirection:function(direction) {
    if (direction === 'up') {
      return 'top';
    }
    if (direction === 'down') {
      return 'bottom';
    }
    return direction;
  }, toggleWindowListener:function(on, eventName, fn, capturing) {
    if (on) {
      this.addWindowListener(eventName, fn, capturing);
    } else {
      this.removeWindowListener(eventName, fn, capturing);
    }
  }}};
});
Ext.define('Ext.viewport.Ios', {extend:Ext.viewport.Default, isFullscreen:function() {
  return this.isHomeScreen();
}, isHomeScreen:function() {
  return window.navigator.standalone === true;
}, constructor:function() {
  this.callParent(arguments);
  document.documentElement.style.overflow = 'hidden';
}, maximize:function() {
  var stretchHeights, orientation, currentHeight, height;
  if (this.isFullscreen()) {
    return this.callParent();
  }
  stretchHeights = this.stretchHeights;
  orientation = this.getOrientation();
  currentHeight = this.getWindowHeight();
  height = stretchHeights[orientation];
  if (window.scrollY > 0) {
    this.scrollToTop();
    if (!height) {
      stretchHeights[orientation] = height = this.getWindowHeight();
    }
    this.setHeight(height);
    this.fireMaximizeEvent();
  } else {
    if (!height) {
      height = this.getScreenHeight();
    }
    this.setHeight(height);
    this.waitUntil(function() {
      this.scrollToTop();
      return currentHeight !== this.getWindowHeight();
    }, function() {
      if (!stretchHeights[orientation]) {
        height = stretchHeights[orientation] = this.getWindowHeight();
        this.setHeight(height);
      }
      this.fireMaximizeEvent();
    }, function() {
      Ext.Logger.error('Timeout waiting for window.innerHeight to change', this);
      height = stretchHeights[orientation] = this.getWindowHeight();
      this.setHeight(height);
      this.fireMaximizeEvent();
    }, 50, 1000);
  }
}, getScreenHeight:function() {
  return window.screen[this.getOrientation() === this.PORTRAIT ? 'height' : 'width'];
}, scrollToTop:function() {
  window.scrollTo(0, 0);
}}, function() {
  if (!Ext.os.is.iOS) {
    return;
  }
  if (Ext.os.version.lt('3.2')) {
    this.override({constructor:function() {
      var stretchHeights = this.stretchHeights = {};
      stretchHeights[this.PORTRAIT] = 416;
      stretchHeights[this.LANDSCAPE] = 268;
      return this.callOverridden(arguments);
    }});
  }
  if (Ext.os.version.lt('5')) {
    this.override({fieldMaskClsTest:'-field-mask', doPreventZooming:function(e) {
      var target = e.target;
      if (target && target.nodeType === 1 && !this.isInputRegex.test(target.tagName) && target.className.indexOf(this.fieldMaskClsTest) === -1) {
        e.preventDefault();
      }
    }});
  }
  if (Ext.os.is.iPad) {
    this.override({isFullscreen:function() {
      return true;
    }});
  }
  if (Ext.os.version.gtEq('7') && Ext.os.version.lt('8')) {
    if (Ext.os.deviceType === 'Tablet' || !Ext.browser.is.Safari || window.navigator.standalone) {
      this.override({constructor:function() {
        var stretchHeights = {}, stretchWidths = {}, orientation = this.determineOrientation(), screenHeight = window.screen.height, screenWidth = window.screen.width, menuHeight = orientation === this.PORTRAIT ? screenHeight - window.innerHeight : screenWidth - window.innerHeight;
        stretchHeights[this.PORTRAIT] = screenHeight - menuHeight;
        stretchHeights[this.LANDSCAPE] = screenWidth - menuHeight;
        stretchWidths[this.PORTRAIT] = screenWidth;
        stretchWidths[this.LANDSCAPE] = screenHeight;
        this.stretchHeights = stretchHeights;
        this.stretchWidths = stretchWidths;
        this.callOverridden(arguments);
        this.on('ready', this.setViewportSizeToAbsolute, this);
        this.on('orientationchange', this.setViewportSizeToAbsolute, this);
      }, getWindowHeight:function() {
        return this.stretchHeights[this.getOrientation()];
      }, getWindowWidth:function() {
        return this.stretchWidths[this.getOrientation()];
      }, setViewportSizeToAbsolute:function() {
        this.setWidth(this.getWindowWidth());
        this.setHeight(this.getWindowHeight());
      }});
    }
    if (Ext.os.deviceType === 'Tablet') {
      this.override({constructor:function() {
        this.callOverridden(arguments);
        window.addEventListener('scroll', function() {
          if (window.scrollX !== 0) {
            window.scrollTo(0, window.scrollY);
          }
        }, false);
      }, setViewportSizeToAbsolute:function() {
        window.scrollTo(0, 0);
        this.callOverridden(arguments);
      }, onElementBlur:function() {
        this.callOverridden(arguments);
        if (window.scrollY !== 0) {
          window.scrollTo(0, 0);
        }
      }});
    }
  }
});
Ext.define('Ext.viewport.Android', {extend:Ext.viewport.Default, config:{translatable:{type:'csstransform'}}, preventPullRefresh:true, constructor:function() {
  var me = this;
  me.callParent(arguments);
  me.on({orientationchange:'hideKeyboardIfNeeded', scope:me, priority:1001});
  if (me.preventPullRefresh) {
    Ext.getBody().setStyle({overflow:'hidden'});
  }
}, getWindowWidth:function() {
  return this.element.getWidth();
}, getWindowHeight:function() {
  return this.element.getHeight();
}, getDummyInput:function() {
  var input = this.dummyInput, focusedElement = this.focusedElement, box = Ext.fly(focusedElement).getBox();
  if (!input) {
    this.dummyInput = input = document.createElement('input');
    input.style.position = 'absolute';
    input.style.opacity = '0';
    input.style.pointerEvents = 'none';
    document.body.appendChild(input);
  }
  input.style.left = box.left + 'px';
  input.style.top = box.top + 'px';
  input.style.display = '';
  return input;
}, doBlurInput:function(e) {
  var target = e.target, focusedElement = this.focusedElement, dummy;
  if (focusedElement && !this.isInputRegex.test(target.tagName)) {
    dummy = this.getDummyInput();
    delete this.focusedElement;
    dummy.focus();
    Ext.defer(function() {
      dummy.style.display = 'none';
    }, 100);
  }
}, hideKeyboardIfNeeded:function() {
  var focusedElement = this.focusedElement;
  if (focusedElement) {
    delete this.focusedElement;
    if (Ext.os.version.lt('4')) {
      focusedElement.style.display = 'none';
    } else {
      focusedElement.blur();
    }
    Ext.defer(function() {
      focusedElement.style.display = '';
    }, 1000);
  }
}, doFireOrientationChangeEvent:function() {
  this.orientationChanging = true;
  this.waitUntil(function() {
    return this.getWindowOuterHeight() !== this.windowOuterHeight;
  }, function() {
    this.windowOuterHeight = this.getWindowOuterHeight();
    this.updateSize();
    this.orientationChanging = false;
  }, function() {
    Ext.Logger.error("Timeout waiting for viewport's outerHeight to change " + 'before firing orientationchange', this);
  });
  return this;
}, getActualWindowOuterHeight:function() {
  return Math.round(this.getWindowOuterHeight() / window.devicePixelRatio);
}, maximize:function() {
  var stretchHeights = this.stretchHeights, orientation = this.orientation, isHeightMaximized, height;
  height = stretchHeights[orientation];
  if (!height) {
    stretchHeights[orientation] = height = this.getActualWindowOuterHeight();
  }
  if (!this.addressBarHeight) {
    this.addressBarHeight = height - this.getWindowHeight();
  }
  this.setHeight(height);
  isHeightMaximized = this.isHeightMaximized.bind(this, height);
  this.scrollToTop();
  this.waitUntil(isHeightMaximized, this.fireMaximizeEvent, this.fireMaximizeEvent);
}, isHeightMaximized:function(height) {
  this.scrollToTop();
  return this.getWindowHeight() === height;
}, doPreventZooming:function(e) {
  var target;
  if ('button' in e && e.button !== 0) {
    return;
  }
  target = e.target;
  if (target && target.nodeType === 1 && !this.isInputRegex.test(target.tagName) && !this.focusedElement) {
    e.preventDefault();
  }
}}, function() {
  var version, userAgent, isBuggy;
  if (!Ext.os.is.Android) {
    return;
  }
  version = Ext.os.version;
  userAgent = Ext.browser.userAgent;
  isBuggy = /(htc|desire|incredible|ADR6300)/i.test(userAgent) && version.lt('2.3');
  if (isBuggy) {
    this.override({constructor:function(config) {
      if (!config) {
        config = {};
      }
      config.autoMaximize = false;
      this.watchDogTick = this.watchDogTick.bind(this);
      Ext.interval(this.watchDogTick, 1000);
      return this.callParent([config]);
    }, watchDogTick:function() {
      this.watchDogLastTick = Ext.Date.now();
    }, doPreventPanning:function() {
      var now = Ext.Date.now(), lastTick = this.watchDogLastTick, deltaTime = now - lastTick;
      if (deltaTime >= 2000) {
        return;
      }
      return this.callParent(arguments);
    }, doPreventZooming:function() {
      var now = Ext.Date.now(), lastTick = this.watchDogLastTick, deltaTime = now - lastTick;
      if (deltaTime >= 2000) {
        return;
      }
      return this.callParent(arguments);
    }});
  }
  if (version.match('2')) {
    this.override({onReady:function() {
      this.addWindowListener('resize', this.onWindowResize.bind(this));
      this.callParent(arguments);
    }, scrollToTop:function() {
      document.body.scrollTop = 100;
    }, onWindowResize:function() {
      var oldWidth = this.windowWidth, oldHeight = this.windowHeight, width = this.getWindowWidth(), height = this.getWindowHeight();
      if (this.getAutoMaximize() && !this.isMaximizing && !this.orientationChanging && window.scrollY === 0 && oldWidth === width && height < oldHeight && (height >= oldHeight - this.addressBarHeight || !this.focusedElement)) {
        this.scrollToTop();
      }
    }});
  } else {
    if (version.gtEq('3.1')) {
      this.override({isHeightMaximized:function(height) {
        this.scrollToTop();
        return this.getWindowHeight() === height - 1;
      }});
    } else {
      if (version.match('3')) {
        this.override({isHeightMaximized:function() {
          this.scrollToTop();
          return true;
        }});
      }
    }
  }
  if (version.gtEq('4')) {
    this.override({doBlurInput:Ext.emptyFn});
  }
});
Ext.define('Ext.viewport.WindowsPhone', {extend:Ext.viewport.Default, requires:[], alternateClassName:'Ext.viewport.WP', config:{translatable:{type:'csstransform'}}, initialize:function() {
  var preventSelection = function(e) {
    var srcElement = e.srcElement.nodeName.toUpperCase(), selectableElements = ['INPUT', 'TEXTAREA'];
    if (selectableElements.indexOf(srcElement) === -1) {
      return false;
    }
  };
  document.body.addEventListener('onselectstart', preventSelection);
  this.addMeta('msapplication-tap-highlight', 'no');
  this.callParent();
}, supportsOrientation:function() {
  return false;
}, onWindowResize:function(width, height) {
  this.callParent([width, height]);
  this.waitUntil(function() {
    var oldWidth = this.windowWidth, oldHeight = this.windowHeight, width = this.getWindowWidth(), height = this.getWindowHeight(), currentOrientation = this.getOrientation(), newOrientation = this.determineOrientation();
    return oldWidth !== width && oldHeight !== height && currentOrientation !== newOrientation;
  }, function() {
    var currentOrientation = this.getOrientation(), newOrientation = this.determineOrientation();
    this.fireOrientationChangeEvent(newOrientation, currentOrientation);
  }, Ext.emptyFn, 250);
}});
Ext.define('Ext.viewport.Viewport', {singleton:true, setup:function(config) {
  var osName = Ext.os.name, viewportName;
  switch(osName) {
    case 'Android':
      viewportName = Ext.browser.name === 'ChromeMobile' ? 'Default' : 'Android';
      break;
    case 'iOS':
      viewportName = 'Ios';
      break;
    case 'Windows':
      viewportName = Ext.browser.name === 'IE' ? 'WindowsPhone' : 'Default';
      break;
    case 'WindowsPhone':
      viewportName = 'WindowsPhone';
      break;
    default:
      viewportName = 'Default';
      break;
  }
  return Ext.Viewport = Ext.create('Ext.viewport.' + viewportName, config);
}});
Ext.define('Ext.overrides.app.Application', {override:'Ext.app.Application', config:{viewport:null}, quickTips:false, destroy:function() {
  this.setQuickTips(false);
  this.callParent();
}, initMainView:function() {
  var me = this, viewport = me.viewport = Ext.Viewport, mainView;
  me.callParent();
  mainView = me.getMainView();
  viewport.onAppLaunch();
  if (mainView) {
    viewport.add(mainView);
  }
}, applyQuickTips:function(quickTips) {
  quickTips = quickTips || null;
  if (quickTips) {
    if (quickTips === true) {
      quickTips = {};
    }
    quickTips = new Ext.tip['Manager'](quickTips);
  }
  return quickTips;
}, updateQuickTips:function(quickTips, oldQuickTips) {
  if (oldQuickTips) {
    oldQuickTips.destroy();
  }
}});
Ext.define('Ext.app.domain.View', {extend:Ext.app.EventDomain, isInstance:true, constructor:function(controller) {
  this.callParent([controller]);
  this.controller = controller;
  this.monitoredClasses = [Ext.Widget];
}, match:function(target, selector, controller) {
  var out = false;
  if (selector === '#') {
    out = controller === target.getController();
  } else {
    out = target.is(selector);
  }
  return out;
}, destroy:function() {
  this.controller = null;
  this.callParent();
}});
Ext.define('Ext.app.ViewController', {extend:Ext.app.BaseController, alias:'controller.controller', mixins:[Ext.mixin.Factoryable], isViewController:true, factoryConfig:{type:'controller'}, config:{bindings:{$value:null, lazy:true}, closeViewAction:'destroy'}, view:null, constructor:function(config) {
  this.compDomain = new Ext.app.domain.View(this);
  this.callParent([config]);
}, beforeInit:Ext.emptyFn, init:Ext.emptyFn, initViewModel:Ext.emptyFn, destroy:function() {
  var me = this, domain = me.compDomain, bind, b, key;
  if (me.$hasBinds) {
    bind = me.getBindings();
    for (key in bind) {
      b = bind[key];
      if (b) {
        b.destroy();
      }
    }
  }
  if (domain) {
    domain.unlisten(me);
    domain.destroy();
  }
  me.compDomain = me.view = null;
  me.callParent();
}, closeView:function() {
  var view = this.getView(), action;
  if (view) {
    action = this.getCloseViewAction();
    view[action]();
  }
}, control:function(selectors, listeners) {
  var obj = selectors;
  if (Ext.isString(selectors)) {
    obj = {};
    obj[selectors] = listeners;
  }
  this.compDomain.listen(obj, this);
}, listen:function(to, controller) {
  var component = to.component;
  if (component) {
    to = Ext.apply({}, to);
    delete to.component;
    this.control(component);
  }
  this.callParent([to, controller]);
}, applyId:function(id) {
  if (!id) {
    id = Ext.id(null, 'controller-');
  }
  return id;
}, getReferences:function() {
  var view = this.view;
  return view && view.getReferences();
}, getView:function() {
  return this.view;
}, lookup:function(key) {
  var view = this.view;
  return view && view.lookup(key);
}, lookupReference:function(key) {
  return this.lookup(key);
}, getSession:function() {
  var view = this.view;
  return view && view.lookupSession();
}, getViewModel:function() {
  var view = this.view;
  return view && view.lookupViewModel();
}, getStore:function(name) {
  var viewModel = this.getViewModel();
  return viewModel ? viewModel.getStore(name) : null;
}, fireViewEvent:function(eventName, args) {
  var view = this.view, result = false, a = arguments;
  if (view) {
    if (view !== args) {
      a = Ext.Array.slice(a);
      a.splice(1, 0, view);
    }
    result = view.fireEvent.apply(view, a);
  }
  return result;
}, applyBindings:function(bindings) {
  if (!bindings) {
    return null;
  }
  var me = this, viewModel = me.getViewModel(), getBindTemplateScope = me.getBindTemplateScope(), b, fn, descriptor;
  me.$hasBinds = true;
  if (!viewModel) {
    Ext.raise('Cannot use bind config without a viewModel');
  }
  for (fn in bindings) {
    descriptor = bindings[fn];
    b = null;
    if (descriptor) {
      b = viewModel.bind(descriptor, fn, me);
      b.getTemplateScope = getBindTemplateScope;
    }
    bindings[fn] = b;
  }
  return bindings;
}, privates:{view:null, attachReference:function(component) {
  var view = this.view;
  if (view) {
    view.attachReference(component);
  }
}, getBindTemplateScope:function() {
  return this.scope;
}, initBindings:function() {
  this.getBindings();
}, setView:function(view) {
  this.view = view;
  if (!this.beforeInit.$nullFn) {
    this.beforeInit(view);
  }
}}});
Ext.define('Ext.util.Scheduler', {mixins:[Ext.mixin.Observable], busyCounter:0, lastBusyCounter:0, destroyed:false, firing:null, notifyIndex:-1, nextId:0, orderedItems:null, passes:0, scheduledCount:0, validIdRe:null, config:{cycleLimit:5, preSort:null, tickDelay:5}, suspendOnNotify:true, constructor:function(config) {
  if (Ext.util.Scheduler.instances) {
    Ext.util.Scheduler.instances.push(this);
  } else {
    Ext.util.Scheduler.instances = [this];
  }
  this.id = Ext.util.Scheduler.count = (Ext.util.Scheduler.count || 0) + 1;
  this.mixins.observable.constructor.call(this, config);
  this.items = new Ext.util.Bag;
}, destroy:function() {
  var me = this, timer = me.timer;
  if (timer) {
    window.clearTimeout(timer);
    me.timer = null;
  }
  me.items.destroy();
  me.items = me.orderedItems = null;
  me.callParent();
  Ext.Array.remove(Ext.util.Scheduler.instances, this);
}, add:function(item) {
  var me = this, items = me.items;
  if (items === me.firing) {
    me.items = items = items.clone();
  }
  item.id = item.id || ++me.nextId;
  item.scheduler = me;
  items.add(item);
  if (!me.sortMap) {
    me.orderedItems = null;
  }
}, remove:function(item) {
  var me = this, items = me.items;
  if (me.destroyed) {
    return;
  }
  if (me.sortMap) {
    Ext.raise('Items cannot be removed during sort');
  }
  if (items === me.firing) {
    me.items = items = items.clone();
  }
  if (item.scheduled) {
    me.unscheduleItem(item);
    item.scheduled = false;
  }
  items.remove(item);
  me.orderedItems = null;
}, sort:function() {
  var me = this, items = me.items, sortMap = {}, preSort = me.getPreSort(), i, item;
  me.orderedItems = [];
  me.sortMap = sortMap;
  me.sortStack = [];
  if (preSort) {
    items.sort(preSort);
  }
  items = items.items;
  for (i = 0; i < items.length; ++i) {
    item = items[i];
    if (!sortMap[item.id]) {
      me.sortItem(item);
    }
  }
  me.sortMap = null;
  me.sortStack = null;
}, sortItem:function(item) {
  var me = this, sortMap = me.sortMap, orderedItems = me.orderedItems, itemId;
  if (!item.scheduler) {
    me.add(item);
  }
  itemId = item.id;
  if (item.scheduler !== me) {
    Ext.raise('Item ' + itemId + ' belongs to another Scheduler');
  }
  me.sortStack.push(item);
  if (sortMap[itemId] === 0) {
    for (var cycle = [], i = 0; i < me.sortStack.length; ++i) {
      cycle[i] = me.sortStack[i].getFullName();
    }
    Ext.raise('Dependency cycle detected: ' + cycle.join('\n --\x3e '));
  }
  if (!(itemId in sortMap)) {
    sortMap[itemId] = 0;
    if (!item.sort.$nullFn) {
      item.sort();
    }
    sortMap[itemId] = 1;
    item.order = me.orderedItems.length;
    orderedItems.push(item);
  }
  me.sortStack.pop();
  return me;
}, sortItems:function(items) {
  var me = this, sortItem = me.sortItem;
  if (items) {
    if (items instanceof Array) {
      Ext.each(items, sortItem, me);
    } else {
      Ext.Object.eachValue(items, sortItem, me);
    }
  }
  return me;
}, applyPreSort:function(preSort) {
  if (typeof preSort === 'function') {
    return preSort;
  }
  var parts = preSort.split(','), direction = [], length = parts.length, c, i, s;
  for (i = 0; i < length; ++i) {
    direction[i] = 1;
    s = parts[i];
    if ((c = s.charAt(0)) === '-') {
      direction[i] = -1;
    } else {
      if (c !== '+') {
        c = 0;
      }
    }
    if (c) {
      parts[i] = s.substring(1);
    }
  }
  return function(lhs, rhs) {
    var ret = 0, i, prop, v1, v2;
    for (i = 0; !ret && i < length; ++i) {
      prop = parts[i];
      v1 = lhs[prop];
      v2 = rhs[prop];
      ret = direction[i] * (v1 < v2 ? -1 : v2 < v1 ? 1 : 0);
    }
    return ret;
  };
}, notify:function() {
  var me = this, timer = me.timer, cyclesLeft = me.getCycleLimit(), globalEvents = Ext.GlobalEvents, suspend = me.suspendOnNotify, busyCounter, i, item, len, queue, firedEvent;
  if (timer) {
    window.clearTimeout(timer);
    me.timer = null;
  }
  if (!me.firing && me.scheduledCount) {
    if (suspend) {
      Ext.suspendLayouts();
    }
    while (me.scheduledCount) {
      if (cyclesLeft) {
        --cyclesLeft;
      } else {
        me.firing = null;
        if (me.onCycleLimitExceeded) {
          me.onCycleLimitExceeded();
        }
        break;
      }
      if (!firedEvent) {
        firedEvent = true;
        if (globalEvents.hasListeners.beforebindnotify) {
          globalEvents.fireEvent('beforebindnotify', me);
        }
      }
      ++me.passes;
      if (!(queue = me.orderedItems)) {
        me.sort();
        queue = me.orderedItems;
      }
      len = queue.length;
      if (len) {
        me.firing = me.items;
        for (i = 0; i < len; ++i) {
          item = queue[i];
          if (item.scheduled) {
            item.scheduled = false;
            --me.scheduledCount;
            me.notifyIndex = i;
            item.react();
            if (!me.scheduledCount) {
              break;
            }
          }
        }
      }
    }
    me.firing = null;
    me.notifyIndex = -1;
    if (suspend) {
      Ext.resumeLayouts(true);
    }
  }
  if ((busyCounter = me.busyCounter) !== me.lastBusyCounter) {
    if (!(me.lastBusyCounter = busyCounter)) {
      me.fireEvent('idle', me);
    }
  }
}, onTick:function() {
  this.timer = null;
  this.notify();
}, scheduleItem:function(item) {
  var me = this;
  ++me.scheduledCount;
  if (!me.timer && !me.firing) {
    me.scheduleTick();
  }
}, scheduleTick:function() {
  var me = this;
  if (!me.destroyed && !me.timer) {
    me.timer = Ext.defer(me.onTick, me.getTickDelay(), me);
  }
}, unscheduleItem:function(item) {
  if (this.scheduledCount) {
    --this.scheduledCount;
  }
}, adjustBusy:function(adjustment) {
  var me = this, busyCounter = me.busyCounter + adjustment;
  me.busyCounter = busyCounter;
  if (busyCounter) {
    if (!me.lastBusyCounter) {
      me.lastBusyCounter = busyCounter;
      me.fireEvent('busy', me);
    }
  } else {
    if (me.lastBusyCounter && !me.timer) {
      me.scheduleTick();
    }
  }
}, isBusy:function() {
  return !this.isIdle();
}, isIdle:function() {
  return !(this.busyCounter + this.lastBusyCounter);
}, debugHooks:{$enabled:false, onCycleLimitExceeded:function() {
  Ext.raise('Exceeded cycleLimit ' + this.getCycleLimit());
}, scheduleItem:function(item) {
  if (!item) {
    Ext.raise('scheduleItem: Invalid argument');
  }
  Ext.log('Schedule item: ' + item.getFullName() + ' - ' + (this.scheduledCount + 1));
  if (item.order <= this.notifyIndex) {
    Ext.log.warn('Suboptimal order: ' + item.order + ' \x3c ' + this.notifyIndex);
  }
  this.callParent([item]);
}, unscheduleItem:function(item) {
  if (!this.scheduledCount) {
    Ext.raise('Invalid scheduleCount');
  }
  this.callParent([item]);
  Ext.log('Unschedule item: ' + item.getFullName() + ' - ' + this.scheduledCount);
}}});
Ext.define('Ext.data.Batch', {mixins:{observable:Ext.mixin.Observable}, config:{pauseOnException:false}, current:-1, total:0, running:false, complete:false, exception:false, constructor:function(config) {
  var me = this;
  me.mixins.observable.constructor.call(me, config);
  me.operations = [];
  me.exceptions = [];
}, add:function(operation) {
  var me = this, i, len;
  if (Ext.isArray(operation)) {
    for (i = 0, len = operation.length; i < len; ++i) {
      me.add(operation[i]);
    }
  } else {
    me.total++;
    operation.setBatch(me);
    me.operations.push(operation);
  }
  return me;
}, sort:function() {
  this.operations.sort(this.sortFn);
}, sortFn:function(operation1, operation2) {
  var ret = operation1.order - operation2.order;
  if (ret) {
    return ret;
  }
  var entityType1 = operation1.entityType, entityType2 = operation2.entityType, rank;
  if (!entityType1 || !entityType2) {
    return 0;
  }
  if (!(rank = entityType1.rank)) {
    entityType1.schema.rankEntities();
    rank = entityType1.rank;
  }
  return (rank - entityType2.rank) * operation1.foreignKeyDirection;
}, start:function(index) {
  var me = this;
  if (me.destroyed || !me.operations.length || me.running) {
    return me;
  }
  me.exceptions.length = 0;
  me.exception = false;
  me.running = true;
  return me.runOperation(Ext.isDefined(index) ? index : me.current + 1);
}, abort:function() {
  var me = this, op;
  if (me.running) {
    op = me.getCurrent();
    if (!op.destroyed) {
      op.abort();
    }
  }
  me.running = false;
  me.aborted = true;
  me.current = undefined;
}, retry:function() {
  return this.start(this.current);
}, runNextOperation:function() {
  var me = this;
  if (me.running) {
    me.runOperation(me.current + 1);
  }
  return me;
}, pause:function() {
  this.running = false;
  return this;
}, getOperations:function() {
  return this.operations;
}, getExceptions:function() {
  return this.exceptions;
}, getCurrent:function() {
  var out = null, current = this.current;
  if (!(current === -1 || this.complete)) {
    out = this.operations[current];
  }
  return out;
}, getTotal:function() {
  return this.total;
}, isRunning:function() {
  return this.running;
}, isComplete:function() {
  return this.complete;
}, hasException:function() {
  return this.exception;
}, runOperation:function(index) {
  var me = this, operations = me.operations, operation = operations[index];
  if (operation === undefined) {
    me.running = false;
    me.complete = true;
    me.fireEvent('complete', me, operations[operations.length - 1]);
  } else {
    me.current = index;
    operation.setInternalCallback(me.onOperationComplete);
    operation.setInternalScope(me);
    operation.execute();
  }
  return me;
}, onOperationComplete:function(operation) {
  var me = this, exception = operation.hasException();
  if (exception) {
    me.exception = true;
    me.exceptions.push(operation);
    me.fireEvent('exception', me, operation);
  }
  if (exception && me.getPauseOnException()) {
    me.pause();
  } else {
    me.fireEvent('operationcomplete', me, operation);
    me.runNextOperation();
  }
}, destroy:function() {
  var me = this, operations = me.operations, op, i, len;
  if (me.running) {
    me.abort();
  }
  for (i = 0, len = me.operations.length; i < len; i++) {
    op = operations[i];
    if (op) {
      if (!op.destroyed && !op.$destroyOwner) {
        op.destroy();
      }
      op[i] = null;
    }
  }
  me.operations = me.exceptions = null;
  me.callParent();
}});
Ext.define('Ext.data.matrix.Slice', {constructor:function(side, id) {
  this.id = id;
  this.side = side;
  this.members = {};
}, attach:function(store) {
  var me = this;
  Ext.Assert.falsey(me.store, 'Store is already attached');
  me.store = store;
  store.matrix = me;
  store.on('load', me.onStoreLoad, me, {single:true});
}, commit:function() {
  var members = this.members, id;
  for (id in members) {
    members[id][2] = 0;
  }
}, onStoreLoad:function(store) {
  this.update(store.getData().items, 0);
}, update:function(recordsOrIds, state) {
  if (!(recordsOrIds instanceof Array)) {
    Ext.raise('Only array of records or record ids are supported');
  }
  var me = this, MatrixSlice = Ext.data.matrix.Slice, side = me.side, assocIndex = side.index, length = recordsOrIds.length, id = me.id, members = me.members, otherSide = side.inverse, otherSlices = otherSide.slices, assoc, call, i, item, otherId, otherSlice, record;
  for (i = 0; i < length; ++i) {
    call = record = null;
    item = recordsOrIds[i];
    otherId = item.isEntity ? (record = item).id : item;
    assoc = members[otherId];
    if (state < 0 && assoc && assoc[2] === 1) {
      delete members[otherId];
      otherSlice = otherSlices[otherId];
      if (otherSlice) {
        delete otherSlice.members[id];
      }
      call = 1;
    } else {
      if (!assoc) {
        assoc = [otherId, otherId, state];
        assoc[assocIndex] = id;
        members[otherId] = assoc;
        otherSlice = otherSlices[otherId];
        if (!otherSlice) {
          otherSlices[otherId] = otherSlice = new MatrixSlice(otherSide, otherId);
        }
        otherSlice.members[id] = assoc;
        call = 1;
      } else {
        if (state !== assoc[2] && state !== 0 && !(state === 1 && assoc[2] === 0)) {
          assoc[2] = state;
          otherSlice = otherSlices[otherId];
          call = 1;
        }
      }
    }
    if (call) {
      if (me.notify) {
        me.notify.call(me.scope, me, otherId, state);
      }
      if (otherSlice && otherSlice.notify) {
        otherSlice.notify.call(otherSlice.scope, otherSlice, id, state);
      }
    }
  }
}, updateId:function(newId) {
  var me = this, oldId = me.id, side = me.side, slices = side.slices, slice = slices[oldId], members = slice.members, index = side.index, otherSlices = side.inverse.slices, assoc, otherId, otherMembers;
  me.id = newId;
  slices[newId] = slice;
  delete slices[oldId];
  for (otherId in members) {
    assoc = members[otherId];
    assoc[index] = newId;
    otherMembers = otherSlices[otherId].members;
    otherMembers[newId] = otherMembers[oldId];
    delete otherMembers[oldId];
  }
}, destroy:function() {
  var me = this, store = me.store;
  if (store) {
    store.matrix = null;
    store.un('load', me.onStoreLoad, me);
  }
  me.notify = me.scope = me.store = me.side = me.members = null;
  me.callParent();
}});
Ext.define('Ext.data.matrix.Side', {constructor:function(matrix, index, role) {
  var me = this;
  me.matrix = matrix;
  me.index = index;
  me.role = role;
  me.slices = {};
}, commit:function() {
  var slices = this.slices, id;
  for (id in slices) {
    slices[id].commit();
  }
}, get:function(id1, id2) {
  var me = this, slices = me.slices, slice = slices[id1] || (slices[id1] = new Ext.data.matrix.Slice(me, id1));
  return id2 || id2 === 0 ? slice.members[id2] : slice;
}, update:function(id1, id2, state) {
  var slice = this.get(id1);
  return slice.update(id2, state);
}, updateId:function(oldId, newId) {
  var slice = this.get(oldId);
  if (slice) {
    slice.updateId(newId);
  }
}, destroy:function() {
  var me = this, slices = me.slices, id;
  for (id in slices) {
    slices[id].destroy();
  }
  me.inverse = me.matrix = me.role = me.slices = null;
  me.callParent();
}});
Ext.define('Ext.data.matrix.Matrix', {constructor:function(session, matrix) {
  var me = this, association = matrix.isManyToMany ? matrix : session.getSchema().getAssociation(matrix), Side = Ext.data.matrix.Side, left = new Side(me, 0, association.left), right = new Side(me, 1, association.right);
  Ext.Assert.truthy(association.isManyToMany, 'Association is not many-to-many');
  me.association = association;
  me.session = session;
  me.left = left;
  me.right = right;
  left.inverse = right;
  right.inverse = left;
}, commit:function() {
  this.left.commit();
  this.right.commit();
}, update:function(id1, id2, state) {
  return this.left.update(id1, id2, state);
}, updateId:function(record, oldId, newId) {
  var Type = record.self, left = this.left, right = this.right, matchSide;
  if (Type === left.role.cls) {
    matchSide = left;
  }
  if (Type === right.role.cls) {
    matchSide = right;
  }
  if (matchSide) {
    matchSide.updateId(oldId, newId);
  }
}, destroy:function() {
  var me = this;
  me.left.destroy();
  me.right.destroy();
  me.association = me.session = me.left = me.right = null;
  me.callParent();
}});
Ext.define('Ext.data.session.ChangesVisitor', {constructor:function(session) {
  var me = this, crud;
  me.session = session;
  crud = session.getCrudProperties();
  me.result = null;
  me.writerOptions = {};
  me.createKey = crud.create;
  me.readKey = crud.read;
  me.updateKey = crud.update;
  me.dropKey = crud.drop;
}, onDirtyRecord:function(record) {
  var me = this, crud = me.crud, created = record.phantom, dropped = record.dropped, type = record.$className, prop = created || dropped ? 'allDataOptions' : 'partialDataOptions', writerOptions = me.writerOptions, name = record.entityName, options, bucket, entry, result;
  if (created && dropped) {
    return false;
  }
  crud = created ? me.createKey : dropped ? me.dropKey : me.updateKey;
  writerOptions = writerOptions[type] || (writerOptions[type] = {});
  if (dropped) {
    if (!(options = writerOptions.drop)) {
      writerOptions.drop = options = {all:record.getProxy().getWriter().getWriteAllFields()};
    }
    if (!options.all) {
      entry = record.id;
    }
  }
  if (!entry) {
    if (!(options = writerOptions[prop])) {
      options = record.getProxy().getWriter().getConfig(prop);
      writerOptions[prop] = options = Ext.Object.chain(options);
      me.setupOptions(options);
    }
    entry = record.getData(options);
  }
  result = me.result || (me.result = {});
  bucket = result[name] || (result[name] = {});
  bucket = bucket[crud] || (bucket[crud] = []);
  bucket.push(entry);
}, setupOptions:function(options) {
  options.serialize = true;
}, onMatrixChange:function(association, id1, id2, state) {
  var me = this, name = association.left.type, assocName = association.right.role, operation = state < 0 ? me.dropKey : me.createKey, bucket, result;
  result = me.result || (me.result = {});
  bucket = result[name] || (result[name] = {});
  bucket = bucket[assocName] || (bucket[assocName] = {});
  bucket = bucket[operation] || (bucket[operation] = {});
  bucket = bucket[id1] || (bucket[id1] = []);
  bucket.push(id2);
}});
Ext.define('Ext.data.session.ChildChangesVisitor', {extend:Ext.data.session.ChangesVisitor, constructor:function() {
  this.seen = {};
  this.callParent(arguments);
}, setupOptions:function(options) {
  this.callParent([options]);
  options.serialize = false;
}, onDirtyRecord:function(record) {
  if (this.callParent(arguments) !== false) {
    if (!record.$source && (record.dropped || !record.phantom)) {
      this.readEntity(record);
    }
  }
}, readEntity:function(record) {
  var me = this, readKey = me.readKey, name = record.entityName, id = record.id, seen = me.seen, seenKey = name + id, result, bucket;
  if (seen[seenKey]) {
    return;
  }
  seen[seenKey] = true;
  result = me.result || (me.result = {});
  bucket = result[name] || (result[name] = {});
  bucket = bucket[readKey] || (bucket[readKey] = []);
  bucket.push(Ext.apply({}, record.modified, record.data));
}});
Ext.define('Ext.data.session.BatchVisitor', {map:null, constructor:function(batch) {
  this.batch = batch;
}, getBatch:function(sort) {
  var map = this.map, batch = this.batch, bucket, entity, name, operation, operationType, proxy, batchActions, records, len, i;
  if (map) {
    if (!batch) {
      batch = new Ext.data.Batch;
    }
    for (name in map) {
      bucket = map[name];
      entity = bucket.entity;
      proxy = entity.getProxy();
      batchActions = proxy.getBatchActions();
      delete bucket.entity;
      for (operationType in bucket) {
        if (batchActions) {
          operation = proxy.createOperation(operationType, {records:bucket[operationType]});
          operation.entityType = entity;
          batch.add(operation);
        } else {
          records = bucket[operationType];
          for (i = 0, len = records.length; i < len; ++i) {
            operation = proxy.createOperation(operationType, {records:[records[i]]});
            operation.entityType = entity;
            batch.add(operation);
          }
        }
      }
    }
  }
  if (batch && sort !== false) {
    batch.sort();
  }
  return batch;
}, onDirtyRecord:function(record) {
  var me = this, operation = record.phantom ? 'create' : record.dropped ? 'destroy' : 'update', name = record.$className, map = me.map || (me.map = {}), bucket = map[name] || (map[name] = {entity:record.self});
  bucket = bucket[operation] || (bucket[operation] = []);
  bucket.push(record);
}});
Ext.define('Ext.mixin.Dirty', {mixinId:'dirty', config:{dirty:{$value:false, lazy:true}}, dirty:false, _dirtyRecordCount:0, ignoreDirty:false, recordStateIsDirtyState:true, isDirty:function() {
  return this.getDirty();
}, applyDirty:function(dirty) {
  return this.ignoreDirty ? false : dirty;
}, updateDirty:function(dirty) {
  var me = this;
  me.dirty = dirty;
  if (me.fireEvent && !me.isDirtyInitializing) {
    me.fireDirtyChange();
  }
}, clearRecordStates:function() {
  var me = this, counters = me._crudCounters;
  if (counters) {
    counters.C = counters.U = counters.D = 0;
  }
  me._dirtyRecordCount = 0;
  if (me.recordStateIsDirtyState) {
    me.setDirty(false);
  }
}, fireDirtyChange:function() {
  var me = this;
  if (!me.ignoreDirty && me.hasListeners.dirtychange) {
    me.fireEvent('dirtychange', me, me.dirty);
  }
}, trackRecordState:function(record, initial) {
  var me = this, counters = me._crudCounters || (me._crudCounters = {C:0, R:0, U:0, D:0}), dirtyRecordCountWas = me._dirtyRecordCount, state = record.crudState, stateWas = record.crudStateWas, changed, dirtyRecordCount;
  if (initial || state !== stateWas) {
    if (!initial && stateWas) {
      --counters[stateWas];
    }
    if (!(record.phantom && state === 'D')) {
      ++counters[state];
    }
    me.checkCounters();
    me._dirtyRecordCount = dirtyRecordCount = counters.C + counters.U + counters.D;
    changed = !dirtyRecordCount !== !dirtyRecordCountWas;
    if (changed && me.recordStateIsDirtyState) {
      me.setDirty(dirtyRecordCount > 0);
    }
  }
  return changed;
}, untrackRecordState:function(record) {
  var me = this, counters = me._crudCounters, dirtyRecordCountWas = me._dirtyRecordCount, state = record.crudState, changed, dirtyRecordCount;
  if (counters && state !== 'D' && !record.erased) {
    --counters[state];
    me.checkCounters();
    me._dirtyRecordCount = dirtyRecordCount = counters.C + counters.U + counters.D;
    changed = !dirtyRecordCount !== !dirtyRecordCountWas;
    if (changed && me.recordStateIsDirtyState) {
      me.setDirty(dirtyRecordCount > 0);
    }
  }
  return changed;
}, checkCounters:function() {
  var counters = this._crudCounters, key;
  for (key in counters) {
    if (counters[key] < 0) {
      Ext.raise('Invalid state for ' + key);
    }
  }
}});
Ext.define('Ext.data.Session', {mixins:[Ext.mixin.Dirty, Ext.mixin.Observable], isSession:true, config:{schema:'default', parent:null, autoDestroy:true, crudProperties:{create:'C', read:'R', update:'U', drop:'D'}}, crudOperations:[{type:'R', entityMethod:'readEntities'}, {type:'C', entityMethod:'createEntities'}, {type:'U', entityMethod:'updateEntities'}, {type:'D', entityMethod:'dropEntities'}], crudKeys:{C:1, R:1, U:1, D:1}, statics:{nextId:1}, constructor:function(config) {
  var me = this;
  me.data = {};
  me.matrices = {};
  me.id = Ext.data.Session.nextId++;
  me.identifierCache = {};
  me.recordCreator = me.recordCreator.bind(me);
  me.mixins.observable.constructor.call(me, config);
}, destroy:function() {
  var me = this, matrices = me.matrices, data = me.data, entityName, entities, record, id;
  for (id in matrices) {
    matrices[id].destroy();
  }
  for (entityName in data) {
    entities = data[entityName];
    for (id in entities) {
      record = entities[id].record;
      if (record) {
        record.$source = null;
        record.unjoin(me);
      }
    }
  }
  me.identifierCache = me.recordCreator = me.matrices = me.data = null;
  me.setSchema(null);
  me.callParent();
}, adopt:function(record) {
  var me = this, associations = record.associations, roleName;
  me.checkModelType(record.self);
  if (record.session && record.session !== me) {
    Ext.raise('Record already belongs to an existing session');
  }
  if (record.session !== me) {
    me.add(record);
    if (associations) {
      for (roleName in associations) {
        associations[roleName].adoptAssociated(record, me);
      }
    }
  }
}, commit:function() {
  var me = this, data = me.data, matrices = me.matrices, dirtyWas = me.getDirty(), entityName, entities, id, record;
  me.suspendEvent('dirtychange');
  for (entityName in data) {
    entities = data[entityName];
    for (id in entities) {
      record = entities[id].record;
      if (record) {
        record.commit();
      }
    }
  }
  for (id in matrices) {
    matrices[id].commit();
  }
  me.clearRecordStates();
  me.resumeEvent('dirtychange');
  if (me.getDirty() !== dirtyWas) {
    me.fireDirtyChange();
  }
}, createRecord:function(type, data, preventAdd) {
  this.checkModelType(type);
  var Model = type.$isClass ? type : this.getSchema().getEntity(type), parent = this.getParent(), id;
  if (data && parent) {
    id = Model.getIdFromData(data);
    if (parent.peekRecord(Model, id)) {
      Ext.raise('A parent session already contains an entry for ' + Model.entityName + ': ' + id);
    }
  }
  return new Model(data, preventAdd ? null : this);
}, getChanges:function() {
  var visitor = new Ext.data.session.ChangesVisitor(this);
  this.visitData(visitor);
  return visitor.result;
}, getChangesForParent:function() {
  var visitor = new Ext.data.session.ChildChangesVisitor(this);
  this.visitData(visitor);
  return visitor.result;
}, getRecord:function(type, id, autoLoad) {
  var me = this, wasInstance = type.isModel, record, Model, parent, parentRec;
  if (wasInstance) {
    wasInstance = type;
    id = type.id;
    type = type.self;
  }
  record = me.peekRecord(type, id);
  if (!record) {
    Model = type.$isClass ? type : me.getSchema().getEntity(type);
    parent = me.getParent();
    if (parent) {
      parentRec = parent.peekRecord(Model, id);
    }
    if (parentRec) {
      if (parentRec.isLoading()) {
        wasInstance = false;
      } else {
        record = parentRec.copy(undefined, me);
        record.$source = parentRec;
      }
    }
    if (!record) {
      if (wasInstance) {
        record = wasInstance;
        me.adopt(record);
      } else {
        record = Model.createWithId(id, null, me);
        if (autoLoad !== false) {
          record.load(Ext.isObject(autoLoad) ? autoLoad : undefined);
        }
      }
    }
  }
  return record;
}, getSaveBatch:function(sort) {
  var visitor = new Ext.data.session.BatchVisitor;
  this.visitData(visitor);
  return visitor.getBatch(sort);
}, onInvalidAssociationEntity:function(entityType, id) {
  Ext.raise('Unable to read association entity: ' + this.getModelIdentifier(entityType, id));
}, onInvalidEntityCreate:function(entityType, id) {
  Ext.raise('Cannot create, record already not exists: ' + this.getModelIdentifier(entityType, id));
}, onInvalidEntityDrop:function(entityType, id) {
  Ext.raise('Cannot drop, record does not exist: ' + this.getModelIdentifier(entityType, id));
}, onInvalidEntityRead:function(entityType, id) {
  Ext.raise('Cannot read, record already not exists: ' + this.getModelIdentifier(entityType, id));
}, onInvalidEntityUpdate:function(entityType, id, dropped) {
  if (dropped) {
    Ext.raise('Cannot update, record dropped: ' + this.getModelIdentifier(entityType, id));
  } else {
    Ext.raise('Cannot update, record does not exist: ' + this.getModelIdentifier(entityType, id));
  }
}, peekRecord:function(type, id, deep) {
  this.checkModelType(type);
  var entityType = type.$isClass ? type : this.getSchema().getEntity(type), entityName = entityType.entityName, entry = this.data[entityName], ret, parent;
  entry = entry && entry[id];
  ret = entry && entry.record;
  if (!ret && deep) {
    parent = this.getParent();
    ret = parent && parent.peekRecord(type, id, deep);
  }
  return ret || null;
}, save:function() {
  var me = this, parent = me.getParent(), visitor;
  if (parent) {
    visitor = new Ext.data.session.ChildChangesVisitor(me);
    me.visitData(visitor);
    parent.update(visitor.result);
    me.commit();
  } else {
    Ext.raise('Cannot commit session, no parent exists');
  }
}, spawn:function() {
  return new this.self({schema:this.getSchema(), parent:this});
}, update:function(data) {
  var me = this, schema = me.getSchema(), crudOperations = me.crudOperations, len = crudOperations.length, crudKeys = me.crudKeys, dirtyWas = me.getDirty(), entityName, entityType, entityInfo, i, operation, item, associations, key, role, associationData;
  me.suspendEvent('dirtychange');
  me.getSchema().processKeyChecks(true);
  for (entityName in data) {
    entityType = schema.getEntity(entityName);
    if (!entityType) {
      Ext.raise('Invalid entity type: ' + entityName);
    }
    entityInfo = data[entityName];
    for (i = 0; i < len; ++i) {
      operation = crudOperations[i];
      item = entityInfo[operation.type];
      if (item) {
        me[operation.entityMethod](entityType, item);
      }
    }
  }
  for (entityName in data) {
    entityType = schema.getEntity(entityName);
    associations = entityType.associations;
    entityInfo = data[entityName];
    for (key in entityInfo) {
      if (crudKeys[key]) {
        continue;
      }
      role = associations[key];
      if (!role) {
        Ext.raise('Invalid association key for ' + entityName + ', "' + key + '"');
      }
      associationData = entityInfo[role.role];
      role.processUpdate(me, associationData);
    }
  }
  me.resumeEvent('dirtychange');
  if (me.getDirty() !== dirtyWas) {
    me.fireDirtyChange();
  }
}, afterCommit:function(record) {
  this.trackRecordState(record);
}, afterDrop:function(record) {
  this.trackRecordState(record);
}, afterEdit:function(record) {
  this.trackRecordState(record);
}, afterErase:function(record) {
  this.evict(record);
}, afterReject:function(record) {
  this.trackRecordState(record);
}, privates:{add:function(record) {
  var me = this, id = record.id, entry = me.getEntry(record.self, id), associations, roleName;
  if (entry.record) {
    Ext.raise('Duplicate id ' + record.id + ' for ' + record.entityName);
  }
  record.session = me;
  entry.record = record;
  me.trackRecordState(record, true);
  me.registerReferences(record);
  associations = record.associations;
  for (roleName in associations) {
    associations[roleName].checkMembership(me, record);
  }
}, applySchema:function(schema) {
  return Ext.data.schema.Schema.get(schema);
}, checkModelType:function(name) {
  if (name.$isClass) {
    name = name.entityName;
  }
  if (!name) {
    Ext.raise('Unable to use anonymous models in a Session');
  } else {
    if (!this.getSchema().getEntity(name)) {
      Ext.raise('Unknown entity type ' + name);
    }
  }
}, createEntities:function(entityType, items) {
  var me = this, len = items.length, i, data, rec, id;
  for (i = 0; i < len; ++i) {
    data = items[i];
    id = entityType.getIdFromData(data);
    rec = me.peekRecord(entityType, id);
    if (!rec) {
      rec = me.createRecord(entityType, data, true);
      rec.phantom = true;
      rec.crudState = 'C';
      me.add(rec);
      rec.crudStateWas = 'C';
    } else {
      me.onInvalidEntityCreate(entityType, id);
    }
  }
}, dropEntities:function(entityType, ids) {
  var len = ids.length, i, rec, id, extractId;
  if (len) {
    extractId = Ext.isObject(ids[0]);
  }
  for (i = 0; i < len; ++i) {
    id = ids[i];
    if (extractId) {
      id = entityType.getIdFromData(id);
    }
    rec = this.peekRecord(entityType, id);
    if (rec) {
      rec.drop();
    } else {
      this.onInvalidEntityDrop(entityType, id);
    }
  }
}, evict:function(record) {
  var me = this, entityName = record.entityName, entities = me.data[entityName], id = record.id;
  if (entities && entities[id]) {
    me.untrackRecordState(record);
    record.unjoin(me);
    delete entities[id];
  }
}, getEntityList:function(entityType, ids) {
  var len = ids.length, i, id, rec, invalid;
  for (i = 0; i < len; ++i) {
    id = ids[i];
    rec = this.peekRecord(entityType, id);
    if (rec) {
      ids[i] = rec;
    } else {
      invalid = true;
      ids[i] = null;
      this.onInvalidAssociationEntity(entityType, id);
    }
  }
  if (invalid) {
    ids = Ext.Array.clean(ids);
  }
  return ids;
}, getEntry:function(type, id) {
  if (type.isModel) {
    id = type.getId();
    type = type.self;
  }
  var entityType = type.$isClass ? type : this.getSchema().getEntity(type), entityName = entityType.entityName, data = this.data, entry;
  entry = data[entityName] || (data[entityName] = {});
  entry = entry[id] || (entry[id] = {});
  return entry;
}, getRefs:function(record, role, includeParent) {
  var entry = this.getEntry(record), refs = entry && entry.refs && entry.refs[role.role], parent = includeParent && this.getParent(), parentRefs, id, rec;
  if (parent) {
    parentRefs = parent.getRefs(record, role);
    if (parentRefs) {
      for (id in parentRefs) {
        rec = parentRefs[id];
        if (!refs || !refs[id]) {
          this.getRecord(rec.self, rec.id);
        }
      }
      refs = entry && entry.refs && entry.refs[role.role];
    }
  }
  return refs || null;
}, getIdentifier:function(entityType) {
  var parent = this.getParent(), cache, identifier, key, ret;
  if (parent) {
    ret = parent.getIdentifier(entityType);
  } else {
    cache = this.identifierCache;
    identifier = entityType.identifier;
    key = identifier.getId() || entityType.entityName;
    ret = cache[key];
    if (!ret) {
      if (identifier.clone) {
        ret = identifier.clone({id:null});
      } else {
        ret = identifier;
      }
      cache[key] = ret;
    }
  }
  return ret;
}, getMatrix:function(matrix, preventCreate) {
  var name = matrix.isManyToMany ? matrix.name : matrix, matrices = this.matrices, ret;
  ret = matrices[name];
  if (!ret && !preventCreate) {
    ret = matrices[name] = new Ext.data.matrix.Matrix(this, matrix);
  }
  return ret || null;
}, getMatrixSlice:function(role, id) {
  var matrix = this.getMatrix(role.association), side = matrix[role.side];
  return side.get(id);
}, getModelIdentifier:function(entityType, id) {
  return id + '@' + entityType.entityName;
}, onIdChanged:function(record, oldId, newId) {
  var me = this, matrices = me.matrices, entityName = record.entityName, id = record.id, bucket = me.data[entityName], entry = bucket[oldId], associations = record.associations, refs = entry.refs, setNoRefs = me._setNoRefs, association, fieldName, refId, role, roleName, roleRefs, key;
  if (bucket[newId]) {
    Ext.raise('Cannot change ' + entityName + ' id from ' + oldId + ' to ' + newId + ' id already exists');
  }
  delete bucket[oldId];
  bucket[newId] = entry;
  for (key in matrices) {
    matrices[key].updateId(record, oldId, newId);
  }
  if (refs) {
    for (roleName in refs) {
      roleRefs = refs[roleName];
      role = associations[roleName];
      association = role.association;
      if (!association.isManyToMany) {
        fieldName = association.field.name;
        for (refId in roleRefs) {
          roleRefs[refId].set(fieldName, id, setNoRefs);
        }
      }
    }
  }
  me.registerReferences(record, oldId);
}, processManyBlock:function(entityType, role, items, processor) {
  var me = this, id, record, records, store;
  if (items) {
    for (id in items) {
      record = me.peekRecord(entityType, id);
      if (record) {
        records = me.getEntityList(role.cls, items[id]);
        store = role.getAssociatedItem(record);
        me[processor](role, store, record, records);
      } else {
        me.onInvalidAssociationEntity(entityType, id);
      }
    }
  }
}, processManyCreate:function(role, store, record, records) {
  if (store) {
    store.add(records);
  } else {
    record[role.getterName](null, null, records);
  }
}, processManyDrop:function(role, store, record, records) {
  if (store) {
    store.remove(records);
  }
}, processManyRead:function(role, store, record, records) {
  if (store) {
    store.setRecords(records);
  } else {
    record[role.getterName](null, null, records);
  }
}, readEntities:function(entityType, items) {
  var me = this, len = items.length, i, data, rec, id;
  for (i = 0; i < len; ++i) {
    data = items[i];
    id = entityType.getIdFromData(data);
    rec = me.peekRecord(entityType, id);
    if (!rec) {
      rec = me.createRecord(entityType, data, true);
    } else {
      me.onInvalidEntityRead(entityType, id);
    }
    rec.phantom = false;
    me.add(rec);
  }
}, recordCreator:function(data, Model) {
  var me = this, id = Model.getIdFromData(data), record = me.peekRecord(Model, id, true);
  if (!record) {
    record = new Model(data, me);
  } else {
    record = me.getRecord(Model, id);
    record.mergeData(data);
  }
  return record;
}, registerReferences:function(record, oldId) {
  var entityName = record.entityName, id = record.id, recordData = record.data, remove = oldId || oldId === 0, entry, i, fk, len, reference, references, refs, roleName;
  len = (references = record.references).length;
  for (i = 0; i < len; ++i) {
    reference = references[i];
    fk = recordData[reference.name];
    if (fk || fk === 0) {
      reference = reference.reference;
      entityName = reference.type;
      roleName = reference.inverse.role;
      entry = this.getEntry(reference.cls, fk);
      refs = entry.refs || (entry.refs = {});
      refs = refs[roleName] || (refs[roleName] = {});
      refs[id] = record;
      if (remove) {
        delete refs[oldId];
      }
    }
  }
}, updateEntities:function(entityType, items) {
  var len = items.length, i, data, rec, id, modified;
  if (Ext.isArray(items)) {
    for (i = 0; i < len; ++i) {
      data = items[i];
      id = entityType.getIdFromData(data);
      rec = this.peekRecord(entityType, id);
      if (rec) {
        rec.set(data);
      } else {
        this.onInvalidEntityUpdate(entityType, id);
      }
    }
  } else {
    for (id in items) {
      data = items[id];
      rec = this.peekRecord(entityType, id);
      if (rec && !rec.dropped) {
        modified = rec.set(data);
      } else {
        this.onInvalidEntityUpdate(entityType, id, !!rec);
      }
    }
  }
}, updateReference:function(record, field, newValue, oldValue) {
  var reference = field.reference, entityName = reference.type, roleName = reference.inverse.role, id = record.id, entry, refs;
  if (oldValue || oldValue === 0) {
    refs = this.getEntry(entityName, oldValue).refs[roleName];
    delete refs[id];
  }
  if (newValue || newValue === 0) {
    entry = this.getEntry(entityName, newValue);
    refs = entry.refs || (entry.refs = {});
    refs = refs[roleName] || (refs[roleName] = {});
    refs[id] = record;
  }
}, visitData:function(visitor) {
  var me = this, data = me.data, matrices = me.matrices, all, assoc, id, id2, matrix, members, name, record, slice, slices, state;
  me.getSchema().processKeyChecks(true);
  for (name in data) {
    all = data[name];
    for (id in all) {
      record = all[id].record;
      if (record) {
        if (record.phantom || record.dirty || record.dropped) {
          if (visitor.onDirtyRecord) {
            visitor.onDirtyRecord(record);
          }
        } else {
          if (visitor.onCleanRecord) {
            visitor.onCleanRecord(record);
          }
        }
      }
    }
  }
  if (visitor.onMatrixChange) {
    for (name in matrices) {
      matrix = matrices[name].left;
      slices = matrix.slices;
      assoc = matrix.role.association;
      for (id in slices) {
        slice = slices[id];
        members = slice.members;
        for (id2 in members) {
          state = (record = members[id2])[2];
          if (state) {
            visitor.onMatrixChange(assoc, record[0], record[1], state);
          }
        }
      }
    }
  }
  return visitor;
}, _setNoRefs:{refs:false}}});
Ext.define('Ext.util.Schedulable', {'abstract':true, isSchedulable:true, scheduled:false, constructor:function() {
  this.getScheduler().add(this);
}, destroy:function() {
  var me = this, scheduler = me.getScheduler();
  if (scheduler && !scheduler.destroyed) {
    scheduler.remove(me);
  }
  me.scheduler = null;
  me.schedule = me.react = Ext.emptyFn;
  me.callParent();
}, getFullName:function() {
  return this.name || this.id;
}, privates:{getScheduler:function() {
  return this.scheduler;
}, schedule:function() {
  var me = this, scheduler;
  if (!me.scheduled) {
    scheduler = me.getScheduler();
    if (scheduler) {
      me.scheduled = true;
      if (me.onSchedule) {
        me.onSchedule();
      }
      scheduler.scheduleItem(me);
    }
  }
}, unschedule:function() {
  var me = this, scheduler;
  if (me.scheduled) {
    scheduler = me.getScheduler();
    if (scheduler && !scheduler.destroyed) {
      scheduler.unscheduleItem(me);
    }
    me.scheduled = false;
  }
}, sort:function() {
}}});
Ext.define('Ext.app.bind.BaseBinding', {extend:Ext.util.Schedulable, isBinding:true, calls:0, kind:20, defaultOptions:{}, lastValue:undefined, constructor:function(owner, callback, scope, options) {
  var me = this;
  me.options = options;
  me.owner = owner;
  me.scope = scope;
  me.callback = callback;
  if (!callback) {
    Ext.raise('Callback is required');
  }
  me.lateBound = Ext.isString(callback);
  if (options && options.deep) {
    me.deep = true;
  }
  me.callParent();
}, destroy:function() {
  var me = this, owner = me.owner;
  if (owner) {
    owner.onBindDestroy(me);
  }
  me.callParent();
  me.scope = me.callback = me.owner = null;
}, isReadOnly:function() {
  return true;
}, privates:{getScheduler:function() {
  var owner = this.owner;
  return owner && owner.getScheduler();
}, getSession:function() {
  var owner = this.owner;
  return owner.isSession ? owner : owner.getSession();
}, notify:function(value) {
  var me = this, options = me.options || me.defaultOptions, previous = me.lastValue;
  if (!me.calls || me.deep || me.valueChanged(value, previous)) {
    ++me.calls;
    me.lastValue = value;
    if (me.lateBound) {
      me.scope[me.callback](value, previous, me);
    } else {
      me.callback.call(me.scope, value, previous, me);
    }
    if (options.single) {
      me.destroy();
    }
  }
}, valueChanged:function(value, previous) {
  var ret = true;
  if (previous !== value) {
    if (value && previous && value instanceof Date && previous instanceof Date) {
      ret = value.getTime() !== previous.getTime();
    }
  } else {
    ret = Ext.isArray(value);
  }
  return ret;
}}});
Ext.define('Ext.app.bind.Binding', {extend:Ext.app.bind.BaseBinding, constructor:function(stub, callback, scope, options) {
  var me = this;
  me.callParent([stub.owner, callback, scope, options]);
  me.stub = stub;
  me.depth = stub.depth;
  if (stub.isAvailable() && !stub.scheduled) {
    me.schedule();
  }
}, destroy:function(fromParent) {
  var me = this, stub = me.stub;
  if (stub && !fromParent) {
    stub.unbind(me);
    me.stub = null;
  }
  me.callParent();
}, bindValidation:function(callback, scope) {
  var stub = this.stub;
  return stub && stub.bindValidation(callback, scope);
}, bindValidationField:function(callback, scope) {
  var stub = this.stub;
  return stub && stub.bindValidationField(callback, scope);
}, getFullName:function() {
  return this.fullName || (this.fullName = '@(' + this.stub.getFullName() + ')');
}, getValue:function() {
  var me = this, stub = me.stub;
  return stub && stub.getValue();
}, isAvailable:function() {
  var stub = this.stub;
  return stub && stub.isAvailable();
}, isLoading:function() {
  var stub = this.stub;
  return stub && stub.isLoading();
}, isReadOnly:function() {
  var stub = this.stub, options = this.options, ret = true;
  if (!(options && options.twoWay === false)) {
    if (stub) {
      ret = stub.isReadOnly();
    }
  }
  return ret;
}, refresh:function() {
}, setValue:function(value) {
  if (this.isReadOnly()) {
    Ext.raise('Cannot setValue on a readonly binding');
  }
  this.stub.set(value);
}, privates:{getDataObject:function() {
  var stub = this.stub;
  return stub && stub.getDataObject();
}, getRawValue:function() {
  var me = this, stub = me.stub;
  return stub && stub.getRawValue();
}, isDescendantOf:function(item) {
  var stub = this.stub;
  return stub ? item === stub || stub.isDescendantOf(item) : false;
}, react:function() {
  this.notify(this.getValue());
}, schedule:function() {
  if (!this.stub.scheduled) {
    this.callParent();
  }
}, sort:function() {
  var stub = this.stub;
  stub.scheduler.sortItem(stub);
}}});
Ext.define('Ext.app.bind.AbstractStub', {extend:Ext.util.Schedulable, children:null, depth:0, generation:1, kind:10, parent:null, constructor:function(owner, name) {
  var me = this;
  me.owner = owner;
  me.name = name;
  me.callParent();
}, destroy:function() {
  var me = this, children = me.children, bindings = me.bindings, len, i, key;
  if (bindings) {
    for (i = 0, len = bindings.length; i < len; ++i) {
      bindings[i].destroy(true);
    }
  }
  for (key in children) {
    children[key].destroy();
  }
  if (me.scheduled) {
    me.unschedule();
  }
  me.callParent();
}, add:function(child) {
  var me = this;
  (me.children || (me.children = {}))[child.name] = child;
  child.depth = me.depth + 1;
  child.parent = me;
}, getChild:function(path) {
  var pathArray = Ext.isString(path) ? path.split('.') : path;
  if (pathArray && pathArray.length) {
    return this.descend(pathArray, 0);
  }
  return this;
}, getFullName:function() {
  var me = this, name = me.fullName, parent = me.parent, s;
  if (!name) {
    name = me.name || me.id;
    if (parent && (s = parent.getFullName())) {
      name = (s.charAt(s.length - 1) !== ':' ? s + '.' : s) + name;
    }
    me.fullName = name;
  }
  return name;
}, getSession:function() {
  var owner = this.owner;
  return owner.isSession ? owner : owner.getSession();
}, bind:function(callback, scope, options) {
  var me = this, binding = new Ext.app.bind.Binding(me, callback, scope, options), bindings = me.bindings || (me.bindings = []);
  binding.depth = me.depth;
  bindings.push(binding);
  return binding;
}, getValue:function() {
  return this.isAvailable() ? this.getRawValue() : null;
}, graft:function(replacement) {
  var me = this, bindings = me.bindings, name = me.name, i;
  me.parent = me.bindings = null;
  me.destroy();
  replacement.depth = me.depth;
  replacement.bindings = bindings;
  replacement.generation = me.generation + 1;
  replacement.name = name;
  replacement.id = me.id;
  replacement.path = me.path;
  if (bindings) {
    for (i = bindings.length; i-- > 0;) {
      bindings[i].stub = replacement;
    }
  }
  return replacement;
}, isDescendantOf:function(item) {
  var parent;
  for (parent = this; parent = parent.parent;) {
    if (parent === item) {
      return true;
    }
  }
  return false;
}, isAvailable:function() {
  return true;
}, isLoading:function() {
  return false;
}, onSchedule:function() {
  var i, len, binding, bindings, p;
  for (p = this.parent; p; p = p.parent) {
    bindings = p.bindings;
    if (bindings) {
      for (i = 0, len = bindings.length; i < len; ++i) {
        binding = bindings[i];
        if (binding.deep && !binding.scheduled) {
          binding.schedule();
        }
      }
    }
  }
}, react:function() {
  var bindings = this.bindings, binding, i, len;
  if (bindings) {
    for (i = 0, len = bindings.length; i < len; ++i) {
      binding = bindings[i];
      if (!binding.scheduled) {
        binding.schedule();
      }
    }
  }
}, unbind:function(binding) {
  var bindings = this.bindings;
  if (bindings && bindings.length) {
    Ext.Array.remove(bindings, binding);
  }
}, privates:{collect:function() {
  var children = this.children, bindings = this.bindings, totalCount = 0, count = 0, child, key;
  if (children) {
    for (key in children) {
      child = children[key];
      count = child.collect();
      if (count === 0) {
        child.destroy();
        delete children[key];
      }
      totalCount += count;
    }
  }
  if (bindings) {
    totalCount += bindings.length;
  }
  return totalCount;
}, getScheduler:function() {
  var owner = this.owner;
  return owner && owner.getScheduler();
}, sort:function() {
  var parent = this.parent;
  if (parent) {
    this.scheduler.sortItem(parent);
  }
}}});
Ext.define('Ext.app.bind.Stub', {extend:Ext.app.bind.AbstractStub, isStub:true, dirty:true, formula:null, validationKey:'validation', constructor:function(owner, name, parent) {
  var me = this, path = name;
  me.callParent([owner, name]);
  me.boundValue = null;
  if (parent) {
    parent.add(me);
    if (!parent.isRootStub) {
      path = parent.path + '.' + name;
    }
    me.checkHadValue();
  }
  me.path = path;
}, destroy:function() {
  var me = this, formula = me.formula, storeBinding = me.storeBinding;
  if (formula) {
    formula.destroy();
  }
  if (storeBinding) {
    storeBinding.destroy();
  }
  me.detachBound();
  me.callParent();
}, bindValidation:function(callback, scope) {
  var parent = this.parent;
  return parent && parent.descend([this.validationKey, this.name]).bind(callback, scope);
}, bindValidationField:function(callback, scope) {
  var parent = this.parent, name = this.name, lateBound = typeof callback === 'string', ret;
  if (parent) {
    ret = parent.bind(function(value) {
      var field = null;
      if (value && value.isModel) {
        field = value.getField(name);
      }
      if (lateBound) {
        scope[callback](field, value, this);
      } else {
        callback.call(scope, field, value, this);
      }
    });
  }
  return ret || null;
}, descend:function(path, index) {
  var me = this, children = me.children || (me.children = {}), pos = index || 0, name = path[pos++], ret;
  if (!(ret = children[name])) {
    ret = new Ext.app.bind.Stub(me.owner, name, me);
  }
  if (pos < path.length) {
    ret = ret.descend(path, pos);
  }
  return ret;
}, getChildValue:function(parentData) {
  var me = this, name = me.name, bindMappings = me.bindMappings, storeMappings = bindMappings.store, modelMappings = bindMappings.model, ret;
  if (!parentData && !Ext.isString(parentData)) {
    ret = me.hadValue ? null : undefined;
  } else {
    ret = me.inspectValue(parentData);
    if (!ret) {
      if (parentData.isEntity) {
        if (modelMappings[name]) {
          ret = parentData[modelMappings[name]]();
        } else {
          ret = parentData.data[name];
        }
      } else {
        if (parentData.isStore && storeMappings[name]) {
          ret = parentData[storeMappings[name]]();
        } else {
          ret = parentData[name];
          if (ret === undefined && me.hadValue) {
            ret = null;
          }
        }
      }
    }
  }
  return ret;
}, getDataObject:function() {
  var me = this, parentData = me.parent.getDataObject(), name = me.name, ret = parentData ? parentData[name] : null, storeMappings = me.bindMappings.store, associations;
  if (!ret) {
    if (parentData && parentData.isEntity) {
      associations = parentData.associations;
      if (associations && name in associations) {
        ret = parentData[associations[name].getterName]();
      }
    }
  } else {
    if (parentData.isStore && name in storeMappings) {
      ret = parentData[storeMappings[name]]();
    }
  }
  if (!ret || !(ret.$className || Ext.isObject(ret))) {
    parentData[name] = ret = {};
    me.hadValue = true;
    me.invalidate(true, true);
  }
  return ret;
}, getRawValue:function() {
  return this.getChildValue(this.getParentValue());
}, graft:function(replacement) {
  var me = this, parent = me.parent, children = me.children, name = me.name, i, ret;
  replacement.parent = parent;
  replacement.children = children;
  if (parent) {
    parent.children[name] = replacement;
  }
  if (children) {
    for (i in children) {
      children[i].parent = replacement;
    }
  }
  me.children = null;
  replacement.checkHadValue();
  ret = me.callParent([replacement]);
  ret.invalidate(true, true);
  return ret;
}, isAvailable:function() {
  return this.checkAvailability();
}, isLoading:function() {
  return !this.checkAvailability(true);
}, invalidate:function(deep, dirtyOnly) {
  var me = this, children = me.children, name;
  me.dirty = true;
  me.checkHadValue();
  if (!dirtyOnly && me.isAvailable()) {
    if (!me.scheduled) {
      me.schedule();
    }
  }
  if (deep && children) {
    for (name in children) {
      children[name].invalidate(deep, dirtyOnly);
    }
  }
}, isReadOnly:function() {
  var formula = this.formula;
  return !!(formula && !formula.set);
}, set:function(value, preventClimb) {
  var me = this, parent = me.parent, name = me.name, formula = me.formula, parentData, associations, association, formulaStub, setterName;
  if (formula && !formula.settingValue && formula.set) {
    formula.setValue(value);
    return;
  } else {
    if (me.isLinkStub) {
      formulaStub = me.getLinkFormulaStub();
      formula = formulaStub ? formulaStub.formula : null;
      if (formula) {
        if (formulaStub.isReadOnly()) {
          Ext.raise('Cannot setValue on a readonly formula');
        }
        formula.setValue(value);
        return;
      }
    }
  }
  parentData = parent.getDataObject();
  if (parentData.isEntity) {
    associations = parentData.associations;
    if (associations && name in associations) {
      association = associations[name];
      setterName = association.setterName;
      if (setterName) {
        parentData[setterName](value);
      }
      me.invalidate(true);
    } else {
      parentData.set(name, value);
    }
  } else {
    if (value && value.constructor === Object || !(value === parentData[name] && parentData.hasOwnProperty(name))) {
      if (preventClimb || !me.setByLink(value)) {
        if (value === undefined) {
          delete parentData[name];
        } else {
          parentData[name] = value;
        }
        me.inspectValue(parentData);
        me.invalidate(true);
      }
    }
  }
}, onStoreDataChanged:function() {
  this.invalidate(true);
}, afterLoad:function(record) {
  this.invalidate(true);
}, afterCommit:function(record) {
  this.afterEdit(record, null);
}, afterEdit:function(record, modifiedFieldNames) {
  var children = this.children, len = modifiedFieldNames && modifiedFieldNames.length, associations = record.associations, bindMappings = this.bindMappings.model, key, i, child, name, ref;
  if (children) {
    if (len) {
      for (i = 0; i < len; ++i) {
        name = modifiedFieldNames[i];
        child = children[name];
        if (!child) {
          ref = record.fieldsMap[name];
          ref = ref && ref.reference;
          child = ref && children[ref.role];
        }
        if (child) {
          child.invalidate(true);
        }
      }
    } else {
      for (key in children) {
        if (!(associations && key in associations)) {
          children[key].invalidate(true);
        }
      }
    }
    for (key in bindMappings) {
      child = children[key];
      if (child) {
        child.invalidate();
      }
    }
  }
  this.invalidate();
}, afterReject:function(record) {
  this.afterEdit(record, null);
}, afterAssociatedRecordSet:function(record, associated, role) {
  var children = this.children, key = role.role;
  if (children && key in children) {
    children[key].invalidate(true);
  }
}, setByLink:function(value) {
  var me = this, n = 0, ret = false, i, link, path, stub, root, name;
  for (stub = me; stub; stub = stub.parent) {
    if (stub.isLinkStub) {
      link = stub;
      if (n) {
        for (path = [], i = 0, stub = me; stub !== link; stub = stub.parent) {
          ++i;
          path[n - i] = stub.name;
        }
      }
      break;
    }
    ++n;
  }
  stub = null;
  if (link) {
    root = link.parent;
    name = link.name;
    if (!root.shouldClimb(name)) {
      stub = root.insertChild(name);
    } else {
      stub = link.getTargetStub();
    }
  }
  if (stub) {
    if (path) {
      stub = stub.descend(path);
    }
    stub.set(value);
    ret = true;
  }
  return ret;
}, setFormula:function(formula) {
  var me = this, oldFormula = me.formula;
  if (oldFormula) {
    oldFormula.destroy();
  }
  me.formula = new Ext.app.bind.Formula(me, formula);
}, react:function() {
  var me = this, bound = this.boundValue, children = me.children, generation;
  if (bound) {
    if (bound.isValidation) {
      bound.refresh();
      generation = bound.generation;
      if (me.lastValidationGeneration === generation) {
        return;
      }
      me.lastValidationGeneration = generation;
    } else {
      if (bound.isModel) {
        if (children && children[me.validationKey]) {
          bound.isValid();
        }
      }
    }
  }
  this.callParent();
}, privates:{bindMappings:{store:{count:'getCount', first:'first', last:'last', loading:'hasPendingLoad', totalCount:'getTotalCount'}, model:{dirty:'isDirty', phantom:'isPhantom', valid:'isValid'}}, checkAvailability:function(isLoading) {
  var me = this, parent = me.parent, bindMappings = me.bindMappings, name = me.name, available = !!(parent && parent.checkAvailability(isLoading)), associations, parentValue, value, availableSet;
  if (available) {
    parentValue = me.getParentValue();
    value = me.inspectValue(parentValue);
    if (value) {
      if (isLoading) {
        available = !value.hasPendingLoad();
      } else {
        if (value.isStore) {
          available = true;
        } else {
          available = !value.isLoading() || value.loadCount > 0;
        }
      }
    } else {
      if (parentValue) {
        if (parentValue.isModel) {
          if (bindMappings.model[name]) {
            available = !parent.isLoading();
            availableSet = true;
          } else {
            associations = parentValue.associations;
            if (!(associations && name in associations)) {
              available = true;
              availableSet = true;
            }
          }
        } else {
          if (parentValue.isStore && bindMappings.store[name] && name !== 'loading') {
            available = !parent.isLoading();
            availableSet = true;
          }
        }
      }
      if (!availableSet) {
        available = me.hadValue || me.getRawValue() !== undefined;
      }
    }
  }
  return available;
}, checkHadValue:function() {
  if (!this.hadValue) {
    this.hadValue = this.getRawValue() !== undefined;
  }
}, collect:function() {
  var me = this, result = me.callParent(), storeBinding = me.storeBinding ? 1 : 0, formula = me.formula ? 1 : 0;
  return result + storeBinding + formula;
}, getLinkFormulaStub:function() {
  var stub = this;
  while (stub.isLinkStub) {
    stub = stub.binding.stub;
  }
  return stub.formula ? stub : null;
}, getParentValue:function() {
  var me = this;
  if (me.dirty) {
    me.parentValue = me.parent.getValue();
    me.dirty = false;
  }
  return me.parentValue;
}, setStore:function(storeBinding) {
  this.storeBinding = storeBinding;
}, inspectValue:function(parentData) {
  var me = this, name = me.name, current = me.boundValue, boundValue = null, associations, raw, changed, associatedEntity;
  if (parentData && parentData.isEntity) {
    associations = parentData.associations;
    if (associations && name in associations) {
      boundValue = parentData[associations[name].getterName]();
    } else {
      if (name === me.validationKey) {
        boundValue = parentData.getValidation();
        me.lastValidationGeneration = null;
      }
    }
  } else {
    if (parentData) {
      raw = parentData[name];
      if (raw && (raw.isModel || raw.isStore)) {
        boundValue = raw;
      }
    }
  }
  changed = current !== boundValue;
  if (changed) {
    if (current) {
      me.detachBound();
    }
    if (boundValue) {
      if (boundValue.isModel) {
        boundValue.join(me);
      } else {
        associatedEntity = boundValue.associatedEntity;
        if (associatedEntity && boundValue.autoLoad !== false && !boundValue.complete && !boundValue.hasPendingLoad()) {
          boundValue.load();
        }
        boundValue.on({scope:me, beginload:'onStoreDataChanged', load:'onStoreDataChanged', datachanged:'onStoreDataChanged', destroy:'onDestroyBound'});
      }
    }
    me.boundValue = boundValue;
  }
  return boundValue;
}, detachBound:function() {
  var me = this, current = me.boundValue;
  if (current && !current.destroyed) {
    if (current.isModel) {
      current.unjoin(me);
    } else {
      current.un({scope:me, beginload:'onStoreDataChanged', load:'onStoreDataChanged', datachanged:'onStoreDataChanged', destroy:'onDestroyBound'});
    }
  }
}, onDestroyBound:function() {
  if (!this.owner.destroying) {
    this.set(null);
  }
}, sort:function() {
  var me = this, formula = me.formula, scheduler = me.scheduler, storeBinding = me.storeBinding;
  me.callParent();
  if (storeBinding) {
    scheduler.sortItem(storeBinding);
  }
  if (formula) {
    scheduler.sortItem(formula);
  }
}}});
Ext.define('Ext.app.bind.LinkStub', {extend:Ext.app.bind.Stub, isLinkStub:true, binding:null, destroy:function() {
  var me = this, binding = me.binding, owner = me.owner;
  if (binding) {
    me.binding = null;
    binding.destroy();
    if (owner) {
      delete owner.linkData[me.name];
    }
  }
  me.target = null;
  me.callParent();
}, getFullName:function() {
  var me = this;
  return me.fullName || (me.fullName = '(' + me.callParent() + ' -\x3e ' + me.binding.getFullName() + ')');
}, getDataObject:function() {
  var binding = this.binding, root = this.parent, name = this.name, rootData, ret;
  if (root.isRootStub && !root.shouldClimb(name)) {
    rootData = root.owner.getData();
    if (!rootData.hasOwnProperty(name)) {
      rootData[name] = ret = {};
    }
  } else {
    ret = binding && binding.getDataObject();
  }
  return ret;
}, getRawValue:function() {
  var binding = this.binding;
  return binding && binding.getRawValue();
}, getValue:function() {
  var binding = this.binding;
  return binding && binding.getValue();
}, getTargetStub:function() {
  var binding = this.binding;
  return binding && binding.stub;
}, isAvailable:function() {
  var binding = this.binding;
  return binding ? binding.isAvailable() : false;
}, isLoading:function() {
  var binding = this.binding;
  return binding ? binding.isLoading() : false;
}, link:function(bindDescriptor, target) {
  var me = this, binding = me.binding;
  if (binding) {
    binding.destroy();
  }
  target = me.target = target || me.owner;
  me.linkDescriptor = bindDescriptor;
  me.binding = target.bind(bindDescriptor, me.onChange, me);
  me.binding.deep = true;
}, onChange:function() {
  this.invalidate(true);
}, react:function() {
  var me = this, linkData = me.owner.linkData;
  linkData[me.name] = me.getValue();
  me.callParent();
}, privates:{collect:function() {
  var me = this, result = me.callParent(), binding = me.binding ? 1 : 0;
  return result + binding;
}, sort:function() {
  var binding = this.binding;
  if (binding) {
    this.scheduler.sortItem(binding);
  }
}}});
Ext.define('Ext.app.bind.RootStub', {extend:Ext.app.bind.AbstractStub, isRootStub:true, depth:0, createRootChild:function(name, direct) {
  var me = this, owner = me.owner, ownerData = owner.getData(), children = me.children, previous = children && children[name], parentStub = previous ? null : me, parentVM, stub;
  if (direct || ownerData.hasOwnProperty(name) || !(parentVM = owner.getParent())) {
    stub = new Ext.app.bind.Stub(owner, name, parentStub);
  } else {
    stub = new Ext.app.bind.LinkStub(owner, name, parentStub);
    stub.link('{' + name + '}', parentVM);
  }
  if (previous) {
    previous.graft(stub);
  }
  return stub;
}, createStubChild:function(name) {
  return this.createRootChild(name, true);
}, descend:function(path, index) {
  var me = this, children = me.children, pos = index || 0, name = path[pos++], ret = children && children[name] || me.createRootChild(name);
  if (pos < path.length) {
    ret = ret.descend(path, pos);
  }
  return ret;
}, getFullName:function() {
  return this.fullName || (this.fullName = this.owner.id + ':');
}, getDataObject:function() {
  return this.owner.data;
}, getRawValue:function() {
  return this.owner.data;
}, getValue:function() {
  return this.owner.data;
}, isDescendantOf:function() {
  return false;
}, set:function(value, preventClimb) {
  if (!value || value.constructor !== Object) {
    Ext.raise('Only an object can be set at the root');
  }
  var me = this, children = me.children || (me.children = {}), owner = me.owner, data = owner.data, parentVM = owner.getParent(), stub, v, key, setSelf, created;
  for (key in value) {
    if (key.indexOf('.') >= 0) {
      Ext.raise('Value names cannot contain dots');
    }
    v = value[key];
    if (v !== undefined) {
      stub = children[key];
      setSelf = preventClimb || !me.shouldClimb(key);
      if (!stub) {
        stub = me.createRootChild(key, setSelf);
        created = true;
      } else {
        if (setSelf && stub.isLinkStub && !stub.getLinkFormulaStub()) {
          stub = me.insertChild(key);
        }
      }
      if (!created || !data.hasOwnProperty(value)) {
        owner.invalidateChildLinks(key);
      }
      stub.set(v, setSelf);
    } else {
      if (data.hasOwnProperty(key)) {
        delete data[key];
        stub = children[key];
        if (stub) {
          if (!stub.isLinkStub && parentVM) {
            stub = me.createRootChild(key);
          }
          owner.invalidateChildLinks(key, true);
          stub.invalidate(true);
        }
      }
    }
  }
}, schedule:Ext.emptyFn, unschedule:Ext.emptyFn, privates:{checkAvailability:function() {
  return true;
}, insertChild:function(name) {
  return this.createRootChild(name, true);
}, invalidateChildLink:function(name, clear) {
  var children = this.children, stub = children && children[name];
  if (stub && stub.isLinkStub && !stub.getLinkFormulaStub()) {
    stub = this.createRootChild(name);
    if (clear) {
      stub.invalidate(true);
    }
    this.owner.invalidateChildLinks(name, clear);
  }
}, shouldClimb:function(name) {
  var parent = this.owner.getParent();
  while (parent) {
    if (parent.getData().hasOwnProperty(name)) {
      return true;
    }
    parent = parent.getParent();
  }
  return false;
}}});
Ext.define('Ext.app.bind.Multi', {extend:Ext.app.bind.BaseBinding, isMultiBinding:true, missing:1, deep:true, constructor:function(descriptor, owner, callback, scope, options) {
  var me = this, trackStatics = options && options.trackStatics;
  me.callParent([owner, callback, scope, options]);
  me.bindings = [];
  me.literal = descriptor.$literal;
  if (descriptor.constructor === Object) {
    if (trackStatics) {
      me.staticKeys = [];
    }
    me.addObject(descriptor, me.lastValue = {}, me.staticKeys);
  } else {
    me.addArray(descriptor, me.lastValue = []);
  }
  if (!--me.missing && !me.scheduled) {
    me.schedule();
  }
}, destroy:function() {
  var me = this;
  me.bindings = Ext.destroy(me.bindings);
  me.callParent();
}, add:function(descriptor, data, property) {
  var me = this, owner = me.owner, bindings = me.bindings, method = me.literal ? descriptor.reference ? 'bindEntity' : 'bindExpression' : 'bind', binding, depth;
  ++me.missing;
  binding = owner[method](descriptor, function(value) {
    data[property] = value;
    if (binding.calls === 1) {
      --me.missing;
    }
    if (!me.missing && !me.scheduled) {
      me.schedule();
    }
  }, me, null);
  depth = binding.depth;
  if (!bindings.length || depth < me.depth) {
    me.depth = depth;
  }
  bindings.push(binding);
  return !this.isBindingStatic(binding);
}, addArray:function(multiBindDescr, array) {
  var me = this, n = multiBindDescr.length, hasDynamic = false, dynamic, b, i;
  for (i = 0; i < n; ++i) {
    b = multiBindDescr[i];
    if (b && (b.reference || Ext.isString(b))) {
      dynamic = me.add(b, array, i);
    } else {
      if (Ext.isArray(b)) {
        dynamic = me.addArray(b, array[i] = []);
      } else {
        if (b && b.constructor === Object) {
          dynamic = me.addObject(b, array[i] = {});
        } else {
          array[i] = b;
          dynamic = false;
        }
      }
    }
    hasDynamic = hasDynamic || dynamic;
  }
  return hasDynamic;
}, addObject:function(multiBindDescr, object, staticKeys) {
  var me = this, hasDynamic = false, dynamic, b, name;
  for (name in multiBindDescr) {
    b = multiBindDescr[name];
    if (b && (b.reference || Ext.isString(b))) {
      dynamic = me.add(b, object, name);
    } else {
      if (Ext.isArray(b)) {
        dynamic = me.addArray(b, object[name] = []);
      } else {
        if (b && b.constructor === Object) {
          dynamic = me.addObject(b, object[name] = {});
        } else {
          object[name] = b;
          dynamic = false;
        }
      }
    }
    if (staticKeys && !dynamic) {
      staticKeys.push(name);
    }
    hasDynamic = hasDynamic || dynamic;
  }
  return hasDynamic;
}, getFullName:function() {
  var me = this, fullName = me.fullName, bindings = me.bindings, length = bindings.length, i;
  if (!fullName) {
    fullName = '@[';
    for (i = 0; i < length; ++i) {
      if (i) {
        fullName += ',';
      }
      fullName += bindings[i].getFullName();
    }
    fullName += ']';
    me.fullName = fullName;
  }
  return fullName;
}, getRawValue:function() {
  return this.lastValue;
}, isDescendantOf:function() {
  return false;
}, isLoading:function() {
  var bindings = this.bindings, n = bindings.length;
  for (; n-- > 0;) {
    if (bindings[n].isLoading()) {
      return true;
    }
  }
  return false;
}, isAvailable:function() {
  var bindings = this.bindings, n = bindings.length;
  for (; n-- > 0;) {
    if (bindings[n].isAvailable()) {
      return true;
    }
  }
  return false;
}, isBindingStatic:function(binding) {
  return binding.isTemplateBinding && binding.isStatic;
}, isStatic:function() {
  var bindings = this.bindings, len = bindings.length, i, binding;
  for (i = 0; i < len; ++i) {
    binding = bindings[i];
    if (!this.isBindingStatic(binding)) {
      return false;
    }
  }
  return true;
}, pruneStaticKeys:function() {
  var value = Ext.apply({}, this.lastValue), keys = this.staticKeys, len = keys.length, i;
  for (i = 0; i < len; ++i) {
    delete value[keys[i]];
  }
  return value;
}, react:function() {
  this.notify(this.lastValue);
}, refresh:function() {
}, privates:{sort:function() {
  this.scheduler.sortItems(this.bindings);
}}});
Ext.define('Ext.app.bind.Formula', {extend:Ext.util.Schedulable, statics:{getFormulaParser:function(name) {
  var cache = this.formulaCache, parser, s;
  if (!cache) {
    cache = this.formulaCache = new Ext.util.LruCache({maxSize:20});
  }
  parser = cache.get(name);
  if (!parser) {
    s = '[^\\.a-z0-9_]' + Ext.String.escapeRegex(name) + '\\(\\s*([\'"])(.*?)\\1\\s*\\)';
    parser = new RegExp(s, 'gi');
    cache.add(name, parser);
  }
  return parser;
}}, isFormula:true, calculation:null, explicit:false, set:null, single:false, fnKeywordArgumentNamesRe:/^function\s*[^\(]*\(\s*([^,\)\s]+)/, fnKeywordRe:/^\s*function/, replaceParenRe:/[\(\)]/g, constructor:function(stub, formula) {
  var me = this, owner = stub.owner, bindTo, expressions, getter, options;
  me.owner = owner;
  me.stub = stub;
  me.callParent();
  if (formula instanceof Function) {
    me.get = getter = formula;
  } else {
    me.get = getter = formula.get;
    me.set = formula.set;
    expressions = formula.bind;
    if (formula.single) {
      me.single = formula.single;
    }
    if (expressions) {
      bindTo = expressions.bindTo;
      if (bindTo) {
        options = Ext.apply({}, expressions);
        delete options.bindTo;
        expressions = bindTo;
      }
    }
  }
  if (!getter) {
    Ext.raise('Must specify a getter method for a formula');
  }
  if (expressions) {
    me.explicit = true;
  } else {
    expressions = getter.$expressions || me.parseFormula(getter);
  }
  me.binding = owner.bind(expressions, me.onChange, me, options);
}, destroy:function() {
  var me = this, binding = me.binding, stub = me.stub;
  if (binding) {
    binding.destroy();
    me.binding = null;
  }
  if (stub) {
    stub.formula = null;
  }
  me.callParent();
  me.getterFn = me.owner = null;
}, getFullName:function() {
  return this.fullName || (this.fullName = this.stub.getFullName() + '\x3d' + this.callParent() + ')');
}, getRawValue:function() {
  return this.calculation;
}, onChange:function() {
  if (!this.scheduled) {
    this.schedule();
  }
}, parseFormula:function(formula) {
  var str = Ext.Function.toCode(formula), defaultProp = 'get', expressions = {$literal:true}, match, getterProp, formulaRe, expr;
  if (this.fnKeywordRe.test(str)) {
    match = this.fnKeywordArgumentNamesRe.exec(str);
    if (match) {
      getterProp = match[1];
    }
  } else {
    match = str.split('\x3d\x3e')[0];
    if (match) {
      match = Ext.String.trim(match.replace(this.replaceParenRe, '')).split(',');
      getterProp = match[0];
    }
  }
  getterProp = getterProp || defaultProp;
  formulaRe = Ext.app.bind.Formula.getFormulaParser(getterProp);
  while (match = formulaRe.exec(str)) {
    expr = match[2];
    expressions[expr] = expr;
  }
  expressions.$literal = true;
  formula.$expressions = expressions;
  return expressions;
}, react:function() {
  var me = this, owner = me.owner, data = me.binding.lastValue, arg;
  if (me.explicit) {
    arg = data;
  } else {
    arg = owner.getFormulaFn(data);
  }
  me.settingValue = true;
  me.stub.set(me.calculation = me.get.call(owner, arg));
  me.settingValue = false;
  if (me.single) {
    me.destroy();
  }
}, setValue:function(value) {
  this.set.call(this.stub.owner, value);
}, privates:{getScheduler:function() {
  var owner = this.owner;
  return owner && owner.getScheduler();
}, sort:function() {
  var me = this, binding = me.binding;
  if (!binding.destroyed) {
    me.scheduler.sortItem(binding);
  }
}}});
Ext.define('Ext.util.Fly', {inheritableStatics:{flyPoolSize:2, fly:function() {
  var T = this, flyweights = T.flyweights || (T.flyweights = []), instance = flyweights.length ? flyweights.pop() : new T;
  instance.reset.apply(instance, arguments);
  return instance;
}}, release:function() {
  var me = this, T = me.self, flyweights = T.flyweights || (T.flyweights = []);
  me.reset();
  if (flyweights.length < T.flyPoolSize) {
    flyweights.push(me);
  }
}, reset:Ext.emptyFn});
Ext.define('Ext.parse.Tokenizer', function(Tokenizer) {
  var flyweights = Tokenizer.flyweights = [], BOOLEAN = {literal:true, 'boolean':true, type:'boolean'}, ERROR = {error:true}, IDENT = {ident:true}, LITERAL = {literal:true}, NULL = {literal:true, nil:true}, NUMBER = {literal:true, number:true, type:'number'}, STRING = {literal:true, string:true, type:'string'};
  return {extend:Ext.util.Fly, isTokenizer:true, statics:{BOOLEAN:BOOLEAN, ERROR:ERROR, IDENT:IDENT, LITERAL:LITERAL, NULL:NULL, NUMBER:NUMBER, STRING:STRING}, config:{keywords:{'null':{type:'literal', is:NULL, value:null}, 'false':{type:'literal', is:BOOLEAN, value:false}, 'true':{type:'literal', is:BOOLEAN, value:true}}, operators:{'+':'plus', '-':'minus', '*':'multiply', '/':'divide', '!':'not', ',':'comma', ':':'colon', '[':'arrayOpen', ']':'arrayClose', '{':'curlyOpen', '}':'curlyClose', '(':'parenOpen', 
  ')':'parenClose'}, patterns:null}, error:null, index:-1, constructor:function(config) {
    this.operators = {};
    this.patterns = [];
    this.initConfig(config);
  }, next:function() {
    var token = this.peek();
    this.head = undefined;
    return token;
  }, peek:function() {
    var me = this, error = me.error, token = me.head;
    if (error) {
      return error;
    }
    if (token === undefined) {
      me.head = token = me.advance();
    }
    return token;
  }, release:function() {
    this.reset();
    if (flyweights.length < Tokenizer.flyPoolSize) {
      flyweights.push(this);
    }
  }, reset:function(text, pos, end) {
    var me = this;
    me.error = null;
    me.head = undefined;
    me.index = -1;
    me.text = text || null;
    me.pos = pos || 0;
    me.end = text && end == null ? text.length : end;
    return me;
  }, privates:{digitRe:/[0-9]/, identFirstRe:/[a-z_$]/i, identRe:/[0-9a-z_$]/i, spaceRe:/[ \t]/, end:0, head:undefined, pos:0, text:null, applyOperators:function(ops) {
    var operators = this.operators, block, c, def, i, len, name, op;
    for (op in ops) {
      block = operators;
      name = ops[op];
      len = op.length;
      for (i = 0; i < len; ++i) {
        c = op.charAt(i);
        block = block[c] || (block[c] = {});
      }
      if (name) {
        block.token = def = {type:'operator', name:name, value:op, is:{operator:true}};
        def.is[name] = true;
      } else {
        block.token = null;
      }
    }
  }, applyPatterns:function(pat) {
    var patterns = this.patterns, def, extract, name, re;
    for (name in pat) {
      def = pat[name];
      extract = def.extract;
      re = def.re;
      delete def.extract;
      delete def.re;
      patterns.push({name:name, re:re, extract:extract, token:def});
    }
  }, advance:function() {
    var me = this, spaceRe = me.spaceRe, text = me.text, length = me.end, c;
    while (me.pos < length) {
      c = text.charAt(me.pos);
      if (spaceRe.test(c)) {
        ++me.pos;
        continue;
      }
      me.index = me.pos;
      return me.parse(c);
    }
    return null;
  }, parse:function(c) {
    var me = this, digitRe = me.digitRe, text = me.text, length = me.end, patterns = me.patterns, i, match, pat, ret;
    if (c === '.' && me.pos + 1 < length) {
      if (digitRe.test(text.charAt(me.pos + 1))) {
        ret = me.parseNumber();
      }
    }
    if (!ret) {
      for (i = 0; i < patterns.length; ++i) {
        pat = patterns[i];
        pat.re.lastIndex = me.pos;
        match = pat.re.exec(text);
        if (match && match.index === me.pos) {
          ret = Ext.apply({value:pat.extract ? pat.extract(match) : match[0]}, pat.token);
          me.pos += match[0].length;
          break;
        }
      }
    }
    if (!ret && me.operators[c]) {
      ret = me.parseOperator(c);
    }
    if (!ret) {
      if (c === '"' || c === "'") {
        ret = me.parseString();
      } else {
        if (digitRe.test(c)) {
          ret = me.parseNumber();
        } else {
          if (me.identFirstRe.test(c)) {
            ret = me.parseIdent();
          } else {
            ret = me.syntaxError('Unexpected character');
          }
        }
      }
    }
    return ret;
  }, parseIdent:function() {
    var me = this, identRe = me.identRe, keywords = me.getKeywords(), includeDots = !me.operators['.'], text = me.text, start = me.pos, end = start, length = me.end, prev = 0, c, value;
    while (end < length) {
      c = text.charAt(end);
      if (includeDots && c === '.') {
        if (prev === '.') {
          return me.syntaxError(end, 'Unexpected dot operator');
        }
        ++end;
      } else {
        if (identRe.test(c)) {
          ++end;
        } else {
          break;
        }
      }
      prev = c;
    }
    if (prev === '.') {
      return me.syntaxError(end - 1, 'Unexpected dot operator');
    }
    value = text.substring(start, me.pos = end);
    return keywords && keywords[value] || {type:'ident', is:IDENT, value:value};
  }, parseNumber:function() {
    var me = this, digitRe = me.digitRe, text = me.text, start = me.pos, length = me.end, c, decimal, exp, token;
    while (me.pos < length) {
      c = text.charAt(me.pos);
      if (c === '-' || c === '+') {
        if (me.pos !== start) {
          break;
        }
        ++me.pos;
      } else {
        if (c === '.') {
          if (decimal) {
            break;
          }
          decimal = true;
          ++me.pos;
        } else {
          if (c === 'e' || c === 'E') {
            if (exp) {
              break;
            }
            decimal = exp = true;
            c = text.charAt(++me.pos);
            if (c === '-' || c === '+') {
              ++me.pos;
            }
          } else {
            if (digitRe.test(c)) {
              ++me.pos;
            } else {
              break;
            }
          }
        }
      }
    }
    token = {type:'literal', is:NUMBER, value:+text.substring(start, me.pos)};
    if (!isFinite(token.value)) {
      token = me.syntaxError(start, 'Invalid number');
    }
    return token;
  }, parseOperator:function(c) {
    var me = this, block = me.operators, text = me.text, length = me.end, end = me.pos, match, matchEnd, token;
    while (block[c]) {
      block = block[c];
      token = block.token;
      ++end;
      if (token) {
        match = token;
        matchEnd = end;
      }
      if (end < length) {
        c = text.charAt(end);
      } else {
        break;
      }
    }
    if (match) {
      me.pos = matchEnd;
    }
    return match;
  }, parseString:function() {
    var me = this, text = me.text, pos = me.pos, start = pos, length = me.end, str = '', c, closed, quote;
    quote = text.charAt(pos++);
    while (pos < length) {
      c = text.charAt(pos++);
      if (c === quote) {
        closed = true;
        break;
      }
      if (c === '\\' && pos < length) {
        c = text.charAt(pos++);
      }
      str += c;
    }
    me.pos = pos;
    if (!closed) {
      return me.syntaxError(start, 'Unterminated string');
    }
    return {type:'literal', is:STRING, value:str};
  }, syntaxError:function(at, message) {
    if (typeof at === 'string') {
      message = at;
      at = this.pos;
    }
    var suffix = at == null ? '' : ' (at index ' + at + ')', error = new Error(message + suffix);
    error.type = 'error';
    error.is = ERROR;
    if (suffix) {
      error.at = at;
    }
    return this.error = error;
  }}};
});
Ext.define('Ext.parse.Symbol', {priority:0, constructor:function(id, config) {
  var me = this, defaultProperty = me.defaultProperty;
  if (config && typeof config === 'object') {
    Ext.apply(me, config);
  } else {
    if (config !== undefined && defaultProperty) {
      me[defaultProperty] = config;
    }
  }
  me.id = id;
}, dump:function() {
  var me = this, ret = {at:me.at, arity:me.arity}, i;
  if ('value' in me) {
    ret.value = me.value;
  }
  if (me.lhs) {
    ret.lhs = me.lhs.dump();
    ret.rhs = me.rhs.dump();
  }
  if (me.operand) {
    ret.operand = me.operand.dump();
  }
  if (me.args) {
    ret.args = [];
    for (i = 0; i < me.args.length; ++i) {
      ret.args.push(me.args[i].dump());
    }
  }
  return ret;
}, led:function() {
  this.parser.syntaxError(this.at, 'Missing operator');
}, nud:function() {
  this.parser.syntaxError(this.at, 'Undefined');
}, update:function(config) {
  if (config && typeof config === 'object') {
    var me = this, priority = config.priority, led = config.led, nud = config.nud;
    if (me.priority <= priority) {
      me.priority = priority;
    }
    if (led) {
      me.led = led;
    }
    if (nud) {
      me.nud = nud;
    }
  }
}});
Ext.define('Ext.parse.symbol.Constant', {extend:Ext.parse.Symbol, arity:'literal', isLiteral:true, defaultProperty:'value', constructor:function(id, config) {
  this.callParent([id, config]);
  this._value = this.value;
}, nud:function() {
  var me = this;
  me.value = me._value;
  me.arity = 'literal';
  me.isLiteral = true;
  return me;
}});
Ext.define('Ext.parse.symbol.Infix', {extend:Ext.parse.Symbol, arity:'binary', isBinary:true, defaultProperty:'priority', led:function(left) {
  var me = this;
  me.lhs = left;
  me.rhs = me.parser.parseExpression(me.priority);
  me.arity = 'binary';
  me.isBinary = true;
  return me;
}});
Ext.define('Ext.parse.symbol.InfixRight', {extend:Ext.parse.symbol.Infix, led:function(left) {
  var me = this;
  me.lhs = left;
  me.rhs = me.parser.parseExpression(me.priority - 1);
  me.arity = 'binary';
  me.isBinary = true;
  return me;
}});
Ext.define('Ext.parse.symbol.Paren', {extend:Ext.parse.Symbol, arity:'binary', isBinary:true, priority:80, led:function(left) {
  var me = this, args = [], parser = me.parser, id = left.id, type = left.arity;
  if (id !== '.' && id !== '[') {
    if ((type !== 'unary' || id !== 'function') && type !== 'ident' && id !== '(' && id !== '\x26\x26' && id !== '||' && id !== '?') {
      parser.syntaxError(left.at, 'Expected a variable name.');
    }
  }
  me.arity = 'invoke';
  me.isInvoke = true;
  me.operand = left;
  me.args = args;
  while (parser.token.id !== ')') {
    if (args.length) {
      parser.advance(',');
    }
    args.push(parser.parseExpression());
  }
  parser.advance(')');
  return me;
}, nud:function() {
  var parser = this.parser, ret = parser.parseExpression();
  parser.advance(')');
  return ret;
}});
Ext.define('Ext.parse.symbol.Prefix', {extend:Ext.parse.Symbol, arity:'unary', isUnary:true, priority:70, nud:function() {
  var me = this;
  me.operand = me.parser.parseExpression(me.priority);
  me.arity = 'unary';
  me.isUnary = true;
  return me;
}});
Ext.define('Ext.parse.Parser', function() {
  var ITSELF = function() {
    return this;
  };
  return {extend:Ext.util.Fly, isParser:true, config:{constants:{'null':null, 'false':false, 'true':true}, infix:{'\x3d\x3d\x3d':40, '!\x3d\x3d':40, '\x3d\x3d':40, '!\x3d':40, '\x3c':40, '\x3c\x3d':40, '\x3e':40, '\x3e\x3d':40, '+':50, '-':50, '*':60, '/':60}, infixRight:{'\x26\x26':30, '||':30}, prefix:{'!':0, '-':0, '+':0}, symbols:{':':0, ',':0, ')':0, '[':0, ']':0, '{':0, '}':0, '(end)':0, '(ident)':{arity:'ident', isIdent:true, nud:ITSELF}, '(literal)':{arity:'literal', isLiteral:true, nud:ITSELF}, 
  '(':{xclass:'Ext.parse.symbol.Paren'}}, tokenizer:{keywords:null}}, token:null, constructor:function(config) {
    this.symbols = {};
    this.initConfig(config);
  }, advance:function(expected) {
    var me = this, tokenizer = me.tokenizer, token = tokenizer.peek(), symbols = me.symbols, index = tokenizer.index, is, name, symbol, value;
    if (me.error) {
      throw me.error;
    }
    if (expected) {
      me.expect(expected);
    }
    if (!token) {
      return me.token = symbols['(end)'];
    }
    tokenizer.next();
    is = token.is;
    value = token.value;
    if (is.ident) {
      symbol = symbols[value] || symbols['(ident)'];
    } else {
      if (is.operator) {
        if (!(symbol = symbols[value])) {
          me.syntaxError(token.at, 'Unknown operator "' + value + '"');
        }
        name = token.name;
      } else {
        if (is.literal) {
          symbol = symbols['(literal)'];
        } else {
          me.syntaxError(token.at, 'Unexpected token');
        }
      }
    }
    me.token = symbol = Ext.Object.chain(symbol);
    symbol.at = index;
    symbol.is = is;
    symbol.value = value;
    if (!symbol.arity) {
      symbol.arity = token.type;
    }
    if (name) {
      symbol.name = name;
    }
    return symbol;
  }, expect:function(expected) {
    var token = this.token;
    if (expected !== token.id) {
      this.syntaxError(token.at, 'Expected "' + expected + '"');
    }
    return this;
  }, parseExpression:function(rightPriority) {
    var me = this, token = me.token, left;
    rightPriority = rightPriority || 0;
    me.advance();
    left = token.nud();
    while (rightPriority < (token = me.token).priority) {
      me.advance();
      left = token.led(left);
    }
    return left;
  }, reset:function(text, pos, end) {
    var me = this;
    me.error = me.token = null;
    me.tokenizer.reset(text, pos, end);
    me.advance();
    return me;
  }, syntaxError:function(at, message) {
    if (typeof at === 'string') {
      message = at;
      at = this.pos;
    }
    var suffix = at == null ? '' : ' (at index ' + at + ')', error = new Error(message + suffix);
    error.type = 'error';
    if (suffix) {
      error.at = at;
    }
    throw this.error = error;
  }, privates:{error:null, addSymbol:function(id, config, type, update) {
    var symbols = this.symbols, symbol = symbols[id], cfg, length, i;
    if (symbol) {
      if (typeof config === 'object') {
        cfg = config;
      } else {
        if (update && type) {
          update = Ext.Array.from(update);
          length = update.length;
          cfg = {};
          for (i = 0; i < length; i++) {
            cfg[update[i]] = type.prototype[update[i]];
          }
        } else {
          return symbol;
        }
      }
      symbol.update(cfg);
    } else {
      if (config && config.xclass) {
        type = Ext.ClassManager.get(config.xclass);
      } else {
        type = type || Ext.parse.Symbol;
      }
      symbols[id] = symbol = new type(id, config);
      symbol.parser = this;
    }
    return symbol;
  }, addSymbols:function(symbols, type, update) {
    var id;
    for (id in symbols) {
      this.addSymbol(id, symbols[id], type, update);
    }
  }, applyConstants:function(constants) {
    this.addSymbols(constants, Ext.parse.symbol.Constant, 'nud');
  }, applyInfix:function(operators) {
    this.addSymbols(operators, Ext.parse.symbol.Infix, 'led');
  }, applyInfixRight:function(operators) {
    this.addSymbols(operators, Ext.parse.symbol.InfixRight, 'led');
  }, applyPrefix:function(operators) {
    this.addSymbols(operators, Ext.parse.symbol.Prefix, 'nud');
  }, applySymbols:function(symbols) {
    this.addSymbols(symbols);
  }, applyTokenizer:function(config) {
    var ret = config;
    if (config && !config.isTokenizer) {
      ret = new Ext.parse.Tokenizer(config);
    }
    this.tokenizer = ret;
  }}};
});
Ext.define('Ext.app.bind.Parser', {extend:Ext.parse.Parser, infix:{':':{priority:70, dump:function() {
  var me = this, ret = {at:me.at, arity:me.arity, value:me.value, operand:me.operand.dump(), fmt:[]}, fmt = me.fmt, i;
  for (i = 0; i < fmt.length; ++i) {
    ret.fmt.push(fmt[i].dump());
  }
  return ret;
}, led:function(left) {
  var me = this;
  me.arity = 'formatter';
  me.operand = left;
  me.fmt = me.parser.parseFmt();
  return me;
}}, '?':{priority:20, led:function(left) {
  var me = this, parser = me.parser, symbol = parser.symbols[':'], temp;
  me.condition = left;
  temp = symbol.priority;
  symbol.priority = 0;
  me.tv = parser.parseExpression(0);
  me.parser.advance(':');
  symbol.priority = temp;
  me.fv = parser.parseExpression(0);
  me.arity = 'ternary';
  return me;
}}}, symbols:{'(':{nud:function() {
  var parser = this.parser, symbol = parser.symbols[':'], ret, temp;
  temp = symbol.priority;
  symbol.priority = 70;
  ret = parser.parseExpression();
  parser.advance(')');
  symbol.priority = temp;
  return ret;
}}}, prefix:{'@':0}, tokenizer:{operators:{'@':'at', '?':'qmark', '\x3d\x3d\x3d':'feq', '!\x3d\x3d':'fneq', '\x3d\x3d':'eq', '!\x3d':'neq', '\x3c':'lt', '\x3c\x3d':'lte', '\x3e':'gt', '\x3e\x3d':'gte', '\x26\x26':'and', '||':'or'}}, compileExpression:function(tokens, tokensMaps) {
  var me = this, debug, fn;
  me.tokens = tokens;
  me.tokensMap = tokensMaps;
  debug = me.token.value === '@' && me.tokenizer.peek();
  if (debug) {
    debug = debug.value === 'debugger';
    if (debug) {
      me.advance();
      me.advance();
    }
  }
  fn = me.parseSlot(me.parseExpression(), debug);
  me.tokens = me.tokensMap = null;
  return fn;
}, compileFormat:function() {
  var me = this, fn;
  try {
    fn = me.parseSlot({arity:'formatter', fmt:me.parseFmt(), operand:{arity:'ident', value:'dummy'}});
    me.expect('(end)');
  } catch (e$56) {
    Ext.raise('Invalid format expression: "' + me.tokenizer.text + '"');
  }
  return fn;
}, privates:{useEval:Ext.isGecko, escapeRe:/(["'\\])/g, parseFmt:function() {
  var me = this, fmt = [], priority = me.symbols[':'].priority, expr;
  do {
    if (fmt.length) {
      me.advance();
    }
    expr = me.parseExpression(priority);
    if (expr.isIdent || expr.isInvoke) {
      fmt.push(expr);
    } else {
      me.syntaxError(expr.at, 'Expected formatter name');
    }
  } while (me.token.id === ':');
  return fmt;
}, parseSlot:function(expr, debug) {
  var me = this, defs = [], body = [], tokens = me.tokens || [], fn, code, i, length, temp;
  me.definitions = defs;
  me.body = body;
  body.push('return ' + me.compile(expr) + ';');
  length = tokens.length;
  code = 'var fm \x3d Ext.util.Format,\nme,';
  temp = 'var a \x3d Ext.Array.from(values);\nme \x3d scope;\n';
  if (tokens.length) {
    for (i = 0; i < length; i++) {
      code += 'v' + i + (i === length - 1 ? ';' : ',');
      temp += 'v' + i + ' \x3d a[' + i + ']; ';
    }
  } else {
    code += 'v0;';
    temp += 'v0 \x3d a[0];';
  }
  defs = Ext.Array.insert(defs, 0, [code]);
  body = Ext.Array.insert(body, 0, [temp]);
  body = body.join('\n');
  if (debug) {
    body = 'debugger;\n' + body;
  }
  defs.push((me.useEval ? '$\x3d' : 'return') + ' function (values, scope) {', body, '}');
  code = defs.join('\n');
  fn = me.useEval ? me.evalFn(code) : (new Function('Ext', code))(Ext);
  me.definitions = me.body = null;
  return fn;
}, compile:function(expr) {
  var me = this, v;
  switch(expr.arity) {
    case 'ident':
      return me.addToken(expr.value);
    case 'literal':
      v = expr.value;
      return typeof v === 'string' ? '"' + String(v).replace(me.escapeRe, '\\$1') + '"' : v;
    case 'unary':
      return me.compileUnary(expr);
    case 'binary':
      return me.compileBinary(expr);
    case 'ternary':
      return me.compileTernary(expr);
    case 'formatter':
      return me.compileFormatter(expr);
  }
  return this.syntaxError(expr.at, 'Compile error! Unknown symbol');
}, compileUnary:function(expr) {
  var v = expr.value, op = expr.operand;
  if (v === '!' || v === '-' || v === '+') {
    return v + '(' + this.compile(op) + ')';
  } else {
    if (v === '@') {
      if (!op.isIdent) {
        return this.syntaxError(expr.at, 'Compile error! Unexpected symbol');
      }
      return op.value;
    }
  }
  return '';
}, compileBinary:function(expr) {
  return '(' + this.compile(expr.lhs) + ' ' + expr.value + ' ' + this.compile(expr.rhs) + ')';
}, compileTernary:function(expr) {
  return '(' + this.compile(expr.condition) + ' ? ' + this.compile(expr.tv) + ' : ' + this.compile(expr.fv) + ')';
}, compileFormatter:function(expr) {
  var me = this, fmt = expr.fmt, length = fmt.length, body = ['var ret;'], i;
  if (fmt.length) {
    body.push('ret \x3d ' + me.compileFormatFn(fmt[0], me.compile(expr.operand)) + ';');
    for (i = 1; i < length; i++) {
      body.push('ret \x3d ' + me.compileFormatFn(fmt[i], 'ret') + ';');
    }
  }
  body.push('return ret;');
  return me.addFn(body.join('\n'));
}, compileFormatFn:function(expr, value) {
  var fmt, args = [], code = '', length, i;
  if (expr.isIdent) {
    fmt = expr.value;
  } else {
    if (expr.isInvoke) {
      fmt = expr.operand.value;
      args = expr.args;
    }
  }
  if (fmt.substring(0, 5) === 'this.') {
    fmt = 'me.' + fmt.substring(5);
  } else {
    if (!(fmt in Ext.util.Format)) {
      return this.syntaxError(expr.at, 'Compile error! Invalid format specified "' + fmt + '"');
    }
    fmt = 'fm.' + fmt;
  }
  code += value;
  length = args.length;
  for (i = 0; i < length; i++) {
    code += ', ' + this.compile(args[i]);
  }
  return fmt + '(' + code + ')';
}, addFn:function(body) {
  var defs = this.definitions, name = 'f' + defs.length;
  defs.push('function ' + name + '() {', body, '}');
  return name + '()';
}, evalFn:function($) {
  eval($);
  return $;
}, addToken:function(token) {
  var tokensMap = this.tokensMap, tokens = this.tokens, pos = 0;
  if (tokensMap && tokens) {
    if (token in tokensMap) {
      pos = tokensMap[token];
    } else {
      tokensMap[token] = pos = tokens.length;
      tokens.push(token);
    }
  }
  return 'v' + pos;
}}});
Ext.define('Ext.app.bind.Template', {escapes:false, buffer:null, slots:null, tokens:null, constructor:function(text) {
  var me = this, initters = me._initters, name;
  me.text = text;
  for (name in initters) {
    me[name] = initters[name];
  }
}, _initters:{apply:function(values, scope) {
  return this.parse().apply(values, scope);
}, getTokens:function() {
  return this.parse().getTokens();
}}, apply:function(values, scope) {
  var me = this, slots = me.slots, buffer = me.buffer, length = slots.length, i, slot;
  for (i = 0; i < length; ++i) {
    slot = slots[i];
    if (slot) {
      buffer[i] = slot(values, scope);
    }
  }
  if (slot && me.single) {
    return buffer[0];
  }
  return buffer.join('');
}, getText:function() {
  return this.buffer.join('');
}, getTokens:function() {
  return this.tokens;
}, isStatic:function() {
  var tokens = this.getTokens(), slots = this.slots;
  return tokens.length === 0 && slots.length === 0;
}, privates:{literalChar:'~', escapeChar:'\\', parse:function() {
  var me = this, text = me.text, parser = Ext.app.bind.Parser.fly(), buffer = me.buffer = [], slots = me.slots = [], length = text.length, pos = 0, escapes = me.escapes, current = '', i = 0, esc = me.escapeChar, lit = me.literalChar, escaped, lastEscaped, c, prev, key;
  for (key in me._initters) {
    delete me[key];
  }
  me.tokens = [];
  me.tokensMap = {};
  while (i < length) {
    c = text[i];
    lastEscaped = escaped;
    escaped = escapes && c === esc;
    if (escaped) {
      c = text[i + 1];
      ++i;
    } else {
      if (c === lit && prev === lit && !lastEscaped) {
        current = current.slice(0, -1);
        current += text.substring(i + 1);
        break;
      } else {
        if (c === '{') {
          if (current) {
            buffer[pos++] = current;
            current = '';
          }
          parser.reset(text, i + 1);
          i = me.parseExpression(parser, pos);
          ++pos;
          continue;
        }
      }
    }
    current += c;
    ++i;
    prev = c;
  }
  if (current) {
    buffer[pos] = current;
  }
  parser.release();
  me.single = buffer.length === 0 && slots.length === 1;
  return me;
}, parseExpression:function(parser, pos) {
  var i;
  this.slots[pos] = parser.compileExpression(this.tokens, this.tokensMap);
  i = parser.token.at + 1;
  parser.expect('}');
  return i;
}}});
Ext.define('Ext.app.bind.TemplateBinding', {extend:Ext.app.bind.BaseBinding, isTemplateBinding:true, lastValue:undefined, value:undefined, constructor:function(template, owner, callback, scope, options) {
  var me = this, tpl = new Ext.app.bind.Template(template), tokens = tpl.getTokens();
  me.callParent([owner, callback, scope, options]);
  me.tpl = tpl;
  me.tokens = tokens;
  tokens.$literal = true;
  if (!tpl.isStatic()) {
    me.multiBinding = new Ext.app.bind.Multi(tokens, owner, me.onBindData, me);
  } else {
    me.isStatic = true;
    me.onData(tpl.getText());
  }
}, destroy:function() {
  var me = this;
  Ext.destroy(me.multiBinding);
  me.tpl = me.multiBinding = null;
  me.callParent();
}, getFullName:function() {
  var multi = this.multiBinding;
  return this.fullName || (this.fullName = '$' + (multi ? multi.getFullName() : this.callParent()));
}, getRawValue:function() {
  return this.value;
}, getTemplateScope:function() {
  return null;
}, isAvailable:function() {
  var multi = this.multiBinding;
  return multi ? multi.isAvailable() : false;
}, isDescendantOf:function() {
  return false;
}, isLoading:function() {
  var multi = this.multiBinding;
  return multi ? multi.isLoading() : false;
}, onBindData:function(data) {
  this.onData(this.tpl.apply(data, this.getTemplateScope()));
}, onData:function(value) {
  var me = this, lastValue = me.value;
  if (lastValue !== (me.value = value)) {
    me.lastValue = lastValue;
    me.schedule();
  }
}, react:function() {
  this.notify(this.value);
}, refresh:function() {
  var multi = this.multiBinding;
  if (multi) {
    multi.refresh();
  }
}, privates:{sort:function() {
  var multi = this.multiBinding;
  if (multi) {
    this.scheduler.sortItem(multi);
  }
}}});
Ext.define('Ext.data.ChainedStore', {extend:Ext.data.AbstractStore, alias:'store.chained', mixins:[Ext.data.LocalStore], isChainedStore:true, config:{source:null, remoteFilter:false, remoteSort:false}, syncSourceGrouping:false, updateRemoteFilter:function(remoteFilter, oldRemoteFilter) {
  if (remoteFilter) {
    Ext.raise('Remote filtering cannot be used with chained stores.');
  }
  this.callParent([remoteFilter, oldRemoteFilter]);
}, updateRemoteSort:function(remoteSort, oldRemoteSort) {
  if (remoteSort) {
    Ext.raise('Remote sorting cannot be used with chained stores.');
  }
  this.callParent([remoteSort, oldRemoteSort]);
}, remove:function() {
  var source = this.getSource();
  if (!source) {
    Ext.raise('Cannot remove records with no source.');
  }
  return source.remove.apply(source, arguments);
}, removeAll:function() {
  var source = this.getSource();
  if (!source) {
    Ext.raise('Cannot remove records with no source.');
  }
  return source.removeAll();
}, getData:function() {
  var me = this, data = me.data;
  if (!data) {
    me.data = data = me.constructDataCollection();
  }
  return data;
}, getTotalCount:function() {
  return this.getCount();
}, getSession:function() {
  return this.getSourceValue('getSession', null);
}, applySource:function(source) {
  if (source) {
    var original = source, s;
    source = Ext.data.StoreManager.lookup(source);
    if (!source) {
      s = 'Invalid source {0}specified for Ext.data.ChainedStore';
      s = Ext.String.format(s, typeof original === 'string' ? '"' + original + '" ' : '');
      Ext.raise(s);
    }
  }
  return source;
}, updateSource:function(source, oldSource) {
  var me = this, data;
  if (oldSource && !oldSource.destroyed) {
    oldSource.removeObserver(me);
  }
  if (source) {
    data = me.getData();
    data.setSource(source.getData());
    if (me.syncSourceGrouping) {
      me.setGrouper(source.getGrouper());
    }
    if (!me.isInitializing) {
      me.fireEvent('refresh', me);
      me.fireEvent('datachanged', me);
    }
    source.addObserver(me);
  }
}, getModel:function() {
  return this.getSourceValue('getModel', null);
}, getProxy:function() {
  return null;
}, onCollectionAdd:function(collection, info) {
  var me = this, records = info.items, lastChunk = !info.next;
  if (me.ignoreCollectionAdd) {
    return;
  }
  if (me.activeRanges) {
    me.syncActiveRanges();
  }
  me.fireEvent('add', me, records, info.at);
  if (lastChunk) {
    me.fireEvent('datachanged', me);
  }
}, onCollectionItemChange:function(collection, info) {
  var me = this, record = info.item, modifiedFieldNames = info.modified || null, type = info.meta;
  if (me.activeRanges && info.newIndex !== info.oldIndex) {
    me.syncActiveRanges();
  }
  me.onUpdate(record, type, modifiedFieldNames, info);
  me.fireEvent('update', me, record, type, modifiedFieldNames, info);
  me.fireEvent('datachanged', me);
}, onCollectionUpdateKey:function(source, details) {
  this.fireEvent('idchanged', this, details.item, details.oldKey, details.newKey);
}, onUpdate:Ext.emptyFn, lastCollectionRefesh:null, onCollectionRefresh:function(collection) {
  var me = this, gen = collection.generation;
  if (!me.isConfiguring && me.lastCollectionRefesh !== gen) {
    me.lastCollectionRefesh = gen;
    me.fireEvent('datachanged', me);
    me.fireEvent('refresh', me);
  }
}, onCollectionRemove:function(collection, info) {
  var me = this, records = info.items, lastChunk = !info.next;
  if (me.ignoreCollectionRemove) {
    return;
  }
  me.fireEvent('remove', me, records, info.at, false);
  if (lastChunk) {
    me.fireEvent('datachanged', me);
  }
}, onSourceBeforeLoad:function(source, operation) {
  this.fireEvent('beforeload', this, operation);
  this.callObservers('BeforeLoad', [operation]);
}, onSourceAfterLoad:function(source, records, successful, operation) {
  this.fireEvent('load', this, records, successful, operation);
  this.callObservers('AfterLoad', [records, successful, operation]);
}, onFilterEndUpdate:function() {
  var me = this;
  if (me.getData().generation === me.lastCollectionRefesh && !me.getRemoteFilter()) {
    me.suppressNextFilter = true;
  }
  me.callParent(arguments);
  me.callObservers('Filter');
}, onSourceBeforePopulate:function() {
  this.ignoreCollectionAdd = true;
  this.callObservers('BeforePopulate');
}, onSourceAfterPopulate:function() {
  var me = this;
  me.ignoreCollectionAdd = false;
  me.fireEvent('datachanged', me);
  me.fireEvent('refresh', me);
  this.callObservers('AfterPopulate');
}, onSourceBeforeClear:function() {
  this.ignoreCollectionRemove = true;
  this.callObservers('BeforeClear');
}, onSourceAfterClear:function() {
  this.ignoreCollectionRemove = false;
  this.callObservers('AfterClear');
}, onSourceBeforeRemoveAll:function() {
  this.ignoreCollectionRemove = true;
  this.callObservers('BeforeRemoveAll');
}, onSourceAfterRemoveAll:function(source, silent) {
  var me = this;
  me.ignoreCollectionRemove = false;
  if (!silent) {
    me.fireEvent('clear', me);
    me.fireEvent('datachanged', me);
  }
  this.callObservers('AfterRemoveAll', [silent]);
}, onSourceFilter:function() {
  var me = this, gen = me.getData().generation;
  if (me.lastCollectionRefesh !== gen) {
    me.lastCollectionRefesh = gen;
    me.fireEvent('refresh', me);
    me.fireEvent('datachanged', me);
  }
}, onSourceGrouperChange:function(source, grouper) {
  if (this.syncSourceGrouping) {
    this.setGrouper(grouper);
  }
}, hasPendingLoad:function() {
  return this.getSourceValue('hasPendingLoad', false);
}, isLoaded:function() {
  return this.getSourceValue('isLoaded', false);
}, isLoading:function() {
  return this.getSourceValue('isLoading', false);
}, doDestroy:function() {
  var me = this;
  me.observers = null;
  me.setSource(null);
  me.getData().destroy(true);
  me.data = null;
  me.callParent();
}, privates:{getSourceValue:function(method, defaultValue) {
  var source = this.getSource(), val = defaultValue;
  if (source && !source.destroyed) {
    val = source[method]();
  }
  return val;
}, isMoving:function() {
  var source = this.getSource();
  return source.isMoving ? source.isMoving.apply(source, arguments) : false;
}, loadsSynchronously:function() {
  return this.getSource().loadsSynchronously();
}}});
Ext.define('Ext.app.ViewModel', {mixins:[Ext.mixin.Factoryable, Ext.mixin.Identifiable], alias:'viewmodel.default', isViewModel:true, factoryConfig:{name:'viewModel'}, collectTimeout:100, expressionRe:/^(?:\{(?:(\d+)|([a-z_][\w.]*))\})$/i, statics:{escape:function(value) {
  var ret = value, key;
  if (typeof value === 'string') {
    ret = '~~' + value;
  } else {
    if (value && value.constructor === Object) {
      ret = {};
      for (key in value) {
        ret[key] = this.escape(value[key]);
      }
    }
  }
  return ret;
}}, $configStrict:false, config:{data:true, formulas:{$value:null, merge:function(newValue, currentValue, target, mixinClass) {
  return this.mergeNew(newValue, currentValue, target, mixinClass);
}}, links:null, parent:null, root:true, scheduler:null, schema:'default', session:null, stores:null, view:null}, constructor:function(config) {
  this.bindings = {};
  this.initConfig(config);
}, destroy:function() {
  var me = this, scheduler = me._scheduler, stores = me.storeInfo, parent = me.getParent(), task = me.collectTask, children = me.children, bindings = me.bindings, key, store, autoDestroy, storeBinding;
  me.destroying = true;
  if (task) {
    task.cancel();
    me.collectTask = null;
  }
  if (children) {
    for (key in children) {
      children[key].destroy();
    }
  }
  if (stores) {
    for (key in stores) {
      store = stores[key];
      storeBinding = store.$binding;
      autoDestroy = store.autoDestroy;
      if (autoDestroy || !store.$wasInstance && autoDestroy !== false) {
        store.destroy();
      }
      Ext.destroy(storeBinding);
    }
  }
  if (parent) {
    parent.unregisterChild(me);
  }
  me.getRoot().destroy();
  for (key in bindings) {
    bindings[key].destroy();
  }
  if (scheduler && scheduler.$owner === me) {
    scheduler.$owner = null;
    scheduler.destroy();
  }
  me.children = me.storeInfo = me._session = me._view = me._scheduler = me.bindings = me._root = me._parent = me.formulaFn = me.$formulaData = null;
  me.callParent();
}, bind:function(descriptor, callback, scope, options) {
  var me = this, track = true, binding;
  scope = scope || me;
  if (!options && descriptor.bindTo !== undefined && !Ext.isString(descriptor)) {
    options = descriptor;
    descriptor = options.bindTo;
  }
  if (!Ext.isString(descriptor)) {
    binding = new Ext.app.bind.Multi(descriptor, me, callback, scope, options);
  } else {
    if (me.expressionRe.test(descriptor)) {
      descriptor = descriptor.substring(1, descriptor.length - 1);
      binding = me.bindExpression(descriptor, callback, scope, options);
      track = false;
    } else {
      binding = new Ext.app.bind.TemplateBinding(descriptor, me, callback, scope, options);
    }
  }
  if (track) {
    me.bindings[binding.id] = binding;
  }
  return binding;
}, getSession:function() {
  var me = this, session = me._session, parent;
  if (!session && (parent = me.getParent())) {
    me.setSession(session = parent.getSession());
  }
  return session || null;
}, getStore:function(key) {
  var storeInfo = this.storeInfo, store;
  if (storeInfo) {
    store = storeInfo[key];
  }
  return store || null;
}, linkTo:function(key, reference) {
  var me = this, stub, create, id, modelType, linkStub, rec;
  if (key.indexOf('.') > -1) {
    Ext.raise('Links can only be at the top-level: "' + key + '"');
  }
  if (reference.isModel) {
    reference = {type:reference.entityName, id:reference.id};
  }
  modelType = reference.type || reference.reference;
  create = reference.create;
  if (modelType) {
    id = reference.id;
    if (!reference.create && Ext.isEmpty(id)) {
      Ext.raise('No id specified. To create a phantom model, specify "create: true" ' + 'as part of the reference.');
    }
    if (create) {
      id = undefined;
    }
    rec = me.getRecord(modelType, id);
    if (Ext.isObject(create)) {
      rec.set(create);
      rec.commit();
      rec.phantom = true;
    }
    stub = me.getRoot().createStubChild(key);
    stub.set(rec);
  } else {
    stub = me.getStub(key);
    if (!stub.isLinkStub) {
      linkStub = new Ext.app.bind.LinkStub(me, stub.name);
      stub.graft(linkStub);
      stub = linkStub;
    }
    stub.link(reference);
  }
}, notify:function() {
  var scheduler = this.getScheduler();
  if (!scheduler.firing) {
    scheduler.notify();
  }
}, get:function(path) {
  return this.getStub(path).getValue();
}, set:function(path, value) {
  var me = this, obj, stub;
  me.getData();
  if (value === undefined && path && path.constructor === Object) {
    stub = me.getRoot();
    value = path;
  } else {
    if (path && path.indexOf('.') < 0) {
      obj = {};
      obj[path] = value;
      value = obj;
      stub = me.getRoot();
    } else {
      stub = me.getStub(path);
    }
  }
  stub.set(value);
}, privates:{registerChild:function(child) {
  var children = this.children;
  if (!children) {
    this.children = children = {};
  }
  children[child.getId()] = child;
}, unregisterChild:function(child) {
  var children = this.children;
  if (!this.destroying && children) {
    delete children[child.getId()];
  }
}, getRecord:function(type, id) {
  var session = this.getSession(), Model = type, hasId = id !== undefined, record;
  if (session) {
    if (hasId) {
      record = session.getRecord(type, id);
    } else {
      record = session.createRecord(type);
    }
  } else {
    if (!Model.$isClass) {
      Model = this.getSchema().getEntity(Model);
      if (!Model) {
        Ext.raise('Invalid model name: ' + type);
      }
    }
    if (hasId) {
      record = Model.createWithId(id);
      record.load();
    } else {
      record = new Model;
    }
  }
  return record;
}, bindExpression:function(descriptor, callback, scope, options) {
  var stub = this.getStub(descriptor);
  return stub.bind(callback, scope, options);
}, applyScheduler:function(scheduler) {
  if (scheduler && !scheduler.isInstance) {
    if (scheduler === true) {
      scheduler = {};
    }
    if (!('preSort' in scheduler)) {
      scheduler = Ext.apply({preSort:'kind,-depth'}, scheduler);
    }
    scheduler = new Ext.util.Scheduler(scheduler);
    scheduler.$owner = this;
  }
  return scheduler;
}, getScheduler:function() {
  var me = this, scheduler = me._scheduler, parent;
  if (!scheduler) {
    if (!(parent = me.getParent())) {
      scheduler = new Ext.util.Scheduler({preSort:'kind,-depth'});
      scheduler.$owner = me;
    } else {
      scheduler = parent.getScheduler();
    }
    me.setScheduler(scheduler);
  }
  return scheduler;
}, getStub:function(bindDescr) {
  var root = this.getRoot();
  return bindDescr ? root.getChild(bindDescr) : root;
}, collect:function() {
  var me = this, parent = me.getParent(), task = me.collectTask;
  if (parent) {
    parent.collect();
    return;
  }
  if (!task) {
    task = me.collectTask = new Ext.util.DelayedTask(me.doCollect, me);
  }
  if (me.collectTimeout === 0) {
    me.doCollect();
  } else {
    task.delay(me.collectTimeout);
  }
}, doCollect:function() {
  var children = this.children, key;
  if (children) {
    for (key in children) {
      children[key].doCollect();
    }
  }
  this.getRoot().collect();
}, invalidateChildLinks:function(name, clear) {
  var children = this.children, key;
  if (children) {
    for (key in children) {
      children[key].getRoot().invalidateChildLink(name, clear);
    }
  }
}, onBindDestroy:function(binding, fromChild) {
  var me = this, parent;
  if (me.destroying) {
    return;
  }
  if (!fromChild) {
    delete me.bindings[binding.id];
  }
  parent = me.getParent();
  if (parent) {
    parent.onBindDestroy(binding, true);
  } else {
    me.collect();
  }
}, applyData:function(newData, data) {
  var me = this, linkData, parent;
  me.getSession();
  if (!data) {
    parent = me.getParent();
    me.linkData = linkData = parent ? Ext.Object.chain(parent.getData()) : {};
    me.data = me._data = Ext.Object.chain(linkData);
  }
  if (newData && newData.constructor === Object) {
    me.getRoot().set(newData, true);
  }
}, applyParent:function(parent) {
  if (parent) {
    parent.registerChild(this);
  }
  return parent;
}, applyStores:function(stores) {
  var me = this, root = me.getRoot(), key, cfg, storeBind, stub, listeners;
  me.storeInfo = {};
  me.listenerScopeFn = function() {
    return me.getView().getInheritedConfig('defaultListenerScope');
  };
  for (key in stores) {
    cfg = stores[key];
    if (cfg.isStore) {
      cfg.$wasInstance = true;
      me.setupStore(cfg, key);
      continue;
    } else {
      if (Ext.isString(cfg)) {
        cfg = {source:cfg};
      } else {
        cfg = Ext.apply({}, cfg);
      }
    }
    listeners = cfg.listeners;
    delete cfg.listeners;
    storeBind = me.bind(cfg, me.onStoreBind, me, {trackStatics:true});
    if (storeBind.isStatic()) {
      storeBind.destroy();
      me.createStore(key, cfg, listeners);
    } else {
      storeBind.$storeKey = key;
      storeBind.$listeners = listeners;
      stub = root.createStubChild(key);
      stub.setStore(storeBind);
    }
  }
}, onStoreBind:function(cfg, oldValue, binding) {
  var info = this.storeInfo, key = binding.$storeKey, store = info[key], proxy;
  if (!store) {
    this.createStore(key, cfg, binding.$listeners, binding);
  } else {
    cfg = Ext.merge({}, binding.pruneStaticKeys());
    proxy = cfg.proxy;
    delete cfg.type;
    delete cfg.model;
    delete cfg.fields;
    delete cfg.proxy;
    delete cfg.listeners;
    if (proxy) {
      delete proxy.reader;
      delete proxy.writer;
      store.getProxy().setConfig(proxy);
    }
    store.setConfig(cfg);
  }
}, createStore:function(key, cfg, listeners, binding) {
  var session = this.getSession(), store;
  cfg = Ext.apply({}, cfg);
  if (cfg.session) {
    cfg.session = session;
  }
  if (cfg.source) {
    cfg.type = cfg.type || 'chained';
  }
  cfg.listeners = listeners;
  cfg.resolveListenerScope = this.listenerScopeFn;
  store = Ext.Factory.store(cfg);
  store.$binding = binding;
  this.setupStore(store, key);
}, setupStore:function(store, key) {
  var me = this, obj = {};
  me.getData();
  store.resolveListenerScope = me.listenerScopeFn;
  me.storeInfo[key] = store;
  obj[key] = store;
  me.setData(obj);
}, applyFormulas:function(formulas) {
  var me = this, root = me.getRoot(), name, stub;
  me.getData();
  for (name in formulas) {
    if (name.indexOf('.') >= 0) {
      Ext.raise('Formula names cannot contain dots: ' + name);
    }
    root.createStubChild(name);
    stub = me.getStub(name);
    stub.setFormula(formulas[name]);
  }
  return formulas;
}, applyLinks:function(links) {
  var link;
  for (link in links) {
    this.linkTo(link, links[link]);
  }
  return links;
}, applySchema:function(schema) {
  return Ext.data.schema.Schema.get(schema);
}, applyRoot:function() {
  var root = new Ext.app.bind.RootStub(this), parent = this.getParent();
  if (parent) {
    root.depth = parent.getRoot().depth - 1000;
  }
  return root;
}, getFormulaFn:function(data) {
  var me = this, fn = me.formulaFn;
  if (!fn) {
    fn = me.formulaFn = function(name) {
      return me.$formulaData[name];
    };
  }
  me.$formulaData = data;
  return fn;
}}});
Ext.define('Ext.app.domain.Controller', {extend:Ext.app.EventDomain, singleton:true, type:'controller', prefix:'controller.', idMatchRe:/^#/, constructor:function() {
  var me = this;
  me.callParent();
  me.monitor(Ext.app.BaseController);
}, match:function(target, selector) {
  var result = false, alias = target.alias;
  if (selector === '*') {
    result = true;
  } else {
    if (selector === '#') {
      result = !!target.isApplication;
    } else {
      if (this.idMatchRe.test(selector)) {
        result = target.getId() === selector.substring(1);
      } else {
        if (alias) {
          result = Ext.Array.indexOf(alias, this.prefix + selector) > -1;
        }
      }
    }
  }
  return result;
}});
Ext.define('Ext.direct.Manager', {singleton:true, mixins:[Ext.mixin.Observable], exceptions:{TRANSPORT:'xhr', PARSE:'parse', DATA:'data', LOGIN:'login', SERVER:'exception'}, providerClasses:{}, remotingMethods:{}, config:{varName:'Ext.REMOTING_API'}, apiNotFoundError:'Ext Direct API was not found at {0}', constructor:function() {
  var me = this;
  me.mixins.observable.constructor.call(me);
  me.transactions = new Ext.util.MixedCollection;
  me.providers = new Ext.util.MixedCollection;
}, addProvider:function(provider) {
  var me = this, args = arguments, relayers = me.relayers || (me.relayers = {}), i, len;
  if (args.length > 1) {
    for (i = 0, len = args.length; i < len; ++i) {
      me.addProvider(args[i]);
    }
    return;
  }
  if (!provider.isProvider) {
    provider = Ext.create('direct.' + provider.type + 'provider', provider);
  }
  me.providers.add(provider);
  provider.on('data', me.onProviderData, me);
  if (provider.relayedEvents) {
    relayers[provider.id] = me.relayEvents(provider, provider.relayedEvents);
  }
  if (!provider.isConnected()) {
    provider.connect();
  }
  return provider;
}, loadProvider:function(config, callback, scope) {
  var me = this, classes = me.providerClasses, type, url, varName, provider, i, len;
  if (Ext.isArray(config)) {
    for (i = 0, len = config.length; i < len; i++) {
      me.loadProvider(config[i], callback, scope);
    }
    return;
  }
  type = config.type;
  url = config.url;
  if (classes[type] && classes[type].checkConfig(config)) {
    provider = me.addProvider(config);
    me.fireEventArgs('providerload', [url, provider]);
    Ext.callback(callback, scope, [url, provider]);
    return;
  }
  varName = config.varName || me.getVarName();
  delete config.varName;
  if (!url) {
    Ext.raise('Need API discovery URL to load a Remoting provider!');
  }
  delete config.url;
  Ext.Loader.loadScript({url:url, scope:me, onLoad:function() {
    this.onApiLoadSuccess({url:url, varName:varName, config:config, callback:callback, scope:scope});
  }, onError:function() {
    this.onApiLoadFailure({url:url, callback:callback, scope:scope});
  }});
}, getProvider:function(id) {
  return id.isProvider ? id : this.providers.get(id);
}, removeProvider:function(provider) {
  var me = this, providers = me.providers, relayers = me.relayers, id;
  provider = provider.isProvider ? provider : providers.get(provider);
  if (provider) {
    provider.un('data', me.onProviderData, me);
    id = provider.id;
    if (relayers[id]) {
      relayers[id].destroy();
      delete relayers[id];
    }
    providers.remove(provider);
    return provider;
  }
  return null;
}, addTransaction:function(transaction) {
  this.transactions.add(transaction);
  return transaction;
}, removeTransaction:function(transaction) {
  var me = this;
  transaction = me.getTransaction(transaction);
  me.transactions.remove(transaction);
  return transaction;
}, getTransaction:function(transaction) {
  return typeof transaction === 'object' ? transaction : this.transactions.get(transaction);
}, onProviderData:function(provider, event) {
  var me = this, i, len;
  if (Ext.isArray(event)) {
    for (i = 0, len = event.length; i < len; ++i) {
      me.onProviderData(provider, event[i]);
    }
    return;
  }
  if (event.name && event.name !== 'event' && event.name !== 'exception') {
    me.fireEvent(event.name, event);
  } else {
    if (event.status === false) {
      me.fireEvent('exception', event);
    }
  }
  me.fireEvent('event', event, provider);
}, parseMethod:function(fn) {
  var current = Ext.global, i = 0, resolved, parts, len;
  if (Ext.isFunction(fn)) {
    resolved = fn;
  } else {
    if (Ext.isString(fn)) {
      resolved = this.remotingMethods[fn];
      if (!resolved) {
        parts = fn.split('.');
        len = parts.length;
        while (current && i < len) {
          current = current[parts[i]];
          ++i;
        }
        resolved = Ext.isFunction(current) ? current : null;
      }
    }
  }
  return resolved || null;
}, resolveApi:function(api, caller) {
  var prefix, action, method, fullName, fn;
  prefix = api && api.prefix;
  if (prefix && prefix.substr(prefix.length - 1) !== '.') {
    prefix += '.';
  }
  for (action in api) {
    method = api[action];
    if (action !== 'prefix' && typeof method !== 'function') {
      fullName = (prefix || '') + method;
      fn = this.parseMethod(fullName);
      if (typeof fn === 'function') {
        api[action] = fn;
      } else {
        Ext.raise("Cannot resolve Direct API method '" + fullName + "' for " + action + ' action in ' + caller.$className + ' instance with id: ' + (caller.id != null ? caller.id : 'unknown'));
      }
    }
  }
  return api;
}, privates:{addProviderClass:function(type, cls) {
  this.providerClasses[type] = cls;
}, onApiLoadSuccess:function(options) {
  var me = this, url = options.url, varName = options.varName, api, provider, error;
  try {
    api = Ext.apply(options.config, eval(varName));
    provider = me.addProvider(api);
  } catch (e$57) {
    error = e$57 + '';
  }
  if (error) {
    me.fireEventArgs('providerloaderror', [url, error]);
    Ext.callback(options.callback, options.scope, [url, error]);
  } else {
    me.fireEventArgs('providerload', [url, provider]);
    Ext.callback(options.callback, options.scope, [url, provider]);
  }
}, onApiLoadFailure:function(options) {
  var url = options.url, error;
  error = Ext.String.format(this.apiNotFoundError, url);
  this.fireEventArgs('providerloaderror', [url, error]);
  Ext.callback(options.callback, options.scope, [url, error]);
}, registerMethod:function(name, method) {
  this.remotingMethods[name] = method;
}, clearAllMethods:function() {
  this.remotingMethods = {};
}}}, function() {
  Ext.Direct = Ext.direct.Manager;
});
Ext.define('Ext.data.JsonP', {singleton:true, requestCount:0, requests:{}, timeout:30000, disableCaching:true, disableCachingParam:'_dc', callbackKey:'callback', request:function(options) {
  options = Ext.apply({}, options);
  if (!options.url) {
    Ext.raise('A url must be specified for a JSONP request.');
  }
  var me = this, disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching, cacheParam = options.disableCachingParam || me.disableCachingParam, id = ++me.requestCount, callbackName = options.callbackName || 'callback' + id, callbackKey = options.callbackKey || me.callbackKey, timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout, params = Ext.apply({}, options.params), url = options.url, name = Ext.name, request, script;
  if (disableCaching && !params[cacheParam]) {
    params[cacheParam] = Ext.Date.now();
  }
  options.params = params;
  params[callbackKey] = name + '.data.JsonP.' + callbackName;
  script = me.createScript(url, params, options);
  me.requests[id] = request = {url:url, params:params, script:script, id:id, scope:options.scope, success:options.success, failure:options.failure, callback:options.callback, callbackKey:callbackKey, callbackName:callbackName};
  if (timeout > 0) {
    request.timeout = Ext.defer(me.handleTimeout, timeout, me, [request]);
  }
  me.setupErrorHandling(request);
  me[callbackName] = me.bindResponse(request);
  me.loadScript(request);
  return request;
}, bindResponse:function(request) {
  var me = this;
  return function(result) {
    Ext.elevate(function() {
      me.handleResponse(result, request);
    });
  };
}, abort:function(request) {
  var me = this, requests = me.requests, key;
  if (request) {
    if (!request.id) {
      request = requests[request];
    }
    me.handleAbort(request);
  } else {
    for (key in requests) {
      if (requests.hasOwnProperty(key)) {
        me.abort(requests[key]);
      }
    }
  }
}, setupErrorHandling:function(request) {
  request.script.onerror = Ext.bind(this.handleError, this, [request]);
}, handleAbort:function(request) {
  request.errorType = 'abort';
  this.handleResponse(null, request);
}, handleError:function(request) {
  request.errorType = 'error';
  this.handleResponse(null, request);
}, cleanupErrorHandling:function(request) {
  request.script.onerror = null;
}, handleTimeout:function(request) {
  request.errorType = 'timeout';
  this.handleResponse(null, request);
}, handleResponse:function(result, request) {
  var success = true;
  Ext.undefer(request.timeout);
  delete this[request.callbackName];
  delete this.requests[request.id];
  this.cleanupErrorHandling(request);
  Ext.fly(request.script).destroy();
  if (request.errorType) {
    success = false;
    Ext.callback(request.failure, request.scope, [request.errorType]);
  } else {
    Ext.callback(request.success, request.scope, [result]);
  }
  Ext.callback(request.callback, request.scope, [success, result, request.errorType]);
}, createScript:function(url, params, options) {
  var script = document.createElement('script');
  script.setAttribute('src', Ext.urlAppend(url, Ext.Object.toQueryString(params)));
  script.setAttribute('async', true);
  script.setAttribute('type', 'text/javascript');
  return script;
}, loadScript:function(request) {
  Ext.getHead().appendChild(request.script);
}});
Ext.define('Ext.data.NodeInterface', {statics:{decorate:function(modelClass) {
  var model = Ext.data.schema.Schema.lookupEntity(modelClass), proto = model.prototype, idName, idField, idType;
  if (!model.prototype.isObservable) {
    model.mixin(Ext.mixin.Observable.prototype.mixinId, Ext.mixin.Observable);
  }
  if (proto.isNode) {
    return;
  }
  idName = proto.idProperty;
  idField = model.getField(idName);
  idType = idField.type;
  model.override(this.getPrototypeBody());
  model.addFields([{name:'parentId', type:idType, defaultValue:null, allowNull:idField.allowNull}, {name:'index', type:'int', defaultValue:-1, persist:false, convert:null}, {name:'depth', type:'int', defaultValue:0, persist:false, convert:null}, {name:'expanded', type:'bool', defaultValue:false, persist:false, convert:null}, {name:'expandable', type:'bool', defaultValue:true, persist:false, convert:null}, {name:'checked', type:'auto', defaultValue:null, persist:false, convert:null}, {name:'leaf', 
  type:'bool', defaultValue:false}, {name:'cls', type:'string', defaultValue:'', persist:false, convert:null}, {name:'iconCls', type:'string', defaultValue:'', persist:false, convert:null}, {name:'icon', type:'string', defaultValue:'', persist:false, convert:null}, {name:'glyph', type:'string', defaultValue:'', persist:false, convert:null}, {name:'root', type:'boolean', defaultValue:false, persist:false, convert:null}, {name:'isLast', type:'boolean', defaultValue:false, persist:false, convert:null}, 
  {name:'isFirst', type:'boolean', defaultValue:false, persist:false, convert:null}, {name:'allowDrop', type:'boolean', defaultValue:true, persist:false, convert:null}, {name:'allowDrag', type:'boolean', defaultValue:true, persist:false, convert:null}, {name:'loaded', type:'boolean', defaultValue:false, persist:false, convert:null}, {name:'loading', type:'boolean', defaultValue:false, persist:false, convert:null}, {name:'href', type:'string', defaultValue:'', persist:false, convert:null}, {name:'hrefTarget', 
  type:'string', defaultValue:'', persist:false, convert:null}, {name:'qtip', type:'string', defaultValue:'', persist:false, convert:null}, {name:'qtitle', type:'string', defaultValue:'', persist:false, convert:null}, {name:'qshowDelay', type:'int', defaultValue:0, persist:false, convert:null}, {name:'children', type:'auto', defaultValue:null, persist:false, convert:null}, {name:'visible', type:'boolean', defaultValue:true, persist:false}, {name:'text', type:'string', persist:false}]);
}, getPrototypeBody:function() {
  var bubbledEvents = {idchanged:true, append:true, remove:true, move:true, insert:true, beforeappend:true, beforeremove:true, beforemove:true, beforeinsert:true, expand:true, collapse:true, beforeexpand:true, beforecollapse:true, sort:true}, silently = {silent:true};
  return {isNode:true, firstChild:null, lastChild:null, parentNode:null, previousSibling:null, nextSibling:null, constructor:function() {
    var me = this;
    me.mixins.observable.constructor.call(me);
    me.callParent(arguments);
    me.childNodes = [];
    return me;
  }, createNode:function(node) {
    var me = this, childType = me.childType, store, storeReader, nodeProxy, nodeReader, reader, typeProperty, T = me.self;
    if (!node.isModel) {
      if (childType) {
        T = me.schema.getEntity(childType);
      } else {
        store = me.getTreeStore();
        storeReader = store && store.getProxy().getReader();
        nodeProxy = me.getProxy();
        nodeReader = nodeProxy ? nodeProxy.getReader() : null;
        reader = !storeReader || nodeReader && nodeReader.initialConfig.typeProperty ? nodeReader : storeReader;
        if (reader) {
          typeProperty = reader.getTypeProperty();
          if (typeProperty) {
            T = reader.getChildType(me.schema, node, typeProperty);
          }
        }
      }
      node = new T(node);
    }
    if (!node.childNodes) {
      node.firstChild = node.lastChild = node.parentNode = node.previousSibling = node.nextSibling = null;
      node.childNodes = [];
    }
    return node;
  }, isLeaf:function() {
    return this.get('leaf') === true;
  }, setFirstChild:function(node) {
    this.firstChild = node;
  }, setLastChild:function(node) {
    this.lastChild = node;
  }, updateInfo:function(commit, info) {
    var me = this, phantom = me.phantom, result, childInfo, children, childCount, i;
    commit = {silent:true, commit:commit};
    if (info.depth != null && info.depth !== me.data.depth) {
      childInfo = {depth:info.depth + 1};
      children = me.childNodes;
      childCount = children.length;
      for (i = 0; i < childCount; i++) {
        children[i].updateInfo(commit, childInfo);
      }
    }
    result = me.set(info, commit);
    me.phantom = phantom;
    return result;
  }, isLast:function() {
    return this.get('isLast');
  }, isFirst:function() {
    return this.get('isFirst');
  }, hasChildNodes:function() {
    return !this.isLeaf() && this.childNodes.length > 0;
  }, isExpandable:function() {
    var me = this;
    if (me.get('expandable')) {
      return !(me.isLeaf() || me.isLoaded() && !me.phantom && !me.hasChildNodes());
    }
    return false;
  }, triggerUIUpdate:function() {
    this.callJoined('afterEdit', []);
  }, appendChild:function(node, suppressEvents, commit) {
    var me = this, treeStore = me.getTreeStore(), bulkUpdate = treeStore && treeStore.bulkUpdate, childInfo = {isLast:true, parentId:me.getId(), depth:(me.data.depth || 0) + 1}, oldParent, previousSibling, modifiedFields, index, result, i, ln;
    Ext.suspendLayouts();
    if (Ext.isArray(node)) {
      ln = node.length;
      result = new Array(ln);
      me.callTreeStore('beginFill');
      for (i = 0; i < ln; i++) {
        result[i] = me.appendChild(node[i], suppressEvents, commit);
      }
      me.callTreeStore('endFill', [result]);
    } else {
      node = me.createNode(node);
      if (suppressEvents !== true && me.fireBubbledEvent('beforeappend', [me, node]) === false) {
        Ext.resumeLayouts(true);
        return false;
      }
      index = me.childNodes.length;
      oldParent = node.parentNode;
      if (oldParent) {
        if (suppressEvents !== true && node.fireBubbledEvent('beforemove', [node, oldParent, me, index]) === false) {
          Ext.resumeLayouts(true);
          return false;
        }
        if (oldParent.removeChild(node, false, suppressEvents, oldParent.getTreeStore() === treeStore) === false) {
          Ext.resumeLayouts(true);
          return false;
        }
      }
      if (treeStore) {
        treeStore.beginUpdate();
      }
      index = me.childNodes.length;
      if (index === 0) {
        me.setFirstChild(node);
      }
      me.childNodes[index] = node;
      node.parentNode = me;
      node.nextSibling = null;
      me.setLastChild(node);
      previousSibling = me.childNodes[index - 1];
      if (previousSibling) {
        node.previousSibling = previousSibling;
        previousSibling.nextSibling = node;
        previousSibling.updateInfo(commit, {isLast:false});
        if (!bulkUpdate) {
          previousSibling.triggerUIUpdate();
        }
      } else {
        node.previousSibling = null;
      }
      childInfo.isFirst = index === 0;
      childInfo.index = index;
      modifiedFields = node.updateInfo(commit, childInfo);
      if (me.isLeaf()) {
        me.set('leaf', false);
      }
      if (!me.isLoaded()) {
        if (bulkUpdate) {
          me.data.loaded = true;
        } else {
          me.set('loaded', true);
        }
      } else {
        if (me.childNodes.length === 1 && !bulkUpdate) {
          me.triggerUIUpdate();
        }
      }
      if (index && me.childNodes[index - 1].isExpanded() && !bulkUpdate) {
        me.childNodes[index - 1].cascade(me.triggerUIUpdate);
      }
      if (treeStore) {
        treeStore.registerNode(me, !bulkUpdate);
        if (bulkUpdate) {
          treeStore.registerNode(node);
        }
      }
      if (suppressEvents !== true) {
        me.fireBubbledEvent('append', [me, node, index]);
        if (oldParent) {
          node.fireBubbledEvent('move', [node, oldParent, me, index]);
        }
      }
      me.callTreeStore('onNodeAppend', [node, index]);
      if (modifiedFields) {
        node.callJoined('afterEdit', [modifiedFields]);
      }
      result = node;
      if (treeStore) {
        treeStore.endUpdate();
      }
    }
    Ext.resumeLayouts(true);
    return result;
  }, getOwnerTree:function() {
    var store = this.getTreeStore();
    return store && store.ownerTree;
  }, getTreeStore:function() {
    var root = this;
    while (root && !root.treeStore) {
      root = root.parentNode;
    }
    return root && root.treeStore;
  }, removeChild:function(node, erase, suppressEvents, isMove) {
    var me = this, index = me.indexOf(node), i, childCount, previousSibling, treeStore = me.getTreeStore(), bulkUpdate = treeStore && treeStore.bulkUpdate, removeContext, removeRange = [];
    if (index === -1 || suppressEvents !== true && me.fireBubbledEvent('beforeremove', [me, node, !!isMove]) === false) {
      return false;
    }
    Ext.suspendLayouts();
    if (treeStore) {
      treeStore.beginUpdate();
    }
    Ext.Array.erase(me.childNodes, index, 1);
    if (me.firstChild === node) {
      me.setFirstChild(node.nextSibling);
    }
    if (me.lastChild === node) {
      me.setLastChild(node.previousSibling);
    }
    previousSibling = node.previousSibling;
    if (previousSibling) {
      node.previousSibling.nextSibling = node.nextSibling;
    }
    if (node.nextSibling) {
      node.nextSibling.previousSibling = node.previousSibling;
      if (index === 0) {
        node.nextSibling.updateInfo(false, {isFirst:true});
      }
      for (i = index, childCount = me.childNodes.length; i < childCount; i++) {
        me.childNodes[i].updateInfo(false, {index:i});
      }
    } else {
      if (previousSibling) {
        previousSibling.updateInfo(false, {isLast:true});
        if (!bulkUpdate) {
          if (previousSibling.isExpanded()) {
            previousSibling.cascade(me.triggerUIUpdate);
          } else {
            previousSibling.triggerUIUpdate();
          }
        }
      }
    }
    if (!me.childNodes.length && !bulkUpdate) {
      me.triggerUIUpdate();
    }
    Ext.resumeLayouts(true);
    if (suppressEvents !== true) {
      removeContext = {parentNode:node.parentNode, previousSibling:node.previousSibling, nextSibling:node.nextSibling};
      me.callTreeStore('beforeNodeRemove', [[node], !!isMove, removeRange]);
      node.previousSibling = node.nextSibling = node.parentNode = null;
      me.fireBubbledEvent('remove', [me, node, !!isMove, removeContext]);
      me.callTreeStore('onNodeRemove', [[node], !!isMove, removeRange]);
    }
    if (erase) {
      node.erase(true);
    } else {
      node.clear();
    }
    if (!isMove) {
      node.set({parentId:null, lastParentId:me.getId()}, silently);
    }
    if (treeStore) {
      treeStore.endUpdate();
    }
    return node;
  }, copy:function(newId, session, deep) {
    var me = this, result, args = [newId], len = me.childNodes ? me.childNodes.length : 0, i;
    if (session && session.isSession) {
      args.push(session);
    } else {
      if (arguments.length < 3) {
        deep = session;
      }
    }
    result = me.callParent(args);
    if (deep) {
      for (i = 0; i < len; i++) {
        result.appendChild(me.childNodes[i].copy(undefined, true));
      }
    }
    return result;
  }, clear:function(erase, resetChildren) {
    var me = this;
    me.parentNode = me.previousSibling = me.nextSibling = null;
    if (erase) {
      me.firstChild = me.lastChild = me.childNodes = null;
    }
    if (resetChildren) {
      me.firstChild = me.lastChild = null;
      me.childNodes.length = 0;
      if (me.data) {
        me.data.children = null;
      }
    }
  }, drop:function() {
    var me = this, childNodes = me.childNodes, parentNode = me.parentNode, treeStore = me.getTreeStore(), node, i, len;
    me.callParent();
    if (parentNode) {
      parentNode.removeChild(me);
    } else {
      if (me.get('root')) {
        treeStore.setRoot(null);
      }
    }
    if (treeStore) {
      treeStore.beginUpdate();
    }
    for (i = 0, len = childNodes ? childNodes.length : 0; i < len; i++) {
      node = childNodes[i];
      node.clear();
      node.drop();
    }
    if (treeStore) {
      treeStore.endUpdate();
    }
  }, erase:function(options) {
    var me = this, childNodes = me.childNodes, len = childNodes && childNodes.length, i, node;
    me.remove();
    me.clear(true);
    me.callParent([options]);
    for (i = 0; i < len; i++) {
      node = childNodes[i];
      node.parentNode = null;
      node.erase(options);
    }
  }, insertBefore:function(node, refNode, suppressEvents) {
    var me = this, index = me.indexOf(refNode), oldParent = node.parentNode, refIndex = index, childCount, previousSibling, i, treeStore = me.getTreeStore(), bulkUpdate = treeStore && treeStore.bulkUpdate, modifiedFields, sibling, siblingModifiedFields;
    if (!refNode) {
      return me.appendChild(node);
    }
    if (node === refNode) {
      return false;
    }
    node = me.createNode(node);
    if (suppressEvents !== true && me.fireBubbledEvent('beforeinsert', [me, node, refNode]) === false) {
      return false;
    }
    if (oldParent === me && me.indexOf(node) < index) {
      refIndex--;
    }
    if (oldParent) {
      if (suppressEvents !== true && node.fireBubbledEvent('beforemove', [node, oldParent, me, index, refNode]) === false) {
        return false;
      }
      if (oldParent.removeChild(node, false, suppressEvents, oldParent.getTreeStore() === treeStore) === false) {
        return false;
      }
    }
    if (treeStore) {
      treeStore.beginUpdate();
    }
    if (refIndex === 0) {
      me.setFirstChild(node);
    }
    Ext.Array.splice(me.childNodes, refIndex, 0, node);
    node.parentNode = me;
    node.nextSibling = refNode;
    refNode.previousSibling = node;
    previousSibling = me.childNodes[refIndex - 1];
    if (previousSibling) {
      node.previousSibling = previousSibling;
      previousSibling.nextSibling = node;
    } else {
      node.previousSibling = null;
    }
    modifiedFields = node.updateInfo(false, {parentId:me.getId(), index:refIndex, isFirst:refIndex === 0, isLast:false, depth:(me.data.depth || 0) + 1});
    for (i = refIndex + 1, childCount = me.childNodes.length; i < childCount; i++) {
      sibling = me.childNodes[i];
      siblingModifiedFields = sibling.updateInfo(false, {index:i});
      if (siblingModifiedFields) {
        sibling.callJoined('afterEdit', [siblingModifiedFields]);
      }
    }
    if (!me.isLoaded()) {
      if (bulkUpdate) {
        me.data.loaded = true;
      } else {
        me.set('loaded', true);
      }
    } else {
      if (me.childNodes.length === 1 && !bulkUpdate) {
        me.triggerUIUpdate();
      }
    }
    if (treeStore) {
      treeStore.registerNode(me, !bulkUpdate);
    }
    if (suppressEvents !== true) {
      me.fireBubbledEvent('insert', [me, node, refNode]);
      if (oldParent) {
        node.fireBubbledEvent('move', [node, oldParent, me, refIndex, refNode]);
      }
    }
    me.callTreeStore('onNodeInsert', [node, refIndex]);
    if (modifiedFields) {
      node.callJoined('afterEdit', [modifiedFields]);
    }
    if (treeStore) {
      treeStore.endUpdate();
    }
    return node;
  }, insertChild:function(index, node) {
    var sibling = this.childNodes[index];
    if (sibling) {
      return this.insertBefore(node, sibling);
    } else {
      return this.appendChild(node);
    }
  }, isLastVisible:function() {
    var me = this, result = me.data.isLast, next = me.nextSibling;
    if (!result && me.getTreeStore().isFiltered()) {
      while (next) {
        if (next.data.visible) {
          return false;
        }
        next = next.nextSibling;
      }
      return true;
    }
    return result;
  }, remove:function(erase, suppressEvents) {
    var me = this, parentNode = me.parentNode;
    if (parentNode) {
      parentNode.removeChild(me, erase, suppressEvents);
    } else {
      if (erase) {
        me.erase(true);
      }
    }
    return me;
  }, removeAll:function(erase, suppressEvents, fromParent) {
    var me = this, childNodes = me.childNodes, len = childNodes.length, node, treeStore, i, removeRange = [];
    if (!len) {
      return me;
    }
    if (!fromParent) {
      treeStore = me.getTreeStore();
      if (treeStore) {
        treeStore.beginUpdate();
        treeStore.suspendEvent('remove');
        me.callTreeStore('beforeNodeRemove', [childNodes, false, removeRange]);
      }
    }
    for (i = 0; i < len; ++i) {
      node = childNodes[i];
      node.previousSibling = node.nextSibling = node.parentNode = null;
      me.fireBubbledEvent('remove', [me, node, false]);
      if (erase) {
        node.erase(true);
      } else {
        node.removeAll(false, suppressEvents, true);
      }
    }
    if (!fromParent && treeStore) {
      treeStore.resumeEvent('remove');
      me.callTreeStore('onNodeRemove', [childNodes, false, removeRange]);
      treeStore.endUpdate();
    }
    me.firstChild = me.lastChild = null;
    childNodes.length = 0;
    if (!fromParent) {
      me.triggerUIUpdate();
    }
    return me;
  }, getChildAt:function(index) {
    return this.childNodes[index];
  }, replaceChild:function(newChild, oldChild, suppressEvents) {
    var s = oldChild ? oldChild.nextSibling : null;
    this.removeChild(oldChild, false, suppressEvents);
    this.insertBefore(newChild, s, suppressEvents);
    return oldChild;
  }, indexOf:function(child) {
    return Ext.Array.indexOf(this.childNodes, child);
  }, indexOfId:function(id) {
    var childNodes = this.childNodes, len = childNodes.length, i = 0;
    for (; i < len; ++i) {
      if (childNodes[i].getId() === id) {
        return i;
      }
    }
    return -1;
  }, getPath:function(field, separator) {
    field = field || this.idProperty;
    separator = separator || '/';
    var path = [this.get(field)], parent = this.parentNode;
    while (parent) {
      path.unshift(parent.get(field));
      parent = parent.parentNode;
    }
    return separator + path.join(separator);
  }, getDepth:function() {
    return this.get('depth');
  }, bubble:function(fn, scope, args) {
    var p = this;
    while (p) {
      if (fn.apply(scope || p, args || [p]) === false) {
        break;
      }
      p = p.parentNode;
    }
  }, cascade:function(spec, scope, args, after) {
    var me = this, before = spec, childNodes, length, i;
    if (arguments.length === 1 && !Ext.isFunction(spec)) {
      after = spec.after;
      scope = spec.scope;
      args = spec.args;
      before = spec.before;
    }
    if (!before || before.apply(scope || me, args || [me]) !== false) {
      childNodes = me.childNodes;
      for (i = 0, length = childNodes.length; i < length; i++) {
        childNodes[i].cascade.call(childNodes[i], before, scope, args, after);
      }
      if (after) {
        after.apply(scope || me, args || [me]);
      }
    }
  }, cascadeBy:function() {
    return this.cascade.apply(this, arguments);
  }, eachChild:function(fn, scope, args) {
    var childNodes = this.childNodes, length = childNodes.length, i;
    for (i = 0; i < length; i++) {
      if (fn.apply(scope || this, args || [childNodes[i]]) === false) {
        break;
      }
    }
  }, findChild:function(attribute, value, deep) {
    return this.findChildBy(function() {
      return this.get(attribute) == value;
    }, null, deep);
  }, findChildBy:function(fn, scope, deep) {
    var cs = this.childNodes, i, len, n, res;
    for (i = 0, len = cs.length; i < len; i++) {
      n = cs[i];
      if (fn.call(scope || n, n) === true) {
        return n;
      } else {
        if (deep) {
          res = n.findChildBy(fn, scope, deep);
          if (res !== null) {
            return res;
          }
        }
      }
    }
    return null;
  }, contains:function(node) {
    return node.isAncestor(this);
  }, isAncestor:function(node) {
    var p = this.parentNode;
    while (p) {
      if (p === node) {
        return true;
      }
      p = p.parentNode;
    }
    return false;
  }, sort:function(sortFn, recursive, suppressEvent) {
    var me = this, childNodes = me.childNodes, ln = childNodes.length, info = {isFirst:true}, i, n;
    if (ln > 0) {
      if (!sortFn) {
        sortFn = me.getTreeStore().getSortFn();
      }
      Ext.Array.sort(childNodes, sortFn);
      me.setFirstChild(childNodes[0]);
      me.setLastChild(childNodes[ln - 1]);
      for (i = 0; i < ln; i++) {
        n = childNodes[i];
        n.previousSibling = childNodes[i - 1];
        n.nextSibling = childNodes[i + 1];
        info.isLast = i === ln - 1;
        info.index = i;
        n.updateInfo(false, info);
        info.isFirst = false;
        if (recursive && !n.isLeaf()) {
          n.sort(sortFn, true, true);
        }
      }
      if (suppressEvent !== true) {
        me.fireBubbledEvent('sort', [me, childNodes]);
        me.callTreeStore('onNodeSort', [childNodes]);
      }
    }
  }, isExpanded:function() {
    return this.get('expanded');
  }, isLoaded:function() {
    return this.get('loaded');
  }, isBranchLoaded:function() {
    var isBranchLoaded = !this.isLeaf() && this.isLoaded();
    if (isBranchLoaded) {
      this.cascade(function(node) {
        if (!node.isLeaf()) {
          isBranchLoaded = isBranchLoaded || node.isBranchLoaded();
        }
        return isBranchLoaded;
      });
    }
    return isBranchLoaded;
  }, isLoading:function() {
    return this.get('loading');
  }, isRoot:function() {
    return !this.parentNode;
  }, isVisible:function() {
    var parent = this.parentNode;
    while (parent) {
      if (!parent.isExpanded()) {
        return false;
      }
      parent = parent.parentNode;
    }
    return true;
  }, expand:function(recursive, callback, scope) {
    var me = this, treeStore, resumeAddEvent;
    if (!me.isLeaf()) {
      if (me.isLoading()) {
        me.on('expand', function() {
          me.expand(recursive, callback, scope);
        }, me, {single:true});
      } else {
        if (!me.isExpanded()) {
          if (me.fireBubbledEvent('beforeexpand', [me]) !== false) {
            if (recursive) {
              if (me.parentNode && me.parentNode.isSynchronousRecursiveExpand) {
                me.isSynchronousRecursiveExpand = true;
              } else {
                treeStore = me.getTreeStore();
                if (treeStore.getProxy().isSynchronous || me.isBranchLoaded()) {
                  me.isSynchronousRecursiveExpand = true;
                  treeStore.suspendEvent('add', 'datachanged');
                  resumeAddEvent = true;
                }
              }
            }
            me.callTreeStore('onBeforeNodeExpand', [me.onChildNodesAvailable, me, [recursive, callback, scope]]);
            if (resumeAddEvent) {
              treeStore.resumeEvent('add', 'datachanged');
              treeStore.fireEvent('datachanged', treeStore);
              treeStore.fireEvent('refresh', treeStore);
            }
            me.isSynchronousRecursiveExpand = false;
          }
        } else {
          if (recursive) {
            me.expandChildren(true, callback, scope);
          } else {
            Ext.callback(callback, scope || me, [me.childNodes]);
          }
        }
      }
    } else {
      Ext.callback(callback, scope || me);
    }
  }, onChildNodesAvailable:function(records, recursive, callback, scope) {
    var me = this, treeStore = me.getTreeStore(), bulkUpdate = treeStore && treeStore.bulkUpdate, ancestor, collapsedAncestors, i;
    Ext.suspendLayouts();
    for (ancestor = me.parentNode; ancestor; ancestor = ancestor.parentNode) {
      if (!ancestor.isExpanded()) {
        (collapsedAncestors || (collapsedAncestors = [])).unshift(ancestor);
      }
    }
    if (bulkUpdate || !treeStore.isVisible(me)) {
      me.data.expanded = true;
    } else {
      me.set('expanded', true);
    }
    if (collapsedAncestors) {
      for (i = 1; i < collapsedAncestors.length; i++) {
        ancestor = collapsedAncestors[i];
        if (bulkUpdate || !treeStore.isVisible(ancestor)) {
          ancestor.data.expanded = true;
        } else {
          ancestor.set('expanded', true);
        }
      }
      collapsedAncestors[0].expand();
      for (i = 1; i < collapsedAncestors.length; i++) {
        ancestor = collapsedAncestors[i];
        ancestor.fireBubbledEvent('expand', [ancestor, ancestor.childNodes]);
      }
    } else {
      me.callTreeStore('onNodeExpand', [records, false]);
    }
    me.fireBubbledEvent('expand', [me, records]);
    if (recursive) {
      me.expandChildren(true, callback, scope);
    } else {
      Ext.callback(callback, scope || me, [me.childNodes]);
    }
    Ext.resumeLayouts(true);
  }, expandChildren:function(recursive, callback, scope, singleExpand) {
    var me = this, origCallback, i, allNodes, expandNodes, ln, node, treeStore;
    if (Ext.isBoolean(callback)) {
      origCallback = callback;
      callback = scope;
      scope = singleExpand;
      singleExpand = origCallback;
    }
    if (singleExpand === undefined) {
      treeStore = me.getTreeStore();
      singleExpand = treeStore && treeStore.singleExpand;
    }
    allNodes = me.childNodes;
    expandNodes = [];
    ln = singleExpand ? Math.min(allNodes.length, 1) : allNodes.length;
    for (i = 0; i < ln; ++i) {
      node = allNodes[i];
      if (!node.isLeaf()) {
        expandNodes[expandNodes.length] = node;
      }
    }
    ln = expandNodes.length;
    for (i = 0; i < ln; ++i) {
      expandNodes[i].expand(recursive);
    }
    if (callback) {
      Ext.callback(callback, scope || me, [me.childNodes]);
    }
  }, collapse:function(recursive, callback, scope) {
    var me = this, expanded = me.isExpanded(), treeStore = me.getTreeStore(), bulkUpdate = treeStore && treeStore.bulkUpdate, len = me.childNodes.length, i, collapseChildren;
    if (!me.isLeaf() && (!expanded && recursive || me.fireBubbledEvent('beforecollapse', [me]) !== false)) {
      Ext.suspendLayouts();
      if (me.isExpanded()) {
        if (recursive) {
          collapseChildren = function() {
            for (i = 0; i < len; i++) {
              me.childNodes[i].setCollapsed(true);
            }
          };
          if (callback) {
            callback = Ext.Function.createSequence(collapseChildren, Ext.Function.bind(callback, scope, [me.childNodes]));
          } else {
            callback = collapseChildren;
          }
        } else {
          if (callback) {
            callback = Ext.Function.bind(callback, scope, [me.childNodes]);
          }
        }
        if (bulkUpdate || !treeStore.contains(me)) {
          me.data.expanded = false;
        } else {
          me.set('expanded', false);
        }
        me.callTreeStore('onNodeCollapse', [me.childNodes, callback, scope]);
        me.fireBubbledEvent('collapse', [me, me.childNodes]);
        callback = null;
      } else {
        if (recursive) {
          for (i = 0; i < len; i++) {
            me.childNodes[i].setCollapsed(true);
          }
        }
      }
      Ext.resumeLayouts(true);
    }
    Ext.callback(callback, scope || me, [me.childNodes]);
  }, setCollapsed:function(recursive) {
    var me = this, len = me.childNodes.length, i;
    if (!me.isLeaf() && me.fireBubbledEvent('beforecollapse', [me]) !== false) {
      me.data.expanded = false;
      me.fireBubbledEvent('collapse', [me, me.childNodes]);
      if (recursive) {
        for (i = 0; i < len; i++) {
          me.childNodes[i].setCollapsed(true);
        }
      }
    }
  }, collapseChildren:function(recursive, callback, scope) {
    var me = this, allNodes = me.childNodes, ln = allNodes.length, collapseNodes = [], node, i;
    for (i = 0; i < ln; ++i) {
      node = allNodes[i];
      if (!node.isLeaf() && node.isLoaded() && node.isExpanded()) {
        collapseNodes.push(node);
      }
    }
    ln = collapseNodes.length;
    if (ln) {
      for (i = 0; i < ln; ++i) {
        node = collapseNodes[i];
        if (i === ln - 1) {
          node.collapse(recursive, callback, scope);
        } else {
          node.collapse(recursive);
        }
      }
    } else {
      Ext.callback(callback, scope);
    }
  }, fireEvent:function(eventName) {
    return this.fireBubbledEvent(eventName, Ext.Array.slice(arguments, 1));
  }, fireBubbledEvent:function(eventName, args) {
    var result, eventSource, topNode;
    if (bubbledEvents[eventName]) {
      for (eventSource = this; result !== false && eventSource; eventSource = (topNode = eventSource).parentNode) {
        result = eventSource.fireEventArgs.call(eventSource, eventName, args);
      }
      if (result !== false) {
        eventSource = topNode.getTreeStore();
        if (eventSource && eventSource.hasListeners && eventSource.hasListeners[eventName = 'node' + eventName]) {
          result = eventSource.fireEventArgs(eventName, args);
        }
      }
      return result;
    } else {
      return this.fireEventArgs.apply(this, arguments);
    }
  }, serialize:function(writerParam) {
    var writer = writerParam || new Ext.data.writer.Json({writeAllFields:true}), result = writer.getRecordData(this), childNodes = this.childNodes, len = childNodes.length, children, i;
    if (len > 0) {
      result.children = children = [];
      for (i = 0; i < len; i++) {
        children.push(childNodes[i].serialize(writer));
      }
    }
    return result;
  }, callTreeStore:function(funcName, args) {
    var me = this, target = me.getTreeStore(), fn = target && target[funcName];
    if (target && fn) {
      args = args || [];
      if (args[0] !== me) {
        args.unshift(me);
      }
      fn.apply(target, args);
    }
  }, addCls:function(cls) {
    this.replaceCls(null, cls);
  }, removeCls:function(cls) {
    this.replaceCls(cls);
  }, replaceCls:function(oldCls, newCls) {
    var pieces = this._parseCls(this.data.cls), parts = this._parseCls(oldCls);
    if (parts.length) {
      pieces = Ext.Array.difference(pieces, parts);
    }
    parts = this._parseCls(newCls);
    if (parts.length) {
      pieces = Ext.Array.unique(pieces.concat(parts));
    }
    this.set('cls', pieces.join(' '));
  }, toggleCls:function(cls, state) {
    var pieces, parts, len, i, p;
    if (state === undefined) {
      pieces = this._parseCls(this.data.cls);
      parts = this._parseCls(cls);
      for (i = 0, len = parts.length; i < len; ++i) {
        p = parts[i];
        if (Ext.Array.contains(pieces, p)) {
          Ext.Array.remove(pieces, p);
        } else {
          pieces.push(p);
        }
      }
      this.set('cls', pieces.join(' '));
    } else {
      if (state) {
        this.addCls(cls);
      } else {
        this.removeCls(cls);
      }
    }
  }, privates:{_noCls:[], spacesRe:/\s+/, join:function(store) {
    if (store.isTreeStore) {
      if (this.isRoot()) {
        this.treeStore = this.store = store;
      }
    } else {
      this.callParent([store]);
    }
  }, callJoined:function(funcName, args) {
    this.callParent([funcName, args]);
    this.callTreeStore(funcName, args);
  }, _parseCls:function(cls) {
    if (!cls) {
      return this._noCls;
    }
    if (typeof cls === 'string') {
      return cls.split(this.spacesRe);
    }
    return cls;
  }}};
}}});
Ext.define('Ext.data.TreeModel', {extend:Ext.data.Model, mixins:[Ext.mixin.Queryable], getRefItems:function() {
  return this.childNodes;
}, getRefOwner:function() {
  return this.parentNode;
}, statics:{defaultProxy:'memory'}}, function() {
  Ext.data.NodeInterface.decorate(this);
});
Ext.define('Ext.data.NodeStore', {extend:Ext.data.Store, alias:'store.node', isNodeStore:true, config:{node:null, recursive:false, rootVisible:false, folderSort:false}, implicitModel:'Ext.data.TreeModel', getTotalCount:function() {
  return this.getCount();
}, updateFolderSort:function(folderSort) {
  var data = this.getData();
  data.setTrackGroups(false);
  if (folderSort) {
    data.setGrouper({groupFn:this.folderSortFn});
  } else {
    data.setGrouper(null);
  }
}, folderSortFn:function(node) {
  return node.data.leaf ? 1 : 0;
}, afterReject:function(record) {
  var me = this;
  if (me.contains(record)) {
    me.onUpdate(record, Ext.data.Model.REJECT, null);
    me.fireEvent('update', me, record, Ext.data.Model.REJECT, null);
  }
}, afterCommit:function(record, modifiedFieldNames) {
  var me = this;
  if (!modifiedFieldNames) {
    modifiedFieldNames = null;
  }
  if (me.contains(record)) {
    me.onUpdate(record, Ext.data.Model.COMMIT, modifiedFieldNames);
    me.fireEvent('update', me, record, Ext.data.Model.COMMIT, modifiedFieldNames);
  }
}, onNodeAppend:function(parent, node) {
  if (parent === this.getNode()) {
    this.add([node].concat(this.retrieveChildNodes(node)));
  }
}, onNodeInsert:function(parent, node, refNode) {
  var me = this;
  if (parent === me.getNode()) {
    me.insert(0, [node].concat(me.retrieveChildNodes(node)));
  }
}, onNodeRemove:function(parent, node) {
  if (parent === this.getNode()) {
    this.remove([node].concat(this.retrieveChildNodes(node)));
  }
}, onNodeExpand:function(parent, records) {
  if (parent === this.getNode()) {
    this.loadRecords(records);
  }
}, applyNode:function(node) {
  if (node) {
    if (!node.isModel) {
      node = new (this.getModel())(node);
    }
    if (!node.isNode) {
      Ext.data.NodeInterface.decorate(node);
    }
  }
  return node;
}, updateNode:function(node, oldNode) {
  var me = this, data;
  if (oldNode && !oldNode.destroyed) {
    oldNode.un({append:'onNodeAppend', insert:'onNodeInsert', remove:'onNodeRemove', scope:me});
    oldNode.unjoin(me);
  }
  if (node) {
    node.on({scope:me, append:'onNodeAppend', insert:'onNodeInsert', remove:'onNodeRemove'});
    node.join(me);
    data = [];
    if (node.childNodes.length) {
      data = data.concat(me.retrieveChildNodes(node));
    }
    if (me.getRootVisible()) {
      data.push(node);
    } else {
      if (node.isLoaded() || node.isLoading()) {
        node.set('expanded', true);
      }
    }
    me.getData().clear();
    me.fireEvent('clear', me);
    me.suspendEvents();
    if (me.isInitializing) {
      me.inlineData = data;
    } else {
      me.add(data);
    }
    me.resumeEvents();
    if (data.length === 0) {
      me.loaded = node.loaded = true;
    }
    me.fireEvent('refresh', me, me.data);
  }
}, isVisible:function(node) {
  var parent = node.parentNode;
  if (!this.getRecursive() && parent !== this.getNode()) {
    return false;
  }
  while (parent) {
    if (!parent.isExpanded()) {
      return false;
    }
    if (parent === this.getNode()) {
      break;
    }
    parent = parent.parentNode;
  }
  return true;
}, privates:{retrieveChildNodes:function(root) {
  var node = this.getNode(), recursive = this.getRecursive(), added = [], child = root;
  if (!root.childNodes.length || !recursive && root !== node) {
    return added;
  }
  if (!recursive) {
    return root.childNodes;
  }
  while (child) {
    if (child._added) {
      delete child._added;
      if (child === root) {
        break;
      } else {
        child = child.nextSibling || child.parentNode;
      }
    } else {
      if (child !== root) {
        added.push(child);
      }
      if (child.firstChild) {
        child._added = true;
        child = child.firstChild;
      } else {
        child = child.nextSibling || child.parentNode;
      }
    }
  }
  return added;
}}});
Ext.define('Ext.data.Request', {isDataRequest:true, config:{action:undefined, params:undefined, method:'GET', url:null, operation:null, proxy:null, disableCaching:false, headers:{}, callbackKey:null, rawRequest:null, jsonData:undefined, xmlData:undefined, withCredentials:false, username:null, password:null, binary:false, callback:null, scope:null, timeout:30000, records:null, directFn:null, args:null, useDefaultXhrHeader:null, responseType:null}, constructor:function(config) {
  this.initConfig(config);
}, getParam:function(key) {
  var params = this.getParams(), val;
  if (params) {
    return params[key];
  }
  return val;
}, setParam:function(key, value) {
  var params = this.getParams() || {};
  params[key] = value;
  this.setParams(params);
}});
Ext.define('Ext.data.TreeStore', {extend:Ext.data.Store, alias:'store.tree', isTreeStore:true, config:{root:null, rootVisible:false, defaultRootProperty:'children', parentIdProperty:null, clearOnLoad:true, clearRemovedOnLoad:true, nodeParam:'node', defaultRootId:'root', defaultRootText:'Root', folderSort:false, pageSize:null}, filterer:'topdown', lazyFill:false, fillCount:0, bulkUpdate:0, nodesToUnregister:0, _silentOptions:{silent:true}, implicitModel:'Ext.data.TreeModel', groupField:null, groupDir:null, 
grouper:null, constructor:function(config) {
  var me = this;
  me.byIdMap = {};
  me.callParent([config]);
  if (Ext.isDefined(me.nodeParameter)) {
    if (Ext.isDefined(Ext.global.console)) {
      Ext.global.console.warn('Ext.data.TreeStore: nodeParameter has been deprecated. ' + 'Please use nodeParam instead.');
    }
    me.nodeParam = me.nodeParameter;
    delete me.nodeParameter;
  }
}, applyFields:function(fields, oldFields) {
  var me = this;
  if (fields) {
    if (me.defaultRootProperty !== me.self.prototype.config.defaultRootProperty) {
      fields = fields.concat({name:me.defaultRootProperty, type:'auto', defaultValue:null, persist:false});
    }
  }
  me.callParent([fields, oldFields]);
}, applyGroupField:function(field) {
  return null;
}, applyGroupDir:function(dir) {
  return null;
}, applyGrouper:function(grouper) {
  if (grouper) {
    Ext.raise("You can't group a TreeStore");
  }
  return null;
}, group:Ext.emptyFn, onSorterEndUpdate:function() {
  var me = this, sorterCollection = me.getSorters(), sorters = sorterCollection.getRange(), rootNode = me.getRoot(), folderSort = me.getFolderSort();
  me.fireEvent('beforesort', me, sorters);
  if (rootNode && (folderSort || sorters.length)) {
    if (me.getRemoteSort()) {
      if (sorters.length) {
        me.load({callback:function() {
          me.fireEvent('sort', me, sorters);
        }});
      }
    } else {
      rootNode.sort(this.getSortFn(), true);
      me.fireEvent('datachanged', me);
      me.fireEvent('refresh', me);
      me.fireEvent('sort', me, sorters);
    }
  } else {
    me.fireEvent('sort', me, sorters);
  }
}, updateFolderSort:function(folderSort) {
  this.needsFolderSort = folderSort;
  this.onSorterEndUpdate();
}, getSortFn:function() {
  return this._sortFn || (this._sortFn = this.createSortFn());
}, createSortFn:function() {
  var me = this, sortersSortFn = this.sorters.getSortFn();
  return function(node1, node2) {
    var node1FolderOrder, node2FolderOrder, result = 0;
    if (me.needsFolderSort) {
      node1FolderOrder = node1.data.leaf ? 1 : 0;
      node2FolderOrder = node2.data.leaf ? 1 : 0;
      result = node1FolderOrder - node2FolderOrder;
    }
    if (me.needsIndexSort && result === 0) {
      result = node1.data.index - node2.data.index;
    }
    return result || sortersSortFn(node1, node2);
  };
}, getTotalCount:function() {
  return this.getCount();
}, afterEdit:function(node, modifiedFieldNames) {
  var me = this, parentNode = node.parentNode, rootVisible = me.getRootVisible(), isHiddenRoot = !parentNode && !rootVisible, prevVisibleNodeIndex, isVisible = node.get('visible'), toAdd, removeStart;
  if (!isHiddenRoot && isVisible !== me.contains(node)) {
    if (isVisible) {
      if (!parentNode || me.isVisible(node)) {
        toAdd = [node];
        if (node.isExpanded()) {
          me.handleNodeExpand(node, node.childNodes, toAdd);
        }
        prevVisibleNodeIndex = node.previousSibling ? me.indexOfPreviousVisibleNode(node.previousSibling) : parentNode ? me.indexOf(parentNode) : -1;
        me.insert(prevVisibleNodeIndex + 1, toAdd);
      }
    } else {
      removeStart = me.indexOf(node);
      me.removeAt(removeStart, me.indexOfNextVisibleNode(node) - removeStart);
    }
  } else {
    if (me.getRoot() && me.needsLocalFilter()) {
      me.onFilterEndUpdate(me.getFilters());
    }
  }
  me.callParent([node, modifiedFieldNames]);
}, afterReject:function(record) {
  var me = this;
  if (me.contains(record)) {
    me.onUpdate(record, Ext.data.Model.REJECT, null);
    me.fireEvent('update', me, record, Ext.data.Model.REJECT, null);
  }
}, afterCommit:function(record, modifiedFieldNames) {
  var me = this;
  if (!modifiedFieldNames) {
    modifiedFieldNames = null;
  }
  if (me.contains(record)) {
    me.onUpdate(record, Ext.data.Model.COMMIT, modifiedFieldNames);
    me.fireEvent('update', me, record, Ext.data.Model.COMMIT, modifiedFieldNames);
  }
}, updateRootVisible:function(rootVisible) {
  var rootNode = this.getRoot(), data;
  if (rootNode) {
    data = this.getData();
    if (rootVisible) {
      data.insert(0, rootNode);
    } else {
      data.remove(rootNode);
    }
  }
}, updateTrackRemoved:function(trackRemoved) {
  this.callParent(arguments);
  this.removedNodes = this.removed;
  this.removed = null;
}, onDestroyRecords:function(records, operation, success) {
  if (success) {
    this.removedNodes.length = 0;
  }
}, updateProxy:function(proxy) {
  var reader;
  if (proxy) {
    if (proxy.setIdParam) {
      proxy.setIdParam(this.getNodeParam());
    }
    reader = proxy.getReader();
    if (Ext.isEmpty(reader.getRootProperty())) {
      reader.setRootProperty(this.getDefaultRootProperty());
    }
  }
}, setProxy:function(proxy) {
  this.changingProxy = true;
  this.callParent([proxy]);
  this.changingProxy = false;
}, updateModel:function(model) {
  var isNode;
  if (model) {
    isNode = model.prototype.isNode;
    Ext.data.NodeInterface.decorate(model);
    if (!isNode && !this.changingProxy) {
      this.getProxy().getReader().buildExtractors(true);
    }
  }
}, onCollectionFilter:Ext.emptyFn, onFilterEndUpdate:function(filters) {
  var me = this, length = filters.length, root = me.getRoot(), childNodes, childNode, filteredNodes, i;
  if (!me.getRemoteFilter()) {
    if (length) {
      me.doFilter(root);
    } else {
      root.cascade({after:function(node) {
        node.set('visible', true, me._silentOptions);
      }});
    }
    if (length) {
      filteredNodes = [];
      childNodes = root.childNodes;
      for (i = 0, length = childNodes.length; i < length; i++) {
        childNode = childNodes[i];
        if (childNode.get('visible')) {
          filteredNodes.push(childNode);
        }
      }
    } else {
      filteredNodes = root.childNodes;
    }
    me.onNodeFilter(root, filteredNodes);
    root.fireEvent('filterchange', root, filteredNodes);
    me.suppressNextFilter = true;
    me.callParent([filters]);
    me.suppressNextFilter = false;
  } else {
    me.callParent([filters]);
  }
}, onNodeFilter:function(root, childNodes) {
  var me = this, data = me.getData(), toAdd = [];
  if (me.getRootVisible() && root.get('visible')) {
    toAdd.push(root);
  }
  me.handleNodeExpand(root, childNodes, toAdd);
  me.suspendEvents();
  data.splice(0, data.getCount(), toAdd);
  me.resumeEvents();
  if (!me.suppressNextFilter) {
    me.fireEvent('datachanged', me);
    me.fireEvent('refresh', me);
  }
}, onBeforeNodeExpand:function(node, callback, scope, args) {
  var me = this, storeReader, nodeProxy, nodeReader, reader, children, callbackArgs;
  if (node.isLoaded()) {
    callbackArgs = [node.childNodes];
    if (args) {
      callbackArgs.push.apply(callbackArgs, args);
    }
    Ext.callback(callback, scope || node, callbackArgs);
  } else {
    if (node.isLoading()) {
      me.on('load', function() {
        callbackArgs = [node.childNodes];
        if (args) {
          callbackArgs.push.apply(callbackArgs, args);
        }
        Ext.callback(callback, scope || node, callbackArgs);
      }, me, {single:true, priority:1001});
    } else {
      storeReader = me.getProxy().getReader();
      nodeProxy = node.getProxy();
      nodeReader = nodeProxy ? nodeProxy.getReader() : null;
      reader = nodeReader && nodeReader.initialConfig.rootProperty ? nodeReader : storeReader;
      children = reader.getRoot(node.raw || node.data);
      if (children || node.phantom && !node.isRoot()) {
        me.fillNode(node, reader.extractData(children || [], {model:node.childType, recordCreator:me.recordCreator}));
        callbackArgs = [node.childNodes];
        if (args) {
          callbackArgs.push.apply(callbackArgs, args);
        }
        Ext.callback(callback, scope || node, callbackArgs);
      } else {
        me.read({node:node, onChildNodesAvailable:function() {
          delete me.lastOptions.onChildNodesAvailable;
          callbackArgs = [node.childNodes];
          if (args) {
            callbackArgs.push.apply(callbackArgs, args);
          }
          Ext.callback(callback, scope || node, callbackArgs);
        }});
        me.flushLoad();
      }
    }
  }
}, onNodeExpand:function(parent, records) {
  var me = this, insertIndex = me.indexOf(parent) + 1, toAdd = [];
  me.handleNodeExpand(parent, records, toAdd);
  if (!me.refreshCounter && parent.isRoot() && !parent.get('visible')) {
    me.loadRecords(toAdd);
  } else {
    ++me.loadCount;
    me.insert(insertIndex, toAdd);
  }
}, handleNodeExpand:function(parent, records, toAdd) {
  var me = this, ln = records ? records.length : 0, i, record;
  if (parent !== this.getRoot() && !me.isVisible(parent)) {
    return;
  }
  if (ln) {
    for (i = 0; i < ln; i++) {
      record = records[i];
      if (record.get('visible')) {
        toAdd.push(record);
        if (record.isExpanded()) {
          if (record.isLoaded()) {
            me.handleNodeExpand(record, record.childNodes, toAdd);
          } else {
            record.set('expanded', false, {silent:true});
            record.expand();
          }
        }
      }
    }
  }
}, onNodeCollapse:function(parent, records, callback, scope) {
  var me = this, collapseIndex = me.indexOf(parent) + 1, lastNodeIndexPlus;
  if (me.needsLocalFilter()) {
    records = Ext.Array.filter(records, me.filterVisible);
  }
  if (records.length && me.isVisible(parent)) {
    lastNodeIndexPlus = me.indexOfNextVisibleNode(parent);
    me.removeAt(collapseIndex, lastNodeIndexPlus - collapseIndex);
  }
  Ext.callback(callback, scope);
}, indexOfNextVisibleNode:function(node) {
  var result;
  while (node.parentNode) {
    for (result = node.nextSibling; result && !result.get('visible'); result = result.nextSibling) {
    }
    if (result) {
      return this.indexOf(result);
    }
    node = node.parentNode;
  }
  return this.getCount();
}, indexOfPreviousVisibleNode:function(node) {
  var result;
  for (result = node; result && !result.get('visible'); result = result.previousSibling) {
  }
  if (result) {
    if (result.isExpanded() && result.lastChild) {
      return this.indexOfPreviousVisibleNode(result.lastChild);
    }
  } else {
    result = node.parentNode;
  }
  return this.indexOf(result);
}, filterNew:function(item) {
  return !item.get('root') && this.callParent([item]);
}, filterRejects:function(item) {
  return !item.get('root') && this.callParent([item]);
}, getNewRecords:function() {
  return Ext.Array.filter(Ext.Object.getValues(this.byIdMap), this.filterNew, this);
}, getRejectRecords:function() {
  return Ext.Array.filter(Ext.Object.getValues(this.byIdMap), this.filterRejects, this);
}, getUpdatedRecords:function() {
  return Ext.Array.filter(Ext.Object.getValues(this.byIdMap), this.filterUpdated);
}, beforeNodeRemove:function(parentNode, childNodes, isMove, removeRange) {
  if (!Ext.isArray(childNodes)) {
    childNodes = [childNodes];
  }
  var me = this, len = childNodes.length, removed = me.removedNodes, startNode, i;
  for (i = 0; !startNode && i < len; i++) {
    if (childNodes[i].get('visible')) {
      startNode = childNodes[i];
    }
  }
  if (startNode) {
    removeRange[0] = me.indexOf(childNodes[0]);
    removeRange[1] = me.indexOfNextVisibleNode(childNodes[childNodes.length - 1]) - removeRange[0];
  } else {
    removeRange[0] = -1;
    removeRange[1] = 0;
  }
  for (i = 0; i < len; i++) {
    childNodes[i].cascade(function(node) {
      me.unregisterNode(node, true);
      if (removed && !isMove) {
        if (!node.phantom && !node.erasing && !me.loading) {
          node.removedFrom = me.indexOf(node);
          removed.push(node);
          me.needsSync = true;
        }
      }
    });
  }
}, afterDrop:Ext.emptyFn, onNodeRemove:function(parentNode, childNodes, isMove, removeRange) {
  var me = this;
  me.suspendAutoSync();
  if (removeRange[0] !== -1) {
    me.removeIsMove = isMove;
    me.removeAt.apply(me, removeRange);
    me.removeIsMove = false;
  }
  me.resumeAutoSync();
}, onNodeAppend:function(parent, node, index) {
  this.onNodeInsert(parent, node, index);
}, onNodeInsert:function(parent, node, index) {
  var me = this, data = node.raw || node.data, removed = me.removedNodes, storeReader, nodeProxy, nodeReader, reader, dataRoot, storeInsertionPoint;
  if (parent && me.needsLocalFilter()) {
    me.doFilter(parent);
  }
  me.beginUpdate();
  if (me.isVisible(node)) {
    if (index === 0 || !node.previousSibling) {
      storeInsertionPoint = me.indexOf(parent);
    } else {
      storeInsertionPoint = me.indexOfPreviousVisibleNode(node.previousSibling);
    }
    me.insert(storeInsertionPoint + 1, node);
    if (!node.isLeaf() && node.isExpanded()) {
      if (node.isLoaded()) {
        me.onNodeExpand(node, node.childNodes);
      } else {
        if (!me.fillCount) {
          node.set('expanded', false);
          node.expand();
        }
      }
    }
  }
  Ext.Array.remove(removed, node);
  me.needsSync = me.needsSync || node.phantom || node.dirty;
  if (!node.isLeaf() && !node.isLoaded() && !me.lazyFill) {
    storeReader = me.getProxy().getReader();
    nodeProxy = node.getProxy();
    nodeReader = nodeProxy ? nodeProxy.getReader() : null;
    reader = nodeReader && nodeReader.initialConfig.rootProperty ? nodeReader : storeReader;
    dataRoot = reader.getRoot(data);
    if (dataRoot) {
      me.fillNode(node, reader.extractData(dataRoot, {model:node.childType, recordCreator:me.recordCreator}));
    }
  }
  me.endUpdate();
}, registerNode:function(node, includeChildren) {
  var me = this, was = me.byIdMap[node.id], children, length, i;
  me.byIdMap[node.id] = node;
  if (node.onRegisterTreeNode && node !== was) {
    node.onRegisterTreeNode(me);
  }
  if (node.onUnregisterTreeNode) {
    me.nodesToUnregister++;
  }
  if (includeChildren === true) {
    children = node.childNodes;
    length = children.length;
    for (i = 0; i < length; i++) {
      me.registerNode(children[i], true);
    }
  }
}, unregisterNode:function(node, includeChildren) {
  var me = this, was = me.byIdMap[node.id], children, length, i;
  delete me.byIdMap[node.id];
  if (includeChildren === true) {
    children = node.childNodes;
    length = children.length;
    for (i = 0; i < length; i++) {
      me.unregisterNode(children[i], true);
    }
  }
  if (node.onUnregisterTreeNode && node === was) {
    node.onUnregisterTreeNode(me);
    me.nodesToUnregister--;
  }
}, onNodeSort:function(node, childNodes) {
  var me = this;
  me.suspendAutoSync();
  if (me.indexOf(node) !== -1 && node.isExpanded() || node === me.getRoot() && !me.getRootVisible()) {
    Ext.suspendLayouts();
    me.onNodeCollapse(node, childNodes);
    me.onNodeExpand(node, childNodes);
    Ext.resumeLayouts(true);
  }
  me.resumeAutoSync(me.autoSync);
}, applyRoot:function(newRoot) {
  var me = this, Model = me.getModel(), idProperty = Model.prototype.idProperty, defaultRootId = me.getDefaultRootId();
  if (newRoot && !newRoot.isNode) {
    newRoot = Ext.apply({text:me.getDefaultRootText(), root:true, isFirst:true, isLast:true, depth:0, index:0, parentId:null, allowDrag:false}, newRoot);
    if (defaultRootId && newRoot[idProperty] === undefined) {
      newRoot[idProperty] = defaultRootId;
    }
    newRoot = new Model(newRoot);
  }
  return newRoot;
}, updateRoot:function(newRoot, oldRoot) {
  var me = this, removeRange = [], initial = me.isConfiguring, oldOwner, toRemove;
  me.getTrackRemoved();
  me.suspendEvent('add', 'remove');
  if (initial) {
    me.suspendEvent('refresh', 'datachanged');
  }
  if (oldRoot && oldRoot.isModel) {
    if (me.getRootVisible()) {
      toRemove = [oldRoot];
    } else {
      toRemove = oldRoot.childNodes;
    }
    me.beforeNodeRemove(null, toRemove, false, removeRange);
    oldRoot.set('root', false);
    me.onNodeRemove(null, toRemove, false, removeRange);
    oldRoot.fireEvent('remove', null, oldRoot, false);
    oldRoot.fireEvent('rootchange', null);
    oldRoot.clearListeners();
    oldRoot.store = oldRoot.treeStore = null;
    me.unregisterNode(oldRoot);
  }
  me.getData().clear();
  if (newRoot) {
    if (newRoot.fireEventArgs('beforeappend', [null, newRoot]) === false) {
      newRoot = null;
    } else {
      oldOwner = newRoot.parentNode;
      if (oldOwner) {
        if (!oldOwner.removeChild(newRoot, false, false, oldOwner.getTreeStore() === me)) {
          return;
        }
      } else {
        if ((oldOwner = newRoot.getTreeStore()) && oldOwner !== me && newRoot === oldOwner.getRoot()) {
          oldOwner.setRoot(null);
        }
      }
      newRoot.store = newRoot.treeStore = me;
      newRoot.set('root', true);
      newRoot.updateInfo(true, {isFirst:true, isLast:true, depth:0, index:0, parentId:null});
      me.registerNode(newRoot, true);
      newRoot.fireEvent('append', null, newRoot, false);
      newRoot.fireEvent('rootchange', newRoot);
      me.onNodeAppend(null, newRoot, 0);
      newRoot.phantom = true;
    }
  }
  if (!initial) {
    me.fireEvent('rootchange', newRoot, oldRoot);
  }
  if (newRoot && (me.getAutoLoad() || newRoot.isExpanded())) {
    if (newRoot.isLoaded()) {
      me.onNodeExpand(newRoot, newRoot.childNodes);
      if (!initial) {
        me.fireEvent('datachanged', me);
        me.fireEvent('refresh', me);
      }
    } else {
      newRoot.data.expanded = false;
      newRoot.expand(false);
      if (newRoot.isLoaded && !me.getProxy().isSynchronous && !initial) {
        me.fireEvent('datachanged', me);
        me.fireEvent('refresh', me);
      }
    }
  } else {
    if (!initial) {
      me.fireEvent('datachanged', me);
      me.fireEvent('refresh', me);
    }
  }
  me.resumeEvent('add', 'remove');
  if (initial) {
    me.resumeEvent('refresh', 'datachanged');
  }
}, doDestroy:function() {
  var me = this, root = me.getRoot();
  if (root && me.nodesToUnregister) {
    root.cascade(function(node) {
      if (node.onUnregisterTreeNode) {
        node.onUnregisterTreeNode(me);
      }
    });
  }
  me.callParent();
}, each:function(fn, scope, includeOptions) {
  var i = 0, filtered = includeOptions, includeCollapsed;
  if (includeOptions && typeof includeOptions === 'object') {
    includeCollapsed = includeOptions.collapsed;
    filtered = includeOptions.filtered;
  }
  if (includeCollapsed) {
    this.getRoot().cascade(function(node) {
      if (filtered === true || node.get('visible')) {
        return fn.call(scope || node, node, i++);
      }
    });
  } else {
    return this.callParent([fn, scope, filtered]);
  }
}, collect:function(dataIndex, options, filtered) {
  var includeCollapsed, map = {}, result = [], allowNull = options, strValue, value;
  if (options && typeof options === 'object') {
    includeCollapsed = options.collapsed;
    filtered = options.filtered;
    allowNull = options.allowNull;
  }
  if (includeCollapsed || filtered) {
    this.getRoot().cascade(function(node) {
      if (filtered === true || node.get('visible')) {
        value = node.get(dataIndex);
        strValue = String(value);
        if ((allowNull || !Ext.isEmpty(value)) && !map[strValue]) {
          map[strValue] = 1;
          result.push(value);
        }
      }
      if (!includeCollapsed && !node.isExpanded()) {
        return false;
      }
    });
  } else {
    result = this.callParent([dataIndex, allowNull, filtered]);
  }
  return result;
}, getNodeById:function(id) {
  return this.byIdMap[id] || null;
}, findNode:function(fieldName, value, startsWith, endsWith, ignoreCase) {
  var result = null, regex;
  if (Ext.isEmpty(value, false)) {
    return result;
  }
  if (fieldName === this.model.idProperty && arguments.length < 3) {
    return this.byIdMap[value];
  }
  regex = Ext.String.createRegex(value, startsWith, endsWith, ignoreCase);
  Ext.Object.eachValue(this.byIdMap, function(node) {
    if (node && regex.test(node.get(fieldName))) {
      result = node;
      return false;
    }
  });
  return result;
}, load:function(options) {
  var node = options && options.node;
  if (!node && !(node = this.getRoot())) {
    node = this.setRoot({expanded:true, autoRoot:true});
    return;
  }
  if (node.isLoading()) {
    return;
  }
  return this.callParent([options]);
}, reload:function(options) {
  var o = Ext.apply({}, options, this.lastOptions);
  o.node = this.getRoot();
  return this.load(o);
}, flushLoad:function() {
  var me = this, options = me.pendingLoadOptions, clearOnLoad = me.getClearOnLoad(), node, callback, scope, isRootLoad, operation, doClear;
  me.clearLoadTask();
  if (!options) {
    return;
  }
  node = options.node || me.getRoot();
  isRootLoad = node && node.isRoot();
  callback = options.callback;
  scope = options.scope;
  options.params = options.params || {};
  if (node.data.expanded && !isRootLoad) {
    node.data.loaded = false;
    if (clearOnLoad) {
      node.data.expanded = false;
    }
    options.callback = function(loadedNodes, operation, success) {
      if (!clearOnLoad) {
        node.collapse();
      }
      node.expand();
      Ext.callback(callback, scope, [loadedNodes, operation, success]);
    };
  }
  options.id = node.getId();
  me.setLoadOptions(options);
  if (me.getRemoteSort() && options.sorters) {
    me.fireEvent('beforesort', me, options.sorters);
  }
  options = Ext.apply({node:options.node || node, internalScope:me, internalCallback:me.onProxyLoad}, options);
  me.lastOptions = Ext.apply({}, options);
  options.isRootLoad = isRootLoad;
  operation = me.createOperation('read', options);
  if (me.fireEvent('beforeload', me, operation) !== false) {
    me.loading = true;
    if (isRootLoad) {
      if (me.getClearRemovedOnLoad()) {
        me.removedNodes.length = 0;
      }
      if (clearOnLoad) {
        me.unregisterNode(node, true);
        node.clear(false, true);
        me.registerNode(node);
        doClear = true;
      }
    } else {
      if (me.loading) {
        node.data.loaded = false;
      }
      if (me.getTrackRemoved() && me.getClearRemovedOnLoad()) {
        me.clearRemoved(node);
      }
      if (clearOnLoad) {
        node.removeAll(false);
      }
    }
    if (me.loading && node) {
      node.set('loading', true, {silent:!(me.contains(node) || node === me.getRoot())});
    }
    if (doClear) {
      me.clearData(true);
      if (me.getRootVisible()) {
        me.suspendEvents();
        me.add(node);
        me.resumeEvents();
      }
    }
    operation.execute();
  }
  return me;
}, onProxyLoad:function(operation) {
  var me = this, options = operation.initialConfig, successful = operation.wasSuccessful(), records = operation.getRecords(), node = options.node, isRootLoad = options.isRootLoad, scope = operation.getScope() || me, args = [records, operation, successful];
  if (me.destroyed) {
    return;
  }
  me.loading = false;
  node.set('loading', false);
  if (successful) {
    ++me.loadCount;
    if (!me.getClearOnLoad()) {
      records = me.cleanRecords(node, records);
    }
    if (me.getParentIdProperty()) {
      records = me.treeify(node, records);
    }
    if (isRootLoad) {
      me.suspendEvent('add', 'update');
    }
    records = me.fillNode(node, records);
  }
  Ext.callback(options.onChildNodesAvailable, scope, args);
  if (isRootLoad) {
    me.resumeEvent('add', 'update');
    me.callObservers('BeforePopulate');
    me.fireEvent('datachanged', me);
    me.fireEvent('refresh', me);
    me.callObservers('AfterPopulate');
  }
  me.fireEvent('load', me, records, successful, operation, node);
}, clearRemoved:function(node) {
  var me = this, removed = me.removedNodes, id = node.getId(), removedLength = removed.length, i = removedLength, recordsToClear = {}, newRemoved = [], removedHash = {}, removedNode, targetNode, targetId;
  if (node === me.getRoot()) {
    me.removedNodes.length = 0;
    return;
  }
  for (; i--;) {
    removedNode = removed[i];
    removedHash[removedNode.getId()] = removedNode;
  }
  for (i = removedLength; i--;) {
    removedNode = removed[i];
    targetNode = removedNode;
    while (targetNode && targetNode.getId() !== id) {
      targetId = targetNode.get('parentId') || targetNode.get('lastParentId');
      targetNode = targetNode.parentNode || me.getNodeById(targetId) || removedHash[targetId];
    }
    if (targetNode) {
      recordsToClear[removedNode.getId()] = removedNode;
    }
  }
  for (i = 0; i < removedLength; i++) {
    removedNode = removed[i];
    if (!recordsToClear[removedNode.getId()]) {
      newRemoved.push(removedNode);
    }
  }
  me.removedNodes = newRemoved;
}, fillNode:function(node, newNodes) {
  var me = this, newNodeCount = newNodes ? newNodes.length : 0;
  if (++me.bulkUpdate === 1) {
    me.suspendEvent('datachanged');
  }
  if (newNodeCount) {
    me.setupNodes(newNodes);
    node.appendChild(newNodes, undefined, true);
  } else {
    if (me.bulkUpdate === 1) {
      node.set('loaded', true);
    } else {
      node.data.loaded = true;
    }
  }
  if (!--me.bulkUpdate) {
    me.resumeEvent('datachanged');
  }
  return newNodes;
}, setupNodes:function(newNodes) {
  var me = this, sorters = me.getSorters(), needsIndexSort = false, newNodeCount = newNodes.length, performLocalSort = me.sortOnLoad && newNodeCount > 1 && !me.getRemoteSort() && me.getFolderSort() || sorters.length, performLocalFilter = me.needsLocalFilter(), node1, node2, i;
  if (performLocalFilter) {
    me.doFilter(newNodes[0]);
  }
  for (i = 1; i < newNodeCount; i++) {
    node1 = newNodes[i];
    node2 = newNodes[i - 1];
    if (performLocalFilter) {
      me.doFilter(node1);
    }
    needsIndexSort = node1.data.index !== node2.data.index;
  }
  if (performLocalSort) {
    me.needsIndexSort = true;
    Ext.Array.sort(newNodes, me.getSortFn());
    me.needsIndexSort = false;
  } else {
    if (needsIndexSort) {
      Ext.Array.sort(newNodes, me.sortByIndex);
    }
  }
}, beginFill:function() {
  var me = this;
  if (!me.fillCount++) {
    me.beginUpdate();
    me.suspendEvent('add', 'update');
    me.suspendAutoSync();
    me.fillArray = [];
  }
}, endFill:function(parent, nodes) {
  var me = this, fillArray = me.fillArray, i, len, index;
  fillArray.push(nodes);
  if (!--me.fillCount) {
    me.resumeAutoSync();
    me.resumeEvent('add', 'update');
    for (i = 0, len = fillArray.length; i < len; i++) {
      index = me.indexOf(fillArray[i][0]);
      if (index !== -1) {
        me.fireEvent('add', me, fillArray[i], index);
      }
    }
    me.fillArray = null;
    me.endUpdate();
  }
}, sortByIndex:function(node1, node2) {
  return node1.data.index - node2.data.index;
}, onIdChanged:function(node, oldId, newId) {
  var childNodes = node.childNodes, len = childNodes && childNodes.length, i;
  this.callParent(arguments);
  delete this.byIdMap[oldId];
  this.byIdMap[newId] = node;
  for (i = 0; i < len; i++) {
    childNodes[i].set('parentId', newId);
  }
}, treeify:function(parentNode, records) {
  var me = this, loadParentNodeId = parentNode.getId(), parentIdProperty = me.getParentIdProperty(), len = records.length, result = [], nodeMap = {}, i, node, parentId, parent, id, children;
  for (i = 0; i < len; i++) {
    node = records[i];
    node.data.depth = 1;
    nodeMap[node.id] = node;
  }
  for (i = 0; i < len; i++) {
    node = records[i];
    parentId = node.data[parentIdProperty];
    if (!(parentId || parentId === 0) || parentId === loadParentNodeId) {
      result.push(node);
    } else {
      if (!nodeMap[parentId]) {
        Ext.raise('Ext.data.TreeStore, Invalid parentId "' + parentId + '"');
      }
      parent = nodeMap[parentId];
      parent.$children = parent.$children || [];
      parent.$children.push(node);
      node.data.depth = parent.data.depth + 1;
    }
  }
  for (id in nodeMap) {
    node = nodeMap[id];
    children = node.$children;
    if (children) {
      delete node.$children;
      me.setupNodes(children);
      node.appendChild(children);
    }
    me.registerNode(node);
  }
  me.setupNodes(result);
  return result;
}, cleanRecords:function(node, records) {
  var nodeHash = {}, childNodes = node.childNodes, i = 0, len = childNodes.length, out = [], rec;
  for (; i < len; ++i) {
    nodeHash[childNodes[i].getId()] = true;
  }
  for (i = 0, len = records.length; i < len; ++i) {
    rec = records[i];
    if (!nodeHash[rec.getId()]) {
      out.push(rec);
    }
  }
  return out;
}, removeAll:function() {
  var me = this, root = me.getRoot(), ln = me.getData().length;
  me.suspendEvents();
  me.setRoot(null);
  me.resumeEvents();
  me.callParent();
  if (ln) {
    me.fireEvent('clear', me);
    me.fireEvent('rootchange', root, null);
  }
}, doSort:function(sorterFn) {
  var me = this;
  if (me.getRemoteSort()) {
    me.load();
  } else {
    me.tree.sort(sorterFn, true);
    me.fireEvent('datachanged', me);
    me.fireEvent('refresh', me);
  }
  me.fireEvent('sort', me, me.sorters.getRange());
}, filterVisible:function(node) {
  return node.get('visible');
}, isVisible:function(node) {
  var parentNode = node.parentNode, visible = node.data.visible, root = this.getRoot();
  while (visible && parentNode) {
    visible = parentNode.data.expanded && parentNode.data.visible;
    parentNode = parentNode.parentNode;
  }
  return visible && !(node === root && !this.getRootVisible());
}, commitChanges:function() {
  var removed = this.removedNodes;
  if (removed) {
    removed.length = 0;
  }
  this.callParent();
}, getRootNode:function() {
  return this.getRoot();
}, setRootNode:function(root) {
  this.setRoot(root);
  return this.getRoot();
}, privates:{fireChangeEvent:function(record) {
  return !!this.byIdMap[record.id];
}, getRawRemovedRecords:function() {
  return this.removedNodes;
}, createOperation:function(type, options) {
  var me = this, node = options.node, proxy;
  if (me.useModelProxy && node && node !== me.getRootNode()) {
    proxy = node.getProxy();
  }
  if (proxy && proxy !== me.getProxy()) {
    return proxy.createOperation(type, options);
  } else {
    return me.callParent([type, options]);
  }
}, recordCreator:function(data, Model) {
  return new Model(data);
}, doFilter:function(node) {
  this.filterNodes(node, this.getFilters().getFilterFn(), true);
}, filterNodes:function(node, filterFn, parentVisible) {
  var me = this, bottomUpFiltering = me.filterer === 'bottomup', match = filterFn(node) && parentVisible || node.isRoot() && !me.getRootVisible(), childNodes = node.childNodes, len = childNodes && childNodes.length, i, matchingChildren;
  if (len) {
    for (i = 0; i < len; ++i) {
      matchingChildren = me.filterNodes(childNodes[i], filterFn, match || bottomUpFiltering) || matchingChildren;
    }
    if (bottomUpFiltering) {
      match = matchingChildren || match;
    }
  }
  node.set('visible', match, me._silentOptions);
  return match;
}, needsLocalFilter:function() {
  return !this.getRemoteFilter() && this.getFilters().length;
}, onRemoteFilterSet:function(filters, remoteFilter) {
  var data = this.getData();
  data.setFilters(null);
  if (filters) {
    filters.on('endupdate', this.onFilterEndUpdate, this);
  }
}, onRemoteSortSet:function(sorters, remoteSort) {
  var data = this.getData();
  data.setSorters(null);
  if (sorters) {
    sorters.on('endupdate', this.onSorterEndUpdate, this);
  }
}}, deprecated:{5:{properties:{tree:null}}}});
Ext.define('Ext.data.Validation', {extend:Ext.data.Model, isValidation:true, syncGeneration:0, attach:function(record) {
  this.record = record;
  this.isBase = record.self === Ext.data.Model;
  delete this.data.id;
}, getValidation:function() {
  return null;
}, isValid:function() {
  var me = this;
  if (me.syncGeneration !== me.record.generation) {
    me.refresh();
  }
  return !me.dirty;
}, refresh:function(force) {
  if (this.isBase) {
    return;
  }
  var me = this, data = me.data, record = me.record, fields = record.fields, generation = record.generation, recordData = record.data, sep = record.validationSeparator, values = null, defaultMessage, currentValue, error, field, i, len, msg, val, name;
  if (force || me.syncGeneration !== generation) {
    me.syncGeneration = generation;
    for (i = 0, len = fields.length; i < len; ++i) {
      field = fields[i];
      name = field.name;
      val = recordData[name];
      defaultMessage = field.defaultInvalidMessage;
      error = 0;
      if (!(name in data)) {
        data[name] = currentValue = true;
      } else {
        currentValue = data[name];
      }
      if (field.validate !== Ext.emptyFn) {
        msg = field.validate(val, sep, null, record);
        if (msg !== true) {
          error = msg || defaultMessage;
        }
      }
      if (!error) {
        error = true;
      }
      if (error !== currentValue) {
        (values || (values = {}))[name] = error;
      }
    }
    if (values) {
      me.set(values);
    }
  }
}});
Ext.define('Ext.dom.Helper', function() {
  var afterbegin = 'afterbegin', afterend = 'afterend', beforebegin = 'beforebegin', beforeend = 'beforeend', bbValues = ['BeforeBegin', 'previousSibling'], aeValues = ['AfterEnd', 'nextSibling'], bb_ae_PositionHash = {beforebegin:bbValues, afterend:aeValues}, fullPositionHash = {beforebegin:bbValues, afterend:aeValues, afterbegin:['AfterBegin', 'firstChild'], beforeend:['BeforeEnd', 'lastChild']};
  return {singleton:true, alternateClassName:['Ext.DomHelper', 'Ext.core.DomHelper'], emptyTags:/^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i, confRe:/^(?:tag|children|cn|html|tpl|tplData)$/i, endRe:/end/i, attributeTransform:{cls:'class', htmlFor:'for'}, closeTags:{}, detachedDiv:document.createElement('div'), decamelizeName:function() {
    var camelCaseRe = /([a-z])([A-Z])/g, cache = {};
    function decamel(match, p1, p2) {
      return p1 + '-' + p2.toLowerCase();
    }
    return function(s) {
      return cache[s] || (cache[s] = s.replace(camelCaseRe, decamel));
    };
  }(), generateMarkup:function(spec, buffer) {
    var me = this, specType = typeof spec, attr, val, tag, i, closeTags;
    if (specType === 'string' || specType === 'number') {
      buffer.push(spec);
    } else {
      if (Ext.isArray(spec)) {
        for (i = 0; i < spec.length; i++) {
          if (spec[i]) {
            me.generateMarkup(spec[i], buffer);
          }
        }
      } else {
        tag = spec.tag || 'div';
        buffer.push('\x3c', tag);
        for (attr in spec) {
          if (spec.hasOwnProperty(attr)) {
            val = spec[attr];
            if (val !== undefined && !me.confRe.test(attr)) {
              if (val && val.join) {
                val = val.join(' ');
              }
              if (typeof val === 'object') {
                buffer.push(' ', attr, '\x3d"');
                me.generateStyles(val, buffer, true).push('"');
              } else {
                buffer.push(' ', me.attributeTransform[attr] || attr, '\x3d"', val, '"');
              }
            }
          }
        }
        if (me.emptyTags.test(tag)) {
          buffer.push('/\x3e');
        } else {
          buffer.push('\x3e');
          if (val = spec.tpl) {
            val.applyOut(spec.tplData, buffer);
          }
          if (val = spec.html) {
            buffer.push(val);
          }
          if (val = spec.cn || spec.children) {
            me.generateMarkup(val, buffer);
          }
          closeTags = me.closeTags;
          buffer.push(closeTags[tag] || (closeTags[tag] = '\x3c/' + tag + '\x3e'));
        }
      }
    }
    return buffer;
  }, generateStyles:function(styles, buffer, encode) {
    var a = buffer || [], name, val;
    for (name in styles) {
      if (styles.hasOwnProperty(name)) {
        val = styles[name];
        name = this.decamelizeName(name);
        if (encode && Ext.String.hasHtmlCharacters(val)) {
          val = Ext.String.htmlEncode(val);
        }
        a.push(name, ':', val, ';');
      }
    }
    return buffer || a.join('');
  }, markup:function(spec) {
    var buf;
    if (typeof spec === 'string') {
      return spec;
    }
    buf = this.generateMarkup(spec, []);
    return buf.join('');
  }, applyStyles:function(el, styles) {
    Ext.fly(el).applyStyles(styles);
  }, createContextualFragment:function(html) {
    var div = this.detachedDiv, fragment = document.createDocumentFragment(), length, childNodes;
    div.innerHTML = html;
    childNodes = div.childNodes;
    length = childNodes.length;
    while (length--) {
      fragment.appendChild(childNodes[0]);
    }
    return fragment;
  }, createDom:function(o) {
    var me = this, markup = me.markup(o), div = me.detachedDiv, child;
    div.innerHTML = markup;
    child = div.firstChild;
    return Ext.supports.ChildContentClearedWhenSettingInnerHTML ? child.cloneNode(true) : child;
  }, insertHtml:function(where, el, html) {
    var me = this, hashVal, range, rangeEl, setStart, frag;
    where = where.toLowerCase();
    if (el.insertAdjacentHTML) {
      if (me.ieInsertHtml) {
        frag = me.ieInsertHtml(where, el, html);
        if (frag) {
          return frag;
        }
      }
      hashVal = fullPositionHash[where];
      if (hashVal) {
        el.insertAdjacentHTML(hashVal[0], html);
        return el[hashVal[1]];
      }
    } else {
      if (el.nodeType === 3) {
        where = where === afterbegin ? beforebegin : where;
        where = where === beforeend ? afterend : where;
      }
      range = Ext.supports.CreateContextualFragment ? el.ownerDocument.createRange() : undefined;
      setStart = 'setStart' + (this.endRe.test(where) ? 'After' : 'Before');
      if (bb_ae_PositionHash[where]) {
        if (range) {
          range[setStart](el);
          frag = range.createContextualFragment(html);
        } else {
          frag = this.createContextualFragment(html);
        }
        el.parentNode.insertBefore(frag, where === beforebegin ? el : el.nextSibling);
        return el[(where === beforebegin ? 'previous' : 'next') + 'Sibling'];
      } else {
        rangeEl = (where === afterbegin ? 'first' : 'last') + 'Child';
        if (el.firstChild) {
          if (range) {
            try {
              range[setStart](el[rangeEl]);
              frag = range.createContextualFragment(html);
            } catch (e$58) {
              frag = this.createContextualFragment(html);
            }
          } else {
            frag = this.createContextualFragment(html);
          }
          if (where === afterbegin) {
            el.insertBefore(frag, el.firstChild);
          } else {
            el.appendChild(frag);
          }
        } else {
          el.innerHTML = html;
        }
        return el[rangeEl];
      }
    }
    Ext.raise({sourceClass:'Ext.DomHelper', sourceMethod:'insertHtml', htmlToInsert:html, targetElement:el, msg:'Illegal insertion point reached: "' + where + '"'});
  }, insertBefore:function(el, o, returnElement) {
    return this.doInsert(el, o, returnElement, beforebegin);
  }, insertAfter:function(el, o, returnElement) {
    return this.doInsert(el, o, returnElement, afterend);
  }, insertFirst:function(el, o, returnElement) {
    return this.doInsert(el, o, returnElement, afterbegin);
  }, append:function(el, o, returnElement) {
    return this.doInsert(el, o, returnElement, beforeend);
  }, overwrite:function(el, html, returnElement) {
    var me = this, newNode;
    el = Ext.getDom(el);
    html = me.markup(html);
    if (me.ieOverwrite) {
      newNode = me.ieOverwrite(el, html);
    }
    if (!newNode) {
      el.innerHTML = html;
      newNode = el.firstChild;
    }
    return returnElement ? Ext.get(newNode) : newNode;
  }, doInsert:function(el, o, returnElement, where) {
    var me = this, newNode;
    el = el.dom || Ext.getDom(el);
    if ('innerHTML' in el) {
      newNode = me.insertHtml(where, el, me.markup(o));
    } else {
      newNode = me.createDom(o, null);
      if (el.nodeType === 3) {
        where = where === afterbegin ? beforebegin : where;
        where = where === beforeend ? afterend : where;
      }
      if (bb_ae_PositionHash[where]) {
        el.parentNode.insertBefore(newNode, where === beforebegin ? el : el.nextSibling);
      } else {
        if (el.firstChild && where === afterbegin) {
          el.insertBefore(newNode, el.firstChild);
        } else {
          el.appendChild(newNode);
        }
      }
    }
    return returnElement ? Ext.get(newNode) : newNode;
  }, createTemplate:function(o) {
    var html = this.markup(o);
    return new Ext.Template(html);
  }, createHtml:function(spec) {
    return this.markup(spec);
  }};
});
Ext.define('Ext.data.identifier.Uuid', {extend:Ext.data.identifier.Generator, alias:'data.identifier.uuid', isUnique:true, config:{id:null}, constructor:function(config) {
  this.callParent([config]);
  this.reconfigure(config);
}, reconfigure:function(config) {
  var cls = this.self;
  this.generate = config && config.version === 1 ? cls.createSequential(config.salt, config.timestamp, config.clockSeq) : cls.createRandom();
}, clone:null, statics:{createRandom:function() {
  var pattern = 'xxxxxxxx-xxxx-4xxx-Rxxx-xMxxxxxxxxxx'.split(''), hex = '0123456789abcdef'.split(''), length = pattern.length, parts = [];
  return function() {
    var r, c, i;
    for (i = 0; i < length; ++i) {
      c = pattern[i];
      if (c !== '-' && c !== '4') {
        r = Math.random() * 16;
        r = c === 'R' ? r & 3 | 8 : r | (c === 'M' ? 1 : 0);
        c = hex[r];
      }
      parts[i] = c;
    }
    return parts.join('');
  };
}, createSequential:function(salt, time, clockSeq) {
  var parts = [], twoPow32 = Math.pow(2, 32), saltLo = salt.lo, saltHi = salt.hi, timeLo = time.lo, timeHi = time.hi, toHex;
  toHex = function(value, length) {
    var ret = value.toString(16).toLowerCase();
    if (ret.length > length) {
      ret = ret.substring(ret.length - length);
    } else {
      if (ret.length < length) {
        ret = Ext.String.leftPad(ret, length, '0');
      }
    }
    return ret;
  };
  if (typeof salt === 'number') {
    saltHi = Math.floor(salt / twoPow32);
    saltLo = Math.floor(salt - saltHi * twoPow32);
  }
  if (typeof time === 'number') {
    timeHi = Math.floor(time / twoPow32);
    timeLo = Math.floor(time - timeHi * twoPow32);
  }
  saltHi |= 256;
  parts[3] = toHex(128 | clockSeq >>> 8 & 63, 2) + toHex(clockSeq & 255, 2);
  parts[4] = toHex(saltHi, 4) + toHex(saltLo, 8);
  return function() {
    parts[0] = toHex(timeLo, 8);
    parts[1] = toHex(timeHi & 65535, 4);
    parts[2] = toHex(timeHi >>> 16 & 4095 | 1 << 12, 4);
    ++timeLo;
    if (timeLo >= twoPow32) {
      timeLo = 0;
      ++timeHi;
    }
    return parts.join('-');
  };
}}}, function() {
  this.Global = new this({id:'uuid'});
});
Ext.define('Ext.data.validator.AbstractDate', {extend:Ext.data.validator.Validator, config:{message:null, format:''}, applyFormat:function(format) {
  if (!format) {
    format = this.getDefaultFormat();
  }
  if (!Ext.isArray(format)) {
    format = [format];
  }
  return format;
}, parse:function(value) {
  if (Ext.isDate(value)) {
    return value;
  }
  var me = this, format = me.getFormat(), len = format.length, ret = null, i;
  for (i = 0; i < len && !ret; ++i) {
    ret = Ext.Date.parse(value, format[i], true);
  }
  return ret;
}, validate:function(value) {
  return this.parse(value) ? true : this.getMessage();
}});
Ext.define('Ext.data.validator.Bound', {extend:Ext.data.validator.Validator, alias:'data.validator.bound', type:'bound', config:{min:undefined, max:undefined, emptyMessage:'Must be present', minOnlyMessage:'Value must be greater than {0}', maxOnlyMessage:'Value must be less than {0}', bothMessage:'Value must be between {0} and {1}'}, resetMessages:function() {
  this._bothMsg = this._minMsg = this._maxMsg = null;
}, updateMin:function() {
  this.resetMessages();
}, updateMax:function() {
  this.resetMessages();
}, updateMinOnlyMessage:function() {
  this.resetMessages();
}, updateMaxOnlyMessage:function() {
  this.resetMessages();
}, updateBothMessage:function() {
  this.resetMessages();
}, validate:function(value) {
  var me = this, min = me.getMin(), max = me.getMax(), hasMin = min != null, hasMax = max != null, msg = this.validateValue(value);
  if (msg !== true) {
    return msg;
  }
  value = me.getValue(value);
  if (hasMin && hasMax) {
    if (value < min || value > max) {
      msg = me._bothMsg || (me._bothMsg = Ext.String.format(me.getBothMessage(), min, max));
    }
  } else {
    if (hasMin) {
      if (value < min) {
        msg = me._minMsg || (me._minMsg = Ext.String.format(me.getMinOnlyMessage(), min));
      }
    } else {
      if (hasMax) {
        if (value > max) {
          msg = me._maxMsg || (me._maxMsg = Ext.String.format(me.getMaxOnlyMessage(), max));
        }
      }
    }
  }
  return msg;
}, validateValue:function(value) {
  if (value === undefined || value === null) {
    return this.getEmptyMessage();
  }
  return true;
}, getValue:Ext.identityFn});
Ext.define('Ext.data.validator.Format', {extend:Ext.data.validator.Validator, alias:'data.validator.format', type:'format', config:{message:'Is in the wrong format', matcher:undefined}, constructor:function() {
  this.callParent(arguments);
  if (!this.getMatcher()) {
    Ext.raise('validator.Format must be configured with a matcher');
  }
}, validate:function(value) {
  var matcher = this.getMatcher(), result = matcher && matcher.test(value);
  return result ? result : this.getMessage();
}});
Ext.define('Ext.data.validator.CIDRv4', {extend:Ext.data.validator.Format, alias:'data.validator.cidrv4', type:'cidrv4', message:'Is not a valid CIDR block', matcher:/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$/});
Ext.define('Ext.data.validator.CIDRv6', {extend:Ext.data.validator.Format, alias:'data.validator.cidrv6', type:'cidrv6', message:'Is not a valid CIDR block', matcher:/^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$/});
Ext.define('Ext.data.validator.Number', {extend:Ext.data.validator.Validator, alias:'data.validator.number', type:'number', config:{decimalSeparator:undefined, message:'Is not a valid number', thousandSeparator:undefined}, constructor:function(config) {
  this.callParent([config]);
  this.rebuildMatcher();
}, applyDecimalSeparator:function(v) {
  return v === undefined ? Ext.util.Format.decimalSeparator : v;
}, updateDecimalSeparator:function() {
  this.rebuildMatcher();
}, applyThousandSeparator:function(v) {
  return v === undefined ? Ext.util.Format.thousandSeparator : v;
}, updateThousandSeparator:function() {
  this.rebuildMatcher();
}, parse:function(v) {
  var sep = this.getDecimalSeparator(), N = Ext.Number;
  if (typeof v === 'string') {
    if (!this.matcher.test(v)) {
      return null;
    }
    v = this.parseValue(v);
  }
  return sep ? N.parseFloat(v) : N.parseInt(v);
}, validate:function(value) {
  return this.parse(value) === null ? this.getMessage() : true;
}, privates:{getMatcherText:function(preventSign) {
  var t = this.getThousandSeparator(), d = this.getDecimalSeparator(), s = '(?:';
  if (t) {
    t = Ext.String.escapeRegex(t);
    s += '(?:\\d{1,3}(' + t + '\\d{3})*)|';
  }
  s += '\\d*)';
  if (d) {
    d = Ext.String.escapeRegex(d);
    s += '(?:' + d + '\\d*)?';
  }
  if (!preventSign) {
    s = this.getSignPart() + s;
  }
  return s;
}, getSignPart:function() {
  return '(\\+|\\-)?';
}, parseValue:function(v) {
  var thousandMatcher = this.thousandMatcher, decimal;
  if (thousandMatcher) {
    v = v.replace(thousandMatcher, '');
  }
  decimal = this.getDecimalSeparator();
  if (decimal && decimal !== '.') {
    v = v.replace(decimal, '.');
  }
  return v;
}, rebuildMatcher:function() {
  var me = this, sep;
  if (!me.isConfiguring) {
    sep = me.getThousandSeparator();
    me.matcher = new RegExp('^' + me.getMatcherText() + '$');
    if (sep) {
      me.thousandMatcher = sep ? new RegExp(Ext.String.escapeRegex(sep), 'g') : null;
    }
  }
}}});
Ext.define('Ext.data.validator.Currency', {extend:Ext.data.validator.Number, alias:'data.validator.currency', type:'currency', config:{symbolAtEnd:undefined, spacer:undefined, symbol:undefined}, message:'Is not a valid currency amount', applySymbolAtEnd:function(value) {
  return value === undefined ? Ext.util.Format.currencyAtEnd : value;
}, updateSymbolAtEnd:function() {
  this.rebuildMatcher();
}, applySpacer:function(value) {
  return value === undefined ? Ext.util.Format.currencySpacer : value;
}, updateSpacer:function() {
  this.rebuildMatcher();
}, applySymbol:function(value) {
  return value === undefined ? Ext.util.Format.currencySign : value;
}, updateSymbol:function() {
  this.rebuildMatcher();
}, privates:{getMatcherText:function() {
  var me = this, ret = me.callParent([true]), symbolPart = me.getSymbolMatcher();
  if (me.getSymbolAtEnd()) {
    ret += symbolPart;
  } else {
    ret = symbolPart + ret;
  }
  return me.getSignPart() + ret;
}, getSymbolMatcher:function() {
  var symbol = Ext.String.escapeRegex(this.getSymbol()), spacer = Ext.String.escapeRegex(this.getSpacer() || ''), s = this.getSymbolAtEnd() ? spacer + symbol : symbol + spacer;
  return '(?:' + s + ')?';
}, parseValue:function(v) {
  v = v.replace(this.currencyMatcher, this.atEnd ? '' : '$1');
  return this.callParent([v]);
}, rebuildMatcher:function() {
  var me = this, symbolPart, atEnd, sign;
  me.callParent();
  if (!me.isConfiguring) {
    atEnd = me.getSymbolAtEnd();
    symbolPart = me.getSymbolMatcher();
    sign = me.getSignPart();
    me.atEnd = atEnd;
    me.currencyMatcher = new RegExp(atEnd ? symbolPart + '$' : '^' + sign + symbolPart);
  }
}}});
Ext.define('Ext.data.validator.CurrencyUS', {extend:Ext.data.validator.Currency, alias:'data.validator.currency-us', type:'currency-us', thousandSeparator:',', decimalSeparator:'.', symbol:'$', spacer:'', symbolAtEnd:false});
Ext.define('Ext.data.validator.Date', {extend:Ext.data.validator.AbstractDate, alias:'data.validator.date', type:'date', isDateValidator:true, message:'Is not a valid date', privates:{getDefaultFormat:function() {
  return [Ext.Date.defaultFormat, 'm/d/Y', 'n/j/Y', 'n/j/y', 'm/j/y', 'n/d/y', 'm/j/Y', 'n/d/Y', 'm-d-y', 'n-d-y', 'm-d-Y', 'mdy', 'mdY', 'Y-m-d'];
}}});
Ext.define('Ext.data.validator.DateTime', {extend:Ext.data.validator.AbstractDate, alias:'data.validator.datetime', type:'datetime', isDateTimeValidator:true, message:'Is not a valid date and time', privates:{getDefaultFormat:function() {
  var D = Ext.Date;
  return D.defaultFormat + ' ' + D.defaultTimeFormat;
}}});
Ext.define('Ext.data.validator.Email', {extend:Ext.data.validator.Format, alias:'data.validator.email', type:'email', message:'Is not a valid email address', matcher:/^(")?(?:[^\."])(?:(?:[\.])?(?:[\w\-!#$%&'*+\/=?\^_`{|}~]))*\1@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/});
Ext.define('Ext.data.validator.List', {extend:Ext.data.validator.Validator, alias:'data.validator.list', type:'list', config:{list:null, message:null}, inclusion:null, validate:function(value) {
  var contains = Ext.Array.contains(this.getList(), value), inclusion = this.inclusion, exclusion = !inclusion, result;
  result = inclusion && contains || exclusion && !contains;
  return result || this.getMessage();
}});
Ext.define('Ext.data.validator.Exclusion', {extend:Ext.data.validator.List, alias:'data.validator.exclusion', type:'exclusion', message:'Is a value that has been excluded', constructor:function() {
  this.callParent(arguments);
  if (!this.getList()) {
    Ext.raise('validator.Exclusion requires a list');
  }
}, inclusion:false});
Ext.define('Ext.data.validator.IPAddress', {extend:Ext.data.validator.Format, alias:'data.validator.ipaddress', type:'ipaddress', message:'Is not a valid IP address', matcher:new RegExp('^(' + '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' + '|' + '((([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))' + 
')$')});
Ext.define('Ext.data.validator.Inclusion', {extend:Ext.data.validator.List, alias:'data.validator.inclusion', type:'inclusion', message:'Is not in the list of acceptable values', constructor:function() {
  this.callParent(arguments);
  if (!this.getList()) {
    Ext.raise('validator.Inclusion requires a list');
  }
}, inclusion:true});
Ext.define('Ext.data.validator.Length', {extend:Ext.data.validator.Bound, alias:'data.validator.length', type:'length', minOnlyMessage:'Length must be at least {0}', maxOnlyMessage:'Length must be no more than {0}', bothMessage:'Length must be between {0} and {1}', getValue:function(v) {
  return String(v).length;
}});
Ext.define('Ext.data.validator.Presence', {extend:Ext.data.validator.Validator, alias:'data.validator.presence', type:'presence', isPresence:true, config:{message:'Must be present', allowEmpty:false}, validate:function(value) {
  var valid = !(value === undefined || value === null);
  if (valid && !this.getAllowEmpty()) {
    valid = value !== '';
  }
  return valid ? true : this.getMessage();
}});
Ext.define('Ext.data.validator.NotNull', {extend:Ext.data.validator.Presence, alias:'data.validator.notnull', type:'notnull', allowEmpty:true});
Ext.define('Ext.data.validator.Phone', {extend:Ext.data.validator.Format, alias:'data.validator.phone', type:'phone', message:'Is not a valid phone number', matcher:new RegExp('^ *' + '(?:' + '\\+?' + '(\\d{1,3})' + '[- .]?' + ')?' + '(?:' + '(?:' + '(\\d{3})' + '|' + '\\((\\d{3})\\)' + ')?' + '[- .]?' + ')' + '(?:' + '([2-9]\\d{2})' + '[- .]?' + ')' + '(\\d{4})' + '(?: *(?:e?xt?) *(\\d*))?' + ' *$')});
Ext.define('Ext.data.validator.Range', {extend:Ext.data.validator.Bound, alias:'data.validator.range', type:'range', minOnlyMessage:'Must be at least {0}', maxOnlyMessage:'Must be no more than than {0}', bothMessage:'Must be between {0} and {1}', config:{nanMessage:'Must be numeric'}, validateValue:function(value) {
  var msg = this.callParent([value]);
  if (msg === true && isNaN(value)) {
    msg = this.getNanMessage();
  }
  return msg;
}});
Ext.define('Ext.data.validator.Time', {extend:Ext.data.validator.AbstractDate, alias:'data.validator.time', type:'time', isTimeValidator:true, message:'Is not a valid time', privates:{getDefaultFormat:function() {
  return Ext.Date.defaultTimeFormat;
}}});
Ext.define('Ext.data.validator.Url', {extend:Ext.data.validator.Format, alias:'data.validator.url', type:'url', message:'Is not a valid URL', matcher:/^(http:\/\/|https:\/\/|ftp:\/\/|\/\/)([-a-zA-Z0-9@:%_\+.~#?&//=])+$/});
Ext.define('Ext.util.TaskRunner', {fireIdleEvent:null, interval:10, timerId:null, constructor:function(interval) {
  var me = this;
  if (typeof interval === 'number') {
    me.interval = interval;
  } else {
    if (interval) {
      Ext.apply(me, interval);
    }
  }
  me.tasks = [];
  me.timerFn = me.onTick.bind(me);
}, newTask:function(config) {
  var task = new Ext.util.TaskRunner.Task(config);
  task.manager = this;
  if (Ext.Timer.track) {
    task.creator = (new Error).stack;
  }
  return task;
}, start:function(task) {
  var me = this, now = Ext.Date.now();
  if (!task.pending) {
    me.tasks.push(task);
    task.pending = true;
  }
  task.stopped = false;
  task.taskStartTime = now;
  task.taskRunTime = task.fireOnStart !== false ? 0 : task.taskStartTime;
  task.taskRunCount = 0;
  if (!me.firing) {
    if (task.fireOnStart !== false) {
      me.startTimer(0, now);
    } else {
      me.startTimer(task.interval, now);
    }
  }
  return task;
}, stop:function(task, andRemove) {
  var me = this, tasks = me.tasks, pendingCount = 0, i;
  if (!task.stopped) {
    task.stopped = true;
    task.pending = false;
    if (task.onStop) {
      task.onStop.call(task.scope || task, task);
    }
  }
  if (andRemove) {
    Ext.Array.remove(tasks, task);
  }
  for (i = 0; !pendingCount && i < tasks.length; i++) {
    if (!tasks[i].stopped) {
      pendingCount++;
    }
  }
  if (!pendingCount) {
    Ext.undefer(me.timerId);
    me.timerId = null;
  }
  return task;
}, stopAll:function(andRemove) {
  var me = this;
  Ext.each(this.tasks, function(task) {
    me.stop(task, andRemove);
  }, null, true);
}, firing:false, nextExpires:1.0E99, onTick:function() {
  var me = this, tasks = me.tasks, fireIdleEvent = me.fireIdleEvent, now = Ext.Date.now(), nextExpires = 1.0E99, len = tasks.length, expires, newTasks, i, task, rt, remove, args;
  var timer = Ext.Timer.get(me.timerId);
  if (timer) {
    timer.tasks = [];
  }
  me.timerId = null;
  me.firing = true;
  for (i = 0; i < len || i < (len = tasks.length); ++i) {
    task = tasks[i];
    if (!(remove = task.stopped)) {
      expires = task.taskRunTime + task.interval;
      if (expires <= now) {
        rt = 1;
        if (fireIdleEvent === null && task.fireIdleEvent !== false) {
          fireIdleEvent = true;
        }
        task.taskRunCount++;
        if (task.args) {
          args = task.addCountToArgs ? task.args.concat([task.taskRunCount]) : task.args;
        } else {
          args = [task.taskRunCount];
        }
        if (timer) {
          timer.tasks.push(task);
        }
        if (me.disableTryCatch) {
          rt = task.run.apply(task.scope || task, args);
        } else {
          try {
            rt = task.run.apply(task.scope || task, args);
          } catch (taskError) {
            try {
              Ext.log({fn:task.run, prefix:'Error while running task', stack:taskError.stack, msg:taskError, level:'error'});
              if (task.onError) {
                rt = task.onError.call(task.scope || task, task, taskError);
              }
            } catch (e$59) {
            }
          }
        }
        task.taskRunTime = now;
        if (rt === false || task.taskRunCount === task.repeat) {
          me.stop(task);
          remove = true;
        } else {
          remove = task.stopped;
          expires = now + task.interval;
        }
      }
      if (!remove && task.duration && task.duration <= now - task.taskStartTime) {
        me.stop(task);
        remove = true;
      }
    }
    if (remove) {
      task.pending = false;
      if (!newTasks) {
        newTasks = tasks.slice(0, i);
      }
    } else {
      if (newTasks) {
        newTasks.push(task);
      }
      if (nextExpires > expires) {
        nextExpires = expires;
      }
    }
  }
  if (newTasks) {
    me.tasks = newTasks;
  }
  me.firing = false;
  if (me.tasks.length) {
    me.startTimer(nextExpires - now, Ext.Date.now());
  }
  if (fireIdleEvent === null) {
    fireIdleEvent = false;
  }
  Ext._suppressIdle = !fireIdleEvent;
}, startTimer:function(timeout, now) {
  var me = this, expires = now + timeout, timerId = me.timerId;
  if (timerId && me.nextExpires - expires > me.interval) {
    timerId = Ext.undefer(timerId);
  }
  if (!timerId) {
    if (timeout < me.interval) {
      timeout = me.interval;
    }
    me.timerId = Ext.defer(me.timerFn, timeout);
    me.nextExpires = expires;
    var timer = Ext.Timer.get(me.timerId);
    if (timer) {
      timer.runner = me;
    }
  }
}}, function() {
  var me = this, proto = me.prototype;
  proto.destroy = proto.stopAll;
  me.Task = new Ext.Class({isTask:true, stopped:true, fireOnStart:false, constructor:function(config) {
    Ext.apply(this, config);
  }, restart:function(interval) {
    if (interval !== undefined) {
      this.interval = interval;
    }
    this.manager.start(this);
  }, start:function(interval) {
    if (this.stopped) {
      this.restart(interval);
    }
  }, stop:function(andRemove) {
    this.manager.stop(this, andRemove);
  }, destroy:function() {
    this.stop(true);
  }});
  proto = me.Task.prototype;
  proto.destroy = proto.stop;
});
Ext.define('Ext.dom.Fly', {extend:Ext.dom.Element, alternateClassName:'Ext.dom.Element.Fly', validNodeTypes:{1:1, 9:1, 11:1}, isFly:true, constructor:function(dom) {
  this.dom = dom;
  this.el = this;
}, attach:function(dom) {
  var me = this, data;
  if (!dom) {
    return me.detach();
  }
  me.dom = Ext.getDom(dom);
  if (!Ext.cache[dom.id]) {
    data = me.peekData();
    if (data) {
      data.isSynchronized = false;
    }
  }
  return me;
}, detach:function() {
  return this.dom = null;
}, addListener:function() {
  Ext.raise('Cannot use addListener() on Ext.dom.Fly instances. ' + 'Please use Ext.get() to retrieve an Ext.dom.Element instance instead.');
} || null, removeListener:function() {
  Ext.raise('Cannot use removeListener() on Ext.dom.Fly instances. ' + 'Please use Ext.get() to retrieve an Ext.dom.Element instance instead.');
} || null}, function(Fly) {
  var flyweights = {}, detachedBodyEl;
  Fly.cache = flyweights;
  Ext.fly = function(dom, named) {
    var fly = null, fn = Ext.fly, nodeType, data;
    named = named || fn.caller && (fn.caller.$name || fn.caller.name) || '_global';
    dom = Ext.getDom(dom);
    if (dom) {
      nodeType = dom.nodeType;
      if (Fly.prototype.validNodeTypes[nodeType] || !nodeType && dom.window == dom) {
        fly = Ext.cache[dom.id];
        if (!fly || fly.dom !== dom) {
          if (named === 'constructor') {
            named = '$constructor';
          }
          fly = flyweights[named] || (flyweights[named] = new Fly);
          fly.dom = dom;
          data = fly.peekData();
          if (data) {
            data.isSynchronized = false;
          }
        }
      }
    }
    return fly;
  };
  Ext.getDetachedBody = function() {
    if (!detachedBodyEl) {
      Ext.detachedBodyEl = detachedBodyEl = new Fly(document.createElement('div'));
      detachedBodyEl.isDetachedBody = true;
    }
    return detachedBodyEl;
  };
});
Ext.define('Ext.dom.CompositeElementLite', {alternateClassName:['Ext.CompositeElementLite'], isComposite:true, isLite:true, statics:{importElementMethods:function() {
  var Element = Ext.dom.Element, prototype = this.prototype;
  Ext.Object.each(Element.prototype, function(name, member) {
    if (typeof member === 'function' && !prototype[name]) {
      prototype[name] = function() {
        return this.invoke(name, arguments);
      };
    }
  });
}}, constructor:function(elements, skipValidation) {
  if (skipValidation) {
    this.elements = elements || [];
  } else {
    this.elements = [];
    this.add(elements);
  }
}, getElement:function(el) {
  var fly = this._fly || (this._fly = new Ext.dom.Fly);
  return fly.attach(el);
}, transformElement:function(el) {
  return Ext.getDom(el);
}, getCount:function() {
  return this.elements.length;
}, add:function(els, root) {
  var elements = this.elements, i, ln;
  if (!els) {
    return this;
  }
  if (typeof els === 'string') {
    els = Ext.fly(root || document).query(els);
  } else {
    if (els.isComposite) {
      els = els.elements;
    } else {
      if (!Ext.isIterable(els)) {
        els = [els];
      }
    }
  }
  for (i = 0, ln = els.length; i < ln; ++i) {
    elements.push(this.transformElement(els[i]));
  }
  return this;
}, invoke:function(fn, args) {
  var me = this, elements = me.elements, ln = elements.length, prototype, element, i;
  if (i !== 0) {
    prototype = (me.isLite ? Ext.dom.Fly : Ext.dom.Element).prototype;
    for (i = 0; i < ln; i++) {
      element = elements[i];
      if (element) {
        prototype[fn].apply(me.getElement(element), args);
      }
    }
  }
  return me;
}, item:function(index) {
  var el = this.elements[index], out = null;
  if (el) {
    out = this.getElement(el);
  }
  return out;
}, slice:function(start, end) {
  return Ext.Array.slice(this.elements, start, end);
}, each:function(fn, scope) {
  var me = this, els = me.elements, len = els.length, i, e;
  for (i = 0; i < len; i++) {
    e = els[i];
    if (e) {
      e = this.getElement(e);
      if (fn.call(scope || e, e, me, i) === false) {
        break;
      }
    }
  }
  return me;
}, fill:function(els) {
  var me = this;
  me.elements = [];
  me.add(els);
  return me;
}, insert:function(index, nodes) {
  Ext.Array.insert(this.elements, index, nodes);
}, filter:function(selector) {
  var me = this, els = me.elements, len = els.length, out = [], i = 0, isFunc = typeof selector === 'function', add, el;
  for (; i < len; i++) {
    el = els[i];
    add = false;
    if (el) {
      el = me.getElement(el);
      if (isFunc) {
        add = selector.call(el, el, me, i) !== false;
      } else {
        add = el.is(selector);
      }
      if (add) {
        out.push(me.transformElement(el));
      }
    }
  }
  me.elements = out;
  return me;
}, indexOf:function(el) {
  return Ext.Array.indexOf(this.elements, this.transformElement(el));
}, replaceElement:function(el, replacement, domReplace) {
  var index = !isNaN(el) ? el : this.indexOf(el), d;
  if (index > -1) {
    replacement = Ext.getDom(replacement);
    if (domReplace) {
      d = this.elements[index];
      d.parentNode.insertBefore(replacement, d);
      Ext.removeNode(d);
    }
    Ext.Array.splice(this.elements, index, 1, replacement);
  }
  return this;
}, clear:function(removeDom) {
  var me = this, els = me.elements, i = els.length - 1;
  if (removeDom) {
    for (; i >= 0; i--) {
      Ext.removeNode(els[i]);
    }
  }
  this.elements = [];
}, addElements:function(els, root) {
  if (!els) {
    return this;
  }
  if (typeof els === 'string') {
    els = Ext.dom.Element.selectorFunction(els, root);
  }
  var yels = this.elements, eLen = els.length, e;
  for (e = 0; e < eLen; e++) {
    yels.push(Ext.get(els[e]));
  }
  return this;
}, first:function() {
  return this.item(0);
}, last:function() {
  return this.item(this.getCount() - 1);
}, contains:function(el) {
  return this.indexOf(el) !== -1;
}, removeElement:function(keys, removeDom) {
  var me = this, elements = me.elements, val, el, k, kLen;
  keys = [].concat(keys);
  for (k = 0, kLen = keys.length; k < kLen; k++) {
    val = keys[k];
    if (el = elements[val] || elements[val = me.indexOf(val)]) {
      if (removeDom) {
        if (el.dom) {
          el.destroy();
        } else {
          Ext.removeNode(el);
        }
      }
      Ext.Array.erase(elements, val, 1);
    }
  }
  return me;
}, destroy:function() {
  this.invoke('destroy', arguments);
  this.callParent();
}}, function(CompositeElementLite) {
  var prototype = CompositeElementLite.prototype;
  CompositeElementLite.importElementMethods();
  prototype.on = prototype.addListener;
});
Ext.define('Ext.dom.CompositeElement', {alternateClassName:'Ext.CompositeElement', extend:Ext.dom.CompositeElementLite, isLite:false, getElement:function(el) {
  return el;
}, transformElement:function(el) {
  return Ext.get(el);
}});
Ext.define('Ext.dom.GarbageCollector', {singleton:true, interval:30000, constructor:function() {
  var me = this;
  me.lastTime = Ext.now();
  me.onTick = me.onTick.bind(me);
  me.onTick.$skipTimerCheck = true;
  me.resume();
}, collect:function() {
  var me = this, cache = Ext.cache, eid, dom, el, t, isGarbage, tagName;
  var collectedIds = [];
  for (eid in cache) {
    if (!cache.hasOwnProperty(eid)) {
      continue;
    }
    el = cache[eid];
    if (el.skipGarbageCollection) {
      continue;
    }
    dom = el.dom;
    if (!dom) {
      Ext.raise('Missing DOM node in element garbage collection: ' + eid);
    }
    try {
      isGarbage = Ext.isGarbage(dom);
    } catch (e$60) {
      delete cache[eid];
      collectedIds.push('#' + el.id);
      continue;
    }
    if (isGarbage) {
      isGarbage = false;
      if (el && el.dom) {
        tagName = el.dom.tagName;
        el.collect();
        collectedIds.push((tagName ? tagName : '') + '#' + el.id);
      }
    }
  }
  if (Ext.isIE9m) {
    t = {};
    for (eid in cache) {
      if (cache.hasOwnProperty(eid)) {
        t[eid] = cache[eid];
      }
    }
    Ext.cache = Ext.dom.Element.cache = t;
  }
  me.lastTime = Ext.now();
  return collectedIds;
}, onTick:function() {
  this.timerId = null;
  if (Ext.enableGarbageCollector) {
    this.collect();
  }
  this.resume();
}, pause:function() {
  var timerId = this.timerId;
  if (timerId) {
    this.timerId = null;
    Ext.undefer(timerId);
  }
}, resume:function() {
  var me = this, lastTime = me.lastTime;
  if (Ext.enableGarbageCollector && Ext.now() - lastTime > me.interval) {
    me.collect();
  }
  if (!me.timerId) {
    me.timerId = Ext.defer(me.onTick, me.interval);
  }
}});
Ext.define('Ext.dom.TouchAction', {singleton:true, lastTouchStartTime:0, minMoveDistance:8, spaceRe:/\s+/, preventSingle:null, preventMulti:null, disabledOverflowDom:null, panXCls:Ext.baseCSSPrefix + 'touch-action-pan-x', panYCls:Ext.baseCSSPrefix + 'touch-action-pan-y', cssValues:['none', 'pan-x', 'pan-y', 'pan-x pan-y', 'pinch-zoom', 'pan-x pinch-zoom', 'pan-y pinch-zoom', 'pan-x pan-y pinch-zoom', 'double-tap-zoom', 'pan-x double-tap-zoom', 'pan-y double-tap-zoom', 'pan-x pan-y double-tap-zoom', 
'pinch-zoom double-tap-zoom', 'pan-x pinch-zoom double-tap-zoom', 'pan-y pinch-zoom double-tap-zoom', ''], objectValues:[{panX:false, panY:false, pinchZoom:false, doubleTapZoom:false}, {panX:true, panY:false, pinchZoom:false, doubleTapZoom:false}, {panX:false, panY:true, pinchZoom:false, doubleTapZoom:false}, {panX:true, panY:true, pinchZoom:false, doubleTapZoom:false}, {panX:false, panY:false, pinchZoom:true, doubleTapZoom:false}, {panX:true, panY:false, pinchZoom:true, doubleTapZoom:false}, {panX:false, 
panY:true, pinchZoom:true, doubleTapZoom:false}, {panX:true, panY:true, pinchZoom:true, doubleTapZoom:false}, {panX:false, panY:false, pinchZoom:false, doubleTapZoom:true}, {panX:true, panY:false, pinchZoom:false, doubleTapZoom:true}, {panX:false, panY:true, pinchZoom:false, doubleTapZoom:true}, {panX:true, panY:true, pinchZoom:false, doubleTapZoom:true}, {panX:false, panY:false, pinchZoom:true, doubleTapZoom:true}, {panX:true, panY:false, pinchZoom:true, doubleTapZoom:true}, {panX:false, panY:true, 
pinchZoom:true, doubleTapZoom:true}, {panX:true, panY:true, pinchZoom:true, doubleTapZoom:true}], attributeName:'data-extTouchAction', constructor:function() {
  var me = this, supports = Ext.supports;
  if (supports.TouchAction) {
    me.cssProp = 'touch-action';
  } else {
    if (supports.MSPointerEvents) {
      me.cssProp = '-ms-touch-action';
    }
  }
  if (supports.TouchEvents) {
    Ext.getWin().on({touchstart:'onTouchStart', touchmove:'onTouchMove', touchend:'onTouchEnd', scope:me, delegated:false, translate:false, capture:true, priority:5000});
    Ext.on({scroll:'onScroll', scope:me, destroyable:true});
  }
  if (Ext.isFunction(Object.freeze)) {
    var objectValues = me.objectValues, i, ln;
    for (i = 0, ln = objectValues.length; i < ln; i++) {
      Object.freeze(objectValues[i]);
    }
  }
}, containsTargets:function(dom, e) {
  var contains = true, event = e.browserEvent, touches = e.type === 'touchend' ? event.changedTouches : event.touches, i, ln;
  for (i = 0, ln = touches.length; i < ln; i++) {
    if (!dom.contains(touches[i].target)) {
      contains = false;
      break;
    }
  }
  return contains;
}, disableOverflow:function(dom, vertical) {
  var me = this, overflowName = vertical ? 'overflow-y' : 'overflow-x', overflowStyle, cls;
  if (!me.disabledOverflowDom && !Ext.isiOS && !Ext.scrollbar.width()) {
    me.disabledOverflowDom = dom;
    cls = vertical ? me.panXCls : me.panYCls;
    while (dom) {
      overflowStyle = Ext.fly(dom).getStyle(overflowName);
      if (overflowStyle === 'auto' || overflowStyle === 'scroll') {
        Ext.fly(dom).addCls(cls);
      }
      dom = dom.parentNode;
    }
  }
}, get:function(dom) {
  var flags = dom.getAttribute(this.attributeName), ret = null;
  if (flags != null) {
    ret = this.objectValues[flags];
  }
  return ret;
}, getFlags:function(touchAction) {
  var flags;
  if (typeof touchAction === 'number') {
    flags = touchAction;
  } else {
    flags = 0;
    if (touchAction.panX !== false) {
      flags |= 1;
    }
    if (touchAction.panY !== false) {
      flags |= 2;
    }
    if (touchAction.pinchZoom !== false) {
      flags |= 4;
    }
    if (touchAction.doubleTapZoom !== false) {
      flags |= 8;
    }
  }
  return flags;
}, isScrollable:function(el, vertical, forward) {
  var overflowStyle = Ext.fly(el).getStyle(vertical ? 'overflow-y' : 'overflow-x'), isScrollable = overflowStyle === 'auto' || overflowStyle === 'scroll';
  if (isScrollable) {
    if (vertical) {
      isScrollable = forward ? el.scrollTop + el.clientHeight < el.scrollHeight : el.scrollTop > 0;
    } else {
      isScrollable = forward ? el.scrollLeft + el.clientWidth < el.scrollWidth : el.scrollLeft > 0;
    }
  }
  return isScrollable;
}, lookupFlags:function(dom) {
  return parseInt(dom.getAttribute && dom.getAttribute(this.attributeName) || 15, 10);
}, onScroll:function() {
  this.scrollOccurred = true;
  this.isDoubleTap = false;
}, onTouchEnd:function(e) {
  var me = this, dom = e.target, touchCount, flags, doubleTapZoom;
  touchCount = e.browserEvent.touches.length;
  if (touchCount === 0) {
    if (me.isDoubleTap) {
      while (dom) {
        flags = me.lookupFlags(dom);
        if (flags != null) {
          doubleTapZoom = flags & 8;
          if (!doubleTapZoom) {
            e.preventDefault();
          }
        }
        dom = dom.parentNode;
      }
    }
    me.isDoubleTap = false;
    me.preventSingle = null;
    me.preventMulti = null;
    me.resetOverflow();
  }
}, onTouchMove:function(e) {
  var me = this, prevent = null, dom = e.target, flags, touchCount, panX, panY, point, startPoint, isVertical, scale, distance, deltaX, deltaY, preventSingle, preventMulti;
  preventSingle = me.preventSingle;
  preventMulti = me.preventMulti;
  touchCount = e.browserEvent.touches.length;
  if (touchCount === 1 && preventSingle === false || preventMulti === false) {
    return;
  }
  if (touchCount > 1 && preventMulti === true || touchCount === 1 && preventSingle === true) {
    prevent = true;
  } else {
    if (touchCount === 1) {
      point = e.getPoint();
      startPoint = me.startPoint;
      scale = Ext.Element.getViewportScale();
      distance = point.getDistanceTo(me.startPoint) * scale;
      deltaX = point.x - startPoint.x;
      deltaY = point.y - startPoint.y;
      isVertical = Math.abs(deltaY) >= Math.abs(deltaX);
    }
    while (dom && dom.nodeType === 1) {
      flags = me.lookupFlags(dom);
      if (flags & 0) {
        prevent = true;
      } else {
        if (touchCount === 1) {
          panX = !!(flags & 1);
          panY = !!(flags & 2);
          if (panX && panY) {
            prevent = false;
          } else {
            if (!panX && !panY) {
              prevent = true;
            } else {
              if (distance >= me.minMoveDistance) {
                prevent = !!(panX && isVertical || panY && !isVertical);
              }
            }
          }
          if (!prevent && me.isScrollable(dom, isVertical, (isVertical ? deltaY : deltaX) < 0)) {
            break;
          }
        } else {
          if (me.containsTargets(dom, e)) {
            prevent = !(flags & 4);
          } else {
            prevent = false;
          }
        }
      }
      if (prevent) {
        break;
      }
      dom = dom.parentNode;
    }
  }
  if (touchCount === 1) {
    me.preventSingle = prevent;
  } else {
    if (touchCount > 1) {
      me.preventMulti = prevent;
    }
  }
  if (prevent) {
    e.preventDefault();
  }
}, onTouchStart:function(e) {
  var me = this, time, flags, dom, panX, panY;
  if (e.browserEvent.touches.length === 1) {
    time = e.time;
    if (!me.scrollOccurred && time - me.lastTouchStartTime <= 500) {
      me.isDoubleTap = true;
    }
    me.lastTouchStartTime = time;
    me.scrollOccurred = false;
    me.startPoint = e.getPoint();
    dom = e.target;
    while (dom) {
      flags = me.lookupFlags(dom);
      if (flags != null) {
        panX = !!(flags & 1);
        panY = !!(flags & 2);
        if (panX !== panY) {
          me.disableOverflow(dom, panX);
          break;
        }
      }
      dom = dom.parentNode;
    }
  } else {
    me.isDoubleTap = false;
  }
}, resetOverflow:function() {
  var me = this, dom = me.disabledOverflowDom;
  while (dom) {
    Ext.fly(dom).removeCls([me.panXCls, me.panYCls]);
    dom = dom.parentNode;
  }
  me.disabledOverflowDom = null;
}, set:function(dom, value) {
  var me = this, cssProp = me.cssProp, flags = me.getFlags(value), supportedFlags = flags & Ext.supports.TouchAction, attributeName = me.attributeName;
  if (cssProp) {
    Ext.fly(dom).setStyle(cssProp, me.cssValues[supportedFlags]);
  }
  if (flags === 15) {
    dom.removeAttribute(attributeName);
  } else {
    dom.setAttribute(attributeName, flags);
  }
}});
Ext.define('Ext.drag.Constraint', {alias:'drag.constraint.base', mixins:[Ext.mixin.Factoryable], factoryConfig:{defaultType:'base', type:'drag.constraint'}, config:{element:null, horizontal:null, region:null, snap:null, source:null, vertical:null, x:null, y:null}, constructor:function(config) {
  this.initConfig(config);
}, applyElement:function(element) {
  if (element && typeof element !== 'boolean') {
    element = Ext.get(element);
  }
  return element || null;
}, applySnap:function(snap) {
  if (typeof snap === 'number') {
    snap = {x:snap, y:snap};
  }
  return snap;
}, constrain:function(xy, info) {
  var me = this, x = xy[0], y = xy[1], constrainInfo = me.constrainInfo, initial = constrainInfo.initial, constrainX = constrainInfo.x, constrainY = constrainInfo.y, snap = constrainInfo.snap, min, max;
  if (!constrainInfo.vertical) {
    if (snap && snap.x) {
      if (snap.xFn) {
        x = snap.x.call(me, info, x);
      } else {
        x = me.doSnap(x, initial.x, snap.x);
      }
    }
    if (constrainX) {
      min = constrainX[0];
      max = constrainX[1];
      if (min !== null && x < min) {
        x = min;
      }
      if (max !== null && x > max) {
        x = max;
      }
    }
  } else {
    x = initial.x;
  }
  if (!constrainInfo.horizontal) {
    if (snap && snap.y) {
      if (snap.yFn) {
        y = snap.y.call(me, info, y);
      } else {
        y = me.doSnap(y, initial.y, snap.y);
      }
    }
    if (constrainY) {
      min = constrainY[0];
      max = constrainY[1];
      if (min !== null && y < min) {
        y = min;
      }
      if (max !== null && y > max) {
        y = max;
      }
    }
  } else {
    y = initial.y;
  }
  return [x, y];
}, destroy:function() {
  this.setSource(null);
  this.setElement(null);
  this.callParent();
}, privates:{constrainValue:function(a, b, resolver) {
  var val = null, aNull = a === null, bNull = b === null;
  if (!(aNull && bNull)) {
    if (aNull) {
      val = b;
    } else {
      if (bNull) {
        val = a;
      } else {
        val = resolver(a, b);
      }
    }
  }
  return val;
}, doSnap:function(position, initial, snap) {
  if (!snap) {
    return position;
  }
  var ratio = (position - initial) / snap, floor = Math.floor(ratio);
  if (ratio - floor <= 0.5) {
    ratio = floor;
  } else {
    ratio = floor + 1;
  }
  return initial + snap * ratio;
}, onDragStart:function(info) {
  var me = this, snap = me.getSnap(), vertical = !!me.getVertical(), horizontal = !!me.getHorizontal(), element = me.getElement(), region = me.getRegion(), proxy = info.proxy, proxyEl = proxy.element, x = me.getX(), y = me.getY(), minX = null, maxX = null, minY = null, maxY = null, rminX = null, rmaxX = null, rminY = null, rmaxY = null, pos, size;
  if (element) {
    if (typeof element === 'boolean') {
      element = me.getSource().getElement().parent();
    }
    if (info.local) {
      pos = element.getStyle('position');
      if (pos === 'relative' || pos === 'absolute') {
        size = element.getSize();
        region = new Ext.util.Region(0, size.width, size.height, 0);
      } else {
        region = element.getRegion(true, true);
      }
    } else {
      region = element.getRegion(true);
    }
  }
  if (region) {
    if (!vertical) {
      rminX = region.left;
      rmaxX = region.right - (proxyEl ? proxy.width : 0);
    }
    if (!horizontal) {
      rminY = region.top;
      rmaxY = region.bottom - (proxyEl ? proxy.height : 0);
    }
  }
  if (!vertical && (region || x)) {
    if (x) {
      minX = x[0];
      maxX = x[1];
    }
    if (minX !== null || maxX !== null || rminX !== null || rmaxX !== null) {
      minX = me.constrainValue(minX, rminX, Math.max);
      maxX = me.constrainValue(maxX, rmaxX, Math.min);
      x = [minX, maxX];
    }
  }
  if (!horizontal && (region || y)) {
    if (y) {
      minY = y[0];
      maxY = y[1];
    }
    if (minY !== null || maxY !== null || rminY !== null || rmaxY !== null) {
      minY = me.constrainValue(minY, rminY, Math.max);
      maxY = me.constrainValue(maxY, rmaxY, Math.min);
      y = [minY, maxY];
    }
  }
  if (snap) {
    snap = {x:snap.x, xFn:typeof snap.x === 'function', y:snap.y, yFn:typeof snap.y === 'function'};
  }
  me.constrainInfo = {initial:info.element.initial, vertical:vertical, horizontal:horizontal, x:x, y:y, snap:snap};
}}});
Ext.define('Ext.drag.Info', {constructor:function(source, e) {
  if (!source) {
    return;
  }
  var me = this, local = source.getLocal(), el, proxyEl, proxy, x, xy, y, pageXY, elPageXY;
  me.source = source;
  me.local = local;
  xy = me.getEventXY(e);
  pageXY = e.getXY();
  el = source.getElement();
  elPageXY = el.getXY();
  xy = local ? el.getLocalXY() : elPageXY;
  x = xy[0];
  y = xy[1];
  me.initialEvent = e;
  me.eventTarget = e.target;
  me.cursor = {current:{x:x, y:y}, delta:{x:0, y:0}, initial:{x:pageXY[0], y:pageXY[1]}, offset:{x:pageXY[0] - elPageXY[0], y:pageXY[1] - elPageXY[1]}};
  me.element = {current:{x:x, y:y}, delta:{x:0, y:0}, initial:{x:x, y:y}};
  me.proxy = {instance:source.getProxy(), current:{x:x, y:y}, delta:{x:0, y:0}, initial:{x:x, y:y}, element:el, isUnderCursor:false, isElement:true};
  me.types = [];
  me.data = {};
  source.describe(me);
  proxy = me.proxy;
  proxyEl = proxy.instance.setupElement(me);
  proxy.isElement = proxyEl === source.getElement();
  proxy.element = proxyEl;
  if (proxyEl) {
    proxy.width = proxyEl.getWidth();
    proxy.height = proxyEl.getHeight();
  }
  if (proxy.isElement) {
    el = me.element;
    el.current = proxy.current;
    el.delta = proxy.delta;
  }
  me.needsCursorCheck = proxy.element && source.manager && source.manager.pointerBug;
}, cursor:null, element:null, eventTarget:null, files:null, isNative:false, proxy:null, source:null, target:null, types:null, valid:false, clearData:function(type) {
  Ext.Array.remove(this.types, type);
  delete this.data[type];
}, clone:function() {
  var me = this, ret = new Ext.drag.Info;
  ret.cursor = Ext.merge({}, me.cursor);
  ret.data = Ext.apply({}, me.data);
  ret.element = Ext.merge({}, me.element);
  ret.eventTarget = me.eventTarget;
  ret.proxy = Ext.merge({}, me.proxy);
  ret.source = me.source;
  ret.target = me.target;
  ret.types = Ext.Array.clone(me.types);
  ret.valid = me.valid;
  return ret;
}, getData:function(type) {
  var me = this, data = me.data, dt = me.dataTransfer, ret;
  if (dt) {
    ret = dt.getData(type);
  } else {
    if (!me.finalized) {
      Ext.raise('Unable to call getData until the drop is complete');
    }
    ret = data[type];
    if (typeof ret === 'function') {
      data[type] = ret = ret.call(me.source, me);
    }
    if (!ret && ret !== 0) {
      ret = '';
    }
  }
  return Ext.Promise.resolve(ret);
}, setData:function(type, value) {
  Ext.Array.include(this.types, type);
  this.data[type] = value;
}, destroy:function() {
  var me = this;
  me.eventTarget = me.data = me.proxy = me.targetMap = me.targetMap = me.types = me.elementMap = me.possibleTargets = me.target = null;
  me.callParent();
}, privates:{data:null, dataTransfer:null, elementMap:null, possibleTargets:null, targetMap:null, copyNativeData:function(target, e) {
  var dt = e.browserEvent.dataTransfer;
  this.target = target;
  this.dataTransfer = dt;
  this.files = dt.files;
}, finalize:function() {
  var me = this, target = me.target;
  me.finalized = true;
  if (target) {
    target.info = null;
    target.handleDrop(me);
  }
}, getAlignXY:function(x, y) {
  var me = this, source = me.source, cursorOffset = me.cursor.offset, proxy = source.getProxy(), proxyEl = me.proxy.element, constrain = source.getConstrain(), xy = [x, y];
  if (proxyEl) {
    if (me.proxy.isElement) {
      xy[0] -= cursorOffset.x;
      xy[1] -= cursorOffset.y;
    } else {
      xy = proxy.adjustCursorOffset(me, xy);
    }
    if (constrain) {
      xy = constrain.constrain(xy, me);
    }
  }
  return xy;
}, getEventXY:function(e) {
  var xy = e.getXY(), source = this.source;
  if (this.local) {
    xy = source.convertToLocalXY(xy);
  }
  return xy;
}, onNativeDragEnter:function(target, e) {
  var me = this;
  me.valid = target.accepts(me);
  target.info = me;
  me.copyNativeData(target, e);
}, onNativeDragLeave:function(target, e) {
  var me = this;
  if (me.target === target) {
    target.info = null;
    me.valid = false;
    me.target = me.dataTransfer = me.files = null;
  }
}, onNativeDragMove:function(target, e) {
  this.copyNativeData(target, e);
}, onNativeDrop:function(target, e) {
  this.copyNativeData(target, e);
  target.info = null;
}, setActive:function(target) {
  var me = this, source = me.source, current = me.target, changed = current !== target;
  if (current && changed) {
    current.handleDragLeave(me);
    current.info = null;
  }
  me.target = target;
  if (target) {
    if (changed) {
      me.valid = !!me.possibleTargets[target.getId()] && target.accepts(me) !== false;
      target.handleDragEnter(me);
      target.info = me;
    }
    target.handleDragMove(me);
  } else {
    me.valid = false;
  }
  if (changed) {
    source.getProxy().update(me);
  }
}, update:function(event, beforeStart) {
  var me = this, xy = me.getEventXY(event), x = xy[0], y = xy[1], alignXY = me.getAlignXY(x, y), alignX = alignXY[0], alignY = alignXY[1], proxyData = me.proxy, cursor = me.cursor, current = cursor.current, delta = cursor.delta, initial = cursor.initial, proxy = proxyData.instance;
  current.x = x;
  current.y = y;
  delta.x = x - initial.x;
  delta.y = y - initial.y;
  current = proxyData.current;
  delta = proxyData.delta;
  initial = proxyData.initial;
  current.x = alignX;
  current.y = alignY;
  delta.x = alignX - initial.x;
  delta.y = alignY - initial.y;
  if (me.needsCursorCheck) {
    proxyData.isUnderCursor = !(x < alignX || y < alignY || x > proxyData.width + alignX || y > proxyData.height + alignY);
  }
  if (!beforeStart && proxy) {
    proxy.setXY(me, alignXY);
  }
}}});
Ext.define('Ext.drag.Item', {mixins:[Ext.mixin.Observable, Ext.mixin.Identifiable], config:{autoDestroy:true, component:null, element:null, groups:null}, constructor:function(config) {
  this.mixins.observable.constructor.call(this, config);
}, isDisabled:function() {
  return this.disabled;
}, disable:function() {
  this.disabled = true;
}, enable:function() {
  this.disabled = false;
}, updateComponent:function(comp, was) {
  var el;
  if (comp) {
    el = comp.el;
  } else {
    if (was && was.el === this.getElement()) {
      el = null;
    } else {
      return;
    }
  }
  this.setElement(el);
}, applyElement:function(element) {
  return element ? Ext.get(element) : null;
}, updateElement:function() {
  this.setupListeners();
}, applyGroups:function(group) {
  if (typeof group === 'string') {
    group = [group];
  }
  return group;
}, destroy:function() {
  var me = this, el = me.getElement();
  me.destroying = true;
  me.setElement(null);
  if (el && me.getAutoDestroy()) {
    el.destroy();
  }
  me.callParent();
}, privates:{disabled:false, convertToLocalXY:function(xy) {
  var c = this.getComponent();
  if (c) {
    xy = c.convertToLocalXY(xy);
  } else {
    xy = this.getElement().translateXY(xy[0], xy[1]);
    xy = [xy.x, xy.y];
  }
  return xy;
}, getElListeners:Ext.privateFn, setupListeners:function(element) {
  var me = this, elListeners = me.elListeners;
  element = element || me.getElement();
  if (elListeners) {
    elListeners.destroy();
    me.elListeners = null;
  }
  if (element) {
    me.elListeners = element.on(Ext.apply({scope:me, destroyable:true}, me.getElListeners()));
  }
}}});
Ext.define('Ext.drag.Manager', {singleton:true, dragCls:Ext.baseCSSPrefix + 'drag-body', pointerBug:Ext.isTouch || (!Ext.supports.CSSPointerEvents || Ext.isIE10m || Ext.isOpera), constructor:function() {
  this.targets = {};
  this.nativeTargets = [];
  Ext.onReady(this.init, this);
}, init:function() {
  Ext.getDoc().on({scope:this, dragenter:{capture:true, fn:'onNativeDragEnter'}, dragleave:'onNativeDragLeave', dragover:'onNativeDragOver', drop:'onNativeDrop'});
}, destroy:function() {
  var me = this, targets = me.targets, key;
  me.destroying = true;
  for (key in targets) {
    targets[key].destroy();
  }
  me.targets = null;
  me.callParent();
}, privates:{elementFromPoint:function(x, y) {
  if (Ext.rootInheritedState.rtl) {
    x = Ext.Element.getViewportWidth() - x;
  }
  return Ext.dom.Element.fromPagePoint(x, y, true);
}, getAtPoint:function(info) {
  var current = info.cursor.current, elementMap = info.elementMap, isUnderCursor = info.proxy.isUnderCursor, proxyEl = this.pointerBug && isUnderCursor ? info.proxy.element.dom : null, target, el;
  if (proxyEl) {
    proxyEl.style.visibility = 'hidden';
  }
  el = this.elementFromPoint(current.x, current.y);
  if (proxyEl) {
    proxyEl.style.visibility = 'visible';
  }
  while (el) {
    target = elementMap[el.id];
    if (target) {
      return target;
    }
    el = el.parentNode;
  }
  return null;
}, getNativeDragInfo:function(e) {
  var info = this.nativeDragInfo;
  if (!info) {
    this.nativeDragInfo = info = new Ext.drag.Info;
    info.isNative = true;
  }
  return info;
}, onDragCancel:function() {
  Ext.getBody().removeCls(this.dragCls);
}, onDragEnd:function(info, e) {
  info.finalize();
  Ext.getBody().removeCls(this.dragCls);
}, onDragMove:function(info, e) {
  this.processDrag(info);
}, onDragStart:function(info, e) {
  var me = this, source = info.source, targets = me.targets, groups = source.getGroups(), targetMap = {}, possibleTargets = {}, elementMap = {}, id, target, targetGroups, groupMap, groupOk, len, i;
  elementMap = {};
  possibleTargets = {};
  if (groups) {
    groupMap = Ext.Array.toMap(groups);
  }
  for (id in targets) {
    target = targets[id];
    if (!target.isDisabled()) {
      groupOk = false;
      targetGroups = target.getGroups();
      if (!groupMap && !targetGroups) {
        groupOk = true;
      } else {
        if (groupMap && targetGroups) {
          for (i = 0, len = targetGroups.length; i < len; ++i) {
            if (groupMap[targetGroups[i]]) {
              groupOk = true;
              break;
            }
          }
        }
      }
      if (groupOk) {
        possibleTargets[id] = target;
      }
    }
    targetMap[id] = target;
    elementMap[target.getElement().id] = target;
  }
  info.possibleTargets = possibleTargets;
  info.targetMap = targetMap;
  info.elementMap = elementMap;
  Ext.getBody().addCls(me.dragCls);
  me.processDrag(info);
}, onNativeDragEnter:function(e) {
  var nativeTargets = this.nativeTargets, target = e.target;
  e.preventDefault();
  if (nativeTargets[nativeTargets.length - 1] !== target) {
    nativeTargets.push(target);
  }
}, onNativeDragLeave:function(e) {
  var nativeTargets = this.nativeTargets;
  Ext.Array.remove(nativeTargets, e.target);
  if (nativeTargets.length === 0) {
    this.nativeDragInfo = null;
  }
}, onNativeDragOver:function(e) {
  e.preventDefault();
}, onNativeDrop:function(e) {
  e.preventDefault();
  this.nativeTargets.length = 0;
  this.nativeDragInfo = null;
}, processDrag:function(info) {
  info.setActive(this.getAtPoint(info));
}, register:function(target) {
  this.targets[target.getId()] = target;
}, unregister:function(target) {
  var id;
  if (this.destroying) {
    return;
  }
  id = target.getId();
  this.targets[id] = null;
  delete this.targets[id];
}}});
Ext.define('Ext.drag.Source', {extend:Ext.drag.Item, defaultIdPrefix:'source-', config:{activateOnLongPress:false, activeCls:null, constrain:null, handle:null, local:null, proxy:'original', revert:false}, dragging:false, constructor:function(config) {
  var describe = config && config.describe;
  if (describe) {
    this.describe = describe;
    config = Ext.apply({}, config);
    delete config.describe;
  }
  this.callParent([config]);
  this.manager = Ext.drag['Manager'];
}, describe:Ext.emptyFn, isDragging:function() {
  return this.dragging;
}, beforeDragStart:Ext.emptyFn, onDragCancel:Ext.emptyFn, onDragEnd:Ext.emptyFn, onDragMove:Ext.emptyFn, onDragStart:Ext.emptyFn, applyActivateOnLongPress:function(activateOnLongPress) {
  if (typeof activateOnLongPress === 'string') {
    activateOnLongPress = [activateOnLongPress];
  }
  return activateOnLongPress;
}, updateActivateOnLongPress:function(activateOnLongPress) {
  if (!this.isConfiguring) {
    this.setupListeners();
  }
}, updateActiveCls:function(cls, oldCls) {
  var el;
  if (this.dragging) {
    el = this.getElement();
    el.replaceCls(oldCls, cls);
  }
}, applyConstrain:function(constrain) {
  if (constrain && !constrain.$isClass) {
    if (constrain.isRegion) {
      constrain = {region:constrain};
    } else {
      if (constrain.isElement || !Ext.isObject(constrain)) {
        constrain = {element:constrain};
      }
    }
    constrain = Ext.apply({source:this}, constrain);
    constrain = Ext.Factory.dragConstraint(constrain);
  }
  return constrain;
}, updateElement:function(element, oldElement) {
  if (oldElement && !oldElement.destroyed) {
    oldElement.un('dragstart', 'stopNativeDrag', this);
  }
  if (element && !this.getHandle()) {
    element.setTouchAction({panX:false, panY:false});
    element.on('dragstart', 'stopNativeDrag', this, {translate:false, delegated:false});
  }
  this.callParent([element, oldElement]);
}, updateHandle:function() {
  if (!this.isConfiguring) {
    this.setupListeners();
  }
}, applyProxy:function(proxy) {
  if (proxy) {
    proxy = Ext.Factory.dragproxy(proxy);
  }
  return proxy;
}, updateProxy:function(proxy, oldProxy) {
  if (oldProxy) {
    oldProxy.destroy();
  }
  if (proxy) {
    proxy.setSource(this);
  }
}, resolveListenerScope:function() {
  var ownerCmp = this.ownerCmp, a = arguments;
  if (ownerCmp) {
    return ownerCmp.resolveListenerScope.apply(ownerCmp, a);
  }
  return this.callParent(a);
}, destroy:function() {
  var me = this;
  me.manager = me.initialEvent = null;
  me.setConstrain(null);
  me.setProxy(null);
  me.callParent();
}, privates:{draggingCls:Ext.baseCSSPrefix + 'drag-dragging', info:null, revertCls:Ext.baseCSSPrefix + 'drag-revert', canActivateOnLongPress:function(e) {
  var activate = this.getActivateOnLongPress();
  return !!(activate && (activate === true || Ext.Array.contains(activate, e.pointerType)));
}, dragCleanup:function(info) {
  var me = this, cls = me.getActiveCls(), proxy = me.getProxy(), el = me.getElement(), proxyEl = info ? info.proxy.element : null;
  if (cls) {
    el.removeCls(cls);
  }
  if (proxyEl) {
    proxyEl.removeCls(me.draggingCls);
  }
  proxy.cleanup(info);
  me.dragging = false;
  me.initialEvent = me.info = null;
}, getElListeners:function() {
  var handle = this.getHandle(), o = {touchstart:'handleTouchStart', dragstart:'handleDragStart', drag:'handleDragMove', dragend:'handleDragEnd', dragcancel:'handleDragCancel'};
  if (handle) {
    o.dragstart = {fn:o.dragstart, delegate:handle};
  }
  if (this.getActivateOnLongPress()) {
    o.longpress = 'handleLongPress';
  }
  return o;
}, handleDragCancel:function(e) {
  var me = this, info = me.info, manager = me.manager;
  if (manager) {
    manager.onDragCancel(info, e);
  }
  me.onDragCancel(info);
  if (me.hasListeners.dragcancel) {
    me.fireEvent('dragcancel', me, info, e);
  }
  Ext.fireEvent('dragcancel', me, info, e);
  me.dragCleanup(info);
}, handleDragEnd:function(e) {
  if (!this.dragging) {
    return;
  }
  var me = this, manager = me.manager, revert = me.getRevert(), info = me.info, proxy = info.proxy;
  info.update(e);
  if (manager) {
    manager.onDragEnd(info, e);
  }
  me.onDragEnd(info);
  if (me.hasListeners.dragend) {
    me.fireEvent('dragend', me, info, e);
  }
  Ext.fireEvent('dragend', me, info, e);
  proxy = proxy.instance;
  if (revert && proxy) {
    proxy.dragRevert(info, me.revertCls, revert, function() {
      me.dragCleanup(info);
    });
  } else {
    me.dragCleanup(info);
  }
}, handleDragMove:function(e) {
  var me = this, info = me.info, manager = me.manager;
  if (!me.dragging) {
    return;
  }
  e.stopPropagation();
  e.claimGesture();
  info.update(e);
  if (manager) {
    manager.onDragMove(info, e);
  }
  me.onDragMove(info);
  if (me.hasListeners.dragmove) {
    me.fireEvent('dragmove', me, info, e);
  }
}, handleDragStart:function(e) {
  var me = this, hasListeners = me.hasListeners, manager = me.manager, constrain = me.getConstrain(), initialEvent = me.initialEvent, el, cls, info, cancel, proxyEl;
  if (me.preventStart(e)) {
    return false;
  }
  if (hasListeners.initdragconstraints) {
    me.fireEvent('initdragconstraints', me, e);
  }
  me.info = info = new Ext.drag.Info(me, initialEvent);
  me.setup(info);
  if (constrain) {
    constrain.onDragStart(info);
  }
  info.update(e, true);
  cancel = me.beforeDragStart(info) === false;
  if (!cancel && hasListeners.beforedragstart) {
    cancel = me.fireEvent('beforedragstart', me, info, e) === false;
  }
  if (cancel) {
    me.dragCleanup();
    return false;
  }
  e.claimGesture();
  me.dragging = true;
  cls = me.getActiveCls();
  el = me.getElement();
  if (cls) {
    el.addCls(cls);
  }
  proxyEl = info.proxy.element;
  if (proxyEl) {
    proxyEl.addCls(me.draggingCls);
  }
  info.update(e);
  if (manager) {
    manager.onDragStart(info, e);
  }
  me.onDragStart(info);
  if (hasListeners.dragstart) {
    me.fireEvent('dragstart', me, info, e);
  }
  Ext.fireEvent('dragstart', me, info, e);
}, handleLongPress:function(e) {
  if (!this.isDisabled() && this.canActivateOnLongPress(e)) {
    this.initialEvent = e;
    e.startDrag();
  }
}, handleTouchStart:function(e) {
  if (!this.isDisabled()) {
    this.initialEvent = e;
  }
}, preventStart:function(e) {
  return this.isDisabled() || !e.longpress && this.canActivateOnLongPress(e);
}, setup:Ext.privateFn, stopNativeDrag:function(e) {
  e.preventDefault();
}}});
Ext.define('Ext.drag.Target', {extend:Ext.drag.Item, defaultIdPrefix:'target-', config:{invalidCls:'', validCls:''}, constructor:function(config) {
  var me = this, accepts = config && config.accepts;
  if (accepts) {
    me.accepts = accepts;
    config = Ext.apply({}, config);
    delete config.accepts;
  }
  me.callParent([config]);
  Ext.drag.Manager.register(me);
}, accepts:function(info) {
  return true;
}, disable:function() {
  this.callParent();
  this.setupListeners(null);
}, enable:function() {
  this.callParent();
  this.setupListeners();
}, beforeDrop:Ext.emptyFn, onDrop:Ext.emptyFn, onDragEnter:Ext.emptyFn, onDragLeave:Ext.emptyFn, onDragMove:Ext.emptyFn, updateInvalidCls:function(invalidCls, oldInvalidCls) {
  var info = this.info;
  this.doUpdateCls(info && !info.valid, invalidCls, oldInvalidCls);
}, updateValidCls:function(validCls, oldValidCls) {
  var info = this.info;
  this.doUpdateCls(info && info.valid, validCls, oldValidCls);
}, destroy:function() {
  Ext.drag.Manager.unregister(this);
  this.callParent();
}, privates:{doUpdateCls:function(needsAdd, cls, oldCls) {
  var el = this.getElement();
  if (oldCls) {
    el.removeCls(oldCls);
  }
  if (cls && needsAdd) {
    el.addCls(cls);
  }
}, getElListeners:function() {
  return {dragenter:'handleNativeDragEnter', dragleave:'handleNativeDragLeave', dragover:'handleNativeDragMove', drop:'handleNativeDrop'};
}, handleDrop:function(info) {
  var me = this, hasListeners = me.hasListeners, valid = info.valid;
  me.getElement().removeCls([me.getInvalidCls(), me.getValidCls()]);
  if (valid && me.beforeDrop(info) !== false) {
    if (hasListeners.beforedrop && me.fireEvent('beforedrop', me, info) === false) {
      return false;
    }
    me.onDrop(info);
    if (hasListeners.drop) {
      me.fireEvent('drop', me, info);
    }
  } else {
    return false;
  }
}, handleDragEnter:function(info) {
  var me = this, cls = info.valid ? me.getValidCls() : me.getInvalidCls();
  if (cls) {
    me.getElement().addCls(cls);
  }
  me.onDragEnter(info);
  if (me.hasListeners.dragenter) {
    me.fireEvent('dragenter', me, info);
  }
}, handleDragLeave:function(info) {
  var me = this;
  me.getElement().removeCls([me.getInvalidCls(), me.getValidCls()]);
  me.onDragLeave(info);
  if (me.hasListeners.dragleave) {
    me.fireEvent('dragleave', me, info);
  }
}, handleDragMove:function(info) {
  var me = this;
  me.onDragMove(info);
  if (me.hasListeners.dragmove) {
    me.fireEvent('dragmove', me, info);
  }
}, handleNativeDragEnter:function(e) {
  var me = this, info = Ext.drag.Manager.getNativeDragInfo(e);
  info.onNativeDragEnter(me, e);
  if (me.hasListeners.dragenter) {
    me.fireEvent('dragenter', me, info);
  }
}, handleNativeDragLeave:function(e) {
  var me = this, info = Ext.drag.Manager.getNativeDragInfo(e);
  info.onNativeDragLeave(me, e);
  if (me.hasListeners.dragleave) {
    me.fireEvent('dragleave', me, info);
  }
}, handleNativeDragMove:function(e) {
  var me = this, info = Ext.drag.Manager.getNativeDragInfo(e);
  info.onNativeDragMove(me, e);
  if (me.hasListeners.dragmove) {
    me.fireEvent('dragmove', me, info);
  }
}, handleNativeDrop:function(e) {
  var me = this, hasListeners = me.hasListeners, info = Ext.drag.Manager.getNativeDragInfo(e), valid = info.valid;
  info.onNativeDrop(me, e);
  if (valid) {
    if (hasListeners.beforedrop && me.fireEvent('beforedrop', me, info) === false) {
      return;
    }
    if (hasListeners.drop) {
      me.fireEvent('drop', me, info);
    }
  }
}}});
Ext.define('Ext.drag.proxy.None', {mixins:[Ext.mixin.Factoryable], alias:'drag.proxy.none', factoryConfig:{aliasPrefix:'drag.proxy.', type:'dragproxy'}, config:{source:null}, constructor:function(config) {
  var getElement = config && config.getElement;
  if (getElement) {
    this.getElement = getElement;
    config = Ext.apply({}, config);
    delete config.getElement;
  }
  this.initConfig(config);
}, cleanup:Ext.emptyFn, dragRevert:function(info, revertCls, options, callback) {
  var positionable = this.getPositionable(info), initial = info.proxy.initial;
  positionable.addCls(revertCls);
  positionable.setXY([initial.x, initial.y], Ext.apply({callback:function() {
    positionable.removeCls(revertCls);
    callback();
  }}, options));
}, getElement:function() {
  return null;
}, getPositionable:function() {
  return this.element;
}, setXY:function(info, xy, animation) {
  var positionable = this.getPositionable(info);
  if (positionable) {
    positionable.setXY(xy, animation);
  }
}, update:Ext.emptyFn, privates:{setupElement:function(info) {
  return this.element = this.getElement(info);
}, adjustCursorOffset:function(info, pos) {
  return pos;
}}});
Ext.define('Ext.drag.proxy.Original', {extend:Ext.drag.proxy.None, alias:'drag.proxy.original', getElement:function(info) {
  return info.source.getElement();
}, getPositionable:function(info) {
  var source = info.source;
  return source.getComponent() || source.getElement();
}});
Ext.define('Ext.drag.proxy.Placeholder', {extend:Ext.drag.proxy.None, alias:'drag.proxy.placeholder', config:{cls:'', cursorOffset:[12, 20], html:null, invalidCls:'', validCls:''}, placeholderCls:Ext.baseCSSPrefix + 'drag-proxy-placeholder', cleanup:function() {
  this.element = Ext.destroy(this.element);
}, getElement:function() {
  var el = Ext.getBody().createChild({cls:this.getCls(), html:this.getHtml()});
  el.addCls(this.placeholderCls);
  el.setTouchAction({panX:false, panY:false});
  return el;
}, update:function(info) {
  var el = this.element, invalidCls = this.getInvalidCls(), validCls = this.getValidCls(), valid = info.valid;
  if (info.target) {
    el.replaceCls(valid ? invalidCls : validCls, valid ? validCls : invalidCls);
  } else {
    el.removeCls([invalidCls, validCls]);
  }
}, updateCls:function(cls, oldCls) {
  var el = this.element;
  if (el) {
    if (oldCls) {
      el.removeCls(oldCls);
    }
    if (cls) {
      el.addCls(cls);
    }
  }
}, updateHtml:function(html) {
  var el = this.element;
  if (el) {
    el.setHtml(html || '');
  }
}, updateInvalidCls:function(invalidCls, oldInvalidCls) {
  this.doUpdateCls(invalidCls, oldInvalidCls);
}, updateValidCls:function(validCls, oldValidCls) {
  this.doUpdateCls(validCls, oldValidCls);
}, destroy:function() {
  this.element = Ext.destroy(this.element);
  this.callParent();
}, privates:{adjustCursorOffset:function(info, xy) {
  var offset = this.getCursorOffset();
  if (offset) {
    xy[0] += offset[0] || 0;
    xy[1] += offset[1] || 0;
  }
  return xy;
}, doUpdateCls:function(cls, oldCls) {
  var el = this.element, hasCls;
  if (el) {
    if (oldCls) {
      hasCls = cls && el.hasCls(oldCls);
      el.removeCls(oldCls);
    }
    if (cls && hasCls) {
      el.addCls(cls);
    }
  }
}}});
Ext.define('Ext.overrides.drag.proxy.Placeholder', {override:'Ext.drag.proxy.Placeholder', getElement:function() {
  var el = this.callParent();
  el.addCls(Ext.baseCSSPrefix + 'root');
  return el;
}});
Ext.define('Ext.event.gesture.Recognizer', {mixins:[Ext.mixin.Identifiable], priority:0, handledEvents:[], isStarted:false, config:{onRecognized:Ext.emptyFn, callbackScope:null}, constructor:function(config) {
  this.initConfig(config);
  Ext.event.publisher.Gesture.instance.registerRecognizer(this);
}, onStart:Ext.emptyFn, onEnd:Ext.emptyFn, onTouchStart:Ext.emptyFn, onTouchMove:Ext.emptyFn, onTouchEnd:function() {
  return this.reset();
}, onTouchCancel:function(e) {
  return this.cancel(e);
}, fire:function(eventName, e, info, isCancel) {
  this.getOnRecognized().call(this.getCallbackScope(), this, eventName, e, info, isCancel);
}, cancel:function(e) {
  if (this.isStarted) {
    this.onCancel(e);
  }
  return this.reset();
}, onCancel:Ext.emptyFn, reset:function() {
  this.isStarted = false;
  return false;
}});
Ext.define('Ext.event.gesture.SingleTouch', {extend:Ext.event.gesture.Recognizer, isSingleTouch:true, onTouchStart:function(e) {
  if (e.touches.length > 1) {
    return this.cancel(e);
  }
}});
Ext.define('Ext.event.gesture.DoubleTap', {extend:Ext.event.gesture.SingleTouch, priority:300, config:{moveDistance:8, tapDistance:24, maxDuration:300}, handledEvents:['singletap', 'doubletap'], singleTapTimer:null, startTime:0, lastTapTime:0, onTouchStart:function(e) {
  var me = this, ret = me.callParent([e]), lastStartPoint;
  if (ret !== false) {
    me.isStarted = true;
    lastStartPoint = me.lastStartPoint = e.changedTouches[0].point;
    me.startPoint = me.startPoint || lastStartPoint;
    me.startTime = e.time;
    Ext.undefer(me.singleTapTimer);
  }
  return ret;
}, onTouchMove:function(e) {
  var me = this, point = e.changedTouches[0].point, scale = Ext.Element.getViewportScale(), distance = Math.round(Math.abs(point.getDistanceTo(me.lastStartPoint) * scale));
  if (distance >= me.getMoveDistance()) {
    return me.cancel(e);
  }
}, onTouchEnd:function(e) {
  var me = this, maxDuration = me.getMaxDuration(), time = e.time, target = e.target, lastTapTime = me.lastTapTime, lastTarget = me.lastTarget, point = e.changedTouches[0].point, duration, scale, distance;
  me.lastTapTime = time;
  me.lastTarget = target;
  if (lastTapTime) {
    duration = time - lastTapTime;
    if (duration <= maxDuration) {
      scale = Ext.Element.getViewportScale();
      distance = Math.round(Math.abs(point.getDistanceTo(me.startPoint) * scale));
      if (distance <= me.getTapDistance()) {
        if (target !== lastTarget) {
          return me.cancel(e);
        }
        me.lastTarget = null;
        me.lastTapTime = 0;
        me.fire('doubletap', e, {touch:e.changedTouches[0], duration:duration});
        return me.callParent([e]);
      }
    }
  }
  if (time - me.startTime > maxDuration) {
    me.fire('singletap', e);
    me.reset();
  } else {
    me.setSingleTapTimer(e);
  }
}, setSingleTapTimer:function(e) {
  var me = this;
  me.singleTapTimer = Ext.defer(function() {
    me.fire('singletap', e);
    me.reset();
  }, me.getMaxDuration());
}, reset:function() {
  var me = this;
  Ext.undefer(me.singleTapTimer);
  me.startTime = me.lastTapTime = 0;
  me.lastStartPoint = me.startPoint = me.singleTapTimer = null;
  return me.callParent();
}}, function(DoubleTap) {
  var gestures = Ext.manifest.gestures;
  DoubleTap.instance = new DoubleTap(gestures && gestures.doubleTap);
});
Ext.define('Ext.event.gesture.Drag', {extend:Ext.event.gesture.SingleTouch, priority:100, startPoint:null, previousPoint:null, lastPoint:null, handledEvents:['dragstart', 'drag', 'dragend', 'dragcancel'], config:{minDistance:8}, constructor:function() {
  this.callParent(arguments);
  this.initInfo();
}, initInfo:function() {
  this.info = {touch:null, previous:{x:0, y:0}, x:0, y:0, delta:{x:0, y:0}, absDelta:{x:0, y:0}, flick:{velocity:{x:0, y:0}}, direction:{x:0, y:0}, time:0, previousTime:{x:0, y:0}, longpress:false};
}, onTouchStart:function(e) {
  var me = this, ret = me.callParent([e]);
  if (ret !== false) {
    me.startTime = e.time;
    me.startPoint = e.changedTouches[0].point;
  }
  return ret;
}, tryDragStart:function(e) {
  var me = this, point = e.changedTouches[0].point, minDistance = me.getMinDistance(), scale = Ext.Element.getViewportScale(), distance = Math.round(Math.abs(point.getDistanceTo(me.startPoint) * scale));
  if (distance >= minDistance) {
    me.doDragStart(e);
  }
}, doDragStart:function(e, isLongPress) {
  var me = this, touch = e.changedTouches[0], point = touch.point, info = me.info, time;
  if (isLongPress) {
    time = Ext.now();
    me.startTime = time;
    me.startPoint = point;
    info.longpress = true;
  } else {
    time = e.time;
  }
  me.isStarted = true;
  me.previousPoint = me.lastPoint = point;
  me.resetInfo('x', e, touch);
  me.resetInfo('y', e, touch);
  info.time = time;
  me.fire('dragstart', e, info);
}, onTouchMove:function(e) {
  var me = this, touch, point;
  if (!me.startPoint) {
    return;
  }
  if (!me.isStarted) {
    me.tryDragStart(e);
  }
  if (!me.isStarted) {
    return;
  }
  touch = e.changedTouches[0];
  point = touch.point;
  if (me.lastPoint) {
    me.previousPoint = me.lastPoint;
  }
  me.lastPoint = point;
  me.lastMoveEvent = e;
  me.updateInfo('x', e, touch);
  me.updateInfo('y', e, touch);
  me.info.time = e.time;
  me.fire('drag', e, me.info);
}, onAxisDragEnd:function(axis, info) {
  var duration = info.time - info.previousTime[axis];
  if (duration > 0) {
    info.flick.velocity[axis] = (info[axis] - info.previous[axis]) / duration;
  }
}, resetInfo:function(axis, e, touch) {
  var me = this, value = me.lastPoint[axis], startValue = me.startPoint[axis], delta = value - startValue, capAxis = axis.toUpperCase(), info = me.info;
  info.touch = touch;
  info.delta[axis] = delta;
  info.absDelta[axis] = Math.abs(delta);
  info.previousTime[axis] = me.startTime;
  info.previous[axis] = startValue;
  info[axis] = value;
  info.direction[axis] = 0;
  info['start' + capAxis] = me.startPoint[axis];
  info['previous' + capAxis] = info.previous[axis];
  info['page' + capAxis] = info[axis];
  info['delta' + capAxis] = info.delta[axis];
  info['absDelta' + capAxis] = info.absDelta[axis];
  info['previousDelta' + capAxis] = 0;
  info.startTime = me.startTime;
}, updateInfo:function(axis, e, touch) {
  var me = this, value = me.lastPoint[axis], previousValue = me.previousPoint[axis], startValue = me.startPoint[axis], delta = value - startValue, info = me.info, direction = info.direction, capAxis = axis.toUpperCase(), previousFlick = info.previous[axis];
  info.touch = touch;
  info.delta[axis] = delta;
  info.absDelta[axis] = Math.abs(delta);
  if (value !== previousFlick && value !== info[axis]) {
    info.previous[axis] = info[axis];
    info.previousTime[axis] = info.time;
  }
  info[axis] = value;
  if (value > previousValue) {
    direction[axis] = 1;
  } else {
    if (value < previousValue) {
      direction[axis] = -1;
    }
  }
  info['start' + capAxis] = startValue;
  info['previous' + capAxis] = info.previous[axis];
  info['page' + capAxis] = info[axis];
  info['delta' + capAxis] = info.delta[axis];
  info['absDelta' + capAxis] = info.absDelta[axis];
  info['previousDelta' + capAxis] = info.previous[axis] - startValue;
  info.startTime = me.startTime;
}, onTouchEnd:function(e) {
  var me = this, touch, point, info;
  if (me.isStarted) {
    touch = e.changedTouches[0];
    point = touch.point;
    info = me.info;
    me.lastPoint = point;
    me.updateInfo('x', e, touch);
    me.updateInfo('y', e, touch);
    info.time = e.time;
    me.onAxisDragEnd('x', info);
    me.onAxisDragEnd('y', info);
    me.fire('dragend', e, info);
  }
  return this.callParent([e]);
}, onCancel:function(e) {
  var me = this, touch = e.changedTouches[0], info = me.info;
  if (!e.touches.length) {
    me.lastPoint = touch.point;
  }
  me.updateInfo('x', e, touch);
  me.updateInfo('y', e, touch);
  info.time = e.time;
  me.fire('dragcancel', e, info, true);
}, reset:function() {
  var me = this;
  me.lastPoint = me.startPoint = me.previousPoint = me.lastPoint = me.lastMoveEvent = null;
  me.initInfo();
  return me.callParent();
}}, function(Drag) {
  var gestures = Ext.manifest.gestures;
  Drag.instance = new Drag(gestures && gestures.drag);
});
Ext.define('Ext.event.gesture.Swipe', {extend:Ext.event.gesture.SingleTouch, priority:600, handledEvents:['swipestart', 'swipe', 'swipecancel'], config:{minDistance:80, maxOffset:35, maxDuration:1000}, onTouchStart:function(e) {
  var me = this, ret = me.callParent([e]), touch;
  if (ret !== false) {
    touch = e.changedTouches[0];
    me.startTime = e.time;
    me.isHorizontal = true;
    me.isVertical = true;
    me.startX = touch.pageX;
    me.startY = touch.pageY;
  }
  return ret;
}, onTouchMove:function(e) {
  var me = this, touch = e.changedTouches[0], x = touch.pageX, y = touch.pageY, deltaX = x - me.startX, deltaY = y - me.startY, absDeltaX = Math.abs(x - me.startX), absDeltaY = Math.abs(y - me.startY), duration = e.time - me.startTime, minDistance, direction, distance;
  if (absDeltaX === 0 && absDeltaY === 0 || duration > me.getMaxDuration()) {
    return me.cancel(e);
  }
  if (me.isHorizontal && absDeltaY > me.getMaxOffset()) {
    me.isHorizontal = false;
  }
  if (me.isVertical && absDeltaX > me.getMaxOffset()) {
    me.isVertical = false;
  }
  if (!me.isVertical || !me.isHorizontal) {
    minDistance = me.getMinDistance();
    if (me.isHorizontal && absDeltaX < minDistance) {
      direction = deltaX < 0 ? 'left' : 'right';
      distance = absDeltaX;
    } else {
      if (me.isVertical && absDeltaY < minDistance) {
        direction = deltaY < 0 ? 'up' : 'down';
        distance = absDeltaY;
      }
    }
  }
  if (!me.isHorizontal && !me.isVertical) {
    return me.cancel(e);
  }
  if (direction && !me.isStarted) {
    me.isStarted = true;
    me.fire('swipestart', e, {touch:touch, direction:direction, distance:distance, duration:duration});
  }
}, onTouchEnd:function(e) {
  var me = this, touch, x, y, deltaX, deltaY, absDeltaX, absDeltaY, minDistance, duration, direction, distance;
  if (me.onTouchMove(e) !== false) {
    touch = e.changedTouches[0];
    x = touch.pageX;
    y = touch.pageY;
    deltaX = x - me.startX;
    deltaY = y - me.startY;
    absDeltaX = Math.abs(deltaX);
    absDeltaY = Math.abs(deltaY);
    minDistance = me.getMinDistance();
    duration = e.time - me.startTime;
    if (me.isVertical && absDeltaY < minDistance) {
      me.isVertical = false;
    }
    if (me.isHorizontal && absDeltaX < minDistance) {
      me.isHorizontal = false;
    }
    if (me.isHorizontal) {
      direction = deltaX < 0 ? 'left' : 'right';
      distance = absDeltaX;
    } else {
      if (me.isVertical) {
        direction = deltaY < 0 ? 'up' : 'down';
        distance = absDeltaY;
      }
    }
    me.fire('swipe', e, {touch:touch, direction:direction, distance:distance, duration:duration});
  }
  return this.callParent([e]);
}, onCancel:function(e) {
  this.fire('swipecancel', e, null, true);
}, reset:function() {
  var me = this;
  me.startTime = me.isHorizontal = me.isVertical = me.startX = me.startY = null;
  return me.callParent();
}}, function(Swipe) {
  var gestures = Ext.manifest.gestures;
  Swipe.instance = new Swipe(gestures && gestures.swipe);
});
Ext.define('Ext.event.gesture.EdgeSwipe', {extend:Ext.event.gesture.Swipe, priority:500, handledEvents:['edgeswipe', 'edgeswipestart', 'edgeswipeend', 'edgeswipecancel'], config:{minDistance:60}, onTouchStart:function(e) {
  var me = this, ret = me.callParent([e]), touch;
  if (ret !== false) {
    touch = e.changedTouches[0];
    me.direction = null;
    me.isHorizontal = true;
    me.isVertical = true;
    me.startX = touch.pageX;
    me.startY = touch.pageY;
  }
  return ret;
}, onTouchMove:function(e) {
  var me = this, touch = e.changedTouches[0], x = touch.pageX, y = touch.pageY, deltaX = x - me.startX, deltaY = y - me.startY, absDeltaY = Math.abs(y - me.startY), absDeltaX = Math.abs(x - me.startX), minDistance = me.getMinDistance(), maxOffset = me.getMaxOffset(), duration = e.time - me.startTime, elementWidth = Ext.Viewport && Ext.Element.getViewportWidth(), elementHeight = Ext.Viewport && Ext.Element.getViewportHeight(), direction, distance;
  if (me.isVertical && absDeltaX > maxOffset) {
    me.isVertical = false;
  }
  if (me.isHorizontal && absDeltaY > maxOffset) {
    me.isHorizontal = false;
  }
  if (me.isVertical && me.isHorizontal) {
    if (absDeltaY > absDeltaX) {
      me.isHorizontal = false;
    } else {
      me.isVertical = false;
    }
  }
  if (me.isHorizontal) {
    direction = deltaX < 0 ? 'left' : 'right';
    distance = deltaX;
  } else {
    if (me.isVertical) {
      direction = deltaY < 0 ? 'up' : 'down';
      distance = deltaY;
    }
  }
  direction = me.direction || (me.direction = direction);
  if (direction === 'up') {
    distance = deltaY * -1;
  } else {
    if (direction === 'left') {
      distance = deltaX * -1;
    }
  }
  me.distance = distance;
  if (!distance) {
    return me.cancel(e);
  }
  if (!me.isStarted) {
    if (direction === 'right' && me.startX > minDistance || direction === 'down' && me.startY > minDistance || direction === 'left' && elementWidth - me.startX > minDistance || direction === 'up' && elementHeight - me.startY > minDistance) {
      return me.cancel(e);
    }
    me.isStarted = true;
    me.startTime = e.time;
    me.fire('edgeswipestart', e, {touch:touch, direction:direction, distance:distance, duration:duration});
  } else {
    me.fire('edgeswipe', e, {touch:touch, direction:direction, distance:distance, duration:duration});
  }
}, onTouchEnd:function(e) {
  var me = this, duration;
  if (me.onTouchMove(e) !== false) {
    duration = e.time - me.startTime;
    me.fire('edgeswipeend', e, {touch:e.changedTouches[0], direction:me.direction, distance:me.distance, duration:duration});
  }
  return this.reset();
}, onCancel:function(e) {
  this.fire('edgeswipecancel', e, {touch:e.changedTouches[0]}, true);
}, reset:function() {
  var me = this;
  me.direction = me.isHorizontal = me.isVertical = me.startX = me.startY = me.startTime = me.distance = null;
  return me.callParent();
}}, function(EdgeSwipe) {
  var gestures = Ext.manifest.gestures;
  EdgeSwipe.instance = new EdgeSwipe(gestures && gestures.edgeSwipe);
});
Ext.define('Ext.event.gesture.LongPress', {extend:Ext.event.gesture.SingleTouch, priority:400, config:{moveDistance:8, minDuration:1000}, handledEvents:['longpress', 'taphold'], onTouchStart:function(e) {
  var me = this, ret = me.callParent([e]);
  if (ret !== false) {
    me.startPoint = e.changedTouches[0].point;
    me.setLongPressTimer(e);
  }
  return ret;
}, setLongPressTimer:function(e) {
  var me = this;
  Ext.undefer(me.timer);
  me.timer = Ext.defer(me.fireLongPress, me.getMinDuration(), me, [e]);
}, onTouchMove:function(e) {
  var me = this, point = e.changedTouches[0].point, scale = Ext.Element.getViewportScale(), distance = Math.round(Math.abs(point.getDistanceTo(me.startPoint) * scale));
  if (distance >= me.getMoveDistance()) {
    return me.cancel(e);
  }
}, reset:function() {
  var me = this;
  me.timer = me.startPoint = Ext.undefer(me.timer);
  return me.callParent();
}, fireLongPress:function(e) {
  var me = this, info = {touch:e.changedTouches[0], duration:me.getMinDuration(), startDrag:me.startDrag};
  this.fire('taphold', e, info);
  this.fire('longpress', e, info);
  this.reset();
}, startDrag:function() {
  var dragRecognizer = Ext.event.gesture.Drag.instance, touchStartEvent = this.parentEvent;
  dragRecognizer.doDragStart(touchStartEvent, true);
  Ext.event.publisher.Gesture.instance.claimRecognizer(dragRecognizer, touchStartEvent);
}}, function(LongPress) {
  var gestures = Ext.manifest.gestures;
  LongPress.instance = new LongPress(gestures && gestures.longPress);
});
Ext.define('Ext.event.gesture.MultiTouch', {extend:Ext.event.gesture.Recognizer, requiredTouchesCount:2, isTracking:false, isMultiTouch:true, onTouchStart:function(e) {
  var me = this, requiredTouchesCount = me.requiredTouchesCount, touches = e.touches, touchesCount = touches.length;
  if (touchesCount === requiredTouchesCount) {
    me.isTracking = true;
  } else {
    if (touchesCount > requiredTouchesCount) {
      return me.cancel(e);
    }
  }
}, reset:function() {
  this.isTracking = false;
  return this.callParent();
}});
Ext.define('Ext.event.gesture.Pinch', {extend:Ext.event.gesture.MultiTouch, priority:700, handledEvents:['pinchstart', 'pinch', 'pinchend', 'pinchcancel'], startDistance:0, lastTouches:null, onTouchMove:function(e) {
  var me = this, touches, firstPoint, secondPoint, distance;
  if (me.isTracking) {
    touches = e.touches;
    firstPoint = touches[0].point;
    secondPoint = touches[1].point;
    distance = firstPoint.getDistanceTo(secondPoint);
    if (distance === 0) {
      return;
    }
    if (!me.isStarted) {
      me.isStarted = true;
      me.startDistance = distance;
      me.fire('pinchstart', e, {touches:touches, distance:distance, scale:1});
    } else {
      me.fire('pinch', e, {touches:touches, distance:distance, scale:distance / me.startDistance});
    }
  }
}, onTouchEnd:function(e) {
  if (this.isStarted) {
    this.fire('pinchend', e);
  }
  return this.callParent([e]);
}, onCancel:function(e) {
  this.fire('pinchcancel', e, null, true);
}, reset:function() {
  this.lastTouches = null;
  this.startDistance = 0;
  return this.callParent();
}}, function(Pinch) {
  var gestures = Ext.manifest.gestures;
  Pinch.instance = new Pinch(gestures && gestures.pinch);
});
Ext.define('Ext.event.gesture.Rotate', {extend:Ext.event.gesture.MultiTouch, priority:800, handledEvents:['rotatestart', 'rotate', 'rotateend', 'rotatecancel'], startAngle:0, lastTouches:null, lastAngle:null, onTouchMove:function(e) {
  var me = this, touches, lastAngle, firstPoint, secondPoint, angle, nextAngle, previousAngle, diff;
  if (me.isTracking) {
    touches = e.touches;
    lastAngle = me.lastAngle;
    firstPoint = touches[0].point;
    secondPoint = touches[1].point;
    angle = firstPoint.getAngleTo(secondPoint);
    if (lastAngle !== null) {
      diff = Math.abs(lastAngle - angle);
      nextAngle = angle + 360;
      previousAngle = angle - 360;
      if (Math.abs(nextAngle - lastAngle) < diff) {
        angle = nextAngle;
      } else {
        if (Math.abs(previousAngle - lastAngle) < diff) {
          angle = previousAngle;
        }
      }
    }
    me.lastAngle = angle;
    if (!me.isStarted) {
      me.isStarted = true;
      me.startAngle = angle;
      me.fire('rotatestart', e, {touches:touches, angle:angle, rotation:0});
    } else {
      me.fire('rotate', e, {touches:touches, angle:angle, rotation:angle - me.startAngle});
    }
    me.lastTouches = Ext.Array.clone(touches);
  }
}, onTouchEnd:function(e) {
  if (this.isStarted) {
    this.fire('rotateend', e);
  }
  return this.callParent([e]);
}, onCancel:function(e) {
  this.fire('rotatecancel', e, null, true);
}, reset:function() {
  var me = this;
  me.lastTouches = me.lastAngle = me.startAngle = null;
  return this.callParent();
}}, function(Rotate) {
  var gestures = Ext.manifest.gestures;
  Rotate.instance = new Rotate(gestures && gestures.rotate);
});
Ext.define('Ext.event.gesture.Tap', {extend:Ext.event.gesture.SingleTouch, priority:200, handledEvents:['tap', 'tapcancel'], config:{moveDistance:8}, onTouchStart:function(e) {
  var me = this, ret = me.callParent([e]);
  if (ret !== false) {
    me.isStarted = true;
    me.startPoint = e.changedTouches[0].point;
  }
  return ret;
}, onTouchMove:function(e) {
  var me = this, point = e.changedTouches[0].point, scale = Ext.Element.getViewportScale(), distance = Math.round(Math.abs(point.getDistanceTo(me.startPoint) * scale));
  if (distance >= me.getMoveDistance()) {
    return me.cancel(e);
  }
}, onTouchEnd:function(e) {
  this.fire('tap', e, {touch:e.changedTouches[0]});
  return this.callParent([e]);
}, onCancel:function(e) {
  this.fire('tapcancel', e, {touch:e.changedTouches[0]}, true);
}, reset:function() {
  this.startPoint = null;
  return this.callParent();
}}, function(Tap) {
  var gestures = Ext.manifest.gestures;
  Tap.instance = new Tap(gestures && gestures.tap);
});
Ext.define('Ext.event.publisher.Focus', {extend:Ext.event.publisher.Dom, type:'focus', handledEvents:['focusenter', 'focusleave', 'focusmove'], handledDomEvents:['focusin', 'focusout'], publishDelegatedDomEvent:function(e) {
  var me = this, relatedTarget = e.relatedTarget;
  if (me.$suppressEvents) {
    return;
  }
  if (e.type === 'focusout') {
    if (relatedTarget == null) {
      me.processFocusIn(e, e.target, document.body);
    }
  } else {
    if (relatedTarget == null || !relatedTarget.tagName) {
      relatedTarget = document.body;
    }
    me.processFocusIn(e, relatedTarget, e.target);
  }
}, processFocusIn:function(e, fromElement, toElement) {
  var me = this, focusFly = me.focusFly, targets = [], commonAncestor, node, backwards, event, focusEnterEvent;
  if (fromElement && focusFly.attach(fromElement).isFocusSuspended() || toElement && focusFly.attach(toElement).isFocusSuspended()) {
    return;
  }
  if (toElement.compareDocumentPosition) {
    backwards = !!(toElement.compareDocumentPosition(fromElement) & 4);
  }
  for (node = fromElement, commonAncestor = Ext.dom.Element.getCommonAncestor(toElement, fromElement, true); node && node !== commonAncestor; node = node.parentNode) {
    targets.push(node);
  }
  if (targets.length) {
    event = me.createSyntheticEvent('focusleave', e, fromElement, toElement, fromElement, toElement, backwards);
    me.publish(event, targets);
    if (event.stopped) {
      return;
    }
  }
  targets.length = 0;
  for (node = toElement; node && node !== commonAncestor; node = node.parentNode) {
    targets.push(node);
  }
  focusEnterEvent = me.createSyntheticEvent('focusenter', e, toElement, fromElement, fromElement, toElement, backwards);
  if (targets.length) {
    me.publish(focusEnterEvent, targets);
    if (focusEnterEvent.stopped) {
      return;
    }
  }
  targets = me.getPropagatingTargets(commonAncestor);
  if (targets.length) {
    event = me.createSyntheticEvent('focusmove', e, toElement, fromElement, fromElement, toElement, backwards);
    me.publish(event, targets);
    if (event.stopped) {
      return;
    }
  }
  if (Ext.GlobalEvents.hasListeners.focus) {
    Ext.GlobalEvents.fireEvent('focus', {event:focusEnterEvent, toElement:toElement, fromElement:fromElement, backwards:backwards});
  }
}, createSyntheticEvent:function(eventName, browserEvent, target, relatedTarget, fromElement, toElement, backwards) {
  var event = new Ext.event.Event(browserEvent);
  event.type = eventName;
  event.relatedTarget = relatedTarget;
  event.target = target;
  event.fromElement = fromElement;
  event.toElement = toElement;
  event.backwards = backwards;
  return event;
}}, function(Focus) {
  var focusTimeout;
  Focus.prototype.focusFly = new Ext.dom.Fly;
  Focus.instance = new Focus;
  if (!Ext.supports.FocusinFocusoutEvents) {
    this.override({handledDomEvents:['focus', 'blur'], publishDelegatedDomEvent:function(e) {
      var me = this, targetIsElement;
      me.callSuper([e]);
      targetIsElement = e.target !== window && e.target !== document;
      if (e.type === 'blur') {
        if (!targetIsElement) {
          if (e.explicitOriginalTarget === Focus.previousActiveElement) {
            if (e.target === window) {
              Ext.undefer(focusTimeout);
              focusTimeout = 0;
              me.processFocusIn(e, Focus.previousActiveElement, document.body);
              Focus.previousActiveElement = null;
            }
          }
        } else {
          focusTimeout = Ext.defer(function() {
            focusTimeout = 0;
            me.processFocusIn(e, e.target, document.body);
            Focus.previousActiveElement = null;
          }, 1);
          if (targetIsElement && Ext.cache[e.target.id]) {
            Ext.cache[e.target.id].focusinTimeout = focusTimeout;
          }
        }
        Focus.previousActiveElement = targetIsElement ? e.target : null;
      } else {
        Ext.undefer(focusTimeout);
        focusTimeout = 0;
        me.processFocusIn(e, Focus.previousActiveElement || document.body, targetIsElement ? e.target : document.body);
      }
    }});
    Ext.define(null, {override:'Ext.dom.Element', destroy:function() {
      if (this.focusinTimeout) {
        Ext.undefer(this.focusinTimeout);
        this.focusinTimeout = null;
      }
      this.callParent();
    }});
  }
});
Ext.define('Ext.field.InputMask', function(InputMask) {
  return {cachedConfig:{blank:'_', characters:{'*':'[A-Za-z0-9]', 'a':'[a-z]', 'A':'[A-Z]', 0:'[0-9]', 9:'[0-9]'}, ignoreCase:true}, config:{pattern:null}, _cached:false, _lastEditablePos:null, _mask:null, statics:{active:{}, from:function(value, existing) {
    var active = InputMask.active, ret;
    if (value === null) {
      ret = null;
    } else {
      if (typeof value !== 'string') {
        if (existing && !existing._cached) {
          ret = existing;
          ret.setConfig(value);
        } else {
          ret = new InputMask(value);
        }
      } else {
        if (!(ret = active[value])) {
          if (!(ret = InputMask.cache.remove(value))) {
            ret = new InputMask({pattern:value});
          }
          active[value] = ret;
          ret._cached = 1;
        } else {
          ++ret._cached;
        }
      }
    }
    return ret;
  }}, constructor:function(config) {
    this.initConfig(config);
  }, release:function() {
    var me = this, cache = InputMask.cache, key;
    if (me._cached && !--me._cached) {
      key = me.getPattern();
      if (InputMask.active[key] !== me) {
        Ext.raise('Invalid call to InputMask#release (not active)');
      }
      if (cache.map[key]) {
        Ext.raise('Invalid call to InputMask#release (already cached)');
      }
      delete InputMask.active[key];
      cache.add(key, me);
      cache.trim(cache.maxSize);
    } else {
      if (me._cached === 0) {
        Ext.raise('Invalid call to InputMask#release (already released)');
      }
    }
  }, clearRange:function(value, start, len) {
    var me = this, blank = me.getBlank(), end = start + len, n = value.length, s = '', i, mask, prefixLen;
    if (!blank) {
      prefixLen = me._prefix.length;
      for (i = 0; i < n; ++i) {
        if (i < prefixLen || i < start || i >= end) {
          s += value[i];
        }
      }
      s = me.formatValue(s);
    } else {
      mask = me.getPattern();
      for (i = 0; i < n; ++i) {
        if (i < start || i >= end) {
          s += value[i];
        } else {
          if (me.isFixedChar(i)) {
            s += mask[i];
          } else {
            s += blank;
          }
        }
      }
    }
    return s;
  }, formatValue:function(value) {
    var me = this, blank = me.getBlank(), i, length, mask, prefix, s;
    if (!blank) {
      prefix = me._prefix;
      length = prefix.length;
      s = this.insertRange('', value, 0);
      for (i = s.length; i > length && me.isFixedChar(i - 1);) {
        --i;
      }
      s = i < length ? prefix : s.slice(0, i - 1);
    } else {
      if (value) {
        s = me.formatValue('');
        s = me.insertRange(s, value, 0);
      } else {
        mask = me.getPattern();
        s = '';
        for (i = 0, length = mask.length; i < length; ++i) {
          if (me.isFixedChar(i)) {
            s += mask[i];
          } else {
            s += blank;
          }
        }
      }
    }
    return s;
  }, getEditPosLeft:function(pos) {
    var i;
    for (i = pos; i >= 0; --i) {
      if (!this.isFixedChar(i)) {
        return i;
      }
    }
    return null;
  }, getEditPosRight:function(pos) {
    var mask = this._mask, len = mask.length, i;
    for (i = pos; i < len; ++i) {
      if (!this.isFixedChar(i)) {
        return i;
      }
    }
    return null;
  }, getFilledLength:function(value) {
    var me = this, blank = me.getBlank(), c, i;
    if (!blank) {
      return value.length;
    }
    for (i = value && value.length; i-- > 0;) {
      c = value[i];
      if (!me.isFixedChar(i) && me.isAllowedChar(c, i)) {
        break;
      }
    }
    return ++i || me._prefix.length;
  }, getSubLength:function(value, substr, pos) {
    var me = this, mask = me.getPattern(), k = 0, maskLen = mask.length, substrLen = substr.length, i;
    for (i = pos; i < maskLen && k < substrLen;) {
      if (!me.isFixedChar(i) || mask[i] === substr[k]) {
        if (me.isAllowedChar(substr[k++], i, true)) {
          ++i;
        }
      } else {
        ++i;
      }
    }
    return i - pos;
  }, insertRange:function(value, substr, pos) {
    var me = this, mask = me.getPattern(), blank = me.getBlank(), filled = me.isFilled(value), prefixLen = me._prefix.length, maskLen = mask.length, substrLen = substr.length, s = value, ch, fixed, i, k;
    if (!blank && pos > s.length) {
      s += mask.slice(s.length, pos);
    }
    for (i = pos, k = 0; i < maskLen && k < substrLen;) {
      fixed = me.isFixedChar(i);
      if (!fixed || mask[i] === substr[k]) {
        ch = substr[k++];
        if (me.isAllowedChar(ch, i, true)) {
          if (i < s.length) {
            if (blank || filled || i < prefixLen) {
              s = s.slice(0, i) + ch + s.slice(i + 1);
            } else {
              s = me.formatValue(s.substr(0, i) + ch + s.substr(i));
            }
          } else {
            if (!blank) {
              s += ch;
            }
          }
          ++i;
        }
      } else {
        if (!blank && i >= s.length) {
          s += mask[i];
        } else {
          if (blank && fixed && substr[k] === blank) {
            ++k;
          }
        }
        ++i;
      }
    }
    return s;
  }, isAllowedChar:function(character, pos, allowBlankChar) {
    var me = this, mask = me.getPattern(), c, characters, rule;
    if (me.isFixedChar(pos)) {
      return mask[pos] === character;
    }
    c = mask[pos];
    characters = me.getCharacters();
    rule = characters[c];
    return !rule || rule.test(character || '') || allowBlankChar && character === me.getBlank();
  }, isEmpty:function(value) {
    var i, len;
    for (i = 0, len = value.length; i < len; ++i) {
      if (!this.isFixedChar(i) && this.isAllowedChar(value[i], i)) {
        return false;
      }
    }
    return true;
  }, isFilled:function(value) {
    return this.getFilledLength(value) === this._mask.length;
  }, isFixedChar:function(pos) {
    return Ext.Array.indexOf(this._fixedCharPositions, pos) > -1;
  }, setCaretToEnd:function(field, value) {
    var filledLen = this.getFilledLength(value), pos = this.getEditPosRight(filledLen);
    if (pos !== null) {
      Ext.raf(function() {
        if (!field.destroyed) {
          field.setCaretPos(pos);
          Ext.raf(function() {
            if (!field.destroyed) {
              field.setCaretPos(pos);
            }
          });
        }
      });
    }
  }, onBlur:function(field, value) {
    if (field.getAutoHideInputMask() !== false) {
      if (this.isEmpty(value)) {
        field.maskProcessed = true;
        field.setValue('');
      }
    }
  }, onFocus:function(field, value) {
    if (field.getAutoHideInputMask() !== false) {
      if (!value) {
        field.maskProcessed = true;
        field.setValue(this._mask);
      }
    }
    this.setCaretToEnd(field, value);
  }, onChange:function(field, value, oldValue) {
    var me = this, s;
    if (field.maskProcessed || value === oldValue) {
      field.maskProcessed = false;
      return true;
    }
    if (value) {
      s = me.formatValue(value);
      field.maskProcessed = true;
      field.setValue(s);
    }
  }, processAutocomplete:function(field, value) {
    var me = this, s;
    if (value) {
      if (value.length > me._mask.length) {
        value = value.substr(0, me._mask.length);
      }
      s = me.formatValue(value);
      field.maskProcessed = true;
      field.inputElement.dom.value = s;
      field.setValue(s);
      this.setCaretToEnd(field, value);
    }
  }, showEmptyMask:function(field, adjustCaret) {
    var s = this.formatValue();
    field.maskProcessed = true;
    field.setValue(s);
    if (adjustCaret) {
      this.setCaretToEnd(field);
    }
  }, onKeyDown:function(field, value, event) {
    if (event.ctrlKey || event.metaKey) {
      return;
    }
    var me = this, key = event.keyCode === event.DELETE, del = key === 'Delete', handled = del || event.keyCode === event.BACKSPACE, s = value, caret, editPos, len, prefixLen, textSelection, start;
    if (handled) {
      caret = field.getCaretPos();
      prefixLen = me._prefix.length;
      textSelection = field.getTextSelection();
      start = textSelection[0];
      len = textSelection[1] - start;
      if (len) {
        s = me.clearRange(value, start, len);
      } else {
        if (caret < prefixLen || !del && caret === prefixLen) {
          caret = prefixLen;
        } else {
          editPos = del ? me.getEditPosRight(caret) : me.getEditPosLeft(caret - 1);
          if (editPos !== null) {
            s = me.clearRange(value, editPos, 1);
            caret = editPos;
          }
        }
      }
      if (s !== value) {
        field.maskProcessed = true;
        field.setValue(s);
      }
      event.preventDefault();
      field.setCaretPos(caret);
    }
  }, onKeyPress:function(field, value, event) {
    var me = this, key = event.keyCode, ch = event.getChar(), mask = me.getPattern(), prefixLen = me._prefix.length, s = value, caretPos, pos, start, textSelection;
    if (key === event.ENTER || key === event.TAB || event.ctrlKey || event.metaKey) {
      return;
    }
    caretPos = field.getCaretPos();
    textSelection = field.getTextSelection();
    if (me.isFixedChar(caretPos) && mask[caretPos] === ch) {
      s = me.insertRange(s, ch, caretPos);
      ++caretPos;
    } else {
      pos = me.getEditPosRight(caretPos);
      if (pos !== null && me.isAllowedChar(ch, pos)) {
        start = textSelection[0];
        s = me.clearRange(s, start, textSelection[1] - start);
        s = me.insertRange(s, ch, pos);
        caretPos = pos + 1;
      }
    }
    if (s !== value) {
      field.maskProcessed = true;
      field.setValue(s);
    }
    event.preventDefault();
    if (caretPos < me._lastEditablePos && caretPos > prefixLen) {
      caretPos = me.getEditPosRight(caretPos);
    }
    field.setCaretPos(caretPos);
  }, onPaste:function(field, value, event) {
    var text, clipdData = event.browserEvent.clipboardData;
    if (clipdData && clipdData.getData) {
      text = clipdData.getData('text/plain');
    } else {
      if (Ext.global.clipboardData && Ext.global.clipboardData.getData) {
        text = Ext.global.clipboardData.getData('Text');
      }
    }
    if (text) {
      this.paste(field, value, text, field.getTextSelection());
    }
    event.preventDefault();
  }, paste:function(field, value, text, selection) {
    var me = this, caretPos = selection[0], len = selection[1] - caretPos, s = len ? me.clearRange(value, caretPos, len) : value, textLen = me.getSubLength(s, text, caretPos);
    s = me.insertRange(s, text, caretPos);
    caretPos += textLen;
    caretPos = me.getEditPosRight(caretPos) || caretPos;
    if (s !== value) {
      field.maskProcessed = true;
      field.setValue(s);
    }
    field.setCaretPos(caretPos);
  }, syncPattern:function(field) {
    var fieldValue = field.getValue(), s;
    if (field.getAutoHideInputMask() === false) {
      if (!fieldValue) {
        this.showEmptyMask(field);
      } else {
        s = this.formatValue(fieldValue);
        field.maskProcessed = true;
        field.setValue(s);
      }
    } else {
      if (fieldValue) {
        s = this.formatValue(fieldValue);
        field.maskProcessed = true;
        field.setValue(s);
      }
    }
  }, applyCharacters:function(map) {
    var ret = {}, flags = this.getIgnoreCase() ? 'i' : '', c, v;
    for (c in map) {
      v = map[c];
      if (typeof v === 'string') {
        v = new RegExp(v, flags);
      }
      ret[c] = v;
    }
    return ret;
  }, updatePattern:function(mask) {
    var me = this, characters = me.getCharacters(), lastEditablePos = 0, n = mask && mask.length, blank = me.getBlank(), fixedPosArr = [], prefix = '', str = '', c, i;
    for (i = 0; i < n; ++i) {
      c = mask[i];
      if (!characters[c]) {
        fixedPosArr.push(str.length);
        str += c;
      } else {
        lastEditablePos = str.length + 1;
        str += blank;
      }
    }
    me._lastEditablePos = lastEditablePos;
    me._mask = str;
    me._fixedCharPositions = fixedPosArr;
    for (i = 0; i < str.length && me.isFixedChar(i); ++i) {
      prefix += str[i];
    }
    me._prefix = prefix;
  }};
}, function(InputMask) {
  InputMask.cache = new Ext.util.LRU;
  InputMask.cache.maxSize = 100;
});
Ext.define('Ext.fx.runner.Css', {extend:Ext.Evented, prefixedProperties:{'transform':true, 'transform-origin':true, 'perspective':true, 'transform-style':true, 'transition':true, 'transition-property':true, 'transition-duration':true, 'transition-timing-function':true, 'transition-delay':true, 'animation':true, 'animation-name':true, 'animation-duration':true, 'animation-iteration-count':true, 'animation-direction':true, 'animation-timing-function':true, 'animation-delay':true}, lengthProperties:{'top':true, 
'right':true, 'bottom':true, 'left':true, 'width':true, 'height':true, 'max-height':true, 'max-width':true, 'min-height':true, 'min-width':true, 'margin-bottom':true, 'margin-left':true, 'margin-right':true, 'margin-top':true, 'padding-bottom':true, 'padding-left':true, 'padding-right':true, 'padding-top':true, 'border-bottom-width':true, 'border-left-width':true, 'border-right-width':true, 'border-spacing':true, 'border-top-width':true, 'border-width':true, 'outline-width':true, 'letter-spacing':true, 
'line-height':true, 'text-indent':true, 'word-spacing':true, 'font-size':true, 'translate':true, 'translateX':true, 'translateY':true, 'translateZ':true, 'translate3d':true, 'x':true, 'y':true}, durationProperties:{'transition-duration':true, 'transition-delay':true, 'animation-duration':true, 'animation-delay':true}, angleProperties:{rotate:true, rotateX:true, rotateY:true, rotateZ:true, skew:true, skewX:true, skewY:true}, DEFAULT_UNIT_LENGTH:'px', DEFAULT_UNIT_ANGLE:'deg', DEFAULT_UNIT_DURATION:'ms', 
customProperties:{x:true, y:true}, formattedNameCache:{'x':'left', 'y':'top'}, transformMethods3d:['translateX', 'translateY', 'translateZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'skewX', 'skewY', 'scaleX', 'scaleY', 'scaleZ'], transformMethodsNo3d:['translateX', 'translateY', 'rotate', 'skewX', 'skewY', 'scaleX', 'scaleY'], constructor:function() {
  var me = this;
  me.transformMethods = Ext.feature.has.Css3dTransforms ? me.transformMethods3d : me.transformMethodsNo3d;
  me.vendorPrefix = Ext.browser.getStyleDashPrefix();
  me.ruleStylesCache = {};
  me.callParent();
}, getStyleSheet:function() {
  var styleSheet = this.styleSheet, styleElement, styleSheets;
  if (!styleSheet) {
    styleElement = document.createElement('style');
    styleElement.type = 'text/css';
    (document.head || document.getElementsByTagName('head')[0]).appendChild(styleElement);
    styleSheets = document.styleSheets;
    this.styleSheet = styleSheet = styleSheets[styleSheets.length - 1];
  }
  return styleSheet;
}, applyRules:function(selectors) {
  var styleSheet = this.getStyleSheet(), ruleStylesCache = this.ruleStylesCache, rules = styleSheet.cssRules, selector, properties, ruleStyle, ruleStyleCache, rulesLength, name, value;
  for (selector in selectors) {
    properties = selectors[selector];
    ruleStyle = ruleStylesCache[selector];
    if (ruleStyle === undefined) {
      rulesLength = rules.length;
      styleSheet.insertRule(selector + '{}', rulesLength);
      ruleStyle = ruleStylesCache[selector] = rules.item(rulesLength).style;
    }
    ruleStyleCache = ruleStyle.$cache;
    if (!ruleStyleCache) {
      ruleStyleCache = ruleStyle.$cache = {};
    }
    for (name in properties) {
      value = this.formatValue(properties[name], name);
      name = this.formatName(name);
      if (ruleStyleCache[name] !== value) {
        ruleStyleCache[name] = value;
        if (value === null) {
          ruleStyle.removeProperty(name);
        } else {
          ruleStyle.setProperty(name, value);
        }
      }
    }
  }
  return this;
}, applyStyles:function(styles) {
  var id, element, elementStyle, properties, name, value;
  for (id in styles) {
    if (styles.hasOwnProperty(id)) {
      this.activeElement = element = document.getElementById(id);
      if (!element) {
        continue;
      }
      elementStyle = element.style;
      properties = styles[id];
      for (name in properties) {
        if (properties.hasOwnProperty(name)) {
          value = this.formatValue(properties[name], name);
          name = this.formatName(name);
          if (value === null) {
            elementStyle.removeProperty(name);
          } else {
            elementStyle.setProperty(name, value);
          }
        }
      }
    }
  }
  this.activeElement = null;
  return this;
}, formatName:function(name) {
  var cache = this.formattedNameCache, formattedName = cache[name];
  if (!formattedName) {
    if ((Ext.os.is.Tizen || !Ext.feature.has.CssTransformNoPrefix) && this.prefixedProperties[name]) {
      formattedName = this.vendorPrefix + name;
    } else {
      formattedName = name;
    }
    cache[name] = formattedName;
  }
  return formattedName;
}, formatValue:function(value, name) {
  var type = typeof value, defaultLengthUnit = this.DEFAULT_UNIT_LENGTH, isCustom = this.customProperties[name], transformMethods, method, i, ln, transformValues, values;
  if (value === null) {
    return '';
  }
  if (type === 'string') {
    if (this.lengthProperties[name]) {
      if (!Ext.dom.Element.hasUnit(value)) {
        value = value + defaultLengthUnit;
        if (isCustom) {
          value = this.getCustomValue(value, name);
        }
      }
    }
    return value;
  } else {
    if (type === 'number') {
      if (value === 0) {
        return '0';
      }
      if (this.lengthProperties[name]) {
        value = value + defaultLengthUnit;
        if (isCustom) {
          value = this.getCustomValue(value, name);
        }
        return value;
      }
      if (this.angleProperties[name]) {
        return value + this.DEFAULT_UNIT_ANGLE;
      }
      if (this.durationProperties[name]) {
        return value + this.DEFAULT_UNIT_DURATION;
      }
    } else {
      if (name === 'transform') {
        transformMethods = this.transformMethods;
        transformValues = [];
        for (i = 0, ln = transformMethods.length; i < ln; i++) {
          method = transformMethods[i];
          transformValues.push(method + '(' + this.formatValue(value[method], method) + ')');
        }
        return transformValues.join(' ');
      } else {
        if (Ext.isArray(value)) {
          values = [];
          for (i = 0, ln = value.length; i < ln; i++) {
            values.push(this.formatValue(value[i], name));
          }
          return values.length > 0 ? values.join(', ') : 'none';
        }
      }
    }
  }
  return value;
}, getCustomValue:function(value, name) {
  var el = Ext.fly(this.activeElement);
  if (name === 'x') {
    value = el.translateXY(parseInt(value, 10)).x;
  } else {
    if (name === 'y') {
      value = el.translateXY(null, parseInt(value, 10)).y;
    }
  }
  return value + this.DEFAULT_UNIT_LENGTH;
}});
Ext.define('Ext.fx.runner.CssTransition', {extend:Ext.fx.runner.Css, alternateClassName:'Ext.Animator', singleton:true, listenersAttached:false, constructor:function() {
  this.runningAnimationsData = {};
  this.transitionQueue = {toData:{}, transitionData:{}};
  return this.callParent(arguments);
}, attachListeners:function() {
  var target = top === window ? Ext.getWin() : Ext.getBody();
  this.listenersAttached = true;
  target.on('transitionend', 'onTransitionEnd', this);
}, onTransitionEnd:function(e) {
  var target = e.target, id = target.id;
  if (id && this.runningAnimationsData.hasOwnProperty(id)) {
    this.refreshRunningAnimationsData(Ext.get(target), [e.browserEvent.propertyName]);
  }
}, getElementId:function(element) {
  return element.getId ? element.getId() : element.id;
}, onAnimationEnd:function(element, data, animation, isInterrupted, isReplaced) {
  var id = this.getElementId(element), runningData = this.runningAnimationsData[id], endRules = {}, endData = {}, runningNameMap, toPropertyNames, i, ln, name;
  animation.un('stop', 'onAnimationStop', this);
  if (runningData) {
    runningNameMap = runningData.nameMap;
  }
  endRules[id] = endData;
  if (data.onBeforeEnd) {
    data.onBeforeEnd.call(data.scope || this, element, isInterrupted);
  }
  animation.fireEvent('animationbeforeend', animation, element, isInterrupted);
  this.fireEvent('animationbeforeend', this, animation, element, isInterrupted);
  if (isReplaced || !isInterrupted && !data.preserveEndState) {
    toPropertyNames = data.toPropertyNames;
    for (i = 0, ln = toPropertyNames.length; i < ln; i++) {
      name = toPropertyNames[i];
      if (runningNameMap && !runningNameMap.hasOwnProperty(name)) {
        endData[name] = null;
      }
    }
  }
  if (data.after) {
    Ext.merge(endData, data.after);
  }
  this.applyStyles(endRules);
  if (data.onEnd) {
    data.onEnd.call(data.scope || this, element, isInterrupted);
  }
  animation.fireEvent('animationend', animation, element, isInterrupted);
  this.fireEvent('animationend', this, animation, element, isInterrupted);
  Ext.AnimationQueue.stop(Ext.emptyFn, animation);
}, onAllAnimationsEnd:function(element) {
  var id = this.getElementId(element), transitionQueue = this.transitionQueue, endRules = {};
  delete this.runningAnimationsData[id];
  endRules[id] = {'transition-property':null, 'transition-duration':null, 'transition-timing-function':null, 'transition-delay':null};
  delete transitionQueue.toData[id];
  delete transitionQueue.transitionData[id];
  this.applyStyles(endRules);
  this.fireEvent('animationallend', this, element);
}, hasRunningAnimations:function(element) {
  var id = this.getElementId(element), runningAnimationsData = this.runningAnimationsData;
  return runningAnimationsData.hasOwnProperty(id) && runningAnimationsData[id].sessions.length > 0;
}, refreshRunningAnimationsData:function(element, propertyNames, interrupt, replace) {
  var id = this.getElementId(element), runningAnimationsData = this.runningAnimationsData, runningData = runningAnimationsData[id], hasCompletedSession = false, nameMap, nameList, sessions, name, session, map, list, i, ln, j, subLn;
  if (!runningData) {
    return;
  }
  nameMap = runningData.nameMap;
  nameList = runningData.nameList;
  sessions = runningData.sessions;
  interrupt = Boolean(interrupt);
  replace = Boolean(replace);
  if (!sessions) {
    return this;
  }
  ln = sessions.length;
  if (ln === 0) {
    return this;
  }
  if (replace) {
    runningData.nameMap = {};
    nameList.length = 0;
    for (i = 0; i < ln; i++) {
      session = sessions[i];
      this.onAnimationEnd(element, session.data, session.animation, interrupt, replace);
    }
    sessions.length = 0;
  } else {
    for (i = 0; i < ln; i++) {
      session = sessions[i];
      map = session.map;
      list = session.list;
      for (j = 0, subLn = propertyNames.length; j < subLn; j++) {
        name = propertyNames[j];
        if (map[name]) {
          delete map[name];
          Ext.Array.remove(list, name);
          session.length--;
          if (--nameMap[name] === 0) {
            delete nameMap[name];
            Ext.Array.remove(nameList, name);
          }
        }
      }
      if (session.length === 0) {
        sessions.splice(i, 1);
        i--;
        ln--;
        hasCompletedSession = true;
        this.onAnimationEnd(element, session.data, session.animation, interrupt);
      }
    }
  }
  if (!replace && !interrupt && sessions.length === 0 && hasCompletedSession) {
    this.onAllAnimationsEnd(element);
  }
}, getRunningData:function(id) {
  var runningAnimationsData = this.runningAnimationsData;
  if (!runningAnimationsData.hasOwnProperty(id)) {
    runningAnimationsData[id] = {nameMap:{}, nameList:[], sessions:[]};
  }
  return runningAnimationsData[id];
}, getTestElement:function() {
  var me = this, testElement = me.testElement, iframe = me.iframe, iframeDocument, iframeStyle;
  if (testElement) {
    if (testElement.ownerDocument.defaultView !== iframe.contentWindow) {
      iframeDocument = iframe.contentDocument;
      iframeDocument.body.appendChild(testElement);
      me.testElementComputedStyle = iframeDocument.defaultView.getComputedStyle(testElement);
    }
  } else {
    iframe = me.iframe = document.createElement('iframe');
    iframe.setAttribute('data-sticky', true);
    iframe.setAttribute('tabIndex', -1);
    iframeStyle = iframe.style;
    iframeStyle.setProperty('visibility', 'hidden', 'important');
    iframeStyle.setProperty('width', '0px', 'important');
    iframeStyle.setProperty('height', '0px', 'important');
    iframeStyle.setProperty('position', 'absolute', 'important');
    iframeStyle.setProperty('border', '0px', 'important');
    iframeStyle.setProperty('zIndex', '-1000', 'important');
    document.body.appendChild(iframe);
    iframeDocument = iframe.contentDocument;
    iframeDocument.open();
    iframeDocument.writeln('\x3c/body\x3e');
    iframeDocument.close();
    me.testElement = testElement = iframeDocument.createElement('div');
    testElement.style.setProperty('position', 'absolute', 'important');
    iframeDocument.body.appendChild(testElement);
    me.testElementComputedStyle = iframeDocument.defaultView.getComputedStyle(testElement);
  }
  return testElement;
}, getCssStyleValue:function(name, value) {
  var testElement = this.getTestElement(), computedStyle = this.testElementComputedStyle, style = testElement.style;
  style.setProperty(name, value);
  if (Ext.browser.is.Firefox) {
    testElement.offsetHeight;
  }
  value = computedStyle.getPropertyValue(name);
  style.removeProperty(name);
  return value;
}, run:function(animations) {
  var me = this, ret = [], isLengthPropertyMap = me.lengthProperties, fromData = {}, toData = me.transitionQueue.toData, data = {}, transitionData = me.transitionQueue.transitionData, element, elementId, from, to, before, fromPropertyNames, toPropertyNames, doApplyTo, message, runningData, elementData, i, j, ln, animation, propertiesLength, sessionNameMap, computedStyle, formattedName, name, toFormattedValue, computedValue, fromFormattedValue, isLengthProperty, runningNameMap, runningNameList, runningSessions, 
  runningSession, messageTimerFn, onBeforeStart;
  if (!me.listenersAttached) {
    me.attachListeners();
  }
  animations = Ext.Array.from(animations);
  for (i = 0, ln = animations.length; i < ln; i++) {
    animation = animations[i];
    animation = Ext.factory(animation, Ext.fx.Animation);
    ret.push(animation);
    me.activeElement = element = animation.getElement();
    Ext.AnimationQueue.start(Ext.emptyFn, animation);
    computedStyle = window.getComputedStyle(element.dom);
    elementId = me.getElementId(element);
    data[elementId] = data = Ext.merge({}, animation.getData());
    onBeforeStart = animation.getOnBeforeStart();
    if (onBeforeStart) {
      onBeforeStart.call(animation.scope || me, element);
    }
    animation.fireEvent('animationstart', animation, data);
    me.fireEvent('animationstart', me, animation, data);
    before = data.before;
    from = data.from;
    to = data.to;
    data.fromPropertyNames = fromPropertyNames = [];
    data.toPropertyNames = toPropertyNames = [];
    for (name in to) {
      if (to.hasOwnProperty(name)) {
        to[name] = toFormattedValue = me.formatValue(to[name], name);
        formattedName = me.formatName(name);
        isLengthProperty = isLengthPropertyMap.hasOwnProperty(name);
        if (!isLengthProperty) {
          toFormattedValue = me.getCssStyleValue(formattedName, toFormattedValue);
        }
        if (from.hasOwnProperty(name)) {
          from[name] = fromFormattedValue = me.formatValue(from[name], name);
          if (!isLengthProperty) {
            fromFormattedValue = me.getCssStyleValue(formattedName, fromFormattedValue);
          }
          if (toFormattedValue !== fromFormattedValue) {
            fromPropertyNames.push(formattedName);
            toPropertyNames.push(formattedName);
          }
        } else {
          computedValue = computedStyle.getPropertyValue(formattedName);
          if (toFormattedValue !== computedValue) {
            toPropertyNames.push(formattedName);
          }
        }
      }
    }
    propertiesLength = toPropertyNames.length;
    if (propertiesLength === 0) {
      me.onAnimationEnd(element, data, animation);
      continue;
    }
    runningData = me.getRunningData(elementId);
    runningSessions = runningData.sessions;
    if (runningSessions.length > 0) {
      me.refreshRunningAnimationsData(element, Ext.Array.merge(fromPropertyNames, toPropertyNames), true, data.replacePrevious);
    }
    runningNameMap = runningData.nameMap;
    runningNameList = runningData.nameList;
    sessionNameMap = {};
    for (j = 0; j < propertiesLength; j++) {
      name = toPropertyNames[j];
      sessionNameMap[name] = true;
      if (!runningNameMap.hasOwnProperty(name)) {
        runningNameMap[name] = 1;
        runningNameList.push(name);
      } else {
        runningNameMap[name]++;
      }
    }
    runningSession = {element:element, map:sessionNameMap, list:toPropertyNames.slice(), length:propertiesLength, data:data, animation:animation};
    runningSessions.push(runningSession);
    animation.on('stop', 'onAnimationStop', me);
    elementData = Ext.apply({}, before);
    Ext.apply(elementData, from);
    if (runningNameList.length > 0) {
      fromPropertyNames = Ext.Array.difference(runningNameList, fromPropertyNames);
      toPropertyNames = Ext.Array.merge(fromPropertyNames, toPropertyNames);
      elementData['transition-property'] = fromPropertyNames;
    }
    fromData[elementId] = elementData;
    toData[elementId] = Ext.apply({}, to);
    transitionData[elementId] = {'transition-property':toPropertyNames, 'transition-duration':data.duration, 'transition-timing-function':data.easing, 'transition-delay':data.delay};
    animation.startTime = Date.now();
  }
  me.activeElement = null;
  message = me.$className;
  me.applyStyles(fromData);
  doApplyTo = function(e) {
    if (e.data === message && e.source === window) {
      window.removeEventListener('message', doApplyTo, false);
      me.applyStyles(me.transitionQueue.toData);
    }
  };
  if (!me.messageTimerId) {
    messageTimerFn = function() {
      var messageFollowupFn;
      me.messageTimerId = null;
      if (Ext.isIE) {
        me.applyStyles(me.transitionQueue.transitionData);
        if (!me.messageFollowupId) {
          messageFollowupFn = function() {
            me.messageFollowupId = null;
            window.addEventListener('message', doApplyTo, false);
            window.postMessage(message, '*');
          };
          messageFollowupFn.$skipTimerCheck = true;
          me.messageFollowupId = Ext.raf(messageFollowupFn);
        }
      } else {
        Ext.merge(me.transitionQueue.toData, me.transitionQueue.transitionData);
        window.addEventListener('message', doApplyTo, false);
        window.postMessage(message, '*');
      }
    };
    messageTimerFn.$skipTimerCheck = true;
    me.messageTimerId = Ext.raf(messageTimerFn);
  }
  return ret;
}, onAnimationStop:function(animation) {
  var me = this, runningAnimationsData = me.runningAnimationsData, activeAnimations = 0, stoppedAnimations = 0, id, runningData, sessions, i, ln, session;
  for (id in runningAnimationsData) {
    if (runningAnimationsData.hasOwnProperty(id)) {
      runningData = runningAnimationsData[id];
      sessions = runningData.sessions;
      activeAnimations++;
      for (i = 0, ln = sessions.length; i < ln; i++) {
        session = sessions[i];
        if (session.animation === animation) {
          me.refreshRunningAnimationsData(session.element, session.list.slice(), false);
          if (animation.destroying) {
            stoppedAnimations++;
          }
        }
      }
    }
  }
  if (activeAnimations === stoppedAnimations) {
    if (me.messageFollowupId) {
      Ext.unraf(me.messageFollowupId);
      me.messageFollowupId = null;
    }
    if (me.messageTimerId) {
      Ext.unraf(me.messageTimerId);
      me.messageTimerId = null;
    }
    Ext.apply(me.transitionQueue, {toData:{}, transitionData:{}});
  }
}});
Ext.define('Ext.fx.easing.Bounce', {extend:Ext.fx.easing.Abstract, config:{springTension:0.3, acceleration:30, startVelocity:0}, getValue:function() {
  var deltaTime = Ext.Date.now() - this.getStartTime(), theta = deltaTime / this.getAcceleration(), powTime = theta * Math.pow(Math.E, -this.getSpringTension() * theta);
  return this.getStartValue() + this.getStartVelocity() * powTime;
}});
Ext.define('Ext.fx.easing.Momentum', {extend:Ext.fx.easing.Abstract, config:{acceleration:30, friction:0, startVelocity:0}, alpha:0, updateFriction:function(friction) {
  var theta = Math.log(1 - friction / 10);
  this.theta = theta;
  this.alpha = theta / this.getAcceleration();
}, updateStartVelocity:function(velocity) {
  this.velocity = velocity * this.getAcceleration();
}, updateAcceleration:function(acceleration) {
  this.velocity = this.getStartVelocity() * acceleration;
  this.alpha = this.theta / acceleration;
}, getValue:function() {
  return this.getStartValue() - this.velocity * (1 - this.getFrictionFactor()) / this.theta;
}, getFrictionFactor:function() {
  var deltaTime = Ext.Date.now() - this.getStartTime();
  return Math.exp(deltaTime * this.alpha);
}, getVelocity:function() {
  return this.getFrictionFactor() * this.velocity;
}});
Ext.define('Ext.fx.easing.BoundMomentum', {extend:Ext.fx.easing.Abstract, config:{momentum:null, bounce:null, minMomentumValue:0, maxMomentumValue:0, minVelocity:0.01, startVelocity:0}, applyMomentum:function(config, currentEasing) {
  return Ext.factory(config, Ext.fx.easing.Momentum, currentEasing);
}, applyBounce:function(config, currentEasing) {
  return Ext.factory(config, Ext.fx.easing.Bounce, currentEasing);
}, updateStartTime:function(startTime) {
  this.getMomentum().setStartTime(startTime);
  this.callParent(arguments);
}, updateStartVelocity:function(startVelocity) {
  this.getMomentum().setStartVelocity(startVelocity);
}, updateStartValue:function(startValue) {
  this.getMomentum().setStartValue(startValue);
}, reset:function() {
  this.lastValue = null;
  this.isBouncingBack = false;
  this.isOutOfBound = false;
  return this.callParent(arguments);
}, getValue:function() {
  var momentum = this.getMomentum(), bounce = this.getBounce(), startVelocity = momentum.getStartVelocity(), direction = startVelocity > 0 ? 1 : -1, minValue = this.getMinMomentumValue(), maxValue = this.getMaxMomentumValue(), boundedValue = direction === 1 ? maxValue : minValue, lastValue = this.lastValue, value, velocity;
  if (startVelocity === 0) {
    return this.getStartValue();
  }
  if (!this.isOutOfBound) {
    value = momentum.getValue();
    velocity = momentum.getVelocity();
    if (Math.abs(velocity) < this.getMinVelocity()) {
      this.isEnded = true;
    }
    if (value >= minValue && value <= maxValue) {
      return value;
    }
    this.isOutOfBound = true;
    bounce.setStartTime(Ext.Date.now()).setStartVelocity(velocity).setStartValue(boundedValue);
  }
  value = bounce.getValue();
  if (!this.isEnded) {
    if (!this.isBouncingBack) {
      if (lastValue !== null) {
        if (direction === 1 && value < lastValue || direction === -1 && value > lastValue) {
          this.isBouncingBack = true;
        }
      }
    } else {
      if (Math.round(value) === boundedValue) {
        this.isEnded = true;
      }
    }
  }
  this.lastValue = value;
  return value;
}});
Ext.define('Ext.fx.easing.EaseOut', {extend:Ext.fx.easing.Linear, alias:'easing.ease-out', config:{exponent:4, duration:1500}, getValue:function() {
  var deltaTime = Ext.Date.now() - this.getStartTime(), duration = this.getDuration(), startValue = this.getStartValue(), endValue = this.getEndValue(), distance = this.distance, theta = deltaTime / duration, thetaC = 1 - theta, thetaEnd = 1 - Math.pow(thetaC, this.getExponent()), currentValue = startValue + thetaEnd * distance;
  if (deltaTime >= duration) {
    this.isEnded = true;
    return endValue;
  }
  return currentValue;
}});
Ext.define('Ext.mixin.ItemRippler', {mixinId:'itemrippler', config:{itemRipple:null}, shouldRippleItem:function(item, e) {
  var itemRipple, ripple;
  if (e.getTarget(this.noItemRippleSelector, this.element)) {
    return false;
  }
  itemRipple = item && this.getItemRipple();
  if (itemRipple && item.isWidget) {
    ripple = item.shouldRipple(e);
    if (ripple) {
      itemRipple = Ext.apply({}, itemRipple, ripple);
    }
  }
  return itemRipple;
}, rippleItem:function(item, e) {
  if (!item) {
    return;
  }
  var me = this, start = e.type.match(me.rippleStateRe), itemRipple = me.shouldRippleItem(item, e), release = itemRipple && itemRipple.release, isRelease = release === true, el = item.isWidget ? item.el : item, pos, delta, rs, rippledItems;
  if (itemRipple && start && isRelease) {
    me.$rippleStart = e.getXY();
  }
  if (itemRipple && el && (!start && isRelease || start && release !== true)) {
    rippledItems = me.$rippledItems || (me.$rippledItems = []);
    rs = me.$rippleStart;
    if (rs) {
      pos = e.getXY();
      delta = Math.sqrt(Math.pow(pos[0] - rs[0], 2) + Math.pow(pos[1] - rs[1], 2));
      if (delta <= 8) {
        el.ripple(e, itemRipple);
        rippledItems.push(el);
      }
    } else {
      el.ripple(e, itemRipple);
      rippledItems.push(el);
    }
    me.$rippleStart = null;
  }
}, destroyAllRipples:function() {
  var items;
  for (items = this.$rippledItems; items && items.length;) {
    items.pop().destroyAllRipples();
  }
}, privates:{noItemRippleSelector:'.' + Ext.baseCSSPrefix + 'item-no-ripple, ' + '.' + Ext.baseCSSPrefix + 'item-no-tap', rippleStateRe:/start|down/}});
Ext.define('Ext.mixin.ConfigProxy', function(ConfigProxy) {
  return {extend:Ext.Mixin, mixinConfig:{id:'configproxy', extended:function(baseClass, derivedClass, classBody) {
    var proxyConfig = classBody.proxyConfig;
    derivedClass.$configProxies = Ext.apply({}, derivedClass.superclass.self.$configProxies);
    if (proxyConfig) {
      delete classBody.proxyConfig;
      ConfigProxy.processClass(derivedClass, proxyConfig);
    }
  }}, onClassMixedIn:function(targetClass) {
    var prototype = targetClass.prototype, proxyConfig = prototype.proxyConfig, initConfig = prototype.initConfig;
    prototype.$proxiedConfigs = null;
    targetClass.$configProxies = {};
    prototype.initConfig = function(config) {
      initConfig.apply(this, arguments);
      this.$proxiedConfigs = null;
      return this;
    };
    if (proxyConfig) {
      delete prototype.proxyConfig;
      ConfigProxy.processClass(targetClass, proxyConfig);
    }
  }, getProxiedConfigs:function(name) {
    var me = this, configs = me.config, configProxies = me.self.$configProxies[name], i = configProxies && configProxies.length, cfg, proxiedConfigs, ret, s, v;
    if (i && me.isConfiguring) {
      proxiedConfigs = me.$proxiedConfigs || (me.$proxiedConfigs = {});
      while (i-- > 0) {
        cfg = configProxies[i];
        proxiedConfigs[s = cfg.name] = cfg;
        if ((v = configs[s]) !== undefined) {
          (ret || (ret = {}))[s] = v;
        }
      }
    }
    return ret;
  }, mergeProxiedConfigs:function(name, itemConfig, alwaysClone) {
    var me = this, ret = itemConfig, proxied = me.getProxiedConfigs(name), configurator;
    if (proxied) {
      if (!itemConfig) {
        ret = proxied;
      } else {
        if (itemConfig.constructor === Object) {
          configurator = me.self.getConfigurator();
          ret = configurator.merge(me, Ext.clone(itemConfig), proxied);
        }
      }
    }
    if (alwaysClone && ret === itemConfig) {
      ret = Ext.clone(ret);
    }
    return ret;
  }, statics:{processClass:function(targetClass, proxyConfig) {
    var ExtConfig = Ext.Config, targetProto = targetClass.prototype, add = {}, proxies = targetClass.$configProxies, cfg, configs, itemGetter, i, item, methods, n, name, proxiedConfigs, s;
    for (item in proxyConfig) {
      itemGetter = ExtConfig.get(item).names.get;
      configs = proxyConfig[item];
      if (Ext.isArray(configs)) {
        methods = null;
      } else {
        methods = configs.methods;
        configs = configs.configs;
      }
      if (!(proxiedConfigs = proxies[item])) {
        proxies[item] = proxiedConfigs = [];
      } else {
        proxies[item] = proxiedConfigs = proxiedConfigs.slice();
      }
      for (i = 0, n = methods && methods.length; i < n; ++i) {
        if (!targetProto[name = methods[i]]) {
          targetProto[name] = ConfigProxy.wrapFn(itemGetter, name);
        } else {
          Ext.raise('Cannot proxy method "' + name + '"');
        }
      }
      for (i = 0, n = configs && configs.length; i < n; ++i) {
        cfg = ExtConfig.get(s = configs[i]);
        if (s in add) {
          Ext.raise('Duplicate proxy config definitions for "' + s + '"');
        }
        if (s in targetProto.config) {
          Ext.raise('Config "' + s + '" already defined for class ' + targetProto.$className);
        }
        add[s] = undefined;
        proxiedConfigs.push(cfg);
        if (!targetProto[name = cfg.names.get]) {
          targetProto[name] = ConfigProxy.wrapGet(itemGetter, name);
        } else {
          Ext.raise('Cannot proxy "' + s + '" config getter');
        }
        if (!targetProto[name = cfg.names.set]) {
          targetProto[name] = ConfigProxy.wrapSet(itemGetter, name, s);
        } else {
          Ext.raise('Cannot proxy "' + s + '" config setter');
        }
      }
    }
    targetClass.addConfig(add);
  }, wrapFn:function(itemGetter, name) {
    return function() {
      var item = this[itemGetter]();
      return item && item[name].apply(item, arguments);
    };
  }, wrapGet:function(itemGetter, configGetter) {
    return function() {
      var item = this[itemGetter]();
      return item && item[configGetter]();
    };
  }, wrapSet:function(itemGetter, configSetter, itemName) {
    return function(value) {
      var me = this, item, proxiedConfigs;
      if (!me.isConfiguring || value !== undefined) {
        item = me[itemGetter]();
        proxiedConfigs = me.$proxiedConfigs;
        if (proxiedConfigs && proxiedConfigs[itemName]) {
          delete proxiedConfigs[itemName];
          item = null;
        }
        if (item) {
          item[configSetter](value);
        }
      }
      return me;
    };
  }}};
});
Ext.define('Ext.mixin.StyleCacher', {extend:Ext.Mixin, mixinConfig:{id:'stylecacher'}, getCachedStyle:function(el, style) {
  var cache = this.$styleCache;
  if (!cache) {
    cache = this.$styleCache = {};
  }
  if (!(style in cache)) {
    cache[style] = Ext.fly(el).getStyle(style);
  }
  return cache[style];
}});
Ext.define('Ext.util.CSS', function() {
  var CSS, rules = null, doc = document, camelRe = /(-[a-z])/gi, camelFn = function(m, a) {
    return a.charAt(1).toUpperCase();
  };
  return {singleton:true, rules:rules, initialized:false, constructor:function() {
    CSS = this;
  }, createStyleSheet:function(cssText, id) {
    var ss, head = doc.getElementsByTagName('head')[0], styleEl = doc.createElement('style');
    styleEl.setAttribute('type', 'text/css');
    if (id) {
      styleEl.setAttribute('id', id);
    }
    ss = styleEl.styleSheet;
    if (ss) {
      head.appendChild(styleEl);
      ss.cssText = cssText;
    } else {
      styleEl.appendChild(doc.createTextNode(cssText));
      head.appendChild(styleEl);
      ss = styleEl.sheet;
    }
    CSS.cacheStyleSheet(ss);
    return ss;
  }, removeStyleSheet:function(stylesheet) {
    var styleEl = typeof stylesheet === 'string' ? doc.getElementById(stylesheet) : stylesheet.ownerNode;
    if (styleEl) {
      styleEl.parentNode.removeChild(styleEl);
    }
  }, swapStyleSheet:function(id, url) {
    var ss;
    CSS.removeStyleSheet(id);
    ss = doc.createElement('link');
    ss.setAttribute('rel', 'stylesheet');
    ss.setAttribute('type', 'text/css');
    ss.setAttribute('id', id);
    ss.setAttribute('href', url);
    doc.getElementsByTagName('head')[0].appendChild(ss);
  }, cacheStyleSheet:function(ss) {
    if (!rules) {
      rules = CSS.rules = {};
    }
    try {
      var ssRules = ss.cssRules || ss.rules, i = ssRules.length - 1, imports = ss.imports, len = imports ? imports.length : 0, rule, j;
      for (j = 0; j < len; ++j) {
        CSS.cacheStyleSheet(imports[j]);
      }
      for (; i >= 0; --i) {
        rule = ssRules[i];
        if (rule.styleSheet) {
          CSS.cacheStyleSheet(rule.styleSheet);
        }
        CSS.cacheRule(rule, ss);
      }
    } catch (e$61) {
    }
  }, cacheRule:function(cssRule, styleSheet) {
    var selectorText, selectorCount, j;
    if (cssRule.styleSheet) {
      return CSS.cacheStyleSheet(cssRule.styleSheet);
    }
    selectorText = cssRule.selectorText;
    if (selectorText) {
      selectorText = selectorText.split(',');
      selectorCount = selectorText.length;
      for (j = 0; j < selectorCount; j++) {
        rules[Ext.String.trim(selectorText[j]).toLowerCase()] = {parentStyleSheet:styleSheet, cssRule:cssRule};
      }
    }
  }, getRules:function(refreshCache) {
    var result = {}, selector;
    if (rules === null || refreshCache) {
      CSS.refreshCache();
    }
    for (selector in rules) {
      result[selector] = rules[selector].cssRule;
    }
    return result;
  }, refreshCache:function() {
    var ds = doc.styleSheets, i = 0, len = ds.length;
    rules = CSS.rules = {};
    for (; i < len; i++) {
      try {
        if (!ds[i].disabled) {
          CSS.cacheStyleSheet(ds[i]);
        }
      } catch (e$62) {
      }
    }
  }, getRule:function(selector, refreshCache, rawCache) {
    var i, result;
    if (!rules || refreshCache) {
      CSS.refreshCache();
    }
    if (!Ext.isArray(selector)) {
      result = rules[selector.toLowerCase()];
      if (result && !rawCache) {
        result = result.cssRule;
      }
      return result || null;
    }
    for (i = 0; i < selector.length; i++) {
      if (rules[selector[i]]) {
        return rawCache ? rules[selector[i].toLowerCase()] : rules[selector[i].toLowerCase()].cssRule;
      }
    }
    return null;
  }, createRule:function(styleSheet, selector, cssText) {
    var result, ruleSet = styleSheet.cssRules || styleSheet.rules, index = ruleSet.length;
    if (styleSheet.insertRule) {
      styleSheet.insertRule(selector + ' {' + cssText + '}', index);
    } else {
      styleSheet.addRule(selector, cssText || ' ');
    }
    CSS.cacheRule(result = ruleSet[index], styleSheet);
    return result;
  }, updateRule:function(selector, property, value) {
    var rule, i, styles;
    if (!Ext.isArray(selector)) {
      rule = CSS.getRule(selector);
      if (rule) {
        if (arguments.length === 2) {
          styles = Ext.Element.parseStyles(property);
          for (property in styles) {
            rule.style[property.replace(camelRe, camelFn)] = styles[property];
          }
        } else {
          rule.style[property.replace(camelRe, camelFn)] = value;
        }
        return true;
      }
    } else {
      for (i = 0; i < selector.length; i++) {
        if (CSS.updateRule(selector[i], property, value)) {
          return true;
        }
      }
    }
    return false;
  }, deleteRule:function(selector) {
    var rule = CSS.getRule(selector, false, true), styleSheet, index;
    if (rule) {
      styleSheet = rule.parentStyleSheet;
      index = Ext.Array.indexOf(styleSheet.cssRules || styleSheet.rules, rule.cssRule);
      if (styleSheet.deleteRule) {
        styleSheet.deleteRule(index);
      } else {
        styleSheet.removeRule(index);
      }
      delete rules[selector];
    }
  }};
});
Ext.define('Ext.util.ClickRepeater', {alternateClassName:'Ext.util.TapRepeater', mixins:[Ext.mixin.Observable], config:{el:null, target:null, disabled:null}, interval:20, delay:250, preventDefault:true, stopDefault:false, timer:0, handler:null, scope:null, constructor:function(config) {
  var me = this;
  if (arguments.length === 2) {
    me.setEl(config);
    config = arguments[1];
  }
  me.mixins.observable.constructor.call(this, config);
}, destroy:function() {
  this.setEl(null);
  this.callParent();
}, privates:{fireClick:function(e) {
  var me = this;
  me.fireEvent('click', me, e);
  Ext.callback(me.handler, me.scope, [me, e], 0, me.getTarget());
}, updateDisabled:function(disabled) {
  var me = this;
  if (disabled) {
    me.savedEl = me.getEl();
    me.setEl(null);
  } else {
    if (me.savedEl) {
      me.setEl(me.savedEl);
    }
  }
}, updateTarget:function(target) {
  this.setEl(target.el);
}, updateEl:function(newEl, oldEl) {
  var me = this, elListeners;
  if (oldEl) {
    oldEl.selectable();
    Ext.undefer(me.timer);
    if (me.pressedCls) {
      oldEl.removeCls(me.pressedCls);
    }
    Ext.getDoc().un('mouseup', me.handleMouseUp, me);
    me.elListeners = Ext.destroy(me.elListeners);
  }
  if (newEl) {
    newEl.unselectable();
    elListeners = {mousedown:me.handleMouseDown, scope:me, destroyable:true};
    if (me.preventDefault || me.stopDefault) {
      elListeners.click = me.eventOptions;
    }
    me.elListeners = newEl.on(elListeners);
  }
}, eventOptions:function(e) {
  if (this.preventDefault) {
    e.preventDefault();
  }
  if (this.stopDefault) {
    e.stopEvent();
  }
}, handleMouseDown:function(e) {
  var me = this, el = me.getEl();
  Ext.undefer(me.timer);
  if (me.pressedCls) {
    el.addCls(me.pressedCls);
  }
  me.mousedownTime = Ext.now();
  if (e.pointerType === 'mouse') {
    el.on('mouseout', me.handleMouseOut, me);
  }
  Ext.getDoc().on('mouseup', me.handleMouseUp, me);
  me.fireEvent('mousedown', me, e);
  me.fireClick(e);
  if (me.accelerate) {
    me.delay = 400;
  }
  me.timer = Ext.defer(me.click, me.delay || me.interval, me, [e]);
  if (me.mousedownPreventDefault) {
    e.preventDefault();
  }
  if (me.mousedownStopEvent) {
    e.stopEvent();
  }
}, click:function(e) {
  var me = this;
  me.fireClick(e);
  me.timer = Ext.defer(me.click, me.accelerate ? me.easeOutExpo(Ext.now() - me.mousedownTime, 400, -390, 12000) : me.interval, me, [e]);
}, easeOutExpo:function(t, b, c, d) {
  return t === d ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
}, handleMouseOut:function() {
  var me = this, el = me.getEl();
  Ext.undefer(me.timer);
  if (me.pressedCls) {
    el.removeCls(me.pressedCls);
  }
  el.on('mouseover', me.handleMouseReturn, me);
}, handleMouseReturn:function(e) {
  var me = this, el = me.getEl();
  el.un('mouseover', me.handleMouseReturn, me);
  if (me.pressedCls) {
    el.addCls(me.pressedCls);
  }
  me.click(e);
}, handleMouseUp:function(e) {
  var me = this, el = me.getEl();
  Ext.undefer(me.timer);
  el.un('mouseover', me.handleMouseReturn, me);
  el.un('mouseout', me.handleMouseOut, me);
  Ext.getDoc().un('mouseup', me.handleMouseUp, me);
  if (me.pressedCls) {
    el.removeCls(me.pressedCls);
  }
  me.fireEvent('mouseup', me, e);
}}});
Ext.define('Ext.util.Spans', {isSpans:true, constructor:function() {
  this.spans = this.spans || [];
}, clear:function() {
  this.spans.length = 0;
  return this;
}, add:function(begin, end) {
  if (end === undefined) {
    if (typeof begin === 'number') {
      end = begin + 1;
    } else {
      end = begin[1];
      begin = begin[0];
    }
  }
  var me = this, spans = me.spans, b, e, first, last, span;
  first = me.bisect(begin);
  if (first) {
    span = spans[first - 1];
    b = span[0];
    e = span[1];
    if (begin <= e) {
      if (end <= e) {
        return false;
      }
      begin = b;
      spans.splice(--first, 1);
    }
  }
  last = me.bisect(end);
  if (last > first) {
    span = spans[last - 1];
    end = Math.max(end, span[1]);
  }
  if (last < spans.length) {
    span = spans[last];
    if (end === span[0]) {
      end = span[1];
      ++last;
    }
  }
  spans.splice(first, last - first, [begin, end]);
  return true;
}, contains:function(begin, end) {
  if (end === undefined) {
    if (typeof begin === 'number') {
      end = begin + 1;
    } else {
      end = begin[1];
      begin = begin[0];
    }
  }
  var spans = this.spans, index = this.bisect(begin), ret = false, e, span;
  if (index && begin < (e = spans[index - 1][1])) {
    ret = end <= e;
  } else {
    if (index < spans.length) {
      span = spans[index];
      ret = span[0] <= begin && end <= span[1];
    }
  }
  return ret;
}, each:function(fn, scope) {
  var spans = this.spans, len = spans.length, i, span, j;
  for (i = 0; i < len; i++) {
    span = spans[i];
    for (j = span[0]; j < span[1]; j++) {
      if (fn.call(scope || this, i) === false) {
        return;
      }
    }
  }
}, intersects:function(begin, end) {
  if (end === undefined) {
    if (typeof begin === 'number') {
      end = begin + 1;
    } else {
      end = begin[1];
      begin = begin[0];
    }
  }
  var spans = this.spans, index = this.bisect(begin), ret = false;
  if (index && begin < spans[index - 1][1]) {
    ret = true;
  } else {
    if (index < spans.length) {
      ret = spans[index][0] < end;
    }
  }
  return ret;
}, remove:function(begin, end) {
  if (end === undefined) {
    if (typeof begin === 'number') {
      end = begin + 1;
    } else {
      end = begin[1];
      begin = begin[0];
    }
  }
  var me = this, spans = me.spans, first = me.bisect(begin), ret = false, last, span, tmp;
  if (first) {
    span = spans[first - 1];
    tmp = span[1];
    if (begin < tmp) {
      span[1] = begin;
      if (end < tmp) {
        spans.splice(first, 0, [end, tmp]);
        return true;
      }
      ret = true;
    }
  }
  last = me.bisect(end);
  if (first < last) {
    ret = true;
    span = spans[last - 1];
    if (end < span[1]) {
      span[0] = end;
      --last;
    }
    last -= first;
    if (last) {
      spans.splice(first, last);
    }
  }
  return ret;
}, stash:function() {
  return this.spans.slice();
}, unstash:function(pickle) {
  this.spans = pickle;
  return this;
}, getCount:function() {
  var spans = this.spans, len = spans.length, result = 0, i, span;
  for (i = 0; i < len; i++) {
    span = spans[i];
    result += span[1] - span[0];
  }
  return result;
}, privates:{bisect:function(value) {
  return Ext.Number.bisectTuples(this.spans, value, 0);
}}});
Ext.define('Ext.util.TaskManager', {extend:Ext.util.TaskRunner, alternateClassName:['Ext.TaskManager'], singleton:true});
Ext.define('Ext.util.TextMetrics', {statics:{shared:null, measure:function(el, text, fixedWidth) {
  var me = this, shared = me.shared || (me.shared = new me(el, fixedWidth));
  shared.bind(el);
  shared.setFixedWidth(fixedWidth || 'auto');
  return shared.getSize(text);
}, destroy:function() {
  this.shared = Ext.destroy(this.shared);
}}, constructor:function(bindTo, fixedWidth) {
  var me = this, measure = me.measure = Ext.getBody().createChild({'data-sticky':true, role:'presentation', cls:Ext.baseCSSPrefix + 'textmetrics', style:{position:'absolute', left:'-1000px', top:'-1000px', visibility:'hidden'}});
  if (bindTo) {
    me.bind(bindTo);
  }
  if (fixedWidth) {
    measure.setWidth(fixedWidth);
  }
}, getSize:function(text) {
  var measure = this.measure, size;
  measure.setHtml(text);
  size = measure.getSize();
  measure.setHtml('');
  return size;
}, bind:function(el) {
  this.measure.setStyle((this.el || (this.self.prototype.el = new Ext.dom.Fly)).attach(el).getStyle(['font-size', 'font-size-adjust', 'font-style', 'font-weight', 'font-family', 'font-kerning', 'font-stretch', 'line-height', 'text-transform', 'text-decoration', 'letter-spacing', 'word-break']));
}, setFixedWidth:function(width) {
  this.measure.setWidth(width);
}, getWidth:function(text) {
  this.measure.dom.style.width = 'auto';
  return this.getSize(text).width;
}, getHeight:function(text) {
  return this.getSize(text).height;
}, destroy:function() {
  var me = this;
  me.el = me.measure = Ext.destroy(me.measure);
  me.callParent();
}}, function() {
  Ext.Element.override({getTextWidth:function(text, min, max) {
    return Ext.Number.constrain(Ext.util.TextMetrics.measure(this.dom, Ext.valueFrom(text, this.dom.innerHTML, true)).width, min || 0, max || 1000000);
  }});
});
Ext.define('Ext.util.translatable.ScrollPosition', {extend:Ext.util.translatable.Dom, alias:'translatable.scrollposition', constructor:function(config) {
  if (config && config.element) {
    this.x = config.element.getScrollLeft();
    this.y = config.element.getScrollTop();
  }
  this.callParent([config]);
}, translateAnimated:function() {
  var element = this.getElement();
  this.x = element.getScrollLeft();
  this.y = element.getScrollTop();
  this.callParent(arguments);
}, doTranslate:function(x, y) {
  var element = this.getElement();
  element.setScrollLeft(Math.round(x));
  element.setScrollTop(Math.round(y));
}, getPosition:function() {
  var me = this, position = me.position, element = me.getElement();
  position.x = element.getScrollLeft();
  position.y = element.getScrollTop();
  return position;
}});
Ext.define('Ext.Button', {extend:Ext.Component, xtype:'button', isButton:true, cachedConfig:{buttonType:'button', iconCls:null, textAlign:null, menuAlign:'tl-bl?', destroyMenu:true, stretchMenu:false}, config:{allowDepress:true, badgeText:null, text:null, icon:false, iconAlign:'left', pressedDelay:0, menu:{lazy:true, $value:null}, arrow:null, arrowAlign:'right', handler:null, toggleHandler:null, scope:null, autoEvent:null, ui:null, enableToggle:false, value:null}, eventedConfig:{pressed:false}, preventDefaultAction:true, 
isMenuOwner:true, baseCls:Ext.baseCSSPrefix + 'button', hasMenuCls:Ext.baseCSSPrefix + 'has-menu', hoveredCls:Ext.baseCSSPrefix + 'hovered', pressedCls:Ext.baseCSSPrefix + 'pressed', pressingCls:Ext.baseCSSPrefix + 'pressing', hasBadgeCls:Ext.baseCSSPrefix + 'has-badge', hasIconCls:Ext.baseCSSPrefix + 'has-icon', hasTextCls:Ext.baseCSSPrefix + 'has-text', hasArrowCls:Ext.baseCSSPrefix + 'has-arrow', noArrowCls:Ext.baseCSSPrefix + 'no-arrow', defaultBindProperty:'text', publishes:['pressed'], element:{reference:'element', 
listeners:{click:'onClick'}}, focusable:true, focusEl:'buttonElement', ariaEl:'buttonElement', backgroundColorEl:'innerElement', focusClsEl:'el', initialize:function() {
  var me = this, el = me.el;
  me.callParent();
  if (me.getConfig('menu', true)) {
    me.addCls(me.hasMenuCls);
  }
  el.on({scope:me, touchstart:'onPress'});
  el.addClsOnOver(me.hoveredCls, me.isEnabled, me);
}, getTemplate:function() {
  return [{reference:'innerElement', cls:Ext.baseCSSPrefix + 'inner-el', children:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', children:[{cls:Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon', reference:'iconElement'}, {reference:'textElement', cls:Ext.baseCSSPrefix + 'text-el'}]}, {reference:'arrowElement', cls:Ext.baseCSSPrefix + 'arrow-el ' + Ext.baseCSSPrefix + 'font-icon'}]}, {reference:'badgeElement', cls:Ext.baseCSSPrefix + 'badge-el'}, this.getButtonTemplate()];
}, getButtonTemplate:function() {
  return {tag:'button', reference:'buttonElement', cls:Ext.baseCSSPrefix + 'button-el', listeners:{focus:'handleFocusEvent', blur:'handleBlurEvent'}};
}, shouldRipple:function() {
  var me = this, ui = me.getUi(), ripple = me.getRipple(), isFab = ui ? ui.split(' ').indexOf('fab') >= 0 : false, text, icon;
  if (!isFab && ripple && ripple.bound === undefined) {
    text = me.getText();
    icon = me.getIconCls();
    if ((!text || text.length === 0) && icon) {
      ripple = Ext.clone(ripple);
      ripple.bound = false;
      ripple.measureSelector = 'x-icon-el';
    }
  }
  return ripple;
}, isPressed:function() {
  return Boolean(this.getPressed());
}, toggle:function() {
  this.setPressed(!this.isPressed());
}, updateBadgeText:function(badgeText) {
  var me = this, el = me.el, badgeElement = me.badgeElement, hasBadgeCls = me.hasBadgeCls;
  if (badgeText) {
    badgeElement.setText(badgeText);
    el.addCls(hasBadgeCls);
  } else {
    el.removeCls(hasBadgeCls);
  }
}, updateButtonType:function(buttonType) {
  this.buttonElement.dom.setAttribute('type', buttonType);
}, updateText:function(text) {
  this.textElement.setHtml(text);
  this.toggleCls(this.hasTextCls, !!text);
}, updateHtml:function(html) {
  this.setText(html);
}, applyPressed:function(pressed) {
  return Boolean(pressed);
}, updatePressed:function(pressed) {
  var me = this, toggleHandler = me.getToggleHandler();
  if (toggleHandler && !me.isConfiguring) {
    Ext.callback(toggleHandler, me.getScope(), [me, pressed], 0, me);
  }
  me.element.toggleCls(me.pressedCls, pressed);
}, updateIcon:function(icon) {
  var me = this, element = me.iconElement, hasIconCls = me.hasIconCls;
  if (icon) {
    me.addCls(hasIconCls);
    element.setStyle('background-image', 'url(' + icon + ')');
  } else {
    element.setStyle('background-image', '');
    if (!me.getIconCls()) {
      me.removeCls(hasIconCls);
    }
  }
}, updateIconCls:function(iconCls, oldIconCls) {
  var me = this, element = me.iconElement, hasIconCls = me.hasIconCls;
  if (iconCls) {
    me.addCls(hasIconCls);
    element.replaceCls(oldIconCls, iconCls);
  } else {
    element.removeCls(oldIconCls);
    if (!me.getIcon()) {
      me.removeCls(hasIconCls);
    }
  }
}, updateIconAlign:function(iconAlign, oldIconAlign) {
  var el = this.el, prefix = Ext.baseCSSPrefix + 'icon-align-';
  el.removeCls(prefix + oldIconAlign);
  el.addCls(prefix + iconAlign);
}, _textAlignCls:{left:Ext.baseCSSPrefix + 'text-align-left', right:Ext.baseCSSPrefix + 'text-align-right', center:''}, updateTextAlign:function(textAlign, oldTextAlign) {
  var textAlignClasses = this._textAlignCls, add = textAlignClasses[textAlign || 'center'], remove = textAlignClasses[oldTextAlign || 'center'];
  this.replaceCls(remove, add);
}, updateArrowAlign:function(align, oldAlign) {
  var element = this.element, cls = Ext.baseCSSPrefix + 'arrow-align-';
  if (oldAlign) {
    element.removeCls(cls + oldAlign);
  }
  element.addCls(cls + align);
}, applyMenu:function(menu) {
  if (menu) {
    if (!menu.isMenu) {
      if (Ext.isArray(menu)) {
        menu = {items:menu};
      }
      if (!menu.xtype) {
        menu.xtype = 'menu';
      }
      menu.ownerCmp = this;
      menu = Ext.widget(menu);
    }
    this.menuMinWidth = menu.getMinWidth();
  }
  return menu;
}, updateMenu:function(menu, oldMenu) {
  var listener = {scope:this, hide:'onMenuHide'};
  if (oldMenu && !oldMenu.destroyed) {
    if (this.getDestroyMenu()) {
      oldMenu.destroy();
    } else {
      if (oldMenu.isMenu) {
        oldMenu.un(listener);
      }
    }
  }
  this.toggleCls(this.hasMenuCls, !!menu);
  if (menu && menu.isMenu) {
    menu.on(listener);
  }
}, updateArrow:function(arrow) {
  this.toggleCls(this.noArrowCls, !arrow);
  this.toggleCls(this.hasArrowCls, !!arrow);
}, applyAutoEvent:function(autoEvent) {
  var me = this;
  if (typeof autoEvent === 'string') {
    autoEvent = {name:autoEvent, scope:me.scope || me};
  }
  return autoEvent;
}, updateAutoEvent:function(autoEvent) {
  var name = autoEvent.name, scope = autoEvent.scope;
  this.setHandler(function() {
    scope.fireEvent(name, scope, this);
  });
  this.setScope(scope);
}, applyPressedDelay:function(delay) {
  if (Ext.isNumber(delay)) {
    return delay;
  }
  return delay ? 100 : 0;
}, enableFocusable:function() {
  this.buttonElement.dom.disabled = false;
  this.callParent();
}, disableFocusable:function() {
  this.callParent();
  this.buttonElement.dom.disabled = true;
}, findEventTarget:function() {
  return this.element;
}, onPress:function(e) {
  var me = this, element = this.findEventTarget(e), pressedDelay = me.getPressedDelay(), pressingCls = me.pressingCls;
  if (!me.getDisabled() && !e.button) {
    if (pressedDelay > 0) {
      me.pressedTimeout = Ext.defer(function() {
        delete me.pressedTimeout;
        if (element) {
          element.addCls(pressingCls);
        }
      }, pressedDelay);
    } else {
      element.addCls(pressingCls);
    }
    Ext.GlobalEvents.setPressedComponent(me, e);
  }
}, onRelease:function(e) {
  this.fireAction('release', [this, e], 'doRelease');
}, doRelease:function(me, e) {
  var element = me.findEventTarget(e);
  if (!me.getDisabled()) {
    if (me.hasOwnProperty('pressedTimeout')) {
      Ext.undefer(me.pressedTimeout);
      delete me.pressedTimeout;
    } else {
      if (element) {
        element.removeCls(me.pressingCls);
      }
    }
  }
}, onClick:function(e) {
  return this.onTap(e);
}, onTap:function(e) {
  if (this.getDisabled()) {
    return false;
  }
  this.fireAction('tap', [this, e], 'doTap');
}, doTap:function(me, e) {
  var menu = me.getMenu(), handler = me.getHandler();
  if (e && e.preventDefault && me.preventDefaultAction) {
    e.preventDefault();
  }
  if (menu) {
    me.toggleMenu(e, menu);
  } else {
    if ((me.getToggleHandler() || me.getEnableToggle()) && (me.getAllowDepress() || !me.isPressed())) {
      me.toggle();
    }
    if (handler) {
      Ext.callback(handler, me.getScope(), [me, e], 0, me);
    }
  }
}, onEnterKey:function(e) {
  this.onTap(e);
  e.stopEvent();
  return false;
}, onDownKey:function(e) {
  var menu = this.getMenu();
  if (menu && !this.getDisabled()) {
    this.showMenu(e, menu);
    e.stopEvent();
    return false;
  }
}, onEscKey:function(e) {
  var menu = this.getMenu();
  if (menu && !this.getDisabled() && menu.isVisible()) {
    menu.hide();
    e.stopEvent();
    return false;
  }
}, onFocus:function(e) {
  if (!this.keyHandlersAdded) {
    this.setKeyMap({scope:'this', SPACE:'onEnterKey', ENTER:'onEnterKey', DOWN:'onDownKey', ESC:'onEscKey'});
    this.keyHandlersAdded = true;
  }
  this.callParent([e]);
}, onMenuHide:function(menu) {
  if (menu.isMenu && !this.$buttonWasPressed) {
    this.setPressed(false);
  }
}, toggleMenu:function(e, menu) {
  var me = this;
  menu = menu || me.getMenu();
  if (menu) {
    if (menu.isVisible()) {
      me.hideMenu(e, menu);
    } else {
      me.showMenu(e, menu);
    }
  }
}, hideMenu:function(e, menu) {
  menu = menu || this.getMenu();
  if (menu) {
    menu.hide();
  }
}, showMenu:function(e, menu) {
  var me = this, isPointerEvent = !e || e.pointerType, pressed;
  menu = menu || me.getMenu();
  me.setupMenuStretch(menu);
  if (menu) {
    if (menu.isVisible()) {
      if (isPointerEvent) {
        menu.hide();
      } else {
        menu.focus();
      }
    } else {
      menu.autoFocus = !isPointerEvent;
      if (menu.isMenu) {
        me.$buttonWasPressed = pressed = me.getPressed();
        menu.showBy(me.element, me.getMenuAlign());
        if (!pressed) {
          me.setPressed(true);
        }
      } else {
        if (menu.isViewportMenu) {
          menu.setDisplayed(!menu.getDisplayed());
        } else {
          menu.show();
        }
      }
    }
  }
}, doDestroy:function() {
  var me = this;
  if (me.hasOwnProperty('pressedTimeout')) {
    Ext.undefer(me.pressedTimeout);
  }
  me.setMenu(null);
  me.callParent();
}, getFocusClsEl:function() {
  return this.element;
}, privates:{setupMenuStretch:function(menu) {
  var me = this;
  if (!me.menuMinWidth) {
    if (me.getStretchMenu()) {
      menu.setMinWidth(me.el.measure('w'));
    } else {
      menu.setMinWidth(null);
    }
  }
}}});
Ext.define('Ext.theme.material.Button', {override:'Ext.Button', config:{ripple:{delegate:'.' + Ext.baseCSSPrefix + 'inner-el'}}, materialIconRe:/^md-icon[-|_](.*)/, applyIconCls:function(classList) {
  var len, i, cls, materialMatch;
  if (classList) {
    classList = Ext.dom.Element.splitCls(classList);
    len = classList.length;
    for (i = 0; i < len; i++) {
      cls = classList[i];
      materialMatch = cls && cls.match(this.materialIconRe);
      if (materialMatch && materialMatch.length > 1) {
        classList.unshift('md-icon');
        break;
      }
    }
    return classList.join(' ');
  }
  return classList;
}});
Ext.define('Ext.Title', {extend:Ext.Component, xtype:'title', config:{title:''}, baseCls:Ext.baseCSSPrefix + 'title', updateTitle:function(newTitle) {
  this.setHtml(newTitle);
}});
Ext.define('Ext.Spacer', {extend:Ext.Component, xtype:'spacer', config:{}, constructor:function(config) {
  config = config || {};
  if (!config.width) {
    config.flex = 1;
  }
  this.callParent([config]);
}});
Ext.define('Ext.layout.Box', {extend:Ext.layout.Auto, alias:'layout.box', isBox:true, config:{orient:'horizontal', align:'stretch', constrainAlign:false, pack:'start', vertical:false, reverse:false, overflow:null, wrap:null}, cls:Ext.baseCSSPrefix + 'layout-box', baseItemCls:Ext.baseCSSPrefix + 'layout-box-item', constrainAlignCls:Ext.baseCSSPrefix + 'constrain-align', flexedCls:Ext.baseCSSPrefix + 'flexed', wrapClsMap:{'true':Ext.baseCSSPrefix + 'wrap', 'wrap':Ext.baseCSSPrefix + 'wrap', 'wrap-reverse':Ext.baseCSSPrefix + 
'wrap-reverse'}, boxRe:/^(?:box|hbox|vbox)$/, orientMap:{horizontal:{sizeProp:'width', containerCls:[Ext.baseCSSPrefix + 'layout-hbox', Ext.baseCSSPrefix + 'horizontal'], itemCls:Ext.baseCSSPrefix + 'layout-hbox-item'}, vertical:{sizeProp:'height', containerCls:[Ext.baseCSSPrefix + 'layout-vbox', Ext.baseCSSPrefix + 'vertical'], itemCls:Ext.baseCSSPrefix + 'layout-vbox-item'}}, constructor:function(config) {
  var me = this;
  me.callParent([config]);
  me.positionSortFn = me.positionSortFn.bind(me);
}, setConfig:function(name, value, options) {
  var config = name, type;
  if (name) {
    if (typeof name === 'string') {
      config = {};
      config[name] = value;
    } else {
      Ext.apply({}, name);
      options = value;
    }
    type = config.type;
    delete config.type;
    if (type && !this.boxRe.test(type)) {
      Ext.raise('Cannot change layout from ' + this.$className + ' to "' + type + '"');
    }
    if (config.vertical == null) {
      if (type === 'vbox') {
        config.vertical = true;
      } else {
        if (type === 'hbox') {
          config.vertical = false;
        }
      }
    }
    this.callParent([config, options]);
  }
  return this;
}, destroy:function() {
  Ext.destroy(this.getOverflow());
  this.positionSortFn = null;
  this.callParent();
}, updateContainer:function(container, oldContainer) {
  var listener = {flexchange:'onItemFlexChange', scope:this, delegate:'\x3e component'};
  this.callParent([container, oldContainer]);
  if (container) {
    container.on(listener);
  }
  if (oldContainer) {
    oldContainer.un(listener);
  }
}, updateVertical:function(vertical) {
  this.setOrient(vertical ? 'vertical' : 'horizontal');
}, applyOrient:function(orient) {
  if (orient !== 'horizontal' && orient !== 'vertical') {
    Ext.log.error("Invalid box orient of: '" + orient + "', must be either 'horizontal' or 'vertical'");
  }
  return orient;
}, updateOrient:function(orient, oldOrient) {
  var me = this, container = me.getContainer(), overflow = me.getOverflow(), renderTarget = container.getRenderTarget(), innerItems = container.innerItems, len = innerItems.length, map = me.orientMap, newMap = map[orient], oldMap = map[oldOrient], vertical = orient === 'vertical', i, itemCls, item;
  me.sizePropertyName = newMap.sizeProp;
  if (oldOrient) {
    renderTarget.removeCls(oldMap.containerCls);
    for (i = 0; i < len; ++i) {
      innerItems[i].removeCls(oldMap.itemCls);
    }
  }
  renderTarget.addCls(newMap.containerCls);
  me.itemCls = itemCls = [me.baseItemCls, newMap.itemCls];
  for (i = 0; i < len; ++i) {
    item = innerItems[i];
    item.addCls(itemCls);
  }
  me.setVertical(vertical);
  me.positionFn = vertical ? 'getTop' : 'getLeft';
  if (overflow) {
    overflow.setVertical(vertical);
  }
}, updateConstrainAlign:function(constrainAlign) {
  this.getContainer().getRenderTarget().toggleCls(this.constrainAlignCls, constrainAlign);
}, onItemInnerStateChange:function(item, isInner) {
  var me = this, flex;
  me.callParent(arguments);
  if (isInner) {
    flex = item.getFlex();
    if (flex) {
      me.setItemFlex(item, flex);
    }
  } else {
    me.setItemFlex(item, null);
  }
}, onItemFlexChange:function(item, flex) {
  if (item.isInnerItem()) {
    this.setItemFlex(item, flex);
  }
}, setItemFlex:function(item, flex) {
  var el = item.el, type = typeof flex, isNumber = type === 'number', isString = type === 'string', parts, grow;
  if (!flex || isNumber || isString) {
    if (isNumber) {
      grow = flex;
      flex = flex + ' ' + flex;
    } else {
      if (isString) {
        parts = Ext.String.splitWords(flex);
        grow = parts[0];
        if (parts.length === 1) {
          flex = grow + ' ' + grow;
        }
      }
    }
    el.setStyle('flex', flex);
  } else {
    grow = flex.grow;
    el.setStyle({flexGrow:grow, flexShrink:flex.shrink, flexBasis:flex.basis});
  }
  item.toggleCls(this.flexedCls, !!grow);
}, convertPosition:function(position) {
  var positionMap = this.positionMap;
  if (positionMap.hasOwnProperty(position)) {
    return positionMap[position];
  }
  return position;
}, applyAlign:function(align) {
  return this.convertPosition(align);
}, updateAlign:function(align, oldAlign) {
  this.getContainer().getRenderTarget().swapCls(align, oldAlign, true, Ext.baseCSSPrefix + 'align');
}, applyPack:function(pack) {
  return this.convertPosition(pack);
}, updatePack:function(pack, oldPack) {
  this.getContainer().getRenderTarget().swapCls(pack, oldPack, true, Ext.baseCSSPrefix + 'pack');
}, updateReverse:function(reverse) {
  this.getContainer().getRenderTarget().toggleCls(Ext.baseCSSPrefix + 'reverse', reverse);
}, ensureVisible:function(item, options) {
  var me = this, container, scrollable, scrollerTarget, vertical, targetInfo, itemInfo, oversized, scroll, delta, deltaX, deltaY, translatable;
  if (!item.isWidget) {
    options = item;
    item = options.item;
  }
  if (options && !isNaN(options.offset)) {
    item = this.getItemByOffset(options.offset);
  }
  if (!item) {
    return;
  }
  container = this.getContainer();
  scrollable = container.getScrollable();
  scrollerTarget = scrollable.getElement();
  vertical = me.getVertical();
  targetInfo = me.getItemInfo(scrollerTarget);
  itemInfo = me.getItemInfo(item);
  oversized = itemInfo.size > targetInfo.size;
  scroll = options && options.scroll || 'min';
  translatable = scrollable.translatable;
  if (me._currentEnsureVisibleItem === item && (translatable && translatable.isAnimating)) {
    return;
  }
  if (scroll === 'min') {
    if (!oversized && itemInfo.start < targetInfo.start || oversized && itemInfo.start > targetInfo.start) {
      delta = itemInfo.start - targetInfo.start;
    } else {
      if (!oversized && itemInfo.end > targetInfo.end || oversized && itemInfo.end < targetInfo.end) {
        delta = itemInfo.end - targetInfo.end;
      } else {
        if (oversized && itemInfo.start < targetInfo.start && itemInfo.end > targetInfo.end) {
          delta = itemInfo.start - targetInfo.start;
        }
      }
    }
  } else {
    if (itemInfo.start < targetInfo.start) {
      delta = itemInfo.end - targetInfo.end;
    } else {
      delta = itemInfo.start - targetInfo.start;
    }
  }
  if (delta) {
    deltaX = !vertical ? delta : null;
    deltaY = vertical ? delta : null;
    me._currentEnsureVisibleItem = item;
    scrollable.scrollBy(deltaX, deltaY, options.animation);
  }
}, getItemByOffset:function(indexOffset) {
  var me = this, container = this.getContainer(), scrollerTarget = container.getScrollable().getElement(), targetInfo = me.getItemInfo(scrollerTarget), items = container.getInnerItems(), len = items.length, minFrontDistance = -Infinity, minEndDistance = -Infinity, startIndex = 0, endIndex = len - 1, index, i, itemFrontDistance, itemEndDistance, item, itemInfo;
  if (!indexOffset) {
    return;
  }
  items.sort(me.positionSortFn);
  for (i = 0; i < len; i++) {
    item = items[i];
    itemInfo = me.getItemInfo(item);
    itemFrontDistance = itemInfo.start - targetInfo.start;
    itemEndDistance = targetInfo.end - itemInfo.end;
    if (itemFrontDistance > minFrontDistance && itemFrontDistance < 0 && itemEndDistance > 0) {
      minFrontDistance = itemFrontDistance;
      startIndex = i;
    }
    if (itemEndDistance > minEndDistance && itemEndDistance < 0 && itemFrontDistance > 0) {
      minEndDistance = itemEndDistance;
      endIndex = i;
      break;
    }
  }
  if (indexOffset > 0) {
    indexOffset--;
    index = endIndex += indexOffset;
    if (endIndex >= len) {
      index = len - 1;
    }
  } else {
    indexOffset++;
    index = startIndex += indexOffset;
    if (startIndex < 0) {
      index = 0;
    }
  }
  return items[index];
}, getItemInfo:function(item) {
  var me = this, vertical = me.getVertical(), el = item.el;
  return {start:el[vertical ? 'getTop' : 'getLeft'](), end:el[vertical ? 'getBottom' : 'getRight'](), size:el[vertical ? 'getHeight' : 'getWidth']()};
}, createOverflow:function(config) {
  return Ext.apply({owner:this, vertical:this.getVertical()}, config);
}, applyOverflow:function(config, existing) {
  return Ext.Factory.layoutOverflow.update(existing, config, this, 'createOverflow');
}, updateWrap:function(wrap, oldWrap) {
  var me = this, el = me.getContainer().getRenderTarget(), map = me.wrapClsMap, cls;
  if (oldWrap) {
    cls = map[oldWrap];
    if (cls) {
      el.removeCls(cls);
    }
  }
  if (wrap) {
    cls = map[wrap];
    if (cls) {
      el.addCls(cls);
    }
  }
}, privates:{positionSortFn:function(a, b) {
  var fn = this.positionFn;
  a = a.el[fn]();
  b = b.el[fn]();
  if (a < b) {
    return -1;
  } else {
    if (b < a) {
      return 1;
    }
  }
  return 0;
}}});
Ext.define('Ext.Toolbar', {extend:Ext.Container, xtype:'toolbar', isToolbar:true, config:{title:null, defaultType:'button', defaultButtonUI:null, minHeight:null, layout:{type:'box', align:'center'}}, statics:{shortcuts:{'-\x3e':true}}, autoSize:null, border:false, classCls:Ext.baseCSSPrefix + 'toolbar', constructor:function(config) {
  config = config || {};
  if (config.docked === 'left' || config.docked === 'right') {
    config.layout = Ext.apply({type:'box', align:'stretch', vertical:true}, config.layout);
  }
  this.callParent([config]);
}, applyTitle:function(title) {
  if (typeof title === 'string') {
    title = {title:title, centered:true};
  }
  return Ext.factory(title, Ext.Title, this.getTitle());
}, updateTitle:function(newTitle, oldTitle) {
  if (newTitle) {
    this.add(newTitle);
  }
  if (oldTitle) {
    oldTitle.destroy();
  }
}, showTitle:function() {
  var title = this.getTitle();
  if (title) {
    title.show();
  }
}, hideTitle:function() {
  var title = this.getTitle();
  if (title) {
    title.hide();
  }
}, onItemAdd:function(item, index) {
  var defaultButtonUI = this.getDefaultButtonUI();
  if (defaultButtonUI) {
    if (item.isSegmentedButton) {
      if (item.getDefaultUI() == null) {
        item.setDefaultUI(defaultButtonUI);
      }
    } else {
      if (item.isButton && item.getUi() == null) {
        item.setUi(defaultButtonUI);
      }
    }
  }
  this.callParent([item, index]);
}, factoryItem:function(config) {
  if (config === '-\x3e') {
    config = {xtype:'component', flex:1};
  }
  return this.callParent([config]);
}});
Ext.define('Ext.panel.Buttons', function() {
  var platformTags = Ext.platformTags, isMacOrAndroid = platformTags.ios || platformTags.mac || platformTags.android;
  return {isOKFirst:!isMacOrAndroid, config:{buttonAlign:null, buttonDefaults:null, buttons:null, minButtonWidth:75, standardButtons:{ok:{text:'OK', weight:isMacOrAndroid ? 120 : 10}, abort:{text:'Abort', weight:isMacOrAndroid ? 110 : 20}, retry:{text:'Retry', weight:isMacOrAndroid ? 100 : 30}, ignore:{text:'Ignore', weight:isMacOrAndroid ? 90 : 40}, yes:{text:'Yes', weight:isMacOrAndroid ? 80 : 50}, no:{text:'No', weight:isMacOrAndroid ? 70 : 60}, cancel:{text:'Cancel', weight:isMacOrAndroid ? 60 : 
  70}, apply:{text:'Apply', weight:isMacOrAndroid ? 50 : 80}, save:{text:'Save', weight:isMacOrAndroid ? 40 : 90}, submit:{text:'Submit', weight:isMacOrAndroid ? 30 : 100}, help:{text:'Help', weight:isMacOrAndroid ? 10 : 110}, close:{text:'Close', weight:isMacOrAndroid ? 20 : 120}}}, _packButtonAlign:{left:'start', right:'end', center:'center'}, updateButtonAlign:function(buttonAlign) {
    var pack, buttonsCt = this._buttons;
    if (buttonAlign && buttonsCt) {
      pack = this._packButtonAlign[buttonAlign];
      if (pack) {
        buttonsCt.getLayout().setPack(pack);
      }
    }
  }, applyButtons:function(buttons, oldButtons) {
    var me = this, array = Ext.convertKeyedItems(buttons, 'xxx', 'xxx'), buttonDefaults = me.getButtonDefaults(), standardButtons = me.getStandardButtons(), n = array ? array.length : 0, button, defaults, handler, i;
    if (buttons && typeof buttons === 'object') {
      if (buttons.xtype || buttons.itemId || buttons.items || buttons.reference) {
        return me.adjustButtons(buttons, oldButtons);
      }
    }
    if (buttons) {
      if (array === buttons) {
        array = [];
        for (i = 0; i < n; ++i) {
          button = buttons[i];
          if (typeof button === 'string') {
            if (!Ext.Toolbar.shortcuts[button]) {
              button = Ext.applyIf({itemId:button, text:button}, buttonDefaults);
            }
          } else {
            if (buttonDefaults) {
              button = Ext.apply({}, button, buttonDefaults);
            }
          }
          array[i] = button;
        }
      } else {
        for (i = 0; i < n; ++i) {
          button = array[i];
          handler = button.xxx;
          defaults = standardButtons[button.itemId];
          if (defaults) {
            Ext.applyIf(button, defaults);
          } else {
            if (handler) {
              Ext.raise('Button handler short-hand is only valid for standardButtons');
            }
          }
          if (handler) {
            delete button.xxx;
            button.handler = handler;
          }
          if (buttonDefaults) {
            Ext.applyIf(button, buttonDefaults);
          }
        }
      }
    }
    return me.adjustButtons(array, oldButtons);
  }, onClassMixedIn:function(targetClass) {
    var proto = targetClass.prototype, buttons = proto.buttons;
    if (buttons) {
      delete proto.buttons;
      targetClass.addConfig({buttons:buttons});
    }
  }, privates:{normalizeButtonBar:function(toolbar, previous, docked, buttonsCtConfig, disableFocusableContainer) {
    var me = this, isComponent, buttonAlign, buttonToolbarDefaults, index, layout, minButtonWidth, pack;
    if (!toolbar) {
      if (previous) {
        previous.destroy();
      }
      return toolbar;
    }
    isComponent = toolbar.isComponent;
    if (Ext.isArray(toolbar)) {
      toolbar = {xtype:'toolbar', items:toolbar};
    } else {
      if (!isComponent) {
        toolbar = Ext.clone(toolbar);
      }
    }
    if (!isComponent) {
      toolbar.$initParent = me;
      toolbar.parent = me;
      if (!toolbar.xtype) {
        toolbar.xtype = 'toolbar';
      }
    }
    if (isComponent) {
      toolbar.setDocked(docked);
    } else {
      if (docked) {
        toolbar.docked = docked;
      }
    }
    if (disableFocusableContainer) {
      if (isComponent) {
        toolbar.setEnableFocusableContainer(false);
      } else {
        toolbar.enableFocusableContainer = false;
      }
    }
    if (buttonsCtConfig && !isComponent) {
      if (buttonsCtConfig.xtype) {
        delete toolbar.xtype;
      }
      toolbar = Ext.merge(Ext.clone(buttonsCtConfig), toolbar);
      toolbar.layout = Ext.merge(layout = {}, toolbar.layout);
      buttonAlign = me.getButtonAlign();
      if (buttonAlign) {
        pack = me._packButtonAlign[buttonAlign];
        if (pack) {
          layout.pack = pack;
        }
      }
      minButtonWidth = this.getMinButtonWidth();
      buttonToolbarDefaults = toolbar.defaults;
      toolbar.defaults = function(config) {
        var defaults = buttonToolbarDefaults || {}, isButton = !config.xtype || config.isButton, cls;
        if (!isButton) {
          cls = Ext.ClassManager.getByAlias('widget.' + config.xtype);
          if (cls) {
            isButton = cls.prototype.isButton;
          }
        }
        if (isButton && minButtonWidth && !('minWidth' in defaults)) {
          defaults = Ext.apply({minWidth:minButtonWidth}, defaults);
        }
        return defaults;
      };
    }
    if (previous) {
      index = me.indexOf(previous);
      previous.destroy();
      toolbar = me.insert(index, toolbar);
    } else {
      toolbar = me.add(toolbar);
    }
    return toolbar;
  }}};
});
Ext.define('Ext.Tool', {extend:Ext.Component, alternateClassName:'Ext.panel.Tool', xtype:['tool', 'paneltool'], isPanelTool:true, isTool:true, focusable:true, tabIndex:0, focusEl:'element', ariaEl:'element', inheritUi:true, classCls:Ext.baseCSSPrefix + 'tool', pressedCls:Ext.baseCSSPrefix + 'pressed', hoveredCls:Ext.baseCSSPrefix + 'hovered', passiveCls:Ext.baseCSSPrefix + 'passive', element:{reference:'element', tabIndex:0, listeners:{click:'onClick', mousedown:'onMouseDown', mouseover:'onMouseOver', 
mouseout:'onMouseOut'}, children:[{reference:'iconElement', cls:Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon'}]}, handler:null, scope:null, toolOwner:null, config:{iconCls:null, type:null, passive:null}, stopEvent:true, weight:10, updateIconCls:function(iconCls, oldValue) {
  this.iconElement.replaceCls(oldValue, iconCls);
}, updateType:function(type, oldType) {
  var me = this, baseCls = Ext.Tool.prototype.classCls, iconElement = me.iconElement;
  me.type = type;
  iconElement.replaceCls(oldType && baseCls + '-type-' + oldType, type && baseCls + '-type-' + type);
}, updateDisabled:function(disabled, oldDisabled) {
  this.callParent([disabled, oldDisabled]);
  this.el.removeCls([this.hoveredCls, this.pressedCls]);
}, updatePassive:function(passive) {
  var me = this;
  me.setDisabled(passive);
  me.el.toggleCls(me.passiveCls, passive);
  me.el.setTabIndex(passive ? null : me.getTabIndex());
  me.focusable = !passive;
}, shouldRipple:function(e) {
  return !this.getPassive() && this.callParent();
}, privates:{_toolTypes:{close:1, collapse:1, disclosure:1, down:1, expand:1, gear:1, help:1, left:1, maximize:1, minimize:1, minus:1, menu:1, next:1, pin:1, plus:1, prev:1, print:1, refresh:1, restore:1, right:1, save:1, search:1, toggle:1, unpin:1, up:1}, invokeToolHandler:function(me, handler, scope, args, ev) {
  if (handler) {
    Ext.callback(handler, me.scope, args, 0, me);
  }
  me.fireEvent('click', me, ev, me.toolOwner || me.ownerCt);
  return true;
}, onClick:function(ev) {
  var me = this, handler = me.handler || me.callback, toolOwner = me.toolOwner, args, invoker;
  if (me.getDisabled()) {
    return false;
  }
  if (me.stopEvent !== false) {
    ev.stopEvent();
  }
  args = [me.parent, me, ev];
  if (toolOwner) {
    args[0] = toolOwner;
    if (toolOwner.augmentToolHandler) {
      toolOwner.augmentToolHandler(me, args);
    }
  }
  invoker = toolOwner && toolOwner.invokeToolHandler ? toolOwner : me;
  return invoker.invokeToolHandler(me, handler, me.scope, args, ev);
}, onMouseDown:function(e) {
  var me = this;
  if (!me.focusable) {
    e.preventDefault();
  }
  if (me.getDisabled()) {
    return false;
  }
  me.addCls(me.pressedCls);
  Ext.GlobalEvents.setPressedComponent(me, e);
}, onRelease:function() {
  this.removeCls(this.pressedCls);
}, onMouseOver:function() {
  if (this.getDisabled()) {
    return false;
  }
  this.addCls(this.hoveredCls);
}, onMouseOut:function() {
  this.removeCls(this.hoveredCls);
}}});
Ext.define('Ext.theme.material.Tool', {override:'Ext.Tool', config:{ripple:{bound:false, color:'default', centered:true}}});
Ext.define('Ext.mixin.Toolable', {mixinId:'toolable', config:{defaultToolWeights:{cached:true, $value:{toggle:10, gear:20, prev:30, next:40, left:50, right:60, down:70, up:80, refresh:90, disclosure:100, plus:100, minus:110, search:120, edit:125, save:130, print:140, expand:150, collapse:160, help:170, pin:180, unpin:190, minimize:200, maximize:210, restore:220, close:230, trash:240}}, toolDefaults:{xtype:'tool', zone:'end'}, tools:null}, toolAnchorName:'bodyElement', afterClassMixedIn:function(targetClass) {
  var proto = targetClass.prototype, already = proto.toolDefaults, getRefItems = proto.getRefItems;
  if (already) {
    delete proto.toolDefaults;
    targetClass.getConfigurator().add({toolDefaults:Ext.apply({xtype:'tool', weight:0, zone:'end'}, already)});
  }
  already = proto.tools;
  if (already) {
    delete proto.tools;
    targetClass.getConfigurator().add({tools:already});
  }
  if (getRefItems) {
    proto.getRefItems = function(deep) {
      return Ext.Array.push(getRefItems.call(this, deep), this.getTools() || Ext.emptyArray);
    };
  } else {
    proto.getRefItems = function() {
      return this.getTools() || Ext.emptyArray;
    };
  }
}, lookupTool:function(id) {
  var tools = this.getTools(), n = tools && tools.length, i, tool;
  for (i = 0; i < n; ++i) {
    tool = tools[i];
    if (tool.type === id || tool.getItemId() === id) {
      return tool;
    }
  }
  return null;
}, addTool:function(tool) {
  var me = this, tools = me.getTools(), before, zone;
  if (!tools || !tools.length) {
    me.setTools([tool]);
    tool = me.getTools()[0];
  } else {
    tools.push(tool = me.instantiateTool(tool));
    Ext.sortByWeight(tools);
    before = tools[tools.indexOf(tool) + 1];
    zone = tool.zone;
    before = before && before.zone === zone ? before.el.dom : null;
    me.getToolZone(zone).el.insertBefore(tool.el, before);
  }
  return tool;
}, applyTools:function(tools) {
  if (tools) {
    var me = this, array = me.createTools(tools), n = array.length, i, tool;
    Ext.sortByWeight(array);
    for (i = 0; i < n; ++i) {
      array[i] = tool = me.instantiateTool(array[i]);
      me.getToolZone(tool.zone).el.appendChild(tool.el);
    }
    tools = array;
  }
  return tools;
}, instantiateTool:function(tool) {
  if (!tool.isTool) {
    tool = Ext.clone(tool);
  }
  tool.ownerCmp = tool.toolOwner = this;
  if (!tool.isTool) {
    tool = Ext.create(tool);
  }
  tool.doInheritUi();
  tool.addCls(this._toolPositionClsMap[tool.zone]);
  return tool;
}, updateTools:function(tools, oldTools) {
  Ext.destroy(oldTools);
}, privates:{_toolZoneNames:{end:'_endZone', head:'_headZone', start:'_startZone', tail:'_tailZone'}, _tailedCls:Ext.baseCSSPrefix + 'tailed', _headedCls:Ext.baseCSSPrefix + 'headed', _toolZoneCls:Ext.baseCSSPrefix + 'tool-zone', _toolZoneClsMap:{end:Ext.baseCSSPrefix + 'end', head:Ext.baseCSSPrefix + 'head', tail:Ext.baseCSSPrefix + 'tail', start:Ext.baseCSSPrefix + 'start'}, _toolPositionClsMap:{end:Ext.baseCSSPrefix + 'end', head:Ext.baseCSSPrefix + 'start', tail:Ext.baseCSSPrefix + 'end', start:Ext.baseCSSPrefix + 
'start'}, _toolDockAlignCls:{left:Ext.baseCSSPrefix + 'align-left', center:Ext.baseCSSPrefix + 'align-center', right:Ext.baseCSSPrefix + 'align-right'}, hasToolZones:false, adjustToolDefaults:function(tool, toolDefaults, defaultToolWeights) {
  toolDefaults = toolDefaults || this.getToolDefaults();
  if (defaultToolWeights === undefined) {
    defaultToolWeights = this.getDefaultToolWeights();
  }
  if (toolDefaults) {
    Ext.applyIf(tool, toolDefaults);
    tool.instanceCls = this.toolCls;
  }
  if (!tool.type && !tool.iconCls) {
    tool.type = tool.itemId;
  }
  if (defaultToolWeights && !('weight' in tool)) {
    tool.weight = defaultToolWeights[tool.type];
  }
  return tool;
}, createTools:function(tools, toolOwner) {
  var me = this, array = Ext.convertKeyedItems(tools, 'handler', 'handler'), n = array.length, defaultToolWeights = me.getDefaultToolWeights(), toolDefaults = me.getToolDefaults(), i, tool;
  toolOwner = toolOwner || me;
  if (array === tools) {
    array = [];
    for (i = 0; i < n; ++i) {
      tool = tools[i];
      if (typeof tool === 'string') {
        tool = me.adjustToolDefaults({type:tool}, toolDefaults, null);
      } else {
        tool = Ext.apply(me.adjustToolDefaults({}, toolDefaults, null), tool);
      }
      tool.toolOwner = toolOwner;
      array[i] = tool;
    }
  } else {
    for (i = 0; i < n; ++i) {
      me.adjustToolDefaults(tool = array[i], toolDefaults, defaultToolWeights);
      tool.toolOwner = toolOwner;
    }
  }
  return array;
}, getToolZone:function(zoneName) {
  var me = this, zonePropName = me._toolZoneNames[zoneName], zone = me[zonePropName], dockWrapName = '_toolDockWrap', anchorElement;
  if (!zonePropName) {
    Ext.raise('Invalid zone name: "' + zoneName + '"');
  }
  if (!zone) {
    zone = Ext.Element.create({classList:[me._toolZoneCls, me._toolZoneClsMap[zoneName]]});
    anchorElement = me[me.toolAnchorName];
    if (!anchorElement) {
      Ext.raise('Invalid tool anchor. No element named "' + me.toolAnchorName + '".');
    }
    if (!me[dockWrapName]) {
      me[dockWrapName] = anchorElement.wrap({cls:Ext.baseCSSPrefix + 'tool-dock'});
      anchorElement.addCls(Ext.baseCSSPrefix + 'tool-anchor');
      me.initUiReference(dockWrapName, 'tool-dock');
      me.syncToolableAlign();
    }
    if (zoneName === 'head') {
      zone.insertBefore(anchorElement);
      anchorElement.addCls(me._headedCls);
    } else {
      if (zoneName === 'tail') {
        zone.insertAfter(anchorElement);
        anchorElement.addCls(me._tailedCls);
      } else {
        if (zoneName === 'start') {
          zone.insertBefore(me._headZone || anchorElement);
        } else {
          if (zoneName === 'end') {
            zone.insertAfter(me._tailZone || anchorElement);
          }
        }
      }
    }
    me[zonePropName] = zone;
    me.hasToolZones = true;
  }
  return zone;
}, syncToolableAlign:function() {
  var me = this, dockWrap = me._toolDockWrap, alignCls = me._toolDockAlignCls, align;
  if (dockWrap && typeof me.getAlign === 'function') {
    align = me.getAlign();
    dockWrap.replaceCls(alignCls[me._toolDockAlign], alignCls[align]);
    me._toolDockAlign = align;
  }
}, doDestroy:function() {
  var me = this;
  me.setTools(null);
  Ext.destroy(me._startZone, me._endZone, me._headZone, me._tailZone, me._toolDockWrap);
}}});
Ext.define('Ext.Panel', {extend:Ext.Container, xtype:'panel', alternateClassName:'Ext.panel.Panel', isPanel:true, mixins:[Ext.panel.Buttons, Ext.mixin.Toolable], defaultBindProperty:'title', config:{headerPosition:'top', header:null, icon:null, iconCls:null, iconAlign:null, title:null, titleAlign:null, anchor:null, anchorPosition:null, closable:null, bbar:null, lbar:null, rbar:null, tbar:null}, cachedConfig:{border:false, bodyBorder:null, bodyPadding:null, bodyStyle:null, buttonToolbar:{xtype:'toolbar', 
itemId:'buttonToolbar', docked:'bottom', defaultType:'button', weighted:true, ui:'footer', defaultButtonUI:'action', layout:{type:'box', vertical:false, pack:'center'}}, closeAction:'destroy', closeToolText:'Close panel'}, classCls:Ext.baseCSSPrefix + 'panel', headerCls:null, titleCls:null, toolCls:Ext.baseCSSPrefix + 'paneltool', sideCls:{top:Ext.baseCSSPrefix + 'top', right:Ext.baseCSSPrefix + 'right', bottom:Ext.baseCSSPrefix + 'bottom', left:Ext.baseCSSPrefix + 'left'}, manageBorders:true, allowHeader:true, 
template:[{reference:'bodyWrapElement', cls:Ext.baseCSSPrefix + 'body-wrap-el', uiCls:'body-wrap-el', children:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', uiCls:'body-el'}]}], initialize:function() {
  var me = this, scrollable;
  me.callParent();
  scrollable = me.getScrollable();
  if (scrollable && scrollable.isVirtualScroller) {
    scrollable.setAutoRefresh(true);
  }
}, addBodyCls:function(cls) {
  this.bodyElement.addCls(cls);
  return this;
}, removeBodyCls:function(cls) {
  this.bodyElement.removeCls(cls);
  return this;
}, applyBodyPadding:function(bodyPadding) {
  if (bodyPadding === true) {
    bodyPadding = 5;
  }
  if (bodyPadding) {
    bodyPadding = Ext.dom.Element.unitizeBox(bodyPadding);
  }
  return bodyPadding;
}, applyBodyStyle:function(bodyStyle, oldBodyStyle) {
  if (oldBodyStyle && bodyStyle === oldBodyStyle && Ext.isObject(oldBodyStyle)) {
    bodyStyle = Ext.apply({}, bodyStyle);
  }
  this.bodyElement.applyStyles(bodyStyle);
  return null;
}, getBodyStyle:function() {
  Ext.Error.raise("'bodyStyle' is a write-only config.  To query element styles use the " + 'Ext.dom.Element API.');
}, addTool:function(tool) {
  var header = this.ensureHeader(), items;
  if (header) {
    items = this.createTools(Ext.Array.from(tool));
    if (items && items.length) {
      items = header.add(items);
    }
  }
  return items;
}, applyHeader:function(newHeader, oldHeader) {
  var me = this, header = oldHeader, isTrue;
  me.allowHeader = newHeader !== false;
  if (oldHeader && !newHeader) {
    header = Ext.destroy(header);
  }
  if (newHeader && me.allowHeader) {
    isTrue = newHeader === true;
    if (header) {
      if (!isTrue) {
        header.setConfig(newHeader);
      }
    } else {
      if (isTrue) {
        newHeader = {};
      }
      newHeader.$initParent = me;
      header = Ext.factory(me.createHeader(newHeader));
      me.header = header;
      delete header.$initParent;
      delete newHeader.$initParent;
      header.ownerCmp = me;
      (me.maxHeightElement || me.el).insertFirst(header.el);
      header.doInheritUi();
    }
  }
  return header || null;
}, updateHeader:function(header) {
  if (header) {
    this.positionHeader(header);
  } else {
    this.syncBorders();
  }
}, applyTools:function(tools) {
  var header = this.ensureHeader(), items;
  if (header) {
    header.clearTools();
    items = this.createTools(tools);
    if (items && items.length) {
      header.add(items);
    }
  }
}, close:function() {
  var me = this, action = me.getCloseAction(), destroy = action === 'destroy';
  if (me.fireEvent('beforeclose', me) !== false) {
    if (action && !destroy) {
      me[action]();
    }
    me.fireEvent('close', me);
    if (destroy) {
      me.destroy();
    }
  }
}, createHeader:function(config) {
  var me = this, ret = {xtype:'panelheader', instanceCls:me.headerCls, docked:'top'}, icon, title;
  me._isCreatingHeader = true;
  if (config && config !== true) {
    Ext.merge(ret, config);
  }
  if (me.initialized) {
    title = me.getTitle();
    if (title != null) {
      if (typeof title === 'string') {
        title = {text:title};
      }
      Ext.merge(ret, {title:title});
    }
    icon = me.getIconCls();
    if (icon != null) {
      ret.iconCls = icon;
    } else {
      icon = me.getIcon();
      if (icon != null) {
        ret.icon = icon;
      }
    }
  }
  me._isCreatingHeader = false;
  return ret;
}, applyAnchor:function(anchor, oldAnchor) {
  var me = this, el = me.el.dom, svgEl, pathEl;
  if (anchor) {
    if (oldAnchor) {
      return;
    } else {
      anchor = me.el.insertFirst({cls:Ext.baseCSSPrefix + 'anchor-el'});
      svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
      svgEl.setAttribute('class', Ext.baseCSSPrefix + 'pointer-el');
      pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      svgEl.appendChild(pathEl);
      anchor.dom.appendChild(svgEl);
    }
    el.style.overflow = 'visible';
  } else {
    if (oldAnchor) {
      me.anchorSize = oldAnchor.destroy();
      el.style.overflow = '';
    }
  }
  return anchor;
}, initAnchor:function() {
  var me = this, anchor = me.getAnchor(), cls = me.sideCls.top, svgEl = anchor.dom.firstChild, pathEl = svgEl.firstChild, anchorSize;
  anchor.addCls(cls);
  anchor.show();
  anchorSize = anchor.measure();
  me.anchorSize = anchorSize = new Ext.util.Offset(anchorSize.width, anchorSize.height);
  me.anchorMargin = parseFloat(anchor.getStyle('marginLeft')) || 0;
  anchor.dom.style.margin = '0';
  svgEl.setAttribute('height', anchorSize.y);
  svgEl.setAttribute('width', anchorSize.x);
  pathEl.setAttribute('d', 'M0 ' + anchorSize.y + ' L' + anchorSize.x / 2 + ' 0.5 L' + anchorSize.x + ' ' + anchorSize.y);
  anchorSize.y -= parseFloat(Ext.fly(pathEl).getStyle('stroke-width'));
  anchor.removeCls(cls);
  anchor.hide();
}, updateAnchorPosition:function(anchorPosition, oldAnchorPosition) {
  var me = this, anchorEl = me.getAnchor(), sideCls = me.sideCls;
  if (anchorEl) {
    if (oldAnchorPosition) {
      anchorEl.removeCls(sideCls[oldAnchorPosition.side]);
    }
    if (anchorPosition) {
      anchorEl.addCls(sideCls[anchorPosition.side]);
      anchorEl.translate(anchorPosition.x, anchorPosition.y);
      anchorEl.show();
    } else {
      anchorEl.hide();
    }
  }
}, updateBorder:function(border, oldBorder) {
  var me = this;
  me.callParent([border, oldBorder]);
  if (me.getBodyBorder() === null) {
    me.setBodyBorderEnabled(border !== false);
  }
  me.syncBorders();
}, updateBodyPadding:function(newBodyPadding) {
  this.bodyElement.setStyle('padding', newBodyPadding);
}, updateBodyBorder:function(bodyBorder) {
  var me = this;
  bodyBorder = bodyBorder === null ? me.getBorder() : bodyBorder;
  me.setBodyBorderEnabled(bodyBorder !== false);
  me.syncBorders();
}, updateClosable:function(closable) {
  var me = this, tools;
  if (closable) {
    tools = me.addTool({type:'close', weight:1000, scope:me, handler:'onCloseTool', tooltip:me.getCloseToolText(), $internal:true});
    if (tools && tools.length) {
      me.closeTool = tools[0];
    }
  } else {
    Ext.destroy(me.closeTool);
  }
}, updateHeaderPosition:function(headerPosition, oldHeaderPosition) {
  this.moveHeaderPosition(headerPosition, oldHeaderPosition);
}, updateIcon:function(icon) {
  var header = this.ensureHeader();
  if (header) {
    header.setIcon(icon);
  }
}, updateIconCls:function(iconCls) {
  var header = this.ensureHeader();
  if (header) {
    header.setIconCls(iconCls);
  }
}, updateIconAlign:function(iconAlign) {
  var header = this.ensureHeader();
  if (header) {
    header.setIconAlign(iconAlign);
  }
}, applyBbar:function(toolbar, previous) {
  return this.normalizeButtonBar(toolbar, previous, 'bottom');
}, applyLbar:function(toolbar, previous) {
  return this.normalizeButtonBar(toolbar, previous, 'left');
}, applyRbar:function(toolbar, previous) {
  return this.normalizeButtonBar(toolbar, previous, 'right');
}, applyTbar:function(toolbar, previous) {
  return this.normalizeButtonBar(toolbar, previous, 'top');
}, updateTitle:function(title) {
  var header = this.ensureHeader(), tab = this.tab;
  if (header) {
    header.setTitle(title);
  }
  if (tab && tab.isTab && !tab.destroying && !tab.destroyed) {
    tab.setText(title);
  }
}, updateTitleAlign:function(titleAlign) {
  var header = this.ensureHeader();
  if (header) {
    header.setTitleAlign(titleAlign);
  }
}, updateUi:function(ui, oldUi) {
  this.callParent([ui, oldUi]);
  if (this.hasResizable) {
    this.onResizableUiChange(ui, oldUi);
  }
  this.anchorSize = null;
}, alignTo:function(component, alignment, options) {
  var me = this, anchorElement = me.getAnchor(), config = me.initialConfig, positioned = me.isPositioned(), setX = positioned ? me.setLeft : me.setX, setY = positioned ? me.setTop : me.setY, x, y, target, anchorMargin, alignmentInfo, resultRegion, oldHeight, parent;
  if (anchorElement) {
    if (!me.anchorSize) {
      me.initAnchor();
    }
  } else {
    return me.callParent([component, alignment, options]);
  }
  anchorMargin = me.anchorMargin;
  target = component.isRegion ? component : (component.isWidget ? component.el : Ext.fly(component)).getRegion();
  target.adjust(-anchorMargin, anchorMargin, anchorMargin, -anchorMargin);
  alignmentInfo = me.getAlignmentInfo(target, alignment);
  if (alignmentInfo.isAligned) {
    return;
  }
  parent = me.getParent();
  if (!me.getFloated()) {
    if (!parent) {
      me.setFloated(true);
    } else {
      me.positioned = true;
    }
  }
  if ('unconstrainedWidth' in me) {
    me.setWidth(me.unconstrainedWidth);
  }
  if ('unconstrainedHeight' in me) {
    me.setHeight(me.unconstrainedHeight);
  }
  me.alignToArgs = [component, alignment, options];
  resultRegion = me.getAlignRegion(target, alignment, Ext.apply({anchorSize:me.anchorSize, axisLock:me.getAxisLock()}, options));
  if (resultRegion) {
    setX.call(me, resultRegion.x);
    setY.call(me, resultRegion.y);
    if (resultRegion.constrainWidth) {
      me.unconstrainedWidth = config.width || me.self.prototype.width;
      oldHeight = me.el.getHeight();
      me.setWidth(alignmentInfo.stats.width = resultRegion.getWidth());
      if (resultRegion.align.position === 0) {
        setY.call(me, resultRegion.y + (oldHeight - me.el.getHeight()));
      }
    }
    if (resultRegion.constrainHeight) {
      me.unconstrainedHeight = config.height || me.self.prototype.height;
      me.setHeight(alignmentInfo.stats.height = resultRegion.getHeight());
    }
    if (resultRegion.anchor) {
      x = 0;
      y = 0;
      if (resultRegion.anchor.align & 1) {
        y = resultRegion.anchor.y - resultRegion.y;
      } else {
        x = resultRegion.anchor.x - resultRegion.x;
      }
      me.setAnchorPosition({side:resultRegion.anchor.position, x:x, y:y});
    } else {
      me.setAnchorPosition(null);
    }
    me.setCurrentAlignmentInfo(alignmentInfo);
  } else {
    if (anchorElement) {
      anchorElement.show();
    }
  }
  if (!me.viewportResizeListener) {
    me.viewportResizeListener = Ext.on({resize:'onViewportResize', scope:me, destroyable:true});
  }
}, getRefItems:function(deep) {
  var items = this.callParent([deep]), header = this.getConfig('header', false, true);
  if (header) {
    if (deep && header.getRefItems) {
      items.unshift.apply(items, header.getRefItems(deep));
    }
    items.unshift(header);
  }
  return items;
}, onCloseTool:function() {
  this.close();
}, onRender:function() {
  var me = this, header;
  me.callParent();
  header = me.getHeader();
  if (header) {
    header.setRendered(true);
  }
  if (me.hasCollapsible) {
    me.onCollapsibleRendered();
  }
}, doDestroy:function() {
  Ext.destroy(this.header, this.anchor);
  this.callParent();
}, privates:{headerPositionMap:{top:{cls:Ext.baseCSSPrefix + 'header-position-top', dom:0, horz:true}, right:{cls:Ext.baseCSSPrefix + 'header-position-right', dom:1, vert:true}, bottom:{cls:Ext.baseCSSPrefix + 'header-position-bottom', dom:1, horz:true}, left:{cls:Ext.baseCSSPrefix + 'header-position-left', dom:0, vert:true}}, adjustButtons:function(buttons, oldButtons) {
  return this.normalizeButtonBar(buttons, oldButtons, 'bottom', this.getButtonToolbar());
}, ensureHeader:function() {
  var me = this, header;
  if (!me._isCreatingHeader) {
    me.getItems();
    header = me.getHeader();
    if (!header && me.allowHeader) {
      me.setHeader(true);
      header = me.getHeader();
    }
  }
  return header;
}, moveHeaderPosition:function(headerPosition, oldHeaderPosition) {
  var me = this, el = me.element, map = me.headerPositionMap, oldItem = map[oldHeaderPosition], newItem = map[headerPosition], oldCls = oldItem ? oldItem.cls : '', newCls = newItem.cls, positionedHeader, header;
  if (oldCls !== newCls) {
    if (oldHeaderPosition) {
      el.removeCls(oldCls);
    }
    el.addCls(newCls);
  }
  if (oldHeaderPosition || headerPosition !== 'top') {
    header = me.ensureHeader();
    if (header) {
      if (!me.isConfiguring) {
        me.positionHeader(header, headerPosition);
        positionedHeader = true;
      }
    }
  }
  if (!positionedHeader) {
    me.syncBorders();
  }
  return header;
}, positionHeader:function(header, position) {
  var me = this, pos = position || me.getHeaderPosition();
  header.setPosition(pos);
  me.syncBorders();
}, setBodyBorderEnabled:function(enabled) {
  this.bodyElement.setStyle('border-width', enabled ? '' : '0');
}, syncBorders:function() {
  if (!this.isConfiguring) {
    this.getLayout().handleDockedItemBorders(true);
  }
}}});
Ext.define('Ext.panel.Collapsible', {override:'Ext.Panel', config:{collapsed:null, collapsible:null, titleCollapse:null}, hasCollapsible:true, collapsed:false, collapsing:false, expanded:false, expanding:false, defaultCollapserCls:'Ext.panel.Collapser', doDestroy:function() {
  this.setCollapsible(null);
  this.callParent();
}, collapse:function(animation) {
  return this.getCollapsible().collapse(animation);
}, expand:function(animation) {
  return this.getCollapsible().expand(animation);
}, saveState:function(state, stateful) {
  var me = this, collapsible = me.getCollapsible(), saved = collapsible && collapsible.getCollapsed() && collapsible.savedProps, direction, property, value;
  me.callParent([state, stateful]);
  if (saved) {
    direction = collapsible.getDirection();
    property = direction === 'top' || direction === 'bottom' ? 'height' : 'width';
    if (stateful && stateful[property] && (value = saved[property]) !== null) {
      state.set(property, value);
    }
  }
}, toggleCollapsed:function(collapsed, animation) {
  return this.getCollapsible().toggleCollapsed(collapsed, animation);
}, getCollapsed:function() {
  var collapsible = this.getCollapsible();
  return collapsible ? collapsible.getCollapsed() : false;
}, updateCollapsed:function(collapsed) {
  var collapsible = this.getCollapsible();
  if (collapsible) {
    collapsible.setCollapsed(collapsed);
  }
}, applyCollapsible:function(collapsible, collapser) {
  if (collapsible === true) {
    collapsible = {direction:this.getHeaderPosition()};
  } else {
    if (typeof collapsible === 'string') {
      collapsible = {direction:collapsible};
    } else {
      if (!collapsible) {
        return null;
      }
    }
  }
  if (collapser) {
    collapser.setConfig(collapsible);
  } else {
    collapsible = Ext.apply({xclass:this.defaultCollapserCls, target:this}, collapsible);
    collapser = Ext.create(collapsible);
  }
  return collapser;
}, updateCollapsible:function(collapsible, oldCollapsible) {
  if (oldCollapsible) {
    if (!this.destroying) {
      oldCollapsible.doExpandCollapse(false);
    }
    oldCollapsible.destroy();
  }
  if (collapsible && this.rendered) {
    this.initCollapsible(collapsible);
  }
}, updateHeader:function(header, oldHeader) {
  var collapsible = this.getCollapsible();
  this.callParent([header, oldHeader]);
  if (this.isConfiguring && collapsible) {
    collapsible.toggleCollapsed(collapsible.getCollapsed(), false);
  }
}, updateHeaderPosition:function(headerPosition, oldHeaderPosition) {
  var collapsible = this.getCollapsible();
  if (collapsible && collapsible.getCollapsed()) {
    headerPosition = collapsible.getDirection();
  }
  this.moveHeaderPosition(headerPosition, oldHeaderPosition);
}, privates:{hasHiddenContent:function() {
  return this.getCollapsed() || this.callParent();
}, initCollapsible:function(collapsible) {
  this.ensureHeader();
  collapsible.initialize();
}, onCollapsibleRendered:function() {
  var collapsible = this.getCollapsible();
  if (collapsible) {
    this.initCollapsible(collapsible);
  }
}, reattachBodyWrap:function() {
  var me = this, header = me._header, el = me.maxHeightElement || me.element, bodyWrap = me.bodyWrapElement;
  if (bodyWrap.parent() !== el) {
    if (header) {
      bodyWrap.insertAfter(header.element);
    } else {
      el.insertFirst(bodyWrap);
    }
  }
}}});
Ext.define('Ext.panel.Resizable', {override:'Ext.Panel', config:{resizable:null}, hasResizable:true, defaultResizerCls:'Ext.panel.Resizer', applyResizable:function(resizable) {
  if (resizable) {
    if (resizable === true) {
      resizable = {};
    }
    resizable = Ext.create(Ext.apply({xclass:this.defaultResizerCls, target:this, ui:this.getUi()}, resizable));
  }
  return resizable;
}, updateResizable:function(resizable, oldResizable) {
  if (oldResizable) {
    oldResizable.destroy();
  }
}, doDestroy:function() {
  this.setResizable(null);
  this.callParent();
}, privates:{onResizableUiChange:function(ui, oldUi) {
  var resizable = this.getResizable();
  if (resizable) {
    resizable.setUi(ui);
  }
}}});
Ext.define('Ext.theme.material.Panel', {override:'Ext.Panel', config:{buttonAlign:'right', buttonToolbar:{defaultButtonUI:null}}});
Ext.define('Ext.Mask', {extend:Ext.Component, xtype:'mask', config:{transparent:false, top:0, left:0, right:0, bottom:0}, baseCls:Ext.baseCSSPrefix + 'mask', initialize:function() {
  var me = this;
  me.callParent();
  me.element.on('tap', 'onTap', me);
  me.on('hide', 'onHide', me);
  me.on('show', 'onShow', me);
}, onHide:function(me) {
  var firstChild;
  if (me.sender && me.tabbingDisabled) {
    me.sender.enableTabbing();
    me.tabbingDisabled = false;
  }
  Ext.util.InputBlocker.unblockInputs();
  if (Ext.browser.is.AndroidStock4 && Ext.os.version.getMinor() === 0) {
    firstChild = this.element.getFirstChild();
    if (firstChild) {
      firstChild.redraw();
    }
  }
}, onShow:function(me) {
  if (me.sender && !me.tabbingDisabled) {
    me.sender.disableTabbing();
    me.tabbingDisabled = true;
  }
}, onTap:function(e) {
  this.fireEvent('tap', this, e);
}, updateTransparent:function(transparent) {
  this.toggleCls(this.baseCls + '-transparent', transparent);
}});
Ext.define('Ext.Sheet', {extend:Ext.Panel, xtype:'sheet', isViewportMenu:false, hidden:true, config:{reveal:null, cover:null, side:null, stretchX:null, stretchY:null, enter:'bottom', exit:'bottom'}, translatable:{type:'csstransform'}, showAnimation:{type:'slideIn', duration:250, easing:'ease-out'}, hideAnimation:{type:'slideOut', duration:250, easing:'ease-in'}, modal:true, hideOnMaskTap:true, centered:true, classCls:Ext.baseCSSPrefix + 'sheet', manageBorders:false, autoSize:null, border:true, bodyBorder:false, 
floated:true, isInputRegex:/^(input|textarea|select|a)$/i, destroy:function() {
  var me = this;
  me.setSide(null);
  me.callParent();
}, applyHideAnimation:function(config) {
  var exit = this.getExit(), direction = exit, anim;
  if (exit === null) {
    return null;
  }
  if (config === true) {
    config = {type:'slideOut'};
  }
  anim = this.callParent([config]);
  if (anim) {
    if (exit === 'bottom') {
      direction = 'down';
    } else {
      if (exit === 'top') {
        direction = 'up';
      }
    }
    anim.setDirection(direction);
  }
  return anim;
}, applyShowAnimation:function(config) {
  var enter = this.getEnter(), direction = enter, anim;
  if (enter === null) {
    return null;
  }
  if (config === true) {
    config = {type:'slideIn'};
  }
  anim = this.callParent([config]);
  if (anim) {
    if (enter === 'bottom') {
      direction = 'down';
    }
    if (enter === 'top') {
      direction = 'up';
    }
    anim.setBefore({display:null});
    anim.setReverse(true);
    anim.setDirection(direction);
  }
  return anim;
}, hide:function(animation) {
  var side = this.getSide();
  if (side) {
    Ext.Viewport.hideMenu(side, animation);
  } else {
    this.callParent([animation]);
  }
}, show:function(animation, options) {
  var me = this, VP = Ext.Viewport, side = options && 'side' in options ? options.side : me.getSide();
  if (side) {
    VP.setMenu(me);
    VP.showMenu(side);
  } else {
    me.callParent([animation, options]);
  }
}, updateSide:function(newSide, oldSide) {
  var me = this, reShow = !me.isConfiguring && me.isVisible();
  me.isViewportMenu = !!newSide;
  if (oldSide) {
    Ext.Viewport.removeMenu(oldSide);
  }
  if (newSide) {
    Ext.Viewport.setMenu(me, {side:newSide});
    if (reShow) {
      me.show();
    }
  }
}, updateStretchX:function(newStretchX) {
  this.getLeft();
  this.getRight();
  if (newStretchX) {
    this.setLeft(0);
    this.setRight(0);
  }
}, updateStretchY:function(newStretchY) {
  this.getTop();
  this.getBottom();
  if (newStretchY) {
    this.setTop(0);
    this.setBottom(0);
  }
}});
Ext.define('Ext.ActionSheet', {extend:Ext.Sheet, xtype:'actionsheet', classCls:Ext.baseCSSPrefix + 'actionsheet', centered:false, layout:'vbox', side:'bottom', defaultType:'button'});
Ext.define('Ext.menu.Item', {extend:Ext.Component, xtype:'menuitem', alternateClassName:'Ext.menu.TextItem', isMenuItem:true, menuExpandDelay:200, menuHideDelay:200, scope:null, destroyMenu:true, clickHideDelay:0, hideOnClick:true, config:{href:null, target:null, handler:null, text:null, menu:{lazy:true, $value:null}, menuAlign:'tl-tr?', icon:null, iconCls:null, iconAlign:'left', indented:null, separator:null}, inheritUi:true, ariaRole:'menuitem', focusable:true, classCls:Ext.baseCSSPrefix + 'menuitem', 
activeCls:Ext.baseCSSPrefix + 'active', hasLeftIconCls:Ext.baseCSSPrefix + 'has-left-icon', hasRightIconCls:Ext.baseCSSPrefix + 'has-right-icon', hasArrowCls:Ext.baseCSSPrefix + 'has-arrow', hasHrefCls:Ext.baseCSSPrefix + 'has-href', isMenuOwner:true, template:[{reference:'bodyElement', tag:'a', href:'#', cls:Ext.baseCSSPrefix + 'body-el ' + Ext.baseCSSPrefix + 'unselectable', children:[{reference:'leftIconWrapElement', cls:Ext.baseCSSPrefix + 'left-icon-wrap-el ' + Ext.baseCSSPrefix + 'icon-wrap-el', 
children:[{reference:'leftIconElement', cls:Ext.baseCSSPrefix + 'left-icon-el ' + Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon'}]}, {html:' ', reference:'textElement', cls:Ext.baseCSSPrefix + 'text-el'}, {reference:'rightIconWrapElement', cls:Ext.baseCSSPrefix + 'right-icon-wrap-el ' + Ext.baseCSSPrefix + 'icon-wrap-el', children:[{reference:'rightIconElement', cls:Ext.baseCSSPrefix + 'right-icon-el ' + Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon'}]}, {reference:'arrowElement', 
cls:Ext.baseCSSPrefix + 'arrow-el ' + Ext.baseCSSPrefix + 'font-icon'}]}], ariaEl:'bodyElement', focusEl:'bodyElement', initialize:function() {
  this.callParent();
  this.syncHasIconCls();
  if (Ext.supports.Touch) {
    this.handleTouch();
  }
}, getFocusClsEl:function() {
  return this.el;
}, expandMenu:function(event) {
  var me = this, menu = me.getMenu();
  if (!me.getDisabled() && menu) {
    menu.parentMenu = me.parentMenu;
    me.hideOnClick = false;
    if (menu.isVisible()) {
      if (event && event.type === 'keydown') {
        menu.focus();
      }
    } else {
      menu.autoFocus = !event || !event.pointerType;
      menu.showBy(me, me.getMenuAlign(), {axisLock:true});
    }
  }
}, getRefItems:function(deep) {
  var menu = this.getMenu(), items;
  if (menu) {
    items = menu.getRefItems(deep);
    items.unshift(menu);
  }
  return items || [];
}, onFocusEnter:function(e) {
  var me = this;
  me.callParent([e]);
  me.addCls(me.activeCls);
  me.activated = true;
  if (me.hasListeners.activate) {
    me.fireEvent('activate', me);
  }
  if (me.parentMenu) {
    me.parentMenu.setActiveItem(me);
  }
}, onFocusLeave:function(e) {
  var me = this, menu = me.menu;
  me.callParent([e]);
  me.removeCls(me.activeCls);
  if (menu) {
    menu.hide();
  }
  me.activated = false;
  if (me.hasListeners.deactivate) {
    me.fireEvent('deactivate', me);
  }
  if (me.parentMenu) {
    me.parentMenu.setActiveItem(null);
  }
}, onRemoved:function(destroying) {
  this.callParent([destroying]);
  this.parentMenu = null;
}, doDestroy:function() {
  var me = this;
  me.separatorElement = Ext.destroy(me.separatorElement);
  me.setMenu(null);
  me.linkClickListener = Ext.destroy(me.linkClickListener);
  me.callParent();
}, updateText:function(text) {
  if (text == null || text === '') {
    text = ' ';
  }
  this.textElement.dom.firstChild.data = text;
}, applyMenu:function(menu) {
  var me = this, ariaDom = me.ariaEl.dom;
  if (menu) {
    if (menu.isMenu) {
      menu.setConstrainAlign(Ext.getBody());
      menu.ownerCmp = me;
    } else {
      menu = Ext.menu.Menu.create(menu, {ownerCmp:me, $initParent:me, constrainAlign:Ext.getBody()});
    }
    ariaDom.setAttribute('aria-haspopup', true);
    ariaDom.setAttribute('aria-owns', menu.id);
  } else {
    ariaDom.removeAttribute('aria-haspopup');
    ariaDom.removeAttribute('aria-owns');
  }
  me.toggleCls(me.hasArrowCls, !!menu);
  return menu;
}, updateMenu:function(menu, oldMenu) {
  if (oldMenu) {
    if (this.destroyMenu) {
      Ext.destroy(oldMenu);
    } else {
      oldMenu.parentMenu = null;
    }
  }
  this.menu = menu;
}, updateHref:function(href) {
  this.bodyElement.dom.href = href;
  this.toggleCls(this.hasHrefCls, !!href);
}, updateTarget:function(target) {
  this.bodyElement.dom.target = target;
}, updateIcon:function(icon) {
  var me = this, iconElement = me.getIconAlign() === 'left' ? this.leftIconElement : this.rightIconElement;
  if (icon) {
    iconElement.setStyle('background-image', 'url(' + icon + ')');
  } else {
    iconElement.setStyle('background-image', '');
  }
  if (!me.isConfiguring) {
    me.syncHasIconCls();
  }
}, updateIconCls:function(iconCls, oldIconCls) {
  var me = this, iconElement = me.getIconAlign() === 'left' ? this.leftIconElement : this.rightIconElement;
  if (iconCls) {
    iconElement.replaceCls(oldIconCls, iconCls);
  } else {
    iconElement.removeCls(oldIconCls);
  }
  if (!me.isConfiguring) {
    me.syncHasIconCls();
  }
}, updateIconAlign:function(iconAlign) {
  if (!this.isConfiguring) {
    this.syncHasIconCls();
  }
}, updateSeparator:function(separator) {
  var me = this, separatorElement = me.separatorElement;
  if (separator) {
    if (separatorElement) {
      separatorElement.show();
    } else {
      me.separatorElement = separatorElement = Ext.Element.create({cls:Ext.baseCSSPrefix + 'menuseparator'});
      me.el.dom.insertBefore(separatorElement.dom, me.el.dom.firstChild);
    }
  } else {
    if (separatorElement) {
      separatorElement.hide();
    }
  }
}, privates:{handleTouch:function() {
  var me = this, linkEl = me.bodyElement;
  me.linkClickListener = linkEl.on({click:me.onClick, capture:true, translate:false, scope:me, destroyable:true});
}, onSpace:function(e) {
  return this.onClick(e);
}, onClick:function(e) {
  var me = this, href = me.getHref(), clickHideDelay = me.clickHideDelay, browserEvent = e.browserEvent, handler = me.getHandler(), isTouchEvent = e.pointerType === 'touch', clickResult;
  if (me.linkClickListener && !isTouchEvent && e.parentEvent) {
    e.stopEvent();
    return;
  }
  if ((!href || me.getDisabled()) && me.bodyElement.dom === e.getTarget('a')) {
    e.stopEvent();
    if (me.getDisabled()) {
      return false;
    }
  }
  if (me.getDisabled() || me.handlingClick) {
    return;
  }
  if (me.hideOnClick && !me.getMenu()) {
    if (!clickHideDelay) {
      me.hideParentMenus();
    } else {
      me.hideParentMenusTimer = Ext.defer(me.hideParentMenus, clickHideDelay, me);
    }
  }
  clickResult = me.fireEvent('click', me, e);
  if (me.destroyed) {
    return;
  }
  if (clickResult !== false && handler) {
    Ext.callback(handler, me.scope, [me, e], 0, me);
  }
  if (me.destroyed) {
    return;
  }
  if (href && e.type !== 'click' && !browserEvent.defaultPrevented) {
    me.handlingClick = true;
    me.bodyElement.dom.click();
    me.handlingClick = false;
  }
  return clickResult;
}, hideParentMenus:function() {
  var menu;
  for (menu = this.getRefOwner(); menu && (menu.isMenu && menu.getFloated() || menu.isMenuItem); menu = menu.getRefOwner()) {
    if (menu.isMenu) {
      menu.hide();
    }
  }
}, hasIcon:function() {
  return !!(this.getIconCls() || this.getIcon());
}, syncHasIconCls:function() {
  var me = this, rightCls = me.hasRightIconCls, leftCls = me.hasLeftIconCls, iconAlign = me.getIconAlign();
  if (me.hasIcon()) {
    if (iconAlign === 'left') {
      me.replaceCls(rightCls, leftCls);
    } else {
      if (iconAlign === 'right') {
        me.replaceCls(leftCls, rightCls);
      }
    }
  } else {
    me.removeCls([leftCls, rightCls]);
  }
}}});
Ext.define('Ext.theme.material.menu.Item', {override:'Ext.menu.Item', config:{ripple:{delegate:'.' + Ext.baseCSSPrefix + 'body-el'}}, shouldRipple:function() {
  var me = this, rippleDelay = me.el.rippleShowTimeout;
  me.clickHideDelay = me.clickHideDelay > rippleDelay ? me.clickHideDelay : rippleDelay;
  return this.getRipple();
}});
Ext.define('Ext.menu.Manager', {singleton:true, alternateClassName:'Ext.menu.MenuMgr', hideAll:function() {
  var allMenus = this.visible, len = allMenus.length, result = false, i;
  if (len) {
    allMenus = allMenus.slice();
    for (i = 0; i < len; i++) {
      allMenus[i].hide();
      result = true;
    }
  }
  return result;
}, privates:{groups:{}, visible:[], constructor:function() {
  var me = this;
  me.onShow = function() {
    me.registerGlobalListeners();
    return me.onShow.apply(me, arguments);
  };
}, onGlobalScroll:function(scroller) {
  var allMenus = this.visible, len = allMenus.length, i, menu;
  if (len && scroller !== Ext.scroll.Scroller.viewport) {
    allMenus = allMenus.slice();
    for (i = 0; i < len; ++i) {
      menu = allMenus[i];
      if (scroller.contains(menu)) {
        menu.hide();
      }
    }
  }
}, checkActiveMenus:function(e) {
  var allMenus = this.visible, len = allMenus.length, i, menu, mousedownCmp = Ext.Component.from(e);
  if (len) {
    allMenus = allMenus.slice();
    for (i = 0; i < len; ++i) {
      menu = allMenus[i];
      if (!(menu.owns(e) || mousedownCmp && mousedownCmp.isMenuOwner && mousedownCmp.getMenu() === menu)) {
        menu.hide();
      }
    }
  }
}, onShow:function(menu) {
  if (menu.getFloated()) {
    Ext.Array.include(this.visible, menu);
  }
}, onHide:function(menu) {
  if (menu.getFloated()) {
    Ext.Array.remove(this.visible, menu);
  }
}, registerGlobalListeners:function() {
  var me = this;
  delete me.onShow;
  Ext.on({mousedown:me.checkActiveMenus, scrollstart:me.onGlobalScroll, scope:me});
  var jasmine = window.jasmine;
  if (jasmine && jasmine.addAllowedListener) {
    jasmine.addAllowedListener('mousedown');
    jasmine.addAllowedListener('scrollstart');
  }
}}});
Ext.define('Ext.layout.VBox', {extend:Ext.layout.Box, alias:'layout.vbox', config:{vertical:true}});
Ext.define('Ext.menu.Menu', {extend:Ext.Panel, xtype:'menu', isMenu:true, config:{align:'tl-bl?', indented:true, separator:null, autoHide:null, groups:null}, allowOtherMenus:false, ignoreParentClicks:false, mouseLeaveDelay:50, defaultType:'menuitem', autoSize:null, twoWayBindable:'groups', keyMap:{scope:'this', SPACE:'onSpaceKey', ESC:'onEscKey'}, layout:{type:'vbox', align:'stretch'}, classCls:Ext.baseCSSPrefix + 'menu', indentedCls:Ext.baseCSSPrefix + 'indented', hasSeparatorCls:Ext.baseCSSPrefix + 
'has-separator', nonMenuItemCls:Ext.baseCSSPrefix + 'non-menuitem', allowFocusingDisabledChildren:true, border:true, defaultFocus:':focusable', floated:true, focusable:true, focusableContainer:true, nameHolder:true, weighted:true, initialize:function() {
  var me = this, listeners = {click:me.onClick, mouseover:me.onMouseOver, scope:me};
  me.callParent();
  if (Ext.supports.Touch) {
    listeners.pointerdown = me.onMouseOver;
  }
  me.element.on(listeners);
  me.itemOverTask = new Ext.util.DelayedTask(me.handleItemOver, me);
  me.mouseMonitor = me.el.monitorMouseLeave(me.mouseLeaveDelay, me.onMouseLeave, me);
}, doDestroy:function() {
  var me = this;
  me.itemOverTask.cancel();
  Ext.menu.Manager.onHide(me);
  me.parentMenu = me.ownerCmp = null;
  if (me.rendered) {
    me.el.un(me.mouseMonitor);
  }
  me.callParent();
}, showBy:function(component, alignment, options) {
  this.callParent([component, alignment || this.getAlign(), options]);
}, onFocusEnter:function(e) {
  var me = this, hierarchyState;
  me.callParent([e]);
  me.mixins.focusablecontainer.onFocusEnter.call(me, e);
  if (me.getFloated()) {
    hierarchyState = me.getInherited();
    if (!hierarchyState.topmostFocusEvent) {
      hierarchyState.topmostFocusEvent = e;
    }
  }
}, onFocusLeave:function(e) {
  this.callParent([e]);
  if (this.getAutoHide() !== false) {
    this.hide();
  }
}, onItemAdd:function(item, index) {
  this.callParent([item, index]);
  this.syncItemIndentedCls(item);
  if (!item.isMenuItem && !item.isMenuSeparator) {
    item.addCls(this.nonMenuItemCls);
  }
}, onItemRemove:function(item, index, destroying) {
  this.callParent([item, index, destroying]);
  item.removeCls(this.indentedCls, this.nonMenuItemCls);
}, beforeShow:function() {
  var me = this, parent;
  if (me.getFloated()) {
    parent = me.hasFloatMenuParent();
    if (!parent && !me.allowOtherMenus) {
      Ext.menu.Manager.hideAll();
    }
  }
  me.callParent(arguments);
}, afterShow:function() {
  var me = this, ariaDom = me.ariaEl.dom;
  me.callParent();
  Ext.menu.Manager.onShow(me);
  if (me.getFloated() && ariaDom) {
    ariaDom.setAttribute('aria-expanded', true);
  }
  if (me.getFloated()) {
    me.maxHeight = me.savedMaxHeight;
  }
  if (me.autoFocus) {
    me.focus();
  }
}, afterHide:function() {
  var me = this, ariaDom = me.ariaEl.dom;
  me.callParent();
  me.lastHide = Ext.Date.now();
  Ext.menu.Manager.onHide(me);
  if (me.getFloated() && ariaDom) {
    ariaDom.setAttribute('aria-expanded', false);
  }
  delete me.getInherited().topmostFocusEvent;
}, factoryItem:function(cfg) {
  var result;
  if (typeof cfg === 'string' && cfg[0] !== '@') {
    if (cfg === '-') {
      cfg = {xtype:'menuseparator'};
    } else {
      cfg = {};
    }
  }
  result = this.callParent([cfg]);
  if (result.isMenuItem) {
    result.parentMenu = this;
  }
  return result;
}, updateIndented:function(indented) {
  var me = this;
  if (!me.isConfiguring) {
    me.bodyElement.toggleCls(me.hasSeparatorCls, !!(indented && me.getSeparator()));
    me.items.each(me.syncItemIndentedCls, me);
  }
}, updateSeparator:function(separator) {
  this.bodyElement.toggleCls(this.hasSeparatorCls, !!(separator && this.getIndented()));
}, privates:{applyItemDefaults:function(item) {
  item = this.callParent([item]);
  if (!item.isComponent && !item.xtype && !item.xclass) {
    if (item.group || item.name) {
      item.xtype = 'menuradioitem';
    } else {
      if ('checked' in item) {
        item.xtype = 'menucheckitem';
      }
    }
  }
  return item;
}, applyGroups:function(groups, oldGroups) {
  var me = this, currentGroups = Ext.apply({}, oldGroups), isConfiguring = me.isConfiguring, groupName, members, len, i, item, value, oldValue;
  if (groups) {
    me.updatingGroups = true;
    for (groupName in groups) {
      oldValue = currentGroups[groupName];
      currentGroups[groupName] = value = groups[groupName];
      if (!isConfiguring) {
        members = me.lookupName(groupName);
        for (i = 0, len = members.length; i < len; i++) {
          item = members[i];
          item.setChecked(item.getValue() === value);
        }
        me.fireEvent('groupchange', me, groupName, value, oldValue);
      }
    }
    me.updatingGroups = false;
  }
  return currentGroups;
}, processFocusableContainerKeyEvent:function(e) {
  var keyCode = e.keyCode, item;
  if (keyCode === e.ESC || Ext.fly(e.target).is('input[type\x3dcheckbox]') && (keyCode === e.LEFT || keyCode === e.RIGHT || keyCode === e.UP || keyCode === e.DOWN)) {
    e.preventDefault();
    item = this.getItemFromEvent(e);
    e.target = item && item.focusEl.dom;
  } else {
    if (keyCode === e.TAB && Ext.fly(e.target).is('input[type\x3dtext],textarea')) {
      e.preventDefault();
      item = this.getItemFromEvent(e);
      e.target = item && item.focusEl.dom;
      if (e.shiftKey) {
        e.shiftKey = false;
        e.keyCode = e.UP;
      } else {
        e.keyCode = e.DOWN;
      }
    } else {
      return this.callParent([e]);
    }
  }
  return e;
}, onEscKey:function(e) {
  if (this.getFloated()) {
    this.hide();
  }
}, onSpaceKey:function(e) {
  var clickedItem = this.getItemFromEvent(e);
  if (clickedItem && clickedItem.isMenuItem) {
    clickedItem.onSpace(e);
  }
}, onFocusableContainerLeftKey:function(e) {
  e.preventDefault();
  if (this.parentMenu) {
    this.hide();
  }
}, onFocusableContainerRightKey:function(e) {
  var clickedItem = this.getItemFromEvent(e);
  e.preventDefault();
  if (clickedItem) {
    clickedItem.expandMenu(e);
  }
}, onClick:function(e) {
  var me = this, type = e.type, clickedItem, clickResult, isKeyEvent = type === 'keydown', isTouchEvent = e.pointerType === 'touch';
  if (me.getDisabled()) {
    return e.stopEvent();
  }
  clickedItem = me.getItemFromEvent(e);
  if (clickedItem && clickedItem.isMenuItem) {
    if (!clickedItem.getMenu() || !me.ignoreParentClicks) {
      clickResult = clickedItem.onClick(e);
    } else {
      e.stopEvent();
    }
    if (me.destroyed) {
      return;
    }
    if (clickedItem.getMenu() && clickResult !== false && (isKeyEvent || isTouchEvent)) {
      clickedItem.expandMenu(e);
    }
  }
  if (!clickedItem || clickedItem.getDisabled()) {
    clickedItem = undefined;
  }
  me.fireEvent('click', me, clickedItem, e);
}, onMouseLeave:function(e) {
  var me = this;
  if (me.itemOverTask) {
    me.itemOverTask.cancel();
  }
  if (me.getDisabled()) {
    return;
  }
  me.fireEvent('mouseleave', me, e);
}, onMouseOver:function(e) {
  var me = this, activeItem = me.getActiveItem(), activeItemMenu = activeItem && activeItem.getMenu && activeItem.getMenu(), activeItemExpanded = activeItemMenu && activeItemMenu.isVisible(), isTouch = e.pointerType === 'touch', mouseEnter, overItem, el;
  if (!me.getDisabled()) {
    if (isTouch) {
      mouseEnter = !me.el.contains(document.activeElement);
    } else {
      mouseEnter = !me.el.contains(e.getRelatedTarget());
    }
    overItem = me.getItemFromEvent(e);
    if (overItem) {
      if (isTouch) {
        me.handleItemOver(e, overItem);
      } else {
        el = overItem.isMenuItem ? overItem.bodyElement : overItem.el;
        if (!el.contains(e.getRelatedTarget())) {
          me.itemOverTask.delay(activeItemExpanded ? me.mouseLeaveDelay : 0, null, null, [e, overItem]);
        }
      }
    }
    if (mouseEnter) {
      me.fireEvent('mouseenter', me, e);
    }
    me.fireEvent('mouseover', me, overItem, e);
  }
}, handleItemOver:function(e, item) {
  var isMouseover = e.pointerType === 'mouse';
  if (!item.containsFocus && (isMouseover || item.isMenuItem)) {
    item.focus();
  }
  if (item.expandMenu && isMouseover) {
    item.expandMenu(e);
  }
}, getItemFromEvent:function(e) {
  var bodyDom = this.bodyElement.dom, toEl = e.getTarget(), component;
  while (toEl && toEl.parentNode !== bodyDom) {
    toEl = toEl.parentNode;
  }
  component = toEl && Ext.getCmp(toEl.id);
  if (component && component.isMenuItem && !e.within(component.bodyElement)) {
    component = null;
  }
  return component;
}, hasFloatMenuParent:function() {
  return this.parentMenu || this.up('menu[_floated\x3dtrue]');
}, syncItemIndentedCls:function(item) {
  var indented = item.isMenuItem ? item.getIndented() : item.indented;
  item.toggleCls(this.indentedCls, !!(indented || this.getIndented() && indented !== false));
}}, statics:{create:function(menu, config) {
  if (Ext.isArray(menu)) {
    menu = Ext.apply({xtype:'menu', items:menu}, config);
  } else {
    menu = Ext.apply({xtype:'menu'}, menu, config);
  }
  return Ext.create(menu);
}}, deprecated:{'6.5':{configs:{plain:{message:'To achieve classic toolkit "plain" effect, use "indented".'}, showSeparator:{message:'To achieve classic toolkit "showSeparator" effect, use "separator".'}}}}});
Ext.define('Ext.theme.material.menu.Menu', {override:'Ext.menu.Menu', config:{indented:false}});
Ext.define('Ext.Chip', {extend:Ext.Component, xtype:'chip', isChip:true, focusable:false, tabIndex:null, classCls:Ext.baseCSSPrefix + 'chip', hasIconCls:Ext.baseCSSPrefix + 'has-icon', closableCls:Ext.baseCSSPrefix + 'closable', element:{reference:'element', children:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', children:[{reference:'iconElement', cls:Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon'}, {reference:'textElement', cls:Ext.baseCSSPrefix + 'text-el'}, {reference:'closeElement', 
cls:Ext.baseCSSPrefix + 'close-el ' + Ext.baseCSSPrefix + 'font-icon', listeners:{click:'onClick'}}]}]}, config:{icon:false, iconCls:null, text:null, closable:null, closeHandler:null, scope:null}, defaultBindProperty:'text', onClick:function(e) {
  var me = this, handler = me.getCloseHandler();
  Ext.callback(handler, me.getScope(), [me, e], 0, me);
}, applyIcon:function(icon) {
  return Ext.resolveResource(icon);
}, updateClosable:function(closable) {
  this.el.toggleCls(this.closableCls, closable);
}, updateIcon:function(icon) {
  var me = this, iconEl = me.iconElement, hasIconCls = me.hasIconCls;
  if (icon) {
    iconEl.setStyle('background-image', 'url(' + icon + ')');
    me.addCls(hasIconCls);
  } else {
    iconEl.setStyle('background-image', '');
    if (!me.getIconCls()) {
      me.removeCls(hasIconCls);
    }
  }
}, updateIconCls:function(iconCls, oldIconCls) {
  this.iconElement.replaceCls(oldIconCls, iconCls);
  this.el.toggleCls(this.hasIconCls, !!iconCls);
}, updateText:function(text) {
  this.textElement.setHtml(Ext.htmlEncode(text));
}});
Ext.define('Ext.Dialog', {extend:Ext.Panel, xtype:['dialog', 'window'], alternateClassName:['Ext.Window', 'Ext.window.Window'], isDialog:true, isWindow:true, ariaRole:'dialog', classCls:Ext.baseCSSPrefix + 'dialog', cachedConfig:{dismissAction:['cancel', 'abort', 'no', 'close'], maximizeAnimation:{easing:'ease-in', from:{opacity:0.6}, to:{opacity:1}}, maximizeProxy:{centered:false, draggable:false, modal:false, showAnimation:null, hideAnimation:null}, maximizeTool:{itemId:'maximize', tooltip:'Maximize to fullscreen'}, 
restoreAnimation:{easing:'ease-in', from:{opacity:1}, to:{opacity:0.6}}, restoreTool:{itemId:'restore', tooltip:'Restore to original size'}}, config:{constrainDrag:true, dismissHandler:null, maximizable:null, maximized:null, maskTapHandler:null, restorable:null}, border:true, bodyBorder:false, centered:true, floated:true, focusable:false, tabIndex:-1, draggable:{handle:'.' + Ext.baseCSSPrefix + 'draggable', listeners:{beforedragstart:'onBeforeDragDialog', scope:'this'}}, keyMap:{ESC:'onEscape', scope:'this'}, 
modal:true, shadow:true, headerCls:Ext.baseCSSPrefix + 'dialogheader', titleCls:Ext.baseCSSPrefix + 'dialogtitle', toolCls:[Ext.baseCSSPrefix + 'paneltool', Ext.baseCSSPrefix + 'dialogtool'], hideMode:'offsets', hideAnimation:{type:'popOut', duration:250, easing:'ease-out'}, showAnimation:{type:'popIn', duration:150, easing:'ease-out'}, initialize:function() {
  var me = this;
  me.callParent();
  if (me.tabGuard) {
    me.addPlugin({type:'tabguard', tabGuardBeforeIndex:me.tabGuardBeforeIndex, tabGuardAfterIndex:me.tabGuardAfterIndex});
  }
}, doDestroy:function() {
  Ext.destroy(this.maximizeTool, this.restoreTool);
  this.callParent();
}, close:function(event) {
  var me = this, buttons = me.getButtons(), actions = me.getDismissAction(), handler = me.getDismissHandler(), action, closeAction, closeActionIsDestroy, done, i, n;
  event = event || null;
  if (me.fireEvent('beforeclose', me, event) !== false) {
    if (handler !== true) {
      if (handler) {
        Ext.callback(handler, null, [me, event], 0, me);
        done = true;
      } else {
        if (actions && buttons) {
          if (typeof actions === 'string') {
            actions = [actions];
          }
          for (i = 0, n = actions.length; i < n; ++i) {
            action = buttons.getComponent(actions[i]);
            if (action && action.isButton) {
              action.onTap(event);
              done = true;
              break;
            }
          }
        }
      }
    }
    if (!done) {
      closeAction = me.getCloseAction();
      if (closeAction) {
        if (!(closeActionIsDestroy = closeAction === 'destroy')) {
          me[closeAction]();
        }
      }
    }
    if (!me.destroyed) {
      me.fireEvent('close', me, event);
      if (closeActionIsDestroy) {
        me.destroy();
      }
    }
  }
}, createMaximizeProxy:function(config) {
  var me = this;
  return Ext.apply({title:me.getTitle(), cls:me.getCls(), userCls:me.getUserCls(), iconCls:me.getIconCls(), ui:me.getUi()}, config);
}, maximize:function(animation) {
  var me = this, maximizing = me.maximizing;
  if (!maximizing && !me.getMaximized()) {
    me._maximizeAnim = animation;
    me.setMaximized(true);
    if (!(maximizing = me.maximizing)) {
      return Ext.Promise.resolve(false);
    }
  }
  return maximizing ? maximizing.promise : Ext.Promise.resolve(true);
}, restore:function(animation) {
  var me = this, restoring = me.restoring;
  if (!restoring && me.getMaximized()) {
    me._maximizeAnim = animation;
    me.setMaximized(false);
    if (!(restoring = me.restoring)) {
      return Ext.Promise.resolve(false);
    }
  }
  return restoring ? restoring.promise : Ext.Promise.resolve(true);
}, shouldRecenter:function() {
  return !this.getMaximized() && this.callParent();
}, updateConstrainDrag:function(constrain) {
  var dragger = this.getDraggable();
  if (dragger) {
    if (constrain === true) {
      constrain = Ext.getBody();
    }
    dragger.setConstrain(constrain);
  }
}, updateDraggable:function(draggable, existing) {
  this.callParent([draggable, existing]);
  if (!this.isConfiguring) {
    this.syncHeaderItems();
  }
}, updateHeader:function(header, oldHeader) {
  var me = this, beforeGuard;
  me.callParent([header, oldHeader]);
  if (header) {
    me.syncHeaderItems();
    if (me.tabGuard && me.getTabGuard) {
      beforeGuard = me.getTabGuard('before');
      if (beforeGuard && beforeGuard.dom) {
        beforeGuard.insertBefore(header.el);
      }
    }
  }
}, applyMaximizable:function(maximizable) {
  var me = this;
  me.maximizeTool = Ext.updateWidget(me.maximizeTool, maximizable, me, 'createMaximizeTool', 'maximizeTool');
  me.syncHeaderItems();
  return maximizable;
}, applyMaximized:function(maximized) {
  var me = this, event;
  if (!me.isConfiguring) {
    event = maximized ? 'beforemaximize' : 'beforerestore';
    if (me.fireEvent(event, me) === false) {
      me._maximizeAnim = undefined;
      return;
    }
  }
  return !!maximized;
}, updateMaximized:function(maximized) {
  var me = this, el = me.el, maximizedCls = me.maximizedCls, maximizeTool = me.maximizeTool, pendingName = maximized ? 'restoring' : 'maximizing', pending = me[pendingName], after, anim, before, center;
  if (me.isConfiguring) {
    me.needsCenter = maximized;
  } else {
    anim = me._maximizeAnim;
    center = me.needsCenter && !maximized;
    me.needsCenter = false;
    if (anim === undefined) {
      anim = me[maximized ? 'getMaximizeAnimation' : 'getRestoreAnimation']();
    }
  }
  me._maximizeAnim = undefined;
  if (pending) {
    pending.destroy();
  }
  if (me.getMaximizable()) {
    me.setRestorable(maximized);
  } else {
    me.syncHeaderItems();
  }
  if (maximizeTool) {
    maximizeTool.setHidden(maximized);
  }
  if (!anim) {
    el.toggleCls(maximizedCls, maximized);
    if (center) {
      me.center();
    }
    me.fireEvent(maximized ? 'maximize' : 'restore', me);
  } else {
    if (maximized) {
      pendingName = 'maximizing';
      before = me.captureSize();
      after = me.captureSize(true);
    } else {
      pendingName = 'restoring';
      el.removeCls(maximizedCls);
      if (center) {
        me.center();
      }
      before = me.captureSize(true);
      after = me.captureSize();
    }
    me[pendingName] = me.animateMaximizeRestore(before, after, anim, function() {
      if (maximized) {
        el.addCls(maximizedCls);
      }
      me[pendingName] = null;
      me.fireEvent(maximized ? 'maximize' : 'restore', me);
    });
  }
}, createMaximizeTool:function(config) {
  var tool = this.adjustToolDefaults(Ext.clone(config));
  tool.handler = 'onMaximize';
  tool.scope = this;
  return tool;
}, applyRestorable:function(restorable) {
  var me = this;
  me.restoreTool = Ext.updateWidget(me.restoreTool, restorable, me, 'createRestoreTool', 'restoreTool');
  me.syncHeaderItems();
  return restorable;
}, createRestoreTool:function(config) {
  var tool = this.adjustToolDefaults(Ext.clone(config));
  tool.handler = 'onRestore';
  tool.scope = this;
  return tool;
}, afterShow:function() {
  this.callParent();
  if (this.getModal()) {
    this.focus();
  }
}, onBeforeDragDialog:function(draggable, info, event) {
  var header = this.getHeader();
  if (!header || !header.el.contains(event.target)) {
    return false;
  }
}, getFocusEl:function() {
  var focusEl = this.callParent();
  if (!focusEl && !this.getButtons() && this.getClosable()) {
    return this.closeTool;
  }
  return focusEl;
}, onCloseTool:function(dialog, tool, event) {
  this.close(event);
}, onEscape:function(event) {
  this.close(event);
}, onMaximize:function() {
  this.setMaximized(true);
}, onRestore:function() {
  this.setMaximized(false);
}, onModalMaskTap:function(e) {
  var me = this, handler = me.getMaskTapHandler(), ret;
  if (handler) {
    Ext.callback(handler, null, [me, e], 0, me);
  } else {
    ret = me.callParent([e]);
  }
  return ret;
}, privates:{draggableCls:Ext.baseCSSPrefix + 'draggable', needsCenter:false, maximizedCls:Ext.baseCSSPrefix + 'maximized', animateMaximizeRestore:function(before, after, anim, callback) {
  var me = this, pending = new Ext.Deferred, proxy = me.getMaximizeProxy(), a = Ext.merge({from:{width:before.w + 'px', height:before.h + 'px', transform:{translateX:before.x + 'px', translateY:before.y + 'px'}}, to:{width:after.w + 'px', height:after.h + 'px', transform:{translateX:after.x + 'px', translateY:after.y + 'px'}}}, anim);
  proxy = me.createMaximizeProxy(proxy);
  proxy = new me.self(proxy);
  proxy.show();
  a.element = proxy.el;
  a.callback = function() {
    proxy.destroy();
    callback();
    pending.resolve(true);
  };
  a = new Ext.fx.animation.Abstract(a);
  Ext.Animator.run(a);
  pending.destroy = function() {
    pending.destroy = Ext.emptyFn;
    a.destroy();
    pending.destroyed = true;
  };
  return pending;
}, captureSize:function(maximized) {
  var me, size;
  if (maximized) {
    return {x:0, y:0, w:Ext.getViewportWidth(), h:Ext.getViewportHeight()};
  }
  me = this;
  size = me.el.measure();
  return {x:me.getX(), y:me.getY(), w:size.width, h:size.height};
}, syncHeaderItems:function() {
  var me = this, maximizeTool = me.maximizeTool, restoreTool = me.restoreTool, header = maximizeTool || restoreTool ? me.ensureHeader() : me.getHeader(), draggableCls = me.draggableCls, draggable, title;
  if (header) {
    draggable = me.getDraggable() && !me.getMaximized();
    header.toggleCls(draggableCls, draggable);
    title = header.getTitle();
    if (title) {
      title.toggleCls(draggableCls, draggable);
    }
    if (maximizeTool && maximizeTool.parent !== header) {
      header.add(maximizeTool);
    }
    if (restoreTool && restoreTool.parent !== header) {
      header.add(restoreTool);
    }
  }
}, updateX:function(x, oldX) {
  this.callParent([x, oldX]);
  if (!this._centering && this.getCentered()) {
    this.setCentered(false);
  }
}}});
Ext.define('Ext.field.Dirty', {extend:Ext.Mixin, mixinConfig:{id:'dirtyfield', after:{_fixReference:'fixDirtyState'}}, config:{bubbleDirty:true, dirty:{lazy:true, $value:false}}, dirty:false, _childDirtyState:null, adjustChildDirtyCount:function(dirty) {
  var me = this, childDirtyState = me._childDirtyState;
  if (childDirtyState) {
    if (childDirtyState.ready) {
      childDirtyState.counter += dirty ? 1 : -1;
      me.setDirty(!!childDirtyState.counter);
    } else {
      if (dirty) {
        ++childDirtyState.counter;
      }
    }
  }
}, beginSyncChildDirty:function() {
  this._childDirtyState = {counter:0, ready:false};
}, finishSyncChildDirty:function() {
  var me = this, childDirtyState = me._childDirtyState, dirty = !!childDirtyState.counter;
  if (dirty !== me.dirty) {
    me.setDirty(dirty);
  } else {
    if (dirty) {
      me.informParentDirty(dirty);
    }
  }
  childDirtyState.ready = true;
}, fireDirtyChange:function() {
  this.fireEvent('dirtychange', this, this.dirty);
}, fixDirtyState:function() {
  var me = this;
  if (!me._childDirtyState && me.dirty) {
    me.informParentDirty(true);
  }
}, informParentDirty:function(dirty) {
  var me = this, parent = me.getBubbleDirty() && me.lookupNameHolder(), childDirtyState = me._childDirtyState, parentChildDirtyState = parent && parent._childDirtyState;
  if (parentChildDirtyState) {
    if (childDirtyState) {
      if (!childDirtyState.ready && parentChildDirtyState.ready) {
        if (!dirty) {
          return;
        }
      }
    }
    parent.adjustChildDirtyCount(dirty, me);
  }
}, invalidateChildDirty:function() {
  this._childDirtyState = null;
}, isDirty:function() {
  if (Ext.referencesDirty) {
    Ext.fixReferences();
  }
  return this.getDirty();
}, updateDirty:function(dirty) {
  var me = this;
  me.dirty = dirty;
  if (!me.isDirtyInitializing) {
    if (me.fireEvent) {
      me.fireDirtyChange();
    }
    me.informParentDirty(dirty);
  }
}});
Ext.define('Ext.field.Field', {extend:Ext.Component, alternateClassName:'Ext.form.Field', xtype:'field', mixins:[Ext.field.Dirty], isField:true, isFormField:true, cachedConfig:{bodyAlign:'start', labelAlign:'left', labelCls:null, labelTextAlign:'left', labelWidth:null, labelMinWidth:null, labelWrap:false}, config:{name:null, label:null, required:false, requiredMessage:'This field is required', value:null, dataType:{cached:true, $value:null}, validators:null, validationMessage:'Is in the wrong format', 
validateDisabled:null, autoFitErrors:null, inline:null, error:null, errorMessage:null, errorTarget:'qtip', errorTpl:null, errorTip:null, sideError:null, tipError:null, titleError:null, underError:null}, htmlErrorsTpl:['\x3ctpl if\x3d"count \x3d\x3d 1"\x3e', '\x3ctpl for\x3d"errors"\x3e{.:htmlEncode}\x3c/tpl\x3e', '\x3ctpl elseif\x3d"count"\x3e', '\x3cul class\x3d"{listCls}"\x3e', '\x3ctpl for\x3d"errors"\x3e\x3cli\x3e{.:htmlEncode}\x3c/li\x3e\x3c/tpl\x3e', '\x3c/ul\x3e', '\x3c/tpl\x3e'], plainErrorsTpl:['\x3ctpl if\x3d"count"\x3e', 
'\x3ctpl for\x3d"errors" between\x3d"\\n"\x3e{.}\x3c/tpl\x3e', '\x3c/tpl\x3e'], _errorTplMap:{title:'plainErrorsTpl'}, originalValue:null, focusable:true, classCls:Ext.baseCSSPrefix + 'field', requiredCls:Ext.baseCSSPrefix + 'required', noLabelWrapCls:Ext.baseCSSPrefix + 'no-label-wrap', invalidCls:Ext.baseCSSPrefix + 'invalid', noAutoFitErrorsCls:Ext.baseCSSPrefix + 'no-auto-fit-errors', inlineCls:Ext.baseCSSPrefix + 'inline', labelAlignVerticalCls:Ext.baseCSSPrefix + 'label-align-vertical', labelAlignHorizontalCls:Ext.baseCSSPrefix + 
'label-align-horizontal', labeledCls:Ext.baseCSSPrefix + 'labeled', verticalLabelMap:{top:1, placeholder:1, bottom:1}, horizontalLabelMap:{left:1, right:1}, nameable:true, validateOnInit:'auto', errorElement:null, errorIconElement:null, errorMessageElement:null, element:{reference:'element', classList:[Ext.supports.CSSMinContent ? '' : Ext.baseCSSPrefix + 'no-min-content', Ext.supports.PercentageSizeFlexBug ? Ext.baseCSSPrefix + 'has-percentage-size-flex-bug' : '']}, initialize:function() {
  var me = this;
  me.callParent();
  if (me.getValue() === '' && me.validateOnInit === 'all') {
    me.validate();
  }
  me.handleFieldDefaults();
}, didValueChange:function(newVal, oldVal) {
  return !this.isEqual(newVal, oldVal);
}, getTemplate:function() {
  return [{reference:'labelElement', cls:Ext.baseCSSPrefix + 'label-el', tag:'label', children:[{reference:'labelTextElement', cls:Ext.baseCSSPrefix + 'label-text-el', tag:'span'}]}, {reference:'bodyWrapElement', cls:Ext.baseCSSPrefix + 'body-wrap-el', children:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', children:this.getBodyTemplate()}, {reference:'errorElement', cls:Ext.baseCSSPrefix + 'error-el', children:[{reference:'errorIconElement', cls:Ext.baseCSSPrefix + 'error-icon-el ' + 
  Ext.baseCSSPrefix + 'font-icon'}, {reference:'errorMessageElement', cls:Ext.baseCSSPrefix + 'error-message-el'}]}]}];
}, getBodyTemplate:Ext.emptyFn, initElement:function() {
  this.callParent();
  this.innerElement = this.innerElement || this.bodyElement;
}, onFocusLeave:function(e) {
  this.callParent([e]);
  this.completeEdit();
}, completeEdit:Ext.emptyFn, updateBodyAlign:function(bodyAlign, oldBodyAlign) {
  var element = this.element;
  if (oldBodyAlign) {
    element.removeCls(Ext.baseCSSPrefix + 'body-align-' + oldBodyAlign);
  }
  if (bodyAlign) {
    element.addCls(Ext.baseCSSPrefix + 'body-align-' + bodyAlign);
  }
}, updateAutoFitErrors:function(autoFitErrors) {
  this.toggleCls(this.noAutoFitErrorsCls, autoFitErrors === false);
}, applyErrorTpl:function(tpl) {
  if (tpl && !tpl.isTemplate) {
    tpl = Ext.XTemplate.get(tpl);
  }
  return tpl;
}, applyDataType:function(field) {
  return field && Ext.Factory.dataField(field);
}, formatErrors:function(errors) {
  var me = this, tpl = me.getErrorTpl();
  if (!tpl) {
    tpl = me.lookupTpl(me._errorTplMap[me.getErrorTarget()] || 'htmlErrorsTpl');
  }
  return tpl.apply({count:errors ? errors.length : 0, label:me.getLabel(), errors:errors});
}, updateError:function(value) {
  var msg = this.formatErrors(Ext.Array.from(value));
  this.setErrorMessage(msg);
}, updateErrorMessage:function(msg) {
  var me = this, owner, errorTarget;
  me.fireEvent('errorchange', me, msg);
  if (me.preventMark) {
    return;
  }
  me.toggleInvalidCls(!!msg);
  errorTarget = me.getErrorTarget();
  switch(errorTarget) {
    case 'side':
      me.setSideError(msg);
      break;
    case 'qtip':
      me.setTipError(msg);
      break;
    case 'title':
      me.setTitleError(msg);
      break;
    case 'under':
      me.setUnderError(msg);
      break;
    case 'parent':
      owner = me.up('[onFieldErrorChange]');
      if (owner) {
        owner.onFieldErrorChange(me, msg);
      }
      break;
  }
}, updateErrorTarget:function(target, oldTarget) {
  var me = this, error, owner;
  if (oldTarget) {
    me.removeCls(Ext.baseCSSPrefix + 'error-target-' + oldTarget);
    if (oldTarget === 'qtip') {
      me.setTipError(null);
    } else {
      if (oldTarget === 'title') {
        me.setTitleError(null);
      } else {
        if (oldTarget === 'side') {
          me.setSideError(null);
        } else {
          if (oldTarget === 'under') {
            me.setUnderError(null);
          } else {
            if (oldTarget === 'parent') {
              owner = me.up('[onFieldErrorChange]');
              if (owner) {
                owner.onFieldErrorChange(me);
              }
            }
          }
        }
      }
    }
  }
  if (target) {
    me.addCls(Ext.baseCSSPrefix + 'error-target-' + target);
    if (!me.isConfiguring) {
      error = me.getError();
      if (error) {
        if (target === 'qtip') {
          me.setTipError(error);
        } else {
          if (target === 'title') {
            me.setTitleError(error);
          } else {
            if (target === 'side') {
              me.setSideError(error);
            } else {
              if (target === 'under') {
                me.setUnderError(error);
              } else {
                if (target === 'parent') {
                  owner = me.up('[onFieldErrorChange]');
                  if (owner) {
                    owner.onFieldErrorChange(me, error);
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}, updateInline:function(inline) {
  this.toggleCls(this.inlineCls, inline);
}, updateSideError:function(error) {
  if (error) {
    error = Ext.apply({html:error}, this.getErrorTip());
  }
  this.errorElement.getData().qtip = error;
}, updateTipError:function(error) {
  if (error) {
    error = Ext.apply({html:error}, this.getErrorTip());
  }
  this.bodyElement.getData().qtip = error;
}, updateTitleError:function(error) {
  var dom = this.el.dom;
  if (error) {
    dom.setAttribute('title', error);
  } else {
    dom.removeAttribute('title');
  }
}, updateUnderError:function(error) {
  this.errorMessageElement.dom.innerHTML = error || '';
}, updateLabel:function(label) {
  this.labelTextElement.setHtml(label);
  this.el.toggleCls(this.labeledCls, !!label);
}, updateLabelAlign:function(newLabelAlign, oldLabelAlign) {
  var me = this, element = me.element;
  if (oldLabelAlign) {
    element.removeCls(Ext.baseCSSPrefix + 'label-align-' + oldLabelAlign);
  }
  if (newLabelAlign) {
    element.addCls(Ext.baseCSSPrefix + 'label-align-' + newLabelAlign);
  }
  element.toggleCls(me.labelAlignVerticalCls, newLabelAlign in me.verticalLabelMap);
  element.toggleCls(me.labelAlignHorizontalCls, newLabelAlign in me.horizontalLabelMap);
}, updateLabelTextAlign:function(labelTextAlign, oldLabelTextAlign) {
  var element = this.element;
  if (oldLabelTextAlign) {
    element.removeCls(Ext.baseCSSPrefix + 'label-text-align-' + oldLabelTextAlign);
  }
  if (labelTextAlign) {
    element.addCls(Ext.baseCSSPrefix + 'label-text-align-' + labelTextAlign);
  }
}, updateLabelCls:function(newLabelCls, oldLabelCls) {
  var labelElement = this.labelElement;
  if (newLabelCls) {
    labelElement.addCls(newLabelCls);
  }
  if (oldLabelCls) {
    labelElement.removeCls(oldLabelCls);
  }
}, updateLabelWidth:function(labelWidth) {
  this.labelElement.setWidth(labelWidth);
}, updateLabelMinWidth:function(labelMinWidth) {
  this.labelElement.setStyle('min-width', Ext.Element.addUnits(labelMinWidth));
}, updateLabelWrap:function(labelWrap) {
  this.element.toggleCls(this.noLabelWrapCls, !labelWrap);
}, updateName:function(newName) {
  this.name = newName;
}, updateRequired:function(required) {
  var me = this;
  me.element.toggleCls(me.requiredCls, required);
  if (!me.isConfiguring) {
    me.validate();
  }
}, updateRequiredMessage:function() {
  if (!this.isConfiguring) {
    this.validate();
  }
}, updateDisabled:function(disabled, oldDisabled) {
  this.callParent([disabled, oldDisabled]);
  if (!this.isConfiguring) {
    this.validate();
  }
}, updateValidateDisabled:function() {
  if (!this.isConfiguring) {
    this.validate();
  }
}, applyValue:function(value) {
  if (this.isConfiguring) {
    this.originalValue = value;
  }
  return value;
}, updateValue:function(value, oldValue) {
  var me = this, rawToValue;
  if (!(Ext.isEmpty(value) && Ext.isEmpty(oldValue))) {
    me.validate();
  }
  if (value !== oldValue) {
    rawToValue = me.rawToValue(me.processRawValue(me.getRawValue()));
    if (!Ext.isEmpty(rawToValue, true) && String(value) !== String(rawToValue)) {
      me._value = value = rawToValue;
    }
    if (!me.isConfiguring) {
      me.fireEvent('change', me, value, oldValue);
    }
  }
  me.setDirty(me.isDirty());
}, reset:function() {
  this.setValue(this.originalValue);
  return this;
}, resetOriginalValue:function() {
  this.originalValue = this.getValue();
  this.setDirty(false);
}, isDirty:function() {
  return !this.isEqual(this.getValue(), this.originalValue);
}, toggleInvalidCls:function(hasError) {
  this.el[hasError ? 'addCls' : 'removeCls'](this.invalidCls);
}, markInvalid:function(messages) {
  this.setError(messages);
}, clearInvalid:function() {
  this.setError(null);
}, isValid:function() {
  return !this.getError();
}, isEqual:function(value1, value2) {
  return String(value1) === String(value2);
}, applyValidators:function(validators) {
  var me = this, i, len, ret;
  validators = validators && !Ext.isArray(validators) ? [validators] : validators;
  len = validators && validators.length;
  ret = len ? [] : null;
  for (i = 0; i < len; ++i) {
    ret.push(me.decodeValidator(validators[i]));
  }
  return ret;
}, wrapValidatorFn:function(fn, validator) {
  var me = this, scope = validator && validator.scope;
  return new Ext.data.validator.Validator(function(value) {
    return Ext.callback(fn, scope, [value], 0, me);
  });
}, doValidate:function(value, errors, skipLazy) {
  var validators = this.getValidators(), len = validators && validators.length, i, result, validator;
  for (i = 0; i < len; ++i) {
    validator = validators[i];
    if (!skipLazy || !validator.lazy) {
      result = validator.validate(value);
      if (result !== true) {
        if (!result || typeof result !== 'string') {
          Ext.raise('Validator did not return a valid result.');
        }
        errors.push(result);
      }
    }
  }
}, parseValue:Ext.identityFn, validate:function(skipLazy) {
  var me = this, empty, errors, field, record, validity, value;
  if (me.isConfiguring && me.validateOnInit === 'none') {
    return true;
  }
  if (!me.getDisabled() || me.getValidateDisabled()) {
    errors = [];
    if (me.isInputField && !me.isSelectField) {
      value = me.getInputValue();
      empty = !value;
      validity = empty && me.inputElement.dom.validity;
      if (validity && validity.badInput) {
        errors.push(me.badFormatMessage);
        empty = false;
      }
    } else {
      value = me.getValue();
      empty = value === '' || value == null;
    }
    if (empty && me.getRequired()) {
      errors.push(me.getRequiredMessage());
    } else {
      if (!errors.length) {
        if (!empty) {
          value = me.parseValue(value, errors);
        }
        if (!errors.length) {
          field = me._validationField;
          record = me._validationRecord;
          if (field && record) {
            field.validate(value, null, errors, record);
          }
          if (!empty) {
            me.doValidate(value, errors, skipLazy);
          }
        }
      }
    }
    if (errors.length) {
      me.setError(errors);
      return false;
    }
  }
  me.setError(null);
  return true;
}, getFocusClsEl:function() {
  return this.element;
}, updateHeight:function(height, oldHeight) {
  this.callParent([height, oldHeight]);
  this.syncFormLayoutHeight();
}, onAdded:function(parent, instanced) {
  this.callParent([parent, instanced]);
  this.syncFormLayoutHeight();
  this.validateLayout();
}, onRemoved:function(destroying) {
  this.callParent([destroying]);
  this.syncFormLayoutHeight();
}, rawToValue:Ext.identityFn, processRawValue:Ext.identityFn, transformRawValue:Ext.identityFn, getRawValue:function() {
  var me = this, value = me.inputElement ? me.inputElement.getValue() : Ext.valueFrom(me.rawValue, '');
  me.rawValue = value;
  return value;
}, handleFieldDefaults:function() {
  var me = this, inheritedState = me.getInherited(), fieldDefaults, key, prop, initialConfig, value;
  if (inheritedState) {
    fieldDefaults = inheritedState.fieldDefaults;
    if (fieldDefaults) {
      initialConfig = me.initialConfig;
      for (key in fieldDefaults) {
        if (!initialConfig[key]) {
          prop = Ext.util.Format.capitalize(key);
          value = fieldDefaults[key];
          if (me['set' + prop]) {
            me['set' + prop](value);
          } else {
            me[key] = value;
          }
        }
      }
    }
  }
}, serialize:function() {
  var me = this, value = me.getValue(), dataField;
  if (value != null) {
    dataField = me._validationField || me.getDataType();
    if (dataField && dataField.serialize) {
      value = dataField.serialize(value);
    }
  }
  return value;
}, privates:{syncFormLayoutHeight:function() {
  var me = this, parent = me.parent, height = me.getHeight();
  if (!(height && parent && parent.getLayout().isFormLayout)) {
    height = null;
  }
  me.bodyElement.setHeight(height);
}, validateLayout:function() {
  var errorTarget = this.getErrorTarget(), parent = this.parent;
  if (this.isInner && parent && parent.getLayout().isFormLayout) {
    this.setLabelAlign('left');
    if (errorTarget === 'under') {
      this.setErrorTarget('side');
    }
  }
}, applyBind:function(bind, currentBindings) {
  var me = this, valueBinding = currentBindings && currentBindings.value, bindings, newValueBind;
  bindings = me.callParent([bind, currentBindings]);
  if (bindings) {
    newValueBind = bindings.value;
    me.hasBindingValue = !!newValueBind;
    if (newValueBind !== valueBinding && me.getInherited().modelValidation) {
      me.updateValueBinding(bindings);
    }
  }
  return bindings;
}, updateValueBinding:function(bindings) {
  var me = this, newBinding = bindings.value, fieldBinding = bindings.$fieldBinding;
  if (fieldBinding) {
    fieldBinding.destroy();
    bindings.$fieldBinding = null;
  }
  if (newBinding && newBinding.bindValidationField) {
    me.fieldBinding = newBinding.bindValidationField('setValidationField', me);
  }
}, setValidationField:function(field, record) {
  this._validationField = field;
  this._validationRecord = record;
}, decodeValidator:function(validator) {
  var type = Ext.typeOf(validator), result = validator.fn;
  if (type === 'function') {
    result = this.wrapValidatorFn(validator);
  } else {
    if (type === 'regexp') {
      result = Ext.Factory.validator({type:'format', matcher:validator});
    } else {
      if (type === 'object' && result && !validator.isValidator) {
        result = this.wrapValidatorFn(result, validator);
      } else {
        result = Ext.Factory.validator(validator);
      }
    }
  }
  return result;
}}});
Ext.define('Ext.theme.material.field.Field', {override:'Ext.field.Field', config:{labelAlign:'top'}});
Ext.define('Ext.field.Input', {extend:Ext.field.Field, xtype:'inputfield', isInputField:true, tag:'input', config:{inputType:{cached:true, $value:'text'}, readOnly:false, inputValue:null}, focusEl:'inputElement', ariaEl:'inputElement', inputTabIndex:0, getBodyTemplate:function() {
  return [this.getInputTemplate()];
}, getInputTemplate:function() {
  return {tag:this.tag, reference:'inputElement', tabindex:this.inputTabIndex, cls:Ext.baseCSSPrefix + 'input-el'};
}, initElement:function() {
  this.callParent();
  this.labelElement.dom.setAttribute('for', this.inputElement.id);
}, updateDisabled:function(disabled, oldDisabled) {
  this.callParent([disabled, oldDisabled]);
  this.inputElement.dom.disabled = !!disabled;
}, updateInputType:function(newInputType) {
  this.setInputAttribute('type', newInputType);
}, updateName:function(name, oldName) {
  this.callParent([name, oldName]);
  this.setInputAttribute('name', name);
}, updateReadOnly:function(readOnly) {
  this.setInputAttribute('readonly', readOnly ? true : null);
}, updateValue:function(value, oldValue) {
  if (this.canSetInputValue()) {
    this.setInputValue(value);
  }
  this.callParent([value, oldValue]);
}, applyInputValue:function(value) {
  return value != null ? value + '' : '';
}, completeEdit:function() {
  var me = this, value = me.getInputValue(), parsedValue = me.parseValue(value);
  if (parsedValue !== null) {
    me.setInputValue(me.getValue());
  }
}, updateInputValue:function(value) {
  var inputElement = this.inputElement.dom;
  if (inputElement.value !== value) {
    inputElement.value = value;
  }
}, reset:function() {
  var me = this, original = me.originalValue;
  if (me.isEqual(original, me.getValue())) {
    me.setInputValue(original);
    if (!me.isValid()) {
      me.validate();
    }
  } else {
    me.setValue(original);
  }
  return me;
}, privates:{canSetInputValue:function() {
  return true;
}, setInputAttribute:function(attribute, newValue) {
  var inputElement = this.inputElement.dom;
  if (!Ext.isEmpty(newValue, true)) {
    inputElement.setAttribute(attribute, newValue);
  } else {
    inputElement.removeAttribute(attribute);
  }
}}, deprecated:{'6.5':{configs:{inputCls:null}}}});
Ext.define('Ext.field.trigger.Base', {extend:Ext.Widget, alias:'trigger.base', mixins:[Ext.mixin.Factoryable], factoryConfig:{defaultType:'trigger', aliasPrefix:'trigger.'}, isTrigger:true, config:{field:null, group:null, side:null, name:null, triggers:null}, classCls:Ext.baseCSSPrefix + 'trigger', groupedCls:Ext.baseCSSPrefix + 'grouped', inheritUi:true, statics:{sort:function(triggers) {
  Ext.sortByWeight(triggers);
  return triggers;
}}, doDestroy:function() {
  var triggers = this.getTriggers(), i, ln;
  if (triggers) {
    for (i = 0, ln = triggers.length; i < ln; i++) {
      triggers[i].destroy();
    }
  }
  this.setTriggers(null);
  this.callParent();
}, updateField:function(field) {
  this.field = this.ownerCmp = field;
  this.doInheritUi();
}, updateGroup:function(group) {
  if (!this.isConfiguring) {
    this.getField().syncTriggers();
  }
}, updateSide:function() {
  if (!this.isConfiguring) {
    this.getField().syncTriggers();
  }
}, updateTriggers:function(triggers) {
  var me = this, dom = me.element.dom, i, ln;
  me.toggleCls(me.groupedCls, !!(triggers && triggers.length));
  if (triggers) {
    for (i = 0, ln = triggers.length; i < ln; i++) {
      dom.appendChild(triggers[i].element.dom);
    }
  }
}});
Ext.define('Ext.field.trigger.Trigger', {extend:Ext.field.trigger.Base, xtype:'trigger', alias:'trigger.trigger', config:{handler:null, iconCls:null, repeat:null, scope:null, focusOnTap:true}, interactiveCls:Ext.baseCSSPrefix + 'interactive', template:[{reference:'iconElement', classList:[Ext.baseCSSPrefix + 'icon-el', Ext.baseCSSPrefix + 'font-icon']}], constructor:function(config) {
  var me = this, repeat;
  me.callParent([config]);
  repeat = me.getRepeat();
  if (repeat) {
    me.repeater = new Ext.util.ClickRepeater(Ext.apply({target:me, preventDefault:true, listeners:{mousedown:'onClickRepeaterTouchStart', mouseup:'onClickRepeaterTouchEnd', click:'onClickRepeaterClick', scope:me}}, repeat));
  } else {
    me.element.on({click:'onClick', mousedown:'onMouseDown', scope:me});
  }
}, doDestroy:function() {
  Ext.destroyMembers(this, 'repeater');
  this.callParent();
}, onClickRepeaterClick:function(clickRepeater, e) {
  this.onClick(e);
}, onClick:function(e) {
  var me = this, handler = !me.getDisabled() && me.getHandler(), field = me.getField(), disabled = !field || me.getDisabled() || field.getDisabled(), focusEl;
  if (disabled) {
    return;
  }
  if (e.pointerType !== 'mouse') {
    e.preventDefault();
    if (me.getFocusOnTap()) {
      focusEl = field.getFocusTrap ? field.getFocusTrap() : field.getFocusEl();
      if (focusEl.dom !== document.activeElement) {
        if (me.isExpandTrigger) {
          field.focusingFromExpandTrigger = true;
        }
        field.focus();
      }
    }
  }
  if (handler) {
    Ext.callback(handler, me.getScope(), [field, me, e], null, field);
  }
}, onMouseDown:function(e) {
  var field;
  if (e.pointerType === 'mouse') {
    field = this.getFocusOnTap() && this.getField();
    if (field && !field.getDisabled()) {
      field.focus();
    }
    e.preventDefault();
  }
}, onClickRepeaterTouchStart:function(clickRepeater, e) {
  this.onMouseDown(e);
}, onClickRepeaterTouchEnd:function(clickRepeater, e) {
  var me = this, field = me.field;
  Ext.callback(me.endHandler, me.scope, [field, me, e], 0, field);
}, updateHandler:function(handler) {
  this.toggleCls(this.interactiveCls, !!handler);
}, updateIconCls:function(iconCls, oldIconCls) {
  this.iconElement.replaceCls(oldIconCls, iconCls);
}});
Ext.define('Ext.field.trigger.Clear', {extend:Ext.field.trigger.Trigger, xtype:'cleartrigger', alias:'trigger.clear', classCls:Ext.baseCSSPrefix + 'cleartrigger', weight:-1000, hidden:true, handler:'onClearIconTap', scope:'this'});
Ext.define('Ext.field.Text', {extend:Ext.field.Input, xtype:'textfield', alternateClassName:'Ext.form.Text', config:{clearable:true, placeholder:null, maxLength:null, autoComplete:null, autoCapitalize:null, autoCorrect:null, autoHideInputMask:null, inputMask:null, pattern:null, triggers:{clear:{type:'clear'}}, editable:true, bodyAlign:'stretch', labelInPlaceholder:{lazy:true, $value:true}, textAlign:null}, cachedConfig:{animateUnderline:false, parseValidator:null}, bubbleEvents:['action'], badFormatMessage:'Value does not match the required format', 
defaultBindProperty:'value', twoWayBindable:{value:1}, publishes:{value:1}, inputType:'text', classCls:Ext.baseCSSPrefix + 'textfield', focusedCls:Ext.baseCSSPrefix + 'focused', emptyCls:Ext.baseCSSPrefix + 'empty', webkitBorderBoxBugCls:Ext.baseCSSPrefix + 'webkit-border-box-bug', requiredIndicator:'*', getBodyTemplate:function() {
  var template = [{reference:'beforeInputElement', cls:Ext.baseCSSPrefix + 'before-input-el'}];
  template.push(this.getInputTemplate());
  template.push({reference:'afterInputElement', cls:Ext.baseCSSPrefix + 'after-input-el'});
  return [{reference:'inputWrapElement', cls:Ext.baseCSSPrefix + 'input-wrap-el' + (Ext.supports.WebKitInputTableBoxModelBug ? ' ' + this.webkitBorderBoxBugCls : ''), children:template}, {reference:'underlineElement', cls:Ext.baseCSSPrefix + 'underline-el'}];
}, initialize:function() {
  var me = this;
  if (Ext.isRobot) {
    me.focusedInputDelay = 0;
  }
  me.callParent();
  me.inputElement.on({keyup:'onKeyUp', keydown:'onKeyDown', keypress:'onKeyPress', paste:'onPaste', mousedown:'onMouseDown', input:{fn:'onInput', delegated:false}, scope:me});
  if ((Ext.isChrome || Ext.isChromeMobile) && me.getLabelAlign() === 'placeholder') {
    me.inputElement.on('animationstart', me.onPlaceholderAutoFill, me);
  }
  me.syncEmptyState();
}, clearValue:function() {
  var me = this, inputMask = me.getInputMask();
  if (inputMask) {
    inputMask.showEmptyMask(me, true);
  } else {
    me.forceSetValue('');
  }
  me.syncEmptyState();
}, isEqual:function(value1, value2) {
  var v1 = this.transformValue(value1), v2 = this.transformValue(value2);
  return v1 === v2;
}, forceSetValue:function(value) {
  this.forceInputChange = true;
  this.setValue(value);
  this.forceInputChange = false;
}, transformValue:function(value) {
  if (value == null) {
    value = '';
  }
  return value;
}, applyInputMask:function(value, instance) {
  var InputMask = Ext.field['InputMask'];
  if (value) {
    if (!InputMask) {
      Ext.raise('Missing Ext.field.InputMask (required to use inputMask)');
    }
  }
  return value ? InputMask.from(value, instance) : null;
}, updateInputMask:function(inputMask, previous) {
  this.hasMask = false;
  if (previous) {
    previous.release();
  }
  if (inputMask) {
    this.hasMask = true;
    inputMask.syncPattern(this);
  }
}, doValidate:function(value, errors, skipLazy) {
  this.callParent([value, errors, skipLazy]);
  if (!skipLazy) {
    var inputMask = this.getInputMask();
    if (inputMask && !inputMask.isFilled(value) && value !== inputMask._mask) {
      errors.push(this.badFormatMessage);
    }
  }
}, parseValue:function(value, errors) {
  var me = this, parser = me.getParseValidator(), field, i, k, len, v, validators;
  if (parser) {
    field = me._validationField;
    for (k = 2; k-- > 0;) {
      validators = k ? me.getValidators() : field && field.getValidators();
      len = validators && validators.length;
      for (i = 0; i < len; ++i) {
        v = validators[i];
        if (v.parse) {
          v = v.parse(value);
          if (v !== null) {
            return v;
          }
        }
      }
    }
    value = parser.parse(value);
    if (value === null && errors) {
      errors.push(me.badFormatMessage);
    }
  }
  return value;
}, applyValue:function(value, oldValue) {
  if (value && typeof value === 'string') {
    value = this.parseValue(value);
    if (value === null) {
      return;
    }
  }
  return this.transformValue(this.callParent([value, oldValue]));
}, updateInputValue:function(value, oldValue) {
  var me = this, inputMask = me.getInputMask();
  me.callParent([value, oldValue]);
  me.syncEmptyState();
  me.syncLabelPlaceholder(false);
  if (inputMask) {
    inputMask.onChange(this, value, oldValue);
  }
}, updateTextAlign:function(newAlign, oldAlign) {
  var element = this.element;
  if (oldAlign) {
    element.removeCls(Ext.baseCSSPrefix + 'text-align-' + oldAlign);
  }
  if (newAlign) {
    element.addCls(Ext.baseCSSPrefix + 'text-align-' + newAlign);
  }
}, updatePlaceholder:function(value) {
  this.setInputAttribute('placeholder', value);
}, applyMaxLength:function(maxLength) {
  if (maxLength !== null && typeof maxLength !== 'number') {
    Ext.raise('Ext.field.Text: [applyMaxLength] value which is not a number');
  }
  return maxLength;
}, updateMaxLength:function(newMaxLength) {
  this.setInputAttribute('maxlength', newMaxLength);
}, applyAutoComplete:function(value) {
  return value === true || value === 'on';
}, updateAutoComplete:function(value) {
  this.setInputAttribute('autocomplete', value ? 'on' : 'off');
}, applyAutoCapitalize:function(value) {
  return value === true || value === 'on';
}, updateAutoCapitalize:function(value) {
  this.setInputAttribute('autocapitalize', value ? 'on' : 'off');
}, applyAutoCorrect:function(value) {
  return value === true || value === 'on';
}, updateAutoCorrect:function(value) {
  this.setInputAttribute('autocorrect', value ? 'on' : 'off');
}, updateReadOnly:function(newReadOnly) {
  var me = this, triggers = me.getTriggers(), isEditable = me.getEditable(), triggerName, trigger;
  me.callParent([newReadOnly || !isEditable]);
  for (triggerName in triggers) {
    trigger = triggers[triggerName];
    if (trigger.disableOnReadOnly !== false) {
      trigger.setDisabled(newReadOnly);
    }
  }
  me.syncEmptyState();
}, updateEditable:function(newEditable) {
  var triggers = this.getTriggers(), isReadOnly = this.getReadOnly(), triggerName, trigger;
  this.updateReadOnly(!newEditable);
  for (triggerName in triggers) {
    trigger = triggers[triggerName];
    if (trigger.disableOnReadOnly !== false) {
      triggers[triggerName].setDisabled(isReadOnly);
    }
  }
}, updatePattern:function(pattern) {
  this.setInputAttribute('pattern', pattern);
}, updateDisabled:function(disabled, oldDisabled) {
  this.callParent([disabled, oldDisabled]);
  this.syncEmptyState();
}, updateClearable:function(clearable, oldClearable) {
  var me = this, triggers, clearTrigger;
  if (!me.isConfiguring) {
    triggers = me.getTriggers();
    clearTrigger = triggers && triggers.clear;
    if (clearable) {
      if (!clearTrigger) {
        me.addTrigger('clear', 'clear');
      }
    } else {
      if (clearTrigger) {
        me.removeTrigger('clear');
      }
    }
  }
}, applyTriggers:function(triggers, oldTriggers) {
  var me = this, instances = oldTriggers || {}, clearable = me.getClearable(), name, trigger, oldTrigger;
  for (name in triggers) {
    trigger = triggers[name];
    oldTrigger = instances[name];
    if (oldTrigger) {
      oldTrigger.destroy();
    }
    if (trigger) {
      if (!clearable && name === 'clear') {
        continue;
      }
      instances[name] = me.createTrigger(name, trigger);
    }
  }
  return instances;
}, updateTriggers:function() {
  this.syncTriggers();
}, addTrigger:function(name, trigger) {
  var me = this, triggers = me.getTriggers(), triggerConfig;
  if (triggers && triggers[name]) {
    Ext.raise('Trigger with name "' + name + '" already exists.');
  }
  if (typeof name !== 'string') {
    Ext.raise('Cannot add trigger. Key must be a string.');
  }
  if (typeof trigger !== 'string' && !Ext.isObject(trigger)) {
    Ext.raise('Cannot add trigger "' + name + '". A config or instance is required.');
  }
  trigger = me.createTrigger(name, trigger);
  if (triggers) {
    triggers[name] = trigger;
    me.syncTriggers();
  } else {
    triggerConfig = {};
    triggerConfig[name] = trigger;
    me.setTriggers(triggerConfig);
  }
  return trigger;
}, removeTrigger:function(trigger, destroy) {
  var me = this, triggers = me.getTriggers(), name = trigger, triggerEl;
  if (name.isTrigger) {
    name = trigger.getName();
  } else {
    trigger = triggers[name];
  }
  if (!name) {
    Ext.raise('Trigger not found.');
  } else {
    if (!triggers[name]) {
      Ext.raise('Cannot remove trigger. Trigger with name "' + name + '" not found.');
    }
  }
  delete triggers[name];
  if (destroy !== false) {
    trigger.destroy();
  } else {
    triggerEl = trigger.el.dom;
    triggerEl.parentNode.removeChild(triggerEl);
  }
  this.syncTriggers();
  return trigger;
}, fireKey:function(e) {
  if (e.isSpecialKey()) {
    this.fireEvent('specialkey', this, e);
  }
}, onKeyPress:function(event) {
  var me = this, inputMask = me.getInputMask();
  if (inputMask) {
    inputMask.onKeyPress(me, me.getValue(), event);
  }
  me.fireEvent('keypress', me, event);
  if (!Ext.supports.SpecialKeyDownRepeat) {
    me.fireKey(event);
  }
}, onKeyDown:function(event) {
  var me = this, inputMask = me.getInputMask();
  me.lastKeyTime = Date.now();
  if (inputMask) {
    inputMask.onKeyDown(me, me.getValue(), event);
  }
  me.ignoreInput = true;
  if (Ext.supports.SpecialKeyDownRepeat) {
    me.fireKey(event);
  }
  me.fireAction('keydown', [me, event], 'doKeyDown');
}, doKeyDown:Ext.emptyFn, onKeyUp:function(e) {
  this.fireAction('keyup', [this, e], 'doKeyUp');
}, doKeyUp:function(me, e) {
  me.syncEmptyState();
  if (e.browserEvent.keyCode === 13) {
    me.fireAction('action', [me, e], 'doAction');
  }
}, onInput:function(e) {
  var me = this, inputEl = me.inputElement.dom, value = inputEl.value, inputMask = me.getInputMask(), parseErrors, oldValue;
  if (inputMask) {
    inputMask.processAutocomplete(this, value);
    value = inputEl.value;
  }
  me._inputValue = value;
  if (!me.hasFocus && me.getLabelAlign() === 'placeholder') {
    me.syncLabelPlaceholder(true);
  }
  if (value) {
    parseErrors = [];
    value = me.parseValue(value, parseErrors);
  }
  if (parseErrors && parseErrors.length) {
    me.setError(parseErrors);
  } else {
    oldValue = me.getValue();
    me.setValue(value);
    if (me.getValue() === oldValue) {
      me.validate();
    }
  }
  me.syncEmptyState();
  if (me.ignoreInput) {
    me.ignoreInput = false;
    return;
  }
  Ext.defer(function() {
    if (!me.ignoreInput && !me.destroyed) {
      me.fireEvent('keyup', e);
      me.ignoreInput = false;
    }
  }, 10);
}, doAction:function() {
  if (document.documentElement.getBoundingClientRect().top < 0) {
    this.blur();
  }
}, onClearIconTap:function(input, e) {
  this.fireAction('clearicontap', [this, input, e], 'doClearIconTap');
}, doClearIconTap:function() {
  this.clearValue();
}, onFocusEnter:function(event) {
  var me = this, inputMask = me.getInputMask();
  me.callParent([event]);
  me.addCls(me.focusedCls);
  me.syncLabelPlaceholder(true);
  if (inputMask) {
    inputMask.onFocus(me, me.getValue());
  }
}, onFocusLeave:function(event) {
  var me = this, inputMask = me.getInputMask();
  me.callParent([event]);
  me.removeCls(me.focusedCls);
  me.syncLabelPlaceholder(true);
  if (inputMask) {
    inputMask.onBlur(me, me.getValue());
  }
}, onPaste:function(e) {
  this.forceInputChange = true;
  this.handlePaste(e);
  this.forceInputChange = false;
}, getCaretPos:function() {
  return this.inputElement.getCaretPos();
}, setCaretPos:function(pos) {
  this.inputElement.setCaretPos(pos);
}, getTextSelection:function() {
  return this.inputElement.getTextSelection();
}, select:function(start, end, direction) {
  if (this.containsFocus) {
    this.inputElement.selectText(start, end, direction);
  }
  return this;
}, reset:function() {
  this.callParent();
  this.syncEmptyState();
}, onClick:function(e) {
  this.fireEvent('click', e);
}, onMouseDown:function(e) {
  this.fireEvent('mousedown', e);
}, trimValueToMaxLength:function() {
  var me = this, maxLength = me.getMaxLength(), value = me.getValue();
  if (maxLength && value.length > maxLength) {
    me.setValue(value.slice(0, maxLength));
  }
}, doDestroy:function() {
  var me = this, triggers = me.getTriggers(), triggerGroups = me.triggerGroups, name, animation;
  animation = me.labelElement && me.labelElement.getActiveAnimation();
  if (animation) {
    animation.stop();
  }
  if (triggerGroups) {
    for (name in triggerGroups) {
      triggerGroups[name].destroy();
    }
    me.triggerGroups = null;
  }
  for (name in triggers) {
    triggers[name].destroy();
  }
  me.setTriggers(null);
  me.setInputMask(null);
  me.callParent();
}, onRender:function() {
  this.callParent();
  this.syncLabelPlaceholder();
}, onPlaceholderAutoFill:function(event) {
  var me = this;
  if (event.browserEvent.animationName === 'onAutoFillStart') {
    me._animPlaceholderLabel = true;
    me.setLabelInPlaceholder(false);
    me.inputElement.removeListener('animationstart', me.onPlaceholderAutoFill, me);
  }
}, getRefItems:function(deep) {
  var me = this, triggers = me.getTriggers(), items = [], triggerName, trigger;
  for (triggerName in triggers) {
    trigger = triggers[triggerName];
    items.push(trigger);
    if (deep && trigger.getRefItems) {
      items.push.apply(items, trigger.getRefItems(deep));
    }
  }
  return items;
}, privates:{focusedInputDelay:300, forceInputChange:false, hasMask:false, lastKeyTime:0, applyParseValidator:function(config) {
  return this.decodeValidator(config);
}, updateLabelInPlaceholder:function(inside) {
  var me = this, placeHolder = me.getPlaceholder() || '', anim = me._animPlaceholderLabel;
  if (me.getLabelAlign() !== 'placeholder' || !me.getLabel()) {
    me.clearWhenVisible('doPositionPlaceholder');
    me.setInputAttribute('placeholder', placeHolder);
    return;
  }
  me.whenVisible('doPositionPlaceholder', [inside, anim]);
  me.el.toggleCls(Ext.baseCSSPrefix + 'label-inside', inside);
}, updateAnimateUnderline:function(value) {
  this.toggleCls(Ext.baseCSSPrefix + 'animate-underline', value);
}, canSetInputValue:function() {
  var me = this;
  return me.hasMask || me.forceInputChange || !me.hasFocus || Date.now() - me.lastKeyTime > me.focusedInputDelay;
}, doPositionPlaceholder:function(inside, doAnimate) {
  var me = this, labelElement = me.labelElement, anim, animation, info, insideInfo, outsideInfo;
  animation = labelElement.getActiveAnimation();
  if (animation) {
    animation.stop();
  }
  info = me.lastPlaceholderAnimInfo;
  if (!info) {
    me.lastPlaceholderAnimInfo = info = me.getPlaceholderAnimInfo();
  }
  insideInfo = info.inside;
  outsideInfo = info.outside;
  anim = {from:inside ? outsideInfo : insideInfo, to:inside ? insideInfo : outsideInfo, preserveEndState:true, duration:250, easing:'ease-out'};
  if (doAnimate) {
    labelElement.animate(anim);
  } else {
    labelElement.setStyle(anim.to);
  }
}, getPlaceholderLabel:function() {
  var me = this, label = me.getLabel();
  if (label && me.getRequired()) {
    label += ' ' + me.requiredIndicator;
  }
  return label;
}, getPlaceholderAnimInfo:function() {
  var me = this, element = me.element, labelElement = me.labelElement, inputElement = me.inputElement, labelOffsets = labelElement.getOffsetsTo(element), inputOffsets = inputElement.getOffsetsTo(element), labelLeftPadding = labelElement.getPadding('l'), inputLeftPadding = inputElement.getPadding('l'), labelTopPadding = labelElement.getPadding('t'), inputTopPadding = inputElement.getPadding('t'), translateX = inputOffsets[0] - labelOffsets[0] + (inputLeftPadding - labelLeftPadding), translateY = inputOffsets[1] - 
  labelOffsets[1] + (inputTopPadding - labelTopPadding);
  return {inside:{transform:{translateX:translateX + 'px', translateY:translateY + 'px'}, 'font-size':inputElement.getStyle('font-size')}, outside:{transform:{translateX:'0px', translateY:'0px'}, 'font-size':labelElement.getStyle('font-size')}};
}, handlePaste:function(e) {
  var me = this, inputMask = me.getInputMask();
  if (inputMask) {
    inputMask.onPaste(me, me.getValue(), e);
  }
  me.fireEvent('paste', me, e);
}, createTrigger:function(name, trigger) {
  if (!trigger.isTrigger) {
    if (trigger === true) {
      trigger = {type:name};
    } else {
      if (typeof trigger === 'string') {
        trigger = {type:trigger};
      }
    }
    trigger = Ext.apply({name:name, field:this}, trigger);
    trigger = trigger.xtype ? Ext.create(trigger) : Ext.Factory.trigger(trigger);
  }
  return trigger;
}, syncLabelPlaceholder:function(animate) {
  var me = this, inside;
  me._animPlaceholderLabel = animate;
  if (me.rendered) {
    if (me.hasValue()) {
      inside = false;
    } else {
      inside = !me.hasFocus || me.getDisabled() || me.getReadOnly();
    }
    me.setLabelInPlaceholder(inside);
  }
  me._animPlaceholderLabel = false;
}, hasValue:function() {
  return this.inputElement && this.inputElement.dom.value;
}, processRawValue:function(value) {
  var me = this, stripRe = me.stripCharsRe, mod, newValue;
  if (stripRe) {
    if (!stripRe.global) {
      mod = 'g';
      mod += stripRe.ignoreCase ? 'i' : '';
      mod += stripRe.multiline ? 'm' : '';
      stripRe = new RegExp(stripRe.source, mod);
    }
    newValue = value.replace(stripRe, '');
    if (newValue !== value) {
      if (!me.transformRawValue.$nullFn) {
        newValue = me.transformRawValue(newValue);
      }
      me.inputElement.dom.value = newValue;
      value = newValue;
    }
  }
  return value;
}, syncTriggers:function() {
  var me = this, triggers = me.getTriggers(), beforeInputElement = me.beforeInputElement, afterInputElement = me.afterInputElement, triggerGroups = me.triggerGroups || (me.triggerGroups = {}), beforeTriggers = [], afterTriggers = [], triggersByGroup = {}, TriggerBase = Ext.field.trigger['Base'], name, trigger, groupName, triggerGroup, i, ln;
  for (name in triggers) {
    trigger = triggers[name];
    groupName = trigger.getGroup();
    if (groupName) {
      (triggersByGroup[groupName] || (triggersByGroup[groupName] = [])).push(trigger);
    } else {
      if (trigger.getSide() === 'left') {
        beforeTriggers.push(trigger);
      } else {
        afterTriggers.push(trigger);
      }
    }
  }
  for (groupName in triggersByGroup) {
    triggerGroup = triggerGroups[groupName];
    if (!triggerGroup) {
      triggerGroup = triggers[groupName];
      if (!triggerGroup) {
        triggerGroup = new TriggerBase;
      }
      triggerGroups[groupName] = triggerGroup;
    }
    triggerGroup.setTriggers(TriggerBase.sort(triggersByGroup[groupName]));
    if (triggerGroup.getSide() === 'left') {
      beforeTriggers.push(triggerGroup);
    } else {
      afterTriggers.push(triggerGroup);
    }
  }
  TriggerBase.sort(beforeTriggers);
  TriggerBase.sort(afterTriggers);
  for (i = 0, ln = beforeTriggers.length; i < ln; i++) {
    beforeInputElement.appendChild(beforeTriggers[i].element);
  }
  for (i = 0, ln = afterTriggers.length; i < ln; i++) {
    afterInputElement.appendChild(afterTriggers[i].element);
  }
  for (groupName in triggerGroups) {
    if (!(groupName in triggersByGroup)) {
      triggerGroup = triggerGroups[groupName];
      triggerGroup.setTriggers(null);
      triggerGroup.destroy();
      delete triggerGroups[groupName];
    }
  }
}, syncEmptyState:function() {
  var me = this, triggers = me.getTriggers(), inputMask = me.getInputMask(), clearTrigger = triggers && triggers.clear, value = me.inputElement.dom.value, visible;
  me.toggleCls(me.emptyCls, !value);
  if (clearTrigger) {
    if (me.getClearable()) {
      if (me.hasValue() && !me.getDisabled() && !me.getReadOnly()) {
        visible = true;
      }
      if (inputMask) {
        if (value === inputMask._mask) {
          visible = false;
        }
      }
    }
    if (visible) {
      clearTrigger.show();
    } else {
      clearTrigger.hide();
    }
  }
}}, deprecated:{'6.5':{configs:{placeHolder:'placeholder', clearIcon:'clearable'}, methods:{getPlaceHolder:'getPlaceholder', setPlaceHolder:'setPlaceholder'}}}}, function() {
  if (Ext.os.is.Android) {
    window.addEventListener('resize', function() {
      var el = document.activeElement, tag = el && el.tagName, focusedField, focusedDom;
      if (tag === 'INPUT' || tag === 'TEXTAREA') {
        focusedField = Ext.Component.from(el);
        focusedDom = focusedField && focusedField.element && focusedField.element.dom;
        if (focusedDom) {
          if (focusedDom.scrollIntoViewIfNeeded) {
            focusedDom.scrollIntoViewIfNeeded();
          } else {
            focusedDom.scrollIntoView();
          }
        }
      }
    });
  }
});
Ext.define('Ext.theme.material.field.Text', {override:'Ext.field.Text', config:{labelAlign:'placeholder', animateUnderline:true}});
Ext.define('Ext.Img', {extend:Ext.Component, xtype:['image', 'img'], alternateClassName:'Ext.Image', config:{src:null, imageCls:Ext.baseCSSPrefix + 'img-image', backgroundCls:Ext.baseCSSPrefix + 'img-background', mode:'background'}, baseCls:Ext.baseCSSPrefix + 'img', beforeInitialize:function() {
  var me = this;
  me.onLoad = me.onLoad.bind(me);
  me.onError = me.onError.bind(me);
}, initialize:function() {
  var me = this;
  me.callParent();
  me.relayEvents(me.renderElement, '*');
  me.element.on({tap:'onTap', scope:me});
}, hide:function() {
  var me = this;
  me.callParent(arguments);
  me.hiddenSrc = me.hiddenSrc || me.getSrc();
  if (!me.isDestroying) {
    me.setSrc(null);
  }
}, afterShow:function() {
  this.callParent();
  if (this.hiddenSrc) {
    this.setSrc(this.hiddenSrc);
    delete this.hiddenSrc;
  }
}, updateMode:function(mode) {
  var me = this, imageCls = me.getImageCls(), backgroundCls = me.getBackgroundCls();
  if (mode === 'background') {
    if (me.imageElement) {
      me.imageElement.destroy();
      delete me.imageElement;
      me.updateSrc(me.getSrc());
    }
    me.replaceCls(imageCls, backgroundCls);
  } else {
    me.imageElement = me.element.createChild({tag:'img'});
    me.replaceCls(backgroundCls, imageCls);
  }
}, updateImageCls:function(newCls, oldCls) {
  this.replaceCls(oldCls, newCls);
}, updateBackgroundCls:function(newCls, oldCls) {
  this.replaceCls(oldCls, newCls);
}, onTap:function(e) {
  this.fireEvent('tap', this, e);
}, applySrc:function(src) {
  return src && Ext.resolveResource(src);
}, updateSrc:function(newSrc) {
  var me = this, dom;
  if (me.getMode() === 'background') {
    dom = this.imageObject || new Image;
  } else {
    dom = me.imageElement.dom;
  }
  this.imageObject = dom;
  dom.setAttribute('src', Ext.isString(newSrc) ? newSrc : '');
  dom.addEventListener('load', me.onLoad, false);
  dom.addEventListener('error', me.onError, false);
}, detachListeners:function() {
  var dom = this.imageObject;
  if (dom) {
    dom.removeEventListener('load', this.onLoad, false);
    dom.removeEventListener('error', this.onError, false);
  }
}, onLoad:function(e) {
  this.detachListeners();
  if (this.getMode() === 'background') {
    this.element.dom.style.backgroundImage = 'url("' + this.imageObject.src + '")';
  }
  this.fireEvent('load', this, e);
}, onError:function(e) {
  this.detachListeners();
  if (this.getMode() === 'background') {
    this.element.dom.style.backgroundImage = 'url("' + this.imageObject.src + '")';
  }
  this.fireEvent('error', this, e);
}, updateWidth:function(width) {
  var sizingElement = this.getMode() === 'background' ? this.element : this.imageElement;
  sizingElement.setWidth(width);
  this.callParent(arguments);
}, updateHeight:function(height) {
  var sizingElement = this.getMode() === 'background' ? this.element : this.imageElement;
  sizingElement.setHeight(height);
  this.callParent(arguments);
}, doDestroy:function() {
  var me = this;
  me.detachListeners();
  me.imageObject = me.imageElement = Ext.destroy(me.imageObject, me.imageElement);
  me.callParent();
}});
Ext.define('Ext.Label', {extend:Ext.Component, xtype:'label', baseCls:Ext.baseCSSPrefix + 'label'});
Ext.define('Ext.LoadMask', {extend:Ext.Mask, xtype:'loadmask', config:{message:'Loading...', cls:Ext.baseCSSPrefix + 'loading-mask', messageCls:Ext.baseCSSPrefix + 'mask-message', indicator:true}, getTemplate:function() {
  var prefix = Ext.baseCSSPrefix;
  return [{reference:'innerElement', cls:prefix + 'mask-inner', children:[{reference:'indicatorElement', cls:prefix + 'loading-spinner-outer', children:[{cls:prefix + 'loading-spinner', children:[{tag:'span', cls:prefix + 'loading-top'}, {tag:'span', cls:prefix + 'loading-right'}, {tag:'span', cls:prefix + 'loading-bottom'}, {tag:'span', cls:prefix + 'loading-left'}]}]}, {reference:'messageElement'}]}];
}, updateMessage:function(newMessage) {
  var cls = Ext.baseCSSPrefix + 'has-message';
  if (newMessage) {
    this.addCls(cls);
  } else {
    this.removeCls(cls);
  }
  this.messageElement.setHtml(newMessage);
}, updateMessageCls:function(newMessageCls, oldMessageCls) {
  this.messageElement.replaceCls(oldMessageCls, newMessageCls);
}, updateIndicator:function(newIndicator) {
  this[newIndicator ? 'removeCls' : 'addCls'](Ext.baseCSSPrefix + 'indicator-hidden');
}});
Ext.define('Ext.field.TextArea', {extend:Ext.field.Text, xtype:'textareafield', alternateClassName:'Ext.form.TextArea', config:{autoCapitalize:false, maxRows:null, clearable:false}, tag:'textarea', classCls:Ext.baseCSSPrefix + 'textareafield', applyMaxRows:function(maxRows) {
  if (maxRows !== null && typeof maxRows !== 'number') {
    throw new Error('Ext.field.TextArea: [applyMaxRows] trying to pass a value which is not a number');
  }
  return maxRows;
}, updateMaxRows:function(newRows) {
  this.setInputAttribute('rows', newRows);
}, doKeyUp:function(me) {
  this.syncEmptyState();
}});
Ext.define('Ext.MessageBox', {extend:Ext.Dialog, xtype:'messagebox', config:{iconCls:null, defaultTextHeight:75, buttons:null, message:null, prompt:null, layout:{type:'vbox', pack:'center'}, multiLine:null}, classCls:Ext.baseCSSPrefix + 'messagebox', closeAction:'hide', headerCls:[Ext.baseCSSPrefix + 'dialogheader', Ext.baseCSSPrefix + 'messageboxheader'], titleCls:[Ext.baseCSSPrefix + 'dialogtitle', Ext.baseCSSPrefix + 'messageboxtitle'], toolCls:[Ext.baseCSSPrefix + 'paneltool', Ext.baseCSSPrefix + 
'dialogtool', Ext.baseCSSPrefix + 'messageboxtool'], statics:{INFO:Ext.baseCSSPrefix + 'msgbox-info', WARNING:Ext.baseCSSPrefix + 'msgbox-warning', QUESTION:Ext.baseCSSPrefix + 'msgbox-question', ERROR:Ext.baseCSSPrefix + 'msgbox-error', OK:{ok:'me.onClick'}, YES:{yes:'me.onClick'}, NO:{no:'me.onClick'}, CANCEL:{cancel:'me.onClick'}, OKCANCEL:{ok:'me.onClick', cancel:'me.onClick'}, YESNOCANCEL:{yes:'me.onClick', no:'me.onClick', cancel:'me.onClick'}, YESNO:{yes:'me.onClick', no:'me.onClick'}}, constructor:function(config) {
  var allowedConfigs = ['ui', 'showAnimation', 'hideAnimation', 'title', 'message', 'prompt', 'iconCls', 'buttons', 'defaultTextHeight'], ln, i, allowedConfig;
  config = config || {};
  if (config.hasOwnProperty('multiline') || config.hasOwnProperty('multiLine')) {
    config.prompt = config.prompt || {};
    Ext.applyIf(config.prompt, {multiLine:config.multiline || config.multiLine});
    delete config.multiline;
    delete config.multiLine;
  }
  this.defaultAllowedConfig = {};
  ln = allowedConfigs.length;
  for (i = 0; i < ln; i++) {
    allowedConfig = allowedConfigs[i];
    this.defaultAllowedConfig[allowedConfig] = this.defaultConfig[allowedConfig];
  }
  this.callParent([config]);
}, applyTitle:function(config) {
  if (typeof config === 'string') {
    return config;
  }
  return config.title;
}, updateTitle:function(newTitle) {
  var header = this.getHeader() || {};
  if (Ext.isSimpleObject(header)) {
    header.title = newTitle;
    this.setHeader(header);
  } else {
    if (Ext.isFunction(header.setTitle)) {
      header.setTitle(newTitle);
    }
  }
}, applyMessage:function(config) {
  config = {html:config, cls:this.baseCls + '-text'};
  return Ext.factory(config, Ext.Component, this._message);
}, updateMessage:function(newMessage) {
  if (newMessage) {
    this.add(newMessage);
  }
}, getMessage:function() {
  if (this._message) {
    return this._message.getHtml();
  }
  return null;
}, applyIconCls:function(config) {
  if (config) {
    config = {xtype:'component', docked:'left', width:40, height:40, hidden:config ? false : true, cls:Ext.baseCSSPrefix + 'icon ' + config};
    return Ext.factory(config, Ext.Component, this._iconCls);
  }
  return config;
}, updateIconCls:function(newIconCls, oldIconCls) {
  this.getTitle();
  this.getButtons();
  if (newIconCls) {
    this.add(newIconCls);
  } else {
    this.remove(oldIconCls);
  }
}, getIconCls:function() {
  var icon = this._iconCls, iconCls;
  if (icon) {
    iconCls = icon.getCls();
    return iconCls ? iconCls[0] : null;
  }
  return null;
}, applyPrompt:function(prompt) {
  var config;
  if (prompt) {
    config = {label:false};
    if (Ext.isObject(prompt)) {
      Ext.apply(config, prompt);
    }
    if (config.multiLine) {
      config.height = Ext.isNumber(config.multiLine) ? parseFloat(config.multiLine) : this.getDefaultTextHeight();
      return Ext.factory(config, Ext.field['TextArea'], this.getPrompt());
    } else {
      return Ext.factory(config, Ext.field['Text'], this.getPrompt());
    }
  }
  return prompt;
}, updatePrompt:function(newPrompt, oldPrompt) {
  if (newPrompt) {
    this.add(newPrompt);
  }
  if (oldPrompt && !oldPrompt.destroyed) {
    this.remove(oldPrompt);
  }
}, onClick:function(button) {
  var me = this, msgBoxOptions = me.msgBoxOptions, prompt = me.getPrompt(), fn = msgBoxOptions.fn, which;
  if (button) {
    if (typeof fn === 'function') {
      button.disable();
      prompt = prompt ? prompt.getValue() : null;
      which = button.getItemId() || button.getText();
      me.on({single:true, hiddenchange:function() {
        fn.call(msgBoxOptions.scope || me, which, prompt, msgBoxOptions);
        button.enable();
      }});
    }
  }
  me.hide();
}, show:function(msgBoxOptions, options) {
  var me = this, buttons, config, prompt;
  Ext.util.InputBlocker.blockInputs();
  if (!msgBoxOptions) {
    return me.callParent(arguments);
  }
  config = Ext.apply({buttons:Ext.MessageBox.OK, draggable:false, prompt:null, defaultFocus:null}, msgBoxOptions);
  if (config.multiLine) {
    config.prompt = config.prompt || {};
    config.prompt.multiLine = config.multiLine;
    delete config.multiLine;
  }
  delete config.value;
  delete config.fn;
  delete config.scope;
  config = Ext.merge({}, me.defaultAllowedConfig, config);
  me.setConfig(config);
  me.msgBoxOptions = msgBoxOptions;
  buttons = me.getButtons();
  buttons.items.each(function(btn) {
    var value;
    if (btn.isButton) {
      value = btn.getScope();
      if (btn.fn && value) {
        btn.fn = btn.fn.bind(value);
      }
      value = btn.getHandler();
      if (!value || value === 'me.onClick') {
        btn.setHandler('onClick');
        btn.setScope(me);
      }
    }
  });
  prompt = me.getPrompt();
  if (prompt) {
    prompt.setValue(msgBoxOptions.value || '');
  }
  me.callParent([null, options]);
  return me;
}, alert:function(title, message, fn, scope) {
  return this.show({title:title || null, message:message || null, buttons:Ext.MessageBox.OK, defaultFocus:'#ok', prompt:false, fn:function() {
    if (fn) {
      Ext.callback(fn, scope, arguments);
    }
  }, scope:scope});
}, confirm:function(title, message, fn, scope) {
  return this.show({title:title || null, message:message || null, buttons:Ext.MessageBox.YESNO, defaultFocus:'#yes', prompt:false, scope:scope, fn:function() {
    if (fn) {
      Ext.callback(fn, scope, arguments);
    }
  }});
}, prompt:function(title, message, fn, scope, multiLine, value, prompt) {
  return this.show({title:title || null, message:message || null, buttons:Ext.MessageBox.OKCANCEL, scope:scope, prompt:prompt || true, defaultFocus:'textfield', multiLine:multiLine, value:value, fn:function() {
    if (fn) {
      Ext.callback(fn, scope, arguments);
    }
  }});
}}, function(MessageBox) {
  Ext.onInternalReady(function() {
    Ext.Msg = new Ext.MessageBox({id:'ext-messagebox'});
  });
});
Ext.define('Ext.SegmentedButton', {extend:Ext.Container, xtype:'segmentedbutton', alternateClassName:'Ext.button.Segmented', isSegmentedButton:true, classCls:Ext.baseCSSPrefix + 'segmentedbutton', config:{allowMultiple:false, allowDepress:false, allowToggle:true, forceSelection:false, pressedButtons:null, defaultType:'button', defaultUI:'segmented', value:undefined, vertical:false}, defaults:{flex:'1 1 auto'}, autoSize:null, layout:{type:'box', vertical:false, align:'stretch'}, defaultBindProperty:'value', 
twoWayBindable:'value', publishes:'value', constructor:function(config) {
  this.valueMap = {};
  this.callParent([config]);
}, initialize:function() {
  var me = this;
  me.callParent();
  me.onAfter({delegate:'\x3e button', scope:me, hide:'onButtonHiddenChange', show:'onButtonHiddenChange'});
}, applyPressedButtons:function(pressedButtons) {
  var buttons = pressedButtons, len, i, button;
  pressedButtons = [];
  if (buttons) {
    buttons = Ext.Array.from(buttons);
    len = buttons && buttons.length;
    for (i = 0; i < len; ++i) {
      button = this.getComponent(buttons[i]);
      if (button) {
        pressedButtons.push(button);
      }
    }
  }
  return pressedButtons;
}, updatePressedButtons:function(pressedButtons) {
  this.setValue(pressedButtons);
}, getPressedButtons:function() {
  var items = this.getItems().items, len = items.length, ret = [], i, button;
  for (i = 0; i < len; ++i) {
    button = items[i];
    if (button.getPressed()) {
      ret.push(button);
    }
  }
  return ret;
}, applyValue:function(value, oldValue) {
  var me = this, buttons = me.getItems(), allowMultiple = me.getAllowMultiple(), values, i, length, button, buttonValue;
  if (me.isConfiguring) {
    if (value == null) {
      values = [];
      length = buttons.length;
      for (i = 0; i < length; i++) {
        button = buttons.getAt(i);
        if (button.isPressed()) {
          buttonValue = me.getButtonValue(button);
          if (!Ext.Array.contains(values, buttonValue)) {
            values.push(buttonValue);
          }
        }
      }
      value = values;
    } else {
      value = Ext.Array.from(value);
      values = value;
      length = values.length;
      for (i = 0; i < length; i++) {
        button = me.lookupButtonByValue(values[i]);
        if (!button) {
          Ext.raise('Invalid value "' + value + '" for segmented button: "' + me.id + '"');
        }
      }
    }
  } else {
    value = Ext.Array.from(value);
    values = value;
    length = values.length;
    for (i = 0; i < length; i++) {
      button = me.lookupButtonByValue(values[i]);
      if (!button) {
        Ext.raise('Invalid value "' + value + '" for segmented button: "' + me.id + '"');
      }
    }
  }
  if (value.length > 1 && !allowMultiple) {
    Ext.raise('Cannot set multiple values when allowMultiple is false');
  }
  value = allowMultiple ? me.sortValues(value) : value[0];
  if ((allowMultiple ? !value.length : value == null) && me.getForceSelection()) {
    value = me.getButtonValue(buttons.getAt(0));
    if (allowMultiple) {
      value = [value];
    }
  }
  return Ext.isDefined(value) ? value : null;
}, updateValue:function(value, oldValue) {
  var me = this, changed = [], newValues = Ext.Array.from(value), oldValues = Ext.Array.from(oldValue), button, i, length;
  me.settingValue = true;
  if (oldValues.length) {
    length = oldValues.length;
    for (i = 0; i < length; i++) {
      button = me.lookupButtonByValue(oldValues[i]);
      if (!Ext.Array.contains(newValues, oldValues[i])) {
        button.setPressed(false);
        changed.push(button);
      }
    }
  }
  if (newValues.length) {
    length = newValues.length;
    for (i = 0; i < length; i++) {
      button = me.lookupButtonByValue(newValues[i]);
      if (!Ext.Array.contains(oldValues, newValues[i])) {
        button.setPressed(true);
        changed.push(button);
      }
    }
  }
  if (!me.isConfiguring) {
    if (me.hasListeners.toggle) {
      length = changed.length;
      me.sortToggleItems(changed);
      for (i = 0; i < length; i++) {
        button = changed[i];
        me.fireEvent('toggle', me, button, button.getPressed());
      }
    }
    if (me.hasListeners.change) {
      changed = me.getAllowMultiple() ? !Ext.Array.equals(value, oldValue) : value !== oldValue;
      if (changed) {
        me.fireEvent('change', me, value, oldValue);
      }
    }
  }
  me.settingValue = false;
}, updateAllowMultiple:function(allowMultiple) {
  if (!this.initialized && !this.getInitialConfig().hasOwnProperty('allowDepress') && allowMultiple) {
    this.setAllowDepress(true);
  }
}, updateVertical:function(vertical) {
  var me = this, vCls = Ext.baseCSSPrefix + 'vertical', hCls = Ext.baseCSSPrefix + 'horizontal';
  me.replaceCls(vertical ? hCls : vCls, vertical ? vCls : hCls);
  me.getLayout().setVertical(vertical);
}, onItemAdd:function(item, index) {
  var me = this, defaultUI = me.getDefaultUI(), value = item.getValue();
  me.getAllowMultiple();
  if (defaultUI && item.getUi() == null) {
    item.setUi(defaultUI);
  }
  if (value !== null) {
    me.valueMap[value] = item;
    me.useValueMap = true;
  }
  item.$segmentedListeners = item.on({scope:me, beforepressedchange:'onBeforePressedChange', pressedchange:'onPressedChange', order:'before', destroyable:true});
  me.callParent([item, index]);
  me.updateFirstAndLastCls(me.getItems());
  item.$enableToggle = item.getEnableToggle();
  item.$allowDepress = item.getAllowDepress();
  item.setEnableToggle(me.getAllowToggle());
  item.setAllowDepress(me.getAllowDepress());
}, onItemRemove:function(item, index, destroying) {
  var me = this, value = item.getValue(), useValueMap = me.useValueMap, listeners = item.$segmentedListeners, current, newValue, i;
  me.callParent([item, index, destroying]);
  if (!me.destroying) {
    if (listeners) {
      listeners.destroy();
    }
    me.updateFirstAndLastCls(this.getItems());
    if (useValueMap) {
      delete me.valueMap[value];
    } else {
      value = index;
    }
    if (item.getPressed()) {
      current = me.getValue();
      if (me.getAllowMultiple()) {
        index = current.indexOf(value);
        newValue = current.slice();
        if (!useValueMap) {
          for (i = newValue.length - 1; i > index; --i) {
            --newValue[i];
          }
        }
        newValue.splice(index, 1);
      } else {
        newValue = null;
      }
      me.setValue(newValue);
    }
    item.setEnableToggle(item.$enableToggle);
    item.setAllowDepress(item.$allowDepress);
  }
  item.$segmentedListeners = null;
}, isPressed:function(button) {
  return button.getPressed();
}, updateDisabled:function(disabled, oldDisabled) {
  var me = this;
  me.items.each(function(item) {
    item.setDisabled(disabled);
  }, me);
  me.callParent([disabled, oldDisabled]);
}, updateDefaultUI:function(defaultUI) {
  var items = this.items && this.items.items, len = items.length, i, item;
  for (i = 0; i < len; i++) {
    item = items[i];
    if (item.getUi() == null) {
      item.setUi(defaultUI);
    }
  }
}, doDestroy:function() {
  this.valueMap = null;
  this.callParent();
}, privates:{getAllPressed:function(items) {
  var map = {}, pressingItem = this.pressingItem, len, i, button, pressed;
  items = items.items;
  len = items.length;
  for (i = 0; i < len; ++i) {
    button = items[i];
    if (button === pressingItem) {
      pressed = !button.getPressed();
    } else {
      pressed = button.getPressed();
    }
    if (pressed) {
      map[button.id] = button;
    }
  }
  return map;
}, lookupButtonByValue:function(value) {
  return this.useValueMap ? this.valueMap[value] : this.getItems().getAt(value);
}, getButtonValue:function(button) {
  var value;
  if (this.useValueMap) {
    value = button.getValue();
  }
  if (value == null) {
    value = this.getItems().indexOf(button);
  }
  return value;
}, onBeforePressedChange:function(button, pressed) {
  var value = this.getValue(), ret;
  if (this.getForceSelection() && !pressed) {
    if (this.getAllowMultiple()) {
      ret = value.length === 1;
    } else {
      if (value === this.getButtonValue(button)) {
        ret = false;
      }
    }
  }
  return ret;
}, onPressedChange:function(button, pressed) {
  var me, Array, allowMultiple, buttonValue, value, valueIndex;
  if (this.settingValue) {
    return;
  }
  me = this;
  Array = Ext.Array;
  allowMultiple = me.getAllowMultiple();
  buttonValue = me.getButtonValue(button);
  value = me.getValue();
  if (allowMultiple) {
    valueIndex = Array.indexOf(value, buttonValue);
  }
  if (pressed) {
    if (allowMultiple) {
      if (valueIndex === -1) {
        value = Array.slice(value);
        value.push(buttonValue);
      }
    } else {
      value = buttonValue;
    }
  } else {
    if (allowMultiple) {
      if (valueIndex > -1) {
        value = Array.slice(value);
        value.splice(valueIndex, 1);
      }
    } else {
      if (value === buttonValue) {
        value = null;
      }
    }
  }
  me.pressingItem = button;
  me.setValue(value);
  me.pressingItem = null;
}, onButtonHiddenChange:function() {
  this.updateFirstAndLastCls(this.getItems());
}, sortToggleItems:function(buttons) {
  var items = this.getItems();
  Ext.Array.sort(buttons, function(a, b) {
    var p1 = a.getPressed() ? 1 : 0, p2 = b.getPressed() ? 1 : 0, ret = p1 - p2;
    if (ret === 0) {
      ret = items.indexOf(a) - items.indexOf(b);
    }
    return ret;
  });
}, sortValues:function(values) {
  var fn = Ext.Array.numericSortFn, map = this.valueMap, items = this.getItems();
  values = Ext.Array.clone(values);
  if (this.useValueMap) {
    fn = function(a, b) {
      a = items.indexOf(map[a]);
      b = items.indexOf(map[b]);
      return a - b;
    };
  }
  Ext.Array.sort(values, fn);
  return values;
}, updateFirstAndLastCls:function(items) {
  var ln = items.length, basePrefix = Ext.baseCSSPrefix, firstCls = basePrefix + 'first', lastCls = basePrefix + 'last', item, i;
  for (i = 0; i < ln; i++) {
    item = items.items[i];
    item.removeCls(firstCls);
    item.removeCls(lastCls);
  }
  for (i = 0; i < ln; i++) {
    item = items.items[i];
    if (!item.isHidden()) {
      item.addCls(firstCls);
      break;
    }
  }
  for (i = ln - 1; i >= 0; i--) {
    item = items.items[i];
    if (!item.isHidden()) {
      item.addCls(lastCls);
      break;
    }
  }
}}});
Ext.define('Ext.TitleBar', {extend:Ext.Container, xtype:'titlebar', defaultBindProperty:'title', isToolbar:true, classCls:Ext.baseCSSPrefix + 'titlebar', inheritUi:true, config:{cls:Ext.baseCSSPrefix + 'navigation-bar', title:null, titleAlign:'center', defaultType:'button', defaultButtonUI:null, minHeight:null, layout:{type:'hbox', align:'center'}, items:[], maxButtonWidth:'40%'}, autoSize:null, border:false, beforeInitialize:function() {
  this.applyItems = this.applyInitialItems;
}, initialize:function() {
  var me = this;
  me.callParent();
  delete me.applyItems;
  me.add(me.initialItems);
  delete me.initialItems;
  me.on({scope:me, painted:'refreshTitlePosition', single:true});
}, applyInitialItems:function(items) {
  var me = this, titleAlign = me.getTitleAlign(), defaults = me.getDefaults() || {};
  me.initialItems = items;
  me.leftBox = me.add({xtype:'container', style:'position: relative', cls:Ext.baseCSSPrefix + 'titlebar-left', autoSize:null, layout:{type:'hbox', align:'center'}, listeners:{resize:'refreshTitlePosition', scope:me}});
  me.spacer = me.add({xtype:'component', style:'position: relative', cls:Ext.baseCSSPrefix + 'titlebar-center', flex:1, listeners:{resize:'refreshTitlePosition', scope:me}});
  me.rightBox = me.add({xtype:'container', style:'position: relative', cls:Ext.baseCSSPrefix + 'titlebar-right', autoSize:null, layout:{type:'hbox', align:'center'}, listeners:{resize:'refreshTitlePosition', scope:me}});
  switch(titleAlign) {
    case 'left':
      me.titleComponent = me.leftBox.add({xtype:'title', cls:Ext.baseCSSPrefix + 'title-align-left', hidden:defaults.hidden});
      me.refreshTitlePosition = Ext.emptyFn;
      break;
    case 'right':
      me.titleComponent = me.rightBox.add({xtype:'title', cls:Ext.baseCSSPrefix + 'title-align-right', hidden:defaults.hidden});
      me.refreshTitlePosition = Ext.emptyFn;
      break;
    default:
      me.titleComponent = me.add({xtype:'title', hidden:defaults.hidden, centered:true});
      break;
  }
  me.doAdd = me.doBoxAdd;
  me.remove = me.doBoxRemove;
  me.doInsert = me.doBoxInsert;
}, doBoxAdd:function(item) {
  var me = this, titleAlign = me.getTitleAlign();
  me.addDefaultButtonUI(item);
  if (item.config.align === 'right') {
    me.rightBox.add(item);
  } else {
    if (me.titleComponent && titleAlign === 'left') {
      me.leftBox.insertBefore(item, me.titleComponent);
    } else {
      me.leftBox.add(item);
    }
  }
}, doBoxRemove:function(item, destroy) {
  if (item.config.align === 'right') {
    this.rightBox.remove(item, destroy);
  } else {
    this.leftBox.remove(item, destroy);
  }
}, doBoxInsert:function(index, item) {
  var me = this;
  me.addDefaultButtonUI(item);
  if (item.config.align === 'right') {
    me.rightBox.insert(index, item);
  } else {
    me.leftBox.insert(index, item);
  }
}, addDefaultButtonUI:function(item) {
  var defaultButtonUI = this.getDefaultButtonUI();
  if (defaultButtonUI) {
    if (item.isSegmentedButton) {
      if (item.getDefaultUI() == null) {
        item.setDefaultUI(defaultButtonUI);
      }
    } else {
      if (item.isButton && item.getUi() == null) {
        item.setUi(defaultButtonUI);
      }
    }
  }
}, calculateMaxButtonWidth:function() {
  var maxButtonWidth = this.getMaxButtonWidth();
  if (Ext.isString(maxButtonWidth)) {
    maxButtonWidth = parseInt(maxButtonWidth.replace('%', ''), 10);
  }
  maxButtonWidth = Math.round(this.element.getWidth() / 100 * maxButtonWidth);
  return maxButtonWidth;
}, refreshTitlePosition:function() {
  var titleElement, leftBox, leftButton, singleButton, leftBoxWidth, maxButtonWidth, spacerBox, titleBox, widthDiff, titleLeft, titleRight, halfWidthDiff, leftDiff, rightDiff;
  if (this.destroyed) {
    return;
  }
  titleElement = this.titleComponent.renderElement;
  titleElement.setWidth(null);
  titleElement.setLeft(null);
  leftBox = this.leftBox;
  leftButton = leftBox.down('button');
  singleButton = leftBox.getItems().getCount() === 1;
  if (leftButton && singleButton) {
    if (leftButton.getWidth() == null) {
      leftButton.renderElement.setWidth('auto');
    }
    leftBoxWidth = leftBox.renderElement.getWidth();
    maxButtonWidth = this.calculateMaxButtonWidth();
    if (leftBoxWidth > maxButtonWidth) {
      leftButton.renderElement.setWidth(maxButtonWidth);
    }
  }
  spacerBox = this.spacer.renderElement.getBox();
  if (Ext.browser.is.IE) {
    titleElement.setWidth(spacerBox.width);
  }
  titleBox = titleElement.getBox();
  widthDiff = titleBox.width - spacerBox.width;
  titleLeft = titleBox.left;
  titleRight = titleBox.right;
  if (widthDiff > 0) {
    halfWidthDiff = widthDiff / 2;
    titleLeft += halfWidthDiff;
    titleRight -= halfWidthDiff;
    titleElement.setWidth(spacerBox.width);
  }
  leftDiff = spacerBox.left - titleLeft;
  rightDiff = titleRight - spacerBox.right;
  if (leftDiff > 0) {
    titleElement.setLeft(leftDiff);
  } else {
    if (rightDiff > 0) {
      titleElement.setLeft(-rightDiff);
    }
  }
  titleElement.repaint();
}, updateTitle:function(newTitle) {
  this.getItems();
  this.titleComponent.setTitle(newTitle);
  if (this.isPainted()) {
    this.refreshTitlePosition();
  }
}});
Ext.define('Ext.theme.neptune.Titlebar', {override:'Ext.TitleBar', config:{defaultButtonUI:'alt'}});
Ext.define('Ext.theme.material.TitleBar', {override:'Ext.TitleBar', config:{titleAlign:'left', defaultButtonUI:'alt'}});
Ext.define('Ext.dataview.Location', {isDataViewLocation:true, isLocation:true, child:null, event:null, item:null, record:null, recordIndex:-1, sourceElement:null, view:null, viewIndex:-1, constructor:function(view, source) {
  this.view = view;
  if (source != null) {
    this.attach(source);
  }
}, attach:function(source) {
  var me = this, view = me.view, store = view.store, record, child, sourceElement;
  if (me.source) {
    Ext.raise('DataView Locations cannot be modified');
  }
  if (source.isEvent) {
    me.event = source;
    sourceElement = source.target;
  }
  if (source.isElement || source.nodeType === 1) {
    sourceElement = source;
  }
  me.source = source;
  if (source.isWidget) {
    sourceElement = source.getFocusEl();
    source = source.element;
  }
  if (typeof source === 'number') {
    child = view.itemFromRecord(source);
    me.recordIndex = source;
    record = store && store.getAt(source);
  } else {
    if (source.isModel) {
      record = source;
    } else {
      record = view.mapToRecord(source);
    }
    child = view.mapToItem(source);
    me.recordIndex = store ? store.indexOf(record) : -1;
  }
  if (child && !sourceElement) {
    sourceElement = child.isWidget ? child.getFocusEl() : child;
  }
  me.child = child;
  me.record = record;
  if (record && child) {
    me.item = child;
  }
  if (child) {
    me.viewIndex = view.mapToViewIndex(child);
  }
  me.sourceElement = Ext.getDom(sourceElement);
}, clone:function() {
  var me = this, ret = new this.self(me.view);
  ret.event = me.event;
  ret.sourceElement = me.sourceElement;
  ret.item = me.item;
  ret.record = me.record;
  ret.recordIndex = me.recordIndex;
  ret.viewIndex = me.viewIndex;
  return ret;
}, equals:function(other) {
  return other && other.view === this.view && other.isDataViewLocation && other.sourceElement === this.sourceElement;
}, getFocusEl:function(as) {
  var item = this.get(), ret = null;
  if (item && item.isWidget) {
    item = item.element;
  }
  if (item) {
    ret = as === 'dom' || as === true ? Ext.getDom(item) : Ext.get(item);
  }
  return ret;
}, get:function() {
  return this.child;
}, isFirstDataItem:function() {
  return this.recordIndex === 0;
}, isFirstViewItem:function() {
  var view = this.view;
  if (view.infinite) {
    return view.previous(this.child == null);
  }
  return this.viewIndex === 0;
}, isLastDataItem:function() {
  return this.recordIndex === this.view.store.getCount() - 1;
}, isLastViewItem:function() {
  var view = this.view;
  if (view.infinite) {
    return view.next(this.child == null);
  }
  return this.viewIndex === view.innerItems.length - 1;
}, refresh:function() {
  var me = this, view = me.view, item = me.child, newSource = view.mapToItem(me.record) || (view.items.contains(item) ? item : view.mapToItem(Math.min(me.viewIndex, view.dataItems.length - 1)));
  return new this.self(view, newSource);
}, isFirst:function() {
  return this.view.isFirstItem(this.child);
}, isLast:function() {
  return this.view.isLastItem(this.child);
}, next:function(options) {
  var me = this, candidate = me.nextItem(options), item = candidate && candidate.get();
  while (candidate && (!item || !item.el.isFocusable())) {
    if (candidate.equals(me)) {
      return me;
    }
    candidate = candidate.nextItem(options);
    item = candidate && candidate.get();
  }
  return candidate || me;
}, previous:function(options) {
  var me = this, candidate = me.previousItem(options), item = candidate && candidate.get();
  while (candidate && (!item || !item.el.isFocusable())) {
    if (candidate.equals(me)) {
      return me;
    }
    candidate = candidate.previousItem(options);
    item = candidate && candidate.get();
  }
  return candidate || me;
}, nextItem:function(options) {
  var view = this.view, item = this.child, wrap = typeof options === 'boolean' ? options : !!(options && options.wrap), nextItem;
  if (view.isLastItem(item)) {
    if (wrap) {
      nextItem = view.getFirstItem();
    } else {
      return null;
    }
  } else {
    nextItem = view.nextItem(item);
  }
  return new this.self(view, nextItem);
}, previousItem:function(options) {
  var view = this.view, item = this.child, wrap = typeof options === 'boolean' ? options : !!(options && options.wrap), prevItem;
  if (view.isFirstItem(item)) {
    if (wrap) {
      prevItem = view.getLastItem();
    } else {
      return null;
    }
  } else {
    prevItem = view.previousItem(item);
  }
  return new this.self(view, prevItem);
}, privates:{as:function(item, as) {
  if (item) {
    if (item.isWidget) {
      if (as === 'cmp') {
        return item;
      }
      item = item.el;
    }
    if (as === 'dom') {
      item = item.dom || item;
    } else {
      if (as === 'el') {
        if (!item.dom) {
          item = Ext.get(item);
        }
      } else {
        Ext.raise('Expected "as" to be "dom" or "el"');
      }
    }
  }
  return item || null;
}}});
Ext.define('Ext.dataview.NavigationModel', {extend:Ext.Evented, alias:'navmodel.dataview', mixins:[Ext.mixin.Factoryable, Ext.mixin.Bufferable], factoryConfig:{type:'navmodel', defaultType:'dataview', instanceProp:'isNavigationModel'}, isNavigationModel:true, config:{view:null, disabled:false}, virtualKeyboardInputRe:/^(input|textarea)$/i, bufferableMethods:{handleChildTrigger:1}, locationClass:'Ext.dataview.Location', setLocation:function(location, options) {
  var me = this, view = me.getView(), oldLocation = me.location, animation = options && options.animation, scroller, child, record, itemContainer, childFloatStyle, locationView;
  if (location == null) {
    return me.clearLocation();
  }
  if (!location.isDataViewLocation) {
    location = this.createLocation(location);
  }
  locationView = location.view;
  if (!location.equals(oldLocation)) {
    record = location.record;
    child = location.child;
    if (record && !child) {
      return locationView.ensureVisible(record, {animation:animation}).then(function() {
        if (!me.destroyed) {
          locationView.getNavigationModel().setLocation({record:record, column:location.column}, options);
        }
      });
    }
    if (child && me.floatingItems == null) {
      child = child.isComponent ? child.el : Ext.fly(child);
      itemContainer = child.up();
      childFloatStyle = child.getStyleValue('float');
      me.floatingItems = view.getInline && view.getInline() || child.isStyle('display', 'inline-block') || childFloatStyle === 'left' || childFloatStyle === 'right' || itemContainer.isStyle('display', 'flex') && itemContainer.isStyle('flex-direction', 'row');
    }
    scroller = locationView.getScrollable();
    if (scroller) {
      scroller.ensureVisible(location.sourceElement, {animation:options && options.animation});
    }
    me.handleLocationChange(location, options);
    if (!me.destroyed) {
      me.doFocus();
    }
  }
}, clearLocation:function() {
  var me = this, targetElement;
  if (me.location) {
    me.lastLocation = me.location;
    targetElement = me.location.getFocusEl();
    if (targetElement && !targetElement.destroyed) {
      Ext.fly(targetElement).removeCls(me.focusedCls);
      me.previousLocation = me.location;
    } else {
      me.previousLocation = null;
    }
    me.location = null;
  }
}, getLocation:function() {
  return this.location;
}, getPreviousLocation:function() {
  var result = this.previousLocation;
  if (result && (!result.sourceElement || !result.sourceElement.destroyed)) {
    result.refresh();
  }
  return result;
}, disable:function() {
  this.setDisabled(true);
}, enable:function() {
  this.setDisabled(false);
}, privates:{createLocation:function(source, options) {
  return Ext.create(this.locationClass, this.getView(), source, options);
}, getKeyNavCfg:function(view) {
  var me = this;
  return {target:view.getFocusEl(), processEvent:me.processViewEvent, processEventScope:me, eventName:'keydown', defaultEventAction:'stopEvent', esc:me.onKeyEsc, f2:me.onKeyF2, up:me.onKeyUp, down:me.onKeyDown, right:me.onKeyRight, left:me.onKeyLeft, pageDown:me.onKeyPageDown, pageUp:me.onKeyPageUp, home:me.onKeyHome, end:me.onKeyEnd, space:me.onKeySpace, enter:me.onKeyEnter, tab:me.onKeyTab, A:{ctrl:true, handler:me.onSelectAllKeyPress}, scope:me};
}, updateView:function(view) {
  var me = this, keyNavCfg = me.getKeyNavCfg(view);
  me.focusedCls = view.focusedCls;
  if (keyNavCfg) {
    me.keyNav = new Ext.util.KeyNav(keyNavCfg);
  }
  me.viewListeners = view.on(me.getViewListeners(view));
}, getViewListeners:function(view) {
  var result = {scope:this};
  result[view.getTriggerEvent()] = 'onChildTrigger';
  return result;
}, processViewEvent:function(e) {
  var location = this.getLocation(), component;
  if (location && e.keyCode) {
    component = Ext.fly(e.target).component;
    e.navigationMode = component && component.parent === this.getView();
    e.setCurrentTarget(location.sourceElement);
    if (!Ext.fly(e.target).isInputField()) {
      return e;
    }
  }
}, doFocus:function(location) {
  var sourceEl, activeEl, focusEl;
  location = location || this.location;
  if (location) {
    focusEl = location && location.getFocusEl();
    if (Ext.os.is.iOS) {
      sourceEl = location.sourceElement;
      activeEl = document.activeElement;
      if (sourceEl && activeEl && sourceEl.nodeName.match(this.virtualKeyboardInputRe) && activeEl.nodeName.match(this.virtualKeyboardInputRe)) {
        return;
      }
    }
    if (focusEl) {
      focusEl.focus();
    }
  }
}, onFocusMove:function(e) {
  var location = this.createLocation(e);
  if (!location.equals(this.location)) {
    this.handleLocationChange(location, {event:e, navigate:false});
  }
}, handleLocationChange:function(location, options) {
  var me = this, oldLocation = me.location, view = me.getView(), target, item;
  me.previousLocation = oldLocation;
  if (oldLocation) {
    me.lastLocation = oldLocation;
    target = oldLocation.getFocusEl();
    if (target && !target.destroyed) {
      Ext.fly(target).removeCls(me.focusedCls);
    }
  }
  me.location = location;
  target = location && location.getFocusEl('dom');
  if (target) {
    item = location.get();
    if (item) {
      if (item.isWidget) {
        item = item.el;
      } else {
        item = Ext.get(item);
      }
      if (item && target === item.dom) {
        item.addCls(me.focusedCls);
      }
      if (options && (options.event || options.select) && options.navigate !== false) {
        me.onNavigate(options.event);
      }
    }
  }
  if (!view.destroyed) {
    view.fireEvent('navigate', view, location, oldLocation);
  }
}, onKeyUp:function(e) {
  var me = this;
  e.preventDefault();
  if (me.location) {
    if (me.floatingItems) {
      me.moveUp(e);
    } else {
      me.movePrevious({event:e});
    }
  } else {
    me.setLocation(0);
  }
}, onKeyDown:function(e) {
  var me = this;
  e.preventDefault();
  if (me.location) {
    if (me.floatingItems) {
      me.moveDown(e);
    } else {
      me.moveNext({event:e});
    }
  } else {
    me.setLocation(0);
  }
}, onKeyLeft:function(e) {
  e.preventDefault();
  this.movePrevious({event:e});
}, onKeyRight:function(e) {
  e.preventDefault();
  this.moveNext({event:e});
}, onKeyF2:function(e) {
  return false;
}, onKeyEsc:function(e) {
  return false;
}, onKeyTab:function(e) {
  return !this.location.actionable;
}, onKeyPageDown:function(e) {
  var me = this, candidate, view, y;
  e.preventDefault();
  if (!me.location.actionable && !me.floatingItems) {
    view = me.getView();
    y = (view.infinite ? view.getItemTop(me.location.child) : me.location.child.el.dom.offsetTop) + view.el.getClientRegion().height;
    candidate = me.createLocation(view.getItemFromPoint(0, y));
    if (!(candidate.child && candidate.child.el.isFocusable())) {
      candidate = candidate.previous();
    }
    me.setLocation(candidate, {event:e});
  }
}, onKeyPageUp:function(e) {
  var me = this, candidate, view, y;
  e.preventDefault();
  if (!me.location.actionable && !me.floatingItems) {
    view = me.getView();
    y = (view.infinite ? view.getItemTop(me.location.child) : me.location.child.el.dom.offsetTop) - view.el.getClientRegion().height;
    candidate = me.createLocation(view.getItemFromPoint(0, y));
    if (!(candidate.child && candidate.child.el.isFocusable())) {
      candidate = candidate.next();
    }
    me.setLocation(candidate, {event:e});
  }
}, onKeyHome:function(e) {
  this.setLocation(0, {event:e});
}, onKeyEnd:function(e) {
  this.setLocation(this.getView().getStore().last(), {event:e});
}, onKeySpace:function(e) {
  this.onNavigate(e);
}, onKeyEnter:function(e) {
  e.stopEvent();
  this.getView()._onChildTap(e);
}, onSelectAllKeyPress:function(e) {
  var view = this.getView(), selModel = view.getSelectable();
  if (selModel && view.getStore().getCount()) {
    selModel[selModel.allSelected ? 'deselectAll' : 'selectAll']();
    e.preventDefault();
    return false;
  }
}, moveUp:function(e) {
  var view = this.getView(), location = this.location, el = this.location.sourceElement, topCentre = Ext.fly(el).getAnchorXY('t'), item;
  topCentre[1] -= Ext.fly(el).getMargin('tb') + 10;
  item = view.getItemFromPagePoint(topCentre[0], topCentre[1], true);
  if (!item || !item.isFocusable()) {
    item = location.isFirst() ? view.getLastItem() : view.getFirstItem();
  }
  if (item) {
    this.setLocation(item, {event:e});
  }
}, moveDown:function(e) {
  var view = this.getView(), location = this.location, el = location.sourceElement, bottomCentre = Ext.fly(el).getAnchorXY('b'), item;
  bottomCentre[1] += Ext.fly(el).getMargin('tb') + 10;
  item = view.getItemFromPagePoint(bottomCentre[0], bottomCentre[1]);
  if (!item || !item.isFocusable()) {
    item = location.isLast() ? view.getFirstItem() : view.getLastItem();
  }
  if (item) {
    this.setLocation(item, {event:e});
  }
}, moveNext:function(options) {
  var location = this.getLocation();
  if (location) {
    location = location.next(options);
    if (location) {
      this.setLocation(location, options);
    }
  }
}, movePrevious:function(options) {
  var location = this.getLocation();
  if (location) {
    location = location.previous(options);
    if (location) {
      this.setLocation(location, options);
    }
  }
}, onChildTrigger:function(view, location) {
  var e = location.event, isFocusingEvent = e.type === (e.pointerType === 'touch' ? 'tap' : 'touchstart');
  if (event.target.id === location.child.id) {
    this.handleLocationChange(location, {event:e});
    return;
  }
  if (isFocusingEvent) {
    this.handleChildTrigger(view, location);
  } else {
    this.doHandleChildTrigger(view, location);
  }
}, doHandleChildTrigger:function(view, location) {
  var myLocation = this.location, event = location.event, compareMethod = location.isGridLocation ? 'equalCell' : 'equals';
  if (myLocation && myLocation[compareMethod](location)) {
    this.onNavigate(event);
  } else {
    this.setLocation(location, {event:event});
  }
}, onNavigate:function(event) {
  var me = this, location = me.location;
  if (!event) {
    event = new Ext.event.Event({target:location.sourceElement});
  }
  Ext.apply(event, {navigationModel:me, from:me.previousLocation, to:location});
  me.getView().onNavigate(event);
}, updateDisabled:function(disabled) {
  if (this.keyNav) {
    if (disabled) {
      this.keyNav.disable();
    } else {
      this.keyNav.enable();
    }
  }
}}});
Ext.define('Ext.dataview.selection.Selection', {mixins:[Ext.mixin.Factoryable], factoryConfig:{type:'selection', defaultType:'records', instanceProp:'isSelection'}, isSelection:true, config:{selectionModel:null}, constructor:function(config) {
  if (config.isDataView) {
    config = {selectionModel:config.getSelectionModel()};
  }
  this.initConfig(config);
  if (!this.getSelectionModel()) {
    Ext.raise('Selection must be configured with a SelectionModel');
  }
}, destroy:function() {
  this.clear();
  this.callParent();
}, privates:{applySelectionModel:function(selectionModel) {
  var view = selectionModel.getView();
  this.view = view.isGrid ? view.ownerGrid : view;
  return selectionModel;
}}});
Ext.define('Ext.dataview.selection.Rows', {extend:Ext.dataview.selection.Selection, alias:'selection.rows', isRows:true, config:{selected:true}, clone:function() {
  return new this.self({selectionModel:this.getSelectionModel(), selected:(new Ext.util.Spans).unstash(this.getSelected().stash())});
}, add:function(range, keepExisting, suppressEvent) {
  var me = this, view = me.view, rowIdx, tmp, record;
  if (range.length === 1) {
    range = range[0];
  }
  if (range.isEntity) {
    record = range;
    range = view.mapToRecordIndex(range);
  }
  if (typeof range === 'number') {
    range = [range, range + 1];
  }
  if (range.length !== 2 || typeof range[0] !== 'number' || typeof range[1] !== 'number') {
    Ext.raise('add must be called with a [start, end] row index *EXCLUSIVE* range');
  }
  if (range[0] > range[1]) {
    tmp = range[1];
    range[1] = range[0];
    range[0] = tmp;
  }
  me.lastSelected = range[1];
  if (!keepExisting) {
    me.clear();
  }
  me.getSelected().add(range);
  for (rowIdx = range[0]; rowIdx < range[1]; rowIdx++) {
    view.onItemSelect(rowIdx);
  }
  me.manageSelection(record);
  if (!suppressEvent) {
    me.getSelectionModel().fireSelectionChange();
  }
}, remove:function(range, suppressEvent) {
  var me = this, selModel = me.getSelectionModel(), view = me.view, rowIdx;
  if (!selModel.getDeselectable() && me.getCount() === 1) {
    return;
  }
  if (range.length === 1) {
    range = range[0];
  }
  if (range.isEntity) {
    range = view.mapToRecordIndex(range);
  }
  if (typeof range === 'number') {
    range = [range, range + 1];
  }
  if (!range.length === 2 && typeof range[0] === 'number' && typeof range[1] === 'number') {
    Ext.raise('remove must be called with a [start, end] record *EXCLUSIVE* range');
  }
  if (range[0] > range[1]) {
    Ext.raise('Range must be [startIndex, endIndex] (exclusive end)');
  }
  me.getSelected().remove(range);
  for (rowIdx = range[0]; rowIdx < range[1]; rowIdx++) {
    view.onItemDeselect(rowIdx);
  }
  if (!suppressEvent) {
    selModel.fireSelectionChange();
  }
}, isSelected:function(record) {
  var me = this, ranges = me.getSelected().spans, len = ranges.length, recIndex, range, i;
  recIndex = record.isEntity ? me.view.getStore().indexOf(record) : record;
  for (i = 0; i < len; i++) {
    range = ranges[i];
    if (recIndex >= range[0] && recIndex < range[1]) {
      return true;
    }
  }
  return false;
}, getCount:function() {
  return this.getSelected().getCount();
}, selectAll:function() {
  var view = this.view, items = view.dataItems, len = items.length, i;
  for (i = 0; i < len; i++) {
    view.onItemSelect(i);
  }
  this.getSelected().add(0, view.store.getTotalCount() || view.store.getCount());
  this.getSelectionModel().fireSelectionChange();
}, getFirstRowIndex:function() {
  var ranges = this.getSelected().spans;
  return ranges.length ? this.getSelected().spans[0][0] : 0;
}, getLastRowIndex:function() {
  var ranges = this.getSelected().spans;
  return ranges.length ? ranges[ranges.length - 1][1] - 1 : 0;
}, eachRow:function(fn, scope) {
  var me = this, ranges = me.getSelected().spans, len = ranges && ranges.length, result, range, i, j;
  for (i = 0; i < len; i++) {
    range = ranges[i];
    for (j = range[0]; result !== false && j < range[1]; j++) {
      result = fn.call(this || scope, j);
    }
  }
}, eachColumn:function(fn, scope) {
  var columns = this.view.getHeaderContainer().getVisibleColumns(), len = columns.length, i;
  if (this.getCount()) {
    for (i = 0; i < len; i++) {
      if (fn.call(this || scope, columns[i], i) === false) {
        return;
      }
    }
  }
}, eachCell:function(fn, scope) {
  var me = this, selection = me.getSelected(), view = me.view, columns = view.ownerGrid.getVisibleColumnManager().getColumns(), range = me.dragRange, colCount, i, j, location, recCount, abort = false;
  if (columns) {
    colCount = columns.length;
    location = new Ext.grid.Location(view);
    if (selection) {
      me.eachRow(function(recordIndex) {
        location.setItem(recordIndex);
        for (i = 0; i < colCount; i++) {
          location.setColumn(columns[i]);
          if (fn.call(scope || me, location, location.columnIndex, location.recordIndex) === false) {
            abort = true;
            return false;
          }
        }
      });
    }
    if (!abort && range != null) {
      me.view.getStore().getRange(range[0], range[1], {forRender:false, callback:function(records) {
        recCount = records.length;
        for (i = 0; !abort && i < recCount; i++) {
          location.setItem(records[i]);
          for (j = 0; !abort && j < colCount; j++) {
            location.setColumn(columns[j]);
            if (fn.call(scope || me, location, location.columnIndex, location.recordIndex) === false) {
              abort = true;
            }
          }
        }
      }});
    }
  }
}, privates:{applySelected:function(spans) {
  if (!spans.isSpans) {
    spans = new Ext.util.Spans;
  }
  return spans;
}, compareRanges:function(lhs, rhs) {
  return lhs[0] - rhs[0];
}, clear:function(suppressEvent) {
  var me = this, selModel = me.getSelectionModel(), view = me.view, items = view.dataItems, len = items.length, indexTop = view.renderInfo.indexTop, i;
  for (i = 0; i < len; i++) {
    view.onItemDeselect(i + indexTop);
  }
  me.getSelected().clear();
  if (!selModel.getDeselectable() && me.lastSelected) {
    me.add(me.lastSelected, true, true);
  }
  me.manageSelection(null);
  if (!suppressEvent) {
    selModel.fireSelectionChange();
  }
}, addRecordRange:function(start, end) {
  return this.add([start, end + 1], true);
}, removeRecordRange:function(start, end) {
  return this.remove([start, end + 1]);
}, isAllSelected:function() {
  var store = this.view.store;
  return this.getCount() === (store.getTotalCount() || store.getCount());
}, setRangeStart:function(start) {
  if (start == null) {
    this.dragRange = null;
  } else {
    this.dragRange = [start, start];
    this.view.onItemSelect(start, true);
  }
}, setRangeEnd:function(end) {
  var me = this, dragRange = me.dragRange || (me.dragRange = [0, end]), oldEnd = dragRange[1], start = dragRange[0], view = me.view, renderInfo = view.renderInfo, tmp = dragRange[1] = end, removeRange = [], addRange = false, rowIdx, limit;
  if (start > end) {
    end = start;
    start = tmp;
  }
  rowIdx = Math.max(Math.min(dragRange[0], start, oldEnd, end), renderInfo.indexTop);
  limit = Math.min(Math.max(dragRange[1], start, oldEnd, end), renderInfo.indexBottom - 1);
  for (; rowIdx <= limit; rowIdx++) {
    if (rowIdx < start || rowIdx > end) {
      view.onItemDeselect(rowIdx);
      removeRange[removeRange.length ? 1 : 0] = rowIdx;
    } else {
      view.onItemSelect(rowIdx, true);
      addRange = true;
    }
  }
  if (addRange) {
    me.addRange(true);
  }
  if (removeRange.length) {
    me.removeRecordRange(removeRange[0], removeRange[1]);
  }
  me.lastSelectedIndex = end;
}, addRange:function(keep) {
  var range = this.dragRange;
  if (range) {
    this.addRecordRange(range[0], range[1]);
    if (!keep) {
      this.dragRange = null;
    }
  }
}, extendRange:function(extensionVector) {
  this.addRecordRange(extensionVector.start, extensionVector.end);
}, reduceRange:function(extensionVector) {
  this.removeRecordRange(extensionVector.start, extensionVector.end);
}, getRange:function() {
  var range = this.dragRange;
  if (range == null) {
    return [0, -1];
  }
  if (range[0] <= range[1]) {
    return range;
  }
  return [range[1], range[0]];
}, getRangeSize:function() {
  var range = this.getRange();
  return range[1] - range[0] + 1;
}, onSelectionFinish:function() {
  var me = this, range = me.getContiguousSelection();
  if (range) {
    me.getSelectionModel().onSelectionFinish(me, new Ext.grid.Location(me.view, {record:range[0], column:0}), new Ext.grid.Location(me.view, {record:range[1], column:me.view.getHeaderContainer().getVisibleColumns().length - 1}));
  } else {
    me.getSelectionModel().onSelectionFinish(me);
  }
}, getContiguousSelection:function() {
  var selected = this.getSelected(), store = this.view.store, spans = selected.spans;
  if (spans === 1 && store.getAt(spans[0][0]) && store.getAt(spans[0][1])) {
    return selected.spans[0];
  }
}, manageSelection:function(record) {
  var me = this, view = me.view, store = view.getStore(), selModel = me.getSelectionModel(), selected;
  if (!store.isVirtualStore || selModel.getMode() !== 'single') {
    return;
  }
  selected = selModel.getSelected();
  if (selected.length) {
    me.adjustPageLock(store, selected.getAt(0), -1);
  }
  if (record) {
    selected.splice.apply(selected, [0, 0, record]);
    me.adjustPageLock(store, record, 1);
  } else {
    selected.remove(selected.getAt(0));
  }
}, adjustPageLock:function(store, record, delta) {
  var page;
  if (!store.isVirtualStore || !record) {
    return;
  }
  page = store.pageMap.getPageOf(store.indexOf(record));
  if (page) {
    page.adjustLock('active', delta);
  }
}}});
Ext.define('Ext.dataview.selection.Records', {extend:Ext.dataview.selection.Rows, alias:'selection.records', isRecords:true, config:{selected:null}, constructor:function(config) {
  this.callParent([config]);
  var selected = this.getSelected();
  if (!(selected && selected.isCollection)) {
    Ext.raise('Ext.dataview.selection.Records must be given a selected Collection');
  }
}, clone:function() {
  return new this.self({selectionModel:this.getSelectionModel(), selected:this.getSelected()});
}, addRowRange:function(start, end, keepExisting, suppressEvent) {
  if (typeof start !== 'number' || typeof end !== 'number') {
    Ext.raise('addRange must be called with a [start, end] row index *EXCLUSIVE* range');
  }
  if (start > end) {
    var tmp = end;
    end = start;
    start = tmp;
  }
  this.add(this.getSelectionModel().getStore().getRange(start, end - 1), keepExisting, suppressEvent);
}, removeRowRange:function(start, end, suppressEvent) {
  if (typeof start !== 'number' || typeof end !== 'number') {
    Ext.raise('addRange must be called with a [start, end] row index *EXCLUSIVE* range');
  }
  if (start > end) {
    var tmp = end;
    end = start;
    start = tmp;
  }
  this.remove(this.getSelectionModel().getStore().getRange(start, end - 1), suppressEvent);
}, add:function(records, keepExisting, suppressEvent) {
  records = Ext.Array.from(records);
  for (var i = 0, ln = records.length; i < ln; i++) {
    if (!records[i].isEntity) {
      Ext.raise('add must be called with records or an array of records');
    }
  }
  var me = this, selected = me.getSelected(), selectionCount = selected.getCount(), args = [keepExisting ? selectionCount : 0, keepExisting ? 0 : selectionCount, records];
  selected.suppressEvent = suppressEvent;
  selected.splice.apply(selected, args);
  selected.suppressEvent = false;
}, remove:function(records, suppressEvent) {
  records = Ext.Array.from(records);
  for (var i = 0, ln = records.length; i < ln; i++) {
    if (!records[i].isEntity) {
      Ext.raise('add must be called with records or an array of records');
    }
  }
  var selected = this.getSelected();
  if (!this.getSelectionModel().getDeselectable() && selected.getCount() === 1) {
    Ext.Array.remove(records, selected.first());
  }
  if (records.length) {
    selected.suppressEvent = suppressEvent;
    selected.remove(records);
    selected.suppressEvent = false;
  }
}, isSelected:function(record) {
  if (!record || !record.isModel) {
    return false;
  }
  return !!this.getSelected().byInternalId.get(record.internalId);
}, getRecords:function() {
  return this.getSelected().getRange();
}, selectAll:function(suppressEvent) {
  var selected = this.getSelected();
  selected.suppressEvent = suppressEvent;
  selected.add(this.getSelectionModel().getStore().getRange());
  selected.suppressEvent = false;
}, getFirstRowIndex:function() {
  return this.getCount() ? this.view.getStore().indexOf(this.getSelected().first()) : 0;
}, getLastRowIndex:function() {
  return this.getCount() ? this.view.getStore().indexOf(this.getSelected().last()) : -1;
}, eachRow:function(fn, scope) {
  var selectedRecords = this.getSelected();
  if (selectedRecords) {
    selectedRecords.each(fn, scope || this);
  }
}, eachColumn:function(fn, scope) {
  var columns = this.view.getHeaderContainer().getVisibleColumns(), len = columns.length, i;
  if (this.getSelected().getCount()) {
    for (i = 0; i < len; i++) {
      if (fn.call(this || scope, columns[i], i) === false) {
        return;
      }
    }
  }
}, eachCell:function(fn, scope) {
  var me = this, selection = me.getSelected(), view = me.view, columns = view.getHeaderContainer().getVisibleColumns(), colCount, i, baseLocation, location;
  if (columns) {
    colCount = columns.length;
    baseLocation = new Ext.grid.Location(view);
    if (selection) {
      selection.each(function(record) {
        location = baseLocation.clone({record:record});
        for (i = 0; i < colCount; i++) {
          location = location.cloneForColumn(columns[i]);
          if (fn.call(scope || me, location, location.columnIndex, location.recordIndex) === false) {
            return false;
          }
        }
      });
    }
  }
}, beginUpdate:function() {
  this.getSelected().beginUpdate();
}, endUpdate:function() {
  this.getSelected().endUpdate();
}, privates:{clear:function(suppressEvent) {
  var selected = this.getSelected(), spliceArgs;
  if (selected) {
    spliceArgs = [0, selected.getCount()];
    if (!this.getSelectionModel().getDeselectable()) {
      spliceArgs[2] = selected.last();
    }
    selected.suppressEvent = suppressEvent;
    selected.splice.apply(selected, spliceArgs);
    selected.suppressEvent = false;
  }
}, addRecordRange:function(start, end) {
  var me = this, view = me.view, store = view.getStore(), tmp = end, range;
  if (start && start.isGridLocation) {
    start = start.recordIndex;
  }
  if (end && end.isGridLocation) {
    end = tmp = end.recordIndex;
  }
  if (start > end) {
    end = start;
    start = tmp;
  }
  range = store.getRange(start, end || start);
  me.getSelected().add(range);
}, removeRecordRange:function(start, end) {
  var me = this, view = me.view, store = view.getStore(), tmp = end, range;
  if (start && start.isGridLocation) {
    start = start.recordIndex;
  }
  if (end && end.isGridLocation) {
    end = tmp = end.recordIndex;
    tmp = end;
  }
  if (start > end) {
    end = start;
    start = tmp;
  }
  range = store.getRange(start, end || start);
  this.getSelected().remove(range);
}, onSelectionFinish:function() {
  var me = this, range = me.getContiguousSelection();
  if (range) {
    me.getSelectionModel().onSelectionFinish(me, new Ext.grid.Location(me.view, {record:range[0], column:0}), new Ext.grid.Location(me.view, {record:range[1], column:me.view.getHeaderContainer().getVisibleColumns().length - 1}));
  } else {
    me.getSelectionModel().onSelectionFinish(me);
  }
}, getContiguousSelection:function() {
  var store = this.view.getStore(), selection, len, i;
  selection = Ext.Array.sort(this.getSelected().getRange(), function(r1, r2) {
    return store.indexOf(r1) - store.indexOf(r2);
  });
  len = selection.length;
  if (len) {
    if (len === 1 && store.indexOf(selection[0]) === -1) {
      return false;
    }
    for (i = 1; i < len; i++) {
      if (store.indexOf(selection[i]) !== store.indexOf(selection[i - 1]) + 1) {
        return false;
      }
    }
    return [store.indexOf(selection[0]), store.indexOf(selection[len - 1])];
  }
}, applySelected:function(selected) {
  if (!selected) {
    Ext.raise('Must pass the selected Collection to the Records Selection');
  }
  return selected;
}, refresh:function() {
  var me = this, view = me.view, selModel = me.getSelectionModel(), selected = me.getSelected(), lastSelected = selModel.getLastSelected(), lastSelectedIdx;
  Ext.dataview.selection.Model.refreshCollection(selected, selModel.getStore().getData(), selModel.ignoredFilters, view.beforeSelectionRefresh && view.beforeSelectionRefresh.bind(view));
  lastSelectedIdx = selected.indexOf(lastSelected);
  if (lastSelectedIdx === -1) {
    selModel.setLastSelected(selected.last());
  } else {
    selModel.setLastSelected(selected.getAt(lastSelectedIdx));
  }
}}});
Ext.define('Ext.dataview.selection.Model', {extend:Ext.Evented, alias:'selmodel.dataview', mixins:[Ext.mixin.Factoryable], factoryConfig:{type:'selmodel', defaultType:'dataview', aliasPrefix:'selmodel.'}, isSelectionModel:true, config:{view:null, store:null, disabled:null, mode:'single', deselectable:true, toggleOnClick:true, lastSelected:null, selected:true, selectedRecord:undefined, selection:{type:'records'}}, modes:{single:true, simple:true, multi:true}, onNavigate:function(e) {
  if (!this.getDisabled()) {
    this.selectWithEvent(e.to.record, e);
  }
}, getSelectedRecords:function() {
  var selection = this.getSelection();
  return selection && selection.isRecords ? selection.getRecords() : Ext.emptyArray;
}, getStoreListeners:function() {
  return {add:'onSelectionStoreAdd', remove:'onSelectionStoreRemove', update:'onSelectionStoreUpdate', clear:{fn:'onSelectionStoreClear', priority:1000}, load:'onSelectionStoreLoad', refresh:'refreshSelection', idchanged:'onIdChanged'};
}, applySelected:function(selected, oldSelected) {
  var me = this, store = me.getStore(), collectionConfig = {rootProperty:'data', extraKeys:{byInternalId:{rootProperty:false, property:'internalId'}}, sorters:[function(r1, r2) {
    return store.indexOf(r1) - store.indexOf(r2);
  }], autoSort:false};
  if (oldSelected) {
    oldSelected.removeObserver(me);
    if (me.destroySelected) {
      oldSelected.destroy();
      me.destroySelected = false;
    }
  }
  if (selected && selected.isCollection) {
    me.destroySelected = false;
    selected.setConfig(collectionConfig);
  } else {
    me.destroySelected = true;
    selected = new Ext.util.Collection(Ext.apply(collectionConfig, selected));
  }
  me.observerPriority = 1000;
  selected.addObserver(me);
  return selected;
}, updateSelected:function(selected) {
  this.setSelectedRecord(selected.last() || null);
}, applyMode:function(mode) {
  var view = this.getView(), el = view.getRenderTarget();
  mode = mode ? mode.toLowerCase() : 'single';
  el.toggleCls(view.multiSelectCls, mode === 'multi');
  return this.modes[mode] ? mode : 'single';
}, updateMode:function(mode) {
  var selection = this.getSelection();
  if (mode !== 'multi' && selection.getCount() > 1) {
    selection.add(this.getLastSelected(), false);
  }
}, updateView:function(view) {
  this.setStore(view ? view.getStore() : null);
}, applyStore:function(store) {
  return store ? Ext.data.StoreManager.lookup(store) : null;
}, updateStore:function(newStore, oldStore) {
  var me = this, bindEvents = Ext.apply({scope:me}, me.getStoreListeners());
  if (oldStore && Ext.isObject(oldStore) && oldStore.isStore) {
    oldStore.un(bindEvents);
  }
  if (newStore) {
    newStore.on(bindEvents);
    if (oldStore) {
      me.refreshSelection();
    }
  }
}, selectByLocation:function(location) {
  if (!location.isDataViewLocation) {
    Ext.raise('selectByLocation MUST be passed an Ext.dataview.Location');
  }
  this.select(location.record);
}, selectAll:function(suppressEvent) {
  this.select(this.getStore().getRange(), true, suppressEvent);
}, deselectAll:function(suppressEvent) {
  var selected = this.getSelected();
  selected.suppressEvent = suppressEvent;
  selected.removeAll();
  selected.suppressEvent = false;
}, applySelectedRecord:function(selectedRecord) {
  if (selectedRecord === false) {
    selectedRecord = null;
  }
  return selectedRecord;
}, updateSelectedRecord:function(selectedRecord) {
  var me = this, selected = me.getSelected(), selectionCount = selected.getCount();
  if (selectedRecord) {
    if (selected.last() !== selectedRecord) {
      if (me.getMode() === 'single') {
        selected.splice(0, selectionCount, selectedRecord);
      } else {
        selected.add(selectedRecord);
      }
    }
    me.setLastSelected(selectedRecord);
  } else {
    if (!me.isConfiguring && selectionCount) {
      me.deselectAll();
    }
  }
  me.getView().publishState('selection', selectedRecord);
}, selectWithEvent:function(record, e) {
  var me = this, mode = me.getMode(), isSelected = me.isSelected(record);
  if (mode === 'multi') {
    me.selectWithEventMulti(record, e, isSelected);
  } else {
    if (isSelected) {
      if (me.getDeselectable() && (mode === 'single' && me.getToggleOnClick()) || mode === 'simple' || e.ctrlKey) {
        me.deselect(record);
      }
    } else {
      me.select(record, mode === 'simple');
    }
  }
  if (!e.shiftKey && me.isSelected(record)) {
    me.selectionStart = record;
  }
}, selectWithEventMulti:function(record, e, isSelected) {
  var me = this, shift = e.shiftKey, ctrl = e.ctrlKey, start = shift ? me.selectionStart : null;
  if (shift && start) {
    me.selectRange(start, record, ctrl);
  } else {
    if (isSelected) {
      me.deselect(record);
    } else {
      me.select(record, true);
    }
  }
}, selectRange:function(startRecord, endRecord, keepExisting) {
  var store = this.getStore(), tmp;
  startRecord = typeof startRecord === 'number' ? startRecord : store.indexOf(startRecord);
  endRecord = typeof endRecord === 'number' ? endRecord : store.indexOf(endRecord);
  if (startRecord > endRecord) {
    tmp = startRecord;
    startRecord = endRecord;
    endRecord = tmp;
  }
  this.getSelection().addRowRange(startRecord, endRecord + 1, keepExisting);
}, select:function(records, keepExisting, suppressEvent) {
  var me = this, record;
  if (me.getDisabled()) {
    return;
  }
  if (typeof records === 'number') {
    records = [me.getStore().getAt(records)];
  }
  if (!records) {
    return;
  }
  if (me.getMode() === 'single' && records) {
    if (me.getSelected().getCount()) {
      me.getSelection().clear(true);
    }
    record = records.length ? records[0] : records;
    me.doSingleSelect(record, suppressEvent);
  } else {
    me.doMultiSelect(records, keepExisting, suppressEvent);
  }
}, doSingleSelect:function(record, suppressEvent) {
  this.doMultiSelect([record], false, suppressEvent);
}, doMultiSelect:function(records, keepExisting, suppressEvent) {
  if (records === null || this.getDisabled()) {
    return;
  }
  this.getSelection().add(records, keepExisting, suppressEvent);
}, deselect:function(records, suppressEvent) {
  var me = this, selection, store, len, i, record;
  if (me.getDisabled()) {
    return;
  }
  records = Ext.isArray(records) ? records : [records];
  selection = me.getSelection();
  store = me.getStore();
  len = records.length;
  for (i = 0; i < len; i++) {
    record = records[i];
    if (typeof record === 'number') {
      records[i] = store.getAt(record);
    }
  }
  selection.remove(records, suppressEvent);
}, onCollectionRemove:function(selectedCollection, chunk) {
  var me = this, view = me.getView(), records = chunk.items;
  me.getSelection().allSelected = this.allSelected = false;
  if (!chunk.next && !chunk.replacement) {
    me.setSelectedRecord(selectedCollection.last() || null);
  }
  view.onItemDeselect(records, selectedCollection.suppressEvent);
  if (!selectedCollection.suppressEvent) {
    me.fireSelectionChange(records, false);
  }
}, onCollectionAdd:function(selectedCollection, adds) {
  var me = this, view = me.getView(), selection = me.getSelection(), records = adds.items;
  if (view.destroyed) {
    return;
  }
  selection.allSelected = this.allSelected = selection.getCount() === view.getStore().getCount();
  me.setSelectedRecord(selectedCollection.last() || null);
  view.onItemSelect(me.getMode() === 'single' ? records[0] : records, selectedCollection.suppressEvent);
  if (!selectedCollection.suppressEvent) {
    me.fireSelectionChange(records, true);
  }
}, fireSelectionChange:function(records, selected) {
  var me = this, view = me.getView(), sel = me.getSelection();
  me.fireEvent('selectionchange', this.view, records, selected, sel);
  view.fireEvent('selectionchange', this.view, records, selected, sel);
}, getSelections:function() {
  if (this.getSelection().isRecords) {
    return this.getSelected().getRange();
  }
}, isRowSelected:function(record) {
  var me = this, sel = me.getSelection();
  if (sel && (sel.isRows || sel.isRecords)) {
    record = Ext.isNumber(record) ? me.getStore().getAt(record) : record;
    return sel.isSelected(record);
  }
  return false;
}, isSelected:function(record) {
  return this.getSelection().isSelected(record);
}, hasSelection:function() {
  return this.getSelection().getCount() > 0;
}, refreshSelection:function() {
  if (this.getSelection().isRecords) {
    this.getSelection().refresh();
  }
}, onSelectionStoreRemove:function(store, records) {
  var selection = this.getSelection();
  if (selection.isRecords) {
    selection.remove(records);
  }
}, onSelectionStoreClear:function(store) {
  this.getSelection().clear();
}, getSelectionCount:function() {
  return this.getSelection().getCount();
}, destroy:function() {
  var me = this;
  me.setView(null);
  Ext.destroy(me.selection, me.destroySelected ? me.selected : null);
}, onIdChanged:function(store, rec, oldId, newId) {
  var selected = this.getSelected();
  if (selected) {
    selected.updateKey(rec, oldId);
  }
}, onSelectionStoreAdd:Ext.emptyFn, onSelectionStoreLoad:Ext.emptyFn, onSelectionStoreUpdate:Ext.emptyFn, onItemSelect:Ext.emptyFn, onItemDeselect:Ext.emptyFn, onEditorKey:Ext.emptyFn, privates:{addIgnoredFilter:function(filter) {
  if (filter) {
    Ext.Array.include(this.ignoredFilters || (this.ignoredFilters = []), filter);
  }
}, removeIgnoredFilter:function(filter) {
  var ignoredFilters = this.ignoredFilters;
  if (ignoredFilters) {
    Ext.Array.remove(ignoredFilters, filter);
    if (!ignoredFilters.length) {
      this.ignoredFilters = null;
    }
  }
}, onSelectionFinish:Ext.privateFn, applySelection:function(selection, oldSelection) {
  if (oldSelection) {
    if (oldSelection.type === selection.type) {
      oldSelection.setConfig(selection);
      return oldSelection;
    }
    Ext.destroy(oldSelection);
  }
  if (selection) {
    var store = this.getStore();
    selection = Ext.Factory.selection(Ext.apply({selectionModel:this, type:store && store.isVirtualStore ? 'rows' : 'records', selected:this.getSelected()}, selection));
  }
  return selection;
}}, statics:{refreshCollection:function(collection, filteredCollection, ignoredFilters, beforeRefresh) {
  var filterFn = filteredCollection.getFilters().getFilterFn(), selections, toRemove = [], toAdd = [], len, selectionLength, i, rec, matchingSelection, toReEnable;
  if (ignoredFilters) {
    toReEnable = [];
    len = ignoredFilters.length;
    for (i = 0; i < len; i++) {
      if (!ignoredFilters[i].getDisabled()) {
        toReEnable.push(ignoredFilters[i]);
        ignoredFilters[i].setDisabled(true);
      }
    }
    if (toReEnable.length) {
      filteredCollection = filteredCollection.getSource() || filteredCollection;
    } else {
      ignoredFilters = null;
    }
  }
  if (collection.getCount()) {
    selections = collection.getRange();
    selectionLength = selections.length;
    for (i = 0; i < selectionLength; i++) {
      rec = selections[i];
      matchingSelection = filteredCollection.get(filteredCollection.getKey(rec));
      if (matchingSelection && ignoredFilters && !filterFn(matchingSelection)) {
        matchingSelection = null;
      }
      if (matchingSelection) {
        if (matchingSelection !== rec) {
          toRemove.push(rec);
          toAdd.push(matchingSelection);
        }
      } else {
        toRemove.push(rec);
      }
    }
    if (beforeRefresh) {
      beforeRefresh(toRemove, toAdd);
    }
    collection.suppressEvent = true;
    collection.splice(collection.getCount(), toRemove, toAdd);
    collection.suppressEvent = false;
  }
  if (toReEnable) {
    len = toReEnable.length;
    for (i = 0; i < len; i++) {
      toReEnable[i].setDisabled(false);
    }
  }
}}});
Ext.define('Ext.dataview.EmptyText', {extend:Ext.Component, xtype:'emptytext', classCls:Ext.baseCSSPrefix + 'emptytext', inheritUi:true, html:'No data to display', top:0, right:0, bottom:0, left:0});
Ext.define('Ext.dataview.Abstract', {extend:Ext.Container, mixins:[Ext.mixin.ConfigProxy, Ext.mixin.ItemRippler], isDataView:true, cachedConfig:{associatedData:null, deferEmptyText:true, deselectOnContainerClick:true, disableSelection:false, emptyTextDefaults:{xtype:'emptytext'}, emptyItemText:' ', itemsFocusable:true, itemTpl:'\x3cdiv\x3e{text:htmlEncode}\x3c/div\x3e', loadingText:'Loading...', pressedDelay:100, scrollToTopOnRefresh:true, storeEventListeners:{add:'onStoreAdd', beforeload:'onStoreBeforeLoad', 
clear:'onStoreClear', load:'onStoreLoad', refresh:'onStoreRefresh', remove:'onStoreRemove', update:'onStoreUpdate'}, triggerEvent:'childtap', triggerCtEvent:'tap'}, config:{itemButtonMode:false, data:null, emptyState:null, emptyText:null, enableTextSelection:null, inline:null, itemCls:null, loadingHeight:null, markDirty:null, navigationModel:{type:'dataview'}, selectable:true}, autoSize:null, publishes:{selection:1}, twoWayBindable:{selection:1}, eventedConfig:{store:undefined}, proxyConfig:{selectable:{configs:['mode', 
'deselectable', 'lastSelected', 'selected'], methods:['isSelected', 'select', 'selectAll', 'deselectAll', 'getSelections', 'hasSelection', 'getSelectionCount']}}, emptyTextProperty:'html', restoreFocus:true, refreshCounter:0, selectionModel:'dataview', defaultBindProperty:'store', focusable:true, scrollable:true, tabIndex:0, classCls:Ext.baseCSSPrefix + 'dataview', focusedCls:Ext.baseCSSPrefix + 'focused', hoveredCls:Ext.baseCSSPrefix + 'hovered', inlineCls:Ext.baseCSSPrefix + 'inline', noWrapCls:Ext.baseCSSPrefix + 
'nowrap', pressedCls:Ext.baseCSSPrefix + 'pressed', scrollDockCls:Ext.baseCSSPrefix + 'scrolldock', selectedCls:Ext.baseCSSPrefix + 'selected', hasLoadedStore:false, scrollDockedItems:null, storeListeners:null, _trueStore:null, beforeInitialize:function(config) {
  this.dataItems = [];
  this.callParent([config]);
}, initialize:function() {
  var me = this;
  me.generateSelectorFunctions();
  me.callParent();
  me.bodyElement.on({touchstart:'_onChildTouchStart', touchend:'_onChildTouchEnd', touchcancel:'_onChildTouchCancel', tap:'_onChildTap', tapcancel:'_onChildTapCancel', longpress:'_onChildLongPress', taphold:'_onChildTapHold', singletap:'_onChildSingleTap', doubletap:'_onChildDoubleTap', swipe:'_onChildSwipe', mouseover:'_onChildMouseOver', mouseout:'_onChildMouseOut', contextmenu:'_onChildContextMenu', delegate:me.eventDelegate, scope:me});
  if (Ext.scrollbar.width()) {
    me.bodyElement.on('touchstart', '_onContainerTouchStart', me);
  }
  me.on(me.getTriggerCtEvent(), 'onContainerTrigger', me);
}, onRender:function() {
  var me = this;
  me.callParent();
  if (me.forceRefreshOnRender) {
    me.runRefresh();
  } else {
    me.refresh();
  }
}, doDestroy:function() {
  var me = this;
  me.destroyAllRipples();
  me.clearPressedTimer();
  me.setStore(null);
  me.setNavigationModel(null);
  me.setSelectable(null);
  me.lastPressedLocation = null;
  me.callParent();
}, createEmptyText:function(emptyText) {
  var ret = Ext.apply({}, this.getEmptyTextDefaults());
  if (typeof emptyText === 'string') {
    ret[this.emptyTextProperty] = emptyText;
  } else {
    if (emptyText) {
      Ext.apply(ret, emptyText);
    }
  }
  ret.isEmptyText = ret.hidden = true;
  ret.showInEmptyState = null;
  return ret;
}, ensureVisible:function(record, options) {
  var me = this, plan = me.ensureVisiblePlan(record, options), step;
  for (;;) {
    if (!(step = plan.steps.pop())) {
      break;
    }
    me[step](plan);
  }
  return plan.promise;
}, gatherData:function(record, recordIndex) {
  var me = this, data = record && record.getData(me.associatedData);
  if (data) {
    if (recordIndex === undefined) {
      recordIndex = me.store.indexOf(record);
    }
    data = me.prepareData(data, recordIndex, record);
  }
  return data || null;
}, getFirstDataItem:function() {
  return this.dataItems[0] || null;
}, getFirstItem:function() {
  return this.getFastItems()[0] || null;
}, getItemAt:function(index) {
  var items = this.getFastItems();
  if (index < 0) {
    index += items.length;
  }
  return items[index] || null;
}, getItemIndex:function(item) {
  return this.mapToRecordIndex(item);
}, getItem:function(record) {
  var ret = null, idx;
  if (record) {
    idx = record.isEntity ? this.store.indexOf(record) : record;
    if (idx > -1) {
      ret = this.getItemAt(idx);
    }
  }
  return ret;
}, getLastDataItem:function() {
  var dataItems = this.dataItems;
  return dataItems[dataItems.length - 1] || null;
}, getLastItem:function() {
  var items = this.getFastItems();
  return items[items.length - 1];
}, getScrollDockedItems:function(which) {
  var scrollDock = this.scrollDockedItems;
  if (scrollDock) {
    if (which) {
      which = this.scrollDockAliases[which] || which;
      scrollDock = scrollDock[which].slice();
    } else {
      scrollDock = scrollDock.start.items.concat(scrollDock.end.items);
    }
  }
  return scrollDock || [];
}, isItemSelected:function(item) {
  var record = this.mapToRecord(item);
  return record ? this.isSelected(record) : false;
}, isFirstItem:function(item) {
  return Ext.getDom(item) === this.getFirstItem();
}, isFirstDataItem:function(item) {
  return Ext.getDom(item) === this.getFirstDataItem();
}, isLastItem:function(item) {
  return Ext.getDom(item) === this.getLastItem();
}, isLastDataItem:function(item) {
  return Ext.getDom(item) === this.getLastDataItem();
}, mapToItem:function(value, as) {
  var me = this, el = me.element, item, items;
  if (value && value.isEvent) {
    item = value.getTarget(me.itemSelector, el);
  } else {
    if (value && (value.isElement || value.nodeType === 1)) {
      item = Ext.fly(value).findParent(me.itemSelector, el);
    } else {
      if (value && value.isEntity) {
        item = me.itemFromRecord(value);
      } else {
        if (value && value.isComponent && me.items.contains(value)) {
          item = value;
        } else {
          items = me.getFastItems();
          if (value < 0) {
            value += items.length;
          }
          item = items[value || 0];
        }
      }
    }
  }
  if (item) {
    item = me.itemAs(item, as || (me.isElementDataView ? 'el' : 'cmp'));
  }
  return item || null;
}, mapToRecord:function(value) {
  var me = this, item = value, el = me.element, store = me.store, dom, rec;
  if (item && item.isEntity) {
    if (store && store.getById(item.id) === item) {
      rec = item;
    }
    item = null;
  } else {
    if (item && item.isEvent) {
      item = item.getTarget(me.itemSelector, el);
    } else {
      if (item && (item.isElement || item.nodeType === 1)) {
        item = Ext.fly(item).findParent(me.itemSelector, el);
      } else {
        if (typeof item === 'number') {
          item = me.mapToItem(item);
        }
      }
    }
  }
  if (item) {
    dom = item.isWidget ? item.el : item;
    dom = dom.dom || dom;
    if (me.itemSelector(dom)) {
      rec = dom.getAttribute('data-recordid');
      rec = rec && store.getByInternalId(+rec);
    }
  }
  return rec || null;
}, mapToRecordIndex:function(value, uncollapsed) {
  var me = this, rec = me.mapToRecord(value), index = -1, store = me.store;
  if (rec) {
    if (uncollapsed && store.isGroupStore) {
      store = store.getSource();
    }
    index = store.indexOf(rec);
  }
  return index;
}, mapToViewIndex:function(value, indexOffset) {
  var me = this, index = -1, item = value, el = me.element, items = me.getFastItems(), dom;
  if (typeof item === 'number') {
    indexOffset = indexOffset || 0;
    for (; item < items.length; ++item) {
      dom = items[item];
      if (dom.isWidget) {
        dom = dom.el.dom;
      }
      if (+dom.getAttribute('data-recordindex') === item + indexOffset) {
        index = item;
        break;
      }
    }
  } else {
    if (item) {
      if (item.isEntity) {
        item = me.itemFromRecord(item);
      } else {
        if (item.isEvent) {
          item = item.getTarget(me.itemSelector, el);
        } else {
          if (item.isElement || item.nodeType === 1) {
            item = Ext.fly(item).findParent(me.itemSelector, el);
          }
        }
      }
      if (item && items.length) {
        if (items[0].isWidget) {
          if (!item.isWidget) {
            item = Ext.Component.from(item);
          }
        } else {
          item = item.nodeType ? item : item.el.dom;
        }
        index = Array.prototype.indexOf.call(items, item);
      }
    }
  }
  return index;
}, nextItem:function(item, as) {
  var next = this.traverseItem(item, 1);
  return as ? this.itemAs(next, as) : next;
}, previousItem:function(item, as) {
  var prev = this.traverseItem(item, -1);
  return as ? this.itemAs(prev, as) : prev;
}, prepareData:function(data, index, record) {
  return data;
}, refresh:function() {
  this.whenVisible('runRefresh');
}, setLocation:function(location, options) {
  return this.getNavigationModel().setLocation(location, options);
}, onFocusEnter:function(e) {
  var me = this;
  me.callParent([e]);
  if (!(e.within(me.getRenderTarget()) || e.target === me.getFocusEl().dom)) {
    return;
  }
  return me.onInnerFocusEnter(e);
}, onInnerFocusEnter:function(e) {
  var me = this, navigationModel = me.getNavigationModel(), focusPosition, itemCount;
  if (navigationModel.lastLocation === 'scrollbar') {
    if (e.relatedTarget) {
      e.relatedTarget.focus();
    }
    return;
  }
  if (e.target === me.getFocusEl().dom) {
    focusPosition = me.restoreFocus && navigationModel.getPreviousLocation();
    if (focusPosition) {
      focusPosition = focusPosition.refresh();
    } else {
      if (e.backwards) {
        focusPosition = me.getLastDataItem();
      } else {
        focusPosition = me.getFirstDataItem();
      }
    }
  } else {
    focusPosition = e;
  }
  me.toggleChildrenTabbability(false);
  itemCount = me.getFastItems().length;
  if (itemCount) {
    if (focusPosition && focusPosition.isWidget) {
      focusPosition = focusPosition.getFocusEl() || focusPosition.el;
    }
    navigationModel.setLocation(focusPosition, {event:e, navigate:false});
  }
  if (navigationModel.getLocation()) {
    me.el.dom.setAttribute('tabIndex', -1);
  }
}, onFocusLeave:function(e) {
  var me = this, navModel = me.getNavigationModel();
  if (navModel.getLocation()) {
    navModel.setLocation(null, {event:e});
    me.el.dom.setAttribute('tabIndex', 0);
  }
  me.callParent([e]);
}, onInnerFocusLeave:function(e) {
  this.getNavigationModel().setLocation(null, {event:e});
}, onFocusMove:function(e) {
  var me = this, el = me.el, renderTarget = me.getRenderTarget(), toComponent = e.event.toComponent, fromComponent = e.event.fromComponent;
  if (!el.contains(e.toElement)) {
    return me.callParent([e]);
  }
  if (el.contains(e.toElement) && !renderTarget.contains(e.toElement) && renderTarget.contains(e.fromElement)) {
    return me.onInnerFocusLeave(e.event);
  }
  if (el.contains(e.fromElement) && !renderTarget.contains(e.fromElement) && renderTarget.contains(e.toElement)) {
    return me.onInnerFocusEnter(e.event);
  }
  if (!renderTarget.contains(e.fromElement) && !renderTarget.contains(e.toElement)) {
    return me.callParent([e]);
  }
  if ((toComponent === me || toComponent.up('dataview,componentdataview') === me) && (fromComponent === me || fromComponent.up('dataview,componentdataview') === me)) {
    me.getNavigationModel().onFocusMove(e.event);
  }
  return me.callParent([e]);
}, onItemAdd:function(item, index) {
  var me = this, scrollDock = item.scrollDock, scrollDockCls = me.scrollDockCls, scrollDockedItems;
  if (!item.$dataItem && item.isInner) {
    if (scrollDock !== null) {
      scrollDock = scrollDock || 'end';
    }
    if (scrollDock) {
      if (!(scrollDockedItems = me.scrollDockedItems)) {
        me.scrollDockedItems = scrollDockedItems = {start:{items:[], height:0, filter:me.filterScrollDockStart, name:scrollDock}, end:{items:[], height:0, filter:me.filterScrollDockEnd, name:scrollDock}};
      }
      scrollDock = me.scrollDockAliases[scrollDock] || scrollDock;
      if (!scrollDockedItems[scrollDock]) {
        Ext.raise('Invalid value for scrollDock: ' + item.scrollDock);
      }
      item.scrollDock = scrollDock;
      scrollDock = scrollDockedItems[scrollDock];
      scrollDock.items = me.innerItems.filter(scrollDock.filter);
      if (item.showInEmptyState === undefined) {
        item.showInEmptyState = false;
      }
      item.addCls(scrollDockCls + ' ' + scrollDockCls + '-' + scrollDock.name);
      if (me.getItemsFocusable()) {
        item.el.set({tabIndex:-1});
      }
      if (me.addScrollDockedItem) {
        me.addScrollDockedItem(item);
      }
    }
  }
  me.callParent([item, index]);
}, onItemDeselect:function(records, suppressEvent) {
  var me = this;
  if (!me.isConfiguring && !me.destroyed) {
    if (suppressEvent) {
      me.setItemSelection(records, false);
    } else {
      me.fireEventedAction('deselect', [me, records], 'setItemSelection', me, [records, false]);
    }
  }
}, onItemSelect:function(records, suppressEvent) {
  var me = this;
  if (suppressEvent) {
    me.setItemSelection(records, true);
  } else {
    me.fireEventedAction('select', [me, records], 'setItemSelection', me, [records, true]);
  }
}, onChildTouchStart:function(location) {
  var me = this, child = location.item, e = location.event, hasListeners = me.hasListeners, curLocation = me.getNavigationModel().getLocation(), actionable = curLocation && curLocation.actionable, name, skip;
  if (!location.actionable && !(location.equalCell || location.equals)(curLocation)) {
    me.rippleItem(child, e);
  }
  name = 'beforechildtouchstart';
  skip = hasListeners[name] && me.fireEvent(name, me, location) === false;
  if (!skip) {
    name = 'beforeitemtouchstart';
    skip = hasListeners[name] && me.fireEvent(name, me, location.viewIndex, child, location.record, e) === false;
  }
  if (!skip) {
    if (!actionable) {
      me.doChildTouchStart(location);
    }
    me.fireChildEvent('touchstart', location);
  }
}, onChildTouchEnd:function(location) {
  var me = this, child = location.item, curLocation = me.getNavigationModel().getLocation(), e = location.event;
  if (!(curLocation && curLocation.actionable)) {
    me.rippleItem(child, e);
  }
  me.clearPressedCls('touchend', location);
}, onChildTouchCancel:function(location) {
  this.clearPressedCls('touchcancel', location);
}, onChildTouchMove:function(location) {
  this.fireChildEvent('touchmove', location);
}, onChildTap:function(location) {
  this.fireChildEvent('tap', location);
}, onChildTapCancel:function(location) {
  var me = this, itemButtonMode = me.getItemButtonMode();
  if (!itemButtonMode) {
    this.clearPressedCls('tapcancel', location);
  }
}, onChildContextMenu:function(location) {
  this.fireChildEvent('contextmenu', location);
}, onChildLongPress:function(location) {
  this.fireChildEvent('longpress', location);
}, onChildTapHold:function(location) {
  this.fireChildEvent('taphold', location);
}, onChildSingleTap:function(location) {
  this.fireChildEvent('singletap', location);
}, onChildDoubleTap:function(location) {
  this.fireChildEvent('doubletap', location);
}, onChildSwipe:function(location) {
  this.fireChildEvent('swipe', location);
}, onChildMouseOver:function(location) {
  var me = this, child = location.item;
  if (me.mouseOverItem !== child) {
    me.mouseOverItem = child;
    if (me.doHover) {
      me.toggleHoverCls(true);
    }
    me.fireChildEvent('mouseenter', location);
  }
}, onChildMouseOut:function(location) {
  var me = this, itemButtonMode = me.getItemButtonMode(), child = location.item, relatedTarget = location.event.getRelatedTarget(me.itemSelector);
  if (child && child.dom !== relatedTarget) {
    if (me.doHover) {
      me.toggleHoverCls(false);
    }
    if (!itemButtonMode) {
      this.clearPressedCls('mouseleave', location);
    } else {
      me.fireChildEvent('mouseleave', location);
    }
    me.mouseOverItem = null;
  }
}, onNavigate:function(e) {
  var me = this, selectable = !me.destroyed && me.getSelectable();
  if (selectable && me.shouldSelectItem(e)) {
    selectable.onNavigate(e);
  }
}, shouldSelectItem:function(e) {
  var me = this, selectable = me.getSelectable(), no = e.stopSelection || !selectable || selectable.getDisabled() || e.isNavKeyPress() && e.ctrlKey, target = !no && e.getTarget('.' + Ext.baseCSSPrefix + 'item-no-select,.' + Ext.baseCSSPrefix + 'item-no-tap', this.element);
  if (target) {
    no = me.el.contains(target);
  }
  return !no;
}, onStoreAdd:function() {
  this.syncEmptyState();
}, onStoreBeforeLoad:function() {
  this.handleBeforeLoad();
}, onStoreClear:function() {
  this.doClear();
}, onStoreLoad:function() {
  this.hasLoadedStore = true;
  this.clearMask();
  this.syncEmptyState();
}, onStoreRefresh:function() {
  this.refresh();
}, onStoreRemove:function() {
  this.syncEmptyState();
}, onStoreUpdate:function(store, record, type, modifiedFieldNames, info) {
  var me = this, item;
  if (!info || !(info.indexChanged || info.filtered)) {
    item = me.itemFromRecord(record);
    if (item) {
      me.syncItemRecord({item:item, modified:me.indexModifiedFields(modifiedFieldNames), record:record});
    }
  }
  if (me.isSelected(record)) {
    me.setItemSelection(record, true);
  }
}, updateAssociatedData:function(assocData) {
  this.associatedData = {associated:assocData};
}, updateData:function(data) {
  var me = this, store = me.store;
  if (!store) {
    me.settingStoreFromData = true;
    me.setStore({data:data, autoDestroy:true});
    me.settingStoreFromData = false;
  } else {
    store.loadData(data);
  }
}, updateDisableSelection:function(value) {
  var el = this.getRenderTarget();
  el.toggleCls(this.showSelectionCls, !value);
}, updateEmptyText:function(emptyText) {
  var me = this, config = emptyText, emptyTextCmp = me.emptyTextCmp;
  if (emptyTextCmp) {
    if (!emptyText || typeof emptyText === 'string') {
      config = {};
      config[me.emptyTextProperty] = emptyText || ' ';
    }
    emptyTextCmp.setConfig(config);
  }
  if (!me.isConfiguring) {
    me.syncEmptyState();
  }
}, updateEnableTextSelection:function(enableTextSelection) {
  this.setUserSelectable({bodyElement:!!enableTextSelection});
}, updateInline:function(inline) {
  var me = this, noWrap = inline && inline.wrap === false;
  me.toggleCls(me.inlineCls, !!inline);
  if (Ext.isEdge && noWrap) {
    me.el.measure('w');
  }
  me.toggleCls(me.noWrapCls, noWrap);
}, updateItemCls:function(newCls, oldCls) {
  if (!this.isConfiguring) {
    var items = this.dataItems, len = items.length, i, item;
    for (i = 0; i < len; i++) {
      item = items[i];
      item = item.isWidget ? item.el : Ext.fly(item);
      item.replaceCls(oldCls, newCls);
    }
  }
}, applyItemTpl:function(config) {
  return Ext.XTemplate.get(config);
}, updateItemTpl:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, updateMarkDirty:function(markDirty) {
  var dataItems = this.dataItems, i, ln, dataItem;
  markDirty = !!markDirty;
  for (i = 0, ln = dataItems.length; i < ln; i++) {
    dataItem = dataItems[i];
    (dataItem.el || Ext.fly(dataItem)).toggleCls(this.markDirtyCls, markDirty);
  }
}, updateMasked:function(masked) {
  var me = this, loadingHeight = me.getLoadingHeight();
  if (masked) {
    if (loadingHeight && loadingHeight > me.el.getHeight()) {
      me.hasLoadingHeight = true;
      me.oldMinHeight = me.getMinHeight();
      me.setMinHeight(loadingHeight);
    }
  } else {
    if (!me.destroying && me.hasLoadingHeight) {
      me.setMinHeight(me.oldMinHeight);
      delete me.hasLoadingHeight;
    }
  }
}, applySelectable:function(selectable, oldSelectable) {
  var me = this, config = {type:me.selectionModel, view:me}, record = me.selection;
  if (selectable === false) {
    selectable = {disabled:true};
  }
  if (selectable) {
    if (typeof selectable === 'string') {
      selectable = {type:me.selectionModel, mode:selectable.toLowerCase(), view:me};
    } else {
      if (selectable.isSelectionModel) {
        return selectable.setConfig(config);
      } else {
        selectable = Ext.apply(config, selectable);
      }
    }
    if (oldSelectable) {
      if (selectable.isSelectionModel || selectable.type !== oldSelectable.type) {
        Ext.raise('Switching out selectables dynamically is not supported');
      }
      selectable = oldSelectable.setConfig(selectable);
    } else {
      selectable = Ext.Factory.selmodel(me.mergeProxiedConfigs('selectable', selectable));
    }
    if (record) {
      delete me.selection;
      if (!record.isEntity) {
        Ext.raise('DataView selection config must be single record');
      }
      if (selectable.getRecords && !selectable.getRecords()) {
        Ext.raise('DataView selection model is configured to not accept records');
      }
      selectable.select(record);
    }
  }
  return selectable;
}, applyStore:function(store) {
  var ret = store ? Ext.data.StoreManager.lookup(store) : null;
  this.store = this._trueStore = ret;
  return ret;
}, updateStore:function(newStore, oldStore) {
  var me = this, mask = me.autoMask, newLoad;
  if (oldStore) {
    if (!oldStore.destroyed) {
      if (oldStore.getAutoDestroy()) {
        oldStore.destroy();
      } else {
        Ext.destroy(me.storeListeners);
      }
    }
    me.dataRange = me.storeListeners = Ext.destroy(me.dataRange);
    if (!me.destroying && !me.destroyed && !newStore) {
      me.doClear();
    }
  }
  if (newStore) {
    if (me.destroying) {
      return;
    }
    me.attachStoreEvents(newStore, Ext.apply({scope:me, destroyable:true}, me.getStoreEventListeners()));
    if (newStore.isLoaded()) {
      me.hasLoadedStore = true;
    }
    newLoad = !newStore.isTreeStore && newStore.hasPendingLoad();
    me.bindStore(newStore);
    if (me.initialized) {
      me.refresh();
    }
  }
  if (!me.isConfiguring || me.settingStoreFromData) {
    me.getSelectable().setStore(newStore);
  }
  if (mask && !newLoad) {
    me.setMasked(false);
    me.autoMask = false;
  } else {
    if (!mask && newLoad) {
      me.handleBeforeLoad();
    }
  }
}, updateHidden:function(hidden, oldHidden) {
  this.callParent([hidden, oldHidden]);
  this.destroyAllRipples();
}, privates:{associatedData:true, doHover:true, showSelectionCls:Ext.baseCSSPrefix + 'show-selection', multiSelectCls:Ext.baseCSSPrefix + 'multi-select', markDirtyCls:Ext.baseCSSPrefix + 'mark-dirty', scrollbarSelector:'.' + Ext.baseCSSPrefix + 'scrollbar', scrollDockAliases:{top:'start', bottom:'end'}, attachStoreEvents:function(store, listeners) {
  this.storeListeners = store.on(listeners);
}, createLocation:function() {
  var nav = this.getNavigationModel();
  return nav.createLocation.apply(nav, arguments);
}, getSelection:function() {
  return this.getSelectable().getSelectedRecord();
}, setSelection:function(record) {
  return this.getSelectable().setSelectedRecord(record);
}, generateSelectorFunctions:function() {
  var renderTarget = this.getRenderTarget(), bodyElement = this.bodyElement;
  this.eventDelegate = this.itemSelector = function(candidate) {
    return candidate && (candidate.parentNode === bodyElement.dom || candidate.parentNode === renderTarget.dom);
  };
}, bindStore:function(store) {
  this._trueStore = store;
  this.dataRange = store.createActiveRange();
}, clearMask:function() {
  this.setMasked(false);
  this.autoMask = false;
}, clearPressedCls:function(type, location) {
  var me = this, record = location.record, child = location.child, el;
  me.clearPressedTimer();
  if (record && child) {
    el = child.isWidget ? child.element : Ext.fly(child);
    el.removeCls(me.pressedCls);
  }
  me.fireChildEvent(type, location);
}, clearPressedTimer:function() {
  var timeout = this.pressedTimeout;
  if (timeout) {
    Ext.undefer(timeout);
    delete this.pressedTimeout;
  }
}, doAddPressedCls:function(record) {
  var me = this, item = me.itemFromRecord(record);
  if (item) {
    item = item.isWidget ? item.element : Ext.fly(item);
    item.addCls(me.pressedCls);
  }
}, doClear:function() {
  this.syncEmptyState();
}, doChildTouchStart:function(location) {
  var me = this, record = location.record, itemButtonMode = me.getItemButtonMode(), pressedDelay = me.getPressedDelay();
  me.clearPressedTimer();
  if (record) {
    if (pressedDelay > 0) {
      me.pressedTimeout = Ext.defer(me.doAddPressedCls, pressedDelay, me, [record]);
    } else {
      me.doAddPressedCls(record);
    }
    if (itemButtonMode) {
      me.lastPressedLocation = location;
      Ext.GlobalEvents.setPressedComponent(me, location);
    }
  }
}, onRelease:function() {
  var me = this;
  if (me.lastPressedLocation) {
    me.clearPressedCls('release', me.lastPressedLocation);
  }
  me.lastPressedLocation = null;
}, ensureVisiblePlan:function(record, plan) {
  var store = this.store, recIndex;
  if (record.record) {
    plan = Ext.apply({}, record);
    record = plan.record;
    delete plan.record;
  } else {
    plan = Ext.apply({}, plan);
  }
  if (record.isEntity) {
    recIndex = store.indexOf(record);
  } else {
    if (typeof record === 'number') {
      recIndex = record;
      record = store.getAt(record);
    } else {
      Ext.raise('ensureVisible first parameter must be record or recordIndex ' + 'or an options object with a record property');
    }
  }
  plan.record = record;
  plan.recordIndex = recIndex;
  plan.animation = plan.animation || plan.animate;
  plan.async = !!plan.animation;
  plan.steps = [];
  if (recIndex < 0 || recIndex >= store.getCount()) {
    Ext.raise('Invalid record passed to ensureVisible');
    plan.promise = Ext.Deferred.getCachedRejected();
  } else {
    if (this.dataRange.isVirtualRange && !record && (recIndex || recIndex === 0)) {
      plan.async = true;
    }
    plan.steps.push('ensureVisibleFocus', 'ensureVisibleSelect', 'ensureVisiblePrep');
  }
  return plan;
}, ensureVisibleFocus:function(plan) {
  if (plan.focus) {
    var me = this, isGrid = me.isGrid;
    if (isGrid && !('column' in plan)) {
      plan.column = 0;
    }
    if (plan.async) {
      plan.promise = plan.promise.then(function(o) {
        me.getNavigationModel().setLocation(isGrid ? plan : plan.record);
        return o;
      });
    } else {
      me.getNavigationModel().setLocation(isGrid ? plan : plan.record);
    }
  }
}, ensureVisiblePrep:function(plan) {
  var me = this, dataRange = me.dataRange, cleanup = function() {
    delete dataRange['goto'];
    return args ? dataRange['goto'](args[0], args[1]).then(function() {
      plan.record = me.store.getAt(plan.recordIndex);
      if (!plan.record) {
        throw new Error('Unable to get record');
      }
    }) : Ext.Promise.resolve();
  }, args, promise;
  if (plan.async) {
    dataRange['goto'] = function(begin, end) {
      if (args) {
        args[0] = begin;
        args[1] = end;
      } else {
        args = [begin, end];
      }
    };
    promise = me.ensureVisibleScroll(plan);
    promise = promise.then(function(v) {
      return cleanup().then(function() {
        return v;
      });
    }, function(ex) {
      cleanup();
      throw ex;
    });
  } else {
    promise = me.ensureVisibleScroll(plan);
  }
  plan.promise = promise;
}, ensureVisibleScroll:function(plan) {
  var item = plan.item || (plan.item = this.itemFromRecord(plan.recIndex));
  return this.getScrollable().ensureVisible(item.el, {animation:plan.animation});
}, ensureVisibleSelect:function(plan) {
  if (plan.select) {
    var me = this, selectable = me.getSelectable(), cell;
    if (plan.async) {
      plan.promise = plan.promise.then(function(o) {
        if (plan.column) {
          cell = me.createLocation(plan);
          selectable.selectCells(cell, cell);
        } else {
          selectable.select(plan.record);
        }
        return o;
      });
    } else {
      if (plan.column) {
        cell = me.createLocation(plan);
        selectable.selectCells(cell, cell);
      } else {
        selectable.select(plan.record);
      }
    }
  }
}, filterScrollDockStart:function(item) {
  var scrollDock = item.scrollDock;
  return scrollDock === 'start' || scrollDock === 'top';
}, filterScrollDockEnd:function(item) {
  var scrollDock = item.scrollDock;
  return scrollDock === 'end' || scrollDock === 'bottom';
}, findTailItem:function(rawElements) {
  var me = this, items = rawElements ? me.innerItems : me.items.items, at = -1, tail = null, i, item, scrollDock;
  for (i = items.length; i-- > 0;) {
    item = items[i];
    scrollDock = item.scrollDock;
    if (scrollDock === 'end') {
      tail = items[at = i];
    } else {
      break;
    }
  }
  return rawElements ? tail : at;
}, fireChildEvent:function(type, location) {
  var me = this, deprecatedName = 'item' + type, name = 'child' + type, hasListeners = me.hasListeners;
  if (hasListeners[name]) {
    me.fireEvent(name, me, location);
  }
  if (hasListeners[deprecatedName] && location.record) {
    me.fireEvent(deprecatedName, me, location.viewIndex, location.item, location.record, location.event);
  }
}, getEmptyTextCmp:function() {
  var me = this, cmp = me.emptyTextCmp;
  if (!cmp) {
    me.emptyTextCmp = cmp = me.add(me.createEmptyText(me.getEmptyText()));
  }
  return cmp;
}, getRecordIndexFromPoint:function(x, y) {
  var item = this.getItemFromPoint(x, y);
  return item ? this.mapToRecordIndex(item) : -1;
}, getItemFromPoint:function(x, y) {
  var me = this, scroller = me.getScrollable(), scrollPosition = scroller.getPosition(), scrollSize = scroller.getSize(), offset = me.getScrollerTarget().getXY();
  return me.getItemFromPagePoint(Math.max(Math.min(x, scrollSize.x), 0) + offset[0] - scrollPosition.x, Math.max(Math.min(y, scrollSize.y), 0) + offset[1] - scrollPosition.y);
}, getItemFromPagePoint:function(x, y) {
  var items = this.getFastItems(), len = items.length, point = new Ext.util.Point(x, y), ret = null, i, item, el;
  for (i = 0; i < len; i++) {
    item = items[i];
    el = item.isWidget ? item.element : Ext.fly(item);
    if (el.getRegion().contains(point)) {
      ret = item.isWidget ? item : Ext.get(el);
      break;
    }
  }
  return ret;
}, handleBeforeLoad:function() {
  var me = this, loadingText = me.getLoadingText();
  if (loadingText) {
    me.autoMask = true;
    me.setMasked({xtype:'loadmask', message:loadingText});
  }
  me.hideEmptyText();
}, hideEmptyText:function() {
  var cmp = this.emptyTextCmp;
  if (cmp) {
    cmp.hide();
  }
}, indexModifiedFields:function(modified) {
  return modified;
}, itemAs:function(item, as) {
  var ret = item;
  if (as !== 'cmp' && as !== 'dom' && as !== 'el') {
    Ext.raise('Invalid "as" value "' + as + '" to mapToItem()');
  }
  if (typeof ret === 'number') {
    ret = null;
  } else {
    if (ret) {
      if (as === 'cmp') {
        if (!ret.isWidget) {
          ret = Ext.getCmp(ret.id);
        }
      } else {
        if (ret.isWidget) {
          ret = ret.el;
        }
        if (ret) {
          if (ret.isElement) {
            if (as === 'dom') {
              ret = ret.dom;
            }
          } else {
            if (as === 'el') {
              ret = Ext.fly(ret);
            }
          }
        }
      }
    }
  }
  return ret;
}, itemFromRecord:function(rec) {
  var index = rec.isEntity ? this.store.indexOf(rec) : rec;
  return index > -1 && this.dataItems[index] || null;
}, onContainerTrigger:function(e) {
  var me = this;
  if (e.target === me.element.dom) {
    if (me.getDeselectOnContainerClick() && me.store) {
      me.getSelectable().deselectAll();
    }
  }
}, runRefresh:function() {
  var me = this, store = me.store, scrollToTopOnRefresh = me.getScrollToTopOnRefresh(), scroller = !scrollToTopOnRefresh && me.getScrollable(), maxY = scroller && scroller.getMaxPosition().y;
  me.syncEmptyState();
  if (store && !me.isConfiguring && (store.isTreeStore || !store.hasPendingLoad())) {
    me.fireEventedAction('refresh', [me], 'doRefresh', me, [scrollToTopOnRefresh]);
    if (scroller && scroller.getMaxPosition().y < maxY) {
      scroller.refresh();
    }
  }
}, saveFocusState:function() {
  var me = this, navModel = me.getNavigationModel(), location = navModel.location, lastFocusedViewIndex, lastFocusedRecord, itemCount, focusItem;
  if (location) {
    lastFocusedRecord = location.record;
    lastFocusedViewIndex = location.viewIndex;
    return function() {
      itemCount = me.getFastItems().length;
      if (itemCount) {
        if (lastFocusedRecord) {
          focusItem = me.mapToItem(lastFocusedRecord);
        }
        if (!focusItem) {
          focusItem = me.mapToItem(Math.min(lastFocusedViewIndex || 0, itemCount - 1));
        }
        navModel.setLocation(null);
        navModel.setLocation(focusItem);
      }
    };
  }
  return Ext.emptyFn;
}, setItemHidden:function(item, hide) {
  if (hide) {
    if (!item.$hidden) {
      item.hide();
      item.$hidden = true;
    }
  } else {
    if (item.$hidden) {
      item.$hidden = false;
      item.show();
    }
  }
}, setItemSelection:function(records, selected) {
  records = Ext.Array.from(records);
  var me = this, len = records.length, pressedCls = me.pressedCls, selectedCls = me.selectedCls, toRemove = pressedCls, i, record, item, toAdd;
  if (!selected) {
    toRemove = [pressedCls, selectedCls];
  } else {
    toAdd = selectedCls;
  }
  if (!me.isConfiguring && !me.destroyed) {
    for (i = 0; i < len; i++) {
      record = records[i];
      item = me.itemFromRecord(record);
      if (item) {
        item = item.isWidget ? item.element : Ext.fly(item);
        item.removeCls(toRemove);
        if (toAdd) {
          item.addCls(toAdd);
        }
      }
    }
  }
}, shouldRippleItem:function(item, e) {
  var disableSelection = this.getDisableSelection();
  if (!disableSelection && this.isItemSelected(item)) {
    return false;
  }
  return this.mixins.itemrippler.shouldRippleItem.call(this, item, e);
}, syncEmptyState:function() {
  var me = this, store = me.store, empty = !store || !store.getCount() && me.getEmptyText(), emptyTextCmp = me.emptyTextCmp;
  if (!empty) {
    if (emptyTextCmp) {
      emptyTextCmp.hide();
    }
  } else {
    if ((me.hasLoadedStore || !me.getDeferEmptyText()) && !(store && store.hasPendingLoad())) {
      emptyTextCmp = emptyTextCmp || me.getEmptyTextCmp();
      emptyTextCmp.show();
    }
  }
  me.setEmptyState(empty);
  return empty;
}, toggleChildrenTabbability:function(enableTabbing) {
  var focusEl = this.getRenderTarget();
  if (enableTabbing) {
    focusEl.restoreTabbableState({skipSelf:true});
  } else {
    focusEl.saveTabbableState({skipSelf:true, includeSaved:false});
  }
}, toggleHoverCls:function(on) {
  var target = this.mouseOverItem;
  if (target && !target.destroyed) {
    target.toggleCls(this.hoveredCls, on);
  }
}, _onChildEvent:function(fn, e) {
  var me = this, last = me.lastPressedLocation, location = me.createLocation(e);
  if (location.child) {
    location.pressing = !!(last && last.child === location.child);
    me[fn](location);
  }
  return location;
}, _onChildTouchStart:function(e) {
  var child = this._onChildEvent('onChildTouchStart', e).child, el = child && (child.element || Ext.get(child));
  if (el) {
    el.on('touchmove', '_onChildTouchMove', this);
  }
}, _onChildTouchMove:function(e) {
  this._onChildEvent('onChildTouchMove', e);
}, _onChildTouchEnd:function(e) {
  var child = this._onChildEvent('onChildTouchEnd', e).child, el = child && (child.element || Ext.get(child));
  if (el) {
    el.un('touchmove', '_onChildTouchMove', this);
  }
}, _onChildTouchCancel:function(e) {
  var child = this._onChildEvent('onChildTouchCancel', e).child, el = child && (child.element || Ext.get(child));
  if (el) {
    el.un('touchmove', '_onChildTouchMove', this);
  }
}, _onChildTap:function(e) {
  var target = e.getTarget('.' + Ext.baseCSSPrefix + 'item-no-tap', this.element);
  if (!target) {
    this._onChildEvent('onChildTap', e);
  }
}, _onChildTapCancel:function(e) {
  this._onChildEvent('onChildTapCancel', e);
}, _onChildContextMenu:function(e) {
  this._onChildEvent('onChildContextMenu', e);
}, _onChildLongPress:function(e) {
  this._onChildEvent('onChildLongPress', e);
}, _onChildTapHold:function(e) {
  this._onChildEvent('onChildTapHold', e);
}, _onChildSingleTap:function(e) {
  this._onChildEvent('onChildSingleTap', e);
}, _onChildDoubleTap:function(e) {
  this._onChildEvent('onChildDoubleTap', e);
}, _onChildSwipe:function(e) {
  this._onChildEvent('onChildSwipe', e);
}, _onChildMouseOver:function(e) {
  var fromItem = e.getRelatedTarget(this.itemSelector), toItem = e.getTarget(this.itemSelector);
  if (toItem !== fromItem) {
    this._onChildEvent('onChildMouseOver', e);
  }
}, _onChildMouseOut:function(e) {
  var toItem = e.getRelatedTarget(this.itemSelector), fromItem = e.getTarget(this.itemSelector);
  if (toItem !== fromItem || !e.getRelatedTarget(this.eventDelegate)) {
    this._onChildEvent('onChildMouseOut', e);
  }
}, _onContainerTouchStart:function(e) {
  var me = this, isWithinScrollbar;
  if (e.getTarget(me.scrollbarSelector)) {
    e.preventDefault();
    isWithinScrollbar = true;
  } else {
    if (!e.getTarget(me.itemSelector)) {
      e.preventDefault();
      if (!me.bodyElement.getClientRegion().contains(e.getPoint())) {
        isWithinScrollbar = true;
      }
    }
  }
  if (isWithinScrollbar) {
    me.getNavigationModel().lastLocation = 'scrollbar';
  }
}, setupChildEvent:Ext.privateFn, updateEmptyState:function(empty) {
  var me = this, items = me.items.items, showInEmptyState, hide, i, item, show;
  for (i = 0; i < items.length; ++i) {
    item = items[i];
    showInEmptyState = item.showInEmptyState;
    hide = show = false;
    if (showInEmptyState === false) {
      hide = !(show = !empty);
    } else {
      if (showInEmptyState) {
        if (typeof showInEmptyState === 'function') {
          hide = !(show = item.showInEmptyState(empty));
          if (show == null) {
            continue;
          }
        } else {
          hide = !(show = empty);
        }
      }
    }
    if (hide) {
      if (item.isInner) {
        me.setItemHidden(item, true);
      } else {
        item.hide();
      }
    } else {
      if (show) {
        if (item.isInner) {
          me.setItemHidden(item, false);
        } else {
          item.show();
        }
      }
    }
  }
}, applyNavigationModel:function(navigationModel) {
  if (navigationModel) {
    if (typeof navigationModel === 'string') {
      navigationModel = {type:navigationModel};
    }
    navigationModel = Ext.Factory.navmodel(Ext.apply({view:this}, navigationModel));
  }
  return navigationModel;
}, updateNavigationModel:function(navigationModel, oldNavigationModel) {
  Ext.destroy(oldNavigationModel);
}, getUseComponents:function() {
  return this.isComponentDataView;
}}});
Ext.define('Ext.theme.material.dataview.Abstract', {override:'Ext.dataview.Abstract', config:{itemRipple:{release:true, color:'default'}}});
Ext.define('Ext.dataview.GenericItem', {mixinId:'dataviewitem', isDataViewItem:true, config:{innerCls:null, contentCls:null, recordIndex:null}, updateRecordIndex:function(value) {
  this.el.dom.setAttribute('data-recordindex', value);
}, getDataview:function() {
  return this.parent;
}, updateInnerCls:function(cls, old) {
  this.innerElement.replaceCls(old, cls);
}, updateContentCls:function(cls, old) {
  this.getInnerHtmlElement().replaceCls(old, cls);
}, privates:{$dirty:false, dirtyCls:Ext.baseCSSPrefix + 'dirty', augmentToolHandler:function(tool, args) {
  var me = this;
  args[1] = {event:args.pop(), item:me, list:me.parent, record:me.getRecord(), tool:args[1]};
}, handleEmptyText:function(html) {
  var parent;
  if (!html) {
    parent = this.parent;
    if (parent && parent.getEmptyItemText) {
      html = parent.getEmptyItemText();
    }
  }
  return html;
}, syncDirty:function(record) {
  var me = this, dirty = record ? record.dirty : false;
  if (dirty !== me.$dirty) {
    me.toggleCls(me.dirtyCls, dirty);
    me.$dirty = dirty;
  }
}}});
Ext.define('Ext.dataview.DataItem', function(DataItem) {
  return {extend:Ext.Container, alternateClassName:'Ext.dataview.component.DataItem', xtype:'dataitem', mixins:[Ext.dataview.GenericItem], config:{itemCls:null, dataMap:{cached:true, $value:null}}, html:' ', classCls:Ext.baseCSSPrefix + 'dataitem', inheritUi:true, autoSize:null, defaultType:'component', referenceHolder:true, template:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', uiCls:'body-el', children:[{reference:'innerElement', cls:Ext.baseCSSPrefix + 'inner-el', uiCls:'inner-el'}]}], 
  updateItemCls:function(newCls, oldCls) {
    this.el.replaceCls(oldCls, newCls);
  }, updateRecord:function(record) {
    var me = this, dataMap, tpl, data, viewModel;
    if (me.destroying) {
      return;
    }
    viewModel = me.getViewModel();
    if (viewModel) {
      viewModel.setData({record:record});
    }
    dataMap = me.getDataMap();
    tpl = me.getTpl();
    if (dataMap) {
      DataItem.executeDataMap(record, me, dataMap);
    }
    me.syncDirty(record);
    if (tpl || !dataMap || me.hasListeners.updatedata) {
      data = me.parent.gatherData(record);
      if (tpl) {
        me.updateData(data);
      }
      if (me.hasListeners.updatedata) {
        me.fireEvent('updatedata', me, data);
      }
    }
  }, updateHtml:function(html, oldHtml) {
    this.callParent([this.handleEmptyText(html), oldHtml]);
  }, privates:{applyDataMap:function(dataMap) {
    return DataItem.parseDataMap(dataMap);
  }, getRenderTarget:function() {
    return this.innerElement;
  }, statics:{assignDataToItem:function(record, target, mappings, legacy) {
    var configMap = Ext.Config.map, cfg, dataPath, i, n, name, s, value;
    for (name in mappings) {
      s = legacy ? name : (cfg = configMap[name]) && cfg.names.set;
      if (!target[s]) {
        if (legacy) {
          Ext.raise('No method "' + name + '" on ' + target.$className);
        } else {
          Ext.raise('No config "' + name + '" on ' + target.$className);
        }
        continue;
      }
      dataPath = mappings[name];
      value = record;
      for (i = 0, n = dataPath.length; value && i < n; ++i) {
        value = value.interpret(dataPath[i]);
      }
      target[s](i < n ? null : value);
    }
  }, executeDataMap:function(record, item, dataMap) {
    var reference, legacy, target, mappings;
    for (reference in dataMap) {
      if (!(mappings = dataMap[reference])) {
        continue;
      }
      legacy = false;
      if (!(target = reference === '#' ? item : item.lookup(reference))) {
        if (typeof item[reference] === 'function') {
          target = item[reference]();
          legacy = true;
          if (!item.$dataMapWarning) {
            item.$dataMapWarning = true;
            Ext.log.warn('Using getters in dataMaps is deprecated (for ' + item.getId() + '); support will be removed in 7.0');
          }
        }
        if (!target) {
          continue;
        }
      }
      DataItem.assignDataToItem(record, target, mappings, legacy);
    }
  }, parseDataMap:function(dataMap) {
    var map = {}, inner, innerSrc, key1, key2;
    for (key1 in dataMap) {
      map[key1] = inner = {};
      innerSrc = dataMap[key1];
      for (key2 in innerSrc) {
        inner[key2] = innerSrc[key2].split('.');
      }
    }
    return map;
  }}}};
});
Ext.define('Ext.dataview.Component', {extend:Ext.dataview.Abstract, xtype:'componentdataview', isComponentDataView:true, config:{itemInnerCls:null, itemConfig:{xtype:'dataitem'}, itemContentCls:null, itemDataMap:null, maxItemCache:20, striped:null, itemCount:0}, firstCls:Ext.baseCSSPrefix + 'first', lastCls:Ext.baseCSSPrefix + 'last', oddCls:Ext.baseCSSPrefix + 'odd', beforeInitialize:function(config) {
  this.itemCache = {max:0, unused:[]};
  this.callParent([config]);
}, isFirstItem:function(item) {
  return item === this.getFirstItem();
}, isFirstDataItem:function(item) {
  return item === this.getFirstDataItem();
}, isLastItem:function(item) {
  return item === this.getLastItem();
}, isLastDataItem:function(item) {
  return item === this.getLastDataItem();
}, doDestroy:function() {
  Ext.destroy(this.itemCache.unused, this.dataRange);
  this.callParent();
}, onRender:function() {
  var me = this, itemConfig = me.getItemConfig(), vm = itemConfig.viewModel;
  if (vm) {
    me.hasItemVm = true;
    itemConfig.viewModel = Ext.applyIf({scheduler:null}, vm);
    if (!me.lookupViewModel()) {
      me.setViewModel(true);
    }
  }
  me.callParent();
}, getViewItems:function() {
  return this.getInnerItems().slice();
}, onStoreAdd:function(store, records, index) {
  var me = this;
  me.callParent(arguments);
  me.setItemCount(store.getCount());
  me.syncItemRange(me.getStoreChangeSyncIndex(index));
}, onStoreRemove:function(store, records, index) {
  var me = this, len = records.length, dataItems = me.dataItems.splice(index, len), itemCount = me.getItemCount(), i;
  me.callParent(arguments);
  if (!dataItems.length) {
    return;
  }
  for (i = len; i-- > 0;) {
    me.removeDataItem(dataItems[i]);
  }
  me.setItemCount(itemCount - len);
  me.syncItemRange(me.getStoreChangeSyncIndex(index));
}, updateItemInnerCls:function(cls) {
  if (!this.isConfiguring) {
    var items = this.dataItems, len = items.length, i, item;
    for (i = 0; i < len; i++) {
      item = items[i];
      if (item.setInnerCls) {
        item.setInnerCls(cls);
      }
    }
  }
}, applyItemConfig:function(itemConfig, oldItemConfig) {
  itemConfig = itemConfig || {};
  if (oldItemConfig && !itemConfig.xtype && !itemConfig.xclass) {
    var xtype = oldItemConfig.xtype, xclass = oldItemConfig.xclass;
    if (xtype || xclass) {
      itemConfig = Ext.apply({}, itemConfig);
      itemConfig[xclass ? 'xclass' : 'xtype'] = xclass || xtype;
    }
  }
  return itemConfig;
}, updateItemConfig:function() {
  if (!this.isConfiguring) {
    this.clearItems();
    this.refresh();
  }
}, updateItemContentCls:function(cls) {
  if (!this.isConfiguring) {
    var items = this.dataItems, len = items.length, i, item;
    for (i = 0; i < len; i++) {
      item = items[i];
      if (item.setContentCls) {
        item.setContentCls(cls);
      }
    }
  }
}, applyItemDataMap:function(dataMap) {
  return Ext.dataview.DataItem.parseDataMap(dataMap);
}, updateMaxItemCache:function(max) {
  this.itemCache.max = max;
}, updateStriped:function(striped) {
  var me = this, dataItems = me.dataItems, oddCls = me.oddCls, i, el, odd;
  me.striped = !!striped;
  if (!me.isConfiguring) {
    for (i = 0; i < dataItems.length; ++i) {
      el = dataItems[i].el;
      odd = striped ? +el.dom.getAttribute('data-recordindex') : 0;
      el.toggleCls(oddCls, odd % 2);
    }
  }
}, privates:{dataRange:null, infinite:false, striped:false, _itemChangeHandlers:['changeItemRecordIndex', 'changeItemRecord', 'changeItemIsFirst', 'changeItemIsLast'], acquireItem:function(cfg, itemsFocusable) {
  var me = this, at = null, el, item;
  if (typeof cfg === 'number') {
    at = cfg;
    cfg = null;
  }
  if (!cfg) {
    cfg = me.getItemConfig();
    itemsFocusable = me.getItemsFocusable();
  }
  if (!(item = me.itemCache.unused.pop())) {
    item = me.createDataItem(cfg);
    item = me.addDataItem(item, at);
    el = item.element;
    if (itemsFocusable) {
      (item.getFocusEl() || el).setTabIndex(-1);
    }
    el.dom.setAttribute('data-viewid', me.id);
  } else {
    item.removeCls(me._cachedRemoveClasses);
    me.addDataItem(item, at);
  }
  return item;
}, addDataItem:function(item, at) {
  var me = this;
  if (at === null) {
    at = me.findTailItem(false);
  }
  item = at < 0 ? me.add(item) : me.insert(at, item);
  me.dataItems.push(item);
  return item;
}, changeItem:function(itemIndex, recordIndex) {
  var me = this, store = me.store, page = store.currentPage, datasetIndex = recordIndex + (page ? (page - 1) * store.pageSize : 0), dataItems = me.dataItems, realIndex = itemIndex < 0 ? dataItems.length + itemIndex : itemIndex, record = me.dataRange.records[recordIndex], item = me.getItemForRecord(realIndex, record, recordIndex), storeCount = store.getCount(), handlers = me._itemChangeHandlers, options = {isFirst:!recordIndex, isLast:recordIndex === storeCount - 1, item:item, itemIndex:realIndex, 
  record:record, recordIndex:recordIndex, datasetIndex:datasetIndex}, i, itemEl;
  options.afterEl = options.beforeEl = options.itemEl = itemEl = item.renderElement;
  options.itemClasses = itemEl.getClassMap(false);
  options.isFirstChanged = item.isFirst !== options.isFirst;
  options.isLastChanged = item.isLast !== options.isLast;
  for (i = 0; i < handlers.length; ++i) {
    me[handlers[i]](options);
  }
  itemEl.setClassMap(options.itemClasses, true);
  return options;
}, changeItemIsFirst:function(options) {
  if (!options.isFirstChanged) {
    return;
  }
  var me = this, firstCls = me.firstCls, item = options.item, itemClasses = options.itemClasses, items = me.scrollDockedItems, i, len;
  if (!(item.isFirst = options.isFirst)) {
    delete itemClasses[firstCls];
  } else {
    itemClasses[firstCls] = 1;
    if (items && !me.infinite) {
      items = items.start.items;
      len = items.length;
      for (i = 0; i < len; ++i) {
        items[i].renderElement.insertBefore(options.beforeEl);
      }
    }
  }
}, changeItemIsLast:function(options) {
  if (!options.isLastChanged) {
    return;
  }
  var me = this, item = options.item, itemClasses = options.itemClasses, lastCls = me.lastCls, items = me.scrollDockedItems, i, len;
  if (!(item.isLast = options.isLast)) {
    delete itemClasses[lastCls];
  } else {
    itemClasses[lastCls] = 1;
    if (items && !me.infinite) {
      items = items.end.items;
      len = items.length;
      for (i = 0; i < len; ++i) {
        items[i].renderElement.insertAfter(options.afterEl);
      }
    }
  }
}, changeItemRecord:function(options) {
  this.syncItemRecord(options);
}, changeItemRecordIndex:function(options) {
  var item = options.item, recordIndex = options.recordIndex, itemClasses = options.itemClasses, oddCls = this.oddCls;
  item.$datasetIndex = options.datasetIndex;
  if (item.isDataViewItem) {
    if (item.getRecordIndex() !== recordIndex) {
      item.setRecordIndex(recordIndex);
    }
  } else {
    item.el.dom.setAttribute('data-recordindex', recordIndex);
  }
  if (this.striped && options.recordIndex % 2) {
    itemClasses[oddCls] = 1;
  } else {
    delete itemClasses[oddCls];
  }
}, clearItemCaches:function() {
  var cache = this.itemCache.unused;
  Ext.destroy(cache);
  cache.length = 0;
}, clearItems:function() {
  var me = this, dataItems = me.dataItems, len = dataItems.length, itemCache = me.itemCache.unused, i;
  for (i = 0; i < len; ++i) {
    me.removeDataItem(dataItems[i], true);
  }
  Ext.destroy(itemCache);
  dataItems.length = itemCache.length = 0;
  me.setItemCount(0);
}, createDataItem:function(cfg) {
  var me = this, cls, config;
  config = {xtype:me.getDefaultType(), tpl:me.getItemTpl(), $dataItem:'record'};
  cls = me.getItemInnerCls();
  if (cls) {
    config.innerCls = cls;
  }
  cls = me.getItemContentCls();
  if (cls) {
    config.contentCls = cls;
  }
  config = Ext.apply(config, cfg || me.getItemConfig());
  config.cls = [config.cls, me.getMarkDirty() ? me.markDirtyCls : '', me.getItemCls()].join(' ');
  return config;
}, doClear:function() {
  this.setItemCount(0);
  this.callParent();
}, doRefresh:function(scrollToTop) {
  var me = this, storeCount = me.dataRange.records.length, scroller = me.getScrollable(), restoreFocus;
  ++me.refreshCounter;
  if (scroller && scrollToTop) {
    scroller.scrollTo(0, 0);
  }
  if (storeCount) {
    restoreFocus = me.saveFocusState();
    me.hideEmptyText();
    me.setItemCount(storeCount);
    me.syncItemRange();
    if (me.hasSelection()) {
      me.setItemSelection(me.getSelections(), true);
    }
    restoreFocus();
  } else {
    me.doClear();
  }
}, getCacheForItem:function() {
  return this.itemCache;
}, getFastItems:function() {
  return this.getInnerItems();
}, getItemForRecord:function(viewIndex) {
  return this.dataItems[viewIndex];
}, getStoreChangeSyncIndex:function(index) {
  return index;
}, removeCachedItem:function(item, preventCache, cache, preventRemoval) {
  var me = this, ret = false, unused = !preventCache && cache && cache.unused;
  if (unused && unused.length < cache.max) {
    if (preventRemoval) {
      me.setItemHidden(item, true);
    } else {
      me.remove(item, false);
    }
    unused.push(item);
  } else {
    item.destroy();
    ret = true;
  }
  return ret;
}, removeDataItem:function(item, preventCache) {
  return this.removeCachedItem(item, preventCache, !preventCache && this.getCacheForItem(item));
}, syncItemRange:function(start, end) {
  var count = this.store.getCount(), i;
  if (end == null) {
    end = count;
  }
  for (i = start || 0; i < end; ++i) {
    this.changeItem(i, i);
  }
}, syncItemRecord:function(options, tombstoneRec) {
  var me = this, item = options.item, itemClasses = options && options.itemClasses, oldRecord = item.getRecord(), record = tombstoneRec || options.record, dataMap = me.getItemDataMap(), el = item.el, viewModel = item.getViewModel(), selectedCls = me.selectedCls;
  if (oldRecord === record) {
    if (!tombstoneRec) {
      if (item.isRecordRefreshable) {
        item.refresh(options);
      } else {
        item.updateRecord(record, oldRecord);
      }
    }
  } else {
    if (me.getSelectable().isRowSelected(record)) {
      if (itemClasses) {
        itemClasses[selectedCls] = true;
      } else {
        el.addCls(selectedCls);
      }
    } else {
      if (itemClasses) {
        delete itemClasses[selectedCls];
      } else {
        el.removeCls(selectedCls);
      }
    }
    item.setRecord(record);
    item.el.dom.setAttribute('data-recordid', record.internalId);
    if (item.isDragging) {
      if (item.draggingRecordId === record.id) {
        itemClasses[item.dragMarkerCls] = true;
      } else {
        delete itemClasses[item.dragMarkerCls];
      }
    }
  }
  if (dataMap) {
    Ext.dataview.DataItem.executeDataMap(record, item, dataMap);
  }
  if (viewModel) {
    viewModel.setData({record:options.record});
  }
}, traverseItem:function(item, delta) {
  var me = this, items = me.innerItems, next = null, cmp = item, i;
  if (item) {
    if (item.isElement) {
      cmp = Ext.getCmp(item.id);
    }
    i = items.indexOf(cmp);
    if (i > -1) {
      next = items[i + delta] || null;
    }
  }
  return next;
}, updateItemCount:function(count) {
  var me = this, items = me.dataItems, cfg, itemsFocusable;
  if (items.length < count) {
    cfg = me.getItemConfig();
    itemsFocusable = me.getItemsFocusable();
    while (items.length < count) {
      me.acquireItem(cfg, itemsFocusable);
    }
  }
  while (items.length > count) {
    me.removeDataItem(items.pop());
  }
}}}, function(ComponentDataView) {
  var proto = ComponentDataView.prototype;
  proto._cachedRemoveClasses = [proto.pressedCls, proto.selectedCls];
});
Ext.define('Ext.dataview.GroupStore', {extend:Ext.data.ChainedStore, isGroupStore:true, syncSourceGrouping:true, getRootSource:function() {
  var source = this.source;
  while (source && source.getSource) {
    source = source.getSource();
  }
  return source;
}, getTotalCount:function() {
  return this.getRootSource().getTotalCount();
}, load:function(options) {
  var source = this.getRootSource();
  if (!source) {
    return;
  }
  return source.load.apply(source, arguments);
}, loadPage:function(page, options) {
  var me = this, source = this.getRootSource();
  me.currentPage = page;
  if (!source) {
    return;
  }
  return source.loadPage.apply(source, arguments);
}, sync:function(options) {
  var source = this.getRootSource();
  if (!source) {
    Ext.raise('Cannot sync records with no source.');
  }
  return source.sync.apply(source, arguments);
}, erase:function(options) {
  var source = this.getRootSource();
  if (!source) {
    Ext.raise('Cannot erase records with no source.');
  }
  return source.erase.apply(source, arguments);
}, nextPage:function(options) {
  this.loadPage(this.currentPage + 1, options);
}, previousPage:function(options) {
  this.loadPage(this.currentPage - 1, options);
}, applyGrouper:function(grouper, oldGrouper) {
  var me = this, source = me.getSource(), ret;
  if (source && grouper !== source.getGrouper()) {
    source.setGrouper(grouper);
    grouper = source.getGrouper();
  }
  ret = me.callParent([grouper, oldGrouper]);
  me.refreshFromSource();
  return ret;
}, constructDataCollection:function() {
  var me = this, collection = me.callParent();
  collection.transformItems = function(items) {
    return me.transformItems(collection, items);
  };
  return collection;
}, createFiltersCollection:function() {
  return this.getSource().getFilters();
}, refreshFromSource:function() {
  var data = this.getData(), list = this.list, was = list.getScrollToTopOnRefresh();
  list.setScrollToTopOnRefresh(false);
  data.onCollectionRefresh(data.getSource());
  list.setScrollToTopOnRefresh(was);
}, transformItems:function(collection, records) {
  var me = this, n = records.length, list = me.list, collapser = list.isGrouping() && list.getCollapsible(), ret = records, groupMap = {}, source = me.getSource(), M = source.getModel(), groupField = collapser && source.getGrouper().getProperty(), collapsed, copy, group, groupKey, i, placeholder, rec, sourceGroups, srcGroup, startCollapsed;
  if (collapser) {
    sourceGroups = collection.getSource().getGroups();
    startCollapsed = collapser.getCollapsed();
    for (i = 0; i < n; ++i) {
      rec = records[i];
      srcGroup = sourceGroups.getItemGroup(rec);
      group = list.groupFrom(groupKey = srcGroup.getGroupKey());
      collapsed = group ? group.collapsed : startCollapsed;
      if (collapsed) {
        if (!copy) {
          copy = ret = records.slice(0, i);
        }
        if (!groupMap[groupKey]) {
          if (!(placeholder = srcGroup.placeholderRec)) {
            srcGroup.placeholderRec = placeholder = new M;
            placeholder.data[groupField] = placeholder.$groupKey = groupKey;
            placeholder.$groupValue = srcGroup.getGroupValue();
            placeholder.$collapsedGroupPlaceholder = true;
            placeholder.$srcGroup = srcGroup;
          }
          groupMap[groupKey] = placeholder;
          copy.push(placeholder);
        }
      } else {
        if (copy) {
          copy.push(rec);
        }
      }
    }
  }
  return ret;
}, updateSource:function(source, oldSource) {
  var me = this;
  if (source) {
    me.list.store = me;
  }
  if (oldSource && !oldSource.destroyed && oldSource.getAutoDestroy()) {
    oldSource.destroy();
  }
  me.callParent([source, oldSource]);
  if (source && !me.destroying) {
    me.getSorters().setSource(source.getSorters());
  }
}});
Ext.define('Ext.dataview.Pinnable', {mixinId:'dataviewpinnable', isDataViewPinnable:true, config:{pinned:null}, pinnedCls:Ext.baseCSSPrefix + 'pinned', updatePinned:function(value) {
  var me = this, el = me.el, pinnedCls = me.pinnedCls, pinnedClsMap = me._pinnedClsMap, classes = el.getClassMap(false);
  delete classes[pinnedClsMap.top];
  delete classes[pinnedClsMap.bottom];
  if (value) {
    classes[pinnedCls] = true;
    pinnedCls = pinnedClsMap[value];
    if (pinnedCls) {
      classes[pinnedCls] = true;
    }
  } else {
    delete classes[pinnedCls];
  }
  el.setClassMap(classes, true);
}, _pinnedClsMap:{top:Ext.baseCSSPrefix + 'pinned-top', bottom:Ext.baseCSSPrefix + 'pinned-bottom'}});
Ext.define('Ext.dataview.ItemHeader', {extend:Ext.Component, xtype:'itemheader', mixins:[Ext.mixin.Toolable, Ext.dataview.Pinnable], isItemHeader:true, config:{group:null, contentWidth:null}, html:' ', classCls:Ext.baseCSSPrefix + 'itemheader', inheritUi:true, toolDefaults:{ui:'itemheader'}, template:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', uiCls:'body-el'}], setGroup:function(group) {
  var me = this, was = me._group;
  me._group = group;
  me.updateGroup(group, was);
  return me;
}, updateGroup:function(group, oldGroup) {
  var me = this, data, grouper, html, list, tpl;
  if (oldGroup && group !== oldGroup && oldGroup.getHeader() === me) {
    oldGroup.setHeader(null);
  }
  if (group) {
    group.setHeader(me);
    list = me.parent;
    grouper = list.getStore().getGrouper();
    tpl = grouper && grouper.owner === list && grouper.headerTpl || me.getTpl();
    if (tpl) {
      data = me.getGroupHeaderTplData();
      html = tpl.apply(data);
    }
  }
  me.setHtml(html || ' ');
}, getScrollerTarget:function() {
  return this.el;
}, doDestroy:function() {
  this.mixins.toolable.doDestroy.call(this);
  this.callParent();
}, privates:{augmentToolHandler:function(tool, args) {
  var info = args[1] = {event:args.pop(), group:this.getGroup(), itemHeader:args[0], tool:args[1]};
  args[0] = info.list = this.parent;
}, getGroupHeaderTplData:function(skipHtml) {
  var group = this.getGroup(), list = this.parent, collection = group && group.data, data = collection && {name:collection.getGroupKey(), group:group, groupField:list.getStore().getGrouper().getProperty(), children:collection.items, count:collection.length};
  if (data) {
    data.value = collection.items[0].data[data.groupField];
  }
  if (!skipHtml) {
    data.html = Ext.htmlEncode(data.name);
  }
  data.groupValue = data.value;
  return data;
}, getList:function() {
  return this.parent;
}, onToggleCollapse:function() {
  this.getGroup().toggleCollapsed();
}, updateContentWidth:function(width) {
  var el = this._toolDockWrap || this.bodyElement;
  if (el) {
    el.setWidth(width ? width : null);
  }
}}});
Ext.define('Ext.dataview.ListCollapser', {isListCollapser:true, config:{collapsed:null, collapseToolText:'Collapse this group', expandToolText:'Expand this group', footer:false, tool:{xtype:'tool', type:'collapse', handler:'up.onToggleCollapse', itemId:'groupCollapser', weight:900, zone:'end'}}, collapsedCls:Ext.baseCSSPrefix + 'group-collapsed', list:null, constructor:function(config) {
  this.initConfig(config);
}, privates:{isRecordRendered:function(recordOrIndex) {
  var list = this.list, group = list.groupFrom(recordOrIndex);
  return !(group && group.collapsed) && list.isRecordRendered(recordOrIndex);
}}});
Ext.define('Ext.dataview.ListGroup', {$configPrefixed:false, config:{collapsed:null, collapsible:null, header:null}, data:null, list:null, beginIndex:-1, endIndex:-1, nextGroup:null, previousGroup:null, constructor:function(config) {
  this.initConfig(config);
}, collapse:function() {
  this.toggleCollapsed(true);
}, expand:function() {
  this.toggleCollapsed(false);
}, getCollapseTool:function() {
  var header = this.peekHeader();
  return header && header.lookupTool('groupCollapser');
}, isAttached:function() {
  var me = this, data = me.data, list = me.list, group = list.store.getGroups(), expected;
  group = group.get(data.getGroupKey());
  expected = Ext.getExpando(group, list.expandoKey);
  return expected === me;
}, toggleCollapsed:function(collapsed) {
  var me = this, list = me.list, event;
  if (me.getCollapsible() !== false && me.isAttached()) {
    if (collapsed == null) {
      collapsed = !me.getCollapsed();
    }
    event = 'beforegroup' + (collapsed ? 'collapse' : 'expand');
    if (list.fireEvent(event, list, me) !== false) {
      me.setCollapsed(collapsed);
    }
  }
}, applyCollapsed:function(collapsed) {
  return !!collapsed;
}, updateCollapsed:function(collapsed, oldCollapsed) {
  var me = this, list = me.list, collapser = list.getCollapsible(), tool = me.getCollapseTool(), header = me.peekHeader();
  if (me.isAttached()) {
    if (tool) {
      tool.setType(collapsed ? 'expand' : 'collapse');
      tool.setTooltip(collapsed ? collapser.getExpandToolText() : collapser.getCollapseToolText());
    }
    if (header) {
      header.el.toggleCls(collapser.collapsedCls, collapsed);
    }
    if (collapsed !== !!oldCollapsed) {
      list.syncGroupCollapse(me, collapsed);
    }
  }
}, updateHeader:function(header) {
  if (header) {
    var me = this, collapsible = me.list.getCollapsible(), collapsed = me.getCollapsed();
    if (collapsible) {
      if (!me.getCollapseTool()) {
        header.addTool(collapsible.getTool());
      }
      if (collapsed === !!collapsed) {
        me.updateCollapsed(collapsed, collapsed);
      } else {
        me.setCollapsed(!!collapsed);
      }
    }
  }
}, peekHeader:function() {
  var me = this, header = me.getHeader();
  if (header && (header.destroying || !me.isAttached())) {
    me.setHeader(header = null);
  }
  return header;
}}, function(ListGroup) {
  var target = ListGroup.prototype;
  Ext.each(['contains', 'containsAll', 'containsKey', 'each', 'eachKey', 'find', 'findBy', 'findIndex', 'findIndexBy', 'first', 'last', 'get', 'getAt', 'getByKey', 'getCount', 'getRange', 'getValues', 'indexOf', 'indexOfKey', 'getSummaryRecord'], function(name) {
    target[name] = function() {
      var data = this.data;
      return data && data[name].apply(data, arguments);
    };
  });
});
Ext.define('Ext.dataview.Disclosable', {mixinId:'disclosable', isListItem:true, toolDefaults:{ui:'listitem'}, toolAnchorName:'innerElement', getDisclosure:function() {
  return this.lookupTool('disclosure');
}, privates:{invokeDisclosure:function(tool, handler, e) {
  var parent = this.parent;
  if (tool.type === 'disclosure' && !handler) {
    if (parent && parent.onItemDisclosureTap) {
      parent.onItemDisclosureTap(this, e);
      return true;
    }
  }
}, syncDisclosure:function(record) {
  var me = this, disclosure = me.getDisclosure(), parent = me.parent;
  if (disclosure) {
    disclosure.setHidden(parent.shouldHideDisclosure(record));
  }
}}});
Ext.define('Ext.dataview.SimpleListItem', {extend:Ext.Component, alternateClassName:'Ext.dataview.component.SimpleListItem', xtype:'simplelistitem', mixins:[Ext.dataview.Disclosable, Ext.mixin.Toolable, Ext.dataview.GenericItem, Ext.dataview.Pinnable], classCls:Ext.baseCSSPrefix + 'listitem', inheritUi:true, html:' ', template:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', uiCls:'body-el', children:[{reference:'innerElement', cls:Ext.baseCSSPrefix + 'inner-el', uiCls:'inner-el'}]}], 
doDestroy:function() {
  this.mixins.toolable.doDestroy.call(this);
  this.callParent();
}, handleFocusEvent:Ext.emptyFn, updateRecord:function(record) {
  var me = this, dataview, data;
  if (me.destroying || me.destroyed) {
    return;
  }
  dataview = me.parent;
  data = dataview && dataview.gatherData(record);
  me.updateData(data);
  me.syncDisclosure(record);
}, updateHtml:function(html, oldHtml) {
  this.callParent([this.handleEmptyText(html), oldHtml]);
}, privates:{getRenderTarget:function() {
  return this.innerElement;
}, invokeToolHandler:function(tool, handler, scope, args, e) {
  if (this.invokeDisclosure(tool, handler, e)) {
    return false;
  }
  return tool.invokeToolHandler(tool, handler, scope, args, e);
}}});
Ext.define('Ext.dataview.ListItemPlaceholder', {extend:Ext.dataview.SimpleListItem, xtype:'listitemplaceholder', isListItemPlaceholder:true, config:{group:null}, html:'', cls:Ext.baseCSSPrefix + 'listitem-placeholder'});
Ext.define('Ext.dataview.List', {extend:Ext.dataview.Component, alternateClassName:'Ext.List', xtype:'list', isList:true, mixins:[Ext.mixin.Bufferable], config:{bufferSize:20, collapseDefaults:{cached:true, $value:{xclass:'Ext.dataview.ListCollapser'}}, collapsible:{lazy:true, $value:true}, disclosureProperty:'disclosure', grouped:true, groupFooter:{cached:true, $value:null}, groupHeader:{cached:true, $value:{xtype:'itemheader', tpl:'{html} ({count})'}}, groupPlaceholder:{cached:true, $value:{xtype:'listitemplaceholder'}}, 
indexBar:null, infinite:null, minimumBufferDistance:5, onItemDisclosure:{$value:null, merge:function(value, oldValue, target) {
  var t = value && target && target.$isClass && typeof value;
  if (t === 'string' || t === 'function') {
    return {handler:value, scope:'self'};
  }
  return value;
}}, pinFooters:false, pinHeaders:true, pinnedFooter:{lazy:true, $value:null}, pinnedHeader:{lazy:true, $value:{xtype:'itemheader'}}, preventSelectionOnDisclose:true, preventSelectionOnTool:true, rowLines:null, useSimpleItems:null, variableHeights:null, grouping:null, horizontalOverflow:{evented:true, $value:null}, innerCtHeight:null, innerWidth:null, pinnedFooterHeight:null, pinnedHeaderHeight:null, topRenderedIndex:null, verticalOverflow:null, visibleHeight:null, visibleLeft:null, visibleTop:null, 
visibleWidth:null}, bufferableMethods:{syncVerticalOverflow:1}, classCls:Ext.baseCSSPrefix + 'list', itemConfig:{xtype:'simplelistitem'}, maintainChildNodes:false, placeholderHeight:null, rowHeight:0, scrollable:{x:false, y:true}, storeEventListeners:{groupchange:'onStoreGroupChange', totalcountchange:'onStoreTotalCountChange'}, template:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', uiCls:'body-el', children:[{reference:'outerCt', className:Ext.baseCSSPrefix + 'list-outer-ct', children:[{reference:'innerCt', 
className:Ext.baseCSSPrefix + 'list-inner-ct'}]}]}], beforeInitialize:function(config) {
  var me = this, infinite = me.getInfinite();
  if (!infinite) {
    me.innerCt.on('resize', 'onInnerCtResize', me);
  }
  me.expandoKey = 'list-' + me.$iid;
  me.gapMap = {};
  if (!me.itemTranslationMethod) {
    me.itemTranslationMethod = Ext.supports.TranslateYCausesHorizontalScroll ? 'cssposition' : 'csstransform';
  }
  me.groupingInfo = {header:{config:me.getGroupHeader(), creator:'createGroupHeader', name:'$header', offset:0, max:0, unused:[]}, footer:{config:me.getGroupFooter(), creator:'createGroupFooter', name:'$footer', offset:1, max:0, unused:[]}, placeholder:{max:0, unused:[]}};
  me.bodyElement.on({resize:'onBodyResize', scope:me});
  me.selfPartner = [me];
  me.stickyItems = [];
  me.stickyItemsByRecordId = {};
  me.callParent([config]);
}, doDestroy:function() {
  var me = this, groupingInfo = me.groupingInfo, viewport = Ext.Viewport;
  if (me.infinite && Ext.os.is.iOS && viewport) {
    viewport.un('orientationchange', 'onOrientationChange', me);
  }
  Ext.destroy(me.resyncListener, groupingInfo.header.unused, groupingInfo.footer.unused, groupingInfo.placeholder.unused);
  me.callParent();
}, createIndexBar:function(config) {
  return Ext.apply({xtype:'indexbar', $initParent:this, parent:this, hidden:true}, config);
}, createPinnedFooter:function(config) {
  var ret = this.createPinnedHeaderFooter(config);
  ret.bottom = 0;
  ret.pinned = 'bottom';
  return ret;
}, createPinnedHeader:function(config) {
  var me = this, groupedHeader = me.getGroupHeader(), ret = me.createPinnedHeaderFooter(config), tools;
  ret.top = 0;
  ret.pinned = 'top';
  if (!ret.tpl && groupedHeader.tpl) {
    ret.tpl = groupedHeader.tpl;
  }
  if (!('tools' in ret)) {
    tools = groupedHeader && groupedHeader.tools;
    if (tools) {
      ret.tools = tools;
    }
  }
  return ret;
}, groupFrom:function(key) {
  var me = this, store = me.isGrouping() && me.store, group = null, expandoKey = me.expandoKey, ret = null, collapser, groups;
  if (store) {
    groups = store.getGroups();
    if (key.isGroup) {
      key = key.getGroupKey();
    } else {
      if (key.isModel) {
        key = groups.getGrouper().getGroupString(key);
      }
    }
    group = groups.get(key);
    if (group) {
      if (!(ret = Ext.getExpando(group, expandoKey))) {
        if (store.isGroupStore) {
          groups = store.getSource().getGroups();
        }
        ret = {data:groups.get(key), list:me};
        collapser = me.getCollapsible();
        if (collapser) {
          ret.collapsed = collapser.getCollapsed();
        }
        ret = new Ext.dataview.ListGroup(ret);
        Ext.setExpando(group, expandoKey, ret);
      }
    }
  }
  return ret;
}, isGrouping:function() {
  var me = this, store = me.getGrouped() && me.store, grouper = store && store.getGrouper(), grouping = !!grouper;
  me.setGrouping(grouping);
  return grouping;
}, isRecordRendered:function(recordOrIndex) {
  var me = this, renderInfo = me.renderInfo;
  if (!me.infinite) {
    return true;
  }
  if (recordOrIndex.isEntity) {
    recordOrIndex = me.store.indexOf(recordOrIndex);
  }
  return recordOrIndex >= renderInfo.indexTop && recordOrIndex < renderInfo.indexBottom;
}, mapToViewIndex:function(value) {
  var me = this, indexOffset;
  if (me.infinite && typeof value === 'number') {
    indexOffset = me.renderInfo.indexTop;
    value -= indexOffset;
  }
  return me.callParent([value, indexOffset]);
}, scrollToRecord:function(record, animation) {
  return this.ensureVisible({record:record, animation:animation});
}, shouldSelectItem:function(e) {
  var me = this, no = !me.callParent([e]), cmp;
  if (!no) {
    cmp = e.getTarget(me.toolSelector);
    cmp = cmp && me.el.contains(cmp) && Ext.Component.from(cmp);
    if (cmp) {
      no = cmp.preventSelection;
      if (no == null) {
        if (cmp.type === 'disclosure') {
          no = me.getPreventSelectionOnDisclose();
        } else {
          no = me.getPreventSelectionOnTool();
        }
      }
    }
  }
  return !no;
}, onBodyResize:function(el, info) {
  var me = this, height = info.height, width = info.width;
  if (width === me.getVisibleWidth()) {
    me.setVisibleHeight(height);
  } else {
    me.suspendSync = true;
    me.setVisibleHeight(me.outerCt.measure('h'));
    me.suspendSync = false;
    me.setVisibleWidth(width);
    me.refreshScrollerSize();
  }
}, onItemAdd:function(item, index) {
  var me = this;
  if (me.infinite) {
    if (item.$dataItem && me.variableHeights) {
      item.on('resize', 'onDataItemResize', me);
    }
    if (item.isInner) {
      item.setTranslatable({type:me.itemTranslationMethod});
    }
  }
  return me.callParent([item, index]);
}, onItemRemove:function(item, index, destroying) {
  var me = this, height = item.$height, scrollDock = item.scrollDock;
  me.callParent([item, index, destroying]);
  if (scrollDock && height) {
    Ext.Array.remove(me.scrollDockedItems[scrollDock].items, item);
    me.adjustScrollDockHeight(scrollDock, -height);
  }
}, onStoreAdd:function(store, records, index) {
  var me = this;
  me.syncEmptyState();
  if (me.infinite) {
    if (me.getVisibleHeight()) {
      me.refreshGrouping();
      me.resyncOnPaint();
    }
  } else {
    me.refreshGrouping();
    me.setItemCount(store.getCount());
    me.syncItemRange(Math.max(0, index - 1));
  }
}, onStoreRemove:function(store, records, index) {
  var me = this, navModel = me.getNavigationModel(), location;
  if (me.infinite) {
    if (me.getVisibleHeight()) {
      me.refreshGrouping();
      me.resyncOnPaint();
    }
    me.syncEmptyState();
  } else {
    me.refreshGrouping();
    me.callParent([store, records, index]);
  }
  if (navModel.location) {
    location = navModel.location.refresh();
    navModel.setLocation(location);
  }
}, onStoreUpdate:function(store, record, type, modifiedFieldNames, info) {
  var me = this, partners = me.allPartners, len, i, h, p, item;
  if (info && info.groupChanged && me.isGrouping()) {
    me.refreshGrouping();
    me.syncRows();
  } else {
    me.callParent([store, record, type, modifiedFieldNames, info]);
    if (me.partnerManager && me.isActivePartner()) {
      h = me.measurePartners(record);
      if (h !== null) {
        for (i = 0, len = partners.length; i < len; ++i) {
          p = partners[i];
          item = p.itemFromRecord(record);
          p.handleItemResize(item, h, true);
        }
      }
    }
  }
}, applyCollapsible:function(value) {
  var me = this, collapser = null, store = me.store;
  if (value && !(store && store.isVirtualStore)) {
    collapser = Ext.clone(me.getCollapseDefaults());
    if (value !== true) {
      collapser = Ext.merge(collapser, value);
    }
    collapser.list = me;
    collapser = Ext.create(collapser);
  }
  return collapser;
}, updateCollapsible:function(value) {
}, updateGrouped:function() {
  var me = this;
  if (me.initialized) {
    me.refreshGrouping();
    me.syncRows();
  }
}, updateGroupFooter:function(footer) {
  var groupingInfo = this.groupingInfo;
  if (groupingInfo) {
    groupingInfo.footer.config = footer;
  }
}, applyGroupHeader:function(header) {
  var tpl = header && header.tpl;
  if (tpl != null) {
    header = Ext.apply({}, header);
    header.tpl = Ext.XTemplate.get(tpl);
  }
  return header;
}, updateGroupHeader:function(header) {
  var groupingInfo = this.groupingInfo;
  if (groupingInfo) {
    groupingInfo.header.config = header;
  }
}, updateGrouping:function(grouping) {
  this.toggleCls(this.groupedCls, grouping);
}, applyIndexBar:function(config, existing) {
  return Ext.updateWidget(existing, config, this, 'createIndexBar');
}, updateIndexBar:function(indexBar) {
  if (indexBar) {
    this.add(indexBar);
  }
}, applyItemConfig:function(itemConfig, oldItemConfig) {
  var ret = this.callParent([itemConfig, oldItemConfig]), disclosure, tools;
  if (this.getOnItemDisclosure()) {
    disclosure = {disclosure:true};
    tools = ret.tools;
    ret.tools = tools ? Ext.merge(disclosure, tools) : disclosure;
  }
  return ret;
}, updateInfinite:function(infinite) {
  var me = this, viewport = Ext.Viewport;
  me.infinite = infinite;
  me.freezeConfig('infinite');
  if (infinite) {
    me.setItemHidden = me.setItemHiddenInfinite;
    me.el.addCls(me.infiniteCls);
    me.innerCt.addCls(me.infiniteCls);
    me.renderInfo = {atBegin:false, atEnd:false, bottom:0, height:0, top:0, indexBottom:0, indexTop:0};
    me.getScrollable().on({scope:me, offsetychange:'onOffsetChange', offsetxchange:'onOffsetChange', scroll:'onContainerScroll', scrollstart:'onContainerScrollStart', scrollend:'onContainerScrollEnd'});
    if (Ext.os.is.iOS) {
      me.on('navigate', me.onListNavigate, me);
      if (viewport) {
        viewport.on('orientationchange', 'onOrientationChange', me);
      }
    }
  } else {
    if (Ext.os.is.iOS && viewport) {
      viewport.un('orientationchange', 'onOrientationChange', me);
    }
  }
}, onListNavigate:function(list, to, from) {
  var nodeName = to.sourceElement.nodeName;
  if (!from || !(nodeName === 'INPUT' || nodeName === 'TEXTAREA')) {
    return;
  }
  list.scrollToRecord(to.record);
}, updateMaxItemCache:function(max, oldMax) {
  var info = this.groupingInfo;
  this.callParent([max, oldMax]);
  info.header.max = info.footer.max = info.placeholder.max = max;
}, updatePinFooters:function(pinFooters) {
  var me = this, pinnedFooter = me.pinnedFooter;
  me.pinFooters = pinFooters;
  if (me.isConfiguring) {
    return;
  }
  if (me.setupFooterPinning()) {
    if (me.infinite) {
      me.syncPinnedFooter();
    }
  } else {
    if (pinnedFooter) {
      me.setItemHidden(pinnedFooter, true);
    }
  }
}, applyPinnedFooter:function(config, existing) {
  var me = this, ret = Ext.updateWidget(existing, config, me, 'createPinnedFooter'), index;
  if (!existing) {
    index = me.getIndexBar();
    if (index) {
      index = me.indexOf(index);
      me.insert(index, ret);
    } else {
      me.add(ret);
    }
    me.setItemHidden(ret, true);
  }
  return ret;
}, updatePinnedFooter:function(pinnedFooter) {
  var me = this;
  me.pinnedFooter = pinnedFooter;
  me.setupFooterPinning();
  if (pinnedFooter) {
    pinnedFooter.$pinnedFooter = true;
  }
}, updatePinHeaders:function(pinHeaders) {
  var me = this, pinnedHeader = me.pinnedHeader;
  me.pinHeaders = pinHeaders;
  if (me.isConfiguring) {
    return;
  }
  if (me.setupHeaderPinning()) {
    if (me.infinite) {
      me.syncPinnedHeader();
    }
  } else {
    if (pinnedHeader) {
      me.setItemHidden(pinnedHeader, true);
    }
  }
}, applyPinnedHeader:function(config, existing) {
  var me = this, ret = Ext.updateWidget(existing, config, me, 'createPinnedHeader');
  if (!existing && ret) {
    me.insert(0, ret);
    me.setItemHidden(ret, true);
  }
  return ret;
}, updatePinnedHeader:function(pinnedHeader) {
  var me = this;
  me.pinnedHeader = pinnedHeader;
  me.setupHeaderPinning();
  if (pinnedHeader) {
    pinnedHeader.$pinnedHeader = true;
  }
}, updateRowLines:function(rowLines) {
  this.innerCt.toggleCls(this.noRowLinesCls, rowLines === false);
}, createScrollable:function(defaults) {
  var scrollable = this.callParent([defaults]);
  if (this.infinite) {
    scrollable = Ext.apply({type:'virtual', innerElement:this.innerCt}, scrollable);
  }
  return scrollable;
}, applyStore:function(store, oldStore) {
  var me = this, ret = me.callParent([store, oldStore]);
  if (ret) {
    if (ret.isVirtualStore) {
      me.setCollapsible(null);
    } else {
      if (me.isGrouping() && me.getCollapsible()) {
        me.store = ret = new Ext.dataview.GroupStore({autoDestroy:true, list:me, source:ret});
      }
    }
  }
  return ret;
}, updateUseSimpleItems:function(useSimpleItems) {
  if (!this.self._updateUseSimpleItemsWarning) {
    this.self._updateUseSimpleItemsWarning = true;
    Ext.log.warn('The Ext.List#useSimpleItems config is deprecated; ' + 'use itemConfig.xtype instead');
  }
  var itemConfig = this.getItemConfig();
  itemConfig = Ext.applyIf({xtype:useSimpleItems ? 'simplelistitem' : 'listitem'}, itemConfig);
  this.setItemConfig(itemConfig);
}, updateVariableHeights:function(variableHeights) {
  this.variableHeights = variableHeights;
}, privates:{toolSelector:'.' + Ext.baseCSSPrefix + 'tool:not(.' + Ext.baseCSSPrefix + 'passive)', infiniteCls:Ext.baseCSSPrefix + 'infinite', groupFirstCls:Ext.baseCSSPrefix + 'group-first', groupLastCls:Ext.baseCSSPrefix + 'group-last', groupedCls:Ext.baseCSSPrefix + 'grouped', hasPinnedFooterCls:Ext.baseCSSPrefix + 'has-pinned-footer', hasPinnedHeaderCls:Ext.baseCSSPrefix + 'has-pinned-header', noRowLinesCls:Ext.baseCSSPrefix + 'no-row-lines', stickyCls:Ext.baseCSSPrefix + 'sticky', tombstoneCls:Ext.baseCSSPrefix + 
'tombstone', blockingScroll:0, gapAfter:0, groupingInfo:null, heightSyncs:0, manageHorizontalOverflow:true, pinnedFooter:null, pinnedHeader:null, lastAdjustedPosition:null, measuredHeight:null, renderInfo:null, suspendSync:false, onContainerScroll:function(scroller, x, y) {
  var me = this, oldX, oldY;
  if (!me.blockingScroll) {
    oldX = me._visibleLeft;
    oldY = me.infinite ? me.lastAdjustedPosition : me._visibleTop;
    me.setVisibleLeft(x);
    me.setVisibleTop(y);
    me.fireEvent('scroll', me, {x:x, y:y, oldX:oldX, oldY:oldY});
  }
}, onContainerScrollStart:function() {
  var me = this, pm = me.partnerManager;
  if (me.variableHeights && pm) {
    pm.claimActivePartner(me);
  }
  me.toggleHoverCls(false);
  me.doHover = false;
}, onContainerScrollEnd:function() {
  var me = this, pm = me.partnerManager;
  me.doHover = true;
  me.toggleHoverCls(true);
  if (me.variableHeights && pm) {
    pm.releaseActivePartner(me);
  }
}, onDataItemResize:function(item, width, height, oldWidth, oldHeight) {
  if (oldWidth === null && oldHeight === null) {
    return;
  }
  this.handleItemResize(item, height);
}, onItemDisclosureTap:function(item, e) {
  var me = this, record = item.getRecord(), index = me.store.indexOf(record);
  me.fireAction('disclose', [me, record, item, index, e], 'doDisclose');
}, onOrientationChange:function() {
  this.rowHeight = 0;
}, _onChildTouchCancel:function(e) {
  if (!e.getTarget(this.toolSelector)) {
    this.callParent([e]);
  }
}, _onChildTouchEnd:function(e) {
  if (!e.getTarget(this.toolSelector)) {
    this.callParent([e]);
  }
}, _onChildTouchStart:function(e) {
  if (!e.getTarget(this.toolSelector)) {
    this.callParent([e]);
  }
}, onOffsetChange:function(scroller) {
  var dataItems = this.dataItems, ln = dataItems.length, i;
  for (i = 0; i < ln; i++) {
    scroller.syncOffsets(dataItems[i].getTranslatable());
  }
}, onRangeAvailable:function(range, first, last) {
  this.syncRows();
}, onScrollDockItemHide:function(item) {
  var height = item.$height;
  if (height) {
    this.adjustScrollDockHeight(item.scrollDock, -height);
    item.$height = null;
  }
}, onScrollDockItemResize:function(item, width, height) {
  var was = item.$height;
  if (was !== height) {
    item.$height = height;
    this.adjustScrollDockHeight(item.scrollDock, height - was);
  }
}, onScrollDockItemShow:function(item) {
  var height = item.$height;
  if (height == null) {
    height = this.measureItem(item);
  }
  this.adjustScrollDockHeight(item.scrollDock, height);
}, onStoreGroupChange:function(store) {
  var me = this, was;
  if (!me.initialized) {
    return;
  }
  if (!store.isGroupStore) {
    was = store.getAutoDestroy();
    store.setAutoDestroy(false);
    this.setStore(store);
    store.setAutoDestroy(was);
  }
  me.refreshGrouping();
  me.syncRows();
}, onStoreTotalCountChange:function() {
  if (this.getVisibleHeight()) {
    this.syncRowsToHeight();
  }
  this.syncEmptyState();
}, addDataItem:function(item, at) {
  var me = this, ret;
  ret = me.callParent([item, at]);
  if (me.infinite) {
    me.getScrollable().syncOffsets(ret.getTranslatable());
  }
  ret.$height = me.variableHeights ? null : me.rowHeight;
  return ret;
}, addScrollDockedItem:function(item) {
  var me = this;
  if (me.infinite) {
    item.on({hide:'onScrollDockItemHide', resize:'onScrollDockItemResize', show:'onScrollDockItemShow', scope:me});
    item.$height = null;
    me.setItemHidden(item, true);
  }
}, adjustContentTop:function(adjust) {
  var me = this, rows = this.dataItems, len = rows.length, renderInfo = me.renderInfo, scrollDock = me.scrollDockedItems, i, row, decoration, item, items;
  for (i = 0; i < len; ++i) {
    row = rows[i];
    me.setItemPosition(row, row.$position + adjust);
    decoration = row.$header;
    if (decoration) {
      me.setItemPosition(decoration, decoration.$position + adjust);
    }
    decoration = row.$footer;
    if (decoration) {
      me.setItemPosition(decoration, decoration.$position + adjust);
    }
    row.$y0 += adjust;
    row.$y1 += adjust;
  }
  if (scrollDock) {
    if (renderInfo.atBegin) {
      items = scrollDock.start.items;
      len = items.length;
      for (i = 0; i < len; ++i) {
        item = items[i];
        if (!item.getHidden()) {
          me.setItemPosition(item, item.$position + adjust);
        }
      }
    }
    if (renderInfo.atEnd) {
      items = scrollDock.end.items;
      len = items.length;
      for (i = 0; i < len; ++i) {
        item = items[i];
        if (!item.getHidden()) {
          me.setItemPosition(item, item.$position + adjust);
        }
      }
    }
  }
}, adjustScrollDockHeight:function(which, amount) {
  var me = this, scrollDock = me.scrollDockedItems;
  scrollDock = scrollDock && scrollDock[which];
  if (scrollDock) {
    scrollDock.height += amount;
    me.resyncOnPaint();
  }
}, _doActivePartnerCheck:function() {
  if (!this.isActivePartner()) {
    Ext.raise('Should not be called by non-active partner');
  }
}, adjustRenderedRows:function(y, oldY) {
  this._doActivePartnerCheck();
  var me = this, bufferSize = me.getBufferSize(), minimumBufferDistance = me.getMinimumBufferDistance(), renderInfo = me.renderInfo, indexTop = renderInfo.indexTop, indexBottom = renderInfo.indexBottom, rows = me.dataItems, rowCount = rows.length, height = me.getVisibleHeight(), storeCount = me.store.getCount(), visibleTopIndex = me.recordIndexByPosition(y), visibleBottomIndex = me.recordIndexByPosition(y + height), newIndexTop, delta;
  if (oldY < y) {
    if (indexBottom - visibleBottomIndex >= minimumBufferDistance) {
      return;
    }
  } else {
    if (visibleTopIndex - indexTop >= minimumBufferDistance) {
      return;
    }
  }
  newIndexTop = visibleTopIndex - (bufferSize >>> 1);
  newIndexTop = Math.max(0, Math.min(newIndexTop, storeCount - rowCount));
  delta = newIndexTop - indexTop;
  if (delta > 0 && delta < rowCount) {
    me.rollDown(delta);
  } else {
    if (delta < 0 && -delta < rowCount) {
      me.rollUp(-delta);
    } else {
      if (delta || me.refreshing) {
        me.teleport(y);
      }
    }
  }
}, bindStore:function(store) {
  var me = this, Model = store.getModel(), tombstoneRec = new Model;
  if (store.isBufferedStore) {
    Ext.raise('Did you mean to use Ext.data.virtual.Store? ' + '(Ext.data.BufferedStore is not supported)');
  }
  if (store.isVirtualStore && !me.infinite) {
    Ext.raise('Virtual stores require infinite:true');
  }
  me.dataRange = me.store.createActiveRange({prefetch:true, callback:'onRangeAvailable', scope:me});
  me.tombstoneRec = tombstoneRec;
  tombstoneRec.tombstone = true;
  if (me.getVisibleHeight()) {
    me.syncRowsToHeight();
  }
}, bisectPosition:function(y) {
  var rows = this.dataItems, begin = 0, end = rows.length - 1, middle, midVal;
  y = y || 0;
  if (y < rows[0].$y0) {
    return -1;
  }
  while (begin <= end) {
    middle = begin + end >>> 1;
    midVal = rows[middle].$y0;
    if (y === midVal) {
      return middle;
    }
    if (midVal < y) {
      begin = middle + 1;
    } else {
      end = middle - 1;
    }
  }
  if (begin && y < rows[begin - 1].$y1) {
    --begin;
  }
  return begin;
}, blockAndScrollTo:function(y, anim) {
  var me = this, scroller = me.getScrollable();
  if (scroller.getPosition().y !== y) {
    scroller.on({single:true, priority:-1000, scroll:function() {
      --me.blockingScroll;
    }});
    ++me.blockingScroll;
  }
  return scroller.scrollTo(null, y, anim);
}, changeHeaderFooter:function(item, recordIndex, def, enabled) {
  var me = this, property = def.name, decoration = item[property] || null, infinite = me.infinite, group, destroyed;
  enabled = enabled && def.config;
  group = enabled && def.map[recordIndex];
  if (group) {
    if (!decoration) {
      if (!(decoration = def.unused.pop())) {
        decoration = me[def.creator]();
      }
      decoration = me.reorderItem(decoration, item, def.offset);
    }
    decoration.$dataRow = item;
    decoration.setGroup(group);
  } else {
    if (decoration) {
      destroyed = me.removeGroupItem(decoration, def, !enabled);
      if (!destroyed && infinite) {
        me.setItemHidden(decoration, true);
        me.reorderItem(decoration);
      }
      decoration = null;
    }
  }
  item[property] = decoration;
}, changeItem:function(itemIndex, recordIndex) {
  var me = this, options = me.callParent([itemIndex, recordIndex]), item = options.item;
  if (me.infinite && me.variableHeights) {
    item.$height = null;
  }
  return options;
}, changeItemGrouping:function(options) {
  var me = this, enabled = me.isGrouping(), groupingInfo = me.groupingInfo, item = options.item, recordIndex = options.recordIndex, collapser;
  me.changeHeaderFooter(item, recordIndex, groupingInfo.header, enabled);
  if (enabled && item.isListItemPlaceholder) {
    collapser = me.getCollapsible();
    if (collapser) {
      enabled = collapser.getFooter();
    }
  }
  me.changeHeaderFooter(item, recordIndex, groupingInfo.footer, enabled);
}, changeItemIsFirst:function(options) {
  if (options.isFirstChanged) {
    var me = this, items = me.scrollDockedItems, i, len;
    me.callParent([options]);
    if (items && !options.isFirst && me.infinite) {
      items = items.start.items;
      len = items.length;
      for (i = 0; i < len; ++i) {
        me.setItemHidden(items[i], true);
      }
    }
  }
}, changeItemIsLast:function(options) {
  if (options.isLastChanged) {
    var me = this, items = me.scrollDockedItems, i, len;
    me.callParent([options]);
    if (items && !options.isLast && me.infinite) {
      items = items.end.items;
      len = items.length;
      for (i = 0; i < len; ++i) {
        me.setItemHidden(items[i], true);
      }
    }
  }
}, changeItemRecord:function(options) {
  var me = this, itemClasses = options.itemClasses, tombstoneCls = me.tombstoneCls;
  if (options.record) {
    delete itemClasses[tombstoneCls];
    me.syncItemRecord(options);
  } else {
    itemClasses[tombstoneCls] = 1;
    me.syncItemRecord(options, me.tombstoneRec);
  }
}, changeItemStuck:function(options) {
  var me = this, item = options.item, record = options.record, stickyItem = record && me.stickyItemsByRecordId[record.internalId] || null;
  if (item.$sticky) {
    if (record !== item.getRecord()) {
      me.dislodgeItem(item, options, stickyItem);
    }
  } else {
    if (stickyItem) {
      me.dislodgeItem(item, options, stickyItem);
      me.removeDataItem(item);
    }
  }
}, clearItemCaches:function() {
  var info = this.groupingInfo, headers = info.header.unused, footers = info.footer.unused, placeholders = info.placeholder.unused;
  this.callParent();
  Ext.destroy(headers, footers, placeholders);
  headers.length = footers.length = placeholders.length = 0;
}, constrainStickyItem:function(item) {
  var me = this, pinnedFooter = me.pinnedFooter, pinnedHeader = me.pinnedHeader, pinned = false, renderInfo = me.renderInfo, recordIndex = item.$recordIndex, h = me.measureItem(item, me), options = item.$sticky, y = options.pos, y0 = me.getVisibleTop(), y1 = y0 + me.getVisibleHeight() - h, ret = y, hide;
  if (options.floated) {
    me.setItemHidden(item, false);
    return null;
  }
  if (pinnedHeader) {
    y0 += me.measureItem(pinnedHeader);
  }
  if (pinnedFooter) {
    y1 -= me.measureItem(pinnedFooter);
  }
  if (recordIndex < renderInfo.indexTop) {
    hide = true;
    y = y0;
    pinned = 'top';
  } else {
    if (recordIndex >= renderInfo.indexBottom) {
      hide = true;
      y = y1;
      pinned = 'bottom';
    } else {
      if (y < y0) {
        y = y0;
        pinned = 'top';
      } else {
        if (y > y1) {
          y = y1;
          pinned = 'bottom';
        }
      }
    }
  }
  if (options.autoPin) {
    ret = y;
    if (item.isDataViewPinnable) {
      item.setPinned(pinned);
    }
  } else {
    if (hide) {
      me.setItemHidden(item, true);
    }
  }
  return ret;
}, createGroupFooter:function() {
  var me = this, footer = me.getGroupFooter();
  if (typeof footer === 'string') {
    footer = {xtype:footer};
  }
  footer = Ext.apply({$dataItem:'footer'}, footer);
  footer.$initParent = footer.ownerCmp = footer.list = me;
  return footer;
}, createGroupHeader:function() {
  var me = this, header = me.getGroupHeader(), collapser = me.getCollapsible(), tool = collapser && collapser.getTool(), tools;
  if (typeof header === 'string') {
    header = {xtype:header};
  }
  header = Ext.apply({$dataItem:'header'}, header);
  header.$initParent = header.ownerCmp = header.list = me;
  if (tool) {
    tool = Ext.clone(tool);
    tools = header.tools;
    if (!tools || Ext.isArray(tools)) {
      header.tools = tools = tools ? tools.slice() : [];
      tools.push(tool);
    } else {
      header.tools = tools = Ext.apply({}, tools);
      tools[tool.itemId] = tool;
    }
  }
  return header;
}, createGroupPlaceholder:function() {
  var me = this, config = me.getGroupPlaceholder();
  if (typeof config === 'string') {
    config = {xtype:config};
  }
  config = Ext.apply({$dataItem:'placeholder'}, config);
  config.$initParent = config.ownerCmp = config.list = me;
  if (!me.variableHeights) {
    config.$height = me.placeholderHeight;
  }
  return config;
}, createPinnedHeaderFooter:function(config) {
  return Ext.merge({translatable:{type:'csstransform'}, isPinnedItem:true, list:this}, config);
}, dislodgeItem:function(item, options, replacement) {
  var me = this, dataItems = me.dataItems, sticky = item.$sticky;
  if (!replacement) {
    replacement = me.acquireItem(me.indexOf(item));
    dataItems.pop();
  } else {
    if (replacement.$sticky && !replacement.$sticky.dislodged) {
      me.dislodgeItem(replacement, {itemIndex:dataItems.indexOf(replacement)});
    }
  }
  me.dataItems[options.itemIndex] = options.item = replacement;
  replacement.$footer = item.$footer;
  replacement.$header = item.$header;
  replacement.$position = null;
  item.$footer = item.$header = null;
  if (sticky) {
    sticky.dislodged = true;
  }
  sticky = replacement.$sticky;
  if (sticky) {
    sticky.dislodged = false;
  }
  return replacement;
}, doClear:function() {
  var me = this, groupingInfo = me.groupingInfo, headers = groupingInfo.header.unused, footers = groupingInfo.footer.unused, placeholders = groupingInfo.placeholder.unused, scroller;
  Ext.destroy(headers, footers, placeholders);
  footers.length = headers.length = placeholders.length = 0;
  if (me.infinite) {
    me.setItemCount(0);
    me.lastAdjustedPosition = null;
    me.setVisibleTop(0);
    scroller = me.getScrollable();
    scroller.scrollTo(null, 0);
    me.refreshScrollerSize();
    me.syncEmptyState();
  } else {
    me.callParent();
  }
}, doDisclose:function(me, record, item, index, e) {
  var onItemDisclosure = me.getOnItemDisclosure(), handler = onItemDisclosure, scope;
  if (handler && handler !== true) {
    if (handler.handler) {
      scope = handler.scope;
      handler = handler.handler;
    }
    Ext.callback(handler, scope, [record, item, index, e], 0, me);
  }
}, doRefresh:function(scrollToTop) {
  var me = this, scroller = me.getScrollable(), store = me.store, preventSync, count, restoreFocus, scrollTop;
  if (me.infinite) {
    count = ++me.refreshCounter;
    me.refreshGrouping();
    if (store.getCount()) {
      me.hideEmptyText();
      if (count > 1 && scroller) {
        if (scrollToTop) {
          restoreFocus = me.saveFocusState();
          me.blockAndScrollTo(0, false);
          me.lastAdjustedPosition = null;
          me.refreshing = true;
          me.syncRowsToHeight(false);
          me.resetVisibleTop();
          me.setVisibleTop(0);
          preventSync = true;
          me.refreshing = false;
          restoreFocus();
        } else {
          scrollTop = scroller.getPosition().y;
        }
      }
    } else {
      if (me.dataItems.length && !store.hasPendingLoad()) {
        me.doClear();
      }
    }
    if (!preventSync) {
      me.resync(true);
      if (scrollTop != null && scrollTop !== scroller.getPosition().y) {
        scroller.scrollTo(null, scrollTop);
      }
    }
  } else {
    me.refreshGrouping();
    me.callParent([scrollToTop]);
  }
}, ensureVisibleScroll:function(plan) {
  var me = this, recIndex = plan.recordIndex, item = plan.item || (plan.item = me.itemFromRecord(recIndex)), scroller = me.getScrollable(), promise, size, y;
  if (item) {
    return scroller.ensureVisible(item.el, {align:plan.align, animation:plan.animation, highlight:plan.highlight, x:false});
  }
  size = scroller.getSize();
  y = Math.floor((size ? size.y : 0) * (recIndex / me.store.getCount()));
  plan.animation = false;
  me.nextTeleportTopIndex = recIndex;
  me.setVisibleTop(y);
  delete me.nextTeleportTopIndex;
  promise = me.blockAndScrollTo(y, false);
  plan.item = me.itemFromRecord(recIndex);
  return promise.then(function() {
    if (!me.destroyed) {
      plan.item = me.itemFromRecord(recIndex);
    }
    return plan;
  });
}, getCacheForItem:function(item) {
  var kind = item.$dataItem, ret;
  if (kind === 'record') {
    ret = this.itemCache;
  } else {
    ret = this.groupingInfo[kind];
  }
  return ret;
}, getItemForRecord:function(viewIndex, record) {
  var me = this, item = me.dataItems[viewIndex], recordIsPlaceholder = record && !!record.$collapsedGroupPlaceholder, cache = me.groupingInfo.placeholder, dom = item.el.dom, options, placeholder;
  if (recordIsPlaceholder !== !!item.isListItemPlaceholder) {
    options = {itemIndex:viewIndex};
    if (recordIsPlaceholder) {
      if (!(placeholder = cache.unused.pop())) {
        placeholder = me.createGroupPlaceholder();
      }
      placeholder = me.insert(viewIndex, placeholder);
      placeholder.setGroup(me.groupFrom(record));
      dom.parentNode.insertBefore(placeholder.el.dom, dom);
      me.dislodgeItem(item, options, placeholder);
      me.removeDataItem(item);
      item = placeholder;
    } else {
      placeholder = item;
      item = me.dislodgeItem(placeholder, options);
      dom.parentNode.insertBefore(item.el.dom, dom);
      me.removeGroupItem(placeholder, cache);
    }
  }
  return item;
}, getItemFromPoint:function(x, y) {
  var me = this, index, pos;
  if (me.infinite) {
    pos = Math.max(0, Math.min(y, me.getScrollable().getSize().y));
    index = me.recordIndexByPosition(pos);
    return me.dataItems[index - me.renderInfo.indexTop];
  }
  return me.callParent([x, y]);
}, getItemTop:function(item) {
  var y;
  item = item.$header || item;
  if (this.infinite) {
    y = item.$y0;
  } else {
    y = this.getScrollable().getEnsureVisibleXY(item.element, {align:{y:'start?'}}).y;
  }
  return y;
}, getPositionedItemTarget:function(item) {
  if (item && item.layer === 'inner') {
    return this.callParent([item]);
  }
  return this.bodyElement;
}, getRecordIndexFromPoint:function(x, y) {
  if (this.infinite) {
    return this.recordIndexByPosition(Math.max(0, Math.min(y, this.getScrollable().getSize().y)));
  }
  return this.callParent([x, y]);
}, getRenderPartners:function() {
  var partners = this.allPartners;
  if (!(partners && this.variableHeights)) {
    partners = this.selfPartner;
  }
  return partners;
}, getRenderTarget:function() {
  return this.innerCt;
}, getScrollableClientRegion:function() {
  return this.callParent().adjust(this.getPinnedHeaderHeight() || 0, 0, -(this.getPinnedFooterHeight() || 0), 0);
}, getScrollerTarget:function() {
  return this.outerCt;
}, getStoreChangeSyncIndex:function(index) {
  return this.isGrouping() ? Math.max(0, index - 1) : index;
}, handleItemResize:function(item, height, force) {
  var me = this, dataItems = me.dataItems, renderInfo = me.renderInfo, row = item.$dataRow || item, bottomUp, count, index, y;
  height += item.el.getMargin('tb');
  if (force || item.$height !== height) {
    item.$height = height;
    index = dataItems.indexOf(row);
    if (index > -1) {
      if (renderInfo.indexTop && renderInfo.indexBottom >= me.store.getCount()) {
        bottomUp = true;
        count = index + 1;
        y = row.$y1;
      } else {
        count = dataItems.length - index;
        y = row.$y0;
      }
      me.positionItems(y, bottomUp, count);
    }
  }
}, isActivePartner:function() {
  if (this.variableHeights && this.partnerManager) {
    return this.partnerManager.isActivePartner(this);
  }
  return true;
}, itemFromRecord:function(rec) {
  var me = this, store = me.store, index, item;
  if (store) {
    if (me.infinite) {
      index = rec.isEntity ? store.indexOf(rec) : rec;
      item = me.dataItems[index - me.renderInfo.indexTop];
    } else {
      item = me.callParent([rec]);
    }
  }
  return item || null;
}, measureItem:function(item, heightCache) {
  var height = item.$height, measured;
  if (height == null) {
    if (this.variableHeights || !heightCache || !(height = heightCache.rowHeight)) {
      measured = item.el.measure('h');
      height = measured + item.el.getMargin('tb');
      if (heightCache) {
        heightCache.rowHeight = height;
      }
    }
    this.setItemHeight(item, height);
    item.$measured = measured;
  }
  return height;
}, measureItems:function() {
  var me = this, scrollDock = me.scrollDockedItems, rows = me.dataItems, n = rows.length, active = me.partnerManager && me.isActivePartner(), hasItemVm = me.hasItemVm, placeholderHeight = me.placeholderHeight, decoration, h, i, item, items, row, rowHeight;
  if (me.variableHeights) {
    if (hasItemVm) {
      me.lookupViewModel().notify();
    }
    while (n-- > 0) {
      row = rows[n];
      if (active) {
        me.measurePartners(row);
      } else {
        if (row.$height == null) {
          row.$height = me.measureItem(row);
        }
        decoration = row.$header;
        if (decoration && decoration.$height == null) {
          decoration.$height = me.measureItem(decoration);
        }
        decoration = row.$footer;
        if (decoration) {
          decoration.$height = me.measureItem(decoration);
        }
      }
    }
  } else {
    if (n) {
      rowHeight = me.rowHeight;
      if (!rowHeight || placeholderHeight === null) {
        if (hasItemVm) {
          me.lookupViewModel().notify();
        }
        for (i = 0; i < n; ++i) {
          row = rows[i];
          if (!row.isListItemPlaceholder) {
            if (!rowHeight) {
              row.$height = null;
              me.rowHeight = rowHeight = me.measureItem(row);
            }
            row.$height = rowHeight;
          } else {
            if (placeholderHeight === null) {
              row.$height = null;
              me.placeholderHeight = placeholderHeight = me.measureItem(row);
            }
            row.$height = placeholderHeight;
          }
        }
      }
    }
  }
  if (scrollDock) {
    items = scrollDock.start.items;
    for (h = 0, n = items.length; n-- > 0;) {
      item = items[n];
      if (!item.getHidden()) {
        h += item.$height || me.measureItem(item);
      }
    }
    scrollDock.start.height = h;
    items = scrollDock.end.items;
    for (h = 0, n = items.length; n-- > 0;) {
      item = items[n];
      if (!item.getHidden()) {
        h += item.$height || me.measureItem(item);
      }
    }
    scrollDock.end.height = h;
  }
}, measurePartners:function(record, preventNotify) {
  var me = this, partners = me.allPartners, len = partners.length, items = new Array(len), largest = 0, min = 0, allEqual = true, item, h, fullH, oldH, p, i, changed;
  if (record.isDataViewItem) {
    record = record.getRecord();
  }
  if (me.hasItemVm && !preventNotify) {
    me.lookupViewModel().notify();
  }
  for (i = 0; i < len; ++i) {
    p = partners[i];
    item = p.itemFromRecord(record);
    items[i] = item;
    item.setMinHeight(null);
  }
  for (i = 0; i < len; ++i) {
    item = items[i];
    oldH = item.$height;
    delete item.$height;
    h = partners[i].measureItem(item);
    fullH = item.$measured;
    changed = changed || oldH !== h;
    if (i === 0) {
      largest = h;
      min = fullH;
    }
    if (h !== largest) {
      allEqual = false;
      if (h > largest) {
        largest = h;
        min = fullH;
      }
    }
  }
  if (!allEqual) {
    for (i = 0; i < len; ++i) {
      item = items[i];
      item.setMinHeight(min);
      partners[i].setItemHeight(item, largest);
    }
  }
  return changed ? min : null;
}, onInnerCtResize:function() {
  this.syncVerticalOverflow();
}, positionItems:function(position, bottomUp, count) {
  var me = this, renderInfo = me.renderInfo, rows = me.dataItems, len = rows.length, scrollDock = me.scrollDockedItems, partners = me.getRenderPartners(), partnerLen = partners.length, i, j, item, items, y, p;
  for (i = 0; i < partnerLen; ++i) {
    p = partners[i];
    if (bottomUp) {
      p.positionItemsBottomUp(position, count);
    } else {
      p.positionItemsTopDown(position, count);
    }
  }
  if (len) {
    renderInfo.top = rows[0].$y0;
    renderInfo.bottom = rows[len - 1].$y1;
  } else {
    renderInfo.top = renderInfo.bottom = scrollDock && scrollDock.start.height || 0;
  }
  renderInfo.height = renderInfo.bottom - renderInfo.top;
  for (i = 0; i < partnerLen; ++i) {
    p = partners[i];
    if (renderInfo.atEnd) {
      y = renderInfo.bottom;
      y += p.gapAfter;
      scrollDock = p.scrollDockedItems;
      if (scrollDock) {
        items = scrollDock.end.items;
        len = items.length;
        for (j = 0; j < len; ++j) {
          item = items[j];
          if (!item.getHidden()) {
            y += p.setItemPosition(item, y);
          }
        }
      }
    }
    p.refreshScrollerSize();
  }
}, positionItemsBottomUp:function(position, count) {
  var me = this, groupingInfo = me.groupingInfo, footers = groupingInfo.footer, headers = groupingInfo.header, renderInfo = me.renderInfo, rows = me.dataItems, scrollDock = me.scrollDockedItems, y = position, indexTop = renderInfo.indexTop, decoration, ht, i, item, row, y1, stickyPos;
  for (i = count; i-- > 0;) {
    row = rows[i];
    y1 = y;
    decoration = row.$footer;
    if (decoration) {
      if ((ht = decoration.$height) == null) {
        ht = me.measureItem(decoration, footers);
      }
      y -= ht;
      me.setItemPosition(decoration, y);
    }
    y -= row.$height;
    if (row.$sticky) {
      row.$sticky.pos = y;
      stickyPos = me.constrainStickyItem(row);
      if (stickyPos !== null) {
        me.setItemPosition(row, stickyPos);
      }
    } else {
      me.setItemPosition(row, y);
    }
    decoration = row.$header;
    if (decoration) {
      if ((ht = decoration.$height) == null) {
        ht = me.measureItem(decoration, headers);
      }
      y -= ht;
      me.setItemPosition(decoration, y);
    }
    y -= me.gapMap[i + indexTop] || 0;
    row.$y0 = y;
    row.$y1 = y1;
  }
  if (renderInfo.atBegin && scrollDock) {
    scrollDock = scrollDock.start.items;
    for (i = scrollDock.length; i-- > 0;) {
      item = scrollDock[i];
      if (!item.getHidden()) {
        y -= item.$height;
        me.setItemPosition(item, y);
      }
    }
  }
  if (y < 0 || y > 0 && renderInfo.indexTop === 0) {
    me.adjustContentTop(-y);
  }
}, positionItemsTopDown:function(position, count) {
  var me = this, groupingInfo = me.groupingInfo, footers = groupingInfo.footer, headers = groupingInfo.header, rows = me.dataItems, len = rows.length, scrollDock = me.scrollDockedItems, indexTop = me.renderInfo.indexTop, y = position, decoration, i, item, row, y0, stickyPos;
  count = count || len;
  if (me.renderInfo.atBegin && count === len) {
    if (scrollDock) {
      scrollDock = scrollDock.start.items;
      y = 0;
      for (i = 0; i < scrollDock.length; ++i) {
        item = scrollDock[i];
        if (!item.getHidden()) {
          y += me.setItemPosition(item, y);
        }
      }
    } else {
      if (y && !Object.keys(me.gapMap).length) {
        Ext.raise('Top-most item should be positioned at 0 not ' + y);
      }
    }
  }
  for (i = len - count; i < len; ++i) {
    row = rows[i];
    y0 = y;
    y += me.gapMap[indexTop + i] || 0;
    decoration = row.$header;
    if (decoration) {
      if (decoration.$height == null) {
        me.measureItem(decoration, headers);
      }
      y += me.setItemPosition(decoration, y);
    }
    if (row.$sticky) {
      row.$sticky.pos = y;
      stickyPos = me.constrainStickyItem(row);
      if (stickyPos !== null) {
        y += me.setItemPosition(row, stickyPos);
      }
    } else {
      y += me.setItemPosition(row, y);
    }
    decoration = row.$footer;
    if (decoration) {
      if (decoration.$height == null) {
        me.measureItem(decoration, footers);
      }
      y += me.setItemPosition(decoration, y);
    }
    row.$y0 = y0;
    row.$y1 = y;
  }
}, refreshGrouping:function() {
  var me = this, grouped = me.isGrouping(), infinite = me.infinite, item;
  if (infinite) {
    item = grouped && me.getPinFooters() ? me.getPinnedFooter() : me.pinnedFooter;
    if (item) {
      me.setItemHidden(item, true);
    }
    item = grouped && me.getPinHeaders() ? me.getPinnedHeader() : me.pinnedHeader;
    if (item) {
      me.setItemHidden(item, true);
    }
  }
  me.refreshGroupIndices();
  me.syncIndexBar();
}, refreshGroupIndices:function() {
  var me = this, store = me.store, groups = me.isGrouping() ? store.getGroups() : null, groupingInfo = me.groupingInfo, footers = groupingInfo.footer, headers = groupingInfo.header, groupCount = groups && groups.length, firstRecordIndex, footerIndices, footerMap, group, headerIndices, previous = null, dataGroup, headerMap, i;
  if (groupCount) {
    headers.map = headerMap = {};
    headers.indices = headerIndices = [];
    footers.map = footerMap = {};
    footers.indices = footerIndices = [];
    for (i = 0; i < groupCount; ++i) {
      group = me.groupFrom(dataGroup = groups.getAt(i));
      firstRecordIndex = store.indexOf(dataGroup.first());
      group.previousGroup = previous;
      headerIndices.push(firstRecordIndex);
      headerMap[group.beginIndex = firstRecordIndex] = group;
      if (previous) {
        previous.nextGroup = group;
        footerIndices.push(firstRecordIndex - 1);
        footerMap[(previous.endIndex = firstRecordIndex) - 1] = previous;
      }
      previous = group;
    }
    group.nextGroup = null;
    group.endIndex = i = store.getCount();
    footerIndices.push(--i);
    footerMap[i] = group;
  } else {
    headers.map = headers.indices = footers.map = footers.indices = null;
  }
}, refreshScrollerSize:function() {
  var me = this, h, renderInfo, scrollDock, storeCount;
  if (me.store && me.infinite) {
    me.syncContentTop();
    renderInfo = me.renderInfo;
    scrollDock = me.scrollDockedItems;
    storeCount = me.store.getCount();
    h = renderInfo.bottom + (storeCount - renderInfo.indexBottom) * me.rowHeight;
    scrollDock = scrollDock && scrollDock.end;
    if (scrollDock) {
      h += scrollDock.height;
    }
    me.getScrollable().setSize({x:null, y:h});
    me.setVerticalOverflow(h > me.getVisibleHeight());
    me.refreshPinnedAreas();
  }
}, reorderItem:function(item, ref, offset) {
  offset = offset || 0;
  var me = this, innerItems = me.innerItems, innerCount = innerItems.length, innerIndex = ref == null ? innerCount : ref.isWidget ? innerItems.indexOf(ref) + offset : ref, items = me.items, index = innerIndex < innerCount ? items.indexOf(innerItems[innerIndex]) : items.length;
  if (!item.isWidget || !me.infinite || me.maintainChildNodes || item.parent !== me) {
    item = me.insert(index, item);
  } else {
    items.insert(index, item);
    index = innerItems.indexOf(item);
    if (index > -1) {
      innerItems.splice(index, 1);
      if (index < innerIndex) {
        --innerIndex;
      }
    }
    if (innerIndex < innerCount) {
      innerItems.splice(innerIndex, 0, item);
    } else {
      innerItems.push(item);
    }
  }
  return item;
}, recordIndexByPosition:function(y) {
  var me = this, renderInfo = me.renderInfo, renderTop = renderInfo.top, renderBottom = renderInfo.bottom, indexTop = renderInfo.indexTop, ret;
  if (y < renderTop) {
    ret = Math.floor(y / renderTop * indexTop);
  } else {
    if (y < renderBottom) {
      ret = indexTop + me.bisectPosition(y);
    } else {
      y -= renderBottom;
      ret = Math.min(renderInfo.indexBottom + Math.floor(y / me.rowHeight), me.store.getCount() - 1);
    }
  }
  return ret;
}, removeDataItem:function(item, preventCache) {
  var me = this, header = item.$header, footer = item.$footer, groupingInfo = me.groupingInfo;
  if (header) {
    me.removeGroupItem(header, groupingInfo.header, preventCache);
  }
  if (footer) {
    me.removeGroupItem(footer, groupingInfo.footer, preventCache);
  }
  item.$header = item.$footer = null;
  return me.callParent([item, preventCache]);
}, removeGroupItem:function(item, cache, preventCache) {
  var destroyed = this.removeCachedItem(item, preventCache, cache, this.infinite);
  if (!destroyed) {
    item.$dataRow = null;
    if (item.setGroup) {
      item.setGroup(null);
    }
  }
  return destroyed;
}, resync:function(force) {
  var me = this, height = me.outerCt.measure('h');
  me.resyncListener = null;
  if (height) {
    if (height === me.getVisibleHeight()) {
      me.syncRowsToHeight(force);
    } else {
      me.setVisibleHeight(height);
    }
  }
}, resyncOnPaint:function() {
  this.whenVisible('resync', [true]);
}, rollDown:function(count) {
  this._doActivePartnerCheck();
  var me = this, dataItems = me.dataItems, renderInfo = me.renderInfo, indexBottom = renderInfo.indexBottom, tailItem = dataItems[dataItems.length - 1], innerTailStart = me.innerItems.indexOf(tailItem) + 1, partners = me.getRenderPartners(), len = partners.length, adjust, decoration, innerTailIndex, i, j, options, p, row;
  if (tailItem.$footer) {
    ++innerTailStart;
  }
  me.setTopRenderedIndex(renderInfo.indexTop + count);
  for (i = 0; i < len; ++i) {
    p = partners[i];
    dataItems = p.dataItems;
    innerTailIndex = innerTailStart;
    for (j = 0; j < count; j++) {
      row = dataItems.shift();
      dataItems.push(row);
      adjust = (row.$header ? 1 : 0) + (row.$footer ? 1 : 0);
      options = p.changeItem(-1, indexBottom + j);
      row = options.item;
      adjust -= (row.$header ? 1 : 0) + (row.$footer ? 1 : 0);
      innerTailIndex -= adjust;
      decoration = row.$header;
      if (decoration) {
        p.reorderItem(decoration, innerTailIndex);
      }
      p.reorderItem(row, innerTailIndex);
      decoration = row.$footer;
      if (decoration) {
        p.reorderItem(decoration, innerTailIndex);
      }
    }
  }
  me.measureItems();
  me.positionItems(renderInfo.bottom, false, count);
}, rollUp:function(count) {
  this._doActivePartnerCheck();
  var me = this, dataItems = me.dataItems, renderInfo = me.renderInfo, indexTop = renderInfo.indexTop, headItem = dataItems[0], innerHeadStart = me.innerItems.indexOf(headItem), partners = me.getRenderPartners(), len = partners.length, decoration, innerHeadIndex, i, j, options, p, row;
  if (headItem.$header) {
    --innerHeadStart;
  }
  me.setTopRenderedIndex(indexTop - count);
  --indexTop;
  for (i = 0; i < len; ++i) {
    p = partners[i];
    dataItems = p.dataItems;
    innerHeadIndex = innerHeadStart;
    for (j = 0; j < count; j++) {
      row = dataItems.pop();
      dataItems.unshift(row);
      options = p.changeItem(0, indexTop - j);
      row = options.item;
      decoration = row.$footer;
      if (decoration) {
        p.reorderItem(decoration, innerHeadIndex);
      }
      p.reorderItem(row, innerHeadIndex);
      decoration = row.$header;
      if (decoration) {
        p.reorderItem(decoration, innerHeadIndex);
      }
    }
  }
  me.measureItems();
  me.positionItems(renderInfo.top, true, count);
}, setGaps:function(gaps) {
  var me = this;
  gaps = gaps || {};
  if (!Ext.Object.equals(me.gapMap, gaps)) {
    me.gapMap = gaps;
    me.gapAfter = me.gapMap[me.store.getCount()] || 0;
    me.syncRowsToHeight(true);
  }
}, setItemHiddenInfinite:function(item, hide) {
  if (!hide) {
    item.$hidden = false;
  } else {
    if (!item.$hidden) {
      item.$hidden = true;
      item.$position = null;
      item.translate(0, -10000);
    }
  }
}, setItemPosition:function(item, y) {
  if (item.$hidden) {
    this.setItemHidden(item, false);
  }
  if (item.$position !== y) {
    item.$position = y;
    item.translate(null, y);
  }
  return item.$height;
}, setupFooterPinning:function() {
  var me = this;
  return me.setupGroupPinning(me.getPinFooters(), me.pinnedFooter, me.hasPinnedFooterCls, 'setPinnedFooterHeight');
}, setupGroupPinning:function(pin, item, cls, setter) {
  var isPinning = pin && !!item;
  if (isPinning) {
    item.setScrollable({x:false, y:false});
  } else {
    this[setter](0);
  }
  this.el.toggleCls(cls, isPinning);
  return isPinning;
}, setupHeaderPinning:function() {
  var me = this;
  return me.setupGroupPinning(me.getPinHeaders(), me.pinnedHeader, me.hasPinnedHeaderCls, 'setPinnedHeaderHeight');
}, shouldHideDisclosure:function(record) {
  var name, show;
  if (this.getOnItemDisclosure()) {
    name = this.getDisclosureProperty();
    show = !name || record.data[name] !== false;
  }
  return !show;
}, stickItem:function(item, options) {
  var me = this, opt = item.$sticky, record = item.getRecord(), stickyCls = me.stickyCls, stickyItems = me.stickyItems, stickyItemsByRecordId = me.stickyItemsByRecordId, stickyPos;
  if (!me.infinite) {
    Ext.raise('Only infinite lists support sticky items');
  }
  if (options) {
    if (!opt) {
      stickyItems.push(item);
      stickyItemsByRecordId[record.internalId] = item;
      item.addCls(stickyCls);
      item.$sticky = opt = {pos:item.$position};
    }
    Ext.apply(opt, options);
    stickyPos = me.constrainStickyItem(item);
    if (stickyPos !== null) {
      me.setItemPosition(item, stickyPos);
    }
  } else {
    if (opt) {
      Ext.Array.remove(stickyItems, item);
      delete stickyItemsByRecordId[record.internalId];
      item.removeCls(stickyCls);
      item.$sticky = null;
      if (opt.autoPin && item.isDataViewPinnable) {
        item.setPinned(false);
      }
      if (opt.floated) {
        delete item.$position;
      }
      if (opt.dislodged) {
        me.removeDataItem(item);
      } else {
        me.setItemPosition(item, opt.pos);
      }
    }
  }
}, syncContentTop:function() {
  var me = this, renderInfo = me.renderInfo, visibleTop = me.getVisibleTop(), visibleHeight = me.getVisibleHeight(), bufferZone = me.getMinimumBufferDistance() * me.rowHeight, adjust;
  if (renderInfo.atEnd) {
    return;
  }
  adjust = visibleTop + visibleHeight - (renderInfo.bottom - bufferZone);
  if (adjust >= 0) {
    me.getScrollable().scrollBy(null, -adjust, false);
  }
}, syncGroupCollapse:function(group, collapsed) {
  this.store.refreshFromSource();
  this.fireEvent(collapsed ? 'groupcollapse' : 'groupexpand', this, group);
}, syncIndexBar:function() {
  var me = this, indexBar = me.getIndexBar(), store = me.store;
  if (indexBar) {
    indexBar.setHidden(me.getEmptyState() || !store || !store.getGrouper());
  }
}, syncPinnedFooter:function(visibleTop) {
  var me = this, dataItems = me.dataItems, len = dataItems.length, pinnedFooter = me.pinnedFooter, renderInfo = me.renderInfo, grouping = me.pinFooters && pinnedFooter && len && me.isGrouping(), hide = pinnedFooter, indexTop = renderInfo.indexTop, scrollDock = me.scrollDockedItems, bottom, footerIndices, footers, height, index, totalHeight, visibleBottomIndex, y, gap;
  visibleTop = visibleTop || me.getVisibleTop();
  if (grouping) {
    totalHeight = me.getScrollable().getSize().y;
    bottom = visibleTop + me.getVisibleHeight();
    hide = bottom <= me.renderInfo.top || bottom >= totalHeight - (scrollDock ? scrollDock.end.height : 0) - me.gapAfter;
    if (!hide) {
      visibleBottomIndex = me.bisectPosition(bottom - 1) + indexTop;
      footers = me.groupingInfo.footer;
      footerIndices = footers.indices;
      index = Ext.Number.binarySearch(footerIndices, visibleBottomIndex);
      pinnedFooter.setGroup(footers.map[footerIndices[index]]);
      if (visibleBottomIndex === footerIndices[index] && dataItems[visibleBottomIndex - indexTop].$y1 === bottom) {
        hide = true;
      } else {
        if (index) {
          index = footerIndices[index - 1];
          if (index < indexTop) {
            y = 0;
          } else {
            y = dataItems[index - indexTop].$y1;
            gap = me.gapMap[index + 1] || 0;
            if (gap) {
              if (!(hide = bottom - y < gap)) {
                y += gap;
              }
            }
          }
        } else {
          y = scrollDock ? scrollDock.start.height : 0;
        }
      }
      if (!hide) {
        height = me.measureItem(pinnedFooter);
        y = bottom - y;
        y = y < height ? height - y : 0;
        me.setItemPosition(pinnedFooter, y);
      }
    }
  }
  if (hide) {
    me.setItemHidden(pinnedFooter, true);
  } else {
    if (pinnedFooter) {
      me.syncPinnedHorz(pinnedFooter);
    }
  }
}, syncPinnedHeader:function(visibleTop) {
  var me = this, dataItems = me.dataItems, len = dataItems.length, pinnedHeader = me.pinnedHeader, renderInfo = me.renderInfo, grouping = me.pinHeaders && pinnedHeader && len && me.isGrouping(), hide = pinnedHeader, indexTop = renderInfo.indexTop, scrollDock = me.scrollDockedItems, headerIndices, headers, height, index, visibleTopIndex, y, headerIndex, gap, item;
  visibleTop = visibleTop || me.getVisibleTop() || 0;
  if (grouping) {
    hide = scrollDock && visibleTop <= scrollDock.start.height || (visibleTopIndex = me.bisectPosition(visibleTop)) < 0 || visibleTopIndex >= len;
    if (!hide) {
      visibleTopIndex += indexTop;
      headers = me.groupingInfo.header;
      headerIndices = headers.indices;
      index = Ext.Number.binarySearch(headerIndices, visibleTopIndex);
      if (headerIndices[index] !== visibleTopIndex) {
        --index;
      }
      headerIndex = headerIndices[index];
      pinnedHeader.setGroup(headers.map[headerIndex]);
      if (headerIndex >= indexTop) {
        item = dataItems[headerIndex - indexTop];
        gap = me.gapMap[headerIndex] || 0;
        if (gap) {
          hide = visibleTop - item.$y0 < gap;
        } else {
          hide = item.$y0 === visibleTop;
        }
      }
      if (!hide) {
        ++index;
        if (index < headerIndices.length) {
          index = headerIndices[index] - indexTop;
          y = index < len ? dataItems[index].$y0 - visibleTop : 0;
        } else {
          y = renderInfo.bottom - visibleTop;
          hide = y <= 0;
        }
        if (!hide) {
          height = me.measureItem(pinnedHeader);
          y = y && y < height ? y - height : 0;
          me.setItemPosition(pinnedHeader, y || 0);
        }
      }
    }
  }
  if (hide) {
    me.setItemHidden(pinnedHeader, true);
  } else {
    if (pinnedHeader) {
      me.syncPinnedHorz(pinnedHeader);
    }
  }
}, syncPinnedHorz:function(item) {
  var me = this, scroller = item.getScrollable();
  item.el.setWidth(me.getScrollable().getClientSize().x);
  if (item.isItemHeader && me.getHorizontalOverflow()) {
    item.setContentWidth(me.getInnerWidth());
  }
  if (me.getHorizontalOverflow() && me.getScrollable().isPrimary !== false) {
    scroller.scrollTo(me.getVisibleLeft(), null);
  }
}, syncRows:function(bottomUp) {
  var me = this, renderInfo = me.renderInfo, scrollDock = me.scrollDockedItems, partners = me.getRenderPartners(), i, position, indexTop, len, innerCt, maxHeight, contentHeight, height, partnerLen, j, p;
  if (!me.infinite) {
    me.syncItemRange();
    return;
  }
  if (!me.isActivePartner()) {
    return;
  }
  maxHeight = me.getMaxHeight();
  len = me.dataItems.length;
  indexTop = renderInfo.indexTop;
  partnerLen = partners.length;
  if (len) {
    if (bottomUp) {
      position = renderInfo.bottom;
    } else {
      position = renderInfo.top;
      if (!indexTop && scrollDock) {
        position = scrollDock.start.height;
      }
    }
    for (i = 0; i < partnerLen; ++i) {
      for (j = 0; j < len; ++j) {
        partners[i].changeItem(j, indexTop + j);
      }
    }
  }
  me.measureItems();
  me.positionItems(position, bottomUp, len);
  for (i = 0; i < partnerLen; ++i) {
    p = partners[i];
    if (p.pinnedHeader) {
      p.syncPinnedHeader();
    }
    if (p.pinnedFooter) {
      p.syncPinnedFooter();
    }
    if (p.stickyItems.length) {
      p.syncStickyItems();
    }
    if (maxHeight) {
      innerCt = p.innerCt;
      contentHeight = renderInfo.bottom + p.gapAfter;
      scrollDock = p.scrollDockedItems;
      if (scrollDock) {
        contentHeight += scrollDock.end.height;
      }
      height = innerCt.measure('h');
      height = p.el.measure('h') - height + p.el.getBorderWidth('tb');
      height = Math.min(maxHeight - height, contentHeight);
      p.setInnerCtHeight(height);
    }
  }
}, syncRowsToHeight:function(force) {
  var me = this, bufferZone = me.getBufferSize(), infinite = me.infinite, rowCountWas = me.getItemCount(), rowHeight = me.rowHeight || 24, firstTime = !me.heightSyncs++, renderInfo = me.renderInfo, oldIndexBottom = renderInfo && renderInfo.indexBottom, storeCount = me.store && me.store.getCount(), visibleHeight = me.getMaxHeight() || me.getVisibleHeight(), partners, indexTop, rowCount, i, len, p, active;
  if (!me.isActivePartner() || !rowCount && !me.store) {
    return;
  }
  if (infinite) {
    rowCount = Math.ceil(visibleHeight / rowHeight) + bufferZone;
    rowCount = Math.min(rowCount, storeCount);
  } else {
    rowCount = storeCount;
  }
  partners = me.getRenderPartners();
  len = partners.length;
  for (i = 0; i < len; ++i) {
    p = partners[i];
    active = p.isActivePartner();
    p.setItemCount(rowCount);
    if (firstTime && me.store.isVirtualStore || rowCountWas !== rowCount || storeCount < oldIndexBottom) {
      if (infinite && active) {
        indexTop = Math.min(storeCount - rowCount, renderInfo.indexTop);
        indexTop = Math.max(0, indexTop);
        if (indexTop === p.getTopRenderedIndex()) {
          p.updateTopRenderedIndex(indexTop);
        } else {
          p.setTopRenderedIndex(indexTop);
        }
      }
      if (!rowCountWas) {
        p.refreshGrouping();
      }
      force = force !== false;
      if (force && storeCount < oldIndexBottom && active) {
        renderInfo.top = renderInfo.indexTop * me.rowHeight;
      }
    }
  }
  if (force || firstTime) {
    me.syncRows();
  }
}, syncStickyItems:function() {
  var me = this, stickyItems = me.stickyItems, n = stickyItems.length, i, stickyItem, stickyPos;
  for (i = 0; i < n; ++i) {
    stickyPos = me.constrainStickyItem(stickyItem = stickyItems[i]);
    if (stickyPos !== null) {
      me.setItemPosition(stickyItem, stickyPos);
    }
  }
}, doSyncVerticalOverflow:function() {
  var scroller = this.getScrollable();
  this.setVerticalOverflow(scroller.getSize().y > scroller.getClientSize().y);
}, resetVisibleTop:function() {
  this.lastAdjustedPosition = this._visibleTop = null;
}, setItemHeight:function(item, height) {
  item.$height = height;
  if (item.$pinnedFooter) {
    this.setPinnedFooterHeight(height);
  } else {
    if (item.$pinnedHeader) {
      this.setPinnedHeaderHeight(height);
    }
  }
}, teleport:function(y) {
  var me = this, scrollSize = me.getScrollable().getSize(), renderInfo = me.renderInfo, rowCount = me.dataItems.length, storeCount = me.store.getCount(), indexMax = storeCount - rowCount, backOff = me.getBufferSize(), scrollDock = me.scrollDockedItems, nextTeleportTopIndex = me.nextTeleportTopIndex, bottomUp, indexTop;
  me._doActivePartnerCheck();
  if (nextTeleportTopIndex !== undefined) {
    indexTop = nextTeleportTopIndex;
  } else {
    indexTop = Math.floor(y / scrollSize.y * storeCount);
  }
  if (indexTop < indexMax) {
    backOff = Math.min(indexTop, backOff >>> 1);
    indexTop -= backOff;
    if (indexTop) {
      renderInfo.top = Math.max(0, y - me.rowHeight * backOff);
    } else {
      renderInfo.top = scrollDock ? scrollDock.start.height : 0;
    }
  } else {
    bottomUp = true;
    indexTop = indexMax;
    renderInfo.bottom = scrollSize.y - me.gapAfter;
    if (scrollDock) {
      renderInfo.bottom -= scrollDock.end.height;
    }
  }
  me.setTopRenderedIndex(indexTop);
  me.syncRows(bottomUp);
}, toggleHoverCls:function(on) {
  var me = this, target = me.mouseOverItem, cls = me.hoveredCls, partners = me.partners, len, i, item, rec;
  me.callParent([on]);
  if (partners && target) {
    rec = target.getRecord();
    for (i = 0, len = partners.length; i < len; ++i) {
      item = partners[i].itemFromRecord(rec);
      if (item) {
        item.toggleCls(cls, on);
      }
    }
  }
}, setItemSelection:function(records, selected) {
  var me = this, len, i, j, selectable, partnerLen, partners = me.partners || [];
  me.callParent([records, selected]);
  if (!me.isActivePartner()) {
    return;
  }
  for (i = 0, len = records.length; i < len; i++) {
    for (j = 0, partnerLen = partners.length; j < partnerLen; ++j) {
      selectable = partners[j].getSelectable();
      if (selected) {
        selectable.setSelectedRecord(records[i]);
      } else {
        selectable.deselect(records[i], true);
      }
    }
  }
}, syncItemRecord:function(options, tombstoneRec) {
  var me = this, ret, partners = this.partners || [], j, partnerLen, selectable, record = options.item.getRecord();
  ret = me.callParent([options, tombstoneRec]);
  for (j = 0, partnerLen = partners.length; j < partnerLen; ++j) {
    selectable = partners[j].getSelectable();
    if (selectable.isRowSelected(record)) {
      me.getSelectable().setSelectedRecord(record);
      break;
    }
  }
  return ret;
}, traverseItem:function(item, delta) {
  var me = this, dataItems = me.dataItems, renderInfo = me.renderInfo, next;
  if (item && me.infinite) {
    if (delta < 0) {
      if (item === dataItems[0] && !item.isFirst) {
        next = renderInfo.indexTop;
      }
    } else {
      if (item === dataItems[dataItems.length - 1] && !item.isLast) {
        next = renderInfo.indexBottom + 1;
      }
    }
  }
  return next ? next - 1 : this.callParent([item, delta]);
}, updateEmptyState:function(empty, was) {
  this.callParent([empty, was]);
  this.syncIndexBar();
}, updateHorizontalOverflow:function(overflow) {
  var scroller = this.getScrollable();
  if (this.manageHorizontalOverflow) {
    scroller.setX(overflow);
    if (!overflow) {
      scroller.scrollTo(0, null);
    }
  }
}, updateInnerCtHeight:function(height) {
  this.innerCt.setHeight(height);
}, updateInnerWidth:function(innerWidth) {
  var me = this, innerCt = me.innerCt, pinnedHeader = me.pinnedHeader, pinnedFooter = me.pinnedFooter, scrollWidth = 0, width;
  if (innerWidth == null) {
    innerCt.setStyle('width', '');
    me.setHorizontalOverflow(false);
  } else {
    innerCt.setStyle('width', innerWidth + 'px');
    width = me.getVisibleWidth();
    if (width != null) {
      if (me.getVerticalOverflow()) {
        scrollWidth = me.getScrollable().getScrollbarSize().width;
      }
      me.setHorizontalOverflow(width < innerWidth + scrollWidth);
    }
  }
  me.refreshScrollerSize();
  if (pinnedHeader) {
    me.syncPinnedHorz(pinnedHeader);
  }
  if (pinnedFooter) {
    me.syncPinnedHorz(pinnedFooter);
  }
}, updateItemCount:function(value, oldValue) {
  var me = this, renderInfo = me.infinite && me.renderInfo;
  me.callParent([value, oldValue]);
  if (!value && renderInfo) {
    renderInfo.atBegin = renderInfo.atEnd = true;
  }
}, updatePinnedFooterHeight:function(height) {
  var me = this;
  if (!me.destroyed && !me.destroying) {
    me.fireEvent('pinnedfooterheightchange', me, height);
  }
}, updatePinnedHeaderHeight:function(height) {
  var me = this;
  if (!me.destroyed && !me.destroying) {
    me.fireEvent('pinnedheaderheightchange', me, height);
  }
}, updateTopRenderedIndex:function(top) {
  var me = this, store = me.store, renderInfo = me.renderInfo, bottom = top + me.dataItems.length, total;
  if (!store.isLoaded() && !store.getAutoLoad()) {
    return;
  }
  renderInfo.atBegin = !top;
  renderInfo.atEnd = bottom === store.getCount();
  renderInfo.indexTop = top;
  renderInfo.indexBottom = bottom;
  if (top === bottom && store.isVirtualStore) {
    bottom = top + store.getPageSize();
    total = store.getTotalCount();
    if (total !== null) {
      bottom = Math.min(total, bottom);
    }
  }
  me.dataRange['goto'](top, bottom);
}, updateVerticalOverflow:function(overflow, oldOverflow) {
  var me = this, items = me.items.items, n = items.length, i, item, width;
  if (me.infinite) {
    width = me.getScrollable().getScrollbarSize().reservedWidth;
    for (i = 0; i < n; ++i) {
      item = items[i];
      if (item.isPinnedItem) {
        item.el.setStyle('width', width);
      }
    }
    me.syncPinnedHeader();
    me.syncPinnedFooter();
    if (oldOverflow != null && overflow !== oldOverflow) {
      me.updateVisibleWidth(me.bodyElement.getWidth());
    }
  }
  me.fireEvent('verticaloverflowchange', me, overflow);
}, updateVisibleHeight:function(height, oldHeight) {
  var me = this;
  if (me.infinite) {
    if (me.store) {
      me.syncRowsToHeight();
    }
  } else {
    me.syncVerticalOverflow();
  }
  me.fireEvent('visibleheightchange', me, height, oldHeight);
}, updateVisibleLeft:function() {
  var me = this;
  if (me.infinite && !me.suspendSync) {
    me.refreshPinnedAreas();
  }
}, updateVisibleTop:function(y, oldY) {
  var me = this, adjusted, len, i, p, partners;
  if (!me.isActivePartner()) {
    return;
  }
  if (me.infinite) {
    oldY = me.lastAdjustedPosition;
    adjusted = me.dataItems.length && (oldY == null || Math.abs(y - oldY) > me.rowHeight);
    if (adjusted) {
      me.lastAdjustedPosition = y;
      me.adjustRenderedRows(y, oldY);
    }
    partners = me.getRenderPartners();
    for (i = 0, len = partners.length; i < len; ++i) {
      p = partners[i];
      if (adjusted) {
        p.lastAdjustedPosition = y;
      }
      p.refreshPinnedAreas(y);
    }
  }
}, updateVisibleWidth:function(width) {
  var me = this, innerWidth = me.getInnerWidth(), scrollWidth = 0;
  if (innerWidth != null) {
    if (me.getVerticalOverflow()) {
      scrollWidth = me.getScrollable().getScrollbarSize().width;
    }
    me.setHorizontalOverflow(width < innerWidth + scrollWidth);
  }
}, refreshPinnedAreas:function(y) {
  var me = this;
  me.syncPinnedHeader(y);
  me.syncPinnedFooter(y);
  if (me.stickyItems.length) {
    me.syncStickyItems();
  }
}}}, function(List) {
  var proto = List.prototype, handlers = proto._itemChangeHandlers = proto._itemChangeHandlers.slice();
  handlers.unshift('changeItemStuck');
  handlers.push('changeItemGrouping');
});
Ext.define('Ext.theme.material.dataview.List', {override:'Ext.dataview.List', config:{rowLines:false}});
Ext.define('Ext.dataview.BoundListLocation', {extend:Ext.dataview.Location, next:function(options) {
  var me = this, candidate = me.nextItem(options), item = candidate && candidate.get();
  while (candidate && (!item || !candidate.record)) {
    if (candidate.equals(me)) {
      return;
    }
    candidate = candidate.nextItem(options);
    item = candidate && candidate.get();
  }
  return candidate;
}, previous:function(options) {
  var me = this, candidate = me.previousItem(options), item = candidate && candidate.get();
  while (candidate && (!item || !candidate.record)) {
    if (candidate.equals(me)) {
      return;
    }
    candidate = candidate.previousItem(options);
    item = candidate && candidate.get();
  }
  return candidate;
}});
Ext.define('Ext.dataview.BoundListNavigationModel', {extend:Ext.dataview.NavigationModel, alias:'navmodel.boundlist', config:{navigateOnSpace:true}, locationClass:'Ext.dataview.BoundListLocation', privates:{getKeyNavCfg:function(view) {
  var me = this, eventEl;
  if (me.keyboard !== false) {
    eventEl = (view.ownerField || view).getFocusEl();
    if (eventEl) {
      return {target:eventEl, eventName:'keydown', defaultEventAction:'stopEvent', esc:me.onKeyEsc, up:me.onKeyUp, down:me.onKeyDown, right:me.onKeyRight, left:me.onKeyLeft, pageDown:me.onKeyPageDown, pageUp:me.onKeyPageUp, home:me.onKeyHome, end:me.onKeyEnd, tab:me.onKeyTab, space:me.onKeySpace, enter:me.onKeyEnter, A:{ctrl:true, handler:me.onSelectAllKeyPress}, priority:1001, scope:me};
    }
  }
}, getViewListeners:function(view) {
  var result = this.callParent([view]);
  result.childtouchstart = 'onChildTouchStart';
  result.childTap = 'onChildTap';
  return result;
}, doFocus:Ext.privateFn, handleLocationChange:function(location, options) {
  var target = location.sourceElement, ownerField = this.getView().ownerField;
  if (target && ownerField) {
    ownerField.inputElement.dom.setAttribute('aria-activedescendant', target.id);
  }
  this.callParent([location, options]);
}, onChildTouchStart:function(view, location) {
  var e = location.event;
  if (e.pointerType !== 'touch') {
    e.preventDefault();
  }
}, onChildTap:function(view, location) {
  var me = this, e = location.event, newLocation;
  if (!view.destroyed) {
    if (e.pointerType === 'touch') {
      e.preventDefault();
    }
    newLocation = me.createLocation(location.item);
    if (me.location && me.location.equals(newLocation)) {
      me.onNavigate(e);
    } else {
      me.setLocation(newLocation, {event:location.event, animation:true});
    }
  }
  if (e.pointerType === 'touch') {
    e.stopEvent();
  }
}, onChildTrigger:Ext.privateFn, onKeyLeft:function() {
  return true;
}, onKeyRight:function() {
  return true;
}, onKeySpace:function(e) {
  if (this.getNavigateOnSpace()) {
    e.preventDefault();
    this.onNavigate(e);
  }
  return true;
}, onKeyEsc:function() {
  var view = this.getView(), field = view.ownerField;
  if (field && view.isVisible()) {
    field.collapse();
  } else {
    return true;
  }
}, onKeyTab:function(e) {
  var view = this.getView(), field = view.ownerField;
  if (view.isVisible()) {
    if (field.getSelectOnTab()) {
      this.selectHighlighted(e);
    }
    if (field.collapse) {
      field.collapse();
    }
  }
  return true;
}, onKeyEnter:function(e) {
  var view = this.getView(), selectable = view.getSelectable(), field = view.ownerField;
  e.stopEvent();
  if (!(field.getMultiSelect && field.getMultiSelect()) && selectable.isSelected(this.location.record) && field.collapse) {
    field.collapse();
  } else {
    this.selectHighlighted(e);
  }
  e.fromBoundList = true;
  field.fireEvent('specialkey', field, e);
  return false;
}, onNavigate:function(event) {
  var doNavigate = event && (event.pointerType || this.getNavigateOnSpace() && event.keyCode === event.SPACE), view = this.getView(), field = view.getRefOwner();
  if (doNavigate) {
    this.callParent([event]);
    if (field && field.maybeCollapse) {
      field.maybeCollapse(event);
    }
  }
}, selectHighlighted:function(e) {
  var me = this, view = me.getView(), store = view.getStore(), selectable = view.getSelectable(), location = me.location, highlightedRec, index;
  if (location && view.getViewItems().length) {
    highlightedRec = location.record;
    if (highlightedRec) {
      if (e.getKey() === e.ENTER || !selectable.isSelected(highlightedRec)) {
        selectable.selectWithEvent(highlightedRec, e);
        if (!view.getStore().contains(highlightedRec)) {
          index = Math.min(location.recordIndex, store.getCount() - 1);
          me.setLocation(store.getAt(index));
        }
      }
    }
  }
}}});
Ext.define('Ext.dataview.BoundList', {extend:Ext.dataview.List, xtype:'boundlist', tabIndex:null, focusEl:null, focusable:false, itemsFocusable:false, navigationModel:{type:'boundlist'}, itemConfig:{cls:Ext.baseCSSPrefix + 'boundlistitem', tools:{selected:{zone:'start', passive:true, cls:Ext.baseCSSPrefix + 'selected-icon', iconCls:Ext.baseCSSPrefix + 'fa fa-check'}}}, onFocusEnter:Ext.emptyFn, onFocusLeave:Ext.emptyFn, afterShow:function() {
  this.callParent();
  this.getNavigationModel().enable();
}, afterHide:function(me) {
  var navModel = me.getNavigationModel();
  me.callParent([me]);
  navModel.setLocation(null);
  navModel.disable();
}, privates:{beforeSelectionRefresh:function(toDeselect, toReselect) {
  var len = toDeselect.length, i, rec;
  for (i = 0; i < len;) {
    rec = toDeselect[i];
    if (rec.isEntered) {
      toDeselect.splice(i, 1);
      len--;
    } else {
      i++;
    }
  }
}}});
Ext.define('Ext.dataview.DataView', {extend:Ext.dataview.Abstract, alternateClassName:'Ext.DataView', xtype:'dataview', isElementDataView:true, constructor:function(config) {
  if (config && config.useComponents) {
    if (this.self !== Ext.dataview.DataView) {
      Ext.raise('The useComponents config has been replaced by Ext.dataview.Component');
    }
    Ext.log.warn('The useComponents config has been replaced by Ext.dataview.Component');
    return new Ext.dataview['Component'](config);
  }
  if (this.useComponents) {
    Ext.raise('The useComponents config has been replaced by Ext.dataview.Component');
  }
  this.callParent([config]);
}, getViewItems:function() {
  return Array.prototype.slice.call(this.getFastItems());
}, onStoreAdd:function(store, records, index) {
  this.callParent(arguments);
  this.renderItems(index, index + records.length);
}, onStoreRemove:function(store, records, index) {
  this.removeItems(index, index + records.length);
}, getItemClass:function(data) {
  return this.getItemCls();
}, privates:{dirtyCls:Ext.baseCSSPrefix + 'dirty', changeItem:function(recordIndex) {
  var me = this, dataItems = me.dataItems, item = dataItems[recordIndex], record = me.dataRange.records[recordIndex], storeCount = me.store.getCount(), options = {isFirst:!recordIndex, isLast:recordIndex === storeCount - 1, item:item, record:record, recordIndex:recordIndex};
  me.syncItemRecord(options);
}, clearItems:function() {
  var elements = this.dataItems, dom;
  while (elements.length) {
    dom = elements.pop();
    Ext.fly(dom).destroy();
  }
}, createDataItem:function(index, record) {
  var me = this, store = me.store, data = me.gatherData(record, index), markDirty = me.getMarkDirty(), dom, itemEl;
  itemEl = Ext.Element.create(me.getItemElementConfig(index, data, store));
  dom = itemEl.dom;
  if (markDirty) {
    itemEl.addCls(me.markDirtyCls);
  }
  dom.setAttribute('data-viewid', me.id);
  dom.setAttribute('data-recordid', record.internalId);
  dom.setAttribute('data-recordindex', index);
  return itemEl;
}, doClear:function() {
  this.clearItems();
  this.callParent();
}, resetSelection:function(records) {
  this.setItemSelection(records, false);
}, doRefresh:function(scrollToTop) {
  var me = this, records = me.dataRange.records, storeCount = records.length, itemCount = me.dataItems.length, scroller = me.getScrollable(), restoreFocus, i;
  if (scroller && scrollToTop) {
    scroller.scrollTo(0, 0);
  }
  ++me.refreshCounter;
  if (!storeCount) {
    me.doClear();
  } else {
    restoreFocus = me.saveFocusState();
    me.hideEmptyText();
    me.resetSelection(records);
    if (itemCount > storeCount) {
      me.removeItems(storeCount, itemCount);
      itemCount = storeCount;
    } else {
      if (itemCount < storeCount) {
        me.renderItems(itemCount, storeCount);
      }
    }
    for (i = 0; i < itemCount; ++i) {
      me.changeItem(i);
    }
    if (me.hasSelection()) {
      me.setItemSelection(me.getSelections(), true);
    }
    restoreFocus();
  }
}, getFastItems:function() {
  return this.getRenderTarget().dom.childNodes;
}, getItemElementConfig:function(index, data, store) {
  var me = this, result = {cls:me.baseCls + '-item ' + (me.getItemClass(data) || ''), html:me.renderItemTpl(index, data, store)};
  if (me.getItemsFocusable()) {
    result.tabIndex = -1;
  }
  return result;
}, removeItems:function(from, to) {
  var me = this, items = me.dataItems.splice(from, to - from), i;
  for (i = 0; i < items.length; ++i) {
    Ext.fly(items[i]).destroy();
  }
}, renderItems:function(from, to) {
  var me = this, dataItems = me.dataItems, records = me.dataRange.records, parentNode = me.getRenderTarget().dom, args = [from, 0], before = me.dataItems[from] || null, dom, i;
  if (records.length) {
    me.hideEmptyText();
  }
  if (!before) {
    before = me.findTailItem(true);
    before = before && before.el.dom;
  }
  for (i = from; i < to; ++i) {
    args.push(dom = me.createDataItem(i, records[i]).dom);
    parentNode.insertBefore(dom, before);
  }
  dataItems.splice.apply(dataItems, args);
}, renderItemTpl:function(index, data, store) {
  var itemTpl = this.getItemTpl(), parent = store.getData().items, value;
  data.xcount = typeof data.xcount === 'number' ? data.xcount : store.getCount();
  data.xindex = typeof data.xindex === 'number' ? data.xindex : index;
  value = itemTpl.apply(data, parent, index + 1, parent.length);
  value = value == null ? '' : String(value);
  return value || this.getEmptyItemText();
}, syncItemRecord:function(options) {
  var me = this, item = options.item, itemFly = Ext.fly(item), record = options.record, store = me.store, recordIndex = options ? options.recordIndex : store.indexOf(record), data = me.gatherData(record, recordIndex);
  item.innerHTML = me.renderItemTpl(recordIndex, data, store);
  item.setAttribute('data-recordid', record.internalId);
  item.setAttribute('data-recordindex', recordIndex);
  itemFly.toggleCls(me.dirtyCls, record.dirty);
  itemFly.toggleCls(me.selectedCls, me.getSelectable().isRowSelected(record));
}, traverseItem:function(item, delta) {
  var me = this, items = me.getRenderTarget().dom.childNodes, next = null, dom, i;
  if (item) {
    if (item.isElement) {
      dom = item.dom;
    } else {
      if (item.isWidget) {
        dom = item.el.dom;
      }
    }
    i = Array.prototype.indexOf.call(items, dom);
    if (i > -1) {
      next = items[i + delta] || null;
      if (next) {
        next = Ext.getCmp(next.id) || next;
      }
    }
  }
  return next;
}}});
Ext.define('Ext.dataview.ChipView', {extend:Ext.dataview.DataView, xtype:'chipview', classCls:Ext.baseCSSPrefix + 'chipview', hasIconCls:Ext.baseCSSPrefix + 'has-icon', closableCls:Ext.baseCSSPrefix + 'closable', iconElCls:Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon', itemTpl:'\x3cdiv class\x3d"' + Ext.baseCSSPrefix + 'body-el"\x3e' + '\x3cdiv class\x3d"{_chipIconCls}" style\x3d"{_chipIconStyle}"\x3e\x3c/div\x3e' + '\x3cdiv class\x3d"' + Ext.baseCSSPrefix + 'text-el"\x3e' + '{_chipText}' + 
'\x3c/div\x3e' + '\x3cdiv class\x3d"' + Ext.baseCSSPrefix + 'close-el ' + Ext.baseCSSPrefix + 'font-icon"\x3e\x3c/div\x3e' + '\x3c/div\x3e', config:{iconField:null, iconClsField:null, displayField:'text', closableField:null, closable:true, closeHandler:null, scope:null, itemUi:null, displayTpl:null}, listeners:{childtap:'onChipTap', scope:'this', priority:3000}, getItemClass:function(values) {
  var me = this, result = [me.callParent([values])], chipCls = Ext.Chip.prototype.getClassCls(), chipClsLen = chipCls.length, uis = me.getItemUi(), uiLen = uis && uis.length, i, j, c;
  for (i = 0; i < chipClsLen; i++) {
    c = chipCls[i];
    result.push(c);
    for (j = 0; j < uiLen; j++) {
      result.push(c + '-' + uis[j]);
    }
  }
  if (me.hasIcon(values)) {
    result.push(me.hasIconCls);
  }
  if (me.getChipClosable(values)) {
    result.push(me.closableCls);
  }
  return result.join(' ');
}, onChipTap:function(chip, location) {
  var me = this, handler = me.getCloseHandler();
  if (handler && location.event.getTarget('.' + Ext.baseCSSPrefix + 'close-el')) {
    return Ext.callback(handler, me.getScope(), [me, location], 0, me);
  }
}, prepareData:function(data, index, record) {
  var me = this, tpl = me.getDisplayTpl();
  data._chipIconCls = me.getChipIconCls(data);
  data._chipIconStyle = me.getChipIconStyle(data);
  data._chipText = tpl ? tpl.apply(data) : data[me.getDisplayField()];
  return data;
}, privates:{applyItemUi:function(value) {
  return typeof value === 'string' ? value.split(' ') : Ext.Array.from(value);
}, updateItemUi:function() {
  this.doRefresh();
}, applyDisplayTpl:function(config) {
  return Ext.XTemplate.get(config);
}, updateDisplayTpl:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, getChipIconUrl:function(values) {
  return Ext.resolveResource(values[this.getIconField()]);
}, getChipIconStyle:function(values) {
  var iconUrl = this.getChipIconUrl(values);
  return iconUrl ? 'background-image: url(' + iconUrl + ')' : '';
}, hasIcon:function(values) {
  var iconClsField = this.getIconClsField();
  return this.getChipIconUrl(values) ? true : iconClsField ? !!values[iconClsField] : false;
}, getChipIconCls:function(values) {
  var iconClsField = this.getIconClsField(), iconCls = iconClsField ? values[iconClsField] : '';
  return this.iconElCls + ' ' + iconCls;
}, getChipClosable:function(values) {
  var closableField = this.getClosableField();
  return closableField ? !!values[closableField] : this.getClosable();
}, _onChildEvent:function(fn, e) {
  if (!this.ownerField || e.target !== this.ownerField.inputElement.dom) {
    return this.callParent([fn, e]);
  }
  return {};
}, syncEmptyState:function() {
  var field = this.ownerField;
  if (field) {
    field.syncEmptyState();
    field.syncLabelPlaceholder(false);
  }
}, syncItemRecord:function(options) {
  var me = this, record = options.record, recordIndex = options ? options.recordIndex : me.store.indexOf(record), data = me.gatherData(record, recordIndex);
  options.item.className = me.getItemClass(data);
  me.callParent([options]);
}}});
Ext.define('Ext.dataview.IndexBar', {extend:Ext.Component, alternateClassName:'Ext.IndexBar', xtype:'indexbar', cachedConfig:{letters:'ABCDEFGHIJKLMNOPQRSTUVWXYZ'}, config:{animation:true, autoHide:false, dynamic:false, listPrefix:null, indicator:true}, eventedConfig:{direction:'vertical'}, top:0, bottom:0, left:0, right:0, inheritUi:true, autoHideCls:Ext.baseCSSPrefix + 'autohide', classCls:Ext.baseCSSPrefix + 'indexbar', horizontalCls:Ext.baseCSSPrefix + 'horizontal', indexedCls:Ext.baseCSSPrefix + 
'indexed', indexedHorizontalCls:Ext.baseCSSPrefix + 'indexed-horizontal', indexedVerticalCls:Ext.baseCSSPrefix + 'indexed-vertical', indexedNoAutoHideCls:Ext.baseCSSPrefix + 'indexed-no-autohide', indicatorCls:Ext.baseCSSPrefix + 'indexbar-indicator', pressedCls:Ext.baseCSSPrefix + 'pressed', verticalCls:Ext.baseCSSPrefix + 'vertical', element:{reference:'element', cls:Ext.baseCSSPrefix + 'unselectable', children:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el'}]}, initialize:function() {
  var me = this, bodyElement = me.bodyElement;
  me.callParent();
  bodyElement.addClsOnClick(me.pressedCls);
  bodyElement.on({tap:'onTap', touchstart:'onTouchStart', touchend:'onTouchEnd', mouseover:'onMouseOver', mouseout:'onMouseOut', drag:'onDrag', dragEnd:'onDragEnd', scope:me});
}, getVertical:function() {
  return this.getDirection() === 'vertical';
}, setVertical:function(vertical) {
  return this.setDirection(vertical ? 'vertical' : 'horizontal');
}, onAdded:function(parent, instanced) {
  var me = this;
  parent.el.addCls(me.indexedCls);
  me.parentListeners = parent.on({pinnedfooterheightchange:'onPinnedFooterHeightChange', pinnedheaderheightchange:'onPinnedHeaderHeightChange', verticaloverflowchange:'onVerticalOverflowChange', destroyable:true, scope:me});
  me.callParent([parent, instanced]);
}, onRemoved:function(destroying) {
  var me = this, parent = me.parent;
  Ext.destroy(me.parentListeners);
  if (parent && !parent.destroying && !parent.destroyed) {
    parent.el.removeCls(me.indexedCls);
  }
  me.callParent([destroying]);
}, privates:{parentListeners:null, onDrag:function(e) {
  this.trackMove(e, false);
}, onDragEnd:function(e) {
  var me = this, indicator = me.getIndicator();
  me.trackMove(e, true);
  if (indicator && me.indicator) {
    me.indicator.hide();
  }
}, onMouseOver:function() {
  var me = this;
  me.$isMouseOver = true;
  if (me.shouldAutoHide('over')) {
    me.bodyElement.show();
  }
}, onMouseOut:function() {
  var me = this;
  me.$isMouseOver = false;
  if (me.shouldAutoHide('out')) {
    me.bodyElement.hide();
  }
}, onPinnedFooterHeightChange:function(list, height) {
  this.setBottom(height);
}, onPinnedHeaderHeightChange:function(list, height) {
  this.setTop(height);
}, onTap:function(e) {
  e.stopPropagation();
}, onTouchStart:function(e) {
  var me = this;
  me.$isPressing = true;
  me.pageBox = me.bodyElement.getBox();
  me.onDrag(e);
  if (me.shouldAutoHide('press')) {
    me.bodyElement.show();
  }
}, onTouchEnd:function(e) {
  var me = this;
  me.$isPressing = false;
  if (me.shouldAutoHide('release')) {
    me.bodyElement.hide();
  }
  me.onDragEnd(e);
}, onVerticalOverflowChange:function(list) {
  this.setRight(list.getScrollable().getScrollbarSize().width);
}, scrollToClosestByIndex:function(index) {
  var me = this, list = me.parent, key = index.toLowerCase(), store = list.getStore(), groups = store.getGroups(), ln = groups.length, group, groupKey, i, closest, item, record;
  for (i = 0; i < ln; i++) {
    group = groups.getAt(i);
    groupKey = group.getGroupKey().toLowerCase();
    if (groupKey >= key) {
      closest = group;
      break;
    }
    closest = group;
  }
  if (closest) {
    record = closest.first();
    if (!list.getInfinite()) {
      item = list.itemFromRecord(record).$header;
    }
    list.ensureVisible(record, {animation:me.getAnimation(), item:item, align:{y:'start'}});
  }
}, shouldAutoHide:function(trigger) {
  var me = this, autoHide = me.getAutoHide(), ret = false;
  if (autoHide) {
    if (autoHide === 'pressed' || !Ext.os.is.Desktop) {
      ret = trigger === 'press' || trigger === 'release';
    } else {
      ret = trigger === 'over' || trigger === 'release' && !me.$isMouseOver || trigger === 'out' && !me.$isPressing;
    }
  }
  return ret;
}, syncIndicatorPosition:function(point, target, isValidTarget) {
  var me = this, isUsingIndicator = me.getIndicator(), direction = me.getDirection(), renderElement = me.renderElement, bodyElement = me.bodyElement, indicator = me.indicator, indicatorInner = me.indicatorInner, first = bodyElement.getFirstChild(), last = bodyElement.getLastChild(), indexbarWidth, indexbarHeight, indicatorSpacing, firstPosition, lastPosition, indicatorSize;
  if (isUsingIndicator && indicator) {
    indicator.show();
    if (direction === 'vertical') {
      indicatorSize = indicator.getHeight();
      indexbarWidth = bodyElement.getWidth();
      indicatorSpacing = bodyElement.getMargin('lr');
      firstPosition = first.getY();
      lastPosition = last.getY();
      if (point.y < firstPosition) {
        target = first;
      } else {
        if (point.y > lastPosition) {
          target = last;
        }
      }
      if (isValidTarget) {
        indicatorInner.setHtml(target.getHtml().toUpperCase());
      }
      indicator.setTop(target.getY() - renderElement.getY() - indicatorSize / 2 + target.getHeight() / 2);
      indicator.setRight(indicatorSpacing + indexbarWidth);
    } else {
      indicatorSize = indicator.getWidth();
      indicatorSpacing = bodyElement.getMargin('tb');
      indexbarHeight = bodyElement.getHeight();
      firstPosition = first.getX();
      lastPosition = last.getX();
      if (point.x < firstPosition) {
        target = first;
      } else {
        if (point.x > lastPosition) {
          target = last;
        }
      }
      indicator.setLeft(target.getX() - renderElement.getX() - indicatorSize / 2 + target.getWidth() / 2);
      indicator.setBottom(indicatorSpacing + indexbarHeight);
    }
    indicatorInner.setHtml(target.getHtml().toUpperCase());
  }
}, trackMove:function(event, drop) {
  var me = this, el = me.bodyElement, pageBox = me.pageBox || (me.pageBox = me.el.getBox()), point = Ext.util.Point.fromEvent(event), target, isValidTarget;
  if (me.getDirection() === 'vertical') {
    if (point.y > pageBox.bottom || point.y < pageBox.top) {
      return;
    }
    target = Ext.Element.fromPoint(pageBox.left + pageBox.width / 2, point.y);
    isValidTarget = target && target.getParent() === el;
  } else {
    if (point.x > pageBox.right || point.x < pageBox.left) {
      return;
    }
    target = Ext.Element.fromPoint(point.x, pageBox.top + pageBox.height / 2);
    isValidTarget = target && target.getParent() === el;
  }
  if (target && isValidTarget) {
    if (me.getIndicator()) {
      me.syncIndicatorPosition(point, target, isValidTarget);
    }
    if (drop || me.getDynamic()) {
      me.scrollToClosestByIndex(target.dom.innerHTML);
    }
  }
}, updateAutoHide:function(autoHide) {
  var me = this, parentEl = me.parent.el, autoHideCls = me.autoHideCls, indexedNoAutoHideCls = me.indexedNoAutoHideCls;
  me.bodyElement.setVisibilityMode(Ext.Element.OPACITY);
  if (autoHide) {
    me.addCls(autoHideCls);
    me.bodyElement.hide();
    parentEl.removeCls(indexedNoAutoHideCls);
  } else {
    me.removeCls(autoHideCls);
    me.bodyElement.show();
    parentEl.addCls(indexedNoAutoHideCls);
  }
}, updateDirection:function(direction) {
  var me = this, verticalCls = me.verticalCls, horizontalCls = me.horizontalCls, indexedVerticalCls = me.indexedVerticalCls, indexedHorizontalCls = me.indexedHorizontalCls, oldCls, newCls, oldIndexedCls, newIndexedCls;
  if (direction === 'vertical') {
    oldCls = horizontalCls;
    newCls = verticalCls;
    oldIndexedCls = indexedHorizontalCls;
    newIndexedCls = indexedVerticalCls;
  } else {
    oldCls = verticalCls;
    newCls = horizontalCls;
    oldIndexedCls = indexedVerticalCls;
    newIndexedCls = indexedHorizontalCls;
  }
  me.element.replaceCls(oldCls, newCls);
  me.bodyElement.replaceCls(oldCls, newCls);
  me.parent.element.replaceCls(oldIndexedCls, newIndexedCls);
}, updateIndicator:function(indicator) {
  var me = this, config = {cls:me.indicatorCls};
  if (indicator && indicator !== true) {
    config = Ext.apply(config, indicator);
  }
  if (indicator) {
    me.indicator = me.el.appendChild(config);
    me.indicatorInner = me.indicator.appendChild({cls:me.indicatorCls + '-inner'});
    me.indicator.hide(false);
  } else {
    if (me.indicator) {
      me.indicator.destroy();
      me.indicatorInner.destroy();
      me.indicator = me.indicatorInner = null;
    }
  }
}, updateLetters:function(letters) {
  var bodyElement = this.bodyElement, len = letters.length, i;
  bodyElement.setHtml('');
  if (letters) {
    for (i = 0; i < len; i++) {
      bodyElement.createChild({cls:Ext.baseCSSPrefix + 'indexbar-item', html:letters[i]});
    }
  }
}, updateListPrefix:function(listPrefix) {
  if (listPrefix && listPrefix.length) {
    this.bodyElement.createChild({html:listPrefix}, 0);
  }
}, updateUi:function(ui, oldUi) {
  var me = this, list = me.parent, listElement = list.element, indexedCls = me.indexedCls;
  if (oldUi) {
    listElement.removeCls(oldUi, indexedCls);
  }
  if (ui) {
    listElement.addCls(ui, indexedCls);
  }
  me.callParent([ui, oldUi]);
}}});
Ext.define('Ext.theme.material.dataview.IndexBar', {override:'Ext.dataview.IndexBar', config:{autoHide:true, letters:['*', '#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']}});
Ext.define('Ext.layout.HBox', {extend:Ext.layout.Box, alias:'layout.hbox', config:{vertical:false}});
Ext.define('Ext.dataview.NestedList', {alternateClassName:'Ext.NestedList', extend:Ext.Container, xtype:'nestedlist', config:{backText:'Back', useTitleAsBackText:true, updateTitleText:true, displayField:'text', loadingText:'Loading...', emptyText:'No items available.', onItemDisclosure:false, allowDeselect:false, useToolbar:null, toolbar:{docked:'top', xtype:'titlebar', ui:'light', inline:true}, title:'', layout:{type:'card', animation:{type:'slide', duration:250, direction:'left'}}, store:null, 
detailContainer:undefined, detailCard:null, backButton:{hidden:true}, listConfig:null, variableHeights:false, lastNode:null, lastActiveList:null, ui:null, clearSelectionOnListChange:true}, baseCls:Ext.baseCSSPrefix + 'nested-list', listMode:'title', constructor:function(config) {
  if (Ext.isObject(config)) {
    if (config.getTitleTextTpl) {
      this.getTitleTextTpl = config.getTitleTextTpl;
    }
    if (config.getItemTextTpl) {
      this.getItemTextTpl = config.getItemTextTpl;
    }
  }
  this.callParent([config]);
}, changeListMode:function(node) {
  var me = this, store = me.getStore(), rootNode = store && store.getRoot();
  if (node === rootNode) {
    me.listMode = 'title';
  } else {
    if (node.parentNode === rootNode) {
      me.listMode = 'node';
    } else {
      me.listMode = 'deep';
    }
  }
}, onChildInteraction:function() {
  if (this.isGoingTo) {
    return false;
  }
}, applyDetailContainer:function(config) {
  if (!config) {
    config = this;
  }
  return config;
}, updateDetailContainer:function(newContainer, oldContainer) {
  if (newContainer) {
    newContainer.on('beforeactiveitemchange', 'onBeforeDetailContainerChange', this);
    newContainer.on('activeitemchange', 'onDetailContainerChange', this);
  }
}, onBeforeDetailContainerChange:function() {
  this.isGoingTo = true;
}, onDetailContainerChange:function() {
  this.isGoingTo = false;
}, onChildTap:function(list, location) {
  var me = this, hasListeners = me.hasListeners, record = location.record;
  if (me.onChildInteraction(list, location) === false) {
    return false;
  }
  if (hasListeners.childtap) {
    location.list = list;
    me.fireEvent('childtap', me, location);
  }
  if (hasListeners.itemtap) {
    me.fireEvent('itemtap', me, list, location.viewIndex, location.child, record, location.event);
  }
  if (record.isLeaf()) {
    if (hasListeners.leafchildtap) {
      location.list = list;
      me.fireEvent('leafchildtap', me, location);
    }
    if (hasListeners.leafitemtap) {
      me.fireEvent('leafitemtap', me, list, location.viewIndex, location.child, record, location.event);
    }
    me.goToLeaf(record);
  } else {
    this.goToNode(record);
  }
}, onBeforeSelect:function() {
  this.fireEvent.apply(this, [].concat('beforeselect', this, Array.prototype.slice.call(arguments)));
}, onContainerTap:function() {
  this.fireEvent.apply(this, [].concat('containertap', this, Array.prototype.slice.call(arguments)));
}, onSelect:function() {
  var args = Array.prototype.slice.call(arguments);
  this.fireEvent.apply(this, [].concat('select', this, args));
  this.onSelectionChange(args);
}, onDeselect:function() {
  var args = Array.prototype.slice.call(arguments);
  this.fireEvent.apply(this, [].concat('deselect', this, args));
  this.onSelectionChange(args);
}, onSelectionChange:function(args) {
  this.fireEvent.apply(this, [].concat('selectionchange', this, args));
}, onChildDoubleTap:function(list, location) {
  var me = this, hasListeners = me.hasListeners;
  if (hasListeners.childdoubletap) {
    location.list = list;
    me.fireEvent('childdoubletap', me, location);
  }
  if (hasListeners.itemdoubletap) {
    me.fireEvent('itemdoubletap', me, list, location.viewIndex, location.child, location.record, location.event);
  }
}, onStoreBeforeLoad:function() {
  var loadingText = this.getLoadingText();
  if (loadingText) {
    this.setMasked({xtype:'loadmask', message:loadingText});
  }
  this.fireEvent.apply(this, [].concat('beforeload', this, Array.prototype.slice.call(arguments)));
}, onStoreLoad:function(store, records, successful, operation, parentNode) {
  this.setMasked(false);
  this.fireEvent.apply(this, [].concat('load', this, Array.prototype.slice.call(arguments)));
  if (store.indexOf(this.getLastNode()) === -1) {
    this.goToNode(store.getRoot());
  }
}, onBackTap:function() {
  var me = this, node = me.getLastNode(), detailCard = me.getDetailCard(), detailCardActive = detailCard && me.getActiveItem() === detailCard, layout = me.getLayout(), animation = layout ? layout.getAnimation() : null, lastActiveList = me.getLastActiveList();
  if (!animation || !(animation && animation.isAnimating)) {
    this.fireAction('back', [this, node, lastActiveList, detailCardActive], 'doBack', null, null, 'after');
  }
}, doBack:function(me, node, lastActiveList, detailCardActive) {
  var layout = me.getLayout(), animation = layout ? layout.getAnimation() : null;
  if (detailCardActive && lastActiveList) {
    if (animation) {
      animation.setReverse(true);
    }
    me.setActiveItem(lastActiveList);
    me.setLastNode(node.parentNode);
    me.syncToolbar();
  } else {
    me.goToNode(node.parentNode);
  }
}, updateData:function(data) {
  if (!this.getStore()) {
    this.setStore(new Ext.data.TreeStore({root:data}));
  }
}, applyStore:function(store) {
  if (store) {
    if (Ext.isString(store)) {
      store = Ext.data.StoreManager.get(store);
    } else {
      if (!(store instanceof Ext.data.TreeStore)) {
        store = Ext.factory(store, Ext.data.TreeStore, null);
      }
    }
    if (!store) {
      Ext.Logger.warn('The specified Store cannot be found', this);
    }
  }
  return store;
}, storeListeners:{rootchange:'onStoreRootChange', load:'onStoreLoad', beforeload:'onStoreBeforeLoad'}, updateStore:function(newStore, oldStore) {
  var me = this, listeners = this.storeListeners;
  listeners.scope = me;
  if (oldStore && Ext.isObject(oldStore) && oldStore.isStore) {
    if (oldStore.autoDestroy) {
      oldStore.destroy();
    }
    oldStore.un(listeners);
  }
  if (newStore) {
    newStore.on(listeners);
    me.goToNode(newStore.getRoot());
  }
}, onStoreRootChange:function(store, node) {
  this.goToNode(node);
}, applyDetailCard:function(detailCard, oldDetailCard) {
  return Ext.factory(detailCard, Ext.Component, detailCard === null ? oldDetailCard : undefined);
}, applyBackButton:function(config) {
  var toolbar = this.getToolbar();
  return !toolbar ? false : Ext.factory(config, Ext.Button, this.getBackButton());
}, updateBackButton:function(newButton, oldButton) {
  var me = this;
  if (newButton) {
    newButton.on('tap', me.onBackTap, me);
    newButton.setText(me.getBackText());
    if (me.$backButtonContainer) {
      me.$backButtonContainer.insert(0, newButton);
    } else {
      me.getToolbar().insert(0, newButton);
    }
  } else {
    if (oldButton) {
      oldButton.destroy();
    }
  }
}, applyToolbar:function(config) {
  var containerConfig;
  if (config && config.splitNavigation) {
    Ext.apply(config, {docked:'top', xtype:'titlebar', ui:'light'});
    containerConfig = config.splitNavigation === true ? {} : config.splitNavigation;
    this.$backButtonContainer = this.add(Ext.apply({xtype:'toolbar', docked:'bottom', hidden:true, ui:'dark'}, containerConfig));
  }
  return Ext.factory(config, Ext.TitleBar, this.getToolbar());
}, updateToolbar:function(newToolbar, oldToolbar) {
  var me = this;
  if (newToolbar) {
    newToolbar.setTitle(me.getTitle());
    if (!newToolbar.getParent()) {
      me.add(newToolbar);
    }
  } else {
    if (oldToolbar) {
      oldToolbar.destroy();
    }
  }
}, updateUseToolbar:function(newUseToolbar, oldUseToolbar) {
  if (!newUseToolbar) {
    this.setToolbar(false);
  }
}, updateTitle:function(newTitle) {
  var me = this, backButton = me.getBackButton();
  if (me.getUpdateTitleText()) {
    if (me.listMode === 'title') {
      me.setToolbarTitle(newTitle);
    } else {
      if (backButton && me.getUseTitleAsBackText() && me.listMode === 'node') {
        backButton.setText(newTitle);
      }
    }
  } else {
    me.setToolbarTitle(newTitle);
  }
}, getItemTextTpl:function(node) {
  return '{' + this.getDisplayField() + '}';
}, getTitleTextTpl:function(node) {
  return '{' + this.getDisplayField() + '}';
}, renderTitleText:function(node, forBackButton) {
  var initialTitle;
  if (!node.titleTpl) {
    node.titleTpl = Ext.create('Ext.XTemplate', this.getTitleTextTpl(node));
  }
  if (node.isRoot()) {
    initialTitle = this.getTitle();
    return forBackButton && initialTitle === '' ? this.getInitialConfig('backText') : initialTitle;
  }
  return node.titleTpl.applyTemplate(node.data);
}, goToNode:function(node) {
  var me = this, activeItem, detailCard, detailCardActive, reverse, firstList, secondList, layout, animation, list;
  if (!node) {
    return;
  }
  activeItem = me.getActiveItem();
  detailCard = me.getDetailCard();
  detailCardActive = detailCard && me.getActiveItem() === detailCard;
  reverse = me.goToNodeReverseAnimation(node);
  firstList = me.firstList;
  secondList = me.secondList;
  layout = me.getLayout();
  animation = layout ? layout.getAnimation() : null;
  if (node.isLeaf()) {
    throw new Error('goToNode: passed a node which is a leaf.');
  }
  if (node === me.getLastNode() && !detailCardActive) {
    return;
  }
  if (detailCardActive) {
    if (animation) {
      animation.setReverse(true);
    }
    list = me.getLastActiveList();
    list.getStore().setNode(node);
    node.expand();
    me.setActiveItem(list);
  } else {
    if (animation) {
      animation.setReverse(reverse);
    }
    if (firstList && secondList) {
      activeItem = me.getActiveItem();
      me.setLastActiveList(activeItem);
      list = activeItem === firstList ? secondList : firstList;
      list.getStore().setNode(node);
      node.expand();
      me.setActiveItem(list);
      if (me.getClearSelectionOnListChange()) {
        list.deselectAll();
      }
    } else {
      if (firstList) {
        me.setLastActiveList(me.getActiveItem());
        me.setActiveItem(me.getList(node));
        me.secondList = me.getActiveItem();
      } else {
        me.setActiveItem(me.getList(node));
        me.firstList = me.getActiveItem();
      }
    }
  }
  me.fireEvent('listchange', me, me.getActiveItem());
  me.setLastNode(node);
  me.changeListMode(node);
  me.syncToolbar();
}, goToLeaf:function(node) {
  var me = this, card, container, sharedContainer, layout, animation, activeItem;
  if (!node.isLeaf()) {
    throw new Error('goToLeaf: passed a node which is not a leaf.');
  }
  card = me.getDetailCard();
  container = me.getDetailContainer();
  sharedContainer = container === me;
  layout = me.getLayout();
  animation = layout ? layout.getAnimation() : false;
  if (card) {
    if (container.getItems().indexOf(card) === -1) {
      container.add(card);
    }
    if (sharedContainer) {
      activeItem = me.getActiveItem();
      if (activeItem instanceof Ext.dataview.List) {
        me.setLastActiveList(activeItem);
      }
      me.setLastNode(node);
    }
    if (animation) {
      animation.setReverse(false);
    }
    container.setActiveItem(card);
    me.syncToolbar();
  }
}, syncToolbar:function(forceDetail) {
  var me = this, detailCard = me.getDetailCard(), node = me.getLastNode(), detailActive = forceDetail || detailCard && me.getActiveItem() === detailCard, parentNode = detailActive ? node : node.parentNode, backButton = me.getBackButton(), toolbar = me.getToolbar(), splitNavigation;
  if (!toolbar) {
    return;
  }
  if (backButton) {
    splitNavigation = toolbar.getInitialConfig('splitNavigation');
    if (splitNavigation) {
      me.$backButtonContainer[parentNode ? 'show' : 'hide']();
    }
    backButton[parentNode ? 'show' : 'hide']();
    if (parentNode && me.getUseTitleAsBackText()) {
      backButton.setText(me.renderTitleText(node.parentNode, true));
    }
  }
  if (node) {
    me.setToolbarTitle(me.renderTitleText(node));
  }
}, updateBackText:function(newText) {
  var btn = this.getBackButton();
  if (btn) {
    btn.setText(newText);
  }
}, goToNodeReverseAnimation:function(node) {
  var lastNode = this.getLastNode();
  if (!lastNode) {
    return false;
  }
  return !lastNode.contains(node) && lastNode.isAncestor(node) ? true : false;
}, getList:function(node) {
  var me = this, treeStore = new Ext.data.NodeStore({recursive:false, node:node, rootVisible:false, model:me.getStore().getModel(), proxy:'memory'}), list;
  node.expand();
  list = Ext.create(Ext.Object.merge({xtype:'list', pressedDelay:250, autoDestroy:true, store:treeStore, onItemDisclosure:me.getOnItemDisclosure(), variableHeights:me.getVariableHeights(), emptyText:me.getEmptyText(), selectable:{deselectable:me.getAllowDeselect()}, listeners:{scope:me, childdoubletap:'onChildDoubleTap', beforeselectionchange:'onBeforeSelect', containertap:'onContainerTap', select:'onSelect', deselect:'onDeselect', childtap:{fn:'onChildTap', priority:1000}, childtouchstart:{fn:'onChildInteraction', 
  priority:1000}}, itemTpl:'\x3cspan\x3ctpl if\x3d"leaf \x3d\x3d true"\x3e class\x3d"x-list-item-leaf"\x3c/tpl\x3e\x3e' + me.getItemTextTpl(node) + '\x3c/span\x3e'}, me.getListConfig()));
  me.relayEvents(list, ['activate']);
  return list;
}, privates:{setToolbarTitle:function(newTitle) {
  var me = this, toolbar = me.getToolbar();
  if (toolbar) {
    toolbar.setTitle(newTitle);
  }
}}});
Ext.define('Ext.theme.material.dataview.NestedList', {override:'Ext.dataview.NestedList', config:{backText:'', useTitleAsBackText:false, backButton:{iconCls:'md-icon-arrow-back', hidden:true}}});
Ext.define('Ext.dataview.listswiper.Item', {extend:Ext.Container, xtype:'listswiperitem', classCls:Ext.baseCSSPrefix + 'listswiperitem', config:{leftActions:null, rightActions:null, undo:{lazy:true, $value:{xtype:'button', text:'Undo', touchAction:{panX:false, panY:false}}}, action:null, state:null, translationTarget:null}, autoSize:null, initialize:function() {
  this.callParent();
  this.ownerCmp.on({scope:this, destroy:'onItemDestroy', removed:'onItemDestroy'});
}, applyUndo:function(config) {
  var action = this.getAction();
  return Ext.apply({}, action && action.undoable, config);
}, onItemDestroy:function(item) {
  var me = this, plugin = me.owner;
  plugin.destroyItem(item);
}, invokeAction:function(action, type) {
  var me = this, plugin = me.owner, list = plugin.cmp, item = me.ownerCmp, fn = action[type], obj = {item:item, record:item && item.getRecord(), action:action};
  list.fireEvent('itemaction' + type, list, obj);
  return Ext.callback(fn, action.getScope && action.getScope() || action.scope, [list, obj], 0, me);
}, updateState:function(state, oldState) {
  if (oldState) {
    this.removeCls(Ext.baseCSSPrefix + oldState);
  }
  if (state) {
    this.addCls(Ext.baseCSSPrefix + state);
  }
}, onDragStart:Ext.emptyFn, onDragMove:Ext.emptyFn, onDragEnd:Ext.emptyFn});
Ext.define('Ext.dataview.listswiper.Accordion', {extend:Ext.dataview.listswiper.Item, xtype:'listswiperaccordion', classCls:Ext.baseCSSPrefix + 'listswiperaccordion', cls:Ext.baseCSSPrefix + 'item-no-tap', config:{bodyOffset:null, actionDefaults:{cls:Ext.baseCSSPrefix + 'listswiperaction', xtype:'button', iconAlign:'top'}, actionUI:'square', singleActionDefaults:{}, multiActionDefaults:{}, undo:{cls:Ext.baseCSSPrefix + 'listswiperundoable', ui:'undo', docked:'right', ignoreDefaults:true}, thresholds:null, 
scaleDrag:true, swipeToCommit:true, side:null}, layout:{type:'hbox', align:'stretch'}, template:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', uiCls:'body-el', children:[{reference:'leftElement', cls:Ext.baseCSSPrefix + 'listswiperaccordion-wrapper ' + Ext.baseCSSPrefix + 'listswiperaccordion-wrapper-left'}, {reference:'rightElement', cls:Ext.baseCSSPrefix + 'listswiperaccordion-wrapper ' + Ext.baseCSSPrefix + 'listswiperaccordion-wrapper-right'}]}], scrollDock:null, constructor:function(config) {
  var me = this;
  me.left = {name:'left', isLeft:true, items:[]};
  me.right = {name:'right', isLeft:false, items:[]};
  me.callParent([config]);
}, initialize:function() {
  var me = this, target = me.getTranslationTarget();
  me.callParent();
  target.on({scope:me, tap:'onDismissTap'});
}, destroy:function() {
  var me = this, target = me.getTranslationTarget();
  if (me.$undoTimer) {
    Ext.unraf(me.$undoTimer);
  }
  if (me.thresholdEl) {
    me.thresholdEl.destroy();
  }
  target.un({scope:me, tap:'onDismissTap'});
  me.callParent();
}, applyLeftActions:function(items) {
  this.addActions('left', items);
}, applyRightActions:function(items) {
  this.addActions('right', items);
}, applySide:function(side) {
  this.side = side && this[side];
  return side;
}, getButtonBackgroundColor:function(button) {
  var action = button.$action, backgroundColorEl = button[action.backgroundColorEl || 'innerElement'];
  return backgroundColorEl.getStyle('backgroundColor');
}, addActions:function(side, items) {
  var me = this, i, config, action, button;
  side = me[side];
  side.el = side.isLeft ? me.leftElement : me.rightElement;
  side.multiple = items.length > 1;
  config = side.multiple ? me.getMultiActionDefaults() : me.getSingleActionDefaults();
  side.el.toggleCls(me.baseCls + '-multiple', side.multiple);
  side.el.toggleCls(me.baseCls + '-single', !side.multiple);
  for (i = 0; i < items.length; i++) {
    action = me.createActionItem(Ext.apply({}, items[i], config));
    action.$side = side;
    button = me.add(action);
    button.addUi(this.getActionUI());
    button.$action = action;
    button.$originalHandler = button.getHandler();
    button.setHandler(me.onActionTap.bind(me, action));
    side.items.push(button);
  }
}, createActionItem:function(config) {
  return Ext.apply({}, config, this.getActionDefaults());
}, getSwipeRange:function() {
  var me = this, side = me.side, plugin = me.owner, swipeMax = plugin.getSwipeMax();
  return me.itemWidth * (swipeMax[side.multiple ? 'multiple' : 'single'] / 100);
}, onActionTap:function(action, button, e) {
  var me = this, state = me.getState();
  if (state !== 'dragpeek') {
    e.stopPropagation();
    this.commit(e, action, button);
  }
}, onDismissTap:function() {
  var me = this, plugin = me.owner, dimissOnTap = plugin.getDismissOnTap();
  if (dimissOnTap) {
    me.dismiss();
  }
}, onRender:function() {
  var me = this, item = me.ownerCmp;
  me.itemWidth = item.el.measure('w');
  me.syncSides();
}, updateSide:function(side, oldSide) {
  var me = this, layout = me.getLayout();
  me.el.replaceCls(oldSide, side, me.baseCls + '-side');
  if (side === 'left') {
    layout.setPack('start');
  } else {
    layout.setPack('end');
  }
}, updateState:function(state, oldState) {
  var me = this, side = me.side, defaultButton = me.getDefaultButton();
  me.callParent([state, oldState]);
  if (side.multiple) {
    me.el.toggleCls(me.baseCls + '-collapsed', state === 'dragcommit');
    if (state === 'dragcommit') {
      defaultButton.el.setStyle({'flex-basis':side.maxActionWidth + 'px'});
    } else {
      defaultButton.setStyle({'flex-basis':null});
    }
    if (oldState === 'dragcommit' && me.isDragging) {
      me.el.addCls(me.baseCls + '-was-collapsed');
    } else {
      me.el.removeCls(me.baseCls + '-was-collapsed');
    }
  }
}, privates:{destroyItem:function() {
  var me = this, plugin = me.owner, item = me.ownerCmp;
  if (!me.destroyed) {
    me.animating = false;
    me.el.removeCls(me.baseCls + '-was-collapsed');
    plugin.destroyItem(item);
  }
}, animateItem:function(offset, config) {
  var me = this, side, target, duration, completeFn;
  config = config || {};
  side = me.side;
  target = this.getTranslationTarget();
  duration = config.duration || 150;
  return new Ext.Promise(function(resolve) {
    me.animating = true;
    me.offset = side.isLeft ? offset : -offset;
    completeFn = function() {
      if (!me.destroyed) {
        me.animating = false;
        me.el.removeCls(me.baseCls + '-was-collapsed');
      }
      resolve();
    };
    if (target.dom) {
      if (side.el.dom) {
        side.el.animate({preserveEndState:true, duration:duration, to:{width:offset}});
      }
      target.animate({preserveEndState:true, duration:duration, to:{transform:{translateX:me.offset}}, callback:completeFn});
    } else {
      completeFn();
    }
  });
}, commit:function(e, action, button) {
  var me = this, plugin = me.owner, undoable, handler, delay, precommitResult, undo, backgroundColor;
  action = action || me.getDefaultAction();
  button = button || me.getDefaultButton();
  undoable = action.undoable;
  handler = button.$originalHandler;
  me.setAction(action);
  me.$precommitResult = precommitResult = me.invokeAction(action, 'precommit');
  if (handler) {
    me.snapback().then(function() {
      Ext.callback(handler, button.getScope(), [action, e], 0, button);
    }).then(function() {
      me.destroyItem();
    });
  } else {
    if (!undoable) {
      me.dismiss();
    } else {
      undo = me.add(me.getUndo());
      undo.addUi(button.getUi());
      me.bodyElement.on({scope:me, tap:'onDismissTap'});
      if (me.$undoTimer) {
        Ext.unraf(me.$undoTimer);
      }
      me.$undoTimer = Ext.raf(function() {
        me.$undoTimer = null;
        me.setState('undo');
        backgroundColor = me.getButtonBackgroundColor(button);
        if (backgroundColor) {
          me.el.setStyle('backgroundColor', backgroundColor);
        }
        undo.setHandler(me.onUndoTap.bind(me));
        delay = plugin.getCommitDelay();
        if (delay) {
          if (precommitResult && precommitResult.then) {
            precommitResult.then(function() {
              plugin.dismissAllTask.delay(delay);
            });
          } else {
            plugin.dismissAllTask.delay(delay);
          }
        }
      });
    }
  }
}, onUndoTap:function() {
  this.undo();
}, undo:function() {
  var me = this, action = me.getAction(), precommitResult = me.$precommitResult;
  me.setState('open');
  if (precommitResult && precommitResult.then) {
    precommitResult.then(function() {
      me.$precommitResult = null;
      me.undo();
    });
    return;
  }
  me.snapback().then(function() {
    me.invokeAction(action, 'revert');
  }).then(function() {
    me.destroyItem();
  });
}, createThresholds:function() {
  var me = this, item = me.ownerCmp, plugin = this.owner, side = me.side, swipeRange = me.getSwipeRange(), commitThreshold = side.commitThreshold, openThreshold = side.openThreshold, width;
  if (plugin.showThresholds && !me.thresholdEl) {
    width = swipeRange - (commitThreshold - openThreshold) - openThreshold;
    me.thresholdEl = item.el.append({style:{display:'flex', flexDirection:'row', justifyContent:'flex-end', position:'absolute', height:'auto', top:0, left:0, right:0}, children:[{style:{width:width + 'px', height:'6px', opacity:0.8, backgroundColor:'#EF5350'}}, {style:{width:commitThreshold - openThreshold + 'px', height:'6px', opacity:0.8, backgroundColor:'#FFEE58'}}, {style:{width:openThreshold + 'px', height:'6px', opacity:0.8, backgroundColor:'#66BB6A'}}]});
  }
  if (me.thresholdEl) {
    me.thresholdEl.setStyle({flexDirection:!side.isLeft ? 'row' : 'row-reverse'});
  }
}, dismiss:function() {
  var me = this, action = me.getAction(), precommitResult = me.$precommitResult;
  if (precommitResult && precommitResult.then) {
    precommitResult.then(function() {
      me.$precommitResult = null;
      me.dismiss();
    });
    return;
  }
  if (action) {
    me.snapback().then(function() {
      me.invokeAction(action, 'commit');
    }).then(function() {
      me.destroyItem();
    });
  } else {
    me.snapback(true);
  }
}, onDragStart:function(e) {
  var me = this, state = me.getState();
  if (me.animating || state === 'undo') {
    return;
  }
  e.claimGesture();
  me.initialOffset = me.offset || 0;
  me.startX = e.getX() - me.el.getX() - me.initialOffset;
  me.isDragging = true;
  me.syncState(e.deltaX);
}, onDragMove:function(e) {
  if (this.getState() === 'undo') {
    return;
  }
  e.preventDefault();
  this.syncState(e.deltaX);
}, onDragEnd:function(e) {
  var me = this, state = me.getState();
  e.preventDefault();
  me.isDragging = false;
  if (state === 'dragcommit') {
    me.commit(e);
  } else {
    if (state === 'dragopen') {
      me.open();
    } else {
      if (state === 'undo') {
        return;
      } else {
        me.snapback(true);
      }
    }
  }
}, getDefaultButton:function(side) {
  var items;
  side = side || this.side;
  items = side.items;
  return items[side.isLeft ? 0 : items.length - 1];
}, getDefaultAction:function(side) {
  var button = this.getDefaultButton(side);
  return button && button.$action;
}, getRenderTarget:function(item) {
  var side = item && item.$side;
  if (side) {
    return side.el;
  }
  return this.callParent(arguments);
}, open:function() {
  return this.animateItem(this.side.naturalWidth);
}, snapback:function(destroy) {
  var me = this, anim = me.animateItem(0);
  return destroy ? anim.then(function() {
    me.destroyItem();
  }) : anim;
}, syncSides:function() {
  var me = this;
  me.syncSide('left');
  me.syncSide('right');
}, syncSide:function(side) {
  var me = this, thresholds = me.getThresholds(), itemWidth = me.itemWidth, element = side === 'left' ? me.leftElement : me.rightElement, children = element.dom.childNodes, maxActionWidth = 0, backgroundColor, defaultButton, childWidth, i, child, naturalWidth;
  side = me[side];
  defaultButton = this.getDefaultButton(side);
  element.addCls(me.baseCls + '-measure');
  for (i = 0; i < children.length; i++) {
    child = Ext.get(children[i]);
    childWidth = child.measure('w');
    if (childWidth > maxActionWidth) {
      maxActionWidth = childWidth;
    }
  }
  naturalWidth = side.naturalWidth = maxActionWidth * children.length;
  side.maxActionWidth = maxActionWidth;
  if (thresholds && thresholds.open) {
    side.openThreshold = thresholds.open / 100 * itemWidth;
  } else {
    side.openThreshold = maxActionWidth;
  }
  if (thresholds && thresholds.commit) {
    side.commitThreshold = thresholds.commit / 100 * itemWidth;
  } else {
    side.commitThreshold = Math.min(0.95 * itemWidth, naturalWidth * 1.4);
  }
  element.removeCls(me.baseCls + '-measure');
  if (side.multiple) {
    backgroundColor = me.getButtonBackgroundColor(defaultButton);
    if (backgroundColor) {
      side.el.setStyle('backgroundColor', backgroundColor);
    }
  }
}, syncState:function(deltaX) {
  var me = this, plugin = me.owner, itemWidth = me.itemWidth, swipeToCommit = me.getSwipeToCommit(), scaleDrag = me.getScaleDrag(), testOffset = me.initialOffset + deltaX, side = this[testOffset < 0 ? 'right' : 'left'], scaler = scaleDrag ? Math.max(1, Math.min(3, Math.abs((side.isLeft ? 0 : 1) - me.startX / itemWidth) * 3)) : 1, offset = me.offset = me.initialOffset + deltaX * scaler, currentSide = me.side, directionLock = plugin.getDirectionLock(), positiveOffset, swipeRange, openThreshold, commitThreshold;
  if (this.left.items.length === 0 || this.right.items.length === 0) {
    directionLock = false;
  }
  if (side.items.length === 0 || currentSide && (side.name !== currentSide.name && directionLock)) {
    offset = me.offset = me.initialOffset + deltaX * 0.1;
    if (side.items.length === 0) {
      me.setSide(side.name);
    }
    me.setState('draglocked');
  } else {
    me.setSide(side.name);
    swipeRange = me.getSwipeRange();
    openThreshold = side.openThreshold;
    commitThreshold = side.commitThreshold;
    positiveOffset = side.isLeft ? Math.abs(Math.max(0, offset)) : Math.abs(Math.min(0, offset));
    me.createThresholds();
    if (positiveOffset <= openThreshold) {
      me.setState('dragpeek');
    } else {
      if (positiveOffset <= commitThreshold || !swipeToCommit) {
        me.setState('dragopen');
      } else {
        me.setState('dragcommit');
      }
    }
    if (side.isLeft) {
      offset = Math.min(offset, swipeRange);
    } else {
      offset = Math.max(offset, -swipeRange);
    }
  }
  me.setBodyOffset(offset);
}, updateBodyOffset:function(offset) {
  var me = this, side = me.side, target = me.getTranslationTarget();
  target.setStyle('transform', 'translateX(' + offset + 'px)');
  side.el.setWidth(Math.abs(offset));
}}});
Ext.define('Ext.dataview.listswiper.ListSwiper', {extend:Ext.plugin.Abstract, alias:'plugin.listswiper', config:{left:[], right:[], dismissOnTap:true, dismissOnScroll:true, commitDelay:0, widget:{xtype:'listswiperaccordion'}, swipeMax:{single:50, multiple:90}, directionLock:true, target:null}, shadowCls:Ext.baseCSSPrefix + 'listswiper-shadow', init:function(list) {
  var me = this, scrollable = list.getScrollable();
  me.items = [];
  list.on({scope:this, add:'onItemAdd'});
  list.el.on({scope:this, dragstart:'onDragStart', drag:'onDragMove', dragend:'onDragEnd'});
  if (scrollable) {
    scrollable.setX(false);
  }
  me.dismissAllTask = new Ext.util.DelayedTask(me.dismissAll, me);
  me.updateDismissOnScroll(me.getDismissOnScroll());
}, destroy:function() {
  var list = this.cmp;
  list.un({scope:this, add:'onItemAdd'});
  list.el.un({scope:this, dragstart:'onDragStart', drag:'onDragMove', dragend:'onDragEnd'});
  this.callParent();
}, createWidget:function(config) {
  var me = this, leftItems = me.getLeft(), rightItems = me.getRight();
  return Ext.apply({owner:me, defaults:me.defaults, leftActions:leftItems, rightActions:rightItems}, config);
}, onScrollStart:function() {
  if (this.getDismissOnScroll()) {
    this.dismissAll();
  }
}, onItemAdd:function(list, item) {
  item.setTouchAction({panX:false});
}, onItemUpdateData:function(item) {
  Ext.asap(this.resyncItem, this, [item]);
}, onDragStart:function(evt) {
  var me = this, list = me.cmp, record = list.mapToRecord(evt), target, translationTarget, renderTarget, item, widget;
  if (!me.hasActions() || evt.absDeltaX < evt.absDeltaY) {
    return;
  }
  if (record) {
    item = list.mapToItem(record);
    if (item) {
      widget = item.$swiperWidget;
      if (!widget) {
        widget = me.createWidget(me.getWidget());
        widget.ownerCmp = item;
        target = me.getTarget();
        if (item.isGridRow || target === 'outer') {
          renderTarget = item.el;
          translationTarget = item.el.first();
        } else {
          renderTarget = item.bodyElement;
          translationTarget = item.hasToolZones ? renderTarget.child('.' + Ext.baseCSSPrefix + 'tool-dock') : item.innerElement;
        }
        translationTarget.addCls(me.shadowCls);
        widget.translationTarget = translationTarget;
        renderTarget = translationTarget.parent();
        item.$swiperWidget = widget = Ext.create(widget);
        renderTarget.insertFirst(widget.el);
        widget.setRendered(true);
        if (list.infinite) {
          list.stickItem(item, true);
        }
        this.items.push(item);
      }
      widget.onDragStart(evt);
    }
  }
}, onDragMove:function(evt) {
  var me = this, list = me.cmp, item = list.mapToItem(evt), swiperItem;
  if (item) {
    swiperItem = item.$swiperWidget;
    if (!me.hasActions() || !swiperItem) {
      return;
    }
    swiperItem.onDragMove(evt);
  }
}, onDragEnd:function(evt) {
  var me = this, list = me.cmp, item = list.mapToItem(evt), swiperItem;
  if (item) {
    swiperItem = item.$swiperWidget;
    if (!me.hasActions() || !swiperItem) {
      return;
    }
    swiperItem.onDragEnd(evt);
  }
}, updateDismissOnScroll:function(value) {
  var list = this.getCmp(), scrollable, listeners;
  if (this.isConfiguring || !list) {
    return;
  }
  scrollable = list.getScrollable();
  if (!scrollable) {
    return;
  }
  listeners = {scrollstart:'onScrollStart', scope:this};
  if (value === true) {
    scrollable.on(listeners);
  } else {
    scrollable.un(listeners);
  }
}, updateTarget:function(target, oldTarget) {
  if (target != null && target !== 'inner' && target !== 'outer') {
    Ext.raise('Invalid target for ListSwiper: ' + target);
  }
}, hasActions:function() {
  return this.getLeft() || this.getRight();
}, privates:{destroyItem:function(item) {
  var me = this, list = me.cmp, swiperWidget = item.$swiperWidget, i = me.items.indexOf(item);
  if (i !== -1) {
    me.items.splice(i, 1);
  }
  if (swiperWidget) {
    swiperWidget.destroy();
  }
  item.$swiperWidget = null;
  if (list.infinite && !item.destroyed) {
    list.stickItem(item, null);
  }
}, dismissAll:function() {
  var me = this;
  me.items.map(function(item) {
    return item.$swiperWidget;
  }).forEach(function(swiperItem) {
    swiperItem.dismiss();
  });
}}});
Ext.define('Ext.tip.ToolTip', {extend:Ext.Panel, xtype:'tooltip', floated:true, hidden:true, shadow:true, border:true, bodyBorder:false, anchor:false, closeAction:'hide', config:{align:'l-r?', alignDelegate:null, allowOver:null, anchorToTarget:true, autoHide:true, delegate:null, dismissDelay:5000, hideDelay:300, mouseOffset:[15, 18], quickShowInterval:250, showDelay:500, showOnTap:null, target:null, trackMouse:false}, classCls:Ext.baseCSSPrefix + 'tooltip', headerCls:Ext.baseCSSPrefix + 'tooltipheader', 
titleCls:Ext.baseCSSPrefix + 'tooltiptitle', toolCls:[Ext.baseCSSPrefix + 'paneltool', Ext.baseCSSPrefix + 'tooltiptool'], closeToolText:null, constructor:function(config) {
  this.currentTarget = new Ext.dom.Fly;
  this.callParent([config]);
}, getRefOwner:function() {
  var target = this.getTarget();
  return target && target.isComponent ? target : this.callParent();
}, updateAnchor:function() {
  this.doRealignToTarget();
}, applyAlign:function(align) {
  var lastChar = align[align.length - 1];
  if (lastChar !== '?' && lastChar !== '!') {
    align += '?';
  }
  return align;
}, updateAlign:function() {
  this.doRealignToTarget();
}, updateAllowOver:function(allowOver) {
  var me = this;
  me.overListeners = Ext.destroy(me.overListeners);
  if (allowOver) {
    me.overListeners = me.el.on({mouseenter:'onTipOver', mouseleave:'onTipOut', scope:me, destroyable:true});
  }
}, applyTarget:function(target) {
  if (target) {
    if (!target.isComponent) {
      target = Ext.get(target.el || target);
    }
  }
  return target;
}, updateTarget:function(target, oldTarget) {
  var me = this;
  if (oldTarget) {
    oldTarget.un('destroy', me.destroy, me);
  }
  if (target) {
    if (target.isComponent) {
      me.targetElement = target.element;
      target.on('destroy', me.destroy, me);
    } else {
      me.targetElement = Ext.get(target);
    }
  } else {
    me.targetElement = null;
  }
  me.attachTargetListeners();
}, updateTrackMouse:function(trackMouse) {
  if (trackMouse) {
    this.setAllowOver(trackMouse);
  }
}, updateDisabled:function(disabled, oldDisabled) {
  var me = this, val;
  me.callParent([disabled, oldDisabled]);
  if (disabled) {
    me.clearTimers();
    me.hide();
    val = null;
  }
  me.attachTargetListeners(val);
}, updateShowOnTap:function(showOnTap) {
  if (!this.isConfiguring) {
    this.attachTargetListeners();
  }
}, realignToTarget:function() {
  this.doRealignToTarget();
}, showBy:function(target, alignment, passedOptions) {
  var me = this, alignTarget = target, alignDelegate = me.getAlignDelegate();
  if (target.isEvent) {
    me.alignToEvent(target);
  } else {
    if (target.isWidget) {
      me.updateCurrentTarget(target.element.dom);
    } else {
      if (target.isElement) {
        me.updateCurrentTarget(target.dom);
      } else {
        if (target.nodeType) {
          me.updateCurrentTarget(target);
        }
      }
    }
    if (alignDelegate) {
      target = Ext.fly(target);
      alignTarget = target.down(alignDelegate, true) || target.up(alignDelegate, me.targetElement, true);
    }
    me.callParent([alignTarget, alignment || me.getAlign(), passedOptions]);
  }
}, beforeShow:function(options) {
  var me = this, result = me.callParent(arguments);
  if (result !== false) {
    if (!options.alignment && (me.pointerEvent || me.getTarget())) {
      options.alignment = {component:me.targetElement, alignment:me.getAlign(), options:{overlap:me.getTrackMouse() && !me.getAnchor()}};
    }
    me.clearTimer('dismiss');
  }
}, afterShow:function() {
  var me = this;
  me.callParent();
  me.postprocessShow();
  me.mousedownListener = Ext.on({mousedown:'onDocMouseDown', scope:me, destroyable:true});
}, hide:function() {
  var me = this;
  me.clearTimer('hide');
  me.clearTimer('dismiss');
  me.callParent();
  me.lastHidden = new Date;
  me.updateCurrentTarget(null);
  Ext.destroy(me.mousedownListener);
}, doDestroy:function() {
  var me = this;
  me.clearTimers();
  me.setTarget(null);
  me.destroyMembers('mousedownListener', 'overListeners');
  me.callParent();
}, privates:{allowRealign:true, onDocMouseDown:function(e) {
  var me = this, delegate = me.getDelegate();
  if (e.within(me.el.dom)) {
    if (e.pointerType !== 'mouse' && me.getAllowOver()) {
      me.clearTimer('dismiss');
    }
  } else {
    if (!me.getClosable()) {
      if (e.within(me.targetElement) && (!delegate || e.getTarget(delegate, me.targetElement))) {
        me.delayHide();
      } else {
        me.disable();
        me.enableTimer = Ext.defer(me.enable, 100, me);
      }
    }
  }
}, onTargetOver:function(e) {
  var me = this, myTarget = me.targetElement, delegate = me.getDelegate(), currentTarget = me.currentTarget, newTarget;
  if (me.getDisabled()) {
    return;
  }
  if (me.getAllowOver() && me.el.contains(e.target)) {
    return;
  }
  if (delegate) {
    if (currentTarget.contains(e.target)) {
      return;
    }
    newTarget = e.getTarget(delegate, myTarget);
    if (newTarget && e.getRelatedTarget(delegate) === newTarget) {
      return;
    }
  } else {
    if (!myTarget.contains(e.relatedTarget)) {
      newTarget = myTarget.dom;
    } else {
      return;
    }
  }
  if (newTarget) {
    me.handleTargetOver(e, newTarget);
  } else {
    if (currentTarget.dom) {
      me.handleTargetOut();
    }
  }
}, handleTargetOver:function(e, newTarget) {
  var me = this, myListeners = me.hasListeners;
  me.pointerEvent = e;
  me.updateCurrentTarget(newTarget);
  if (me.isVisible()) {
    if (myListeners.beforeshow && me.fireEvent('beforeshow', me) === false) {
      return me.hide();
    }
    me.clearTimer('hide');
    me.clearTimer('dismiss');
    me.showByTarget(newTarget);
    if (myListeners.show) {
      me.fireEvent('show', me);
    }
    me.postprocessShow();
  } else {
    me.delayShow(newTarget);
  }
}, postprocessShow:function() {
  var me = this, dismissDelay = me.getDismissDelay();
  me.clearTimer('show');
  if (dismissDelay && me.getAutoHide()) {
    me.dismissTimer = Ext.defer(me.hide, dismissDelay, me);
  }
  me.toFront();
}, onTargetTap:function(e) {
  if (e.pointerType !== 'mouse' && Ext.fly(e.target).isVisible(true)) {
    this.onTargetOver(e);
  }
}, onTargetOut:function(e) {
  if (this.currentTarget.dom && !this.currentTarget.contains(e.relatedTarget)) {
    if (!this.getAllowOver() && e.within(this.el, true)) {
      this.handleTargetOut();
    }
  }
}, handleTargetOut:function() {
  var me = this;
  if (me.showTimer) {
    me.clearTimer('show');
  }
  if (me.isVisible() && me.getAutoHide()) {
    me.delayHide();
  }
}, onTipOver:function() {
  this.clearTimer('hide');
  this.clearTimer('dismiss');
}, onTipOut:function(e) {
  if (!this.currentTarget.dom || !e.getPoint().isContainedBy(this.currentTarget.getRegion())) {
    this.handleTargetOut();
  }
}, onMouseMove:function(e) {
  var me = this, dismissDelay = me.getDismissDelay();
  if (!me.el.contains(e.target)) {
    me.pointerEvent = e;
  }
  if (me.isVisible() && me.currentTarget.contains(e.target)) {
    if (dismissDelay && me.getAutoHide() !== false) {
      me.clearTimer('dismiss');
      me.dismissTimer = Ext.defer(me.hide, dismissDelay, me);
    }
    if (me.getTrackMouse()) {
      me.alignToEvent(e);
    }
  }
}, delayShow:function(target) {
  var me = this;
  me.clearTimer('hide');
  if (me.getHidden() && !me.showTimer) {
    if (me.getDelegate() && Ext.Date.getElapsed(me.lastHidden) < me.getQuickShowInterval()) {
      me.showByTarget(target);
    } else {
      me.showTimer = Ext.defer(me.showByTarget, !me.pointerEvent || me.pointerEvent.pointerType === 'mouse' ? me.getShowDelay() : 0, me, [target]);
    }
  } else {
    if (!me.getHidden() && me.getAutoHide() !== false) {
      me.showByTarget(target);
    }
  }
}, showByTarget:function(target) {
  var me = this, isTarget = me.getAnchorToTarget() && !me.getTrackMouse();
  me.lastShowWasPointer = !isTarget;
  me.showBy(isTarget ? target : me.pointerEvent, me.getAlign(), {overlap:me.getTrackMouse() && !me.getAnchor()});
}, delayHide:function() {
  var me = this;
  if (!me.isHidden() && !me.hideTimer) {
    me.clearTimer('dismiss');
    me.hideTimer = Ext.defer(me.hide, me.getHideDelay(), me);
  }
}, alignToEvent:function(event) {
  var me = this, options = {overlap:me.getTrackMouse() && !me.getAnchor()}, mouseOffset = me.getMouseOffset(), target = event.getPoint().adjust(-Math.abs(mouseOffset[1]), Math.abs(mouseOffset[0]), Math.abs(mouseOffset[1]), -Math.abs(mouseOffset[0])), align = me.getAnchor() ? me.getAlign() : null;
  if (!align && mouseOffset) {
    if (mouseOffset[0] > 0) {
      if (mouseOffset[1] > 0) {
        align = 'tl-br?';
      } else {
        align = 'bl-tr?';
      }
    } else {
      if (mouseOffset[1] > 0) {
        align = 'tr-bl?';
      } else {
        align = 'br-tl?';
      }
    }
  }
  if (me.isVisible()) {
    me.clearTimer('hide');
    me.alignTo(target, align, options);
  } else {
    me.showBy(target, align, options);
  }
}, _timerNames:{}, clearTimer:function(name) {
  var me = this, names = me._timerNames, propName = names[name] || (names[name] = name + 'Timer'), timer = me[propName];
  if (timer) {
    Ext.undefer(timer);
    me[propName] = null;
    if (name === 'show' && me.isHidden()) {
      me.updateCurrentTarget(null);
    }
  }
}, clearTimers:function() {
  var me = this;
  me.clearTimer('show');
  me.clearTimer('dismiss');
  me.clearTimer('hide');
  me.clearTimer('enable');
}, clipTo:function(clippingEl, sides) {
  var clippingRegion;
  if (clippingEl.isRegion) {
    clippingRegion = clippingEl;
  } else {
    clippingRegion = (clippingEl.isComponent ? clippingEl.el : Ext.fly(clippingEl)).getConstrainRegion();
  }
  this.callParent([clippingRegion, sides]);
  this.tipElement.clipTo(clippingRegion, sides);
}, doRealignToTarget:function() {
  var me = this, currentTarget = me.currentTarget, dom = currentTarget && currentTarget.dom;
  me.clearTimers();
  if (me.allowRealign && me.isVisible() && dom) {
    me.realign(null, me.getAlign());
  }
}, updateCurrentTarget:function(dom) {
  var me = this, currentTarget = me.currentTarget, was = currentTarget.dom;
  currentTarget.attach(dom);
  if (!me.isConfiguring) {
    me.fireEvent('hovertarget', me, currentTarget, was);
  }
}, attachTargetListeners:function(target) {
  var me = this, listeners;
  me.targetListeners = Ext.destroy(me.targetListeners);
  if (target === null) {
    return;
  }
  target = me.targetElement;
  if (target) {
    listeners = {mouseover:'onTargetOver', mouseout:'onTargetOut', mousemove:'onMouseMove', scope:me, destroyable:true};
    if (me.getShowOnTap()) {
      listeners.tap = 'onTargetTap';
    }
    me.targetListeners = target.on(listeners);
  }
}}});
Ext.define('Ext.field.BoxLabelable', {extend:Ext.Mixin, mixinConfig:{id:'boxLabelable', after:{initElement:'afterInitElement'}}, config:{boxLabel:null, boxLabelAlign:null}, boxLabeledCls:Ext.baseCSSPrefix + 'box-labeled', getBodyTemplate:function() {
  return [{reference:'boxWrapElement', cls:Ext.baseCSSPrefix + 'box-wrap-el', children:[{reference:'boxElement', cls:Ext.baseCSSPrefix + 'box-el', children:this.getBoxTemplate()}, {tag:'label', reference:'boxLabelElement', cls:Ext.baseCSSPrefix + 'box-label-el'}]}];
}, getBoxTemplate:Ext.emptyFn, updateBoxLabel:function(boxLabel) {
  this.boxLabelElement.setHtml(boxLabel);
  this.el.toggleCls(this.boxLabeledCls, !!boxLabel);
}, updateBoxLabelAlign:function(boxLabelAlign, oldBoxLabelAlign) {
  var me = this, el = me.el;
  if (oldBoxLabelAlign) {
    el.removeCls(Ext.baseCSSPrefix + 'box-label-align-' + oldBoxLabelAlign);
  }
  if (boxLabelAlign) {
    el.addCls(Ext.baseCSSPrefix + 'box-label-align-' + boxLabelAlign);
  }
}, afterInitElement:function() {
  var inputElement = this.inputElement;
  if (inputElement) {
    this.boxLabelElement.dom.setAttribute('for', inputElement.id);
  }
}});
Ext.define('Ext.field.Checkbox', {extend:Ext.field.Input, alternateClassName:'Ext.form.Checkbox', xtype:['checkbox', 'checkboxfield'], mixins:[Ext.field.BoxLabelable], qsaLeftRe:/[[]/g, qsaRightRe:/[\]]/g, shareableName:true, isCheckbox:true, defaultBindProperty:'checked', twoWayBindable:{checked:1}, publishes:{checked:1}, config:{value:'', checked:false}, inputType:'checkbox', classCls:Ext.baseCSSPrefix + 'checkboxfield', checkedCls:Ext.baseCSSPrefix + 'checked', getBodyTemplate:function() {
  return this.mixins.boxLabelable.getBodyTemplate.call(this);
}, getBoxTemplate:function() {
  return [{reference:'iconElement', cls:Ext.baseCSSPrefix + 'font-icon ' + Ext.baseCSSPrefix + 'icon-el', children:[this.getInputTemplate()]}];
}, getInputTemplate:function() {
  var template = this.callParent();
  template.listeners = template.listeners || {};
  template.listeners.change = {fn:'onChange', delegated:false};
  return template;
}, getSubmitValue:function() {
  return this.getChecked() ? Ext.isEmpty(this._value) ? true : this._value : null;
}, serialize:function() {
  return this.getSubmitValue();
}, checkedRe:/^(true|1|on)/i, getChecked:function() {
  return !!this.inputElement.dom.checked;
}, applyChecked:function(checked) {
  if (this.isConfiguring) {
    this.originalState = checked;
  }
  return !!this.checkedRe.test(String(checked));
}, updateChecked:function(checked, oldChecked) {
  var me = this, eventName;
  if (!me.$onChange) {
    me.inputElement.dom.checked = checked;
  }
  me.toggleCls(me.checkedCls, checked);
  if (me.initialized) {
    eventName = checked ? 'check' : 'uncheck';
    me.fireEvent(eventName, me);
    me.fireEvent('change', me, checked, oldChecked);
  }
  me.setDirty(me.isDirty());
}, isChecked:function() {
  return this.getChecked();
}, isDirty:function() {
  return this.getChecked() !== this.originalState;
}, check:function() {
  return this.setChecked(true);
}, uncheck:function() {
  return this.setChecked(false);
}, onChange:function(e) {
  var me = this;
  me.$onChange = true;
  me.setChecked(!!e.target.checked);
  delete me.$onChange;
}, getSameGroupFields:function() {
  var me = this, component = me.lookupNameHolder(), name = me.name;
  if (!component) {
    Ext.Logger.warn(me.self.$className + ' components must always be descendants of an Ext.field.Panel.');
    name = name.replace(me.qsaLeftRe, '\\[').replace(me.qsaRightRe, '\\]');
    return Ext.Viewport.query('checkboxfield[name\x3d' + name + ']');
  }
  return component.lookupName(name);
}, getGroupValues:function() {
  var values = [];
  this.getSameGroupFields().forEach(function(field) {
    if (field.getChecked()) {
      values.push(field.getValue());
    }
  });
  return values;
}, setGroupValues:function(values) {
  this.getSameGroupFields().forEach(function(field) {
    field.setChecked(values.indexOf(field.getValue()) !== -1);
  });
  return this;
}, resetGroupValues:function() {
  this.getSameGroupFields().forEach(function(field) {
    field.setChecked(field.originalState);
  });
  return this;
}, reset:function() {
  this.setChecked(this.originalState);
  return this;
}, resetOriginalValue:function() {
  this.originalState = this.getChecked();
  this.setDirty(false);
}, getRawValue:function() {
  return this.getChecked();
}, rawToValue:Ext.emptyFn});
Ext.define('Ext.theme.material.field.Checkbox', {override:'Ext.field.Checkbox', config:{labelAlign:'left', bodyAlign:'end', ripple:{delegate:'.' + Ext.baseCSSPrefix + 'icon-el', bound:false, color:'default'}}});
Ext.define('dilocsync.overrides.field.Checkbox', {override:'Ext.field.Checkbox', initialize:function() {
  this.callParent(arguments);
  this.resetOriginalValue();
}});
Ext.define('Ext.field.Manager', {mixinId:'fieldmanager', fillRecord:function(record) {
  var values, name;
  if (record) {
    values = this.getValues();
    for (name in values) {
      if (values.hasOwnProperty(name) && record.getField(name)) {
        record.set(name, values[name]);
      }
    }
  }
  return this;
}, consumeRecord:function(record) {
  var data = record && record.data;
  if (data) {
    this.setValues(data);
  }
}, setValues:function(values) {
  var fields = this.getFields(), name, field, value, ln, i, f;
  values = values || {};
  for (name in values) {
    if (values.hasOwnProperty(name)) {
      field = fields[name];
      value = values[name];
      if (field) {
        if (Ext.isArray(field)) {
          ln = field.length;
          for (i = 0; i < ln; i++) {
            f = field[i];
            if (f.isRadio) {
              f.setGroupValue(value);
              break;
            } else {
              if (f.isCheckbox) {
                if (Ext.isArray(value)) {
                  f.setChecked(value.indexOf(f._value) !== -1);
                } else {
                  f.setChecked(value === f._value);
                }
              } else {
                if (Ext.isArray(value)) {
                  f.setValue(value[i]);
                }
              }
            }
          }
        } else {
          if (field.isRadio || field.isCheckbox) {
            field.setChecked(value);
          } else {
            field.setValue(value);
          }
        }
        if (this.getTrackResetOnLoad && this.getTrackResetOnLoad()) {
          field.resetOriginalValue();
        }
      }
    }
  }
  return this;
}, getValues:function(options, nameless) {
  var fields = this.getFields(), values = {}, isArray = Ext.isArray, enabled = options, field, value, addValue, bucket, name, ln, i, serialize;
  if (Ext.isObject(options)) {
    enabled = options.enabled;
    nameless = options.nameless;
    serialize = options.serialize;
  }
  addValue = function(field, name) {
    if (!nameless && (!name || name === 'null') || field.isFile) {
      return;
    }
    value = serialize || field.isCheckbox ? field.serialize() : field.getValue();
    if (!(enabled && field.getDisabled())) {
      if (field.isRadio) {
        if (field.isChecked()) {
          values[name] = value;
        }
      } else {
        bucket = values[name];
        if (!Ext.isEmpty(bucket)) {
          if (!field.isCheckbox || field.isChecked()) {
            if (!isArray(bucket)) {
              bucket = values[name] = [bucket];
            }
            if (isArray(value)) {
              bucket = values[name] = bucket.concat(value);
            } else {
              bucket.push(value);
            }
          }
        } else {
          values[name] = value;
        }
      }
    }
  };
  for (name in fields) {
    if (fields.hasOwnProperty(name)) {
      field = fields[name];
      if (isArray(field)) {
        ln = field.length;
        for (i = 0; i < ln; i++) {
          addValue(field[i], name);
        }
      } else {
        addValue(field, name);
      }
    }
  }
  return values;
}, getSubmitValues:function(options) {
  return this.getValues(Ext.applyIf({serialize:true}, options));
}, reset:function(clearInvalid) {
  this.getFields(false).forEach(function(field) {
    field.reset();
    if (clearInvalid) {
      field.setError(null);
    }
  });
  return this;
}, updateDisabled:function(newDisabled) {
  this.getFields(false).forEach(function(field) {
    field.setDisabled(newDisabled);
  });
  return this;
}, setErrors:function(errors) {
  var setError = function(field, fieldname) {
    if (field) {
      messages = errors[fieldname];
      if (messages === null || Ext.isArray(messages) && messages.length === 0) {
        field.setError(null);
      } else {
        field.setError(messages);
      }
    }
  }, fieldname, field, messages, i, length;
  if (!Ext.isObject(errors)) {
    Ext.raise('setErrors requires an Object parameter');
  }
  for (fieldname in errors) {
    field = this.lookupName(fieldname) || this.lookup(fieldname);
    if (Ext.isArray(field)) {
      for (i = 0, length = field.length; i < length; i++) {
        setError(field[i], fieldname);
      }
    } else {
      setError(field, fieldname);
    }
  }
  return this;
}, clearErrors:function() {
  var fields = this.getFields(false), i, length, field;
  for (i = 0, length = fields.length; i < length; i++) {
    field = fields[i];
    if (field.getName() && field.setError) {
      field.setError(null);
    }
  }
  return this;
}, getErrors:function() {
  var errors = {}, fields, i, length, field, error;
  fields = this.getFields(false).filter(function(field) {
    return field.getName();
  });
  for (i = 0, length = fields.length; i < length; i++) {
    field = fields[i];
    error = field.getError();
    if (!error || !error.length) {
      error = null;
    }
    errors[field.getName()] = error;
  }
  return errors;
}, isValid:function() {
  var fields = this.getFields(false), i, length;
  for (i = 0, length = fields.length; i < length; i++) {
    if (!fields[i].isValid()) {
      return false;
    }
  }
  return true;
}, validate:function(skipLazy) {
  var fields = this.getFields(false), valid = true, i, length;
  for (i = 0, length = fields.length; i < length; i++) {
    if (!fields[i].validate(skipLazy)) {
      valid = false;
    }
  }
  return valid;
}, getFields:function(byName, deep) {
  var relation = deep === false ? '\x3e' : '', selector = relation + 'field' + (byName ? '[name\x3d' + byName + ']' : ''), fields = this.query(selector), asArray = byName === false, obj, i, length, field, name, bucket;
  if (!fields && asArray) {
    return [];
  } else {
    if (fields && !asArray) {
      if (!byName) {
        obj = {};
        for (i = 0, length = fields.length; i < length; i++) {
          field = fields[i];
          name = field.getName();
          bucket = obj[name];
          if (bucket) {
            if (Ext.isArray(bucket)) {
              bucket.push(field);
            } else {
              obj[name] = [bucket, field];
            }
          } else {
            obj[name] = field;
          }
        }
        return obj;
      } else {
        if (fields.length < 2) {
          return fields[0];
        }
      }
    }
  }
  return fields;
}, getFocusedField:function() {
  var fields = this.getFields(false), ln = fields.length, field, i;
  for (i = 0; i < ln; i++) {
    field = fields[i];
    if (field.hasFocus) {
      return field;
    }
  }
  return null;
}, getNextField:function() {
  var fields = this.getFields(false), focusedField = this.getFocusedField(), index;
  if (focusedField) {
    index = fields.indexOf(focusedField);
    if (index !== fields.length - 1) {
      index++;
      return fields[index];
    }
  }
  return false;
}, focusNextField:function() {
  var field = this.getNextField();
  if (field) {
    field.focus();
    return field;
  }
  return false;
}, getPreviousField:function() {
  var fields = this.getFields(false), focusedField = this.getFocusedField(), index;
  if (focusedField) {
    index = fields.indexOf(focusedField);
    if (index !== 0) {
      index--;
      return fields[index];
    }
  }
  return false;
}, focusPreviousField:function() {
  var field = this.getPreviousField();
  if (field) {
    field.focus();
    return field;
  }
  return false;
}});
Ext.define('Ext.mixin.FieldDefaults', {extend:Ext.Mixin, mixinConfig:{id:'fieldDefaults', before:{initInheritedState:'initInheritedState'}}, initInheritedState:function(inheritedState) {
  var me = this, fieldDefaults = me.fieldDefaults;
  if (fieldDefaults) {
    inheritedState.fieldDefaults = fieldDefaults;
  }
}});
Ext.define('Ext.field.Container', {extend:Ext.field.Field, xtype:['containerfield', 'fieldcontainer'], mixins:[Ext.field.Manager, Ext.mixin.ConfigProxy, Ext.mixin.FieldDefaults], config:{container:{xtype:'container', autoSize:null, defaultType:'textfield', defaults:{errorTarget:'parent'}, layout:{type:'hbox'}}}, proxyConfig:{container:{configs:['defaults', 'defaultType', 'items', 'layout', 'autoSize'], methods:['add', 'insert', 'remove', 'removeAll', 'getAt', 'child', 'down', 'query']}}, bodyAlign:'stretch', 
classCls:Ext.baseCSSPrefix + 'containerfield', isField:false, isContainer:true, isContainerField:true, errorTpl:'\x3ctpl if\x3d"count \x3d\x3d 1"\x3e' + '\x3ctpl for\x3d"errors"\x3e{label:htmlEncode}: {error:htmlEncode}\x3c/tpl\x3e' + '\x3ctpl elseif\x3d"count"\x3e' + '\x3cul class\x3d"{listCls}"\x3e' + '\x3ctpl for\x3d"errors"\x3e' + '\x3cli\x3e{label:htmlEncode}: {error:htmlEncode}\x3c/li\x3e' + '\x3c/tpl\x3e' + '\x3c/ul\x3e' + '\x3c/tpl\x3e', doDestroy:function() {
  this.setContainer(null);
  this.callParent();
}, applyContainer:function(container, oldContainer) {
  if (container) {
    if (!container.isInstance) {
      container = this.mergeProxiedConfigs('container', container);
      container.$initParent = this;
      container = Ext.create(container);
      delete container.$initParent;
    }
    container.ownerCmp = this;
  }
  return container;
}, updateContainer:function(container, oldContainer) {
  var bodyElement = this.bodyElement;
  if (oldContainer) {
    bodyElement.removeChild(oldContainer.el);
    oldContainer.destroy();
  }
  if (container) {
    bodyElement.appendChild(container.el);
  }
}, updateRecord:function(record) {
  this.consumeRecord(record);
}, onFieldErrorChange:function(field) {
  var me = this, errors = me.getErrors(), fields = me.getFields(), name, fieldErrors, label, messages;
  for (name in errors) {
    field = fields[name];
    fieldErrors = errors[name];
    if (fieldErrors) {
      label = field.getLabel() || field.getPlaceholder() || field.getName();
      fieldErrors = Ext.Array.from(fieldErrors).map(function(error) {
        return {label:label, error:error};
      });
      if (messages) {
        messages = messages.concat(fieldErrors);
      } else {
        messages = fieldErrors;
      }
    }
  }
  me.setError(messages || null);
}, getRefItems:function(deep) {
  var refItems = [], container = this.getContainer();
  if (container) {
    refItems.push(container);
    if (deep && container.getRefItems) {
      refItems.push.apply(refItems, container.getRefItems(deep));
    }
  }
  return refItems;
}, getFocusEl:function() {
  var items = this.getFields(false), length = items && items.length, i, item, focusEl;
  for (i = 0; i < length; i++) {
    item = items[i];
    focusEl = item.getFocusEl();
    if (focusEl) {
      return focusEl;
    }
  }
  return this.callParent();
}, reset:function(clearInvalid) {
  if (clearInvalid) {
    this.setError(null);
  }
  return this.mixins.fieldmanager.reset.call(this, clearInvalid);
}, setErrors:function(errors) {
  var me = this, fields = me.getFields(), fieldname, field, messages;
  if (!Ext.isObject(errors)) {
    Ext.raise('setErrors requires an Object parameter');
  }
  me.setError(null);
  for (fieldname in errors) {
    field = fields[fieldname];
    if (field) {
      messages = errors[fieldname];
      if (messages == null || Ext.isArray(messages) && messages.length === 0) {
        field.setError(null);
      } else {
        field.setError(Ext.Array.from(messages));
      }
    }
  }
  return me;
}, isValid:function() {
  return this.mixins.fieldmanager.isValid.call(this);
}, validate:function(skiplazy) {
  return this.mixins.fieldmanager.validate.call(this, skiplazy);
}, getFields:function(byName, deep) {
  if (deep == null) {
    deep = false;
  }
  return this.mixins.fieldmanager.getFields.call(this, byName, deep);
}});
Ext.define('Ext.field.FieldGroupContainer', {extend:Ext.field.Container, xtype:'groupcontainer', config:{vertical:false, fieldsName:undefined, defaultFieldValue:'on'}, delegate:'[isField]', shareableName:true, container:{cls:Ext.baseCSSPrefix + 'group-inner-container', layout:{type:'box'}, defaults:{labelAlign:'right'}}, verticalCls:Ext.baseCSSPrefix + 'field-group-vertical', classCls:Ext.baseCSSPrefix + 'field-group-container', defaultBindProperty:'value', initialize:function() {
  var me = this;
  me.callParent();
  me.on({change:'onGroupChange', delegate:me.delegate, scope:me});
  me.getContainer().on({add:'onGroupItemAdd', scope:me});
  me.validate();
  me.resetOriginalValue();
}, applyFieldsName:function(name) {
  return name || this.getName() || this.getId();
}, updateVertical:function(vertical) {
  this.getContainer().toggleCls(this.verticalCls, vertical);
}, updateFieldsName:function(name, oldName) {
  var items = this.getGroupItems(), ln = items.length, item, itemName, i;
  for (i = 0; i < ln; i++) {
    item = items[i];
    itemName = item.getName();
    if (itemName === null || itemName === oldName) {
      item.setName(name);
    }
  }
}, updateDefaultFieldValue:function(value, oldValue) {
  var items = this.getGroupItems(), ln = items.length, item, itemValue, i;
  for (i = 0; i < ln; i++) {
    item = items[i];
    itemValue = item.getValue();
    if (itemValue === '' || itemValue === oldValue) {
      item.setValue(value);
    }
  }
}, getGroupItems:function(query) {
  return this.query(this.delegate + (query || ''));
}, getValue:function(enabled, all) {
  return this.getValues(enabled, all);
}, setValue:function(value) {
  var me = this;
  if (me.isEqual(value, me.getValue())) {
    return me;
  }
  me.setValues(value);
  return me;
}, isEqual:function(value1, value2) {
  return Ext.Object.equals(value1, value2);
}, isValid:function() {
  var value = this.getValue(), required = this.getRequired();
  if (required && Ext.Object.isEmpty(value)) {
    return false;
  }
  return true;
}, onGroupChange:function() {
  var me = this, newVal, oldVal;
  if (me.isConfiguring || me.isDestructing() || me.suspendCheckChange) {
    return;
  }
  newVal = me.getValue();
  oldVal = me.lastValue || me.originalValue;
  if (!me.isEqual(newVal, oldVal)) {
    me.lastValue = newVal;
    me.fireEvent('change', me, newVal, oldVal);
    me.validate();
  }
}, initializeItemsConfig:function(item) {
  var fieldsName, defaultFieldValue;
  if (!item.isCheckbox) {
    return;
  }
  fieldsName = this.getFieldsName();
  defaultFieldValue = this.getDefaultFieldValue();
  if (item.getName() === null) {
    item.setName(fieldsName);
  }
  if (!item.getValue()) {
    item.setValue(defaultFieldValue);
  }
}, handleContainerAdd:function(container) {
  var me = this, innerItems = container.getInnerItems(), ln = innerItems.length, i, item;
  for (i = 0; i < ln; i++) {
    item = innerItems[i];
    if (item.isContainer) {
      me.handleContainerAdd(item);
      item.on('add', 'onGroupItemAdd', me);
      continue;
    }
    me.initializeItemsConfig(item);
  }
}, onGroupItemAdd:function(container, item) {
  if (item.isContainer) {
    this.handleContainerAdd(item);
    item.on('add', 'onGroupItemAdd', this);
    return;
  }
  this.initializeItemsConfig(item);
}, validate:function(skipLazy) {
  var me = this, isValid = true, empty, errors, value;
  if (!me.getRequired()) {
    return isValid;
  }
  if (!me.getDisabled() || me.getValidateDisabled()) {
    errors = [];
    value = me.getValue();
    value = Ext.Object.isEmpty(value) ? '' : value;
    empty = value === '' || value == null;
    if (empty) {
      errors.push(me.getErrorMessage() || me.getRequiredMessage());
    } else {
      value = me.parseValue(value, errors);
      me.doValidate(value, errors, skipLazy);
    }
    me.updateErrorMessage(errors.join(''));
    if (errors.length) {
      isValid = false;
    }
  }
  return isValid;
}});
Ext.define('Ext.field.CheckboxGroup', {extend:Ext.field.FieldGroupContainer, xtype:'checkboxgroup', isCheckboxGroup:true, defaultType:'checkbox', delegate:'[isCheckbox]', instanceCls:Ext.baseCSSPrefix + 'checkbox-group', setValue:function(value) {
  var me = this, items, ln, item, name, b, cbValue, cbName;
  if (me.isEqual(value, me.lastValue)) {
    return me;
  }
  items = me.getGroupItems();
  ln = items.length;
  me.suspendCheckChange = 1;
  for (b = 0; b < ln; b++) {
    item = items[b];
    name = item.getName();
    cbValue = false;
    if (value) {
      cbName = value[name];
      if (Ext.isArray(cbName)) {
        cbValue = Ext.Array.contains(cbName, item.getValue());
      } else {
        cbValue = cbName;
      }
    }
    item.setChecked(cbValue);
  }
  me.suspendCheckChange = 0;
  me.onGroupChange();
  return me;
}, getValue:function() {
  var items = this.getGroupItems(), ln = items.length, values = {}, item, name, value, bucket, b;
  for (b = 0; b < ln; b++) {
    item = items[b];
    name = item.getName();
    value = item.getValue();
    if (value && item.getChecked()) {
      if (values.hasOwnProperty(name)) {
        bucket = values[name];
        if (!Ext.isArray(bucket)) {
          bucket = values[name] = [bucket];
        }
        bucket.push(value);
      } else {
        values[name] = value;
      }
    }
  }
  return values;
}});
Ext.define('Ext.field.ChipViewNavigationModel', {extend:Ext.dataview.BoundListNavigationModel, alias:'navmodel.fieldchipview', privates:{getKeyNavCfg:function(view) {
  var me = this, eventEl;
  if (this.keyboard !== false) {
    eventEl = (view.ownerField || view).getFocusEl();
    if (eventEl) {
      return {target:eventEl, eventName:'keydown', processEvent:view.ownerField ? me.processViewEvent : undefined, processEventScope:me, defaultEventAction:'stopEvent', 'delete':me.onKeyDelete, backspace:me.onKeyDelete, right:me.onKeyRight, left:me.onKeyLeft, A:{ctrl:true, handler:me.onSelectAllKeyPress}, priority:1002, scope:me};
    }
  }
}, processViewEvent:function(e) {
  var me = this, ownerField = me.getView().ownerField;
  if (ownerField) {
    if (ownerField.inputElement.dom.value.length || !ownerField.getValueCollection().getCount()) {
      me.clearLocation();
      return;
    }
  }
  return e;
}, onKeyLeft:function(e) {
  var me = this, view = me.getView(), location = me.location, options = {event:e};
  e.preventDefault();
  if (location) {
    if (!location.isFirstDataItem()) {
      if (!e.shiftKey) {
        view.getSelectable().deselectAll();
      }
      me.movePrevious(options);
    }
  } else {
    me.setLocation(view.getLastDataItem(), options);
  }
  return true;
}, onKeyRight:function(e) {
  var me = this, view = me.getView(), location = me.location;
  e.preventDefault();
  if (location) {
    if (location.isLastDataItem()) {
      view.getSelectable().deselectAll();
      me.clearLocation();
    } else {
      if (!e.shiftKey) {
        view.getSelectable().deselectAll();
      }
      me.moveNext({event:e});
    }
  }
  return true;
}, onKeyDelete:function(e) {
  var view = this.getView(), ownerField = view.ownerField, selModel, selected, location, isLast;
  if (ownerField) {
    selModel = view.getSelectable();
    selected = selModel.getSelectedRecords();
    if (selected.length) {
      selModel.deselect(selected);
      ownerField.getValueCollection().remove(selected);
      location = this.getLocation();
      if (location) {
        isLast = location.isLast();
        if (isLast && e.keyCode === e.DELETE) {
          this.clearLocation();
        } else {
          if (view.dataItems.length) {
            selModel.select(location.refresh().record);
          }
        }
      }
    } else {
      if (e.keyCode === e.BACKSPACE) {
        this.onKeyLeft(e);
      }
    }
  }
}, onNavigate:function(event) {
  var view = this.getView(), ownerField = view.ownerField, location = this.getLocation;
  if (ownerField) {
    if (!location || !view.getSelectable().isSelected(location.record)) {
      Ext.dataview.NavigationModel.prototype.onNavigate.call(this, event);
    }
  } else {
    this.callParent([event]);
  }
}}});
Ext.define('Ext.field.trigger.Expand', {extend:Ext.field.trigger.Trigger, xtype:'expandtrigger', alias:'trigger.expand', classCls:Ext.baseCSSPrefix + 'expandtrigger', isExpandTrigger:true, handler:'onExpandTap', scope:'this'});
Ext.define('Ext.field.Picker', {extend:Ext.field.Text, xtype:'pickerfield', config:{picker:{lazy:true, $value:'auto'}, floatedPicker:{lazy:true, $value:null}, edgePicker:{lazy:true, $value:null}, clearable:false, matchFieldWidth:true, floatedPickerAlign:'tl-bl?', pickerSlotAlign:'center', hideTrigger:false, focusTrap:{lazy:true, $value:{tabIndex:-1, cls:'x-hidden-clip'}}}, triggers:{expand:{type:'expand'}}, alignTarget:'bodyElement', keyMap:{scope:'this', DOWN:'onDownArrow', ESC:'onEsc'}, keyMapTarget:'inputElement', 
autoComplete:false, classCls:Ext.baseCSSPrefix + 'pickerfield', initialize:function() {
  var me = this;
  me.callParent();
  Ext.on('hide', 'onGlobalHide', me);
  me.inputElement.on('click', 'onInputElementClick', me);
}, onFocusEnter:function(info) {
  this.callParent([info]);
  if (Ext.isTouchMode() && info.event.toElement === this.inputElement.dom) {
    this.getFocusTrap().focus();
    this.expand();
  }
}, onFocusMove:function(info) {
  var me = this, focusTrap;
  me.callParent([info]);
  if (Ext.isTouchMode()) {
    focusTrap = me.getFocusTrap();
    if (info.fromElement === focusTrap.dom && info.toElement === me.getFocusEl().dom) {
      if (me.getEditable()) {
        me.collapse();
      } else {
        focusTrap.focus();
        me.expand();
      }
    }
  }
}, onFocusLeave:function(e) {
  this.callParent([e]);
  this.collapse();
}, onEsc:function(e) {
  if (Ext.isIE) {
    e.preventDefault();
  }
  if (this.expanded) {
    this.collapse();
    e.stopEvent();
  }
}, onDownArrow:function(e) {
  var me = this;
  if (e.time - me.lastDownArrow > 150) {
    delete me.lastDownArrow;
  }
  if (!me.expanded) {
    e.stopEvent();
    me.onExpandTap();
    me.setPickerLocation(true);
    me.lastDownArrow = e.time;
  } else {
    if (!e.stopped && e.time - me.lastDownArrow < 150) {
      delete me.lastDownArrow;
    }
  }
}, setPickerLocation:Ext.emptyFn, updateHideTrigger:function(hideTrigger) {
  var triggers = this.getTriggers(), expand = triggers && triggers.expand;
  if (expand) {
    expand.setHidden(hideTrigger);
  }
}, applyPicker:function(picker) {
  var me = this, pickerListeners = {show:'onPickerShow', hide:'onPickerHide', scope:me}, type = picker, config;
  if (!type) {
    type = 'auto';
  } else {
    if (Ext.isObject(picker)) {
      type = null;
      if (!picker.isWidget && !picker.xtype) {
        config = picker;
        type = 'auto';
      }
    }
  }
  if (type) {
    if (type === 'auto') {
      type = me.getAutoPickerType();
    }
    if (type === 'edge') {
      picker = me.createEdgePicker(config);
    } else {
      if (type !== 'floated') {
        Ext.raise('Picker type must be "edge" or "floated" not "' + type + '"');
      } else {
        picker = me.createFloatedPicker(config);
        pickerListeners.resize = pickerListeners.hiddenchange = 'realignFloatedPicker';
      }
    }
  }
  if (picker.isWidget) {
    picker.ownerField = me;
  } else {
    picker = Ext.apply({ownerField:me}, picker);
    me.fireEvent('beforepickercreate', me, picker);
    picker = Ext.create(picker);
  }
  me.pickerType = type || (picker.isViewportMenu ? 'edge' : 'floated');
  me.fireEvent('pickercreate', me, picker);
  picker.on(pickerListeners);
  return picker;
}, getAutoPickerType:function() {
  return Ext.platformTags.phone ? 'edge' : 'floated';
}, getRefItems:function(deep) {
  var me = this, result = me.callParent([deep]), picker = me.getConfig('picker', false, true);
  if (picker) {
    result.push(picker);
    if (deep) {
      Ext.Array.push(result, picker.getRefItems(deep));
    }
  }
  return result;
}, updatePicker:function(picker) {
  var value = this.getValue();
  if (picker && picker.setValue && value != null) {
    if (this.pickerType === 'floated' || picker.isPicker) {
      picker.setValue(value);
    }
  }
}, applyFocusTrap:function(focusTrap) {
  var result = this.el.appendChild(Ext.dom.Element.create(focusTrap));
  result.$isFocusTrap = true;
  return result;
}, onResize:function() {
  var me = this, picker = me.getConfig('picker', false, true), GlobalEvents = Ext.GlobalEvents, scrollableAncestor;
  if (picker && me.pickerType === 'floated' && picker.isVisible()) {
    scrollableAncestor = me.up('[scrollable]');
    if (scrollableAncestor) {
      scrollableAncestor = scrollableAncestor.getScrollable();
      GlobalEvents.suspendEvent('scroll');
      scrollableAncestor.ensureVisible(me.el);
    }
    me.realignFloatedPicker();
    if (scrollableAncestor) {
      Ext.defer(GlobalEvents.resumeEvent, 100, GlobalEvents, ['scroll']);
    }
  }
}, realignFloatedPicker:function(picker) {
  var me = this;
  picker = picker || me.getConfig('picker', false, true);
  if (picker && picker.isVisible()) {
    if (me.getMatchFieldWidth()) {
      picker.setWidth(me[me.alignTarget].getWidth());
    }
    picker.realign(me[me.alignTarget], me.getFloatedPickerAlign(), {minHeight:100});
    if (!Ext.keyboardMode) {
      me.setPickerLocation();
    }
  }
}, onInputElementClick:function(e) {
  var me = this;
  if (e.pointerType === 'mouse' && (!me.getEditable() && !me.getReadOnly())) {
    me[me.expanded ? 'collapse' : 'expand']();
  }
}, onExpandTap:function() {
  if (this.expanded) {
    if (Ext.now() - this.expanded > 100) {
      this.collapse();
    }
  } else {
    this.expand();
  }
  return false;
}, expand:function() {
  if (!this.expanded && !this.getReadOnly() && !this.getDisabled()) {
    this.showPicker();
  }
}, collapse:function() {
  var picker, eXt = Ext;
  if (this.expanded) {
    picker = this.getPicker();
    if (this.pickerType === 'edge') {
      eXt.Viewport.removeMenu(picker.getSide(), true);
    } else {
      picker.hide();
    }
  }
}, collapseIf:function(e) {
  var me = this;
  if (!me.destroyed && (!e.within(me.bodyElement, false, true) && !me.owns(e.target))) {
    me.collapse();
  }
}, showPicker:function() {
  var me = this, alignTarget = me[me.alignTarget], picker = me.getPicker();
  if (me.pickerType === 'floated') {
    if (me.getMatchFieldWidth()) {
      picker.setWidth(alignTarget.getWidth());
    }
    picker.showBy(alignTarget, me.getFloatedPickerAlign(), {minHeight:100});
    me.touchListeners = Ext.getDoc().on({translate:false, touchstart:me.collapseIf, scope:me, delegated:false, destroyable:true});
  } else {
    me.setShowPickerValue(picker);
    picker.show();
  }
}, updatePickerValue:function(picker, value) {
  var slot = picker.getSlots()[0], name = slot.name || slot.getName(), pickerValue = {};
  pickerValue[name] = value;
  picker.setValue(pickerValue);
}, onPickerShow:function() {
  var me = this;
  me.expanded = Ext.now();
  if (me.pickerType === 'edge') {
    me.el.dom.scrollIntoView();
  }
  if (me.pickerType === 'edge') {
    me.el.dom.scrollIntoView();
  }
  me.hideEventListeners = Ext.on({mousedown:'collapseIf', scroll:'onGlobalScroll', scope:me, destroyable:true});
  me.fireEvent('expand', me);
}, onPickerHide:function() {
  var me = this;
  me.expanded = false;
  Ext.destroy(me.hideEventListeners, me.touchListeners);
  me.fireEvent('collapse', me);
}, doDestroy:function() {
  this.destroyMembers('picker', 'hideEventListeners', 'touchListeners', 'focusTrap');
  this.callParent();
}, privates:{isFocusing:function(info) {
  return info.event.toElement === this.getFocusTrap().dom || this.callParent([info]);
}, isBlurring:function(info) {
  return info.event.fromElement === this.getFocusTrap().dom || this.callParent([info]);
}, onGlobalHide:function(cmp) {
  if (this === cmp || cmp.isAncestor(this)) {
    this.collapse();
  }
}, onGlobalScroll:function(scroller, x, y) {
  var me = this, scrollingEl = scroller.getElement();
  if (me.expanded) {
    if (me.pickerType === 'edge') {
      return;
    }
    if (!me.getPicker().owns(scrollingEl) && scrollingEl.dom !== document.body) {
      me.collapse();
    }
  }
}, revertFocusTo:function(target) {
  if (Ext.isTouchMode()) {
    this.getFocusTrap().focus();
  } else {
    target.focus();
  }
}, setShowPickerValue:function(picker) {
  var value = this.getValue();
  if (value != null) {
    this.updatePickerValue(picker, value);
  }
}}});
Ext.define('Ext.picker.Slot', {extend:Ext.dataview.DataView, xtype:'pickerslot', isSlot:true, config:{title:null, showTitle:true, cls:Ext.baseCSSPrefix + 'picker-slot', name:null, value:null, flex:1, align:'left', displayField:'text', valueField:'value', itemTpl:null, scrollable:{x:false, y:true, scrollbars:false}, verticallyCenterItems:true}, focusable:false, tabIndex:null, focusEl:null, itemsFocusable:false, scrollToTopOnRefresh:false, snapSelector:'.' + Ext.baseCSSPrefix + 'dataview-item', deselectable:false, 
navigationModel:{type:'boundlist', keyboard:false}, onFocusEnter:Ext.emptyFn, onFocusLeave:Ext.emptyFn, applyTitle:function(title) {
  if (title) {
    title = Ext.create('Ext.Component', {cls:Ext.baseCSSPrefix + 'picker-slot-title', docked:'top', html:title});
  }
  return title;
}, updateTitle:function(newTitle, oldTitle) {
  if (newTitle) {
    this.add(newTitle);
    this.setupBar();
  }
  if (oldTitle) {
    this.remove(oldTitle);
  }
}, updateShowTitle:function(showTitle) {
  var title = this.getTitle(), mode = showTitle ? 'show' : 'hide';
  if (title) {
    title.on(mode, this.setupBar, this, {single:true, delay:50});
    title[showTitle ? 'show' : 'hide']();
  }
}, updateDisplayField:function(newDisplayField) {
  if (!this.config.itemTpl) {
    this.setItemTpl('\x3cdiv class\x3d"' + Ext.baseCSSPrefix + 'picker-item {cls}\x3ctpl if\x3d"extra"\x3e ' + Ext.baseCSSPrefix + 'picker-invalid\x3c/tpl\x3e"\x3e' + '{' + newDisplayField + '}\x3c/div\x3e');
  }
}, updateAlign:function(newAlign, oldAlign) {
  this.element.swapCls(Ext.baseCSSPrefix + 'picker-' + oldAlign, Ext.baseCSSPrefix + 'picker-' + newAlign);
}, applyData:function(data) {
  var parsedData = [], ln = data && data.length, displayField = this.getDisplayField(), valueField = this.getDisplayField(), i, item, obj;
  if (data && Ext.isArray(data) && ln) {
    for (i = 0; i < ln; i++) {
      item = data[i];
      obj = {};
      if (Ext.isArray(item)) {
        obj[valueField] = item[0];
        obj[displayField] = item[1];
      } else {
        if (Ext.isPrimitive(item)) {
          obj[valueField] = item;
          obj[displayField] = item;
        } else {
          if (Ext.isObject(item)) {
            obj = item;
          }
        }
      }
      parsedData.push(obj);
    }
  }
  return data;
}, initialize:function() {
  this.callParent();
  this.on({scope:this, painted:'onPainted', single:true});
}, onPainted:function() {
  this.setupBar();
}, onResize:function() {
  var value = this.getValue();
  if (value) {
    this.setValue(value);
  }
}, getPicker:function() {
  if (!this.picker) {
    this.picker = this.getParent();
  }
  return this.picker;
}, setupBar:function() {
  if (!this.isPainted()) {
    return;
  }
  var me = this, title = me.getTitle(), titleHeight = me.getShowTitle() && title ? title.el.measure('h') : 0, barHeight = me.getPicker().bar.measure('h'), offset;
  if (me.getVerticallyCenterItems()) {
    offset = Math.ceil((me.el.measure('h') - titleHeight - barHeight) / 2);
    me.bodyElement.setStyle({'padding-top':offset + 'px'});
    if (!me.bottomSpacer) {
      me.bottomSpacer = me.add({xtype:'component', scrollDock:'end', height:offset, style:'pointer-events: none'});
    } else {
      me.bottomSpacer.setHeight(offset);
    }
  }
  me.setValue(me.getValue());
}, getScrollableClientRegion:function() {
  return this.picker.bar.getClientRegion();
}, navigateToItem:function(item, animation) {
  var navModel = this.getNavigationModel(), curLocation = navModel.getLocation(), newLocation = navModel.createLocation(item);
  if (!curLocation || curLocation.equals(newLocation)) {
    this.getScrollable().scrollIntoView(item, false, animation);
  } else {
    navModel.setLocation(newLocation, {animation:animation});
  }
}, onScrollEnd:function(x, y) {
  var me = this, picker = me.picker, ownerField = picker.ownerField, multiSelect = ownerField && ownerField.getMultiSelect && ownerField.getMultiSelect(), viewItems = me.getViewItems(), index, item;
  if (picker.isVisible()) {
    index = Ext.Number.constrain(Math.round(y / Ext.fly(viewItems[0]).measure('h')), 0, viewItems.length - 1);
    item = viewItems[index];
    if (item) {
      if (multiSelect) {
        me.navigateToItem(item);
      } else {
        me.setValue(me.getStore().getAt(index).get(me.getValueField()), true);
      }
      me.fireEvent('slotpick', me, me.getValue(), item);
    }
  }
}, getValue:function(useDom) {
  if (this._value === false) {
    return null;
  }
  if (!useDom) {
    return this._value;
  }
  var me = this, valueField = me.getValueField(), ownerField = me.picker.ownerField, multiSelect = ownerField && ownerField.getMultiSelect && ownerField.getMultiSelect(), valueCollection = me.getSelected();
  return valueCollection.getCount() ? multiSelect ? valueCollection.collect(valueField, 'data') : valueCollection.first().get(valueField) : null;
}, setValue:function(value, animation) {
  var me = this, store = me.getStore(), index = !Ext.isEmpty(value) && store ? store.findExact(me.getValueField(), value) : -1, selection;
  if (index === -1) {
    value = null;
  } else {
    selection = store.getAt(index);
  }
  if (selection) {
    me.select(selection);
    if (me.refreshCounter) {
      me.getNavigationModel().setLocation(selection, {animation:animation});
    }
  }
  me._value = value;
}});
Ext.define('Ext.picker.Picker', {extend:Ext.Sheet, xtype:'picker', alternateClassName:'Ext.Picker', isPicker:true, config:{doneButton:true, cancelButton:true, useTitles:false, slots:null, value:null, height:220, layout:{type:'hbox', align:'stretch'}, centered:false, left:0, right:0, bottom:0, defaultType:'pickerslot', toolbarPosition:'top', toolbar:{xtype:'titlebar'}, side:'bottom'}, baseCls:Ext.baseCSSPrefix + 'picker', floated:true, focusable:true, tabIndex:-1, constructor:function(config) {
  this.callParent([config]);
  if (config && 'value' in config) {
    this.setValue(config.value);
  }
}, initialize:function() {
  this.callParent();
  this.on({scope:this, delegate:'pickerslot', slotpick:'onSlotPick'});
}, getTemplate:function() {
  var me = this, clsPrefix = Ext.baseCSSPrefix, template = me.callParent();
  template[0].children[0].children = [{reference:'mask', cls:clsPrefix + 'picker-mask', children:[{reference:'bar', cls:clsPrefix + 'picker-bar'}]}];
  return template;
}, applyToolbar:function(config, oldToolbar) {
  if (config) {
    if (config === true) {
      config = {};
    }
    Ext.applyIf(config, {docked:this.getToolbarPosition()});
  }
  return Ext.factory(config, 'Ext.TitleBar', oldToolbar);
}, updateToolbar:function(newToolbar) {
  if (newToolbar) {
    this.add(newToolbar);
  }
}, applyDoneButton:function(config, oldButton) {
  if (config) {
    if (config === true) {
      config = {};
    }
    if (typeof config === 'string') {
      config = {text:config};
    }
    Ext.applyIf(config, {align:'right', text:'Done'});
  }
  return Ext.factory(config, 'Ext.Button', oldButton);
}, updateDoneButton:function(newDoneButton) {
  var toolbar = this.getToolbar();
  if (newDoneButton) {
    toolbar.add(newDoneButton);
    newDoneButton.on('tap', this.onDoneButtonTap, this);
  }
}, applyCancelButton:function(config, oldButton) {
  if (config) {
    if (Ext.isBoolean(config)) {
      config = {};
    }
    if (typeof config === 'string') {
      config = {text:config};
    }
    Ext.applyIf(config, {align:'left', text:'Cancel'});
  }
  return Ext.factory(config, 'Ext.Button', oldButton);
}, updateCancelButton:function(newCancelButton) {
  var toolbar = this.getToolbar();
  if (newCancelButton) {
    toolbar.add(newCancelButton);
    newCancelButton.on('tap', this.onCancelButtonTap, this);
  }
}, updateUseTitles:function(useTitles) {
  var innerItems = this.getInnerItems(), ln = innerItems.length, cls = Ext.baseCSSPrefix + 'use-titles', i, innerItem;
  this.toggleCls(cls, useTitles);
  for (i = 0; i < ln; i++) {
    innerItem = innerItems[i];
    if (innerItem.isSlot) {
      innerItem.setShowTitle(useTitles);
    }
  }
}, applySlots:function(slots) {
  if (slots) {
    var ln = slots.length, i;
    for (i = 0; i < ln; i++) {
      slots[i].picker = this;
    }
  }
  return slots;
}, updateSlots:function(newSlots) {
  var me = this, bcss = Ext.baseCSSPrefix, innerItems;
  me.removeAll();
  if (newSlots) {
    me.add(newSlots);
  }
  innerItems = me.getInnerItems();
  if (innerItems.length > 0) {
    innerItems[0].addCls(bcss + 'first');
    innerItems[innerItems.length - 1].addCls(bcss + 'last');
  }
  me.updateUseTitles(me.getUseTitles());
  me.setValue(me.getValue());
}, onDoneButtonTap:function() {
  var me = this, oldValue = me._value, newValue = me.getValue(true);
  if (newValue !== oldValue) {
    me._values = me._value = newValue;
    me.fireEvent('change', me, newValue);
  }
  me.hide();
  Ext.util.InputBlocker.unblockInputs();
}, onCancelButtonTap:function() {
  this.fireEvent('cancel', this);
  this.hide();
  Ext.util.InputBlocker.unblockInputs();
}, onSlotPick:function(slot) {
  this.fireEvent('pick', this, this.getValue(true), slot);
}, afterShow:function() {
  this.callParent();
  this.scrollSlotsIntoView();
  Ext.util.InputBlocker.blockInputs();
}, updateDisplayed:function(displayed, oldDisplayed) {
  this.callParent([displayed, oldDisplayed]);
  Ext.util.InputBlocker.blockInputs();
}, scrollSlotsIntoView:function() {
  var slots = this.getInnerItems(), i, slot, location;
  for (i = 0; i < slots.length; i++) {
    slot = slots[i];
    location = slot.getNavigationModel().location;
    slot.navigateToItem(location ? location.item : slot.itemFromRecord(0));
  }
}, setValue:function(values, animated) {
  var me = this, slots = me.getInnerItems(), ln = slots.length, key, slot, i, value;
  if (!values) {
    values = {};
    for (i = 0; i < ln; i++) {
      values[slots[i].getName()] = null;
    }
  }
  for (key in values) {
    value = values[key];
    for (i = 0; i < slots.length; i++) {
      slot = slots[i];
      if (slot.getName() === key) {
        if (animated) {
          slot.setValueAnimated(value);
        } else {
          slot.setValue(value);
        }
        break;
      }
    }
  }
  me._values = me._value = values;
  return me;
}, setValueAnimated:function(values) {
  this.setValue(values, true);
}, getValue:function(useDom) {
  var values = {}, items = this.getItems().items, ln = items.length, item, i;
  if (useDom) {
    for (i = 0; i < ln; i++) {
      item = items[i];
      if (item && item.isSlot) {
        values[item.getName()] = item.getValue(useDom);
      }
    }
    this._values = values;
  }
  return this._values;
}, getValues:function() {
  return this.getValue();
}});
Ext.define('Ext.picker.Tablet', {extend:Ext.Panel, xtype:'tabletpicker', isPicker:true, focusable:true, tabIndex:-1});
Ext.define('Ext.picker.SelectPicker', {extend:Ext.picker.Picker, xtype:'selectpicker', constructor:function(config) {
  var ownerField = config.ownerCmp, id = ownerField.getId() + '-picker', realConfig = Ext.apply({ownerField:ownerField, id:id, slots:[{id:id + '-slot', ownerField:ownerField, selectable:config.selectable || true, align:ownerField.getPickerSlotAlign(), name:ownerField.getValueField(), valueField:ownerField.getValueField(), displayField:ownerField.getDisplayField(), value:ownerField.getValue(), store:ownerField._pickerStore || ownerField.getStore(), itemTpl:ownerField.getItemTpl(), itemCls:ownerField.getItemCls()}]}, 
  config);
  if (ownerField.getMultiSelect()) {
    realConfig.cancelButton = false;
    realConfig.slots[0].selectable = {selected:ownerField.getValueCollection(), selectedRecord:ownerField.getSelection(), deselectable:true, mode:'multi'};
  } else {
    realConfig.listeners = {change:'onPickerChange', scope:this};
  }
  this.callParent([realConfig]);
  this.slot = Ext.getCmp(id + '-slot');
}, onPickerChange:function(picker, value) {
  var ownerField = this.ownerField;
  ownerField.setValue(ownerField.findRecordByValue(value[ownerField.getValueField()]));
}, refresh:function() {
  this.slots.refresh();
}, setDisableSelection:function(disableSelection) {
  return this.slot.setDisableSelection(disableSelection);
}, setValue:function(value) {
  if (this.slot) {
    this.slot.setValue(value);
  }
  return this;
}, getEmptyText:function() {
  return this.slot.getEmptyText();
}, getItemCount:function() {
  return this.slot.getItemCount();
}, getNavigationModel:function() {
  return this.slot.getNavigationModel();
}, getSelectable:function() {
  return this.slot.getSelectable();
}, getViewItems:function() {
  return this.slot.getViewItems();
}, getStore:function() {
  return this.slot.getStore();
}, setStore:function(store) {
  this.slot.setStore(store);
}, deselectAll:function() {
  this.slot.deselectAll();
}});
Ext.define('Ext.field.Select', {extend:Ext.field.Picker, xtype:'selectfield', alternateClassName:'Ext.form.Select', isSelectField:true, config:{valueCollection:{rootProperty:'data'}, valueField:'value', itemTpl:false, itemCls:null, displayTpl:null, displayField:'text', store:null, options:null, hiddenName:null, autoSelect:false, autoFocus:true, autoFocusLast:true, selection:null, autoLoadOnValue:false, forceSelection:true, valueNotFoundText:null, selectOnTab:true, multiSelect:null, delimiter:',', 
filterPickList:false, collapseOnSelect:null, chipView:{$value:{xtype:'chipview', tabIndex:null, focusable:false, itemsFocusable:false, focusedCls:'', navigationModel:'fieldchipview', selectable:{mode:'multi'}, closable:true, closeHandler:'up.onChipCloseTap'}, lazy:true}, recordCreator:null, recordCreatorScope:null}, editable:false, floatedPicker:{xtype:'boundlist', infinite:false, navigationModel:{disabled:true}, scrollToTopOnRefresh:false, loadingHeight:70, maxHeight:300, floated:true, axisLock:true, 
hideAnimation:null}, edgePicker:{xtype:'selectpicker', cover:true}, classCls:Ext.baseCSSPrefix + 'selectfield', multiSelectCls:Ext.baseCSSPrefix + 'multiselect', twoWayBindable:{selection:1}, publishes:{selection:1}, applyValueCollection:function(valueCollection) {
  if (!valueCollection.isCollection) {
    valueCollection = new Ext.util.Collection(valueCollection);
  }
  valueCollection.addObserver(this);
  return valueCollection;
}, createSelectionRecord:function(data) {
  var Model = this.getStore().getModel();
  return new Model(data);
}, completeEdit:Ext.emptyFn, expand:function() {
  if (this.getStore()) {
    this.callParent();
  }
}, getRefItems:function(deep) {
  var me = this, result = me.callParent([deep]), chipView = me.chipView;
  if (chipView) {
    result.push(chipView);
    if (deep) {
      Ext.Array.push(result, chipView.getRefItems(deep));
    }
  }
  return result;
}, maybeCollapse:function(event) {
  var record = event.to && event.to.record, multi = this.getMultiSelect(), selection = this.getSelection();
  if (!multi && record === selection) {
    this.collapse();
  }
}, onCollectionRemove:function(valueCollection, chunk) {
  var me = this, selection = valueCollection.getRange();
  if (!chunk.replacement) {
    me.processingCollectionMutation = true;
    me.setSelection(selection.length ? me.getMultiSelect() ? selection : selection[0] : null);
    me.processingCollectionMutation = false;
  }
}, onCollectionAdd:function(valueCollection, adds) {
  var selection = valueCollection.getRange();
  this.processingCollectionMutation = true;
  this.setSelection(this.getMultiSelect() ? selection : selection[0]);
  this.processingCollectionMutation = false;
}, onCollectionEndUpdate:function() {
  var me = this, pickerStore = me._pickerStore, chipView, chipViewNavModel;
  if (me.getMultiSelect()) {
    chipView = me.chipView;
    chipViewNavModel = chipView.getNavigationModel();
    if (chipViewNavModel.location && !me.getValueCollection().contains(chipViewNavModel.location.record)) {
      chipViewNavModel.clearLocation();
    }
    chipView.getSelectable().refreshSelection();
  } else {
    me.setFieldDisplay();
  }
  if (pickerStore && me.getFilterPickList()) {
    pickerStore.getData().onFilterChange();
  }
}, clearValue:function() {
  var me = this;
  me.forceSetValue(null);
  me.syncEmptyState();
}, applyValue:function(value, oldValue) {
  var me = this, store;
  me.getOptions();
  store = me.getStore();
  me.syncMode = 'value';
  if (value && value.isEntity) {
    if (!store || !store.getDataSource().contains(value)) {
      value.isEntered = true;
    }
    me.setSelection(value);
    return;
  }
  if (me.isConfiguring) {
    me.originalValue = value;
  }
  if (store && value) {
    if (me.getAutoLoadOnValue() && !store.isLoaded() && !store.hasPendingLoad()) {
      store.load();
    }
  }
  return me.transformValue(value);
}, updateValue:function(value, oldValue) {
  var me = this;
  me.syncValue();
  if (me.getMultiSelect() ? !value || !oldValue || !Ext.Array.equals(value, oldValue) : value !== oldValue) {
    Ext.field.Field.prototype.updateValue.call(this, value, oldValue);
  }
}, transformValue:function(value) {
  if (value == null || value === '') {
    value = this.getForceSelection() ? null : '';
  } else {
    if (this.getMultiSelect()) {
      value = Ext.Array.from(value);
    } else {
      if (Ext.isIterable(value)) {
        value = value[0];
      }
    }
  }
  return value;
}, findRecordByValue:function(value) {
  var me = this, store = me.getStore(), valueField = me.getValueField(), result, ret = null;
  if (store) {
    result = store.byValue.get(value);
    if (result) {
      ret = result[0] || result;
    }
  }
  if (!ret) {
    ret = me.getValueCollection().findBy(function(record) {
      return record.get(valueField) === value;
    });
  }
  return ret;
}, findRecordByDisplay:function(value) {
  var store = this.getStore(), result, ret = false;
  if (store) {
    result = store.byText.get(value);
    if (result) {
      ret = result[0] || result;
    }
  }
  return ret;
}, applyChipView:function(chipView, existingChipView) {
  return Ext.updateWidget(existingChipView, chipView, this, 'createChipView');
}, updateChipView:function(chipView) {
  if (chipView) {
    chipView.on({element:'bodyElement', touchstart:'onChipBodyTouchStart', tap:'onChipBodyTap', scope:this, priority:1000});
  }
  this.chipView = chipView;
}, applySelection:function(selection, oldSelection) {
  var multiValues = selection && this.getMultiSelect();
  selection = multiValues ? Ext.Array.from(selection) : selection;
  if (multiValues ? !oldSelection || !Ext.Array.equals(selection, oldSelection) : selection !== oldSelection) {
    return selection || null;
  }
}, updateMultiSelect:function(multiSelect) {
  var me = this, picker = me.getConfig('picker', false, true), chipView = me.chipView, valueCollection = me.getValueCollection(), selection = valueCollection.last(), selectable;
  if (multiSelect) {
    if (chipView) {
      chipView.show();
    } else {
      me.getChipView();
      me.chipView.render(me.inputWrapElement.dom, me.inputElement.dom);
    }
    me.chipView.bodyElement.dom.appendChild(me.inputElement.dom);
    me.setInputValue('');
    if (selection) {
      me.setSelection([selection]);
    }
  } else {
    if (chipView) {
      me.inputWrapElement.dom.insertBefore(me.inputElement.dom, me.afterInputElement.dom);
      chipView.hide();
    }
    if (selection) {
      valueCollection.splice(0, 1.0E99, [selection]);
    }
  }
  if (picker) {
    selectable = picker.getSelectable();
    selectable.setConfig({deselectable:multiSelect, mode:multiSelect ? 'multi' : 'single'});
  }
  me.el.toggleCls(me.multiSelectCls, multiSelect);
}, updateSelection:function(selection, oldSelection) {
  var me = this, isNull = selection == null, multiSelect = me.getMultiSelect(), valueCollection = me.getValueCollection(), valueField = me.getValueField(), oldValue = me._value, newValue = null, picker, spliceArgs;
  if (me._ignoreSelection || me.destroyed || me.destroying) {
    return;
  }
  if (!me.processingCollectionMutation) {
    if (isNull || oldSelection && selection.length < oldSelection.length || !valueCollection.containsAll(selection)) {
      spliceArgs = [0, valueCollection.getCount()];
      if (!isNull) {
        spliceArgs.push(selection);
      }
      valueCollection.splice.apply(valueCollection, spliceArgs);
      if (me.destroyed) {
        return;
      }
    }
  }
  if (selection) {
    if (valueField) {
      if (multiSelect) {
        newValue = valueCollection.collect(valueField, 'data');
        if (newValue.length !== valueCollection.length) {
          Ext.raise('The valueField of a combobox must be unique');
        }
      } else {
        newValue = selection.get(valueField);
      }
      me.setValue(newValue);
    }
    if (me.fireEvent('select', me, selection) === false) {
      me.setValue(oldValue);
      me._selection = oldSelection;
    }
  } else {
    me.clearValue();
  }
  if (me.destroyed) {
    return;
  }
  picker = me.getConfig('picker', false, true);
  if (picker && picker.isVisible()) {
    if (!multiSelect || me.getCollapseOnSelect() || !me.getStore().getCount()) {
      if (!multiSelect && selection && oldSelection && selection.id === oldSelection.id) {
        picker.refresh();
      } else {
        if (!(selection && selection.isEntered)) {
          me.collapse();
        }
      }
    }
  }
}, getRecordDisplayData:function(record) {
  return record.getData();
}, createFloatedPicker:function() {
  var me = this, multiSelect = me.getMultiSelect(), result = Ext.merge({ownerCmp:me, store:me._pickerStore || me.getStore(), selectable:{selected:me.getValueCollection(), selectedRecord:me.getSelection(), deselectable:!!multiSelect, mode:multiSelect ? 'multi' : 'single'}, itemTpl:me.getItemTpl(), itemCls:me.getItemCls()}, me.getFloatedPicker());
  result.navigationModel.navigateOnSpace = !me.getEditable();
  return result;
}, createEdgePicker:function() {
  return Ext.merge({ownerCmp:this}, this.getEdgePicker());
}, realignFloatedPicker:function(picker) {
  picker = picker || this.getConfig('picker', false, true);
  if (picker && picker.isVisible()) {
    if (!picker.getItemCount() && !picker.getStore().hasPendingLoad()) {
      this.collapse();
    }
    this.callParent([picker]);
  }
}, setPickerLocation:function(fromKeyboard) {
  var me = this, picker = me.getConfig('picker', false, true), store, location;
  if (picker && me.expanded) {
    store = picker.getStore();
    if (picker.getItemCount()) {
      location = picker.getSelectable().getLastSelected();
      if (!location || !store.contains(location)) {
        if (fromKeyboard || me.getAutoFocusLast()) {
          location = picker.getNavigationModel().lastLocation;
          if (location) {
            location = location.refresh();
          }
        }
        if (!location && (fromKeyboard || me.getAutoFocus())) {
          location = store.getAt(0);
        }
      }
      picker.getNavigationModel().setLocation(location);
      if (!fromKeyboard) {
        Ext.setKeyboardMode(true);
      }
    }
  }
}, updatePicker:function(picker, oldPicker) {
  var filterPickList = this.getFilterPickList();
  if (picker && filterPickList) {
    picker.getSelectable().addIgnoredFilter(filterPickList);
  }
  this.callParent([picker, oldPicker]);
}, updatePickerValue:function(picker, value) {
  var name = this.getValueField(), pickerValue = {};
  if (!value) {
    value = this.getValue();
  }
  pickerValue[name] = value;
  picker.setValue(pickerValue);
}, applyItemTpl:function(itemTpl) {
  if (itemTpl === false) {
    itemTpl = '\x3cspan class\x3d"x-list-label"\x3e{' + this.getDisplayField() + ':htmlEncode}\x3c/span\x3e';
  }
  return itemTpl;
}, applyDisplayTpl:function(displayTpl) {
  if (displayTpl && !displayTpl.isTemplate) {
    displayTpl = new Ext.XTemplate(displayTpl);
  }
  return displayTpl;
}, applyOptions:function(options) {
  if (options) {
    var len = options.length, valueField = this.getValueField(), displayField = this.getDisplayField(), i, value, option;
    options = Ext.Array.slice(options);
    for (i = 0; i < len; i++) {
      value = options[i];
      if (Ext.isPrimitive(value)) {
        options[i] = option = {};
        option.id = value;
        option[valueField] = value;
        if (displayField && displayField !== valueField) {
          option[displayField] = value;
        }
      }
    }
    options = Ext.data.StoreManager.lookup({fields:[valueField, displayField], data:options});
  }
  return options;
}, updateOptions:function(options, oldOptions) {
  if (options) {
    this.setStore(options);
  } else {
    if (oldOptions === this.getStore()) {
      this.setStore(null);
    }
  }
}, applyStore:function(store) {
  if (store) {
    store = Ext.data.StoreManager.lookup(store);
  }
  return store;
}, updateStore:function(store, oldStore) {
  var me = this, valueField = me.getValueField(), displayField = me.getDisplayField(), extraKeySpec;
  if (oldStore) {
    if (oldStore.getAutoDestroy()) {
      oldStore.destroy();
    } else {
      oldStore.byValue = oldStore.byText = Ext.destroy(oldStore.byValue, oldStore.byText);
    }
  }
  if (store) {
    extraKeySpec = {byValue:{rootProperty:'data', unique:false, property:valueField}};
    if (displayField !== valueField) {
      extraKeySpec.byText = {rootProperty:'data', unique:false, property:displayField};
    }
    store.setExtraKeys(extraKeySpec);
    if (displayField === valueField) {
      store.byText = store.byValue;
    }
    store.on({scope:me, add:'onStoreDataChanged', remove:'onStoreDataChanged', update:'onStoreRecordUpdated', load:{fn:'onStoreLoad', priority:-1}, refresh:'onStoreRefresh'});
    if (store.isLoaded() && !store.hasPendingLoad()) {
      me.syncValue();
    } else {
      if (me.getValue() != null && me.getAutoLoadOnValue() && !store.isLoaded() && !store.hasPendingLoad()) {
        store.load();
      }
    }
  }
  me.updatePickerStore();
}, applyValueField:function(valueField) {
  if (valueField == null) {
    valueField = this.getDisplayField();
  }
  return valueField;
}, updateValueField:function(valueField) {
  var store = this.getStore();
  if (store && !this.isConfiguring) {
    store.byValue.setCollection(null);
    store.setExtraKeys({byValue:{rootProperty:'data', unique:false, property:valueField}});
  }
}, applyDisplayField:function(displayField) {
  if (displayField == null) {
    displayField = this.getValueField();
  }
  return displayField;
}, updateDisplayField:function(displayField) {
  var store = this.getStore();
  if (store && !this.isConfiguring) {
    store.byText.setCollection(null);
    store.setExtraKeys({byText:{rootProperty:'data', unique:false, property:displayField}});
  }
}, onStoreLoad:function(store, records, success) {
  var me = this, filtering = me.isFiltering;
  me.isFiltering = false;
  if (success) {
    me.syncMode = filtering ? 'filter' : 'store';
    me.syncValue();
  }
}, syncValue:function() {
  var me = this, store = me.getStore(), forceSelection = me.getForceSelection(), valueNotFoundText = me.getValueNotFoundText(), is, isCleared, isInput, value, matchedRecord;
  if (me.reconcilingValue || !store || !store.isLoaded() || store.hasPendingLoad()) {
    return;
  }
  me.reconcilingValue = true;
  me.getSelection();
  is = {};
  is[me.syncMode] = true;
  value = (isInput = is.input || is.filter) ? me.getInputValue() : me.getValue();
  isCleared = value == null || value === '';
  if (!isCleared) {
    if (me.getMultiSelect()) {
      return me.syncMultiValues(Ext.Array.from(value));
    }
    matchedRecord = (isInput ? store.byText : store.byValue).get(value);
    if (matchedRecord) {
      if (!matchedRecord.isEntity) {
        matchedRecord = matchedRecord[0];
      }
    } else {
      if (!forceSelection) {
        matchedRecord = me.findRecordByValue(value);
      }
    }
  }
  if (!isCleared && !matchedRecord && !forceSelection) {
    matchedRecord = me.createEnteredRecord(value);
  } else {
    if (isInput || is.store) {
      if (!matchedRecord && forceSelection) {
        me.setValue(null);
        me.setSelection(null);
        if (!is.filter) {
          me.setFieldDisplay();
        }
      }
    } else {
      if (isCleared) {
        if (me.mustAutoSelect()) {
          matchedRecord = store.first();
          if (me.getAutoSelect() === 'initial') {
            me.setAutoSelect(false);
          }
        } else {
          me.setSelection(null);
        }
      } else {
        if (!matchedRecord && valueNotFoundText) {
          me.setError(valueNotFoundText);
        }
      }
    }
  }
  if (matchedRecord) {
    me.setSelection(matchedRecord);
  }
  me.reconcilingValue = false;
}, syncMultiValues:function(values) {
  var me = this, matchedRecords = [], valueArray = [], forceSelection = me.getForceSelection(), valueField = me.getValueField(), valueCollection = me.getValueCollection(), val, record, len, i, key;
  for (i = 0, len = values.length; i < len; i++) {
    record = val = values[i];
    if (!record || !record.isEntity) {
      record = me.findRecordByValue(key = record);
      if (!record) {
        record = valueCollection.find(valueField, key);
      }
    }
    if (!record) {
      if (!forceSelection) {
        if (!record && val) {
          record = me.createEnteredRecord(val);
        }
      }
    }
    if (record) {
      matchedRecords.push(record);
      valueArray.push(record.get(valueField));
    }
  }
  if (matchedRecords.length) {
    me._value = valueArray;
    me.setSelection(matchedRecords);
  } else {
    me._value = null;
    me.setSelection();
  }
  me.reconcilingValue = false;
}, onStoreDataChanged:function() {
  var me = this, value;
  if (me.getForceSelection()) {
    value = me.getValue();
    if (value != null) {
      me.setValue(value);
    }
  }
}, onStoreRecordUpdated:function(store, record) {
  if (this.getValueCollection().contains(record)) {
    this.updateSelection(this.getSelection());
  }
  if (!this.getMultiSelect()) {
    this.setFieldDisplay();
  }
}, onStoreRefresh:function(store) {
  var me = this, picker = me.getConfig('picker', false, true), valueCollection = me.getValueCollection(), selectionModelCollection, ignoredFilters, filterPickList, pickerNavModel, pickerLocation;
  if (picker) {
    selectionModelCollection = picker.getSelectable().getSelected();
    pickerNavModel = picker.getNavigationModel();
    pickerLocation = pickerNavModel.getLocation();
    if (pickerLocation && !picker.getStore().contains(pickerLocation.record)) {
      pickerNavModel.clearLocation();
    }
  }
  if (selectionModelCollection !== valueCollection) {
    ignoredFilters = [];
    if (me.getPrimaryFilter) {
      ignoredFilters.push(me.getPrimaryFilter());
    }
    filterPickList = me.getFilterPickList();
    if (filterPickList) {
      ignoredFilters.push(filterPickList);
    }
    Ext.dataview.selection.Model.refreshCollection(valueCollection, store.getData(), ignoredFilters, Ext.dataview.BoundList.prototype.beforeSelectionRefresh);
  }
}, reset:function() {
  var me = this, picker = me.getConfig('picker', false, true), record = me.originalValue || null, store;
  if (me.getAutoSelect()) {
    store = me.getStore();
    record = record != null ? record : store && store.getAt(0);
  } else {
    if (picker) {
      picker.deselectAll();
    }
  }
  me.setValue(record);
  return me;
}, doDestroy:function() {
  var me = this, store = me.getStore();
  if (store && !store.destroyed && store.getAutoDestroy()) {
    store.destroy();
  }
  me.destroyMembers('options', 'chipView');
  me.callParent();
}, privates:{syncMode:null, createChipView:function(chipView) {
  var me = this, chipViewCfg = Ext.merge({ownerField:me, ownerCmp:me, store:{data:me.getValueCollection()}}, chipView);
  if (!(chipViewCfg.displayField || chipViewCfg.displayTpl)) {
    chipViewCfg.displayField = me.getDisplayField();
  }
  return chipViewCfg;
}, createEnteredRecord:function(value) {
  var me = this, recordCreator = me.getRecordCreator(), displayField = me.getDisplayField(), valueField = me.getValueField(), dataObj, result;
  if (recordCreator) {
    result = Ext.callback(recordCreator, me.getRecordCreatorScope(), [value, me.getStore().getModel(), me], 0, me);
  } else {
    dataObj = {};
    dataObj[displayField] = value;
    if (valueField && displayField !== valueField) {
      dataObj[valueField] = value;
    }
    result = me.createSelectionRecord(dataObj);
  }
  if (result) {
    result.isEntered = true;
  }
  return result;
}, hasValue:function() {
  return this.callParent() || this.getValueCollection().getCount();
}, onChipCloseTap:function(chipView, location) {
  var record = location.record;
  chipView.getNavigationModel().clearLocation();
  chipView.getSelectable().deselect(record);
  this.getValueCollection().remove(record);
  location.event.stopEvent();
  return false;
}, onChipBodyTouchStart:function(e) {
  if (e.pointerType !== 'touch' && !this.containsFocus) {
    this.inputElement.focus();
    e.preventDefault();
  }
}, onChipBodyTap:function(e) {
  if (e.pointerType === 'touch' && !this.containsFocus) {
    this.inputElement.focus();
    e.preventDefault();
  }
  if (!e.getTarget('.' + Ext.Chip.prototype.classCls)) {
    this.onInputElementClick(e);
  }
}, mustAutoSelect:function() {
  var me = this, autoSelect = me.getAutoSelect();
  if (autoSelect && !(me.isConfiguring || autoSelect === 'initial')) {
    autoSelect = !me.getClearable() && me.getRequired();
  }
  return !!autoSelect;
}, applyFilterPickList:function(filterPickList, oldFilterPickerList) {
  var me = this, pickerStore = me._pickerStore;
  if (oldFilterPickerList && oldFilterPickerList.isFilter && pickerStore) {
    pickerStore.removeFilter(oldFilterPickerList);
  }
  if (filterPickList) {
    filterPickList = new Ext.util.Filter({scope:me, filterFn:me.filterPicked});
  }
  return filterPickList;
}, updateFilterPickList:function(filterPickList, oldFilterPickList) {
  var picker = this.getConfig('picker', false, true);
  if (picker) {
    if (filterPickList) {
      picker.getSelectable().addIgnoredFilter(filterPickList);
    } else {
      if (oldFilterPickList) {
        picker.getSelectable().removeIgnoredFilter(oldFilterPickList);
      }
    }
  }
  this.updatePickerStore();
  if (picker) {
    picker.setDisableSelection(filterPickList);
  }
}, filterPicked:function(record) {
  return !this.getValueCollection().contains(record);
}, updatePickerStore:function() {
  var me = this, picker = me.getConfig('picker', false, true), store = me.getStore(), filterPickList = me.getFilterPickList() || undefined, localFiltering = me.getQueryMode && me.getQueryMode() === 'local' || filterPickList, result = store, filters;
  if (localFiltering) {
    filters = [];
    if (me.getPrimaryFilter) {
      filters.push(me.getPrimaryFilter());
    }
    if (filterPickList) {
      filters.push(filterPickList);
    }
    if (me._pickerStore && me._pickerStore.isChainedStore) {
      result = me._pickerStore.setConfig({source:store, filters:filters});
    } else {
      me._pickerStore = result = Ext.Factory.store({type:'chained', source:store, filters:filters});
    }
  } else {
    me._pickerStore = result = store;
  }
  if (picker) {
    picker.setStore(result);
  }
}, setFieldDisplay:function() {
  var me = this, selection, inputValue = '', displayTpl;
  if (!me.getMultiSelect()) {
    selection = me.getValueCollection().first();
    if (selection) {
      displayTpl = me.getDisplayTpl();
      if (displayTpl) {
        inputValue = displayTpl.apply(me.getRecordDisplayData(selection));
      } else {
        inputValue = selection.get(me.getDisplayField());
      }
    }
    me.setInputValue(inputValue);
    me.syncEmptyState();
  }
}}, rawToValue:Ext.emptyFn});
Ext.define('Ext.field.ComboBox', {extend:Ext.field.Select, xtype:['combobox', 'comboboxfield'], alternateClassName:['Ext.form.field.ComboBox'], config:{primaryFilter:true, queryParam:'query', queryMode:'remote', queryCaching:true, queryDelay:true, minChars:null, anyMatch:false, caseSensitive:false, typeAhead:false, typeAheadDelay:250, triggerAction:'all', allQuery:null, enableRegEx:null}, autoSelect:false, classCls:Ext.baseCSSPrefix + 'combobox', editable:true, forceSelection:false, lastQuery:{}, 
keyMap:{scope:'this', ENTER:'onEnterKey'}, platformConfig:{phone:{editable:false}}, onCollectionAdd:function(valueCollection, adds) {
  if (this.getMultiSelect()) {
    this.inputElement.dom.value = '';
    if (this.expanded) {
      this.doRawFilter();
    }
  }
  this.callParent([valueCollection, adds]);
}, onInput:function(e) {
  var me = this, filterTask = me.doFilterTask, value = me.inputElement.dom.value, filters = me.getStore().getFilters(), keyboardEvent, isDelimiter;
  if (Ext.supports.inputEventData) {
    isDelimiter = e.browserEvent.data === me.getDelimiter();
  } else {
    keyboardEvent = me.lastKeyMapEvent;
    isDelimiter = keyboardEvent && keyboardEvent.getChar() === me.getDelimiter() && Ext.ticks() - keyboardEvent.time < 20;
  }
  me._inputValue = value;
  if (!me.hasFocus && me.getLabelAlign() === 'placeholder') {
    me.syncLabelPlaceholder(true);
  }
  if (!me.getForceSelection() || value === '' && !me.getRequired()) {
    if (me.getMultiSelect()) {
      if (isDelimiter) {
        return me.addNewMultiValues();
      }
    } else {
      me.callParent([e]);
    }
  } else {
    me.syncEmptyState();
  }
  if (value.length) {
    if (!filterTask) {
      filterTask = me.doFilterTask = new Ext.util.DelayedTask(me.doRawFilter, me);
    }
    filterTask.delay(me.getQueryDelay());
  } else {
    me.collapse();
    filters.beginUpdate();
    me.getPrimaryFilter().setDisabled(true);
    filters.endUpdate();
  }
}, onEnterKey:function(e) {
  var me = this;
  if (!me.getForceSelection() && me.getMultiSelect()) {
    me.addNewMultiValues();
  }
}, addNewMultiValues:function() {
  var me = this, inputValue = me.inputElement.dom.value, newValue;
  newValue = me.getValue() || [];
  newValue.push.apply(newValue, inputValue.split(me.getDelimiter()));
  return me.setValue(Ext.Array.clean(newValue));
}, doRawFilter:function() {
  var me = this, rawValue = me.inputElement.dom.value, lastQuery = me.lastQuery.query, isErase = lastQuery && lastQuery.length > rawValue.length;
  me.doFilter({query:rawValue, isErase:isErase});
}, onExpandTap:function() {
  var me = this, triggerAction = me.getTriggerAction();
  if (me.expanded) {
    if (Ext.now() - me.expanded > 100) {
      me.collapse();
    }
  } else {
    if (!me.getReadOnly() && !me.getDisabled()) {
      if (triggerAction === 'all') {
        me.doFilter({query:me.getAllQuery(), force:true});
      } else {
        if (triggerAction === 'last') {
          me.doFilter({query:me.lastQuery.query, force:true});
        } else {
          me.doFilter({query:me.inputElement.dom.value});
        }
      }
    }
  }
}, clearValue:function() {
  var me = this;
  me.setValue(null);
  me.setInputValue('');
  me.setFieldDisplay();
}, doFilter:function(query) {
  var me = this, isLocal = me.getQueryMode() === 'local', lastQuery = me.lastQuery, store = me.getStore() && me._pickerStore, filter = me.getPrimaryFilter(), filters = store.getFilters(), queryPlan = me.beforeFilter(Ext.apply({filterGeneration:filter.generation, lastQuery:lastQuery || {}, combo:me, cancel:false}, query)), picker, source;
  if (store && queryPlan !== false && !queryPlan.cancel) {
    if (me.getEnableRegEx()) {
      try {
        queryPlan.query = new RegExp(queryPlan.query);
      } catch (e$63) {
        queryPlan.query = null;
      }
    }
    filter.setValue(queryPlan.query);
    if (!me.getQueryCaching() || filter.generation !== lastQuery.filterGeneration || query.force) {
      if (Ext.isEmpty(queryPlan.query)) {
        filter.setDisabled(true);
      } else {
        filter.setDisabled(false);
        me.isFiltering = !isLocal;
      }
      me.lastQuery = queryPlan;
      filters.beginUpdate();
      filters.endUpdate();
      if (store.isChainedStore) {
        source = store.getSource();
        if (!source.isLoaded() && !source.hasPendingLoad()) {
          source.load();
        }
      }
    }
    if (me.getTypeAhead()) {
      me.doTypeAhead(queryPlan);
    }
    picker = me.getPicker();
    if (!isLocal || store.getCount() || picker.getEmptyText && picker.getEmptyText()) {
      me.expand();
      if (queryPlan.query && isLocal) {
        me.setPickerLocation();
      }
      return true;
    }
    me.collapse();
  }
  return false;
}, beforeFilter:function(queryPlan) {
  var me = this, query = queryPlan.query, len;
  if (me.fireEvent('beforequery', queryPlan) === false) {
    queryPlan.cancel = true;
  } else {
    if (!queryPlan.cancel) {
      len = query && query.length;
      if (!queryPlan.force && len && len < me._getMinChars()) {
        queryPlan.cancel = true;
      }
    }
  }
  return queryPlan;
}, completeEdit:function() {
  var me = this, inputValue = me.getInputValue(), value = me.getValue(), selection = me.getSelection();
  if (me.doFilterTask) {
    me.doFilterTask.cancel();
  }
  if (!me.getForceSelection() && me.getMultiSelect()) {
    if (inputValue) {
      if (this.getSelectOnTab()) {
        me.addNewMultiValues();
      } else {
        this.setInputValue('');
      }
    }
  } else {
    if (inputValue) {
      if (!selection || selection.get(this.getDisplayField()) !== inputValue) {
        me.syncMode = 'input';
        me.syncValue();
        if (!me.getValue()) {
          me.setValue(value);
        }
      }
    } else {
      if (selection) {
        if (me.getRequired()) {
          me.setFieldDisplay(selection);
        } else {
          me.setSelection(null);
        }
      }
    }
    if (me.getTypeAhead()) {
      me.select(inputValue ? inputValue.length : 0);
    }
  }
}, onStoreFilterChange:function() {
  var me = this, store = me.getStore(), selection = me.getSelection() || null, toRemove = [];
  if (selection && !me.destroying && store && store.isLoaded() && me.getPrimaryFilter().getDisabled()) {
    if (me.getMultiSelect()) {
      Ext.Array.each(selection, function(record) {
        if (!record.isEntered && !store.contains(record)) {
          toRemove.push(record);
        }
      });
    } else {
      if (!selection.isEntered && !store.contains(selection)) {
        toRemove.push(selection);
      }
    }
    if (toRemove.length) {
      this.getValueCollection().remove(toRemove);
    }
  }
}, onListSelect:Ext.emptyFn, applyQueryDelay:function(queryDelay) {
  if (queryDelay === true) {
    queryDelay = this.getQueryMode() === 'local' ? 10 : 500;
  }
  return queryDelay;
}, applyPrimaryFilter:function(filter, oldFilter) {
  var me = this, store = me.getStore() && me._pickerStore, isInstance = filter && filter.isFilter, methodName;
  if (store && oldFilter) {
    if (filter) {
      if (isInstance) {
        store.removeFilter(oldFilter, true);
      } else {
        oldFilter.setConfig(filter);
        return;
      }
    } else {
      if (!store.destroyed) {
        store.getFilters().remove(oldFilter);
      }
    }
  }
  if (filter) {
    if (filter === true) {
      filter = {id:me.id + '-primary-filter', anyMatch:me.getAnyMatch(), caseSensitive:me.getCaseSensitive(), root:'data', property:me.getDisplayField(), value:me.inputElement.dom.value, disabled:true};
    }
    if (typeof filter === 'string') {
      methodName = filter;
      filter = {filterFn:function(rec) {
        var methodOwner = me.resolveListenerScope(me);
        return methodOwner[methodName].call(this, rec);
      }};
    }
    if (!filter.isFilter) {
      filter = new Ext.util.Filter(filter);
    }
    filter.serialize = function() {
      return me.serializePrimaryFilter(this);
    };
    if (store) {
      store.addFilter(filter, true);
    }
  }
  return filter;
}, updateOptions:function(options, oldOptions) {
  if (options) {
    this.setQueryMode('local');
  }
  this.callParent([options, oldOptions]);
}, updatePicker:function(picker, oldPicker) {
  if (picker) {
    picker.getSelectable().addIgnoredFilter(this.getPrimaryFilter());
  }
  this.callParent([picker, oldPicker]);
}, updateStore:function(store, oldStore) {
  var me = this, isRemote = me.getQueryMode() === 'remote', primaryFilter, proxy, oldFilters;
  if (isRemote) {
    store.setRemoteFilter(true);
    proxy = store.getProxy();
    if (proxy.setFilterParam) {
      proxy.setFilterParam(me.getQueryParam());
    }
  }
  me.callParent([store, oldStore]);
  primaryFilter = me.getPrimaryFilter();
  if (primaryFilter) {
    if (oldStore && !oldStore.destroyed) {
      oldFilters = oldStore.getFilters();
      if (oldFilters) {
        oldFilters.remove(primaryFilter);
      }
    }
    me._pickerStore.addFilter(primaryFilter, true);
  }
  if (me.getQueryMode() === 'local') {
    store.on({filterchange:'onStoreFilterChange', scope:me});
  }
}, serializePrimaryFilter:function(filter) {
  return filter.getValue();
}, doDestroy:function() {
  var me = this;
  me.setPrimaryFilter(null);
  if (me.typeAheadTask) {
    me.typeAheadTask = me.typeAheadTask.cancel();
  }
  me.callParent();
}, doTypeAhead:function(queryPlan) {
  var me = this;
  if (!me.typeAheadTask) {
    me.typeAheadTask = new Ext.util.DelayedTask(me.onTypeAhead, me);
  }
  if (!queryPlan.lastQuery.query || !queryPlan.query || queryPlan.query.length > queryPlan.lastQuery.query.length || !Ext.String.startsWith(queryPlan.lastQuery.query, queryPlan.query)) {
    me.typeAheadTask.delay(me.getTypeAheadDelay());
  }
}, onTypeAhead:function() {
  var me = this, displayField = me.getDisplayField(), inputEl = me.inputElement.dom, rawValue = inputEl.value, store = me.getStore(), record = store.findRecord(displayField, rawValue), newValue, len, selStart;
  if (record) {
    newValue = record.get(displayField);
    len = newValue.length;
    selStart = rawValue.length;
    if (selStart !== 0 && selStart !== len) {
      inputEl.value = me._inputValue = newValue;
      me.select(selStart, len);
    }
  }
}, privates:{_getMinChars:function() {
  var result = this.getMinChars();
  if (result == null) {
    result = this.getQueryMode() === 'remote' ? 4 : 0;
  }
  return result;
}, setFieldDisplay:function(selection) {
  var me = this, inputValue;
  me.callParent([selection]);
  if (!me.getMultiSelect()) {
    if (me.getTypeAhead()) {
      inputValue = me.getInputValue();
      me.select(inputValue ? inputValue.length : 0);
    }
  }
}}});
Ext.define('Ext.field.trigger.Date', {extend:Ext.field.trigger.Expand, xtype:'datetrigger', alias:'trigger.date', classCls:Ext.baseCSSPrefix + 'datetrigger'});
Ext.define('Ext.picker.Date', {extend:Ext.picker.Picker, xtype:'datepicker', alternateClassName:'Ext.DatePicker', config:{yearFrom:1980, yearTo:(new Date).getFullYear(), monthText:'Month', dayText:'Day', yearText:'Year', slotOrder:['month', 'day', 'year'], doneButton:true}, initialize:function() {
  var me = this;
  me.callParent();
  me.on({scope:me, delegate:'\x3e slot', slotpick:me.onSlotPick});
}, setValue:function(value, animated) {
  var me = this;
  if (Ext.isDate(value)) {
    value = {day:value.getDate(), month:value.getMonth() + 1, year:value.getFullYear()};
  }
  me.callParent([value, animated]);
  if (me.rendered) {
    me.onSlotPick();
  }
  return me;
}, getValue:function(useDom) {
  var values = {}, items = this.getItems().items, ln = items.length, daysInMonth, day, month, year, item, i;
  for (i = 0; i < ln; i++) {
    item = items[i];
    if (item.isSlot) {
      values[item.getName()] = item.getValue(useDom);
    }
  }
  if (values.year === null && values.month === null && values.day === null) {
    return null;
  }
  year = Ext.isNumber(values.year) ? values.year : 1;
  month = Ext.isNumber(values.month) ? values.month : 1;
  day = Ext.isNumber(values.day) ? values.day : 1;
  if (month && year && month && day) {
    daysInMonth = this.getDaysInMonth(month, year);
  }
  day = daysInMonth ? Math.min(day, daysInMonth) : day;
  return new Date(year, month - 1, day);
}, updateYearFrom:function() {
  if (this.initialized) {
    this.createSlots();
  }
}, updateYearTo:function() {
  if (this.initialized) {
    this.createSlots();
  }
}, updateMonthText:function(newMonthText, oldMonthText) {
  var innerItems = this.getInnerItems, ln = innerItems.length, item, i;
  if (this.initialized) {
    for (i = 0; i < ln; i++) {
      item = innerItems[i];
      if (typeof item.title === 'string' && item.title === oldMonthText || item.title.html === oldMonthText) {
        item.setTitle(newMonthText);
      }
    }
  }
}, updateDayText:function(newDayText, oldDayText) {
  var innerItems = this.getInnerItems, ln = innerItems.length, item, i;
  if (this.initialized) {
    for (i = 0; i < ln; i++) {
      item = innerItems[i];
      if (typeof item.title === 'string' && item.title === oldDayText || item.title.html === oldDayText) {
        item.setTitle(newDayText);
      }
    }
  }
}, updateYearText:function(yearText) {
  var innerItems = this.getInnerItems, ln = innerItems.length, item, i;
  if (this.initialized) {
    for (i = 0; i < ln; i++) {
      item = innerItems[i];
      if (item.title === this.yearText) {
        item.setTitle(yearText);
      }
    }
  }
}, constructor:function() {
  this.callParent(arguments);
  this.createSlots();
}, createSlots:function() {
  var me = this, slotOrder = me.getSlotOrder(), yearsFrom = me.getYearFrom(), yearsTo = me.getYearTo(), years = [], days = [], months = [], slots = [], reverse = yearsFrom > yearsTo, ln, i, daysInMonth;
  while (yearsFrom) {
    years.push({text:yearsFrom, value:yearsFrom});
    if (yearsFrom === yearsTo) {
      break;
    }
    if (reverse) {
      yearsFrom--;
    } else {
      yearsFrom++;
    }
  }
  daysInMonth = me.getDaysInMonth(1, (new Date).getFullYear());
  for (i = 0; i < daysInMonth; i++) {
    days.push({text:i + 1, value:i + 1});
  }
  for (i = 0, ln = Ext.Date.monthNames.length; i < ln; i++) {
    months.push({text:Ext.Date.monthNames[i], value:i + 1});
  }
  slotOrder.forEach(function(item) {
    slots.push(me.createSlot(item, days, months, years));
  });
  me.setSlots(slots);
}, createSlot:function(name, days, months, years) {
  var me = this, result;
  switch(name) {
    case 'year':
      result = {name:'year', align:'center', data:years, title:me.getYearText(), flex:3};
      break;
    case 'month':
      result = {name:name, align:'right', data:months, title:me.getMonthText(), flex:4};
      break;
    case 'day':
      result = {name:'day', align:'center', data:days, title:me.getDayText(), flex:2};
  }
  if (me._value) {
    result.value = me._value[name];
  }
  return result;
}, onSlotPick:function() {
  var me = this, addDays = [], value, daySlot, valueField, dayStore, dayData, daysInMonth, slotCount, year, month, i, spliceArgs;
  if (me.isConfiguring) {
    return;
  }
  value = me.getValue(true);
  daySlot = me.getDaySlot();
  me.callParent(arguments);
  if (!daySlot) {
    return;
  }
  valueField = daySlot.getValueField();
  dayStore = daySlot.getStore();
  dayData = dayStore.getData();
  slotCount = dayStore.getCount();
  year = value.getFullYear();
  month = value.getMonth();
  daysInMonth = me.getDaysInMonth(month + 1, year);
  if (slotCount === daysInMonth) {
    return;
  }
  if (daysInMonth > slotCount) {
    for (i = slotCount; i < daysInMonth; i++) {
      addDays.push(dayStore.createModel({text:i + 1, value:i + 1}));
    }
    spliceArgs = [slotCount, 0, addDays];
  } else {
    spliceArgs = [daysInMonth, 5];
  }
  dayData.splice.apply(dayData, spliceArgs);
  i = dayStore.find(valueField, value.getDate());
  if (i > -1) {
    daySlot.navigateToItem(daySlot.mapToItem(i));
    daySlot.setValue(daySlot.getValue(true));
  }
}, getDaySlot:function() {
  var innerItems = this.getInnerItems(), ln = innerItems.length, i, slot;
  if (this.daySlot) {
    return this.daySlot;
  }
  for (i = 0; i < ln; i++) {
    slot = innerItems[i];
    if (slot.isSlot && slot.getName() === 'day') {
      this.daySlot = slot;
      return slot;
    }
  }
  return null;
}, getDaysInMonth:function(month, year) {
  var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  return month === 2 && this.isLeapYear(year) ? 29 : daysInMonth[month - 1];
}, isLeapYear:function(year) {
  return !!((year & 3) === 0 && (year % 100 || year % 400 === 0 && year));
}, onDoneButtonTap:function() {
  var me = this, oldValue = me._value, newValue = me.getValue(true), ownerField = me.ownerField, testValue = newValue;
  if (Ext.isDate(newValue)) {
    testValue = newValue.toDateString();
  }
  if (Ext.isDate(oldValue)) {
    oldValue = oldValue.toDateString();
  }
  if (testValue !== oldValue) {
    if (ownerField) {
      ownerField.onPickerChange(me, newValue);
    }
    me.fireEvent('change', me, newValue);
  }
  me.hide();
  Ext.util.InputBlocker.unblockInputs();
}});
Ext.define('Ext.layout.Carousel', {extend:Ext.layout.Auto, alias:'layout.carousel', config:{visibleChildren:1, frontIndex:{$value:true, lazy:true}, animation:true}, vertical:false, targetCls:Ext.baseCSSPrefix + 'layout-carousel', wrapCls:Ext.baseCSSPrefix + 'layout-carousel-wrap', itemCls:Ext.baseCSSPrefix + 'layout-carousel-item', singularCls:Ext.baseCSSPrefix + 'layout-carousel-singular', destroy:function() {
  var container = this.getContainer();
  Ext.destroy(container.carouselElement, this.activeAnim);
  this.callParent();
}, updateContainer:function(container, oldContainer) {
  var me = this;
  me.callParent([container, oldContainer]);
  container.bodyElement.addCls(me.wrapCls);
  container.carouselElement = container.getRenderTarget().appendChild({cls:me.targetCls});
  Ext.override(container, {privates:{getRenderTarget:function() {
    return this.carouselElement;
  }}});
}, onContainerInitialized:function(container) {
  var me = this;
  me.callParent([container]);
  if (!me.frontItem) {
    me.setFrontItem(me.getFrontIndex(), false);
  }
}, updateVisibleChildren:function(count) {
  var me = this, target = me.getContainer().getRenderTarget(), pct, items, item, i, len;
  items = me.getLayoutItems();
  pct = me.calcItemBasis(count) + '%';
  if (items.length > count) {
    target.setStyle('left', '-' + pct);
    target.setStyle('transform', 'translateX(' + pct + ')');
  }
  for (i = 0, len = items.length; i < len; i++) {
    item = items[i];
    item.el.setStyle('flex-basis', pct);
  }
  target.toggleCls(me.singularCls, count === 1);
}, applyFrontIndex:function(itemIdx) {
  var count, index;
  if (typeof itemIdx !== 'number') {
    count = this.getVisibleChildren();
    index = count - 1;
    itemIdx = !index ? index : index % 2 ? Math.floor(index / 2) + 1 : index / 2;
  }
  return itemIdx;
}, applyDuration:function(duration) {
  if (typeof duration !== 'number') {
    duration = parseInt(duration, 10) || 500;
  }
  return duration;
}, calcItemBasis:function(count) {
  count = count != null ? count : this.getVisibleChildren();
  return count === 1 ? 100 : !(count % 2) ? 100 / count : (100 / count).toFixed(5);
}, insertInnerItem:function(item, index) {
  var me = this;
  me.callParent([item, index]);
  if (index === 0) {
    me.frontItem = item;
  }
  item.el.setStyle('order', index + 1);
  item.el.setStyle('flex-basis', me.calcItemBasis() + '%');
}, getLayoutItemCount:function() {
  return this.getLayoutItems().length;
}, getLayoutItems:function() {
  return this.getContainer().getInnerItems();
}, getItemIndex:function(item) {
  return this.getContainer().innerIndexOf(item);
}, shiftIndex:function(index, increment) {
  var count = this.getLayoutItemCount();
  index += increment;
  if (increment < 0) {
    index = index < 0 ? count - 1 : index;
  } else {
    if (increment > 0) {
      index = index >= count ? 0 : index;
    }
  }
  return index;
}, getVisibleItems:function() {
  return this.visibleItems;
}, getEdgeItem:function(increment) {
  var items = this.getOrderedLayoutItems();
  return increment < 0 ? items[0] : items[items.length - 1];
}, getFirstVisibleItem:function() {
  return this.getVisibleItems()[0];
}, getLastVisibleItem:function() {
  var items = this.getVisibleItems();
  return items[items.length - 1];
}, getFrontItem:function() {
  return this.frontItem;
}, getFrontItemIndex:function() {
  return this.getItemIndex(this.getFrontItem());
}, getOrderedLayoutItems:function() {
  var items = Ext.Array.clone(this.getLayoutItems());
  return items.sort(this.sortByOrder);
}, setFrontItem:function(index, animate) {
  var me = this, container = me.getContainer(), target = container.getRenderTarget(), frontIndex = me.getFrontIndex(), visibleChildren = me.getVisibleChildren(), items, item, oldFrontItem, oldFrontIndex, visibleItems, direction, basis, i, len, ret, deferred;
  items = me.getLayoutItems();
  if (items.length < visibleChildren) {
    return Ext.Deferred.getCachedResolved();
  }
  if (typeof index !== 'number') {
    index = items.indexOf(index);
  }
  basis = me.calcItemBasis();
  target.setStyle('left', '-' + basis + '%');
  oldFrontItem = me.getFrontItem();
  me.frontItem = items[index];
  frontIndex++;
  items = items.slice(index).concat(items.slice(0, index));
  oldFrontIndex = items.indexOf(oldFrontItem);
  items = items.slice(-frontIndex).concat(items.slice(0, items.length - frontIndex));
  if (animate == null) {
    animate = me.getAnimation();
  }
  if (animate) {
    if (typeof animate === 'boolean') {
      animate = {};
    }
    direction = oldFrontIndex > -1 && oldFrontIndex <= Math.floor(items.length / 2) ? 1 : -1;
    Ext.destroy(me.activeAnim);
    deferred = new Ext.Deferred;
    ret = deferred.promise;
    me.activeAnim = Ext.Animator.run(Ext.apply({element:target, to:{transform:{translateX:basis * direction + '%'}}, callback:function() {
      me.orderItems(items);
      deferred.resolve();
      me.activeAnim = null;
    }}, animate));
  }
  me.visibleItems = visibleItems = [];
  for (i = 0, len = items.length; i < len; i++) {
    item = items[i];
    if (i > 0 && i <= visibleChildren) {
      visibleItems.push(item);
    }
    item.$carouselOrder = i + 1;
  }
  if (!animate) {
    me.orderItems(items);
    ret = Ext.Deferred.getCachedResolved();
  }
  visibleItems.sort(me.sortByOrder);
  return ret;
}, getMoveItem:function(increment) {
  var index = this.getFrontItemIndex();
  index = this.shiftIndex(index, increment);
  return this.getLayoutItems()[index];
}, cancelAnimation:function() {
  Ext.destroy(this.activeAnim);
}, move:function(increment, animate) {
  return this.setFrontItem(this.getMoveItem(increment), animate);
}, prev:function(animate) {
  return this.move(-1, animate);
}, next:function(animate) {
  return this.move(1, animate);
}, privates:{orderItems:function(items) {
  var len = items.length, i, item;
  for (i = 0; i < len; ++i) {
    item = items[i];
    item.el.setStyle('order', item.$carouselOrder + 1);
  }
}, sortByOrder:function(a, b) {
  return +a.$carouselOrder - b.$carouselOrder;
}}});
Ext.define('Ext.panel.DateView', {extend:Ext.Widget, xtype:'dateview', config:{specialDates:null, specialDays:null, monthOffset:0}, cachedConfig:{captionFormat:null, dateCellFormat:null, format:null, headerLength:null, hideCaption:true, hideOutside:true, startDay:null, weekendDays:null}, element:{reference:'element'}, tableTpl:{reference:'tableElement', tag:'table', cellspacing:'0', cellpadding:'0', children:[]}, captionTpl:{reference:'captionElement', tag:'caption'}, headTpl:{tag:'thead', reference:'headElement'}, 
headRowTpl:{tag:'tr'}, headCellTpl:{tag:'th', cls:Ext.baseCSSPrefix + 'cell', children:[{tag:'div', cls:Ext.baseCSSPrefix + 'inner ' + Ext.dom.Element.unselectableCls}]}, bodyTpl:{tag:'tbody', reference:'bodyElement'}, bodyRowTpl:{tag:'tr'}, bodyCellTpl:{tag:'td', cls:Ext.baseCSSPrefix + 'cell', tabIndex:-1, children:[{tag:'div', cls:Ext.baseCSSPrefix + 'inner ' + Ext.dom.Element.unselectableCls}]}, rows:6, columns:7, cellCls:Ext.baseCSSPrefix + 'cell', emptyCls:Ext.baseCSSPrefix + 'empty', weekendDayCls:Ext.baseCSSPrefix + 
'weekend', disabledDayCls:Ext.baseCSSPrefix + 'disabled', specialDateCls:Ext.baseCSSPrefix + 'special', todayCls:Ext.baseCSSPrefix + 'today', outsideCls:Ext.baseCSSPrefix + 'outside', prevMonthCls:Ext.baseCSSPrefix + 'prev-month', nextMonthCls:Ext.baseCSSPrefix + 'next-month', currentMonthCls:Ext.baseCSSPrefix + 'current-month', constructor:function(config) {
  this.firstOfMonth = Ext.Date.getFirstDateOfMonth(new Date);
  this.callParent([config]);
}, initElement:function() {
  var me = this;
  me.callParent();
  me.headCells = me.headElement.query('th');
  me.bodyCells = me.bodyElement.query('td');
  me.cellMap = {};
}, getMonth:function() {
  return Ext.Date.add(this.firstOfMonth, Ext.Date.MONTH, this.getMonthOffset());
}, getTemplate:function() {
  var me = this, table = me.tableTpl, headRow = me.headRowTpl, headCell = me.headCellTpl, bodyRow = me.bodyRowTpl, bodyCell = me.bodyCellTpl, rows = me.rows, columns = me.columns, headTpl, bodyTpl, i, len;
  headRow = Ext.apply({children:[]}, headRow);
  bodyRow = Ext.apply({children:[]}, bodyRow);
  for (i = 0, len = columns; i < len; i++) {
    headRow.children.push(headCell);
    bodyRow.children.push(bodyCell);
  }
  headTpl = Ext.apply({children:[]}, me.headTpl);
  headTpl.children.push(headRow);
  bodyTpl = Ext.apply({children:[]}, me.bodyTpl);
  for (i = 0, len = rows; i < len; i++) {
    bodyTpl.children.push(bodyRow);
  }
  table.children = [me.captionTpl, headTpl, bodyTpl];
  return [table];
}, getCellByDate:function(date) {
  return date ? this.cellMap[date.getTime()] : null;
}, updateWeekendDays:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, updateStartDay:function(dayIndex) {
  var cells = this.headCells, weekendDays = this.getWeekendDays(), weekendCls = this.weekendDayCls, headerLength = this.getHeaderLength(), cell, i, len, offsetIdx;
  for (i = 0, len = cells.length; i < len; i++) {
    cell = cells[i];
    offsetIdx = (i + dayIndex) % 7;
    cell.firstChild.innerHTML = Ext.Date.getShortDayName(offsetIdx).substr(0, headerLength);
    Ext.fly(cell).toggleCls(weekendCls, !!weekendDays[offsetIdx]);
  }
}, updateSpecialDates:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, updateSpecialDays:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, applyMonthOffset:function(offset) {
  return !isNaN(offset) ? offset : 0;
}, updateMonthOffset:function() {
  this.refresh();
}, updateCaptionFormat:function(format) {
  var month = this.getMonth();
  if (month) {
    this.captionElement.setHtml(Ext.Date.format(month, format));
  }
}, updateHideCaption:function(hide) {
  this.toggleCls(Ext.baseCSSPrefix + 'hide-caption', hide);
}, refresh:function() {
  var me = this, ExtDate = Ext.Date, cells = me.bodyCells, monthStart, startOffset, startDate, startDay, date, cellMap, cell, params, i, len, outPrev, outNext, currentMonth, month;
  if (me.refreshing) {
    return;
  }
  me.refreshing = true;
  monthStart = me.getMonth();
  startDay = me.getStartDay();
  startOffset = startDay - monthStart.getDay();
  if (startOffset > 0) {
    startOffset -= 7;
  }
  startDate = ExtDate.add(monthStart, ExtDate.DAY, startOffset);
  cellMap = me.cellMap = {};
  currentMonth = monthStart.getMonth();
  params = {today:Ext.Date.clearTime(new Date), weekendDays:me.getWeekendDays(), specialDates:me.getSpecialDates(), specialDays:me.getSpecialDays(), format:me.getFormat(), dateCellFormat:me.getDateCellFormat(), hideOutside:me.getHideOutside()};
  for (i = 0, len = cells.length; i < len; i++) {
    cell = cells[i];
    date = ExtDate.add(startDate, ExtDate.DAY, i);
    month = date.getMonth();
    outPrev = month < currentMonth;
    outNext = month > currentMonth;
    cellMap[date.getTime()] = cell;
    params.cell = cell;
    params.date = date;
    params.outside = outPrev || outNext;
    params.outsidePrevious = outPrev;
    params.outsideNext = outNext;
    me.refreshCell(params);
  }
  me.captionElement.setHtml(Ext.Date.format(monthStart, me.getCaptionFormat()));
  me.refreshing = false;
}, refreshCell:function(params) {
  var me = this, cell = params.cell, date = params.date, dayOfWeek = date.getDay(), ms = date.getTime(), specialDates = params.specialDates, specialDays = params.specialDays, cls = [me.cellCls], formatted = Ext.Date.format(date, params.format), empty = params.outside && params.hideOutside, html, special, disabled;
  if (!empty) {
    if (params.outsidePrevious) {
      cls.push(me.outsideCls, me.prevMonthCls);
    } else {
      if (params.outsideNext) {
        cls.push(me.outsideCls, me.nextMonthCls);
      } else {
        cls.push(me.currentMonthCls);
        if (Ext.Date.isEqual(date, params.today)) {
          cls.push(me.todayCls);
        }
      }
    }
    if (params.weekendDays[dayOfWeek]) {
      cls.push(me.weekendDayCls);
    }
    if (!special && specialDays) {
      special = specialDays[dayOfWeek];
    }
    if (specialDates) {
      special = specialDates.dates[ms] || specialDates.re && specialDates.re.test(formatted);
    }
    if (special) {
      cls.push(me.specialDateCls);
    }
  } else {
    cls.push(me.emptyCls);
  }
  disabled = me.getParent().isDateDisabled(date);
  if (!empty && disabled) {
    cls.push(me.disabledDayCls);
  }
  cell.tabIndex = -1;
  if (empty) {
    html = '\x26#160;';
  } else {
    html = Ext.Date.format(date, params.dateCellFormat);
  }
  cell.firstChild.innerHTML = html;
  if (me.transformCellCls) {
    me.transformCellCls(date, cls);
  }
  cell.className = cls.join(' ');
  cell.date = date;
  cell.disabled = disabled;
}, ownsDate:function(d) {
  var curr = this.getMonth();
  return d.getFullYear() === curr.getFullYear() && d.getMonth() === curr.getMonth();
}, privates:{measurePaneSize:function() {
  var el = this.element.first();
  return el.measure('w') + el.getMargin('lr');
}}});
Ext.define('Ext.panel.Title', {extend:Ext.Component, xtype:'paneltitle', isPanelTitle:true, cachedConfig:{textAlign:'left', iconAlign:'left', rotation:0, rotateIcon:null}, config:{text:'', icon:null, iconCls:null}, weight:-10, inheritUi:true, element:{reference:'element', cls:Ext.baseCSSPrefix + 'unselectable'}, template:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', children:[{reference:'iconElement', cls:Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon'}, {reference:'textElement', 
cls:Ext.baseCSSPrefix + 'text-el'}]}], verticalCls:Ext.baseCSSPrefix + 'vertical', horizontalCls:Ext.baseCSSPrefix + 'horizontal', rotateIconCls:Ext.baseCSSPrefix + 'rotate-icon', iconAlignVerticalCls:Ext.baseCSSPrefix + 'icon-align-vertical', hasIconCls:Ext.baseCSSPrefix + 'has-icon', _textAlignClasses:{left:Ext.baseCSSPrefix + 'text-align-left', center:Ext.baseCSSPrefix + 'text-align-center', right:Ext.baseCSSPrefix + 'text-align-right'}, _iconAlignClasses:{top:Ext.baseCSSPrefix + 'icon-align-top', 
right:Ext.baseCSSPrefix + 'icon-align-right', bottom:Ext.baseCSSPrefix + 'icon-align-bottom', left:Ext.baseCSSPrefix + 'icon-align-left'}, _rotationClasses:{90:Ext.baseCSSPrefix + 'rotate-90', 270:Ext.baseCSSPrefix + 'rotate-270'}, classCls:Ext.baseCSSPrefix + 'paneltitle', _titleSuffix:'-title', afterRender:function() {
  if (Ext.isSafari) {
    this.repaintBodyElement();
  }
  this.callParent();
}, updateIcon:function(icon, oldIcon) {
  var me = this, iconEl;
  me.syncIconVisibility();
  iconEl = me.iconElement;
  iconEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
}, updateIconAlign:function(align, oldAlign) {
  var me = this, iconAlignClasses = me._iconAlignClasses, el = me.el;
  if (oldAlign) {
    el.removeCls(iconAlignClasses[oldAlign]);
  }
  if (align) {
    el.addCls(iconAlignClasses[align]);
  }
  el.toggleCls(me.iconAlignVerticalCls, align === 'top' || align === 'bottom');
}, updateIconCls:function(cls, oldCls) {
  var iconEl = this.iconElement;
  this.syncIconVisibility();
  if (oldCls) {
    iconEl.removeCls(oldCls);
  }
  if (cls) {
    iconEl.addCls(cls);
  }
}, updateRotation:function(rotation, oldRotation) {
  var me = this, verticalCls = me.verticalCls, horizontalCls = me.horizontalCls, el = me.el;
  oldRotation = parseInt(oldRotation, 10);
  rotation = parseInt(rotation, 10);
  if (oldRotation !== 0) {
    el.removeCls(me._rotationClasses[oldRotation]);
  }
  if (rotation === 0) {
    el.replaceCls(verticalCls, horizontalCls);
  } else {
    el.replaceCls(horizontalCls, [verticalCls, me._rotationClasses[rotation]]);
  }
  if (Ext.isSafari && this.rendered) {
    this.repaintBodyElement();
  }
}, updateRotateIcon:function(rotateIcon) {
  this.el.toggleCls(this.rotateIconCls, !!rotateIcon);
}, updateText:function(text) {
  var el = this.textElement.dom;
  el.innerHTML = text || '\x26#160;';
  el.setAttribute('data-title', text);
}, updateTextAlign:function(align, oldAlign) {
  var me = this, textAlignClasses = me._textAlignClasses;
  if (oldAlign) {
    me.removeCls(textAlignClasses[oldAlign]);
  }
  if (align) {
    me.addCls(textAlignClasses[align]);
  }
}, privates:{repaintBodyElement:function() {
  var bodyElement = this.bodyElement.dom, bodyStyle = bodyElement.style;
  bodyStyle.width = '-webkit-min-content';
  bodyElement.offsetWidth;
  bodyStyle.width = '';
}, syncIconVisibility:function() {
  this.el.toggleCls(this.hasIconCls, !!(this.getIcon() || this.getIconCls()));
}}, deprecated:{'6.5':{configs:{glyph:null}}}});
Ext.define('Ext.panel.DateTitle', {extend:Ext.panel.Title, xtype:'datetitle', classCls:Ext.baseCSSPrefix + 'datetitle', template:[{reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', children:[{reference:'iconElement', cls:Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon'}, {cls:Ext.baseCSSPrefix + 'text-container-el', children:[{reference:'yearElement', cls:Ext.baseCSSPrefix + 'year-el'}, {reference:'textElement', cls:Ext.baseCSSPrefix + 'text-el'}]}]}], config:{split:{cached:true, 
$value:false}, titleActive:{cached:true, $value:true}, year:null}, initialize:function() {
  var me = this;
  me.callParent();
  me.yearElement.on('tap', 'onYearTap', me);
  me.textElement.on('tap', 'onTextTap', me);
}, updateSplit:function(split) {
  this.yearElement.setDisplayed(split);
  this.toggleCls(Ext.baseCSSPrefix + 'split', split);
}, updateTitleActive:function(titleActive) {
  var cls = Ext.baseCSSPrefix + 'inactive';
  this.textElement.toggleCls(cls, !titleActive);
  this.yearElement.toggleCls(cls, titleActive);
}, updateYear:function(year) {
  this.yearElement.dom.textContent = year;
}, privates:{onTextTap:function(e) {
  this.fireEvent('titletap', this, e);
}, onYearTap:function(e) {
  this.fireEvent('yeartap', this, e);
}}});
Ext.define('Ext.panel.YearPicker', {extend:Ext.dataview.BoundList, xtype:'yearpicker', classCls:Ext.baseCSSPrefix + 'yearpicker', config:{defaultOffset:100, end:undefined, start:undefined}, itemConfig:{ui:'yearpicker', tools:null}, itemTpl:'{year}', pinFooters:false, pinHeaders:false, scrollToTopOnRefresh:false, initialize:function() {
  this.callParent();
  this.rebuildStore();
}, focusYear:function(year) {
  var me = this, rec = me.getStore().getById(year), item = me.mapToItem(rec), scrollable = me.getScrollable(), y = scrollable.getEnsureVisibleXY(item.element, {align:{y:'center?'}}).y;
  scrollable.scrollTo(null, y, false);
  me.getNavigationModel().setLocation(rec);
  me.select(rec);
}, onChildTap:function(location) {
  var rec = location.record;
  if (rec) {
    location.event.stopEvent();
    this.fireEvent('yeartap', this, rec.id);
  }
}, applyEnd:function(end) {
  if (!end) {
    end = (new Date).getFullYear() + this.getDefaultOffset();
  }
  return end;
}, updateEnd:function() {
  this.rebuildStore();
}, applyStart:function(start) {
  if (!start) {
    start = (new Date).getFullYear() - this.getDefaultOffset();
  }
  return start;
}, updateStart:function() {
  this.rebuildStore();
}, privates:{forceRefreshOnRender:true, rebuildStore:function() {
  var me = this, start = me.getStart(), end = me.getEnd(), store = me.getStore(), data, i;
  if (me.isConfiguring) {
    return;
  }
  if (!store) {
    store = new Ext.data.Store({autoDestroy:true});
    me.setStore(store);
  }
  data = [];
  for (i = start; i <= end; ++i) {
    data.push({id:i, year:i});
  }
  store.loadData(data);
}}});
Ext.define('Ext.panel.Date', {extend:Ext.Panel, xtype:'datepanel', config:{animation:true, autoConfirm:false, captionFormat:{$value:'F Y', cached:true}, dateCellFormat:{$value:'j', cached:true}, disabledDates:null, disabledDays:null, focusableDate:null, format:{$value:Ext.Date.defaultFormat, cached:true}, handler:null, headerFormat:{$value:'D, M j Y', cached:true}, headerLength:1, hideCaptions:true, hideOutside:false, maxDate:null, minDate:null, navigationPosition:'header', nextText:'Next Month (Control+Right)', 
panes:1, prevText:'Previous Month (Control+Left)', selectOnNavigate:true, showAfterMaxDate:false, showBeforeMinDate:false, showFooter:null, showTodayButton:null, specialDates:null, specialDays:null, splitTitle:false, startDay:{$value:Ext.Date.firstDayOfWeek, cached:true}, titleAnimation:null, value:undefined, weekendDays:{$value:Ext.Date.weekendDays, cached:true}, yearPicker:{lazy:true, $value:{}}, yearPickerDefaults:null}, focusable:true, tabIndex:0, border:false, mouseWheelBuffer:500, autoSize:null, 
headerCls:Ext.baseCSSPrefix + 'datepanelheader', titleCls:Ext.baseCSSPrefix + 'datetitle', toolCls:[Ext.baseCSSPrefix + 'paneltool', Ext.baseCSSPrefix + 'datepaneltool'], header:{title:{xtype:'datetitle'}}, tools:{previousMonth:{reference:'navigatePrevMonth', iconCls:'x-fa fa-angle-left', cls:Ext.baseCSSPrefix + 'left-year-tool ', weight:-100, increment:-1, focusable:false, tabIndex:null, forceTabIndex:true, listeners:{click:'onMonthToolClick'}}, previousYear:{reference:'navigatePrevYear', iconCls:'x-fa fa-angle-double-left', 
cls:Ext.baseCSSPrefix + 'left-month-tool', weight:-90, increment:-12, focusable:false, tabIndex:null, forceTabIndex:true, listeners:{click:'onMonthToolClick'}}, nextYear:{reference:'navigateNextYear', iconCls:'x-fa fa-angle-double-right', cls:Ext.baseCSSPrefix + 'right-month-tool', weight:90, increment:12, focusable:false, tabIndex:null, forceTabIndex:true, listeners:{click:'onMonthToolClick'}}, nextMonth:{reference:'navigateNextMonth', iconCls:'x-fa fa-angle-right', cls:Ext.baseCSSPrefix + 'right-year-tool', 
weight:100, increment:1, focusable:false, tabIndex:null, forceTabIndex:true, listeners:{click:'onMonthToolClick'}}}, keyMapTarget:'bodyElement', keyMap:{'*+LEFT':'onLeftArrowKey', '*+RIGHT':'onRightArrowKey', UP:'onUpArrowKey', DOWN:'onDownArrowKey', '*+PAGE_UP':'onPageUpKey', '*+PAGE_DOWN':'onPageDownKey', HOME:'onHomeKey', END:'onEndKey', ENTER:'onEnterKey', SPACE:'onSpaceKey', BACKSPACE:'onBackspaceKey', '*+TAB':'onTabKey', scope:'this'}, paneXtype:'dateview', classCls:Ext.baseCSSPrefix + 'datepanel', 
layout:{type:'carousel', animation:{duration:100}}, defaultListenerScope:true, referenceHolder:true, buttonToolbar:{enableFocusableContainer:false, cls:Ext.baseCSSPrefix + 'datepanel-footer', reference:'footer'}, buttons:{footerTodayButton:{text:'Today', tabIndex:-1, hidden:true, weight:-20, handler:'onTodayButtonClick', reference:'footerTodayButton'}, spacer:{xtype:'component', weight:-10, flex:1}, ok:{tabIndex:-1, handler:'onOkButtonClick'}, cancel:{tabIndex:-1, handler:'onCancelButtonClick'}}, 
sidePaneOffset:2, initialize:function() {
  var me = this, value = me.getValue();
  me.callParent();
  me.setToolText('navigatePrevMonth', me.getPrevText());
  me.setToolText('navigateNextMonth', me.getNextText());
  me.bodyElement.on({click:{delegate:me.cellSelector, fn:'onDateClick'}, focus:'onBodyFocus', wheel:Ext.Function.createThrottled(me.onMouseWheel, me.mouseWheelBuffer), scope:me});
  me.getShowFooter();
  me.preventAnim = true;
  me.setFocusableDate(value);
  me.preventAnim = false;
  me.setTitleByDate(value);
  Ext.fly(me.getCellByDate(value)).addCls(me.selectedCls);
}, onRender:function() {
  this.callParent();
  this.measurePaneSize();
}, doDestroy:function() {
  var me = this;
  Ext.destroy(me.animTitle, me.animBody);
  me.callParent();
}, focusDate:function(date) {
  var me = this;
  me.doFocus = true;
  me.setFocusableDate(date);
  me.doFocus = false;
}, updateAnimation:function(animate) {
  this.getLayout().setAnimation(animate);
}, updateAutoConfirm:function(autoConfirm) {
  var me = this;
  me.getButtons();
  if (!autoConfirm) {
    me.setShowFooter(true);
  } else {
    me.setShowFooter(me.initialConfig.showFooter);
  }
}, updateCaptionFormat:function(format) {
  this.broadcastConfig('captionFormat', format);
}, updateDateCellFormat:function(format) {
  this.broadcastConfig('dateCellFormat', format);
}, applyDisabledDates:function(dates) {
  if (!dates) {
    return dates;
  }
  var cfg = {dates:{}}, re = [], item, i, len;
  if (dates instanceof RegExp) {
    cfg.re = dates;
  } else {
    if (!Ext.isArray(dates)) {
      dates = [dates];
    }
    for (i = 0, len = dates.length; i < len; i++) {
      item = dates[i];
      if (item instanceof Date) {
        item = Ext.Date.clearTime(item);
        cfg.dates[item.getTime()] = true;
      } else {
        if (item instanceof RegExp) {
          re.push(item.source);
        } else {
          re.push(Ext.String.escapeRegex(item));
        }
      }
    }
    if (re.length) {
      cfg.re = new RegExp('(?:' + re.join('|') + ')');
    }
  }
  return cfg;
}, updateDisabledDates:function() {
  this.refreshPanes();
}, applyDisabledDays:function(days) {
  return days ? Ext.Array.toMap(days) : days;
}, updateDisabledDays:function() {
  this.refreshPanes();
}, updateFormat:function(format) {
  this.broadcastConfig('format', format);
}, updateHeader:function(header, oldHeader) {
  this.callParent([header, oldHeader]);
  header.getTitle().on({scope:this, yeartap:'onYearTitleTap', titletap:'onTitleTap'});
}, applyMaxDate:function(date) {
  if (typeof date === 'string') {
    date = Ext.Date.parse(date, this.getFormat());
  }
  return date;
}, updateMaxDate:function() {
  this.refreshPanes();
}, applyMinDate:function(date) {
  if (typeof date === 'string') {
    date = Ext.Date.parse(date, this.getFormat());
  }
  return date;
}, updateMinDate:function() {
  this.refreshPanes();
}, updateNavigationPosition:function(pos) {
  var me = this, toolList = me.toolList, len = toolList.length, isHeader = pos === 'header', ct = isHeader ? me.toolCt : me.getHeader(), tools, i, c;
  if (isHeader && me.isConfiguring) {
    return;
  }
  me.getTools();
  tools = [];
  for (i = 0; i < len; ++i) {
    c = me.lookup(toolList[i]);
    if (c) {
      tools.push(c);
      ct.remove(c, false);
      c.toggleCls(me.toolCls, isHeader);
    }
  }
  me.toolCt = Ext.destroy(me.toolCt);
  if (pos === 'header') {
    me.getHeader().add(tools);
  } else {
    tools.push({xtype:'component', flex:1, weight:0});
    me.toolCt = me.add({xtype:'container', cls:Ext.baseCSSPrefix + 'navigation-tools', defaultType:'tool', weighted:true, layout:'hbox', bottom:'auto', items:tools});
  }
}, updateNextText:function(text) {
  this.setToolText('navigateNextMonth', text);
}, updatePrevText:function(text) {
  this.setToolText('navigatePrevMonth', text);
}, applyPanes:function(count) {
  if (count < 1) {
    Ext.raise('Cannot configure less than 1 pane for Calendar picker');
  }
  return count;
}, updatePanes:function(count) {
  var me = this;
  me.getLayout().setVisibleChildren(count);
  me.initPanes();
  me.singlePane = count === 1;
  me.toggleCls(Ext.baseCSSPrefix + 'single', me.singlePane);
}, updateShowFooter:function(showFooter) {
  this.lookup('footer').setHidden(!showFooter);
  this.getShowTodayButton();
}, updateShowTodayButton:function(showButton) {
  var footerBtn;
  this.getButtons();
  footerBtn = this.lookup('footerTodayButton');
  if (footerBtn) {
    footerBtn.setHidden(!showButton);
  }
}, applySpecialDates:function(dates) {
  return this.applyDisabledDates(dates);
}, updateSpecialDates:function(cfg) {
  this.broadcastConfig('specialDates', cfg);
}, applySpecialDays:function(days) {
  return days ? Ext.Array.toMap(days) : days;
}, updateSpecialDays:function(daysMap) {
  this.broadcastConfig('specialDays', daysMap);
}, updateSplitTitle:function(splitTitle) {
  this.getHeader().getTitle().setSplit(splitTitle);
}, updateStartDay:function(day) {
  this.broadcastConfig('startDay', day);
}, applyValue:function(date) {
  if (typeof date === 'string') {
    date = Ext.Date.parse(date, this.getFormat());
  } else {
    if (!date) {
      date = new Date;
    }
  }
  return Ext.isDate(date) ? Ext.Date.clearTime(date, true) : null;
}, updateValue:function(value, oldValue) {
  var me = this, handler = me.getHandler(), selectedCls = me.selectedCls, cell;
  if (oldValue) {
    cell = me.getCellByDate(oldValue);
    if (cell) {
      Ext.fly(cell).removeCls(selectedCls);
    }
  }
  if (!me.isConfiguring) {
    if (me.hasFocus) {
      me.focusDate(value);
    } else {
      me.setFocusableDate(value);
    }
    cell = me.getCellByDate(value);
    if (cell) {
      Ext.fly(cell).addCls(selectedCls);
    }
    me.setTitleByDate(value);
    me.fireEvent('change', me, value, oldValue);
    if (handler) {
      Ext.callback(handler, me.scope, [me, value, oldValue]);
    }
  }
}, applyWeekendDays:function(days) {
  return Ext.Array.toMap(days);
}, updateWeekendDays:function(daysMap) {
  this.broadcastConfig('weekendDays', daysMap);
}, applyYearPicker:function(yearPicker, oldYearPicker) {
  return Ext.updateWidget(oldYearPicker, yearPicker, this, 'createYearPicker', 'yearPickerDefaults');
}, updateYearPicker:function(yearPicker) {
  if (yearPicker) {
    this.add(yearPicker);
  }
}, replacePanes:function(increment, animate) {
  var me = this, panes, cb, direction, ret;
  if (me.destroying || me.destroyed) {
    return;
  }
  panes = me.getLayout().getVisibleItems();
  cb = function() {
    var pane, offset, j, jlen;
    for (j = 0, jlen = panes.length; j < jlen; j++) {
      pane = panes[j];
      offset = pane.getMonthOffset();
      pane.setMonthOffset(offset + increment);
    }
  };
  if (animate == null) {
    animate = me.getAnimation();
  }
  if (animate) {
    direction = increment < 0 ? 'up' : 'down';
    ret = me.animateVertical(me.carouselElement, direction, 0, cb, 'animBody');
  } else {
    cb();
    ret = Ext.Deferred.getCachedResolved();
  }
  return ret;
}, initPanes:function() {
  var me = this, count = me.getPanes() + this.sidePaneOffset, panes = [], oldPanes, index, center, i;
  index = count - 1;
  center = !index ? index : index % 2 ? Math.floor(index / 2) + 1 : Math.floor(index / 2);
  for (i = 0; i < count; i++) {
    panes.push(me.getPaneTemplate(i - center));
  }
  oldPanes = me.getInnerItems();
  for (i = 0; i < oldPanes.length; i++) {
    me.remove(oldPanes[i], true);
  }
  me.add(panes);
  me.getLayout().setFrontItem(center, false);
}, getPaneByDate:function(date) {
  var me = this, panes = me.getInnerItems(), month, pane, i, len;
  month = Ext.Date.getFirstDateOfMonth(date);
  for (i = 0, len = panes.length; i < len; i++) {
    pane = panes[i];
    if (Ext.Date.isEqual(pane.getMonth(), month)) {
      return pane;
    }
  }
  return null;
}, getCellByDate:function(date) {
  var pane = this.getPaneByDate(date);
  return pane ? pane.getCellByDate(date) : null;
}, updateCellTabIndex:function(date, tabIndex) {
  var cell = date && this.getCellByDate(date);
  if (cell) {
    Ext.fly(cell).setTabIndex(tabIndex);
  }
  return cell;
}, canSwitchTo:function(date, offset) {
  var me = this, boundary, prevent;
  if (offset < 0) {
    boundary = me.getMinDate();
    prevent = !me.getShowBeforeMinDate();
    if (boundary && prevent) {
      if (date.getTime() < Ext.Date.getFirstDateOfMonth(boundary).getTime()) {
        return false;
      }
    }
  } else {
    if (offset > 0) {
      boundary = me.getMaxDate();
      prevent = !me.getShowAfterMaxDate();
      if (boundary && prevent) {
        if (date.getTime() > Ext.Date.getLastDateOfMonth(boundary).getTime()) {
          return false;
        }
      }
    }
  }
  return true;
}, setValueWithoutAnim:function(value) {
  this.preventAnim = true;
  this.setValue(value);
  this.preventAnim = false;
}, navigateTo:function(date, animate) {
  var me = this, layout = me.getLayout(), month, increment, boundary, prevent;
  if (date.getTime() < (month = layout.getFirstVisibleItem().getMonth()).getTime()) {
    boundary = month;
  } else {
    if (date.getTime() > (month = layout.getLastVisibleItem().getMonth()).getTime()) {
      boundary = month;
    } else {
      boundary = date;
    }
  }
  increment = date.getFullYear() * 12 + date.getMonth() - (boundary.getFullYear() * 12 + boundary.getMonth());
  if (increment < 0) {
    boundary = me.getMinDate();
    prevent = !me.getShowBeforeMinDate();
    if (boundary && prevent) {
      if (date.getTime() < Ext.Date.getFirstDateOfMonth(boundary).getTime()) {
        increment = 0;
      }
    }
  } else {
    if (increment > 0) {
      boundary = me.getMaxDate();
      prevent = !me.getShowAfterMaxDate();
      if (boundary && prevent) {
        if (date.getTime() > Ext.Date.getLastDateOfMonth(boundary).getTime()) {
          increment = 0;
        }
      }
    }
  }
  return me.navigateByIncrement(increment, animate, 0);
}, switchPanes:function(increment, animate) {
  var me = this, layout = me.getLayout(), edgePane, pane;
  edgePane = increment < 0 ? layout.getFirstVisibleItem() : layout.getLastVisibleItem();
  pane = layout.getEdgeItem(increment);
  pane.setMonthOffset(edgePane.getMonthOffset() + increment);
  return layout.move(increment, animate);
}, onMonthToolClick:function(tool) {
  var me = this, D = Ext.Date, increment = tool.increment, date = D.add(me.getFocusableDate(), D.MONTH, increment), hasFocus = me.hasFocus, pane = pane = this.getLayout().getFrontItem(), month = D.add(pane.getMonth(), D.MONTH, increment);
  if (!me.canSwitchTo(month, increment)) {
    return;
  }
  me.navIncrement = me.singlePane ? 0 : increment;
  if (hasFocus || me.getSelectOnNavigate()) {
    me.setValue(date);
  } else {
    me.doFocus = hasFocus;
    me.setFocusableDate(date);
    me.doFocus = false;
  }
  me.navIncrement = 0;
}, onDateClick:function(e) {
  var me = this, cell = e.getTarget(me.cellSelector, me.bodyElement), date = cell && cell.date, focus = true, disabled = cell && cell.disabled;
  if (!date || me.getDisabled()) {
    return;
  }
  if (!disabled) {
    me.setValue(date);
    if (me.getAutoConfirm()) {
      if (e.pointerType === 'touch') {
        e.preventDefault();
      }
      focus = false;
      me.fireEvent('select', me, date);
    }
  }
  if (focus) {
    me.focusDate(date);
  }
}, onMouseWheel:function(e) {
  var dy = e.browserEvent.deltaY;
  if (dy && !this.pickerVisible) {
    this.onMonthToolClick({increment:Ext.Number.sign(dy)});
  }
}, onOkButtonClick:function() {
  this.setValue(this.getFocusableDate());
}, onCancelButtonClick:function() {
  this.fireEventArgs('tabout', [this]);
}, onTodayButtonClick:function() {
  var me = this, offset;
  offset = me.getLayout().getFrontItem().getMonthOffset();
  if (offset !== 0) {
    if (Math.abs(offset) === 1) {
      me.switchPanes(-offset);
    } else {
      me.replacePanes(-offset);
    }
  }
  me.setValue(Ext.Date.clearTime(new Date));
}, getFocusEl:function() {
  if (!this.initialized) {
    return null;
  }
  return this.getCellByDate(this.getFocusableDate());
}, onLeftArrowKey:function(e) {
  this.walkCells(e.target.date, e.ctrlKey ? Ext.Date.MONTH : Ext.Date.DAY, -1);
  e.preventDefault();
}, onRightArrowKey:function(e) {
  this.walkCells(e.target.date, e.ctrlKey ? Ext.Date.MONTH : Ext.Date.DAY, 1);
  e.preventDefault();
}, onUpArrowKey:function(e) {
  this.walkCells(e.target.date, Ext.Date.DAY, -7);
  e.preventDefault();
}, onDownArrowKey:function(e) {
  this.walkCells(e.target.date, Ext.Date.DAY, 7);
  e.preventDefault();
}, onPageUpKey:function(e) {
  var unit = e.ctrlKey || e.shiftKey ? Ext.Date.YEAR : Ext.Date.MONTH;
  this.walkCells(e.target.date, unit, -1);
  e.preventDefault();
}, onPageDownKey:function(e) {
  var unit = e.ctrlKey || e.shiftKey ? Ext.Date.YEAR : Ext.Date.MONTH;
  this.walkCells(e.target.date, unit, 1);
  e.preventDefault();
}, onHomeKey:function(e) {
  this.walkCells(Ext.Date.getFirstDateOfMonth(e.target.date));
  e.preventDefault();
}, onEndKey:function(e) {
  this.walkCells(Ext.Date.getLastDateOfMonth(e.target.date));
  e.preventDefault();
}, onBackspaceKey:function(e) {
  this.walkCells(new Date);
  e.preventDefault();
}, onEnterKey:function(e) {
  var me = this, target = e.target, date = target && target.date;
  if (date && !target.disabled) {
    me.setValue(date);
    me.fireEvent('select', me, target.date);
  }
}, onSpaceKey:function(e) {
  this.onEnterKey(e);
  e.preventDefault();
}, onTabKey:function(e) {
  this.handleTabKey(e);
  return true;
}, handleTabKey:function(e) {
  var me = this, target = e.target, picker = me.pickerField;
  if (!me.getDisabled() && me.getAutoConfirm() && target && target.date && !target.disabled) {
    me.setValue(target.date);
    if (picker && picker.isEditorComponent) {
      e.preventDefault();
    }
  } else {
    me.fireEventArgs('tabout', [me]);
  }
}, walkCells:function(date, unit, increment) {
  var me = this, newDate;
  if (!me.getDisabled()) {
    date = me.getFocusableDate();
    newDate = unit ? Ext.Date.add(date, unit, increment) : date;
    if (me.isDateDisabled(newDate)) {
      me.focusDate(newDate);
    } else {
      me.setValue(newDate);
    }
  }
}, onBodyFocus:function(e) {
  var me = this, date = me.getFocusableDate(), cell = me.getCellByDate(date);
  if (!cell) {
    me.navigateTo(date, false);
  }
  cell = me.updateCellTabIndex(date, me.getTabIndex());
  cell.focus();
}, getTabIndex:function() {
  return this.getConfig('tabIndex', true);
}, getFocusClsEl:function() {
  return this.bodyElement;
}, onFocusEnter:function(e) {
  if (this.bodyElement.contains(e.target)) {
    this.onFocus(e);
  }
  this.callParent([e]);
}, onFocusLeave:function(e) {
  this.onBlur(e);
  this.callParent([e]);
}, privates:{cellSelector:'.' + Ext.baseCSSPrefix + 'cell', clonedCls:Ext.baseCSSPrefix + 'cloned', lastNavigate:0, hideFocusCls:Ext.baseCSSPrefix + 'hide-focus', selectedCls:Ext.baseCSSPrefix + 'selected', toolList:['navigatePrevMonth', 'navigatePrevYear', 'navigateNextYear', 'navigateNextMonth'], paneWidthMap:{}, pickerVisible:false, applyFocusableDate:function(date) {
  var me = this, D = Ext.Date, boundary;
  if (date) {
    date = D.clearTime(date || new Date);
    if ((boundary = me.getMinDate()) && !me.getShowBeforeMinDate() && date.getTime() < boundary.getTime()) {
      date = boundary;
    } else {
      if ((boundary = me.getMaxDate()) && !me.getShowAfterMaxDate() && date.getTime() > boundary.getTime()) {
        date = boundary;
      }
    }
  }
  return date;
}, updateFocusableDate:function(date, oldDate) {
  var me = this, focus = me.doFocus, layout = me.getLayout(), cls = me.hideFocusCls, increment = me.navIncrement, visibleItems, toPane, anim, navigate, oldCell, p;
  if (me.destroying || me.destroyed) {
    return;
  }
  if (oldDate) {
    oldCell = me.getCellByDate(oldDate);
    me.updateCellTabIndex(oldDate, -1);
  }
  if (date) {
    toPane = me.getPaneByDate(date);
    if (!me.preventAnim) {
      anim = me.getAnimation();
    }
    visibleItems = layout.getVisibleItems();
    me.lastNavigate = navigate = Date.now();
    if (!increment && (!anim || visibleItems.indexOf(toPane) > -1)) {
      me.navigateTo(date, false);
      if (focus) {
        me.getCellByDate(date).focus();
      }
    } else {
      if (oldCell) {
        Ext.fly(oldCell).addCls(cls);
      }
      p = increment ? me.navigateByIncrement(increment) : me.navigateTo(date);
      p.then(function() {
        oldCell = me.getCellByDate(oldDate);
        if (oldCell) {
          Ext.fly(oldCell).removeCls(cls);
        }
        if (focus && me.lastNavigate === navigate) {
          me.getCellByDate(date).focus();
        }
      });
    }
    me.updateCellTabIndex(date, me.getTabIndex());
  }
}, animateVertical:function(el, direction, offset, beforeFn, prop) {
  var me = this, clone = el.dom.cloneNode(true), ret = new Ext.Deferred;
  clone.id = '';
  Ext.fly(clone).addCls(me.clonedCls);
  el.parent().appendChild(clone);
  if (beforeFn) {
    beforeFn();
  }
  Ext.destroy(me[prop]);
  me[prop] = Ext.Animator.run([{offset:offset, type:'slide', direction:direction, element:el}, {offset:offset, type:'slideOut', direction:direction, element:clone, callback:function() {
    Ext.fly(clone).destroy();
    me[prop] = null;
    ret.resolve();
  }}]);
  return ret.promise;
}, broadcastConfig:function(config, value) {
  if (this.isConfiguring) {
    return;
  }
  var panes = this.getInnerItems(), setter, pane, i, len;
  setter = Ext.Config.get(config).names.set;
  for (i = 0, len = panes.length; i < len; i++) {
    pane = panes[i];
    if (pane[setter]) {
      pane[setter](value);
    }
  }
}, createYearPicker:function(config) {
  return Ext.apply({xtype:'yearpicker', hidden:true, top:0, right:0, bottom:0, left:0, listeners:{yeartap:'onYearPickerTap'}}, config);
}, getPaneTemplate:function(offset) {
  var me = this;
  return {xtype:me.paneXtype, monthOffset:offset, hideOutside:me.getHideOutside(), hideCaption:me.getHideCaptions(), startDay:me.getStartDay(), weekendDays:me.getWeekendDays(), specialDates:me.getSpecialDates(), specialDays:me.getSpecialDays(), format:me.getFormat(), captionFormat:me.getCaptionFormat(), dateCellFormat:me.getDateCellFormat(), headerLength:me.getHeaderLength(), transformCellCls:me.transformCellCls};
}, getPositionedItemTarget:function() {
  return this.bodyElement;
}, isDateDisabled:function(date) {
  var me = this, ms = date.getTime(), minDate = me.getMinDate(), maxDate = me.getMaxDate(), disabled, disabledDays, disabledDates, formatted, re;
  disabled = minDate && ms < minDate.getTime() || maxDate && ms > maxDate.getTime();
  if (!disabled) {
    disabledDays = me.getDisabledDays();
    if (disabledDays) {
      disabled = disabledDays[date.getDay()];
    }
  }
  if (!disabled) {
    disabledDates = me.getDisabledDates();
    if (disabledDates) {
      disabled = disabledDates.dates[ms];
      re = disabledDates.re;
      if (!disabled && re) {
        formatted = Ext.Date.format(date, me.getFormat());
        disabled = re.test(formatted);
      }
    }
  }
  return !!disabled;
}, measurePaneSize:function() {
  var me = this, count = me.getPanes(), ui = me.getUi() || 'default', map = me.paneWidthMap, borderWidth;
  if (!map.hasOwnProperty(ui)) {
    map[ui] = this.getLayout().getFrontItem().measurePaneSize();
  }
  borderWidth = me.el.getBorderWidth('lr');
  me.setWidth(borderWidth + count * map[ui]);
}, navigateByIncrement:function(increment, animate) {
  var ret;
  if (Math.abs(increment) === 1) {
    ret = this.switchPanes(increment, animate);
  } else {
    if (increment !== 0) {
      ret = this.replacePanes(increment, animate);
    } else {
      if (!animate) {
        this.getLayout().cancelAnimation();
        ret = Ext.Deferred.getCachedResolved();
      }
    }
  }
  return ret;
}, onTitleTap:function() {
  var visible;
  if (this.getSplitTitle()) {
    visible = false;
  } else {
    visible = !this.pickerVisible;
  }
  this.toggleYearPicker(visible);
}, onYearPickerTap:function(picker, year) {
  this.toggleYearPicker(false);
  var d = Ext.Date.clone(this.getFocusableDate());
  d.setFullYear(year);
  this.setValue(d);
}, onYearTitleTap:function() {
  this.toggleYearPicker(!this.pickerVisible);
}, refreshPanes:function() {
  if (this.isConfiguring) {
    return;
  }
  var panes = this.getInnerItems(), len = panes.length, i;
  for (i = 0; i < len; ++i) {
    panes[i].refresh();
  }
}, setTitleByDate:function(date) {
  var me = this, prev = me.lastTitleDate, anim;
  if (prev && prev.getTime() === date.getTime()) {
    anim = false;
  } else {
    anim = this.preventAnim ? false : anim;
  }
  me.setTitleText(Ext.Date.format(date, me.getHeaderFormat()), date, prev, anim);
  me.lastTitleDate = date;
}, setTitleText:function(text, date, oldDate, animate) {
  var me = this, title, direction, titleAnim;
  if (me.destroying || me.destroyed) {
    return;
  }
  if (animate === undefined) {
    titleAnim = me.getTitleAnimation();
    if (titleAnim !== null) {
      animate = titleAnim;
    } else {
      animate = me.getAnimation();
    }
  }
  animate = me.rendered ? animate : false;
  title = me.getHeader().getTitle();
  if (animate) {
    if (me.getSplitTitle()) {
      Ext.raise('Animation is not supported with title split');
    }
    direction = (oldDate || date).getTime() < date.getTime() ? 'bottom' : 'top';
    me.animateVertical(title.textElement, direction, '150%', function() {
      title.setText(text);
    }, 'animTitle');
  } else {
    if (me.getSplitTitle()) {
      title.setYear(date.getFullYear());
      title.setText(text);
    } else {
      title.setText(text);
    }
  }
}, setToolText:function(type, text) {
  var tool = this.lookup(type);
  if (tool) {
    tool.setTooltip(text);
  }
}, toggleYearPicker:function(visible) {
  var me = this, picker = me.getYearPicker();
  if (picker) {
    if (me.getSplitTitle()) {
      me.getHeader().getTitle().setTitleActive(!visible);
    }
    picker.setHidden(!visible);
    if (visible) {
      picker.focusYear(me.getFocusableDate().getFullYear());
    }
    me.pickerVisible = visible;
  }
}}});
Ext.define('Ext.theme.neptune.panel.Date', {override:'Ext.panel.Date', border:true});
Ext.define('Ext.theme.material.panel.Date', {override:'Ext.panel.Date', config:{headerFormat:'D, M j', hideCaptions:false, hideOutside:true, navigationPosition:'caption', selectOnNavigate:false, showTodayButton:false, splitTitle:true, titleAnimation:false, tools:{previousYear:null, nextYear:null}}});
Ext.define('Ext.field.Date', {extend:Ext.field.Picker, alternateClassName:['Ext.form.DatePicker', 'Ext.field.DatePicker'], xtype:['datefield', 'datepickerfield'], config:{destroyPickerOnHide:false, dataType:{type:'date'}, dateFormat:'', altFormats:'m/d/Y|' + 'n/j/Y|' + 'n/j/y|' + 'm/j/y|' + 'n/d/y|' + 'm/j/Y|' + 'n/d/Y|' + 'm-d-y|' + 'm-d-Y|' + 'm/d|' + 'm-d|' + 'md|' + 'mdy|' + 'mdY|' + 'd|' + 'Y-m-d|' + 'n-j|' + 'n/j', minDate:null, maxDate:null, triggers:{expand:{type:'date'}}}, classCls:Ext.baseCSSPrefix + 
'datepickerfield', matchFieldWidth:false, isDateField:true, minDateMessage:'The date in this field must be equal to or after {0}', maxDateMessage:'The date in this field must be equal to or before {0}', initTime:'12', initTimeFormat:'H', floatedPicker:{xtype:'datepanel', autoConfirm:true, floated:true, listeners:{tabout:'onTabOut', select:'onPickerChange', scope:'owner'}, keyMap:{ESC:'onTabOut', scope:'owner'}}, edgePicker:{xtype:'datepicker', cover:true}, parseValidator:'date', applyValue:function(value, 
oldValue) {
  if (!(value || value === 0)) {
    value = null;
  }
  value = this.callParent([value, oldValue]);
  if (value) {
    if (this.isConfiguring) {
      this.originalValue = value;
    }
    if (Ext.isDate(value) && Ext.isDate(oldValue) && value.getTime() === oldValue.getTime()) {
      return;
    }
  }
  return value;
}, updateValue:function(value, oldValue) {
  var picker = this._picker;
  if (picker && picker.isPicker && Ext.isDate(value)) {
    this.updatePickerValue(picker, value);
  }
  this.callParent([value, oldValue]);
}, updatePickerValue:function(picker, value) {
  picker.setValue(value);
}, applyInputValue:function(value, oldValue) {
  if (Ext.isDate(value)) {
    value = Ext.Date.format(value, this.getDateFormat());
  }
  return this.callParent([value, oldValue]);
}, applyAltFormats:function(altFormats) {
  if (altFormats && !Ext.isArray(altFormats)) {
    altFormats = altFormats.split('|');
  }
  return altFormats;
}, applyDateFormat:function(dateFormat) {
  return dateFormat || Ext.util.Format.defaultDateFormat;
}, updateDateFormat:function() {
  var me = this, value;
  if (!me.isConfiguring && !me.hasFocus) {
    value = me.getValue();
    if (Ext.isDate(value)) {
      me.setInputValue(value);
    }
  }
}, applyMinDate:function(minDate) {
  if (typeof minDate === 'string') {
    minDate = Ext.Date.parse(minDate, this.getDateFormat());
  }
  if (minDate !== null && !Ext.isDate(minDate)) {
    Ext.raise('Date object or string in dateFormat required');
  }
  return minDate ? Ext.Date.clearTime(minDate, true) : null;
}, applyMaxDate:function(maxDate) {
  if (typeof maxDate === 'string') {
    maxDate = Ext.Date.parse(maxDate, this.getDateFormat());
  }
  if (maxDate !== null && !Ext.isDate(maxDate)) {
    Ext.raise('Date object or string in dateFormat required');
  }
  return maxDate ? Ext.Date.clearTime(maxDate, true) : null;
}, getFormattedValue:function(format) {
  var value = this.getValue();
  return Ext.isDate(value) ? Ext.Date.format(value, format || this.getDateFormat()) : '';
}, applyPicker:function(picker, oldPicker) {
  var me = this;
  picker = me.callParent([picker, oldPicker]);
  if (picker) {
    me.pickerType = picker.xtype === 'datepicker' ? 'edge' : 'floated';
    picker.ownerCmp = me;
  }
  return picker;
}, createFloatedPicker:function() {
  return this.getFloatedPicker();
}, createEdgePicker:function() {
  var me = this, minDate = this.getMinDate(), maxDate = this.getMaxDate();
  return Ext.merge({yearFrom:minDate ? minDate.getFullYear() : (new Date).getFullYear() - 20, yearTo:maxDate ? maxDate.getFullYear() : (new Date).getFullYear() + 20}, me.getEdgePicker());
}, setPickerLocation:function(fromKeyboard) {
  var me = this, pickerType = me.pickerType, picker = me.getPicker(), value = me.getValue(), limit;
  me.$ignorePickerChange = true;
  if (value != null) {
    picker.setValue(value);
  } else {
    if (pickerType === 'edge') {
      picker.setValue(new Date);
    }
  }
  delete me.$ignorePickerChange;
  if (pickerType === 'floated') {
    picker.el.dom.tabIndex = -1;
    limit = me.getMinDate();
    if (limit) {
      picker.setMinDate(limit);
    }
    limit = me.getMaxDate();
    if (limit) {
      picker.setMaxDate(limit);
    }
    value = value || new Date;
    picker.setValueWithoutAnim(value);
    if (fromKeyboard) {
      picker.focusDate(value);
    }
  }
}, doValidate:function(value, errors, skipLazy) {
  var me = this, format = me.getDateFormat(), limit, t;
  me.callParent([value, errors, skipLazy]);
  limit = me.getMinDate();
  t = +value;
  if (limit && t < +limit) {
    limit = Ext.Date.format(limit, format);
    errors.push(Ext.String.format(me.minDateMessage, limit));
  }
  limit = me.getMaxDate();
  if (limit && t > +limit) {
    limit = Ext.Date.format(limit, format);
    errors.push(Ext.String.format(me.maxDateMessage, limit));
  }
}, onPickerChange:function(picker, value) {
  var me = this;
  if (me.$ignorePickerChange) {
    return;
  }
  me.forceSetValue(value);
  me.fireEvent('select', me, value);
  me.onTabOut(picker);
}, onTabOut:function() {
  this.collapse();
}, parseValue:function(value, errors) {
  var me = this, date = value, defaultFormat = me.getDateFormat(), altFormats = me.getAltFormats(), formats = altFormats ? [defaultFormat].concat(altFormats) : [defaultFormat], formatsLength = formats.length, i, format;
  if (date) {
    if (!Ext.isDate(date)) {
      for (i = 0; i < formatsLength; i++) {
        format = formats[i];
        date = Ext.Date.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat);
        if (date) {
          return Ext.Date.clearTime(date);
        }
      }
    }
    if (date !== null) {
      return date;
    }
  }
  return this.callParent([value, errors]);
}, isEqual:function(value1, value2) {
  var v1 = this.transformValue(value1), v2 = this.transformValue(value2);
  return +v1 === +v2;
}, transformValue:function(value) {
  if (Ext.isObject(value)) {
    value = new Date(value.year, value.month, value.day);
    if (isNaN(value.getTime())) {
      value = null;
    }
  }
  return value;
}, doDestroy:function() {
  var picker = this._picker;
  if (picker && picker.isPicker) {
    picker.destroy();
  }
  this.callParent();
}, rawToValue:function(rawValue) {
  var me = this;
  return me.parseValue(rawValue) || rawValue || null;
}, privates:{setShowPickerValue:function(picker) {
  this.updatePickerValue(picker, this.getValue() || new Date);
}}, deprecated:{'6.5':{configs:{format:'dateFormat'}}}});
Ext.define('Ext.theme.material.field.Date', {override:'Ext.field.Date', config:{floatedPicker:{selectOnNavigate:true, header:{hidden:true}}}});
Ext.define('dilocsync.overrides.field.Date', {override:'Ext.field.Date', submitFormat:false, initialize:function() {
  this.callParent(arguments);
  this.resetOriginalValue();
}, getSubmitValue:function() {
  var value = this.getValue();
  if (this.submitFormat) {
    value = Ext.Date.format(value, this.submitFormat);
  }
  return value;
}});
Ext.define('Ext.field.DatePickerNative', {extend:Ext.field.Date, alternateClassName:'Ext.form.DatePickerNative', xtype:'datepickernativefield', onFocus:function(e) {
  var me = this, success, fail, dateTimePickerFunc;
  if (!(navigator.plugins && navigator.plugins.dateTimePicker)) {
    me.callParent();
    return;
  }
  success = function(res) {
    me.setValue(res);
  };
  fail = function(e) {
    console.log('DateTimePicker: error occurred or cancelled: ' + e);
  };
  try {
    dateTimePickerFunc = me.getName() === 'date' ? navigator.plugins.dateTimePicker.selectDate : navigator.plugins.dateTimePicker.selectTime;
    dateTimePickerFunc(success, fail, {value:me.getValue()});
  } catch (ex) {
    fail(ex);
  }
}});
Ext.define('Ext.field.Display', {extend:Ext.field.Field, xtype:'displayfield', alternateClassName:'Ext.form.Display', submitValue:false, validateOnChange:false, focusable:false, readOnly:true, config:{encodeHtml:true, renderer:null}, classCls:Ext.baseCSSPrefix + 'displayfield', initialize:function() {
  this.callParent();
  this.syncDom();
}, getBodyTemplate:function() {
  return [{reference:'inputElement', cls:Ext.baseCSSPrefix + 'input-el'}];
}, updateValue:function(newValue, oldValue) {
  this.callParent([newValue, oldValue]);
  this.syncDom();
}, updateHtmlEncode:function() {
  this.syncDom();
}, updateRenderer:function() {
  this.syncDom();
}, validate:Ext.returnTrue, isValid:Ext.returnTrue, rawToValue:Ext.emptyFn, privates:{getDisplayValue:function() {
  var me = this, value = Ext.valueFrom(me.getValue(), ''), renderer = me.getRenderer();
  if (renderer) {
    value = Ext.callback(renderer, me.scope, [value, me], 0, me);
  }
  return value;
}, syncDom:function() {
  var me = this, dom = me.inputElement.dom, value;
  if (!me.isConfiguring) {
    value = me.getDisplayValue();
    if (me.getEncodeHtml()) {
      dom.textContent = value;
    } else {
      dom.innerHTML = value;
    }
  }
}}});
Ext.define('Ext.field.Email', {extend:Ext.field.Text, alternateClassName:'Ext.form.Email', xtype:'emailfield', config:{autoCapitalize:false}, inputType:'email', classCls:Ext.baseCSSPrefix + 'emailfield'});
Ext.define('Ext.field.File', {extend:Ext.field.Text, xtype:'filefield', mixins:[Ext.mixin.ConfigProxy], isFile:true, proxyConfig:{fileButton:['multiple', 'accept', 'capture']}, readOnly:true, editable:false, focusable:false, inputTabIndex:-1, triggers:{file:{type:'file'}}, classCls:Ext.baseCSSPrefix + 'filefield', captureLookup:{video:'camcorder', image:'camera', audio:'microphone'}, onChange:function(me, value, startValue) {
  me.fireEvent('change', this, value, startValue);
}, applyName:function(name) {
  var multiple;
  if (name) {
    if (multiple && name.substr(-2, 2) !== '[]') {
      name += '[]';
    } else {
      if (!multiple && name.substr(-2, 2) === '[]') {
        name = name.substr(0, name.length - 2);
      }
    }
  }
  return name;
}, updateName:function(name) {
  var fileTrigger = this.getTriggers().file, inputElement = fileTrigger && fileTrigger.getComponent().buttonElement.dom;
  if (name && inputElement) {
    inputElement.name = name;
  }
}, updateMultiple:function() {
  var name = this.getName();
  if (!Ext.isEmpty(name)) {
    this.setName(name);
  }
}, updateTriggers:function(triggers, oldTriggers) {
  this.callParent([triggers, oldTriggers]);
  this.getFileButton().on('change', 'onFileButtonChange', this);
}, updateValue:function(value, oldValue) {
  this.callParent([value, oldValue]);
  this.getFileButton().setValue(value);
}, getFileButton:function() {
  return this.getTriggers().file.getComponent();
}, reset:function() {
  var me = this, original = me.originalValue;
  if (original == null) {
    me.setInputValue('');
    me._value = '';
  }
  me.getFileButton().buttonElement.dom.value = '';
}, getFiles:function() {
  return this.getFileButton().getFiles();
}, privates:{onFileButtonChange:function(fileButton, value) {
  var buttonElement = fileButton.buttonElement.dom, files = buttonElement.files, len, i, file;
  if (files) {
    value = [];
    for (i = 0, len = files.length; i < len; i++) {
      file = files[i];
      value.push(file.name);
    }
    value = value.join(', ');
  }
  this.setValue(value);
}}});
Ext.define('dilocsync.overrides.field.File', {override:'Ext.field.File', previousFiles:[], clearTrigger:null, afterRender:function() {
  var $jscomp$this = this;
  this.clearTrigger = this.el.down('.x-cleartrigger');
  this.clearTrigger.on('click', function() {
    return $jscomp$this.reset();
  });
}, setDisabled:function(_value) {
  this.callParent(arguments);
  this.getFileButton().setDisabled(_value);
  if (_value) {
    this.clearTrigger.hide();
  } else {
    if (this.getFileNames()) {
      this.clearTrigger.show();
    }
  }
}, setValue:function(_files) {
  if (Ext.isArray(_files)) {
    this.previousFiles = _files;
    this.callParent([Ext.Array.pluck(_files, 'name').join(', ')]);
    if (!this.isDisabled()) {
      this.clearTrigger.show();
    }
  } else {
    if (arguments[0]) {
      this.callParent(arguments);
      this.clearTrigger.show();
    }
  }
}, reset:function() {
  this.clearTrigger.hide();
  this.previousFiles = [];
  this.originalValue = null;
  this.callParent(arguments);
}, getEncodedFiles:function(_success, _failure) {
  var fileInputPromises = [];
  var files = this.getFiles();
  if (files.length > 0) {
    var $jscomp$loop$102 = {};
    var $jscomp$iter$0 = $jscomp.makeIterator(files), $jscomp$key$file = $jscomp$iter$0.next();
    for (; !$jscomp$key$file.done; $jscomp$loop$102 = {file:$jscomp$loop$102.file}, $jscomp$key$file = $jscomp$iter$0.next()) {
      $jscomp$loop$102.file = $jscomp$key$file.value;
      {
        fileInputPromises.push(new Ext.Promise(function($jscomp$loop$102) {
          return function(_resolve, _reject) {
            var fileReader = new FileReader;
            fileReader.onerror = _reject;
            fileReader.onload = function(_event) {
              _resolve({name:$jscomp$loop$102.file.name, data:_event.target.result});
            };
            fileReader.readAsDataURL($jscomp$loop$102.file);
          };
        }($jscomp$loop$102)));
      }
    }
    Ext.Promise.all(fileInputPromises).then(_success)['catch'](_failure);
  } else {
    _success(this.previousFiles);
  }
}, getFileNames:function() {
  return this.getInputValue();
}});
Ext.define('Ext.field.FileButton', {extend:Ext.Button, xtype:'filebutton', config:{value:null, multiple:false, accept:null, capture:null}, buttonType:'file', ui:'action', text:'Browse...', preventDefaultAction:false, keyHandlersAdded:true, getButtonTemplate:function() {
  var template = this.callParent();
  template.tag = 'input';
  template.listeners = template.listeners || {};
  template.listeners.change = {fn:'onChange', delegated:false};
  return template;
}, applyAccept:function(value) {
  switch(value) {
    case 'video':
    case 'audio':
    case 'image':
      value = value + '/*';
      break;
  }
  this.setInputAttribute('accept', value);
}, applyCapture:function(value) {
  this.setInputAttribute('capture', value);
  return value;
}, applyMultiple:function(value) {
  this.setInputAttribute('multiple', value ? '' : null);
  return value;
}, onChange:function(e) {
  this.setValue(this.buttonElement.dom.value);
}, updateValue:function(value, oldValue) {
  this.fireEvent('change', this, value, oldValue);
}, getFiles:function() {
  return this.buttonElement.dom.files;
}, privates:{setInputAttribute:function(attribute, newValue) {
  var buttonElement = this.buttonElement.dom;
  if (!Ext.isEmpty(newValue, true)) {
    buttonElement.setAttribute(attribute, newValue);
  } else {
    buttonElement.removeAttribute(attribute);
  }
}}});
Ext.define('Ext.field.Hidden', {extend:Ext.field.Input, alternateClassName:'Ext.form.Hidden', xtype:'hiddenfield', inputType:'hidden', hidden:true, classCls:Ext.baseCSSPrefix + 'hiddenfield'});
Ext.define('Ext.field.Number', {extend:Ext.field.Text, xtype:'numberfield', alternateClassName:'Ext.form.Number', config:{minValue:null, maxValue:null, decimals:2, trim:true, decimalSeparator:null}, inputType:Ext.os.is.Desktop ? 'text' : 'number', minValueText:'The minimum value for this field is {0}', maxValueText:'The maximum value for this field is {0}', decimalsText:'The maximum decimal places is {0}', badFormatMessage:'Value is not a valid number', classCls:Ext.baseCSSPrefix + 'numberfield', 
parseValidator:'number', initialize:function() {
  var me = this;
  me.getDecimals();
  if (me.getDecimalSeparator() === null) {
    me.setDecimalSeparator(Ext.util.Format.decimalSeparator);
  }
  me.callParent();
  me.inputElement.dom.setAttribute('inputmode', 'numeric');
  if (me.getInputMask()) {
    Ext.raise('NumberFields cannot use input masks');
  }
}, updateDecimals:function(decimals) {
  var me = this, format = '0', zeroChar = me.getTrim() ? '#' : '0', value;
  me.syncDecimalValidator();
  if (decimals) {
    format += '.' + Ext.String.repeat(zeroChar, decimals);
  }
  me.numberFormat = format;
  if (!me.isConfiguring) {
    value = me.getValue();
    if (Ext.isDate(value)) {
      me.setInputValue(value);
    }
  }
}, applyInputValue:function(value) {
  var me = this, decimalSeparator = me.getDecimalSeparator();
  this.getDecimals();
  if (typeof value === 'number') {
    value = Ext.util.Format.number(value, this.numberFormat);
  }
  if (value && Ext.isString(value) && decimalSeparator) {
    value = value.replace(Ext.util.Format.decimalSeparator, decimalSeparator);
  }
  return value;
}, doValidate:function(value, errors, skipLazy) {
  var me = this, String = Ext.String, minValue = me.getMinValue(), maxValue = me.getMaxValue();
  me.callParent([value, errors, skipLazy]);
  if (minValue != null && value < minValue) {
    errors.push(String.format(me.minValueText, minValue));
  } else {
    if (maxValue != null && value > maxValue) {
      errors.push(String.format(me.maxValueText, maxValue));
    }
  }
}, onKeyDown:function(e) {
  var me = this, raw;
  if (me.getInputType() !== 'number') {
    if (!e.ctrlKey && !e.altKey) {
      raw = me.calculateNewValue(e.key());
      if (!me.specialKeys[e.getCharCode()] && !me.isAllowableValue(raw)) {
        e.preventDefault();
        return false;
      }
    }
  }
  me.callParent([e]);
}, transformValue:function(value) {
  if (!(value || value === 0)) {
    value = null;
  }
  return value;
}, rawToValue:Ext.emptyFn, updateDecimalSeparator:function() {
  this.syncDecimalValidator();
}, privates:{calculateNewValue:function(text) {
  var me = this, textSelection = me.getTextSelection(), raw = me.getInputValue();
  if (textSelection[1]) {
    raw = raw.substr(0, textSelection[0]) + text + raw.substr(textSelection[1]);
  } else {
    raw = Ext.String.insert(raw, text, me.getCaretPos());
  }
  return raw;
}, handlePaste:function(e) {
  var me = this, text;
  if (me.getInputType() !== 'number') {
    text = e.getClipboardData('text/plain');
    if (text) {
      text = me.calculateNewValue(text);
      if (me.isAllowableValue(text)) {
        me.setValue(text);
      }
      e.preventDefault();
      return false;
    }
  }
  me.callParent([e]);
  me.validate();
}, isAllowableValue:function(value) {
  var minValue = this.getMinValue(), allowNegative = minValue == null || minValue < 0;
  if (!allowNegative && Ext.String.startsWith(value, '-')) {
    return false;
  }
  return this.isPartialValue(value) || this.parseValue(value) !== null;
}, isPartialValue:function(value) {
  var me = this, minValue = me.getMinValue(), allowNegative = minValue == null || minValue < 0;
  if (allowNegative && value === '-') {
    return true;
  }
  if (me.getDecimals() && (value === '.' || allowNegative && value === '-.')) {
    return true;
  }
  return false;
}, syncDecimalValidator:function() {
  var me = this, separator = me.getDecimals() === 0 ? null : me.getDecimalSeparator();
  me.setParseValidator(Ext.create('Ext.data.validator.Number', {decimalSeparator:separator}));
  me.validate();
}}}, function(C) {
  var E = Ext.event.Event;
  C.prototype.specialKeys = Ext.Array.toMap([E.BACKSPACE, E.TAB, E.RETURN, E.CTRL, E.DELETE, E.LEFT, E.RIGHT, E.UP, E.DOWN, E.HOME, E.END, E.META]);
});
Ext.define('Ext.form.Borders', {mixinId:'formborders', config:{fieldSeparators:null, inputBorders:null}, fieldSeparatorsCls:Ext.baseCSSPrefix + 'form-field-separators', noInputBordersCls:Ext.baseCSSPrefix + 'form-no-input-borders', updateFieldSeparators:function(fieldSeparators, oldFieldSeparators) {
  var bodyElement = this.bodyElement, cls = this.fieldSeparatorsCls;
  if (fieldSeparators) {
    bodyElement.addCls(cls);
  } else {
    if (oldFieldSeparators) {
      bodyElement.removeCls(cls);
    }
  }
}, updateInputBorders:function(inputBorders, oldInputBorders) {
  var bodyElement = this.bodyElement, cls = this.noInputBordersCls;
  if (inputBorders === false) {
    bodyElement.addCls(cls);
  } else {
    if (oldInputBorders === false) {
      bodyElement.removeCls(cls);
    }
  }
}});
Ext.define('Ext.theme.material.form.Borders', {override:'Ext.form.Borders', config:{fieldSeparators:false, inputBorders:true}});
Ext.define('Ext.field.Panel', {extend:Ext.Panel, xtype:'fieldpanel', isFieldPanel:true, mixins:[Ext.field.Dirty, Ext.field.Manager, Ext.form.Borders], scrollable:true, nameable:true, shareableName:true, nameHolder:true, publishes:{dirty:1}, config:{api:null, baseParams:null, paramOrder:null, paramsAsHash:null, timeout:30, url:null}, load:function(options) {
  var me = this, api, url, waitMsg, successFn, failureFn, load, args;
  options = options || {};
  api = me.getApi();
  url = options.url || me.getUrl();
  waitMsg = options.waitMsg;
  successFn = function(response, data) {
    me.setValues(data.data);
    if (Ext.isFunction(options.success)) {
      options.success.call(options.scope || me, me, response, data);
    }
    me.fireEvent('load', me, response);
  };
  failureFn = function(response, data) {
    if (Ext.isFunction(options.failure)) {
      options.failure.call(options.scope, me, response, data);
    }
    me.fireEvent('exception', me, response);
  };
  if (options.waitMsg) {
    if (typeof waitMsg === 'string') {
      waitMsg = {xtype:'loadmask', message:waitMsg};
    }
    me.setMasked(waitMsg);
  }
  if (api) {
    api = Ext.direct.Manager.resolveApi(api, me);
    me.setApi(api);
    load = api.load;
    if (!load) {
      Ext.raise('Cannot find Ext Direct API method for load action');
    }
    args = load.$directCfg.method.getArgs({params:me.getParams(options.params), paramOrder:me.getParamOrder(), paramsAsHash:me.getParamsAsHash(), scope:me, callback:function(data, response, success) {
      me.setMasked(false);
      if (success) {
        successFn(response, data);
      } else {
        failureFn(response, data);
      }
    }});
    load.apply(window, args);
  } else {
    if (url) {
      return Ext.Ajax.request({url:url, timeout:(options.timeout || me.getTimeout()) * 1000, method:options.method || 'GET', autoAbort:options.autoAbort, headers:Ext.apply({'Content-Type':'application/x-www-form-urlencoded; charset\x3dUTF-8'}, options.headers || {}), callback:function(callbackOptions, success, response) {
        var responseText = response.responseText, statusResult = Ext.data.request.Ajax.parseStatus(response.status, response);
        me.setMasked(false);
        if (success) {
          if (statusResult && responseText.length === 0) {
            success = true;
          } else {
            response = Ext.decode(responseText);
            success = !!response.success;
          }
          if (success) {
            successFn(response, responseText);
          } else {
            failureFn(response, responseText);
          }
        } else {
          failureFn(response, responseText);
        }
      }});
    }
  }
}, getParams:function(params) {
  return Ext.apply({}, params, this.getBaseParams());
}, updateDisabled:function(newDisabled, oldDisabled) {
  this.mixins.fieldmanager.updateDisabled.call(this, newDisabled, oldDisabled);
  this.callParent([newDisabled, oldDisabled]);
}, updateRecord:function(record) {
  this.consumeRecord(record);
}});
Ext.define('Ext.field.trigger.Reveal', {extend:Ext.field.trigger.Trigger, xtype:'revealtrigger', alias:'trigger.reveal', classCls:Ext.baseCSSPrefix + 'revealtrigger', weight:-1000, hidden:true, handler:'onRevealTap', scope:'this'});
Ext.define('Ext.field.Password', {extend:Ext.field.Text, xtype:'passwordfield', alternateClassName:'Ext.form.Password', config:{autoCapitalize:false, revealable:false, revealed:{$value:false, lazy:true}}, inputType:'password', classCls:Ext.baseCSSPrefix + 'passwordfield', revealedCls:Ext.baseCSSPrefix + 'revealed', isPassword:true, applyTriggers:function(triggers, oldTriggers) {
  if (triggers && this.getRevealable() && !triggers.reveal) {
    triggers = Ext.apply({reveal:{type:'reveal'}}, triggers);
  }
  return this.callParent([triggers, oldTriggers]);
}, updateRevealed:function(newValue, oldValue) {
  var me = this;
  if (newValue) {
    me.element.addCls(me.revealedCls);
    me.setInputType('text');
  } else {
    me.element.removeCls(me.revealedCls);
    me.setInputType('password');
  }
}, updateValue:function(value, oldValue) {
  this.syncRevealTrigger();
  this.callParent([value, oldValue]);
}, doKeyUp:function(me, e) {
  this.callParent([me, e]);
  this.syncRevealTrigger();
}, onRevealTap:function(e) {
  this.fireAction('revealicontap', [this, e], 'doRevealTap');
}, doRevealTap:function(me, e) {
  this.setRevealed(!this.getRevealed());
}, privates:{isValidTextValue:function(value) {
  return value !== undefined && value !== null && value !== '';
}, syncRevealTrigger:function() {
  var me = this, triggers = me.getTriggers(), revealTrigger = triggers && triggers.reveal, visible, value;
  if (revealTrigger) {
    if (me.getRevealable()) {
      value = me.getValue();
      if (value != null && value !== '' && !me.getDisabled() && !me.getReadOnly()) {
        visible = true;
      }
    }
    if (visible) {
      revealTrigger.show();
    } else {
      revealTrigger.hide();
    }
  }
}}});
Ext.define('Ext.field.Radio', {extend:Ext.field.Checkbox, xtype:['radio', 'radiofield'], alternateClassName:'Ext.form.Radio', isRadio:true, inputType:'radio', classCls:Ext.baseCSSPrefix + 'radiofield', getValue:function() {
  return this._value === undefined ? null : this._value;
}, setValue:function(value) {
  this._value = value;
  return this;
}, getSubmitValue:function() {
  var value = this._value;
  if (value === undefined || value === null) {
    value = true;
  }
  return this.getChecked() ? value : null;
}, updateChecked:function(checked, oldChecked) {
  var me = this;
  me.callParent([checked, oldChecked]);
  if (me.initialized && checked) {
    me.refreshGroupValues(me);
  }
}, getGroupValue:function() {
  var fields = this.getSameGroupFields(), ln = fields.length, i = 0, field;
  for (; i < ln; i++) {
    field = fields[i];
    if (field.getChecked()) {
      return field.getValue();
    }
  }
  return null;
}, getSameGroupFields:function() {
  var me = this, component = me.lookupNameHolder(), name = me.name.replace(me.qsaLeftRe, '\\[').replace(me.qsaRightRe, '\\]');
  return component.query('radiofield[name\x3d' + name + ']');
}, setGroupValue:function(value) {
  var fields = this.getSameGroupFields(), ln = fields.length, i = 0, field;
  for (; i < ln; i++) {
    field = fields[i];
    if (field.getValue() === value) {
      field.setChecked(true);
      return field;
    }
  }
}, refreshGroupValues:function(trigger) {
  var fields = this.getSameGroupFields(), ln = fields.length, i = 0, field;
  for (; i < ln; i++) {
    field = fields[i];
    if (field !== trigger) {
      field.setChecked(false);
    }
  }
}});
Ext.define('Ext.field.RadioGroup', {extend:Ext.field.FieldGroupContainer, xtype:'radiogroup', isRadioGroup:true, defaultType:'radiofield', simpleValue:true, delegate:'[isRadio]', instanceCls:Ext.baseCSSPrefix + 'radio-group', getChecked:function(query) {
  return this.getGroupItems('[checked]' + (query || ''))[0];
}, isEqual:function(value1, value2) {
  if (this.simpleValue) {
    return String(value1) === String(value2);
  }
  return this.callParent([value1, value2]);
}, setValue:function(value) {
  var me = this, items, len, item, i, rbValue, name;
  if (me.isEqual(value, me.lastValue)) {
    return me;
  }
  items = me.getGroupItems();
  len = items.length;
  me.suspendCheckChange = 1;
  if (me.simpleValue) {
    for (i = 0; i < len; i++) {
      item = items[i];
      if (item.getValue() === value) {
        item.setChecked(true);
        break;
      }
    }
  } else {
    if (Ext.isObject(value)) {
      for (name in value) {
        rbValue = value[name];
        for (i = 0; i < len; i++) {
          item = items[i];
          if (item.getName() === name && rbValue === item.getValue()) {
            item.setChecked(true);
            break;
          }
        }
      }
    }
  }
  me.suspendCheckChange = 0;
  me.onGroupChange();
  return me;
}, getValue:function() {
  var me = this, items, ln, values, item, name, value, bucket, b, field;
  if (me.simpleValue) {
    field = me.getChecked();
    if (field) {
      value = field.getValue();
    }
    return value;
  }
  items = this.getGroupItems();
  ln = items.length;
  values = {};
  for (b = 0; b < ln; b++) {
    item = items[b];
    name = item.getName();
    value = item.getValue();
    if (value && item.getChecked()) {
      if (values.hasOwnProperty(name)) {
        bucket = values[name];
        if (!Ext.isArray(bucket)) {
          bucket = values[name] = [bucket];
        }
        bucket.push(value);
      } else {
        values[name] = value;
      }
    }
  }
  return values;
}});
Ext.define('Ext.field.trigger.Search', {extend:Ext.field.trigger.Trigger, xtype:'searchtrigger', alias:'trigger.search', classCls:Ext.baseCSSPrefix + 'searchtrigger'});
Ext.define('Ext.field.Search', {extend:Ext.field.Text, xtype:'searchfield', alternateClassName:'Ext.form.Search', inputType:'search', triggers:{search:{type:'search', side:'left'}}, classCls:Ext.baseCSSPrefix + 'searchfield'});
Ext.define('Ext.slider.Thumb', {extend:Ext.Component, xtype:'thumb', baseCls:Ext.baseCSSPrefix + 'thumb', isSliderThumb:true, config:{fillCls:null, fillTrack:null, dragMax:null, dragMin:null, slider:null}, template:[{reference:'iconElement', classList:[Ext.baseCSSPrefix + 'icon-el', Ext.baseCSSPrefix + 'font-icon']}], draggable:{local:true, constrain:{horizontal:true}, listeners:{beforedragstart:'onBeforeDragStart', dragstart:'onDragStart', dragmove:'onDragMove', dragend:'onDragEnd', scope:'this'}}, 
touchAction:{panX:false}, translatable:{type:'cssposition', listeners:{animationstart:'onAnimationStart', animationend:'onAnimationEnd', translate:'onTranslate', scope:'this'}}, elementWidth:0, pressingCls:Ext.baseCSSPrefix + 'pressing', fillCls:Ext.baseCSSPrefix + 'fill-el', sizerCls:Ext.baseCSSPrefix + 'thumb-sizer', constructor:function(config) {
  this.sizerElement = Ext.Element.create({cls:this.sizerCls});
  this.callParent([config]);
}, initialize:function() {
  var me = this, fillElement;
  me.callParent();
  me.el.addClsOnClick(me.pressingCls, me.shouldAddPressingCls, me);
  fillElement = me.fillElement = Ext.Element.create({cls:me.fillCls});
  fillElement.setVisibilityMode(1);
}, updateFillTrack:function(fillTrack) {
  var fillElement = this.fillElement;
  if (fillTrack === false) {
    fillElement.hide();
  } else {
    fillElement.show();
    fillElement.setStyle('background-color', typeof fillTrack === 'string' ? fillTrack : '');
  }
}, updateFillCls:function(fillCls, oldFillCls) {
  this.fillElement.replaceCls(oldFillCls, fillCls);
}, shouldAddPressingCls:function() {
  return !this.isDisabled();
}, initDragConstraints:function() {
  if (this.isDisabled()) {
    return false;
  }
  this.getSlider().refreshAllThumbConstraints();
}, onAnimationStart:function(translatable, x, y) {
  this.getSlider().onThumbAnimationStart(this, x, y);
}, onAnimationEnd:function(translatable, x, y) {
  if (!this.destroyed) {
    this.getSlider().onThumbAnimationEnd(this, x, y);
  }
}, onBeforeDragStart:function(source, info, event) {
  var xy;
  if (this.isDisabled()) {
    return false;
  }
  xy = info.proxy.current;
  this.getSlider().onThumbBeforeDragStart(this, event, xy.x, xy.y);
}, onDragStart:function(source, info, event) {
  var xy = info.proxy.current;
  this.getSlider().onThumbDragStart(this, event, xy.x, xy.y);
}, onDragMove:function(source, info, event) {
  var xy;
  if (this.isDisabled()) {
    return false;
  }
  xy = info.proxy.current;
  this.getSlider().onThumbDragMove(this, event, xy.x, xy.y);
}, onDragEnd:function(source, info, event) {
  var xy;
  if (this.isDisabled()) {
    return false;
  }
  xy = info.proxy.current;
  this.getSlider().onThumbDragEnd(this, event, xy.x, xy.y);
}, onTranslate:function(translatable, x, y) {
  if (this.initialized) {
    this.getSlider().syncFill(this, x);
  }
}, onResize:function(width) {
  var me = this, slider = me.ownerCmp;
  me.elementWidth = width;
  if (slider && slider.thumbs && slider.thumbs[0] === me) {
    slider.onThumbResize(me, width);
  }
}, getElementWidth:function() {
  return this.elementWidth;
}, updateUi:function(ui, oldUi) {
  var me = this, sizerCls = me.sizerCls, sizerElement = me.sizerElement;
  if (oldUi) {
    sizerElement.removeCls(oldUi, sizerCls);
  }
  if (ui) {
    sizerElement.addCls(ui, sizerCls);
  }
  me.callParent([ui, oldUi]);
}, updateDragMax:function(max) {
  var constraint = this.getDraggable().getConstrain(), range = constraint.getX();
  constraint.setX([range && range[0], max]);
}, updateDragMin:function(min) {
  var constraint = this.getDraggable().getConstrain(), range = constraint.getX();
  constraint.setX([min, range && range[1]]);
}, destroy:function() {
  Ext.destroyMembers(this, 'fillElement', 'sizerElement');
  this.callParent();
}});
Ext.define('Ext.slider.Slider', {extend:Ext.Component, xtype:'slider', config:{thumbDefaults:{xtype:'thumb', inheritUi:true, translatable:{easingX:{duration:300, type:'ease-out'}}}, increment:1, value:0, valueIsArray:false, minValue:0, maxValue:100, allowThumbsOverlapping:false, animation:true, readOnly:false}, defaultBindProperty:'value', twoWayBindable:{value:1}, classCls:Ext.baseCSSPrefix + 'slider', elementWidth:0, offsetValueRatio:0, activeThumb:null, isThumbAnimating:0, template:[{reference:'trackElement', 
cls:Ext.baseCSSPrefix + 'track-el'}, {reference:'thumbWrapElement', cls:Ext.baseCSSPrefix + 'thumb-wrap-el'}], fillSelector:'.' + Ext.baseCSSPrefix + 'fill-el', constructor:function(config) {
  if (config && config.hasOwnProperty('values')) {
    config = Ext.apply({value:config.values}, config);
    delete config.values;
  }
  this.thumbs = [];
  this.callParent([config]);
}, initialize:function() {
  this.callParent();
  this.element.on('tap', 'onTap', this);
}, onRender:function() {
  this.callParent();
  this.whenVisible('refreshSizes');
}, applyThumbDefaults:function(defaults) {
  return Ext.apply({slider:this, ownerCmp:this}, defaults);
}, factoryThumb:function() {
  var thumb = Ext.create(this.getThumbDefaults());
  thumb.doInheritUi();
  return thumb;
}, getThumbs:function() {
  return this.thumbs;
}, getThumb:function(index) {
  if (typeof index !== 'number') {
    index = 0;
  }
  return this.thumbs[index];
}, refreshOffsetValueRatio:function() {
  var me = this, valueRange = me.getMaxValue() - me.getMinValue(), trackWidth = me.elementWidth - me.thumbWidth;
  me.offsetValueRatio = valueRange === 0 ? 0 : trackWidth / valueRange;
}, onThumbResize:function(thumb, thumbWidth) {
  this.thumbWidth = thumbWidth;
  this.refresh();
}, onResize:function(width) {
  this.elementWidth = width;
  this.refresh();
}, refresh:function() {
  this.refreshing = true;
  this.refreshValue();
  this.refreshing = false;
}, setActiveThumb:function(thumb) {
  var oldActiveThumb = this.activeThumb;
  if (oldActiveThumb && oldActiveThumb !== thumb) {
    oldActiveThumb.setZIndex(null);
  }
  this.activeThumb = thumb;
  thumb.setZIndex(2);
  return this;
}, onThumbBeforeDragStart:function(thumb, e) {
  if (this.offsetValueRatio === 0 || e.absDeltaX <= e.absDeltaY || this.getReadOnly()) {
    return false;
  }
}, onThumbDragStart:function(thumb, e) {
  var me = this;
  if (me.getAllowThumbsOverlapping()) {
    me.setActiveThumb(thumb);
  }
  me.dragStartValue = me.getArrayValues()[me.getThumbIndex(thumb)];
  me.fireEvent('dragstart', me, thumb, me.dragStartValue, e);
}, onThumbDragMove:function(thumb, e, offsetX) {
  var me = this, index = me.getThumbIndex(thumb), offsetValueRatio = me.offsetValueRatio, constrainedValue = me.constrainValue(me.getMinValue() + offsetX / offsetValueRatio);
  e.stopPropagation();
  me.setIndexValue(index, constrainedValue);
  me.fireEvent('drag', me, thumb, me.getArrayValues(), e);
  return false;
}, setIndexValue:function(index, value, animation) {
  var me = this, thumb = me.thumbs[index], values = me.getArrayValues(), minValue = me.getMinValue(), offsetValueRatio = me.offsetValueRatio, increment = me.getIncrement(), pos = (value - minValue) * offsetValueRatio;
  thumb.setXY(pos, null, animation);
  values[index] = minValue + Math.round(pos / offsetValueRatio / increment) * increment;
  me.setValue(values);
  me.refreshAdjacentThumbConstraints(thumb);
}, onChange:function(thumb, newValue, oldValue) {
  var me = this;
  if (me.hasListeners.change) {
    me.fireEvent('change', me, thumb, newValue, oldValue);
  }
}, onThumbDragEnd:function(thumb, e) {
  var me = this, index = me.getThumbIndex(thumb), newValue = me.getArrayValues()[index], oldValue = me.dragStartValue;
  me.snapThumbPosition(thumb, newValue);
  me.fireEvent('dragend', me, thumb, me.getArrayValues(), e);
  if (oldValue !== newValue) {
    me.onChange(thumb, newValue, oldValue);
  }
}, getThumbIndex:function(thumb) {
  return this.thumbs.indexOf(thumb);
}, refreshAdjacentThumbConstraints:function(thumb) {
  var me = this, offsetX = thumb.getLeft(), thumbs = me.thumbs, index = me.getThumbIndex(thumb), previousThumb = thumbs[index - 1], nextThumb = thumbs[index + 1], thumbWidth = me.getAllowThumbsOverlapping() ? 0 : me.thumbWidth;
  if (previousThumb) {
    previousThumb.setDragMax(offsetX - thumbWidth);
  }
  if (nextThumb) {
    nextThumb.setDragMin(offsetX + thumbWidth);
  }
}, onTap:function(e) {
  var me = this, element = me.element, minDistance = Infinity, i, absDistance, testValue, closestIndex, oldValue, thumb, ln, values, value, offset, elementX, targetElement, touchPointX;
  if (me.offsetValueRatio === 0 || me.isDisabled() || me.getReadOnly()) {
    return;
  }
  targetElement = Ext.get(e.target);
  if (!targetElement || Ext.browser.engineName === 'WebKit' && targetElement.hasCls('x-thumb')) {
    return;
  }
  touchPointX = e.touch.point.x;
  elementX = element.getX();
  offset = touchPointX - elementX - me.thumbWidth / 2;
  value = me.constrainValue(me.getMinValue() + offset / me.offsetValueRatio);
  values = me.getArrayValues();
  ln = values.length;
  if (ln === 1) {
    closestIndex = 0;
  } else {
    for (i = 0; i < ln; i++) {
      testValue = values[i];
      absDistance = Math.abs(testValue - value);
      if (absDistance < minDistance) {
        minDistance = absDistance;
        closestIndex = i;
      }
    }
  }
  oldValue = values[closestIndex];
  thumb = me.thumbs[closestIndex];
  me.setIndexValue(closestIndex, value, me.getAnimation());
  if (oldValue !== value) {
    me.onChange(thumb, value, oldValue);
  }
}, updateThumbs:function(newThumbs) {
  this.add(newThumbs);
}, applyValue:function(value, oldValue) {
  var me = this, values = Ext.Array.from(value || 0), valueIsArray = me.getValueIsArray(), filteredValues = [], previousFilteredValue = me.getMinValue(), filteredValue, i, ln;
  for (i = 0, ln = values.length; i < ln; i++) {
    filteredValue = me.constrainValue(values[i]);
    if (filteredValue < previousFilteredValue) {
      Ext.log.warn("Invalid values of '" + Ext.encode(values) + "', values at smaller indexes must " + 'be smaller than or equal to values at greater indexes');
      filteredValue = previousFilteredValue;
    }
    filteredValues.push(filteredValue);
    previousFilteredValue = filteredValue;
  }
  if (!me.refreshing && oldValue && Ext.Array.equals(values, oldValue)) {
    filteredValues = undefined;
  } else {
    me.values = filteredValues;
    if (!valueIsArray && filteredValues.length === 1) {
      filteredValues = filteredValues[0];
    }
  }
  return filteredValues;
}, updateValue:function() {
  var me = this, thumbs = me.thumbs, values = me.getArrayValues(), len = values.length, i;
  me.setThumbsCount(len);
  if (!this.isThumbAnimating) {
    for (i = 0; i < len; i++) {
      me.snapThumbPosition(thumbs[i], values[i]);
    }
  }
}, refreshValue:function() {
  this.refreshOffsetValueRatio();
  this.updateValue();
}, constrainValue:function(value) {
  var me = this, minValue = me.getMinValue(), maxValue = me.getMaxValue(), increment = me.getIncrement(), remainder;
  value = parseFloat(value);
  if (isNaN(value)) {
    value = minValue;
  }
  remainder = (value - minValue) % increment;
  value -= remainder;
  if (Math.abs(remainder) >= increment / 2) {
    value += remainder > 0 ? increment : -increment;
  }
  value = Math.max(minValue, value);
  value = Math.min(maxValue, value);
  return value;
}, setThumbsCount:function(count) {
  var me = this, thumbs = me.thumbs, thumbsCount = thumbs.length, i, thumb;
  while (count < thumbs.length) {
    thumb = thumbs.pop();
    thumb.destroy();
  }
  while (count > thumbs.length) {
    thumb = me.factoryThumb();
    thumbs.push(thumb);
    me.trackElement.appendChild(thumb.fillElement);
    me.thumbWrapElement.appendChild(thumb.element);
    me.element.appendChild(thumb.sizerElement);
  }
  if (thumbsCount !== count) {
    for (i = 0; i < count; i++) {
      thumb = thumbs[i];
      if (count > 2) {
        thumb.setFillTrack(false);
      } else {
        if (count === 2) {
          thumb.setFillTrack(i === 1);
        } else {
          thumb.setFillTrack(true);
        }
      }
    }
  }
  return this;
}, setValues:function(value) {
  this.setValue(value);
}, getValues:function() {
  return this.getValue();
}, getArrayValues:function() {
  return this.values;
}, applyIncrement:function(increment) {
  if (increment === 0) {
    increment = 1;
  }
  return Math.abs(increment);
}, updateAllowThumbsOverlapping:function(newValue, oldValue) {
  if (typeof oldValue !== 'undefined') {
    this.refreshValue();
  }
}, updateMinValue:function(newValue, oldValue) {
  if (typeof oldValue !== 'undefined') {
    this.refreshValue();
  }
}, updateMaxValue:function(newValue, oldValue) {
  if (typeof oldValue !== 'undefined') {
    this.refreshValue();
  }
}, updateIncrement:function(newValue, oldValue) {
  if (typeof oldValue !== 'undefined') {
    this.refreshValue();
  }
}, updateDisabled:function(disabled) {
  var thumbs, ln, i;
  this.callParent(arguments);
  thumbs = this.thumbs;
  ln = thumbs.length;
  for (i = 0; i < ln; i++) {
    thumbs[i].setDisabled(disabled);
  }
}, doDestroy:function() {
  this.thumbs = Ext.destroy(this.thumbs);
  this.callParent();
}, getRefItems:function(deep) {
  return this.thumbs;
}, privates:{refreshAllThumbConstraints:function() {
  var me = this, thumbs = me.thumbs, len = thumbs.length, thumbWidth = me.getAllowThumbsOverlapping() ? 0 : me.thumbWidth, i;
  for (i = 0; i < len; i++) {
    me.refreshAdjacentThumbConstraints(thumbs[i]);
  }
  thumbs[0].setDragMin(0);
  thumbs[len - 1].setDragMax(me.elementWidth - thumbWidth);
}, refreshSizes:function() {
  var me = this, thumb = me.thumbs[0];
  me.elementWidth = me.element.measure('w');
  if (thumb) {
    me.thumbWidth = thumb.element.measure('w');
  }
  me.refresh();
}, snapThumbPosition:function(thumb, value) {
  var ratio = this.offsetValueRatio, offset;
  if (isFinite(ratio)) {
    offset = Ext.Number.correctFloat((value - this.getMinValue()) * ratio);
    thumb.setXY(offset, null);
  }
}, syncFill:function(thumb, offset) {
  var me = this, thumbs = me.thumbs, values = me.getArrayValues(), ln = values.length, prevOffset = 0, fillElements = me.trackElement.query(me.fillSelector, false), thumbIndex = thumbs.indexOf(thumb), thumbOffset, fillElement, i;
  offset = offset + Math.ceil(thumb.element.getWidth() / 2);
  for (i = 0; i < ln; i++) {
    thumb = thumbs[i];
    fillElement = fillElements[i];
    thumbOffset = i === thumbIndex ? offset : thumb.getLeft() + thumb.element.getWidth() / 2;
    fillElement.setWidth(thumbOffset - prevOffset);
    fillElement.setLocalX(prevOffset);
    prevOffset = thumbOffset;
  }
}, onThumbAnimationStart:function() {
  this.isThumbAnimating++;
}, onThumbAnimationEnd:function() {
  this.isThumbAnimating--;
}}});
Ext.define('Ext.field.Slider', {extend:Ext.field.Field, xtype:'sliderfield', alternateClassName:'Ext.form.Slider', mixins:[Ext.mixin.ConfigProxy, Ext.field.BoxLabelable], config:{slider:{xtype:'slider', inheritUi:true}, liveUpdate:false, tabIndex:-1, readOnly:false, value:0}, classCls:Ext.baseCSSPrefix + 'sliderfield', proxyConfig:{slider:['increment', 'minValue', 'maxValue']}, bodyAlign:'stretch', defaultBindProperty:'value', twoWayBindable:{values:1, value:1}, constructor:function(config) {
  config = config || {};
  if (config.hasOwnProperty('values')) {
    config.value = config.values;
  }
  this.callParent([config]);
  this.updateMultipleState();
}, initialize:function() {
  this.callParent();
  this.getSlider().on({scope:this, change:'onSliderChange', dragstart:'onSliderDragStart', drag:'onSliderDrag', dragend:'onSliderDragEnd'});
}, getBodyTemplate:function() {
  return this.mixins.boxLabelable.getBodyTemplate.call(this);
}, applySlider:function(slider) {
  if (slider && !slider.isInstance) {
    slider = this.mergeProxiedConfigs('slider', slider);
    slider.$initParent = this;
    slider = Ext.create(slider);
    delete slider.$initParent;
  }
  this.boxElement.appendChild(slider.el);
  slider.ownerCmp = this;
  return slider;
}, updateSlider:function(slider) {
  slider.doInheritUi();
}, getValue:function() {
  return this._value;
}, applyValue:function(value, oldValue) {
  value = this.callParent([value, oldValue]) || 0;
  if (this.dragging && this.isSyncing('value')) {
    value = undefined;
  } else {
    if (Ext.isArray(value)) {
      value = value.slice(0);
      if (oldValue && Ext.Array.equals(value, oldValue)) {
        value = undefined;
      }
    } else {
      value = [value];
    }
  }
  return value;
}, updateValue:function(value, oldValue) {
  if (!this.dragging) {
    value = this.setSliderValue(value);
  }
  this.callParent([value, oldValue]);
}, setSliderValue:function(value) {
  return this.getSlider().setValue(value).getValue();
}, onSliderChange:function(slider, thumb, newValue, oldValue) {
  this.setValue(slider.getValue());
  this.fireEvent('dragchange', this, slider, thumb, newValue, oldValue);
}, onSliderDragStart:function(slider, thumb, startValue, e) {
  this.dragging = true;
  this.fireEvent('dragstart', this, slider, thumb, startValue, e);
}, onSliderDrag:function(slider, thumb, value, e) {
  var me = this;
  if (me.getLiveUpdate()) {
    me.setValue(slider.getValue());
  }
  me.fireEvent('drag', me, slider, thumb, value, e);
}, onSliderDragEnd:function(slider, thumb, startValue, e) {
  this.dragging = false;
  this.fireEvent('dragend', this, slider, thumb, startValue, e);
}, setValues:function(value) {
  this.setValue(value);
  this.updateMultipleState();
}, getValues:function() {
  return this.getValue();
}, reset:function() {
  var config = this.config, initialValue = this.config.hasOwnProperty('values') ? config.values : config.value;
  this.setValue(initialValue);
}, updateReadOnly:function(newValue) {
  this.getSlider().setReadOnly(newValue);
}, updateMultipleState:function() {
  var value = this.getValue();
  if (value && value.length > 1) {
    this.addCls(Ext.baseCSSPrefix + 'slider-multiple');
  }
}, updateDisabled:function(disabled, oldDisabled) {
  this.callParent([disabled, oldDisabled]);
  this.getSlider().setDisabled(disabled);
}, doDestroy:function() {
  this.getSlider().destroy();
  this.callParent();
}, getRefItems:function(deep) {
  var refItems = [], slider = this.getSlider();
  if (slider) {
    refItems.push(slider);
    if (deep && slider.getRefItems) {
      refItems.push.apply(refItems, slider.getRefItems(deep));
    }
  }
  return refItems;
}, rawToValue:Ext.emptyFn});
Ext.define('Ext.field.SingleSlider', {extend:Ext.field.Slider, xtype:'singlesliderfield', twoWayBindable:{value:1}, defaultBindProperty:'value', publishes:{value:1}, applyValue:function(value, oldValue) {
  value = this.callParent([value, oldValue]);
  if (value && Ext.isArray(value)) {
    value = value[0];
  }
  return value;
}, getValue:function() {
  var value = this.callParent();
  if (value && Ext.isArray(value)) {
    value = value[0];
  }
  return value;
}, onSliderChange:function(slider, thumb, newValue, oldValue) {
  this.setValue(newValue);
  this.fireEvent('dragchange', this, slider, newValue, oldValue);
}, onSliderDragStart:function(slider, thumb, startValue, e) {
  this.fireEvent('dragstart', this, slider, startValue, e);
}, onSliderDrag:function(slider, thumb, value, e) {
  var me = this;
  if (me.getLiveUpdate()) {
    me.setValue(value);
  }
  me.fireEvent('drag', me, slider, value, e);
}, onSliderDragEnd:function(slider, thumb, startValue, e) {
  this.fireEvent('dragend', this, slider, startValue, e);
}});
Ext.define('Ext.field.trigger.SpinDown', {extend:Ext.field.trigger.Trigger, xtype:'spindowntrigger', alias:'trigger.spindown', classCls:Ext.baseCSSPrefix + 'spindowntrigger', handler:'onSpinDown', scope:'this', focusOnTap:false});
Ext.define('Ext.field.trigger.SpinUp', {extend:Ext.field.trigger.Trigger, xtype:'spinuptrigger', alias:'trigger.spinup', classCls:Ext.baseCSSPrefix + 'spinuptrigger', handler:'onSpinUp', scope:'this', focusOnTap:false});
Ext.define('Ext.field.Spinner', {extend:Ext.field.Number, xtype:'spinnerfield', alternateClassName:'Ext.form.Spinner', config:{stepValue:1, accelerateOnTapHold:true, cycle:false, clearable:false, groupButtons:true}, triggers:{spindown:{type:'spindown', group:'spin', repeat:true}, spinup:{type:'spinup', group:'spin', repeat:true}}, value:0, decimals:0, classCls:Ext.baseCSSPrefix + 'spinnerfield', groupedButtonsCls:Ext.baseCSSPrefix + 'grouped-buttons', initElement:function() {
  this.callParent();
  this.inputElement.dom.readOnly = true;
}, updateGroupButtons:function(groupButtons) {
  var downTrigger = this.getTriggers().spindown;
  downTrigger.setGroup(groupButtons ? 'spin' : null);
  downTrigger.setSide(groupButtons ? null : 'left');
}, applyTriggers:function(triggers, oldTriggers) {
  var accelerate = this.getAccelerateOnTapHold(), upTrigger, downTrigger, upRepeat, downRepeat;
  if (triggers && accelerate) {
    upTrigger = triggers.spinup;
    downTrigger = triggers.spindown;
    upRepeat = upTrigger.repeat;
    if (upRepeat) {
      upTrigger.repeat = Ext.apply({accelerate:accelerate}, upRepeat);
    }
    downRepeat = downTrigger.repeat;
    if (downRepeat) {
      downTrigger.repeat = Ext.apply({accelerate:accelerate}, downRepeat);
    }
  }
  return this.callParent([triggers, oldTriggers]);
}, onKeyDown:function(e) {
  var limit;
  if (this.getInputType() !== 'number') {
    switch(e.getKey()) {
      case e.UP:
        e.stopEvent();
        this.spin(false);
        break;
      case e.DOWN:
        e.stopEvent();
        this.spin(true);
        break;
      case e.HOME:
        limit = this.getMinValue();
        if (limit != null) {
          e.stopEvent();
          this.setValue(limit);
        }
        break;
      case e.END:
        limit = this.getMaxValue();
        if (limit != null) {
          e.stopEvent();
          this.setValue(limit);
        }
        break;
    }
  }
  this.callParent([e]);
}, onSpinDown:function() {
  if (!this.getDisabled() && !this.getReadOnly()) {
    this.spin(true);
  }
}, onSpinUp:function() {
  if (!this.getDisabled() && !this.getReadOnly()) {
    this.spin(false);
  }
}, spin:function(down) {
  var me = this, originalValue = me.getValue(), stepValue = me.getStepValue(), direction = down ? 'down' : 'up', minValue = me.getMinValue(), maxValue = me.getMaxValue(), value;
  if (down) {
    value = originalValue - stepValue;
  } else {
    value = originalValue + stepValue;
  }
  if (me.getCycle()) {
    if (originalValue === minValue && value < minValue) {
      value = maxValue;
    }
    if (originalValue === maxValue && value > maxValue) {
      value = minValue;
    }
  } else {
    if (minValue != null && value < minValue) {
      value = minValue;
    } else {
      if (maxValue != null && value > maxValue) {
        value = maxValue;
      }
    }
  }
  me.spinning = true;
  me.setValue(value);
  me.spinning = false;
  value = me.getValue();
  me.fireEvent('spin', me, value, direction);
  me.fireEvent('spin' + direction, me, value);
}, rawToValue:Ext.emptyFn, privates:{spinning:false, canSetInputValue:function() {
  return this.spinning || this.callParent();
}}});
Ext.define('Ext.field.trigger.Time', {extend:Ext.field.trigger.Expand, xtype:'timetrigger', alias:'trigger.time', classCls:Ext.baseCSSPrefix + 'timetrigger'});
Ext.define('Ext.panel.TimeHeader', {extend:Ext.Component, xtype:'analogtimeheader', classCls:Ext.baseCSSPrefix + 'analogtimeheader', config:{position:null}, template:[{reference:'headerEl', cls:Ext.baseCSSPrefix + 'header-el', children:[{reference:'timeEl', cls:Ext.baseCSSPrefix + 'time-wrapper-el', children:[{cls:Ext.baseCSSPrefix + 'time-el ' + Ext.baseCSSPrefix + 'hour-el', reference:'hoursEl', listeners:{click:'onHoursClick'}}, {cls:Ext.baseCSSPrefix + 'time-el', html:':'}, {cls:Ext.baseCSSPrefix + 
'time-el ' + Ext.baseCSSPrefix + 'minute-el', reference:'minutesEl', listeners:{click:'onMinutesClick'}}]}, {reference:'meridiemEl', cls:Ext.baseCSSPrefix + 'meridiem-wrapper-el', children:[{cls:Ext.baseCSSPrefix + 'am-el ' + Ext.baseCSSPrefix + 'meridiem-el', reference:'amEl', html:'AM', listeners:{click:'onAmClick'}}, {cls:Ext.baseCSSPrefix + 'pm-el ' + Ext.baseCSSPrefix + 'meridiem-el', reference:'pmEl', html:'PM', listeners:{click:'onPmClick'}}]}]}], onHoursClick:function(e) {
  this.ownerCmp.onHoursClick(e);
}, onMinutesClick:function(e) {
  this.ownerCmp.onMinutesClick(e);
}, onAmClick:function(e) {
  this.ownerCmp.onAmClick(e);
}, onPmClick:function(e) {
  this.ownerCmp.onPmClick(e);
}});
Ext.define('Ext.panel.TimeView', {extend:Ext.Panel, xtype:'analogtime', config:{value:'now', autoAdvance:true, vertical:true, confirmable:false, confirmHandler:null, declineHandler:null, scope:'this', buttonAlign:'right', defaultButtons:{ok:{handler:'up.onConfirm'}, cancel:{handler:'up.onDecline'}}, mode:'hour', meridiem:true, alignPMInside:false, hourDisplayFormat:'G'}, updateMeridiem:function() {
  this.updateTimeView();
}, updateAlignPMInside:function() {
  this.updateTimeView();
}, updateHourDisplayFormat:function() {
  this.updateTimeView();
}, updateTimeView:function() {
  var me = this;
  if (me.isConfiguring) {
    return;
  }
  me.layoutFace();
  me.updateValue();
}, platformConfig:{'phone || tablet':{vertical:'auto'}}, classCls:Ext.baseCSSPrefix + 'analogtime', dotIndicatorCls:Ext.baseCSSPrefix + 'analog-picker-dot-indicator', hour12Cls:Ext.baseCSSPrefix + 'analog-picker-12hr-format', hour24Cls:Ext.baseCSSPrefix + 'analog-picker-24hr-format', animationTimeDelay:200, initDate:'1/1/1970', header:{xtype:'analogtimeheader'}, listeners:{painted:'onPainted', scope:'this'}, MAX_MINUTES:24 * 60 + 59, getTemplate:function() {
  var template = this.callParent(), child = template[0].children[0];
  child.children = [{reference:'pickerWrapEl', cls:Ext.baseCSSPrefix + 'picker-wrap-el', children:[{cls:Ext.baseCSSPrefix + 'analog-picker-el', reference:'analogPickerEl', children:[{cls:Ext.baseCSSPrefix + 'analog-picker-hand-el', reference:'handEl'}, {cls:Ext.baseCSSPrefix + 'analog-picker-face-el', reference:'faceEl'}], listeners:{mousedown:'onFaceMouseDown', mouseup:'onFaceMouseUp'}}]}];
  return template;
}, activateHours:function(value, options) {
  var me = this, header = me.getHeader(), am = this.getAm(), hoursEl = header.hoursEl, minutesEl = header.minutesEl, hours = me.getHours();
  me.setMode('hour');
  if (value == null) {
    value = hours > 11 ? hours - 12 : hours;
    value += am ? 0 : 12;
  }
  hoursEl.addCls('active');
  minutesEl.removeCls('active');
  me.setHours(value, options);
}, activateMinutes:function(value, options) {
  var me = this, header = me.getHeader(), hoursEl = header.hoursEl, minutesEl = header.minutesEl;
  me.setMode('minute');
  value = value != null ? value : me.getMinutes();
  minutesEl.addCls('active');
  hoursEl.removeCls('active');
  me.setMinutes(value, options);
}, applyValue:function(value) {
  var now;
  if (Ext.isDate(value)) {
    value = value.getHours() * 60 + value.getMinutes();
  } else {
    if (value === 'now' || !Ext.isNumber(value) || isNaN(value) || value < 0 || value > this.MAX_MINUTES) {
      now = new Date;
      value = now.getHours() * 60 + now.getMinutes();
    }
  }
  return value;
}, getAngleFromTime:function(time, type) {
  var me = this, isMinute = type !== 'hour', isMeridiem = me.getMeridiem(), alignPMInside = me.getAlignPMInside(), total = isMinute ? 60 : isMeridiem || alignPMInside ? 12 : 24, anglePerItem = 360 / total, initialRotation = me.getIntialRotation(type, anglePerItem);
  return time * anglePerItem - initialRotation;
}, getCenter:function() {
  var me = this, center, size;
  if (!me._center) {
    me._center = center = me.analogPickerEl.getXY();
    size = me.analogPickerEl.measure();
    center[0] += Math.floor(size.width / 2);
    center[1] += Math.floor(size.height / 2);
  }
  return me._center;
}, getTimeFromAngle:function(angle, radius) {
  var me = this, mode = me.getMode(), isMinute = mode !== 'hour', isMeridiem = me.getMeridiem(), alignPMInside = me.getAlignPMInside(), total = isMinute ? 60 : isMeridiem || alignPMInside ? 12 : 24, anglePerItem = 360 / total, initialRotation = me.getIntialRotation(mode, anglePerItem), returnVal;
  angle = anglePerItem * Math.round(angle / anglePerItem) + initialRotation;
  if (angle >= 360) {
    angle -= 360;
  }
  if (angle === 0 && !isMinute) {
    returnVal = total;
  } else {
    returnVal = angle / anglePerItem;
  }
  if (!isMinute && !isMeridiem && (radius && radius < 75) && alignPMInside) {
    returnVal += 12;
  }
  return returnVal;
}, getElementByValue:function(value) {
  var me = this, mode = me.getMode();
  value = parseInt(value);
  if (mode === 'hour' && value === 0) {
    value = me.getMeridiem() ? 12 : 24;
  }
  if (!me.itemValueMap) {
    me.layoutFace();
  }
  return me.itemValueMap[value];
}, getHours:function() {
  var value = this.getValue();
  return Math.floor(value / 60);
}, getMinutes:function() {
  var me = this, value = me.getValue(), hour = me.getHours();
  return value != null ? value - hour * 60 : 0;
}, getAm:function() {
  var value = this.getValue(), hour = Math.floor(value / 60);
  if (hour === 24) {
    hour = 0;
  }
  return hour < 12;
}, layoutFace:function() {
  var me = this, parent, mode, face, pickerWidth, isMinute, type, padding, outerTrackWidth, total, i, item, itemText, rot, alignPMInside, translateX, styleStr, hourDisplayFormat, text;
  if (!me.rendered) {
    return;
  }
  parent = me.getParent();
  mode = me.getMode();
  face = me.faceEl;
  pickerWidth = face.measure('w');
  isMinute = mode === 'minute';
  type = isMinute ? 'minute' : 'hour';
  padding = 50;
  outerTrackWidth = 70;
  total = isMinute ? 60 : me.getMeridiem() ? 12 : 24;
  alignPMInside = me.getAlignPMInside();
  styleStr = 'rotate({0}deg) translateX({1}px) rotate({2}deg)';
  hourDisplayFormat = me.getHourDisplayFormat();
  face.setHtml('');
  me.itemValueMap = {};
  for (i = 1; i <= total; i++) {
    item = Ext.Element.create();
    rot = me.getAngleFromTime(i, type);
    itemText = i;
    translateX = (pickerWidth - padding) / 2;
    if (isMinute) {
      itemText = i;
      if (i % 5 !== 0) {
        item.setStyle('opacity', 0);
      }
      if (i === 60) {
        itemText = '0';
      }
      item.addCls('minute-picker-el');
    } else {
      item.addCls('hour-picker-el');
      item.toggleCls('align-pm-inside', alignPMInside);
      if (i > 12 && alignPMInside) {
        translateX = (pickerWidth - padding - outerTrackWidth) / 2;
        item.addCls('inner-track');
      }
    }
    item.setStyle('transform', Ext.String.format(styleStr, rot, translateX, -rot));
    item.type = type;
    item.value = parseInt(itemText);
    item.rotation = rot;
    if (isMinute) {
      text = Ext.String.leftPad(itemText, 2, '0');
    } else {
      text = Ext.Date.format(new Date((new Date).setHours(itemText)), hourDisplayFormat);
    }
    me.itemValueMap[item.value] = item;
    item.setText(text);
    face.appendChild(item);
  }
  if (parent && parent.isHeighted()) {
    parent.updateHeight();
  }
}, onConfirm:function(e) {
  var me = this;
  me.updateField();
  Ext.callback(me.getConfirmHandler(), me.getScope(), [me, e], 0, me);
}, onDecline:function(e) {
  var me = this;
  me.collapsePanel();
  Ext.callback(me.getDeclineHandler(), me.getScope(), [me, e], 0, me);
}, onFaceElementClick:function(target, options) {
  var me = this, value, type;
  target = Ext.fly(target);
  if (!target) {
    return;
  }
  value = target.value;
  type = target.type;
  if (type) {
    if (type === 'hour') {
      me.syncHours(value, options);
    } else {
      me.setMinutes(value, options);
      if (!me.getConfirmable()) {
        me.updateField();
      }
    }
  }
  if (me.getAutoAdvance() && me.getMode() === 'hour') {
    me.activateMinutes(null, {delayed:true, animate:true});
  }
}, onFaceMouseDown:function(e) {
  var me = this;
  if (!me.dragging) {
    e.preventDefault();
    me.startDrag();
  }
}, onFaceMouseUp:function(e) {
  var me = this, target;
  if (e.pointerType === 'touch') {
    target = document.elementFromPoint.apply(document, e.getXY());
  } else {
    target = e.target;
  }
  me.stopDrag();
  me.onFaceElementClick(target);
}, onHoursClick:function() {
  this.activateHours(null, {animate:true});
}, onMouseMove:function(e) {
  var me = this, options = {disableAnimation:true}, mode = me.getMode(), angle, center, point, x, y, value, radius;
  if (me.dragging) {
    center = me.getCenter();
    point = e.getXY();
    x = point[0] - center[0];
    y = point[1] - center[1];
    angle = Math.atan2(y, x);
    angle = angle * (180 / Math.PI);
    radius = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
    if (y < 0) {
      angle += 360;
    }
    value = me.getAlignPMInside() ? me.getTimeFromAngle(angle, radius) : me.getTimeFromAngle(angle);
    if (mode === 'hour') {
      me.syncHours(value, options);
    } else {
      me.setMinutes(value, options);
    }
  }
}, onAmClick:function() {
  this.setAm(true);
}, onMinutesClick:function() {
  this.activateMinutes(null, {animate:true});
}, onOrientationChange:function() {
  this.setVerticalByOrientation();
}, onPainted:function() {
  var me = this;
  me.layoutFace();
  me.updateValue();
  me.activateHours();
}, onPmClick:function() {
  this.setAm(false);
}, setAm:function(value) {
  var me = this, current = me.getAm(), hours = me.getHours(), header = me.getHeader(), amEl = header.amEl, pmEl = header.pmEl, el = value ? amEl : pmEl, hour12Cls = me.hour12Cls, hour24Cls = me.hour24Cls;
  if (me.getMeridiem()) {
    amEl.replaceCls(hour24Cls, hour12Cls);
    pmEl.replaceCls(hour24Cls, hour12Cls);
  } else {
    amEl.replaceCls(hour12Cls, hour24Cls);
    pmEl.replaceCls(hour12Cls, hour24Cls);
  }
  if (!me.hasSetAm || current !== value) {
    amEl.removeCls('active');
    pmEl.removeCls('active');
    el.addCls('active');
    me.hasSetAm = true;
  }
  if (current !== value) {
    me.setHours(hours + (value ? -12 : 12));
  }
}, setClockHand:function(options) {
  var me = this, isMinute = options.type === 'minute', currentMode = me.getMode(), mode = isMinute ? 'minute' : 'hour', isMeridiem = me.getMeridiem(), alignPMInside = me.getAlignPMInside(), hourValue = isMeridiem ? me.convert24to12Hours(options.value) : options.value, analogPickerEl = me.analogPickerEl, handEl = me.handEl, el = me.getElementByValue(hourValue), is24Hours = !isMinute && !isMeridiem, value, rotation;
  if (!isMinute && isMeridiem) {
    value = me.convert24to12Hours(options.value);
  } else {
    value = options.value;
  }
  rotation = me.getAngleFromTime(value, options.type);
  analogPickerEl.removeCls(['animated', 'animated-delayed']);
  analogPickerEl.toggleCls(me.dotIndicatorCls, isMinute && value % 5 !== 0);
  if (currentMode !== mode) {
    this.setMode(isMinute ? 'minute' : 'hour');
  }
  if (isMinute) {
    el = me.getElementByValue(value);
  }
  if (el && (!me.activeElement || me.activeElement !== el)) {
    if (me.activeElement) {
      me.activeElement.removeCls('active');
    }
    me.activeElement = el;
    if (options.disableAnimation) {
      el.addCls('active');
    } else {
      Ext.defer(function() {
        el.addCls('active');
      }, me.animationTimeDelay);
    }
  }
  if (handEl.rotation !== rotation) {
    analogPickerEl.toggleCls('animated' + (options.delayed ? '-delayed' : ''), !!options.animate);
    handEl.setStyle('transform', 'rotate(' + rotation + 'deg)');
    handEl.rotation = rotation;
  }
  if (is24Hours && !alignPMInside) {
    handEl.addCls('format-24hr');
  } else {
    handEl.removeCls('format-24hr');
  }
  if (is24Hours && alignPMInside && (options.value === 0 || options.value > 12)) {
    handEl.addCls('inner-dial');
  } else {
    handEl.removeCls('inner-dial');
  }
}, setHours:function(value, options) {
  var me = this, header = me.getHeader(), mode = me.getMode(), minutes = me.getMinutes(), isMeridiem = me.getMeridiem(), displayValue = isMeridiem ? me.convert24to12Hours(value) : value;
  if (isMeridiem && displayValue === 0) {
    displayValue = 12;
  } else {
    if (!isMeridiem && displayValue === 24) {
      displayValue = 0;
    }
  }
  header.hoursEl.setText(displayValue);
  if (mode === 'hour') {
    me.setClockHand(Ext.apply({value:value, type:'hour', 'meridiem':me.getMeridiem()}, options));
  }
  me.setValue(value * 60 + minutes);
}, setMinutes:function(value, options) {
  var me = this, header = me.getHeader(), mode = me.getMode(), hours = me.getHours();
  header.minutesEl.setText(Ext.String.leftPad(value, 2, '0'));
  if (mode === 'minute') {
    me.setClockHand(Ext.apply({value:value, type:'minute'}, options));
  }
  me.setValue(hours * 60 + value);
}, setTime:function(hour, minute, am) {
  var me = this;
  me.setHours(hour);
  me.setMinutes(minute);
  me.setAm(am);
}, startDrag:function() {
  var me = this;
  me.el.on({mousemove:'onMouseMove', scope:me});
  me.dragging = true;
}, stopDrag:function() {
  var me = this;
  me.el.un({mousemove:'onMouseMove', scope:me});
  me._center = null;
  me.dragging = false;
}, updateConfirmable:function(confirmable) {
  this.setButtons(confirmable && this.getDefaultButtons());
}, updateMode:function() {
  this.layoutFace();
}, updateValue:function() {
  var me = this, hour = me.getHours(), minutes = me.getMinutes(), am = me.getAm();
  if (this.rendered) {
    me.setHours(hour);
    me.setMinutes(minutes);
    me.hasSetAm = false;
    me.setAm(am);
  }
}, updateField:function() {
  var me = this, hour = me.getHours(), minutes = me.getMinutes(), newValue = new Date(me.initDate);
  newValue.setHours(hour > 23 ? hour - 12 : hour);
  newValue.setMinutes(minutes);
  me.fireEvent('select', me.parent, newValue);
}, collapsePanel:function() {
  this.fireEvent('collapsePanel', this);
}, setVerticalByOrientation:function() {
  this.updateVertical('auto');
}, updateVertical:function(vertical) {
  var me = this, viewport = Ext.Viewport;
  if (viewport) {
    if (vertical === 'auto') {
      vertical = viewport.getOrientation() === viewport.PORTRAIT;
      viewport.on('orientationchange', 'onOrientationChange', me);
    } else {
      viewport.un('orientationchange', 'onOrientationChange', me);
    }
  }
  me.toggleCls(Ext.baseCSSPrefix + 'vertical', vertical);
  me.setHeaderPosition(vertical ? 'top' : 'left');
  me.layoutFace();
}, doDestroy:function() {
  var viewport = Ext.Viewport;
  if (viewport) {
    viewport.un('orientationchange', 'onOrientationChange', this);
  }
  this.callParent();
}, convert24to12Hours:function(hour) {
  return hour > 12 ? hour - 12 : hour;
}, getIntialRotation:function(type, anglePerItem) {
  var me = this, isMinute = type !== 'hour', isMeridiem = me.getMeridiem(), alignPMInside = me.getAlignPMInside(), angleCount = isMinute ? 15 : isMeridiem ? 3 : alignPMInside ? 3 : 6;
  return anglePerItem * angleCount;
}, syncHours:function(value, options) {
  var me = this, hasMeridiem = me.getMeridiem(), am = me.getAm();
  if (hasMeridiem) {
    if (!am && value !== 12) {
      value = value + 12;
    } else {
      if (am && value === 12) {
        value = 0;
      }
    }
  } else {
    if (value === 24) {
      value = 0;
    }
  }
  me.setHours(value, options);
}});
Ext.define('Ext.panel.Time', {extend:Ext.Panel, xtype:'timepanel', mixins:[Ext.mixin.ConfigProxy], config:{view:{xtype:'analogtime'}}, proxyConfig:{view:{configs:['value', 'autoAdvance', 'vertical', 'confirmable', 'confirmHandler', 'declineHandler', 'scope', 'defaultButtons', 'mode', 'meridiem', 'alignPMInside', 'hourDisplayFormat'], methods:['getHours', 'getMinutes', 'updateField']}}, autoSize:null, initialize:function() {
  var me = this;
  me.callParent();
  if (me.getFloated()) {
    me.el.dom.setAttribute('tabIndex', -1);
    me.el.on('mousedown', me.onMouseDown, me);
  }
  me.relayEvents(me.getView(), ['collapsePanel', 'select']);
}, applyView:function(config, view) {
  return Ext.updateWidget(view, config, this, 'createView');
}, createView:function(config) {
  return this.mergeProxiedConfigs('view', config);
}, updateView:function(view, oldView) {
  if (oldView) {
    Ext.destroy(oldView);
  }
  this.add(view);
}, updateButtonAlign:function(align) {
  this.getView().setButtonAlign(align);
}, onMouseDown:function(e) {
  e.preventDefault();
}});
Ext.define('Ext.field.Time', {extend:Ext.field.Picker, xtype:'timefield', config:{triggers:{expand:{type:'time'}}, format:'', altFormats:'g:ia|' + 'g:iA|' + 'g:i a|' + 'g:i A|' + 'h:i|' + 'g:i|' + 'H:i|' + 'ga|' + 'ha|' + 'gA|' + 'h a|' + 'g a|' + 'g A|' + 'gi|' + 'hi|' + 'gia|' + 'hia|' + 'g|' + 'H|' + 'gi a|' + 'hi a|' + 'giA|' + 'hiA|' + 'gi A|' + 'hi A'}, platformConfig:{'phone || tablet':{floatedPicker:{modal:true, centered:true}, errorTarget:'under'}}, picker:'floated', floatedPicker:{xtype:'timepanel', 
floated:true, confirmable:true, listeners:{select:'onPickerChange', collapsePanel:'collapse', scope:'owner'}}, initDate:'1970-01-01', initDateFormat:'Y-m-d', matchFieldWidth:false, createFloatedPicker:function(config) {
  var pickerConfig = this.getFloatedPicker();
  return Ext.apply(pickerConfig, config);
}, getAutoPickerType:function() {
  return 'floated';
}, onPickerChange:function(picker, value) {
  var me = this;
  me.forceSetValue(value);
  me.fireEvent('select', me, value);
  me.collapse();
}, parseValue:function(value, errors) {
  var me = this, date = value, defaultFormat = me.getFormat(), altFormats = me.getAltFormats(), formats = [defaultFormat].concat(altFormats), i, len, format;
  if (date) {
    if (!Ext.isDate(date)) {
      for (i = 0, len = formats.length; i < len; i++) {
        format = formats[i];
        date = Ext.Date.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
        if (date) {
          return date;
        }
      }
    }
    if (date) {
      return date;
    }
  }
  return this.callParent([value, errors]);
}, realignFloatedPicker:function(picker) {
  picker = picker || this.getPicker();
  if (picker.isCentered()) {
    picker.center();
  } else {
    return this.callParent([picker]);
  }
}, showPicker:function() {
  var me = this, picker;
  me.callParent();
  picker = me.getPicker();
  picker.setValue(me.getValue());
  if (picker.getModal()) {
    me.getFocusTrap().focus();
  }
}, isEqual:function(value1, value2) {
  var v1 = this.transformValue(value1), v2 = this.transformValue(value2);
  return +v1 === +v2;
}, transformValue:function(value) {
  if (Ext.isDate(value)) {
    if (isNaN(value.getTime())) {
      value = null;
    }
  }
  return value;
}, applyInputValue:function(value, oldValue) {
  if (Ext.isDate(value)) {
    return Ext.Date.format(value, this.getFormat());
  }
  return this.callParent([value, oldValue]);
}, applyPicker:function(picker, oldPicker) {
  var me = this;
  if (picker === 'edge') {
    Ext.log.warn('Time Panel does not support "edge" picker, defaulting to "floated"');
    picker = 'floated';
  }
  picker = me.callParent([picker, oldPicker]);
  if (picker) {
    picker.ownerCmp = me;
  }
  return picker;
}, applyAltFormats:function(altFormats) {
  if (!altFormats) {
    return [];
  } else {
    if (!Ext.isArray(altFormats)) {
      return altFormats.split('|');
    }
  }
  return altFormats;
}, applyFormat:function(format) {
  return format || Ext.Date.defaultTimeFormat;
}, updateFormat:function(format) {
  this.setParseValidator({type:'time', format:format});
}, applyValue:function(value, oldValue) {
  if (!(value || value === 0)) {
    value = null;
  }
  value = this.callParent([value, oldValue]);
  if (value) {
    if (this.isConfiguring) {
      this.originalValue = value;
    }
  }
  return value;
}, updateValue:function(value, oldValue) {
  var picker = this._picker;
  if (picker) {
    picker.setValue(value);
  }
  this.callParent([value, oldValue]);
}, rawToValue:function(value) {
  return this.parseValue(value);
}});
Ext.define('dilocsync.overrides.field.Time', {override:'Ext.field.Time', submitFormat:false, initialize:function() {
  this.callParent(arguments);
  this.resetOriginalValue();
}, getSubmitValue:function() {
  var value = this.getValue();
  if (this.submitFormat) {
    value = Ext.Date.format(value, this.submitFormat);
  }
  return value;
}});
Ext.define('Ext.slider.Toggle', {extend:Ext.slider.Slider, xtype:'toggleslider', config:{onThumbUi:'toggle-on', offThumbUi:'toggle-off'}, value:0, classCls:Ext.baseCSSPrefix + 'toggleslider', minValueCls:Ext.baseCSSPrefix + 'off', maxValueCls:Ext.baseCSSPrefix + 'on', applyMinValue:function() {
  return 0;
}, applyMaxValue:function() {
  return 1;
}, applyIncrement:function() {
  return 1;
}, updateMinValueCls:function(newCls, oldCls) {
  var element = this.element;
  if (oldCls && element.hasCls(oldCls)) {
    element.replaceCls(oldCls, newCls);
  }
}, updateMaxValueCls:function(newCls, oldCls) {
  var element = this.element;
  if (oldCls && element.hasCls(oldCls)) {
    element.replaceCls(oldCls, newCls);
  }
}, setIndexValue:function(index, value, animation) {
  var oldValue = this.getValue()[index], thumb, newValue;
  this.callParent(arguments);
  thumb = this.thumbs[index];
  newValue = this.getValue();
  if (oldValue !== newValue) {
    this.fireEvent('change', this, thumb, newValue, oldValue);
  }
}, onChange:function(thumb, newValue, oldValue) {
  var me = this, isOn = newValue > 0, onCls = me.maxValueCls, offCls = me.minValueCls, element = me.element;
  element.addCls(isOn ? onCls : offCls);
  element.removeCls(isOn ? offCls : onCls);
  me.thumbs[0].setUi(isOn ? me.getOnThumbUi() : me.getOffThumbUi());
  me.callParent([thumb, newValue, oldValue]);
}, toggle:function() {
  var value = this.getValue();
  this.setValue(value === 1 ? 0 : 1);
  return this;
}, onTap:function() {
  var oldValue, newValue, thumb;
  if (this.isDisabled() || this.getReadOnly()) {
    return;
  }
  oldValue = this.getValue();
  newValue = oldValue === 1 ? 0 : 1;
  thumb = this.thumbs[0];
  this.setIndexValue(0, newValue, this.getAnimation());
  this.refreshAdjacentThumbConstraints(thumb);
}, privates:{syncFill:function() {
  var me = this, fillElement = me.trackElement.down(me.fillSelector), values = me.getArrayValues();
  if (values && values[0] === 1) {
    fillElement.show();
  } else {
    fillElement.hide();
  }
}}});
Ext.define('Ext.field.Toggle', {extend:Ext.field.SingleSlider, xtype:'togglefield', alternateClassName:'Ext.form.Toggle', twoWayBindable:{value:1}, publishes:{value:1}, config:{slider:{xtype:'toggleslider'}, activeLabel:null, inactiveLabel:null, value:false}, bodyAlign:'start', classCls:Ext.baseCSSPrefix + 'togglefield', updateActiveLabel:function(newActiveLabel, oldActiveLabel) {
  this.getSlider().element.dom.setAttribute('data-activelabel', newActiveLabel);
}, updateInactiveLabel:function(newInactiveLabel, oldInactiveLabel) {
  this.getSlider().element.dom.setAttribute('data-inactivelabel', newInactiveLabel);
}, applyValue:function(value, oldValue) {
  value = this.callParent([value, oldValue]);
  if (typeof value !== 'boolean') {
    value = value !== 0;
  }
  return value;
}, updateValue:function(value, oldValue) {
  var me = this, active = me.getActiveLabel(), inactive = me.getInactiveLabel();
  if (active || inactive) {
    me.setLabel(value ? active : inactive);
  }
  me.callParent([value, oldValue]);
}, setSliderValue:function(value) {
  this.getSlider().setValue(value ? 1 : 0);
  return !!value;
}, toggle:function() {
  this.setValue(!this.getValue());
  return this;
}, getRawValue:function() {
  return this.getValue();
}, rawToValue:Ext.emptyFn});
Ext.define('Ext.theme.material.field.Toggle', {override:'Ext.field.Toggle', config:{ripple:{delegate:'.' + Ext.baseCSSPrefix + 'thumb', bound:false, fit:false, color:'default'}}});
Ext.define('Ext.field.Url', {extend:Ext.field.Text, xtype:'urlfield', alternateClassName:'Ext.form.Url', config:{autoCapitalize:false}, inputType:'url', classCls:Ext.baseCSSPrefix + 'urlfield'});
Ext.define('Ext.field.trigger.Component', {extend:Ext.field.trigger.Base, alias:'trigger.component', classCls:Ext.baseCSSPrefix + 'componenttrigger', config:{component:null}, doDestroy:function() {
  this.setComponent(null);
  this.callParent();
}, applyComponent:function(config, existing) {
  return Ext.updateWidget(existing, config, this, 'createComponent');
}, createComponent:function(config) {
  return Ext.apply({$initParent:this, ownerCmp:this}, config);
}, updateComponent:function(component) {
  if (component) {
    delete component.$initParent;
    component.ownerCmp = this;
    this.el.appendChild(component.el);
  }
}, updateDisabled:function(disabled, oldDisabled) {
  this.callParent([disabled, oldDisabled]);
  this.getComponent().setDisabled(disabled);
}, getRefItems:function(deep) {
  var refItems = [], component = this.getComponent();
  if (component) {
    refItems.push(component);
    if (deep && component.getRefItems) {
      refItems.push.apply(refItems, component.getRefItems(deep));
    }
  }
  return refItems;
}});
Ext.define('Ext.field.trigger.File', {extend:Ext.field.trigger.Component, alias:'trigger.file', classCls:Ext.baseCSSPrefix + 'filetrigger', component:{xtype:'filebutton'}, disableOnReadOnly:false});
Ext.define('Ext.field.trigger.Menu', {extend:Ext.field.trigger.Trigger, xtype:'menutrigger', alias:'trigger.menu', cachedConfig:{menuAlign:'tl-bl?', destroyMenu:true}, config:{menu:{lazy:true, $value:null}}, doDestroy:function() {
  this.setMenu(null);
  this.callParent();
}, applyMenu:function(menu, oldMenu) {
  if (menu) {
    if (Ext.isArray(menu)) {
      menu = {items:menu};
    }
  }
  if (oldMenu && !this.getDestroyMenu()) {
    oldMenu = null;
  }
  return Ext.factory(menu, Ext.menu.Menu, oldMenu);
}, updateMenu:function(menu, oldMenu) {
  if (oldMenu && oldMenu.ownerCmp === this) {
    delete oldMenu.ownerCmp;
  }
  if (menu) {
    menu.ownerCmp = this;
  }
}, onClick:function(e) {
  var menu = this.getMenu();
  if (menu) {
    this.showMenu(e, menu);
  } else {
    this.callParent([e]);
  }
}, showMenu:function(e, menu) {
  var isPointerEvent = !e || e.pointerType;
  menu = menu || this.getMenu();
  if (menu) {
    if (menu.isVisible()) {
      if (isPointerEvent) {
        menu.hide();
      } else {
        menu.focus();
      }
    } else {
      menu.autoFocus = !isPointerEvent;
      if (menu.isMenu) {
        menu.showBy(this.element, this.getMenuAlign());
      } else {
        if (menu.isViewportMenu) {
          menu.setDisplayed(!menu.getDisplayed());
        } else {
          menu.show();
        }
      }
    }
  }
}});
Ext.define('Ext.form.FieldSet', {extend:Ext.Container, xtype:'fieldset', mixins:[Ext.form.Borders, Ext.mixin.FieldDefaults], config:{title:null, instructions:null}, autoSize:null, baseCls:Ext.baseCSSPrefix + 'form-fieldset', applyTitle:function(title) {
  if (typeof title === 'string') {
    title = {title:title};
  }
  Ext.applyIf(title, {docked:'top', cls:this.baseCls + '-title'});
  return Ext.factory(title, Ext.Title, this._title);
}, updateTitle:function(newTitle, oldTitle) {
  if (newTitle) {
    this.add(newTitle);
  }
  if (oldTitle) {
    this.remove(oldTitle);
  }
}, getTitle:function() {
  var title = this._title;
  if (title && title instanceof Ext.Title) {
    return title.getTitle();
  }
  return title;
}, applyInstructions:function(instructions) {
  if (typeof instructions === 'string') {
    instructions = {title:instructions};
  }
  Ext.applyIf(instructions, {docked:'bottom', cls:this.baseCls + '-instructions'});
  return Ext.factory(instructions, Ext.Title, this._instructions);
}, updateInstructions:function(newInstructions, oldInstructions) {
  if (newInstructions) {
    this.add(newInstructions);
  }
  if (oldInstructions) {
    this.remove(oldInstructions);
  }
}, getInstructions:function() {
  var instructions = this._instructions;
  if (instructions && instructions instanceof Ext.Title) {
    return instructions.getTitle();
  }
  return instructions;
}, updateDisabled:function(newDisabled) {
  this.query('field').forEach(function(field) {
    field.setDisabled(newDisabled);
  });
  return this;
}});
Ext.define('Ext.form.Panel', {extend:Ext.field.Panel, xtype:'formpanel', isFormPanel:true, mixins:[Ext.mixin.FieldDefaults], alternateClassName:'Ext.form.FormPanel', classCls:Ext.baseCSSPrefix + 'formpanel', element:{reference:'element', tag:'form', novalidate:'novalidate'}, config:{enableSubmissionForm:true, enctype:null, method:'post', multipartDetection:true, standardSubmit:false, submitOnAction:false, trackResetOnLoad:false}, getTemplate:function() {
  var template = this.callParent();
  template.push({tag:'input', type:'submit', cls:Ext.baseCSSPrefix + 'hidden-submit'});
  return template;
}, initialize:function() {
  this.callParent();
  this.element.on('submit', 'onSubmit', this);
}, applyEnctype:function(newValue) {
  var form = this.element.dom || null;
  if (form) {
    if (newValue) {
      form.setAttribute('enctype', newValue);
    } else {
      form.setAttribute('enctype');
    }
  }
}, onSubmit:function(event) {
  var me = this;
  if (event && !me.getStandardSubmit()) {
    event.stopEvent();
  } else {
    this.submit(null, event);
  }
}, updateSubmitOnAction:function(value) {
  this[value ? 'on' : 'un']({action:'onFieldAction', scope:this});
}, onFieldAction:function(field) {
  if (this.getSubmitOnAction()) {
    field.blur();
    this.submit();
  }
}, submit:function(options, e) {
  var me = this, formValues, form;
  options = options || {};
  formValues = me.getSubmitValues({enabled:me.getStandardSubmit() || !options.submitDisabled});
  form = me.element.dom || {};
  if (this.getEnableSubmissionForm()) {
    form = this.createSubmissionForm(form, formValues);
  }
  options = Ext.apply({url:me.getUrl() || form.action, submit:false, form:form, method:me.getMethod() || form.method || 'post', autoAbort:false, params:null, waitMsg:null, headers:null, success:null, failure:null}, options || {});
  return me.fireAction('beforesubmit', [me, formValues, options, e], 'doBeforeSubmit', null, null, 'after');
}, privates:{applyExtraParams:function(options) {
  var form = options.form, params = Ext.merge(this.getBaseParams() || {}, options.params), name, input;
  for (name in params) {
    input = document.createElement('input');
    input.setAttribute('type', 'text');
    input.setAttribute('name', name);
    input.setAttribute('value', params[name]);
    form.appendChild(input);
  }
}, beforeAjaxSubmit:function(form, options, successFn, failureFn) {
  var me = this, url = options.url || me.getUrl(), request = Ext.merge({}, {url:url, timeout:me.getTimeout() * 1000, form:form, scope:me}, options), formValues = {}, jsonSubmit = me.jsonSubmit, paramsKey = 'params', contentType = 'x-www-form-urlencoded; charset\x3dUTF-8', original, placeholder, formData;
  delete request.success;
  delete request.failure;
  if (jsonSubmit) {
    paramsKey = 'jsonData';
    contentType = 'json';
    formValues = me.getSubmitValues({enabled:me.getStandardSubmit() || !options.submitDisabled});
    delete request.params;
    delete request.form;
  }
  request[paramsKey] = Ext.merge({}, me.getBaseParams(), options.params, formValues);
  request.header = Ext.apply({'Content-Type':'application/' + contentType}, options.headers || {});
  request.callback = function(callbackOptions, success, response) {
    var responseText = response.responseText, responseXML = response.responseXML, statusResult = Ext.data.request.Ajax.parseStatus(response.status, response);
    if (form.$fileswap) {
      Ext.each(form.$fileswap, function(item) {
        original = item.original;
        placeholder = item.placeholder;
        placeholder.parentNode.insertBefore(original, placeholder.nextSibling);
        placeholder.parentNode.removeChild(placeholder);
      });
      form.$fileswap = null;
      delete form.$fileswap;
    }
    me.setMasked(false);
    if (response.success === false) {
      success = false;
    }
    if (success) {
      if (statusResult && responseText && responseText.length === 0) {
        success = true;
      } else {
        if (!Ext.isEmpty(response.responseBytes)) {
          success = statusResult.success;
        } else {
          if (Ext.isString(responseText) && response.request.options.responseType === 'text') {
            response.success = true;
          } else {
            if (Ext.isString(responseText)) {
              try {
                response = Ext.decode(responseText);
              } catch (e$64) {
                response.success = false;
                response.error = e$64;
                response.message = e$64.message;
              }
            } else {
              if (Ext.isSimpleObject(responseText)) {
                response = responseText;
                Ext.applyIf(response, {success:true});
              }
            }
          }
          if (!Ext.isEmpty(responseXML)) {
            response.success = true;
          }
          success = !!response.success;
        }
      }
      if (success) {
        successFn(response, responseText);
      } else {
        failureFn(response, responseText);
      }
    } else {
      failureFn(response, responseText);
    }
  };
  if (Ext.feature.has.XHR2 && request.xhr2) {
    delete request.form;
    formData = request.data = new FormData(form);
    if (request.params) {
      Ext.iterate(request.params, function(name, value) {
        if (Ext.isArray(value)) {
          Ext.each(value, function(v) {
            formData.append(name, v);
          });
        } else {
          formData.append(name, value);
        }
      });
      delete request.params;
    }
  }
  return Ext.Ajax.request(request);
}, beforeDirectSubmit:function(api, form, options, successFn, failureFn) {
  var me = this, submit;
  me.applyExtraParams(options);
  api = Ext.direct.Manager.resolveApi(api, me);
  me.setApi(api);
  submit = api.submit;
  if (!submit) {
    Ext.raise('Cannot find Ext Direct API method for submit action');
  }
  return submit(form, function(data, response, success) {
    me.setMasked(false);
    if (success) {
      if (data.success) {
        successFn(response, data);
      } else {
        failureFn(response, data);
      }
    } else {
      failureFn(response, data);
    }
  }, me);
}, beforeStandardSubmit:function(form, options) {
  var field, fields, ln, body, i;
  if (options.url && Ext.isEmpty(form.action)) {
    form.action = options.url;
  }
  fields = this.query('spinnerfield');
  ln = fields.length;
  body = document.body;
  for (i = 0; i < ln; i++) {
    field = fields[i];
    if (!field.getDisabled()) {
      field.setDisabled(false);
    }
  }
  body.appendChild(form);
  form.method = (options.method || form.method).toLowerCase();
  form.submit();
  body.removeChild(form);
}, createSubmissionForm:function(form, values) {
  var fields = this.getFields(), name, input, field, fileTrigger, inputDom;
  if (form.nodeType === 1) {
    form = form.cloneNode(false);
    for (name in values) {
      input = document.createElement('input');
      input.setAttribute('type', 'text');
      input.setAttribute('name', name);
      input.setAttribute('value', values[name]);
      form.appendChild(input);
    }
  }
  for (name in fields) {
    if (fields.hasOwnProperty(name)) {
      field = fields[name];
      if (field.isFile) {
        fileTrigger = field.getTriggers().file;
        inputDom = fileTrigger && fileTrigger.getComponent().buttonElement.dom;
        if (inputDom) {
          if (!form.$fileswap) {
            form.$fileswap = [];
          }
          input = inputDom.cloneNode(true);
          inputDom.parentNode.insertBefore(input, inputDom.nextSibling);
          form.appendChild(inputDom);
          form.$fileswap.push({original:inputDom, placeholder:input});
        }
      } else {
        if (field.isPassword) {
          if (field.getInputType() !== 'password') {
            field.setRevealed(false);
          }
        }
      }
    }
  }
  return form;
}, doBeforeSubmit:function(me, formValues, options) {
  var form = options.form || {}, multipartDetected = false, api, scope, ret, successFn, failureFn, waitMsg;
  if (this.getMultipartDetection() === true) {
    this.getFields(false).forEach(function(field) {
      if (field.isFile === true) {
        multipartDetected = true;
        return false;
      }
    });
    if (multipartDetected) {
      form.setAttribute('enctype', 'multipart/form-data');
    }
  }
  if (options.enctype) {
    form.setAttribute('enctype', options.enctype);
  }
  if (me.getStandardSubmit()) {
    ret = me.beforeStandardSubmit(form, options);
  } else {
    api = me.getApi();
    scope = options.scope || me;
    failureFn = function(response, responseText) {
      if (Ext.isFunction(options.failure)) {
        options.failure.call(scope, me, response, responseText);
      }
      me.fireEvent('exception', me, response);
    };
    successFn = function(response, responseText) {
      if (Ext.isFunction(options.success)) {
        options.success.call(options.scope || me, me, response, responseText);
      }
      me.fireEvent('submit', me, response);
    };
    waitMsg = options.waitMsg;
    if (options.waitMsg) {
      if (typeof waitMsg === 'string') {
        waitMsg = {xtype:'loadmask', message:waitMsg};
      }
      me.setMasked(waitMsg);
    }
    if (api) {
      ret = me.beforeDirectSubmit(api, form, options, successFn, failureFn);
    } else {
      ret = me.beforeAjaxSubmit(form, options, successFn, failureFn);
    }
  }
  return ret;
}}});
Ext.define('dilocsync.overrides.form.Panel', {override:'Ext.form.Panel', getValues:function(_enabled, _all) {
  var fields = this.getFields(), values = {}, isArray = Ext.isArray, field, value, addValue, bucket, name, ln, i;
  addValue = function(_field, _name) {
    if (!_all && (!_name || _name === 'null') || _field.isFile) {
      return;
    }
    if (_field.isCheckbox || _field.submitFormat) {
      value = _field.getSubmitValue();
    } else {
      value = _field.getValue();
    }
    if (!(_enabled && _field.getDisabled())) {
      if (_field.isRadio) {
        if (_field.isChecked()) {
          values[_name] = value;
        }
      } else {
        bucket = values[_name];
        if (!Ext.isEmpty(bucket)) {
          if (!_field.isCheckbox || _field.isChecked()) {
            if (!isArray(bucket)) {
              bucket = values[_name] = [bucket];
            }
            if (isArray(value)) {
              bucket = values[_name] = bucket.concat(value);
            } else {
              bucket.push(value);
            }
          }
        } else {
          values[_name] = value;
        }
      }
    }
  };
  for (name in fields) {
    if (fields.hasOwnProperty(name)) {
      field = fields[name];
      if (isArray(field)) {
        ln = field.length;
        for (i = 0; i < ln; i++) {
          addValue(field[i], name);
        }
      } else {
        addValue(field, name);
      }
    }
  }
  return values;
}});
Ext.define('Ext.grid.Location', {extend:Ext.dataview.Location, isGridLocation:true, actionable:false, cell:null, column:null, columnIndex:-1, summary:false, row:null, rowBody:null, isTreeLocation:false, inheritableStatics:{defineProtoProperty:function(propName, getterName) {
  Object.defineProperty(this.prototype, propName, {get:function() {
    var v = this[getterName]();
    Object.defineProperty(this, propName, {value:v, configurable:true});
    return v;
  }});
}}, attach:function(source) {
  var me = this, view = me.view, store = view.store, item, cell, column, columns, sourceRec, sourceCol, first;
  if (source.constructor === Object) {
    sourceRec = source.record;
    if (typeof sourceRec === 'number') {
      sourceRec = store.getAt(Math.max(Math.min(sourceRec, store.getCount() - 1), 0));
    }
    sourceCol = source.column;
    if (typeof sourceCol === 'number') {
      columns = view.getVisibleColumns();
      sourceCol = columns[Math.max(Math.min(sourceCol, columns.length - 1), 0)];
    }
    if (!(sourceRec && sourceCol)) {
      if (sourceRec) {
        sourceCol = view.getFirstVisibleColumn();
      } else {
        sourceRec = store.getAt(0);
      }
    }
    cell = view.mapToCell(sourceRec, sourceCol);
    if (cell) {
      source = cell.element;
    } else {
      me._setColumn(sourceCol);
      source = sourceRec;
    }
  }
  me.callParent([source]);
  item = me.item;
  if (item && item.isGridRow) {
    me.row = item;
    me.summary = item.isSummaryRow;
    if (!cell) {
      cell = view.mapToCell(source);
      if (!cell) {
        columns = view.getVisibleColumns();
        first = columns[0];
        if (first) {
          cell = item.getCellByColumn(first);
        }
      }
    }
    me.cell = cell;
    if (cell) {
      me.column = column = cell.getColumn();
      columns = columns || view.getVisibleColumns();
      me.columnIndex = columns.indexOf(column);
      me.isTreeLocation = !!cell.isTreeCell;
    } else {
      me.rowBody = view.mapToRowBody(source);
    }
  }
}, beforeEdit:function(editor) {
  return this.fireEditEvent('beforeedit', editor);
}, fireEditEvent:function(eventName, editor) {
  var me = this, view = me.view;
  if (editor) {
    me.editor = editor;
  }
  return view.fireEvent(eventName, view, me);
}, clone:function(options) {
  var me = this, ret = me.callParent(), record, column, cell;
  if (options) {
    if (options.record !== undefined) {
      record = options.record;
    }
    if (options.column !== undefined) {
      column = options.column;
    }
    delete ret.sourceElement;
  }
  if (record != null) {
    delete me.source;
    me.superclass.attach.call(ret, record);
    ret.row = ret.item;
  } else {
    ret.row = ret.child = me.row;
    ret.summary = me.summary;
    ret.rowBody = me.rowBody;
  }
  if (column != null) {
    ret._setColumn(column);
  } else {
    ret.cell = cell = me.cell;
    ret.column = me.column;
    ret.columnIndex = me.columnIndex;
    me.isTreeLocation = !!(cell && cell.isTreeCell);
  }
  return ret;
}, cloneForColumn:function(column) {
  return this.clone({column:column});
}, equals:function(other) {
  var me = this;
  if (other && other.view === me.view && other.isGridLocation) {
    if (me.actionable !== other.actionable) {
      return false;
    }
    if (me.sourceElement && me.actionable) {
      return other.sourceElement === me.sourceElement;
    }
    if (me.recordIndex !== other.recordIndex || me.record !== other.record) {
      return false;
    }
    return me.column === other.column;
  }
  return false;
}, equalCell:function(other) {
  var me = this;
  return other && other.view === me.view && other.isGridLocation && me.recordIndex === other.recordIndex && me.column === other.column;
}, getFocusEl:function(as) {
  var me = this, ret;
  if (me.actionable) {
    ret = me.sourceElement;
  } else {
    ret = me.get();
    ret = ret && !ret.destroyed && ret.el.dom;
  }
  return Ext.getBody().contains(ret) ? me.as(ret, as || 'el') : null;
}, getCell:function(as) {
  var result = this.cell, ret = null;
  if (result) {
    ret = as === 'dom' || as === true ? result.el.dom : as === 'cmp' ? result : result.el;
  }
  return ret;
}, get:function() {
  return this.cell;
}, isFirstColumn:function() {
  var column = this.column, ret = false;
  if (column) {
    ret = this.view.isFirstVisibleColumn(column);
  }
  return ret;
}, isLastColumn:function() {
  var column = this.column, ret = false;
  if (column) {
    ret = this.view.isLastVisibleColumn(column);
  }
  return ret;
}, refresh:function() {
  var me = this, column = me.column, oldColumnIndex = me.columnIndex, newColumnIndex = me.view.getHeaderContainer().indexOfLeaf(column), location;
  if (newColumnIndex === -1) {
    newColumnIndex = oldColumnIndex === -1 ? 0 : oldColumnIndex;
  }
  location = me.callParent();
  return location._setColumn(newColumnIndex);
}, next:function(options) {
  var me = this, candidate;
  if (me.actionable) {
    return me.navigate();
  } else {
    for (candidate = me.nextCell(options); candidate && !candidate.get().el.isFocusable(); candidate = candidate.nextCell(options)) {
    }
    return candidate || me;
  }
}, previous:function(options) {
  var me = this, candidate;
  if (me.actionable) {
    return me.navigate(true);
  } else {
    for (candidate = me.previousCell(options); candidate && !candidate.get().el.isFocusable(); candidate = candidate.previousCell(options)) {
    }
    return candidate || me;
  }
}, down:function(options) {
  var me = this, column = options && options.column || me.column, candidate = me.nextItem(options), cell;
  if (candidate) {
    candidate._setColumn(column);
    cell = candidate.get();
    while (candidate && (!cell || !cell.el.isFocusable())) {
      candidate = candidate.nextItem(options);
      if (candidate) {
        candidate._setColumn(column);
        cell = candidate.get();
      }
    }
    if (candidate && !candidate.equals(me)) {
      return candidate;
    }
  }
  return me;
}, up:function(options) {
  var me = this, column = options && options.column || me.column, candidate = me.previousItem(options), cell;
  if (candidate) {
    candidate._setColumn(column);
    cell = candidate.get();
    while (candidate && (!cell || !cell.el.isFocusable())) {
      candidate = candidate.previousItem(options);
      if (candidate) {
        candidate._setColumn(column);
        cell = candidate.get();
      }
    }
  }
  if (candidate && !candidate.equals(me)) {
    return candidate;
  }
  return me;
}, privates:{determineActionable:function() {
  var target = this.sourceElement, cell = this.cell, actionable = false;
  if (target && (!cell || cell.destroyed || cell.element.dom !== target)) {
    actionable = Ext.fly(target).isFocusable(true);
  }
  return actionable;
}, navigate:function(reverse) {
  var me = this, activeEl = me.sourceElement, view = me.view, scrollable = view.getScrollable(), actionables = view.getNavigationModel().actionables, len = actionables && actionables.length, candidate = me.clone(), previousCandidate = me.clone(), testEl, visitOptions = {callback:function(el) {
    testEl = Ext.fly(el);
    if (!testEl.$isFocusTrap && testEl.isFocusable()) {
      component = Ext.Component.from(el);
      if (!component || !component.getDisabled()) {
        focusables.push(el);
      }
    }
  }, reverse:reverse, skipSelf:true}, focusables = [], i, result, component;
  while (candidate && !result && candidate.get()) {
    focusables.length = 0;
    candidate.get().el.visit(visitOptions);
    activeEl = focusables[activeEl ? Ext.Array.indexOf(focusables, activeEl) + 1 : 0];
    if (activeEl) {
      result = candidate;
      result.source = result.sourceElement = activeEl;
      delete result.actionable;
      if (candidate.child) {
        scrollable.ensureVisible(candidate.child.el);
      }
      scrollable.ensureVisible(activeEl);
      activeEl.focus();
    } else {
      candidate = candidate[reverse ? 'previousCell' : 'nextCell']();
      if (candidate.equals(previousCandidate)) {
        return me;
      }
      if (candidate && len) {
        for (i = 0; !result && i < len; i++) {
          view.ensureVisible(candidate.record, {column:candidate.columnIndex, focus:true});
          result = actionables[i].activateCell(candidate);
        }
      }
    }
    previousCandidate = candidate;
  }
  return result || me;
}, activate:function() {
  var me = this, view = me.view, scrollable = view.getScrollable(), actionables = view.getNavigationModel().actionables, len = actionables && actionables.length, candidate = me.clone(), activeEl, i, result;
  candidate.get().el.visit({callback:function(el) {
    if (Ext.fly(el).isFocusable()) {
      activeEl = el;
      return false;
    }
  }, skipSelf:true});
  if (activeEl) {
    result = candidate;
    result.source = result.sourceElement = activeEl;
    delete result.actionable;
    if (candidate.child) {
      scrollable.ensureVisible(candidate.child.el);
    }
    scrollable.ensureVisible(activeEl);
    activeEl.focus();
  } else {
    for (i = 0; !result && i < len; i++) {
      result = actionables[i].activateCell(candidate);
    }
  }
  return result;
}, getFocusables:function() {
  var focusables = [], element = this.sourceElement;
  if (element) {
    Ext.fly(element).visit({callback:function(el) {
      if (Ext.fly(el).isFocusable()) {
        focusables.push(el);
      }
    }, skipSelf:true});
  }
  return focusables;
}, nextCell:function(options) {
  var me = this, startPoint = me.clone(), result = me.clone(), columns = me.getVisibleColumns(), rowIndex = me.view.store.indexOf(me.row.getRecord()), targetIndex, wrap = false;
  if (options) {
    if (typeof options === 'boolean') {
      wrap = options;
    } else {
      wrap = options.wrap;
    }
  }
  do {
    targetIndex = columns.indexOf(result.column) + 1;
    if (targetIndex === columns.length || !me.child.isGridRow) {
      if (rowIndex < me.view.store.getData().count() - 1) {
        result = me.getUpdatedLocation(columns[0], rowIndex + 1);
      } else {
        if (wrap) {
          result = me.getUpdatedLocation(columns[0], 0);
        }
      }
    } else {
      result = me.getUpdatedLocation(columns[targetIndex], rowIndex);
    }
    if (result && result.equals(startPoint)) {
      break;
    }
    if (!result) {
      result = startPoint;
      break;
    }
  } while (result && !result.sourceElement);
  return result;
}, getVisibleColumns:function() {
  var me = this, view = me.view, partners = view.allPartners || [view], partnerLen = partners.length, i, visibleColumns = [];
  for (i = 0; i < partnerLen; i++) {
    visibleColumns = visibleColumns.concat(partners[i].getVisibleColumns());
  }
  return visibleColumns;
}, previousCell:function(options) {
  var me = this, startPoint = me.clone(), result = me.clone(), columns = me.getVisibleColumns(), rowIndex = me.view.store.indexOf(me.row.getRecord()), targetIndex, wrap = false;
  if (options) {
    if (typeof options === 'boolean') {
      wrap = options;
    } else {
      wrap = options.wrap;
    }
  }
  do {
    targetIndex = columns.indexOf(result.column) - 1;
    if (targetIndex === -1 || !me.child.isGridRow) {
      if (rowIndex > 0) {
        result = me.getUpdatedLocation(columns[columns.length - 1], rowIndex - 1);
      } else {
        if (wrap) {
          result = me.getUpdatedLocation(columns[columns.length - 1], me.view.store.getData().count() - 1);
        }
      }
    } else {
      result = me.getUpdatedLocation(columns[targetIndex], rowIndex);
    }
    if (result && result.equals(startPoint)) {
      break;
    }
    if (!result) {
      result = startPoint;
      break;
    }
  } while (result && !result.sourceElement);
  return result;
}, getUpdatedLocation:function(column, targetRowIndex) {
  var me = this, grid = column.getGrid(), targetRecord = me.view.store.getData().getAt(targetRowIndex), location = grid.createLocation(targetRecord);
  location.column = column;
  location.columnIndex = grid.getVisibleColumns().indexOf(column);
  location.cell = location.row && location.row.getCellByColumn(column);
  if (location.cell) {
    delete me.event;
    delete me.actionable;
    location.isTreeLocation = !!location.cell.isTreeCell;
    location.sourceElement = location.cell.el.dom;
    return location;
  } else {
    return null;
  }
}, _setColumn:function(column) {
  var me = this, columns = me.view.getVisibleColumns(), index;
  if (typeof column === 'number') {
    index = column;
    column = columns[index];
  } else {
    index = columns.indexOf(column);
  }
  delete me.event;
  delete me.actionable;
  me.column = column;
  me.columnIndex = index;
  me.cell = me.row && me.row.getCellByColumn(column);
  if (me.cell) {
    me.isTreeLocation = !!me.cell.isTreeCell;
    me.sourceElement = me.cell.el.dom;
  }
  return me;
}}}, function(Cls) {
  Cls.defineProtoProperty('actionable', 'determineActionable');
});
Ext.define('Ext.grid.NavigationModel', {extend:Ext.dataview.NavigationModel, alias:'navmodel.grid', locationClass:'Ext.grid.Location', statics:{ignoreInputFieldKeys:{PAGE_UP:true, PAGE_DOWN:true, END:true, HOME:true, LEFT:true, UP:true, RIGHT:true, DOWN:true}}, setLocation:function(location, options) {
  var me = this, view = me.getView(), event = options && options.event;
  me.columnIndex = -1;
  if (location != null && !location.isGridLocation) {
    if (Ext.isArray(location)) {
      location = {column:location[0], record:location[1]};
    } else {
      if (typeof location === 'number') {
        location = view.store.getAt(location);
      }
    }
    location = me.createLocation(location);
    if (event) {
      location.event = event;
    }
  }
  return me.callParent([location, options]);
}, clearLocation:function() {
  var me = this, item;
  if (me.location) {
    me.previousLocation = me.location;
    item = me.location.sourceElement;
    if (item) {
      Ext.fly(item).removeCls(me.focusedCls);
    }
    me.location = null;
  }
}, registerActionable:function(actionable) {
  var me = this, view = me.getView(), actionables = me.actionables || (me.actionables = []), triggerEvent, listeners;
  if (!Ext.Array.contains(actionables, actionable)) {
    actionables.push(actionable);
    triggerEvent = actionable.getTriggerEvent();
    if (triggerEvent) {
      listeners = {scope:me, args:[actionable]};
      listeners[triggerEvent] = 'triggerActionable';
      actionable.triggerEventListener = view.bodyElement.on(listeners);
    }
  }
}, unregisterActionable:function(actionable) {
  var actionables = this.actionables;
  if (actionables) {
    Ext.Array.remove(actionables, actionable);
  }
}, privates:{onFocusMove:function(e) {
  var me = this, view = me.getView(), location = me.getLocation();
  if (e.toElement === view.el.dom && location) {
    me.clearLocation();
    return me.setLocation(location);
  }
  location = me.createLocation(e);
  if (!location.equals(me.location)) {
    me.handleLocationChange(location, {event:e, navigate:false});
  }
}, processViewEvent:function(e) {
  var me = this, view = me.getView(), cell = view.mapToCell(e);
  if (Ext.fly(e.target).isInputField() && me.self.ignoreInputFieldKeys[e.getKeyName()]) {
    return false;
  }
  if (cell && cell.row.grid === view) {
    return e;
  }
}, activateCell:function(location) {
  location.clone().activate();
}, triggerActionable:function(actionable, e) {
  var actionLocation = this.createLocation(e);
  actionLocation = actionLocation.cell && actionable.activateCell(actionLocation);
  if (actionLocation) {
    this.setLocation(actionLocation);
  }
}, onChildTouchStart:function(view, location) {
  var e = location.event;
  if (location.header || location.footer) {
    e.preventDefault();
  } else {
    if (this.location && !this.location.equalCell(location)) {
      this.setLocation(location, {event:location.event, navigate:this.getView().getTriggerEvent() === 'childtouchstart'});
    }
  }
}, onKeyUp:function(e) {
  e.preventDefault();
  if (!this.location.actionable) {
    if (this.location) {
      this.moveUp(e);
    } else {
      this.setLocation(0);
    }
  }
}, onKeyDown:function(e) {
  e.preventDefault();
  if (!this.location.actionable) {
    if (this.location) {
      this.moveDown(e);
    } else {
      this.setLocation(0);
    }
  }
}, onKeyLeft:function(e) {
  var location = this.location, isSimpleTree = location.isLastColumn() && location.isFirstColumn();
  if (!location.actionable) {
    e.preventDefault();
    if (location.isTreeLocation && !location.record.isLeaf() && location.record.isExpanded()) {
      if (isSimpleTree === !e.ctrlKey) {
        return location.cell.collapse();
      }
    }
    if (!(e.shiftKey && location.isFirstColumn())) {
      this.movePrevious({event:e});
    }
  } else {
    if (Ext.fly(e.target).isInputField()) {
      return true;
    }
  }
}, onKeyRight:function(e) {
  var location = this.location, isSimpleTree = location.isLastColumn() && location.isFirstColumn();
  if (!location.actionable) {
    e.preventDefault();
    if (location.isTreeLocation && !location.record.isLeaf() && !location.record.isExpanded()) {
      if (isSimpleTree === !e.ctrlKey) {
        return location.cell.expand();
      }
    }
    if (!(e.shiftKey && location.isLastColumn())) {
      this.moveNext({event:e});
    }
  } else {
    if (Ext.fly(e.target).isInputField()) {
      return true;
    }
  }
}, onKeyF2:function(e) {
  if (this.location.actionable) {
    this.onKeyEsc();
  } else {
    this.activateCell(this.location);
  }
}, onKeyEsc:function(e) {
  if (this.location.actionable) {
    this.location.get().el.focus();
  }
}, onKeyTab:function(e) {
  var me = this, location = me.location, navigate;
  if (location.actionable) {
    navigate = function() {
      me.location = e.shiftKey ? location.previous() : location.next();
    };
    navigate();
  } else {
    return true;
  }
}, onKeyPageDown:function(e) {
  var me = this, view, y, candidate;
  e.preventDefault();
  if (!me.location.actionable) {
    view = me.getView();
    y = (view.infinite ? view.getItemTop(me.location.child) : me.location.child.el.dom.offsetTop) + view.getVisibleHeight();
    candidate = view.getRecordIndexFromPoint(0, y);
    view.ensureVisible(candidate).then(function() {
      candidate = new Ext.grid.Location(view, {record:candidate, column:me.location.column});
      if (!(candidate.sourceElement && Ext.fly(candidate.sourceElement).isFocusable())) {
        candidate = candidate.up();
      }
      me.setLocation(candidate, {event:e});
    });
  }
}, onKeyPageUp:function(e) {
  var me = this, view, y, candidate;
  e.preventDefault();
  if (!me.location.actionable) {
    view = me.getView();
    y = (view.infinite ? view.getItemTop(me.location.child) : me.location.child.el.dom.offsetTop) - view.getVisibleHeight();
    candidate = view.getRecordIndexFromPoint(0, y);
    view.ensureVisible(candidate).then(function() {
      candidate = new Ext.grid.Location(view, {record:candidate, column:me.location.column});
      if (!(candidate.sourceElement && Ext.fly(candidate.sourceElement).isFocusable())) {
        candidate = candidate.down();
      }
      me.setLocation(candidate, {event:e});
    });
  }
}, onKeyHome:function(e) {
  e.preventDefault();
  if (!this.location.actionable) {
    if (e.ctrlKey) {
      this.setLocation({record:this.getView().getStore().first(), column:this.location.column}, {event:e});
    } else {
      this.setLocation({record:this.location.record, column:this.getView().getFirstVisibleColumn()}, {event:e});
    }
  }
}, onKeyEnd:function(e) {
  e.preventDefault();
  if (!this.location.actionable) {
    if (e.ctrlKey) {
      this.setLocation({record:this.getView().getStore().last(), column:this.location.column}, {event:e});
    } else {
      this.setLocation({record:this.location.record, column:this.getView().getLastVisibleColumn()}, {event:e});
    }
  }
}, onKeySpace:function(e) {
  var target = Ext.fly(e.target), events, focusables, result;
  this.onNavigate(e);
  if (!this.location.actionable) {
    focusables = this.location.getFocusables();
    if (focusables.length) {
      events = Ext.get(focusables[0]).events;
    }
  } else {
    if (target.isInputField()) {
      result = true;
    } else {
      events = target.events;
    }
  }
  if (events) {
    if (events.tap) {
      events.tap.fire(e);
    }
    if (events.click) {
      events.click.fire(e);
    }
  }
  return result;
}, onKeyEnter:function(e) {
  var l = this.location;
  e.stopEvent();
  if (!l.actionable) {
    if (l.isTreeLocation && l.record.data.checked != null) {
      l.record.set('checked', !l.record.data.checked);
    } else {
      this.activateCell(l);
    }
  } else {
    this.onKeySpace(e);
  }
}, onSelectAllKeyPress:function(e) {
  if (Ext.fly(e.target).isInputField()) {
    return true;
  } else {
    return this.callParent([e]);
  }
}, moveUp:function(e) {
  var location = this.getLocation();
  if (location) {
    location = location.up();
    if (location) {
      this.setLocation(location, {event:e});
    }
  }
}, moveDown:function(e) {
  var location = this.getLocation();
  if (location) {
    location = location.down();
    if (location) {
      this.setLocation(location, {event:e});
    }
  }
}}});
Ext.define('Ext.grid.cell.Base', {extend:Ext.Widget, xtype:'gridcellbase', isGridCell:true, mixins:[Ext.mixin.Toolable], cachedConfig:{align:null, cls:null, bodyCls:null, bodyStyle:null, cellCls:null, selectable:null}, config:{column:null, hidden:false, record:null, value:null}, classCls:Ext.baseCSSPrefix + 'gridcell', dirtyCls:Ext.baseCSSPrefix + 'dirty', alignCls:{left:Ext.baseCSSPrefix + 'align-left', center:Ext.baseCSSPrefix + 'align-center', right:Ext.baseCSSPrefix + 'align-right'}, inheritUi:true, 
cellSelector:'.' + Ext.baseCSSPrefix + 'gridcell', defaultBindProperty:'value', toolDefaults:{zone:'head', ui:'gridcell'}, getTemplate:function() {
  var template = {reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', uiCls:'body-el'};
  if (!(template.children = this.innerTemplate)) {
    template.html = ' ';
  }
  return [template];
}, doDestroy:function() {
  this.setColumn(null);
  this.setRecord(null);
  this.mixins.toolable.doDestroy.call(this);
  this.callParent();
}, getComputedWidth:function() {
  return this.getHidden() ? 0 : this.getWidth();
}, updateAlign:function(align, oldAlign) {
  var me = this, alignCls = me.alignCls;
  if (oldAlign) {
    me.removeCls(alignCls[oldAlign]);
  }
  if (align) {
    if (!alignCls[align]) {
      Ext.raise("Invalid value for align: '" + align + "'");
    }
    me.addCls(alignCls[align]);
  }
  me.syncToolableAlign();
}, updateBodyCls:function(cellCls, oldCellCls) {
  if (cellCls || oldCellCls) {
    this.bodyElement.replaceCls(oldCellCls, cellCls);
  }
}, updateBodyStyle:function(style) {
  this.bodyElement.applyStyles(style);
}, updateCellCls:function(cls, oldCls) {
  this.element.replaceCls(oldCls, cls);
}, updateCls:function(cls, oldCls) {
  this.element.replaceCls(oldCls, cls);
}, updateColumn:function(column) {
  var dataIndex = null, row = this.row;
  if (column) {
    dataIndex = row && row.isSummaryRow && column.getSummaryDataIndex() || column.getDataIndex();
  }
  this.dataIndex = dataIndex;
}, updateRecord:function() {
  if (!this.destroyed && !this.destroying) {
    this.refresh();
  }
}, updateSelectable:function(value) {
  this.toggleCls(Ext.baseCSSPrefix + 'item-no-select', value === false);
}, refresh:function(ctx) {
  var me = this, was = me.refreshContext, context, modified, value;
  if (!me.isBound('value')) {
    ctx = ctx || was;
    modified = ctx && ctx.modified;
    if (!modified || me.bound(modified)) {
      me.refreshContext = context = me.beginRefresh(ctx);
      value = me.refreshValue(context);
      if (value !== me.getValue()) {
        me.setValue(value);
      } else {
        if (me.writeValue) {
          me.writeValue();
        }
      }
      me.refreshContext = was;
    }
  }
}, refreshValue:function(context) {
  var me = this, record = context.record, dataIndex = context.dataIndex, value, dirty, modified;
  if (context.summary) {
    value = me.summarize(context);
  } else {
    if (record && dataIndex) {
      value = record.get(dataIndex);
      modified = record.modified;
      dirty = !!(modified && modified.hasOwnProperty(dataIndex));
      if (dirty !== me.$dirty) {
        me.toggleCls(me.dirtyCls, dirty);
        me.$dirty = dirty;
      }
    }
  }
  return value;
}, privates:{refreshCounter:0, $dirty:false, refreshContext:null, storeMethodRe:/^(?:average|max|min|sum)$/, augmentToolHandler:function(tool, args) {
  var info = args[1] = {event:args.pop(), record:this.getRecord(), column:this.getColumn(), cell:args[0], tool:args[1]};
  args[0] = info.grid = info.column.getGrid();
}, beginRefresh:function(context) {
  var me = this, column = me.getColumn(), row = me.row;
  context = context || (row ? row.beginRefresh() : {record:me.getRecord()});
  ++me.refreshCounter;
  context.from = context.from || 'cell';
  context.cell = me;
  context.column = column;
  context.dataIndex = me.dataIndex;
  context.scope = column.getScope();
  return context;
}, bound:function(fields) {
  return !!fields[this.dataIndex];
}, summarize:function(context) {
  var me = this, column = context.column, summaryType = column.getSummaryType(), dataIndex = context.dataIndex, group = context.group, store = context.store, records = context.records, value;
  if (summaryType) {
    if (!column.$warnSummaryType) {
      column.$warnSummaryType = true;
      Ext.log.warn('[column] summaryType is deprecated; use summaryRenderer (' + column.getId() + ')');
    }
    if (Ext.isFunction(summaryType)) {
      value = summaryType.call(store, store.data.items.slice(), dataIndex);
    } else {
      if (summaryType === 'count') {
        value = store.getCount();
      } else {
        if (me.storeMethodRe.test(summaryType)) {
          value = store[summaryType](dataIndex);
        } else {
          value = Ext.callback(summaryType, null, [store.data.items.slice(), dataIndex, store], 0, me);
        }
      }
    }
  } else {
    if (!(summaryType = column.getSummary())) {
      if (dataIndex) {
        value = context.record.get(dataIndex);
      }
    } else {
      if (!dataIndex) {
        Ext.raise('Cannot use summary config w/o summaryDataIndex or dataIndex (' + context.grid.getId() + ')');
      } else {
        if (group) {
          if (group.isVirtualGroup) {
            Ext.raise('Cannot calculate a group summary on a virtual store (' + context.grid.getId() + ')');
          }
        } else {
          if (store.getRemoteSort()) {
            Ext.raise('Cannot calculate a summary on a remoteSort store (' + context.grid.getId() + ')');
          }
        }
        value = summaryType.calculate(records, dataIndex, 'data', 0, records.length);
      }
    }
  }
  return value;
}}, deprecated:{'6.5':{configs:{innerStyle:'bodyStyle', innerCls:'bodyCls'}}}});
Ext.define('Ext.grid.cell.Text', {extend:Ext.grid.cell.Base, xtype:'textcell', config:{encodeHtml:true, rawValue:null, zeroValue:null}, getTemplate:function() {
  var template = this.callParent();
  template[0]['data-qoverflow'] = true;
  return template;
}, formatValue:function(v) {
  var me = this, context = me.refreshContext, column = context.column, zeroValue = me.getZeroValue(), format = column.getFormatter(), renderer, scope;
  if (context.summary) {
    renderer = column.getSummaryRenderer();
    if (renderer) {
      format = null;
      scope = context.scope;
      if (typeof renderer === 'string') {
        v = Ext.callback(renderer, scope, [v, context], 0, column);
      } else {
        v = renderer.call(scope || me, v, context);
      }
    }
    format = column.getSummaryFormatter() || format;
  } else {
    if (v === 0 && zeroValue !== null) {
      v = zeroValue;
      format = null;
    }
  }
  if (format) {
    v = format(v);
  }
  if (v != null) {
    v = String(v);
  } else {
    v = '';
  }
  return v;
}, printValue:function(v) {
  var me = this, was = me.refreshContext, s;
  me.refreshContext = me.beginRefresh(was);
  s = me.formatValue(v);
  if (me.getEncodeHtml()) {
    s = Ext.htmlEncode(s);
  }
  me.refreshContext = was;
  return s;
}, updateRawValue:function(rawValue) {
  var dom = this.bodyElement.dom, value = rawValue == null ? '' : rawValue;
  if (this.getEncodeHtml()) {
    dom.textContent = value;
  } else {
    dom.innerHTML = value;
  }
}, updateValue:function() {
  var me = this, was = me.refreshContext, row = me.row;
  if (row && row.parent) {
    if (!was) {
      me.refreshContext = me.beginRefresh();
    }
    me.writeValue();
    me.refreshContext = was;
  }
}, updateZeroValue:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, writeValue:function() {
  var me = this, value = me.getValue();
  if (!(value = me.formatValue(value))) {
    value = me.getColumn().getEmptyText();
  }
  me.setRawValue(value);
}});
Ext.define('Ext.grid.cell.Cell', {extend:Ext.grid.cell.Text, xtype:'gridcell', config:{tpl:null, renderer:null, formatter:null, scope:null}, friendly:null, updateColumn:function(column, oldColumn) {
  var me = this, friendly = true, tpl, renderer, formatter;
  me.callParent([column, oldColumn]);
  if (column) {
    tpl = column.getTpl();
    renderer = column.getRenderer();
    formatter = column.getFormatter();
    if (renderer !== null) {
      me.setRenderer(renderer);
      friendly = typeof renderer === 'function' && renderer.length === 1;
    }
    if (tpl !== null) {
      me.setTpl(tpl);
      friendly = false;
    }
    if (formatter !== null) {
      me.setFormatter(formatter);
    }
    me.friendly = friendly;
  }
}, applyTpl:function(tpl) {
  return Ext.XTemplate.get(tpl);
}, applyFormatter:function(format) {
  var me = this, fmt = format, parser;
  if (typeof fmt === 'string') {
    parser = Ext.app.bind.Parser.fly(fmt);
    fmt = parser.compileFormat();
    parser.release();
    return function(v) {
      return fmt(v, me.getScope() || me.resolveListenerScope());
    };
  } else {
    if (typeof fmt !== 'function') {
      Ext.raise('Invalid formatter');
    }
  }
  return fmt;
}, updateTpl:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, updateRenderer:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, updateFormatter:function() {
  if (!this.isConfiguring) {
    this.refresh();
  }
}, formatValue:function(v) {
  var me = this, context = me.refreshContext, dataIndex = context.dataIndex, column = context.column, record = context.record, zeroValue = me.getZeroValue(), raw = v, summary = context.summary, args, data, format, renderer, scope, tpl;
  if (!context.summary && v === 0 && zeroValue !== null) {
    raw = zeroValue;
  } else {
    if (!(tpl = me.getTpl(context))) {
      format = me.getFormatter();
      if (summary) {
        renderer = column.getSummaryRenderer();
        if (renderer) {
          format = null;
          scope = context.scope;
          if (typeof renderer === 'string') {
            raw = Ext.callback(renderer, scope, [v, context], 0, column);
            me.friendly = false;
          } else {
            raw = renderer.call(scope || me, v, context);
            if (renderer.length > 1) {
              me.friendly = false;
            }
          }
        }
        format = column.getSummaryFormatter() || format;
      } else {
        renderer = me.getRenderer();
        if (renderer) {
          args = [v, record, dataIndex, me, column];
          scope = me.getScope() || context.scope;
          if (typeof renderer === 'function') {
            raw = renderer.apply(scope || column, args);
          } else {
            raw = Ext.callback(renderer, scope, args, 0, me);
          }
        }
      }
      if (format) {
        raw = format(raw);
      }
    } else {
      if (!(data = context.data)) {
        context.data = data = context.summary ? context.record.getData() : context.grid.gatherData(context.record);
      }
      raw = tpl.apply(data);
    }
  }
  if (raw != null) {
    raw = String(raw);
  } else {
    raw = '';
  }
  return raw;
}, privates:{bound:function(fields) {
  var me = this, bound = !!fields[me.dataIndex], column, depends, i;
  if (!bound) {
    column = me.getColumn();
    depends = column && column.getDepends();
    if (depends) {
      for (i = depends.length; !bound && i-- > 0;) {
        bound = !!fields[depends[i]];
      }
    } else {
      if (!me.friendly) {
        bound = true;
      }
    }
  }
  return bound;
}}});
Ext.define('Ext.grid.RowBody', {extend:Ext.Component, xtype:'rowbody', config:{widget:null}, classCls:Ext.baseCSSPrefix + 'rowbody', inheritUi:true, template:[{reference:'spacerElement', cls:Ext.baseCSSPrefix + 'spacer-el'}, {reference:'contentElement', cls:Ext.baseCSSPrefix + 'content-el'}], initialize:function() {
  var me = this, grid, rowExpander;
  me.callParent();
  grid = me.row.getGrid();
  if (grid && grid.hasRowExpander) {
    rowExpander = grid.findPlugin('rowexpander');
    if (rowExpander) {
      me.spacerElement.setWidth(rowExpander.getColumn().getWidth());
    }
  }
}, applyWidget:function(widget) {
  var row = this.row;
  if (widget) {
    widget = Ext.apply({ownerCmp:row}, widget);
    widget = Ext.widget(widget);
  }
  return widget;
}, updateWidget:function(widget, oldWidget) {
  if (oldWidget) {
    oldWidget.destroy();
  }
  if (widget) {
    this.contentElement.appendChild(widget.element);
  }
}, updateRecord:function(record, oldRecord) {
  var tpl = this.getTpl();
  if (tpl) {
    this.callParent([record, oldRecord]);
  }
}, getInnerHtmlElement:function() {
  return this.contentElement;
}, doDestroy:function() {
  this.setWidget(null);
  this.callParent();
}});
Ext.define('Ext.grid.Row', {extend:Ext.Component, xtype:'gridrow', mixins:[Ext.mixin.Queryable, Ext.dataview.GenericItem, Ext.dataview.Pinnable], isGridRow:true, isRecordRefreshable:true, hasGridCells:true, cachedConfig:{collapsed:true}, config:{body:null, expandedField:null, defaultCellUI:null, stickyVisibility:null, flexbox:false}, classCls:[Ext.baseCSSPrefix + 'listitem', Ext.baseCSSPrefix + 'gridrow'], inheritUi:true, expandedCls:Ext.baseCSSPrefix + 'expanded', flexboxCls:Ext.baseCSSPrefix + 
'flexbox', element:{reference:'element', children:[{reference:'cellsElement', className:Ext.baseCSSPrefix + 'cells-el'}]}, constructor:function(config) {
  this.cells = [];
  this.columnMap = {};
  this.callParent([config]);
}, updateFlexbox:function(value) {
  this.cellsElement.el.toggleCls(this.flexboxCls, value);
}, doDestroy:function() {
  var me = this;
  me.setRecord(null);
  me.setBody(null);
  me.cells = Ext.destroy(me.cells);
  me.callParent();
}, collapse:function() {
  this.setCollapsed(true);
}, expand:function() {
  this.setCollapsed(false);
}, toggleCollapsed:function() {
  this.setCollapsed(!this.getCollapsed());
}, updateCollapsed:function(collapsed) {
  var me = this, body = me.getBody(), grid = me.getParent(), record = me.getRecord(), expandField = me.getExpandedField(), expandedCls = me.expandedCls, expanderCell = me.expanderCell, recordsExpanded;
  if (record) {
    if (expandField) {
      record.set(expandField, !collapsed);
    } else {
      recordsExpanded = grid.$recordsExpanded || (grid.$recordsExpanded = {});
      if (collapsed) {
        delete recordsExpanded[record.internalId];
      } else {
        recordsExpanded[record.internalId] = true;
      }
    }
  }
  if (expanderCell) {
    expanderCell.setCollapsed(collapsed);
  }
  if (body) {
    if (collapsed) {
      body.hide();
      me.removeCls(expandedCls);
    } else {
      body.show();
      me.addCls(expandedCls);
    }
  }
}, applyBody:function(config, existing) {
  return Ext.updateWidget(existing, config, this, 'createBody');
}, createBody:function(body) {
  return Ext.merge({xtype:'rowbody', ownerCmp:this, row:this, hidden:true}, body);
}, updateBody:function(body) {
  var me = this, grid = me.getParent();
  if (body) {
    me.bodyElement.appendChild(body.element);
    if (me.rendered && !body.rendered) {
      body.setRendered(true);
    }
  }
  if (grid) {
    grid.setVariableHeights(true);
    if (!grid.hasRowExpander) {
      me.expand();
    }
  }
}, onAdded:function(grid) {
  var me = this, cells = me.cells, cell, col, columns, i, k, n;
  me.callParent(arguments);
  if (grid) {
    columns = grid.getColumns();
    for (i = 0, n = columns.length; i < n; i++) {
      cell = cells[i];
      col = columns[i];
      if (cell) {
        if (cell.getColumn() === col) {
          continue;
        }
        for (k = cells.length; k-- > i;) {
          cell = cells[k];
          me.removeColumn(cell.getColumn());
        }
      }
      me.addColumn(columns[i]);
    }
  }
}, addColumn:function(column) {
  this.insertColumn(this.cells.length, column);
}, getCells:function(selector) {
  return selector ? Ext.ComponentQuery.query(selector, this.cells) : this.cells;
}, getRefItems:function(deep) {
  var result = [], body = this.getConfig('body', false, true), cells = this.cells, len = cells && cells.length, i, cell;
  for (i = 0; i < len; i++) {
    cell = cells[i];
    result.push(cell);
    if (deep && cell.getRefItems) {
      result.push.apply(result, cell.getRefItems());
    }
  }
  if (body) {
    result.push(body);
    if (deep && body.getRefItems) {
      result.push.apply(result, body.getRefItems());
    }
  }
  return result;
}, insertColumn:function(index, column) {
  var me = this, cells = me.cells, cell;
  if (column.isHeaderGroup) {
    return;
  }
  cell = me.createCell(column);
  if (index >= cells.length) {
    me.cellsElement.appendChild(cell.element);
    cells.push(cell);
  } else {
    cell.element.insertBefore(cells[index].element);
    cells.splice(index, 0, cell);
  }
  me.columnMap[column.getId()] = cell;
  if (cell.isExpanderCell) {
    me.expanderCell = cell;
  }
  if (me.rendered) {
    cell.setRendered(true);
  }
}, insertColumnBefore:function(column, ref) {
  var me = this, map = me.columnMap, id = column.getId(), cell = map[id], cells = me.cells, refCell, refIndex, index;
  if (ref) {
    refCell = me.getCellByColumn(ref);
    refIndex = cells.indexOf(refCell);
  } else {
    refIndex = cells.length - (cell ? 1 : 0);
  }
  if (cell) {
    index = cells.indexOf(cell);
    Ext.Array.move(cells, index, refIndex);
    if (refCell) {
      cell.element.insertBefore(refCell.element);
    } else {
      me.cellsElement.appendChild(cell.element);
    }
  } else {
    me.insertColumn(refIndex, column);
  }
}, removeColumn:function(column) {
  var me = this, columnMap = me.columnMap, columnId = column.getId(), cell = columnMap[columnId];
  if (cell) {
    Ext.Array.remove(me.cells, cell);
    delete columnMap[columnId];
    cell.destroy();
  }
}, updateRecord:function(record) {
  if (!this.destroyed && !this.destroying) {
    this.refresh();
  }
}, setColumnWidth:function(column) {
  var cell = this.getCellByColumn(column);
  if (cell) {
    cell.setWidth(column.getComputedWidth());
  }
}, showColumn:function(column) {
  this.setCellHidden(column, false);
}, hideColumn:function(column) {
  this.setCellHidden(column, true);
}, getCellByColumn:function(column) {
  return this.columnMap[column.getId()];
}, getColumnByCell:function(cell) {
  return cell.getColumn();
}, updateStickyVisibility:function(value) {
  this.fireEvent('stickyvisiblitychange', value);
}, refresh:function(context) {
  var me = this, cells = me.cells, body = me.getBody(), len = cells.length, expandField = me.getExpandedField(), grid = me.getParent(), sm = grid.getSelectable(), selection = sm.getSelection(), isCellSelection = selection.isCells || selection.isColumns, i, visibleIndex, cell, record, recordsExpanded;
  me.refreshContext = context = me.beginRefresh(context);
  record = context.record;
  me.syncDirty(record);
  for (i = 0, visibleIndex = 0; i < len; ++i) {
    cell = cells[i];
    if (!context.summary || !cell.getColumn().getIgnore()) {
      if (cell.getRecord() === record) {
        cell.refresh(context);
      } else {
        cell.refreshContext = context;
        cell.setRecord(record);
        cell.refreshContext = null;
      }
      if (isCellSelection) {
        cell.toggleCls(grid.selectedCls, sm.isCellSelected(me._recordIndex, visibleIndex));
      }
    }
    if (!cell.isHidden()) {
      visibleIndex++;
    }
  }
  context.cell = context.column = context.dataIndex = context.scope = null;
  if (body) {
    body.refreshContext = context;
    if (body.getRecord() === record) {
      body.updateRecord(record);
    } else {
      body.setRecord(record);
    }
    body.refreshContext = null;
    if (expandField) {
      me.setCollapsed(!record.get(expandField));
    } else {
      recordsExpanded = grid.$recordsExpanded || (grid.$recordsExpanded = {});
      if (grid.hasRowExpander) {
        me.setCollapsed(!recordsExpanded[record.internalId]);
      }
    }
  }
  me.refreshContext = null;
}, privates:{refreshContext:null, beginRefresh:function(context) {
  var me = this, grid = me.getParent();
  context = context || {};
  context.from = context.from || 'row';
  context.grid = grid;
  context.record = me.getRecord();
  context.row = me;
  context.store = grid.store;
  return context;
}, createCell:function(column) {
  var cell = column.createCell(this);
  cell = Ext.create(cell);
  delete cell.$initParent;
  if (cell.inheritUi) {
    cell.doInheritUi();
  }
  cell.el.setTabIndex(-1);
  return cell;
}, setCellHidden:function(column, hidden) {
  var cell = this.getCellByColumn(column);
  if (cell) {
    cell.setHidden(hidden);
  }
}, getGrid:function() {
  return this.grid || this.getParent();
}}});
Ext.define('Ext.grid.HeaderContainer', {extend:Ext.Container, xtype:'headercontainer', isHeaderContainer:true, config:{columns:null, defaultColumnUI:null, sortable:true, verticalOverflow:null, reserveScrollbar:null, grid:null}, docked:'top', defaultType:'column', layout:{type:'hbox', align:'stretch'}, inheritUi:true, scrollable:{x:false, y:false}, weighted:true, autoSize:null, constructor:function(config) {
  var me = this, isRoot = !me.isGridColumn;
  me.isRootHeader = isRoot;
  if (isRoot) {
    config.grid._headerContainer = me;
  }
  me.columns = [];
  me.callParent([config]);
  if (isRoot) {
    config.grid._headerContainer = null;
  }
}, initialize:function() {
  var me = this;
  me.callParent();
  if (me.isRootHeader) {
    me.setInstanceCls(Ext.baseCSSPrefix + 'headercontainer');
    me.on({tap:'onHeaderTap', triggertap:'onHeaderTriggerTap', columnresize:'onColumnResize', show:'onColumnShow', hide:'onColumnHide', sort:'onColumnSort', scope:me, delegate:'[isLeafHeader]'});
    me.on({tap:'onGroupTap', triggertap:'onGroupTriggerTap', show:'onGroupShow', hide:'onGroupHide', add:'onColumnAdd', move:'onColumnMove', remove:'onColumnRemove', scope:me, delegate:'[isHeaderGroup]'});
    me.on({add:'onColumnAdd', move:'onColumnMove', remove:'onColumnRemove', scope:me});
  }
}, getRootHeaderCt:function() {
  var grid = this.getGrid();
  return grid && grid.getHeaderContainer();
}, getColumnForField:function(fieldName) {
  var columns = this.columns, n = columns.length, c, i;
  for (i = 0; i < n; ++i) {
    c = columns[i].getColumnForField(fieldName);
    if (c) {
      return c;
    }
  }
  return null;
}, getColumns:function(selector) {
  var result = this.columns;
  if (selector) {
    if (typeof selector === 'string') {
      result = Ext.ComponentQuery.query(selector, result);
    } else {
      if (Ext.isFunction(selector)) {
        return result.filter(selector);
      }
    }
  }
  return result;
}, getVisibleColumns:function() {
  var me = this, result = me.visibleColumns;
  if (!result) {
    result = me.visibleColumns = me.columns.filter(me.visibleLeafFilter);
  }
  return result;
}, getClosestVisibleHeader:function(index) {
  var result = typeof index === 'number' ? this.getVisibleColumns()[index] : index;
  if (result && result.hidden) {
    result = result.next(':visible') || result.prev(':visible');
  }
  return result;
}, indexOfLeaf:function(column) {
  return this.getVisibleColumns().indexOf(column);
}, factoryItem:function(item) {
  var grid = this.getGrid();
  if (item.isComponent) {
    if (item.isGridColumn) {
      item.setGrid(grid);
    }
  } else {
    item = Ext.apply({grid:grid}, item);
  }
  return this.callParent([item]);
}, updateColumns:function(columns) {
  var me = this;
  if (me.isRootHeader) {
    me.columns = [];
    me.visibleColumns = null;
    me.add(columns);
  }
}, beginColumnUpdate:function() {
  var me = this;
  if (!me.isRootHeader) {
    return;
  }
  me.hasBulkUpdate = me.hasBulkUpdate || 0;
  me.hasBulkUpdate++;
  if (me.hasBulkUpdate === 1) {
    me.bulkAdd = [];
    me.updateMenuDisabledState = Ext.emptyFn;
  }
}, endColumnUpdate:function() {
  var me = this, length, i, columns, item;
  if (!me.isRootHeader || !me.hasBulkUpdate) {
    return;
  }
  me.hasBulkUpdate--;
  if (me.hasBulkUpdate === 0) {
    columns = me.bulkAdd;
    length = columns && columns.length;
    if (length) {
      me.visibleColumns = null;
      me.columns = me.getLeaves();
      for (i = 0; i < length; i++) {
        item = columns[i];
        item.columnIndex = me.columns.indexOf(item.column);
      }
      Ext.Array.sort(columns, me.sortByColumnIndex);
      for (i = 0; i < length; i++) {
        item = columns[i];
        me.fireEvent('columnadd', me, item.column, item.columnIndex);
      }
    }
    me.getGrid().refreshInnerWidth();
    me.bulkAdd = null;
    delete me.updateMenuDisabledState;
    me.updateMenuDisabledState();
    if (this.isRootHeader) {
      this.onColumnComputedWidthChange();
    }
  }
}, sortByColumnIndex:function(a, b) {
  return a.columnIndex - b.columnIndex;
}, add:function(items) {
  var ret, rootHeaders = this.getRootHeaderCt();
  if (rootHeaders) {
    rootHeaders.beginColumnUpdate();
  }
  ret = this.callParent([items]);
  if (rootHeaders) {
    rootHeaders.endColumnUpdate();
  }
  return ret;
}, insert:function(index, item) {
  var ret, rootHeaders = this.getRootHeaderCt();
  if (rootHeaders) {
    rootHeaders.beginColumnUpdate();
  }
  ret = this.callParent([index, item]);
  if (rootHeaders) {
    rootHeaders.endColumnUpdate();
  }
  return ret;
}, remove:function(which, destroy) {
  var ret, rootHeaders = this.getRootHeaderCt();
  if (rootHeaders) {
    rootHeaders.beginColumnUpdate();
  }
  ret = this.callParent([which, destroy]);
  if (rootHeaders) {
    rootHeaders.endColumnUpdate();
  }
  return ret;
}, onColumnAdd:function(container, column) {
  var me = this, grid = me.getGrid(), groupColumns, ln, i, ui;
  if (column.isHeaderGroup) {
    groupColumns = column.getItems().items;
    for (i = 0, ln = groupColumns.length; i < ln; i++) {
      me.onColumnAdd(column, groupColumns[i]);
    }
  } else {
    ui = column.getUi();
    if (ui == null) {
      column.setUi(me.getDefaultColumnUI());
    }
    column.setGrid(grid);
    me.bulkAdd.push({column:column});
  }
  me.updateMenuDisabledState();
}, onColumnMove:function(parent, column, toIdx, fromIdx) {
  var me = this, columns = me.columns, group = null, cols;
  me.visibleColumns = null;
  if (column.isHeaderGroup) {
    cols = column.getItems().items;
    group = column;
  } else {
    cols = [column];
  }
  fromIdx = columns.indexOf(cols[0]);
  me.columns = me.getLeaves();
  me.fireEvent('columnmove', me, cols, group, fromIdx);
}, onColumnRemove:function(parent, column) {
  var me = this, columns, i, ln;
  me.visibleColumns = null;
  if (column.isHeaderGroup) {
    if (!column.destroying) {
      columns = column.getItems().items;
      ln = columns.length;
      for (i = 0; i < ln; i++) {
        me.onColumnRemove(column, columns[i]);
      }
    }
  } else {
    Ext.Array.remove(me.columns, column);
    me.fireEvent('columnremove', me, column);
  }
  me.updateMenuDisabledState();
}, onHeaderTap:function(column, e) {
  var selModel = this.getGrid().getSelectable(), ret = this.fireEvent('columntap', this, column, e);
  if (ret !== false) {
    if (selModel.onHeaderTap) {
      selModel.onHeaderTap(this, column, e);
    }
  }
}, onGroupTriggerTap:function(column) {
  column.showMenu();
}, onHeaderTriggerTap:function(column) {
  column.showMenu();
}, onColumnShow:function(column) {
  var me = this;
  me.visibleColumns = null;
  me.fireEvent('columnshow', me, column);
  me.updateMenuDisabledState();
  if (this.isRootHeader) {
    this.onColumnComputedWidthChange();
  }
}, onColumnHide:function(column) {
  var me = this;
  me.visibleColumns = null;
  me.fireEvent('columnhide', me, column);
  me.updateMenuDisabledState();
  if (this.isRootHeader) {
    this.onColumnComputedWidthChange();
  }
}, onGroupShow:function(group) {
  var columns = group.getInnerItems(), ln = columns.length, i, column;
  this.visibleColumns = null;
  for (i = 0; i < ln; i++) {
    column = columns[i];
    if (!column.isHidden()) {
      this.fireEvent('columnshow', this, column);
    }
  }
  this.updateMenuDisabledState();
}, onGroupHide:function(group) {
  var columns = group.getInnerItems(), ln = columns.length, i, column;
  this.visibleColumns = null;
  for (i = 0; i < ln; i++) {
    column = columns[i];
    this.fireEvent('columnhide', this, column);
  }
  this.updateMenuDisabledState();
}, onGroupTap:function(column, e) {
  return this.fireEvent('headergrouptap', this, column, e);
}, onColumnResize:function(column, width, oldWidth) {
  this.fireEvent('columnresize', this, column, width, oldWidth);
}, onColumnSort:function(column, direction, newDirection) {
  if (direction !== null) {
    this.fireEvent('columnsort', this, column, direction, newDirection);
  }
}, scrollTo:function(x) {
  this.getScrollable().scrollTo(x);
}, updateGrid:function(grid) {
  if (this.isRootHeader) {
    this.parent = grid;
  }
}, doDestroy:function() {
  this.setGrid(null);
  this.callParent();
}, afterRender:function() {
  this.callParent();
  if (this.isRootHeader) {
    this.onColumnComputedWidthChange();
  }
}, privates:{columnsResizing:null, updateVerticalOverflow:function() {
  this.syncReserveSpace();
}, updateReserveScrollbar:function() {
  this.syncReserveSpace();
}, updateMenuDisabledState:function() {
  if (this.rendered) {
    var me = this.isRootHeader ? this : this.getRootHeaderCt(), columns = [], menuOfferingColumns = [], len, i, column, columnIsHideable, checkItem;
    me.visitPreOrder('gridcolumn:not([hidden])', function(col) {
      columns.push(col);
      if (!col.isHidden(true) && !col.getMenuDisabled() && col.getConfig('menu', true)) {
        menuOfferingColumns.push(col);
      }
    });
    len = columns.length;
    for (i = 0; i < len; ++i) {
      column = columns[i];
      checkItem = column.getHideShowMenuItem(false);
      if (checkItem) {
        columnIsHideable = menuOfferingColumns.length > 1 || menuOfferingColumns[0] !== column;
        checkItem['set' + (checkItem.getMenu() ? 'CheckChange' : '') + 'Disabled'](!columnIsHideable);
      }
    }
  }
}, getLeaves:function() {
  return this.query('[isLeafHeader]');
}, onColumnComputedWidthChange:function(column, computedWidth) {
  var me = this, totalColumnWidth = 0, changedColumns = me.columnsResizing, columns, len, i, c, width;
  if (me.destroying) {
    return;
  }
  if (changedColumns) {
    changedColumns.push(column);
    return;
  }
  me.columnsResizing = changedColumns = [];
  columns = me.getColumns();
  len = columns.length;
  for (i = 0; i < len; i++) {
    c = columns[i];
    if (c === column) {
      changedColumns.push(c);
      width = computedWidth;
    } else {
      width = c.isHidden(true) ? 0 : c.measureWidth();
    }
    totalColumnWidth += width;
  }
  totalColumnWidth = Math.floor(totalColumnWidth);
  me.getGrid().onColumnComputedWidthChange(changedColumns, totalColumnWidth);
  me.columnsResizing = null;
}, setRendered:function(rendered) {
  this.visibleColumns = null;
  this.callParent([rendered]);
}, setSortState:function() {
  var grid = this.getGrid(), store = grid.getStore(), columns = grid.getColumns(), isGrouped = store.isGrouped(), len = columns && columns.length, sorters = store.getSorters(), grouper = store.getGrouper(), i, header, isGroupedHeader, sorter;
  for (i = 0; i < len; i++) {
    header = columns[i];
    sorter = header.sorter;
    isGroupedHeader = store.getGroupField() === header.getDataIndex();
    if (sorter) {
      if (isGrouped && !isGroupedHeader) {
        sorter = null;
      } else {
        if (isGrouped && isGroupedHeader) {
          sorter = grouper;
        } else {
          if (!(sorters.contains(sorter) || grouper === sorter)) {
            sorter = null;
          }
        }
      }
    }
    header.setSortState(sorter);
  }
}, syncReserveSpace:function() {
  var reserve = this.getVerticalOverflow() || this.getReserveScrollbar(), scrollbarWidth = 0, grid, scroller;
  if (reserve) {
    grid = this.getGrid();
    if (grid) {
      scroller = grid.getScrollable();
      if (scroller) {
        scrollbarWidth = scroller.getScrollbarSize().width + 'px';
      }
    }
  }
  this.el.setStyle('padding-right', scrollbarWidth);
}, visibleLeafFilter:function(c) {
  return c.isLeafHeader && !c.isHidden();
}}});
Ext.define('Ext.menu.CheckItem', {extend:Ext.menu.Item, xtype:'menucheckitem', isMenuCheckItem:true, hideOnClick:false, config:{checked:false, checkHandler:null, checkChangeDisabled:false, value:null, showCheckbox:null}, classCls:Ext.baseCSSPrefix + 'menucheckitem', checkedCls:Ext.baseCSSPrefix + 'checked', checkboxIconElCls:Ext.baseCSSPrefix + 'checkbox-icon-el', ariaRole:'menuitemcheckbox', defaultBindProperty:'checked', submenuText:'{0} submenu', href:null, target:null, element:{reference:'element', 
tabindex:Ext.is.iOS ? -1 : null, cls:Ext.baseCSSPrefix + 'unselectable ' + Ext.baseCSSPrefix + 'has-left-icon'}, focusEl:'checkboxElement', ariaEl:'checkboxElement', getTemplate:function() {
  var template = this.callParent(), body = template[0];
  body.tag = 'div';
  body.href = null;
  body.children.push({tag:'input', type:'checkbox', reference:'checkboxElement', cls:Ext.baseCSSPrefix + 'checkbox-el'});
  return template;
}, initialize:function() {
  var me = this;
  me.callParent();
  me.element.on({mousedown:'onCheckboxMousedown', translate:false, scope:me});
  me.checkboxElement.on({change:'onCheckboxChange', delegated:false, scope:me});
  this.syncCheckboxCls();
}, enableFocusable:function() {
  this.mixins.focusable.enableFocusable();
  this.checkboxElement.dom.readOnly = '';
}, disableFocusable:function() {
  this.mixins.focusable.disableFocusable();
  this.checkboxElement.dom.readOnly = 'readonly';
}, setChecked:function(checked, suppressEvents) {
  var me = this, isConfiguring = me.isConfiguring;
  if (suppressEvents) {
    me.isConfiguring = true;
  }
  me.callParent([checked]);
  if (suppressEvents) {
    me.isConfiguring = isConfiguring;
  }
}, updateChecked:function(checked) {
  this.checkboxElement.dom.checked = checked;
  this.onCheckChange();
}, updateCheckChangeDisabled:function(checkChangeDisabled) {
  this.checkboxElement.dom.readOnly = checkChangeDisabled;
}, updateValue:function(value) {
  this.checkboxElement.dom.value = value;
}, updateText:function(text) {
  var me = this, ariaDom = me.ariaEl.dom;
  me.callParent([text]);
  if (me.getValue() === null) {
    me.setValue(text);
  }
  if (ariaDom && me.getMenu()) {
    ariaDom.setAttribute('aria-label', Ext.String.formatEncode(me.submenuText, text));
  }
}, applyShowCheckbox:function(showCheckbox) {
  return !!showCheckbox;
}, updateShowCheckbox:function(showCheckbox) {
  this.checkboxElement.setDisplayed(showCheckbox);
}, updateIcon:function(icon, oldIcon) {
  this.callParent([icon, oldIcon]);
  if (!this.isConfiguring) {
    this.syncCheckboxCls();
  }
}, updateIconCls:function(iconCls, oldIconCls) {
  this.callParent([iconCls, oldIconCls]);
  if (!this.isConfiguring) {
    this.syncCheckboxCls();
  }
}, updateIconAlign:function(iconAlign, oldIconAlign) {
  this.callParent([iconAlign, oldIconAlign]);
  if (!this.isConfiguring) {
    this.syncCheckboxCls();
  }
}, privates:{onSpace:function(e) {
  if (this.getDisabled()) {
    e.preventDefault();
  }
}, onClick:function(e) {
  var me = this, arrowElement = me.arrowElement, result, parentResult, region;
  if (me.getDisabled()) {
    e.preventDefault();
  }
  if (e.pointerType !== 'mouse') {
    region = me.bodyElement.getRegion();
    if (me.getMenu()) {
      region.setWidth(region.getWidth() - arrowElement.getWidth() - arrowElement.getMargin('lr'));
    }
    if (region.contains(e.getPoint())) {
      result = false;
    } else {
      e.preventDefault();
    }
  }
  parentResult = me.callParent([e]);
  return result === false ? result : parentResult;
}, onCheckboxMousedown:function(e) {
  if (Ext.isApple && !Ext.isChrome || !this.checkboxElement.contains(e.target)) {
    e.preventDefault();
  }
}, onCheckboxChange:function() {
  var me = this, checkboxElement = me.checkboxElement.dom, meChecked = me.getChecked(), isChecked = checkboxElement.checked;
  if (me.getCheckChangeDisabled()) {
    checkboxElement.checked = meChecked;
    return false;
  }
  if (isChecked === meChecked || me.getDisabled()) {
    return;
  }
  if (me.fireEvent('beforecheckchange', me, isChecked) === false) {
    checkboxElement.checked = !isChecked;
  } else {
    me.setChecked(isChecked);
  }
}, onCheckChange:function() {
  var me = this, checked = me.checkboxElement.dom.checked, el = me.el, ariaDom = me.ariaEl.dom;
  el.toggleCls(me.checkedCls, !!checked);
  if (ariaDom) {
    ariaDom.setAttribute('aria-checked', me.getMenu() ? 'mixed' : checked);
  }
  me.publishState('checked', checked);
  if (!me.isConfiguring) {
    Ext.callback(me.getCheckHandler(), me.scope, [me, checked], 0, me);
    me.fireEvent('checkchange', me, checked);
  }
}, syncHasIconCls:function() {
  var me = this;
  me.toggleCls(me.hasRightIconCls, me.hasIcon());
}, syncCheckboxCls:function() {
  var me = this, leftIconElement = me.leftIconElement, rightIconElement = me.rightIconElement, checkboxIconElCls = me.checkboxIconElCls, checkboxIconElement, oldCheckboxIconElement;
  if (me.hasIcon() && me.getIconAlign() === 'left') {
    checkboxIconElement = rightIconElement;
    oldCheckboxIconElement = leftIconElement;
  } else {
    checkboxIconElement = leftIconElement;
    oldCheckboxIconElement = rightIconElement;
  }
  checkboxIconElement.addCls(checkboxIconElCls);
  oldCheckboxIconElement.removeCls(checkboxIconElCls);
}}});
Ext.define('Ext.grid.column.Column', {extend:Ext.grid.HeaderContainer, alternateClassName:'Ext.grid.column.Template', xtype:['gridcolumn', 'column', 'templatecolumn'], isGridColumn:true, mixins:[Ext.mixin.StyleCacher, Ext.mixin.Toolable], config:{align:undefined, cell:{xtype:'gridcell'}, dataIndex:null, locked:null, defaultWidth:100, depends:null, emptyText:{cached:true, $value:' '}, text:' ', sortable:true, groupable:true, resizable:true, hideable:true, renderer:null, formatter:null, scope:null, 
editable:null, editor:null, defaultEditor:{lazy:true, $value:{}}, editorDefaults:{cached:true, $value:{'default':{xtype:'textfield', autoComplete:false, textAlign:undefined}, 'bool,boolean':{xtype:'checkboxfield', bodyAign:undefined}, date:{xtype:'datefield', textAlign:undefined}, 'float,number':{xtype:'numberfield', textAlign:undefined}, 'int,integer':{xtype:'numberfield', decimals:0, textAlign:undefined}}}, ignore:false, ignoreExport:false, exportStyle:null, exportRenderer:false, summary:null, 
summaryCell:null, summaryDataIndex:null, summaryFormatter:null, summaryRenderer:null, summaryType:null, exportSummaryRenderer:false, minWidth:40, tpl:null, computedWidth:null, grouper:{lazy:true, $value:null}, groupHeaderTpl:null, sorter:{lazy:true, $value:true}, scratchCell:{lazy:true, $value:true}, menu:{lazy:true, $value:{}}, menuDisabled:null, hideShowMenuItem:{lazy:true, $value:{xtype:'menucheckitem'}}}, updateLocked:function(v) {
  var me = this, grid = me.getGrid(), region = grid && grid.region, lockedGrid, key, targetRegion;
  if (region) {
    lockedGrid = region.lockedGrid;
    key = lockedGrid.getRegionKey(v);
    targetRegion = lockedGrid.getRegion(key);
    if (targetRegion && targetRegion !== region) {
      lockedGrid.handleChangeRegion(targetRegion, me);
    }
  }
  return v;
}, toolDefaults:{ui:'gridcolumn', zone:'tail'}, toolAnchorName:'titleWrapElement', dockTools:false, scrollable:false, docked:null, sortState:null, ariaSortStates:{ASC:'ascending', DESC:'descending'}, inheritUi:true, classCls:Ext.baseCSSPrefix + 'gridcolumn', sortedCls:Ext.baseCSSPrefix + 'sorted', secondarySortCls:Ext.baseCSSPrefix + 'secondary-sort', auxSortCls:Ext.baseCSSPrefix + 'aux-sort', resizableCls:Ext.baseCSSPrefix + 'resizable', groupCls:Ext.baseCSSPrefix + 'group', leafCls:Ext.baseCSSPrefix + 
'leaf', menuOpenCls:Ext.baseCSSPrefix + 'menu-open', alignCls:{left:Ext.baseCSSPrefix + 'align-left', center:Ext.baseCSSPrefix + 'align-center', right:Ext.baseCSSPrefix + 'align-right'}, constructor:function(config) {
  var me = this, isHeaderGroup, menu;
  if (config.columns || me.columns) {
    isHeaderGroup = me.isHeaderGroup = true;
  } else {
    me.isLeafHeader = true;
  }
  me.callParent([config]);
  me.addCls(isHeaderGroup ? me.groupCls : me.leafCls);
  menu = me.getConfig('menu', true);
  if (!menu && me.getMenuDisabled() === null) {
    me.setMenuDisabled(true);
  }
}, getTemplate:function() {
  var me = this, beforeTitleTemplate = me.beforeTitleTemplate, afterTitleTemplate = me.afterTitleTemplate, titleTpl = [];
  if (beforeTitleTemplate) {
    titleTpl.push.apply(titleTpl, beforeTitleTemplate);
  }
  titleTpl.push({reference:'titleElement', className:Ext.baseCSSPrefix + 'title-el', children:[{reference:'textElement', className:Ext.baseCSSPrefix + 'text-el', 'data-qoverflow':true}, {reference:'sortIconElement', cls:Ext.baseCSSPrefix + 'sort-icon-el ' + Ext.baseCSSPrefix + 'font-icon'}]});
  if (afterTitleTemplate) {
    titleTpl.push.apply(titleTpl, afterTitleTemplate);
  }
  return [{reference:'headerElement', cls:Ext.baseCSSPrefix + 'header-el', children:[{reference:'titleWrapElement', cls:Ext.baseCSSPrefix + 'title-wrap-el', uiCls:'title-wrap-el', children:titleTpl}, {reference:'resizerElement', cls:Ext.baseCSSPrefix + 'resizer-el ' + Ext.baseCSSPrefix + 'item-no-tap'}, {reference:'triggerElement', cls:Ext.baseCSSPrefix + 'trigger-el ' + Ext.baseCSSPrefix + 'font-icon ' + Ext.baseCSSPrefix + 'item-no-tap'}]}, {reference:'bodyElement', cls:Ext.baseCSSPrefix + 'body-el', 
  uiCls:'body-el'}];
}, initialize:function() {
  var me = this;
  if (me.isLeafHeader && !me.getWidth() && me.getFlex() == null) {
    me.setWidth(me.getDefaultWidth());
  }
  me.callParent();
  me.element.on({tap:'onColumnTap', longpress:'onColumnLongPress', scope:this});
  me.triggerElement.on({tap:'onTriggerTap', scope:this});
  me.resizerElement.on({tap:'onResizerTap', doubletap:'onResizerDoubleTap', scope:this});
  if (me.isHeaderGroup) {
    me.on({add:'doVisibilityCheck', remove:'doVisibilityCheck', show:'onColumnShow', hide:'onColumnHide', move:'onColumnMove', delegate:'\x3e column', scope:me});
    me.on({show:'onShow', scope:me});
  }
}, doDestroy:function() {
  var me = this;
  me.destroyMembers('editor', 'resizeListener', 'menu', 'hideShowMenuItem', 'childColumnsMenu');
  me.setScratchCell(null);
  me.mixins.toolable.doDestroy.call(me);
  me.callParent();
}, onAdded:function(parent, instanced) {
  this.visibleIndex = null;
  this.callParent([parent, instanced]);
}, ensureEditor:function() {
  var me = this, editable = me.getEditable(), editor = editable !== false && me.getEditor(), cfg;
  if (!editor && editable) {
    cfg = me.getDefaultEditor();
    editor = Ext.create(cfg);
    me.setEditor(editor);
  }
  return editor;
}, getVisibleIndex:function() {
  var visibleIndex = this.visibleIndex, rootHeaders;
  if (visibleIndex == null) {
    if (this.isHeaderGroup) {
      visibleIndex = false;
    } else {
      rootHeaders = this.getRootHeaderCt();
      if (rootHeaders) {
        visibleIndex = rootHeaders.indexOfLeaf(this);
      }
    }
    this.visibleIndex = visibleIndex;
  }
  return visibleIndex;
}, _columnScopeRe:/^column\./, _gridScopeRe:/^grid\./, applyMenu:function(menu) {
  var me = this, grid = me.getGrid(), columnScopeRe = me._columnScopeRe, gridScopeRe = me._gridScopeRe, extraItems, gridColumnMenu, i, item, items, s;
  Ext.destroy(me.sortChangeListener);
  if (menu && !menu.isMenu) {
    if (Ext.isArray(menu)) {
      extraItems = menu;
      menu = null;
    } else {
      if (!menu.items) {
        menu = {items:menu};
      }
    }
    if (!(gridColumnMenu = grid.getColumnMenu())) {
      menu = menu ? Ext.clone(menu) : {};
    } else {
      gridColumnMenu = Ext.clone(gridColumnMenu);
      menu = menu ? Ext.merge(gridColumnMenu, menu) : gridColumnMenu;
    }
    menu.ownerCmp = me;
    menu = Ext.create(menu);
    me.sortChangeListener = menu.on({groupchange:'onColumnMenuGroupChange', scope:me});
    items = menu.getItems().items;
    for (i = items && items.length; i-- > 0;) {
      item = items[i];
      if (columnScopeRe.test(s = item.getHandler() || '')) {
        item.setHandler(s.substr(7));
        item.scope = me;
      } else {
        if (gridScopeRe.test(s)) {
          item.setHandler(s.substr(5));
          item.scope = grid;
        } else {
          if (item.isMenuCheckItem) {
            if (columnScopeRe.test(s = item.getCheckHandler() || '')) {
              item.setCheckHandler(s.substr(7));
              item.scope = me;
            } else {
              if (gridScopeRe.test(s)) {
                item.setCheckHandler(s.substr(5));
                item.scope = grid;
              }
            }
          }
        }
      }
    }
    if (extraItems) {
      menu.add(extraItems);
    }
    grid.fireEvent('columnmenucreated', grid, me, menu);
  }
  return menu;
}, updateMenu:function(menu, oldMenu) {
  if (oldMenu) {
    oldMenu.destroy();
  }
}, beforeShowMenu:function(menu) {
  var me = this, store = me.getGrid().getStore(), isGrouped = store && !!store.getGrouper(), groupByThis = menu.getComponent('groupByThis'), showInGroups = menu.getComponent('showInGroups'), sortAsc = menu.getComponent('sortAsc'), sortDesc = menu.getComponent('sortDesc');
  sortAsc.setDisabled(!store);
  sortDesc.setDisabled(!store);
  if (!store) {
    groupByThis.setHidden(true);
    showInGroups.setHidden(true);
    return;
  }
  menu.suspendEvent('groupchange');
  if (sortAsc) {
    me.syncMenuItemState(sortAsc);
  }
  if (sortDesc) {
    me.syncMenuItemState(sortDesc);
  }
  if (groupByThis) {
    groupByThis.setHidden(!(me.canGroup() && !store.isTreeStore));
  }
  menu.resumeEvent('groupchange');
  if (showInGroups) {
    showInGroups.setHidden(store.isTreeStore);
    showInGroups.setChecked(isGrouped);
    showInGroups.setDisabled(!isGrouped);
  }
}, showMenu:function() {
  var me = this, menu = !me.getMenuDisabled() && me.getMenu(), menuOpenCls = me.menuOpenCls, grid;
  if (menu) {
    grid = me.getGrid();
    if (me.beforeShowMenu(menu) !== false && grid.beforeShowColumnMenu(me, menu) !== false) {
      menu.showBy(me.triggerElement);
      me.addCls(menuOpenCls);
      menu.on({single:true, hide:function() {
        if (!(me.destroyed || me.destroying)) {
          me.removeCls(menuOpenCls);
        }
        if (!(grid.destroyed || grid.destroying)) {
          grid.onColumnMenuHide(me, menu);
        }
      }});
    }
  }
}, getCells:function() {
  var cells = [], rows = this.getGrid().items.items, len = rows.length, i, row;
  for (i = 0; i < len; ++i) {
    row = rows[i];
    if (row.isGridRow) {
      cells.push(row.getCellByColumn(this));
    }
  }
  return cells;
}, getColumnForField:function(fieldName) {
  if (fieldName === this.getDataIndex()) {
    return this;
  }
  return this.callParent([fieldName]);
}, isHideable:function() {
  var menuOfferingColumns = [];
  this.getRootHeaderCt().visitPreOrder('gridcolumn:not([hidden])', function(col) {
    if (!col.getMenuDisabled() && col.getConfig('menu', true)) {
      menuOfferingColumns.push(col);
    }
  });
  return menuOfferingColumns.length > 1 || menuOfferingColumns[0] !== this;
}, applyTpl:function(tpl) {
  return Ext.XTemplate.get(tpl);
}, applyAlign:function(align, oldAlign) {
  if (align == null) {
    align = this.isHeaderGroup ? 'center' : 'left';
  }
  return align;
}, updateAlign:function(align, oldAlign) {
  var me = this, alignCls = me.alignCls;
  if (oldAlign) {
    me.removeCls(alignCls[oldAlign]);
  }
  if (align) {
    if (!alignCls[align]) {
      Ext.raise("Invalid value for align: '" + align + "'");
    }
    me.addCls(alignCls[align]);
  }
  me.syncToolableAlign();
}, updateMenuDisabled:function(menuDisabled) {
  if (this.triggerElement) {
    this.triggerElement.setVisible(!menuDisabled);
  }
}, onColumnTap:function(e) {
  var me = this, grid = me.getGrid(), selModel = grid.getSelectable(), store = grid.getStore(), sorters = store && store.getSorters(true), sorter = store && me.pickSorter(), sorterIndex = sorter ? sorters.indexOf(sorter) : -1, isSorted = sorter && (sorterIndex !== -1 || sorter === store.getGrouper());
  if (Ext.Component.from(e) !== me || e.getTarget('.' + Ext.baseCSSPrefix + 'item-no-tap', me)) {
    return;
  }
  if (store && me.isSortable() && (!selModel || !selModel.getColumns())) {
    if (sorter.isGrouper) {
      sorter.toggle();
      store.group(sorter);
    } else {
      if (sorterIndex === 0) {
        me.toggleSortState();
      } else {
        if (isSorted) {
          store.sort(sorter, 'prepend');
        } else {
          me.sort('ASC');
        }
      }
    }
  }
  return me.fireEvent('tap', me, e);
}, onTriggerTap:function(e) {
  this.fireEvent('triggertap', this, e);
}, onResizerTap:function(e) {
  if (e.getPoint().isContainedBy(this.triggerElement.getRegion())) {
    this.fireEvent('triggertap', this, e);
  }
}, onResizerDoubleTap:function(e) {
  e.claimGesture();
  Ext.asap(this.autoSize, this);
}, onColumnLongPress:function(e) {
  this.fireEvent('longpress', this, e);
}, onGroupByThis:function() {
  var me = this, grid = me.getGrid(), grouper = me.getGrouper(), store = grid.getStore(), dataIndex;
  if (!grouper) {
    dataIndex = me.getDataIndex();
    if (dataIndex != null) {
      me.setGrouper({property:dataIndex});
      grouper = me.getGrouper();
    }
  }
  if (store && store.isVirtualStore && grouper) {
    Ext.Logger.warn('Virtual store does not suppport grouping');
    return;
  }
  if (grouper) {
    store.setGrouper(grouper);
  }
}, onColumnMenuGroupChange:function(menu, groupName, value) {
  if (groupName === 'sortDir') {
    this.setSortDirection(value);
  }
}, getSortDirection:function() {
  var sorter = this.pickSorter();
  return sorter && sorter.getDirection();
}, setSortDirection:function(direction) {
  var me = this, grid = me.getGrid(), store = grid.getStore(), sorter = me.pickSorter(), sorters = store.getSorters(true), isSorted = sorter && (sorters.contains(sorter) || sorter.isGrouper);
  if (direction) {
    if (isSorted) {
      if (sorter.getDirection() !== direction) {
        sorter.setDirection(direction);
        if (sorter.isGrouper) {
          store.group(sorter);
        } else {
          sorters.beginUpdate();
          sorters.endUpdate();
        }
      }
    } else {
      return me.sort(direction);
    }
  } else {
    if (sorter) {
      sorters.remove(sorter);
    }
  }
  if (!store.getRemoteSort()) {
    me.getRootHeaderCt().setSortState();
  }
}, syncMenuItemState:function(menuItem) {
  if (menuItem) {
    var me = this, sortable = me.isSortable(), store = me.getGrid().getStore(), sorter = me.pickSorter(), isSorted = sorter && (store.getSorters().contains(sorter) || sorter.isGrouper);
    menuItem.setDisabled(!sortable);
    menuItem.setChecked(sortable && isSorted && sorter.getDirection() === menuItem.getValue());
  }
}, onToggleShowInGroups:function() {
  var grid = this.getGrid(), store = grid.getStore();
  store.setGrouper(null);
}, updateResizable:function() {
  var me = this, widthed = me.getWidth() != null, flexed = me.getFlex() != null;
  me.toggleCls(me.resizableCls, !!(me.getResizable() && (widthed || flexed || me.isLeafHeader)));
}, updateText:function(text) {
  this.setHtml(text || ' ');
}, onResize:function() {
  if (!this.isHidden(true)) {
    this.updateResizable(this.getResizable());
    this.measureWidth();
    this.syncRowHeight();
  }
}, syncRowHeight:function() {
  var grids = this.getGrid().allPartners || [this.getGrid()], i, len = grids.length, grid;
  for (i = 0; i < len; ++i) {
    grid = grids[i];
    grid.syncRowsToHeight(true);
  }
}, getComputedWidth:function() {
  return this.isVisible(true) ? this._computedWidth : 0;
}, updateColumns:function(columns) {
  this.getItems();
  this.add(columns);
}, measureWidth:function() {
  var width = this.el.measure('w');
  this.setComputedWidth(width);
  return width;
}, updateComputedWidth:function(value, oldValue) {
  var me = this, rootHeaderCt = !me.isConfiguring && me.getRootHeaderCt();
  if (rootHeaderCt) {
    rootHeaderCt.onColumnComputedWidthChange(me, value);
    me.fireEvent('columnresize', me, value, oldValue);
  }
}, updateDataIndex:function(dataIndex) {
  var sorter;
  if (!this.isConfiguring) {
    sorter = this.pickSorter();
    if (sorter) {
      this.setSorter(null);
    }
  }
}, applyGroupHeaderTpl:function(tpl) {
  return Ext.XTemplate.get(tpl);
}, updateGroupHeaderTpl:function(tpl) {
  var grouper = this.grouper;
  if (grouper) {
    grouper.headerTpl = tpl;
  }
}, isSortable:function() {
  var me = this;
  return me.isLeafHeader && me.getSortable() && (me.pickSorter() || me.getDataIndex()) && me.getRootHeaderCt().getSortable() && me.getGrid().sortableColumns !== false;
}, applyEditor:function(value) {
  if (value && !value.isInstance) {
    if (typeof value === 'string') {
      value = {xtype:value};
    }
    if (!value.xtype) {
      value = Ext.apply({xtype:value.field ? 'celleditor' : 'textfield'}, value);
    }
    return Ext.create(value);
  }
  return value;
}, applyEditorDefaults:function(defaults) {
  var ret = {}, i, key, keys;
  if (defaults) {
    for (key in defaults) {
      keys = key.split(',');
      for (i = 0; i < keys.length; ++i) {
        ret[keys[i]] = defaults[key];
      }
    }
  }
  return ret;
}, applyDefaultEditor:function(editor) {
  var me = this, dataIndex = me.getDataIndex(), bodyAlign = 'bodyAlign', textAlign = 'textAlign', defaults, model, field, undef;
  if (dataIndex) {
    model = me.getGrid().store.getModel();
    field = model.getField(dataIndex);
    if (!editor.isInstance) {
      editor = Ext.clone(editor);
      if (!editor.xtype) {
        defaults = me.getEditorDefaults();
        defaults = Ext.clone(field && defaults[field.type] || defaults['default']);
        if (textAlign in defaults && defaults[textAlign] === undef) {
          defaults[textAlign] = me.getAlign();
        } else {
          if (bodyAlign in defaults && defaults[bodyAlign] === undef) {
            defaults[bodyAlign] = me.getAlign();
          }
        }
        Ext.applyIf(editor, defaults);
      }
    }
    editor._validationField = field;
  }
  return editor;
}, updateEditor:function(editor, oldEditor) {
  if (oldEditor && (!editor || editor.isCellEditor && editor.getField() !== oldEditor)) {
    oldEditor.destroy();
  }
  if (editor) {
    editor.$column = this;
  }
}, applyFormatter:function(format) {
  var me = this, fmt = format, parser;
  if (fmt) {
    parser = Ext.app.bind.Parser.fly(fmt);
    fmt = parser.compileFormat();
    parser.release();
    return function(v) {
      return fmt(v, me.getScope() || me.resolveListenerScope());
    };
  }
  return fmt;
}, applySummaryFormatter:function(format) {
  var me = this, fmt = format, parser;
  if (fmt) {
    parser = Ext.app.bind.Parser.fly(fmt);
    fmt = parser.compileFormat();
    parser.release();
    return function(v) {
      return fmt(v, me.getScope() || me.resolveListenerScope());
    };
  }
  return fmt;
}, applyGrouper:function(grouper) {
  var me = this, cfg = grouper;
  if (cfg && !cfg.isInstance) {
    if (typeof cfg === 'string') {
      cfg = {groupFn:cfg};
    } else {
      cfg = Ext.apply({}, cfg);
    }
    if (typeof cfg.groupFn === 'string') {
      cfg = me.scopeReplacer(cfg, grouper, 'groupFn', 'setGroupFn');
    }
    if (typeof cfg.sorterFn === 'string') {
      cfg = me.scopeReplacer(cfg, grouper, 'sorterFn', 'setSorterFn');
    }
    grouper = new Ext.util.Grouper(cfg);
  }
  if (grouper) {
    grouper.owner = me.getGrid();
    grouper.headerTpl = me.getGroupHeaderTpl();
  }
  return grouper;
}, updateGrouper:function(grouper, oldGrouper) {
  var store = this.getGrid().getStore();
  if (store && oldGrouper) {
    if (oldGrouper === store.getGrouper()) {
      store.setGrouper(grouper);
    }
  }
  this.grouper = grouper;
}, applySorter:function(sorter) {
  var me = this, cfg = sorter, sortProperty;
  if (cfg && !cfg.isInstance) {
    if (cfg === true) {
      sortProperty = me.getSortParam();
      if (!sortProperty) {
        return null;
      }
      cfg = {property:sortProperty, direction:'ASC'};
    } else {
      if (typeof cfg === 'string') {
        cfg = {sorterFn:cfg};
      }
      if (typeof cfg.sorterFn === 'string') {
        cfg = me.scopeReplacer(cfg, sorter, 'sorterFn', 'setSorterFn');
      }
    }
    sorter = new Ext.util.Sorter(cfg);
  }
  if (sorter) {
    sorter.owner = me.getGrid();
  }
  return sorter;
}, updateSorter:function(sorter, oldSorter) {
  var store = this.getGrid().getStore(), sorters = store ? store.getSorters() : null, at;
  if (sorters) {
    if (oldSorter && (at = sorters.indexOf(oldSorter)) > -1) {
      if (sorter) {
        sorters.splice(at, 1, sorter);
      } else {
        sorters.remove(oldSorter);
      }
    }
  }
  this.sorter = sorter;
}, pickSorter:function() {
  var me = this, store = me.getGrid().getStore(), result;
  if (store.isGrouped() && store.getGroupField() === me.getDataIndex()) {
    result = me.getGrouper() || store.getGrouper();
    me.sortState = result.getDirection();
  } else {
    result = me.getSorter();
  }
  return result;
}, applyHideShowMenuItem:function(config, existing) {
  return Ext.updateWidget(existing, config, this, 'createHideShowMenuItem');
}, createHideShowMenuItem:function(defaults) {
  return Ext.apply({text:this.getText(), checked:!this.getHidden(), column:this}, defaults);
}, getHideShowMenuItem:function(deep) {
  var me = this, result = me.callParent(), items = me.items.items, len = items.length, childItems = [], childColumnsMenu = me.childColumnsMenu, i;
  if (me.isHeaderGroup && deep !== false) {
    if (!childColumnsMenu) {
      result.setMenu({});
      me.childColumnsMenu = childColumnsMenu = result.getMenu();
    }
    if (!childColumnsMenu.items.length || me.rebuildChildColumnsMenu) {
      for (i = 0; i < len; i++) {
        if (items[i].getHideable()) {
          childItems.push(items[i].getHideShowMenuItem());
        }
      }
      childColumnsMenu.removeAll(false);
      childColumnsMenu.add(childItems);
    }
  }
  result['set' + (result.getMenu() ? 'CheckChange' : '') + 'Disabled'](!me.isHideable());
  return result;
}, getInnerHtmlElement:function() {
  return this.textElement;
}, getSortParam:function() {
  return this.getDataIndex();
}, applyCell:function(cell, oldCell) {
  if (oldCell) {
    cell = Ext.apply(oldCell, cell);
  }
  return cell;
}, createCell:function(row) {
  var me = this, cfg = {row:row, ownerCmp:row || me, column:me, width:me.rendered ? me.getComputedWidth() || me.measureWidth() : me.getWidth(), minWidth:me.getMinWidth()}, align = me.getAlign(), cellCfg;
  if (row && row.isSummaryRow) {
    cellCfg = me.getSummaryCell();
    if (!cellCfg) {
      cellCfg = me.getCell();
      if (cellCfg.xtype === 'widgetcell') {
        cellCfg = Ext.apply({}, cellCfg);
        cellCfg.xtype = 'gridcell';
        delete cellCfg.widget;
      }
    }
  } else {
    cellCfg = me.getCell();
  }
  if (align) {
    cfg.align = align;
  }
  if (row) {
    cfg.hidden = me.isHidden(row.getGrid().getHeaderContainer());
    cfg.record = row.getRecord();
    if (!(cfg.ui = row.getDefaultCellUI())) {
      delete cfg.ui;
    }
  }
  if (typeof cellCfg === 'string') {
    cfg.xtype = cellCfg;
  } else {
    Ext.apply(cfg, cellCfg);
  }
  return cfg;
}, applyScratchCell:function(cell, oldCell) {
  var me = this;
  if (cell) {
    cell = Ext.create(me.createCell());
    if (!cell.printValue) {
      Ext.destroy(cell);
      cell = me.createCell();
      cell.xtype = 'gridcell';
      cell = Ext.create(cell);
    }
    cell.addCls(me.floatingCls);
  }
  if (oldCell) {
    oldCell.destroy();
  }
  return cell;
}, printValue:function(value) {
  var me = this, row = me.getGrid().dataItems[0], cell;
  if (row && row.isGridRow) {
    cell = row.getCellByColumn(me);
  }
  cell = cell && cell.printValue ? cell : me.getScratchCell();
  return cell.printValue(value);
}, autoSize:function() {
  var me = this, max = Math.max, textMatrics = new Ext.util.TextMetrics, widthAdjust = 0, maxWidth = 0, innerCells = me.getCells(), grid = me.getGrid(), columnIndex, textWidth, rec, store, len, i, records, idx, paddedWidth, cellElement;
  if (!me.getResizable()) {
    return;
  }
  store = grid.getStore();
  columnIndex = me.getDataIndex();
  if (store && columnIndex) {
    if (store.isVirtualStore) {
      records = store.pageMap.pages;
    } else {
      records = store.getData() && store.getData().items;
    }
    if (columnIndex && Ext.isArray(records)) {
      len = records.length;
      for (i = 0; i < len; i++) {
        textWidth = textMatrics.getWidth(records[i].get(columnIndex));
        maxWidth = max(maxWidth, textWidth);
      }
    } else {
      if (Ext.isObject(records)) {
        for (idx in records) {
          rec = records[idx].records;
          len = rec && rec.length;
          for (i = 0; i < len; i++) {
            textWidth = textMatrics.getWidth(rec[i].get(columnIndex));
            maxWidth = max(maxWidth, textWidth);
          }
        }
      }
    }
  }
  paddedWidth = me.textElement.dom.offsetWidth + me.titleElement.getPadding('lr');
  maxWidth = max(maxWidth, paddedWidth);
  if (innerCells.length) {
    len = innerCells.length;
    cellElement = innerCells[0].element;
    for (i = 0; i < len; i++) {
      maxWidth = max(maxWidth, innerCells[i].element.getTextWidth());
    }
    if (Ext.supports.ScrollWidthInlinePaddingBug) {
      widthAdjust += cellElement.getPadding('r');
    }
    if (grid.getColumnLines()) {
      widthAdjust += cellElement.getBorderWidth('lr');
    }
    maxWidth += widthAdjust;
  }
  maxWidth = max(maxWidth + 1, me.getMinWidth());
  me.setWidth(maxWidth);
  textMatrics.destroy();
}, privates:{directionSequence:{'null':'ASC', 'ASC':'DESC', 'DESC':null}, applySummary:function(summary) {
  if (summary) {
    summary = Ext.Factory.dataSummary(summary);
  }
  return summary;
}, beginRefresh:function(context) {
  var me = this, grid = me.getGrid();
  context = context || {};
  context.column = me;
  context.grid = grid;
  context.store = grid.store;
  return context;
}, canGroup:function() {
  return this.getGroupable() && (this.getDataIndex() || this.getGrouper());
}, sort:function(direction, mode) {
  var me = this, sorter = me.pickSorter(), grid = me.getGrid(), store = grid.getStore(), sorters = store.getSorters();
  if (!me.isSortable()) {
    return;
  }
  if (sorter.isGrouper) {
    if (sorter.getDirection() !== direction) {
      sorter.toggle();
      store.group(sorter);
    }
  } else {
    if (direction) {
      if (sorter) {
        if (sorters.indexOf(sorter) !== 0) {
          sorter.setDirection(direction);
        }
      } else {
        me.setSorter({property:me.getSortParam(), direction:'ASC'});
        sorter = me.getSorter();
      }
      store.sort(sorter, mode || grid.getMultiColumnSort() ? 'multi' : 'replace');
    } else {
      if (sorter) {
        sorters.remove(sorter);
        if (!store.getRemoteSort()) {
          me.getRootHeaderCt().setSortState();
        }
      }
    }
  }
}, toggleSortState:function() {
  this.sort(this.directionSequence[this.sortState]);
}, setSortState:function(sorter) {
  var me = this, store = me.getGrid().getStore(), grouper = store.isGrouped() && store.getGrouper(), oldDirection = me.sortState, direction = null, sortedCls = me.sortedCls, secondarySortCls = me.secondarySortCls, auxSortCls = me.auxSortCls, ascCls = sortedCls + '-asc', descCls = sortedCls + '-desc', ariaDom = me.ariaEl.dom, sortPrioClass = '', changed, index, remove = [secondarySortCls, auxSortCls], add;
  if (sorter) {
    if (typeof sorter === 'string') {
      direction = sorter;
    } else {
      if (!sorter.isSorter) {
        Ext.raise('Must pass a sorter instance into HeaderContainer#saveState');
      }
      if (sorter === grouper) {
        index = 0;
      } else {
        index = store.getSorters().indexOf(sorter);
      }
      if (index === -1) {
        Ext.raise("Sorter passed to HeaderContainer#saveState not in grid's store");
      }
      direction = sorter.getDirection();
      sortPrioClass = index === 1 ? secondarySortCls : index > 1 ? auxSortCls : '';
    }
  }
  changed = direction !== oldDirection;
  me.sortState = direction;
  switch(direction) {
    case 'DESC':
      add = [sortedCls, descCls, sortPrioClass];
      remove.push(ascCls);
      break;
    case 'ASC':
      add = [sortedCls, ascCls, sortPrioClass];
      remove.push(descCls);
      break;
    default:
      remove.push(sortedCls, ascCls, descCls);
      break;
  }
  me.replaceCls(remove, add);
  if (ariaDom) {
    if (direction) {
      ariaDom.setAttribute('aria-sort', me.ariaSortStates[direction]);
    } else {
      ariaDom.removeAttribute('aria-sort');
    }
  }
  if (changed) {
    me.fireEvent('sort', me, direction, oldDirection);
  }
}, getVisibleCount:function() {
  var columns = this.getInnerItems(), len = columns.length, count = 0, i;
  for (i = 0; i < len; ++i) {
    if (columns[i].isHeaderGroup) {
      count += columns[i].getVisibleCount();
    } else {
      count += columns[i].isHidden() ? 0 : 1;
    }
  }
  return count;
}, onShow:function() {
  var toShow;
  if (!this.getVisibleCount()) {
    toShow = this.getComponent(0);
    if (toShow) {
      toShow.show();
    }
  }
}, doVisibilityCheck:function() {
  var me = this, columns = me.getInnerItems(), ln = columns.length, i, column;
  for (i = 0; i < ln; i++) {
    column = columns[i];
    if (!column.isHidden()) {
      if (me.isHidden()) {
        if (me.initialized) {
          me.show();
        } else {
          me.setHidden(false);
        }
      }
      return;
    }
  }
  me.hide();
  me.rebuildChildColumnsMenu = true;
  me.updateMenuDisabledState();
}, onColumnShow:function() {
  var me = this, hideShowItem;
  if (me.getVisibleCount() > 0) {
    me.show();
    hideShowItem = me.getHideShowMenuItem(false);
    hideShowItem.setChecked(true);
    hideShowItem.setCheckChangeDisabled(false);
  }
  me.rebuildChildColumnsMenu = true;
  me.updateMenuDisabledState();
}, onColumnHide:function(column) {
  var me = this, hideShowItem;
  if (me.getVisibleCount() === 0) {
    me.hide();
    hideShowItem = me.getHideShowMenuItem(false);
    hideShowItem.setChecked(false);
    hideShowItem.setCheckChangeDisabled(true);
  }
  me.rebuildChildColumnsMenu = true;
  me.updateMenuDisabledState();
}, onColumnMove:function(column) {
  this.rebuildChildColumnsMenu = true;
}, scopeReplacer:function(config, original, prop, setter) {
  var me = this, name = config[prop];
  if (typeof name === 'string') {
    prop = prop || 'sorterFn';
    setter = setter || 'setSorterFn';
    if (original === config) {
      config = Ext.apply({}, config);
    }
    config[prop] = function() {
      var scope = me.resolveListenerScope(), fn = scope && scope[name], ret = 0;
      if (fn) {
        this[setter](fn.bind(scope));
        ret = fn.apply(scope, arguments);
      } else {
        if (!scope) {
          Ext.raise('Cannot resolve scope for column ' + me.id);
        } else {
          Ext.raise('No such method "' + name + '" on ' + scope.$className);
        }
      }
      return ret;
    };
  }
  return config;
}}});
Ext.define('Ext.grid.cell.Date', {extend:Ext.grid.cell.Text, xtype:'datecell', isDateCell:true, config:{format:''}, updateColumn:function(column, oldColumn) {
  var format;
  this.callParent([column, oldColumn]);
  if (column && column.isDateColumn) {
    format = column.getFormat();
    if (format !== null) {
      this.setFormat(format);
    }
  }
}, applyFormat:function(format) {
  return format || Ext.Date.defaultFormat;
}, updateFormat:function(format) {
  if (!this.isConfiguring) {
    this.writeValue();
  }
}, formatValue:function(value) {
  return value ? Ext.Date.format(value, this.getFormat()) : '';
}});
Ext.define('Ext.grid.column.Date', {extend:Ext.grid.column.Column, xtype:'datecolumn', isDateColumn:true, config:{format:null, defaultEditor:{xtype:'datepickerfield'}, cell:{xtype:'datecell'}}});
Ext.define('Ext.grid.menu.Shared', {extend:Ext.menu.Item, config:{grid:null}, doDestroy:function() {
  this.setGrid(null);
  this.callParent();
}, updateGrid:function(grid, oldGrid) {
  var me = this;
  if (oldGrid) {
    oldGrid.removeSharedMenuItem(me);
  }
  me.grid = grid;
  if (grid) {
    grid.addSharedMenuItem(me);
  }
}, onBeforeShowColumnMenu:function(menu) {
  menu.add(this);
}, onColumnMenuHide:function(menu) {
  if (!this.destroyed) {
    menu.remove(this, false);
  }
}});
Ext.define('Ext.grid.menu.Columns', {extend:Ext.grid.menu.Shared, xtype:'gridcolumnsmenu', iconCls:Ext.baseCSSPrefix + 'headermenu-columns-icon', text:'Columns', menu:{}, updateMenu:function(menu, oldMenu) {
  var me = this;
  me.callParent([menu, oldMenu]);
  Ext.destroy(me.menuListeners);
  if (menu) {
    me.menuListeners = menu.on({checkchange:'onCheckItem', delegate:'menucheckitem', scope:me, destroyable:true});
  }
}, onBeforeShowColumnMenu:function(menu, column, grid) {
  var columns = grid.getHeaderContainer().items.items, items = [], len = columns.length, subMenu = this.getMenu(), i, col;
  this.callParent([menu, column, grid]);
  for (i = 0; i < len; ++i) {
    col = columns[i];
    if (col.getHideable()) {
      items.push(col.getHideShowMenuItem());
    }
  }
  subMenu.removeAll(false);
  subMenu.add(items);
}, onCheckItem:function(menuItem, checked) {
  menuItem.column.setHidden(!checked);
}});
Ext.define('Ext.grid.menu.GroupByThis', {extend:Ext.menu.Item, xtype:'gridgroupbythismenuitem', iconCls:Ext.baseCSSPrefix + 'headermenu-group-by-this', text:'Group by this field'});
Ext.define('Ext.grid.menu.ShowInGroups', {extend:Ext.menu.CheckItem, xtype:'gridshowingroupsmenuitem', hideOnClick:true, text:'Show in groups'});
Ext.define('Ext.menu.RadioItem', {extend:Ext.menu.CheckItem, xtype:'menuradioitem', classCls:Ext.baseCSSPrefix + 'menuradioitem', nameable:true, shareableName:true, ariaRole:'menuitemradio', config:{group:null, allowUncheck:null}, initialize:function() {
  if (!this.getGroup()) {
    Ext.raise('Menu RadioItems must be configured with a group');
  }
  this.callParent();
}, privates:{onSpace:function(e) {
  if (this.checkboxElement.dom.checked) {
    e.preventDefault();
  }
}, updateGroup:function(group) {
  this.name = group;
}, onCheckboxChange:function() {
  var checkboxElement = this.checkboxElement.dom, isChecked = checkboxElement.checked;
  if (isChecked === this.getChecked() || this.getDisabled()) {
    return;
  }
  if (!isChecked && !this.getAllowUncheck()) {
    checkboxElement.checked = true;
  } else {
    this.callParent();
  }
}, onCheckChange:function() {
  var me = this, checkboxElement = me.checkboxElement.dom, parentMenu = me.getParent(), name, groups, siblings, len, i;
  me.getGroup();
  name = me.name;
  if (name && parentMenu && !parentMenu.updatingGroups) {
    groups = {};
    if (checkboxElement.checked) {
      groups[name] = me.getValue();
      parentMenu.setGroups(groups);
    } else {
      siblings = parentMenu.lookupName(name);
      len = siblings && siblings.length;
      for (i = 0; i < len && !siblings[i].checkboxElement.dom.checked; i++) {
      }
      if (i === len) {
        groups[name] = null;
        parentMenu.setGroups(groups);
      }
    }
  }
  me.callParent();
}}});
Ext.define('Ext.grid.menu.SortAsc', {extend:Ext.menu.RadioItem, xtype:'gridsortascmenuitem', iconCls:Ext.baseCSSPrefix + 'headermenu-sort-asc', text:'Sort Ascending', value:'ASC', allowUncheck:true, group:'grid-sorters'});
Ext.define('Ext.grid.menu.SortDesc', {extend:Ext.menu.RadioItem, xtype:'gridsortdescmenuitem', iconCls:Ext.baseCSSPrefix + 'headermenu-sort-desc', text:'Sort Descending', value:'DESC', allowUncheck:true, group:'grid-sorters'});
Ext.define('Ext.grid.selection.Cells', {extend:Ext.dataview.selection.Selection, alias:'selection.cells', isCells:true, clone:function() {
  var me = this, result = new me.self(me.view);
  if (me.startCell) {
    result.startCell = me.startCell.clone();
    result.endCell = me.endCell.clone();
  }
  return result;
}, isSelected:function(recordIndex, columnIndex) {
  var range;
  if (this.startCell) {
    if (recordIndex.isGridLocation) {
      columnIndex = recordIndex.columnIndex;
      recordIndex = recordIndex.recordIndex;
    }
    if (!(Ext.isNumber(recordIndex) && Ext.isNumber(columnIndex))) {
      Ext.raise('Cells#isSelected must be passed either a GridLocation of ' + 'a row and column index');
    }
    range = this.getRowRange();
    if (recordIndex >= range[0] && recordIndex <= range[1]) {
      range = this.getColumnRange();
      return columnIndex >= range[0] && columnIndex <= range[1];
    }
  }
  return false;
}, eachRow:function(fn, scope) {
  var me = this, rowRange = me.getRowRange(), store = me.view.store, rowIdx;
  for (rowIdx = rowRange[0]; rowIdx <= rowRange[1]; rowIdx++) {
    if (fn.call(scope || me, store.getAt(rowIdx)) === false) {
      return;
    }
  }
}, eachColumn:function(fn, scope) {
  var colRange = this.getColumnRange(), columns = this.view.getVisibleColumns(), i;
  for (i = colRange[0]; i <= colRange[1]; i++) {
    if (fn.call(scope || this, columns[i], i) === false) {
      return;
    }
  }
}, eachCell:function(fn, scope) {
  var me = this, view = me.view, store = view.store, rowRange = me.getRowRange(), colRange = me.getColumnRange(), baseLocation, location, rowIdx, colIdx;
  for (rowIdx = rowRange[0]; rowIdx <= rowRange[1]; rowIdx++) {
    baseLocation = new Ext.grid.Location(view, store.getAt(rowIdx));
    for (colIdx = colRange[0]; colIdx <= colRange[1]; colIdx++) {
      location = baseLocation.cloneForColumn(colIdx);
      if (fn.call(scope || me, location, colIdx, rowIdx) === false) {
        return;
      }
    }
  }
}, getFirstRowIndex:function() {
  return this.startCell ? Math.min(this.startCell.recordIndex, this.endCell.recordIndex) : 0;
}, getLastRowIndex:function() {
  return this.startCell ? Math.max(this.startCell.recordIndex, this.endCell.recordIndex) : -1;
}, getFirstColumnIndex:function() {
  return this.startCell ? Math.min(this.startCell.columnIndex, this.endCell.columnIndex) : 0;
}, getLastColumnIndex:function() {
  return this.startCell ? Math.max(this.startCell.columnIndex, this.endCell.columnIndex) : -1;
}, privates:{clear:function(suppressEvent) {
  var me = this, view = me.view, changed;
  if (view.getVisibleColumns().length) {
    me.eachCell(function(location) {
      view.onCellDeselect(location);
      changed = true;
    });
  }
  me.startCell = me.endCell = null;
  if (changed && !suppressEvent) {
    this.getSelectionModel().fireSelectionChange();
  }
}, setRangeStart:function(startCell) {
  this.startCell = (this.endCell = startCell.clone()).clone();
  this.view.onCellSelect(startCell);
  this.fireCellSelection();
}, setRangeEnd:function(endCell) {
  var me = this, view = me.view, store = view.store, renderInfo = view.renderInfo, maxColIdx = view.getVisibleColumns().length - 1, range, lastRange, rowStart, rowEnd, colStart, colEnd, rowIdx, colIdx, location, baseLocation;
  me.endCell = endCell.clone();
  range = me.getRange();
  lastRange = me.lastRange || range;
  rowStart = Math.max(Math.min(range[0][1], lastRange[0][1]), renderInfo.indexTop);
  rowEnd = Math.min(Math.max(range[1][1], lastRange[1][1]), renderInfo.indexBottom - 1);
  colStart = Math.min(range[0][0], lastRange[0][0]);
  colEnd = Math.min(Math.max(range[1][0], lastRange[1][0]), maxColIdx);
  for (rowIdx = rowStart; rowIdx <= rowEnd; rowIdx++) {
    baseLocation = new Ext.grid.Location(view, store.getAt(rowIdx));
    for (colIdx = colStart; colIdx <= colEnd; colIdx++) {
      location = baseLocation.cloneForColumn(colIdx);
      if (rowIdx < range[0][1] || rowIdx > range[1][1] || colIdx < range[0][0] || colIdx > range[1][0]) {
        view.onCellDeselect(location);
      } else {
        view.onCellSelect(location);
      }
    }
  }
  me.lastRange = range;
  me.fireCellSelection();
}, extendRange:function(extensionVector) {
  var me = this, view = me.view, newEndCell;
  if (extensionVector[extensionVector.type] < 0) {
    newEndCell = new Ext.grid.Location(view, {record:me.getLastRowIndex(), column:me.getLastColumnIndex()});
    me.startCell = extensionVector.start.clone();
    me.setRangeEnd(newEndCell);
    view.getNavigationModel().setLocation({column:extensionVector.start.columnIndex, record:extensionVector.start.record});
  } else {
    me.startCell = new Ext.grid.Location(view, {record:me.getFirstRowIndex(), column:me.getFirstColumnIndex()});
    me.setRangeEnd(extensionVector.end);
    view.getNavigationModel().setLocation({column:extensionVector.end.columnIndex, record:extensionVector.end.record});
  }
}, reduceRange:function(extensionVector) {
  var me = this, view = me.view, newEndCell;
  if (extensionVector.type === 'rows') {
    newEndCell = new Ext.grid.Location(view, {record:extensionVector.end.recordIndex - 1, column:extensionVector.end.columnIndex});
    me.setRangeEnd(newEndCell);
    view.getNavigationModel().setLocation({column:extensionVector.end.columnIndex, record:me.view.getStore().getAt(extensionVector.end.recordIndex - 1)});
  } else {
    newEndCell = new Ext.grid.Location(view, {record:extensionVector.end.recordIndex, column:extensionVector.end.columnIndex});
    me.setRangeEnd(newEndCell);
    view.getNavigationModel().setLocation({column:extensionVector.end.columnIndex, record:me.view.getStore().getAt(extensionVector.end.recordIndex)});
  }
}, getRange:function() {
  return [[this.getFirstColumnIndex(), this.getFirstRowIndex()], [this.getLastColumnIndex(), this.getLastRowIndex()]];
}, getRangeSize:function() {
  return this.getCount();
}, getRecords:function() {
  var rowRange = this.getRowRange();
  return this.getSelectionModel().getStore().getRange(rowRange[0], rowRange[1]);
}, getCount:function() {
  var range = this.getRange();
  return (range[1][0] - range[0][0] + 1) * (range[1][1] - range[0][1] + 1);
}, fireCellSelection:function() {
  var me = this, selModel = me.getSelectionModel(), view = selModel.getView();
  view.fireEvent('cellselection', view, me.getRange());
}, selectAll:function() {
  var me = this, view = me.view, columns = view.getVisibleColumns();
  me.clear();
  me.setRangeStart(new Ext.grid.Location(view, {record:0, column:0}));
  me.setRangeEnd(new Ext.grid.Location(view, {record:view.store.last(), column:columns[columns.length - 1]}));
}, isAllSelected:function() {
  var start = this.startCell, end = this.endCell;
  if (start) {
    if (!start.columnIndex && !start.recordIndex) {
      return end.columnIndex === end.view.getVisibleColumns().length - 1 && end.recordIndex === end.view.store.getCount() - 1;
    }
  }
  return false;
}, getColumnRange:function() {
  return [this.getFirstColumnIndex(), this.getLastColumnIndex()];
}, getLastSelected:function() {
  return this.view.getStore().getAt(this.endCell.recordIndex);
}, getRowRange:function() {
  return [this.getFirstRowIndex(), this.getLastRowIndex()];
}, onSelectionFinish:function() {
  var me = this, view = me.view;
  if (me.getCount()) {
    me.getSelectionModel().onSelectionFinish(me, new Ext.grid.Location(view, {record:me.getFirstRowIndex(), column:me.getFirstColumnIndex()}), new Ext.grid.Location(view, {record:me.getLastRowIndex(), column:me.getLastColumnIndex()}));
  } else {
    me.getSelectionModel().onSelectionFinish(me);
  }
}}});
Ext.define('Ext.grid.selection.Columns', {extend:Ext.dataview.selection.Selection, alias:'selection.columns', isColumns:true, clone:function() {
  var me = this, result = new me.self(me.view), columns = me.selectedColumns;
  if (columns) {
    result.selectedColumns = Ext.Array.slice(columns);
  }
  return result;
}, eachRow:function(fn, scope) {
  var columns = this.selectedColumns;
  if (columns && columns.length) {
    this.view.getStore().each(fn, scope || this);
  }
}, eachColumn:function(fn, scope) {
  var me = this, columns = me.selectedColumns, len, i;
  if (columns) {
    len = columns.length;
    for (i = 0; i < len; i++) {
      if (fn.call(scope || me, columns[i], i) === false) {
        return false;
      }
    }
  }
}, eachCell:function(fn, scope) {
  var me = this, view = me.view, columns = me.selectedColumns, context = new Ext.grid.Location(view), len, i;
  if (columns) {
    len = columns.length;
    view.getStore().each(function(record) {
      context = context.clone({record:record});
      for (i = 0; i < len; i++) {
        context = context.clone({column:columns[i]});
        if (fn.call(scope || me, context, context.columnIndex, context.recordIndex) === false) {
          return false;
        }
      }
    });
  }
}, isSelected:function(column) {
  var selectedColumns = this.selectedColumns;
  if (column && column.isGridColumn && selectedColumns && selectedColumns.length) {
    return Ext.Array.contains(selectedColumns, column);
  }
  return false;
}, getCount:function() {
  var selectedColumns = this.selectedColumns;
  return selectedColumns ? selectedColumns.length : 0;
}, getColumns:function() {
  return this.selectedColumns || [];
}, privates:{add:function(column, suppressEvent) {
  var me = this, selModel;
  if (!column.isGridColumn) {
    Ext.raise('Column selection must be passed a grid Column header object');
  }
  selModel = me.getSelectionModel();
  Ext.Array.include(me.selectedColumns || (me.selectedColumns = []), column);
  me.refreshColumns(column);
  selModel.updateHeaderState();
  if (!suppressEvent) {
    selModel.fireSelectionChange();
    me.fireColumnSelection();
  }
}, clear:function(suppressEvent) {
  var me = this, selModel = me.getSelectionModel(), prevSelection = me.selectedColumns;
  if (prevSelection && prevSelection.length) {
    me.selectedColumns = [];
    me.refreshColumns.apply(me, prevSelection);
    selModel.updateHeaderState();
    if (!suppressEvent) {
      selModel.fireSelectionChange();
      me.fireColumnSelection();
    }
  }
}, setRangeStart:function(startColumn) {
  var me = this, prevSelection = me.getColumns();
  prevSelection.push(startColumn);
  me.clear(true);
  me.startColumn = startColumn;
  me.add(startColumn);
}, setRangeEnd:function(endColumn) {
  var me = this, prevSelection = me.getColumns(), headerCt = this.view.ownerGrid.getHeaderContainer(), columns = headerCt.getVisibleColumns(), start = headerCt.indexOfLeaf(me.startColumn), end = headerCt.indexOfLeaf(endColumn), i;
  if (end < start) {
    i = start;
    start = end;
    end = i;
  }
  me.selectedColumns = [];
  for (i = start; i <= end; i++) {
    me.selectedColumns.push(columns[i]);
    prevSelection.push(columns[i]);
  }
  me.refreshColumns.apply(me, prevSelection);
  me.fireColumnSelection();
}, isAllSelected:function() {
  var selectedColumns = this.selectedColumns, headerContainer;
  if (!selectedColumns) {
    return false;
  }
  headerContainer = this.view.getHeaderContainer();
  return selectedColumns.length === headerContainer.getVisibleColumns().length;
}, refreshColumns:function(column) {
  var me = this, view = me.view, store = view.store, renderInfo = view.renderInfo, columns = arguments, len = columns.length, selected = [], location, rowIdx, colIdx;
  if (view.rendered) {
    for (colIdx = 0; colIdx < len; colIdx++) {
      selected[colIdx] = me.isSelected(columns[colIdx]);
    }
    for (rowIdx = renderInfo.indexTop; rowIdx < renderInfo.indexBottom; rowIdx++) {
      location = new Ext.grid.Location(view, store.getAt(rowIdx));
      for (colIdx = 0; colIdx < len; colIdx++) {
        location = location.cloneForColumn(columns[colIdx]);
        if (selected[colIdx]) {
          view.onCellSelect(location);
        } else {
          view.onCellDeselect(location);
        }
      }
    }
  }
}, remove:function(column, suppressEvent) {
  var me = this, selModel = me.getSelectionModel();
  if (!column.isGridColumn) {
    Ext.raise('Column selection must be passed a grid Column header object');
  }
  if (me.selectedColumns) {
    Ext.Array.remove(me.selectedColumns, column);
    if (column.getGrid() && column.isVisible()) {
      me.refreshColumns(column);
      selModel.updateHeaderState();
      if (!suppressEvent) {
        selModel.fireSelectionChange();
        me.fireColumnSelection();
      }
    }
  }
}, fireColumnSelection:function() {
  var me = this, selModel = me.getSelectionModel(), view = selModel.getView();
  view.fireEvent('columnselection', view, me.selectedColumns);
}, selectAll:function() {
  var me = this;
  me.clear();
  me.selectedColumns = me.getSelectionModel().lastContiguousColumnRange = me.view.getHeaderContainer().getVisibleColumns();
  me.refreshColumns.apply(me, me.selectedColumns);
}, extendRange:function(extensionVector) {
  var me = this, columns = me.view.getHeaderContainer().getVisibleColumns(), i;
  for (i = extensionVector.start.columnIndex; i <= extensionVector.end.columnIndex; i++) {
    me.add(columns[i]);
  }
}, reduceRange:function(extensionVector) {
  var me = this, columns = me.view.getHeaderContainer().getVisibleColumns(), startIdx = extensionVector.start.columnIndex, endIdx = extensionVector.end.columnIndex, reduceTo = Math.abs(startIdx - endIdx) + 1, diff = me.selectedColumns.length - reduceTo, i;
  for (i = diff; i > 0; i--) {
    me.remove(columns[endIdx + i]);
  }
}, onSelectionFinish:function() {
  var me = this, range = me.getContiguousSelection(), start, end;
  if (range) {
    start = new Ext.grid.Location(me.view, {record:0, column:range[0]});
    end = new Ext.grid.Location(me.view, {record:me.view.getStore().getCount() - 1, column:range[1]});
    me.getSelectionModel().onSelectionFinish(me, start, end);
  } else {
    me.getSelectionModel().onSelectionFinish(me);
  }
}, getContiguousSelection:function() {
  var selection = Ext.Array.sort(this.getColumns(), function(c1, c2) {
    var c1Grid = c1.getGrid().ownerGrid, c1IndexOfLeaf = c1Grid.getHeaderContainer().indexOfLeaf(c1), c2Grid = c2.getGrid().ownerGrid, c2IndexOfLeaf = c2Grid.getHeaderContainer().indexOfLeaf(c2);
    return c1IndexOfLeaf - c2IndexOfLeaf;
  }), len = selection.length, i;
  if (len) {
    for (i = 1; i < len; i++) {
      if (selection[i].getVisibleIndex() !== selection[i - 1].getVisibleIndex() + 1) {
        return false;
      }
    }
    return [selection[0], selection[len - 1]];
  }
}}});
Ext.define('Ext.grid.selection.Replicator', {extend:Ext.plugin.Abstract, alias:'plugin.selectionreplicator', init:function(grid) {
  this.gridListeners = grid.on({beforeselectionextend:this.onBeforeSelectionExtend, scope:this, destroyable:true});
}, onBeforeSelectionExtend:function(ownerGrid, sel, extension) {
  var columns = this.columns = [];
  sel.eachColumn(function(column) {
    columns.push(column);
  });
  return this.replicateSelection(ownerGrid, sel, extension);
}, replicateSelection:function(ownerGrid, sel, extension) {
  var me = this, columns, colCount, j, column, values, startIdx, endIdx, selFirstRowIdx, selLastRowIdx, i, increment, store, record, prevValues, prevValue, selectedRowCount, lastTwoRecords, x, y;
  if (extension.columns || sel.isColumns) {
    return;
  }
  columns = me.columns;
  selFirstRowIdx = sel.getFirstRowIndex();
  selLastRowIdx = sel.getLastRowIndex();
  selectedRowCount = selLastRowIdx - selFirstRowIdx + 1;
  lastTwoRecords = [];
  colCount = columns.length;
  store = columns[0].getGrid().getStore();
  if (selectedRowCount === 1) {
    values = me.getColumnValues(sel.view.getStore().getAt(selFirstRowIdx));
  } else {
    values = new Array(colCount);
    if (extension.rows < 0) {
      lastTwoRecords = [store.getAt(selFirstRowIdx + 1), store.getAt(selFirstRowIdx)];
    } else {
      lastTwoRecords = [store.getAt(selLastRowIdx - 1), store.getAt(selLastRowIdx)];
    }
    lastTwoRecords[0] = me.getColumnValues(lastTwoRecords[0]);
    lastTwoRecords[1] = me.getColumnValues(lastTwoRecords[1]);
    for (j = 0; j < colCount; j++) {
      x = lastTwoRecords[1][j];
      y = lastTwoRecords[0][j];
      if (!isNaN(x) && !isNaN(y)) {
        values[j] = Number(x) - Number(y);
      }
    }
  }
  if (extension.rows < 0) {
    startIdx = extension.end.recordIndex;
    endIdx = extension.start.recordIndex - 1;
    increment = -1;
  } else {
    startIdx = extension.start.recordIndex;
    endIdx = extension.end.recordIndex + 1;
    increment = 1;
  }
  if (selectedRowCount === 1) {
    for (i = startIdx; i !== endIdx; i += increment) {
      record = store.getAt(i);
      for (j = 0; j < colCount; j++) {
        column = columns[j];
        if (column.getDataIndex()) {
          record.set(column.getDataIndex(), values[j]);
        }
      }
    }
  } else {
    for (i = startIdx; i !== endIdx; i += increment) {
      record = store.getAt(i);
      prevValues = me.getColumnValues(store.getAt(i - increment));
      for (j = 0; j < colCount; j++) {
        column = columns[j];
        if (column.getDataIndex()) {
          prevValue = prevValues[j];
          if (!isNaN(prevValue)) {
            record.set(column.getDataIndex(), Ext.coerce(Number(prevValue) + values[j], prevValue));
          }
        }
      }
    }
  }
}, getColumnValues:function(record) {
  var columns = this.columns, len = columns.length, i, column, result = new Array(columns.length);
  for (i = 0; i < len; i++) {
    column = columns[i];
    if (column.getDataIndex()) {
      result[i] = record.get(column.getDataIndex());
    }
  }
  return result;
}, destroy:function() {
  this.gridListeners = Ext.destroy(this.gridListeners);
  this.callParent();
}});
Ext.define('Ext.grid.selection.SelectionExtender', {maskBox:{}, constructor:function(config) {
  var me = this, view = config.view, handleListeners = {dragstart:'onDragStart', dragend:'onDragEnd', scope:me};
  Ext.apply(me, config);
  me.el = view.outerCt;
  me.handle = view.bodyElement.createChild({cls:Ext.baseCSSPrefix + 'selmodel-extender-drag-handle'}).hide();
  if (Ext.supports.Touch) {
    handleListeners.longpress = 'onHandleLongpress';
  }
  me.handle.on(handleListeners);
  me.mask = view.outerCt.createChild({cls:Ext.baseCSSPrefix + 'selmodel-extender-mask'}).hide();
  me.scrollListener = view.getScrollable().on({scroll:me.onViewScroll, scope:me, destroyable:true});
  me.viewListener = view.on({columnresize:'alignHandle', columnhide:'alignHandle', columnshow:'alignHandle', columnmove:'alignHandle', scope:me, destroyable:true});
  if (config && config.axes) {
    me.setAxes(config.axes);
  }
}, setAxes:function(axes) {
  var me = this;
  me.axes = axes;
  me.extendX = !!(axes & 1);
  me.extendY = !!(axes & 2);
}, setHandle:function(firstPos, endPos) {
  var me = this;
  me.firstPos = firstPos;
  me.endPos = endPos;
  if (firstPos && endPos && endPos.getCell(true)) {
    me.curPos = endPos;
    me.alignHandle();
  } else {
    me.disable();
  }
}, alignHandle:function() {
  var me = this, lastCell = me.endPos;
  if (me.firstPos && lastCell && me.view.isRecordRendered(lastCell.recordIndex)) {
    lastCell = lastCell.clone({record:lastCell.record, column:lastCell.column}).getCell();
    if (lastCell && lastCell.isVisible()) {
      me.enable();
    } else {
      me.disable();
    }
    me.handle.alignTo(lastCell, 'c-br');
  } else {
    me.disable();
  }
}, enable:function() {
  this.handle.show();
}, disable:function() {
  this.handle.hide();
  this.mask.hide();
}, onHandleLongpress:function(e) {
  e.startDrag();
}, onDragStart:function(e) {
  if (e.pointerType !== 'touch' || e.longpress) {
    e.claimGesture();
    this.handle.on('drag', this.onDrag, this);
  }
}, onDrag:function(e) {
  var me = this, target, view, scrollClientRegion, touch, realTarget, overCell, scrollTask, thresh, scrollDelta, scrollBy;
  if (e.changedTouches) {
    touch = e.changedTouches[0];
    if (touch && !Ext.fly(touch.target).getRegion().contains(touch.point)) {
      realTarget = Ext.event.Event.resolveTextNode(Ext.Element.fromPagePoint(touch.pageX, touch.pageY, true));
      if (realTarget) {
        e.target = realTarget;
      }
    }
  }
  target = e.target;
  view = me.view;
  scrollClientRegion = view.getScrollable().getElement().getClientRegion();
  overCell = new Ext.grid.Location(view, target);
  scrollTask = me.scrollTask || (me.scrollTask = Ext.util.TaskManager.newTask({run:me.doAutoScroll, scope:me, interval:10}));
  thresh = 25 * (window.devicePixelRatio || 1);
  scrollDelta = 3 * (window.devicePixelRatio || 1);
  scrollBy = me.scrollBy || (me.scrollBy = []);
  e.claimGesture();
  me.lastXY = [e.pageX, e.pageY];
  if (!me.el.contains(target)) {
    scrollBy[0] = scrollBy[1] = 0;
    return scrollTask.stop();
  }
  if (me.lastXY[1] > scrollClientRegion.bottom - thresh) {
    if (me.extendY) {
      scrollBy[1] = scrollDelta;
      scrollTask.start();
    }
  } else {
    if (me.lastXY[1] < scrollClientRegion.top + thresh) {
      if (me.extendY) {
        scrollBy[1] = -scrollDelta;
        scrollTask.start();
      }
    } else {
      if (me.lastXY[0] > scrollClientRegion.right - thresh) {
        if (me.extendX) {
          scrollBy[0] = scrollDelta;
          scrollTask.start();
        }
      } else {
        if (me.lastXY[0] < scrollClientRegion.left + thresh) {
          if (me.extendX) {
            scrollBy[0] = -scrollDelta;
            scrollTask.start();
          }
        } else {
          scrollBy[0] = scrollBy[1] = 0;
          scrollTask.stop();
        }
      }
    }
  }
  if (overCell && overCell.getCell() && !overCell.equals(me.lastOverCell)) {
    me.lastOverCell = overCell;
    me.syncMaskOnCell(overCell);
  }
}, doAutoScroll:function() {
  var me = this, view = me.view, scroller = view.getScrollable(), scrollOverCell;
  scroller.scrollBy.apply(scroller, me.scrollBy);
  scrollOverCell = document.elementFromPoint.apply(document, me.lastXY);
  if (scrollOverCell) {
    scrollOverCell = new Ext.grid.Location(me.view, scrollOverCell);
    if (scrollOverCell && scrollOverCell.getCell() && !scrollOverCell.equals(me.lastOverCell)) {
      me.lastOverCell = scrollOverCell;
      me.syncMaskOnCell(scrollOverCell);
    }
  }
}, onDragEnd:function(e) {
  var me = this, selectable = me.view.getSelectable(), selection = selectable && selectable.getSelection();
  me.handle.un('drag', me.onDrag, me);
  if (me.scrollTask) {
    me.scrollTask.stop();
  }
  if (me.extensionDescriptor) {
    me.disable();
    if (selection.isColumns && e.direction.y < 0 || selection.isRows && e.direction.x < 0) {
      me.alignHandle();
      return;
    }
    selectable.extendSelection(me.extensionDescriptor);
  }
}, onViewScroll:function() {
  var me = this;
  if (me.active && me.lastOverCell || me.firstPos) {
    me.endPos = me.endPos.clone({record:me.endPos.recordIndex});
    me.alignHandle();
  }
}, stopEvent:function(e) {
  e.stopEvent();
}, syncMaskOnCell:function(overCell) {
  var me = this, view = me.view, renderInfo = view.renderInfo, maskBox = me.maskBox, startRecordIndex = me.firstPos.recordIndex, endRecordIndex = me.endPos.recordIndex, extensionStart = me.firstPos.clone({record:startRecordIndex}), extensionEnd = me.endPos.clone({record:endRecordIndex}), preventReduce = !me.allowReduceSelection, selRegion, firstCell, firstCellEl, endCell, endCellEl, curPos;
  firstCell = me.firstPos.clone({record:Ext.Number.constrain(Math.min(startRecordIndex, endRecordIndex), renderInfo.indexTop, renderInfo.indexBottom - 1), column:me.firstPos.column});
  endCell = me.endPos.clone({record:Ext.Number.constrain(Math.max(firstCell.recordIndex, endRecordIndex), renderInfo.indexTop, renderInfo.indexBottom - 1)});
  firstCellEl = firstCell.getCell();
  endCellEl = endCell.getCell();
  me.selectionRegion = selRegion = firstCellEl.getRegion().union(endCellEl.getRegion());
  me.curPos = curPos = overCell;
  overCell = overCell.getCell('el');
  me.mask.dom.style.borderTopWidth = me.mask.dom.style.borderRightWidth = me.mask.dom.style.borderBottomWidth = me.mask.dom.style.borderLeftWidth = '';
  if (curPos.recordIndex < me.firstPos.recordIndex && me.extendY) {
    me.extensionDescriptor = {type:'rows', start:extensionStart.clone({record:curPos.recordIndex}), end:extensionEnd.clone({record:me.firstPos.recordIndex - 1}), rows:curPos.recordIndex - me.firstPos.recordIndex, mousePosition:me.lastXY};
    me.mask.dom.style.borderBottomWidth = '0';
    maskBox.x = selRegion.x;
    maskBox.y = overCell.getY();
    maskBox.width = selRegion.right - selRegion.left;
    maskBox.height = selRegion.top - overCell.getY();
  } else {
    if (curPos.recordIndex > me.endPos.recordIndex && me.extendY) {
      me.extensionDescriptor = {type:'rows', start:extensionStart.clone({record:me.endPos.recordIndex + 1}), end:extensionEnd.clone({record:curPos.recordIndex}), rows:curPos.recordIndex - me.endPos.recordIndex, mousePosition:me.lastXY};
      me.mask.dom.style.borderTopWidth = '0';
      maskBox.x = selRegion.x;
      maskBox.y = selRegion.bottom;
      maskBox.width = selRegion.right - selRegion.left;
      maskBox.height = overCell.getRegion().bottom - selRegion.bottom;
    } else {
      if (!preventReduce && curPos.recordIndex < me.endPos.recordIndex && me.extendY && curPos.columnIndex === me.endPos.columnIndex) {
        me.extensionDescriptor = {type:'rows', start:extensionStart.clone({record:me.endPos.recordIndex}), end:extensionEnd.clone({record:curPos.recordIndex + 1}), rows:-1, mousePosition:me.lastXY, reduce:true};
        me.mask.dom.style.borderTopWidth = '0';
        maskBox.x = selRegion.x;
        maskBox.y = selRegion.top;
        maskBox.width = selRegion.right - selRegion.left;
        maskBox.height = overCell.getRegion().bottom - selRegion.top;
      } else {
        if (curPos.columnIndex < me.firstPos.columnIndex && me.extendX) {
          me.extensionDescriptor = {type:'columns', start:extensionStart.clone({column:curPos.columnIndex}), end:extensionEnd.clone({column:me.firstPos.columnIndex - 1}), columns:curPos.columnIndex - me.firstPos.columnIndex, mousePosition:me.lastXY};
          me.mask.dom.style.borderRightWidth = '0';
          maskBox.x = overCell.getX();
          maskBox.y = selRegion.top;
          maskBox.width = selRegion.left - overCell.getX();
          maskBox.height = selRegion.bottom - selRegion.top;
        } else {
          if (curPos.columnIndex > me.endPos.columnIndex && me.extendX) {
            me.extensionDescriptor = {type:'columns', start:extensionStart.clone({column:me.endPos.columnIndex + 1}), end:extensionEnd.clone({column:curPos.columnIndex}), columns:curPos.columnIndex - me.endPos.columnIndex, mousePosition:me.lastXY};
            me.mask.dom.style.borderLeftWidth = '0';
            maskBox.x = selRegion.right;
            maskBox.y = selRegion.top;
            maskBox.width = overCell.getRegion().right - selRegion.right;
            maskBox.height = selRegion.bottom - selRegion.top;
          } else {
            if (!preventReduce && curPos.columnIndex < me.endPos.columnIndex && me.extendX) {
              me.extensionDescriptor = {type:'columns', start:extensionStart.clone({column:me.firstPos.columnIndex}), end:extensionEnd.clone({column:curPos.columnIndex}), columns:-1, mousePosition:me.lastXY, reduce:true};
              me.mask.dom.style.borderLeftWidth = '0';
              maskBox.x = selRegion.left;
              maskBox.y = selRegion.top;
              maskBox.width = overCell.getRegion().right - selRegion.left;
              maskBox.height = selRegion.bottom - selRegion.top;
            } else {
              me.extensionDescriptor = null;
            }
          }
        }
      }
    }
  }
  if (view.hasListeners.selectionextenderdrag) {
    view.fireEvent('selectionextenderdrag', view, view.getSelectable().getSelection(), me.extensionDescriptor);
  }
  if (me.extensionDescriptor) {
    me.mask.show();
    me.mask.setBox(maskBox);
  } else {
    me.mask.hide();
  }
}, destroy:function() {
  this.destroyMembers('viewListener', 'scrollListener', 'mask', 'handle');
}});
Ext.define('Ext.grid.cell.Number', {extend:Ext.grid.cell.Text, xtype:'numbercell', isNumberCell:true, config:{format:'0,000.00'}, classCls:Ext.baseCSSPrefix + 'numbercell', zeroValue:null, updateColumn:function(column, oldColumn) {
  var format;
  this.callParent([column, oldColumn]);
  if (column && column.isNumberColumn) {
    format = column.getFormat();
    if (format !== null) {
      this.setFormat(format);
    }
  }
}, updateFormat:function(format) {
  if (!this.isConfiguring) {
    this.writeValue();
  }
}, formatValue:function(value) {
  var hasValue = value || value === 0, zeroValue;
  if (value === 0 && (zeroValue = this.getZeroValue()) !== null) {
    value = zeroValue || '';
  } else {
    value = hasValue ? Ext.util.Format.number(value, this.getFormat()) : '';
  }
  return value;
}});
Ext.define('Ext.grid.cell.Check', {extend:Ext.grid.cell.Base, xtype:'checkcell', config:{disabled:null}, innerTemplate:[{reference:'checkboxElement', tabIndex:-1, cls:Ext.baseCSSPrefix + 'checkbox-el ' + Ext.baseCSSPrefix + 'font-icon'}], classCls:Ext.baseCSSPrefix + 'checkcell', disabledCls:Ext.baseCSSPrefix + 'disabled', checkedCls:Ext.baseCSSPrefix + 'checked', constructor:function(config) {
  this.callParent([config]);
  this.checkboxElement.on('tap', 'onTap', this);
}, applyValue:function(value) {
  return !!value;
}, updateValue:function(value, oldValue) {
  var me = this, column = me.getColumn();
  me.el.toggleCls(me.checkedCls, !!value);
  if (value) {
    column.updateHeaderState();
  } else {
    column.setHeaderStatus(value);
  }
}, updateColumn:function(column, oldColumn) {
  this.callParent([column, oldColumn]);
  if (column) {
    this.setDisabled(column.getDisabled());
  }
}, applyDisabled:function(disabled) {
  return Boolean(disabled);
}, updateDisabled:function(disabled) {
  this.element.toggleCls(this.disabledCls, disabled);
}, disable:function() {
  this.setDisabled(true);
}, enable:function() {
  this.setDisabled(false);
}, onTap:function(e) {
  var me = this, record = me.getRecord(), column = me.getColumn(), recordIndex = column.up('grid').getStore().indexOf(record), checked;
  if (record) {
    checked = !column.isRecordChecked(record);
    if (me.getDisabled()) {
      return;
    }
    if (column.fireEvent('beforecheckchange', me, recordIndex, checked, record, e) !== false) {
      if (me.getColumn().getStopSelection()) {
        e.stopSelection = true;
      }
      if (record) {
        column.setRecordChecked(record, checked, e);
      }
      if (column.hasListeners.checkchange) {
        column.fireEvent('checkchange', me, recordIndex, checked, record, e);
      }
    }
  }
}});
Ext.define('Ext.theme.material.grid.cell.Check', {override:'Ext.grid.cell.Check', config:{ripple:{delegate:'.' + Ext.baseCSSPrefix + 'checkbox-el', bound:false, color:'default', centered:true}}});
Ext.define('Ext.grid.column.Check', {extend:Ext.grid.column.Column, isCheckColumn:true, xtype:'checkcolumn', cachedConfig:{headerCheckboxAlign:'bottom'}, config:{stopSelection:true, headerCheckbox:false}, align:'center', classCls:Ext.baseCSSPrefix + 'checkcolumn', noHeaderCheckboxCls:Ext.baseCSSPrefix + 'no-header-checkbox', checkedCls:Ext.baseCSSPrefix + 'checked', hasTextCls:Ext.baseCSSPrefix + 'has-text', checkboxAlignCls:{top:Ext.baseCSSPrefix + 'checkbox-align-top', right:Ext.baseCSSPrefix + 
'checkbox-align-right', bottom:Ext.baseCSSPrefix + 'checkbox-align-bottom', left:Ext.baseCSSPrefix + 'checkbox-align-left'}, text:'', ignoreExport:true, cell:{xtype:'checkcell'}, afterTitleTemplate:[{reference:'checkboxElement', classList:[Ext.baseCSSPrefix + 'checkbox-el', Ext.baseCSSPrefix + 'font-icon']}], onColumnTap:function(e) {
  var me = this;
  if (e.target === me.checkboxElement.dom && !me.getDisabled()) {
    me.toggleAll(e);
  }
  me.callParent([e]);
}, toggleAll:function(e) {
  var me = this, checked = !me.allChecked;
  if (me.fireEvent('beforeheadercheckchange', me, checked, e) !== false) {
    me.doToggleAll(checked);
    me.setHeaderStatus(checked);
    me.fireEvent('headercheckchange', me, checked, e);
  }
}, doToggleAll:function(checked) {
  var me = this, store = me.getGrid().getStore();
  store.each(function(record) {
    me.setRecordChecked(record, checked);
  });
}, setRecordChecked:function(record, checked, e) {
  checked = !!checked;
  this.doSetRecordChecked(record, checked);
  if (checked) {
    this.updateHeaderState();
  } else {
    this.setHeaderStatus(checked);
  }
}, doSetRecordChecked:function(record, checked) {
  var dataIndex = this.getDataIndex();
  if (record.get(dataIndex) !== checked) {
    record.set(dataIndex, checked);
  }
}, areAllChecked:function() {
  var me = this, store = me.getGrid().getStore(), records, len, i;
  if (store && !store.isVirtualStore && store.getCount() > 0) {
    records = store.getData().items;
    len = records.length;
    for (i = 0; i < len; ++i) {
      if (!me.isRecordChecked(records[i])) {
        return false;
      }
    }
    return true;
  }
}, isRecordChecked:function(record) {
  return record.get(this.getDataIndex());
}, updateHeaderState:function() {
  if (!this.destroyed && this.getHeaderCheckbox() !== false) {
    this.setHeaderStatus(this.areAllChecked());
  }
}, setHeaderStatus:function(checked) {
  var me = this;
  if (me.allChecked !== checked) {
    me.allChecked = checked;
    me.el.toggleCls(me.checkedCls, checked);
  }
}, updateDisabled:function(disabled, oldDisabled) {
  var me = this, grid = me.getGrid(), rows, len, i;
  me.callParent([disabled, oldDisabled]);
  if (grid) {
    rows = grid.getViewItems();
    len = rows.length;
    for (i = 0; i < len; i++) {
      rows[i].getCellByColumn(me).setDisabled(disabled);
    }
  }
}, updateHeaderCheckboxAlign:function(align, oldAlign) {
  var me = this, checkboxAlignCls = me.checkboxAlignCls;
  if (oldAlign) {
    me.removeCls(checkboxAlignCls[oldAlign]);
  }
  if (align) {
    if (!checkboxAlignCls[align]) {
      Ext.raise("Invalid value for checkboxAlign: '" + align + "'");
    }
    me.addCls(checkboxAlignCls[align]);
  }
}, updateHeaderCheckbox:function(headerCheckbox) {
  var me = this, grid = me.getGrid();
  me.el.toggleCls(me.noHeaderCheckboxCls, !headerCheckbox);
  me.setSortable(me.getSortable() && !headerCheckbox);
  if (grid) {
    me.updateHeaderState();
  }
}, updateText:function(text) {
  this.setHtml(text);
  this.toggleCls(this.hasTextCls, !!text);
}});
Ext.define('Ext.grid.column.Selection', {extend:Ext.grid.column.Check, xtype:'selectioncolumn', classCls:Ext.baseCSSPrefix + 'selectioncolumn', cell:{cls:Ext.baseCSSPrefix + 'selection-cell'}, weight:-900, menu:null, sortable:false, draggable:false, resizable:false, hideable:false, ignore:true, stopSelection:false, updateHeaderState:function() {
  if (!this.isConfiguring) {
    this.getGrid().getSelectable().updateHeaderState();
  }
}, toggleAll:function(e) {
  this.getGrid().getSelectable().toggleAll(this, e);
}, setRecordChecked:function(record, checked, e) {
  var selectionModel = this.getGrid().getSelectable();
  if (checked) {
    selectionModel.select(record, selectionModel.getMode() !== 'single');
  } else {
    selectionModel.deselect(record);
  }
}, isRecordChecked:function(record) {
  return this.getGrid().getSelectable().isRowSelected(record);
}});
Ext.define('Ext.grid.column.Number', {extend:Ext.grid.column.Column, xtype:'numbercolumn', isNumberColumn:true, config:{format:null}, cell:{xtype:'numbercell'}, defaultEditor:{xtype:'numberfield'}});
Ext.define('Ext.grid.cell.RowNumberer', {extend:Ext.grid.cell.Number, xtype:'rownumberercell', classCls:Ext.baseCSSPrefix + 'rownumberercell', format:'0,000', refreshValue:function(context) {
  var row = context.row, ret;
  if (context.summary) {
    ret = ' ';
  } else {
    ret = row ? row.$datasetIndex + 1 : null;
  }
  return ret;
}});
Ext.define('Ext.grid.column.RowNumberer', {extend:Ext.grid.column.Number, xtype:'rownumberer', isRowNumberer:true, cell:{xtype:'rownumberercell'}, menu:null, align:'right', hideable:false, ignore:true, ignoreExport:true, sortable:false, text:'', width:'auto', minWidth:null, onAdded:function(parent, instanced) {
  var me = this, grid;
  me.callParent([parent, instanced]);
  me.checkWidth();
  grid = me.getGrid();
  me.gridListeners = grid.on({storechange:'attachStoreListeners', scope:me, destroyable:true});
  me.attachStoreListeners(grid.getStore());
}, onRemoved:function(destroying) {
  Ext.destroy(this.gridListeners, this.storeListeners);
  this.callParent([destroying]);
}, privates:{attachStoreListeners:function(store) {
  Ext.destroy(this.storeListeners);
  if (store) {
    this.storeListeners = store.on({datachanged:'checkWidth', totalcountchange:'checkWidth', scope:this, destroyable:true});
  }
}, getCharWidth:function() {
  var me = this, charWidth = me._charWidth, text, cell, cellUi, gridUi, textWidth;
  if (!charWidth) {
    text = '0000000000';
    cell = me.getScratchCell();
    cellUi = me.getCell().ui;
    if (cellUi) {
      cell.addUi(cellUi);
    }
    gridUi = me.getGrid().getUi();
    if (gridUi) {
      cell.addUi(gridUi);
    }
    document.body.appendChild(cell.el.dom);
    textWidth = Ext.util.TextMetrics.measure(cell.bodyElement, text).width;
    document.body.removeChild(cell.el.dom);
    me._charWidth = charWidth = textWidth / text.length;
  }
  return charWidth;
}, checkWidth:function() {
  var me = this;
  if (document.fonts) {
    document.fonts.ready.then(function() {
      if (!me.destroyed) {
        me.doCheckWidth();
      }
    });
  } else {
    me.doCheckWidth();
  }
}, doCheckWidth:function() {
  var me = this, store = me.getGrid().getStore(), charLen = 1, charWidth = me.getCharWidth();
  if (store && store.getTotalCount()) {
    charLen = me.getScratchCell().printValue(store.getTotalCount()).length;
  }
  me.textElement.setStyle('min-width', Math.ceil(charLen * charWidth) + 'px');
}}});
Ext.define('Ext.grid.selection.Model', {extend:Ext.dataview.selection.Model, alias:'selmodel.grid', isGridSelectionModel:true, config:{columns:{$value:false, lazy:true}, cells:{$value:false, lazy:true}, rows:{$value:true, lazy:true}, drag:false, extensible:{$value:false, lazy:true}, reducible:true, checkbox:false, headerCheckbox:true, checkboxDefaults:{xtype:'selectioncolumn', text:null, width:30}, showNumbererColumn:false}, checkboxSelect:false, checkboxColumnIndex:0, mode:'multi', columnSelectCls:Ext.baseCSSPrefix + 
'selmodel-column-select', rowNumbererHeaderCls:Ext.baseCSSPrefix + 'selmodel-row-numberer-hd', updateView:function(view, oldView) {
  var me = this, rowNumberer = me.numbererColumn = view.getRowNumbers(), checkbox = me.getCheckbox();
  me.callParent([view, oldView]);
  if (oldView) {
    me.navigationModel = null;
    Ext.destroy(me.viewListeners);
  }
  if (view) {
    if (rowNumberer) {
      rowNumberer.setCell({cls:me.rowNumbererCellCls});
      rowNumberer.setCls(me.rowNumbererHeaderCls);
    }
    if (checkbox) {
      view.registerColumn(checkbox);
    }
    me.viewListeners = view.on(me.getViewListeners());
  }
}, onViewCreated:function(view) {
  if (this.getColumns()) {
    view.addCls(this.columnSelectCls);
  }
  this.updateHeaderState();
}, updateDrag:function(drag) {
  var view = this.getView(), viewListeners = {dragstart:'onViewDragStart', delegate:view.eventDelegate, scope:this};
  if (Ext.supports.Touch) {
    viewListeners.longpress = 'onViewLongpress';
  }
  view.innerCt[drag ? 'on' : 'un'](viewListeners);
}, getSelection:function(what, reset) {
  var config, result;
  if (what === 'rows' || what === 'records') {
    what = this.getStore().isVirtualStore ? 'rows' : 'records';
  }
  result = this.callParent();
  if (what) {
    what = what.toLowerCase();
    if (!result || result.type !== what) {
      config = {type:what};
      if (what === 'records') {
        config.selected = this.getSelected();
      }
      this.setSelection(config);
      result = this.callParent();
    } else {
      if (reset) {
        result.clear(true);
      }
    }
  }
  return result;
}, createCheckboxColumn:function(checkboxDefaults) {
  var me = this;
  return Ext.apply({headerCheckbox:me.getHeaderCheckbox() !== false}, checkboxDefaults);
}, onHeaderTap:function(headerCt, header, e) {
  var me = this, sel = me.getSelection(), isSelected = false, range, columns, i;
  if (header === this.numbererColumn) {
    me.toggleAll(header, e);
  } else {
    if (me.getColumns() && header !== me.getCheckbox()) {
      if (e.shiftKey && sel && sel.lastColumnSelected) {
        if (!e.ctrlKey) {
          sel.clear();
        }
        headerCt = me.getView().getHeaderContainer();
        columns = headerCt.getColumns();
        range = Ext.Array.sort([headerCt.indexOfLeaf(sel.lastColumnSelected), headerCt.indexOf(header)], Ext.Array.numericSortFn);
        for (i = range[0]; i <= range[1]; i++) {
          me.selectColumn(columns[i], true);
        }
      } else {
        isSelected = me.isColumnSelected(header);
        if (!e.ctrlKey) {
          sel.clear();
        } else {
          if (isSelected) {
            me.deselectColumn(header);
            me.getSelection().lastColumnSelected = null;
          }
        }
        if (!isSelected || !e.ctrlKey && e.pointerType !== 'touch') {
          me.selectColumn(header, e.ctrlKey);
          me.getSelection().lastColumnSelected = header;
        }
        me.updateSelectionExtender();
      }
    }
  }
}, toggleAll:function(header, e) {
  var me = this, sel = me.getSelection();
  e.stopEvent();
  if (!sel || !sel.isAllSelected()) {
    me.selectAll();
  } else {
    me.deselectAll();
  }
  me.updateHeaderState();
  me.lastColumnSelected = null;
}, selectByLocation:function(location) {
  if (!location.isGridLocation) {
    Ext.raise('selectByLocation MUST be passed an Ext.grid.Location');
  }
  var me = this, record = location.record, column = location.column;
  if (me.getCells()) {
    me.selectCells(location, location);
  } else {
    if (me.getRows() && record) {
      this.select(record);
    } else {
      if (me.getColumns() && column) {
        me.selectColumn(column);
      }
    }
  }
}, updateHeaderState:function() {
  var me = this, store = me.getStore(), sel = me.getSelection(), isChecked = false, checkHd = me.getCheckbox(), storeCount;
  if (store && sel && sel.isRows) {
    storeCount = store.getCount();
    if (store.isBufferedStore) {
      isChecked = sel.allSelected;
    } else {
      isChecked = storeCount > 0 && storeCount === sel.getCount();
    }
  }
  if (checkHd) {
    checkHd.setHeaderStatus(isChecked);
  }
}, onColumnUpdate:function(headerCt, columns) {
  var me = this, checkColumn = me.getCheckbox();
  if (checkColumn) {
    if (headerCt) {
      headerCt.remove(checkColumn, false);
    }
    columns.push(checkColumn);
  }
}, select:function(records, keepExisting, suppressEvent) {
  var me = this, sel = me.getSelection('records'), store = me.getStore(), len, i, record;
  if (!Ext.isArray(records)) {
    records = [records];
  }
  len = records.length;
  for (i = 0; i < len; i++) {
    record = records[i];
    if (typeof record === 'number') {
      records[i] = record = store.getAt(record);
    }
  }
  sel.add(records, keepExisting, suppressEvent);
}, deselect:function(records, suppressEvent) {
  var me = this, sel = me.getSelection('records'), store = me.getView().getStore(), len, i, record;
  if (sel && sel.isRecords) {
    if (!Ext.isArray(records)) {
      records = [records];
    }
    len = records.length;
    for (i = 0; i < len; i++) {
      record = records[i];
      if (typeof record === 'number') {
        records[i] = record = store.getAt(record);
      }
    }
  }
  sel.remove(records, suppressEvent);
}, onCollectionRemove:function(selectedCollection, chunk) {
  this.updateHeaderState();
  this.callParent([selectedCollection, chunk]);
}, onCollectionAdd:function(selectedCollection, adds) {
  this.updateHeaderState();
  this.callParent([selectedCollection, adds]);
}, selectCells:function(rangeStart, rangeEnd, suppressEvent) {
  var me = this, view = me.getView(), sel;
  rangeStart = rangeStart.isGridLocation ? rangeStart.clone() : new Ext.grid.Location(view, {record:rangeStart[0], column:rangeStart[1]});
  rangeEnd = rangeEnd.isGridLocation ? rangeEnd.clone() : new Ext.grid.Location(view, {record:rangeEnd[0], column:rangeEnd[1]});
  me.resetSelection(true);
  sel = me.getSelection('cells');
  sel.setRangeStart(rangeStart);
  sel.setRangeEnd(rangeEnd);
  if (!suppressEvent) {
    me.fireSelectionChange();
  }
}, selectAll:function(suppressEvent) {
  var me = this, sel = me.getSelection(), doSelect;
  if (me.getRows()) {
    sel = me.getSelection('records');
    doSelect = true;
  } else {
    if (me.getCells()) {
      sel = me.getSelection('cells');
      doSelect = true;
    } else {
      if (me.getColumns()) {
        sel = me.getSelection('columns');
        doSelect = true;
      }
    }
  }
  if (doSelect) {
    sel.selectAll(suppressEvent);
  }
}, deselectAll:function(suppressEvent) {
  var sel = this.getSelection();
  if (sel && sel.getCount()) {
    sel.clear(suppressEvent);
  }
}, selectRows:function(rows, keepSelection, suppressEvent) {
  var sel = this.getSelection('records');
  if (!keepSelection) {
    this.resetSelection(true);
  }
  sel.add(rows, keepSelection, suppressEvent);
}, isSelected:function(record) {
  return this.isRowSelected(record);
}, selectColumn:function(column, keepSelection, suppressEvent) {
  var selData = this.getSelection('columns');
  if (!selData.isSelected(column)) {
    if (!keepSelection) {
      selData.clear(suppressEvent);
      selData.setRangeStart(column);
    } else {
      selData.add(column);
    }
  }
}, deselectColumn:function(column, suppressEvent) {
  var selData = this.getSelection();
  if (selData && selData.isColumns && selData.isSelected(column)) {
    selData.remove(column, suppressEvent);
  }
}, destroy:function() {
  var me = this, view = me.getView(), checkbox = me.checkbox;
  if (view && !view.destroying && checkbox) {
    view.unregisterColumn(checkbox, true);
  }
  Ext.destroy(me.viewListeners, me.getConfig('extensible', null, true));
  me.callParent();
}, privates:{axesConfigs:{x:1, y:2, xy:3, both:3, 'true':3}, getViewListeners:function() {
  return {columnschanged:'onColumnsChanged', columnmove:'onColumnMove', scope:this, destroyable:true};
}, refreshSelection:function() {
  if (this.getSelection().isRecords) {
    this.callParent();
  } else {
    this.resetSelection();
  }
}, onColumnsChanged:function() {
  var me = this, selData = me.getSelection(), view, selectionChanged;
  if (selData) {
    view = selData.view;
    if (selData.isCells) {
      if (view.visibleColumns().length) {
        selData.eachCell(function(location) {
          view.onCellDeselect(location);
        });
      } else {
        me.clearSelections();
      }
    } else {
      if (selData.isColumns) {
        selectionChanged = false;
        selData.eachColumn(function(column) {
          if (!column.isVisible() || !view.isAncestor(column)) {
            me.remove(column);
            selectionChanged = true;
          }
        });
      }
    }
  }
  Ext.on('idle', selectionChanged ? me.fireSelectionChange : me.updateSelectionExtender, me, {single:true});
}, onColumnMove:function() {
  this.updateSelectionExtender();
}, resetSelection:function(suppressEvent) {
  var sel = this.getSelection();
  if (sel) {
    sel.clear(suppressEvent);
  }
}, onViewLongpress:function(e) {
  if (e.pointerType === 'touch') {
    e.startDrag();
  }
}, onViewDragStart:function(e) {
  if (e.pointerType === 'touch' && !e.longpress) {
    return;
  }
  var me = this, view = me.getView(), location = new Ext.grid.Location(view, e), header = location.column, viewLocation = view.getNavigationModel().getLocation(), isCheckClick = header === me.getCheckbox(), resumingSelection = false, sel;
  if (!location.cell) {
    return;
  }
  if (e.claimed || e.button > 0 || e.altKey || viewLocation && viewLocation.actionable || !view.shouldSelectItem(e)) {
    return;
  }
  if (header) {
    e.claimGesture();
    me.mousedownPosition = location.clone();
    if (isCheckClick) {
      me.checkCellClicked = location.cell.element.dom;
    }
    if (header === me.numbererColumn || isCheckClick || !me.getCells()) {
      if (me.getRows()) {
        if (e.shiftKey && me.isSelected(location.record)) {
          resumingSelection = true;
        } else {
          if (!e.shiftKey && !isCheckClick && me.checkboxOnly) {
            return;
          }
        }
        sel = me.getSelection('records');
        if (!e.shiftKey && !e.ctrlKey && !isCheckClick) {
          sel.clear();
        }
      } else {
        if (me.getColumns()) {
          sel = me.getSelection('columns');
          if (e.shiftKey && me.isColumnSelected(location.column)) {
            resumingSelection = true;
          } else {
            if (!e.shiftKey && !e.ctrlKey && !isCheckClick) {
              sel.clear();
            }
          }
        } else {
          return false;
        }
      }
    } else {
      sel = me.getSelection('cells');
      if (e.shiftKey && me.isCellSelected(location.recordIndex, location.columnIndex)) {
        resumingSelection = true;
      } else {
        if (!e.shiftKey) {
          sel.clear();
        }
      }
    }
    if (!resumingSelection) {
      me.lastDragLocation = null;
    }
    if (e.longpress) {
      location.row.removeCls(view.pressedCls);
      me.onViewSelectionDrag(e);
    }
    if (sel) {
      view.innerCt.on('dragend', me.onViewDragEnd, me, {single:true});
      me.mousemoveListener = view.innerCt.on({drag:'onViewSelectionDrag', scope:me, delegate:view.eventDelegate, destroyable:true});
    }
  }
}, onViewSelectionDrag:function(e) {
  var me = this, view = me.getView(), newLocation, touch, realTarget;
  if (e.changedTouches) {
    touch = e.changedTouches[0];
    if (touch && !Ext.fly(touch.target).getRegion().contains(touch.point)) {
      realTarget = Ext.event.Event.resolveTextNode(Ext.Element.fromPagePoint(touch.pageX, touch.pageY, true));
      if (realTarget) {
        e.target = realTarget;
      }
    }
  }
  me.stopAutoScroller();
  if (!Ext.fly(e.target).up(view.eventDelegate)) {
    me.scrollTowardsPointer(e, view);
    return;
  }
  newLocation = me.dragLocation = new Ext.grid.Location(view, e);
  me.changeSelectionRange(view, newLocation, e);
}, changeSelectionRange:function(view, location, e) {
  var me = this, overColumn = location.column, overRecord = location.record, overRowIdx = location.recordIndex, lastDragLocation = me.lastDragLocation, selData, lastOverRecord, lastOverColumn, recChange, colChange;
  e.claimGesture();
  if (lastDragLocation) {
    lastOverRecord = lastDragLocation.record;
    lastOverColumn = lastDragLocation.column;
  }
  if (me.checkCellClicked) {
    selData = me.getSelection('rows');
    selData.setRangeStart(me.getStore().indexOf(overRecord));
    me.checkCellClicked = null;
    return;
  }
  selData = me.getSelection();
  if (me.getExtensible()) {
    me.getExtensible().disable();
  }
  if (overColumn) {
    recChange = overRecord !== lastOverRecord;
    colChange = overColumn !== lastOverColumn;
    if (selData.isRows || selData.isRecords) {
      if (recChange) {
        if (lastOverRecord) {
          selData.setRangeEnd(overRowIdx);
        } else {
          selData.setRangeStart(overRowIdx);
        }
      }
    } else {
      if (selData.isCells) {
        if (recChange || colChange) {
          if (lastOverRecord) {
            selData.setRangeEnd(location);
          } else {
            selData.setRangeStart(location);
          }
        }
      } else {
        if (selData.isColumns) {
          if (colChange) {
            if (lastOverColumn) {
              selData.setRangeEnd(location.column);
            } else {
              selData.setRangeStart(location.column);
            }
          }
        }
      }
    }
    if (recChange || colChange) {
      view.getNavigationModel().setLocation(location);
    }
    me.lastDragLocation = location;
  }
}, scrollTowardsPointer:function(e, view) {
  var me = this, scrollClientRegion = view.getScrollable().getElement().getClientRegion(), point = e.getXY(), scrollTask = me.scrollTask || (me.scrollTask = Ext.util.TaskManager.newTask({run:me.doAutoScroll, args:[e, view], scope:me, interval:10})), thresh = 25 * (window.devicePixelRatio || 1), scrollDelta = 3 * (window.devicePixelRatio || 1), scrollBy = me.scrollBy || (me.scrollBy = []);
  e.claimGesture();
  if (point[1] > scrollClientRegion.bottom - thresh) {
    scrollBy[0] = 0;
    scrollBy[1] = scrollDelta;
    scrollTask.start();
  } else {
    if (point[1] < scrollClientRegion.top + thresh) {
      scrollBy[0] = 0;
      scrollBy[1] = -scrollDelta;
      scrollTask.start();
    } else {
      if (point[0] > scrollClientRegion.right - thresh) {
        scrollBy[0] = scrollDelta;
        scrollBy[1] = 0;
        scrollTask.start();
      } else {
        if (point[0] < scrollClientRegion.left + thresh) {
          scrollBy[0] = -scrollDelta;
          scrollBy[1] = 0;
          scrollTask.start();
        }
      }
    }
  }
}, doAutoScroll:function(e, view) {
  var me = this, scrollClientRegion = view.getScrollable().getElement().getClientRegion(), scroller = view.getScrollable(), xy = [], cell, location;
  scroller.scrollBy.apply(scroller, me.scrollBy);
  if (me.scrollBy[0]) {
    xy[0] = me.scrollBy[0] > 0 ? scrollClientRegion.right - 5 : scrollClientRegion.left + 5;
  } else {
    xy[0] = e.getX();
  }
  if (me.scrollBy[1]) {
    xy[1] = me.scrollBy[1] > 0 ? scrollClientRegion.bottom - 5 : scrollClientRegion.top + 5;
  } else {
    xy[1] = e.getY();
  }
  cell = document.elementFromPoint.apply(document, xy);
  if (cell) {
    cell = Ext.fly(cell).up(view.cellSelector);
    if (!cell) {
      me.stopAutoScroller();
      return;
    }
    location = new Ext.grid.Location(view, cell);
    if (cell && !location.equals(me.lastDragLocation)) {
      me.changeSelectionRange(view, location, e);
    }
  }
}, stopAutoScroller:function() {
  var me = this;
  if (me.scrollTask) {
    me.scrollBy[0] = me.scrollBy[1] = 0;
    me.scrollTask.stop();
    me.scrollTask = null;
  }
}, onViewDragEnd:function(e) {
  var me = this, view = me.getView(), dragLocation = me.dragLocation, changedCell = !dragLocation || !dragLocation.equals(me.mousedownPosition), location = e.location, sel;
  me.checkCellClicked = null;
  me.stopAutoScroller();
  if (view && !view.destroyed) {
    if (!location) {
      e.location = new Ext.grid.Location(view, e);
    }
    if (me.getExtensible() && changedCell) {
      me.getExtensible().disable();
    }
    me.mousemoveListener.destroy();
    if ((sel = me.getSelection()) && sel.isRows) {
      sel.addRange(true);
    } else {
      if (changedCell) {
        me.fireSelectionChange();
      }
    }
  }
}, onNavigate:function(navigateEvent) {
  var me = this, view = me.getView(), store = me.getStore(), selectingRows = me.getRows(), selectingCells = me.getCells(), selectingColumns = me.getColumns(), checkbox = me.getCheckbox(), checkboxOnly = me.checkboxOnly, mode = me.getMode(), location = navigateEvent.to, toColumn = location.column, record = location.record, sel = me.getSelection(), ctrlKey = navigateEvent.ctrlKey, shiftKey = navigateEvent.shiftKey, adding = true, isSpace = navigateEvent.getKey() === navigateEvent.SPACE, count, changedRow, 
  selectionChanged, selected, continueLocation;
  if (navigateEvent.stopSelection || toColumn === me.checkboxColumn) {
    return;
  }
  if (!navigateEvent.pointerType && !isSpace) {
    if (ctrlKey) {
      return;
    }
    changedRow = !navigateEvent.from || location.recordIndex !== navigateEvent.from.recordIndex;
    if (!changedRow && !(selectingCells || selectingColumns)) {
      return;
    }
  }
  if (sel && (sel.isCells || sel.isColumns && selectingRows && !(ctrlKey || shiftKey)) && sel.getCount() > 1 && !shiftKey && navigateEvent.type === 'click') {
    return;
  }
  if (!(selectingCells || selectingColumns || selectingRows) || !record || navigateEvent.type === 'mousedown') {
    return;
  }
  if (ctrlKey && navigateEvent.keyCode === navigateEvent.A && mode === 'multi') {
    if (!sel || sel.getCount() < 2) {
      me.selectAll();
    } else {
      me.deselectAll();
    }
    me.updateHeaderState();
    return;
  }
  if (shiftKey && mode === 'multi') {
    if (toColumn === me.numbererColumn || toColumn === me.checkColumn || !(selectingCells || selectingColumns) || sel && (sel.isRows || sel.isRecords)) {
      if (selectingRows) {
        if (toColumn !== checkbox && checkboxOnly) {
          return;
        }
        sel = me.getSelection('records');
        if (!sel.getRangeSize()) {
          if (me.selectionStart == null) {
            me.selectionStart = location.recordIndex;
          }
          sel.setRangeStart(me.selectionStart);
        } else {
          continueLocation = new Ext.grid.Location(view, me.getLastSelected());
          sel.setRangeStart(continueLocation.recordIndex);
        }
        sel.setRangeEnd(location.recordIndex);
        selectionChanged = true;
      }
    } else {
      if (selectingCells) {
        sel = me.getSelection('cells');
        count = sel.getCount();
        if (!sel.getRangeSize()) {
          sel.setRangeStart(navigateEvent.from || new Ext.grid.Location(me.getView(), {record:0, column:0}));
        }
        sel.setRangeEnd(location);
        adding = count < sel.getCount();
        selectionChanged = true;
      } else {
        if (selectingColumns) {
          sel = me.getSelection('columns');
          if (!sel.getCount()) {
            sel.setRangeStart(toColumn);
          }
          sel.setRangeEnd(toColumn);
          selectionChanged = true;
        }
      }
    }
  } else {
    me.selectionStart = null;
    if (sel && (mode !== 'multi' || !ctrlKey) && !isSpace) {
      sel.clear(true);
    }
    if (selectingRows && (toColumn === me.numbererColumn || toColumn === checkbox || !selectingCells)) {
      if (toColumn !== checkbox && checkboxOnly || navigateEvent.keyCode && navigateEvent.from && record === navigateEvent.from.record) {
        return;
      }
      sel = me.getSelection('records');
      if (sel.isSelected(record)) {
        if (ctrlKey || toColumn === checkbox || me.getDeselectable()) {
          sel.remove(record);
          selectionChanged = true;
        }
      } else {
        sel.add(record, ctrlKey || toColumn === checkbox);
        selectionChanged = true;
      }
      if (selectionChanged && (selected = sel.getSelected()) && selected.length) {
        me.selectionStart = store.indexOf(selected.first());
        sel.setRangeStart(me.selectionStart);
      }
    } else {
      if (selectingCells) {
        sel = me.getSelection('cells', true);
        sel.setRangeStart(location);
        selectionChanged = true;
      } else {
        if (selectingColumns) {
          sel = me.getSelection('columns');
          if (ctrlKey) {
            if (sel.isSelected(toColumn)) {
              sel.remove(toColumn);
            } else {
              sel.add(toColumn);
            }
          } else {
            sel.setRangeStart(toColumn);
          }
          selectionChanged = true;
        }
      }
    }
  }
  if (selectionChanged) {
    if (!sel.isRecords) {
      me.fireSelectionChange(null, adding);
    }
  }
  me.lastDragLocation = location;
}, isColumnSelected:function(column) {
  var me = this, sel = me.getSelection(), ret = false;
  if (sel && sel.isColumns) {
    ret = sel.isSelected(column);
  }
  return ret;
}, isCellSelected:function(row, column) {
  var sel = this.getSelection();
  if (sel) {
    if (sel.isColumns) {
      if (typeof column === 'number') {
        column = this.getView().getVisibleColumns()[column];
      }
      return sel.isSelected(column);
    }
    if (sel.isCells) {
      return sel.isSelected(row, column);
    }
    return sel.isSelected(row);
  }
  return false;
}, updateSelection:function(selection, oldSelection) {
  var view = this.getView();
  Ext.destroy(oldSelection);
  if (selection && selection.getCount()) {
    view = selection.view;
    if (selection.isRows) {
      selection.eachRow(view.onRowSelect, view);
    } else {
      if (selection.isColumns) {
        selection.eachCell(view.onCellSelect, view);
      } else {
        if (selection.isCells) {
          selection.eachCell(view.onCellSelect, view);
        }
      }
    }
  }
}, updateRows:function(rows) {
  var sel;
  if (!rows) {
    this.setCheckbox(false);
    sel = this.getSelection();
    if (sel && sel.isRows) {
      sel.clear();
    }
  }
}, updateColumns:function(columns) {
  var me = this, view = me.getView(), sel = me.getSelection();
  if (!columns && sel && sel.isColumns) {
    sel.clear();
    me.fireSelectionChange();
  }
  view.toggleCls(me.columnSelectCls, !!columns);
}, updateCells:function(cells) {
  var me = this, sel = me.getSelection();
  if (!cells && sel && sel.isCells) {
    sel.clear();
    me.fireSelectionChange();
  }
}, updateMode:function(mode) {
  if (mode === 'multi') {
    this.setDrag(this.getInitialConfig().drag);
  } else {
    if (!this.isConfiguring) {
      this.setDrag(false);
    }
  }
}, fireSelectionChange:function(records, selecting) {
  var me = this, view = me.getView(), sel = me.getSelection();
  me.updateSelectionExtender();
  me.fireEvent('selectionchange', view, me.getSelection());
  if (sel.isCells) {
    view.fireEvent('selectionchange', view, sel.getRange(), selecting, sel);
  } else {
    view.fireEvent('selectionchange', view, sel.isRecords ? records : sel.isCells ? sel.getRecords() : null, selecting, me.getSelection());
  }
}, updateSelectionExtender:function() {
  var sel = this.getSelection();
  if (sel) {
    sel.onSelectionFinish();
  }
}, onSelectionFinish:function(sel, firstCell, lastCell) {
  var extensible = this.getExtensible();
  if (extensible) {
    extensible.setHandle(firstCell, lastCell);
  }
}, applyExtensible:function(extensible, oldExtensible) {
  var me = this, axes;
  if (!extensible) {
    return undefined;
  }
  if (extensible === true || typeof extensible === 'string') {
    axes = me.axesConfigs[extensible];
    if (oldExtensible) {
      oldExtensible.setAxes(axes);
      return oldExtensible;
    }
    extensible = {axes:axes};
  } else {
    extensible = Ext.Object.chain(extensible);
  }
  extensible.allowReduceSelection = me.getReducible();
  extensible.view = me.getView();
  if (oldExtensible) {
    oldExtensible.destroy();
  }
  return new Ext.grid.selection.SelectionExtender(extensible);
}, applyReducible:function(reducible) {
  return !!reducible;
}, updateReducible:function(reducible) {
  var extensible;
  extensible = this.getConfig('extensible', null, true);
  if (extensible) {
    extensible.allowReduceSelection = reducible;
  }
}, applyCheckbox:function(checkbox) {
  var me = this;
  if (checkbox) {
    me.checkboxOnly = checkbox === 'only';
    me.checkboxColumn = checkbox = Ext.create(me.createCheckboxColumn(me.getCheckboxDefaults()));
  }
  return checkbox;
}, updateCheckbox:function(checkbox, oldCheckbox) {
  var me = this, view;
  if (!me.isConfiguring) {
    view = me.getView();
    if (oldCheckbox) {
      view.unregisterColumn(oldCheckbox, true);
    }
    if (checkbox) {
      view.registerColumn(checkbox);
      me.setRows(true);
    }
  }
}, applyView:function(view) {
  return view.ownerGrid;
}, extendSelection:function(extension) {
  var me = this, view = me.getView(), sel = me.getSelection(), action = extension.reduce ? 'reduce' : 'extend';
  if (view.fireEvent('beforeselectionextend', view, sel, extension) !== false) {
    sel[action + 'Range'](extension);
    if (!sel.isRows) {
      me.fireSelectionChange();
    }
  }
}, onIdChanged:function(store, rec, oldId, newId) {
  var sel = this.getSelection();
  if (sel && sel.isRecords) {
    sel.getSelected().updateKey(rec, oldId);
  }
}, onSelectionStoreAdd:function() {
  this.callParent(arguments);
  this.updateHeaderState();
}, onSelectionStoreClear:function() {
  this.callParent(arguments);
  this.updateHeaderState();
}, onSelectionStoreLoad:function() {
  this.callParent(arguments);
  this.updateHeaderState();
}}}, function(GridModel) {
  var RowNumberer = Ext.ClassManager.get('Ext.grid.column.RowNumberer'), cellCls;
  if (RowNumberer) {
    cellCls = Ext.grid.column.RowNumberer.prototype.cellCls;
    GridModel.prototype.rowNumbererCellCls = (cellCls ? cellCls + ' ' : '') + Ext.baseCSSPrefix + 'selmodel-row-numberer-cell';
  }
});
Ext.define('Ext.grid.plugin.ColumnResizing', {extend:Ext.Component, alias:['plugin.columnresizing', 'plugin.gridcolumnresizing'], config:{grid:null, realtime:false}, hasResizingCls:Ext.baseCSSPrefix + 'has-columnresizing', resizingCls:Ext.baseCSSPrefix + 'resizing', columnSelector:'.' + Ext.baseCSSPrefix + 'gridcolumn', resizerSelector:'.' + Ext.baseCSSPrefix + 'gridcolumn .' + Ext.baseCSSPrefix + 'resizer-el', init:function(grid) {
  this.setGrid(grid);
  grid.getHeaderContainer().setTouchAction({panX:false});
}, updateGrid:function(grid, oldGrid) {
  var me = this, cls = me.hasResizingCls, headerContainer, resizeMarker;
  if (oldGrid) {
    headerContainer = oldGrid.getHeaderContainer();
    headerContainer.renderElement.un({touchstart:'onContainerTouchStart', scope:me, priority:100});
    oldGrid.removeCls(cls);
  }
  if (grid) {
    me._resizeMarker = resizeMarker = grid.resizeMarkerElement;
    me._resizeMarkerParent = resizeMarker.parent();
    headerContainer = grid.getHeaderContainer();
    headerContainer.renderElement.on({touchstart:'onContainerTouchStart', scope:me});
    grid.addCls(cls);
  }
}, onContainerTouchStart:function(e) {
  var me = this, gridHeader = me.getGrid().getHeaderContainer(), target = e.getTarget(me.columnSelector), resizer = e.getTarget(me.resizerSelector), column;
  if (resizer && !e.multitouch && target && !me._resizeColumn) {
    column = Ext.Component.from(target);
    if (column && column.getResizable()) {
      me._startColumnWidth = column.getComputedWidth();
      me._minColumnWidth = column.getMinWidth();
      me._maxColumnWidth = column.getMaxWidth();
      me._resizeColumn = column;
      me._startX = e.getX();
      column.addCls(me.resizingCls);
      gridHeader.renderElement.suspendEvent('drag', 'longpress');
      if (!this.getRealtime()) {
        me._resizeMarker.show();
        me._resizeMarker.setLeft(column.el.getOffsetsTo(me._resizeMarkerParent)[0] + me._startColumnWidth);
      } else {
        column.setWidth(me._startColumnWidth);
      }
      me.touchListeners = Ext.getBody().on({touchEnd:'onTouchEnd', touchMove:'onTouchMove', scope:me, destroyable:true});
    }
  } else {
    if (e.multitouch && me._resizeColumn) {
      me.endResize();
    }
  }
}, onTouchMove:function(e) {
  var me = this, column = me._resizeColumn, resizeAmount;
  if (e.isMultitouch) {
    me.endResize();
  } else {
    if (column) {
      resizeAmount = e.getX() - me._startX;
      me.currentColumnWidth = Math.max(Math.ceil(me._startColumnWidth + resizeAmount), me._minColumnWidth);
      if (me._maxColumnWidth) {
        me.currentColumnWidth = Math.min(me.currentColumnWidth, me._maxColumnWidth);
      }
      if (me.getRealtime()) {
        column.setWidth(me.currentColumnWidth);
        column.renderElement.setWidth(me.currentColumnWidth);
      } else {
        me._resizeMarker.setLeft(column.el.getOffsetsTo(me._resizeMarkerParent)[0] + me.currentColumnWidth);
      }
      column.resizing = true;
      e.claimGesture();
    }
  }
}, onTouchEnd:function(e) {
  var column = this._resizeColumn, hasResized = e.getX() !== this._startX;
  Ext.destroy(this.touchListeners);
  if (column) {
    this.endResize();
    if (!hasResized) {
      column.onResizerTap(e);
    }
  }
}, endResize:function() {
  var me = this, column = me._resizeColumn, grid = me.getGrid();
  if (column) {
    if (!me.getRealtime()) {
      grid.resizeMarkerElement.hide();
    }
    if (me.currentColumnWidth) {
      column.setFlex(null);
      if (column.resizing) {
        column.setWidth(me.currentColumnWidth);
        column.resizing = false;
      } else {
        if (me._resizeColumn.getWidth() === me._startColumnWidth) {
          column.setWidth(me._startColumnWidth);
        }
      }
    }
    column.removeCls(me.resizingCls);
    me._resizeColumn = null;
  }
}});
Ext.define('Ext.dd.ScrollManager', {singleton:true, scrollTowardsPointer:function(component) {
  var me = this, scrollTask = me.scrollTask || (me.scrollTask = Ext.util.TaskManager.newTask({run:Ext.dd.ScrollManager.doAutoScroll, args:[component], scope:me, interval:100}));
  scrollTask.start();
}, stopAutoScroller:function() {
  var me = this;
  if (me.scrollTask) {
    me.scrollTask.stop();
    me.scrollTask = null;
  }
}, doAutoScroll:function(component) {
  var me = this, animate = true, scrollAmount, position, maxPosition, posDiff, posY, direction, scroller;
  if (!me.info) {
    Ext.dd.ScrollManager.stopAutoScroller.apply(me);
    return;
  }
  direction = Ext.dd.ScrollManager.getScrollDirection(component, me.info);
  scroller = component.getScrollable();
  if (!scroller) {
    scroller = me.getViewScrollable();
  }
  if (!direction || !scroller) {
    return;
  }
  scrollAmount = me.scrollAmount;
  position = scroller.position;
  posY = position.y;
  if (component.isLockedGrid) {
    animate = false;
  }
  if (direction === -1) {
    if (posY >= scrollAmount) {
      scroller.scrollBy(0, -scrollAmount, animate);
    } else {
      if (posY > 0) {
        scroller.scrollBy(0, -posY, animate);
      }
    }
  } else {
    maxPosition = scroller.getMaxPosition();
    posDiff = maxPosition.y - posY;
    if (posDiff > 0 && maxPosition.y >= posY) {
      if (posDiff < scrollAmount) {
        scrollAmount = posDiff;
      }
      scroller.scrollBy(0, scrollAmount, animate);
    }
  }
}, getScrollDirection:function(component, info) {
  var bodyBox = component.bodyElement.getBox(), cursorPosition = info.cursor.current, currentPos, percentDiff;
  if (cursorPosition.x > bodyBox.right || cursorPosition.x < bodyBox.left) {
    return 0;
  }
  currentPos = cursorPosition.y - bodyBox.y;
  percentDiff = currentPos / bodyBox.height * 100;
  return percentDiff < 15 ? -1 : percentDiff > 85 ? 1 : 0;
}});
Ext.define('Ext.dd.Manager', {singleton:true, getTargetEl:function(info) {
  var source = info.source, pos = info.cursor.current;
  return source.manager.elementFromPoint(pos.x, pos.y);
}, getPosition:function(info, targetNode, axis) {
  var cursorPosition = info.cursor.current, targetBox = targetNode.element.getBox(), posDiff, nodeSize, percentDiff;
  axis = axis || 'y';
  posDiff = cursorPosition[axis] - targetBox[axis];
  nodeSize = targetNode.element[axis === 'y' ? 'getHeight' : 'getWidth']();
  percentDiff = posDiff / nodeSize * 100;
  return percentDiff < 50 ? 'before' : 'after';
}, toggleTargetNodeCls:function(targetNode, cls, state) {
  var j, clsLen;
  if (Ext.isArray(cls)) {
    clsLen = cls.length;
    for (j = 0; j < clsLen; j++) {
      targetNode.toggleCls(cls[j], state);
    }
  } else {
    targetNode.toggleCls(cls, state);
  }
}, getTargetComp:function(info) {
  var targetEl = this.getTargetEl(info), targetComp;
  if (targetEl) {
    targetComp = Ext.Component.from(targetEl);
    if (targetComp.isGridCell) {
      targetComp = targetComp.row;
    }
  }
  return targetComp;
}, getSourceComp:function(info) {
  return Ext.Component.from(info.eventTarget);
}, toggleMarkerCls:function(view, targetNode, cls, state) {
  var me = this, record, store, visibleGrid, partnerRow, recIndex, ln, i;
  if (view.isLockedGrid) {
    store = view.getStore();
    record = targetNode.getRecord();
    recIndex = store.indexOf(record);
    if (recIndex !== -1) {
      visibleGrid = view.visibleGrids;
      ln = visibleGrid.length;
      for (i = 0; i < ln; i++) {
        partnerRow = visibleGrid[i].getItemAt(recIndex);
        if (partnerRow) {
          me.toggleTargetNodeCls(partnerRow, cls, state);
        }
      }
    }
  } else {
    me.toggleTargetNodeCls(targetNode, cls, state);
  }
}, toggleProxyCls:function(info, cls, state) {
  var proxy = info.proxy;
  if (proxy && proxy.element) {
    proxy.element.toggleCls(cls, state);
  }
}});
Ext.define('Ext.plugin.dd.DragDrop', {extend:Ext.plugin.Abstract, alias:'plugin.viewdragdrop', dragText:undefined, enableDrag:true, containerScroll:true, dropIndicator:null, enableDrop:true, handle:null, groups:null, overCls:'', scrollAmount:80, activateOnLongPress:Ext.supports.Touch && Ext.supports.TouchEvents ? true : false, enable:function() {
  var me = this;
  if (me.dragZone) {
    me.dragZone.unlock();
  }
  if (me.dropZone) {
    me.dropZone.unlock();
  }
}, disable:function() {
  var me = this;
  if (me.dragZone) {
    me.dragZone.lock();
  }
  if (me.dropZone) {
    me.dropZone.lock();
  }
}, destroy:function() {
  var me = this;
  me.dragZone = me.dropZone = Ext.destroy(me.dragZone, me.dropZone);
  me.callParent();
}});
Ext.define('Ext.grid.plugin.HeaderReorder', {extend:Ext.plugin.dd.DragDrop, alias:'plugin.headerreorder', config:{grid:null}, handle:'.' + Ext.baseCSSPrefix + 'gridcolumn', groups:'gridHeaderGroup', dropIndicator:Ext.baseCSSPrefix + 'grid-column-drop-indicator', updateGrid:function(grid, oldGrid) {
  var me = this;
  if (oldGrid) {
    me.dragZone = me.dropZone = Ext.destroy(me.dragZone, me.dropZone);
  }
  if (grid) {
    me.initializeDrag(grid);
  }
}, initializeDrag:function(view) {
  var me = this, headerCt = view.getHeaderContainer(), dragZone = {};
  if (me.enableDrag) {
    if (me.proxy) {
      dragZone.proxy = me.proxy;
    }
    if (me.activateOnLongPress) {
      dragZone.activateOnLongPress = me.activateOnLongPress;
    }
    me.dragZone = new Ext.grid.HeaderDragZone(Ext.apply({element:headerCt.bodyElement, handle:me.handle, groups:me.groups, view:view, constrain:Ext.getBody()}, dragZone));
  }
  if (me.enableDrop) {
    me.dropZone = new Ext.grid.HeaderDropZone({element:headerCt.el, groups:me.groups, view:view, dropIndicator:me.dropIndicator});
  }
}});
Ext.define('Ext.grid.RowHeader', {extend:Ext.dataview.ItemHeader, xtype:'rowheader', classCls:Ext.baseCSSPrefix + 'rowheader', isRowHeader:true, toolDefaults:{ui:'itemheader rowheader'}, privates:{augmentToolHandler:function(tool, args) {
  this.callParent([tool, args]);
  args[1].grid = args[1].list;
}, getGroupHeaderTplData:function() {
  var data = this.callParent([true]), grid = this.parent, partners = grid.allPartners || [grid], len = partners.length, i, p, column;
  if (data) {
    for (i = 0; i < len; ++i) {
      p = partners[i];
      column = p.getColumnForField(data.groupField);
      if (column) {
        break;
      }
    }
  }
  if (column) {
    data.columnName = column.getText();
    if (column.printValue) {
      data.html = column.printValue(data.value);
    }
  } else {
    if (data) {
      data.html = Ext.htmlEncode(data.name);
    }
  }
  return data;
}}});
Ext.define('Ext.grid.Grid', {extend:Ext.dataview.List, xtype:'grid', isGrid:true, mixins:[Ext.mixin.ConfigProxy], storeEventListeners:{sort:'onStoreSort'}, config:{columns:null, columnMenu:{cached:true, $value:{xtype:'menu', weighted:true, align:'tl-bl?', hideOnParentHide:false, items:{sortAsc:{xtype:'gridsortascmenuitem', group:'sortDir', weight:-100}, sortDesc:{xtype:'gridsortdescmenuitem', group:'sortDir', weight:-90}, groupByThis:{xtype:'gridgroupbythismenuitem', handler:'column.onGroupByThis', 
separator:true, weight:-50}, showInGroups:{xtype:'gridshowingroupsmenuitem', handler:'column.onToggleShowInGroups', weight:-40}}}}, columnResize:true, headerContainer:{xtype:'headercontainer'}, hideHeaders:false, enableColumnMove:true, hideScrollbar:null, itemsFocusable:false, title:'', titleBar:{xtype:'titlebar', docked:'top'}, sortable:true, multiColumnSort:false, columnsMenuItem:{lazy:true, $value:{xtype:'gridcolumnsmenu', weight:-80, separator:true}}, columnLines:null, rowNumbers:null}, itemConfig:{xtype:'gridrow'}, 
groupHeader:{xtype:'rowheader'}, infinite:true, navigationModel:'grid', pinnedHeader:{xtype:'rowheader'}, scrollable:true, scrollToTopOnRefresh:false, striped:true, proxyConfig:{headerContainer:['reserveScrollbar']}, selectionModel:'grid', classCls:Ext.baseCSSPrefix + 'grid', columnLinesCls:Ext.baseCSSPrefix + 'column-lines', getTemplate:function() {
  var template = this.callParent();
  template.push({reference:'resizeMarkerElement', className:Ext.baseCSSPrefix + 'resize-marker-el', hidden:true});
  return template;
}, beforeInitialize:function() {
  this.ownerGrid = this;
  this.callParent();
}, initialize:function() {
  var me = this, columns = me.getColumns(), persist = me.registeredColumns, titleBar = me.getTitleBar(), headerContainer = me.getHeaderContainer(), scroller = me.getScrollable(), selectable = me.getSelectable();
  me.callParent();
  if (scroller) {
    headerContainer.getScrollable().addPartner(scroller, 'x');
  }
  if (titleBar) {
    me.insert(0, titleBar);
  }
  me.add(headerContainer);
  if (selectable) {
    selectable.onViewCreated(me);
  }
  if (!columns.length && persist && persist.length) {
    headerContainer.add(persist);
  }
}, doDestroy:function() {
  this.destroyMembers('columnsMenu', 'columnsMenuItem', 'rowNumbererColumn');
  this.callParent();
}, addColumn:function(column) {
  return this.getHeaderContainer().add(column);
}, addSharedMenuItem:function(sharedItem) {
  (this.sharedMenuItems || (this.sharedMenuItems = [])).push(sharedItem);
}, removeSharedMenuItem:function(sharedItem) {
  var sharedMenuItems = this.sharedMenuItems;
  if (sharedMenuItems) {
    Ext.Array.remove(sharedMenuItems, sharedItem);
  }
}, beforeShowColumnMenu:function(column, menu) {
  var me = this, i, n, item, sharedMenuItems;
  me.getColumnsMenuItem();
  sharedMenuItems = me.sharedMenuItems;
  for (i = 0, n = sharedMenuItems && sharedMenuItems.length; i < n; ++i) {
    item = sharedMenuItems[i];
    item.onBeforeShowColumnMenu(menu, column, me);
  }
  return me.fireEvent('beforeshowcolumnmenu', me, column, menu);
}, onColumnMenuHide:function(column, menu) {
  var me = this, sharedMenuItems = me.sharedMenuItems, n = sharedMenuItems && sharedMenuItems.length, i, item;
  for (i = 0; i < n; ++i) {
    item = sharedMenuItems[i];
    if (!item.destroyed && !item.destroying && !menu.isHidden()) {
      item.onColumnMenuHide(menu, column, me);
    }
  }
}, getColumnForField:function(fieldName) {
  return this.getHeaderContainer().getColumnForField(fieldName);
}, getColumns:function(selector) {
  return this.getHeaderContainer().getColumns(selector);
}, getVisibleColumns:function() {
  return this.getHeaderContainer().getVisibleColumns();
}, insertColumn:function(index, column) {
  return this.getHeaderContainer().insert(index, column);
}, insertColumnBefore:function(column, before) {
  var ret;
  if (!before) {
    ret = this.getHeaderContainer().add(column);
  } else {
    ret = before.getParent().insertBefore(column, before);
  }
  return ret;
}, mapToCell:function(value, column) {
  var me = this, ret;
  if (value) {
    if (value.isGridCell && value.row.getGrid() === me) {
      ret = value;
    } else {
      if (value.isEntity) {
        value = me.mapToItem(value);
      }
      if (value) {
        if (value.isGridRow) {
          column = column || me.getFirstVisibleColumn();
          if (column) {
            ret = value.getCellByColumn(column);
          }
        } else {
          ret = Ext.Component.from(value, me.innerCt, 'gridcellbase');
        }
      }
    }
  }
  return ret || null;
}, mapToItem:function(value, as) {
  if (value && value.isGridCell) {
    value = value.row;
  }
  return this.callParent([value, as]);
}, mapToRowBody:function(value) {
  if (value) {
    if (!value.isGridRow) {
      value = this.mapToItem(value);
    }
    if (value && value.isGridRow) {
      value = value.getBody();
    }
  }
  return value || null;
}, removeColumn:function(column) {
  return this.getHeaderContainer().remove(column);
}, registerActionable:function(actionable) {
  this.getNavigationModel().registerActionable(actionable);
}, unregisterActionable:function(actionable) {
  this.getNavigationModel().unregisterActionable(actionable);
}, onColumnAdd:function(container, column, columnIndex) {
  var me = this, items, ln, i, row;
  if (!me.initializingColumns && !me.destroying) {
    items = me.items.items;
    ln = items.length;
    for (i = 0; i < ln; i++) {
      row = items[i];
      if (row.hasGridCells) {
        row.insertColumn(columnIndex, column);
      }
    }
    me.onColumnChange('columnadd', [me, column, columnIndex]);
  }
}, onColumnHide:function(container, column) {
  var me = this, items, ln, i, row;
  if (me.initialized && !me.destroying) {
    items = me.items.items;
    ln = items.length;
    for (i = 0; i < ln; i++) {
      row = items[i];
      if (row.hasGridCells) {
        row.hideColumn(column);
      }
    }
    me.onColumnChange('columnhide', [me, column]);
  }
}, onColumnMove:function(container, columns, group, fromIdx) {
  var me = this, before = null, colLen = columns.length, items, ln, i, j, row, column, index, leaves;
  if (me.initialized && !me.destroying) {
    items = me.items.items;
    ln = items.length;
    leaves = me.getHeaderContainer().getColumns();
    index = leaves.indexOf(columns[colLen - 1]);
    before = leaves[index + 1] || null;
    for (i = colLen - 1; i >= 0; --i) {
      column = columns[i];
      for (j = 0; j < ln; j++) {
        row = items[j];
        if (row.hasGridCells) {
          row.insertColumnBefore(column, before);
        }
      }
      me.onColumnChange('columnmove', [me, column, fromIdx + i, leaves.indexOf(column)]);
      before = column;
    }
  }
}, onColumnRemove:function(container, column) {
  var me = this, items, ln, i, row;
  if (me.initialized && !me.destroying) {
    if (column === me.sortedColumn) {
      me.sortedColumn = null;
    }
    items = me.items.items;
    ln = items.length;
    for (i = 0; i < ln; i++) {
      row = items[i];
      if (row.hasGridCells) {
        row.removeColumn(column);
      }
    }
    me.onColumnChange('columnremove', [me, column]);
  }
}, onColumnResize:function(container, column, width, oldWidth) {
  var me = this;
  if (!me.destroying) {
    if (oldWidth && !column.getHidden()) {
      if (me.infinite) {
        me.refreshScrollerSize();
      }
      me.fireEvent('columnresize', me, column, width);
    }
  }
}, onColumnShow:function(container, column) {
  var me = this, items, ln, i, row;
  if (me.initialized && !me.destroying) {
    items = me.items.items;
    ln = items.length;
    for (i = 0; i < ln; i++) {
      row = items[i];
      if (row.hasGridCells) {
        row.showColumn(column);
      }
    }
    me.onColumnChange('columnshow', [me, column]);
  }
}, onColumnSort:function(container, column, direction) {
  this.fireEvent('columnsort', this, column, direction);
}, onRender:function() {
  var hideHeaders = this._hideHeaders;
  this.callParent();
  if (hideHeaders) {
    this.updateHideHeaders(hideHeaders);
  }
}, privates:{dataItemMap:{header:1, footer:1}, handleStoreSort:function() {
  if (this.rendered) {
    this.getHeaderContainer().setSortState();
  }
}, onStoreGroupChange:function(store, grouper) {
  this.callParent([store, grouper]);
  this.handleStoreSort();
}, onStoreSort:function() {
  this.handleStoreSort();
}, registerColumn:function(column) {
  var me = this, columns = me.registeredColumns, headerCt = me.getHeaderContainer();
  if (!column.isGridColumn) {
    column = Ext.create(column);
  }
  if (!columns) {
    me.registeredColumns = columns = [];
  }
  columns.push(column);
  if (!me.isConfiguring || headerCt && headerCt.items.getCount()) {
    headerCt.add(column);
  }
  return column;
}, unregisterColumn:function(column, destroy) {
  var columns = this.registeredColumns, headerCt = this.getHeaderContainer();
  if (!this.destroying) {
    if (columns) {
      Ext.Array.remove(columns, column);
    }
    if (headerCt) {
      headerCt.remove(column, destroy === true);
    }
  }
  return column;
}, generateSelectorFunctions:function() {
  var me = this;
  me.callParent();
  me.eventDelegate = function(candidate) {
    var comp = Ext.Component.from(candidate), ret = true, row;
    if (!comp || comp === me) {
      return false;
    }
    if (comp.getRefOwner() === me) {
      ret = comp.isGridRow || me.dataItemMap[comp.$dataItem];
    } else {
      row = comp.row;
      ret = row && row.isGridRow && (row.grid || row.list) === me;
    }
    return ret;
  };
}, getFirstVisibleColumn:function() {
  var columns = this.getVisibleColumns();
  return columns.length ? columns[0] : null;
}, getLastVisibleColumn:function() {
  var columns = this.getVisibleColumns(), len = columns.length;
  return len ? columns[len - 1] : null;
}, isFirstVisibleColumn:function(column) {
  return this.getFirstVisibleColumn() === column;
}, isLastVisibleColumn:function(column) {
  return this.getLastVisibleColumn() === column;
}, createDataItem:function(cfg) {
  var item = this.callParent([cfg]);
  item.grid = this;
  return item;
}, onColumnChange:function(changeEvent, eventArgs) {
  var me = this;
  if (changeEvent !== 'columnmove' && changeEvent !== 'columnadd' && changeEvent !== 'columnremove') {
    me.refreshInnerWidth();
  }
  if (!me.isConfiguring) {
    me.fireEventArgs(changeEvent, eventArgs);
  }
  me.clearItemCaches();
}, refreshInnerWidth:function() {
  var body = this.getHeaderContainer().bodyElement.dom;
  this.setInnerWidth(Math.max(body.scrollWidth, body.clientWidth));
}, onColumnComputedWidthChange:function(changedColumns, totalColumnWidth) {
  var me = this, groupingInfo = me.groupingInfo;
  if (!me.destroying) {
    me.setInnerWidth(totalColumnWidth);
    me.setCellSizes(changedColumns, me.items.items);
    me.setCellSizes(changedColumns, me.itemCache);
    if (me.isGrouping()) {
      me.setCellSizes(changedColumns, groupingInfo.header.unused);
      me.setCellSizes(changedColumns, groupingInfo.footer.unused);
    }
    if (me.hasListeners.columnlayout) {
      me.fireEvent('columnlayout', me, changedColumns, totalColumnWidth);
    }
  }
}, onCellSelect:function(location) {
  var cell = location.getCell();
  if (cell) {
    cell.addCls(this.selectedCls);
  }
}, onCellDeselect:function(location) {
  var cell = location.getCell();
  if (cell) {
    cell.removeCls(this.selectedCls);
  }
}, setCellSizes:function(changedColumns, items) {
  var len = items.length, changedColCount = changedColumns.length, row, i, j;
  for (i = 0; i < len; i++) {
    row = items[i];
    if (row.hasGridCells) {
      for (j = 0; j < changedColCount; j++) {
        row.setColumnWidth(changedColumns[j]);
      }
    }
  }
}, updateColumnLines:function(columnLines) {
  this.el.toggleCls(this.columnLinesCls, columnLines);
}, updateColumnResize:function(enabled) {
  var me = this, plugin = me.findPlugin('columnresizing');
  if (!plugin) {
    if (enabled) {
      me.addPlugin('columnresizing');
    }
  } else {
    plugin.setGrid(enabled ? me : null);
  }
}, updateColumns:function(columns) {
  var me = this, header = me.getHeaderContainer(), count = columns && columns.length, persist = me.registeredColumns;
  if (header) {
    me.rowHeight = null;
    if (header) {
      header.beginColumnUpdate();
      if (header.getItems().getCount()) {
        if (persist) {
          header.remove(persist, false);
        }
        if (count) {
          header.remove(columns.filter(function(col) {
            return col.isInstance;
          }), false);
        }
        header.removeAll(true, true);
      }
      if (count) {
        me.initializingColumns = me.isConfiguring;
        header.setColumns(columns);
        if (persist) {
          header.add(persist);
        }
        delete me.initializingColumns;
      }
      header.endColumnUpdate();
    }
  }
}, applyStore:function(store, oldStore) {
  var me = this, ret = me.callParent([store, oldStore]);
  if (ret && ret.isVirtualStore && me.getGrouped()) {
    Ext.Logger.warn('Virtual store does not suppport grouping');
  }
  return ret;
}, applyRowNumbers:function(rowNumbers) {
  var me = this;
  if (rowNumbers) {
    rowNumbers = me.rowNumbererColumn = Ext.create(Ext.apply({xtype:'rownumberer', weight:-1000, editRenderer:me.renderEmpty}, rowNumbers));
  }
  return rowNumbers;
}, updateRowNumbers:function(rowNumbers, oldRowNumbers) {
  if (oldRowNumbers) {
    this.unregisterColumn(oldRowNumbers, true);
  }
  if (rowNumbers) {
    this.registerColumn(rowNumbers);
  }
}, renderEmpty:function() {
  return ' ';
}, applyColumnsMenuItem:function(config, existing) {
  return Ext.updateWidget(existing, config, this, 'createColumnsMenuItem');
}, createColumnsMenuItem:function(config) {
  return Ext.apply({grid:this}, config);
}, applyHeaderContainer:function(config, existing) {
  return Ext.updateWidget(existing, config, this, 'createHeaderContainer');
}, createHeaderContainer:function(config) {
  config = this.mergeProxiedConfigs('headerContainer', config, true);
  config.sortable = this.getSortable();
  config.grid = this;
  return config;
}, updateHeaderContainer:function(headerContainer) {
  if (headerContainer) {
    headerContainer.on({columnresize:'onColumnResize', columnshow:'onColumnShow', columnhide:'onColumnHide', columnadd:'onColumnAdd', columnmove:'onColumnMove', columnremove:'onColumnRemove', columnsort:'onColumnSort', scope:this});
  }
}, updateHideHeaders:function(hideHeaders) {
  if (this.rendered) {
    var headerContainer = this.getHeaderContainer();
    if (hideHeaders) {
      headerContainer.el.setStyle({visibility:'hidden', marginBottom:'-' + headerContainer.el.measure('h') + 'px'});
    } else {
      headerContainer.el.setStyle({visibility:'', marginBottom:''});
    }
  }
}, updateHideScrollbar:function(hide) {
  var w = Ext.scrollbar.width();
  this.element.setStyle('margin-right', hide ? -w + 'px' : '');
}, updateTitle:function(title) {
  var titleBar = this.getTitleBar();
  if (titleBar) {
    if (title) {
      titleBar.setTitle(title);
      if (titleBar.isHidden()) {
        titleBar.show();
      }
    } else {
      titleBar.hide();
    }
  }
}, applyTitleBar:function(config, existing) {
  return Ext.updateWidget(existing, config);
}, updateTitleBar:function(titleBar) {
  if (titleBar && !titleBar.getTitle()) {
    titleBar.setTitle(this.getTitle());
  }
}, applyTotalColumnWidth:function(totalColumnWidth) {
  var rows = this.dataItems;
  return rows.length === 0 ? undefined : totalColumnWidth;
}, updateVerticalOverflow:function(value, was) {
  var headerContainer = this.getHeaderContainer(), summaryRow = this.findPlugin('summaryrow') || this.findPlugin('gridsummaryrow'), scrollable = this.getScrollable(), verticalScrollbarWidth = scrollable && scrollable.getScrollbarSize().width, y = !!(scrollable && scrollable.getY()), addOverflow = y && verticalScrollbarWidth > 0 && value, row;
  this.callParent([value, was]);
  headerContainer.setVerticalOverflow(addOverflow);
  if (summaryRow) {
    row = summaryRow.getRow();
    if (!row.destroyed) {
      row.rightSpacer.setStyle({width:(addOverflow ? verticalScrollbarWidth - 1 : 0) + 'px'});
    }
  }
}, updateEnableColumnMove:function(enabled) {
  var me = this, plugin = me.findPlugin('headerreorder');
  if (!plugin && enabled) {
    plugin = me.addPlugin('headerreorder');
  }
  if (plugin) {
    plugin.setGrid(enabled ? me : null);
  }
}, getSelection:function() {
  var me = this, selectable = me.getSelectable(), selection = selectable.getSelection(), selectionType = selection.type;
  if (selectionType === 'columns') {
    return selection.lastColumnSelected;
  }
  if (selectionType === 'cells') {
    return selection.endCell && selection.endCell.record;
  }
  return this.callParent();
}}}, function(Grid) {
  Grid.prototype.indexModifiedFields = Ext.Array.toMap;
});
Ext.define('Ext.theme.material.grid.Grid', {override:'Ext.grid.Grid', config:{rowLines:true, striped:false}});
Ext.define('Ext.plugin.dd.DragZone', {extend:Ext.drag.Source, dragMarkerCls:Ext.baseCSSPrefix + 'drag-indicator', describe:function(info) {
  var dragData = this.getDragData(info.eventTarget);
  info.setData('dragData', dragData);
}, proxy:{type:'placeholder', cls:Ext.baseCSSPrefix + 'proxy-drag-el', cursorOffset:Ext.supports.Touch && Ext.supports.TouchEvents ? [44, -75] : [12, 20]}, beforeDragStart:function(info) {
  var proxy = this.getProxy();
  if (proxy && proxy.setHtml) {
    proxy.setHtml(this.getDragText(info));
  }
}, getDragText:function(info) {
  return '';
}, getDragData:Ext.emptyFn});
Ext.define('Ext.plugin.dd.DropZone', {extend:Ext.drag.Target, dropMarkerCls:Ext.baseCSSPrefix + 'drop-indicator', validDropCls:Ext.baseCSSPrefix + 'valid-drop', onDragMove:Ext.emptyFn, onDrop:Ext.emptyFn, onDragLeave:function(info) {
  this.removeDropMarker();
  Ext.dd.Manager.toggleProxyCls(info, this.validDropCls, false);
}, getViewScrollable:Ext.emptyFn, removeDropMarker:Ext.emptyFn});
Ext.define('Ext.grid.GridDropZone', {extend:Ext.plugin.dd.DropZone, onDragMove:function(info) {
  var me = this, ddManager = Ext.dd.Manager, targetCmp = ddManager.getTargetComp(info), ddRecords, isSameGroup, highlight, store, targetRecord, isValidTarget, positionCls;
  highlight = ddManager.getPosition(info, targetCmp);
  positionCls = me.dropMarkerCls + '-' + highlight;
  if (!targetCmp || targetCmp.hasCls(positionCls)) {
    return;
  }
  if (targetCmp.getRecord) {
    targetRecord = targetCmp.getRecord();
  }
  isSameGroup = Ext.Array.intersect(me.getGroups(), info.source.getGroups()).length;
  if (!targetRecord || !isSameGroup) {
    if (targetCmp.getStore) {
      store = targetCmp.getStore();
    }
    if (!store || store && store.getCount() > 0) {
      return;
    }
  }
  ddRecords = info.data.dragData.records;
  isValidTarget = ddRecords.indexOf(targetRecord) === -1;
  if (me.ddEl) {
    me.removeDropMarker();
  }
  if (isValidTarget) {
    me.addDropMarker(targetCmp, [me.dropIndicator, positionCls]);
    me.ddEl = targetCmp;
  }
}, onDrop:function(info) {
  var me = this, draggedData, position, targetNode, targetComponent, targetRecord, component;
  if (!me.ddEl) {
    return;
  }
  draggedData = info.data.dragData;
  position = me.ddEl.hasCls(me.dropMarkerCls + '-before') ? 'before' : 'after';
  targetNode = Ext.dd.Manager.getTargetComp(info);
  if (targetNode.isGridRow) {
    targetComponent = targetNode.parent;
  }
  targetRecord = targetNode.getRecord();
  component = me.view;
  if (component.fireEvent('beforedrop', targetNode, draggedData, targetRecord, position) !== false) {
    me.onNodeDrop(draggedData, targetRecord, position, targetComponent || component);
    component.fireEvent('drop', targetNode, draggedData, targetRecord, position);
  }
  me.removeDropMarker();
}, onNodeDrop:function(data, record, position, targetComponent) {
  var sourceView = data.view, targetStore = targetComponent.getStore(), crossView = targetComponent !== sourceView, records = data.records, removeRecord = crossView || records.length > 1, index, i, len, selModel, selectable;
  if (this.copy) {
    len = records.length;
    for (i = 0; i < len; i++) {
      records[i] = records[i].copy();
    }
  } else {
    if (removeRecord) {
      sourceView.getStore().remove(records);
    }
  }
  if (record && position) {
    index = targetStore.indexOf(record);
    if (position !== 'before') {
      index++;
    }
    targetStore.insert(index, records);
  } else {
    targetStore.add(records);
  }
  if (removeRecord) {
    selectable = targetComponent.getSelectable();
    selModel = selectable.getSelection().getSelectionModel();
    selModel.select(records);
  }
}, addDropMarker:function(targetNode, positionCls) {
  var me = this, ddManager = Ext.dd.Manager;
  ddManager.toggleProxyCls(me.info, me.validDropCls, true);
  ddManager.toggleMarkerCls(me.view, targetNode, positionCls, true);
  if (me.overCls) {
    ddManager.toggleTargetNodeCls(targetNode, me.overCls, true);
  }
}, removeDropMarker:function() {
  var me = this, prefix = me.dropMarkerCls + '-', ddManager = Ext.dd.Manager, cls;
  if (me.info) {
    ddManager.toggleProxyCls(me.info, me.validDropCls, false);
  }
  if (me.ddEl) {
    cls = [me.dropIndicator, prefix + 'before', prefix + 'after'];
    ddManager.toggleMarkerCls(me.view, me.ddEl, cls, false);
    if (me.overCls) {
      ddManager.toggleTargetNodeCls(me.ddEl, me.overCls, false);
    }
    me.ddEl = null;
  }
}});
Ext.define('Ext.grid.HeaderDragZone', {extend:Ext.plugin.dd.DragZone, autoDestroy:false, resizerCls:Ext.baseCSSPrefix + 'resizer-el', maskCls:Ext.baseCSSPrefix + 'mask', beforeDragStart:function(info) {
  var targetCmp = Ext.dd.Manager.getSourceComp(info), targetEl = targetCmp.renderElement, hoveredNodeEl = Ext.dd.Manager.getTargetEl(info), isDragSuspended = targetEl.isSuspended('drag') || targetEl.isSuspended('longpress');
  if (isDragSuspended || targetCmp.isDragColumn || targetCmp.getDraggable() === false || Ext.fly(info.eventTarget).hasCls(this.resizerCls) || Ext.fly(hoveredNodeEl).hasCls(this.maskCls)) {
    return false;
  }
  this.callParent([info]);
}, getDragText:function(info) {
  var targetCmp = Ext.dd.Manager.getTargetComp(info);
  return targetCmp.getText();
}});
Ext.define('Ext.grid.HeaderDropZone', {extend:Ext.grid.GridDropZone, dropMarkerCls:Ext.baseCSSPrefix + 'header-drop-indicator', autoDestroy:false, isValidDrag:function(targetCmp, sourceCmp) {
  var info = this.info, cursor, prevSibling, nextSibling, box, diff;
  if (!!targetCmp.up(sourceCmp)) {
    return false;
  }
  cursor = info.cursor.current;
  prevSibling = sourceCmp.previousSibling();
  nextSibling = sourceCmp.nextSibling();
  if (targetCmp === prevSibling) {
    box = prevSibling.element.getBox();
    diff = (cursor.x - box.left) / box.width;
    if (diff > 0.5) {
      return false;
    }
  } else {
    if (targetCmp === nextSibling) {
      box = nextSibling.element.getBox();
      diff = (cursor.x - box.left) / box.width;
      if (diff <= 0.5) {
        return false;
      }
    }
  }
  return true;
}, onDragMove:function(info) {
  var me = this, ddManager = Ext.dd.Manager, targetCmp = ddManager.getTargetComp(info), isDragTarget = targetCmp.isDragColumn, sourceCmp = ddManager.getSourceComp(info), notHeader = !targetCmp.isHeaderContainer || !sourceCmp.isHeaderContainer, highlight, positionCls;
  if (notHeader || targetCmp === sourceCmp || isDragTarget || targetCmp.getParent() === me.view) {
    if (this.ddEl) {
      this.removeDropMarker();
    }
    return;
  }
  highlight = ddManager.getPosition(info, targetCmp, 'x');
  positionCls = me.dropMarkerCls + '-' + highlight;
  if (targetCmp.hasCls(positionCls)) {
    return;
  }
  if (this.ddEl) {
    this.removeDropMarker();
  }
  if (me.isValidDrag(targetCmp, sourceCmp)) {
    me.ddEl = targetCmp;
    me.addDropMarker(targetCmp, [me.dropIndicator, positionCls]);
  }
}, trackHeaderMove:function(header, headerCt) {
  var parentCt;
  if (!header || header === headerCt || header.innerItems.length) {
    return;
  }
  parentCt = header.getParent();
  parentCt.remove(header);
  this.trackHeaderMove(parentCt, headerCt);
}, onDrop:function(info) {
  var me = this, dropMethod = 'insertBefore', ddManager, targetCmp, headerCt, sourceCmp, dropAt, position, relativeToItem, fromCtRoot, fromIdx, sourceCmpParent;
  if (!me.ddEl) {
    return;
  }
  ddManager = Ext.dd.Manager;
  targetCmp = ddManager.getTargetComp(info);
  headerCt = targetCmp.getParent() || targetCmp.getRootHeaderCt();
  sourceCmp = ddManager.getSourceComp(info);
  fromCtRoot = sourceCmp.getRootHeaderCt();
  fromIdx = fromCtRoot.indexOf(sourceCmp);
  dropAt = headerCt.indexOf(targetCmp);
  position = ddManager.getPosition(info, targetCmp, 'x');
  sourceCmpParent = sourceCmp.getParent();
  me.removeDropMarker();
  if (dropAt === -1) {
    return;
  }
  if (position === 'after') {
    relativeToItem = headerCt.getAt(dropAt + 1);
    if (!relativeToItem) {
      dropMethod = 'insertAfter';
      relativeToItem = targetCmp;
    }
  } else {
    relativeToItem = headerCt.getAt(dropAt);
  }
  headerCt[dropMethod](sourceCmp, relativeToItem || null);
  me.trackHeaderMove(sourceCmpParent, fromCtRoot);
  fromCtRoot.fireEvent('move', fromCtRoot, sourceCmp, dropAt, fromIdx);
}});
Ext.define('Ext.layout.Fit', {extend:Ext.layout.Auto, alias:'layout.fit', isFit:true, cls:Ext.baseCSSPrefix + 'layout-fit', itemCls:Ext.baseCSSPrefix + 'layout-fit-item'});
Ext.define('Ext.layout.Center', {extend:Ext.layout.Auto, alias:'layout.center', cls:Ext.baseCSSPrefix + 'layout-center', itemCls:Ext.baseCSSPrefix + 'layout-center-item'});
Ext.define('Ext.menu.Separator', {extend:Ext.Component, xtype:'menuseparator', isMenuSeparator:true, focusable:false, classCls:Ext.baseCSSPrefix + 'menuseparator', ariaRole:'separator'});
Ext.define('Ext.panel.Collapser', {mixins:[Ext.mixin.ConfigProxy], config:{animation:{duration:250}, collapseAnimation:null, collapsed:false, collapseToolText:'Collapse panel', direction:'top', drawer:{xtype:'panel', border:true, top:0, left:0, cls:Ext.baseCSSPrefix + 'drawer'}, drawerHideDelay:500, dynamic:null, expandAnimation:null, expandToolText:'Expand panel', target:null, tool:{xtype:'tool', weight:900}, useDrawer:true, state:'expanded'}, proxyConfig:{target:['titleCollapse']}, collapsed:false, 
collapsing:false, expanded:false, expanding:false, extraSpace:0, $unanimated:false, constructor:function(config) {
  this.initConfig(config);
}, initialize:function() {
  var me = this;
  me.rendered = true;
  me.ensureCollapseTool();
  if (me.getCollapsed()) {
    me.doExpandCollapse(true, true);
  }
  me.initialized = true;
  me.setupHeaderListeners();
}, destroy:function() {
  var me = this, active = me.activeOperation, task = me.drawerTask;
  me.destroying = true;
  if (task) {
    task.cancel();
  }
  if (active) {
    active.anim.end();
  }
  if (!me.getTarget().destroying) {
    me.reattachBodyWrap();
  }
  Ext.destroy(me.headerListeners, me.drawerListeners, me.drawer, me.collapsibleTool);
  me.callParent();
}, collapse:function(animation) {
  return this.toggleCollapsed(true, animation);
}, expand:function(animation) {
  return this.toggleCollapsed(false, animation);
}, hideDrawer:function(animation) {
  var me = this, drawer = me.drawer, ret;
  if (me.isSliding || !me.getCollapsed() || !drawer || !me.drawerVisible) {
    return;
  }
  animation = me.parseAnimation(false, animation);
  if (animation) {
    me.getTarget().element.addCls(me.slidingCls);
    ret = me.doAnimation(false, me.getSlideOutCfg(me.getDirection(), me.afterDrawerHide, animation));
    me.isSliding = true;
  } else {
    me.afterDrawerHide();
    ret = Ext.Promise.resolve();
  }
  return ret;
}, isDynamic:function() {
  var dynamic = this.getDynamic(), target;
  if (dynamic === null) {
    target = this.getTarget();
    dynamic = target.getFloated() || !target.getRefOwner();
  }
  return dynamic;
}, showDrawer:function(animation) {
  var me = this, savedProps = me.savedProps, direction = me.getDirection(), target = me.getTarget(), headerSize = me.getHeaderSize(), endDirection = me.endDirection, vertical = me.verticalMap[direction], drawer, w, h, ret, header;
  if (me.isSliding || !me.getCollapsed() || !me.getDrawer()) {
    return Ext.Promise.resolve();
  }
  drawer = me.createDrawer();
  if (vertical) {
    h = '100%';
    w = savedProps.measuredWidth || me.defaultSize;
    drawer.setTop(0);
    drawer.setBottom(0);
    if (endDirection[direction]) {
      drawer.setLeft(null);
      drawer.setRight(headerSize);
    } else {
      drawer.setRight(null);
      drawer.setLeft(headerSize);
    }
  } else {
    w = '100%';
    h = savedProps.measuredHeight || me.defaultSize;
    drawer.setRight(0);
    drawer.setLeft(0);
    if (endDirection[direction]) {
      drawer.setTop(null);
      drawer.setBottom(headerSize);
    } else {
      drawer.setBottom(null);
      drawer.setTop(headerSize);
    }
    if (target.getHeader() && target.getHeaderPosition() === direction) {
      header = drawer.ensureHeader();
      if (header) {
        header.hide();
      }
    }
  }
  me.configureDrawer(drawer, w, h);
  drawer.show();
  animation = me.parseAnimation(false, animation);
  me.isSliding = true;
  if (animation) {
    animation = me.getSlideInCfg(direction, me.afterDrawerShow, animation);
    animation.preserveEndState = true;
    me.getTarget().element.addCls(me.slidingCls);
    ret = me.doAnimation(false, animation);
  } else {
    me.afterDrawerShow();
    ret = Ext.Promise.resolve();
  }
  return ret;
}, toggleCollapsed:function(collapsed, animation) {
  var me = this, target = me.getTarget(), current = me.getCollapsed(), event, info, ret;
  if (me.activeOperation) {
    me.activeOperation.anim.end();
    current = me.getCollapsed();
  }
  if (collapsed === current) {
    return Ext.Promise.resolve();
  }
  if (me.$unanimated) {
    me.$unanimated = animation = false;
  } else {
    if (me.rendered) {
      animation = me.parseAnimation(collapsed, animation);
    } else {
      animation = null;
    }
  }
  event = 'before' + (collapsed ? 'collapse' : 'expand');
  if (me.initialized && target.hasListeners[event]) {
    info = {animation:animation};
    if (target.fireEvent(event, target, info) === false) {
      return Ext.Promise.resolve();
    }
    animation = info.animation;
  }
  me.hideDrawer(false);
  if (animation) {
    ret = me.doExpandCollapseAnimated(collapsed, animation);
  } else {
    ret = me.doExpandCollapse(collapsed);
  }
  return ret;
}, applyAnimation:function(config) {
  if (config === true) {
    config = {};
  }
  return config;
}, updateCollapsed:function(collapsed) {
  var me = this;
  if (me.rendered && !me.preventUpdate) {
    me._collapsed = !collapsed;
    me.toggleCollapsed(collapsed);
  } else {
    me.setState(collapsed ? 'collapsed' : 'expanded');
  }
}, updateCollapseToolText:function(text) {
  this.setToolTextIf(text, this.getCollapsed());
}, updateDirection:function(direction, oldDirection) {
  var me = this;
  if (!me.isConfiguring) {
    if (me.getCollapsed()) {
      me.getTarget().moveHeaderPosition(direction, oldDirection);
    }
    me.ensureCollapseTool();
  }
}, updateDynamic:function(dynamic) {
  var me = this, drawer = me.drawer;
  if (dynamic && drawer) {
    if (me.hasDetachedBody) {
      me.reattachBodyWrap();
    }
    me.drawer = Ext.destroy(drawer);
  }
}, updateExpandToolText:function(text) {
  this.setToolTextIf(text, !this.getCollapsed());
}, updateState:function(state, oldState) {
  var me = this, target = me.getTarget();
  if (oldState) {
    me[oldState] = target[oldState] = false;
  }
  if (state) {
    me[state] = target[state] = true;
  }
}, updateTitleCollapse:function() {
  if (this.rendered) {
    this.setupHeaderListeners();
  }
}, updateUseDrawer:function() {
  if (this.rendered) {
    this.setupHeaderListeners();
  }
}, privates:{animateEndCls:Ext.baseCSSPrefix + 'placeholder-animate-end', collapsingDirections:{top:['up', 'down'], left:['left', 'right'], bottom:['down', 'up'], right:['right', 'left']}, defaultSize:300, endDirection:{right:1, bottom:1}, headerChangePosition:{top:['top', 'bottom'], left:['left', 'right'], bottom:['bottom', 'top'], right:['right', 'left']}, hasDetachedBody:false, rendered:false, slidingCls:Ext.baseCSSPrefix + 'sliding', verticalMap:{right:1, left:1}, afterAnimation:function(active) {
  active.deferred.resolve();
  this.activeOperation = null;
}, afterDrawerHide:function() {
  var me = this, target = me.getTarget(), active = me.activeOperation, drawer = me.drawer, header;
  target.element.removeCls(me.slidingCls);
  me.drawerVisible = me.isSliding = false;
  if (!me.destroying) {
    me.drawerListeners = Ext.destroy(me.drawerListeners);
    drawer.hide();
    header = drawer.getHeader();
    if (header) {
      header.show();
    }
    target.fireEvent('drawerhide', target);
  }
  if (active) {
    me.afterAnimation(active);
  }
}, afterDrawerShow:function() {
  var me = this, active = me.activeOperation, drawerListeners, listenerCfg, target = me.getTarget(), header;
  me.isSliding = false;
  me.drawerVisible = true;
  if (!me.destroying) {
    target.element.removeCls(me.slidingCls);
    listenerCfg = {mouseleave:'handleElMouseLeave', mouseenter:'handleElMouseEnter', scope:me, destroyable:true};
    drawerListeners = [Ext.on('mousedown', 'handleGlobalDrawerEvent', me, {destroyable:true}), Ext.getDoc().on('mousemove', 'handleGlobalDrawerEvent', me, {destroyable:true}), me.drawer.element.on(listenerCfg)];
    header = target.getHeader();
    if (header) {
      drawerListeners.push(header.element.on(listenerCfg));
    }
    me.drawerListeners = drawerListeners;
    target.fireEvent('drawershow', target);
  }
  if (active) {
    me.afterAnimation(active);
  }
}, afterExpandCollapseAnimation:function() {
  var me = this, active = me.activeOperation, target = me.getTarget(), cls = active.animCls, anim, header, bodyWrap;
  if (!me.destroying) {
    header = target.getHeader();
    if (active.placeHolder) {
      me.drawer.hide();
    }
    if (active.reattach) {
      me.reattachBodyWrap();
    }
    if (header && active.restoreHeaderVis) {
      header.element.setVisibility(true);
    }
    if (cls) {
      target.element.removeCls(cls);
    }
    if (active.restore) {
      anim = active.anim.config;
      if (anim.to.height) {
        anim.element.setHeight(null);
      }
      if (anim.to.width) {
        anim.element.setWidth(null);
      }
      me.restoreProps();
      bodyWrap = target.bodyWrapElement;
      bodyWrap.setWidth(null).setHeight(null);
      header = header && header.element;
      if (header) {
        header.setWidth(null).setHeight(null);
      }
    }
    me.afterExpandCollapse(active.collapsed, true);
  }
  me.afterAnimation(active);
}, afterExpandCollapse:function(collapsed) {
  var me = this, target = me.getTarget(), types = me.headerChangePosition, direction = me.getDirection(), headerPosition = target.getHeaderPosition(), event = collapsed ? 'collapse' : 'expand', globals = Ext.GlobalEvents;
  target.bodyWrapElement.setVisible(!collapsed);
  if (types[headerPosition].indexOf(direction) < 0) {
    target.moveHeaderPosition(collapsed ? direction : headerPosition, !collapsed ? direction : headerPosition);
  }
  me.setState(collapsed ? 'collapsed' : 'expanded');
  me.preventUpdate = true;
  target._collapsed = !collapsed;
  target.setCollapsed(collapsed);
  me.preventUpdate = false;
  me.ensureCollapseTool();
  target.toggleCls(me.expandedCls, !collapsed);
  if (me.initialized) {
    if (target.hasListeners[event]) {
      target.fireEvent(event, target);
    }
    if (globals.hasListeners[event]) {
      globals.fireEvent(event, target);
    }
  }
}, createDrawer:function() {
  var me = this, p = me.drawer;
  if (!p) {
    me.drawer = p = Ext.create(me.getDrawer());
    p.bodyWrapElement.hide();
  }
  return p;
}, configureDrawer:function(drawer, width, height, resetPos) {
  var me = this, target = me.getTarget(), bodyWrap = target.bodyWrapElement;
  drawer.setTitle(target.getTitle());
  drawer.setWidth(width);
  drawer.setHeight(height);
  if (resetPos) {
    drawer.setTop(0);
    drawer.setRight(null);
    drawer.setBottom(null);
    drawer.setLeft(0);
  }
  drawer.element.append(bodyWrap);
  me.getContainerTarget().appendChild(drawer.element);
  bodyWrap.show();
  drawer.show();
  me.hasDetachedBody = true;
}, doAnimation:function(collapsed, animation, activeOperation) {
  var deferred, anim;
  activeOperation = activeOperation || {};
  deferred = activeOperation.deferred || new Ext.Deferred;
  anim = new Ext.fx.Animation(animation);
  activeOperation.anim = anim;
  activeOperation.deferred = deferred;
  activeOperation.collapsed = collapsed;
  this.activeOperation = activeOperation;
  Ext.Animator.run(anim);
  return deferred.promise;
}, doExpandCollapse:function(collapsed, initial) {
  var me = this, target = me.getTarget(), direction;
  if (me.rendered) {
    if (collapsed) {
      me.saveProps();
      target.setFlex(null);
      direction = me.getDirection();
      if (direction === 'top' || direction === 'bottom') {
        target.setHeight(null);
      } else {
        target.setWidth(null);
      }
    } else {
      me.reattachBodyWrap();
      me.restoreProps();
    }
    me.afterExpandCollapse(collapsed);
  }
  return initial ? null : Ext.Promise.resolve();
}, doExpandCollapseAnimated:function(collapsed, animation) {
  var me = this;
  me.setState(collapsed ? 'collapsing' : 'expanding');
  if (me.isDynamic()) {
    return me.doExpandCollapseDynamic(collapsed, animation);
  }
  return me.doExpandCollapsePlaceholder(collapsed, animation);
}, doExpandCollapseDynamic:function(collapsed, animation) {
  var me = this, target = me.getTarget(), headerPosition = target.getHeaderPosition(), direction = me.getDirection(), targetEl = target.element, bodyWrap = target.bodyWrapElement, header = target.getHeader(), headerEl = header && header.element, from = {}, to = {}, directionVertical = direction === 'top' || direction === 'bottom', headerVertical = headerPosition === 'top' || headerPosition === 'bottom', headerSize = me.getHeaderSize(), headerDifferent = headerPosition !== direction, extraSpace = 
  me.extraSpace, height, width, savedProps, size;
  me.extraSpace = 0;
  if (collapsed) {
    savedProps = me.saveProps();
    height = savedProps.measuredHeight;
    width = savedProps.measuredWidth;
    if (directionVertical) {
      me.measureAndSet(bodyWrap, 'Height');
      if (headerDifferent) {
        me.measureAndSet(headerEl, 'Height');
      }
      from.height = height;
      to.height = headerVertical ? headerSize : 0;
      target.setHeight(null);
      target.setMinHeight(null);
    } else {
      me.measureAndSet(bodyWrap, 'Width');
      if (headerDifferent) {
        me.measureAndSet(headerEl, 'Width');
      }
      from.width = width;
      to.width = headerVertical ? headerSize : 0;
      target.setWidth(null);
      target.setMinWidth(null);
    }
    target.setFlex(null);
  } else {
    headerDifferent = headerPosition !== direction;
    me.reattachBodyWrap();
    if (directionVertical) {
      targetEl.setHeight(null);
    } else {
      targetEl.setWidth(null);
    }
    me.restoreProps(true);
    if (headerDifferent) {
      target.moveHeaderPosition(collapsed ? direction : headerPosition, !collapsed ? direction : headerPosition);
    }
    bodyWrap.show();
    if (headerEl) {
      headerEl.setWidth(null).setHeight(null);
    }
    me.measureAndSet(bodyWrap, directionVertical ? 'Height' : 'Width', true);
    size = targetEl.measure();
    height = size.height;
    width = size.width;
    target.setFlex(null);
    me.measureAndSet(headerEl, directionVertical ? 'Height' : 'Width');
    if (directionVertical) {
      from.height = headerSize;
      to.height = height + extraSpace;
      target.setHeight(null);
    } else {
      from.width = headerSize;
      to.width = width + extraSpace;
      target.setWidth(null);
    }
  }
  return me.doAnimation(collapsed, Ext.apply({scope:me, callback:me.afterExpandCollapseAnimation, element:targetEl, preserveEndState:true, from:from, to:to}, animation), {restore:!collapsed});
}, doExpandCollapsePlaceholder:function(collapsed, animation) {
  var me = this, types = me.collapsingDirections, target = me.getTarget(), targetEl = target.element, headerPosition = target.getHeaderPosition(), direction = me.getDirection(), directionVertical = direction === 'top' || direction === 'bottom', headerVertical = headerPosition === 'top' || headerPosition === 'bottom', header = target.getHeader(), headerDifferent = directionVertical !== headerVertical, containerBox = me.getContainerTarget().getBox(), height, width, drawer, anim, animCls, restoreHeaderVis, 
  savedProps, size, active;
  drawer = me.createDrawer();
  if (collapsed) {
    savedProps = me.saveProps();
    height = savedProps.measuredHeight;
    width = savedProps.measuredWidth;
  } else {
    me.reattachBodyWrap();
    me.restoreProps(true);
    size = targetEl.measure();
    height = size.height;
    width = size.width;
  }
  me.configureDrawer(drawer, width, height, true);
  drawer.setLeft(targetEl.getLeft() - containerBox.left);
  drawer.setTop(targetEl.getTop() - containerBox.top);
  if (directionVertical) {
    target.setHeight(null);
    target.setMinHeight(null);
  } else {
    target.setWidth(null);
    target.setMinWidth(null);
  }
  target.setFlex(null);
  if (collapsed) {
    if (headerDifferent && types[headerPosition].indexOf(direction) < 0) {
      target.moveHeaderPosition(collapsed ? direction : headerPosition, !collapsed ? direction : headerPosition);
    }
    if (header) {
      header.element.setVisibility(false);
    }
    anim = me.getSlideOutCfg(direction, function() {
      if (me.destroying) {
        return;
      }
      active = me.activeOperation;
      drawer.hide();
      if (header) {
        header.element.setVisibility(true);
        me.doAnimation(collapsed, {type:'slideIn', element:header.element, reverse:true, direction:direction, isElementBoxFit:false, scope:me, callback:me.afterExpandCollapseAnimation}, active);
      } else {
        me.afterExpandCollapseAnimation();
      }
    }, animation);
  } else {
    anim = me.getSlideInCfg(direction, me.afterExpandCollapseAnimation, animation);
    if (me.endDirection[direction]) {
      animCls = me.animateEndCls;
      targetEl.addCls(animCls);
    }
    if (!headerDifferent) {
      header.element.setVisibility(false);
      restoreHeaderVis = true;
    }
  }
  return me.doAnimation(collapsed, anim, {placeHolder:true, restore:!collapsed, reattach:true, animCls:animCls, restoreHeaderVis:restoreHeaderVis});
}, ensureCollapseTool:function() {
  var me = this, target = me.getTarget(), header = target.ensureHeader(), pos = me.getDirection(), collapsed = me.getCollapsed(), types = me.collapsingDirections, tool = me.collapsibleTool, cfg = me.getTool();
  if (header && cfg) {
    if (!tool) {
      me.collapsibleTool = tool = target.addTool(Ext.apply({handler:me.onToggleToolTap, scope:me, $internal:true}, cfg))[0];
    }
    tool.setType(collapsed ? types[pos][1] : types[pos][0]);
    tool.setTooltip(collapsed ? me.getExpandToolText() : me.getCollapseToolText());
  } else {
    me.collapsibleTool = Ext.destroy(tool);
  }
}, getAnimationFor:function(collapsed) {
  var anim = collapsed ? this.getCollapseAnimation() : this.getExpandAnimation();
  return anim || this.getAnimation();
}, getContainerTarget:function() {
  return this.getTarget().element.parent();
}, getDrawerTask:function() {
  var me = this, task = me.drawerTask;
  if (!task) {
    me.drawerTask = task = new Ext.util.DelayedTask(me.hideDrawer, me);
  }
  return task;
}, getHeaderSize:function() {
  var header = this.getTarget().ensureHeader(), headerEl = header && header.element;
  return headerEl ? Math.min(headerEl.measure('h'), headerEl.measure('w')) : 0;
}, getSlideInCfg:function(direction, callback, animation) {
  return Ext.apply({type:'slideIn', direction:direction, reverse:true, element:this.drawer.element, isElementBoxFit:false, scope:this, callback:callback}, animation);
}, getSlideOutCfg:function(direction, callback, animation) {
  return Ext.apply({type:'slideOut', direction:direction, element:this.drawer.element, isElementBoxFit:false, scope:this, callback:callback}, animation);
}, handleElMouseEnter:function() {
  this.getDrawerTask().cancel();
}, handleElMouseLeave:function(e) {
  var me = this, toElement = e.getRelatedTarget(), target = me.getTarget();
  if (toElement && (target.owns(toElement) || me.drawer.owns(toElement))) {
    return;
  }
  me.getDrawerTask().delay(me.getDrawerHideDelay());
}, handleGlobalDrawerEvent:function(e) {
  var me = this, drawer = me.drawer, target = me.getTarget(), task;
  task = me.getDrawerTask();
  if (target.owns(e) || drawer.owns(e)) {
    task.cancel();
  } else {
    task.delay(me.getDrawerHideDelay());
  }
}, measureAndSet:function(el, dimension, clear) {
  var setter, getter;
  if (!el) {
    return;
  }
  setter = 'set' + dimension;
  getter = 'get' + dimension;
  if (clear) {
    el[setter](null);
  }
  el[setter](el[getter](false, true));
}, onHeaderTap:function(e) {
  var me = this, titleCollapse = me.getTitleCollapse(), collapsed = me.getCollapsed(), cmp = Ext.Component.from(e);
  if (!(cmp.isPanelTitle || cmp.isPanelHeader)) {
    return;
  }
  if (titleCollapse) {
    me.toggleCollapsed(!collapsed);
  } else {
    if (me.getUseDrawer() && collapsed && !me.isDynamic()) {
      me[me.drawerVisible ? 'hideDrawer' : 'showDrawer']();
    }
  }
}, onToggleToolTap:function() {
  this.toggleCollapsed(!this.getCollapsed());
}, parseAnimation:function(collapsed, animation) {
  if (animation === undefined) {
    animation = this.getAnimationFor(collapsed);
  } else {
    if (animation) {
      if (typeof animation === 'boolean') {
        animation = {};
      }
      animation = Ext.apply({}, animation, this.getAnimationFor(collapsed));
    }
  }
  return animation;
}, reattachBodyWrap:function() {
  if (this.hasDetachedBody) {
    this.getTarget().reattachBodyWrap();
    this.hasDetachedBody = false;
  }
}, restoreProps:function(keep) {
  var me = this, target = me.getTarget(), savedProps = me.savedProps, prop;
  if (savedProps) {
    prop = savedProps.flex;
    if (prop) {
      target.setFlex(prop);
    }
    target.setMinHeight(savedProps.minHeight);
    target.setMinWidth(savedProps.minWidth);
    target.setHeight(savedProps.height);
    target.setWidth(savedProps.width);
    if (!keep) {
      me.savedProps = null;
    }
  }
}, saveProps:function() {
  var me = this, target = me.getTarget(), size = target.element.measure(), props;
  me.savedProps = props = {flex:target.getFlex(), minHeight:target.getMinHeight(), minWidth:target.getMinWidth(), height:target.getHeight(), width:target.getWidth(), measuredWidth:size.width, measuredHeight:size.height};
  return props;
}, setToolTextIf:function(text, doSet) {
  var tool = this.collapsibleTool;
  if (text && tool && doSet) {
    tool.setTooltip(text);
  }
}, setupHeaderListeners:function() {
  var me = this, header = me.getTarget().getHeader();
  me.headerListeners = Ext.destroy(me.headerListeners);
  if (header && (me.getUseDrawer() || me.getTitleCollapse())) {
    me.headerListeners = header.element.on({destroyable:true, scope:me, tap:'onHeaderTap'});
  }
}, unanimated:function(fn) {
  this.$unanimated = true;
  if (fn) {
    fn(this);
    this.$unanimated = false;
  }
  return this;
}}});
Ext.define('Ext.panel.Header', {extend:Ext.Container, xtype:'panelheader', isPanelHeader:true, config:{icon:null, iconAlign:null, iconCls:null, titleRotation:'auto', title:null, titleAlign:null, layout:{type:'box', vertical:false, align:'center'}, position:null}, autoSize:null, classCls:Ext.baseCSSPrefix + 'panelheader', verticalCls:Ext.baseCSSPrefix + 'vertical', horizontalCls:Ext.baseCSSPrefix + 'horizontal', toolEndCls:Ext.baseCSSPrefix + 'end', toolStartCls:Ext.baseCSSPrefix + 'start', rotationMap:{top:'0', 
right:'90', bottom:'0', left:'270'}, dockCls:{top:Ext.baseCSSPrefix + 'docked-top', right:Ext.baseCSSPrefix + 'docked-right', bottom:Ext.baseCSSPrefix + 'docked-bottom', left:Ext.baseCSSPrefix + 'docked-left'}, weighted:true, vertical:false, inheritUi:true, addTools:function(tools) {
  var items = Ext.Array.from(tools);
  if (items && items.length) {
    items = this.add(items);
  }
  return items;
}, applyTitle:function(newTitle, oldTitle) {
  var title = oldTitle;
  if (title) {
    if (!newTitle || typeof newTitle === 'string') {
      title.setText(newTitle || '');
    } else {
      if (newTitle) {
        title.setConfig(newTitle);
      }
    }
  } else {
    title = Ext.create(this.createTitle(newTitle));
  }
  return title;
}, createTitle:function(config) {
  var panel = this.getRefOwner();
  if (config && typeof config === 'string') {
    config = {text:config};
  }
  return Ext.merge({xtype:'paneltitle', instanceCls:panel && panel.titleCls || null, flex:'1 1 auto'}, config);
}, onItemAdd:function(item, index) {
  var me = this, title = me.getTitle(), titleWeight = title && title.weight || -10, itemWeight = item.weight || 0;
  me.callParent([item, index]);
  if (item.isTool) {
    item.addCls(itemWeight < titleWeight ? me.toolStartCls : me.toolEndCls);
  }
}, onItemRemove:function(item, index, destroying) {
  this.callParent([item, index, destroying]);
  if (item.isTool) {
    item.removeCls([this.toolStartCls, this.toolEndCls]);
  }
}, updateIcon:function(icon) {
  this.ensureTitle().setIcon(icon);
}, updateIconAlign:function(align) {
  this.ensureTitle().setIconAlign(align);
}, updateIconCls:function(cls) {
  this.ensureTitle().setIconCls(cls);
}, updateTitle:function(title, oldTitle) {
  if (oldTitle) {
    oldTitle.setConfig(title);
  } else {
    this.add(title);
  }
}, updateTitleAlign:function(align) {
  this.ensureTitle().setTextAlign(align);
}, updateTitleRotation:function(rotation) {
  var me = this, owner;
  if (rotation === 'auto') {
    if (me.isConfiguring) {
      return;
    }
    owner = me.getRefOwner();
    if (!owner) {
      Ext.raise('Cannot use rotation auto without an owning panel.');
    }
    if (owner) {
      rotation = me.rotationMap[owner.getHeaderPosition()];
    }
  }
  me.rotateTitle(rotation);
}, updatePosition:function(position, oldPosition) {
  var me = this, layout = me.getLayout(), isLeft = position === 'left', isRight = position === 'right', vertical = me.vertical = isLeft || isRight, verticalCls = me.verticalCls, horizontalCls = me.horizontalCls, dockCls = me.dockCls;
  layout.setVertical(vertical);
  layout.setReverse(isLeft);
  if (oldPosition) {
    me.removeCls(dockCls[oldPosition]);
  }
  if (position) {
    me.addCls(dockCls[position]);
  }
  if (vertical) {
    me.replaceCls(horizontalCls, verticalCls);
  } else {
    me.replaceCls(verticalCls, horizontalCls);
  }
  if (me.getTitleRotation() === 'auto') {
    me.rotateTitle(me.rotationMap[position]);
  }
}, privates:{clearTools:function() {
  var items = this.getItems().items, c, i;
  for (i = items.length; i-- > 0;) {
    c = items[i];
    if (c.isTool && !c.$internal) {
      this.remove(c);
    }
  }
}, ensureTitle:function() {
  var me = this, title = me.getTitle();
  if (!title) {
    me.setTitle('');
    title = me.getTitle();
  }
  return title;
}, isVertical:function() {
  return this.vertical;
}, rotateTitle:function(rotation) {
  this.ensureTitle().setRotation(rotation);
}, sortByWeight:function(item1, item2) {
  return (item1.weight || 0) - (item2.weight || 0);
}}, deprecated:{'6.5':{configs:{glyph:null}}}});
Ext.define('Ext.theme.material.panel.Header', {override:'Ext.panel.Header', config:{titleAlign:'left'}});
Ext.define('Ext.panel.Resizer', {config:{constrainToParent:true, dynamic:false, edges:null, maxSize:null, minSize:null, preserveRatio:false, snap:null, split:false, target:null, ui:null}, constructor:function(config) {
  this.edgeMap = {};
  this.initConfig(config);
}, applyEdges:function(edges, oldEdges) {
  var positionMap = this.positionMap, len, i;
  if (edges) {
    if (edges === 'all') {
      edges = Ext.Array.clone(this.allEdges);
    } else {
      if (typeof edges === 'string') {
        edges = edges.trim();
        edges = edges.split(this.edgeDelimiterRe);
      } else {
        edges = Ext.Array.clone(edges);
      }
    }
    for (i = 0, len = edges.length; i < len; ++i) {
      if (!positionMap[edges[i]]) {
        Ext.raise('Invalid edge specified: ' + edges[i]);
      }
      edges[i] = positionMap[edges[i]];
    }
    edges.sort();
  }
  if (edges && oldEdges && Ext.Array.equals(edges, oldEdges)) {
    edges = undefined;
  }
  return edges;
}, updateEdges:function(edges, oldEdges) {
  var me = this, map = me.edgeMap, newMap = {}, split = me.getSplit(), baseCls = me.baseCls, infoMap = me.edgeInfoMap, ui = me.getUi(), splitEdges = me.splitEdges, disabled = me.disabled, firstCorner = me.firstCorner, el = me.getTarget().element, splitPrefix = me.splitPrefix, edgeEl, key, len, i, edge;
  if (edges) {
    for (i = 0, len = edges.length; i < len; ++i) {
      newMap[edges[i]] = true;
    }
  }
  if (oldEdges) {
    for (key in map) {
      if (!newMap[key]) {
        edgeEl = map[key];
        if (infoMap[key].corner && edgeEl === firstCorner) {
          firstCorner = null;
        }
        edgeEl.destroy();
        if (split && key in splitEdges) {
          el.removeCls(splitPrefix + key);
        }
      }
    }
    if (me.firstCorner && !firstCorner) {
      me.firstCorner = el.child('.' + this.baseCls + '[data-corner]');
    }
  }
  if (edges) {
    for (key in newMap) {
      newMap[key] = edge = map[key] || me.createEdge(el, key);
      if (split) {
        edge.addCls(me.splitterCls);
        if (key in splitEdges) {
          el.addCls(splitPrefix + key);
        }
      } else {
        edge.addCls(me.handleCls);
      }
      if (disabled) {
        edge.addCls(me.disabledCls);
      }
      if (ui) {
        edge.addCls(ui, baseCls);
      }
    }
  }
  this.edgeMap = newMap;
}, applyMaxSize:function(maxSize) {
  return this.applyConstraintValue(maxSize);
}, applyMinSize:function(minSize) {
  return this.applyConstraintValue(minSize);
}, applySnap:function(snap) {
  return this.applyConstraintValue(snap);
}, updateSplit:function(split) {
  var me = this, map = me.edgeMap, splitEdges = me.splitEdges, splitPrefix = me.splitPrefix, key, el, target;
  if (me.isConfiguring) {
    return;
  }
  target = me.getTarget().element;
  for (key in map) {
    el = map[key];
    if (el.isElement) {
      el.toggleCls(me.splitterCls, split);
      el.toggleCls(me.handleCls, !split);
      if (key in splitEdges) {
        target.toggleCls(splitPrefix + key, split);
      }
    }
  }
}, updateTarget:function(target) {
  var me = this;
  me.targetListeners = me.dragListeners = Ext.destroy(me.targetListeners, me.dragListeners);
  if (target) {
    me.setupDragListeners();
    me.targetListeners = target.on({expand:'onTargetExpand', collapse:'onTargetCollapse', scope:me, destroyable:true});
    if (target.hasCollapsible && target.getCollapsed()) {
      me.onTargetCollapse(target);
    }
  }
}, updateUi:function(ui, oldUi) {
  var edgeMap = this.edgeMap, baseCls = this.baseCls, key, edge;
  if (this.isConfiguring) {
    return;
  }
  for (key in edgeMap) {
    edge = edgeMap[key];
    if (oldUi) {
      edge.removeCls(oldUi, baseCls);
    }
    if (ui) {
      edge.addCls(ui, baseCls);
    }
  }
}, destroy:function() {
  var me = this, target = me.getTarget();
  if (me.dragStarted) {
    me.cleanup();
  }
  if (target && !target.destroying) {
    me.setEdges(null);
  }
  me.setTarget(null);
  me.callParent();
}, privates:{baseCls:Ext.baseCSSPrefix + 'panelresizer', proxyCls:Ext.baseCSSPrefix + 'panelresizer-proxy', disabledCls:Ext.baseCSSPrefix + 'disabled', handleCls:Ext.baseCSSPrefix + 'handle', splitterCls:Ext.baseCSSPrefix + 'splitter', horizontalCls:Ext.baseCSSPrefix + 'horizontal', verticalCls:Ext.baseCSSPrefix + 'vertical', splitPrefix:Ext.baseCSSPrefix + 'split-', edgeDelegateSelector:'\x3e .' + Ext.baseCSSPrefix + 'panelresizer', allEdges:['north', 'northeast', 'east', 'southeast', 'south', 'southwest', 
'west', 'northwest'], defaultMaxSize:100000, defaultMinSize:50, edgeDelimiterRe:/(?:\s*,\s*)|\s+/, emptyConstrain:[null, null], edgeInfoMap:{north:{vert:true, constrainProp:{vert:'bottom'}, adjustHeightOffset:-1, splitPosSetter:'setY', oppSplitPosSetter:'setX', sizeProp:'height', startEdge:'top', touchAction:{panY:false}}, northeast:{horz:true, vert:true, corner:true, constrainProp:{horz:'left', vert:'bottom'}, adjustHeightOffset:-1, adjustWidthOffset:1, touchAction:{panX:false, panY:false}}, east:{horz:true, 
constrainProp:{horz:'left'}, adjustWidthOffset:1, splitPosSetter:'setX', oppSplitPosSetter:'setY', sizeProp:'width', startEdge:'right', touchAction:{panX:false}}, southeast:{horz:true, vert:true, corner:true, constrainProp:{horz:'left', vert:'top'}, adjustHeightOffset:1, adjustWidthOffset:1, touchAction:{panX:false, panY:false}}, south:{vert:true, constrainProp:{vert:'top'}, adjustHeightOffset:1, splitPosSetter:'setY', oppSplitPosSetter:'setX', sizeProp:'height', startEdge:'bottom', touchAction:{panY:false}}, 
southwest:{horz:true, vert:true, corner:true, constrainProp:{horz:'right', vert:'top'}, adjustHeightOffset:1, adjustWidthOffset:-1, touchAction:{panX:false, panY:false}}, west:{horz:true, constrainProp:{horz:'right'}, adjustWidthOffset:-1, splitPosSetter:'setX', oppSplitPosSetter:'setY', sizeProp:'width', startEdge:'left', touchAction:{panX:false}}, northwest:{horz:true, vert:true, corner:true, constrainProp:{horz:'right', vert:'bottom'}, adjustHeightOffset:-1, adjustWidthOffset:-1, touchAction:{panX:false, 
panY:false}}}, positionMap:{n:'north', north:'north', ne:'northeast', northeast:'northeast', e:'east', east:'east', se:'southeast', southeast:'southeast', s:'south', south:'south', sw:'southwest', southwest:'southwest', w:'west', west:'west', nw:'northwest', northwest:'northwest'}, sideInvertMap:{top:'bottom', right:'left', bottom:'top', left:'right'}, splitEdges:{north:true, east:true, south:true, west:true}, applyConstraintValue:function(v) {
  if (!Ext.isArray(v)) {
    v = [v, v];
  }
  return v;
}, calculateConstrain:function(targetVal, localVal, defaultValue) {
  var v = targetVal;
  if (v === null) {
    v = localVal;
  }
  if (v === null) {
    v = defaultValue;
  }
  return v;
}, createEdge:function(targetEl, pos) {
  var me = this, info = me.edgeInfoMap[pos], corner = info.corner, firstCorner = me.firstCorner, el = targetEl.createChild({cls:me.baseCls + ' ' + Ext.baseCSSPrefix + pos, 'data-edge':pos}, corner ? null : firstCorner);
  el.setTouchAction(info.touchAction);
  if (corner) {
    el.dom.setAttribute('data-corner', 'true');
  }
  if (corner && !firstCorner) {
    me.firstCorner = el;
  }
  return el;
}, createProxy:function(edge, asFloat) {
  var me = this, proxyCls = me.proxyCls, orientationCls = edge.horz ? me.horizontalCls : me.verticalCls, modeCls = asFloat ? me.handleCls : me.splitterCls;
  return Ext.getBody().createChild({cls:proxyCls + ' ' + modeCls + ' ' + orientationCls});
}, cleanup:function() {
  var me = this, info = me.info, proxy = info && info.proxy;
  if (me.dragStarted) {
    if (proxy) {
      proxy.destroy();
    }
    me.dragStarted = false;
    me.info = null;
  }
}, getBoxLayout:function() {
  var parent = this.getTarget().getParent(), layout = parent && parent.getLayout();
  return layout && layout.isBox ? layout : null;
}, getEdge:function(position) {
  position = this.positionMap[position];
  return this.edgeMap[position] || null;
}, getProxy:function() {
  var info = this.info;
  return info && info.proxy;
}, handleDrag:function(e) {
  var info, target, edge, asFloat, box, horz, vert, offsetWidth, offsetHeight, adjustWidthOffset, adjustHeightOffset, modifiesX, modifiesY, minHeight, minWidth, maxHeight, maxWidth, snappedWidth, snappedHeight, w, h, ratio, dragRatio, oppX, oppY, newBox;
  if (!this.dragStarted) {
    return;
  }
  info = this.info;
  target = info.target;
  edge = info.edge;
  asFloat = info.asFloat;
  box = info.startBox;
  horz = edge.horz;
  vert = edge.vert;
  offsetWidth = 0;
  offsetHeight = 0;
  adjustWidthOffset = edge.adjustWidthOffset;
  adjustHeightOffset = edge.adjustHeightOffset;
  modifiesX = asFloat && edge.adjustWidthOffset < 0;
  modifiesY = asFloat && edge.adjustHeightOffset < 0;
  minHeight = info.minHeight;
  minWidth = info.minWidth;
  maxHeight = info.maxHeight;
  maxWidth = info.maxWidth;
  if (adjustWidthOffset) {
    offsetWidth = Math.round(adjustWidthOffset * e.deltaX);
  }
  if (adjustHeightOffset) {
    offsetHeight = Math.round(adjustHeightOffset * e.deltaY);
  }
  newBox = {width:box.width + offsetWidth, height:box.height + offsetHeight, x:box.x + (modifiesX ? -offsetWidth : 0), y:box.y + (modifiesY ? -offsetHeight : 0)};
  w = newBox.width;
  h = newBox.height;
  snappedWidth = horz ? this.snap(w, info.snapWidth, offsetWidth > 0) : w;
  snappedHeight = vert ? this.snap(h, info.snapHeight, offsetHeight > 0) : h;
  if (w !== snappedWidth || h !== snappedHeight) {
    if (modifiesX) {
      newBox.x -= snappedWidth - w;
    }
    if (modifiesY) {
      newBox.y -= snappedHeight - h;
    }
    newBox.width = w = snappedWidth;
    newBox.height = h = snappedHeight;
  }
  if (horz && (w < minWidth || w > maxWidth)) {
    newBox.width = w = Ext.Number.constrain(w, minWidth, maxWidth);
    if (modifiesX) {
      newBox.x = box.x + (box.width - w);
    }
  }
  if (vert && (h < minHeight || h > maxHeight)) {
    newBox.height = h = Ext.Number.constrain(h, minHeight, maxHeight);
    if (modifiesY) {
      newBox.y = box.y + (box.height - h);
    }
  }
  if (asFloat && (info.preserveRatio || e.shiftKey)) {
    ratio = info.ratio;
    h = Math.min(Math.max(minHeight, w / ratio), maxHeight);
    w = Math.min(Math.max(minWidth, newBox.height * ratio), maxWidth);
    if (horz && vert) {
      oppX = box.x + (modifiesX ? box.width : 0);
      oppY = box.y + (modifiesY ? box.height : 0);
      dragRatio = Math.abs(oppX - e.pageX) / Math.abs(oppY - e.pageY);
      if (dragRatio > ratio) {
        newBox.height = h;
      } else {
        newBox.width = w;
      }
      if (modifiesX) {
        newBox.x = box.x - (newBox.width - box.width);
      }
      if (modifiesY) {
        newBox.y = box.y - (newBox.height - box.height);
      }
    } else {
      if (horz) {
        newBox.height = h;
      } else {
        newBox.width = w;
      }
    }
  }
  if (target.hasListeners.resizedrag) {
    target.fireEvent('resizedrag', target, {edge:info.edgeName, event:e, width:newBox.width, height:newBox.height});
  }
  this.resize(newBox, e.type === 'dragend', e);
}, handleDragCancel:function(e) {
  var info = this.info, target = info.target;
  this.cleanup();
  if (target.hasListeners.resizedragcancel) {
    target.fireEvent('resizedragcancel', target, {edge:info.edgeName, event:e});
  }
}, handleDragEnd:function(e) {
  this.handleDrag(e);
  this.cleanup();
}, handleDragStart:function(e) {
  var me = this, emptyConstrain = me.emptyConstrain, target = me.getTarget(), hasListeners = target.hasListeners, dynamic = me.getDynamic(), edgeName = e.target.getAttribute('data-edge'), edge = me.edgeInfoMap[edgeName], horz = edge.horz, vert = edge.vert, region = target.element.getRegion(), snap = me.getSnap() || emptyConstrain, minSize = me.getMinSize() || emptyConstrain, maxSize = me.getMaxSize() || emptyConstrain, defaultMinSize = me.defaultMinSize, defaultMaxSize = me.defaultMaxSize, info, 
  proxy, context, asFloat, layout, layoutVert, clearFlex;
  if (hasListeners.beforeresizedragstart) {
    context = {edge:edgeName, event:e};
    if (target.fireEvent('beforeresizedragstart', target, context) === false) {
      return;
    }
  }
  asFloat = target.getFloated() || target.isPositioned();
  if (target.getFlex()) {
    layout = me.getBoxLayout();
    if (layout) {
      layoutVert = layout.getVertical();
      clearFlex = horz && !layoutVert || vert && layoutVert;
    }
  }
  me.info = info = {target:target, edgeName:edgeName, dynamic:dynamic, startBox:region, snapHeight:snap[1], snapWidth:snap[0], clearFlex:clearFlex, minHeight:me.calculateConstrain(target.getMinHeight(), minSize[1], defaultMinSize), minWidth:me.calculateConstrain(target.getMinWidth(), minSize[0], defaultMinSize), maxHeight:me.calculateConstrain(target.getMaxHeight(), maxSize[1], defaultMaxSize), maxWidth:me.calculateConstrain(target.getMaxWidth(), maxSize[0], defaultMaxSize), edge:edge, asFloat:asFloat, 
  preserveRatio:asFloat ? me.getPreserveRatio() : false, ratio:asFloat ? region.width / region.height : 0, start:region[edge.startEdge], floated:target.getFloated()};
  if (!dynamic) {
    info.proxy = proxy = me.createProxy(edge, asFloat);
    if (asFloat) {
      proxy.setBox(region);
    } else {
      proxy[edge.splitPosSetter](info.start);
      proxy[edge.oppSplitPosSetter](horz ? region.top : region.left);
      proxy.setSize(horz ? undefined : region.width, vert ? undefined : region.height);
    }
  }
  me.setupDragConstraints(info);
  me.dragStarted = true;
  if (hasListeners.resizedragstart) {
    target.fireEvent('resizedragstart', target, context || {edge:edgeName, event:e});
  }
  e.stopPropagation();
  return false;
}, handleTouchStart:function(e) {
  e.preventDefault();
}, onTargetCollapse:function() {
  var me = this, map = me.edgeMap, key;
  me.disabled = true;
  me.dragListeners = Ext.destroy(me.dragListeners);
  for (key in map) {
    map[key].addCls(me.disabledCls);
  }
}, onTargetExpand:function() {
  var me = this, map = me.edgeMap, key;
  me.disabled = false;
  me.setupDragListeners();
  for (key in map) {
    map[key].removeCls(me.disabledCls);
  }
}, resize:function(newBox, atEnd, e) {
  var me = this, info = me.info, target = info.target, box = info.startBox, asFloat = info.asFloat, edge = info.edge, x = newBox.x, y = newBox.y, posChanged = asFloat && (box.x !== x || box.y !== y), horz = edge.horz, vert = edge.vert, floated = info.floated, onTarget = info.dynamic || atEnd, resizeTarget, isProxy, prop, diff, offset, targetParent, parentXY, positionEnd;
  if (onTarget) {
    resizeTarget = me.getTarget();
  } else {
    resizeTarget = info.proxy;
    isProxy = true;
  }
  if (!asFloat && isProxy) {
    prop = edge.sizeProp;
    offset = horz ? edge.adjustWidthOffset : edge.adjustHeightOffset;
    diff = (newBox[prop] - box[prop]) * offset;
    resizeTarget[edge.splitPosSetter](info.start + diff);
  } else {
    resizeTarget.setSize(horz ? newBox.width : undefined, vert ? newBox.height : undefined);
    if (!isProxy && info.clearFlex) {
      resizeTarget.setFlex(null);
    }
    if (posChanged) {
      positionEnd = !floated && onTarget;
      if (positionEnd) {
        targetParent = target.element.dom.parentNode;
        parentXY = Ext.fly(targetParent).getXY();
      }
      if (horz) {
        if (positionEnd) {
          resizeTarget.setLeft(x - parentXY[0]);
        } else {
          resizeTarget.setX(x);
        }
      }
      if (vert) {
        if (positionEnd) {
          resizeTarget.setTop(y - parentXY[1]);
        } else {
          resizeTarget.setY(y);
        }
      }
    }
  }
  if (atEnd) {
    if (target.hasListeners.resizedragend) {
      target.fireEvent('resizedragend', target, {edge:info.edgeName, event:e, width:newBox.width, height:newBox.height});
    }
  }
}, setupDragConstraints:function(info) {
  var me = this, dom = me.getTarget().element.dom, parent = dom.parentNode, clone = dom.cloneNode(false), fly = Ext.fly(clone), maxSize = me.defaultMaxSize, box, parentBox, edge, prop, invertMap;
  clone.style.position = 'absolute';
  fly.setMinHeight(info.minHeight);
  fly.setMinWidth(info.minWidth);
  fly.setMaxHeight(info.maxHeight);
  fly.setMaxWidth(info.maxWidth);
  fly.setHeight(1);
  fly.setWidth(1);
  parent.appendChild(clone);
  info.minHeight = fly.getHeight();
  info.minWidth = fly.getWidth();
  fly.setHeight(maxSize);
  fly.setWidth(maxSize);
  info.maxHeight = fly.getHeight();
  info.maxWidth = fly.getWidth();
  if (me.getConstrainToParent()) {
    box = info.startBox;
    parentBox = Ext.fly(parent).getRegion();
    edge = info.edge;
    invertMap = me.sideInvertMap;
    if (edge.horz) {
      prop = edge.constrainProp.horz;
      info.maxWidth = Math.min(info.maxWidth, Math.abs(box[prop] - parentBox[invertMap[prop]]));
    }
    if (edge.vert) {
      prop = edge.constrainProp.vert;
      info.maxHeight = Math.min(info.maxHeight, Math.abs(box[prop] - parentBox[invertMap[prop]]));
    }
  }
  parent.removeChild(clone);
}, setupDragListeners:function() {
  var me = this, delegate = me.edgeDelegateSelector;
  me.dragListeners = me.getTarget().element.on({scope:me, destroyable:true, delegate:delegate, dragstart:{priority:1000, delegate:delegate, fn:'handleDragStart'}, drag:'handleDrag', dragend:'handleDragEnd', dragcancel:'handleDragCancel', touchstart:'handleTouchStart'});
}, snap:function(value, increment, roundUp) {
  var m, m2;
  if (increment) {
    m = value % increment;
    if (m !== 0) {
      m2 = m * 2;
      value -= m;
      if (roundUp && m2 >= increment) {
        value += increment;
      } else {
        if (!roundUp && m2 > increment) {
          value += increment;
        } else {
          if (m2 < -increment) {
            value -= increment;
          }
        }
      }
    }
  }
  return value;
}}});
Ext.define('Ext.plugin.Responsive', {extend:Ext.plugin.Abstract, alias:'plugin.responsive', constructor:function() {
  this.callParent(arguments);
  Ext.log.warn('responsive plugin is deprecated; require "Ext.Responsive" instead');
}, id:'responsive'});
Ext.define('Ext.scroll.NativeScroller', {extend:Ext.scroll.Scroller, alias:'scroller.native', config:{monitorScroll:null, scrollingElement:null, spacerXY:null, xCls:null, yCls:null}, statics:{initViewportScroller:function() {
  var scroller = Ext.getViewportScroller();
  if (!scroller.getElement()) {
    scroller.setElement(Ext.getBody());
  }
}}, constructor:function(config) {
  var me = this;
  me.trackingPosition = {x:null, y:null};
  me.callParent([config]);
  me.syncXCls();
  me.syncYCls();
}, doDestroy:function() {
  var Scroller = Ext.scroll.Scroller, me = this;
  me.setX(null);
  me.setY(null);
  if (me._spacer) {
    me._spacer.destroy();
  }
  if (me.scrollListener) {
    me.scrollListener.destroy();
  }
  if (me.translatable) {
    me.translatable = null;
  }
  if (Scroller.viewport === me) {
    Scroller.viewport = null;
  }
  me.callParent();
}, getClientSize:function() {
  var dom = this.getElement().dom;
  return {x:dom.clientWidth, y:dom.clientHeight};
}, getScrollbarSize:function() {
  var me = this, width = 0, height = 0, element = me.getScrollingElement(), dom, x, y, hasXScroll, hasYScroll, scrollbarSize;
  if (element && !element.destroyed) {
    x = me.getX();
    y = me.getY();
    dom = element.dom;
    if (x || y) {
      scrollbarSize = Ext.scrollbar.size();
    }
    if (x === 'scroll') {
      hasXScroll = true;
    } else {
      if (x) {
        hasXScroll = dom.scrollWidth > dom.clientWidth;
      }
    }
    if (y === 'scroll') {
      hasYScroll = true;
    } else {
      if (y) {
        hasYScroll = dom.scrollHeight > dom.clientHeight;
      }
    }
    if (hasXScroll) {
      height = scrollbarSize.height;
    }
    if (hasYScroll) {
      width = scrollbarSize.width;
    }
  }
  return {width:width, height:height, reservedWidth:hasYScroll ? scrollbarSize.reservedWidth : '', reservedHeight:hasXScroll ? scrollbarSize.reservedHeight : ''};
}, getSize:function() {
  var element = this.getScrollingElement(), size, dom;
  if (element && !element.destroyed) {
    dom = element.dom;
    size = {x:dom.scrollWidth, y:dom.scrollHeight};
  } else {
    size = {x:0, y:0};
  }
  return size;
}, getMaxPosition:function() {
  var element = this.getScrollingElement(), x = 0, y = 0, dom;
  if (element && !element.destroyed) {
    dom = element.dom;
    x = dom.scrollWidth - dom.clientWidth;
    y = dom.scrollHeight - dom.clientHeight;
  }
  return {x:x, y:y};
}, getMaxUserPosition:function() {
  var me = this, element = me.getScrollingElement(), x = 0, y = 0, dom;
  if (element && !element.destroyed) {
    dom = element.dom;
    if (me.getX()) {
      x = dom.scrollWidth - dom.clientWidth;
    }
    if (me.getY()) {
      y = dom.scrollHeight - dom.clientHeight;
    }
  }
  return {x:x, y:y};
}, refresh:function() {
  var me = this, scrollPosition = me.getElementScroll(), x = scrollPosition.left, y = scrollPosition.top, position = me.position, trackingPosition = me.trackingPosition;
  position.x = trackingPosition.x = x;
  position.y = trackingPosition.y = y;
  return this.callParent();
}, updateElement:function(element, oldElement) {
  var me = this, nativeScrollerCls = me.nativeScrollerCls, scrollingElement = null;
  me.callParent([element, oldElement]);
  if (oldElement && !oldElement.destroyed) {
    oldElement.removeCls([nativeScrollerCls, this.getXCls(), this.getYCls()]);
  }
  if (element) {
    if (element.dom === document.documentElement || element.dom === document.body) {
      scrollingElement = Ext.scroll.Scroller.getScrollingElement();
    } else {
      scrollingElement = element;
    }
    element.addCls(nativeScrollerCls);
  }
  me.setScrollingElement(scrollingElement);
  if (!me.isConfiguring) {
    me.syncXCls();
    me.syncYCls();
    me.getTranslatable().setElement(scrollingElement);
  }
}, updateSize:function(size) {
  var me = this, element = me.getScrollingElement(), x = size.x, y = size.y, spacer;
  if (element) {
    spacer = me.getSpacer();
    if (!x && !y) {
      spacer.hide();
    } else {
      if (x > 0) {
        x -= 1;
      }
      if (y > 0) {
        y -= 1;
      }
      me.setSpacerXY({x:x, y:y});
      spacer.show();
    }
  }
}, updateX:function(x) {
  if (!this.isConfiguring) {
    this.syncXCls();
  }
}, updateY:function(y) {
  if (!this.isConfiguring) {
    this.syncYCls();
  }
}, privates:{nativeScrollerCls:Ext.baseCSSPrefix + 'nativescroller', spacerCls:Ext.baseCSSPrefix + 'scroller-spacer', overflowXClsMap:{auto:Ext.baseCSSPrefix + 'overflow-x-auto', 'true':Ext.baseCSSPrefix + 'overflow-x-auto', 'false':Ext.baseCSSPrefix + 'overflow-x-hidden', scroll:Ext.baseCSSPrefix + 'overflow-x-scroll'}, overflowYClsMap:{auto:Ext.baseCSSPrefix + 'overflow-y-auto', 'true':Ext.baseCSSPrefix + 'overflow-y-auto', 'false':Ext.baseCSSPrefix + 'overflow-y-hidden', scroll:Ext.baseCSSPrefix + 
'overflow-y-scroll'}, constrainScrollRange:function(scrollRange) {
  if (scrollRange < 1000000) {
    return scrollRange;
  }
  if (!this.maxSpacerTranslate) {
    var maxScrollHeight = Math.pow(2, 32), tooHigh = maxScrollHeight, tooLow = 500, scrollTest = Ext.getBody().createChild({style:{position:'absolute', left:'-10000px', top:'0', width:'500px', height:'500px'}, cn:{cls:this.spacerCls}}, null, true), stretcher = Ext.get(scrollTest.firstChild), sStyle = stretcher.dom.style;
    stretcher.translate(0, maxScrollHeight - 1);
    sStyle.lineHeight = Number(!parseInt(sStyle.lineHeight, 10)) + 'px';
    while (tooHigh !== tooLow + 1) {
      stretcher.translate(0, maxScrollHeight = tooLow + Math.floor((tooHigh - tooLow) / 2));
      sStyle.lineHeight = Number(!parseInt(sStyle.lineHeight, 10)) + 'px';
      if (scrollTest.scrollHeight < maxScrollHeight) {
        tooHigh = maxScrollHeight;
      } else {
        tooLow = maxScrollHeight;
      }
    }
    stretcher.translate(0, Ext.scroll.Scroller.prototype.maxSpacerTranslate = tooLow);
    tooHigh = tooLow * 2;
    while (tooHigh !== tooLow + 1) {
      stretcher.dom.style.marginTop = (maxScrollHeight = tooLow + Math.floor((tooHigh - tooLow) / 2)) + 'px';
      sStyle.lineHeight = Number(!parseInt(sStyle.lineHeight, 10)) + 'px';
      if (scrollTest.scrollHeight < maxScrollHeight) {
        tooHigh = maxScrollHeight;
      } else {
        tooLow = maxScrollHeight;
      }
    }
    Ext.fly(scrollTest).destroy();
    Ext.scroll.Scroller.prototype.maxSpacerMargin = tooLow - Ext.scroll.Scroller.prototype.maxSpacerTranslate;
  }
  return Math.min(scrollRange, this.maxSpacerTranslate);
}, doHighlight:function(el, highlight) {
  if (highlight !== true) {
    Ext.fly(el).highlight(highlight);
  } else {
    Ext.fly(el).highlight();
  }
}, doScrollTo:function(x, y, animate) {
  var me = this, element = me.getScrollingElement(), translatable = me.getTranslatable(), maxPosition, xInf, yInf, ret, deferred;
  if (element && !element.destroyed) {
    xInf = x === Infinity;
    yInf = y === Infinity;
    if (xInf || yInf) {
      maxPosition = me.getMaxPosition();
      if (xInf) {
        x = maxPosition.x;
      }
      if (yInf) {
        y = maxPosition.y;
      }
    }
    if (x !== null) {
      x = me.convertX(x);
    }
    if (animate) {
      deferred = new Ext.Deferred;
      translatable.on('animationend', function() {
        if (me.destroyed) {
          deferred.reject();
        } else {
          deferred.resolve();
        }
      }, Ext.global, {single:true, onFrame:true});
      translatable.translate(x, y, animate);
      ret = deferred.promise;
    } else {
      translatable.translate(x, y);
      ret = Ext.Deferred.getCachedResolved();
      me.onScroll();
    }
  } else {
    ret = Ext.Deferred.getCachedRejected();
  }
  return ret;
}, getElementScroll:function() {
  return this.getScrollingElement().getScroll();
}, getSpacer:function() {
  var me = this, spacer = me._spacer, element;
  if (!spacer) {
    element = me.getScrollingElement();
    spacer = me._spacer = element.createChild({cls:me.spacerCls, role:'presentation'}, element.dom.firstChild);
    spacer.setVisibilityMode(2);
    spacer.hide();
    element.position();
  }
  return spacer;
}, onScroll:function(e) {
  var me = this, position = me.position, scrollPosition = me.getElementScroll(), x = scrollPosition.left, y = scrollPosition.top, deltaX = x - position.x, deltaY = y - position.y;
  if (deltaX || deltaY) {
    if (e) {
      if (!me.getX() && !me.getY() && !me.getMonitorScroll()) {
        e.preventDefault();
        return;
      }
    }
    position.x = x;
    position.y = y;
    if (!me.isScrolling) {
      me.setPrimary(true);
      me.callPartners('onPartnerScrollStart', x, y);
      me.fireScrollStart(x, y, deltaX, deltaY);
      me.callPartners('fireScrollStart', x, y);
    }
    if (me.isPrimary) {
      me.callPartners('onPartnerScroll', x, y);
      me.fireScroll(x, y, deltaX, deltaY);
      me.callPartners('fireScroll', x, y);
      me.onScrollEnd(x, y);
    }
  }
}, doOnScrollEnd:function(x, y) {
  var me = this, position = me.position, trackingPosition = me.trackingPosition;
  if (!me.destroying && !me.destroyed) {
    me.isScrolling = Ext.isScrolling = false;
    trackingPosition.x = position.x;
    trackingPosition.y = position.y;
    me.callPartners('onPartnerScrollEnd');
    me.fireScrollEnd(x, y);
    me.callPartners('fireScrollEnd', x, y);
    if (!me.isScrolling) {
      me.setPrimary(null);
    }
  }
}, restoreState:function() {
  var me = this, trackingPosition = me.trackingPosition;
  me.doScrollTo(trackingPosition.x, trackingPosition.y);
}, syncXCls:function() {
  var me = this;
  if (me.getElement()) {
    me.setXCls(me.overflowXClsMap[me.getX()]);
  }
}, syncYCls:function() {
  var me = this;
  if (me.getElement()) {
    me.setYCls(me.overflowYClsMap[me.getY()]);
  }
}, translateSpacer:function(x, y) {
  this.getSpacer().translate(x, y);
}, updateScrollingElement:function(element, oldElement) {
  var me = this, doc = document, scrollListener = me.scrollListener, dom, eventSource;
  if (scrollListener) {
    scrollListener.destroy();
    me.scrollListener = null;
  }
  if (element) {
    dom = element.dom;
    if (dom === doc.scrollingElement || dom === doc.documentElement) {
      eventSource = Ext.getWin();
    } else {
      eventSource = element;
    }
    me.scrollListener = eventSource.on({scroll:'onScroll', scope:me, destroyable:true});
  }
}, applySpacerXY:function(pos, oldPos) {
  if (oldPos && pos.x === oldPos.x && pos.y === oldPos.y) {
    pos = undefined;
  }
  return pos;
}, updateSpacerXY:function(pos) {
  var me = this, spacer = me.getSpacer(), sStyle = spacer.dom.style, scrollHeight = pos.y, shortfall;
  sStyle.marginTop = '';
  me.translateSpacer(pos.x, me.constrainScrollRange(scrollHeight));
  sStyle.lineHeight = Number(!parseInt(sStyle.lineHeight, 10)) + 'px';
  if (scrollHeight > 1000000) {
    shortfall = scrollHeight - me.getScrollingElement().dom.scrollHeight;
    if (shortfall > 0) {
      sStyle.marginTop = Math.min(shortfall, me.maxSpacerMargin || 0) + 'px';
    }
  }
}, createTranslatable:function(defaults) {
  if (this.isConfiguring) {
    this.getElement();
  }
  return Ext.apply({element:this.getScrollingElement()}, defaults);
}, updateXCls:function(xCls, oldXCls) {
  var scrollingElement = this.getScrollingElement();
  if (scrollingElement && !scrollingElement.destroyed) {
    scrollingElement.replaceCls(oldXCls, xCls);
  }
}, updateYCls:function(yCls, oldYCls) {
  var scrollingElement = this.getScrollingElement();
  if (scrollingElement && !scrollingElement.destroyed) {
    scrollingElement.replaceCls(oldYCls, yCls);
  }
}}}, function(NativeScroller) {
  var Scroller = Ext.scroll.Scroller;
  Ext.getViewportScroller = function(autoCreate) {
    var scroller = Scroller.viewport;
    if (!scroller && autoCreate !== false) {
      Scroller.viewport = scroller = new NativeScroller;
      NativeScroller.initViewportScroller();
    }
    return scroller;
  };
  Ext.setViewportScroller = function(scroller) {
    var current = Scroller.viewport;
    if (scroller !== current) {
      Ext.destroy(current);
      if (scroller && !scroller.isScroller) {
        scroller = new NativeScroller(scroller);
      }
      Scroller.viewport = scroller;
    }
  };
  Ext.onReady(function() {
    NativeScroller.initViewportScrollerTimer = Ext.defer(NativeScroller.initViewportScroller, 100);
  });
});
Ext.define('Ext.scroll.indicator.Indicator', {extend:Ext.Widget, alias:'scrollindicator.indicator', mixins:[Ext.mixin.Factoryable], factoryConfig:{defaultType:'overlay', aliasPrefix:'scrollindicator.'}, isScrollIndicator:true, classCls:Ext.baseCSSPrefix + 'scrollindicator', config:{axis:null, enabled:null, scroller:null, value:null}, privates:{axisClsMap:{x:Ext.baseCSSPrefix + 'horizontal', y:Ext.baseCSSPrefix + 'vertical'}, updateAxis:function(axis) {
  this.addCls(this.axisClsMap[axis]);
}}});
Ext.define('Ext.scroll.indicator.Bar', {extend:Ext.scroll.indicator.Indicator, alias:'scrollindicator.bar', isScrollbar:true, config:{stylesheet:true}, classCls:Ext.baseCSSPrefix + 'scrollbar', enabledCls:Ext.baseCSSPrefix + 'enabled', scrollCls:Ext.baseCSSPrefix + 'overflow-scroll', cornerCls:Ext.baseCSSPrefix + 'scrollbar-corner', maxScrollSize:100000, scale:1, position:0, template:[{reference:'spacerElement', cls:Ext.baseCSSPrefix + 'spacer-el'}], constructor:function(config) {
  this.callParent([config]);
  this.element.on('scroll', 'onScrollbarScroll', this);
}, doDestroy:function() {
  this.setEnabled(null);
  this.callParent();
}, privates:{hasRules:{x:false, y:false}, names:{x:{scrollerCls:Ext.baseCSSPrefix + 'has-horizontal-scrollbar', margin:'margin-right', spacerMargin:'margin-left', getAxis:'getX', size:'height', oppositeSize:'width', scrollPosition:'scrollLeft', minSize:'min-height'}, y:{scrollerCls:Ext.baseCSSPrefix + 'has-vertical-scrollbar', margin:'margin-bottom', spacerMargin:'margin-top', getAxis:'getY', size:'width', oppositeSize:'height', scrollPosition:'scrollTop', minSize:'min-width'}}, onRefresh:function() {
  var me = this, scroller = me.getScroller(), scrollEl = scroller.getElement(), axis = me.getAxis(), names = me.names[axis], axisValue = scroller[names.getAxis](), scrollSize = scroller.getSize()[axis], clientSize = scrollEl[axis === 'x' ? 'getWidth' : 'getHeight'](), scrollMax = scroller.getMaxPosition()[axis], oppositeScrollbarSize = scroller.getScrollbarSize()[names.oppositeSize], maxScrollSize = me.maxScrollSize;
  if (clientSize && scrollSize) {
    me.setEnabled(scroller.isAxisEnabled(me.getAxis()));
    me.toggleCls(me.scrollCls, axisValue === 'scroll');
    me.scale = Math.max(scrollMax / (maxScrollSize - clientSize + oppositeScrollbarSize), 1);
    me.spacerElement.setStyle(names.spacerMargin, Math.min(scrollSize, maxScrollSize) - 1 + 'px');
  }
}, onScroll:function() {
  var me = this, scroller = me.getScroller(), axis = me.getAxis();
  if (!scroller.isScrollbarScrolling) {
    me.element.dom[me.names[axis].scrollPosition] = Math.round(me.getScroller().position[axis] / me.scale);
    me.readPosition();
  }
}, onScrollbarScroll:function() {
  var me = this, scroller = me.getScroller(), axis = me.getAxis(), oldPos = me.position, pos = me.readPosition(), isY = axis === 'y';
  if (oldPos !== pos && (!scroller.isScrolling || scroller.isScrollbarScrolling)) {
    scroller.isScrollbarScrolling = true;
    scroller.doScrollTo(isY ? null : pos, isY ? pos : null);
  }
}, readPosition:function() {
  var me = this, position = Math.round(me.element.dom[me.names[me.getAxis()].scrollPosition] * me.scale);
  me.position = position;
  return position;
}, updateAxis:function(axis, oldAxis) {
  var me = this, el = me.el, innerEl = me.getScroller().getInnerElement(), names = me.names[axis], extraPadding = Ext.isIE ? 1 : 0, scrollbarSize = Ext.scrollbar.size()[names.size] + extraPadding + 'px';
  this.callParent([axis, oldAxis]);
  el.setStyle(names.size, scrollbarSize);
  el.setStyle(names.margin, scrollbarSize);
  innerEl.setStyle(names.minSize, 'calc(100% - ' + scrollbarSize + ')');
}, updateEnabled:function(enabled) {
  var me = this, scroller = me.getScroller(), scrollerElement;
  if (!me.destroying && !me.destroyed) {
    me.toggleCls(me.enabledCls, !!enabled);
  }
  if (scroller) {
    scrollerElement = scroller.getElement();
    if (scrollerElement && !scrollerElement.destroyed) {
      scrollerElement.toggleCls(me.names[me.getAxis()].scrollerCls, !!enabled);
    }
  }
}, updateScroller:function(scroller) {
  var me = this, scrollerElement;
  if (scroller) {
    scrollerElement = scroller.getElement();
    if (scrollerElement) {
      scrollerElement.appendChild(me.el);
      if (!scroller.isConfiguring) {
        me.setEnabled(scroller.isAxisEnabled(me.getAxis()));
      }
    }
  }
}, applyStylesheet:function() {
  var proto = this.self.prototype, stylesheet = proto.stylesheet;
  if (!stylesheet) {
    proto.stylesheet = stylesheet = Ext.util.CSS.createStyleSheet('');
  }
  return stylesheet;
}}});
Ext.define('Ext.scroll.indicator.Overlay', {extend:Ext.scroll.indicator.Indicator, alias:'scrollindicator.overlay', config:{axis:null, hideAnimation:true, hideDelay:100}, defaultHideAnimation:{to:{opacity:0}, duration:300}, names:{x:{side:'l', getSize:'getHeight', setLength:'setWidth', translate:'translateX'}, y:{side:'t', getSize:'getWidth', setLength:'setHeight', translate:'translateY'}}, oppositeAxis:{x:'y', y:'x'}, classCls:Ext.baseCSSPrefix + 'scrolloverlay', visible:false, element:{reference:'element', 
style:'opacity: 0'}, applyHideAnimation:function(hideAnimation) {
  if (hideAnimation) {
    hideAnimation = Ext.mergeIf({onEnd:this.onHideAnimationEnd, scope:this}, this.defaultHideAnimation, hideAnimation);
  }
  return hideAnimation;
}, constructor:function(config) {
  var me = this, axis;
  me.callParent([config]);
  if (Ext.os.is.iOS) {
    me.addUi('ios');
  }
  if (Ext.os.is.Android) {
    me.addUi('android');
  }
  axis = me.getAxis();
  me.names = me.names[axis];
}, hide:function() {
  var me = this, delay = me.getHideDelay();
  if (!me.visible) {
    return;
  }
  me.visible = false;
  if (delay) {
    me._hideTimer = Ext.defer(me.doHide, delay, me);
  } else {
    me.doHide();
  }
}, updateScroller:function(scroller) {
  scroller.getElement().appendChild(this.element);
}, updateValue:function(value) {
  var me = this, el = me.element, names = me.names, axis = me.getAxis(), scroller = me.getScroller(), maxScrollPosition = scroller.getMaxUserPosition()[axis], clientSize = scroller.getClientSize()[axis], baseLength = me.length, length = baseLength, maxPosition = clientSize - baseLength - me.sizeAdjust, round = Math.round, position;
  if (value < 0) {
    length = round(baseLength + baseLength * value / clientSize);
    position = 0;
  } else {
    if (value > maxScrollPosition) {
      length = round(baseLength - baseLength * (value - maxScrollPosition) / clientSize);
      position = maxPosition + baseLength - length;
    } else {
      position = round(value / maxScrollPosition * maxPosition);
    }
  }
  me[names.translate](position);
  el[names.setLength](length);
}, show:function() {
  var me = this, el = me.element, anim = el.getActiveAnimation();
  if (me.visible) {
    return;
  }
  me.visible = true;
  if (anim) {
    anim.end();
  }
  if (el.stopAnimation) {
    el.stopAnimation();
  }
  if (!me.size) {
    me.cacheStyles();
  }
  me.refreshLength();
  clearTimeout(me._hideTimer);
  el.setStyle('opacity', '');
}, destroy:function() {
  this.callParent();
  clearTimeout(this._hideTimer);
}, privates:{cacheStyles:function() {
  var me = this, el = me.element, names = me.names;
  me.size = el[names.getSize]();
  me.margin = el.getMargin(names.side);
}, doHide:function() {
  var animation = this.getHideAnimation(), el = this.element;
  if (animation) {
    el.animate(animation);
  } else {
    el.setStyle('opacity', 0);
  }
}, hasOpposite:function() {
  return this.getScroller().isAxisEnabled(this.oppositeAxis[this.getAxis()]);
}, onHideAnimationEnd:function() {
  this.element.setStyle('opacity', '0');
}, onScroll:function() {
  var me = this;
  me.setValue(me.getScroller().position[me.getAxis()]);
}, onScrollEnd:function() {
  this.hide();
}, onScrollStart:function() {
  var me = this;
  me.setValue(me.getScroller().position[me.getAxis()]);
  me.show();
}, refreshLength:function() {
  var me = this, names = me.names, axis = me.getAxis(), scroller = me.getScroller(), scrollSize = scroller.getSize()[axis], clientSize = scroller.getClientSize()[axis], ratio = clientSize / scrollSize, baseSizeAdjust = me.margin * 2, sizeAdjust = me.hasOpposite() ? baseSizeAdjust + me.size : baseSizeAdjust, length = Math.round((clientSize - sizeAdjust) * ratio);
  me.sizeAdjust = sizeAdjust;
  me.length = length;
  me.element[names.setLength](length);
}, translateX:function(value) {
  this.element.translate(value);
}, translateY:function(value) {
  this.element.translate(0, value);
}}});
Ext.define('Ext.scroll.VirtualScroller', {extend:Ext.scroll.Scroller, alias:'scroller.virtual', isVirtualScroller:true, config:{autoRefresh:false, barIndicator:{lazy:true, $value:{type:'bar'}}, bounceEasing:{duration:400}, directionLock:false, disabled:null, clientSize:undefined, scrollbarSize:{width:0, height:0}, indicators:{x:true, y:true}, infinite:true, innerElement:null, maxAbsoluteVelocity:6, maxPosition:{x:0, y:0}, maxUserPosition:{x:0, y:0}, minPosition:{x:0, y:0}, minUserPosition:{x:0, y:0}, 
momentumEasing:{momentum:{acceleration:30, friction:0.5}, bounce:{acceleration:30, springTension:0.3}, minVelocity:1}, outOfBoundRestrictFactor:0.5, overlayIndicator:{lazy:true, $value:{type:'overlay'}}, pageSize:{x:500000, y:500000}, slotSnapEasing:{duration:150}, slotSnapOffset:{x:0, y:0}, slotSnapSize:{x:0, y:0}, startMomentumResetTime:300}, eventedConfig:{offsetX:0, offsetY:0}, translatable:'csstransform', dragStartTime:0, dragEndTime:0, isDragging:false, isWheeling:false, isAnimating:false, 
touchScrollCount:0, isMouseEvent:{mousedown:1, mousemove:1, mouseup:1}, listenerMap:{touchstart:'onTouchStart', touchmove:'onTouchMove', dragstart:'onDragStart', drag:'onDrag', dragend:'onDragEnd'}, constructor:function(config) {
  var me = this, onEvent = 'onEvent', autoRefresh;
  me.elementListeners = {touchstart:onEvent, touchmove:onEvent, dragstart:onEvent, drag:onEvent, dragend:onEvent, wheel:'onWheel', scope:me};
  me.minPosition = {x:0, y:0};
  me.startPosition = {x:0, y:0};
  me.velocity = {x:0, y:0};
  me.isAxisEnabledFlags = {x:false, y:false};
  me.flickStartPosition = {x:0, y:0};
  me.flickStartTime = {x:0, y:0};
  me.lastDragPosition = {x:0, y:0};
  me.dragDirection = {x:0, y:0};
  me.scrollbarSize = {width:0, height:0};
  me.callParent([config]);
  autoRefresh = me.getAutoRefresh();
  me.refreshScrollbarSize();
  if (autoRefresh) {
    me.refresh(true);
  } else {
    me.refreshAxes();
    me.callIndicators('onRefresh');
  }
  me.scheduleRefresh = {idle:me.doRefresh, scope:me, single:true, destroyable:true};
}, doDestroy:function() {
  var me = this, element = me.getElement(), innerElement = me.getInnerElement(), sizeMonitors = me.sizeMonitors;
  if (sizeMonitors) {
    sizeMonitors.element.destroy();
    sizeMonitors.container.destroy();
  }
  if (element && !element.destroyed) {
    element.removeCls(me.cls);
  }
  if (innerElement && !innerElement.destroyed) {
    innerElement.removeCls(me.innerCls);
  }
  if (me._isWrapped) {
    if (!element.destroyed) {
      me.unwrapContent();
    }
    innerElement.destroy();
  }
  me.setElement(null);
  me.setInnerElement(null);
  me.setIndicators(null);
  Ext.destroyMembers(me, 'scrollbarCorner');
  me.callParent();
}, refresh:function(immediate) {
  var me = this;
  if (immediate) {
    me.doRefresh();
  } else {
    if (!me.refreshScheduled) {
      me.refreshScheduled = Ext.on(me.scheduleRefresh);
    }
  }
  return me;
}, updateDisabled:function(disabled) {
  if (!this.isConfiguring) {
    if (disabled) {
      this.detachListeners();
    } else {
      this.attachListeners();
    }
  }
}, updateElement:function(element, oldElement) {
  var me = this, virtualScrollerCls = me.virtualScrollerCls, innerElement = me.getInnerElement(), autoRefresh;
  me.callParent([element, oldElement]);
  if (oldElement && !oldElement.destroyed) {
    oldElement.removeCls(virtualScrollerCls);
  }
  if (element) {
    element.addCls(virtualScrollerCls);
    if (!innerElement) {
      innerElement = me.wrapContent(element);
      me.setInnerElement(innerElement);
    }
    if (!me.getDisabled()) {
      me.attachListeners();
    }
    if (!me.isConfiguring) {
      autoRefresh = me.getAutoRefresh();
      if (autoRefresh) {
        me.toggleResizeListeners(autoRefresh);
        me.refresh();
      }
    }
  }
}, applyIndicators:function(indicators, oldIndicators) {
  var me = this, type, defaultsConfig, xIndicator, yIndicator, oldXIndicator, oldYIndicator;
  if (indicators) {
    if (indicators === true || typeof indicators === 'string') {
      xIndicator = yIndicator = indicators;
    } else {
      type = indicators.type;
      xIndicator = indicators.x;
      yIndicator = indicators.y;
    }
  }
  if (oldIndicators) {
    indicators = oldIndicators;
  } else {
    indicators = {x:null, y:null};
  }
  if (xIndicator || yIndicator) {
    defaultsConfig = Ext.scrollbar.width() && type !== 'overlay' ? 'barIndicator' : 'overlayIndicator';
  }
  oldXIndicator = indicators.x;
  oldYIndicator = indicators.y;
  if (xIndicator) {
    indicators.x = Ext.Factory.scrollindicator.update(oldXIndicator, xIndicator, me, 'createXIndicator', defaultsConfig);
  } else {
    if (oldXIndicator) {
      oldXIndicator.destroy();
      indicators.x = null;
    }
  }
  if (yIndicator) {
    indicators.y = Ext.Factory.scrollindicator.update(oldYIndicator, yIndicator, me, 'createYIndicator', defaultsConfig);
  } else {
    if (oldYIndicator) {
      oldYIndicator.destroy();
      indicators.y = null;
    }
  }
  return indicators;
}, updateIndicators:function(indicators) {
  if (!this.isConfiguring) {
    this.refreshScrollbarSize();
  }
}, createXIndicator:function(defaults) {
  return Ext.apply({axis:'x', scroller:this}, defaults);
}, createYIndicator:function(defaults) {
  return Ext.apply({axis:'y', scroller:this}, defaults);
}, applySlotSnapSize:function(snapSize) {
  if (typeof snapSize === 'number') {
    snapSize = {x:snapSize, y:snapSize};
  }
  return snapSize;
}, updateX:function() {
  if (!this.isConfiguring) {
    this.refreshAxes();
    this.refreshScrollbarSize();
  }
}, updateY:function() {
  if (!this.isConfiguring) {
    this.refreshAxes();
    this.refreshScrollbarSize();
  }
}, privates:{virtualScrollerCls:Ext.baseCSSPrefix + 'virtualscroller', innerCls:Ext.baseCSSPrefix + 'scroller-inner', scrollbarCornerCls:Ext.baseCSSPrefix + 'scrollbar-corner', attachListeners:function() {
  this.getElement().on(this.elementListeners);
}, callIndicators:function(methodName, force) {
  var me = this, indicators = me.getIndicators(), xIndicator, yIndicator;
  if (indicators) {
    if (force || me.isAxisEnabled('x')) {
      xIndicator = indicators.x;
      if (xIndicator && xIndicator[methodName]) {
        xIndicator[methodName]();
      }
    }
    if (force || me.isAxisEnabled('y')) {
      yIndicator = indicators.y;
      if (yIndicator && yIndicator[methodName]) {
        yIndicator[methodName]();
      }
    }
  }
}, constrainX:function(x) {
  return Math.min(this.getMaxPosition().x, Math.max(x, 0));
}, constrainY:function(y) {
  return Math.min(this.getMaxPosition().y, Math.max(y, 0));
}, convertEasingConfig:function(config) {
  return config;
}, detachListeners:function() {
  this.getElement().un(this.elementListeners);
}, doRefresh:function(size) {
  var me = this, configuredSize = me.configuredSize;
  if (me.refreshScheduled) {
    me.refreshScheduled = me.refreshScheduled.destroy();
  }
  if (me.getElement()) {
    me.stopAnimation();
    me.getTranslatable().refresh();
    me.setSize({x:configuredSize.x ? undefined : null, y:configuredSize.y ? undefined : null});
    me.fireEvent('refresh', me);
  }
}, doScrollTo:function(x, y, animate) {
  var me = this, isDragging = me.isDragging, isPrimary = me.isPrimary, ret, deferred, position, positionChanged, translatable, translationX, translationY;
  if (me.destroyed || !me.getElement()) {
    return me;
  }
  translatable = me.getTranslatable();
  position = me.position;
  if (!isDragging || me.isAxisEnabled('x')) {
    if (isNaN(x) || typeof x !== 'number') {
      x = position.x;
    } else {
      if (isPrimary !== false && !isDragging) {
        x = me.constrainX(x);
      }
      if (position.x !== x) {
        positionChanged = true;
      }
    }
  }
  if (!isDragging || me.isAxisEnabled('y')) {
    if (isNaN(y) || typeof y !== 'number') {
      y = position.y;
    } else {
      if (isPrimary !== false && !isDragging) {
        y = me.constrainY(y);
      }
      if (position.y !== y) {
        positionChanged = true;
      }
    }
  }
  if (positionChanged) {
    if (!me.isScrolling) {
      me.onScrollStart();
    }
    translationX = me.convertX(-x);
    translationY = -y;
    if (animate) {
      deferred = new Ext.Deferred;
      translatable.on('animationend', function() {
        if (me.destroyed) {
          deferred.reject();
        } else {
          deferred.resolve();
        }
      }, Ext.global, {single:true, onFrame:true});
      translatable.translateAnimated(translationX, translationY, animate);
      ret = deferred.promise;
    } else {
      translatable.translate(translationX, translationY);
      me.onScroll(x, y);
      if (me.isWheeling || me.isScrollbarScrolling) {
        me.onScrollEnd();
      } else {
        if (!isDragging) {
          me.doOnScrollEnd();
        }
      }
    }
  } else {
    if (animate && animate.callback) {
      animate.callback();
    }
  }
  return ret || Ext.Deferred.getCachedResolved();
}, getAnimationEasing:function(axis, e) {
  if (!this.isAxisEnabled(axis)) {
    return null;
  }
  var me = this, currentPosition = me.position[axis], minPosition = me.getMinUserPosition()[axis], maxPosition = me.getMaxUserPosition()[axis], maxAbsVelocity = me.getMaxAbsoluteVelocity(), boundValue = null, dragEndTime = me.dragEndTime, velocity = e.flick.velocity[axis], isX = axis === 'x', easingConfig, easing;
  if (currentPosition < minPosition) {
    boundValue = minPosition;
  } else {
    if (currentPosition > maxPosition) {
      boundValue = maxPosition;
    }
  }
  if (isX) {
    currentPosition = me.convertX(currentPosition);
    boundValue = me.convertX(boundValue);
  }
  if (boundValue !== null) {
    easing = me.getBounceEasing()[axis];
    easing.setConfig({startTime:dragEndTime, startValue:-currentPosition, endValue:-boundValue});
    return easing;
  }
  if (velocity === 0) {
    return null;
  }
  if (velocity < -maxAbsVelocity) {
    velocity = -maxAbsVelocity;
  } else {
    if (velocity > maxAbsVelocity) {
      velocity = maxAbsVelocity;
    }
  }
  easing = me.getMomentumEasing()[axis];
  easingConfig = {startTime:dragEndTime, startValue:-currentPosition, startVelocity:velocity * 1.5, minMomentumValue:-maxPosition, maxMomentumValue:0};
  if (isX) {
    me.convertEasingConfig(easingConfig);
  }
  easing.setConfig(easingConfig);
  return easing;
}, getSnapPosition:function(axis) {
  var me = this, snapSize = me.getSlotSnapSize()[axis], snapPosition = null, position, snapOffset, maxPosition, mod;
  if (snapSize !== 0 && me.isAxisEnabled(axis)) {
    position = me.position[axis];
    snapOffset = me.getSlotSnapOffset()[axis];
    maxPosition = me.getMaxUserPosition()[axis];
    mod = Math.floor((position - snapOffset) % snapSize);
    if (mod !== 0) {
      if (position !== maxPosition) {
        if (Math.abs(mod) > snapSize / 2) {
          snapPosition = Math.min(maxPosition, position + (mod > 0 ? snapSize - mod : mod - snapSize));
        } else {
          snapPosition = position - mod;
        }
      } else {
        snapPosition = position - mod;
      }
    }
  }
  return snapPosition;
}, isAxisEnabled:function(axis) {
  this.getX();
  this.getY();
  return this.isAxisEnabledFlags[axis];
}, onAnimationEnd:function() {
  this.isAnimating = false;
  this.snapToBoundary();
  this.onScrollEnd();
}, onAnimationFrame:function(translatable, x, y) {
  this.onScroll(this.convertX(-x), -y);
}, onAnimationStart:function() {
  this.isAnimating = true;
}, onAxisDrag:function(axis, delta) {
  if (delta && this.isAxisEnabled(axis)) {
    var me = this, flickStartPosition = me.flickStartPosition, flickStartTime = me.flickStartTime, lastDragPosition = me.lastDragPosition, dragDirection = me.dragDirection, old = me.position[axis], min = me.getMinUserPosition()[axis], max = me.getMaxUserPosition()[axis], start = me.startPosition[axis], last = lastDragPosition[axis], current = start - delta, lastDirection = dragDirection[axis], restrictFactor = me.getOutOfBoundRestrictFactor(), startMomentumResetTime = me.getStartMomentumResetTime(), 
    now = Ext.Date.now(), distance;
    if (current < min) {
      current *= restrictFactor;
    } else {
      if (current > max) {
        distance = current - max;
        current = max + distance * restrictFactor;
      }
    }
    if (current > last) {
      dragDirection[axis] = 1;
    } else {
      if (current < last) {
        dragDirection[axis] = -1;
      }
    }
    if (lastDirection !== 0 && dragDirection[axis] !== lastDirection || now - flickStartTime[axis] > startMomentumResetTime) {
      flickStartPosition[axis] = old;
      flickStartTime[axis] = now;
    }
    lastDragPosition[axis] = current;
    return true;
  }
}, onDrag:function(e) {
  var me = this, lastDragPosition = me.lastDragPosition;
  if (!me.isDragging) {
    return;
  }
  if (me.onAxisDrag('x', me.convertX(e.deltaX)) | me.onAxisDrag('y', e.deltaY)) {
    me.doScrollTo(lastDragPosition.x, lastDragPosition.y);
  }
}, onDragEnd:function(e) {
  var me = this, easingX, easingY;
  if (me.isDragging) {
    me.dragEndTime = Ext.Date.now();
    me.onDrag(e);
    me.isDragging = false;
    easingX = me.getAnimationEasing('x', e);
    easingY = me.getAnimationEasing('y', e);
    if (easingX || easingY) {
      me.getTranslatable().animate(easingX, easingY);
    } else {
      me.onScrollEnd();
    }
  }
}, onDragStart:function(e) {
  var me = this, absDeltaX = e.absDeltaX, absDeltaY = e.absDeltaY, startPosition = me.startPosition, flickStartPosition = me.flickStartPosition, flickStartTime = me.flickStartTime, lastDragPosition = me.lastDragPosition, currentPosition = me.position, dragDirection = me.dragDirection, x = currentPosition.x, y = currentPosition.y, now = Ext.Date.now(), horizontal = me.getX(), vertical = me.getY();
  Ext.undefer(me.scrollEndTimer);
  if (me.getDirectionLock() && !(horizontal && vertical)) {
    if (horizontal && absDeltaX > absDeltaY || vertical && absDeltaY > absDeltaX) {
      e.stopPropagation();
    } else {
      return;
    }
  }
  lastDragPosition.x = x;
  lastDragPosition.y = y;
  flickStartPosition.x = x;
  flickStartPosition.y = y;
  startPosition.x = x;
  startPosition.y = y;
  flickStartTime.x = now;
  flickStartTime.y = now;
  dragDirection.x = 0;
  dragDirection.y = 0;
  me.dragStartTime = now;
  me.isDragging = true;
  if (!me.isScrolling) {
    me.onScrollStart();
  }
}, onElementResize:function() {
  this.refresh(true);
}, onEvent:function(e) {
  var me = this, self = me.self;
  if ((!self.isTouching || me.isTouching) && !self.isWheeling && e.pointerType !== 'mouse' && (me.getY() || me.getX())) {
    return me[me.listenerMap[e.type]](e);
  }
}, onInnerElementResize:function() {
  this.refresh(true);
}, onPartnerScroll:function(x, y) {
  this.callParent([x, y]);
  this.callIndicators('onScroll');
}, onPartnerScrollStart:function(x, y, deltaX, deltaY) {
  this.callParent([x, y, deltaX, deltaY]);
  this.callIndicators('onScrollStart');
}, onPartnerScrollEnd:function() {
  this.callParent();
  this.callIndicators('onScrollEnd', true);
}, onScroll:function(logicalX, logicalY) {
  var me = this, position = me.position, deltaX = logicalX - position.x, deltaY = logicalY - position.y, pageSize, pageSizeX, pageSizeY, offsetX, offsetY, physicalX, physicalY;
  if (deltaX || deltaY) {
    position.x = logicalX;
    position.y = logicalY;
    if (me.getInfinite()) {
      pageSize = me.getPageSize();
      pageSizeX = pageSize.x;
      if (pageSizeX) {
        offsetX = me.getOffsetX();
        physicalX = logicalX - offsetX;
        if (physicalX > pageSizeX) {
          me.setOffsetX(Math.floor(logicalX / pageSizeX) * pageSizeX);
        } else {
          if (physicalX < -pageSizeX) {
            me.setOffsetX(Math.ceil(logicalX / pageSizeX) * pageSizeX);
          }
        }
      }
      pageSizeY = pageSize.y;
      if (pageSizeY) {
        offsetY = me.getOffsetY();
        physicalY = logicalY - offsetY;
        if (physicalY > pageSizeY) {
          me.setOffsetY(Math.floor(logicalY / pageSizeY) * pageSizeY);
        } else {
          if (physicalY < -pageSizeY) {
            me.setOffsetY(Math.ceil(logicalY / pageSizeY) * pageSizeY);
          }
        }
      }
    }
    if (me.isPrimary) {
      me.callIndicators('onScroll');
      me.callPartners('onPartnerScroll', logicalX, logicalY);
      me.fireScroll(logicalX, logicalY, deltaX, deltaY);
      me.callPartners('fireScroll', logicalX, logicalY);
    }
  }
}, doOnScrollEnd:function() {
  var me = this, position = me.position, x = position.x, y = position.y;
  if (!me.destroying && !me.destroyed && me.isScrolling && me.isPrimary && !me.isTouching && !me.snapToSlot() && me.touchScrollCount <= 1) {
    me.isScrolling = Ext.isScrolling = me.isWheeling = me.self.isWheeling = me.isScrollbarScrolling = false;
    me.callIndicators('onScrollEnd');
    me.callPartners('onPartnerScrollEnd');
    me.fireScrollEnd(x, y);
    me.callPartners('fireScrollEnd', x, y);
    if (!me.isScrolling) {
      me.setPrimary(null);
    }
  }
  if (me.touchScrollCount > 0) {
    me.touchScrollCount--;
  }
}, onScrollStart:function() {
  var me = this, position = me.position, x = position.x, y = position.y;
  if (!me.isScrolling) {
    me.setPrimary(true);
    me.callIndicators('onScrollStart');
    me.callPartners('onPartnerScrollStart', x, y);
    me.fireScrollStart(x, y, 0, 0);
    me.callPartners('fireScrollStart', x, y);
  }
}, onTouchEnd:function() {
  var me = this;
  me.isTouching = me.self.isTouching = false;
  if (!me.isAnimating) {
    me.onScrollEnd();
  }
}, onTouchMove:function(e) {
  e.preventDefault();
}, onTouchStart:function(e) {
  var me = this;
  Ext.getDoc().on({touchend:'onTouchEnd', scope:me, single:true});
  me.isTouching = me.self.isTouching = true;
  me.stopAnimation();
  me.touchScrollCount++;
}, onWheel:function(e) {
  var me = this, self = me.self, deltaX = e.deltaX, deltaY = e.deltaY, position = me.position, oldX = position.x, oldY = position.y, x = me.constrainX(position.x + deltaX), y = me.constrainY(position.y + deltaY);
  if (x !== oldX || y !== oldY) {
    me.isWheeling = self.isWheeling = true;
    me.doScrollTo(x, y);
    e.preventDefault();
  } else {
    if (me.isScrolling) {
      me.onScrollEnd();
    }
  }
}, refreshAxes:function() {
  var me = this, flags = me.isAxisEnabledFlags, size = me.getSize(), clientSize = me.getClientSize(), maxX, maxY, x, y;
  if (!size || !clientSize) {
    return;
  }
  maxX = Math.max(0, size.x - clientSize.x);
  maxY = Math.max(0, size.y - clientSize.y);
  x = me.getX();
  y = me.getY();
  me.setMaxPosition({x:maxX, y:maxY});
  if (x === true || x === 'auto') {
    flags.x = !!maxX;
  } else {
    if (x === false) {
      flags.x = false;
    } else {
      if (x === 'scroll') {
        flags.x = true;
      }
    }
  }
  if (y === true || y === 'auto') {
    flags.y = !!maxY;
  } else {
    if (y === false) {
      flags.y = false;
    } else {
      if (y === 'scroll') {
        flags.y = true;
      }
    }
  }
  me.setMaxUserPosition({x:flags.x ? maxX : 0, y:flags.y ? maxY : 0});
  if (!me.isConfiguring) {
    me.callIndicators('onRefresh', true);
  }
}, refreshScrollbarSize:function() {
  var me = this, indicators = me.getIndicators(), barSize = me.scrollbarSize, scrollbarSize = Ext.scrollbar.size(), xIndicator, yIndicator;
  if (indicators) {
    xIndicator = indicators.x;
    yIndicator = indicators.y;
    if (xIndicator && xIndicator.isScrollbar && me.getX()) {
      barSize.height = scrollbarSize.height;
    }
    if (yIndicator && yIndicator.isScrollbar && me.getY()) {
      barSize.width = scrollbarSize.width;
    }
  }
}, refreshSize:function(size, oldSize) {
  var me = this, el = me.getElement(), extraPadding = Ext.isIE ? 1 : 0, scrollbarSize, scrollbarWidth, scrollbarHeight, globalScrollbarSize, hasVerticalScrollbar, hasHorizontalScrollbar, clientSizeX, clientSizeY, sizeX, sizeY, dom, innerDom, flags, measuredX, measuredY, indicators, xIndicator, yIndicator, recalcX, recalcY, scrollbarCorner;
  if (el && !el.destroyed) {
    dom = el.dom;
    innerDom = me.getInnerElement().dom;
    sizeX = size.x;
    sizeY = size.y;
    scrollbarSize = me.scrollbarSize;
    scrollbarWidth = scrollbarSize.width;
    scrollbarHeight = scrollbarSize.height;
    globalScrollbarSize = Ext.scrollbar.size();
    hasVerticalScrollbar = false;
    hasHorizontalScrollbar = false;
    indicators = me.getIndicators();
    xIndicator = indicators.x;
    yIndicator = indicators.y;
    scrollbarCorner = me.scrollbarCorner;
    if (sizeX === undefined) {
      sizeX = oldSize && oldSize.x;
    }
    if (sizeY === undefined) {
      sizeY = oldSize && oldSize.y;
    }
    if (sizeX == null) {
      sizeX = innerDom.scrollWidth;
      measuredX = true;
    }
    if (sizeY == null) {
      sizeY = innerDom.scrollHeight;
      measuredY = true;
    }
    clientSizeX = dom.clientWidth;
    clientSizeY = dom.clientHeight;
    flags = me.getScrollbarFlags(sizeX, sizeY, clientSizeX, clientSizeY);
    hasVerticalScrollbar = !!(flags & 1);
    hasHorizontalScrollbar = !!(flags & 2);
    if (flags && flags !== me.scrollbarFlags) {
      if (xIndicator) {
        xIndicator.setEnabled(me.getX() === 'scroll');
        xIndicator.setStyle('visibility', 'hidden');
      }
      if (yIndicator) {
        yIndicator.setEnabled(me.getY() === 'scroll');
        yIndicator.setStyle('visibility', 'hidden');
      }
      if (measuredX && hasVerticalScrollbar) {
        yIndicator.setEnabled(true);
        recalcX = true;
      }
      if (measuredY && hasHorizontalScrollbar) {
        xIndicator.setEnabled(true);
        recalcY = true;
      }
      if (recalcX) {
        sizeX = innerDom.scrollWidth;
      }
      if (recalcY) {
        sizeY = innerDom.scrollHeight;
      }
      if (recalcX || recalcY) {
        flags = me.getScrollbarFlags(sizeX, sizeY, clientSizeX, clientSizeY);
        hasVerticalScrollbar = !!(flags & 1);
        hasHorizontalScrollbar = !!(flags & 2);
      }
      if (hasHorizontalScrollbar && hasVerticalScrollbar) {
        if (!scrollbarCorner) {
          me.scrollbarCorner = scrollbarCorner = me.getElement().createChild({cls:me.scrollbarCornerCls});
          scrollbarCorner.setVisibilityMode(2);
          if (Ext.isWindows) {
            scrollbarCorner.setStyle({width:scrollbarWidth + extraPadding + 'px', height:scrollbarHeight + extraPadding + 'px'});
          }
        }
        scrollbarCorner.show();
      } else {
        if (scrollbarCorner) {
          scrollbarCorner.hide();
        }
      }
      if (xIndicator) {
        xIndicator.setStyle('visibility', '');
      }
      if (yIndicator) {
        yIndicator.setStyle('visibility', '');
      }
      me.scrollbarFlags = flags;
      me.setScrollbarSize({width:hasVerticalScrollbar ? scrollbarWidth : 0, height:hasHorizontalScrollbar ? scrollbarHeight : 0, reservedWidth:hasVerticalScrollbar ? globalScrollbarSize.reservedWidth : '', reservedHeight:hasHorizontalScrollbar ? globalScrollbarSize.reservedHeight : ''});
    }
    clientSizeX = hasVerticalScrollbar ? clientSizeX - scrollbarWidth : clientSizeX;
    clientSizeY = hasHorizontalScrollbar ? clientSizeY - scrollbarHeight : clientSizeY;
    me.setClientSize({x:clientSizeX, y:clientSizeY});
    return {x:Math.max(sizeX, clientSizeX), y:Math.max(sizeY, clientSizeY)};
  }
  return null;
}, getScrollbarFlags:function(sizeX, sizeY, clientSizeX, clientSizeY) {
  var me = this, flags = 0, scrollbarSize = me.scrollbarSize, scrollbarWidth = scrollbarSize.width, scrollbarHeight = scrollbarSize.height;
  if (scrollbarWidth && (me.getY() === 'scroll' || sizeY > clientSizeY)) {
    flags |= 1;
  }
  if (scrollbarHeight && (me.getX() === 'scroll' || sizeX > clientSizeX)) {
    flags |= 2;
  }
  if (flags & 1 && (scrollbarHeight && sizeX > clientSizeX - scrollbarWidth)) {
    flags |= 2;
  }
  if (flags & 2 && (scrollbarWidth && sizeY > clientSizeY - scrollbarHeight)) {
    flags |= 1;
  }
  return flags;
}, snapToBoundary:function() {
  var me = this, position = me.getPosition();
  if (me.isConfiguring || !(position.x || position.y)) {
    return;
  }
  var minPosition = me.getMinUserPosition(), maxPosition = me.getMaxUserPosition(), minX = minPosition.x, minY = minPosition.y, maxX = maxPosition.x, maxY = maxPosition.y, x = Math.round(position.x), y = Math.round(position.y);
  if (x < minX) {
    x = minX;
  } else {
    if (x > maxX) {
      x = maxX;
    }
  }
  if (y < minY) {
    y = minY;
  } else {
    if (y > maxY) {
      y = maxY;
    }
  }
  me.doScrollTo(x, y);
}, snapToSlot:function() {
  var me = this, snapX = me.getSnapPosition('x'), snapY = me.getSnapPosition('y'), easing = me.getSlotSnapEasing();
  if (snapX !== null || snapY !== null) {
    me.doScrollTo(snapX, snapY, {easingX:easing.x, easingY:easing.y});
    return true;
  }
  return false;
}, stopAnimation:function() {
  this.getTranslatable().stopAnimation();
}, syncOffsets:function(translatable) {
  translatable.setOffsetX(-this.getOffsetX());
  translatable.setOffsetY(-this.getOffsetY());
}, toggleResizeListeners:function(autoRefresh) {
  var me = this, element = me.getElement(), method, innerElement;
  if (element) {
    innerElement = me.getInnerElement();
    method = autoRefresh ? 'on' : 'un';
    element[method]('resize', 'onElementResize', me);
    innerElement[method]('resize', 'onInnerElementResize', me);
  }
}, unwrapContent:function() {
  var innerDom = this.getInnerElement().dom, dom = this.getElement().dom, child;
  while (child = innerDom.firstChild) {
    dom.insertBefore(child, innerDom);
  }
}, wrapContent:function(element) {
  var wrap = document.createElement('div'), dom = element.dom, child;
  while (child = dom.lastChild) {
    wrap.insertBefore(child, wrap.firstChild);
  }
  dom.appendChild(wrap);
  this.setInnerElement(wrap);
  this._isWrapped = true;
  return this.getInnerElement();
}, updateAutoRefresh:function(autoRefresh) {
  this.toggleResizeListeners(autoRefresh);
}, applyBounceEasing:function(easing) {
  var defaultClass = Ext.fx.easing.EaseOut;
  return {x:Ext.factory(easing, defaultClass), y:Ext.factory(easing, defaultClass)};
}, updateBounceEasing:function(easing) {
  this.getTranslatable().setEasingX(easing.x).setEasingY(easing.y);
}, updateClientSize:function() {
  if (!this.isConfiguring) {
    this.refreshAxes();
  }
}, applyInnerElement:function(innerElement) {
  if (innerElement) {
    if (!innerElement.isElement) {
      innerElement = Ext.get(innerElement);
    }
  }
  if (this.isConfiguring && !innerElement) {
    Ext.raise('Cannot create Ext.scroll.VirtualScroller with null innerElement');
  }
  return innerElement;
}, updateInnerElement:function(innerElement) {
  if (innerElement) {
    innerElement.addCls(this.innerCls);
  }
  this.getTranslatable().setElement(innerElement);
}, applyMaxPosition:function(maxPosition, oldMaxPosition) {
  if (oldMaxPosition && maxPosition.x === oldMaxPosition.x && maxPosition.y === oldMaxPosition.y) {
    return;
  }
  var translatable = this.getTranslatable(), yEasing;
  if (translatable.isAnimating) {
    yEasing = translatable.activeEasingY;
    if (yEasing && yEasing.getStartVelocity && yEasing.getStartVelocity() < 0 && maxPosition.y < oldMaxPosition.y) {
      yEasing.setMinMomentumValue(-maxPosition.y);
    }
  }
  return maxPosition;
}, applyMaxUserPosition:function(maxUserPosition, oldMaxUserPosition) {
  if (!oldMaxUserPosition || maxUserPosition.x !== oldMaxUserPosition.x || maxUserPosition.y !== oldMaxUserPosition.y) {
    return maxUserPosition;
  }
}, updateMaxUserPosition:function() {
  this.snapToBoundary();
}, updateMinUserPosition:function() {
  this.snapToBoundary();
}, applyMomentumEasing:function(easing) {
  var defaultClass = Ext.fx.easing.BoundMomentum;
  return {x:Ext.factory(easing, defaultClass), y:Ext.factory(easing, defaultClass)};
}, updateOffsetX:function(offsetX) {
  if (!this.isConfiguring) {
    this.getTranslatable().setOffsetX(offsetX);
  }
}, updateOffsetY:function(offsetY) {
  if (!this.isConfiguring) {
    this.getTranslatable().setOffsetY(offsetY);
  }
}, applySize:function(size, oldSize) {
  size = this.callParent([size, oldSize]);
  return this.refreshSize(size, oldSize);
}, updateSize:function(size, oldSize) {
  if (!this.isConfiguring) {
    this.refreshAxes();
  }
}, applySlotSnapEasing:function(easing) {
  var defaultClass = Ext.fx.easing.EaseOut;
  return {x:Ext.factory(easing, defaultClass), y:Ext.factory(easing, defaultClass)};
}, applySlotSnapOffset:function(snapOffset) {
  if (typeof snapOffset === 'number') {
    snapOffset = {x:snapOffset, y:snapOffset};
  }
  return snapOffset;
}, updateTranslatable:function(translatable) {
  if (translatable) {
    translatable.on({animationframe:'onAnimationFrame', animationstart:'onAnimationStart', animationend:'onAnimationEnd', scope:this});
  }
}, createTranslatable:function(defaults) {
  return Ext.apply({element:this.getInnerElement()}, defaults);
}}});
Ext.define('Ext.state.Builder', {constructor:function(parent, name) {
  var me = this;
  me.name = name || null;
  me.parent = parent || null;
  me.root = parent ? parent.root : me;
}, child:function(name) {
  return new this.self(this, name);
}, get:function(name) {
  var data = this.getData(), ret;
  if (data && data.$) {
    ret = data.$[name];
  }
  return ret;
}, remove:function(name) {
  var data = this.getData();
  if (data && data.$) {
    delete data.$[name];
  }
}, save:function(instance, name) {
  var me = this, cfg = instance.self.$config.configs[name], value = instance[cfg.names.get](), statefulConfigs = instance.$statefulConfigs, save = statefulConfigs && statefulConfigs[name];
  if (!save && !cfg.equals(instance.config[name], value)) {
    statefulConfigs = statefulConfigs || (instance.$statefulConfigs = {});
    statefulConfigs[name] = save = true;
  }
  if (save) {
    if (!cfg.save || cfg.save(me, name, value, instance) !== false) {
      me.set(name, value);
    }
  }
  return me;
}, set:function(name, value) {
  var me = this, data = me.data, s;
  if (typeof name === 'string') {
    if (value === undefined) {
      if (data) {
        data = data.$;
      }
      if (data) {
        delete data[name];
      }
    } else {
      data = data || me.getData(true);
      data = data.$ || (data.$ = {});
      data[name] = value;
    }
  } else {
    for (s in name) {
      me.set(s, name[s]);
    }
  }
  return me;
}, privates:{data:null, id:null, owner:null, clear:function() {
  var me = this, parent = me.parent, data = parent && parent.getData();
  if (data) {
    delete data[me.name];
  }
  me.data = null;
}, getData:function(create) {
  var me = this, parent = me.parent, data = me.data, name = me.name;
  if (!data) {
    if (parent) {
      parent = parent.getData(create);
      if (parent) {
        if (!(data = parent[name] || null) && create) {
          parent[name] = data = {};
        }
      }
    } else {
      if (create) {
        data = {};
      }
    }
    me.data = data;
  }
  return data;
}}});
Ext.define('Ext.tip.Manager', {config:{tooltip:{xtype:'tooltip', align:'', anchorToTarget:false, anchor:false, closeAction:'hide', quickShowInterval:0, maxWidth:'80vw'}, overflowTip:{align:'l-r?', anchor:true, showOnTap:true}}, interceptTitles:false, constructor:function(config) {
  var me = this, tip;
  me.initConfig(config);
  me._fly = new Ext.dom.Fly;
  me.tip = tip = Ext.create(me.createTooltip());
  tip.allowRealign = false;
  tip.on({beforeshow:'onBeforeShow', hovertarget:'onHoverTarget', scope:me});
  me.globalListeners = Ext.on({scope:me, destroyable:true, dragstart:'dragDisable', dragend:'dragEnable', dragcancel:'dragEnable'});
  if (!me.self.instance) {
    me.self.instance = me;
  }
}, disable:function() {
  var n = ++this.disabled;
  if (n === 1) {
    this.getTooltip().disable();
  }
}, enable:function() {
  var n = --this.disabled;
  if (n === 0) {
    this.getTooltip().enable();
  } else {
    if (n < 0) {
      this.disabled = 0;
    }
  }
}, destroy:function() {
  var me = this;
  if (me.self.instance === me) {
    me.self.instance = null;
  }
  me._fly.detach();
  me.globalListeners = me.tip = Ext.destroy(me.tip, me.globalListeners);
  me.callParent();
}, createTooltip:function() {
  var me = this, config = me.getTooltip();
  return Ext.apply({id:'ext-global-tooltip', delegate:me.delegateQuickTip.bind(me), target:Ext.getBody()}, config);
}, hide:function() {
  if (this.tip) {
    this.tip.hide();
  }
}, privates:{disabled:0, _propertyMap:function() {
  var numFn = function(v) {
    return parseInt(v, 10);
  }, boolFn = function(v) {
    return !!v;
  }, fn = Ext.identityFn;
  return {ui:{prop:'data-qui', parse:fn}, html:{prop:'data-qtip', parse:fn}, width:{prop:'data-qwidth', parse:numFn}, minWidth:{prop:'data-qminWidth', parse:fn}, maxWidth:{prop:'data-qmaxWidth', parse:fn}, title:{prop:'data-qtitle', parse:fn}, autoHide:{prop:'data-qautoHide', parse:boolFn}, cls:{prop:'data-qcls', parse:fn}, axisLock:{prop:'data-axislock', parse:fn}, align:{prop:'data-qalign', parse:fn}, alignDelegate:{prop:'data-qaligndelegate', parse:fn}, anchor:{prop:'data-qanchor', parse:fn}, 
  showDelay:{prop:'data-qshowDelay', parse:numFn}, hideDelay:{prop:'data-qhideDelay', parse:numFn}, dismissDelay:{prop:'data-qdismissDelay', parse:numFn}, trackMouse:{prop:'data-qtrackMouse', parse:boolFn}, anchorToTarget:{prop:'data-qanchorToTarget', parse:boolFn}, allowOver:{prop:'data-qallowover', parse:boolFn}, closable:true};
}(), applyOverflowTip:function(config) {
  var phone = Ext.platformTags.phone;
  return Ext.apply({axisLock:!phone, maxWidth:phone ? '80vw' : 400}, config);
}, delegateQuickTip:function(dom) {
  var qtip = this.getTipConfig(dom, 'html');
  return !!qtip;
}, dragDisable:function() {
  if (!this.disabled) {
    this.tip.disable();
  }
}, dragEnable:function() {
  if (!this.disabled) {
    this.tip.enable();
  }
}, getTipConfig:function(dom, property) {
  var me = this, propertyMap = me._propertyMap, tipDefaults = me._tipDefaults, fly = me._fly, data = fly.attach(dom).getData().qtip, tip = me.tip, textAttr = propertyMap.html.prop, name, text, ret, value, item;
  if (!tipDefaults && property !== 'html') {
    me._tipDefaults = tipDefaults = {};
    for (name in propertyMap) {
      tipDefaults[name] = tip.getConfig(name);
    }
  }
  if (data) {
    if (property) {
      ret = data[property];
    } else {
      ret = Ext.apply({}, tipDefaults);
      Ext.apply(ret, data);
    }
  } else {
    if (dom.hasAttribute(textAttr)) {
      text = dom.getAttribute(textAttr);
      if (!text) {
        text = me.interceptTitles && dom.title;
        if (text) {
          dom.setAttribute(textAttr, text);
          dom.removeAttribute('title');
        }
      }
    } else {
      if (dom.hasAttribute('data-qoverflow')) {
        text = fly.dom.innerHTML;
        if (property !== 'html') {
          tipDefaults = Ext.apply({}, me.getOverflowTip(), tipDefaults);
        }
        if (!property) {
          if (!me.hasTextOverflow(dom)) {
            return false;
          }
        }
      }
    }
    if (text) {
      if (property === 'html') {
        ret = text;
      } else {
        if (property) {
          item = propertyMap[property];
          if (item.prop) {
            if (dom.hasAttribute(item.prop)) {
              ret = item.parse(dom.getAttribute(item.prop));
            }
          }
        } else {
          ret = data = {html:text};
          for (name in propertyMap) {
            if (name !== 'html') {
              item = propertyMap[name];
              value = null;
              if (item.prop) {
                if (dom.hasAttribute(item.prop)) {
                  value = item.parse(dom.getAttribute(item.prop));
                }
              }
              if (value === null) {
                value = tipDefaults[name];
              }
              data[name] = value;
            }
          }
        }
      }
    }
  }
  fly.detach();
  if (property && ret == null && property !== 'html') {
    ret = tipDefaults[property];
  }
  return ret;
}, onBeforeShow:function(tip) {
  var me = this, dom = tip.currentTarget.dom, data, header;
  if (dom) {
    data = me.getTipConfig(dom);
    if (data === false) {
      return false;
    }
    if (!data) {
      return;
    }
    data.anchorToTarget = !!(data.align || data.anchor);
    tip.setConfig(data);
    header = tip.getHeader();
    if (header) {
      header.setHidden(!data.title && !data.closable);
    }
  }
}, priorityConfigs:['showDelay', 'anchor', 'anchorToTarget', 'align', 'trackMouse'], onHoverTarget:function(tip, currentTarget) {
  var dom = currentTarget.dom, cfg;
  if (dom) {
    cfg = {};
    this.priorityConfigs.forEach(function(name) {
      cfg[name] = this.getTipConfig(dom, name);
    }, this);
    cfg.anchorToTarget = !!(cfg.align || cfg.anchor);
    tip.setConfig(cfg);
  }
}, hasTextOverflow:function(candidate) {
  var textSize;
  if (Ext.fly(candidate).isStyle('text-overflow', 'ellipsis')) {
    textSize = Ext.util.TextMetrics.measure(candidate, candidate.innerHTML);
    return textSize.width > Ext.fly(candidate).getViewRegion().width;
  }
}}});
Ext.namespace('Ext.theme.is').Neptune = true;
Ext.theme.name = 'Neptune';
Ext.theme.getDocCls = function() {
  return Ext.platformTags.desktop ? '' : 'x-big';
};
Ext.define('Ext.theme.Material', {singleton:true, _autoUpdateMeta:true, _defaultWeight:'500', _colors:{'red':{50:'#ffebee', 100:'#ffcdd2', 200:'#ef9a9a', 300:'#e57373', 400:'#ef5350', 500:'#f44336', 600:'#e53935', 700:'#d32f2f', 800:'#c62828', 900:'#b71c1c', 'a100':'#ff8a80', 'a200':'#ff5252', 'a400':'#ff1744', 'a700':'#d50000'}, 'pink':{50:'#fce4ec', 100:'#f8bbd0', 200:'#f48fb1', 300:'#f06292', 400:'#ec407a', 500:'#e91e63', 600:'#d81b60', 700:'#c2185b', 800:'#ad1457', 900:'#880e4f', 'a100':'#ff80ab', 
'a200':'#ff4081', 'a400':'#f50057', 'a700':'#c51162'}, 'purple':{50:'#f3e5f5', 100:'#e1bee7', 200:'#ce93d8', 300:'#ba68c8', 400:'#ab47bc', 500:'#9c27b0', 600:'#8e24aa', 700:'#7b1fa2', 800:'#6a1b9a', 900:'#4a148c', 'a100':'#ea80fc', 'a200':'#e040fb', 'a400':'#d500f9', 'a700':'#aa00ff'}, 'deep-purple':{50:'#ede7f6', 100:'#d1c4e9', 200:'#b39ddb', 300:'#9575cd', 400:'#7e57c2', 500:'#673ab7', 600:'#5e35b1', 700:'#512da8', 800:'#4527a0', 900:'#311b92', 'a100':'#b388ff', 'a200':'#7c4dff', 'a400':'#651fff', 
'a700':'#6200ea'}, 'indigo':{50:'#e8eaf6', 100:'#c5cae9', 200:'#9fa8da', 300:'#7986cb', 400:'#5c6bc0', 500:'#3f51b5', 600:'#3949ab', 700:'#303f9f', 800:'#283593', 900:'#1a237e', 'a100':'#8c9eff', 'a200':'#536dfe', 'a400':'#3d5afe', 'a700':'#304ffe'}, 'blue':{50:'#e3f2fd', 100:'#bbdefb', 200:'#90caf9', 300:'#64b5f6', 400:'#42a5f5', 500:'#2196f3', 600:'#1e88e5', 700:'#1976d2', 800:'#1565c0', 900:'#0d47a1', 'a100':'#82b1ff', 'a200':'#448aff', 'a400':'#2979ff', 'a700':'#2962ff'}, 'light-blue':{50:'#e1f5fe', 
100:'#b3e5fc', 200:'#81d4fa', 300:'#4fc3f7', 400:'#29b6f6', 500:'#03a9f4', 600:'#039be5', 700:'#0288d1', 800:'#0277bd', 900:'#01579b', 'a100':'#80d8ff', 'a200':'#40c4ff', 'a400':'#00b0ff', 'a700':'#0091ea'}, 'cyan':{50:'#e0f7fa', 100:'#b2ebf2', 200:'#80deea', 300:'#4dd0e1', 400:'#26c6da', 500:'#00bcd4', 600:'#00acc1', 700:'#0097a7', 800:'#00838f', 900:'#006064', 'a100':'#84ffff', 'a200':'#18ffff', 'a400':'#00e5ff', 'a700':'#00b8d4'}, 'teal':{50:'#e0f2f1', 100:'#b2dfdb', 200:'#80cbc4', 300:'#4db6ac', 
400:'#26a69a', 500:'#009688', 600:'#00897b', 700:'#00796b', 800:'#00695c', 900:'#004d40', 'a100':'#a7ffeb', 'a200':'#64ffda', 'a400':'#1de9b6', 'a700':'#00bfa5'}, 'green':{50:'#e8f5e9', 100:'#c8e6c9', 200:'#a5d6a7', 300:'#81c784', 400:'#66bb6a', 500:'#4caf50', 600:'#43a047', 700:'#388e3c', 800:'#2e7d32', 900:'#1b5e20', 'a100':'#b9f6ca', 'a200':'#69f0ae', 'a400':'#00e676', 'a700':'#00c853'}, 'light-green':{50:'#f1f8e9', 100:'#dcedc8', 200:'#c5e1a5', 300:'#aed581', 400:'#9ccc65', 500:'#8bc34a', 600:'#7cb342', 
700:'#689f38', 800:'#558b2f', 900:'#33691e', 'a100':'#ccff90', 'a200':'#b2ff59', 'a400':'#76ff03', 'a700':'#64dd17'}, 'lime':{50:'#f9fbe7', 100:'#f0f4c3', 200:'#e6ee9c', 300:'#dce775', 400:'#d4e157', 500:'#cddc39', 600:'#c0ca33', 700:'#afb42b', 800:'#9e9d24', 900:'#827717', 'a100':'#f4ff81', 'a200':'#eeff41', 'a400':'#c6ff00', 'a700':'#aeea00'}, 'yellow':{50:'#fffde7', 100:'#fff9c4', 200:'#fff59d', 300:'#fff176', 400:'#ffee58', 500:'#ffeb3b', 600:'#fdd835', 700:'#fbc02d', 800:'#f9a825', 900:'#f57f17', 
'a100':'#ffff8d', 'a200':'#ffff00', 'a400':'#ffea00', 'a700':'#ffd600'}, 'amber':{50:'#fff8e1', 100:'#ffecb3', 200:'#ffe082', 300:'#ffd54f', 400:'#ffca28', 500:'#ffc107', 600:'#ffb300', 700:'#ffa000', 800:'#ff8f00', 900:'#ff6f00', 'a100':'#ffe57f', 'a200':'#ffd740', 'a400':'#ffc400', 'a700':'#ffab00'}, 'orange':{50:'#fff3e0', 100:'#ffe0b2', 200:'#ffcc80', 300:'#ffb74d', 400:'#ffa726', 500:'#ff9800', 600:'#fb8c00', 700:'#f57c00', 800:'#ef6c00', 900:'#e65100', 'a100':'#ffd180', 'a200':'#ffab40', 'a400':'#ff9100', 
'a700':'#ff6d00'}, 'deep-orange':{50:'#fbe9e7', 100:'#ffccbc', 200:'#ffab91', 300:'#ff8a65', 400:'#ff7043', 500:'#ff5722', 600:'#f4511e', 700:'#e64a19', 800:'#d84315', 900:'#bf360c', 'a100':'#ff9e80', 'a200':'#ff6e40', 'a400':'#ff3d00', 'a700':'#dd2c00'}, 'brown':{50:'#efebe9', 100:'#d7ccc8', 200:'#bcaaa4', 300:'#a1887f', 400:'#8d6e63', 500:'#795548', 600:'#6d4c41', 700:'#5d4037', 800:'#4e342e', 900:'#3e2723'}, 'grey':{50:'#fafafa', 100:'#f5f5f5', 200:'#eeeeee', 300:'#e0e0e0', 400:'#bdbdbd', 500:'#9e9e9e', 
600:'#757575', 700:'#616161', 800:'#424242', 900:'#212121'}, 'blue-grey':{50:'#eceff1', 100:'#cfd8dc', 200:'#b0bec5', 300:'#90a4ae', 400:'#78909c', 500:'#607d8b', 600:'#546e7a', 700:'#455a64', 800:'#37474f', 900:'#263238', 1E3:'#11171a'}}, hasFashion:function() {
  return !!window.Fashion && !!Fashion.css && Fashion.css.setVariables;
}, setAutoUpdateMeta:function(value) {
  this._autoUpdateMeta = value;
}, getAutoUpdateMeta:function() {
  return this._autoUpdateMeta;
}, getDefaultWeight:function() {
  return this._defaultWeight;
}, setDarkMode:function(value) {
  if (!this.hasFashion()) {
    Ext.Logger.warn('Fashion was not found and is required to set CSS Variables for Material Theme');
    return;
  }
  Fashion.css.setVariables({'dark-mode':value ? 'true' : 'false'});
}, setColors:function(colorsConfig) {
  var obj = {}, baseColor, accentColor;
  if (!this.hasFashion()) {
    Ext.Logger.warn('Fashion was not found and is required to set CSS Variables for Material Theme');
    return;
  }
  colorsConfig = Ext.merge({baseWeight:this.getDefaultWeight(), accentWeight:this.getDefaultWeight()}, colorsConfig);
  baseColor = this._colors[colorsConfig.base];
  accentColor = this._colors[colorsConfig.accent];
  if (baseColor) {
    if (baseColor[colorsConfig.baseWeight]) {
      obj['base-color-name'] = colorsConfig.base;
      if (this.getAutoUpdateMeta()) {
        this.updateMetaThemeColor(colorsConfig.base, colorsConfig.baseWeight);
      }
    } else {
      Ext.Logger.warn('Base color weight: ' + colorsConfig.baseWeight + ' is not a valid weight', this);
    }
  } else {
    if (colorsConfig.base) {
      Ext.Logger.warn('Base color: ' + colorsConfig.base + ' is not a valid material color', this);
    }
  }
  if (accentColor) {
    if (accentColor[colorsConfig.accentWeight]) {
      obj['accent-color-name'] = colorsConfig.accent;
    } else {
      Ext.Logger.warn('Accent color weight: ' + colorsConfig.accentWeight + ' is not a valid weight', this);
    }
  } else {
    if (colorsConfig.accent) {
      Ext.Logger.warn('Accent color: ' + colorsConfig.accent + ' is not a valid material color', this);
    }
  }
  if (colorsConfig.darkMode !== null) {
    obj['dark-mode'] = colorsConfig.darkMode ? 'true' : 'false';
  }
  Fashion.css.setVariables(obj);
}, updateMetaThemeColor:function(colorName, weight) {
  var color = this._colors[colorName], toolbarIsDynamic = Ext.manifest.material.toolbar.dynamic, meta;
  if (!weight) {
    weight = this.getDefaultWeight();
  }
  if (Ext.platformTags.android && Ext.platformTags.chrome && toolbarIsDynamic && color) {
    color = color[weight];
    meta = Ext.query('meta[name\x3d"theme-color"]')[0];
    if (meta) {
      meta.setAttribute('content', color);
    }
  }
}, getColors:function() {
  return this._colors;
}});
var color, toolbarIsDynamic, head, meta;
if (Ext.platformTags.android && Ext.platformTags.chrome && Ext.manifest.material && Ext.manifest.material.toolbar) {
  color = Ext.manifest.material.toolbar.color;
  toolbarIsDynamic = Ext.manifest.material.toolbar.dynamic;
  head = document.head;
  if (toolbarIsDynamic && Ext.supports.CSSVariables) {
    color = getComputedStyle(document.body).getPropertyValue('--primary-color-md');
    color = color.replace(/ /g, '').replace(/^#(?:\\3)?/, '#');
  }
  if (color) {
    meta = document.createElement('meta');
    meta.setAttribute('name', 'theme-color');
    meta.setAttribute('content', color);
    head.appendChild(meta);
  }
}
Ext.namespace('Ext.theme.is').Material = true;
Ext.theme.name = 'Material';
Ext.namespace('Ext.theme.is')['cn-consult-theme-base'] = true;
Ext.theme.name = 'cn-consult-theme-base';
Ext.define(null, {override:'Ext.ux.gauge.needle.Abstract', compatibility:Ext.isIE10p, setTransform:function(centerX, centerY, rotation) {
  var needleGroup = this.getNeedleGroup();
  this.callParent([centerX, centerY, rotation]);
  needleGroup.set({transform:getComputedStyle(needleGroup.dom).getPropertyValue('transform')});
}, updateStyle:function(style) {
  var pathElement;
  this.callParent([style]);
  if (Ext.isObject(style) && 'transform' in style) {
    pathElement = this.getNeedlePath();
    pathElement.set({transform:getComputedStyle(pathElement.dom).getPropertyValue('transform')});
  }
}});
Ext.define('Ext.ux.ajax.Simlet', function() {
  var urlRegex = /([^?#]*)(#.*)?$/, dateRegex = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/, intRegex = /^[+-]?\d+$/, floatRegex = /^[+-]?\d+\.\d+$/;
  function parseParamValue(value) {
    var m;
    if (Ext.isDefined(value)) {
      value = decodeURIComponent(value);
      if (intRegex.test(value)) {
        value = parseInt(value, 10);
      } else {
        if (floatRegex.test(value)) {
          value = parseFloat(value);
        } else {
          if (!!(m = dateRegex.exec(value))) {
            value = new Date(Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +m[6]));
          }
        }
      }
    }
    return value;
  }
  return {alias:'simlet.basic', isSimlet:true, responseProps:['responseText', 'responseXML', 'status', 'statusText', 'responseHeaders'], status:200, statusText:'OK', constructor:function(config) {
    Ext.apply(this, config);
  }, doGet:function(ctx) {
    return this.handleRequest(ctx);
  }, doPost:function(ctx) {
    return this.handleRequest(ctx);
  }, doRedirect:function(ctx) {
    return false;
  }, doDelete:function(ctx) {
    var me = this, xhr = ctx.xhr, records = xhr.options.records;
    me.removeFromData(ctx, records);
  }, exec:function(xhr) {
    var me = this, ret = {}, method = 'do' + Ext.String.capitalize(xhr.method.toLowerCase()), fn = me[method];
    if (fn) {
      ret = fn.call(me, me.getCtx(xhr.method, xhr.url, xhr));
    } else {
      ret = {status:405, statusText:'Method Not Allowed'};
    }
    return ret;
  }, getCtx:function(method, url, xhr) {
    return {method:method, params:this.parseQueryString(url), url:url, xhr:xhr};
  }, handleRequest:function(ctx) {
    var me = this, ret = {}, val;
    Ext.Array.forEach(me.responseProps, function(prop) {
      if (prop in me) {
        val = me[prop];
        if (Ext.isFunction(val)) {
          val = val.call(me, ctx);
        }
        ret[prop] = val;
      }
    });
    return ret;
  }, openRequest:function(method, url, options, async) {
    var ctx = this.getCtx(method, url), redirect = this.doRedirect(ctx), xhr;
    if (options.action === 'destroy') {
      method = 'delete';
    }
    if (redirect) {
      xhr = redirect;
    } else {
      xhr = new Ext.ux.ajax.SimXhr({mgr:this.manager, simlet:this, options:options});
      xhr.open(method, url, async);
    }
    return xhr;
  }, parseQueryString:function(str) {
    var m = urlRegex.exec(str), ret = {}, key, value, pair, parts, i, n;
    if (m && m[1]) {
      parts = m[1].split('\x26');
      for (i = 0, n = parts.length; i < n; ++i) {
        if ((pair = parts[i].split('\x3d'))[0]) {
          key = decodeURIComponent(pair.shift());
          value = parseParamValue(pair.length > 1 ? pair.join('\x3d') : pair[0]);
          if (!(key in ret)) {
            ret[key] = value;
          } else {
            if (Ext.isArray(ret[key])) {
              ret[key].push(value);
            } else {
              ret[key] = [ret[key], value];
            }
          }
        }
      }
    }
    return ret;
  }, redirect:function(method, url, params) {
    switch(arguments.length) {
      case 2:
        if (typeof url === 'string') {
          break;
        }
        params = url;
      case 1:
        url = method;
        method = 'GET';
        break;
    }
    if (params) {
      url = Ext.urlAppend(url, Ext.Object.toQueryString(params));
    }
    return this.manager.openRequest(method, url);
  }, removeFromData:function(ctx, records) {
    var me = this, data = me.getData(ctx), model = ctx.xhr.options.proxy && ctx.xhr.options.proxy.getModel() || {}, idProperty = model.idProperty || 'id', i;
    Ext.each(records, function(record) {
      var id = record.get(idProperty);
      for (i = data.length; i-- > 0;) {
        if (data[i][idProperty] === id) {
          me.deleteRecord(i);
          break;
        }
      }
    });
  }};
}());
Ext.define('Ext.ux.ajax.DataSimlet', function() {
  function makeSortFn(def, cmp) {
    var order = def.direction, sign = order && order.toUpperCase() === 'DESC' ? -1 : 1;
    return function(leftRec, rightRec) {
      var lhs = leftRec[def.property], rhs = rightRec[def.property], c = lhs < rhs ? -1 : rhs < lhs ? 1 : 0;
      if (c || !cmp) {
        return c * sign;
      }
      return cmp(leftRec, rightRec);
    };
  }
  function makeSortFns(defs, cmp) {
    var sortFn, i;
    for (sortFn = cmp, i = defs && defs.length; i;) {
      sortFn = makeSortFn(defs[--i], sortFn);
    }
    return sortFn;
  }
  return {extend:Ext.ux.ajax.Simlet, buildNodes:function(node, path) {
    var me = this, nodeData = {data:[]}, len = node.length, children, i, child, name;
    me.nodes[path] = nodeData;
    for (i = 0; i < len; ++i) {
      nodeData.data.push(child = node[i]);
      name = child.text || child.title;
      child.id = path ? path + '/' + name : name;
      children = child.children;
      if (!(child.leaf = !children)) {
        delete child.children;
        me.buildNodes(children, child.id);
      }
    }
  }, deleteRecord:function(pos) {
    if (this.data && typeof this.data !== 'function') {
      Ext.Array.removeAt(this.data, pos);
    }
  }, fixTree:function(ctx, tree) {
    var me = this, node = ctx.params.node, nodes;
    if (!(nodes = me.nodes)) {
      me.nodes = nodes = {};
      me.buildNodes(tree, '');
    }
    node = nodes[node];
    if (node) {
      if (me.node) {
        me.node.sortedData = me.sortedData;
        me.node.currentOrder = me.currentOrder;
      }
      me.node = node;
      me.data = node.data;
      me.sortedData = node.sortedData;
      me.currentOrder = node.currentOrder;
    } else {
      me.data = null;
    }
  }, getData:function(ctx) {
    var me = this, params = ctx.params, order = (params.filter || '') + (params.group || '') + '-' + (params.sort || '') + '-' + (params.dir || ''), tree = me.tree, dynamicData, data, fields, sortFn, filters;
    if (tree) {
      me.fixTree(ctx, tree);
    }
    data = me.data;
    if (typeof data === 'function') {
      dynamicData = true;
      data = data.call(this, ctx);
    }
    if (!data || order === '--') {
      return data || [];
    }
    if (!dynamicData && order === me.currentOrder) {
      return me.sortedData;
    }
    ctx.filterSpec = params.filter && Ext.decode(params.filter);
    ctx.groupSpec = params.group && Ext.decode(params.group);
    fields = params.sort;
    if (params.dir) {
      fields = [{direction:params.dir, property:fields}];
    } else {
      if (params.sort) {
        fields = Ext.decode(params.sort);
      } else {
        fields = null;
      }
    }
    if (ctx.filterSpec) {
      filters = new Ext.util.FilterCollection;
      filters.add(this.processFilters(ctx.filterSpec));
      data = Ext.Array.filter(data, filters.getFilterFn());
    }
    sortFn = makeSortFns(ctx.sortSpec = fields);
    if (ctx.groupSpec) {
      sortFn = makeSortFns([ctx.groupSpec], sortFn);
    }
    data = Ext.isArray(data) ? data.slice(0) : data;
    if (sortFn) {
      Ext.Array.sort(data, sortFn);
    }
    me.sortedData = data;
    me.currentOrder = order;
    return data;
  }, processFilters:Ext.identityFn, getPage:function(ctx, data) {
    var ret = data, length = data.length, start = ctx.params.start || 0, end = ctx.params.limit ? Math.min(length, start + ctx.params.limit) : length;
    if (start || end < length) {
      ret = ret.slice(start, end);
    }
    return ret;
  }, getGroupSummary:function(groupField, rows, ctx) {
    return rows[0];
  }, getSummary:function(ctx, data, page) {
    var me = this, groupField = ctx.groupSpec.property, accum, todo = {}, summary = [], fieldValue, lastFieldValue;
    Ext.each(page, function(rec) {
      fieldValue = rec[groupField];
      todo[fieldValue] = true;
    });
    function flush() {
      if (accum) {
        summary.push(me.getGroupSummary(groupField, accum, ctx));
        accum = null;
      }
    }
    Ext.each(data, function(rec) {
      fieldValue = rec[groupField];
      if (lastFieldValue !== fieldValue) {
        flush();
        lastFieldValue = fieldValue;
      }
      if (!todo[fieldValue]) {
        return !summary.length;
      }
      if (accum) {
        accum.push(rec);
      } else {
        accum = [rec];
      }
      return true;
    });
    flush();
    return summary;
  }};
}());
Ext.define('Ext.ux.ajax.JsonSimlet', {extend:Ext.ux.ajax.DataSimlet, alias:'simlet.json', doGet:function(ctx) {
  var me = this, data = me.getData(ctx), page = me.getPage(ctx, data), reader = ctx.xhr.options.proxy && ctx.xhr.options.proxy.getReader(), root = reader && reader.getRootProperty(), ret = me.callParent(arguments), response = {};
  if (root && Ext.isArray(page)) {
    response[root] = page;
    response[reader.getTotalProperty()] = data.length;
  } else {
    response = page;
  }
  if (ctx.groupSpec) {
    response.summaryData = me.getSummary(ctx, data, page);
  }
  ret.responseText = Ext.encode(response);
  return ret;
}, doPost:function(ctx) {
  return this.doGet(ctx);
}});
Ext.define('Ext.ux.ajax.SimXhr', {readyState:0, mgr:null, simlet:null, constructor:function(config) {
  var me = this;
  Ext.apply(me, config);
  me.requestHeaders = {};
}, abort:function() {
  var me = this;
  if (me.timer) {
    Ext.undefer(me.timer);
    me.timer = null;
  }
  me.aborted = true;
}, getAllResponseHeaders:function() {
  var headers = [];
  if (Ext.isObject(this.responseHeaders)) {
    Ext.Object.each(this.responseHeaders, function(name, value) {
      headers.push(name + ': ' + value);
    });
  }
  return headers.join('\r\n');
}, getResponseHeader:function(header) {
  var headers = this.responseHeaders;
  return headers && headers[header] || null;
}, open:function(method, url, async, user, password) {
  var me = this;
  me.method = method;
  me.url = url;
  me.async = async !== false;
  me.user = user;
  me.password = password;
  me.setReadyState(1);
}, overrideMimeType:function(mimeType) {
  this.mimeType = mimeType;
}, schedule:function() {
  var me = this, delay = me.simlet.delay || me.mgr.delay;
  if (delay) {
    me.timer = Ext.defer(function() {
      me.onTick();
    }, delay);
  } else {
    me.onTick();
  }
}, send:function(body) {
  var me = this;
  me.body = body;
  if (me.async) {
    me.schedule();
  } else {
    me.onComplete();
  }
}, setReadyState:function(state) {
  var me = this;
  if (me.readyState !== state) {
    me.readyState = state;
    me.onreadystatechange();
  }
}, setRequestHeader:function(header, value) {
  this.requestHeaders[header] = value;
}, onreadystatechange:Ext.emptyFn, onComplete:function() {
  var me = this, callback, text;
  me.readyState = 4;
  Ext.apply(me, me.simlet.exec(me));
  callback = me.jsonpCallback;
  if (callback) {
    text = callback + '(' + me.responseText + ')';
    eval(text);
  }
}, onTick:function() {
  var me = this;
  me.timer = null;
  me.onComplete();
  if (me.onreadystatechange) {
    me.onreadystatechange();
  }
}});
Ext.define('Ext.ux.ajax.SimManager', {singleton:true, defaultType:'basic', delay:150, ready:false, constructor:function() {
  this.simlets = [];
}, getSimlet:function(url) {
  var me = this, index = url.indexOf('?'), simlets = me.simlets, len = simlets.length, i, simlet, simUrl, match;
  if (index < 0) {
    index = url.indexOf('#');
  }
  if (index > 0) {
    url = url.substring(0, index);
  }
  for (i = 0; i < len; ++i) {
    simlet = simlets[i];
    simUrl = simlet.url;
    if (simUrl instanceof RegExp) {
      match = simUrl.test(url);
    } else {
      match = simUrl === url;
    }
    if (match) {
      return simlet;
    }
  }
  return me.defaultSimlet;
}, getXhr:function(method, url, options, async) {
  var simlet = this.getSimlet(url);
  if (simlet) {
    return simlet.openRequest(method, url, options, async);
  }
  return null;
}, init:function(config) {
  var me = this;
  Ext.apply(me, config);
  if (!me.ready) {
    me.ready = true;
    if (!('defaultSimlet' in me)) {
      me.defaultSimlet = new Ext.ux.ajax.Simlet({status:404, statusText:'Not Found'});
    }
    me._openRequest = Ext.data.Connection.prototype.openRequest;
    Ext.data.request.Ajax.override({openRequest:function(options, requestOptions, async) {
      var xhr = !options.nosim && me.getXhr(requestOptions.method, requestOptions.url, options, async);
      if (!xhr) {
        xhr = this.callParent(arguments);
      }
      return xhr;
    }});
    if (Ext.data.JsonP) {
      Ext.data.JsonP.self.override({createScript:function(url, params, options) {
        var fullUrl = Ext.urlAppend(url, Ext.Object.toQueryString(params)), script = !options.nosim && me.getXhr('GET', fullUrl, options, true);
        if (!script) {
          script = this.callParent(arguments);
        }
        return script;
      }, loadScript:function(request) {
        var script = request.script;
        if (script.simlet) {
          script.jsonpCallback = request.params[request.callbackKey];
          script.send(null);
          request.script = document.createElement('script');
        } else {
          this.callParent(arguments);
        }
      }});
    }
  }
  return me;
}, openRequest:function(method, url, async) {
  var opt = {method:method, url:url};
  return this._openRequest.call(Ext.data.Connection.prototype, {}, opt, async);
}, register:function(simlet) {
  var me = this;
  me.init();
  function reg(one) {
    var simlet = one;
    if (!simlet.isSimlet) {
      simlet = Ext.create('simlet.' + (simlet.type || simlet.stype || me.defaultType), one);
    }
    me.simlets.push(simlet);
    simlet.manager = me;
  }
  if (Ext.isArray(simlet)) {
    Ext.each(simlet, reg);
  } else {
    if (simlet.isSimlet || simlet.url) {
      reg(simlet);
    } else {
      Ext.Object.each(simlet, function(url, s) {
        s.url = url;
        reg(s);
      });
    }
  }
  return me;
}});
Ext.define('cnconsult.logger.Logger', {alternateClassName:'cnconsult.Logger', singleton:true, config:{console:true}, constructor:function() {
  this.initConfig();
}, log:function(_options) {
  var hasConsoleSupport = console !== undefined;
  var hasGroupSupport = hasConsoleSupport && console.hasOwnProperty('groupCollapsed') && console.hasOwnProperty('groupEnd');
  var isOnlyMessage = Ext.isString(_options);
  var $jscomp$destructuring$var0 = _options;
  var prefix = $jscomp$destructuring$var0.prefix;
  var fn = $jscomp$destructuring$var0.fn;
  var level = $jscomp$destructuring$var0.level;
  var dump = $jscomp$destructuring$var0.dump;
  var stack = $jscomp$destructuring$var0.stack;
  var catchedError = $jscomp$destructuring$var0.catchedError;
  var useSentry = $jscomp$destructuring$var0.useSentry;
  var $jscomp$destructuring$var1 = _options;
  var message = $jscomp$destructuring$var1.message;
  var consoleType = 'log';
  if (isOnlyMessage) {
    message = _options;
  }
  if (prefix) {
    message = prefix + ' - ' + message;
  }
  if (level && level !== 'debug') {
    message = '[' + level.charAt(0).toUpperCase() + '] ' + message;
  }
  if (Ext.Array.contains(['info', 'warn', 'error'], level)) {
    consoleType = level;
  }
  if (fn) {
    message += '\nCaller: ' + fn.toString();
  }
  if (hasConsoleSupport && this.getConsole()) {
    if (isOnlyMessage) {
      console.log(message);
    } else {
      if (hasGroupSupport) {
        console.groupCollapsed(message);
      }
      if (Ext.isObject(dump)) {
        console[consoleType](message);
        console.log('Dump:');
        console.dir(dump);
      } else {
        if (dump !== undefined) {
          console[consoleType](message, dump);
        } else {
          console[consoleType](message);
        }
      }
      if (catchedError) {
        console.log('Exception catched Error:');
        console.dir(catchedError);
      }
      if (stack) {
        console.trace();
      }
      if (hasGroupSupport) {
        console.groupEnd();
      }
    }
  }
  if (window['Sentry'] !== undefined && useSentry) {
    Sentry.withScope(function(_scope) {
      if (catchedError) {
        _scope.setExtra('Error', message);
        Sentry.captureException(catchedError);
      } else {
        if (dump) {
          _scope.setExtra('dump', dump);
        }
        Sentry.captureMessage(message);
      }
    });
  }
}});
Ext.define('cnconsult.Translator', {requires:[], statics:{translation:{}, loadTranslation:function(_languageFileUrl) {
  this.translation = {};
  var url = _languageFileUrl;
  var isCrossOriginRestricted = false, xhr, status, noCacheUrl = url + '?dc\x3d' + Ext.Date.now();
  if (typeof XMLHttpRequest !== 'undefined') {
    xhr = new XMLHttpRequest;
  } else {
    xhr = new ActiveXObject('Microsoft.XMLHTTP');
  }
  try {
    xhr.open('GET', noCacheUrl, false);
    xhr.send(null);
  } catch (e$65) {
    isCrossOriginRestricted = true;
  }
  status = xhr.status === 1223 ? 204 : xhr.status;
  if (!isCrossOriginRestricted) {
    isCrossOriginRestricted = status === 0;
  }
  if (isCrossOriginRestricted) {
    cnconsult.Logger.log({prefix:'Translator-\x3eloadTranslation', message:"Failed loading synchronously via XHR: '" + url + "'; It's likely that the file is either " + 'being loaded from a different domain or from the local file system whereby cross origin ' + 'requests are not allowed due to security reasons. Use asynchronous loading with ' + 'Ext.require instead.', level:'error'});
  } else {
    if (status >= 200 && status < 300) {
      this.translation = Ext.JSON.decode(xhr.responseText);
    } else {
      cnconsult.Logger.log({prefix:'Translator-\x3eloadTranslation', message:'ERROR loading language file (' + url + ')', level:'error'});
    }
  }
  xhr = null;
}, loadTranslationAsync:function(_languageFileUrl, _callback, _scope) {
  this.translation = {};
  Ext.Ajax.request({url:_languageFileUrl, success:function(_response) {
    cnconsult.Logger.log({prefix:'Translator-\x3eloadTranslationAsync-\x3esuccess', message:'Loaded language, response is:', dump:_response});
    this.translation = Ext.JSON.decode(_response.responseText);
    cnconsult.Logger.log({prefix:'Translator-\x3eloadTranslationAsync-\x3esuccess', message:'Translation is:', dump:this.translation});
    Ext.callback(_callback, _scope);
  }, failure:function() {
    cnconsult.Logger.log({prefix:'Translator-\x3eloadTranslationAsync-\x3e-\x3efailure', message:'Failed to load translation file ' + _languageFileUrl + '!', level:'error'});
    Ext.callback(_callback, _scope);
  }, scope:this});
}, staticTr:function(_scope) {
  return function(_str) {
    return cnconsult.Translator.tr(_scope, _str, true);
  };
}, tr:function(_scope, _string, _isContext) {
  var string;
  var context;
  if (!_isContext) {
    if (_scope.trContext) {
      context = _scope.trContext;
    } else {
      context = _scope.$className;
    }
  } else {
    context = _scope;
  }
  if (this.translation[context] && this.translation[context][_string]) {
    string = this.translation[context][_string];
  } else {
    string = _string;
  }
  if (string.indexOf('%1') >= 0) {
    return new TranslatedString(string);
  } else {
    return string;
  }
}}});
function TranslatedString(_string) {
  this.string = _string;
  this.inArg = 0;
  this.arg = function() {
    for (var i = 0; i < arguments.length; i++) {
      this.inArg++;
      this.string = this.string.replace(new RegExp('%' + this.inArg, 'gm'), arguments[i]);
    }
    if (this.string.indexOf('%' + (this.inArg + 1)) >= 0) {
      return this;
    } else {
      return this.string;
    }
  };
  this.toString = function() {
    return this.string;
  };
}
String.prototype.arg = function() {
  cnconsult.Logger.log({prefix:'String-\x3earg', message:'Called string.arg() on a string that has no %1!', level:'warn'});
  return this;
};
Ext.define('cnconsult.Translatable', {tr:function(_string, _forceParentClass) {
  if (Ext.isBoolean(_forceParentClass) && _forceParentClass === true) {
    return cnconsult.Translator.tr(this.superclass, _string);
  } else {
    return cnconsult.Translator.tr(this, _string);
  }
}, trWithContext:function(_context, _string) {
  return cnconsult.Translator.tr(_context, _string, true);
}});
Ext.define('cnconsult.storage.Base', {config:{prefix:''}, mixins:[Ext.mixin.Observable], constructor:function(_config) {
  this.mixins.observable.constructor.call(this, _config);
}, set:function(_key, _value) {
}, get:function(_key, _defaultValue) {
  return _defaultValue;
}, getAll:function() {
  return {};
}, remove:function(_key) {
}, removeAll:function() {
  return false;
}});
Ext.define('cnconsult.storage.File', {extend:cnconsult.storage.Base, config:{syncRoot:'', fileSystem:null}, storedObject:null, fileWriter:null, blockedSaveAttempts:0, saveInProgress:false, configToSave:null, configFileName:'configStore', tempFile:null, constructor:function(_config) {
  this.callParent(arguments);
  this.bufferedSave = Ext.Function.createBuffered(function() {
    this.saveInProgress = true;
    this.configToSave = Ext.encode(this.storedObject);
    this.writeToTempFile();
  }, 500, this);
  if (this.config.prefix !== '') {
    this.configFileName += '_' + this.config.prefix;
  }
  this.config.fileSystem.root.getFile('sync/' + this.configFileName + '.json', {create:true, exclusive:false}, Ext.bind(this.loadConfigFile, this), function() {
    cnconsult.Logger.log({prefix:'File-\x3econstructor', message:'Error while loading config file', dump:arguments, level:'error'});
  });
}, loadConfigFile:function(_fileEntry) {
  _fileEntry.file(Ext.bind(function(_file) {
    var reader = new FileReader;
    reader.onloadend = Ext.bind(function(_event) {
      var conf = (new TextDecoder('utf-8')).decode(reader.result);
      if (conf === '') {
        cnconsult.Logger.log({prefix:'File-\x3eloadConfigFileForIos', message:'Storage is empty, checking whether temp file exists...'});
        this.config.fileSystem.root.getFile('sync/' + this.configFileName + '_temp.json', {exclusive:false}, Ext.bind(function(_fileEntry) {
          cnconsult.Logger.log({prefix:'File-\x3eloadConfigFileForIos', message:'There is a storage temp file, try to use this as storage...'});
          _fileEntry.file(Ext.bind(function(_file) {
            cnconsult.Logger.log({prefix:'File-\x3eloadConfigFileForIos', message:'Loading content of temp file...'});
            var tempReader = new FileReader;
            tempReader.onloadend = Ext.bind(function(_event) {
              var tempConf = (new TextDecoder('utf-8')).decode(tempReader.result);
              if (_event.target.result === '') {
                cnconsult.Logger.log({prefix:'File-\x3eloadConfigFileForIos', message:"Temp file is also empty, so we'll start with an empty storage."});
                this.storedObject = {};
              } else {
                this.storedObject = Ext.decode(tempConf);
              }
              cnconsult.Logger.log({prefix:'File-\x3eloadConfigFileForIos', message:'CONFIG LOADED (from temp file)', dump:this.storedObject});
              this.fireEvent('loaded');
            }, this);
            tempReader.readAsArrayBuffer(_file);
          }, this));
        }, this), Ext.bind(function() {
          cnconsult.Logger.log({prefix:'File-\x3eloadConfigFileForIos', message:"No storage files (normal or temp) found. Let's start with an empty storage!"});
          this.storedObject = {};
          this.fireEvent('loaded');
        }, this));
      } else {
        this.storedObject = Ext.decode(conf);
        cnconsult.Logger.log({prefix:'File-\x3eloadConfigFileForIos', message:'CONFIG LOADED', dump:this.storedObject});
        this.fireEvent('loaded');
      }
    }, this);
    reader.onerror = Ext.bind(function() {
      cnconsult.Logger.log({prefix:'File-\x3eloadConfigFileForIos', message:'Error loading conf file:', dump:arguments, level:'error'});
    });
    reader.readAsArrayBuffer(_file);
  }, this));
}, set:function(_key, _value) {
  this.storedObject[_key] = _value;
  this.save();
  return true;
}, get:function(_key, _defaultValue) {
  var value = this.storedObject[_key];
  if (Ext.isString(value) && (value.indexOf('{') === 0 || value.indexOf('[') === 0)) {
    value = Ext.decode(value);
  }
  if (value === null || typeof value === 'undefined') {
    return _defaultValue;
  }
  if (value === 'false') {
    return false;
  }
  if (value === 'true') {
    return true;
  } else {
    return value;
  }
}, getAll:function() {
  return this.storedObject;
}, remove:function(_key) {
  delete this.storedObject[_key];
  this.save();
  return true;
}, removeAll:function() {
  this.storedObject = {};
  this.save();
  return true;
}, save:function() {
  if (!this.saveInProgress) {
    this.blockedSaveAttempts = 0;
    this.bufferedSave();
  } else {
    if (this.blockedSaveAttempts >= 10) {
      this.saveInProgress = false;
    }
    this.blockedSaveAttempts++;
    Ext.Function.defer(this.save, 500, this);
  }
}, writeToTempFile:function() {
  this.config.fileSystem.root.getFile('sync/' + this.configFileName + '_temp.json', {create:true, exclusive:false}, Ext.bind(function(_fileEntry) {
    this.tempFile = _fileEntry;
    _fileEntry.createWriter(Ext.bind(function(_writer) {
      cnconsult.Logger.log({prefix:'File-\x3ewriteToTempFile', message:'Writer created'});
      var fileWriter = _writer;
      fileWriter.write(this.configToSave);
      fileWriter.onwriteend = Ext.bind(function() {
        this.moveTempToOriginalFile();
      }, this);
      fileWriter.onerror = Ext.bind(function() {
        cnconsult.Logger.log({prefix:'File-\x3ewriteToTempFile', message:'Error during write to temp file.', dump:arguments, level:'error'});
        this.saveInProgress = false;
      }, this);
    }, this));
  }, this), function() {
    cnconsult.Logger.log({prefix:'File-\x3ewriteToTempFile', message:'Error getting temp file', dump:arguments, level:'error'});
  });
}, moveTempToOriginalFile:function() {
  if (this.tempFile) {
    this.tempFile.moveTo(this.config.syncRoot, this.configFileName + '.json');
    this.saveInProgress = false;
  }
}});
Ext.define('cnconsult.storage.LocalStorage', {extend:cnconsult.storage.Base, setPrefix:function(_prefix) {
  if (_prefix !== '') {
    this.config.prefix = _prefix + ':';
  } else {
    this.config.prefix = '';
  }
}, getPrefix:function() {
  if (this.config.prefix !== '' && this.config.prefix.indexOf(':') > 0) {
    return this.config.prefix.substr(0, this.config.prefix.length - 1);
  } else {
    return '';
  }
}, set:function(_key, _value) {
  if (Ext.isObject(_value) || Ext.isArray(_value)) {
    localStorage.setItem(this.config.prefix + _key, Ext.encode(_value));
  } else {
    localStorage.setItem(this.config.prefix + _key, _value);
  }
  return true;
}, get:function(_key, _defaultValue) {
  var value = localStorage.getItem(this.config.prefix + _key);
  if (Ext.isString(value) && (value.indexOf('{') === 0 || value.indexOf('[') === 0)) {
    value = Ext.decode(value);
  }
  if (value === null) {
    return _defaultValue;
  }
  if (value === 'false') {
    return false;
  }
  if (value === 'true') {
    return true;
  } else {
    return value;
  }
}, getAll:function(_doDecode) {
  var returnData = {}, key;
  for (var i = 0; i < localStorage.length; i++) {
    key = localStorage.key(i);
    if (this.config.prefix === '' || key.indexOf(this.config.prefix) === 0) {
      var value = localStorage.getItem(localStorage.key(i));
      if (_doDecode === true && (value.indexOf('{') === 0 || value.indexOf('[' === 0))) {
        value = Ext.decode(value);
      }
      returnData[key.substr(this.config.prefix.length)] = value;
    }
  }
  return returnData;
}, remove:function(_key) {
  localStorage.removeItem(this.config.prefix + _key);
  return true;
}, removeAll:function() {
  var allValues = this.getAll(), key;
  for (key in allValues) {
    this.remove(key);
  }
  return true;
}});
Ext.define('dilocsync.util.FileViewerHelper', {singleton:true, mixins:[Ext.mixin.Observable], config:{primary:null, secondary:null, viewersInNightMode:false, viewersScrollingContinuous:false, hiddenFileViewers:null}, init:function() {
  var $jscomp$this = this;
  if (dilocsync.core.Master.isPhonegap()) {
    var master = dilocsync.core.Master;
    var identity = master.getIdentity();
    var storage = master.getStorage();
    if (!Ext.Object.isEmpty(identity) && Ext.isDefined(identity.options)) {
      cnconsult.Logger.log({prefix:'FileViewerHelper-\x3einit', message:'Init primary and secondary FileViewerNG'});
      var fileViewer1 = new Promise(function(_resolve, _reject) {
        $jscomp$this.setPrimary(new FileViewerNG(_resolve, $jscomp$this));
      });
      var fileViewer2 = new Promise(function(_resolve, _reject) {
        $jscomp$this.setSecondary(new FileViewerNG(_resolve, $jscomp$this));
      });
      Ext.Promise.all([fileViewer1, fileViewer2]).then(function() {
        var fileViewerConfig = storage.get('core:fileviewer:config', {});
        if (fileViewerConfig.nightMode) {
          $jscomp$this.setViewersInNightMode(true);
          $jscomp$this.enableNightMode(true);
        }
        if (fileViewerConfig.continuous) {
          $jscomp$this.setViewersScrollingContinuous(true);
          $jscomp$this.toggleScrolling(true);
        }
      });
    }
  }
}, isFileTypeSupport:function(_type) {
  var supportedFileTypes = ['pdf', 'bmp', 'jpg', 'jpeg', 'png', 'gif', 'html', 'htm', 'svg', 'txt', 'mp4'];
  if (dilocsync.util.Platform.isIOS()) {
    supportedFileTypes.push('tif', 'tiff', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'rtf');
  }
  return Ext.Array.contains(supportedFileTypes, _type.toLowerCase());
}, hideVisibleFileViewers:function() {
  var fileViewers = Ext.ComponentQuery.query('fileviewer');
  var hiddenViewers = [];
  fileViewers.forEach(function(_fileViewer) {
    var fvController = _fileViewer.getController();
    if (fvController.getIsVisible()) {
      fvController.hideViewer();
      hiddenViewers.push(_fileViewer);
    }
  });
  return hiddenViewers;
}, showHiddenFileViewers:function(_hiddenViewers) {
  _hiddenViewers.forEach(function(_fileViewer) {
    var fvController = _fileViewer.getController();
    fvController.showViewer();
  });
}, exitFullscreenFileViewers:function() {
  var fileViewers = Ext.ComponentQuery.query('fileviewer');
  var exitedFullscreenFileViewer = false;
  fileViewers.forEach(function(_fileViewer) {
    var fvController = _fileViewer.getController();
    if (fvController.getViewerInFullscreen()) {
      exitedFullscreenFileViewer = fvController.exitFullScreen();
    }
  });
  return exitedFullscreenFileViewer;
}, isInFullscreen:function() {
  var fileViewers = Ext.ComponentQuery.query('fileviewer');
  var isInFullscreen = false;
  fileViewers.forEach(function(_fileViewer) {
    var fvController = _fileViewer.getController();
    if (fvController.getViewerInFullscreen()) {
      isInFullscreen = true;
    }
  });
  return isInFullscreen;
}, enableNightMode:function(_enable) {
  var fileViewers = Ext.ComponentQuery.query('fileviewer');
  this.getPrimary().enableNightMode(_enable);
  this.getSecondary().enableNightMode(_enable);
  this.setViewersInNightMode(_enable);
  fileViewers.forEach(function(_fileViewer) {
    _fileViewer.down('#nightButton').setIconCls(_enable ? 'x-fa fa-sun' : 'x-fa fa-moon');
    if (_enable) {
      _fileViewer.down('toolbar[reference\x3dactionToolbar]').addCls('dilocsync-fileviewer-action-toolbar-nightmode');
    } else {
      _fileViewer.down('toolbar[reference\x3dactionToolbar]').removeCls('dilocsync-fileviewer-action-toolbar-nightmode');
    }
  });
  this.storeFileViewerConfig('nightMode', _enable);
  Ext.fireEvent('nightMode', _enable);
}, toggleScrolling:function(_continuous) {
  this.getPrimary().toggleScrolling();
  this.getSecondary().toggleScrolling();
  this.setViewersScrollingContinuous(_continuous);
  var fileViewers = Ext.ComponentQuery.query('fileviewer');
  fileViewers.forEach(function(_fileViewer) {
    _fileViewer.lookup('toggleScrollingButton').setIconCls(_continuous ? 'x-fa fa-arrows-alt-h' : 'x-fa fa-arrows-alt-v');
  });
  this.storeFileViewerConfig('continuous', _continuous);
}, storeFileViewerConfig:function(_key, _value) {
  var storage = dilocsync.core.Master.getStorage();
  var currentConfig = storage.get('core:fileviewer:config', {});
  currentConfig[_key] = _value;
  storage.set('core:fileviewer:config', currentConfig);
}});
Ext.define('dilocsync.view.components.ErrorMessageBox', {extend:Ext.MessageBox, xtype:'errormessagebox', mixins:[cnconsult.Translatable], initialize:function() {
  var me = this;
  this.setConfig({title:this.tr('Error'), iconCls:'x-fa fa-times', buttons:[{text:this.tr('OK'), handler:me.destroy, scope:me}]});
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.SuccessMessageBox', {extend:Ext.MessageBox, xtype:'successmessagebox', mixins:[cnconsult.Translatable], initialize:function() {
  var me = this;
  this.setConfig({iconCls:'x-fa fa-check', buttons:[{text:this.tr('OK'), handler:me.destroy, scope:me}]});
  this.callParent(arguments);
}});
Ext.define('dilocsync.util.MessageHelper', {singleton:true, mixins:[cnconsult.Translatable], showError:function(_message) {
  var messageBox = Ext.create('dilocsync.view.components.ErrorMessageBox', {message:_message});
  var hiddenViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  messageBox.on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
  messageBox.show();
}, showSuccess:function(_title, _message) {
  var messageBox = Ext.create('dilocsync.view.components.SuccessMessageBox', {title:_title, message:_message});
  var hiddenViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  messageBox.on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
  messageBox.show();
}, showDebug:function(_message) {
  dilocsync.util.MessageHelper.showError('[' + Ext.Date.format(new Date, 'Y-m-d H:i:s') + '] ' + _message);
}, showMessage:function(_messageBoxConfig) {
  var messageBox = Ext.create('Ext.MessageBox', _messageBoxConfig);
  var hiddenViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  messageBox.on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
  messageBox.show();
  return messageBox;
}, showAcknowledge:function(_title, _message, _fn, _scope) {
  this.showMessage({title:_title, message:_message, buttons:[{text:this.tr('Ok'), handler:function() {
    Ext.callback(_fn, _scope);
    this.up('messagebox').destroy();
  }}]});
}, showPrompt:function(_title, _message, _fn, _scope, _multiLine, _value, _prompt) {
  var hiddenViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  var messageBox = Ext.create('Ext.MessageBox', {top:'10%', standardButtons:{ok:{text:this.tr('OK')}, cancel:{text:this.tr('Cancel')}}});
  messageBox.on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
  messageBox.prompt(_title, _message, function(_buttonId, _text) {
    Ext.callback(_fn, _scope, [_buttonId, _text]);
    messageBox.destroy();
  }, _scope, _multiLine, _value, _prompt);
  messageBox.setLeft(Ext.Viewport.el.getWidth() / 2 - messageBox.el.getWidth() / 2);
}, showConfirm:function(_title, _message, _fn, _scope, _keepFileViewersHidden) {
  var messageBox = Ext.create('Ext.MessageBox');
  var hiddenViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  if (!_keepFileViewersHidden) {
    messageBox.on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
  }
  messageBox.confirm(_title, _message, function(_button) {
    Ext.callback(_fn, _scope, [_button]);
    messageBox.destroy();
  }, _scope);
}, showSyncRecommendMessage:function() {
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var syncAdviceThreshold = identity.options.syncAdviceThreshold;
  this.showMessage({title:this.tr('Recommend Sync'), message:this.tr('The last Sync is more than %1 hour(s) ago. We recommend to sync again now!').arg(syncAdviceThreshold), buttons:[{text:this.tr('Close'), handler:function() {
    this.up('messagebox').destroy();
  }}, {text:this.tr('Sync now'), handler:function() {
    master.getSyncEngine().startSync();
    this.up('messagebox').destroy();
  }}]});
}});
Ext.define('dilocsync.Application', {extend:Ext.app.Application, name:'dilocsync', onAppUpdate:function() {
  dilocsync.util.MessageHelper.showConfirm('Application Update', 'This application has an update, reload?', function(choice) {
    if (choice === 'yes') {
      window.location.reload();
    }
  });
}});
Ext.define('dilocsync.store.DiLocStorage', {extend:Ext.data.Store, config:{saveKey:''}, sync:function(_options) {
  var records = (this.getData().getSource() || this.getData()).getRange();
  var data = [];
  for (var i = 0; i < records.length; i++) {
    data.push(records[i].getData());
  }
  dilocsync.core.Master.getStorage().set(this.getSaveKey(), data);
  if (typeof _options !== 'undefined') {
    if (_options.hasOwnProperty('callback')) {
      Ext.callback(_options.callback, _options.scope);
    }
  }
}, load:function() {
  var records = dilocsync.core.Master.getStorage().get(this.getSaveKey());
  if (records && records.length > 0) {
    this.add(records);
  }
}});
Ext.define('dilocsync.model.Confirmation', {extend:Ext.data.Model, fields:[{name:'requestId', type:'integer'}, {name:'name', type:'string'}, {name:'path', type:'string'}, {name:'uuid', type:'string'}, {name:'checksum', type:'string'}, {name:'state', type:'string'}, {name:'fileType', type:'string'}, {name:'icon', type:'string', convert:function(_value, _record) {
  return _record.get('fileType');
}}, {name:'buttonText', type:'string'}, {name:'confirmationText', type:'string'}, {name:'confirmationTimestamp', type:'integer'}, {name:'visibleFrom', type:'date'}, {name:'visibleTo', type:'date'}, {name:'signatureRequired', type:'boolean', defaultValue:false}, {name:'signature', type:'string'}], proxy:{type:'memory'}});
Ext.define('dilocsync.util.Filters', {singleton:true, visibleFrom:function(_node) {
  var now = Date.now();
  var visibleFrom = _node.get('visibleFrom');
  if (visibleFrom) {
    visibleFrom = new Date(visibleFrom);
    return now >= Ext.Number.parseInt(Ext.Date.format(visibleFrom, 'time'));
  } else {
    return true;
  }
}, visibleTo:function(_node) {
  var now = Date.now();
  var visibleTo = _node.get('visibleTo');
  if (visibleTo) {
    visibleTo = new Date(visibleTo);
    return now < Ext.Number.parseInt(Ext.Date.format(visibleTo, 'time'));
  } else {
    return true;
  }
}});
Ext.define('dilocsync.store.Confirmations', {extend:dilocsync.store.DiLocStorage, mixins:[cnconsult.Translatable], storeId:'Confirmations', model:'dilocsync.model.Confirmation', sorters:'name', groupDir:'DESC', saveKey:'page:confirmations:confirmationRecords', listeners:{datachanged:function(_store) {
  var unconfirmedFiles = _store.countUnconfirmedFiles();
  var menuItem = Ext.getStore('menuItems').findRecord('view', 'confirmations');
  if (menuItem) {
    menuItem.set('badgeText', unconfirmedFiles > 0 ? unconfirmedFiles : '');
  }
}}, constructor:function() {
  var me = this;
  me.callParent(arguments);
  me.setGrouper({groupFn:Ext.Function.bind(function(record) {
    if (record.get('state') === 'unconfirmed') {
      return this.tr('Unconfirmed');
    } else {
      return this.tr('Confirmed');
    }
  }, this), direction:'DESC', sortProperty:'state'});
  me.setFilters([dilocsync.util.Filters.visibleFrom, dilocsync.util.Filters.visibleTo]);
}, countUnconfirmedFiles:function() {
  var records = this.getRange();
  var unconfirmedRecords = 0;
  for (var i = 0; i < this.getCount(); i++) {
    if (records[i].get('state') === 'unconfirmed') {
      unconfirmedRecords++;
    }
  }
  return unconfirmedRecords;
}, getConfirmedFiles:function() {
  var records = this.getRange();
  var confirmedRecords = [];
  for (var i = 0; i < this.getCount(); i++) {
    if (records[i].get('state') === 'confirmed') {
      confirmedRecords.push(records[i]);
    }
  }
  return confirmedRecords;
}});
Ext.define('dilocsync.util.MultiUserSupport', {singleton:true, MULTI_USER_SUPPORT_AVAILABLE_STORAGE_PATH:'core:personalization:multiUserSupportAvailable', MULTI_USER_SUPPORT_ENABLED_STORAGE_PATH:'core:personalization:multiUserSupportEnabled', DAYS_UNTIL_USER_IS_CONSIDERED_INACTIVE_STORAGE_PATH:'core:personalization:daysUntilUserIsConsideredInactive', isAvailable:function() {
  var storage = dilocsync.core.Master.getStorage();
  return storage.get(this.MULTI_USER_SUPPORT_AVAILABLE_STORAGE_PATH, false);
}, setAvailable:function(isAvailable) {
  var storage = dilocsync.core.Master.getStorage();
  storage.set(this.MULTI_USER_SUPPORT_AVAILABLE_STORAGE_PATH, isAvailable);
}, isEnabled:function() {
  var storage = dilocsync.core.Master.getStorage();
  return storage.get(this.MULTI_USER_SUPPORT_ENABLED_STORAGE_PATH, false);
}, setEnabled:function(isEnabled) {
  var storage = dilocsync.core.Master.getStorage();
  storage.set(this.MULTI_USER_SUPPORT_ENABLED_STORAGE_PATH, isEnabled);
}, getDaysUntilUserIsConsideredInactive:function() {
  var storage = dilocsync.core.Master.getStorage();
  return storage.get(this.DAYS_UNTIL_USER_IS_CONSIDERED_INACTIVE_STORAGE_PATH, 30);
}, setDaysUntilUserIsConsideredInactive:function(daysUntilUserIsConsideredInactive) {
  var storage = dilocsync.core.Master.getStorage();
  storage.set(this.DAYS_UNTIL_USER_IS_CONSIDERED_INACTIVE_STORAGE_PATH, daysUntilUserIsConsideredInactive);
}});
Ext.define('dilocsync.core.Personalization', {mixins:[Ext.mixin.Observable], master:null, storage:null, config:{master:null, storage:null}, constructor:function(_config) {
  this.mixins.observable.constructor.call(this, _config);
  this.storage = this.config.storage;
  this.master = this.config.master;
}, isPersonalized:function() {
  if (dilocsync.util.MultiUserSupport.isEnabled()) {
    return this.storage.isCurrentUserSet();
  } else {
    return this.storage.get('core:personalized', false);
  }
}, getData:function() {
  var data = {};
  data.username = this.storage.get('core:personalization:username');
  data.usergroup = this.storage.get('core:personalization:usergroup');
  data.userlang = this.master.getUserLanguage();
  data.deviceIdCode = this.master.deviceIdCode();
  if (this.storage.get('core:personalization:email')) {
    data.email = this.storage.get('core:personalization:email');
  }
  if (this.storage.get('core:personalization:useridcode')) {
    data.userIdCode = this.storage.get('core:personalization:useridcode');
  }
  if (this.storage.get('core:personalization:userid')) {
    data.userId = this.storage.get('core:personalization:userid');
  }
  if (data.deviceIdCode.indexOf('-') !== -1) {
    data.deviceIdCode = data.deviceIdCode.substring(0, data.deviceIdCode.indexOf('-')) + '...';
  }
  return data;
}, personalize:function(_personalizationData, _noEvent) {
  if (_personalizationData && _personalizationData.customerId && _personalizationData.syncSecret && _personalizationData.userName && _personalizationData.userGroup) {
    try {
      if (_personalizationData.userId) {
        this.storage.setCurrentUser(_personalizationData.userId);
        this.storage.set('core:personalization:userid', _personalizationData.userId);
      }
      this.storage.set('core:personalization:customerId', _personalizationData.customerId);
      this.storage.set('core:personalization:syncSecret', _personalizationData.syncSecret);
      this.storage.set('core:personalization:username', _personalizationData.userName);
      this.storage.set('core:personalization:usergroup', _personalizationData.userGroup);
      this.storage.set('core:personalization:lastLogin', Date.now() / 1000);
      dilocsync.core.Master.setUserLanguage(_personalizationData.userLang);
      if (_personalizationData.userEmail) {
        this.storage.set('core:personalization:email', _personalizationData.userEmail);
      }
      if (_personalizationData.userIdCode) {
        this.storage.set('core:personalization:useridcode', _personalizationData.userIdCode);
      }
      this.storage.set('core:personalized', true);
      if (_noEvent !== true) {
        this.fireEvent('personalized');
      }
    } catch (e$66) {
      cnconsult.Logger.log({prefix:'Personalization-\x3epersonalize', message:'Exception: error saving data', level:'error', catchedError:e$66, useSentry:true});
    }
  } else {
    cnconsult.Logger.log({prefix:'Personalization-\x3epersonalize', message:'An error occurred while saving the personalization data! Didnt get all needed data!', level:'error', dump:_personalizationData, useSentry:true});
  }
}, depersonalize:function(_callback, _scope) {
  Ext.Ajax.request({url:this.master.getBackendUrl() + '/syncregisterng/dePersonalizeDevice', params:{syncSecret:this.storage.get('core:personalization:syncSecret')}, success:function(response) {
    var responseData = Ext.decode(response.responseText, true);
    if (responseData && responseData.success) {
      this.fireEvent('depersonalizestart');
      this.storage.remove('core:personalization:username');
      this.storage.remove('core:personalization:personalizationData');
      this.storage.remove('core:personalization:usergroup');
      this.storage.remove('core:personalization:userid');
      this.storage.remove('core:personalization:email');
      this.storage.remove('core:personalization:useridcode');
      this.storage.remove('core:syncengine:lastSyncTimestamp');
      this.storage.remove('core:identity');
      this.storage.set('core:personalized', false);
      dilocsync.core.Master.clearAlmanacs();
      dilocsync.core.Master.getSyncReportStorage().deleteAllReports();
      var confirmationStore = Ext.getStore('Confirmations');
      if (confirmationStore) {
        confirmationStore.removeAll();
        confirmationStore.sync();
      }
      dilocsync.core.Master.deleteDataDirectory(function(_success) {
        if (!_success) {
          cnconsult.Logger.log({prefix:'Personalization-\x3edepersonalize', message:'Error deleting data directory in dilocsync.core.Master.deleteDataDirectory callback success\x3dfalse'});
        }
        Ext.callback(_callback, _scope, [true]);
      }, this);
    } else {
      Ext.callback(_callback, _scope, [false]);
    }
  }, failure:function() {
    Ext.callback(_callback, _scope, [false]);
  }, scope:this});
}});
Ext.define('dilocsync.core.AsyncWalk', {walkArray:function(_array, _eachMethod, _eachScope, _callback, _scope, _additionalParams) {
  _additionalParams = Ext.Array.from(_additionalParams);
  var next = function() {
    if (_array.length > 0) {
      var currentElement = _array.shift();
      var params = Ext.Array.merge([currentElement, next], _additionalParams);
      _eachMethod.apply(_eachScope, params);
    } else {
      Ext.callback(_callback, _scope);
    }
  };
  next();
}, walkObject:function(_object, _eachMethod, _eachScope, _callback, _scope, _additionalParams) {
  var id = Math.random().toString(14).substring(2);
  var keys = [];
  _additionalParams = Ext.Array.from(_additionalParams);
  for (var key in _object) {
    if (_object.hasOwnProperty(key)) {
      keys.push(key);
    }
  }
  var next = function() {
    if (keys.length > 0) {
      var currentKey = keys.shift();
      var params = Ext.Array.merge([currentKey, _object[currentKey], function() {
        return window.postMessage({next:id}, '*');
      }], _additionalParams);
      _eachMethod.apply(_eachScope, params);
    } else {
      window.removeEventListener('message', onNextMessage);
      Ext.callback(_callback, _scope);
    }
  };
  var onNextMessage = function(_message) {
    try {
      if (_message.data.next === id) {
        next();
      }
    } catch (e$67) {
      window.removeEventListener('message', onNextMessage);
      console.log('AsyncWalk -\x3e walkObject: Exception catched during walkObject-\x3enext(): ', e$67);
    }
  };
  window.addEventListener('message', onNextMessage);
  window.postMessage({next:id}, '*');
}});
Ext.define('dilocsync.core.ServerBackendDetection', {require:['Ext.Ajax', 'dilocsync.core.AsyncWalk'], foundUrl:null, detectBackendUrl:function(_server, _callback, _scope) {
  var testUrls = ['https://' + _server + '/capsules/syncmanager/backend/syncregisterng/test'];
  if (!_server.includes('diloc')) {
    testUrls.push('http://' + _server + '/capsules/syncmanager/backend/syncregisterng/test');
  }
  var asyncArrayWalk = Ext.create('dilocsync.core.AsyncWalk');
  asyncArrayWalk.walkArray(testUrls, this.testUrl, this, function() {
    cnconsult.Logger.log({prefix:'ServerBackendDetection-\x3edetectBackendUrl', message:'Finished detecting! Found url: ' + this.foundUrl});
    if (this.foundUrl) {
      this.foundUrl = this.foundUrl.replace('/syncregister/test', '');
      this.foundUrl = this.foundUrl.replace('/syncregisterng/test', '');
      Ext.callback(_callback, _scope, [this.foundUrl]);
    } else {
      Ext.callback(_callback, _scope, [false]);
    }
  }, this);
}, testUrl:function(_url, _callback) {
  if (this.foundUrl) {
    cnconsult.Logger.log({prefix:'ServerBackendDetection-\x3etestUrl', message:'Skipping url because we already have one: ' + _url});
    _callback();
  } else {
    cnconsult.Logger.log({prefix:'ServerBackendDetection-\x3etestUrl', message:'Testing url: ' + _url});
    Ext.Ajax.request({url:_url, success:function() {
      cnconsult.Logger.log({prefix:'ServerBackendDetection-\x3etestUrl', message:'Success for url : ' + _url});
      this.foundUrl = _url;
      _callback();
    }, failure:function() {
      cnconsult.Logger.log({prefix:'ServerBackendDetection-\x3etestUrl', message:'url (' + _url + ') did not work, check the next one.', level:'warn'});
      _callback();
    }, scope:this});
  }
}});
Ext.define('dilocsync.util.File', {singleton:true, fileSystem:null, mixins:[cnconsult.Translatable], basename:function(_path) {
  var path = _path;
  if (_path[_path.length - 1] === '/') {
    path = _path.substring(0, path.lastIndexOf('/'));
  }
  var slashPos = path.lastIndexOf('/');
  return path.substring(slashPos + 1);
}, dirname:function(_path) {
  var slashPos = _path.lastIndexOf('/');
  return _path.substring(0, slashPos);
}, extension:function(_path) {
  if (_path.lastIndexOf('.') === -1) {
    return '';
  }
  return _path.substring(_path.lastIndexOf('.') + 1);
}, getFileNameWithoutExtension:function(_filePath) {
  return dilocsync.util.File.basename(_filePath).split('.')[0];
}, formatPath:function(_path) {
  if (_path.startsWith('data/')) {
    return _path.substring(5);
  } else {
    if (_path.startsWith('userfilebox/')) {
      return this.tr('User file box') + _path.substring(_path.indexOf('/', 12));
    }
  }
  return _path;
}, sha256OfFileEntry:function(_fileEntry, _success, _error) {
  window.FileHash.sha256(_fileEntry.toURL(), function(_result) {
    return _success(_result.result);
  }, _error);
}, encodeURI:function(_uri) {
  var uri = encodeURI(_uri);
  uri = uri.split('+').join('%2B');
  uri = uri.split('@').join('%40');
  uri = uri.split('\x26').join('%26');
  uri = uri.split('#').join('%23');
  return uri;
}, iconClsByType:function(_type) {
  var cls = '';
  var fontAwesomePrefix = 'x-fa fa-';
  var knowledgeIconPrefix = 'knowledge-icon knowledge-icon-';
  switch(_type.toLowerCase()) {
    case 'folder':
    case 'directory':
      cls = fontAwesomePrefix + 'folder fa-lg item-folder-color dilocsync-list-item-folder';
      break;
    case 'txt':
    case 'rtf':
      cls = 'file-icon file-icon-txt';
      break;
    case 'pdf':
      cls = 'file-icon file-icon-pdf';
      break;
    case 'xls':
    case 'xlsx':
      cls = 'file-icon file-icon-xls';
      break;
    case 'doc':
    case 'docx':
      cls = 'file-icon file-icon-doc';
      break;
    case 'ppt':
    case 'pptx':
      cls = 'file-icon file-icon-ppt';
      break;
    case 'htm':
    case 'html':
      cls = 'file-icon file-icon-html';
      break;
    case 'jpg':
    case 'jpeg':
      cls = 'file-icon file-icon-jpg';
      break;
    case 'bmp':
      cls = 'file-icon file-icon-bmp';
      break;
    case 'png':
      cls = 'file-icon file-icon-png';
      break;
    case 'gif':
      cls = 'file-icon file-icon-gif';
      break;
    case 'tif':
    case 'tiff':
      cls = 'file-icon file-icon-tif';
      break;
    case 'zip':
    case 'rar':
    case '7z':
      cls = 'file-icon file-icon-zip';
      break;
    case 'mp4':
      cls = 'file-icon file-icon-mpg';
      break;
    case 'svg':
      cls = 'file-icon file-icon-svg';
      break;
    case 'partner':
      cls = knowledgeIconPrefix + 'partner';
      break;
    case 'machine':
      cls = knowledgeIconPrefix + 'machine';
      break;
    case 'pencil':
      cls = knowledgeIconPrefix + 'pencil';
      break;
    case 'book':
      cls = knowledgeIconPrefix + 'book';
      break;
    case 'device':
      cls = knowledgeIconPrefix + 'device';
      break;
    case 'mobile':
      cls = knowledgeIconPrefix + 'mobile';
      break;
    case 'other':
      cls = knowledgeIconPrefix + 'other';
      break;
    case 'map':
      cls = knowledgeIconPrefix + 'map';
      break;
    case 'location':
      cls = knowledgeIconPrefix + 'location';
      break;
    case 'dangerousgood':
      cls = knowledgeIconPrefix + 'dangerousgood';
      break;
    case 'railway':
      cls = knowledgeIconPrefix + 'railway';
      break;
    case 'trailer':
      cls = knowledgeIconPrefix + 'trailer';
      break;
    case 'series':
      cls = knowledgeIconPrefix + 'series';
      break;
    default:
      cls = fontAwesomePrefix + 'file-o';
      break;
  }
  return cls;
}, formatBytes:function(_bytes) {
  var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  if (_bytes === 0) {
    return 'n/a';
  }
  var i = parseInt(Math.floor(Math.log(_bytes) / Math.log(1024)));
  if (i === 0) {
    return _bytes + ' ' + sizes[i];
  }
  return (_bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
}, isFileTypeVideo:function(_type) {
  var supportedVideoTypes = ['mp4'];
  return Ext.Array.contains(supportedVideoTypes, _type.toLowerCase());
}, tagMarkup:function(_tags) {
  var html = '';
  Ext.Array.each(_tags, function(_tag) {
    var name = _tag.name;
    var style = '';
    if (_tag.hasOwnProperty('color') && _tag.color) {
      var backgroundColor = _tag.color;
      var fontColor = dilocsync.util.Color.getContrast(backgroundColor);
      style = 'style\x3d"background-color: #' + backgroundColor + '; color:' + fontColor + '" ';
    }
    html += '\x3cspan class\x3d"dilocsync-sync-tag" ' + style + '\x3e' + name + '\x3c/span\x3e';
  });
  return html;
}, hasFavoriteTag:function(_fileInfo) {
  var hasFavoriteTag = false;
  if (_fileInfo && _fileInfo.hasOwnProperty('tags') && Ext.isArray(_fileInfo.tags)) {
    Ext.Array.each(_fileInfo.tags, function(_tag) {
      if (_tag.hasOwnProperty('isFavorite') && _tag.isFavorite === true) {
        hasFavoriteTag = true;
        return false;
      }
    }, this);
    return hasFavoriteTag;
  }
}, hasImportantTag:function(_fileInfo) {
  var hasImportantTag = false;
  if (_fileInfo && _fileInfo.hasOwnProperty('tags') && Ext.isArray(_fileInfo.tags)) {
    Ext.Array.each(_fileInfo.tags, function(_tag) {
      if (_tag.hasOwnProperty('isImportant') && _tag.isImportant === true) {
        hasImportantTag = true;
        return false;
      }
    }, this);
    return hasImportantTag;
  }
}, fileExists:function(_filePath) {
  return new Promise(function(_resolve) {
    dilocsync.core.Master.devicePathExists(_filePath, function(_fullPath) {
      _resolve(_fullPath !== null);
    });
  });
}, removeFileEntry:function(_fileEntry) {
  return new Promise(function(_resolve, _reject) {
    _fileEntry.remove(function() {
      return _resolve();
    }, function(_err) {
      return _reject(_err);
    });
  });
}, removeFile:function(_filePath) {
  return dilocsync.util.File.getFile(_filePath).then(function(_fileEntry) {
    return dilocsync.util.File.removeFileEntry(_fileEntry);
  });
}, getEntry:function(_entryUrl) {
  return new Promise(function(_resolve, _reject) {
    window.resolveLocalFileSystemURL(_entryUrl, function(_entry) {
      return _resolve(_entry);
    }, function(_err) {
      return _reject(_err);
    });
  });
}, getFile:function(_fileUrl) {
  return dilocsync.util.File.getEntry(_fileUrl).then(function(_entry) {
    if (_entry.isFile) {
      return _entry;
    } else {
      throw new Error('Path is not a file');
    }
  });
}, getRelativeFile:function(_path) {
  return new Promise(function(_resolve, _reject) {
    dilocsync.core.Master.getSyncRoot().getFile(_path, {}, _resolve, _reject);
  });
}, getDirectory:function(_directoryUrl) {
  return dilocsync.util.File.getEntry(_directoryUrl).then(function(_entry) {
    if (_entry.isDirectory) {
      return _entry;
    } else {
      throw new Error('Path is not a directory');
    }
  });
}, readEntriesFromDirectory:function(_directoryEntry) {
  return new Promise(function(_resolve, _reject) {
    var directoryReader = _directoryEntry.createReader();
    directoryReader.readEntries(function(_entries) {
      return _resolve(_entries);
    }, function(_err) {
      return _reject(_err);
    });
  });
}, listFiles:function(_directoryUrl) {
  return dilocsync.util.File.getDirectory(_directoryUrl).then(function(_directoryEntry) {
    return dilocsync.util.File.readEntriesFromDirectory(_directoryEntry);
  }).then(function(_entries) {
    return _entries.filter(function(_entry) {
      return _entry.isFile;
    }).map(function(_entry) {
      return _entry.toURL();
    });
  });
}, getRootDirectoryName:function(_record) {
  var rootFsEntryName = _record.get('rootFsEntryName');
  return dilocsync.util.File.validateRootDirectoryName(rootFsEntryName);
}, validateRootDirectoryName:function(_rootFsEntryName) {
  if (!_rootFsEntryName) {
    _rootFsEntryName = 'fs-data';
  }
  return _rootFsEntryName;
}});
Ext.define('dilocsync.core.AlmanacDirectory', {path:null, directories:null, files:null, icon:null, title:null, description:null, size:null, uuid:null, validFrom:null, validTo:null, visibleFrom:null, visibleTo:null, tags:null, constructor:function(_path, _data) {
  this.path = _path;
  this.directories = {};
  this.files = {};
  if (_data) {
    if (_data.files && Ext.isObject(_data.files)) {
      this.files = Ext.clone(_data.files);
    }
    if (_data.directories && Ext.isObject(_data.directories)) {
      var directoryName;
      for (directoryName in _data.directories) {
        if (_data.directories.hasOwnProperty(directoryName)) {
          this.directories[directoryName] = new dilocsync.core.AlmanacDirectory(_path + directoryName + '/', _data.directories[directoryName]);
        }
      }
    }
    if (_data.title) {
      this.title = _data.title;
    }
    if (_data.description) {
      this.description = _data.description;
    }
    if (_data.size) {
      this.size = _data.size;
    }
    if (_data.uuid) {
      this.uuid = _data.uuid;
    }
    if (_data.validFrom) {
      this.validFrom = _data.validFrom;
    }
    if (_data.validTo) {
      this.validTo = _data.validTo;
    }
    if (_data.visibleFrom) {
      this.visibleFrom = _data.visibleFrom;
    }
    if (_data.visibleTo) {
      this.visibleTo = _data.visibleTo;
    }
    if (_data.tags) {
      this.tags = _data.tags;
    }
    if (_data.metaData) {
      if (_data.metaData.title) {
        this.title = _data.metaData.title;
      }
      if (_data.metaData.description) {
        this.description = _data.metaData.description;
      }
      if (_data.metaData.size) {
        this.size = _data.metaData.size;
      }
      if (_data.metaData.uuid) {
        this.uuid = _data.metaData.uuid;
      }
      if (_data.metaData.validFrom) {
        this.validFrom = _data.metaData.validFrom;
      }
      if (_data.metaData.validTo) {
        this.validTo = _data.metaData.validTo;
      }
      if (_data.metaData.visibleFrom) {
        this.visibleFrom = _data.metaData.visibleFrom;
      }
      if (_data.metaData.visibleTo) {
        this.visibleTo = _data.metaData.visibleTo;
      }
      if (_data.metaData.tags) {
        this.tags = _data.metaData.tags;
      }
    }
  }
}, fileNeedsUpdating:function(_localFile, _remoteFile) {
  var checksumNotEqual = _localFile.hasOwnProperty('checksum') && _remoteFile.hasOwnProperty('checksum') ? _localFile.checksum !== _remoteFile.checksum : _localFile.md5 !== _remoteFile.md5;
  if (checksumNotEqual) {
    return true;
  } else {
    return false;
  }
}, needsMetaUpdating:function(_local, _remote) {
  var propertiesToCheck = ['title', 'description', 'validFrom', 'validTo', 'visibleFrom', 'visibleTo'];
  var propertyNotEqual = false;
  var tagsNotEqual = false;
  Ext.Array.each(propertiesToCheck, function(_propertyName) {
    if (_remote.hasOwnProperty(_propertyName)) {
      if (!_local.hasOwnProperty(_propertyName) && _remote[_propertyName] !== null || _local.hasOwnProperty(_propertyName) && _local[_propertyName] !== _remote[_propertyName]) {
        propertyNotEqual = true;
        return false;
      }
    } else {
      if (_local.hasOwnProperty(_propertyName)) {
        propertyNotEqual = true;
        return false;
      }
    }
  }, this);
  if (!propertyNotEqual && (_local.hasOwnProperty('tags') || _remote.hasOwnProperty('tags'))) {
    if (_local.tags && _remote.tags && _local.tags.length === _remote.tags.length) {
      Ext.Array.each(_remote.tags, function(_tag, _index) {
        if (!Ext.Object.equals(_tag, _local.tags[_index])) {
          tagsNotEqual = true;
        }
      }, this);
    } else {
      if (!(!_remote.hasOwnProperty('tags') && Ext.isArray(_local.tags) && _local.tags.length === 0)) {
        tagsNotEqual = true;
      }
    }
  }
  return propertyNotEqual || tagsNotEqual;
}, compareWithOther:function(_almanacDirectory) {
  var result = {filesToDelete:[], filesToDownload:{}, filesToCheck:{}};
  var filename;
  for (filename in this.files) {
    if (this.files.hasOwnProperty(filename)) {
      if (!_almanacDirectory.files[filename]) {
        result.filesToDelete.push(this.path + filename);
      } else {
        if (this.fileNeedsUpdating(this.files[filename], _almanacDirectory.files[filename])) {
          result.filesToDownload[this.path + filename] = _almanacDirectory.files[filename];
        } else {
          result.filesToCheck[this.path + filename] = _almanacDirectory.files[filename];
        }
      }
    }
  }
  for (filename in _almanacDirectory.files) {
    if (_almanacDirectory.files.hasOwnProperty(filename)) {
      if (!this.files[filename]) {
        result.filesToDownload[this.path + filename] = _almanacDirectory.files[filename];
      }
    }
  }
  var directoryName;
  for (directoryName in _almanacDirectory.directories) {
    if (_almanacDirectory.directories.hasOwnProperty(directoryName)) {
      if (!this.directories[directoryName]) {
        cnconsult.Logger.log({prefix:'AlmanacDirectory-\x3ecompareWithOther', message:'Creating new empty local directory!', dump:this.path + directoryName});
        this.directories[directoryName] = new dilocsync.core.AlmanacDirectory(this.path + directoryName + '/', {});
      }
    }
  }
  for (directoryName in this.directories) {
    if (this.directories.hasOwnProperty(directoryName)) {
      if (!_almanacDirectory.directories[directoryName]) {
        result.filesToDelete.push(this.path + directoryName);
      } else {
        var directoryResult = this.directories[directoryName].compareWithOther(_almanacDirectory.directories[directoryName]);
        result.filesToDelete = result.filesToDelete.concat(directoryResult.filesToDelete);
        result.filesToDownload = Ext.apply(result.filesToDownload, directoryResult.filesToDownload);
        result.filesToCheck = Ext.apply(result.filesToCheck, directoryResult.filesToCheck);
      }
    }
  }
  return result;
}, compareWithOtherAlmanacDirectory:function(_almanacDirectory) {
  var result = {filesToDelete:{}, filesOnlyToDeleteFromFileSystem:{}, filesToDownload:{}, filesToCheck:{}, filesNeedMetaUpdate:{}, directoryChanges:false, directoryMetaChanges:false};
  var filename;
  for (filename in this.files) {
    if (this.files.hasOwnProperty(filename)) {
      if (!_almanacDirectory.files[filename]) {
        result.filesToDelete[this.path + filename] = this.files[filename];
      } else {
        if (this.fileNeedsUpdating(this.files[filename], _almanacDirectory.files[filename])) {
          result.filesOnlyToDeleteFromFileSystem[this.path + filename] = this.files[filename];
          result.filesToDownload[this.path + filename] = _almanacDirectory.files[filename];
        } else {
          result.filesToCheck[this.path + filename] = _almanacDirectory.files[filename];
          if (this.needsMetaUpdating(this.files[filename], _almanacDirectory.files[filename])) {
            result.filesNeedMetaUpdate[this.path + filename] = _almanacDirectory.files[filename];
          }
        }
      }
    }
  }
  for (filename in _almanacDirectory.files) {
    if (_almanacDirectory.files.hasOwnProperty(filename)) {
      if (!this.files[filename]) {
        result.filesToDownload[this.path + filename] = _almanacDirectory.files[filename];
      }
    }
  }
  var directoryName;
  for (directoryName in _almanacDirectory.directories) {
    if (_almanacDirectory.directories.hasOwnProperty(directoryName)) {
      if (!this.directories[directoryName]) {
        cnconsult.Logger.log({prefix:'AlmanacDirectory-\x3ecompareWithOtherAlmanacDirectory', message:'Creating new empty local directory!', dump:this.path + directoryName});
        this.directories[directoryName] = new dilocsync.core.AlmanacDirectory(this.path + directoryName + '/', {});
        result.directoryChanges = true;
      }
    }
  }
  for (directoryName in this.directories) {
    if (this.directories.hasOwnProperty(directoryName)) {
      if (!_almanacDirectory.directories[directoryName]) {
        result.filesToDelete = Ext.apply(result.filesToDelete, this.directories[directoryName].getAllFiles());
        result.filesToDelete[this.path + directoryName] = this.directories[directoryName];
        result.directoryChanges = true;
      } else {
        var directoryResult = this.directories[directoryName].compareWithOtherAlmanacDirectory(_almanacDirectory.directories[directoryName]);
        result.filesToDelete = Ext.apply(result.filesToDelete, directoryResult.filesToDelete);
        result.filesOnlyToDeleteFromFileSystem = Ext.apply(result.filesOnlyToDeleteFromFileSystem, directoryResult.filesOnlyToDeleteFromFileSystem);
        result.filesToDownload = Ext.apply(result.filesToDownload, directoryResult.filesToDownload);
        result.filesToCheck = Ext.apply(result.filesToCheck, directoryResult.filesToCheck);
        result.filesNeedMetaUpdate = Ext.apply(result.filesNeedMetaUpdate, directoryResult.filesNeedMetaUpdate);
        if (directoryResult.directoryChanges) {
          result.directoryChanges = true;
        }
        if (directoryResult.directoryMetaChanges) {
          result.directoryMetaChanges = true;
        }
      }
    }
  }
  if (this.needsMetaUpdating(this, _almanacDirectory)) {
    result.directoryMetaChanges = true;
  }
  this.title = _almanacDirectory.title ? _almanacDirectory.title : null;
  this.description = _almanacDirectory.description ? _almanacDirectory.description : null;
  this.size = _almanacDirectory.size ? _almanacDirectory.size : null;
  this.uuid = _almanacDirectory.uuid ? _almanacDirectory.uuid : null;
  this.validFrom = _almanacDirectory.validFrom ? _almanacDirectory.validFrom : null;
  this.validTo = _almanacDirectory.validTo ? _almanacDirectory.validTo : null;
  this.visibleFrom = _almanacDirectory.visibleFrom ? _almanacDirectory.visibleFrom : null;
  this.visibleTo = _almanacDirectory.visibleTo ? _almanacDirectory.visibleTo : null;
  this.tags = _almanacDirectory.tags ? _almanacDirectory.tags : null;
  return result;
}, serialize:function() {
  var data = {files:this.files};
  if (this.icon) {
    data.icon = this.icon;
  }
  if (this.title) {
    data.title = this.title;
  }
  if (this.description) {
    data.description = this.description;
  }
  if (this.size) {
    data.size = this.size;
  }
  if (this.uuid) {
    data.uuid = this.uuid;
  }
  if (this.validFrom) {
    data.validFrom = this.validFrom;
  }
  if (this.validTo) {
    data.validTo = this.validTo;
  }
  if (this.visibleFrom) {
    data.visibleFrom = this.visibleFrom;
  }
  if (this.visibleTo) {
    data.visibleTo = this.visibleTo;
  }
  if (this.tags) {
    data.tags = this.tags;
  }
  for (var directoryName in this.directories) {
    if (!data.directories) {
      data.directories = {};
    }
    if (this.directories.hasOwnProperty(directoryName)) {
      data.directories[directoryName] = this.directories[directoryName].serialize();
    }
  }
  return data;
}, toDirectoryItem:function(_pathPrefix) {
  var item = {title:this.title, description:this.description, size:this.size, validFrom:this.validFrom, validTo:this.validTo, visibleFrom:this.visibleFrom, visibleTo:this.visibleTo, tags:this.tags, name:dilocsync.util.File.basename(this.path), path:_pathPrefix + this.path, icon:'folder'};
  for (var directoryName in this.directories) {
    if (!item.items) {
      item.items = [];
    }
    if (this.directories.hasOwnProperty(directoryName)) {
      item.items.push(this.directories[directoryName].toDirectoryItem(_pathPrefix));
    }
  }
  if (!item.items) {
    item.items = [];
  }
  for (var filename in this.files) {
    if (this.files.hasOwnProperty(filename)) {
      item.items.push(this.mapFileItem(filename, _pathPrefix));
    }
  }
  return item;
}, toNonRecursiveDirectoryItem:function(_pathPrefix) {
  var item = {title:this.title, description:this.description, size:this.size, validFrom:this.validFrom, validTo:this.validTo, visibleFrom:this.visibleFrom, visibleTo:this.visibleTo, tags:this.tags, name:dilocsync.util.File.basename(this.path), path:_pathPrefix + this.path, icon:'folder'};
  var directoryItems = [];
  var fileItems = [];
  var compareItems = function(a, b) {
    if (a.name === b.name) {
      return 0;
    } else {
      if (a.name < b.name) {
        return -1;
      } else {
        return 1;
      }
    }
  };
  for (var directoryName in this.directories) {
    if (this.directories.hasOwnProperty(directoryName)) {
      var directory = this.directories[directoryName];
      directoryItems.push({name:directoryName, path:this.path + directoryName, icon:'folder', leaf:false, uuid:directory.uuid, title:directory.title, description:directory.description, size:directory.size, validFrom:directory.validFrom, validTo:directory.validTo, visibleFrom:directory.visibleFrom, visibleTo:directory.visibleTo, tags:directory.tags});
    }
  }
  directoryItems.sort(compareItems);
  for (var filename in this.files) {
    if (this.files.hasOwnProperty(filename)) {
      var file = this.mapFileItem(filename, _pathPrefix);
      var now = Date.now();
      var maxDate = new Date(8.64E15);
      var visibleFrom = new Date(file.visibleFrom ? file.visibleFrom : 0);
      var visibleTo = new Date(file.visibleTo ? file.visibleTo : maxDate);
      if (now >= Ext.Number.parseInt(Ext.Date.format(visibleFrom, 'time')) && now < Ext.Number.parseInt(Ext.Date.format(visibleTo, 'time'))) {
        fileItems.push(file);
      }
    }
  }
  fileItems.sort(compareItems);
  item.items = directoryItems.concat(fileItems);
  return item;
}, mapFileItem:function(filename, _pathPrefix) {
  var file = this.files[filename];
  _pathPrefix = _pathPrefix || '';
  return {name:filename, path:_pathPrefix + this.path + filename, icon:dilocsync.util.File.extension(filename).toLowerCase(), size:file.size, read:!!file.read, leaf:true, md5:file.md5, uuid:file.uuid, title:file.title, description:file.description, fileType:dilocsync.util.File.extension(filename).toLowerCase(), alternativeFileType:file.hasOwnProperty('fileType') && file.fileType ? file.fileType : dilocsync.util.File.extension(filename).toLowerCase(), fileUuid:file.fileUuid, checksum:file.checksum, 
  validFrom:file.validFrom, validTo:file.validTo, visibleFrom:file.visibleFrom, visibleTo:file.visibleTo, tags:file.tags, rootFsEntryName:file.rootFsEntryName, loaded:file.loaded};
}, getFile:function(_fileName) {
  for (var filename in this.files) {
    if (filename === _fileName) {
      return this.files[filename];
    }
  }
  return false;
}, fileExists:function(_fileName) {
  for (var filename in this.files) {
    if (filename === _fileName) {
      return true;
    }
  }
  return false;
}, findFilesRecursively:function(_searchWord, _excludeDirectories) {
  _excludeDirectories = _excludeDirectories === undefined ? [] : _excludeDirectories;
  var results = [];
  for (var directoryName in this.directories) {
    if (this.directories.hasOwnProperty(directoryName) && !_excludeDirectories.includes(directoryName)) {
      var directoryResults = this.directories[directoryName].findFilesRecursively(_searchWord, _excludeDirectories);
      results = Ext.Array.merge(results, directoryResults);
    }
  }
  if (!_excludeDirectories.includes(this.path)) {
    var $jscomp$loop$103 = {};
    for (var filename in this.files) {
      if (this.files.hasOwnProperty(filename)) {
        if (!_searchWord.startsWith('#')) {
          if (filename.toLowerCase().indexOf(_searchWord.toLowerCase()) > -1 || this.files[filename].hasOwnProperty('title') && this.files[filename].title && this.files[filename].title.toLowerCase().indexOf(_searchWord.toLowerCase()) > -1) {
            results.push(this.mapFileItem(filename));
          }
        } else {
          $jscomp$loop$103.searchWord = _searchWord.toLowerCase().substring(1);
          if (this.files[filename].hasOwnProperty('tags')) {
            Ext.Array.each(this.files[filename].tags, function($jscomp$loop$103) {
              return function(_tag) {
                if (_tag.name.toLowerCase().indexOf($jscomp$loop$103.searchWord) > -1) {
                  results.push(this.mapFileItem(filename));
                }
              };
            }($jscomp$loop$103), this);
          }
        }
      }
      $jscomp$loop$103 = {searchWord:$jscomp$loop$103.searchWord};
    }
  }
  return results;
}, findFilesByChecksum:function(_checksum, _results, _excludeDirectories) {
  _excludeDirectories = _excludeDirectories === undefined ? [] : _excludeDirectories;
  var results = [];
  if (_results) {
    results = _results;
  }
  for (var directoryName in this.directories) {
    if (this.directories.hasOwnProperty(directoryName) && !_excludeDirectories.includes(directoryName)) {
      results = this.directories[directoryName].findFilesByChecksum(_checksum, results, _excludeDirectories);
    }
  }
  if (!_excludeDirectories.includes(this.path)) {
    for (var filename in this.files) {
      if (this.files.hasOwnProperty(filename)) {
        var file = this.files[filename];
        if (file && file.checksum === _checksum) {
          results.push(this.mapFileItem(filename));
        }
      }
    }
  }
  return results;
}, findImportantFiles:function(_results) {
  var results = [];
  if (_results) {
    results = _results;
  }
  for (var directoryName in this.directories) {
    if (this.directories.hasOwnProperty(directoryName)) {
      results = this.directories[directoryName].findImportantFiles(results);
    }
  }
  for (var filename in this.files) {
    if (this.files.hasOwnProperty(filename)) {
      var file = this.files[filename];
      if (file && this.isTaggedAsImportant(file)) {
        results.push(this.mapFileItem(filename));
      }
    }
  }
  return results;
}, getAllFiles:function() {
  var results = {};
  for (var $jscomp$iter$1 = $jscomp.makeIterator(Object.entries(this.files)), $jscomp$key$$jscomp$destructuring$var2 = $jscomp$iter$1.next(); !$jscomp$key$$jscomp$destructuring$var2.done; $jscomp$key$$jscomp$destructuring$var2 = $jscomp$iter$1.next()) {
    var $jscomp$destructuring$var2 = $jscomp$key$$jscomp$destructuring$var2.value;
    {
      var $jscomp$destructuring$var3 = $jscomp.makeIterator($jscomp$destructuring$var2);
      var fileName = $jscomp$destructuring$var3.next().value;
      var file = $jscomp$destructuring$var3.next().value;
      results[this.path + fileName] = file;
    }
  }
  for (var $jscomp$iter$2 = $jscomp.makeIterator(Object.values(this.directories)), $jscomp$key$directory = $jscomp$iter$2.next(); !$jscomp$key$directory.done; $jscomp$key$directory = $jscomp$iter$2.next()) {
    var directory = $jscomp$key$directory.value;
    {
      Object.assign(results, directory.getAllFiles());
    }
  }
  return results;
}, getAllFileNames:function(_results) {
  var results = [];
  if (_results) {
    results = _results;
  }
  for (var directoryName in this.directories) {
    if (this.directories.hasOwnProperty(directoryName)) {
      results = this.directories[directoryName].getAllFileNames(results);
    }
  }
  for (var currentFile in this.files) {
    if (this.files.hasOwnProperty(currentFile)) {
      var file = this.files[currentFile];
      var fileName = file.checksum + '.' + file.fileType;
      results.push(fileName);
    }
  }
  return results;
}, isTaggedAsImportant:function(_file) {
  var isImportant = false;
  if (Ext.isArray(_file.tags)) {
    Ext.Array.each(_file.tags, function(tag) {
      if (tag.hasOwnProperty('isImportant') && tag.isImportant === true) {
        isImportant = true;
        return false;
      }
    });
  }
  return isImportant;
}, countUnreadFilesRecursively:function() {
  var directory = this;
  var unreadFilesCount = 0;
  var countUnreadFilesInDirectory = function(_directory) {
    if (_directory.files) {
      Ext.Object.each(_directory.files, function(_fileName, _fileObject) {
        var now = Date.now();
        var maxDate = new Date(8.64E15);
        var visibleFrom = new Date(_fileObject.visibleFrom ? _fileObject.visibleFrom : 0);
        var visibleTo = new Date(_fileObject.visibleTo ? _fileObject.visibleTo : maxDate);
        if (!_fileObject.read && now >= Ext.Number.parseInt(Ext.Date.format(visibleFrom, 'time')) && now < Ext.Number.parseInt(Ext.Date.format(visibleTo, 'time'))) {
          unreadFilesCount++;
        }
      });
      Ext.Object.each(_directory.directories, function(_subDirectoryName, _subDirectoryObject) {
        countUnreadFilesInDirectory(_subDirectoryObject);
      });
    }
  };
  countUnreadFilesInDirectory(directory);
  return unreadFilesCount;
}, findRandomPdf:function(_pdf) {
  var pdf = null;
  if (_pdf) {
    pdf = _pdf;
  }
  for (var filename in this.files) {
    if (this.files.hasOwnProperty(filename) && dilocsync.util.File.extension(filename).toLowerCase() === 'pdf') {
      pdf = this.files[filename].checksum + '.' + dilocsync.util.File.extension(filename).toLowerCase();
      break;
    }
  }
  if (!pdf) {
    for (var directoryName in this.directories) {
      if (this.directories.hasOwnProperty(directoryName)) {
        pdf = this.directories[directoryName].findRandomPdf(pdf);
        if (pdf) {
          break;
        }
      }
    }
  }
  return pdf;
}});
Ext.define('dilocsync.core.Almanac', {mixins:[Ext.mixin.Observable], identifier:null, path:null, rootDirectory:null, createdAt:null, updatedAt:null, version:null, constructor:function(_config) {
  this.mixins.observable.constructor.call(this);
  if (_config.hasOwnProperty('identifier')) {
    this.identifier = _config.identifier;
    this.path = _config.path;
    this.createdAt = _config.createdAt;
    this.updatedAt = _config.updatedAt;
    this.version = _config.version;
    this.rootDirectory = new dilocsync.core.AlmanacDirectory('/', _config.root);
  } else {
    this.rootDirectory = new dilocsync.core.AlmanacDirectory('/', _config);
  }
}, getRootDirectory:function() {
  return this.rootDirectory;
}, compareWithOther:function(_otherAlmanac) {
  return this.rootDirectory.compareWithOther(_otherAlmanac.getRootDirectory());
}, compareWithOtherAlmanacDirectory:function(_otherAlmanac) {
  return this.rootDirectory.compareWithOtherAlmanacDirectory(_otherAlmanac.getRootDirectory());
}, getDirectoryForPath:function(_path) {
  var dirs = Ext.Array.clean(_path.split('/'));
  var dirsCount = dirs.length;
  var directory = this.rootDirectory;
  for (var i = 0; i < dirsCount; i++) {
    if (directory.directories[dirs[i]]) {
      directory = directory.directories[dirs[i]];
    } else {
      return null;
    }
  }
  return directory;
}, createDirectory:function(_path) {
  var dirs = Ext.Array.clean(_path.split('/'));
  var dirsCount = dirs.length;
  var currentDirectories = this.rootDirectory;
  var lastExistingDirectory = null;
  var i = 0;
  for (; i < dirsCount; i++) {
    if (currentDirectories.directories[dirs[i]]) {
      currentDirectories = currentDirectories.directories[dirs[i]];
    } else {
      lastExistingDirectory = currentDirectories;
      lastExistingDirectory.directories[dirs[i]] = new dilocsync.core.AlmanacDirectory(lastExistingDirectory.path + dirs[i] + '/', {});
      lastExistingDirectory = lastExistingDirectory.directories[dirs[i]];
      currentDirectories = lastExistingDirectory;
    }
  }
  return lastExistingDirectory;
}, updateFile:function(_filePath, _size, _checksum, _properties) {
  var path = dilocsync.util.File.dirname(_filePath);
  if (path === '') {
    path = '/';
  }
  var filename = dilocsync.util.File.basename(_filePath);
  var dir = this.getDirectoryForPath(path);
  if (!dir) {
    dir = this.createDirectory(path);
  }
  if (dir) {
    var event = 'fileupdated';
    var metaUpdate = false;
    if (!dir.files[filename]) {
      event = 'fileadded';
      dir.files[filename] = {};
    }
    if (event === 'fileupdated') {
      metaUpdate = dir.files[filename].hasOwnProperty('checksum') && dir.files[filename].checksum === _checksum;
    }
    dir.files[filename].size = _size;
    dir.files[filename].md5 = _checksum;
    dir.files[filename].checksum = _checksum;
    if (Ext.isObject(_properties)) {
      if (Ext.isObject(dir.files[filename])) {
        var localProperties = Ext.Object.getKeys(dir.files[filename]);
        var remoteProperties = Ext.Object.getKeys(_properties);
        var propertiesToReset = ['title', 'description', 'validFrom', 'validTo', 'visibleFrom', 'visibleTo', 'tags'];
        var propertiesToCheck = Ext.Array.difference(localProperties, remoteProperties);
        Ext.Array.each(propertiesToCheck, function(propertyName) {
          if (Ext.Array.contains(propertiesToReset, propertyName)) {
            delete dir.files[filename][propertyName];
          }
        }, this);
      }
      Ext.Object.each(_properties, function(_propertyName, _propertyValue) {
        dir.files[filename][_propertyName] = _propertyValue;
      });
    }
    if (this.path && path.indexOf(this.path) === -1) {
      this.fireEvent(event, this.path + path, filename, _properties, _checksum, metaUpdate);
    } else {
      this.fireEvent(event, path, filename, _properties, _checksum, metaUpdate);
    }
    return true;
  }
  return false;
}, setFileLoaded:function(_path) {
  var path = dilocsync.util.File.dirname(_path);
  if (path === '') {
    path = '/';
  }
  var filename = dilocsync.util.File.basename(_path);
  var dir = this.getDirectoryForPath(path);
  if (!dir) {
    cnconsult.Logger.log({prefix:'Almanac-\x3esetFileLoaded', message:'Could not set loaded property. Parent directory does not exist.', level:'error', dump:{_path:_path}});
    return;
  }
  if (!dir.files[filename]) {
    cnconsult.Logger.log({prefix:'Almanac-\x3esetFileLoaded', message:'Could not set loaded property. File does not exist.', level:'error', dump:{_path:_path}});
    return;
  }
  dir.files[filename].loaded = true;
}, deletePath:function(_path) {
  var path = dilocsync.util.File.dirname(_path);
  if (path === '') {
    path = '/';
  }
  var filename = dilocsync.util.File.basename(_path);
  var dir = this.getDirectoryForPath(path);
  if (dir) {
    var fileInfo = dir.files[filename] ? dir.files[filename] : null;
    if (this.path && path.indexOf(this.path) === -1) {
      this.fireEvent('filedeleted', this.path + path, filename, fileInfo);
    } else {
      this.fireEvent('filedeleted', path, filename, fileInfo);
    }
    if (dir.files[filename]) {
      delete dir.files[filename];
      return true;
    } else {
      if (dir.directories[filename]) {
        delete dir.directories[filename];
        return true;
      }
    }
  } else {
    return false;
  }
}, serialize:function() {
  return this.rootDirectory.serialize();
}, getFileByPath:function(_filePath) {
  var directoryPath = dilocsync.util.File.dirname(_filePath);
  var almanacDirectory = directoryPath ? this.getDirectoryForPath(directoryPath) : this.getRootDirectory();
  if (almanacDirectory) {
    var fileName = dilocsync.util.File.basename(_filePath);
    if (fileName) {
      if (almanacDirectory.fileExists(fileName)) {
        return almanacDirectory.getFile(fileName);
      } else {
        cnconsult.Logger.log({prefix:'Almanac-\x3egetFileByPath', message:'Error retrieving file from almanac. File does not exist.', level:'error', dump:{fileName:fileName, directoryPath:directoryPath}});
        return false;
      }
    } else {
      cnconsult.Logger.log({prefix:'Almanac-\x3egetFileByPath', message:"Error retrieving file from almanac. Filename couldn't be found in the given file path", level:'error', dump:_filePath});
      return false;
    }
  } else {
    cnconsult.Logger.log({prefix:'Almanac-\x3egetFileByPath', message:'Error retrieving file from almanac. No directory found in the local almanac for the following file path:', level:'error', dump:_filePath});
    return false;
  }
}, fileExists:function(_filePath) {
  var directoryPath = dilocsync.util.File.dirname(_filePath);
  var almanacDirectory = directoryPath ? this.getDirectoryForPath(directoryPath) : this.getRootDirectory();
  if (almanacDirectory) {
    var fileName = dilocsync.util.File.basename(_filePath);
    if (fileName) {
      return almanacDirectory.fileExists(fileName);
    } else {
      cnconsult.Logger.log({prefix:'Almanac-\x3efileExists', message:'No filename found in the given file path', level:'error', dump:_filePath});
      return false;
    }
  } else {
    cnconsult.Logger.log({prefix:'Almanac-\x3efileExists', message:'No directory found in the local almanac for the following file path:', level:'error', dump:_filePath});
    return false;
  }
}, findFilesRecursively:function(_fileName) {
  if (this.getRootDirectory()) {
    return this.getRootDirectory().findFilesRecursively(_fileName);
  } else {
    return [];
  }
}, findImportantFiles:function() {
  if (this.getRootDirectory()) {
    return this.getRootDirectory().findImportantFiles();
  } else {
    return [];
  }
}, findFilesByChecksum:function(_checksum) {
  if (this.getRootDirectory()) {
    return this.getRootDirectory().findFilesByChecksum(_checksum, []);
  } else {
    return [];
  }
}, markFileAsReadInAlmanac:function(_path) {
  var fileName = dilocsync.util.File.basename(_path);
  var directoryPath = dilocsync.util.File.dirname(_path);
  var almanacDirectory = this.getDirectoryForPath(directoryPath || '/');
  var almanacFile = almanacDirectory.files[fileName];
  if (almanacFile) {
    almanacFile.read = true;
    Ext.fireEvent('filereadflagchanged', Ext.History.getToken().replace('folder/', ''));
  }
}, findRandomPdf:function() {
  if (this.getRootDirectory()) {
    return this.getRootDirectory().findRandomPdf();
  } else {
    return null;
  }
}});
Ext.define('dilocsync.core.FullTextSearch', {mixins:[Ext.mixin.Observable, cnconsult.Translatable], fullTextSearch:null, initialized:false, constructor:function(_config) {
  this.mixins.observable.constructor.call(this, _config);
  this.fullTextSearch = new FullTextSearch(this.initializeFullTextSearch, this);
}, initializeFullTextSearch:function() {
  var now = new Date;
  var lastUpdatedAt = Ext.Date.parse(dilocsync.core.Master.getStorage().get('fulltextsearch:lastUpdated', false), 'c');
  var timeDiff = Ext.Date.diff(lastUpdatedAt, now, Ext.Date.DAY);
  var master = dilocsync.core.Master;
  if (lastUpdatedAt !== false && timeDiff < 7) {
    if (Ext.os.is.iOS || device.platform === 'iOS') {
      var blankPdfFilePath = cordova.file.applicationDirectory + 'www/blank.pdf';
      this.indexFile(blankPdfFilePath, this.fullTextSearchInitialized, this);
    } else {
      cnconsult.Logger.log({prefix:'FullTextSearch-\x3einitializeFullTextSearch', message:'Android: Index a file to init index database.'});
      var randomPdf;
      var almanacs = dilocsync.core.Master.getAlmanacs();
      Ext.Object.each(almanacs, function(_key, _almanac) {
        var pdf = _almanac.findRandomPdf();
        if (pdf) {
          randomPdf = 'fs-data/' + pdf;
          return false;
        }
      }, this);
      if (randomPdf) {
        var randomPdfFilePath = dilocsync.core.Master.devicePath(randomPdf);
        cnconsult.Logger.log({prefix:'FullTextSearch-\x3einitializeFullTextSearch', message:'Index random pdf:', dump:randomPdf});
        this.indexFile(randomPdfFilePath, this.fullTextSearchInitialized, this);
      } else {
        cnconsult.Logger.log({prefix:'FullTextSearch-\x3einitializeFullTextSearch', message:'No random pdf found!'});
      }
    }
  } else {
    master.getStorage().set('fulltextsearch:lastUpdated', false);
    this.fullTextSearch.deleteDatabase(function(_success) {
      cnconsult.Logger.log({prefix:'FullTextSearch-\x3einitializeFullTextSearch', message:'Database successfully deleted. Start indexing...'});
      if (_success === true) {
        var syncRootDataDirectory = master.devicePath('fs-data/');
        cnconsult.Logger.log({prefix:'FullTextSearch-\x3einitializeFullTextSearch', message:'Start indexing data directory'});
        this.indexDirectory(syncRootDataDirectory, function(_success) {
          if (_success === true) {
            dilocsync.core.Master.getStorage().set('fulltextsearch:lastUpdated', Ext.Date.format(new Date, 'c'));
            this.initialized = true;
            this.fireEvent('databaseInitialized');
          }
        }, this);
      }
    }, this);
  }
}, fullTextSearchInitialized:function(_success) {
  if (_success) {
    this.initialized = true;
    this.fireEvent('databaseInitialized');
  }
}, readyToSearch:function() {
  return this.initialized;
}, indexDirectory:function(_directory, _callback, _scope) {
  cnconsult.Logger.log({prefix:'FullTextSearch-\x3eindexDirectory', message:'Start indexing directory', dump:_directory});
  this.fullTextSearch.indexDirectory(_directory, false, function(_success) {
    cnconsult.Logger.log({prefix:'FullTextSearch-\x3eindexDirectory', message:'Directory indexing finished.', dump:_success});
    Ext.callback(_callback, _scope, [_success]);
  }, this);
}, indexFile:function(_filePath, _callback, _scope) {
  cnconsult.Logger.log({prefix:'FullTextSearch-\x3eindexFile', message:'Start indexing file:', dump:_filePath});
  this.fullTextSearch.indexFile(_filePath, function(_success) {
    cnconsult.Logger.log({prefix:'FullTextSearch-\x3eindexFile', message:'File indexing finished.', dump:_success});
    Ext.callback(_callback, _scope, [_success]);
  }, this);
}, indexNewFiles:function(_filesToIndex, _callback, _scope) {
  cnconsult.Logger.log({prefix:'FullTextSearch-\x3eindexNewFiles', message:'Files to index', dump:_filesToIndex});
  var fileToIndex = _filesToIndex.pop();
  if (fileToIndex) {
    if (dilocsync.util.File.extension(fileToIndex).toLowerCase() === 'pdf') {
      cnconsult.Logger.log({prefix:'FullTextSearch-\x3eindexNewFiles', message:'Start indexing file:', dump:fileToIndex});
      this.fullTextSearch.indexFile(fileToIndex, function(_success) {
        cnconsult.Logger.log({prefix:'FullTextSearch-\x3eindexNewFiles', message:'Finished with indexing file', dump:{fileToIndex:fileToIndex, success:_success}});
        Ext.callback(this.indexNewFiles, this, [_filesToIndex, _callback, _scope]);
      }, this);
    } else {
      cnconsult.Logger.log({prefix:'FullTextSearch-\x3eindexNewFiles', message:'File ' + fileToIndex + ' will be skipped, because it is no pdf file...'});
      Ext.callback(this.indexNewFiles, this, [_filesToIndex, _callback, _scope]);
    }
  } else {
    Ext.callback(_callback, _scope);
  }
}, search:function(_searchWord, _callback, _scope) {
  cnconsult.Logger.log({prefix:'FullTextSearch-\x3esearch', message:'Start searching for:', dump:_searchWord});
  this.fullTextSearch.search(_searchWord, 30, function(_results) {
    cnconsult.Logger.log({prefix:'FullTextSearch-\x3esearch', message:'Searching finished, preparing results...', dump:_results});
    var master = dilocsync.core.Master;
    var results = [];
    var uniqueFullTextSearchResults = [];
    var $jscomp$loop$104 = {};
    for (var fullTextSearchResultKey in _results) {
      if (_results.hasOwnProperty(fullTextSearchResultKey)) {
        var fullTextSearchResult = _results[fullTextSearchResultKey], pageIndex, searchResultPath;
        if ((Ext.os.is.iOS || device.platform === 'iOS') && fullTextSearchResult.hasOwnProperty('filePath')) {
          searchResultPath = fullTextSearchResult.filePath.replace(/.*\/Data\/Application\/.*\/Documents\/sync\/\//, '');
        } else {
          if (Ext.os.is.Android && fullTextSearchResult.hasOwnProperty('filePath')) {
            searchResultPath = '/' + fullTextSearchResult.filePath.replace(dilocsync.core.Master.devicePath(''), '');
          }
        }
        searchResultPath = searchResultPath.normalize();
        pageIndex = fullTextSearchResult.pageIndex;
        var almanacs = master.getAlmanacs();
        var fileRepresentations = [];
        $jscomp$loop$104.checksum = dilocsync.util.File.basename(searchResultPath).replace('.' + dilocsync.util.File.extension(searchResultPath), '');
        Ext.Object.each(almanacs, function($jscomp$loop$104) {
          return function(_almanacName, _almanac) {
            var checksumSearchResults = _almanac.findFilesByChecksum($jscomp$loop$104.checksum), preparedFullTextSearchResult = _results[fullTextSearchResultKey], path;
            if (checksumSearchResults.length > 0) {
              for (var checksumSearchResult in checksumSearchResults) {
                if (checksumSearchResults.hasOwnProperty(checksumSearchResult)) {
                  path = _almanacName + checksumSearchResults[checksumSearchResult].path;
                  preparedFullTextSearchResult.filePath = path;
                  var uniqueKey = path + '-' + pageIndex;
                  if (uniqueFullTextSearchResults.indexOf(uniqueKey) !== -1) {
                    console.log('Skipping file because of duplicate entry...', path);
                    continue;
                  } else {
                    if (!master.fileExistsInAlmanacs(path)) {
                      console.log('File does not exist...', path);
                      continue;
                    }
                  }
                  uniqueFullTextSearchResults.push(uniqueKey);
                  results.push(Ext.clone(preparedFullTextSearchResult));
                }
              }
            }
          };
        }($jscomp$loop$104), this);
      }
      $jscomp$loop$104 = {checksum:$jscomp$loop$104.checksum};
    }
    Ext.callback(_callback, _scope, [results]);
  }, this);
}});
Ext.define('dilocsync.core.IdentityNormalizer', {personalizationData:null, constructor:function(_personalizationData) {
  this.personalizationData = _personalizationData;
  this.stringReplaceValues = {'{usergroup}':_personalizationData.usergroup, '{username}':_personalizationData.username, '{userlang}':_personalizationData.userlang, '{deviceid}':_personalizationData.deviceIdCode, '{userid}':_personalizationData.userId};
}, normalize:function(_identity) {
  var identity = Ext.clone(_identity);
  for (var index in identity) {
    var currentValue = identity[index];
    if (currentValue && typeof currentValue == 'object') {
      if (currentValue.hasOwnProperty(this.personalizationData.userlang)) {
        identity[index] = this.normalizeString(currentValue[this.personalizationData.userlang]);
      } else {
        var availableLanguages = ['de', 'en', 'fr', 'it', 'dk', 'pl'];
        var normalized = false;
        for (var i$68 = 0; i$68 < availableLanguages.length; i$68++) {
          if (currentValue.hasOwnProperty(availableLanguages[i$68])) {
            identity[index] = this.normalizeString(currentValue[availableLanguages[i$68]]);
            normalized = true;
            break;
          }
        }
        if (!normalized) {
          identity[index] = this.normalize(currentValue);
        }
      }
    }
    if (typeof currentValue == 'string') {
      identity[index] = this.normalizeString(currentValue);
    }
    if (Ext.isArray(currentValue)) {
      for (var i = 0; i < currentValue.length; i++) {
        var arrayValue = currentValue[i];
        if (typeof arrayValue == 'string') {
          currentValue[i] = this.normalizeString(arrayValue);
        }
        if (typeof arrayValue == 'object') {
          currentValue[i] = this.normalize(arrayValue);
        }
      }
    }
  }
  return identity;
}, normalizeString:function(_string) {
  if (typeof _string == 'string') {
    var normalizedString = _string;
    for (var index in this.stringReplaceValues) {
      var replaceValue = this.stringReplaceValues[index];
      normalizedString = normalizedString.replace(new RegExp(index, 'g'), replaceValue);
    }
    return normalizedString;
  } else {
    return _string;
  }
}});
Ext.define('dilocsync.core.SyncEngineInterface', {startSync:function() {
}, abortSync:function() {
}, isSyncing:function() {
}, wasLastSyncFromAutoSync:function() {
}});
Ext.define('dilocsync.core.syncengine.AlmanacSyncActions', {config:{almanac:null, almanacIdentifier:null, almanacPath:null, filesToDownload:{}, highPriorityFilesToDownload:{}, filesToDelete:{}, filesOnlyToDeleteFromAlmanac:{}, filesOnlyToDeleteFromFileSystem:{}, filesToCheck:{}, filesNeedMetaUpdate:{}}, constructor:function(_config) {
  this.initConfig(_config);
  this.callParent(_config);
}});
Ext.define('dilocsync.core.syncengine.SyncData', {mixins:[Ext.mixin.Observable, cnconsult.Translatable], depersonalizationNeeded:false, openExternalUrlData:false, identityChanged:false, remoteIdentity:null, registryUpdates:null, registryUpdated:false, reloadRequired:false, almanacsInfoList:null, localAlmanac:null, localAlmanacs:null, remoteAlmanac:null, remoteAlmanacs:null, almanacsSyncActions:null, almanacsSyncActionsBackup:null, syncActions:null, syncReportGenerator:null, downloadSize:null, syncReportAvailable:false, 
deviceStolen:false, startedFromAutoSync:false, passwordChangeRequired:false, hasHighPriorityFiles:false, multiUserSettingsChanged:false, depersonalize:function() {
  this.depersonalizationNeeded = true;
}, isDepersonalizationNeeded:function() {
  return this.depersonalizationNeeded;
}, openExternalUrl:function(_openUrlData) {
  this.openExternalUrlData = _openUrlData;
}, isOpenExternalUrlActivated:function() {
  return this.openExternalUrlData;
}, identityChange:function() {
  this.identityChanged = true;
}, hasIdentityChanged:function() {
  return this.identityChanged;
}, setRemoteIdentity:function(_identity) {
  this.remoteIdentity = _identity;
}, getRemoteIdentity:function() {
  return this.remoteIdentity;
}, setRegistryUpdates:function(_registryUpdates) {
  this.registryUpdates = _registryUpdates;
}, getRegistryUpdates:function() {
  return this.registryUpdates;
}, setRegistryUpdated:function() {
  this.registryUpdated = true;
}, getRegistryUpdated:function() {
  return this.registryUpdated;
}, requireReload:function() {
  this.reloadRequired = true;
}, isReloadRequired:function() {
  return this.reloadRequired;
}, setMultiUserSettingsChanged:function() {
  this.multiUserSettingsChanged = true;
}, getMultiUserSettingsChanged:function() {
  return this.multiUserSettingsChanged;
}, setAlmanacsInfoList:function(_almanacs) {
  this.almanacsInfoList = _almanacs;
}, getAlmanacsInfoList:function() {
  return this.almanacsInfoList;
}, setLocalAlmanac:function(_localAlmanac) {
  this.localAlmanac = _localAlmanac;
}, getLocalAlmanac:function() {
  return this.localAlmanac;
}, addToLocalAlmanacs:function(_almanac) {
  if (!Ext.isArray(this.localAlmanacs)) {
    this.localAlmanacs = [];
  }
  this.localAlmanacs.push(_almanac);
}, getLocalAlmanacs:function() {
  return this.localAlmanacs;
}, addToRemoteAlmanacs:function(_almanac) {
  if (!Ext.isArray(this.remoteAlmanacs)) {
    this.remoteAlmanacs = [];
  }
  this.remoteAlmanacs.push(_almanac);
}, getRemoteAlmanacs:function() {
  return this.remoteAlmanacs;
}, setRemoteAlmanac:function(_remoteAlmanac) {
  this.remoteAlmanac = _remoteAlmanac;
}, getRemoteAlmanac:function() {
  return this.remoteAlmanac;
}, addToAlmanacsSyncActions:function(_almanacSyncActions) {
  if (!Ext.isArray(this.almanacsSyncActions)) {
    this.almanacsSyncActions = [];
  }
  this.almanacsSyncActions.push(_almanacSyncActions);
}, getAlmanacsSyncActions:function() {
  return this.almanacsSyncActions;
}, setAlmanacsSyncActionsBackup:function(_almanacsSyncActions) {
  this.almanacsSyncActionsBackup = _almanacsSyncActions;
}, getAlmanacsSyncActionsBackup:function() {
  return this.almanacsSyncActionsBackup;
}, setSyncActions:function(_syncActions) {
  this.syncActions = _syncActions;
}, getSyncActions:function() {
  return this.syncActions;
}, setSyncReportGenerator:function(_syncReportGenerator) {
  this.syncReportGenerator = _syncReportGenerator;
}, getSyncReportGenerator:function() {
  return this.syncReportGenerator;
}, setDownloadSize:function(_downloadSize) {
  this.downloadSize = _downloadSize;
}, getDownloadSize:function() {
  return this.downloadSize;
}, setSyncReportAvailable:function() {
  this.syncReportAvailable = true;
}, isSyncReportAvailable:function() {
  return this.syncReportAvailable;
}, markDeviceAsStolen:function() {
  this.deviceStolen = true;
}, hasDeviceBeenStolen:function() {
  return this.deviceStolen;
}, setStartedFromAutoSync:function() {
  this.startedFromAutoSync = true;
}, isAutoSyncing:function() {
  return this.startedFromAutoSync;
}, setPasswordChangeRequired:function(_value) {
  this.passwordChangeRequired = _value;
}, getPasswordChangeRequired:function() {
  return this.passwordChangeRequired;
}, setHasHighPriorityFiles:function(_value) {
  this.hasHighPriorityFiles = _value;
}, getHasHighPriorityFiles:function() {
  return this.hasHighPriorityFiles;
}});
Ext.define('dilocsync.core.syncengine.tasks.BaseSyncTask', {mixins:[Ext.mixin.Observable, cnconsult.Translatable], master:null, storage:null, syncData:null, abortNeeded:false, config:{master:null, storage:null, syncData:null}, constructor:function(_config) {
  this.mixins.observable.constructor.call(this, _config);
  this.storage = this.config.storage;
  this.master = this.config.master;
  this.syncData = this.config.syncData;
}, execute:function(_next, _abort, _scope) {
}, abort:function() {
  this.abortNeeded = true;
}, persistAlmanac:function(_almanac, _path) {
  this.master.persistAlmanacByPath(_almanac, _path);
}, doExecuteTask:function() {
  var task = Ext.getClassName(this).split('.').pop();
  var identity = this.master.getIdentity();
  var identityUtil = dilocsync.util.Identity;
  switch(task) {
    case 'SyncCompletedForms':
    case 'SyncForms':
      return !!identityUtil.getOption(identity, 'enableForms');
    case 'SyncGeoStationList':
    case 'SyncLocomotionTypes':
      return identityUtil.getOption(identity, 'enableGpsTracking') && dilocsync.util.Platform.supportsGpsTracking();
    case 'SyncRouteKnowledgeLines':
      return false;
    case 'CheckForUndeletedFiles':
      {
        var taskAlreadyExecuted = this.storage.get('core:files:undeletedFileCheckerExecuted');
        return !taskAlreadyExecuted || identityUtil.getOption(identity, 'checkForUndeletedFiles');
      }
    case 'SyncTokens':
      return !Ext.is.Phone;
    default:
      return true;
  }
}});
Ext.define('dilocsync.core.syncengine.tasks.Depersonalization', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, callbackScope:null, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Checking if device needs to be depersonalized...'), 0, 0, null);
  if (this.syncData.isDepersonalizationNeeded()) {
    this.callbackScope = _scope;
    this.master.getPersonalization().depersonalize(this.finishDepersonalization, this);
  } else {
    Ext.callback(_next, _scope);
  }
}, finishDepersonalization:function() {
  dilocsync.util.MessageHelper.showMessage({title:this.tr('Device depersonalized'), message:this.tr('Device was depersonalized from the server'), buttons:[{itemId:'ok', text:'Ok', handler:function() {
    dilocsync.core.Master.reloadApplication(false);
  }}]});
}});
Ext.define('dilocsync.core.syncengine.tasks.IdentityChangeChecker', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Checking for tab changes...'), 0, 0, null);
  if (this.syncData.hasIdentityChanged()) {
    this.fireEvent('identitychanged');
  }
  Ext.callback(_next, _scope);
}});
Ext.define('dilocsync.core.syncengine.tasks.OpenExternalUrl', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, abortCallback:null, callbackScope:null, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Loading external url...'), 0, 0, null);
  var openUrlData = this.syncData.isOpenExternalUrlActivated();
  if (openUrlData) {
    this.abortCallback = _abort;
    this.callbackScope = _scope;
    this.openExternalUrl(openUrlData, this.closeExternalUrl, this);
  } else {
    Ext.callback(_next, _scope);
  }
}, openExternalUrl:function(_openUrl, _callback, _scope) {
  var url = _openUrl.url, width = _openUrl.width, height = _openUrl.height;
  var username = '';
  if (dilocsync.core.Master.getStorage().get('core:personalization:email')) {
    username = dilocsync.core.Master.getStorage().get('core:personalization:email');
  } else {
    if (dilocsync.core.Master.getStorage().get('core:personalization:useridcode')) {
      username = dilocsync.core.Master.getStorage().get('core:personalization:useridcode');
    }
  }
  var replaceValues = [{placeHolder:'{serverUrl}', value:this.master.getBackendUrl().replace('backend/', '')}, {placeHolder:'{userlang}', value:this.master.getUserLanguage()}, {placeHolder:'{syncSecret}', value:this.storage.get('core:personalization:syncSecret')}, {placeHolder:'{emailOrIdCode}', value:username}, {placeHolder:'{deviceIdCode}', value:dilocsync.core.Master.deviceIdCode()}];
  for (var i = 0; i < replaceValues.length; i++) {
    var replace = replaceValues[i];
    url = url.replace(new RegExp(replace.placeHolder, 'g'), replace.value);
  }
  var externalUrlLoader = Ext.create('dilocsync.view.ExternalUrlLoader', {width:width + 'px', height:height + 'px'});
  externalUrlLoader.setUrl(url);
  externalUrlLoader.on('abort', function() {
    externalUrlLoader.hide();
    Ext.callback(_callback, _scope, ['noalert']);
  }, this);
  externalUrlLoader.on('hide', function() {
    externalUrlLoader.hide();
    Ext.callback(_callback, _scope, ['noalert']);
  }, this);
  externalUrlLoader.on('personalizationupdated', function(_updatedPersonalizationData) {
    externalUrlLoader.hide();
    dilocsync.core.Master.getPersonalization().personalize(_updatedPersonalizationData, true);
    Ext.callback(_callback, _scope, [false, this.tr('Due to your last changes you need to sync again.')]);
  }, this);
  Ext.Viewport.add(externalUrlLoader);
}, closeExternalUrl:function(_message) {
  if (!_message) {
    _message = 'noalert';
  }
  Ext.callback(this.abortCallback, this.callbackScope, [false, _message]);
}});
Ext.define('dilocsync.core.syncengine.tasks.PersonalizationChecker', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Checking whether device is personalized...'), 0, 0, null);
  if (this.master.getPersonalization().isPersonalized()) {
    Ext.callback(_next, _scope);
  } else {
    Ext.callback(_abort, _scope, [false, this.tr('Device is not Personalized!')]);
  }
}});
Ext.define('dilocsync.core.syncengine.tasks.RegistryUpdates', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Checking for registry updates...'), 0, 0, null);
  var userGroupName = this.storage.get('core:personalization:usergroup');
  var registryUpdates = this.syncData.getRegistryUpdates();
  if (registryUpdates && registryUpdates.usergroup !== userGroupName) {
    this.syncData.identityChange();
    if (dilocsync.core.Master.getStorage().get('core:personalization:usergroup') !== registryUpdates.usergroup) {
      this.syncData.setRegistryUpdated();
      dilocsync.core.Master.getStorage().set('core:personalization:usergroup', registryUpdates.usergroup);
    }
  }
  var userId = this.storage.get('core:personalization:userid');
  if (registryUpdates && registryUpdates.userId !== userId) {
    this.syncData.identityChange();
    if (dilocsync.core.Master.getStorage().get('core:personalization:userid') !== registryUpdates.userId) {
      this.syncData.setRegistryUpdated();
      dilocsync.core.Master.getStorage().set('core:personalization:userid', registryUpdates.userId);
    }
  }
  if (registryUpdates && registryUpdates.userEmail) {
    if (dilocsync.core.Master.getStorage().get('core:personalization:email') !== registryUpdates.userEmail) {
      this.syncData.setRegistryUpdated();
      dilocsync.core.Master.getStorage().set('core:personalization:email', registryUpdates.userEmail);
    }
  }
  if (registryUpdates && registryUpdates.userIdCode) {
    if (dilocsync.core.Master.getStorage().get('core:personalization:useridcode') !== registryUpdates.userIdCode) {
      this.syncData.setRegistryUpdated();
      dilocsync.core.Master.getStorage().set('core:personalization:useridcode', registryUpdates.userIdCode);
    }
  }
  if (registryUpdates && registryUpdates.userName) {
    if (dilocsync.core.Master.getStorage().get('core:personalization:username') !== registryUpdates.userName) {
      this.syncData.setRegistryUpdated();
      dilocsync.core.Master.getStorage().set('core:personalization:username', registryUpdates.userName);
    }
  }
  if (registryUpdates.userlang && registryUpdates.userlang !== this.master.getUserLanguage()) {
    this.master.setUserLanguage(registryUpdates.userlang);
    this.syncData.requireReload();
  }
  Ext.callback(_next, _scope);
}});
Ext.define('dilocsync.core.syncengine.tasks.SaveSyncReport', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Saving sync report...'), 0, 0, null);
  var syncReportGenerator = this.syncData.getSyncReportGenerator();
  if (syncReportGenerator) {
    var hasHighPriorityFiles = this.syncData.getHasHighPriorityFiles(), syncReport = syncReportGenerator.finishSyncReport(hasHighPriorityFiles);
    if (syncReport) {
      var syncReportStorage = this.master.getSyncReportStorage();
      syncReportStorage.saveReport(syncReport);
      this.syncData.setSyncReportAvailable();
    }
  }
  Ext.callback(_next, _scope);
}});
Ext.define('dilocsync.core.syncengine.tasks.UpdateLastSyncTime', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Updating last sync time...'), 0, 0, null);
  var now = new Date;
  this.storage.set('core:syncengine:lastSyncTimestamp', Ext.Date.format(now, 'c'));
  Ext.callback(_next, _scope);
}});
Ext.define('dilocsync.core.syncengine.tasks.ConnectionChecker', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Checking connectivity...'), 0, 0, null);
  if (dilocsync.core.Master.isOnline()) {
    Ext.callback(_next, _scope);
  } else {
    Ext.callback(_abort, _scope, [false, this.tr('Device seems to be offline. Please check your internet connection!')]);
  }
}});
Ext.define('dilocsync.core.syncengine.tasks.StolenChecker', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, abortCallback:null, nextCallback:null, callbackScope:null, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Checking if device has been marked as stolen...'), 0, 0, null);
  this.abortCallback = _abort;
  this.nextCallback = _next;
  this.callbackScope = _scope;
  dilocsync.core.Master.isStolen(this.finishStolenCheck, this);
}, finishStolenCheck:function(_isStolen) {
  if ((_isStolen === 'yes!' || _isStolen === 'yes') && this.abortCallback) {
    this.syncData.markDeviceAsStolen();
    Ext.callback(this.abortCallback, this.callbackScope, [false, this.tr('Device was marked as stolen')]);
  } else {
    if (this.nextCallback) {
      Ext.callback(this.nextCallback, this.callbackScope);
    } else {
      cnconsult.Logger.log({prefix:'StolenChecker-\x3efinishStolenCheck', message:"No callback functions saved, that won't be funny now..."});
    }
  }
}});
Ext.define('dilocsync.model.Station', {extend:Ext.data.Model, alias:'model.station', fields:[{name:'identifier', type:'string'}, {name:'uopId', type:'string'}, {name:'latitude', type:'number'}, {name:'longitude', type:'number'}, {name:'name', type:'string'}, {name:'enhancedName', type:'string'}]});
Ext.define('dilocsync.store.AllStations', {extend:Ext.data.Store, alias:'store.allStations', storeId:'AllStations', proxy:{type:'indexeddb', databaseName:'StationDatabase', table:'stations'}, model:'dilocsync.model.Station', autoLoad:true});
Ext.define('dilocsync.core.syncengine.tasks.SyncGeoStationList', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  if (this.doExecuteTask()) {
    this.fireEvent('syncprogress', this.tr('Syncing geo station list...'), 0, 0, null);
    var allStationsStore = dilocsync.util.Helper.initStore('AllStations');
    var storeVersion = this.storage.get('core:geostationlist:version');
    Ext.Ajax.request({url:this.master.getBackendUrl() + '/syncrideknowledge/geoStationList', params:{syncSecret:this.storage.get('core:personalization:syncSecret'), version:storeVersion}, success:function(_response) {
      var response = Ext.decode(_response.responseText, true);
      if (response && response.success) {
        var responseData = response.result;
        var serverVersion = responseData.version;
        var serverGeoStations = responseData.geoStations;
        if (serverVersion && storeVersion !== serverVersion) {
          this.fireEvent('syncprogress', this.tr('A newer version of the geo station list is available, updating...'), 0, 0, null);
          var newStations = [];
          for (var i = 0; i < serverGeoStations.length; i++) {
            var newStation = serverGeoStations[i];
            newStations.push({identifier:newStation.idCode, name:newStation.name, uopId:newStation.uopId, latitude:newStation.lat, longitude:newStation.lon, enhancedName:newStation.idCode + ' - ' + newStation.name});
          }
          allStationsStore.getProxy().clear();
          allStationsStore.loadData(newStations);
          allStationsStore.sync({success:function() {
            this.storage.set('core:geostationlist:version', serverVersion);
            Ext.callback(_next, _scope);
          }, failure:function() {
            console.log('Error syncing the sync geo station list');
            Ext.callback(_next, _scope);
          }, scope:this});
        } else {
          this.fireEvent('syncprogress', this.tr('Geo station list does not need an update!'), 0, 0, null);
          Ext.callback(_next, _scope);
        }
      } else {
        Ext.callback(_next, _scope);
        Sentry.withScope(function(_scope) {
          _scope.setExtra('response', response);
          Sentry.captureMessage('An error occurred while syncing the geo station list requests!');
        });
      }
    }, failure:function(response) {
      Ext.callback(_next, _scope);
      console.log('Error syncing the sync geo station list', response);
    }, scope:this});
  } else {
    Ext.callback(_next, _scope);
  }
}});
Ext.define('dilocsync.model.RouteKnowledgeLine', {extend:Ext.data.Model, alias:'model.routeknowledgelinemodel', config:{fields:[{name:'id', type:'number'}, {name:'groupName', type:'string'}, {name:'lineName', type:'string'}, {name:'since', type:'date'}, {name:'refreshedAt', type:'date'}, {name:'until', type:'date'}]}, idProperty:'id'});
Ext.define('dilocsync.store.RouteKnowledgeLines', {extend:dilocsync.store.DiLocStorage, storeId:'RouteKnowledgeLines', model:'dilocsync.model.RouteKnowledgeLine', saveKey:'page:driveInfo:routeknowledgelines', alias:'store.routeknowledgelines', autoLoad:true});
Ext.define('dilocsync.core.syncengine.tasks.SyncRouteKnowledgeLines', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  if (this.doExecuteTask()) {
    this.fireEvent('syncprogress', this.tr('Syncing route knowledge lines...'), 0, 0, null);
    var routeKnowledgeLinesStore = dilocsync.util.Helper.initStore('RouteKnowledgeLines');
    var routeKnowledgeLines = [];
    routeKnowledgeLinesStore.getData().each(function(_record) {
      routeKnowledgeLines.push({id:_record.get('id'), until:_record.get('until')});
    }, this);
    if (routeKnowledgeLinesStore) {
      Ext.Ajax.request({url:this.master.getBackendUrl() + '/syncrideknowledge/routeKnowledgeLines', params:{syncSecret:this.storage.get('core:personalization:syncSecret'), routeKnowledgeLinesIdsUntil:Ext.encode(routeKnowledgeLines)}, success:function(_response) {
        var response = Ext.decode(_response.responseText, true);
        if (response && response.success) {
          var responseData = response.result;
          var serverRouteKnowledgeLines = responseData.routeKnowledgeLines;
          Ext.Array.forEach(serverRouteKnowledgeLines, function(_record) {
            var routeKnowledgeLine = routeKnowledgeLinesStore.findRecord('id', _record.id, 0, false, false, true);
            if (routeKnowledgeLine) {
              routeKnowledgeLine.set('lineName', _record.lineName);
              routeKnowledgeLine.set('groupName', _record.groupName);
              routeKnowledgeLine.set('since', _record.since);
              routeKnowledgeLine.set('refreshedAt', _record.refreshedAt);
              routeKnowledgeLine.set('until', _record.until);
            } else {
              routeKnowledgeLinesStore.add({id:_record.id, lineName:_record.lineName, groupName:_record.groupName, since:_record.since, refreshedAt:_record.refreshedAt, until:_record.until});
            }
          }, this);
          routeKnowledgeLinesStore.sync({callback:function() {
            this.fireEvent('syncprogress', this.tr('Successfully synchronized route knowledge lines!'), 0, 0, null);
            Ext.callback(_next, _scope, [true]);
          }, failure:function() {
            Ext.callback(_next, _scope);
            console.log('Error syncing the route knowledge lines.', response);
          }, scope:this});
        } else {
          Ext.callback(_next, _scope);
          Sentry.withScope(function(_scope) {
            _scope.setExtra('response', response);
            Sentry.captureMessage('An error occurred while syncing the route knowledge lines!');
          });
        }
      }, failure:function(response) {
        Ext.callback(_next, _scope);
        console.log('Error syncing the route knowledge lines.', response);
      }, scope:this});
    }
  } else {
    Ext.callback(_next, _scope);
  }
}});
Ext.define('dilocsync.util.PromiseHelpers', {singleton:true, delay:function(_delayInMilliseconds) {
  return new Promise(function(_resolve) {
    return setTimeout(_resolve, _delayInMilliseconds);
  });
}});
Ext.define('dilocsync.core.syncengine.tasks.db.PreSync', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, documentRepository:null, constructor:function(_config) {
  this.documentRepository = _config.documentRepository;
  this.callParent([_config]);
}, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Preparing synchronization...'), 0, 0, null);
  Ext.Ajax.request({url:this.master.getBackendUrl() + '/clientsync/preSync', params:{syncSecret:this.storage.get('core:personalization:syncSecret'), version:dilocsync.core.Master.version, deviceType:dilocsync.core.Master.deviceType(), additionalDeviceInformation:Ext.encode({'platformName':dilocsync.util.Platform.getPlatform(), 'platformVersion':dilocsync.util.Platform.getVersion(), 'manufacturer':device.manufacturer, 'model':device.model})}, success:Ext.bind(this.onSuccess, this, [_next, _abort, 
  _scope], true), failure:Ext.bind(this.onFailure, this, [_next, _abort, _scope], true), scope:this});
}, onSuccess:function(_response, _options, _next, _abort, _scope) {
  try {
    var response = Ext.decode(_response.responseText);
    if (response.success) {
      if (response.result.depersonalize && response.result.depersonalize === 'doit') {
        this.syncData.depersonalize();
      }
      if (response.result.openUrl) {
        this.syncData.openExternalUrl(response.result.openUrl);
      }
      if (response.result.identity) {
        if (Ext.encode(this.storage.get('core:identity', false)) !== Ext.encode(response.result.identity)) {
          var identity = dilocsync.core.Master.getIdentity();
          cnconsult.Logger.log({prefix:'PreSync-\x3eonSuccess', message:'identity.json changed!'});
          this.syncData.identityChange();
          var preventDisplayStandbyIsAlreadySet = identity.hasOwnProperty('options') && identity.options.hasOwnProperty('preventDisplayStandby') && identity.options.preventDisplayStandby;
          if (!preventDisplayStandbyIsAlreadySet && response.result.identity.options.hasOwnProperty('preventDisplayStandby') && response.result.identity.options.preventDisplayStandby) {
            if (window.plugins && window.plugins.insomnia) {
              window.plugins.insomnia.keepAwake();
            }
          }
        }
        this.syncData.setRemoteIdentity(response.result.identity);
        this.storage.set('core:identity', Ext.encode(response.result.identity));
      }
      if (response.result.registryUpdates) {
        this.syncData.setRegistryUpdates(response.result.registryUpdates);
      }
      if (response.result.passwordChangeRequired) {
        this.syncData.setPasswordChangeRequired(response.result.passwordChangeRequired);
      }
      if (response.result.hasOwnProperty('multiUserSupportAvailable')) {
        if (dilocsync.util.MultiUserSupport.isAvailable() !== response.result.multiUserSupportAvailable) {
          dilocsync.util.MultiUserSupport.setAvailable(response.result.multiUserSupportAvailable);
          this.syncData.setMultiUserSettingsChanged(true);
        }
      }
      if (response.result.hasOwnProperty('multiUserSupportEnabled')) {
        var multiUserSupportEnabledOnServer = response.result.multiUserSupportEnabled;
        var multiUserSupportWasPreviouslyEnabledOnClient = dilocsync.util.MultiUserSupport.isEnabled();
        if (multiUserSupportWasPreviouslyEnabledOnClient && !multiUserSupportEnabledOnServer) {
          var ensureSettingsAreSavedDelay = 550;
          this.storage.removeAllUserSettings();
          this.storage.set('core:personalized', false);
          this.documentRepository.clearDocumentOwnerships().then(function() {
            return dilocsync.util.MultiUserSupport.setEnabled(false);
          })['catch'](function(_err) {
            return cnconsult.Logger.log({level:'error', prefix:'PreSync-\x3eonSuccess', message:'Error while disabling MultiUserSupport', catchedError:_err, stack:true});
          }).then(function() {
            return dilocsync.util.PromiseHelpers.delay(ensureSettingsAreSavedDelay);
          })['finally'](function() {
            return dilocsync.util.ApplicationHelpers.reloadApplicationWithAcknowledge();
          });
          return;
        }
        if (!multiUserSupportWasPreviouslyEnabledOnClient && multiUserSupportEnabledOnServer) {
          cnconsult.Logger.log({level:'warn', prefix:'PreSync-\x3eonSuccess', message:'MultiUserSupport disabled on the client, enabled on the server. Ignoring Server'});
        }
      }
      if (response.result.hasOwnProperty('daysUntilUserIsConsideredInactive')) {
        dilocsync.util.MultiUserSupport.setDaysUntilUserIsConsideredInactive(response.result.daysUntilUserIsConsideredInactive);
      }
      if (response.result.hasOwnProperty('gpsDebugUrl')) {
        this.storage.set('page:driveInfo:gpsDebugUrl', response.result.gpsDebugUrl);
      }
      if (response.result.hasOwnProperty('customerIdCode')) {
        this.storage.set('core:personalization:customerIdCode', response.result.customerIdCode);
      }
      if (response.result.almanacs && Ext.isArray(response.result.almanacs) && response.result.almanacs.length > 0) {
        var almanacs = [];
        Ext.Array.each(response.result.almanacs, function(_almanac) {
          if (_almanac && _almanac.identifier !== 'software') {
            almanacs.push(_almanac);
          }
        }, this);
        this.syncData.setAlmanacsInfoList(almanacs);
      } else {
        Ext.log({level:'error'}, 'Almanacs setting was not successful! Response almanacs are not set or empty.');
        Ext.callback(_abort, _scope, [false, this.tr('Almanacs setting was not successful! Response almanacs are not set or empty')]);
      }
      Ext.callback(_next, _scope);
    } else {
      var errorMessage = response.backendError;
      if (errorMessage === 'UnknownDevice') {
        cnconsult.Logger.log({prefix:'PreSync-\x3eonSuccess', message:'Device has been deactivated, reset it...'});
        dilocsync.core.Master.resetDevice();
      } else {
        Ext.callback(_abort, _scope, [false, this.tr('Server-error retrieving sync configuration: %1').arg(errorMessage)]);
      }
    }
  } catch (e$69) {
    cnconsult.Logger.log({prefix:'PreSync-\x3eonSuccess', message:'Error during preSync response handling.', level:'error', catchedError:e$69, useSentry:true});
    Ext.callback(_abort, _scope, [false, this.tr('Unknown server-error retrieving sync configuration.')]);
  }
}, onFailure:function(_response, _options, _next, _abort, _scope) {
  Ext.callback(_abort, _scope, [false, this.tr('Error retrieving sync configuration.')]);
}});
Ext.define('dilocsync.core.syncengine.tasks.db.FetchAlmanacs', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var remoteAlmanacs = this.syncData.getAlmanacsInfoList();
  var remoteAlmanacsIdentifiers = Ext.isArray(remoteAlmanacs) ? Ext.Array.pluck(remoteAlmanacs, 'identifier') : [];
  var localAlmanacs = this.storage.get('core:almanacs');
  var localAlmanacsMap = Ext.isArray(localAlmanacs) ? Ext.Array.toValueMap(localAlmanacs, 'identifier') : {};
  var localAlmanacsIdentifiers = Ext.isArray(localAlmanacs) ? Ext.Array.pluck(localAlmanacs, 'identifier') : [];
  var almanacsToDownload = [];
  var almanacsToDelete = Ext.Array.difference(localAlmanacsIdentifiers, remoteAlmanacsIdentifiers);
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  Ext.Array.each(remoteAlmanacs, function(remoteAlmanac) {
    var localAlmanac = localAlmanacsMap[remoteAlmanac.identifier];
    if (!localAlmanac || localAlmanac && localAlmanac.version !== remoteAlmanac.version || window.forceSync) {
      almanacsToDownload.push(this.downloadAlmanac(remoteAlmanac.identifier));
    }
  }, this);
  delete window.forceSync;
  this.fireEvent('syncprogress', this.tr('Retrieving almanacs...'), 0, 0, null);
  if (almanacsToDelete.length > 0) {
    Ext.Array.each(almanacsToDelete, function(deleteAlmanacIdentifier) {
      var localAlmanac = localAlmanacsMap[deleteAlmanacIdentifier];
      if (localAlmanac && localAlmanac.path) {
        storage.remove('core:almanac:' + localAlmanac.path);
      }
    }, this);
    storage.set('core:almanacs', this.syncData.getAlmanacsInfoList());
    dilocsync.core.Master.initAlmanacs();
  }
  if (almanacsToDownload.length > 0) {
    Ext.Promise.all(almanacsToDownload).then(Ext.bind(this.handleAlmanacs, this, [_next, _abort, _scope], true))['catch'](Ext.bind(this.handleDownloadError, this, [_next, _abort, _scope], true));
  } else {
    cnconsult.Logger.log({prefix:'FetchAlmanacs-\x3eexecute', message:'Nothing to do, finishing synchronization.'});
    Ext.callback(_abort, _scope, [true]);
  }
}, downloadAlmanac:function(_identifier) {
  var me = this;
  return new Ext.Promise(function(_resolve, _reject) {
    Ext.Ajax.request({url:me.master.getBackendUrl() + '/clientsync/downloadAlmanac', timeout:120000, params:{syncSecret:me.storage.get('core:personalization:syncSecret'), almanacUuid:_identifier, syncDeviceIdCode:me.master.deviceIdCode()}, success:function(_response) {
      _resolve(Ext.decode(_response.responseText));
    }, failure:function(_response) {
      _reject(_response.backendError);
    }});
  });
}, handleAlmanacs:function(_responses, _next, _abort, _scope) {
  Ext.Array.each(_responses, function(_response) {
    var $jscomp$this = this;
    if (_response && _response.success) {
      var almanac = new dilocsync.core.Almanac(_response.result);
      this.syncData.addToRemoteAlmanacs(almanac);
      if (typeof device === 'undefined' || almanac.path.startsWith('trainschedules')) {
        cnconsult.Logger.log({prefix:'FetchAlmanacs-\x3ehandleAlmanacs', message:'Persist almanac in local storage, so that at least the directories are visible in a chrome browser on windows devices'});
      }
      if (almanac.path.startsWith('trainschedules')) {
        this.handleTrainScheduleAlmanac(almanac, _response.result.path).then(function() {
          return $jscomp$this.persistAlmanac(almanac, _response.result.path);
        })['catch'](function(error) {
          return console.log(error);
        });
      }
    } else {
      if (_response && _response.backendError) {
        Ext.callback(_abort, _scope, [false, this.tr('Server-error retrieving almanac: %1').arg(_response.backendError)]);
      }
    }
  }, this);
  if (typeof device === 'undefined') {
    cnconsult.Logger.log({prefix:'FetchAlmanacs-\x3ehandleAlmanacs', message:'Persist almanac in local storage, so that at least the directories are visible in a chrome browser on windows devices'});
    this.storage.set('core:almanacs', this.syncData.getAlmanacsInfoList());
    dilocsync.core.Master.initAlmanacs();
  }
  Ext.callback(_next, _scope);
}, handleTrainScheduleAlmanac:function(_almanac, _path) {
  var me = this;
  return new Ext.Promise(function(_resolve, _reject) {
    dilocsync.core.Master.getSyncRoot().getDirectory('train-schedule-data', {create:true}, Ext.bind(function(_directory) {
      me.readAllEntries(_directory, function(entries) {
        var names = entries.map(function(entry) {
          return entry.name.slice(0, -4);
        });
        var allFiles = _almanac.getRootDirectory().getAllFiles();
        for (var key in allFiles) {
          if (allFiles.hasOwnProperty(key)) {
            var file = allFiles[key];
            file.loaded = names.includes(file.checksum);
          }
        }
        _resolve();
      });
    }, this));
  });
}, readAllEntries:function(directoryEntry, callback) {
  var reader = directoryEntry.createReader();
  var entries = [];
  function readChunk() {
    reader.readEntries(function(results) {
      if (!results.length) {
        callback(entries);
      } else {
        entries = entries.concat(Array.from(results));
        readChunk();
      }
    }, function(error) {
      cnconsult.Logger.log({prefix:'FetchAlmanacs-\x3ereadAllEntries', message:'Could not read all entries in the file directory', level:'error', dump:{error:error}});
    });
  }
  readChunk();
}, handleDownloadError:function(_error, _next, _abort, _scope) {
  Ext.callback(_abort, _scope, [false, this.tr('Server-error retrieving almanac: %1').arg(_error.message)]);
}});
Ext.define('dilocsync.core.syncengine.tasks.db.GenerateSyncActions', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, abortCallback:null, callbackScope:null, nextCallback:null, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Generating sync actions...'), 0, 0, null);
  this.nextCallback = _next;
  this.abortCallback = _abort;
  this.callbackScope = _scope;
  var almanacsInfoList = this.syncData.getAlmanacsInfoList();
  var remoteAlmanacs = this.syncData.getRemoteAlmanacs();
  var remoteAlmanacsMap = Ext.isArray(remoteAlmanacs) ? Ext.Array.toValueMap(remoteAlmanacs, 'identifier') : {};
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  if (remoteAlmanacs) {
    Ext.Array.each(almanacsInfoList, function(_almanacInfo) {
      var remoteAlmanac = remoteAlmanacsMap[_almanacInfo.identifier];
      if (remoteAlmanac) {
        var almanacData = storage.get('core:almanac:' + _almanacInfo.path, null) ? storage.get('core:almanac:' + _almanacInfo.path, null) : {};
        var almanac = new dilocsync.core.Almanac({root:almanacData, identifier:remoteAlmanac.identifier, path:remoteAlmanac.path, createdAt:remoteAlmanac.createdAt, updatedAt:remoteAlmanac.updatedAt, version:remoteAlmanac.version});
        var actions = _almanacInfo.path.startsWith('trainschedules') ? {filesToDownload:{}, filesToDelete:{}, filesOnlyToDeleteFromFileSystem:{}, filesToCheck:{}, filesNeedMetaUpdate:{}} : almanac.compareWithOtherAlmanacDirectory(remoteAlmanac);
        var almanacSyncActions = Ext.create('dilocsync.core.syncengine.AlmanacSyncActions', {almanac:almanac, almanacIdentifier:_almanacInfo.identifier, almanacPath:_almanacInfo.path, filesToDownload:actions.filesToDownload, filesToDelete:actions.filesToDelete, filesOnlyToDeleteFromFileSystem:actions.filesOnlyToDeleteFromFileSystem, filesToCheck:actions.filesToCheck, filesNeedMetaUpdate:actions.filesNeedMetaUpdate});
        this.syncData.addToLocalAlmanacs(almanac);
        this.syncData.addToAlmanacsSyncActions(almanacSyncActions);
        if (actions.directoryChanges || actions.directoryMetaChanges) {
          master.persistAlmanacByPath(almanac, _almanacInfo.path);
        }
      }
    }, this);
    if (!Ext.isEmpty(this.syncData.getAlmanacsSyncActions())) {
      this.syncData.setAlmanacsSyncActionsBackup(Ext.clone(this.syncData.getAlmanacsSyncActions()));
      Ext.callback(this.nextCallback, this.callbackScope);
    } else {
      cnconsult.Logger.log({prefix:'GenerateSyncActions-\x3eexecute', message:"Somehow we didn't get a sync actions object, wtf happened?", level:'error'});
      Ext.callback(this.abortCallback, this.callbackScope, [false, this.tr('An unknown error occured, sync process aborted.')]);
    }
  } else {
    cnconsult.Logger.log({prefix:'GenerateSyncActions-\x3eexecute', message:'GenerateSyncActions: Nothing to do, finishing synchronization.'});
    Ext.callback(this.abortCallback, this.callbackScope, [true]);
  }
}});
Ext.define('dilocsync.core.syncengine.tasks.db.PrepareQueues', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, abortCallback:null, callbackScope:null, nextCallback:null, syncActions:null, filesToDownloadChecksums:null, filesToPrioDownloadChecksums:null, filesExistCache:null, documentRepository:null, constructor:function(_config) {
  this.documentRepository = _config.documentRepository;
  this.callParent([_config]);
}, abort:function() {
  this.callParent();
  this.fireEvent('abort', 'aborted');
}, execute:function(_next, _abort, _scope) {
  var $jscomp$this = this;
  this.fireEvent('syncprogress', this.tr('Comparing against local files...'), 0, 0, null);
  cnconsult.Logger.log({prefix:'PrepareQueues-\x3eexecute', message:'Checking whether all files of local almanac are really existing on the device.'});
  this.nextCallback = _next;
  this.abortCallback = _abort;
  this.callbackScope = _scope;
  this.filesToDownloadChecksums = {};
  this.filesToPrioDownloadChecksums = {};
  this.filesExistCache = {};
  this.syncActions = this.syncData.getAlmanacsSyncActions();
  try {
    this.addOwnershipsForFilesNotInLocalAlmanac().then(function() {
      return $jscomp$this.doCheckFilesForPrioDownload();
    }).then(function() {
      return $jscomp$this.doCheckFilesForDuplicates();
    }).then(function() {
      return $jscomp$this.prepareFilesExistCache();
    }).then(function() {
      return $jscomp$this.markAlreadyExistingFilesAsDownloadedAndRemoveFromDownloadQueues();
    }).then(function() {
      return $jscomp$this.doCheckFilesForExistence();
    }).then(function() {
      return $jscomp$this.doCheckFilesToDelete();
    }).then(function() {
      return $jscomp$this.doCheckFilesToDeleteOnlyFromFileSystem();
    }).then(function() {
      return $jscomp$this.finishPreparing();
    })['catch'](function() {
      return $jscomp$this.onFailureCallback();
    });
  } catch (e$70) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3eexecute', message:'Caught exception during preparing queues.', catchedError:e$70});
  }
}, onFailureCallback:function() {
  if (this.abortNeeded) {
    Ext.callback(this.abortCallback, this.callbackScope, [false, 'noalert']);
  } else {
    Ext.callback(this.abortCallback, this.callbackScope, [false, this.tr('Some files failed to synchronize! This is most probably due to network errors. You should just try again.')]);
  }
}, addOwnershipsForFilesNotInLocalAlmanac:function() {
  var $jscomp$this = this;
  var currentUserId = this.storage.get('core:personalization:userid');
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var almanacOwnershipPromises = almanacsSyncActions.map(function(_singleAlmanacSyncActions) {
    var ownershipPromises = Object.values(_singleAlmanacSyncActions.getFilesToDownload()).map(function(_fileToDownload) {
      return $jscomp$this.documentRepository.addOwnerForDocument(_fileToDownload.checksum, currentUserId);
    });
    return Promise.all(ownershipPromises);
  });
  return Promise.all(almanacOwnershipPromises)['catch'](function(_err) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3eaddOwnershipsForFilesNotInLocalAlmanac', message:'Error adding ownerships for files not in local almanac', catchedError:_err});
    throw _err;
  });
}, doCheckFilesForPrioDownload:function() {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var me = this;
  var identity = dilocsync.core.Master.getIdentity();
  var promises = [];
  var disablePrioSync = false;
  if (identity.hasOwnProperty('options') && identity.options.hasOwnProperty('disablePrioSync') && identity.options.disablePrioSync) {
    disablePrioSync = true;
  }
  if (disablePrioSync === false) {
    var walker = new dilocsync.core.AsyncWalk;
    var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
    Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
      var promise = new Ext.Promise(function(_resolve, _reject) {
        if (me.getStorage().get('core:syncengine:lastSyncTimestamp', false)) {
          console.log('PromiseFilesToDownloadPrioCheck - check if we have to move files to the high prio download queue.', _almanacSyncActions.getFilesToDownload());
          me.on('abort', _reject);
          if (Ext.Object.getSize(_almanacSyncActions.getFilesToDownload()) > 0) {
            walker.walkObject(_almanacSyncActions.getFilesToDownload(), me.filesToDownloadPrioCheck, me, _resolve, me, [_almanacSyncActions]);
          } else {
            _resolve();
          }
        } else {
          _resolve();
        }
      });
      promises.push(promise);
    }, me);
  }
  return Ext.Promise.all(promises)['catch'](function(_err) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3edoCheckFilesForPrioDownload', message:'Error checking if download queue contains high priority files', catchedError:_err});
    throw _err;
  });
}, doCheckFilesForDuplicates:function() {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      console.log('PromiseFilesToDownloadDuplicatesCheck - check if we have duplicated checksum files in download queue.');
      me.on('abort', _reject);
      if (Ext.Object.getSize(_almanacSyncActions.getFilesToDownload()) > 0) {
        walker.walkObject(_almanacSyncActions.getFilesToDownload(), me.filesToDownloadDuplicateCheck, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises)['catch'](function(_err) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3edoCheckFilesForDuplicates', message:'Error checking if download queue contains duplicates', catchedError:_err});
    throw _err;
  });
}, prepareFilesExistCache:function() {
  var $jscomp$this = this;
  if (this.abortNeeded) {
    throw 'aborted';
  }
  cnconsult.Logger.log({prefix:'PrepareQueues-\x3eprepareFilesExistCache', message:'Preparing cache for existing files'});
  return new Promise(function(_resolve, _reject) {
    $jscomp$this.master.getSyncRoot().getDirectory('fs-data', {}, function(_dir) {
      dilocsync.util.File.readEntriesFromDirectory(_dir).then(function(_entries) {
        for (var $jscomp$iter$3 = $jscomp.makeIterator(_entries), $jscomp$key$fileEntry = $jscomp$iter$3.next(); !$jscomp$key$fileEntry.done; $jscomp$key$fileEntry = $jscomp$iter$3.next()) {
          var fileEntry = $jscomp$key$fileEntry.value;
          {
            $jscomp$this.filesExistCache[fileEntry.name] = true;
          }
        }
        _resolve();
      })['catch'](_reject);
    }, _reject);
  });
}, markAlreadyExistingFilesAsDownloadedAndRemoveFromDownloadQueues:function() {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  cnconsult.Logger.log({prefix:'PrepareQueues-\x3emarkAlreadyExistingFilesAsDownloadedAndRemoveFromDownloadQueues', message:'Check if we have already existing files which can be removed from the download queue'});
  var promises = [];
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var $jscomp$loop$105 = {};
  var $jscomp$iter$4 = $jscomp.makeIterator(almanacsSyncActions), $jscomp$key$singleAlmanacSyncActions = $jscomp$iter$4.next();
  for (; !$jscomp$key$singleAlmanacSyncActions.done; $jscomp$loop$105 = {singleAlmanacSyncActions:$jscomp$loop$105.singleAlmanacSyncActions}, $jscomp$key$singleAlmanacSyncActions = $jscomp$iter$4.next()) {
    $jscomp$loop$105.singleAlmanacSyncActions = $jscomp$key$singleAlmanacSyncActions.value;
    {
      var almanac = $jscomp$loop$105.singleAlmanacSyncActions.getAlmanac();
      var almanacPath = $jscomp$loop$105.singleAlmanacSyncActions.getAlmanacPath();
      var downloadQueue = $jscomp$loop$105.singleAlmanacSyncActions.getFilesToDownload();
      var downloadQueueUpdated = this.markAlreadyExistingFilesAsDownloadedAndReturnFilesNotYetExistingFromAlmanac(almanac, almanacPath, downloadQueue).then(function($jscomp$loop$105) {
        return function(_filesToDownloadWithoutAlreadyExistingFiles) {
          $jscomp$loop$105.singleAlmanacSyncActions.setFilesToDownload(_filesToDownloadWithoutAlreadyExistingFiles);
        };
      }($jscomp$loop$105));
      promises.push(downloadQueueUpdated);
      var highPrioQueue = $jscomp$loop$105.singleAlmanacSyncActions.getHighPriorityFilesToDownload();
      var highPrioQueueUpdated = this.markAlreadyExistingFilesAsDownloadedAndReturnFilesNotYetExistingFromAlmanac(almanac, almanacPath, highPrioQueue).then(function($jscomp$loop$105) {
        return function(_filesToDownloadWithoutAlreadyExistingFiles) {
          $jscomp$loop$105.singleAlmanacSyncActions.setHighPriorityFilesToDownload(_filesToDownloadWithoutAlreadyExistingFiles);
        };
      }($jscomp$loop$105));
      promises.push(highPrioQueueUpdated);
    }
  }
  return Promise.all(promises)['catch'](function(_err) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3eremoveAlreadyExistingFilesFromFilesToDownload', message:'Error while removing already existing files from download queue', catchedError:_err});
    throw _err;
  });
}, markAlreadyExistingFilesAsDownloadedAndReturnFilesNotYetExistingFromAlmanac:function(_almanac, _almanacPath, _fileQueue) {
  var $jscomp$this = this;
  return this.checkIfFilesExistInQueue(_fileQueue).then(function(_result) {
    var filesNotAlreadyExistingOnFileSystem = {};
    for (var $jscomp$iter$5 = $jscomp.makeIterator(_result), $jscomp$key$$jscomp$destructuring$var4 = $jscomp$iter$5.next(); !$jscomp$key$$jscomp$destructuring$var4.done; $jscomp$key$$jscomp$destructuring$var4 = $jscomp$iter$5.next()) {
      var $jscomp$destructuring$var4 = $jscomp$key$$jscomp$destructuring$var4.value;
      {
        var $jscomp$destructuring$var5 = $jscomp$destructuring$var4;
        var path = $jscomp$destructuring$var5.path;
        var fileInfo = $jscomp$destructuring$var5.fileInfo;
        var fileExists = $jscomp$destructuring$var5.fileExists;
        if (fileExists) {
          _almanac.updateFile(path, fileInfo.size, fileInfo.checksum, fileInfo);
        } else {
          filesNotAlreadyExistingOnFileSystem[path] = fileInfo;
        }
      }
    }
    if (!_almanacPath.startsWith('trainschedules')) {
      $jscomp$this.persistAlmanac(_almanac, _almanacPath);
    }
    return filesNotAlreadyExistingOnFileSystem;
  });
}, checkIfFilesExistInQueue:function(_queue) {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    var result = [];
    var walker = new dilocsync.core.AsyncWalk;
    walker.walkObject(_queue, function(_path, _fileInfo, _callback, _result) {
      var fileExists = _fileInfo.checksum + '.' + _fileInfo.fileType in this.filesExistCache;
      _result.push({path:_path, fileInfo:_fileInfo, fileExists:fileExists});
      _callback();
    }, $jscomp$this, function() {
      return _resolve(result);
    }, $jscomp$this, [result]);
  });
}, doCheckFilesForExistence:function() {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      console.log('PromiseFilesToCheck - check if files exists on device or if we have to add the to download queue');
      me.on('abort', _reject);
      if (Ext.Object.getSize(_almanacSyncActions.getFilesToCheck()) > 0) {
        walker.walkObject(_almanacSyncActions.getFilesToCheck(), me.checkFileExistence, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises)['catch'](function(_err) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3edoCheckFilesForExistence', message:'Error while checking files for existence', catchedError:_err});
    throw _err;
  });
}, doCheckFilesToDelete:function() {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      console.log('PromiseFilesToDelete - check if files to delete are only be used in one place and can be deleted from the device.');
      me.on('abort', _reject);
      if (Ext.Object.getSize(_almanacSyncActions.getFilesToDelete()) > 0) {
        walker.walkObject(_almanacSyncActions.getFilesToDelete(), me.checkCanFileBeDeleted, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises)['catch'](function(_err) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3edoCheckFilesToDelete', message:'Error checking if files can be deleted', catchedError:_err});
    throw _err;
  });
}, doCheckFilesToDeleteOnlyFromFileSystem:function() {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      console.log('PromiseFilesOnlyToDeleteFromFileSystem - check if files to delete are only be used in one place and can be deleted from the device.');
      me.on('abort', _reject);
      if (Ext.Object.getSize(_almanacSyncActions.getFilesOnlyToDeleteFromFileSystem()) > 0) {
        walker.walkObject(_almanacSyncActions.getFilesOnlyToDeleteFromFileSystem(), me.checkCanFileBeDeletedFromFileSystem, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises)['catch'](function(_err) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3edoCheckFilesToDelete', message:'Error checking if files can be deleted from file system', catchedError:_err});
    throw _err;
  });
}, checkFileExistence:function(_path, _fileInfo, _callback, _almanacSyncActions) {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var fileName = _fileInfo.checksum + '.' + _fileInfo.fileType;
  if (!(fileName in this.filesExistCache)) {
    this.addDownload(_path, _fileInfo, _almanacSyncActions);
  }
  _callback();
}, checkCanFileBeDeleted:function(_path, _fileInfo, _callback, _almanacSyncActions) {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var checksum = _fileInfo.checksum;
  var filesWithSameChecksum = [];
  Ext.Array.each(this.syncActions, function(_syncAction) {
    var almanac = _syncAction.getAlmanac();
    var files = almanac.findFilesByChecksum(checksum);
    filesWithSameChecksum = Ext.Array.merge(filesWithSameChecksum, files);
  }, this);
  Ext.Array.each(Ext.Array.merge(Object.keys(this.filesToDownloadChecksums), Object.keys(this.filesToPrioDownloadChecksums)), function(_fileToDownloadChecksum) {
    if (_fileToDownloadChecksum === checksum) {
      console.log('PrepareQueues: checkCanFileBeDeleted -\x3e File will be downloaded, do not delete it!', _fileToDownloadChecksum, checksum, _fileInfo);
      filesWithSameChecksum = Ext.Array.merge(filesWithSameChecksum, [_fileInfo]);
    }
  }, this);
  if (filesWithSameChecksum.length > 1) {
    delete _almanacSyncActions.getFilesToDelete()[_path];
    _almanacSyncActions.getFilesOnlyToDeleteFromAlmanac()[_path] = _fileInfo;
  }
  _callback();
}, checkCanFileBeDeletedFromFileSystem:function(_path, _fileInfo, _callback, _almanacSyncActions) {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var checksum = _fileInfo.checksum;
  var filesWithSameChecksum = [];
  Ext.Array.each(this.syncActions, function(_syncAction) {
    var almanac = _syncAction.getAlmanac();
    var files = almanac.findFilesByChecksum(checksum);
    filesWithSameChecksum = Ext.Array.merge(filesWithSameChecksum, files);
  }, this);
  Ext.Array.each(Ext.Array.merge(Object.keys(this.filesToDownloadChecksums), Object.keys(this.filesToPrioDownloadChecksums)), function(_fileToDownloadChecksum) {
    if (_fileToDownloadChecksum === checksum) {
      console.log('PrepareQueues: checkCanFileBeDeletedFromFileSystem -\x3e File will be downloaded, do not delete it!', _fileToDownloadChecksum, checksum, _fileInfo);
      filesWithSameChecksum = Ext.Array.merge(filesWithSameChecksum, [_fileInfo]);
    }
  }, this);
  if (filesWithSameChecksum.length > 1) {
    delete _almanacSyncActions.getFilesOnlyToDeleteFromFileSystem()[_path];
  }
  _callback();
}, addDownload:function(_path, _fileInfo, _almanacSyncActions) {
  cnconsult.Logger.log({prefix:'PrepareQueues-\x3eaddDownload', message:'File does not exist on the device, downloading it!'});
  if (this.hasHighPriority(_fileInfo)) {
    _almanacSyncActions.getHighPriorityFilesToDownload()[_path] = _fileInfo;
  } else {
    _almanacSyncActions.getFilesToDownload()[_path] = _fileInfo;
  }
}, filesToDownloadPrioCheck:function(_path, _fileInfo, _callback, _almanacSyncActions) {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  if (_fileInfo && 'checksum' in _fileInfo) {
    if (this.hasHighPriority(_fileInfo)) {
      if (_fileInfo.checksum in this.filesToPrioDownloadChecksums) {
        console.log('PrepareQueues-\x3efilesToDownloadPrioCheck checksum already in prio download queue only add/update in almanac: ', _almanacSyncActions.getAlmanacPath() + _path, _fileInfo.checksum);
        _almanacSyncActions.getFilesNeedMetaUpdate()[_path] = _fileInfo;
      } else {
        _almanacSyncActions.getHighPriorityFilesToDownload()[_path] = _fileInfo;
        this.syncData.setHasHighPriorityFiles(true);
        this.filesToPrioDownloadChecksums[_fileInfo.checksum] = true;
      }
      delete _almanacSyncActions.getFilesToDownload()[_path];
    }
  } else {
    console.log('PrepareQueues-\x3efilesToDownloadPrioCheck: File has no checksum set, deleting it from almanac sync actions!', _path, _fileInfo);
    delete _almanacSyncActions.getFilesToDownload()[_path];
  }
  _callback();
}, filesToDownloadDuplicateCheck:function(_path, _fileInfo, _callback, _almanacSyncActions) {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  if (_fileInfo && 'checksum' in _fileInfo) {
    if (_fileInfo.checksum in this.filesToDownloadChecksums) {
      console.log('PrepareQueues-\x3efilesToDownloadDuplicateCheck checksum already in download queue only add/update in almanac: ', _almanacSyncActions.getAlmanacPath() + _path, _fileInfo.checksum);
      _almanacSyncActions.getFilesNeedMetaUpdate()[_path] = _fileInfo;
      delete _almanacSyncActions.getFilesToDownload()[_path];
    } else {
      this.filesToDownloadChecksums[_fileInfo.checksum] = true;
    }
  } else {
    console.log('PrepareQueues-\x3efilesToDownloadDuplicateCheck: File has no checksum set, deleting it from almanac sync actions!', _path, _fileInfo);
    delete _almanacSyncActions.getFilesToDownload()[_path];
  }
  _callback();
}, hasHighPriority:function(_fileInfo) {
  var hasHighPriority = false;
  if (_fileInfo && _fileInfo.hasOwnProperty('tags') && Ext.isArray(_fileInfo.tags)) {
    Ext.Array.each(_fileInfo.tags, function(_tag) {
      if (_tag.hasOwnProperty('syncPriority') && _tag.syncPriority === 'high') {
        hasHighPriority = true;
        return false;
      }
    }, this);
    return hasHighPriority;
  }
}, finishPreparing:function() {
  if (this.abortNeeded) {
    throw 'aborted';
  }
  var filesToDelete = {};
  var filesToDownload = {};
  var filesToDeleteFromAlmanac = {};
  var filesToDeleteFromFileSystem = {};
  var filesNeedMetaUpdate = {};
  var highPriorityFilesToDownload = {};
  Ext.Array.each(this.syncActions, function(_almanacSyncActions) {
    Ext.apply(filesToDelete, _almanacSyncActions.getFilesToDelete());
    Ext.apply(filesToDeleteFromAlmanac, _almanacSyncActions.getFilesOnlyToDeleteFromAlmanac());
    Ext.apply(filesToDeleteFromFileSystem, _almanacSyncActions.getFilesOnlyToDeleteFromFileSystem());
    Ext.apply(filesToDownload, _almanacSyncActions.getFilesToDownload());
    Ext.apply(filesNeedMetaUpdate, _almanacSyncActions.getFilesNeedMetaUpdate());
    Ext.apply(highPriorityFilesToDownload, _almanacSyncActions.getHighPriorityFilesToDownload());
  }, this);
  if (Ext.Object.getSize(filesToDelete) > 0 || Ext.Object.getSize(filesNeedMetaUpdate) > 0 || Ext.Object.getSize(highPriorityFilesToDownload) > 0 || Ext.Object.getSize(filesToDownload) > 0 || Ext.Object.getSize(filesToDeleteFromAlmanac) > 0 || Ext.Object.getSize(filesToDeleteFromFileSystem) > 0) {
    cnconsult.Logger.log({prefix:'PrepareQueues-\x3efinishPreparing', message:'Files Info:', level:'info', dump:{'Files to download count':Ext.Object.getSize(filesToDownload), 'Files to download':filesToDownload, 'Files to highPriority files to download count':Ext.Object.getSize(highPriorityFilesToDownload), 'Files to highPriority files to download':highPriorityFilesToDownload, 'Files to delete count':Ext.Object.getSize(filesToDelete), 'Files to delete':filesToDelete, 'Files to files to delete from almanac count':Ext.Object.getSize(filesToDeleteFromAlmanac), 
    'Files to files to delete from almanac':filesToDeleteFromAlmanac, 'Files to files to delete from FileSystem count':Ext.Object.getSize(filesToDeleteFromFileSystem), 'Files to files to delete from FileSystem':filesToDeleteFromFileSystem, 'Files to files need meta update count':Ext.Object.getSize(filesNeedMetaUpdate), 'Files to files need meta update':filesNeedMetaUpdate}});
    if (Ext.Object.getSize(highPriorityFilesToDownload) > 0) {
      this.syncData.setHasHighPriorityFiles(true);
    }
  } else {
    console.log('PrepareQueues: Nothing to do, continuing to next sync step and saving almanacs info list.', this.syncData.getAlmanacsInfoList());
    this.storage.set('core:almanacs', this.syncData.getAlmanacsInfoList());
  }
  Ext.callback(this.nextCallback, this.callbackScope);
}});
Ext.define('dilocsync.core.syncengine.tasks.db.DownloadSizeChecker', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Checking total download size...'), 0, 0, null);
  var identity = this.master.getIdentity();
  var downloadSize = this.calculateDownloadSize();
  var downloadCheckSizeThreshold = 30;
  if (identity.options && identity.options.downloadCheckSizeThreshold && !isNaN(identity.options.downloadCheckSizeThreshold)) {
    downloadCheckSizeThreshold = identity.options.downloadCheckSizeThreshold;
  }
  cnconsult.Logger.log({prefix:'DownloadSizeChecker-\x3eexecute', message:'Download check size threshold is set to: ' + downloadCheckSizeThreshold});
  if (!this.syncData.isAutoSyncing() && downloadCheckSizeThreshold > 0 && downloadSize > downloadCheckSizeThreshold * 1024 * 1024) {
    dilocsync.util.MessageHelper.showConfirm(this.tr('Large amount of files to sync'), this.tr('There are over %1 MB of files to download during synchronization. This may take a while to complete, depending on the speed of your internet connection. Do you want to continue?').arg(downloadCheckSizeThreshold), function(_button) {
      if (_button === 'yes') {
        Ext.callback(_next, _scope);
      } else {
        Ext.callback(_abort, _scope, [false, 'noalert']);
      }
    }, this);
  } else {
    Ext.callback(_next, _scope);
  }
}, calculateDownloadSize:function() {
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var downloadSize = 0;
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var filesToDownload = _almanacSyncActions.getFilesToDownload();
    var index;
    for (index in filesToDownload) {
      if (filesToDownload.hasOwnProperty(index)) {
        var file = filesToDownload[index];
        if (file && file.hasOwnProperty('size')) {
          downloadSize += file.size;
        } else {
          cnconsult.Logger.log({prefix:'DownloadSizeChecker-\x3ecalculateDownloadSize', message:'File has no size!', level:'warn', dump:{file:file, index:index}});
        }
      }
    }
  }, this);
  this.syncData.setDownloadSize(downloadSize);
  return downloadSize;
}});
Ext.define('dilocsync.model.Form', {extend:Ext.data.Model, fields:[{name:'id', type:'integer'}, {name:'version', type:'integer'}, {name:'path', type:'string', calculate:function(_data) {
  return 'forms/' + _data.id + '/' + _data.version + '.json';
}}, {name:'name', type:'string'}, {name:'description', type:'string'}, {name:'createdAt', type:'date'}, {name:'updatedAt', type:'date'}, {name:'state', type:'string'}, {name:'icon', type:'string', defaultValue:'form-icon-not-completed'}, {name:'syncPartnerId', type:'integer'}, {name:'customer', type:'string'}], isCompletedForm:function() {
  return this.entityName === 'dilocsync.model.CompletedForm';
}});
Ext.define('dilocsync.store.Forms', {extend:dilocsync.store.DiLocStorage, storeId:'Forms', model:'dilocsync.model.Form', saveKey:'page:forms:formsMetaData', autoLoad:true, alias:'store.forms', sorters:'name', constructor:function() {
  this.callParent(arguments);
  this.setGrouper({groupFn:function(_record) {
    if (!_record.get('syncPartnerId')) {
      return '* ' + _record.get('customer');
    }
    return _record.get('customer') || '-';
  }, property:'customer'});
}});
Ext.define('dilocsync.core.syncengine.tasks.db.SyncForms', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var $jscomp$this = this;
  if (this.doExecuteTask()) {
    this.fireEvent('syncprogress', this.tr('Syncing forms...'), 0, 0, null);
    var formsStore = dilocsync.util.Helper.initStore('Forms');
    this.getPublishedForms().then(function(_publishedForms) {
      $jscomp$this.getSyncFormsDirectory().then(function(_syncFormsDir) {
        $jscomp$this.getAllFilesFromDirectory(_syncFormsDir).then(function(_formDirectories) {
          $jscomp$this.fireEvent('syncprogress', $jscomp$this.tr('Cleaning the forms directory...'), 0, 0, null);
          var walker = new dilocsync.core.AsyncWalk;
          var me = $jscomp$this;
          var formsToDownload = Ext.clone(_publishedForms);
          var cleanUpPromise = new Ext.Promise(function(_resolve, _reject) {
            if (_formDirectories.length > 0) {
              walker.walkArray(_formDirectories, me.cleanup, me, _resolve, me, [formsToDownload, formsStore]);
            } else {
              _resolve();
            }
          });
          cleanUpPromise.then(function() {
            formsStore.sync();
            if (formsToDownload.length > 0) {
              $jscomp$this.fireEvent('syncprogress', $jscomp$this.tr('Downloading the new forms from the server...'), 0, 0, null);
              var formIdsToDownload = formsToDownload.map(function(_formToDownload) {
                return _formToDownload.id;
              });
              $jscomp$this.downloadForms(formIdsToDownload).then(function(_downloadedForms) {
                $jscomp$this.fireEvent('syncprogress', $jscomp$this.tr('Downloaded new forms...'), 0, 0, null);
                var saveDownloadedFormsPromise = new Ext.Promise(function(_resolve, _reject) {
                  walker.walkArray(_downloadedForms, me.saveForm, me, _resolve, me, [formsStore]);
                });
                $jscomp$this.fireEvent('syncprogress', $jscomp$this.tr('Saving the new forms data...'), 0, 0, null);
                saveDownloadedFormsPromise.then(function() {
                  formsStore.sync();
                  $jscomp$this.fireEvent('syncprogress', $jscomp$this.tr('Saved successfully the new downloaded forms...'), 0, 0, null);
                  Ext.callback(_next, _scope, [true]);
                })['catch'](function(_err) {
                  Sentry.withScope(function(_scope) {
                    _scope.setExtra('saveDownloadedFormsError', _err);
                    Sentry.captureMessage('An error occurred while saving the forms data!');
                  });
                  Ext.callback(_abort, _scope, [false, $jscomp$this.tr('An error occurred while saving the forms data!')]);
                });
              })['catch'](function(_err) {
                Sentry.withScope(function(_scope) {
                  _scope.setExtra('downloadFormsError', _err);
                  Sentry.captureMessage('An error occurred while downloading the forms!');
                });
                Ext.callback(_abort, _scope, [false, $jscomp$this.tr('An error occurred while downloading the forms!')]);
              });
            } else {
              Ext.callback(_next, _scope, [true]);
            }
          });
        });
      })['catch'](function(_err) {
        Sentry.withScope(function(_scope) {
          _scope.setExtra('getSyncFormsDirectory', _err);
          Sentry.captureMessage('An error occurred while loading the sync/forms directory!');
        });
        Ext.callback(_abort, _scope, [false, $jscomp$this.tr('An error occurred while loading the sync/forms directory!')]);
      });
    })['catch'](function(_err) {
      Sentry.withScope(function(_scope) {
        _scope.setExtra('getPublishedFormsError', _err);
        Sentry.captureMessage('An error occurred while syncing the forms!');
      });
      Ext.callback(_abort, _scope, [false, $jscomp$this.tr('An error occurred while syncing the forms!')]);
    });
  } else {
    Ext.callback(_next, _scope);
  }
}, saveForm:function(_formData, _callback, _store) {
  var $jscomp$this = this;
  var formDirectoryName = _formData.id.toString();
  var formFileName = _formData.version + '.json';
  this.getSyncFormsDirectory().then(function(_synFormsDirectory) {
    _synFormsDirectory.getDirectory(formDirectoryName, {create:true}, function(_formDirectory) {
      _formDirectory.getFile(formFileName, {create:true}, function(_file) {
        _file.createWriter(function(_writer) {
          _writer.onwriteend = Ext.bind(function() {
            delete _formData.formData;
            _store.add(_formData);
            cnconsult.Logger.log({prefix:'SyncForms-\x3esaveForm', message:'Created successfully the form file and saved the metaData in the storage!', dump:formDirectoryName + '/' + formFileName});
            _callback();
          }, $jscomp$this);
          _writer.write(_formData.formData);
        });
      }, function(_error) {
        cnconsult.Logger.log({prefix:'SyncForms-\x3esaveForm', message:'An error occurred while getting or creating the form file!', dump:formFileName});
        _callback();
      });
    }, function(_error) {
      cnconsult.Logger.log({prefix:'SyncForms-\x3esaveForm', message:'An error occurred while loading the form directory!', dump:formDirectoryName});
      _callback();
    });
  })['catch'](function(_error) {
    cnconsult.Logger.log({prefix:'SyncForms-\x3esaveForm', message:'An error occurred while loading the forms directory!', dump:formDirectoryName});
    _callback();
  });
}, getPublishedForms:function() {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    Ext.Ajax.request({url:$jscomp$this.master.getBackendUrl() + '/formclientsync/getPublishedForms', params:{syncSecret:$jscomp$this.storage.get('core:personalization:syncSecret'), deviceIdCode:$jscomp$this.master.deviceIdCode()}, success:function(_response) {
      var response = Ext.decode(_response.responseText, true);
      if (response && response.success) {
        _resolve(response.result.publishedFormsIdVersion);
      } else {
        _reject(response);
      }
    }, failure:function(_response) {
      _reject(_response);
    }, scope:$jscomp$this});
  });
}, downloadForms:function(_formIds) {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    Ext.Ajax.request({url:$jscomp$this.master.getBackendUrl() + '/formclientsync/downloadForms', params:{syncSecret:$jscomp$this.storage.get('core:personalization:syncSecret'), deviceIdCode:$jscomp$this.master.deviceIdCode(), formsIds:Ext.encode(_formIds)}, success:function(_response) {
      var response = Ext.decode(_response.responseText, true);
      if (response && response.success) {
        _resolve(response.result.forms);
      } else {
        _reject(response);
      }
    }, failure:function(_response) {
      _reject(_response);
    }, scope:$jscomp$this});
  });
}, getSyncFormsDirectory:function() {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    $jscomp$this.master.getSyncRoot().getDirectory('forms', {create:true}, _resolve, _reject);
  });
}, cleanup:function(_syncFormsDirEntry, _callback, _formsToDownload, _store) {
  var formIndex = _formsToDownload.findIndex(function(_formToDownload) {
    return _formToDownload.id.toString() === _syncFormsDirEntry.name;
  });
  var form = formIndex === -1 ? null : _formsToDownload[formIndex];
  var dirEmpty = true;
  _syncFormsDirEntry.createReader().readEntries(function(_formDirEntries) {
    Ext.Array.forEach(_formDirEntries, function(_formDirEntry) {
      if (_formDirEntry.name.match(/\d+_\d+\.json/)) {
        dirEmpty = false;
      } else {
        var index = _store.findBy(function(record) {
          return record.get('id') === parseInt(_syncFormsDirEntry.name) && record.get('version') === parseInt(_formDirEntry.name);
        });
        var record = _store.getAt(index);
        if (form && form.version + '.json' === _formDirEntry.name) {
          dirEmpty = false;
          if (record && record.get('customer')) {
            _formsToDownload.splice(formIndex, 1);
          }
        } else {
          if (record) {
            _store.remove(record);
          }
        }
      }
    });
    _callback();
  }, function(_error) {
    console.error('Error occurred when reading the entries of the directory ' + _syncFormsDirEntry.name + ' with: ', _error.code);
    _callback();
  });
}, getAllFilesFromDirectory:function(_directory) {
  return new Promise(function(_resolve, _reject) {
    _directory.createReader().readEntries(_resolve, function(_error) {
      console.error('Error occured when reading the entries of the directory ' + _directory.name + ' with: ', _error.code);
      _resolve([]);
    });
  });
}});
Ext.define('dilocsync.model.SyncReportMetaData', {extend:Ext.data.Model, identifier:'uuid', fields:[{name:'date', type:'date', dateFormat:'c'}, {name:'state', type:'string'}, {name:'reason', type:'string'}, {name:'reasonType', type:'string'}, {name:'formattedDate', type:'string', convert:function(_value, _record) {
  return Ext.Date.format(_record.get('date'), 'd.m. H:i:s');
}}]});
Ext.define('dilocsync.model.Tag', {extend:Ext.data.Model, fields:[{name:'id'}, {name:'customerId', type:'int', allowNull:true}, {name:'name', type:'string'}, {name:'isFavorite', type:'boolean'}, {name:'isImportant', type:'boolean'}, {name:'isPinned', type:'boolean'}, {name:'isAutoConfirm', type:'boolean'}, {name:'forFiles', type:'boolean'}, {name:'forDirectories', type:'boolean'}, {name:'isConfirmationRequired', type:'boolean'}, {name:'description', type:'string'}], idProperty:'id'});
Ext.define('dilocsync.model.SyncReportTreeItem', {extend:Ext.data.TreeModel, fields:[{name:'name', type:'string'}, {name:'path', type:'string'}, {name:'state', type:'string'}, {name:'type', type:'string'}, {name:'fileType', type:'string'}, {name:'checksum', type:'string'}, {name:'uuid', type:'string'}, {name:'unreadCount', type:'integer'}, {name:'title', type:'string'}, {name:'validFrom', type:'date'}, {name:'validTo', type:'date'}, {name:'visibleFrom', type:'date'}, {name:'visibleTo', type:'date'}, 
{name:'metaUpdate', type:'boolean', defaultValue:false}], hasMany:[{model:'dilocsync.model.Tag', name:'tags'}], decrementUnreadCount:function() {
  this.set('unreadCount', this.get('unreadCount') - 1);
  if (this.parentNode) {
    this.parentNode.decrementUnreadCount();
  }
}, privates:{callJoined:function(funcName, args) {
  var modifiedFieldNames = Ext.isArray(args) && args.length >= 1 ? args[0] : false;
  if (funcName === 'afterEdit' && modifiedFieldNames) {
    if (modifiedFieldNames.indexOf('state') !== -1) {
      if (this.parentNode) {
        this.parentNode.decrementUnreadCount();
      }
      this.notifyStore('changeStateOfRecord', this.get('state'));
    }
  }
  this.callParent(arguments);
}, notifyStore:function(fn) {
  var args = Ext.Array.clone(arguments);
  var store = this.getTreeStore();
  args[0] = this;
  if (store !== undefined && typeof store[fn] == 'function') {
    store[fn].apply(store, args);
  }
}}});
Ext.define('dilocsync.store.SyncReports', {extend:Ext.data.TreeStore, config:{syncReport:null, model:'dilocsync.model.SyncReportTreeItem', sortOrder:['folder', 'new', 'update', 'delete']}, constructor:function(_config) {
  var $jscomp$this = this;
  this.callParent(arguments);
  this.config.syncReport = _config.syncReport;
  if (_config.syncReport) {
    var reportSortOrder = _config.syncReport.getSortOrder();
    if (reportSortOrder && Ext.Array.difference(this.config.sortOrder, reportSortOrder).length === 0) {
      this.config.sortOrder = reportSortOrder;
    }
    this.setSorters({sorterFn:function(_record1, _record2) {
      var sortIndex1 = $jscomp$this.config.sortOrder.indexOf(_record1.get('type'));
      var sortIndex2 = $jscomp$this.config.sortOrder.indexOf(_record2.get('type'));
      return sortIndex1 - sortIndex2;
    }});
    this.setRoot(this.convertToSyncReportTreeItem(_config.syncReport.getReportData()));
  } else {
    cnconsult.Logger.log({prefix:'SyncReports-\x3econstructor', message:'Creating a SyncReports store without a SyncReport configured!', level:'warn'});
    this.setRoot({});
  }
}, convertToSyncReportTreeItem:function(_syncReportItem) {
  var syncReportTreeItem = {name:_syncReportItem.name, type:'folder', leaf:true}, childFolders = [], childFiles = [], i;
  if (_syncReportItem.folders && _syncReportItem.folders.length > 0) {
    for (i = 0; i < _syncReportItem.folders.length; i++) {
      childFolders.push(this.convertToSyncReportTreeItem(_syncReportItem.folders[i]));
    }
  }
  if (_syncReportItem.files && _syncReportItem.files.length > 0) {
    for (i = 0; i < _syncReportItem.files.length; i++) {
      childFiles.push(this.convertToSyncReportTreeItem(_syncReportItem.files[i]));
    }
  }
  if (_syncReportItem.path) {
    syncReportTreeItem.path = _syncReportItem.path;
  }
  if (_syncReportItem.state) {
    syncReportTreeItem.state = _syncReportItem.state;
  }
  if (_syncReportItem.type) {
    syncReportTreeItem.type = _syncReportItem.type;
  }
  if (_syncReportItem.checksum) {
    syncReportTreeItem.checksum = _syncReportItem.checksum;
  }
  if (_syncReportItem.uuid) {
    syncReportTreeItem.uuid = _syncReportItem.uuid;
  }
  if (_syncReportItem.validFrom) {
    syncReportTreeItem.validFrom = _syncReportItem.validFrom;
  }
  if (_syncReportItem.validTo) {
    syncReportTreeItem.validTo = _syncReportItem.validTo;
  }
  if (_syncReportItem.visibleFrom) {
    syncReportTreeItem.visibleFrom = _syncReportItem.visibleFrom;
  }
  if (_syncReportItem.visibleTo) {
    syncReportTreeItem.visibleTo = _syncReportItem.visibleTo;
  }
  if (_syncReportItem.tags) {
    syncReportTreeItem.tags = _syncReportItem.tags;
  }
  if (_syncReportItem.title) {
    syncReportTreeItem.title = _syncReportItem.title;
  }
  if (_syncReportItem.metaUpdate) {
    syncReportTreeItem.metaUpdate = _syncReportItem.metaUpdate;
  }
  if (_syncReportItem.path) {
    syncReportTreeItem.fileType = dilocsync.util.File.extension(_syncReportItem.path).toLowerCase();
  }
  if (syncReportTreeItem.type === 'folder') {
    syncReportTreeItem.unreadCount = this.config.syncReport.recursivelyCount(_syncReportItem);
  }
  if (childFolders.length > 0 || childFiles.length > 0) {
    syncReportTreeItem.leaf = false;
    syncReportTreeItem.children = childFolders.concat(childFiles);
  }
  return syncReportTreeItem;
}, changeStateOfRecord:function(_record, _newState) {
  if (this.config.syncReport) {
    this.config.syncReport.setFilePathState(_record.get('path'), _newState);
  }
}});
Ext.define('dilocsync.core.syncreport.SyncReport', {mixins:[Ext.mixin.Observable], config:{data:null}, reportData:null, reportTreeStore:null, date:null, state:'unread', reason:'', reasonType:'', wasHighPrioritySync:false, constructor:function(_config) {
  this.date = new Date;
  this.mixins.observable.constructor.call(this, _config);
}, getData:function() {
  return {date:Ext.Date.format(this.date, 'c'), state:this.state, report:this.reportData, reason:this.reason, reasonType:this.reasonType, wasHighPrioritySync:this.wasHighPrioritySync};
}, getReportData:function() {
  return this.reportData;
}, setData:function(_data) {
  if (_data.date) {
    this.date = new Date(_data.date);
  }
  if (_data.state) {
    this.state = _data.state;
  }
  if (_data.report) {
    this.reportData = _data.report;
  }
  if (_data.reason) {
    this.reason = _data.reason;
  }
  if (_data.reasonType) {
    this.reasonType = _data.reasonType;
  }
  if (_data.wasHighPrioritySync) {
    this.wasHighPrioritySync = _data.wasHighPrioritySync;
  }
}, getMetaData:function() {
  return Ext.create('dilocsync.model.SyncReportMetaData', {date:this.date, state:this.state, reason:this.reason, reasonType:this.reasonType, wasHighPrioritySync:this.wasHighPrioritySync});
}, getTreeStore:function() {
  if (!this.reportTreeStore) {
    this.reportTreeStore = Ext.create('dilocsync.store.SyncReports', {syncReport:this});
  }
  return this.reportTreeStore;
}, setFilePathState:function(_path, _state) {
  this.recursivelyFindFileByPath(this.reportData, _path, Ext.bind(function(_file, _newState) {
    if (_file.state !== _newState) {
      _file.state = _newState;
    }
  }, this, _state, true));
  this.syncReportChanged();
}, recursivelyFindFileByPath:function(_folder, _path, _callback) {
  if (_folder.path && _path.indexOf(_folder.path) !== -1) {
    if (_folder.files && _folder.files.length > 0) {
      for (var j = 0; j < _folder.files.length; j++) {
        if (_folder.files[j].path === _path) {
          _callback(_folder.files[j]);
        }
      }
    }
  }
  if (_folder.folders && _folder.folders.length > 0) {
    for (var i = 0; i < _folder.folders.length; i++) {
      this.recursivelyFindFileByPath(_folder.folders[i], _path, _callback);
    }
  }
}, recursivelyCallOnEveryFile:function(_folder, _callback) {
  if (_folder.files && _folder.files.length > 0) {
    for (var j = 0; j < _folder.files.length; j++) {
      _callback(_folder.files[j]);
    }
  }
  if (_folder.folders && _folder.folders.length > 0) {
    for (var i = 0; i < _folder.folders.length; i++) {
      this.recursivelyCallOnEveryFile(_folder.folders[i], _callback);
    }
  }
}, recursivelyCount:function(_folder) {
  var count = 0;
  if (_folder.files && _folder.files.length > 0) {
    for (var j = 0; j < _folder.files.length; j++) {
      if (_folder.files[j].state === 'unread') {
        count++;
      }
    }
  }
  if (_folder.folders && _folder.folders.length > 0) {
    for (var i = 0; i < _folder.folders.length; i++) {
      count = count + this.recursivelyCount(_folder.folders[i]);
    }
  }
  return count;
}, countUnreadFiles:function() {
  return this.recursivelyCount(this.reportData);
}, syncReportChanged:function() {
  var changedState = false;
  var unreadFilesCount = this.countUnreadFiles();
  if (unreadFilesCount === 0 && this.state === 'unread') {
    changedState = 'read';
  } else {
    if (unreadFilesCount !== 0 && this.state === 'read') {
      changedState = 'unread';
    }
  }
  if (changedState) {
    this.state = changedState;
  }
  this.fireEvent('syncreportchanged', this, changedState);
}, markAsRead:function() {
  this.recursivelyCallOnEveryFile(this.reportData, Ext.bind(function(_file, _newState) {
    if (_file.state !== _newState) {
      _file.state = _newState;
    }
  }, this, 'read', true));
  this.reportTreeStore = null;
  this.syncReportChanged();
}, getSortOrder:function() {
  var storage = dilocsync.core.Master.getStorage();
  var sortOrder = storage.get('syncreport:sortOrder');
  return Ext.isArray(sortOrder) ? sortOrder : null;
}});
Ext.define('dilocsync.core.syncreport.Generator', {config:{syncReportConfig:''}, reportAlmanac:null, syncReportData:null, reportFoldersByPath:null, reportEmpty:true, constructor:function(_config) {
  this.initConfig(_config);
}, startBuildingNewSyncReport:function(_almanac) {
  cnconsult.Logger.log({prefix:'Generator-\x3estartBuildingNewSyncReport', message:'Create a new sync report.'});
  this.reportEmpty = true;
  this.reportAlmanac = _almanac;
  if (Ext.isArray(this.reportAlmanac)) {
    Ext.Array.each(this.reportAlmanac, function(_almanac) {
      _almanac.on('fileadded', this.onFileAdded, this);
      _almanac.on('fileupdated', this.onFileUpdated, this);
      _almanac.on('filedeleted', this.onFileDeleted, this);
    }, this);
  } else {
    this.reportAlmanac.on('fileadded', this.onFileAdded, this);
    this.reportAlmanac.on('fileupdated', this.onFileUpdated, this);
    this.reportAlmanac.on('filedeleted', this.onFileDeleted, this);
  }
  if (Ext.isObject(this.config.syncReportConfig)) {
    this.reportFoldersByPath = {};
    var reportDataTree = {name:'root', expanded:true};
    reportDataTree.folders = this.buildTree(this.config.syncReportConfig.directories);
    this.syncReportData = {date:new Date, state:'unread', report:reportDataTree, reason:'', reasonType:''};
    return true;
  } else {
    return false;
  }
}, finishSyncReport:function(hasHighPriorityFiles) {
  if (this.reportAlmanac && this.syncReportData && !this.reportEmpty) {
    if (Ext.isArray(this.reportAlmanac)) {
      Ext.Array.each(this.reportAlmanac, function(_almanac) {
        _almanac.un('fileadded', this.onFileAdded, this);
        _almanac.un('fileupdated', this.onFileUpdated, this);
        _almanac.un('filedeleted', this.onFileDeleted, this);
      }, this);
    } else {
      this.reportAlmanac.un('fileadded', this.onFileAdded, this);
      this.reportAlmanac.un('fileupdated', this.onFileUpdated, this);
      this.reportAlmanac.un('filedeleted', this.onFileDeleted, this);
    }
    if (hasHighPriorityFiles) {
      this.syncReportData.wasHighPrioritySync = hasHighPriorityFiles;
    }
    var syncReport = Ext.create('dilocsync.core.syncreport.SyncReport', {data:this.syncReportData});
    this.syncReportData = null;
    this.reportFoldersByPath = null;
    return syncReport;
  } else {
    return null;
  }
}, buildTree:function(_currentSubFolderConfigArray) {
  var folderArray = [];
  for (var i = 0; i < _currentSubFolderConfigArray.length; i++) {
    var folderConfig = _currentSubFolderConfigArray[i], folder = {name:folderConfig.name, expanded:folderConfig.expanded};
    if (folderConfig.path) {
      folder.path = folderConfig.path;
      folder.files = [];
      this.reportFoldersByPath[folderConfig.path] = folder;
    }
    if (folderConfig.directories && folderConfig.directories.length > 0) {
      folder.folders = this.buildTree(folderConfig.directories);
    }
    folderArray.push(folder);
  }
  return folderArray;
}, onFileAdded:function(_path, _file, _properties, _checksum) {
  if (this.syncReportData) {
    cnconsult.Logger.log({prefix:'Generator-\x3eonFileAdded', message:'Add file ' + _path, dump:_file});
    var now = Date.now();
    if (_properties && (_properties.hasOwnProperty('visibleFrom') && _properties.visibleFrom || _properties.hasOwnProperty('visibleTo') && _properties.visibleTo)) {
      if (_properties.hasOwnProperty('visibleFrom') && _properties.visibleFrom) {
        var visibleFrom = new Date(_properties.visibleFrom);
        if (now < Ext.Number.parseInt(Ext.Date.format(visibleFrom, 'time'))) {
          cnconsult.Logger.log({prefix:'Generator-\x3eonFileAdded', message:'DO NOT add file to SyncReport because it is not yet visible for the user!', level:'info'});
          return;
        }
      }
      if (_properties.hasOwnProperty('visibleTo') && _properties.visibleTo) {
        var visibleTo = new Date(_properties.visibleTo);
        if (now > Ext.Number.parseInt(Ext.Date.format(visibleTo, 'time'))) {
          cnconsult.Logger.log({prefix:'Generator-\x3eonFileAdded', message:'DO NOT add file to SyncReport because it is not visible anymore!', level:'info'});
          return;
        }
      }
    }
    var folders = this.findFolderByPath(_path);
    var uuid = null;
    if (_properties && _properties.hasOwnProperty('uuid') && _properties.uuid) {
      uuid = _properties.uuid;
    }
    for (var i = 0; i < folders.length; i++) {
      var folder = folders[i];
      this.reportEmpty = false;
      folder.files.push({name:_file, path:_path + '/' + _file, checksum:_checksum, state:'unread', type:'new', uuid:uuid, title:_properties && _properties.hasOwnProperty('title') ? _properties.title : null, validFrom:_properties && _properties.hasOwnProperty('validFrom') ? _properties.validFrom : null, validTo:_properties && _properties.hasOwnProperty('validTo') ? _properties.validTo : null, visibleFrom:_properties && _properties.hasOwnProperty('visibleFrom') ? _properties.visibleFrom : null, visibleTo:_properties && 
      _properties.hasOwnProperty('visibleTo') ? _properties.visibleTo : null, tags:_properties && _properties.hasOwnProperty('tags') ? _properties.tags : null});
    }
  }
}, onFileUpdated:function(_path, _file, _data, _checksum, _metaUpdate) {
  if (this.syncReportData) {
    cnconsult.Logger.log({prefix:'Generator-\x3eonFileUpdated', message:'updated file ' + _path, dump:_file});
    var folders = this.findFolderByPath(_path);
    var checksum, uuid, title, validFrom, validTo, visibleFrom, visibleTo, tags;
    if (Ext.isObject(_data)) {
      checksum = _data.hasOwnProperty('checksum') ? _data.checksum : null;
      uuid = _data.hasOwnProperty('uuid') ? _data.uuid : null;
      title = _data.hasOwnProperty('title') ? _data.title : null;
      validFrom = _data.hasOwnProperty('validFrom') ? _data.validFrom : null;
      validTo = _data.hasOwnProperty('validTo') ? _data.validTo : null;
      visibleFrom = _data.hasOwnProperty('visibleFrom') ? _data.visibleFrom : null;
      visibleTo = _data.hasOwnProperty('visibleTo') ? _data.visibleTo : null;
      tags = _data.hasOwnProperty('tags') ? _data.tags : null;
    } else {
      checksum = _data;
    }
    for (var i = 0; i < folders.length; i++) {
      var folder = folders[i];
      this.reportEmpty = false;
      folder.files.push({name:_file, path:_path + '/' + _file, checksum:checksum, state:'unread', type:'update', uuid:uuid, title:title, validFrom:validFrom, validTo:validTo, visibleFrom:visibleFrom, visibleTo:visibleTo, tags:tags, metaUpdate:_metaUpdate ? _metaUpdate : false});
    }
  }
}, onFileDeleted:function(_path, _file) {
  if (this.syncReportData) {
    cnconsult.Logger.log({prefix:'Generator-\x3eonFileDeleted', message:'File deleted: ' + _path, dump:_file});
    var folders = this.findFolderByPath(_path);
    for (var i = 0; i < folders.length; i++) {
      var folder = folders[i];
      this.reportEmpty = false;
      folder.files.push({name:_file, path:_path + '/' + _file, state:'unread', type:'delete'});
    }
  }
}, findFolderByPath:function(_path) {
  var foundFolders = [], path = _path, reportPath;
  if (path[0] === '/') {
    path = path.substring(1);
  }
  if (!Ext.String.endsWith(path, '/')) {
    path += '/';
  }
  if (Ext.String.startsWith(path, 'userfilebox/')) {
    path = 'data/' + path;
  }
  for (reportPath in this.reportFoldersByPath) {
    if (path.indexOf(reportPath) === 0) {
      foundFolders.push(this.reportFoldersByPath[reportPath]);
    }
  }
  return foundFolders;
}});
Ext.define('dilocsync.core.syncreport.ConfigLoader', {mixins:[Ext.mixin.Observable], config:{personalisationData:null, fileSystem:null, syncReportConfigFile:'', storage:null}, syncReportConfig:null, normalizer:null, constructor:function(_config) {
  this.mixins.observable.constructor.call(this, _config);
  this.storage = this.config.storage;
}, loadConfigFromFile:function() {
  var configFileName = this.config.syncReportConfigFile, master = dilocsync.core.Master, configFilePath, almanac, almanacFile;
  if (this.config.fileSystem && configFileName && configFileName !== '') {
    almanac = master.getAlmanacForPath('system');
    if (almanac) {
      almanacFile = almanac.getRootDirectory().files[configFileName];
      if (almanacFile) {
        configFilePath = 'sync/fs-data/' + almanacFile.checksum + '.' + dilocsync.util.File.extension(configFileName).toLowerCase();
      } else {
        console.warn('Error loading sync report config! No almanac file found for given sync report config file name!', configFileName, almanac);
      }
    } else {
      console.warn('Error loading sync report config! No system almanac found.');
    }
    if (configFilePath) {
      this.config.fileSystem.root.getFile(configFilePath, {create:false, exclusive:false}, Ext.bind(function(_fileEntry) {
        _fileEntry.file(Ext.bind(function(_file) {
          var reader = new FileReader;
          reader.onloadend = Ext.bind(function(_event) {
            try {
              var config = Ext.decode(_event.target.result);
              if (config) {
                this.syncReportConfig = this.normalizeConfig(config);
                if (this.syncReportConfig.showLastReports) {
                  this.storage.set('syncreport:showLastReports', this.syncReportConfig.showLastReports);
                }
                if (this.syncReportConfig.sortOrder) {
                  this.storage.set('syncreport:sortOrder', this.syncReportConfig.sortOrder);
                } else {
                  this.storage.remove('syncreport:sortOrder');
                }
                console.log('## SYNC REPORT CONFIG LOADED', this.syncReportConfig);
                cnconsult.Logger.log({prefix:'ConfigLoader-\x3eloadConfigFromFile', message:'Sync report config loaded!', dump:this.syncReportConfig});
                this.fireEvent('configloaded');
              } else {
                cnconsult.Logger.log({prefix:'ConfigLoader-\x3eloadConfigFromFile', message:'sync-report contains no truthy json!', level:'error'});
                this.fireEvent('loadingconfigfailed');
              }
            } catch (e$71) {
              cnconsult.Logger.log({prefix:'ConfigLoader-\x3eloadConfigFromFile', message:'Caught exception while parsing syncreport config.', level:'error', catchedError:e$71, useSentry:true});
              this.fireEvent('loadingconfigfailed');
            }
          }, this);
          reader.readAsText(_file);
        }, this));
      }, this), Ext.bind(function() {
        cnconsult.Logger.log({prefix:'ConfigLoader-\x3eloadConfigFromFile', message:'Error opening sync-report-config', level:'error', dump:arguments});
        this.fireEvent('loadingconfigfailed');
      }, this));
    } else {
      cnconsult.Logger.log({prefix:'ConfigLoader-\x3eloadConfigFromFile', message:"Config file path couldn't be loaded!", level:'warn'});
      this.fireEvent('loadingconfigfailed');
    }
  }
}, normalizeConfig:function(_config) {
  if (this.config.personalisationData) {
    try {
      var normalizer = Ext.create('dilocsync.core.IdentityNormalizer', this.config.personalisationData);
      return normalizer.normalize(_config);
    } catch (e$72) {
      return _config;
    }
  } else {
    return _config;
  }
}, getSyncReportConfig:function() {
  return this.syncReportConfig;
}});
Ext.define('dilocsync.core.syncengine.tasks.db.BuildSyncReportGenerator', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, abortCallback:null, callbackScope:null, nextCallback:null, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Preparing generation of sync report...'), 0, 0, null);
  this.nextCallback = _next;
  this.abortCallback = _abort;
  this.callbackScope = _scope;
  var identity = this.master.getIdentity();
  if (identity.options && identity.options.syncReportConfig && this.getStorage().get('core:syncengine:lastSyncTimestamp', false) !== false) {
    cnconsult.Logger.log({prefix:'BuildSyncReportGenerator-\x3eexecute', message:'Create SyncReportConfigLoader, fileSystem'});
    var syncReportConfigLoader = Ext.create('dilocsync.core.syncreport.ConfigLoader', {personalisationData:this.master.getPersonalization().getData(), fileSystem:this.master.getFileSystem(), syncReportConfigFile:identity.options.syncReportConfig, storage:this.storage});
    cnconsult.Logger.log({prefix:'BuildSyncReportGenerator-\x3eexecute', message:'SyncReportConfigLoader created'});
    syncReportConfigLoader.on('configloaded', Ext.bind(this.onConfigLoaded, this, [syncReportConfigLoader, identity], false), this, {single:true});
    syncReportConfigLoader.on('loadingconfigfailed', this.onLoadingConfigFailed, this, {single:true});
    syncReportConfigLoader.loadConfigFromFile();
  } else {
    Ext.callback(_next, _scope);
  }
}, onConfigLoaded:function(_syncReportConfigLoader, _identity) {
  cnconsult.Logger.log({prefix:'BuildSyncReportGenerator-\x3eonConfigLoaded', message:'config loaded!'});
  var syncReportConfigObject = _syncReportConfigLoader.getSyncReportConfig();
  cnconsult.Logger.log({prefix:'BuildSyncReportGenerator-\x3eonConfigLoaded', message:'create SyncReportGenerator with this identity', dump:{identity:_identity, syncReportConfigObject:syncReportConfigObject}});
  var syncReportGenerator = Ext.create('dilocsync.core.syncreport.Generator', {syncEngine:this, syncReportConfig:syncReportConfigObject});
  this.syncData.setSyncReportGenerator(syncReportGenerator);
  var almanacs = this.syncData.getLocalAlmanacs();
  syncReportGenerator.startBuildingNewSyncReport(almanacs);
  Ext.callback(this.nextCallback, this.callbackScope);
}, onLoadingConfigFailed:function() {
  cnconsult.Logger.log({prefix:'BuildSyncReportGenerator-\x3eonLoadingConfigFailed', message:'config load failed'});
  Ext.callback(this.nextCallback, this.callbackScope);
}});
Ext.define('dilocsync.core.SyncEngine', {extend:dilocsync.core.SyncEngineInterface, mixins:[Ext.mixin.Observable, cnconsult.Translatable], lastSyncTimestamp:function() {
  var dateStr = this.storage.get('core:syncengine:lastSyncTimestamp', null);
  if (dateStr) {
    return Ext.Date.parse(dateStr, 'c');
  } else {
    return null;
  }
}, documentRepository:null, master:null, storage:null, syncData:null, aborted:false, syncTasks:null, afterFileSyncTasks:null, syncProgress:0, progressPercentageForPreSyncTasks:20, progressPercentageForSyncingFiles:75, progressPercentageForAfterSyncTasks:5, syncing:false, lastSyncFromAutoSync:false, runningTask:null, config:{master:null, storage:null, documentRepository:null}, constructor:function(_config) {
  this.mixins.observable.constructor.call(this, _config);
  this.storage = this.config.storage;
  this.master = this.config.master;
  this.documentRepository = this.config.documentRepository;
  this.syncTasks = ['ConnectionChecker', 'PersonalizationChecker', 'StolenChecker', 'db.PreSync', 'SyncRouteKnowledgeLines', 'SyncGeoStationList', 'SyncRides', 'SyncUserActivities', 'Depersonalization', 'OpenExternalUrl', 'RegistryUpdates', 'db.FetchAlmanacs', 'db.MigrateData', 'db.GenerateSyncActions', 'db.Favorites', 'db.Dossiers', 'db.ImportantDocuments', 'db.BuildSyncReportGenerator', 'db.PrepareQueues', 'db.DownloadSizeChecker', 'db.SynchronizeFiles', 'SaveSyncReport'];
  this.afterFileSyncTasks = ['db.SyncFinish', 'db.CheckForUndeletedFiles', 'db.BuildKnowledgeAlmanac', 'db.IndexFiles', 'UpdateLastSyncTime', 'IdentityChangeChecker', 'db.SyncConfirmations', 'db.SyncForms', 'db.SyncCompletedForms', 'db.SyncLocomotionTypes', 'db.SyncTokens'];
}, abortSync:function() {
  cnconsult.Logger.log({prefix:'SyncEngine-\x3eabortSync', message:'Aborts the synchronization'});
  this.aborted = true;
  if (this.runningTask) {
    this.runningTask.abort();
  }
  if (this.runningTask.$className !== 'dilocsync.core.syncengine.tasks.SaveSyncReport') {
    var syncReportGenerator = this.syncData.getSyncReportGenerator();
    if (syncReportGenerator) {
      this.saveSyncReport(syncReportGenerator, this.tr('Sync was aborted'), 'abort');
    }
  }
  this.fireEvent('syncaborted', this);
}, startSync:function(_autoSync) {
  var master = dilocsync.core.Master, backendUrl = master.getBackendUrl(), storage = master.getStorage(), initialSync = !!storage.get('core:syncengine:lastSyncTimeStamp', null), reason = 'manual';
  if (initialSync) {
    reason = 'initial';
  } else {
    if (_autoSync) {
      reason = 'auto';
    }
  }
  if (this.isSyncing()) {
    console.log('SyncEngine-\x3estartSync(' + reason + ') was NOT started because a other sync is already running!');
    return;
  }
  this.syncing = true;
  Ext.Ajax.request({url:backendUrl + '/syncng/preCheck', params:{syncReason:reason, syncSecret:storage.get('core:personalization:syncSecret'), version:master.version}, success:function(_response) {
    try {
      var response = Ext.decode(_response.responseText);
      var syncConfig = response.result || response.data;
      if (syncConfig && response.success) {
        if (syncConfig.hasOwnProperty('doSync') && syncConfig.doSync) {
          storage.set('core:syncAlgorithm', 'db-based');
          if (!storage.get('core:syncengine:lastSyncTimestamp', false)) {
            master.getStorage().set('sync4DataMigrated', true);
          }
          master.getSyncRoot().getDirectory('fs-data', {create:true}, Ext.bind(function(_fsDataDirectory) {
            console.log('fs-data directory exists, continuing...');
            master.detectBackendUrl((new URL(backendUrl)).host, true, function() {
              this.beforeExecutingSyncTasks(_autoSync);
            }, this);
          }, this));
        } else {
          if (syncConfig.hasOwnProperty('minimumVersionRequired') && syncConfig.minimumVersionRequired) {
            this.syncFinished(false, this.tr('Minimum app version %1 required for syncing. You are currently on version %2.').arg(syncConfig.minimumVersionRequired).arg(master.version));
          } else {
            if (syncConfig.hasOwnProperty('showMessage') && syncConfig.showMessage) {
              this.syncFinished(false, syncConfig.showMessage);
            } else {
              this.syncFinished(false, this.tr('Server is currently not available for syncing!'));
            }
          }
        }
      } else {
        this.syncFinished(false, syncConfig.backendError);
      }
    } catch (error) {
      console.log('startSync-\x3esuccess catch error', error);
      this.syncFinished(false, this.tr('Server is currently not available for syncing!'));
    }
  }, failure:function() {
    this.syncFinished(false, this.tr('Server is currently not available for syncing!'));
  }, scope:this});
}, beforeExecutingSyncTasks:function(_autoSync) {
  console.log('SyncEngineNG - startSync()');
  this.lastSyncFromAutoSync = _autoSync === true;
  this.syncProgress = 0;
  this.aborted = false;
  this.syncData = Ext.create('dilocsync.core.syncengine.SyncData');
  if (this.lastSyncFromAutoSync) {
    this.syncData.setStartedFromAutoSync();
  }
  this.fireEvent('syncstarted');
  this.executeSyncTasks();
}, executeSyncTasks:function() {
  var i = 0;
  function loadNextSyncTask() {
    if (!this.aborted) {
      if (i < this.syncTasks.length) {
        cnconsult.Logger.log({prefix:'SyncEngine-\x3eexecuteSyncTasks-\x3eloadNextSyncTask', message:'Do SyncTask: ' + this.syncTasks[i]});
        this.runningTask = Ext.create('dilocsync.core.syncengine.tasks.' + this.syncTasks[i], {master:this.master, storage:this.storage, syncData:this.syncData, documentRepository:this.documentRepository});
        this.runningTask.on('syncprogress', this.onSyncProgressEvent, this);
        this.runningTask.execute(function() {
          i++;
          loadNextSyncTask.apply(this);
        }, this.syncProgressFinished, this);
      } else {
        this.syncProgressFinished(true);
      }
    } else {
      this.syncProgressFinished(false, 'noalert');
    }
  }
  loadNextSyncTask.apply(this);
}, syncProgressFinished:function(_success, _errorMessage) {
  if (_success) {
    this.executeAfterFileSyncTasks(_success, _errorMessage, this.syncFinished, this);
  } else {
    this.syncFinished(_success, _errorMessage);
  }
}, executeAfterFileSyncTasks:function(_success, _errorMessage, _callback, _scope) {
  var i = 0;
  function loadNextAfterFileSyncTask() {
    if (!this.aborted) {
      if (i < this.afterFileSyncTasks.length) {
        cnconsult.Logger.log({prefix:'SyncEngine-\x3eexecuteAfterFileSyncTasks-\x3eloadNextAfterFileSyncTask', message:'Do AfterSyncTask: ' + this.afterFileSyncTasks[i]});
        this.runningTask = Ext.create('dilocsync.core.syncengine.tasks.' + this.afterFileSyncTasks[i], {master:this.master, storage:this.storage, syncData:this.syncData});
        this.runningTask.on('syncprogress', this.onAfterFileSyncProgressEvent, this);
        this.runningTask.on('identitychanged', function() {
          this.fireEvent('identitychanged');
        }, this);
        this.runningTask.execute(function() {
          i++;
          loadNextAfterFileSyncTask.apply(this);
        }, this.syncProgressFinished, this);
      } else {
        Ext.callback(_callback, _scope, [_success, _errorMessage]);
      }
    }
  }
  loadNextAfterFileSyncTask.apply(this);
}, onSyncProgressEvent:function(_message, _progress, _subProgress, _remainingDownloadTime, _isSyncingFiles) {
  if (_isSyncingFiles === true) {
    this.syncProgress = this.progressPercentageForPreSyncTasks + _progress / 100 * this.progressPercentageForSyncingFiles;
  } else {
    this.syncProgress = this.syncProgress + this.progressPercentageForPreSyncTasks / this.syncTasks.length;
  }
  var subProgress = 0;
  if (_subProgress) {
    subProgress = _subProgress;
  }
  this.fireEvent('syncprogress', _message, this.syncProgress, subProgress, _remainingDownloadTime);
}, onAfterFileSyncProgressEvent:function(_message, _progress, _subProgress, _remainingDownloadTime) {
  if (this.syncProgress < 100 - this.progressPercentageForAfterSyncTasks) {
    this.syncProgress = 100 - this.progressPercentageForAfterSyncTasks;
  }
  this.syncProgress = this.syncProgress + this.progressPercentageForAfterSyncTasks / this.afterFileSyncTasks.length;
  var subProgress = 0;
  if (_subProgress) {
    subProgress = _subProgress;
  }
  this.fireEvent('syncprogress', _message, this.syncProgress, subProgress, _remainingDownloadTime);
}, syncFinished:function(_success, _errorMessage) {
  cnconsult.Logger.log({prefix:'SyncEngine-\x3esyncFinished', message:'Success: ' + _success + ', Error message: ' + _errorMessage});
  var generator;
  this.syncing = false;
  if (this.syncData && this.syncData.hasDeviceBeenStolen()) {
    dilocsync.core.Master.resetDevice();
  }
  var syncReportAvailable = false;
  if (this.syncData && this.syncData.isSyncReportAvailable()) {
    syncReportAvailable = true;
  }
  var reloadRequired = false;
  if (this.syncData && this.syncData.isReloadRequired()) {
    reloadRequired = true;
  }
  var syncReportDirectories = null;
  if (_success) {
    generator = this.syncData.getSyncReportGenerator();
    if (generator && generator.getSyncReportConfig() && generator.getSyncReportConfig().hasOwnProperty('directories')) {
      syncReportDirectories = generator.getSyncReportConfig().directories;
    }
  }
  if (!_success && generator) {
    this.saveSyncReport(generator, _errorMessage, 'error');
  }
  this.fireEvent('syncfinished', _success, _errorMessage, syncReportAvailable, reloadRequired, syncReportDirectories);
  if (this.syncData && this.syncData.getRegistryUpdated()) {
    Ext.fireEvent('registryUpdated');
  }
  if (this.syncData && this.syncData.getPasswordChangeRequired()) {
    Ext.fireEvent('passwordChangeRequired');
  }
  if (this.syncData && this.syncData.getMultiUserSettingsChanged()) {
    Ext.fireEvent('multiUserSettingsChanged');
  }
  delete this.syncData;
}, isSyncing:function() {
  return this.syncing;
}, isAborted:function() {
  return this.aborted;
}, wasLastSyncFromAutoSync:function() {
  return this.lastSyncFromAutoSync;
}, saveSyncReport:function(_syncReportGenerator, _reason, _reasonType) {
  var hasHighPriorityFiles = this.syncData.getHasHighPriorityFiles(), syncReport;
  if (_syncReportGenerator && _syncReportGenerator.hasOwnProperty('syncReportData') && _syncReportGenerator.syncReportData) {
    _syncReportGenerator.syncReportData.reason = _reason;
    _syncReportGenerator.syncReportData.reasonType = _reasonType;
  }
  syncReport = _syncReportGenerator.finishSyncReport(hasHighPriorityFiles);
  if (syncReport) {
    var syncReportStorage = this.master.getSyncReportStorage();
    syncReportStorage.saveReport(syncReport);
    this.syncData.setSyncReportAvailable();
  }
}});
Ext.define('dilocsync.core.syncreport.Storage', {mixins:[Ext.mixin.Observable], config:{applicationStorage:null, syncReportStorageKeyPrefix:'syncreport:', deleteReportsThreshold:-1}, syncReportCollection:null, syncReportMetaCollection:null, unreadSyncReports:0, constructor:function(_config) {
  this.syncReportCollection = Ext.create('Ext.util.MixedCollection');
  this.syncReportMetaCollection = Ext.create('Ext.util.MixedCollection');
  this.mixins.observable.constructor.call(this, _config);
  this.buildSyncReportMetaStorageFromApplicationStorage();
  this.syncReportMetaCollection.on('add', this.onSyncReportMetaCollectionChanged, this);
  this.syncReportMetaCollection.on('replace', this.onSyncReportMetaCollectionChanged, this);
  this.syncReportMetaCollection.on('remove', this.onSyncReportMetaCollectionChanged, this);
  if (this.getApplicationStorage()) {
    var lastReportsThreshold = this.getApplicationStorage().get('syncreport:showLastReports', null);
    if (lastReportsThreshold && lastReportsThreshold >= 0) {
      this.setDeleteReportsThreshold(lastReportsThreshold);
      this.cleanup();
    }
  }
}, buildSyncReportMetaStorageFromApplicationStorage:function() {
  if (this.getApplicationStorage()) {
    var syncReportMetaData, key;
    this.syncReportMetaStorageData = this.getApplicationStorage().get(this.getSyncReportStorageKeyPrefix() + 'metadata');
    if (!Ext.isArray(this.syncReportMetaStorageData)) {
      this.syncReportMetaStorageData = [];
    }
    for (var i = 0; i < this.syncReportMetaStorageData.length; i++) {
      syncReportMetaData = Ext.create('dilocsync.model.SyncReportMetaData', this.syncReportMetaStorageData[i]);
      key = Ext.Date.format(syncReportMetaData.get('date'), 'c');
      if (syncReportMetaData.get('state') === 'unread') {
        this.increaseUnread(true);
      }
      this.syncReportMetaCollection.add(key, syncReportMetaData);
    }
  } else {
    this.syncReportMetaStorageData = [];
  }
}, cleanup:function() {
  var deleteReportsThreshold = this.getDeleteReportsThreshold();
  if (!deleteReportsThreshold || deleteReportsThreshold < 0) {
    return false;
  }
  this.syncReportMetaCollection.sortByKey('DESC');
  this.syncReportMetaCollection.each(function(_syncReportMetaData, _i) {
    if (_i >= deleteReportsThreshold) {
      this.deleteReport(_syncReportMetaData);
    }
  }, this);
  return true;
}, deleteAllReports:function() {
  this.syncReportMetaCollection.sortByKey('DESC');
  this.syncReportMetaCollection.each(function(_syncReportMetaData, _i) {
    this.deleteReport(_syncReportMetaData);
  }, this);
  return true;
}, onSyncReportMetaCollectionChanged:function() {
  var metaData = [];
  this.syncReportMetaCollection.each(function(_syncReportMetaData, _i) {
    var data = _syncReportMetaData.getData();
    metaData.push(data);
  }, this);
  if (this.getApplicationStorage()) {
    this.getApplicationStorage().set(this.getSyncReportStorageKeyPrefix() + 'metadata', metaData);
  }
}, saveReport:function(_syncReport) {
  var syncReportData = _syncReport.getData(), syncReportMetaData = _syncReport.getMetaData(), key = Ext.Date.format(syncReportMetaData.get('date'), 'c');
  if (this.syncReportMetaCollection.containsKey(key)) {
    this.syncReportMetaCollection.replace(key, syncReportMetaData);
    this.syncReportCollection.replace(key, _syncReport);
  } else {
    if (syncReportMetaData.get('state') === 'unread') {
      this.increaseUnread();
    }
    this.syncReportMetaCollection.add(key, syncReportMetaData);
    this.syncReportCollection.add(key, _syncReport);
    _syncReport.on('syncreportchanged', this.onSyncReportChanged, this);
  }
  if (this.getApplicationStorage()) {
    this.getApplicationStorage().set(this.getSyncReportStorageKeyPrefix() + 'reportdata:' + key, syncReportData);
  }
}, onSyncReportChanged:function(_syncReport, _newReportState) {
  this.saveReport(_syncReport);
  if (_newReportState && _newReportState === 'read') {
    this.decreaseUnread();
  } else {
    if (_newReportState && _newReportState === 'unread') {
      this.increaseUnread();
    }
  }
}, deleteReport:function(_syncReportMetaData) {
  var key = Ext.Date.format(_syncReportMetaData.get('date'), 'c');
  if (_syncReportMetaData.get('state') === 'unread') {
    cnconsult.Logger.log({prefix:'Storage-\x3edeleteReport', message:'decrease unread'});
    this.decreaseUnread();
  }
  if (this.syncReportCollection.containsKey(key)) {
    cnconsult.Logger.log({prefix:'Storage-\x3edeleteReport', message:'syncReportCollection removeAtKey: ' + key});
    this.syncReportCollection.removeAtKey(key);
  }
  if (this.syncReportMetaCollection.containsKey(key)) {
    cnconsult.Logger.log({prefix:'Storage-\x3edeleteReport', message:'syncReportMetaCollection removeAtKey: ' + key});
    this.syncReportMetaCollection.removeAtKey(key);
  }
  if (this.getApplicationStorage()) {
    cnconsult.Logger.log({prefix:'Storage-\x3edeleteReport', message:'applicationStorage remove report'});
    this.getApplicationStorage().remove(this.getSyncReportStorageKeyPrefix() + 'reportdata:' + key);
  }
}, loadReport:function(_syncReportMetaData) {
  var date = _syncReportMetaData.get('date');
  var key = Ext.Date.format(_syncReportMetaData.get('date'), 'c'), syncReport = this.syncReportCollection.get(key);
  cnconsult.Logger.log({prefix:'Storage-\x3eloadReport', message:'date of syncreportmetadata to load is: ' + date});
  if (!syncReport && this.getApplicationStorage()) {
    var syncReportData = this.getApplicationStorage().get(this.getSyncReportStorageKeyPrefix() + 'reportdata:' + key);
    if (!syncReportData) {
      return false;
    }
    syncReport = Ext.create('dilocsync.core.syncreport.SyncReport', {data:syncReportData});
    syncReport.on('syncreportchanged', this.onSyncReportChanged, this);
    this.syncReportCollection.add(key, syncReport);
  } else {
    if (!syncReport) {
      return false;
    }
  }
  return syncReport;
}, countUnreadReports:function() {
  return this.unreadSyncReports;
}, getLastReportMetaData:function(_limit, _justUnread) {
  var arrayToReturn = [];
  this.syncReportMetaCollection.sortByKey('DESC');
  if (!_limit) {
    _limit = this.syncReportMetaCollection.length;
  }
  this.syncReportMetaCollection.each(function(_item, _index) {
    if (_justUnread) {
      if (arrayToReturn.length < _limit) {
        if (_item.get('state') === 'unread') {
          arrayToReturn.push(_item);
        }
      } else {
        return false;
      }
    } else {
      if (_index < _limit) {
        arrayToReturn.push(_item);
      } else {
        if (_item.get('state') === 'unread') {
          arrayToReturn.push(_item);
        }
      }
    }
  }, this);
  return arrayToReturn;
}, increaseUnread:function(_silent) {
  this.unreadSyncReports++;
  cnconsult.Logger.log({prefix:'Storage-\x3eincreaseUnread', message:'fire event: unread count changed to ' + this.unreadSyncReports});
  if (!_silent) {
    this.updateBadge();
  }
}, decreaseUnread:function(_silent) {
  this.unreadSyncReports--;
  cnconsult.Logger.log({prefix:'Storage-\x3edecreaseUnread', message:'fire event: unread count changed to ' + this.unreadSyncReports});
  if (!_silent) {
    this.updateBadge();
  }
}, updateBadge:function() {
  var menuItem = Ext.getStore('menuItems').findRecord('view', 'syncreports');
  if (menuItem) {
    menuItem.set('badgeText', this.unreadSyncReports || '');
  }
}});
Ext.define('dilocsync.util.Platform', {singleton:true, getPlatform:function() {
  return device.platform;
}, getVersion:function() {
  return device.version;
}, is:function(_platformNames) {
  var isPlatform = false;
  for (var $jscomp$iter$6 = $jscomp.makeIterator(_platformNames), $jscomp$key$platformName = $jscomp$iter$6.next(); !$jscomp$key$platformName.done; $jscomp$key$platformName = $jscomp$iter$6.next()) {
    var platformName = $jscomp$key$platformName.value;
    {
      switch(platformName) {
        case 'android':
          isPlatform = this.isAndroid();
          break;
        case 'ios':
          isPlatform = this.isIOS();
          break;
        case 'windows':
          isPlatform = this.isWindows();
          break;
      }
      if (isPlatform) {
        break;
      }
    }
  }
  return isPlatform;
}, isAndroid:function() {
  return this.isPlatform('Android');
}, isIOS:function() {
  return this.isPlatform('iOS');
}, isWindows:function() {
  return this.isPlatform('windows') || this.isPlatform('windows8');
}, isPhonegap:function() {
  return typeof device !== 'undefined';
}, supportsFullTextSearch:function() {
  return this.isIOS() || this.isAndroid();
}, supportsOnlyExternalFileOpen:function() {
  return this.isWindows();
}, supportsOpenWith:function() {
  return this.isIOS() || this.isAndroid();
}, supportsGpsTracking:function() {
  return this.isIOS() || this.isAndroid();
}, supportsVersionNumberPlugin:function() {
  return this.isIOS() || this.isAndroid();
}, isPlatform:function(_platformName) {
  return this.isPhonegap() ? this.getPlatform() === _platformName : false;
}, convertFilePath:function(_realPath) {
  if (this.isIOS()) {
    return window.WkWebView.convertFilePath(_realPath);
  }
  return _realPath;
}, supportsDocumentImports:function() {
  return this.isIOS() || this.isAndroid();
}, supportsLocalNotification:function() {
  if (!this.isAndroid()) {
    return true;
  }
  var version = this.getVersion();
  return !(version.startsWith('8.') || version > 11);
}, supportsMultiuser:function() {
  return !this.isIOS();
}, supportsEmbeddedWebpage:function() {
  return !this.isWindows();
}});
Ext.define('dilocsync.core.Master', {mixins:[Ext.mixin.Observable, cnconsult.Translatable], singleton:true, version:'0', versionCode:'0', presetRegistrationData:null, config:{initialHref:null, storageProfile:'default', fileSystem:null, syncRoot:null, backendUrl:'', storage:null, syncEngine:null, personalization:null, almanac:null, almanacs:{}, syncReportStorage:null, fullTextSearch:null, lastLiveTickerCheck:null, lastStolenCheck:null, liveTickerUpdateRunning:false, checkStolenCheckRunning:false, 
initFinished:false, documentRepository:null}, constructor:function(_config) {
  this.setInitialHref(window.location.href);
  this.mixins.observable.constructor.call(this, _config);
}, initVersionInformation:function() {
  var $jscomp$this = this;
  cnconsult.Logger.log({prefix:'Master-\x3egetAppVersion', message:'Trying to get app version..'});
  cordova.getAppVersion.getVersionNumber(function(version) {
    cnconsult.Logger.log({prefix:'Master-\x3egetAppVersion', message:'version: ' + version});
    $jscomp$this.version = version;
  });
  cordova.getAppVersion.getVersionCode(function(versionCode) {
    return $jscomp$this.versionCode = versionCode;
  });
}, applyStorage:function(newValue, oldValue) {
  if (oldValue) {
    console.error('Storage was already set');
  }
  return newValue;
}, initMaster:function(_documentRepository) {
  var $jscomp$this = this;
  try {
    this.setDocumentRepository(_documentRepository);
    this.setBackendUrl(this.getStorage().get('core:backendUrl', ''));
    this.setSyncEngine(Ext.create('dilocsync.core.SyncEngine', {master:this, storage:this.getStorage(), documentRepository:_documentRepository}));
    this.setPersonalization(Ext.create('dilocsync.core.Personalization', {master:this, storage:this.getStorage()}));
    if (this.getPersonalization() && this.getPersonalization().isPersonalized()) {
      this.onPersonalized();
    } else {
      this.getPersonalization().on('personalized', function() {
        $jscomp$this.onPersonalized();
      });
    }
    if (dilocsync.util.Platform.supportsFullTextSearch()) {
      console.log('FullTextSearch should be available, start initializing it...');
      this.setFullTextSearch(Ext.create('dilocsync.core.FullTextSearch'));
    }
    this.initCustomEventListener();
    this.deleteTemporaryFileDirectory();
    this.setInitFinished(true);
    this.fireEvent('initialized');
  } catch (e$73) {
    cnconsult.Logger.log({prefix:'Master-\x3einitMaster', message:'Exception during initMaster', level:'error', catchedError:e$73, useSentry:true});
  }
}, onPersonalized:function() {
  this.setSyncReportStorage(Ext.create('dilocsync.core.syncreport.Storage', {applicationStorage:this.getStorage(), syncReportStorageKeyPrefix:'syncreport:storage:'}));
  this.initAlmanacs();
}, initAlmanacs:function() {
  var knowledgesBasePath = this.getKnowledgesBasePath();
  if (knowledgesBasePath) {
    var almanacPath = knowledgesBasePath;
    if (Ext.String.endsWith(almanacPath, '/')) {
      almanacPath = almanacPath.substring(0, almanacPath.length - 1);
    }
    this.getAlmanacs()[almanacPath] = new dilocsync.core.Almanac(this.getStorage().get('core:almanac:' + knowledgesBasePath, 'nodefault-d28;['));
  }
  Ext.Array.each(this.getStorage().get('core:almanacs', []), function(_almanacInfo) {
    this.getAlmanacs()[_almanacInfo.path] = new dilocsync.core.Almanac(this.getStorage().get('core:almanac:' + _almanacInfo.path, 'nodefault-d28;['));
  }, this);
}, getKnowledgesBasePath:function() {
  var identity = this.getIdentity();
  var basePath = false;
  if (identity.hasOwnProperty('pages') && Ext.isArray(identity.pages)) {
    var pagesMap = Ext.Array.toValueMap(identity.pages, 'type');
    if (pagesMap.hasOwnProperty('knowledge') && pagesMap.knowledge.hasOwnProperty('config') && pagesMap.knowledge.config.hasOwnProperty('path')) {
      basePath = pagesMap.knowledge.config.path;
    }
    return basePath;
  }
}, initCustomEventListener:function() {
  if (this.isPhonegap()) {
    document.addEventListener('online', Ext.bind(this.onDeviceOnline, this), false);
    document.addEventListener('offline', Ext.bind(this.onDeviceOffline, this), false);
  }
}, initLanguage:function(_callback, _scope) {
  cnconsult.Logger.log({prefix:'Master-\x3einitLanguage', message:'Init language labels'});
  var lang = this.getUserLanguage();
  if (lang !== 'en') {
    cnconsult.Translator.loadTranslationAsync('resources/lang/diloc-syncmobile_' + lang + '.lang', function() {
      Ext.callback(_callback, _scope);
    }, this);
    var yes = 'Yes';
    var no = 'No';
    if (lang === 'de') {
      yes = 'Ja';
      no = 'Nein';
    }
    if (lang === 'fr') {
      yes = 'Oui';
      no = 'Non';
    }
    if (lang === 'it') {
      yes = 'Si';
      no = 'No';
    }
    var messageBox = Ext.MessageBox;
    Ext.apply(messageBox, {YES:{text:yes, itemId:'yes', ui:'action'}, NO:{text:no, itemId:'no'}});
    Ext.apply(messageBox, {YESNO:[messageBox.NO, messageBox.YES]});
  } else {
    Ext.defer(Ext.bind(function(_callback, _scope) {
      Ext.callback(_callback, _scope);
    }, this), 1, this, [_callback, _scope]);
  }
}, isPhonegap:function() {
  return typeof device !== 'undefined';
}, isRegistered:function() {
  return this.getStorage().get('core:registered', false);
}, registerDevice:function(_server, _password, _callback, _scope) {
  this.detectBackendUrl(_server, true, function() {
    if (this.getBackendUrl()) {
      Ext.Ajax.request({url:this.getBackendUrl() + '/syncregisterng/checkPassword', params:{password:_password, deviceType:this.deviceType()}, success:function(response) {
        try {
          var data = Ext.decode(response.responseText);
          cnconsult.Logger.log({prefix:'Master-\x3eregisterDevice', message:'get backend url', dump:data});
          if (data && data.success && data.data === 'ok') {
            Ext.Ajax.request({url:this.getBackendUrl() + '/syncregisterng/preRegisterDevice', params:{password:_password, deviceIdCode:this.deviceIdCode(), deviceType:this.deviceType()}, success:function(response) {
              try {
                var preRegisterDeviceData = Ext.decode(response.responseText);
                cnconsult.Logger.log({prefix:'Master-\x3eregisterDevice', message:'preRegisterDevice device data', dump:preRegisterDeviceData});
                if (preRegisterDeviceData && preRegisterDeviceData.success && preRegisterDeviceData.data.syncSecret) {
                  this.getStorage().set('core:registered', true);
                  this.getStorage().set('core:disableUserCreation', preRegisterDeviceData.data.disableUserCreation);
                  this.getStorage().set('core:personalization:customerId', preRegisterDeviceData.data.customerId);
                  this.getStorage().set('core:personalization:syncSecret', preRegisterDeviceData.data.syncSecret);
                  Ext.callback(_callback, _scope, [true]);
                  this.fireEvent('registered');
                } else {
                  Ext.callback(_callback, _scope, [false, this.tr('Error while preregistering, needed data not received.', 'German: Fehler bei der Vorregistrierung, einige benötigten Daten wurden nicht empfangen.')]);
                }
              } catch (e$74) {
                cnconsult.Logger.log({prefix:'Master-\x3eregisterDevice', message:'Exception catched during saving of registration data.', level:'error', dump:e$74, useSentry:true});
                Ext.callback(_callback, _scope, [false, this.tr('Error registering: An unknown server error happened.', 'German: Fehler beim Registrieren: Ein unbekannter Serverfehler ist aufgetreten.')]);
              }
            }, failure:function() {
              Ext.callback(_callback, _scope, [false, this.tr('Error registering: An unknown server error happened.', 'German: Fehler beim Registrieren: Ein unbekannter Serverfehler ist aufgetreten.')]);
            }, scope:this});
          } else {
            Ext.callback(_callback, _scope, [false, this.tr('Error registering: The password is probably wrong.', 'German: Fehler beim Registrieren: Möglicherweise ist das Passwort falsch.')]);
          }
        } catch (e$75) {
          cnconsult.Logger.log({prefix:'Master-\x3eregisterDevice', message:'Error registering: An unknown server error happened.', level:'error', dump:e$75, useSentry:true});
          Ext.callback(_callback, _scope, [false, this.tr('Error registering: An unknown server error happened.', 'German: Fehler beim Registrieren: Ein unbekannter Serverfehler ist aufgetreten')]);
        }
      }, failure:function() {
        Ext.callback(_callback, _scope, [false, this.tr('Error registering: The password is probably wrong.', 'German: Fehler beim Registrieren: Möglicherweise ist das Passwort falsch.')]);
      }, scope:this});
    } else {
      Ext.callback(_callback, _scope, [false, this.tr('The server does not support DiLoc|Sync!', 'German: Der Server Unterstützt DiLoc|Sync nicht!')]);
    }
  }, this);
}, detectBackendUrl:function(_server, _bypassCache, _callback, _scope) {
  if (this.getBackendUrl() && _bypassCache !== true) {
    Ext.callback(_callback, _scope);
    return;
  }
  var backendDetector = Ext.create('dilocsync.core.ServerBackendDetection');
  backendDetector.detectBackendUrl(_server, function(_url) {
    if (_url) {
      this.setBackendUrl(_url);
      this.getStorage().set('core:backendUrl', this.getBackendUrl());
    } else {
      this.setBackendUrl(null);
    }
    Ext.callback(_callback, _scope);
  }, this);
}, deviceIdCode:function() {
  var deviceIdCode = this.getStorage().get('core:deviceIdCode', false);
  if (deviceIdCode) {
    return deviceIdCode;
  } else {
    if (dilocsync.util.Platform.isWindows()) {
      deviceIdCode = Ext.create('Ext.data.identifier.Uuid').generate();
    } else {
      if (typeof window.device !== 'undefined') {
        deviceIdCode = device.uuid;
      } else {
        deviceIdCode = Math.random().toString(36).substring(2, 28);
      }
    }
    this.getStorage().set('core:deviceIdCode', deviceIdCode);
    return deviceIdCode;
  }
}, getUserLanguage:function() {
  var languageString = navigator.language;
  var lang = languageString.split('_')[0];
  lang = lang.split('-')[0];
  return this.getStorage().get('core:userLang', lang.toLowerCase());
}, setUserLanguage:function(_lang) {
  this.getStorage().set('core:userLang', _lang);
}, getIdentity:function() {
  if (this.getPersonalization() && this.getPersonalization().isPersonalized()) {
    var normalizer = new dilocsync.core.IdentityNormalizer(this.getPersonalization().getData());
    try {
      var identity = this.getStorage().get('core:identity', '{}');
      return normalizer.normalize(identity);
    } catch (e$76) {
      return {};
    }
  } else {
    return {};
  }
}, devicePath:function(_path) {
  if (this.getSyncRoot()) {
    return this.getSyncRoot().toURL() + '/' + _path;
  }
  return '' + _path;
}, devicePathExists:function(_path, _callback, _scope) {
  if (this.isPhonegap()) {
    var fullPath = _path;
    var path = _path;
    if (!_path.startsWith(this.devicePath(''))) {
      fullPath = this.devicePath(_path);
    }
    fullPath = fullPath.replace('////', '//');
    if (path.startsWith(this.devicePath(''))) {
      path = path.replace(this.devicePath(''), '');
    }
    if (path.startsWith('//')) {
      path = path.replace('//', '');
    }
    if (path.startsWith('/')) {
      path = path.replace('/', '');
    }
    this.getSyncRoot().getFile(path, {create:false}, function() {
      Ext.callback(_callback, _scope, [fullPath]);
    }, function() {
      Ext.callback(_callback, _scope, [null]);
    });
  } else {
    Ext.callback(_callback, _scope, [this.devicePath(_path)]);
  }
}, deviceType:function() {
  var os = Ext.os;
  var deviceType = 'netbook';
  if (os.deviceType === 'Desktop' || os.name === 'MacOS') {
    if (os.name === 'MacOS') {
      deviceType = 'ios_tablet';
    }
  } else {
    deviceType = os.name.toLowerCase() + '_' + os.deviceType.toLowerCase();
  }
  return deviceType;
}, deleteDataDirectory:function(_callback, _scope) {
  var $jscomp$this = this;
  var deleteDataPromise = new Ext.Promise(function(_resolve, _reject) {
    $jscomp$this.deleteDataDirectoryByName(function(_success) {
      _success ? _resolve() : _reject();
    }, $jscomp$this, 'fs-data');
  });
  var deleteFormPromise = new Ext.Promise(function(_resolve, _reject) {
    $jscomp$this.deleteDataDirectoryByName(function(_success) {
      _success ? _resolve() : _reject();
    }, $jscomp$this, 'forms');
  });
  var deleteTrainSchedulesPromise = new Ext.Promise(function(_resolve, _reject) {
    $jscomp$this.deleteDataDirectoryByName(function(_success) {
      _success ? _resolve() : _reject();
    }, $jscomp$this, 'train-schedule-data');
  });
  Ext.Promise.all([deleteDataPromise, deleteFormPromise, deleteTrainSchedulesPromise]).then(function() {
    Ext.callback(_callback, _scope, [true]);
  })['catch'](function() {
    Ext.callback(_callback, _scope, [false]);
  });
}, deleteDataDirectoryByName:function(_callback, _scope, _directoryName) {
  if (this.getSyncRoot()) {
    this.getSyncRoot().getDirectory(_directoryName, null, function(_dataDirectory) {
      _dataDirectory.removeRecursively(function() {
        Ext.callback(_callback, _scope, [true]);
      }, function(_error) {
        cnconsult.Logger.log({prefix:'Master-\x3edeleteDataDirectory', message:'Failed to delete the "' + _directoryName + ' " directory!', level:'error', dump:_error, useSentry:true});
        Ext.callback(_callback, _scope, [false]);
      });
    }, function(_error) {
      cnconsult.Logger.log({prefix:'Master-\x3edeleteDataDirectory', message:'Directory " ' + _directoryName + ' " could not be deleted!', level:'error', dump:_error, useSentry:true});
      Ext.callback(_callback, _scope, [false]);
    });
  } else {
    cnconsult.Logger.log({prefix:'Master-\x3edeleteDataDirectory', message:'ClearDataDirectory: No sync root found'});
    Ext.callback(_callback, _scope, [true]);
  }
}, deleteSystemDirectory:function(_callback, _scope) {
  if (this.getSyncRoot()) {
    this.getSyncRoot().getDirectory('system', null, function(_systemDirectory) {
      _systemDirectory.removeRecursively(function() {
        Ext.callback(_callback, _scope, [true]);
      }, function(_error) {
        cnconsult.Logger.log({prefix:'Master-\x3edeleteSystemDirectory', message:'Failed to delete the "system" directory!', level:'error', catchedError:_error, useSentry:true});
        Ext.callback(_callback, _scope, [false]);
      });
    }, function(_error) {
      cnconsult.Logger.log({prefix:'Master-\x3edeleteSystemDirectory', message:'Failed to load the "system" directory!', level:'error', catchedError:_error, useSentry:true});
      Ext.callback(_callback, _scope, [false]);
    });
  } else {
    cnconsult.Logger.log({prefix:'Master-\x3edeleteSystemDirectory', message:'DeleteSystemDirectory: No sync root found!'});
    Ext.callback(_callback, _scope, [true]);
  }
}, deleteTemporaryFileDirectory:function(_callback, _scope) {
  if (this.getSyncRoot()) {
    this.getSyncRoot().getDirectory('fs-data/temp-external-open', null, function(_tempDirectory) {
      _tempDirectory.removeRecursively(function() {
        Ext.callback(_callback, _scope, [true]);
      }, function(_error) {
        cnconsult.Logger.log({prefix:'Master-\x3edeleteTemporaryFileDirectory', message:'Failed to delete the "temp-external-open" directory!', level:'error', catchedError:_error, useSentry:true});
        Ext.callback(_callback, _scope, [false]);
      });
    }, function(_error) {
      cnconsult.Logger.log({prefix:'Master-\x3edeleteTemporaryFileDirectory', message:'Failed to load the "temp-external-open" directory! Maybe it does not exist yet?', level:'warn', dump:_error});
      Ext.callback(_callback, _scope, [false]);
    });
  } else {
    cnconsult.Logger.log({prefix:'Master-\x3edeleteTemporaryFileDirectory', message:'DeleteTempDirectory: No sync root found!'});
    Ext.callback(_callback, _scope, [true]);
  }
}, clearAlmanacs:function() {
  this.getStorage().remove('core:almanacs');
  var almanacs = this.getAlmanacs() || {};
  var almanacsPaths = Object.keys(almanacs);
  for (var $jscomp$iter$7 = $jscomp.makeIterator(almanacsPaths), $jscomp$key$almanacPath = $jscomp$iter$7.next(); !$jscomp$key$almanacPath.done; $jscomp$key$almanacPath = $jscomp$iter$7.next()) {
    var almanacPath = $jscomp$key$almanacPath.value;
    {
      this.getStorage().remove('core:almanac:' + almanacPath);
    }
  }
  this.setAlmanacs({});
}, persistAlmanacByPath:function(_almanac, _path) {
  try {
    var almanacSerialized = _almanac.serialize();
    var almanacEncoded = Ext.encode(almanacSerialized);
    this.getStorage().set('core:almanac:' + _path, almanacEncoded);
  } catch (e$77) {
    cnconsult.Logger.log({prefix:'Master-\x3epersistAlmanacByPath', message:'Exception catched during persist almanac by path!', level:'error', dump:{almanac:_almanac, path:_path}, catchedError:e$77, useSentry:true});
  }
}, reloadApplication:function(_withConfirmation) {
  if (_withConfirmation) {
    dilocsync.util.MessageHelper.showConfirm(this.tr('Reload'), this.tr('Your app needs a reload. Are you sure that you want to reload now?'), function(_button) {
      if (_button === 'yes') {
        Ext.Function.defer(function() {
          window.location = this.getInitialHref();
        }, 50, this);
      }
    }, this);
  } else {
    Ext.Function.defer(function() {
      window.location = this.getInitialHref();
    }, 50, this);
  }
}, loadTickerMessages:function(_callback, _scope) {
  if (this.isOnline() && this.getPersonalization().isPersonalized() && this.getBackendUrl()) {
    Ext.Ajax.request({url:this.getBackendUrl() + '/syncng/getTickerMessages', params:{syncSecret:this.getStorage().get('core:personalization:syncSecret')}, success:function(response) {
      try {
        var data = Ext.decode(response.responseText);
        if (data && (data.success && data.data) || data.result) {
          var liveTickerData = data.hasOwnProperty('data') ? data.data : data.result;
          Ext.callback(_callback, _scope, [liveTickerData]);
        } else {
          Ext.callback(_callback, _scope, [null]);
        }
      } catch (e$78) {
        cnconsult.Logger.log({prefix:'Master-\x3eloadTickerMessages', message:'Error loading ticker messages', level:'error', catchedError:e$78, useSentry:true});
        Ext.callback(_callback, _scope, [null]);
      }
    }, failure:function() {
      Ext.callback(_callback, _scope, [null]);
    }, scope:this});
  }
}, isOnline:function() {
  return !(navigator && navigator.network && navigator.network.connection && navigator.network.connection.type === Connection.NONE);
}, onDeviceOnline:function() {
  this.fireEvent('connectiononline');
  this.checkStolen(true);
}, onDeviceOffline:function() {
  this.fireEvent('connectionoffline');
}, checkStolen:function(_forceCheck) {
  var forceCheck = false;
  if (_forceCheck) {
    forceCheck = true;
  }
  var now = new Date;
  if (forceCheck || !this.getLastStolenCheck() || !this.getCheckStolenCheckRunning() && Ext.Date.diff(this.getLastStolenCheck(), new Date, Ext.Date.MINUTE) >= 10) {
    this.setCheckStolenCheckRunning(true);
    this.isStolen(function(_isStolen) {
      this.setLastStolenCheck(now);
      this.setCheckStolenCheckRunning(false);
      if (_isStolen === 'yes!') {
        this.resetDevice();
      }
    }, this);
  }
  if (Ext.Date.diff(this.getLastStolenCheck(), new Date, Ext.Date.MINUTE) >= 30) {
    this.setCheckStolenCheckRunning(false);
  }
}, isStolen:function(_callback, _scope) {
  if (this.isOnline() && this.getPersonalization().isPersonalized() && this.getBackendUrl()) {
    Ext.Ajax.request({url:this.getBackendUrl() + '/syncregisterng/checkStolen', params:{syncSecret:this.getStorage().get('core:personalization:syncSecret')}, success:function(response) {
      try {
        var data = Ext.decode(response.responseText);
        if (data && data.success && data.data) {
          Ext.callback(_callback, _scope, [data.data]);
        } else {
          Ext.callback(_callback, _scope, [null]);
        }
      } catch (e$79) {
        cnconsult.Logger.log({prefix:'Master-\x3eisStolen', message:'Error check whether this device is stolen', level:'error', catchedError:e$79, useSentry:true});
        Ext.callback(_callback, _scope, [null]);
      }
    }, failure:function() {
      Ext.callback(_callback, _scope, [null]);
    }, scope:this});
  }
}, resetDevice:function() {
  this.getStorage().removeAll();
  Ext.defer(function() {
    this.deleteDataDirectory(function() {
      this.reloadApplication();
    }, this);
  }, 1000, this);
}, fileExistsInAlmanacs:function(_filePath) {
  var fileExists = false, almanac, almanacPath, path;
  if (_filePath) {
    almanac = this.getAlmanacForPath(_filePath);
    if (almanac) {
      almanacPath = this.getAlmanacPath(_filePath);
      path = _filePath.replace(almanacPath, '');
      if (almanac.fileExists(path)) {
        fileExists = true;
      } else {
        cnconsult.Logger.log({prefix:'Master-\x3efileExistsInAlmanacs', message:'File does not exist in almanac!', dump:{almanac:almanac, almanacPath:almanacPath, path:path}});
      }
    } else {
      cnconsult.Logger.log({prefix:'Master-\x3efileExistsInAlmanacs', message:'No almanac found for file.', dump:_filePath});
    }
  }
  return fileExists;
}, getAlmanacForPath:function(_path) {
  var almanacs = this.getAlmanacs();
  var path = _path, almanac;
  if (path.startsWith('/')) {
    path = path.slice(1);
  }
  if (almanacs.hasOwnProperty(path) && almanacs[path]) {
    almanac = almanacs[path];
  } else {
    for (var almanacPath in almanacs) {
      if (almanacs.hasOwnProperty(almanacPath) && path.startsWith(almanacPath)) {
        almanac = almanacs[almanacPath];
        break;
      }
    }
  }
  return almanac;
}, getAlmanacPath:function(_path) {
  var almanacs = this.getAlmanacs();
  var path = _path, almanacBasePath;
  if (path.startsWith('/')) {
    path = path.slice(1);
  }
  if (almanacs.hasOwnProperty(path) && almanacs[path]) {
    almanacBasePath = path;
  } else {
    for (var almanacPath in almanacs) {
      if (almanacs.hasOwnProperty(almanacPath) && path.startsWith(almanacPath)) {
        almanacBasePath = almanacPath;
        break;
      }
    }
  }
  return almanacBasePath;
}, fullTextSearchIndexNewFiles:function() {
  var me = this;
  var search = me.getFullTextSearch();
  var filesToIndex = this.getStorage().get('fulltextsearch:filesToIndex', false);
  if (search && search.readyToSearch() && filesToIndex) {
    search.indexNewFiles(filesToIndex, function() {
      cnconsult.Logger.log({prefix:'Master-\x3efullTextSearchIndexNewFiles', message:'Master finish indexing new files'});
      me.getStorage().set('fulltextsearch:filesToIndex', false);
    }, search);
  }
}, importsEnabled:function() {
  var identity = this.getIdentity();
  return dilocsync.util.Platform.supportsDocumentImports() && (identity.options && (identity.options.hasOwnProperty('enableImports') && identity.options.enableImports));
}});
Ext.define('dilocsync.overrides.presetregistrationdata', {override:'dilocsync.core.Master', presetRegistrationData:{password:'', serverUrl:''}});
Ext.define('dilocsync.core.AutoSyncManager', {mixins:[Ext.mixin.Observable, cnconsult.Translatable], config:{onAppStart:false, interval:0, autoSyncLowBatteryManagement:false, lowBatteryInterval:0, lowBatteryThreshold:0, batteryStatus:100, syncEngine:null, autoSyncTimeoutId:null, syncCheckInterval:60, waitOnFailTimeout:null, waitOnFailTimeoutDefault:60, lastAutoSyncTry:0}, constructor:function(_autoSyncConfig) {
  this.setSyncEngine(dilocsync.core.Master.getSyncEngine());
  this.getSyncEngine().on('syncfinished', this.onSyncFinished, this);
  this.setupConfig(_autoSyncConfig);
  this.mixins.observable.constructor.call(this, arguments);
}, setupConfig:function(_autoSyncConfig) {
  if (_autoSyncConfig.interval > 0) {
    this.setInterval(_autoSyncConfig.interval);
  }
  if (_autoSyncConfig.lowBatteryInterval > 0 && _autoSyncConfig.lowBatteryThreshold) {
    this.setLowBatteryInterval(_autoSyncConfig.lowBatteryInterval);
    this.setLowBatteryThreshold(_autoSyncConfig.lowBatteryThreshold);
  }
  if (_autoSyncConfig.onAppStart) {
    this.setOnAppStart(true);
  }
  if (_autoSyncConfig.syncCheckInterval) {
    this.setSyncCheckInterval(_autoSyncConfig.syncCheckInterval);
  }
  if (_autoSyncConfig.waitOnFailTimeoutDefault) {
    this.setWaitOnFailTimeoutDefault(_autoSyncConfig.waitOnFailTimeoutDefault);
  }
}, start:function(_afterReconfiguration) {
  if (_afterReconfiguration !== true && this.getOnAppStart() && !this.getSyncEngine().isSyncing()) {
    cnconsult.Logger.log({prefix:'AutoSyncManager-\x3estart', message:'Auto sync on app start is configured, so start syncing...'});
    this.doSync(true);
  }
  if (this.getAutoSyncTimeoutId()) {
    window.clearInterval(this.getAutoSyncTimeoutId());
  }
  if (this.getInterval()) {
    cnconsult.Logger.log({prefix:'AutoSyncManager-\x3estart', message:'Auto sync is configured'});
    if (this.getLowBatteryInterval() && this.getLowBatteryThreshold()) {
      cnconsult.Logger.log({prefix:'AutoSyncManager-\x3estart', message:'Low battery energy management is enabled, change interval if battery status is under the configured low battery threshold'});
      if (!this.getAutoSyncLowBatteryManagement() && this.getLowBatteryInterval()) {
        window.addEventListener('batterystatus', Ext.bind(this.batteryStatusChangeListener, this), false);
        this.setAutoSyncLowBatteryManagement(true);
      }
    }
    this.setAutoSyncTimeoutId(window.setInterval(Ext.bind(this.autoSync, this), this.getSyncCheckInterval() * 1000));
  } else {
    cnconsult.Logger.log({prefix:'AutoSyncManager-\x3estart', message:"Auto sync isn't configured"});
  }
}, batteryStatusChangeListener:function(_batteryStatus) {
  cnconsult.Logger.log({prefix:'AutoSyncManager-\x3ebatteryStatusChangeListener', message:'Battery status has changed to ', dump:_batteryStatus.level});
  this.setBatteryStatus(_batteryStatus.level);
}, autoSync:function() {
  var doSync = this.isSyncNeeded(this.getWaitOnFailTimeout(), this.getSyncInterval(), this.getSyncEngine().lastSyncTimestamp(), this.getLastAutoSyncTry(), new Date, this.getSyncEngine().isSyncing());
  if (doSync) {
    this.doSync();
  }
}, isSyncNeeded:function(_waitOnFailTimeout, _syncInterval, _lastSync, _lastSyncTry, _now, _isSyncing) {
  var syncNeeded = false;
  if (_waitOnFailTimeout) {
    var secondsSinceLastSync = Ext.Date.diff(_lastSyncTry, _now, Ext.Date.SECOND);
    cnconsult.Logger.log({prefix:'AutoSyncManager-\x3eisSyncNeeded', message:'Last sync try was at ' + _lastSyncTry + ' which was ' + secondsSinceLastSync + ' second(s) ago. Auto sync wait on fail timeout is configured to ' + _waitOnFailTimeout + ' is syncing: ' + this.getSyncEngine().isSyncing()});
    if (_waitOnFailTimeout <= secondsSinceLastSync && _isSyncing === false) {
      syncNeeded = true;
    }
  } else {
    var minutesSinceLastSync = Ext.Date.diff(_lastSync, _now, Ext.Date.MINUTE);
    cnconsult.Logger.log({prefix:'AutoSyncManager-\x3eisSyncNeeded', message:'Last sync was at ' + _lastSync + ' which was ' + minutesSinceLastSync + ' minute(s) ago. Auto sync interval is configured to ' + _syncInterval + ' is syncing: ' + this.getSyncEngine().isSyncing()});
    if (_syncInterval <= minutesSinceLastSync && _isSyncing === false) {
      syncNeeded = true;
    }
  }
  return syncNeeded;
}, doSync:function(_noDelay) {
  var me = this;
  var now = new Date;
  var randomDelayInMs = _noDelay ? 0 : Ext.Number.randomInt(0, this.getSyncCheckInterval() * 1000);
  Ext.defer(function() {
    me.getSyncEngine().startSync(true);
    me.setLastAutoSyncTry(now);
  }, randomDelayInMs, me);
}, getSyncInterval:function() {
  if (this.getLowBatteryInterval() && this.getLowBatteryThreshold()) {
    if (this.getBatteryStatus() <= this.getLowBatteryThreshold()) {
      return this.getLowBatteryInterval();
    }
  }
  return this.getInterval();
}, onSyncFinished:function(_success, _errorMessage, _syncReportAvailable, _reloadRequired) {
  if (this.getSyncEngine().wasLastSyncFromAutoSync()) {
    var hasHighPriorityFiles = false;
    if (this.getSyncEngine().hasOwnProperty('syncData')) {
      hasHighPriorityFiles = this.getSyncEngine().syncData.getHasHighPriorityFiles();
    }
    var title = this.tr('Sync finished');
    var text = this.tr('Synchronization finished successfully.');
    if (_success === true) {
      if (hasHighPriorityFiles) {
        text += ' ' + this.tr('All necessary files for your drive were synced!');
      }
      if (_syncReportAvailable === true) {
        text += ' ' + this.tr('A synchronization report is available.');
      }
      this.setWaitOnFailTimeout(false);
    } else {
      if (_success === false) {
        if (_errorMessage !== 'noalert') {
          title = this.tr('Sync error');
          text = this.tr('Synchronization failed with message: %1').arg(_errorMessage);
        }
        this.setWaitOnFailTimeout(this.calculateWaitOnFailTimeout(this.getWaitOnFailTimeout(), this.getSyncInterval() * 60, this.getWaitOnFailTimeoutDefault()));
      }
    }
    if (typeof cordova !== 'undefined' && dilocsync.util.Platform.supportsLocalNotification()) {
      cordova.plugins.notification.local.schedule({id:1, title:title, text:text});
    } else {
      cnconsult.Logger.log({prefix:'AutoSyncManager-\x3eonSyncFinished', message:title + ' - ' + text});
    }
    if (_success === true && hasHighPriorityFiles && this.hasNormalFilesToDownload()) {
      this.doSync(true);
    }
  }
}, hasNormalFilesToDownload:function() {
  var almanacsSyncActions = this.getSyncEngine().hasOwnProperty('syncData') ? this.getSyncEngine().syncData.getAlmanacsSyncActions() : null;
  var hasNormalFilesToDownload = false;
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    if (Ext.Object.getSize(_almanacSyncActions.getFilesToDownload()) > 0) {
      hasNormalFilesToDownload = true;
    }
  }, this);
  return hasNormalFilesToDownload;
}, calculateWaitOnFailTimeout:function(_currentTimeout, _intervalInSeconds, _defaultTimeout) {
  var timeout;
  if (!_currentTimeout) {
    timeout = _defaultTimeout;
  } else {
    if (2 * _currentTimeout <= _intervalInSeconds) {
      timeout = 2 * _currentTimeout;
    } else {
      if (2 * _currentTimeout >= _intervalInSeconds && _currentTimeout < _intervalInSeconds) {
        timeout = _intervalInSeconds;
      } else {
        timeout = 2 * _intervalInSeconds;
      }
    }
  }
  return timeout;
}});
Ext.define('dilocsync.core.FileVisibleManager', {mixins:[Ext.mixin.Observable, cnconsult.Translatable], config:{fileVisibleCheckIntervalId:null, lastCheckDayOfYear:0, runner:null, checkTask:null}, constructor:function(_config) {
  var me = this;
  var second = 1000;
  var minute = second * 60;
  var hour = minute * 60;
  var day = hour * 24;
  me.mixins.observable.constructor.call(me, _config);
  me.setLastCheckDayOfYear(Ext.Date.getDayOfYear(new Date));
  me.setRunner(new Ext.util.TaskRunner);
  me.setCheckTask(this.getRunner().newTask({run:function() {
    var dayOfYear = Ext.Date.getDayOfYear(new Date);
    if (dayOfYear > me.getLastCheckDayOfYear()) {
      cnconsult.Logger.log({prefix:'FileVisibleManager-\x3econstructor', message:'trigger checkFileVisibility at ', dump:Ext.Date.format(new Date, 'H:i:s d.m.Y')});
      me.checkFileVisibility();
      me.setLastCheckDayOfYear(dayOfYear);
      me.getCheckTask().restart(day);
    }
  }, scope:me, interval:5 * minute}));
  me.getCheckTask().start();
}, checkFileVisibility:function() {
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var storage = master.getStorage();
  var almanacs = master.getAlmanacs();
  var lastVisiblityCheck = storage.get('core:lastVisibilityCheck', false);
  var lastCheck = new Date(lastVisiblityCheck ? lastVisiblityCheck : 8.64E15);
  var newVisibleFiles = [];
  Ext.Object.each(almanacs, function(_almanacPath, _almanac) {
    newVisibleFiles = Ext.Array.merge(newVisibleFiles, this.getNewVisibleFiles(_almanacPath, _almanac, lastCheck));
  }, this);
  if (newVisibleFiles.hasOwnProperty('length') && newVisibleFiles.length > 0) {
    if (identity.options && identity.options.syncReportConfig) {
      cnconsult.Logger.log({prefix:'FileVisibleManager-\x3echeckFileVisibility', message:'Building SyncReportGenerator for creating a SyncReport for new visible files...'});
      var syncReportConfigLoader = Ext.create('dilocsync.core.syncreport.ConfigLoader', {personalisationData:master.getPersonalization().getData(), fileSystem:master.getFileSystem(), syncReportConfigFile:identity.options.syncReportConfig, storage:storage});
      cnconsult.Logger.log({prefix:'FileVisibleManager-\x3echeckFileVisibility', message:'SyncReportConfigLoader created'});
      syncReportConfigLoader.on('configloaded', Ext.bind(this.onConfigLoaded, this, [syncReportConfigLoader, identity, almanacs, newVisibleFiles], false), this, {single:true});
      syncReportConfigLoader.on('loadingconfigfailed', function() {
        cnconsult.Logger.log({prefix:'FileVisibleManager-\x3echeckFileVisibility', message:"SyncReportConfigLoader couldn't be build because config could not be loaded!", level:'error'});
      }, this, {single:true});
      syncReportConfigLoader.loadConfigFromFile();
    }
    var title = this.tr('New visible files'), text = this.tr('There are %1 new visible files.').arg(newVisibleFiles.length), buttonHandler = Ext.Function.bind(function(_button) {
      if (_button.getItemId() === 'openSyncReport') {
        dilocsync.getApplication().redirectTo('syncreports');
      }
      _button.up('messagebox').destroy();
    }, this, [], true);
    var okayButton = {itemId:'ok', text:this.tr('Ok'), handler:buttonHandler};
    var openSyncReportButton = {itemId:'openSyncReport', text:this.tr('Open Sync Report'), handler:buttonHandler, scope:this};
    dilocsync.util.MessageHelper.showMessage({title:title, message:text, buttons:[okayButton, openSyncReportButton]});
  } else {
    cnconsult.Logger.log({prefix:'FileVisibleManager-\x3echeckFileVisibility', message:"There are no new visible files. User mustn't be informed!"});
  }
  storage.set('core:lastVisibilityCheck', new Date);
}, getNewVisibleFiles:function(_almanacPath, _almanac, _lastCheck) {
  var filesToCheck = this.filesWithVisibleFromSet(_almanac.getRootDirectory(), [], _almanacPath), newVisibleFiles = [];
  Ext.Array.each(filesToCheck, function(_fileToCheck) {
    var visibleFrom = new Date(_fileToCheck.visibleFrom ? _fileToCheck.visibleFrom : 0);
    var now = Date.now();
    if (_lastCheck < Ext.Number.parseInt(Ext.Date.format(visibleFrom, 'time')) && now > Ext.Number.parseInt(Ext.Date.format(visibleFrom, 'time'))) {
      newVisibleFiles.push(_fileToCheck);
    }
  });
  return newVisibleFiles;
}, filesWithVisibleFromSet:function(_almanacDirectory, _results, _path) {
  var results = [], path = '';
  if (_results) {
    results = _results;
  }
  if (_path) {
    path = _path;
  }
  for (var directoryName in _almanacDirectory.directories) {
    if (_almanacDirectory.directories.hasOwnProperty(directoryName)) {
      results = this.filesWithVisibleFromSet(_almanacDirectory.directories[directoryName], results, path + '/' + directoryName);
    }
  }
  for (var filename in _almanacDirectory.files) {
    if (_almanacDirectory.files.hasOwnProperty(filename)) {
      var file = _almanacDirectory.files[filename];
      if (file && file.hasOwnProperty('visibleFrom') && file.visibleFrom) {
        file.name = filename;
        file.path = path;
        results.push(file);
      }
    }
  }
  return results;
}, onConfigLoaded:function(_syncReportConfigLoader, _identity, _almanacs, _newVisibleFiles) {
  cnconsult.Logger.log({prefix:'FileVisibleManager-\x3eonConfigLoaded', message:'SyncReportConfigLoader - Config loaded!'});
  var syncReportConfigObject = _syncReportConfigLoader.getSyncReportConfig();
  cnconsult.Logger.log({prefix:'FileVisibleManager-\x3eonConfigLoaded', message:'create SyncReportGenerator with this identity', dump:{identity:_identity, syncReportConfigObject:syncReportConfigObject}});
  var syncReportGenerator = Ext.create('dilocsync.core.syncreport.Generator', {syncEngine:null, syncReportConfig:syncReportConfigObject});
  var almanacs = [];
  Ext.Object.each(_almanacs, function(_path, _almanac) {
    var almanac = new dilocsync.core.Almanac({root:_almanac.rootDirectory, identifier:_almanac.rootDirectory.uuid, path:_path});
    almanacs.push(almanac);
  });
  syncReportGenerator.startBuildingNewSyncReport(almanacs);
  Ext.Array.each(_newVisibleFiles, function(_newVisibleFile) {
    syncReportGenerator.onFileAdded(_newVisibleFile.path, _newVisibleFile.name, null, _newVisibleFile.checksum);
  });
  if (syncReportGenerator.hasOwnProperty('syncReportData') && syncReportGenerator.syncReportData && syncReportGenerator.syncReportData.hasOwnProperty('reason')) {
    syncReportGenerator.syncReportData.reasonType = 'newVisible';
    syncReportGenerator.syncReportData.reason = this.tr('New visible files');
  }
  var syncReport = syncReportGenerator.finishSyncReport();
  if (syncReport) {
    var syncReportStorage = dilocsync.core.Master.getSyncReportStorage();
    syncReportStorage.saveReport(syncReport);
  }
}});
Ext.define('dilocsync.util.Migration', {singleton:true, run:function() {
  this.transformStorageToV4();
}, transformStorageToV4:function() {
  var master = dilocsync.core.Master, storage = master.getStorage();
  if (storage.get('storageMigratedToV4', 'notyettransformed') === 'notyettransformed') {
    cnconsult.Logger.log({prefix:'Migration-\x3etransformStorageToV4', message:'Run migrations to v4'});
    var backendUrl = storage.get('core:backendUrl', null);
    if (backendUrl && backendUrl.endsWith('/')) {
      storage.set('core:backendUrl', backendUrl.slice(0, -1));
    }
    var favorites = storage.get('favoriteRecords', null);
    if (favorites) {
      storage.set('page:favorites:favoriteRecords', favorites);
      storage.remove('favoriteRecords');
    }
    var almanac = storage.get('core:almanach', null);
    if (almanac) {
      storage.set('core:almanac', almanac);
      storage.remove('core:almanach');
    }
    var confirmationRecords = storage.get('readConfirmationRecords', null);
    if (confirmationRecords) {
      storage.set('page:confirmations:confirmationRecords', confirmationRecords);
      storage.remove('readConfirmationRecords');
    }
    var dailyLaArea = storage.get('dailyla:lastarea', null);
    if (dailyLaArea) {
      storage.set('page:dailyla:lastArea', dailyLaArea);
      storage.remove('dailyla:lastarea');
    }
    var workFolders = storage.get('workfolders', null);
    if (workFolders && Ext.isArray(workFolders)) {
      var dossiers = {'children':[], 'icon':'folders', 'leaf':false};
      Ext.Array.each(workFolders, function(_workFolderMetaData) {
        var workFolder = storage.get('Workfolder_' + _workFolderMetaData.id);
        if (workFolder) {
          var dossier = {'name':_workFolderMetaData.name, 'children':[], 'createdAt':_workFolderMetaData.createdAt, 'icon':'folder'};
          Ext.Array.each(workFolder, function(_workFolderItem) {
            var workFolderFile = {'name':_workFolderItem.filePath, 'icon':'file', 'filePath':_workFolderItem.filePath};
            dossier.children.push(workFolderFile);
          });
          dossiers.children.push(dossier);
          storage.remove('Workfolder_' + _workFolderMetaData.id);
        }
      });
      storage.set('dossiers:tree', dossiers);
      storage.remove('workfolders');
    }
    storage.set('storageMigratedToV4', 'transformedToV4');
  }
}});
Ext.define('dilocsync.core.DriveInfoDasManager', {singleton:true, mixins:[Ext.mixin.Observable], config:{runner:null, dasProxyUrl:'', dasCiTicket:'', trainNumber:'', trainDate:'', pollingInterval:1000, errorPollingInterval:20000, failedDasRequests:0, pollingTask:null, dasC:null, farsightRearview:null, currentFetchRequest:null, dascLog:null, dascLogInterval:null}, constructor:function(_config) {
  this.mixins.observable.constructor.call(this, _config);
  this.setRunner(new Ext.util.TaskRunner);
}, init:function(_config) {
  var $jscomp$this = this;
  this.setDasProxyUrl(_config.dasProxyUrl);
  this.setDasCiTicket(_config.dasCiTicket);
  this.setTrainDate(_config.trainDate);
  this.setTrainNumber(_config.trainNumber);
  if (_config.trackDasC) {
    this.setDascLog(dilocsync.util.Helper.initStore('DasCLog'));
    this.setDascLogInterval(setInterval(function() {
      $jscomp$this.getDascLog().sync();
    }, 5 * 60 * 1000));
  }
}, start:function() {
  var task = this.getRunner().newTask({run:function() {
    this.setCurrentFetchRequest(this.fetch());
  }, interval:this.getPollingInterval(), scope:this});
  this.setPollingTask(task);
  task.start();
}, stop:function() {
  this.getPollingTask().stop();
  this.getCurrentFetchRequest().abort();
  this.setPollingTask(null);
  this.setPollingInterval(1000);
  this.setCurrentFetchRequest(null);
  if (this.getDascLogInterval()) {
    clearInterval(this.getDascLogInterval());
    this.setDascLogInterval(null);
    this.getDascLog().sync();
  }
}, fetch:function() {
  return Ext.Ajax.request({url:this.getDasProxyUrl() + 'dasc/1.0/fetch', params:{dasCiTicket:this.getDasCiTicket(), trainNumber:this.getTrainNumber(), trainDate:this.getTrainDate(), deviceId:dilocsync.core.Master.deviceIdCode()}, success:function(_response) {
    if (this.getFailedDasRequests() > 5) {
      this.setPollingInterval(1000);
    }
    this.setFailedDasRequests(0);
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData) {
      if (responseData.hasOwnProperty('result') && responseData.result === 'ok') {
        var pollInterval = responseData.pollInterval * 1000;
        var dasC = responseData.dasC;
        var farsightRearview = responseData.farsightRearview;
        var message;
        this.setDasC(dasC);
        this.setFarsightRearview(farsightRearview);
        this.fireEvent('farsightRearview', farsightRearview);
        if (dasC && (dasC.hasOwnProperty('constantSpeedAdvice') || dasC.hasOwnProperty('coastingAdvice'))) {
          if (dasC.hasOwnProperty('constantSpeedAdvice')) {
            message = 'constantSpeedAdvice: ' + Ext.encode(dasC.constantSpeedAdvice);
            this.fireEvent('dasc', 'constantSpeedAdvice', dasC.constantSpeedAdvice);
          } else {
            if (dasC.hasOwnProperty('coastingAdvice')) {
              message = 'coastingAdvice: ' + Ext.encode(dasC.coastingAdvice);
              this.fireEvent('dasc', 'coastingAdvice', dasC.coastingAdvice);
            } else {
              message = 'reset';
              this.fireEvent('dasc', 'reset', null);
            }
          }
        } else {
          message = 'reset';
          this.fireEvent('dasc', 'reset', null);
        }
        if (this.getDascLog()) {
          this.getDascLog().add({time:(new Date).toISOString(), message:message, trainNumber:this.getTrainNumber()});
        }
        if (pollInterval !== this.getPollingInterval()) {
          this.setPollingInterval(pollInterval);
          this.getPollingTask().restart(pollInterval);
        }
      } else {
        if (responseData.result === 'failed') {
          console.error('Error fetch DASC code: ' + responseData.errorCode + ' message: ' + responseData.errorMessage);
          this.fireEvent('authenticationFailed');
        } else {
          console.error('Error fetch DASC result not defined');
        }
      }
    } else {
      console.error('Error fetch DASC no response data');
    }
  }, failure:function() {
    this.setFailedDasRequests(this.getFailedDasRequests() + 1);
    console.error('Error fetch DASC request failure');
    if (this.getDascLog()) {
      this.getDascLog().add({time:(new Date).toISOString(), message:'DASC request failed. Failures: ' + this.getFailedDasRequests(), trainNumber:this.getTrainNumber()});
    }
    if (this.getFailedDasRequests() > 5 && this.getPollingInterval() !== this.getErrorPollingInterval()) {
      console.error('Increase polling interval to prevent server spam.');
      this.setPollingInterval(this.getErrorPollingInterval());
      this.getPollingTask().restart(this.getPollingInterval());
    }
  }, scope:this});
}});
Ext.define('dilocsync.util.Confirmations', {singleton:true, mixins:[cnconsult.Translatable, Ext.route.Mixin], config:{messageBox:null}, showMessage:function() {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var messageHelper = dilocsync.util.MessageHelper;
  var identity = master.getIdentity();
  var count = Ext.getStore('Confirmations').countUnconfirmedFiles();
  var prio = false;
  var messageBox;
  var buttons;
  if (identity.hasOwnProperty('options') && identity.options.hasOwnProperty('readConfirmationMessagePrio')) {
    prio = identity.options.readConfirmationMessagePrio;
  }
  if (count > 0 && prio && !this.getMessageBox() && Ext.util.History.getToken() !== 'confirmations') {
    var okButton = {text:this.tr('Ok'), handler:Ext.bind(this.destroyMessageBox, this)};
    var openConfirmationsButton = {text:this.tr('Open confirmations'), handler:Ext.bind(function(_button) {
      this.redirectTo('confirmations');
      this.destroyMessageBox();
    }, this)};
    var unlockButton = {text:this.tr('Unlock'), iconCls:'x-fa fa-lock', handler:Ext.bind(function(_button) {
      messageHelper.showPrompt(this.tr('Unlock'), this.tr('Please insert your confirmation unlock password!'), function(_buttonId, _password) {
        var hashedUnlockCode = SparkMD5.hash(_password);
        Ext.Ajax.request({url:master.getBackendUrl() + '/syncng/checkConfirmationUnlockCode', params:{syncSecret:storage.get('core:personalization:syncSecret'), unlockCode:hashedUnlockCode}, success:function(_response) {
          var reply = null;
          try {
            reply = Ext.decode(_response.responseText);
          } catch (e$80) {
            cnconsult.Logger.log({prefix:'Confirmation-\x3eshowMessage', message:'Exception: Unknown server error during checking unlock code.', level:'error', catchedError:e$80, useSentry:true});
            this.showErrorMessage(this.tr('Error'), this.tr('Unknown server error during checking unlock code.'));
          }
          if (reply && reply.success && reply.hasOwnProperty('result')) {
            if (reply.result === 'ok') {
              master.getStorage().set('page:confirmations:unlockDate', Date.now());
              this.destroyMessageBox();
              this.redirectTo(Ext.History.getToken(), true);
            } else {
              this.showErrorMessage(this.tr('Error'), this.tr('An error occurred. Please update to the latest version. If the error still occurs, please contact your administrator.'));
            }
          } else {
            if (reply && reply.backendError) {
              this.showErrorMessage(this.tr('Wrong code'), this.tr("The unlock code wasn't correct. Please try again or contact your administrator."));
            } else {
              this.showErrorMessage(this.tr('Error'), this.tr('An error occurred. Please update to the latest version. If the error still occurs, please contact your administrator.'));
            }
          }
        }, failure:Ext.bind(this.showErrorMessage, this, [this.tr('Wrong code'), this.tr("The unlock code wasn't correct. Please try again or contact your administrator.")], false), scope:this});
      }, this);
    }, this)};
    switch(prio) {
      case 'minor':
        buttons = [okButton, openConfirmationsButton];
        break;
      case 'major':
        var unlockDate = master.getStorage().get('page:confirmations:unlockDate');
        if (!unlockDate || Date.now() - unlockDate >= 60 * 60 * 24 * 1000) {
          buttons = [unlockButton, openConfirmationsButton];
        } else {
          buttons = [openConfirmationsButton];
        }
        break;
    }
    messageBox = messageHelper.showMessage({title:this.tr('Confirmations'), message:this.tr('You have %1 unconfirmed documents').arg(count), buttons:buttons});
    this.setMessageBox(messageBox);
  }
  return messageBox;
}, showErrorMessage:function(_title, _message) {
  var me = this;
  var messageHelper = dilocsync.util.MessageHelper;
  this.getMessageBox().hide();
  messageHelper.showMessage({title:_title, message:_message, buttons:[{text:this.tr('Ok'), itemId:'ok', handler:function() {
    this.up('messagebox').destroy();
    me.redirectTo(Ext.History.getToken(), true);
    Ext.defer(me.destroyMessageBox, me, 300);
  }}], scope:this});
}, destroyMessageBox:function() {
  if (this.getMessageBox()) {
    this.getMessageBox().destroy();
    this.setMessageBox(null);
  }
}});
Ext.define('dilocsync.util.GeoStationTracker', {mixins:[Ext.mixin.Observable, cnconsult.Translatable], prefix:'GeoStationTracker', rideDataHandler:null, currentPositionTimeout:5000, getCurrentPositionInterval:null, geolocation:null, gpsSignal:false, gpsInterval:2500, constructor:function(config) {
  var identity = dilocsync.core.Master.getIdentity();
  if (identity.options && identity.options.hasOwnProperty('currentPositionTimeout') && identity.options.currentPositionTimeout > 5) {
    this.currentPositionTimeout = identity.options.currentPositionTimeout;
  }
  if (identity.options && identity.options.gps && identity.options.gps.interval) {
    this.gpsInterval = identity.options.gps.interval;
  }
  this.geolocation = window.BackgroundGeolocation;
  this.initConfig(config);
  this.mixins.observable.constructor.call(this, config);
  this.callParent(arguments);
}, initialize:function() {
  var $jscomp$this = this;
  return new Promise(function(resolve, reject) {
    $jscomp$this.geolocation.on('location', function(_location) {
      return $jscomp$this.onLocation(_location);
    });
    $jscomp$this.geolocation.ready({locationAuthorizationRequest:'Always', desiredAccuracy:$jscomp$this.geolocation.DESIRED_ACCURACY_HIGH, distanceFilter:0, disableElasticity:true, activityType:$jscomp$this.geolocation.ACTIVITY_TYPE_AUTOMOTIVE_NAVIGATION, locationUpdateInterval:2000, disableStopDetection:true, disableMotionActivityUpdates:true, pausesLocationUpdatesAutomatically:false, backgroundPermissionRationale:{title:$jscomp$this.tr("Allow %1 to access to this device's location in the background?").arg('{applicationName}'), 
    message:$jscomp$this.tr('In order to track the stations in the background, please enable %1 location permission.').arg('{backgroundPermissionOptionLabel}'), positiveAction:$jscomp$this.tr('Change to %1').arg('"{backgroundPermissionOptionLabel}"'), negativeAction:$jscomp$this.tr('Cancel')}, logLevel:$jscomp$this.geolocation.LOG_LEVEL_OFF}, function() {
      cnconsult.Logger.log({message:'Geolocation ready', prefix:$jscomp$this.prefix + '-\x3einitialize', level:'debug'});
      $jscomp$this.setupRideUid();
      var storage = dilocsync.core.Master.getStorage();
      if (!storage.get('page:driveInfo:permissionDialogConfirmed')) {
        dilocsync.util.MessageHelper.showAcknowledge($jscomp$this.tr('Background location access'), $jscomp$this.tr('DiLoc|Sync collects location data to track stations for the route knowledge.') + '\x3cbr\x3e' + $jscomp$this.tr('Once the drive has been started, locations are tracked even when the app is not in use.'), function() {
          storage.set('page:driveInfo:permissionDialogConfirmed', true);
          resolve();
        }, $jscomp$this);
      } else {
        resolve();
      }
    }, function() {
      cnconsult.Logger.log({message:'Geolocation not ready', prefix:$jscomp$this.prefix + '-\x3einitialize', level:'error'});
      reject('Geolocation not ready');
    });
  });
}, onLocation:function(_location) {
  cnconsult.Logger.log({message:'Position updated', prefix:this.prefix + '-\x3eonLocation', level:'debug', dump:_location});
  this.rideDataHandler.addCoordinateForCurrentRide({lat:_location.coords.latitude, lon:_location.coords.longitude, accuracy:_location.coords.accuracy, time:Math.floor(_location.timestamp.getTime() / 1000)});
}, setupRideUid:function() {
  var storage = dilocsync.core.Master.getStorage();
  if (!storage.get('page:driveInfo:rideUid')) {
    var rideUid = Date.now() + '' + Ext.Number.randomInt(1000, 9999);
    storage.set('page:driveInfo:rideUid', rideUid);
  }
}, start:function() {
  var $jscomp$this = this;
  cnconsult.Logger.log({message:'Start GPS tracking', prefix:this.prefix + '-\x3estart', level:'debug'});
  this.geolocation.start(function() {
    $jscomp$this.setGPS(true);
    $jscomp$this.geolocation.changePace(true);
  });
}, stop:function() {
  cnconsult.Logger.log({message:'Stopped GPS tracking', prefix:this.prefix + '-\x3estop', level:'debug'});
  if (this.geolocation) {
    this.geolocation.stop();
    this.setGPS(false);
  }
  clearInterval(this.getCurrentPositionInterval);
  this.getCurrentPositionInterval = null;
}, setGPS:function(_state) {
  Ext.fireEvent('gpsSignal', _state);
  this.gpsSignal = _state;
}, getCurrentPosition:function() {
  return this.geolocation.getCurrentPosition({timeout:this.currentPositionTimeout, desiredAccuracy:this.geolocation.DESIRED_ACCURACY_HIGH, maximumAge:1000, persist:true, samples:1});
}, getOneTimePosition:function() {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    $jscomp$this.geolocation.requestPermission().then(function() {
      $jscomp$this.getCurrentPosition().then(function(_location) {
        _resolve({latitude:_location.coords.latitude, longitude:_location.coords.longitude});
      })['catch'](_reject);
    })['catch'](_reject);
  });
}});
Ext.define('dilocsync.model.RouteKnowledgeRide', {extend:Ext.data.Model, alias:'model.routeknowledgeride', config:{fields:[{name:'submit', type:'boolean'}, {name:'trainNumber', type:'string'}, {name:'createdOn', type:'date'}, {name:'idCodes', type:'array'}, {name:'visitedStations', type:'array'}, {name:'gpsLog', type:'array'}, {name:'appVersion', type:'string'}, {name:'drivenSegments', type:'string'}]}, idProperty:'createdOn'});
Ext.define('dilocsync.store.RouteKnowledgeRides', {extend:dilocsync.store.DiLocStorage, storeId:'RouteKnowledgeRides', model:'dilocsync.model.RouteKnowledgeRide', saveKey:'page:driveInfo:routeknowledgerides', alias:'store.routeknowledgerides', autoLoad:true});
Ext.define('dilocsync.view.components.station.SelectStationDialogModel', {extend:Ext.app.ViewModel, alias:'viewmodel.selectStationDialog', data:{station:null, saveButtonText:'', geoStationTracker:null, disableNearbyStations:false}});
Ext.define('dilocsync.view.components.station.SelectStationDialogController', {extend:Ext.app.ViewController, alias:'controller.selectStationDialog', mixins:[cnconsult.Translatable], config:{bufferedSearch:null}, init:function() {
  var $jscomp$this = this;
  var store = dilocsync.util.Helper.initStore('AllStations');
  this.setBufferedSearch(Ext.Function.createBuffered(function(_value) {
    var list = $jscomp$this.lookup('allStationsList');
    var result = [];
    if (_value && _value.length > 2) {
      var records = store.query('enhancedName', _value, true);
      records.each(function(_record) {
        result.push({identifier:_record.get('identifier'), name:_record.get('name'), latitude:_record.get('latitude'), longitude:_record.get('longitude')});
      });
    }
    $jscomp$this.onStationDeselect();
    list.setData(result);
  }, 1000, this));
  if (store.isLoaded()) {
    this.initNearbyStations();
  } else {
    store.on('load', function() {
      this.initNearbyStations();
    }, this, {single:true});
  }
}, initNearbyStations:function() {
  var $jscomp$this = this;
  var viewModel = this.getViewModel();
  if (!viewModel.get('disableNearbyStations')) {
    viewModel.get('geoStationTracker').getOneTimePosition().then(function(_position) {
      var store = dilocsync.util.Helper.initStore('AllStations');
      var list = $jscomp$this.lookup('nearbyStationsList');
      var result = [];
      var geoMinMaxValues = $jscomp$this.calculateCoordinateMinMaxValues(_position);
      var records = store.queryBy(function(_record) {
        return _record.get('latitude') >= geoMinMaxValues.latMin && _record.get('latitude') <= geoMinMaxValues.latMax && _record.get('longitude') >= geoMinMaxValues.lonMin && _record.get('longitude') <= geoMinMaxValues.lonMax;
      });
      records.each(function(_record) {
        var distance = haversine(_position, {latitude:_record.get('latitude'), longitude:_record.get('longitude')}).toFixed(0);
        if (distance <= 1000) {
          result.push({identifier:_record.get('identifier'), name:_record.get('name'), latitude:_record.get('latitude'), longitude:_record.get('longitude'), distance:distance});
        }
      });
      result.sort(function(a, b) {
        return a.distance - b.distance;
      });
      if (result.length > 0) {
        list.setData(result);
      } else {
        list.setEmptyText($jscomp$this.tr('No stations to display'));
      }
    })['catch'](function() {
      dilocsync.util.MessageHelper.showMessage({title:$jscomp$this.tr('GPS Error'), message:$jscomp$this.tr('Failed to locate nearby stations. Please ensure that the GPS is enabled!'), buttons:[{text:$jscomp$this.tr('Try again'), handler:function(_btn) {
        _btn.up('messagebox').destroy();
        $jscomp$this.initNearbyStations();
      }}, {text:$jscomp$this.tr('Close'), handler:function(_btn) {
        _btn.up('messagebox').destroy();
      }}], scope:$jscomp$this});
    });
  }
}, calculateCoordinateMinMaxValues:function(_location) {
  var coef = 1000 * 8.9E-6;
  var lat = _location.latitude;
  var lon = _location.longitude;
  return {latMin:lat - coef, latMax:lat + coef, lonMin:lon - coef / Math.cos(lat * 0.018), lonMax:lon + coef / Math.cos(lat * 0.018)};
}, onSearchChange:function(_field, _value) {
  this.getBufferedSearch()(_value);
}, onSearchClear:function() {
  this.onStationDeselect();
  this.lookup('allStationsList').setData([]);
}, onStationSelect:function(_list, _record) {
  this.getViewModel().set('station', _record);
}, onStationDeselect:function() {
  this.getViewModel().set('station', null);
}, showNearbyStations:function() {
  this.lookup('allStationsList').getSelectable().deselectAll();
  this.lookup('searchList').hide();
  this.lookup('nearbyStations').show();
}, showSearchList:function() {
  this.lookup('nearbyStationsList').getSelectable().deselectAll();
  this.lookup('nearbyStations').hide();
  this.lookup('searchList').show();
}, onSetStationTapped:function() {
  this.getView().fireEvent('stationSelected', this.getView(), this.getViewModel().get('station'));
}, onBeforeShow:function() {
  var hiddenViewers = Ext.callback(function() {
    var previousHiddenViewers = dilocsync.util.FileViewerHelper.getHiddenFileViewers();
    if (previousHiddenViewers) {
      dilocsync.util.FileViewerHelper.setHiddenFileViewers(null);
      return previousHiddenViewers;
    }
    return dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  });
  this.getView().on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
}});
Ext.define('dilocsync.view.components.station.SelectStationDialog', {extend:Ext.Dialog, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'selectStationDialog', viewModel:{type:'selectStationDialog'}, controller:'selectStationDialog', cls:'dilocsync-station-select-station-dialog', centered:true, closable:true, maskTapHandler:'destroy', layout:{type:'vbox', align:'stretch'}, responsiveConfig:{'phone':{width:'80%', height:'80%'}, '(tablet \x26\x26 landscape) || desktop':{width:'50%', height:'80%'}, 
'tablet \x26\x26 portrait':{width:'80%', height:'50%'}}, listeners:{beforeshow:'onBeforeShow'}, initialize:function() {
  var $jscomp$this = this;
  var disableNearbyStations = this.getViewModel().get('disableNearbyStations');
  this.setItems([{xtype:'container', reference:'nearbyStations', flex:1, layout:{type:'vbox', align:'stretch'}, items:this.getNearbyStationsItems(), hidden:disableNearbyStations}, {xtype:'container', reference:'searchList', flex:1, layout:{type:'vbox', align:'stretch'}, items:this.getSearchListItems(), hidden:!disableNearbyStations}, {xtype:'toolbar', docked:'bottom', items:['-\x3e', {xtype:'button', handler:'onSetStationTapped', ui:'confirm', disabled:true, bind:{text:'{saveButtonText}', disabled:'{!station}'}}]}]);
  this.callParent(arguments);
  if (disableNearbyStations) {
    Ext.defer(function() {
      $jscomp$this.lookup('searchField').focus();
    }, 1000);
  }
}, getNearbyStationsItems:function() {
  return [{xtype:'label', html:this.tr('Nearby stations:')}, {xtype:'list', reference:'nearbyStationsList', flex:'0 1 auto', minHeight:50, itemTpl:['{identifier} - {name}', '\x3cdiv class\x3d"nearby-station-list-distance"\x3e{distance}m\x3c/div\x3e'], data:[], deferEmptyText:false, emptyText:this.tr('Nearby Stations loading...'), listeners:{select:'onStationSelect', deselect:'onStationDeselect'}}, {xtype:'button', text:this.tr('Select station manually'), ui:'content-button', handler:'showSearchList', 
  margin:'30 0 0 0'}];
}, getSearchListItems:function() {
  return [{xtype:'searchfield', reference:'searchField', label:this.tr('Search in stations list'), listeners:{change:'onSearchChange', clearicontap:'onSearchClear'}}, {xtype:'list', reference:'allStationsList', flex:'0 1 auto', minHeight:50, itemTpl:'{identifier} - {name}', data:[], deferEmptyText:false, emptyText:this.tr('Enter a search term'), listeners:{select:'onStationSelect', deselect:'onStationDeselect'}}, {xtype:'button', text:this.tr('Show nearby stations'), ui:'content-button', handler:'showNearbyStations', 
  margin:'30 0 0 0', hidden:this.getViewModel().get('disableNearbyStations')}];
}});
Ext.define('dilocsync.view.main.MainController', {extend:Ext.app.ViewController, mixins:[cnconsult.Translatable], alias:'controller.main', listen:{global:{'passwordChangeRequired':'onPasswordChangeRequired', 'gpsSignal':'onGpsSignal', 'startDriveAdvisory':'onStartDriveAdvisory', 'stopDriveAdvisory':'onStopDriveAdvisory', 'startGpsTracking':'showGpsRideDialog', 'stopGpsTracking':'showGpsRideDialog', 'startDigitalOrder':'onStartDigitalOrder', 'stopDigitalOrder':'onStopDigitalOrder'}}, geoStationTracker:null, 
farsightRearviewInterval:null, rideDataHandler:null, inactiveMessageTimeout:null, init:function() {
  this.checkEnableDriveActivity();
  this.initDriveInfoData();
  this.checkIfDriveAdviceMessagesShouldBeHidden();
  this.getViewModel().bind('{gpsTrackingStarted}', function(_gpsTrackingStarted) {
    if (_gpsTrackingStarted) {
      this.inactiveMessageTimeout = Ext.defer(this.showInactiveMessage, 1000 * 60 * 60 * 12, this);
    } else {
      Ext.undefer(this.inactiveMessageTimeout);
    }
  }, this);
  dilocsync.core.DriveInfoDasManager.on('dasc', this.onDasChange, this);
  dilocsync.core.DriveInfoDasManager.on('farsightRearview', this.onFarsightRearviewChange, this);
  dilocsync.core.DriveInfoDasManager.on('authenticationFailed', this.onDasAuthenticationFailed, this);
  dilocsync.core.Master.getSyncEngine().on('identitychanged', this.onIdentityChanged, this);
}, checkIfDriveAdviceMessagesShouldBeHidden:function() {
  var master = dilocsync.core.Master;
  var viewModel = this.getViewModel();
  var identity = master.getIdentity();
  if (identity && identity.options && identity.options.hasOwnProperty('enableFarsightRearviewFullWidth')) {
    viewModel.set('farsightRearviewFullWidth', identity.options.enableFarsightRearviewFullWidth);
  }
}, onIdentityChanged:function() {
  this.checkEnableDriveActivity();
  this.checkIfDriveAdviceMessagesShouldBeHidden();
}, checkEnableDriveActivity:function() {
  var helper = dilocsync.util.Identity;
  var identity = dilocsync.core.Master.getIdentity();
  this.getViewModel().set('enableDriveAdvisory', !!helper.getOption(identity, 'enableDriveAdvisory'));
  if (dilocsync.util.Platform.supportsGpsTracking()) {
    if (!this.rideDataHandler) {
      this.rideDataHandler = Ext.create('dilocsync.util.RideDataHandler');
      this.rideDataHandler.submitData();
    }
    this.getViewModel().set('enableGpsTracking', !!helper.getOption(identity, 'enableGpsTracking'));
  }
}, initDriveInfoData:function() {
  var storage = dilocsync.core.Master.getStorage();
  var viewModel = this.getViewModel();
  viewModel.set('trainNumber', storage.get('page:driveInfo:trainNumber'));
  if (!storage.get('page:driveInfo:locomotionTypes')) {
    storage.remove('page:driveInfo:locomotionType');
  }
  viewModel.set('locomotionType', Ext.Array.from(storage.get('page:driveInfo:locomotionType')));
  viewModel.set('locoTypesStore', dilocsync.util.Helper.initStore('LocomotionTypes'));
  viewModel.set('digitalOrderTokens', dilocsync.util.Helper.initStore('DigitalOrderTokens'));
}, onDasChange:function(_type, _data) {
  this.getViewModel().set({'dascType':dilocsync.util.Helper.camelCaseToTitle(_type), 'dascData':_data});
}, onFarsightRearviewChange:function(_data) {
  var $jscomp$this = this;
  if (this.farsightRearviewInterval) {
    clearInterval(this.farsightRearviewInterval);
    this.farsightRearviewInterval = null;
  }
  this.setFarsightRearviewData(_data);
  if (_data && _data.hasOwnProperty('endValidity')) {
    this.farsightRearviewInterval = setInterval(function() {
      var endValidity = (new Date(_data.endValidity)).getTime();
      var now = (new Date).getTime();
      if (now > endValidity) {
        $jscomp$this.setFarsightRearviewData(null);
        clearInterval($jscomp$this.farsightRearviewInterval);
      }
    }, 1000);
  }
}, setFarsightRearviewData:function(_data) {
  this.getViewModel().set({'farsightRearview':_data});
}, onPasswordChangeRequired:function() {
  var syncEngine = dilocsync.core.Master.getSyncEngine();
  var hiddenViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  var dialog = Ext.create({xtype:'dialog', width:'90%', height:'90%', items:[{xtype:'user-change-password'}], buttons:{ok:function() {
    dialog.destroy();
  }}});
  syncEngine.abortSync();
  dialog.down('user-change-password').on('passwordchanged', function() {
    dialog.destroy();
    syncEngine.startSync();
  });
  dialog.on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
  dialog.show();
}, onStartGpsTracking:function(_continue) {
  var $jscomp$this = this;
  var initStationTracker = new Promise(function(_resolve, _reject) {
    if (!$jscomp$this.geoStationTracker) {
      $jscomp$this.geoStationTracker = Ext.create('dilocsync.util.GeoStationTracker', {rideDataHandler:$jscomp$this.rideDataHandler});
      $jscomp$this.geoStationTracker.initialize().then(_resolve);
    } else {
      $jscomp$this.geoStationTracker.setupRideUid();
      _resolve();
    }
  });
  initStationTracker.then(function() {
    if (_continue) {
      $jscomp$this.geoStationTracker.start();
      $jscomp$this.getViewModel().set('gpsTrackingStarted', true);
    } else {
      $jscomp$this.showSelectStationDialog($jscomp$this.tr('Select start station'), $jscomp$this.tr('Set station and start drive')).then(function(_station) {
        $jscomp$this.rideDataHandler.setStartStationForCurrentRide({identifier:_station.get('identifier'), name:_station.get('name'), uopId:_station.get('uopId'), lat:_station.get('latitude'), lon:_station.get('longitude'), time:Math.floor(Date.now() / 1000)});
        $jscomp$this.geoStationTracker.start();
        $jscomp$this.getViewModel().set('gpsTrackingStarted', true);
      });
    }
  });
}, showGpsRideDialog:function() {
  var $jscomp$this = this;
  var storage = dilocsync.core.Master.getStorage();
  var rideUid = storage.get('page:driveInfo:rideUid');
  if (!rideUid) {
    this.onStartGpsTracking();
  } else {
    var hiddenFileViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
    var viewModelData = {gpsTrackingStarted:this.getViewModel().get('gpsTrackingStarted')};
    if (!viewModelData.gpsTrackingStarted) {
      var ridesStore = dilocsync.util.Helper.initStore('Rides');
      viewModelData.ride = ridesStore.findRecord('rideUid', rideUid, 0, false, false, true);
      if (!viewModelData.ride) {
        dilocsync.util.FileViewerHelper.setHiddenFileViewers(hiddenFileViewers);
        this.onStartGpsTracking();
        return;
      }
    }
    Ext.create('dilocsync.view.components.gpsridedialog.GpsRideDialog', {viewModel:{data:viewModelData}, listeners:{continueRide:function() {
      dilocsync.util.FileViewerHelper.showHiddenFileViewers(hiddenFileViewers);
      $jscomp$this.onStartGpsTracking(true);
    }, pauseRide:function() {
      dilocsync.util.FileViewerHelper.showHiddenFileViewers(hiddenFileViewers);
      $jscomp$this.onStopGpsTracking(true);
    }, stopRide:function() {
      dilocsync.util.FileViewerHelper.setHiddenFileViewers(hiddenFileViewers);
      $jscomp$this.onStopGpsTracking();
    }, cancel:function() {
      dilocsync.util.FileViewerHelper.showHiddenFileViewers(hiddenFileViewers);
    }}}).show();
  }
}, showInactiveMessage:function() {
  var $jscomp$this = this;
  var autoPauseTimeout = setTimeout(function() {
    Ext.ComponentQuery.query('#inactiveMessageBox')[0].destroy();
    $jscomp$this.onStopGpsTracking(true);
  }, 1000 * 60 * 5);
  dilocsync.util.MessageHelper.showMessage({itemId:'inactiveMessageBox', title:this.tr('Take a break or continue?'), message:this.tr('You have been using GNSS tracking for more than 12 consecutive hours.\x3cbr\x3eTo save resources, GNSS tracking will be automatically paused shortly'), buttons:[{text:this.tr('Take a brake'), handler:function(_btn) {
    clearTimeout(autoPauseTimeout);
    $jscomp$this.onStopGpsTracking(true);
    _btn.up('messagebox').destroy();
  }}, {text:this.tr('Continue'), handler:function(_btn) {
    clearTimeout(autoPauseTimeout);
    _btn.up('messagebox').destroy();
  }}]});
}, showSelectStationDialog:function(_title, _buttonText, _disableNearbyStations) {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    Ext.create('dilocsync.view.components.station.SelectStationDialog', {title:_title, viewModel:{data:{saveButtonText:_buttonText, geoStationTracker:$jscomp$this.geoStationTracker, disableNearbyStations:_disableNearbyStations}}, listeners:{stationSelected:function(_dialog, _stationIdCode) {
      _dialog.destroy();
      _resolve(_stationIdCode);
    }}}).show();
  });
}, onStartDriveAdvisory:function() {
  this.getViewModel().set('driveAdvisoryPending', true);
  this.doTrainBinding();
}, onDasAuthenticationFailed:function() {
  this.doTrainUnbinding(true);
}, doTrainBinding:function() {
  var toolbar = this.lookup('bottomToolbar');
  var driveInfo = this.lookup('driveInfo');
  var farsightRearviewFullWidth = this.lookup('farsightRearviewFullWidth');
  var viewModel = this.getViewModel();
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var dascManager = dilocsync.core.DriveInfoDasManager;
  var trainDate = Ext.Date.format(viewModel.get('trainDate'), 'Y-m-d');
  Ext.Ajax.request({url:master.getBackendUrl() + '/trainbinding/bind', params:{syncSecret:storage.get('core:personalization:syncSecret'), trainNumber:storage.get('page:driveInfo:trainNumber'), trainDate:trainDate}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData) {
      if (responseData.result && responseData.result.hasOwnProperty('result') && responseData.result.result === 'ok') {
        if (!viewModel.get('farsightRearviewFullWidth')) {
          toolbar.setActiveItem(driveInfo);
        } else {
          toolbar.setActiveItem(farsightRearviewFullWidth);
        }
        viewModel.set('driveAdvisoryStarted', true);
        dascManager.init({trainDate:trainDate, trainNumber:storage.get('page:driveInfo:trainNumber'), dasCiTicket:responseData.result.dasCiTicket, dasProxyUrl:responseData.result.dasProxyUrl, trackDasC:responseData.result.trackDasC});
        dascManager.start();
      } else {
        if (responseData.result && responseData.result.hasOwnProperty('result') && responseData.result.result === 'failed') {
          console.error('Error train binding code: ' + responseData.errorCode + ' message: ' + responseData.errorMessage);
        } else {
          console.error('Error train binding result not defined');
        }
      }
    } else {
      console.error('Error train binding no response data');
    }
  }, failure:function() {
    console.error('Error train binding request failure');
  }, callback:function(_options, _success, _response) {
    viewModel.set('driveAdvisoryPending', false);
    if (!viewModel.get('driveAdvisoryStarted')) {
      if (_success) {
        var responseData = Ext.decode(_response.responseText, true);
        var errorMessage = responseData.backendError || responseData.result.errorMessage;
        dilocsync.util.MessageHelper.showError(this.tr('Start of drive advisory failed. The following error occurred: %1').arg(errorMessage));
      } else {
        dilocsync.util.MessageHelper.showError(this.tr('Start of drive advisory failed. Make sure you have a working internet connection and try again.'));
      }
    }
  }, scope:this});
}, doTrainUnbinding:function(_doRebind) {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var dascManager = dilocsync.core.DriveInfoDasManager;
  Ext.Ajax.request({url:master.getBackendUrl() + '/trainbinding/unbind', params:{syncSecret:storage.get('core:personalization:syncSecret'), trainNumber:storage.get('page:driveInfo:trainNumber'), trainDate:dascManager.getTrainDate()}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData) {
      if (responseData.result && responseData.result.hasOwnProperty('result') && responseData.result.result === 'ok') {
        dascManager.stop();
        if (_doRebind) {
          this.doTrainBinding();
        }
      } else {
        if (responseData.result && responseData.result.hasOwnProperty('result') && responseData.result.result === 'failed') {
          console.error('Error train unbind code: ' + responseData.errorCode + ' message: ' + responseData.errorMessage);
        } else {
          console.error('Error train unbind result not defined');
        }
      }
    } else {
      console.error('Error train unbind no response data');
    }
  }, failure:function() {
    console.error('Error train unbind request failure');
  }, scope:this});
}, onStopGpsTracking:function(_pause) {
  var $jscomp$this = this;
  if (_pause) {
    this.geoStationTracker.stop();
    this.getViewModel().set('gpsTrackingStarted', false);
  } else {
    this.showSelectStationDialog(this.tr('Select end station'), this.tr('Set station and stop drive'), !this.getViewModel().get('gpsTrackingStarted')).then(function(_station) {
      $jscomp$this.rideDataHandler.setEndStationForCurrentRide({identifier:_station.get('identifier'), name:_station.get('name'), uopId:_station.get('uopId'), lat:_station.get('latitude'), lon:_station.get('longitude'), time:Math.floor(Date.now() / 1000)});
      if ($jscomp$this.geoStationTracker) {
        $jscomp$this.geoStationTracker.stop();
      }
      dilocsync.core.Master.getStorage().remove('page:driveInfo:rideUid');
      dilocsync.core.Master.getStorage().remove('page:driveInfo:trainNumber');
      dilocsync.core.Master.getStorage().remove('page:driveInfo:locomotionType');
      $jscomp$this.getViewModel().set({gpsTrackingStarted:false, trainNumber:'', locomotionType:''});
    });
  }
}, onStopDriveAdvisory:function() {
  var tabMenu = this.lookup('tabMenu');
  this.getViewModel().set('driveAdvisoryStarted', false);
  this.lookup('bottomToolbar').setActiveItem(tabMenu);
  tabMenu.getController().updateToolbarLayout();
  this.doTrainUnbinding();
}, onStartDigitalOrder:function() {
  this.getViewModel().set('digitalOrderStarted', true);
}, onStopDigitalOrder:function() {
  this.getViewModel().set('digitalOrderStarted', false);
}, showSideMenu:function() {
  Ext.Viewport.showMenu('left');
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.main.MainController', src:'Main', action:'MenüAnzeigen', trackedAt:new Date});
}, onGpsSignal:function(_signal) {
  this.getViewModel().set('gpsSignal', _signal);
}});
Ext.define('dilocsync.view.main.MainModel', {extend:Ext.app.ViewModel, alias:'viewmodel.main', data:{trainNumber:'', trainDate:new Date, locomotionType:'', dascType:'', dascData:'', farsightRearview:null, enableDriveAdvisory:false, enableGpsTracking:false, driveAdvisoryPending:false, driveAdvisoryStarted:false, gpsTrackingStarted:false, digitalOrderStarted:false, digitalOrderDate:new Date, digitalOrderToken:null, digitalOrderUserRole:'LeadingTrainDriver', gpsSignal:false, farsightRearviewFullWidth:false}, 
formulas:{gpsSignalClass:{bind:'{gpsSignal}', get:function(_signalState) {
  return _signalState ? 'gps-signal-good' : 'gps-signal-bad';
}}, enableDigitalOrder:{bind:{length:'{digitalOrderTokens.data.length}', started:'{digitalOrderStarted}'}, get:function(_data) {
  if (_data.started) {
    return true;
  }
  return _data.length > 0;
}}}});
Ext.define('dilocsync.model.MenuItem', {extend:Ext.data.Model, fields:[{name:'label', type:'string'}, {name:'iconCls', type:'string'}, {name:'pressed', type:'boolean', defaultValue:false}, {name:'badgeText', type:'string'}, {name:'badgeFn'}, {name:'userCls', type:'string'}, {name:'order', type:'number'}, {name:'config'}, {name:'route', type:'string'}, {name:'view', type:'string'}, {name:'showInSideMenu', type:'boolean', defaultValue:false}, {name:'showInPhoneTabMenu', type:'boolean', defaultValue:false}, 
{name:'showInTabletTabMenu', type:'boolean', defaultValue:false}, {name:'isMenuButton', type:'boolean', defaultValue:false}, {name:'isSetupView', type:'boolean', defaultValue:false}]});
Ext.define('dilocsync.store.MenuItems', {extend:Ext.data.Store, storeId:'menuItems', model:'dilocsync.model.MenuItem', sorters:[{property:'order', direction:'ASC'}]});
Ext.define('dilocsync.view.menus.tabmenu.TabMenuModel', {extend:Ext.app.ViewModel, alias:'viewmodel.menusTabmenu', stores:{tabMenuItems:{source:'menuItems', storeId:'tabMenuItems', filters:[{property:Ext.os.deviceType === 'Phone' ? 'showInPhoneTabMenu' : 'showInTabletTabMenu', value:true}]}}, data:{}});
Ext.define('dilocsync.view.menus.AbstractMenuController', {extend:Ext.app.ViewController, mixins:[cnconsult.Translatable], config:{viewMenuItemsStoreId:''}, init:function() {
  this.updateViewMenuItems();
}, addMenuItemsToView:function() {
  var store = this.getStore(this.getViewMenuItemsStoreId());
  var items = [];
  store.each(function(_menuItemConfig) {
    var item = {text:_menuItemConfig.get('label'), iconCls:_menuItemConfig.get('iconCls'), userCls:_menuItemConfig.get('userCls'), badgeText:_menuItemConfig.get('badgeText'), pressed:_menuItemConfig.get('pressed'), menuItemId:_menuItemConfig.getId()};
    items.push(item);
  });
  this.getView().add(items);
  this.fireEvent('toolbaritemsadded');
}, initBadges:function() {
  var store = this.getStore(this.getViewMenuItemsStoreId());
  store.each(function(_menuItemConfig) {
    if (Ext.isFunction(_menuItemConfig.get('badgeFn'))) {
      _menuItemConfig.get('badgeFn')();
    }
  });
}, updateViewMenuItems:function() {
  this.getView().removeAll();
  this.initBadges();
  this.addMenuItemsToView();
}, updateMenuItem:function(_store, _record, _operation, _modifiedFieldNames) {
  var button = this.getView().down('[menuItemId\x3d' + _record.getId() + ']');
  if (button && Ext.isArray(_modifiedFieldNames)) {
    if (_modifiedFieldNames.includes('badgeText')) {
      button.setBadgeText(_record.get('badgeText'));
    }
    if (_modifiedFieldNames.includes('pressed')) {
      button.setPressed(_record.get('pressed'));
    }
  }
}, showSideMenu:function() {
  Ext.Viewport.showMenu('left');
}, hideSideMenu:function() {
  Ext.Viewport.hideMenu('left');
}, onMenuItemTap:function(_button) {
  var store = Ext.getStore('menuItems');
  var menuItem = store.getById(_button.menuItemId);
  var token = Ext.History.getToken();
  if (menuItem) {
    if (menuItem.get('isMenuButton')) {
      dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.menus.AbstractMenuController', src:'Main', action:'MenüButtonGeklickt', trackedAt:new Date, extras:{currentRoute:token, button:'menuButton'}});
      this.showSideMenu();
    } else {
      var currentView = null;
      if (token === 'forms') {
        currentView = Ext.Viewport.down(token);
      }
      var controller = currentView && Ext.isFunction(currentView.getController) ? currentView.getController() : null;
      if (!controller || !Ext.isFunction(controller.doRedirect) || controller.doRedirect()) {
        var route = menuItem.get('route');
        dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.menus.AbstractMenuController', src:'Main.GeheAufSeite', action:route, trackedAt:new Date, extras:{currentRoute:token, route:route, button:'menuButton'}});
        this.redirectTo(route, {force:true});
      }
    }
  }
}});
Ext.define('dilocsync.view.menus.tabmenu.TabMenuController', {extend:dilocsync.view.menus.AbstractMenuController, alias:'controller.menusTabmenu', listen:{store:{'#tabMenuItems':{'add':'updateViewMenuItems', 'update':'updateMenuItem'}}, component:{'button':{tap:'onMenuItemTap'}}}, config:{viewMenuItemsStoreId:'tabMenuItems'}, init:function() {
  this.callParent(arguments);
  Ext.Viewport.on('orientationchange', this.updateToolbarLayout, this);
  Ext.Viewport.on('resize', this.updateToolbarLayout, this);
  this.on('toolbaritemsadded', this.updateToolbarLayout, this);
}, updateToolbarLayout:function() {
  var completeWidth = 0;
  var offset = 20;
  var view = this.getView();
  var toolbarButtons = view.getItems().items;
  var screenWidth = dilocsync.util.Screen.getScreenWidth();
  var parentItems = view.getParent().getItems().items;
  toolbarButtons.forEach(function(_value) {
    completeWidth += _value.el.getWidth();
  });
  parentItems.forEach(function(_value) {
    if (_value.isXType('button') && _value.isVisible()) {
      completeWidth += _value.el.getWidth();
    }
  });
  if (completeWidth + offset > screenWidth) {
    view.setLayout({pack:'start'});
  } else {
    view.setLayout({pack:'center'});
  }
}});
Ext.define('dilocsync.view.menus.tabmenu.TabMenu', {extend:Ext.Toolbar, xtype:'menusTabmenu', viewModel:{type:'menusTabmenu'}, controller:'menusTabmenu', cls:'dilocsync-tabmenu', ui:'tabmenu-toolbar', scrollable:true, layout:{type:'hbox'}, defaults:{iconAlign:'top', ui:'tabmenu-button'}});
Ext.define('dilocsync.view.components.liveticker.LiveTicker', {extend:Ext.Component, xtype:'liveticker', mixins:[cnconsult.Translatable], cls:'dilocsync-live-ticker', controller:'liveticker', config:{message:null}, applyMessage:function(_newMessage, _oldMessage) {
  if (_newMessage !== _oldMessage) {
    return _newMessage;
  }
}, updateMessage:function(_newMessage) {
  this.setLiveTickerText(_newMessage);
}, setLiveTickerText:function(_message) {
  var marqueeEl = this.el.down('.marquee3k');
  if (marqueeEl && marqueeEl.hasCls('is-init')) {
    Marquee3k.stopAll();
  }
  this.setHtml(_message ? '\x3cdiv class\x3d"marquee3k" data-speed\x3d"1"\x3e\x3cp\x3e' + _message + '\x3c/p\x3e\x3c/div\x3e' : '');
  if (_message) {
    Ext.defer(function() {
      Marquee3k.init();
    }, 200);
  }
}});
Ext.define('dilocsync.view.components.farsightRearview.FarsightRearviewController', {extend:Ext.app.ViewController, alias:'controller.farsightRearview', bindings:{onFarsightRearviewChange:'{farsightRearview}'}, init:function() {
  var view = this.getView();
  view.on('initialize', this.onViewInitialize, this);
}, onViewInitialize:function() {
  var data = this.getViewModel().get('farsightRearview');
  this.onFarsightRearviewChange(data);
}, onFarsightRearviewChange:function(data) {
  if (data && data.rearview) {
    var rearviewItems = this.getDirectionItems(data.rearview, 'rearview');
    this.lookup('rearviewBlocks').setItems(Ext.clone(rearviewItems).reverse());
  }
  if (data && data.farsight) {
    var farsightItems = this.getDirectionItems(data.farsight, 'farsight');
    this.lookup('farsightBlocks').setItems(farsightItems);
  }
}, getDirectionItems:function(blocks, direction) {
  var items = [];
  var displayBlock = null;
  Ext.Array.each(blocks, function(block, index) {
    var item;
    if (Ext.isObject(block)) {
      if (Ext.Object.isEmpty(block)) {
        item = {cls:'dilocsync-farsight-rearview-block dilocsync-farsight-rearview-block-free'};
      } else {
        item = {cls:'dilocsync-farsight-rearview-block dilocsync-farsight-rearview-block-blocked'};
        if (!displayBlock) {
          displayBlock = block;
        }
      }
    } else {
      item = {cls:'dilocsync-farsight-rearview-block dilocsync-farsight-rearview-block-no-info'};
    }
    items.push(item);
  }, this);
  this.getViewModel().set(direction + 'DisplayBlock', displayBlock);
  return items;
}});
Ext.define('dilocsync.view.components.farsightRearview.FarsightRearviewModel', {extend:Ext.app.ViewModel, alias:'viewmodel.farsightRearview', data:{rearviewDisplayBlock:null, farsightDisplayBlock:null}, formulas:{rearviewTopText:{bind:{bindTo:'{rearviewDisplayBlock}', deep:true}, get:function(_block) {
  var text = '';
  if (_block) {
    if (_block.trainCategory) {
      text += _block.trainCategory + ' ';
    }
    if (_block.averageSpeed) {
      text += _block.averageSpeed + ' km/h';
    }
  }
  return text;
}}, rearviewBottomText:{bind:{bindTo:'{rearviewDisplayBlock}', deep:true}, get:function(_block) {
  var text = '';
  if (_block) {
    if (_block.distance) {
      text += 'ca. ' + _block.distance + 'm ';
    }
    if (_block.lzbOrEtcsLead) {
      text += '|LZB|';
    }
  }
  return text;
}}, farsightTopText:{bind:{bindTo:'{farsightDisplayBlock}', deep:true}, get:function(_block) {
  var text = '';
  if (_block) {
    if (_block.trainCategory) {
      text += _block.trainCategory + ' ';
    }
    if (_block.averageSpeed) {
      text += _block.averageSpeed + ' km/h';
    }
  }
  return text;
}}, farsightBottomText:{bind:{bindTo:'{farsightDisplayBlock}', deep:true}, get:function(_block) {
  var text = '';
  if (_block) {
    if (_block.distance) {
      text += 'ca. ' + _block.distance + 'm ';
    }
    if (_block.lzbOrEtcsLead) {
      text += '|LZB|';
    }
  }
  return text;
}}}});
Ext.define('dilocsync.view.components.farsightRearview.FarsightRearview', {extend:Ext.Container, xtype:'farsightRearview', controller:'farsightRearview', viewModel:{type:'farsightRearview'}, mixins:[cnconsult.Translatable], layout:{type:'hbox', align:'stretch'}, cls:'dilocsync-farsight-rearview', initialize:function() {
  var me = this;
  me.setItems([{xtype:'container', layout:{type:'vbox', align:'stretch'}, cls:'dilocsync-farsight-rearview-display', items:[{xtype:'component', height:20, bind:{html:'{rearviewTopText}'}}, {xtype:'container', layout:{type:'hbox', align:'stretch'}, defaults:{xtype:'component'}, reference:'rearviewBlocks'}, {xtype:'component', height:20, bind:{html:'{rearviewBottomText}'}}]}, {xtype:'component', cls:'dilocsync-farsight-rearview-triangle'}, {xtype:'container', layout:{type:'vbox', align:'stretch'}, 
  cls:'dilocsync-farsight-rearview-display', items:[{xtype:'component', height:20, bind:{html:'{farsightTopText}'}}, {xtype:'container', layout:{type:'hbox', align:'stretch'}, reference:'farsightBlocks'}, {xtype:'component', height:20, bind:{html:'{farsightBottomText}'}}]}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.farsightrearviewfullwidth.FarsightRearviewFullWidthController', {extend:Ext.app.ViewController, alias:'controller.farsightRearviewFullWidth', mixins:[cnconsult.Translatable], init:function() {
  var $jscomp$this = this;
  this.getViewModel().bind('{farsightRearview}', function(_data) {
    return $jscomp$this.processData(_data);
  });
}, processData:function(_farsightRearviewData) {
  if (_farsightRearviewData) {
    this.getViewModel().set({rearview:this.buildData(_farsightRearviewData.rearview), farsight:this.buildData(_farsightRearviewData.farsight)});
  } else {
    var defaultData = {speed:null, distance:null, states:{0:'unknown', 1:'unknown', 2:'unknown', 3:'unknown', 4:'unknown'}};
    this.getViewModel().set({rearview:defaultData, farsight:defaultData});
  }
}, buildData:function(_trains) {
  var data = {states:{}};
  Ext.Array.each(_trains, function(_trainInfo, _index) {
    if (_trainInfo === null) {
      data.states[_index] = 'unknown';
    } else {
      if (Ext.Object.isEmpty(_trainInfo)) {
        data.states[_index] = 'free';
      } else {
        if (!Object.values(data.states).includes('busy')) {
          if (_trainInfo.averageSpeed) {
            data.speed = _trainInfo.trainCategory + ' ' + _trainInfo.averageSpeed;
          }
          if (_trainInfo.distance) {
            data.distance = _trainInfo.distance + 'm';
            if (_trainInfo.lzbOrEtcsLead) {
              data.distance += ' [LZB]';
            }
          }
        }
        data.states[_index] = 'busy';
      }
    }
  });
  return data;
}});
Ext.define('dilocsync.view.components.farsightrearviewfullwidth.FarsightRearviewFullWidthModel', {extend:Ext.app.ViewModel, alias:'viewmodel.farsightRearviewFullWidth', data:{rearview:{speed:null, distance:null, states:{0:'unknown', 1:'unknown', 2:'unknown', 3:'unknown', 4:'unknown'}}, farsight:{speed:null, distance:null, states:{0:'unknown', 1:'unknown', 2:'unknown', 3:'unknown', 4:'unknown'}}}});
Ext.define('dilocsync.view.components.farsightrearviewfullwidth.FarsightRearviewFullWidth', {extend:Ext.Container, mixins:[cnconsult.Translatable], xtype:'farsightRearviewFullWidth', viewModel:{type:'farsightRearviewFullWidth'}, controller:'farsightRearviewFullWidth', cls:'farsightRearviewFullWidth', initialize:function() {
  this.setItems([{xtype:'container', layout:{type:'hbox', pack:'center', align:'stretch'}, items:[{style:'text-align: right', flex:1, bind:{html:'\x3ch3\x3e{rearview.speed} km/h\x3c/h3\x3e', style:'visibility: {rearview.speed ? "visible" : "hidden"}'}}, {xtype:'container', layout:{type:'hbox', pack:'center', align:'stretch'}, flex:3, items:[{bind:{html:'\x3cdiv class\x3d"step {rearview.states.4}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step {rearview.states.3}"\x3e\x26nbsp;\x3c/div\x3e'}, 
  cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step {rearview.states.2}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step {rearview.states.1}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step {rearview.states.0}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step own"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step {farsight.states.0}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, 
  {bind:{html:'\x3cdiv class\x3d"step {farsight.states.1}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step {farsight.states.2}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step {farsight.states.3}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}, {bind:{html:'\x3cdiv class\x3d"step {farsight.states.4}"\x3e\x26nbsp;\x3c/div\x3e'}, cls:'step-el'}]}, {flex:1, bind:{html:'\x3ch3\x3e{farsight.speed} km/h\x3c/h3\x3e', style:'visibility: {farsight.speed ? "visible" : "hidden"}'}}]}, 
  {xtype:'container', layout:{type:'hbox', pack:'center', align:'stretch'}, items:[{flex:1}, {style:'text-align: center', flex:1, bind:{html:'\x3ch5\x3eca. {rearview.distance}\x3c/h5\x3e', style:'visibility: {rearview.distance ? "visible" : "hidden"}'}}, {style:'text-align: center', flex:1, bind:{html:'\x3ch5\x3eca. {farsight.distance}\x3c/h5\x3e', style:'visibility: {farsight.distance ? "visible" : "hidden"}'}}, {flex:1}]}]);
}});
Ext.define('dilocsync.view.main.Main', {extend:Ext.Panel, xtype:'app-main', mixins:[cnconsult.Translatable], controller:'main', viewModel:'main', layout:'card', initialize:function() {
  var toolbarItems = [{docked:'left', xtype:'button', text:this.tr('GNSS'), iconCls:'x-fa fa-play', iconAlign:'top', ui:'tabmenu-button', cls:'dilocsync-button-drive-start', handler:'showGpsRideDialog', bind:{hidden:'{gpsTrackingStarted || !trainNumber || !enableGpsTracking}'}}, {docked:'left', xtype:'button', text:this.tr('Stop'), hidden:true, iconCls:'x-fa fa-stop', iconAlign:'top', ui:'tabmenu-button', cls:'dilocsync-button-drive-stop', handler:'showGpsRideDialog', bind:{hidden:'{!gpsTrackingStarted}'}}, 
  {docked:'left', xtype:'button', text:this.tr('Menu'), iconAlign:'top', ui:'tabmenu-button', iconCls:'x-fa fa-bars', handler:'showSideMenu'}, {docked:'left', xtype:'farsightRearview', bind:{hidden:'{!driveAdvisoryStarted || farsightRearviewFullWidth}'}}, {xtype:'menusTabmenu', reference:'tabMenu'}, {xtype:'farsightRearviewFullWidth', reference:'farsightRearviewFullWidth'}, {xtype:'container', reference:'driveInfo', cls:'dilocsync-driveinfo', layout:{type:'hbox', pack:'center', align:'stretch'}, 
  items:[{xtype:'component', bind:{hidden:'{!dascData.optimalSpeed}', html:'\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-train"\x3e\x3c/span\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-text"\x3e{dascData.optimalSpeed \x3d\x3d\x3d 999 ? "VMax" : dascData.optimalSpeed + " km/h"}\x3c/span\x3e'}, cls:'dilocsync-driveinfo-widget'}, {xtype:'component', bind:{hidden:'{!dascData.location}', html:'\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-map-signs"\x3e\x3c/span\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-text"\x3e{dascData.location}\x3c/span\x3e'}, 
  cls:'dilocsync-driveinfo-widget'}, {xtype:'component', bind:{data:{reasonCode:'{dascData.reasonCode}'}}, tpl:'\x3ctpl if\x3d"reasonCode\x3d\x3d\'followTrain\'"\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-arrow-right"\x3e\x3c/span\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-arrow-right dilocsync-warning"\x3e\x3c/span\x3e\x3c/tpl\x3e' + '\x3ctpl if\x3d"reasonCode\x3d\x3d\'energyOptimisation\'"\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-arrow-right"\x3e\x3c/span\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-leaf dilocsync-ok"\x3e\x3c/span\x3e\x3c/tpl\x3e' + 
  '\x3ctpl if\x3d"reasonCode\x3d\x3d\'timeSupplementRequired\'"\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-train"\x3e\x3c/span\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-fast-forward"\x3e\x3c/span\x3e\x3c/tpl\x3e' + '\x3ctpl if\x3d"reasonCode\x3d\x3d\'trainDelayed\'"\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-train"\x3e\x3c/span\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-clock dilocsync-warning"\x3e\x3c/span\x3e\x3c/tpl\x3e' + 
  '\x3ctpl if\x3d"reasonCode\x3d\x3d\'trainCrossing\'"\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-arrow-right"\x3e\x3c/span\x3e\x3cspan class\x3d"dilocsync-driveinfo-widget-icon x-fa fa-refresh dilocsync-warning"\x3e\x3c/span\x3e\x3c/tpl\x3e', cls:'dilocsync-driveinfo-widget'}]}, {xtype:'button', docked:'right', text:this.tr('Stop'), iconCls:'x-fa fa-stop', iconAlign:'top', ui:'tabmenu-button', cls:'dilocsync-button-drive-stop', handler:function() {
    dilocsync.util.DigitalOrderHelper.stop();
  }, hidden:true, bind:{hidden:'{!digitalOrderStarted}'}}, {xtype:'digitalordertoolbar', docked:'right', hidden:true, bind:{hidden:'{!digitalOrderStarted}'}}];
  this.setItems([{docked:'bottom', xtype:'container', reference:'bottomToolbar', layout:{type:'card'}, height:94, cls:'dilocsync-bottom-bar', items:toolbarItems}, {xtype:'liveticker', docked:'bottom'}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.menus.sidemenu.SideMenuModel', {extend:Ext.app.ViewModel, alias:'viewmodel.sidemenu', stores:{sideMenuItems:{source:'menuItems', storeId:'sideMenuItems', filters:[{property:'showInSideMenu', value:true}]}}});
Ext.define('dilocsync.view.menus.sidemenu.SideMenuController', {extend:dilocsync.view.menus.AbstractMenuController, alias:'controller.sidemenu', listen:{store:{'#sideMenuItems':{'add':'updateViewMenuItems', 'update':'updateMenuItem'}}, component:{'button':{tap:'onMenuItemTap'}}}, config:{viewMenuItemsStoreId:'sideMenuItems', hiddenViewers:[], lastRoute:''}, onMenuItemTap:function(_button) {
  this.callParent(arguments);
  this.hideSideMenu();
}, onShow:function() {
  this.setLastRoute(Ext.History.getToken());
  this.setHiddenViewers(dilocsync.util.FileViewerHelper.hideVisibleFileViewers());
}, onHide:function() {
  if (this.getLastRoute() === Ext.History.getToken()) {
    dilocsync.util.FileViewerHelper.showHiddenFileViewers(this.getHiddenViewers());
  }
}, logout:function() {
  dilocsync.core.Master.reloadApplication();
}});
Ext.define('dilocsync.view.menus.sidemenu.SideMenu', {extend:Ext.ActionSheet, xtype:'sidemenu', viewModel:{type:'sidemenu'}, controller:'sidemenu', scrollable:true, width:300, defaults:{iconAlign:'left', textAlign:'left', ui:'sidemenu-button'}, listeners:{show:'onShow', hide:'onHide'}, initialize:function() {
  this.setItems([{xtype:'toolbar', docked:'bottom', hidden:!dilocsync.util.MultiUserSupport.isEnabled(), reference:'logoutToolbar', items:[{text:'Logout', ui:'toolbar-button', iconCls:'x-fa fa-sign-out-alt', handler:'logout'}]}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.model.Website', {extend:Ext.data.Model, fields:[{name:'title', type:'string'}, {name:'url', type:'string'}, {name:'addressBarLocked', type:'boolean'}, {name:'toolBarHidden', type:'boolean'}, {name:'printEnabled', type:'boolean'}, {name:'openWithSystemBrowser', type:'boolean'}, {name:'previewImageUrl', type:'string', calculate:function(values) {
  return dilocsync.core.Master.getBackendUrl() + '/api/url2img/?url\x3d' + values.url + '\x26thumbnailWidth\x3d300\x26thumbnailHeight\x3d300\x26thumbnail\x3dtrue';
}}]});
Ext.define('dilocsync.store.Websites', {extend:Ext.data.Store, storeId:'websites', model:'dilocsync.model.Website'});
Ext.define('dilocsync.model.Favorite', {extend:Ext.data.Model, identifier:'uuid', fields:[{name:'uuid', type:'string'}, {name:'name', type:'string'}, {name:'checksum', type:'string'}, {name:'fileType', type:'string'}, {name:'validFrom', type:'date'}, {name:'validTo', type:'date'}, {name:'path', type:'string'}, {name:'icon', type:'string'}, {name:'rootFsEntryName', type:'string'}, {name:'almanacIdentifier'}, {name:'almanacPath'}, {name:'markedAsFavoriteDate'}, {name:'group', type:'string', defaultValue:'local'}]});
Ext.define('dilocsync.store.Favorites', {extend:dilocsync.store.DiLocStorage, storeId:'Favorites', model:'dilocsync.model.Favorite', sorters:'name', groupDir:'ASC', saveKey:'page:favorites:favoriteRecords'});
Ext.define('dilocsync.store.DiLocTreeStorage', {extend:Ext.data.TreeStore, config:{saveKey:''}, sync:function() {
  var data = this.getRoot().serialize();
  data = Ext.encode(data);
  dilocsync.core.Master.getStorage().set(this.getSaveKey(), data);
}, load:function() {
  var tree = dilocsync.core.Master.getStorage().get(this.getSaveKey());
  if (tree && tree.children && tree.children.length > 0) {
    this.setRoot(tree);
    this.getRoot().expand();
  } else {
    this.setRoot({expanded:false, autoRoot:true});
  }
}});
Ext.define('dilocsync.model.Dossier', {extend:Ext.data.TreeModel, identifier:'uuid', fields:[{name:'name', type:'string'}, {name:'icon', type:'string', defaultValue:'folder'}, {name:'createdAt', type:'date'}], proxy:{type:'memory'}});
Ext.define('dilocsync.store.Dossiers', {extend:dilocsync.store.DiLocTreeStorage, model:'dilocsync.model.Dossier', storeId:'Dossiers', saveKey:'dossiers:tree', trackRemoved:false, sorters:[{property:'addedAt', direction:'DESC'}], sync:function() {
  this.callParent(arguments);
  this.fireEvent('datachanged', this);
}});
Ext.define('dilocsync.view.components.InfoToast', {extend:Ext.Sheet, xtype:'infotoast', cls:'dilocsync-toast', padding:10, modal:false, showAnimation:{type:'popIn', duration:250, easing:'ease-out'}, hideAnimation:{type:'popOut', duration:250, easing:'ease-out'}, zIndex:999});
Ext.define('dilocsync.model.AlmanacEntry', {extend:Ext.data.TreeModel, fields:[{name:'uuid', type:'string'}, {name:'name', type:'string'}, {name:'title', type:'string', convert:function(_value, _record) {
  return _value ? _value : _record.get('name');
}}, {name:'description', type:'string'}, {name:'fileType', type:'string'}, {name:'size', type:'int'}, {name:'fileUuid', type:'string'}, {name:'checksum', type:'string'}, {name:'validFrom', type:'date'}, {name:'validTo', type:'date'}, {name:'visibleFrom', type:'date'}, {name:'visibleTo', type:'date'}, {name:'path', type:'string'}, {name:'icon', type:'string'}, {name:'isFolder', type:'boolean', convert:function(_value, _record) {
  return _record.get('icon') === 'folder';
}}, {name:'date', type:'date'}, {name:'read', type:'boolean', defaultValue:false}, {name:'rootFsEntryName', type:'string'}, {name:'loaded', type:'boolean', defaultValue:false}], hasMany:[{model:'dilocsync.model.Tag', name:'tags'}]});
Ext.define('dilocsync.model.ImportantDocument', {extend:dilocsync.model.AlmanacEntry, identifier:'uuid'});
Ext.define('dilocsync.store.ImportantDocuments', {extend:dilocsync.store.DiLocTreeStorage, storeId:'ImportantDocuments', model:'dilocsync.model.ImportantDocument', sorters:'name', groupDir:'ASC', saveKey:'page:importantTaggedDocuments'});
Ext.define('dilocsync.core.FileGarbageCollector', {singleton:true, doFileGarbageCollectorCheck:function(_documentRepository, _settingsStorage, _daysUntilNextCleanUp) {
  _daysUntilNextCleanUp = _daysUntilNextCleanUp === undefined ? 30 : _daysUntilNextCleanUp;
  if (this._isCleanupNeeded(_settingsStorage, _daysUntilNextCleanUp)) {
    cnconsult.Logger.log({prefix:'FileGarbageCollector-\x3edoFileGarbageCollectorCheck', message:'Start clean up!'});
    console.time('FileGarbageCollector');
    this.doDeleteUnusedFiles(_documentRepository, _settingsStorage);
  } else {
    cnconsult.Logger.log({prefix:'FileGarbageCollector-\x3edoFileGarbageCollectorCheck', message:'No clean up!'});
  }
}, _isCleanupNeeded:function(_settingsStorage, _daysUntilNextCleanUp) {
  if (dilocsync.util.MultiUserSupport.isEnabled()) {
    return true;
  }
  var lastCleanUp = _settingsStorage.get('core:fileGarbageCollector:lastCleanUp', false);
  var today = Ext.Date.format(new Date, 'c');
  var daysSinceLastCleanUp = Ext.Date.diff(Ext.Date.parse(lastCleanUp, 'c'), Ext.Date.parse(today, 'c'), 'd');
  return !lastCleanUp || lastCleanUp && daysSinceLastCleanUp > _daysUntilNextCleanUp;
}, doDeleteUnusedFiles:function(_documentRepository, _settingsStorage) {
  _documentRepository.removeNoLongerRequiredDocuments().then(function() {
    var timestamp = Ext.Date.format(new Date, 'c');
    _settingsStorage.set('core:fileGarbageCollector:lastCleanUp', timestamp);
    cnconsult.Logger.log({prefix:'FileGarbageCollector-\x3edoDeleteUnusedFiles', message:'checkForFilesToDelete Files deleted all DONE!', dump:timestamp});
  })['catch'](function(_err) {
    cnconsult.Logger.log({level:'error', prefix:'FileGarbageCollector-\x3edoDeleteUnusedFiles', message:'Error while removing no longer required documents', catchedError:_err, stack:true});
  });
}});
Ext.define('dilocsync.core.MultiUserCapableSettingsStorage', {USER_SPECIFIC_SETTING_PATHS:['core:personalization:username', 'core:personalization:useridcode', 'core:personalization:userid', 'core:personalization:usergroup', 'core:personalization:email', 'core:fileviewer:config', 'core:almanacs', 'core:almanac', 'core:syncengine:lastSyncTimestamp', 'core:lastVisibilityCheck', 'core:identity', 'core:personalization:lastLogin', 'dossiers:tree', 'syncreport:showLastReports', 'core:syncengine:lastSyncTimeStamp', 
'knowledge:lastRoute', 'knowledge:needSync'], USER_SPECIFIC_SETTING_NAMESPACES:['syncreport:storage:', 'core:almanac:', 'fulltextsearch:', 'page:'], DEVICE_SETTING_PATHS:['core:userLang', 'storageMigratedToV4', 'core:backendUrl', 'core:deviceIdCode', 'core:registered', 'core:disableUserCreation', 'core:personalization:customerId', 'core:personalization:syncSecret', 'core:personalized', 'core:personalization:multiUserSupportAvailable', 'core:personalization:multiUserSupportEnabled', 'core:personalization:daysUntilUserIsConsideredInactive', 
'core:syncAlgorithm', 'sync4DataMigrated', 'core:geostationlist:version', 'core:fileGarbageCollector:lastCleanUp'], USER_PREFIX:'user:', storage:undefined, currentUserId:undefined, multiUserSupportEnabled:false, constructor:function(storage, multiUserSupportEnabled) {
  this.storage = storage;
  this.multiUserSupportEnabled = multiUserSupportEnabled;
}, _isUserPrefixed:function(settingPath) {
  return settingPath.startsWith(this.USER_PREFIX);
}, _isUserPrefixedFor:function(settingPath, userId) {
  return settingPath.startsWith(this._userIdPrefix(userId));
}, _isUserSpecific:function(settingPath) {
  return this.USER_SPECIFIC_SETTING_PATHS.includes(settingPath) || this.USER_SPECIFIC_SETTING_NAMESPACES.some(function(item) {
    return settingPath.startsWith(item);
  });
}, _userIdPrefix:function(userId) {
  return '' + this.USER_PREFIX + userId + ':';
}, _prefixSettingPathWithUserId:function(settingPath, userId) {
  return '' + this._userIdPrefix(userId) + settingPath;
}, _isKnownSettingPath:function(settingPath) {
  return this._isUserSpecific(settingPath) || this.DEVICE_SETTING_PATHS.includes(settingPath);
}, setCurrentUser:function(userId) {
  this.currentUserId = userId;
}, isCurrentUserSet:function() {
  return this.currentUserId !== undefined;
}, get:function(settingPath, defaultValue) {
  if (this.multiUserSupportEnabled) {
    if (settingPath === 'core:personalized') {
      cnconsult.Logger.log({level:'error', prefix:'MultiUserCapableSettingsStorage-\x3eget', message:'Personalization state must be checked via dilocsync.core.Personalization#isPersonalized'});
      return defaultValue;
    }
    if (!this._isKnownSettingPath(settingPath)) {
      cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3eget', message:'unknown setting detected, assuming user specific setting for "' + settingPath + '"'});
      return this.getForUser(settingPath, this.currentUserId, defaultValue);
    }
    if (this._isUserSpecific(settingPath)) {
      return this.getForUser(settingPath, this.currentUserId, defaultValue);
    }
  }
  return this.storage.get(settingPath, defaultValue);
}, getAll:function() {
  if (this.multiUserSupportEnabled) {
    var settingsWithoutUserPrefix = {};
    var replaceRegExp = new RegExp('^' + this.USER_PREFIX + '\\d+:');
    for (var $jscomp$iter$8 = $jscomp.makeIterator(Object.entries(this.storage.getAll())), $jscomp$key$$jscomp$destructuring$var6 = $jscomp$iter$8.next(); !$jscomp$key$$jscomp$destructuring$var6.done; $jscomp$key$$jscomp$destructuring$var6 = $jscomp$iter$8.next()) {
      var $jscomp$destructuring$var6 = $jscomp$key$$jscomp$destructuring$var6.value;
      {
        var $jscomp$destructuring$var7 = $jscomp.makeIterator($jscomp$destructuring$var6);
        var key = $jscomp$destructuring$var7.next().value;
        var value = $jscomp$destructuring$var7.next().value;
        if (this._isUserPrefixed(key)) {
          if (this._isUserPrefixedFor(key, this.currentUserId)) {
            key = key.replace(replaceRegExp, '');
          } else {
            continue;
          }
        }
        settingsWithoutUserPrefix[key] = value;
      }
    }
    return settingsWithoutUserPrefix;
  }
  return this.storage.getAll();
}, getForUser:function(settingPath, userId, defaultValue) {
  if (this.multiUserSupportEnabled) {
    if (userId === undefined) {
      cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3eget', message:'trying to load user specific setting "' + settingPath + '" without a set current user id, loading setting without user prefix'});
      return this.storage.get(settingPath, defaultValue);
    }
    return this.storage.get(this._prefixSettingPathWithUserId(settingPath, userId), defaultValue);
  }
  cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3egetForUser', message:'not supported for single user mode'});
}, remove:function(settingPath) {
  if (this.multiUserSupportEnabled) {
    if (!this._isKnownSettingPath(settingPath)) {
      cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3eremove', message:'unknown setting detected, assuming user specific setting for "' + settingPath + '"'});
      return this._removeForUser(settingPath, this.currentUserId);
    }
    if (this._isUserSpecific(settingPath)) {
      return this._removeForUser(settingPath, this.currentUserId);
    }
  }
  this.storage.remove(settingPath);
}, _removeForUser:function(settingPath, userId) {
  if (this.multiUserSupportEnabled) {
    if (userId === undefined) {
      cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3e_removeForUser', message:'trying to remove user specific setting "' + settingPath + '" without a set current user id, doing nothing'});
      return;
    }
    this.storage.remove(this._prefixSettingPathWithUserId(settingPath, userId));
    return;
  }
  cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3e_removeForUser', message:'not supported for single user mode'});
}, removeAll:function() {
  this.storage.removeAll();
}, removeAllForUser:function(userId) {
  if (this.multiUserSupportEnabled) {
    var allSettings = this.storage.getAll();
    for (var $jscomp$iter$9 = $jscomp.makeIterator(Object.keys(allSettings)), $jscomp$key$key = $jscomp$iter$9.next(); !$jscomp$key$key.done; $jscomp$key$key = $jscomp$iter$9.next()) {
      var key = $jscomp$key$key.value;
      {
        if (key.startsWith(this._userIdPrefix(userId))) {
          this.storage.remove(key);
        }
      }
    }
  } else {
    this.removeAllUserSettings();
  }
}, removeAllUserSettings:function() {
  var $jscomp$this = this;
  var allSettings = this.storage.getAll();
  var userSpecificSettingPaths = Object.keys(allSettings).filter(function(settingPath) {
    return $jscomp$this._isUserPrefixed(settingPath) || $jscomp$this._isUserSpecific(settingPath);
  });
  for (var $jscomp$iter$10 = $jscomp.makeIterator(userSpecificSettingPaths), $jscomp$key$key = $jscomp$iter$10.next(); !$jscomp$key$key.done; $jscomp$key$key = $jscomp$iter$10.next()) {
    var key = $jscomp$key$key.value;
    {
      this.storage.remove(key);
    }
  }
}, set:function(settingPath, settingValue) {
  if (this.multiUserSupportEnabled) {
    if (!this._isKnownSettingPath(settingPath)) {
      cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3eset', message:'unknown setting detected, assuming user specific setting for "' + settingPath + '"'});
      return this._setForUser(settingPath, settingValue, this.currentUserId);
    }
    if (this._isUserSpecific(settingPath)) {
      return this._setForUser(settingPath, settingValue, this.currentUserId);
    }
  }
  this.storage.set(settingPath, settingValue);
}, _setForUser:function(settingPath, settingValue, userId) {
  if (this.multiUserSupportEnabled) {
    if (userId === undefined) {
      cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3e_setForUser', message:'trying to set user specific setting "' + settingPath + '" without a set current user id, doing nothing'});
      return;
    }
    this.storage.set(this._prefixSettingPathWithUserId(settingPath, userId), settingValue);
    return;
  }
  cnconsult.Logger.log({level:'warn', prefix:'MultiUserCapableSettingsStorage-\x3e_setForUser', message:'not supported for single user mode'});
}});
Ext.define('dilocsync.controller.Init', {extend:Ext.app.Controller, mixins:[cnconsult.Translatable], config:{autoSyncManager:null, fileVisibleManager:null, deviceBackButtonTappedCount:0}, listen:{global:{filereadflagchanged:'folderBadgeSetter'}}, init:function() {
  var $jscomp$this = this;
  var performInit = Ext.bind(function() {
    cnconsult.Logger.setConsole(true);
    Ext.route.Router.setMultipleToken('$');
    var master = dilocsync.core.Master;
    if (dilocsync.util.Platform.isAndroid()) {
      document.addEventListener('backbutton', Ext.bind(this.androidBackButtonHandler, this), false);
    }
    Ext.on('fullscreenleft', dilocsync.util.FileViewerHelper.exitFullscreenFileViewers, this);
    Ext.create('dilocsync.store.MenuItems');
    Ext.create('dilocsync.store.Websites');
    this.initCustomEventListener();
    this.initStorage(function() {
      var $jscomp$this = this;
      this.initDocumentRepository()['catch'](function(_err) {
        cnconsult.Logger.log({level:'error', prefix:'Init-\x3einitDocumentRepository', message:'Error initializing the document repository: ' + _err.message});
        throw _err;
      }).then(function() {
        master.initMaster($jscomp$this.documentRepository);
        console.log('Init process is ready!');
        var loaderAnimation = Ext.get('loader');
        if (loaderAnimation) {
          loaderAnimation.destroy();
        }
      });
    }, this);
    this.initOpenCustomUrlHandling();
  }, this);
  if (dilocsync.util.Platform.isPhonegap()) {
    document.addEventListener('deviceready', function() {
      if (dilocsync.util.Platform.isAndroid()) {
        $jscomp$this.checkStorageMigration(performInit);
      } else {
        performInit();
      }
    }, false);
  } else {
    performInit();
  }
}, checkStorageMigration:function(_callback) {
  var migrationNeeded = window.StorageMigration.isMigrationNeeded();
  var languageCode = navigator.language.split('_')[0].split('-')[0];
  cnconsult.Translator.loadTranslationAsync('resources/lang/diloc-syncmobile_' + languageCode + '.lang', function() {
    var $jscomp$this = this;
    if (migrationNeeded === 1) {
      cnconsult.Logger.log({prefix:'Init-\x3echeckStorageMigration', message:'Migration of storage is needed'});
      Ext.get('loader').insertHtml('beforeEnd', '\x3ch4 style\x3d"text-align: center;"\x3e' + this.tr('App is migrating the storage. This may take a moment. Please do not close the app or abort the process!') + '\x3c/h4\x3e');
      Ext.get('loader').insertHtml('beforeEnd', '\x3ch4 style\x3d"text-align: center;"\x3e' + this.tr('Files migrated: ') + '\x3cspan id\x3d"migrationProgress"\x3e-\x3c/span\x3e\x3c/h4\x3e');
      Ext.get('loader').insertHtml('beforeEnd', '\x3cdiv style\x3d"position: absolute;bottom: 0;width: 100%;z-index: 10000;text-align: center;color: #696969"\x3e' + '\x3ch4\x3e' + this.tr('The migration is necessary because Google has new guidelines regarding storage access.') + '\x3c/h4\x3e\x3c/div\x3e');
      var progressEl = Ext.get('migrationProgress');
      window.publishProgress = function(_progress) {
        progressEl.setText(_progress);
      };
      window.migrationCallback = function(_failedFiles) {
        cnconsult.Logger.log({prefix:'Init-\x3echeckStorageMigration', message:'Migration callback, result:', dump:_failedFiles});
        if (_failedFiles === 0) {
          var successMessage = '\x3cb\x3e' + $jscomp$this.tr('The migration was successful.') + '\x3c/b\x3e';
          successMessage += '\x3cbr\x3e\x3cbr\x3e' + $jscomp$this.tr('You can now use the app as usual.');
          dilocsync.util.MessageHelper.showAcknowledge($jscomp$this.tr('Success'), successMessage, _callback, $jscomp$this);
        } else {
          window.forceSync = true;
          var failedMessage = '\x3cb\x3e' + $jscomp$this.tr('The migration was successful, but %1 files could not be migrated.').arg(_failedFiles) + '\x3c/b\x3e';
          failedMessage += '\x3cbr\x3e' + $jscomp$this.tr('Please start a synchronization so that the missing files are loaded again.');
          failedMessage += '\x3cbr\x3e' + $jscomp$this.tr('You can then use the app as usual again.');
          dilocsync.util.MessageHelper.showAcknowledge($jscomp$this.tr('Success'), failedMessage, _callback, $jscomp$this);
        }
      };
      window.StorageMigration.migrate();
    } else {
      if (migrationNeeded === 2) {
        var infoMessage = this.tr('You still have existing data from an old installation of the app.');
        infoMessage += '\x3cbr\x3e\x3cbr\x3e\x3cb\x3e' + this.tr('Please remove the folder "sync" from the root of your internal storage.') + '\x3c/b\x3e';
        dilocsync.util.MessageHelper.showAcknowledge(this.tr('Info'), infoMessage, _callback, this);
      } else {
        _callback();
      }
    }
  }, this);
}, initDocumentRepository:function() {
  if (!dilocsync.util.Platform.isPhonegap()) {
    return Promise.resolve();
  }
  var removeFile = dilocsync.util.File.removeFile;
  var fileExists = dilocsync.util.File.fileExists;
  var listFiles = dilocsync.util.File.listFiles;
  var syncRootUrl = dilocsync.core.Master.getSyncRoot().toURL();
  var settingsStorage = dilocsync.core.Master.getStorage();
  if (dilocsync.util.MultiUserSupport.isEnabled() && dilocsync.util.Platform.supportsMultiuser()) {
    var documentOwnershipTracker = Ext.create('dilocsync.core.repository.DocumentOwnershipTracker');
    this.documentRepository = Ext.create('dilocsync.core.repository.MultiUserDocumentRepository', syncRootUrl, listFiles, fileExists, removeFile, settingsStorage, documentOwnershipTracker);
    return documentOwnershipTracker.initialize();
  } else {
    this.documentRepository = Ext.create('dilocsync.core.repository.SingleUserDocumentRepository', syncRootUrl, listFiles, fileExists, removeFile, settingsStorage);
    return Promise.resolve();
  }
}, initOpenCustomUrlHandling:function() {
  window.handleOpenURL = Ext.bind(function(_url) {
    var url = _url;
    url = url.replace('dilocsync://', '');
    if (url) {
      if (this && Ext.isFunction(this.redirectTo)) {
        this.redirectTo(url, true);
      }
    }
  }, this);
}, androidBackButtonHandler:function(_event) {
  var me = this;
  _event.preventDefault();
  if (!dilocsync.util.FileViewerHelper.exitFullscreenFileViewers()) {
    var resetTappedCounterTask = new Ext.util.DelayedTask(function() {
      me.setDeviceBackButtonTappedCount(0);
    });
    me.setDeviceBackButtonTappedCount(me.getDeviceBackButtonTappedCount() + 1);
    resetTappedCounterTask.delay(3000);
    if (this.getDeviceBackButtonTappedCount() === 2) {
      cordova.plugins.exit();
    } else {
      var backButtonText = this.tr('Tap again for closing the app.');
      var toast = Ext.create('dilocsync.view.components.InfoToast', {html:backButtonText});
      Ext.Viewport.down('menusTabmenu').add(toast);
      toast.show();
      Ext.defer(toast.hide, 2000, toast);
      Ext.defer(toast.destroy, 3000, toast);
    }
  }
}, initCustomEventListener:function() {
  var master = dilocsync.core.Master;
  master.on({initialized:'onMasterInitialized', scope:this});
}, initStorage:function(_callback, _scope) {
  var master = dilocsync.core.Master;
  if (dilocsync.util.Platform.isPhonegap()) {
    cnconsult.Logger.log({prefix:'Init-\x3einitStorage', message:'Master detected phonegap, loading filesystem and syncroot...'});
    master.initVersionInformation();
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, Ext.bind(function(_fileSystem) {
      master.setFileSystem(_fileSystem);
      _fileSystem.root.getDirectory('sync', {create:true}, Ext.bind(function(_syncRoot) {
        master.setSyncRoot(_syncRoot);
        cnconsult.Logger.log({prefix:'Init-\x3einitStorage', message:'Syncroot path loaded.'});
        var fileStorage = Ext.create('cnconsult.storage.File', {prefix:master.getStorageProfile(), syncRoot:master.getSyncRoot(), fileSystem:_fileSystem, listeners:{'loaded':function() {
          var multiUserCapableSettingsStorage = Ext.create('dilocsync.core.MultiUserCapableSettingsStorage', fileStorage, fileStorage.get(dilocsync.util.MultiUserSupport.MULTI_USER_SUPPORT_ENABLED_STORAGE_PATH, false));
          master.setStorage(multiUserCapableSettingsStorage);
          if (!master.isRegistered() && master.presetRegistrationData.serverUrl && master.presetRegistrationData.password) {
            if (!master.getBackendUrl()) {
              master.getStorage().set('core:backendUrl', master.presetRegistrationData.serverUrl);
            }
          }
          dilocsync.util.Migration.run();
          master.initLanguage(_callback, _scope);
        }, scope:this}});
      }, this), Ext.bind(function(_error) {
        console.error('Error getting root directory.', _error);
      }));
    }, this), Ext.bind(function() {
      cnconsult.Logger.log({prefix:'Init-\x3einitStorage-\x3erequestFileSystem', level:'error', message:'Failed get filesytem', dump:arguments});
    }, this));
  } else {
    console.log("No phonegap, so no real filesystem support. We'll just create a rudimentary settings store.", this);
    var localStorage$81 = Ext.create('cnconsult.storage.LocalStorage', {prefix:master.getStorageProfile()});
    var multiUserSupportEnabled = localStorage$81.get(dilocsync.util.MultiUserSupport.MULTI_USER_SUPPORT_ENABLED_STORAGE_PATH, false);
    master.setStorage(Ext.create('dilocsync.core.MultiUserCapableSettingsStorage', localStorage$81, multiUserSupportEnabled));
    master.initLanguage(_callback, _scope);
  }
}, _onPersonalized:function() {
  this.addPages(true);
  this.initReadConfirmations();
  this.initFavorites();
  this.initDossiers();
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    dilocsync.util.PdfViewerHelper.init();
  } else {
    dilocsync.util.FileViewerHelper.init();
    if (dilocsync.util.FileViewerHelper.getPrimary() === null) {
      dilocsync.core.Master.getSyncEngine().on({syncfinished:function() {
        dilocsync.util.FileViewerHelper.init();
      }, single:true, scope:this});
    }
  }
  this.initializeAutoSync();
  this.initializeFileVisibleManager();
  dilocsync.util.Identity.checkIfSyncIsRecommend();
}, onMasterInitialized:function() {
  var $jscomp$this = this;
  var master = dilocsync.core.Master;
  var syncEngine = master.getSyncEngine();
  var route = Ext.History.getToken();
  route = route ? route : 'home';
  syncEngine.on({syncfinished:function(_success, _errorMessage, _syncReportAvailable, _reloadRequired) {
    if (_reloadRequired) {
      Ext.defer(function() {
        master.reloadApplication(false);
      }, 550);
    } else {
      this.addPages();
      master.fullTextSearchIndexNewFiles();
    }
  }, scope:this});
  this.addSetupPages();
  this.initializeStandbyPrevention();
  this.enhanceUserDataForSentry();
  if (dilocsync.util.Platform.supportsOpenWith()) {
    this.initOpenWithPlugin();
  }
  if (master.importsEnabled()) {
    this.initImports();
  }
  this.initImportantDocuments();
  this.setupCheckStoleIntervalCheck();
  if (dilocsync.util.Platform.isPhonegap()) {
    dilocsync.core.FileGarbageCollector.doFileGarbageCollectorCheck(this.documentRepository, dilocsync.core.Master.getStorage(), 30);
  }
  if (master.getPersonalization().isPersonalized()) {
    this._onPersonalized();
  } else {
    master.getPersonalization().on('personalized', function() {
      $jscomp$this._onPersonalized();
    });
  }
  cnconsult.Logger.log({prefix:'Init-\x3eonMasterInitialized', message:'Init route', dump:route});
  this.redirectTo(route, true);
}, initOpenWithPlugin:function() {
  var me = this;
  var master = dilocsync.core.Master;
  var title = this.tr('Local documents');
  var okText = this.tr('Ok');
  var text = this.tr('Document imports are currently disabled for your company. If you are interested, please contact your administrator.');
  var confirmTitle = this.tr('Overwrite file');
  var confirmMessage = this.tr('A file with this name already exists. Do you want to overwrite the existing file?');
  cordova.openwith.setVerbosity(cordova.openwith.DEBUG);
  cordova.openwith.init(initSuccess, initError);
  function initSuccess() {
    cnconsult.Logger.log({prefix:'Init-\x3einitOpenWithPlugin', message:'Successfully initialized openwith plugin!', level:'debug'});
  }
  function initError(err) {
    cnconsult.Logger.log({prefix:'Init-\x3einitOpenWithPlugin', message:'Initializing openwith plugin failed: ', level:'error', catchedError:err});
  }
  cordova.openwith.addHandler(function(_intent) {
    if (master.importsEnabled()) {
      fileImportHandler(_intent);
    } else {
      disabledImportsHandler(_intent);
    }
  });
  function disabledImportsHandler(_intent) {
    cnconsult.Logger.log({prefix:'Init-\x3einitOpenWithPlugin', message:'DisabledImportsHandler added!', level:'debug'});
    dilocsync.util.MessageHelper.showMessage({title:title, message:text, buttons:[{itemId:'ok', text:okText, handler:function(_btn) {
      _btn.up('messagebox').destroy();
    }}]});
  }
  function fileImportHandler(_intent) {
    var $jscomp$arguments = arguments;
    cnconsult.Logger.log({prefix:'Init-\x3einitOpenWithPlugin', message:'FileImportHandler added!', level:'debug', dump:_intent});
    if (_intent.items.length > 0) {
      cordova.openwith.load(_intent.items[0], function(_data, _item) {
        var path = decodeURI(_item.path);
        var fileName = dilocsync.util.File.basename(path);
        var store = Ext.getStore('Imports');
        var existingEntry = store.findRecord('name', fileName);
        if (existingEntry) {
          dilocsync.util.MessageHelper.showConfirm(confirmTitle, confirmMessage, function(choice) {
            if (choice === 'yes') {
              writeImportedFile(_data, _item, path, existingEntry);
              dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.controller.Init', src:'LokaleDokumente', action:'ImportierteDateiÜberschrieben', trackedAt:new Date, extras:{mode:'override'}});
            }
          });
        } else {
          writeImportedFile(_data, _item, path, existingEntry);
          dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.controller.Init', src:'LokaleDokumente', action:'DateiImportiert', trackedAt:new Date, extras:{mode:'add'}});
        }
      }, function() {
        return console.error('Error in import', $jscomp$arguments);
      });
    }
  }
  function writeImportedFile(data, item, path, existingEntry) {
    var master = dilocsync.core.Master;
    var fileName = dilocsync.util.File.basename(path);
    var fileType = dilocsync.util.File.extension(fileName);
    var store = Ext.getStore('Imports');
    master.getSyncRoot().getDirectory('imports', {create:true}, function(_importDirectory) {
      _importDirectory.getFile(fileName, {create:true}, function(_file) {
        _file.createWriter(function(_writer) {
          _writer.onwriteend = Ext.bind(function() {
            if (!existingEntry) {
              store.add({'name':fileName, 'fileType':fileType, 'icon':fileType, 'uuid':'imported'});
              store.sync();
            }
            me.redirectTo('imports', true);
          });
          _writer.write(dilocsync.util.Helper.b64toBlob(data, item.type));
        });
      }, function(_error) {
        cnconsult.Logger.log({prefix:'Init-\x3einitOpenWithPlugin', message:'Error getting or creating import file for iOS.', level:'error', catchedError:_error});
      });
    }, function(_error) {
      cnconsult.Logger.log({prefix:'Init-\x3einitOpenWithPlugin', message:"Imports: Import directory for iOS couldn't be loaded!", level:'error', catchedError:_error});
    });
  }
}, initReadConfirmations:function() {
  try {
    var master = dilocsync.core.Master;
    var syncEngine = master.getSyncEngine();
    var store = Ext.create('dilocsync.store.Confirmations');
    store.load();
    dilocsync.util.Confirmations.showMessage();
    syncEngine.on({syncfinished:function(_success, _errorMessage, _syncReportAvailable, _reloadRequired) {
      if (!syncEngine.wasLastSyncFromAutoSync()) {
        dilocsync.util.Confirmations.showMessage();
      }
    }, scope:this});
  } catch (e$82) {
    cnconsult.Logger.log({prefix:'Init-\x3einitReadConfirmations', message:'Exception during read-confirmation initialization', level:'error', catchedError:e$82, useSentry:true});
  }
}, initializeAutoSync:function() {
  try {
    cnconsult.Logger.log({prefix:'Init-\x3einitializeAutoSync', message:'Check if auto sync is configured, if yes set up AutoSyncManager...'});
    var identity = dilocsync.core.Master.getIdentity();
    if (identity.options && identity.options.autoSync) {
      cnconsult.Logger.log({prefix:'Init-\x3einitializeAutoSync', message:'Initialize and start AutoSyncManager...'});
      this.setAutoSyncManager(Ext.create('dilocsync.core.AutoSyncManager', identity.options.autoSync));
      this.getAutoSyncManager().start(false);
    }
  } catch (e$83) {
    cnconsult.Logger.log({prefix:'Init-\x3einitializeAutoSync', message:'Exception caught during initialization of autosync', level:'error', catchedError:e$83, useSentry:true});
  }
}, initializeFileVisibleManager:function() {
  try {
    cnconsult.Logger.log({prefix:'Init-\x3einitializeFileVisibleManager', message:'Initializing FileVisibleManager...'});
    this.setFileVisibleManager(Ext.create('dilocsync.core.FileVisibleManager'));
    this.getFileVisibleManager().checkFileVisibility();
  } catch (e$84) {
    cnconsult.Logger.log({prefix:'Init-\x3einitializeFileVisibleManager', message:'Exception caught during initialization of FileVisibleManager', level:'error', catchedError:e$84, useSentry:true});
  }
}, initFavorites:function() {
  try {
    var master = dilocsync.core.Master, syncEngine = master.getSyncEngine(), store = Ext.create('dilocsync.store.Favorites');
    store.load();
    syncEngine.on({syncfinished:function() {
      store.each(function(_record) {
        var fileName = _record.get('checksum') + '.' + _record.get('fileType');
        var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(_record);
        dilocsync.core.Master.devicePathExists(rootFsEntryName + '/' + fileName, function(_fullPath) {
          if (_fullPath === null || !_record.get('uuid')) {
            var deleteFavorite = true;
            var almanacPath = _record.get('almanacPath');
            if (almanacPath) {
              var almanac = master.getAlmanacForPath(almanacPath);
              if (almanac) {
                var file = almanac.getFileByPath(_record.get('almanacFilePath'));
                if (file) {
                  if (file.hasOwnProperty('uuid') && file.uuid) {
                    _record.set('uuid', file.uuid);
                  }
                  _record.set('checksum', file.checksum);
                  _record.set('path', master.devicePath(rootFsEntryName + '/' + file.checksum + '.' + _record.get('fileType')));
                  deleteFavorite = false;
                }
              }
            }
            if (deleteFavorite) {
              store.remove(_record);
            }
          }
        }, this);
      }, this);
      store.sync();
    }, scope:this});
  } catch (e$85) {
    cnconsult.Logger.log({prefix:'Init-\x3einitFavorites', message:'During favorites initialization', level:'error', catchedError:e$85, useSentry:true});
  }
}, initImports:function() {
  try {
    var store = Ext.create('dilocsync.store.Imports');
    store.load();
  } catch (e$86) {
    console.log('Exception: Init-\x3eImports', e$86);
    Sentry.withScope(function(_scope) {
      _scope.setExtra('launchError', 'During imports initialization');
      Sentry.captureException(e$86);
    });
  }
}, initImportantDocuments:function() {
  try {
    var master = dilocsync.core.Master;
    var identity = master.getIdentity();
    if (identity.options && !identity.options.importantDocumentsPath) {
      var store = Ext.create('dilocsync.store.ImportantDocuments');
      store.load();
    }
  } catch (e$87) {
    cnconsult.Logger.log({prefix:'Init-\x3einitImportantDocuments', message:'During important documents initialization', level:'error', catchedError:e$87, useSentry:true});
  }
}, initDossiers:function() {
  try {
    var store = Ext.create('dilocsync.store.Dossiers');
    store.load();
  } catch (e$88) {
    cnconsult.Logger.log({prefix:'Init-\x3einitDossiers', message:'During dossiers initialization', level:'error', catchedError:e$88, useSentry:true});
  }
}, setupCheckStoleIntervalCheck:function() {
  var task = Ext.TaskManager.start({run:dilocsync.core.Master.checkStolen, interval:10 * 60 * 1000, scope:dilocsync.core.Master});
}, enhanceUserDataForSentry:function() {
  var master = dilocsync.core.Master;
  if (master.getPersonalization().isPersonalized()) {
    var personalizationData = master.getPersonalization().getData();
    Sentry.configureScope(function(_scope) {
      _scope.setUser({name:personalizationData.username, device:personalizationData.deviceIdCode, backendUrl:master.getBackendUrl('')});
    });
  }
}, initializeStandbyPrevention:function() {
  try {
    var identity = dilocsync.core.Master.getIdentity();
    if (identity.options && identity.options.preventDisplayStandby && identity.options.preventDisplayStandby === true) {
      if (window.plugins && window.plugins.insomnia) {
        window.plugins.insomnia.keepAwake();
      } else {
        console.log('Insomnia plugin is not available');
      }
    }
  } catch (e$89) {
    cnconsult.Logger.log({prefix:'Init-\x3einitializeStandbyPrevention', message:'Exception during initialize standby prevention', level:'error', catchedError:e$89, useSentry:true});
  }
}, addSetupPages:function() {
  cnconsult.Logger.log({prefix:'Init-\x3eaddSetupPages', message:'init setup pages'});
  var menuItems = [{isSetupView:true, route:'setup/device/registration', view:'registration', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}, {isSetupView:true, route:'setup/user/personalization', view:'personalization', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}, {isSetupView:true, route:'setup/user/personalization/create', view:'user-create', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}, {isSetupView:true, 
  route:'setup/user/personalization/knowledges', view:'user-knowledge', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}];
  try {
    var menuItemsStore = Ext.getStore('menuItems');
    menuItemsStore.removeAll();
    menuItemsStore.add(menuItems);
  } catch (e$90) {
    cnconsult.Logger.log({prefix:'Init-\x3eaddSetupPages', message:'Exception occurred', level:'error', catchedError:e$90});
  }
}, addPages:function(_initialCall) {
  cnconsult.Logger.log({prefix:'Init-\x3eaddPages', message:'init pages'});
  try {
    var menuItem;
    var me = this;
    var websites = false;
    var master = dilocsync.core.Master;
    var identity = master.getIdentity();
    var menuItemsStore = Ext.getStore('menuItems');
    var menuItems = [{label:this.tr('Start'), order:200, iconCls:'x-fa fa-home', route:'home', view:'home', showInSideMenu:true, showInPhoneTabMenu:true, showInTabletTabMenu:true}, {label:this.tr('About'), order:1200, iconCls:'x-fa fa-info-circle', route:'about', view:'about', showInSideMenu:true, showInPhoneTabMenu:true, showInTabletTabMenu:true}, {label:this.tr('User settings'), iconCls:'x-fa fa-cogs', order:1500, route:'usersettings', view:'usersettings', showInSideMenu:true, showInPhoneTabMenu:false, 
    showInTabletTabMenu:false}, {isSetupView:true, route:'setup/device/registration', view:'registration', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}, {isSetupView:true, route:'setup/user/personalization', view:'personalization', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}, {isSetupView:true, route:'setup/user/personalization/create', view:'user-create', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}, {isSetupView:true, 
    route:'setup/user/personalization/knowledges', view:'user-knowledge', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}, {isSetupView:false, route:'search', view:'searchpanel', showInSideMenu:false, showInPhoneTabMenu:false, showInTabletTabMenu:false}];
    var websitesStore = Ext.getStore('websites');
    websitesStore.removeAll();
    if (identity.pages) {
      Ext.Array.each(identity.pages, function(_page, _index) {
        var menuItem = {label:_page.title, config:_page.config, showInSideMenu:Ext.isDefined(_page.showInSideMenu) ? _page.showInSideMenu : true, showInPhoneTabMenu:Ext.isDefined(_page.showInPhoneTabMenu) ? _page.showInPhoneTabMenu : true, showInTabletTabMenu:Ext.isDefined(_page.showInTabletTabMenu) ? _page.showInTabletTabMenu : true};
        switch(_page.type) {
          case 'folder':
            var isTrainSchedulePage = _page.config.path.startsWith('trainschedules/');
            Ext.apply(menuItem, {order:300 + _index, iconCls:isTrainSchedulePage ? 'x-fa fa-book' : 'x-fa fa-folder', userCls:'dilocsync-badge-unread', route:'folder/' + _page.config.path, view:'folder', badgeFn:function() {
              if (_page.config.showUnreadFileBadge) {
                me.folderBadgeSetter(_page.config.path);
              }
            }});
            break;
          case 'knowledge':
            Ext.apply(menuItem, {order:400, iconCls:'x-fa fa-check-square', route:'knowledges', view:'knowledges'});
            break;
          case 'routeknowledge':
            Ext.apply(menuItem, {order:450, iconCls:'x-fa fa-map-marked-alt', route:'routeknowledge', view:'routeknowledge'});
            menuItem.label = this.tr('Railway knowledge');
            break;
          case 'dailyla':
            Ext.apply(menuItem, {order:500, iconCls:'x-fa fa-file', route:'dailyla', view:'dailyla', badgeFn:function() {
              var master = dilocsync.core.Master;
              var helper = dilocsync.util.Identity;
              var identity = master.getIdentity();
              var pageConfig = helper.getPageConfigByType(identity, 'dailyla');
              if (pageConfig) {
                var checker = Ext.create('dilocsync.core.DailyLaChecker', {basePath:pageConfig.config.path, areas:pageConfig.config.subscribedAreas, additionalAreas:Ext.Array.from(pageConfig.config.additionalAreas), areaPrefix:pageConfig.config.areaPrefix, filesNeedToBeThereUntil:pageConfig.config.filesNeedToBeThereUntil});
                var numMissingFiles = checker.numMissingFiles();
                var menuItem$91 = Ext.getStore('menuItems').findRecord('view', 'dailyla');
                if (menuItem$91) {
                  menuItem$91.set('badgeText', numMissingFiles > 0 ? '!' : '');
                }
              }
            }});
            break;
          case 'drivemode':
            Ext.apply(menuItem, {order:600, iconCls:'x-fa fa-columns', route:'drivemode', view:'drivemode', showInPhoneTabMenu:false});
            if (Ext.os.deviceType === 'Phone') {
              menuItem.showInSideMenu = false;
            }
            break;
          case 'web':
            if (_page.config.embedAsIframe && dilocsync.util.Platform.supportsEmbeddedWebpage()) {
              Ext.apply(menuItem, {order:1000 + _index, iconCls:'x-fa fa-globe', route:'embeddedwebpage/' + _page.title, view:'embeddedwebpage'});
            } else {
              menuItem = false;
              websites = true;
              var website = {'title':_page.title, 'url':_page.config.url, 'addressBarLocked':_page.config.addressBarLocked, 'toolBarHidden':_page.config.toolBarHidden, 'printEnabled':_page.config.printEnabled, 'openWithSystemBrowser':_page.config.openWithSystemBrowser};
              websitesStore.add(website);
            }
            break;
          case 'shiftjuggler':
            Ext.apply(menuItem, {order:1050, iconCls:'x-fa fa-calendar', route:'shiftjuggler', view:'shiftjuggler'});
            break;
          case 'locbook':
            Ext.apply(menuItem, {order:690, iconCls:'x-fa fa-book', route:'locbook', view:'locbook'});
            break;
          default:
            menuItem = false;
            break;
        }
        if (menuItem) {
          menuItems.push(menuItem);
        }
      }, this);
    }
    if (websites) {
      menuItem = {label:this.tr('Websites'), order:1000, showInSideMenu:true, showInPhoneTabMenu:false, showInTabletTabMenu:true, iconCls:'x-fa fa-globe', route:'website', view:'website'};
      menuItems.push(menuItem);
    }
    if (master.importsEnabled()) {
      menuItem = {label:this.tr('Imported documents'), order:399, iconCls:'x-fa fa-folder', route:'imports', view:'imports', showInSideMenu:true, showInPhoneTabMenu:true, showInTabletTabMenu:true, config:{'path':'imports', 'title':this.tr('Imports')}};
      menuItems.push(menuItem);
    }
    if (identity.options && (typeof identity.options.disableReadConfirmations === 'undefined' || !identity.options.disableReadConfirmations)) {
      menuItem = {label:this.tr('Confirmations'), order:800, showInSideMenu:true, showInPhoneTabMenu:false, showInTabletTabMenu:true, iconCls:'x-fa fa-check-square', route:'confirmations', view:'confirmations', badgeFn:function() {
        var store = Ext.getStore('Confirmations');
        store.fireEvent('datachanged', store);
      }};
      menuItems.push(menuItem);
    }
    if (identity.options && (typeof identity.options.disableFavorites === 'undefined' || !identity.options.disableFavorites)) {
      menuItem = {label:this.tr('Favorites'), order:900, showInSideMenu:true, showInPhoneTabMenu:false, showInTabletTabMenu:true, iconCls:'x-fa fa-star', route:'favorites', view:'favorites'};
      menuItems.push(menuItem);
    }
    if (identity.options && identity.options.syncReportConfig) {
      menuItem = {label:this.tr('Sync Reports'), order:700, showInSideMenu:true, showInPhoneTabMenu:false, showInTabletTabMenu:true, iconCls:'x-fa fa-clipboard', route:'syncreports', view:'syncreports', badgeFn:function() {
        dilocsync.core.Master.getSyncReportStorage().updateBadge();
      }};
      menuItems.push(menuItem);
    }
    if (identity.options && (identity.options.enableDriveAdvisory || identity.options.enableGpsTracking || identity.options.enableDigitalOrder)) {
      menuItems.push({label:this.tr('Train rides'), iconCls:'x-fa fa-train', order:250, route:'driveinfo', view:'driveinfopage', showInSideMenu:true, showInPhoneTabMenu:false, showInTabletTabMenu:false});
    }
    if (identity.options && identity.options.hasOwnProperty('enableDynamicSchedule') && identity.options.enableDynamicSchedule) {
      menuItems.push({label:this.tr('Dyn. Schedule'), order:670, iconCls:'x-fa fa-list-alt', route:'dynamicschedule', view:'dynamicschedule', showInSideMenu:true, showInPhoneTabMenu:true, showInTabletTabMenu:true});
    }
    if (identity.options && identity.options.hasOwnProperty('enableForms') && identity.options.enableForms) {
      menuItems.push({label:this.tr('Forms'), order:650, showInSideMenu:true, showInPhoneTabMenu:false, showInTabletTabMenu:true, iconCls:'x-fas fa-pen-square', route:'forms', view:'forms', config:{title:this.tr('Forms'), path:'forms'}, badgeFn:function() {
        var store = dilocsync.util.Helper.initStore('CompletedForms');
        store.fireEvent('datachanged', store);
      }});
    }
    menuItemsStore.removeAll();
    menuItemsStore.add(menuItems);
    if (!_initialCall && identity.options && identity.options.autoSync) {
      if (!this.getAutoSyncManager()) {
        this.setAutoSyncManager(Ext.create('dilocsync.core.AutoSyncManager', identity.options.autoSync));
        this.getAutoSyncManager().start(true);
      }
      this.getAutoSyncManager().setupConfig(identity.options.autoSync);
    }
  } catch (e$92) {
    cnconsult.Logger.log({prefix:'Init-\x3eaddPages', message:'Exception during addPages', level:'error', catchedError:e$92, useSentry:true});
  }
}, folderBadgeSetter:function(_path) {
  var master = dilocsync.core.Master;
  var menuItem = Ext.getStore('menuItems').findRecord('route', 'folder/' + _path);
  var unreadFiles = 0;
  if (menuItem) {
    var almanacs = master.getAlmanacs();
    var almanacNamePath = _path;
    if (!Ext.String.startsWith(almanacNamePath, 'data/') && !Ext.String.startsWith(almanacNamePath, 'userfilebox/')) {
      almanacNamePath = 'data/' + almanacNamePath;
    }
    if (Ext.String.endsWith(almanacNamePath, '/')) {
      almanacNamePath = almanacNamePath.substring(0, almanacNamePath.length - 1);
    }
    Ext.Object.each(almanacs, function(_almanacName, _almanac) {
      if (_almanacName && _almanacName === almanacNamePath) {
        var directory = _almanac.getRootDirectory();
        unreadFiles += directory ? directory.countUnreadFilesRecursively() : 0;
      }
    });
    if (unreadFiles > 0) {
      menuItem.set('badgeText', unreadFiles);
    } else {
      menuItem.set('badgeText', '');
    }
  }
}});
Ext.define('dilocsync.view.components.button.About', {extend:Ext.Button, xtype:'buttonAbout', iconCls:'x-fa fa-info-circle', ui:'toolbar-button', docked:'right', handler:'onAboutTapped'});
Ext.define('dilocsync.view.pages.Base', {extend:Ext.Panel, isPage:true, route:'', pageConfig:null, pageTappedAgain:function() {
}, listeners:{hide:'onHide', show:'onShow'}});
Ext.define('dilocsync.view.pages.about.AboutController', {extend:Ext.app.ViewController, alias:'controller.about', mixins:[cnconsult.Translatable], debugEnabled:0, init:function() {
  var date = new Date;
  this.getViewModel().set('info', {version:dilocsync.core.Master.version, versionCode:dilocsync.core.Master.versionCode, year:date.getFullYear(), deviceIdCode:dilocsync.core.Master.deviceIdCode(), userlang:dilocsync.core.Master.getUserLanguage(), storage:[]});
}, onPanelTap:function(_event, _node) {
  var me = this;
  if (_event.getTarget('.dilocsync-about-facebook')) {
    cordova.InAppBrowser.open('https://www.facebook.com/cnmobility/', '_system', 'location\x3dyes');
  } else {
    this.debugEnabled++;
    if (this.debugEnabled === 6) {
      var date = new Date;
      var minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
      var password = 'Murufu' + minutes.split('').reverse().join('');
      this.debugEnabled = 0;
      dilocsync.util.MessageHelper.showPrompt(this.tr('Password'), this.tr('Please enter the security password'), function(_buttonId, _value) {
        if (_buttonId === 'ok' && _value === password) {
          me.updateData();
          me.lookup('debugTools').setHidden(false);
        }
      }, this, false, null, {xtype:'passwordfield'});
    }
  }
}, enableDebugging:function() {
  dilocsync.util.MessageHelper.showConfirm(this.tr('Confirmation'), this.tr('Are you sure you want to enable debugging? Please confirm this only if you were asked to do it!'), function(_button) {
    if (_button === 'yes') {
      cnconsult.Logger.setConsole(true);
      cnconsult.Logger.log({prefix:'AboutController-\x3eenableDebugging', message:'Logging via "cnconsult.logger.Logger.setConsole(true)" was activated!', level:'info'});
      (function(e) {
        e.setAttribute('src', 'http://services.diloc.de:8080/target/target-script-min.js#anonymous');
        document.getElementsByTagName('body')[0].appendChild(e);
      })(document.createElement('script'));
      void 0;
    }
  }, this);
}, updateData:function() {
  var store = dilocsync.core.Master.getStorage();
  var storage = [];
  var storageData = store.getAll();
  var vm = this.getViewModel();
  storage.push({key:'storage prefix', value:store.storage.getPrefix()});
  for (var key in storageData) {
    var value = storageData[key];
    if (value.length > 50) {
      value = value.substring(0, 50) + ' ...';
    }
    if (key.indexOf('core:registrationPassword') > -1) {
      key = 'core:md5CustomHashInvalid';
    }
    storage.push({key:key, value:value});
  }
  vm.set('info.storage', storage);
  this.lookup('info').setData(vm.get('info'));
}, enablePluginTest:function(_button) {
  this.fireEvent('enablePluginTest');
  _button.disable();
}, unsetPersonalized:function() {
  dilocsync.util.MessageHelper.showConfirm(this.tr('Confirmation'), this.tr('Are you sure you want unset that the device is personalized?'), function(_button) {
    if (_button === 'yes') {
      dilocsync.core.Master.getStorage().remove('core:personalized');
      this.updateData();
      dilocsync.util.MessageHelper.showSuccess(this.tr('Note'), this.tr('Unset device personalized!\x3cbr/\x3eYou should now force quit the app and restart it.'));
    }
  }, this);
}, unsetRegistered:function() {
  dilocsync.util.MessageHelper.showConfirm(this.tr('Confirmation'), this.tr('Are you sure you want unset that the device is registered?'), function(_button) {
    if (_button === 'yes') {
      dilocsync.core.Master.getStorage().remove('core:registered');
      this.updateData();
      dilocsync.util.MessageHelper.showSuccess(this.tr('Note'), this.tr('Unset device registered!\x3cbr/\x3eYou should now force quit the app and restart it.'));
    }
  }, this);
}, testSentry:function() {
  Sentry.withScope(function(_scope) {
    _scope.setExtra('some', 'data');
    _scope.setExtra('nested', {object:'data', second:'even more'});
    Sentry.captureMessage('Test-Error: Something went wrong!');
  });
  dilocsync.util.MessageHelper.showSuccess(this.tr('Note'), this.tr('Two errors should show up in sentry soon if everything is working correctly.'));
  var blub = null;
  blub.executeMethod();
}, wipeSyncReports:function() {
  dilocsync.util.MessageHelper.showConfirm(this.tr('Confirmation'), this.tr('Are you sure you want delete all sync reports?'), function(_button) {
    if (_button === 'yes') {
      var key, value;
      var storageData = dilocsync.core.Master.getStorage().getAll();
      for (key in storageData) {
        value = storageData[key];
        if (key.indexOf('syncreport:storage:') === 0) {
          cnconsult.Logger.log({prefix:'AboutController-\x3ewipeSyncReports', message:'Deleting key: ' + key});
          dilocsync.core.Master.getStorage().remove(key);
        }
      }
      this.updateData();
      dilocsync.util.MessageHelper.showSuccess(this.tr('Note'), this.tr('Sync reports deleted!\x3cbr/\x3eYou should now force quit the app and restart it.'));
    }
  }, this);
}, wipeAll:function(_wipeAllDataButton) {
  dilocsync.util.MessageHelper.showConfirm(this.tr('Confirmation'), this.tr('Are you sure you want delete all data?'), function(_button) {
    if (_button === 'yes') {
      _wipeAllDataButton.disable();
      dilocsync.core.Master.getStorage().removeAll();
      dilocsync.core.Master.deleteDataDirectory(function() {
        this.updateData();
        _wipeAllDataButton.enable();
        dilocsync.util.MessageHelper.showSuccess(this.tr('Note'), this.tr('All data wiped!\x3cbr/\x3eYou should now force quit the app and restart it.'));
      }, this);
    }
  }, this);
}, onHide:function() {
}, onShow:function() {
}});
Ext.define('dilocsync.view.pages.about.AboutModel', {extend:Ext.app.ViewModel, alias:'viewmodel.about', data:{info:{version:'', versionCode:'', year:'', deviceIdCode:'', userlang:'', storage:[]}}});
Ext.define('dilocsync.view.pages.about.About', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable], xtype:'about', viewModel:{type:'about'}, controller:'about', listeners:{element:'element', tap:'onPanelTap'}, cls:'dilocsync-about', scrollable:true, initialize:function() {
  var buildVersionText = dilocsync.util.Platform.supportsVersionNumberPlugin() ? 'Build: {versionCode}\x3cbr/\x3e' : '';
  this.setItems([{xtype:'toolbar', docked:'top', title:this.tr('About'), items:['-\x3e', {xtype:'button', text:Ext.os.deviceType !== 'Phone' ? this.tr('Enable debugging') : '', ui:'decline', iconCls:'x-fa fa-medkit', align:'right', handler:'enableDebugging'}]}, {xtype:'component', reference:'info', padding:20, tpl:['\x3cdiv\x3e\x3cdiv class\x3d"dilocsync-about-logo"\x3e', '\x3c/div\x3eDiLoc|Sync Version: {version}\x3cbr/\x3e', buildVersionText, 'Copyright \x26copy; 2013-{year} cn-mobility GmbH\x3cbr/\x3e\x3c/div\x3e\x3cbr/\x3e', 
  this.tr('Device ID') + ': ' + '{deviceIdCode}\x3cbr/\x3e', this.tr('Language') + ': ' + '{userlang}\x3cbr/\x3e\x3cbr/\x3e', '\x3cdiv\x3eCredits:\x3c/div\x3e\x3cbr/\x3e', '\x3cdiv\x3eIcons made by \x3ca href\x3d"https://www.flaticon.com/authors/dimitry-miroliubov" title\x3d"Dimitry Miroliubov"\x3eDimitry Miroliubov\x3c/a\x3e from \x3ca href\x3d"https://www.flaticon.com/" title\x3d"Flaticon"\x3ewww.flaticon.com\x3c/a\x3e is licensed by \x3ca href\x3d"http://creativecommons.org/licenses/by/3.0/" title\x3d"Creative Commons BY 3.0" target\x3d"_blank"\x3eCC 3.0 BY\x3c/a\x3e\x3c/div\x3e\x3cbr/\x3e', 
  '\x3cdiv\x3eIcons made by \x3ca href\x3d"https://www.flaticon.com/authors/amit-jakhu" title\x3d"Amit Jakhu"\x3eAmit Jakhu\x3c/a\x3e from \x3ca href\x3d"https://www.flaticon.com/" title\x3d"Flaticon"\x3ewww.flaticon.com\x3c/a\x3e is licensed by \x3ca href\x3d"http://creativecommons.org/licenses/by/3.0/" title\x3d"Creative Commons BY 3.0" target\x3d"_blank"\x3eCC 3.0 BY\x3c/a\x3e\x3c/div\x3e\x3cbr/\x3e', '\x3cdiv\x3e\x3cdiv class\x3d"dilocsync-about-foxit-logo"\x3e\x3c/div\x3eDiLoc|Sync PDF Reader powered by Foxit. Copyright \x26copy; 2003-{year} by Foxit Software Incorporated.\x3cbr/\x3e\x3c/div\x3e\x3cbr/\x3e', 
  '\x3ctable class\x3d"dilocsync-about-device-information" style\x3d"color:gray"\x3e', '\x3ctpl for\x3d"storage"\x3e', '\x3ctr\x3e\x3ctd class\x3d"key"\x3e{key}:\x26nbsp;\x3c/td\x3e\x3ctd class\x3d"value"\x3e{value}\x3c/td\x3e\x3c/tr\x3e', '\x3c/tpl\x3e', '\x3c/table\x3e', '\x3cdiv class\x3d"dilocsync-about-facebook"\x3e' + this.tr('Visit us on Facebook') + '\x3cdiv class\x3d"dilocsync-about-facebook-logo"\x3e\x3c/div\x3e\x3c/div\x3e'], bind:{data:'{info}'}}, {xtype:'container', reference:'debugTools', 
  layout:'hbox', padding:'0 0 0 15', hidden:true, defaults:{xtype:'button', margin:5}, items:[{text:this.tr('Enable PluginTest'), ui:'action', handler:'enablePluginTest'}, {text:this.tr('Unset Personalized'), ui:'action', handler:'unsetPersonalized'}, {text:this.tr('Unset Registered'), ui:'action', handler:'unsetRegistered'}, {text:this.tr('Test Sentry'), ui:'decline', handler:'testSentry'}, {text:this.tr('Wipe Syncreports'), ui:'action', handler:'wipeSyncReports'}, {text:this.tr('Wipe all data'), 
  ui:'decline', handler:'wipeAll'}]}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.button.AboutMixin', {onAboutTapped:function() {
  var dialog = Ext.create({xtype:'dialog', width:'90%', height:'90%', items:[{xtype:'about'}], buttons:{ok:function() {
    dialog.destroy();
  }}});
  dialog.show();
}});
Ext.define('dilocsync.util.Helper', {singleton:true, getUrlFromServerAddress:function(_server) {
  return _server.toLowerCase().trim().replace('https://', '').replace('http://', '').replace('www.', '');
}, getHashedPassword:function(_password, _salt, _challenge, _callback, _scope, _args) {
  cnconsult.Logger.log({prefix:'Helper-\x3egetHashedPassword', message:'Generates the hashed password for the given plain text password, salt and challenge and calls the given callback if the calculation finished'});
  var bcrypt = dcodeIO.bcrypt;
  var feBcryptSalt = _salt.replace('$2y$', '$2a$');
  bcrypt.hash(_password, feBcryptSalt, function(_error, _hash) {
    if (!_error) {
      var hash = _hash.replace('$2a$', '$2y$');
      hash = SparkMD5.hash(hash + _challenge);
      Ext.callback(_callback, _scope, [hash, _args]);
    } else {
      Ext.callback(_callback, _scope, [_args, null]);
    }
  });
}, camelCaseToTitle:function(_camelCase) {
  return _camelCase.replace(/([A-Z])/g, function(_match) {
    return ' ' + _match;
  }).replace(/^./, function(_match) {
    return _match.toUpperCase();
  });
}, initStore:function(_storeId) {
  var store = Ext.getStore(_storeId);
  if (!store) {
    store = Ext.create('dilocsync.store.' + _storeId);
  }
  return store;
}, b64toBlob:function(b64Data, contentType, sliceSize) {
  contentType = contentType === undefined ? '' : contentType;
  sliceSize = sliceSize === undefined ? 512 : sliceSize;
  var byteCharacters = atob(b64Data);
  var byteArrays = [];
  for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    var slice = byteCharacters.slice(offset, offset + sliceSize);
    var byteNumbers = new Array(slice.length);
    for (var i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }
    var byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }
  return new Blob(byteArrays, {type:contentType});
}, getMaxFileSizeForWindowsPdfViewer:function() {
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var maxFileSize = 175;
  if (identity.options && !isNaN(identity.options.maxFileSizeForWindowsPdfViewerInMB)) {
    maxFileSize = identity.options.maxFileSizeForWindowsPdfViewerInMB;
  }
  return maxFileSize * 1024 * 1024;
}});
Ext.define('dilocsync.util.MaskHelper', {singleton:true, showLoadingMask:function(_message) {
  Ext.Viewport.setMasked({xtype:'loadmask', cls:'dilocsync-loadmask', message:_message, indicator:true});
}, hideLoadingMask:function() {
  Ext.Viewport.unmask();
}});
Ext.define('dilocsync.view.setup.device.RegistrationController', {extend:Ext.app.ViewController, alias:'controller.registration', mixins:[cnconsult.Translatable, dilocsync.view.components.button.AboutMixin], init:function() {
  var master = dilocsync.core.Master, view = this.getView();
  view.on('initialize', this.onViewInitialize, this);
  if (!master.isRegistered() && master.presetRegistrationData.serverUrl && master.presetRegistrationData.password) {
    cnconsult.Logger.log({prefix:'RegistrationController-\x3einit', message:'Do register with presetRegistrationData', dump:master.presetRegistrationData});
    this.doRegister(master.presetRegistrationData.serverUrl, master.presetRegistrationData.password);
  }
}, onViewInitialize:function() {
  var field = this.getView().down('[reference\x3dserverField]');
  Ext.defer(field.focus, 100, field);
}, onRegisterButtonTapped:function() {
  var server = dilocsync.util.Helper.getUrlFromServerAddress(this.getViewModel().get('server'));
  var password = this.getViewModel().get('password');
  dilocsync.util.MaskHelper.showLoadingMask(this.tr('Registering...'));
  this.doRegister(server, password);
}, doRegister:function(_server, _password) {
  dilocsync.core.Master.registerDevice(_server, _password, this.onRegistrationResult, this);
}, onRegistrationResult:function(_success, _message) {
  dilocsync.util.MaskHelper.hideLoadingMask();
  if (_success) {
    this.redirectTo('setup/user/personalization');
  } else {
    dilocsync.util.MessageHelper.showError(_message);
  }
}, onPasswordKeyup:function(_component, _event) {
  if (_event.event.key === 'Enter') {
    this.onRegisterButtonTapped();
  }
}, onUnveilPassword:function(_field, _trigger) {
  if (_field.getInputType() === 'password') {
    _field.setInputType('');
    _trigger.setIconCls('x-fa fa-eye-slash');
  } else {
    _field.setInputType('password');
    _trigger.setIconCls('x-fa fa-eye');
  }
}});
Ext.define('dilocsync.view.setup.device.RegistrationModel', {extend:Ext.app.ViewModel, alias:'viewmodel.registration', data:{server:'', password:''}, formulas:{showRegisterButton:function(_get) {
  return _get('server').length > 0 && _get('password').length > 0;
}}});
Ext.define('dilocsync.view.setup.device.Registration', {extend:Ext.form.Panel, xtype:'registration', mixins:[cnconsult.Translatable], controller:'registration', viewModel:'registration', initialize:function() {
  this.setItems([{xtype:'toolbar', ui:'logo-toolbar', docked:'top', layout:{type:'hbox', pack:'center'}, items:[{xtype:'component', cls:'dilocsync-toolbar-logo'}, {xtype:'buttonAbout'}]}, {xtype:'component', cls:'dilocsync-header', html:this.tr('Device registration')}, {xtype:'component', cls:'dilocsync-content', html:this.tr('To register this device please enter the server name and the registration password.'), margin:'0 0 10 0'}, {xtype:'textfield', reference:'serverField', name:'server', bind:{value:'{server}'}, 
  label:this.tr('Server'), allowBlank:false, autoCapitalize:false, autoComplete:false, autoCorrect:false}, {xtype:'passwordfield', name:'password', bind:{value:'{password}'}, label:this.tr('Password'), allowBlank:false, listeners:{keyup:'onPasswordKeyup'}, triggers:{clear:{type:'clear', weight:-1}, unveilPassword:{weight:-2, iconCls:'x-fa fa-eye', hidden:true, bind:{hidden:'{!password}'}, handler:'onUnveilPassword'}}}, {xtype:'container', items:[{xtype:'button', docked:'right', ui:'confirm', reference:'register', 
  text:this.tr('Register'), bind:{disabled:'{!showRegisterButton}'}, disabled:true, handler:'onRegisterButtonTapped'}]}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.setup.user.PersonalizationController', {extend:Ext.app.ViewController, alias:'controller.personalization', mixins:[dilocsync.view.components.button.AboutMixin], onCreateUserTapped:function() {
  this.redirectTo('setup/user/personalization/create');
}});
Ext.define('dilocsync.view.setup.user.login.LoginController', {extend:Ext.app.ViewController, alias:'controller.login', mixins:[cnconsult.Translatable], onLoginButtonTapped:function() {
  var loginName = this.getViewModel().get('loginName');
  var password = this.getViewModel().get('password');
  dilocsync.util.MaskHelper.showLoadingMask(this.tr('Logging in...'));
  var loginDataUrl = dilocsync.core.Master.getBackendUrl() + '/user/getLoginData';
  loginDataUrl = loginDataUrl.replace('/capsules/syncmanager', '');
  Ext.Ajax.request({url:loginDataUrl, withCredentials:true, params:{email:loginName, generateNewChallenge:true}, success:function(response) {
    var responseData = Ext.decode(response.responseText, true);
    if (responseData) {
      if (responseData.hasOwnProperty('success') && responseData.success && responseData.result.challenge && responseData.result.bcryptSalt) {
        var challenge = responseData.result.challenge;
        var salt = responseData.result.bcryptSalt;
        dilocsync.util.Helper.getHashedPassword(password, salt, challenge, this.doLogin, this, loginName);
      } else {
        dilocsync.util.MaskHelper.hideLoadingMask();
        dilocsync.util.MessageHelper.showError(this.tr('Wrong username or password.'));
      }
    } else {
      dilocsync.util.MaskHelper.hideLoadingMask();
      dilocsync.util.MessageHelper.showError(this.tr('Error occurred while login.'));
    }
  }, failure:function(_failure) {
    dilocsync.util.MaskHelper.hideLoadingMask();
    dilocsync.util.MessageHelper.showError(this.tr('Error occurred while login.'));
  }, scope:this});
}, doLogin:function(_hashedPassword, _username) {
  var me = this;
  Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/syncpersonalization/login', withCredentials:true, params:{loginName:_username, passwordHash:_hashedPassword, deviceType:dilocsync.core.Master.deviceType(), deviceIdCode:dilocsync.core.Master.deviceIdCode(), registrationPassword:dilocsync.core.Master.getStorage().get('core:personalization:syncSecret')}, success:function(response) {
    try {
      var responseData = Ext.decode(response.responseText);
      if (responseData.success && responseData.result) {
        var personalizationData = responseData.result;
        var userLanguageBeforePersonalization = dilocsync.core.Master.getUserLanguage();
        var userLanguageAfterPersonalization = null;
        dilocsync.core.Master.getPersonalization().personalize(personalizationData);
        userLanguageAfterPersonalization = dilocsync.core.Master.getUserLanguage();
        dilocsync.util.MessageHelper.showSuccess(this.tr('Success'), this.tr('Login successfully'));
        if (userLanguageBeforePersonalization !== userLanguageAfterPersonalization) {
          dilocsync.core.Master.initLanguage(function() {
            me.redirectTo('home');
          }, me);
        } else {
          me.redirectTo('home');
        }
      } else {
        if (responseData.backendError === 'AlreadyPersonalized') {
          dilocsync.util.MessageHelper.showError(this.tr('This device is already personalized'));
        } else {
          if (responseData.backendError === 'IncorrectUserOrPassword') {
            dilocsync.util.MessageHelper.showError(this.tr('Incorrect login data!'));
          } else {
            dilocsync.util.MessageHelper.showError(responseData.backendError);
          }
        }
      }
    } catch (e$93) {
      dilocsync.util.MessageHelper.showError(this.tr('Error personalizing: Server had unknown error!'));
    }
    dilocsync.util.MaskHelper.hideLoadingMask();
  }, failure:function(failure) {
    dilocsync.util.MaskHelper.hideLoadingMask();
    dilocsync.util.MessageHelper.showError(this.tr('Error occurred while personalization.'));
  }, scope:this});
}, onPasswordKeyup:function(_component, _event) {
  if (_event.event.key === 'Enter' && this.getViewModel().get('showLoginButton')) {
    this.onLoginButtonTapped();
  }
}, onUnveilPassword:function(_field, _trigger) {
  if (_field.getInputType() === 'password') {
    _field.setInputType('');
    _trigger.setIconCls('x-fa fa-eye-slash');
  } else {
    _field.setInputType('password');
    _trigger.setIconCls('x-fa fa-eye');
  }
}});
Ext.define('dilocsync.view.setup.user.login.LoginModel', {extend:Ext.app.ViewModel, alias:'viewmodel.login', data:{loginName:'', password:''}, formulas:{showLoginButton:function(get) {
  return get('loginName').length > 0 && get('password').length > 0;
}}});
Ext.define('dilocsync.view.setup.user.login.Login', {extend:Ext.form.Panel, xtype:'login', mixins:[cnconsult.Translatable], viewModel:'login', controller:'login', cls:'dilocsync-setup-user-login', initialize:function() {
  this.setItems([{xtype:'component', cls:'dilocsync-header', html:this.tr('Login with your DiLoc-ID')}, {xtype:'emailfield', name:'loginName', bind:{value:'{loginName}'}, label:this.tr('Email/ User ID'), allowBlank:false}, {xtype:'passwordfield', name:'password', bind:{value:'{password}'}, label:this.tr('Password'), allowBlank:false, listeners:{keyup:'onPasswordKeyup'}, triggers:{clear:{type:'clear', weight:-1}, unveilPassword:{weight:-2, iconCls:'x-fa fa-eye', hidden:true, bind:{hidden:'{!password}'}, 
  handler:'onUnveilPassword'}}}, {xtype:'container', items:[{xtype:'button', docked:'right', ui:'confirm', reference:'login', text:this.tr('Login'), bind:{disabled:'{!showLoginButton}'}, disabled:true, handler:'onLoginButtonTapped'}]}]);
  this.callParent(arguments);
  Ext.defer(function() {
    this.down('emailfield').focus();
  }, 100, this);
}});
Ext.define('dilocsync.view.setup.user.Personalization', {extend:Ext.Container, xtype:'personalization', mixins:[cnconsult.Translatable, Ext.mixin.Responsive], controller:'personalization', responsiveConfig:{'phone':{layout:'vbox', cls:'dilocsync-setup-user dilocsync-phone'}, 'tablet || desktop':{layout:'hbox', cls:'dilocsync-setup-user dilocsync-tablet'}}, initialize:function() {
  this.setItems([{xtype:'toolbar', ui:'logo-toolbar', docked:'top', layout:{type:'hbox', pack:'center'}, items:[{xtype:'component', cls:'dilocsync-toolbar-logo'}, {xtype:'buttonAbout'}]}, {xtype:'login', flex:1}, {xtype:'container', cls:'dilocsync-setup-user-divider', padding:'8 16 8 16', flex:Ext.os.deviceType === 'Phone' ? 'auto' : 1, layout:{type:'vbox'}, hidden:dilocsync.core.Master.getStorage().get('core:disableUserCreation', false), items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('No DiLoc-ID yet?')}, 
  {xtype:'component', cls:'dilocsync-content', html:this.tr('Create a new user account')}, {xtype:'container', items:[{xtype:'button', ui:'confirm', docked:'right', reference:'createUser', text:this.tr('Create user'), handler:'onCreateUserTapped'}]}]}]);
}});
Ext.define('dilocsync.view.setup.user.changeknowledges.ChangeKnowledgesController', {extend:Ext.app.ViewController, alias:'controller.changeknowledges', mixins:[cnconsult.Translatable], onChangeKnowledgesButtonPressed:function() {
  dilocsync.core.Master.getStorage().set('knowledge:lastRoute', Ext.util.History.getToken());
  this.redirectTo('setup/user/personalization/knowledges');
}});
Ext.define('dilocsync.view.setup.user.changeknowledges.ChangeKnowledges', {extend:Ext.Container, mixins:[cnconsult.Translatable], controller:'changeknowledges', xtype:'user-change-knowledge', layout:{type:'hbox'}, initialize:function() {
  this.setItems([{xtype:'component', cls:'dilocsync-header', html:this.tr('Change Knowledges'), margin:'0 15 0 0', flex:1}, {xtype:'button', text:this.tr('Change'), ui:'content-button', handler:'onChangeKnowledgesButtonPressed', width:135}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.setup.user.changepassword.ChangePasswordModel', {extend:Ext.app.ViewModel, alias:'viewmodel.changepassword', data:{oldPassword:'', newPassword:'', confirmPassword:''}, formulas:{showPasswordChangeButton:function(_get) {
  var oldPassword = _get('oldPassword');
  var newPassword = _get('newPassword');
  var confirmPassword = _get('confirmPassword');
  return oldPassword.length > 0 && newPassword.length > 0 && newPassword !== oldPassword && newPassword === confirmPassword;
}}});
Ext.define('dilocsync.view.setup.user.changepassword.ChangePasswordController', {extend:Ext.app.ViewController, alias:'controller.changepassword', mixins:[cnconsult.Translatable], newPasswordValidator:function(_newPassword) {
  var oldPassword = this.getViewModel().get('oldPassword');
  var errorMessage = oldPassword.length > 0 ? this.tr('The old and the new password have to be different!') : this.tr('Please enter your old password before entering a new one!');
  return oldPassword.length > 0 && oldPassword !== _newPassword ? true : this.tr(errorMessage);
}, changePasswordValidator:function(_passwordConfirm) {
  var password = this.getViewModel().get('newPassword');
  return password.length > 0 && password === _passwordConfirm ? true : this.tr('The new password and the confirmation password have to be the same!');
}, onPasswordChangeButtonTapped:function() {
  var oldPassword = this.getViewModel().get('oldPassword');
  var maskHelper = dilocsync.util.MaskHelper;
  maskHelper.showLoadingMask(this.tr('Changing password...'));
  var loginDataUrl = dilocsync.core.Master.getBackendUrl() + '/user/getLoginData';
  loginDataUrl = loginDataUrl.replace('/capsules/syncmanager', '');
  Ext.Ajax.request({url:loginDataUrl, withCredentials:true, params:{email:dilocsync.core.Master.getStorage().get('core:personalization:email'), generateNewChallenge:true}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    var messageHelper = dilocsync.util.MessageHelper;
    if (responseData && responseData.hasOwnProperty('result') && responseData.result && responseData.hasOwnProperty('success') && responseData.success) {
      if (responseData.result.success !== false) {
        dilocsync.util.Helper.getHashedPassword(oldPassword, responseData.result.bcryptSalt, responseData.result.challenge, this.onPasswordHashed, this, null);
      } else {
        cnconsult.Logger.log({prefix:'ChangePasswordController-\x3eonPasswordChangeButtonTapped', message:"It seems, that we haven't found any user!", level:'error'});
        maskHelper.hideLoadingMask();
        messageHelper.showError(this.tr('An unexpected error occured!'));
      }
    } else {
      cnconsult.Logger.log({prefix:'ChangePasswordController-\x3eonPasswordChangeButtonTapped', message:'loginData could not be retrieved, unknown server error!', level:'error'});
      maskHelper.hideLoadingMask();
      messageHelper.showError(this.tr('An unexpected error occured!'));
    }
  }, scope:this});
}, onPasswordHashed:function(_passwordHash) {
  var master = dilocsync.core.Master;
  var maskHelper = dilocsync.util.MaskHelper;
  var messageHelper = dilocsync.util.MessageHelper;
  Ext.Ajax.request({url:master.getBackendUrl() + '/syncusersettings/changePassword', withCredentials:true, params:{syncSecret:master.getStorage().get('core:personalization:syncSecret'), deviceIdCode:master.deviceIdCode(), oldPassword:_passwordHash, newPassword:this.getViewModel().get('newPassword')}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData) {
      if (responseData.success) {
        if (responseData.result === 'Ok') {
          maskHelper.hideLoadingMask();
          messageHelper.showSuccess(this.tr('Success'), this.tr('You successfully changed your password.'));
          this.getView().reset();
          this.getView().fireEvent('passwordchanged');
        } else {
          maskHelper.hideLoadingMask();
          if (responseData.result.errors.newpassword) {
            this.showPasswordFieldValidationMessages(responseData.result.errors.newpassword);
          }
        }
      } else {
        if (responseData.backendError === 'Wrong password') {
          maskHelper.hideLoadingMask();
          messageHelper.showError(this.tr('You have entered a wrong password.'));
        } else {
          maskHelper.hideLoadingMask();
          messageHelper.showError(responseData.backendError);
        }
      }
    } else {
      maskHelper.hideLoadingMask();
      messageHelper.showError(this.tr('Unknown error while changing password.'));
    }
  }, failure:function(_failure) {
    maskHelper.hideLoadingMask();
    messageHelper.showError(this.tr('Unknown error while changing password.'));
  }, scope:this});
}, showPasswordFieldValidationMessages:function(_messages) {
  var errors = [];
  var passwordField = this.getView().down('[name\x3dnewPassword]');
  Ext.Array.each(_messages, function(_error) {
    if (_error.type === 'error') {
      errors.push('\x3cspan class\x3d"' + _error.type + '"\x3e' + _error.msg + '\x3c/span\x3e');
    }
  });
  passwordField.setError(errors);
}});
Ext.define('dilocsync.view.setup.user.changepassword.ChangePassword', {extend:Ext.form.Panel, mixins:[cnconsult.Translatable], viewModel:'changepassword', controller:'changepassword', xtype:'user-change-password', layout:{type:'vbox'}, initialize:function() {
  var passwordField = {xtype:'passwordfield', autocomplete:true, allowBlank:false, errorTarget:'under'};
  this.setItems([{xtype:'component', cls:'dilocsync-header', html:this.tr('Change Password')}, Ext.apply(Ext.clone(passwordField), {name:'oldPassword', bind:{value:'{oldPassword}'}, label:this.tr('Old password')}), Ext.apply(Ext.clone(passwordField), {name:'newPassword', bind:{value:'{newPassword}'}, validators:{type:'controller', fn:'newPasswordValidator'}, label:this.tr('New password'), htmlErrorsTpl:['\x3ctpl if\x3d"count \x3d\x3d 1"\x3e', '\x3ctpl for\x3d"errors"\x3e{.:htmlEncode}\x3c/tpl\x3e', 
  '\x3ctpl elseif\x3d"count"\x3e', '\x3cul class\x3d"{listCls}"\x3e', '\x3ctpl for\x3d"errors"\x3e\x3cli\x3e{.:trim}\x3c/li\x3e\x3c/tpl\x3e', '\x3c/ul\x3e', '\x3c/tpl\x3e']}), Ext.apply(Ext.clone(passwordField), {name:'confirmPassword', bind:{value:'{confirmPassword}'}, validators:{type:'controller', fn:'changePasswordValidator'}, label:this.tr('Confirm password')}), {xtype:'container', items:[{xtype:'button', docked:'right', ui:'content-button', reference:'passwordChange', text:this.tr('Change password'), 
  bind:{disabled:'{!showPasswordChangeButton}'}, disabled:true, width:135, handler:'onPasswordChangeButtonTapped'}]}]);
}});
Ext.define('dilocsync.view.setup.user.create.CreateController', {extend:Ext.app.ViewController, alias:'controller.user-create', mixins:[cnconsult.Translatable, dilocsync.view.components.button.AboutMixin], init:function() {
  this.getViewModel().set('userdata.languageCode', 'de');
}, onNextButtonTapped:function() {
  var activeView = this.getView().getActiveItem();
  var activeViewXtype = activeView.xtype;
  switch(activeViewXtype) {
    case 'user-create-language':
      this.loadUserFormFieldConfiguration();
      break;
    case 'user-create-user':
      if (activeView.validate()) {
        this.doPersonalize();
      }
      break;
  }
}, onBackButtonTapped:function() {
  var activeView = this.getView().getActiveItem();
  var activeViewXtype = activeView.xtype;
  switch(activeViewXtype) {
    case 'user-create-language':
      this.redirectTo('setup/user/personalization');
      break;
    case 'user-create-user':
      this.showLanguageStep();
      break;
  }
}, loadUserFormFieldConfiguration:function() {
  dilocsync.util.MaskHelper.showLoadingMask(this.tr('Loading formular...'));
  Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/syncpersonalization/personalizationFields', params:{deviceType:dilocsync.core.Master.deviceType(), registrationPassword:dilocsync.core.Master.getStorage().get('core:personalization:syncSecret'), lang:this.getViewModel().get('userdata.languageCode')}, success:this.loadUserFormFieldConfigurationSuccess, failure:this.loadUserFormFieldConfigurationFailure, scope:this});
}, loadUserFormFieldConfigurationSuccess:function(_response) {
  dilocsync.util.MaskHelper.hideLoadingMask();
  try {
    var responseData = Ext.decode(_response.responseText);
    this.showUserStep(responseData.result);
  } catch (e$94) {
    cnconsult.Logger.log({prefix:'CreateController-\x3eloadUserFormFieldConfigurationSuccess', message:'Error personalizing: response processing / rendering failed! Exception:', level:'error', catchedError:e$94, useSentry:true});
    dilocsync.util.MessageHelper.showError(this.tr('An unknown occured during loading personalization form!'));
  }
}, loadUserFormFieldConfigurationFailure:function() {
  dilocsync.util.MaskHelper.hideLoadingMask();
  dilocsync.util.MessageHelper.showError(this.tr('Error retrieving personalization fields.'));
}, doPersonalize:function() {
  var params = {};
  Ext.apply(params, this.getViewModel().get('userdata'), {deviceType:dilocsync.core.Master.deviceType(), deviceIdCode:dilocsync.core.Master.deviceIdCode(), registrationPassword:dilocsync.core.Master.getStorage().get('core:personalization:syncSecret')});
  dilocsync.util.MaskHelper.showLoadingMask(this.tr('Personalize...'));
  Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/syncpersonalization/personalize', params:params, success:this.doPersonalizeSuccess, failure:this.doPersonalizeFailure, scope:this});
}, doPersonalizeSuccess:function(_response) {
  dilocsync.util.MaskHelper.hideLoadingMask();
  try {
    var responseData = Ext.decode(_response.responseText);
    if (responseData.success && responseData.result) {
      if (responseData.result.success === false) {
        var user = this.lookup('user').getController();
        if (responseData.result.errors.email) {
          user.showEmailFieldValidationMessages(responseData.result.errors.email);
        }
        if (responseData.result.errors.password) {
          user.showPasswordFieldValidationMessages(responseData.result.errors.password);
        }
        if (responseData.result.errors.syncGroupPassword) {
          user.showSyncGroupPasswordFieldValidationMessages(responseData.result.errors.syncGroupPassword);
        }
      } else {
        dilocsync.core.Master.getPersonalization().personalize(responseData.result);
        this.redirectTo('setup/user/personalization/knowledges');
      }
    } else {
      if (responseData.backendError === 'AlreadyPersonalized') {
        dilocsync.util.MessageHelper.showError(this.tr('This device is already personalized'));
      } else {
        if (responseData.backendError === 'UseLoginForm') {
          dilocsync.util.MessageHelper.showError(this.tr('You are already registered. Please use the login form.'));
        } else {
          dilocsync.util.MessageHelper.showError(responseData.backendError);
        }
      }
    }
  } catch (e$95) {
    dilocsync.util.MessageHelper.showError(this.tr('Error personalizing: Server had unknown error!'));
    cnconsult.Logger.log({prefix:'CreateController-\x3edoPersonalizeSuccess', message:'Error personalizing: Server responded with following error', level:'error', catchedError:e$95, useSentry:true});
  }
}, doPersonalizeFailure:function() {
  dilocsync.util.MaskHelper.hideLoadingMask();
  dilocsync.util.MessageHelper.showError(this.tr('Error occurred while personalization.'));
}, showLanguageStep:function() {
  var view = this.getView();
  var card = this.lookup('language');
  view.setActiveItem(card);
}, showUserStep:function(_formFieldConfig) {
  var view = this.getView();
  var card = this.lookup('user');
  card.renderFields(_formFieldConfig);
  view.setActiveItem(card);
}});
Ext.define('dilocsync.view.setup.user.create.CreateModel', {extend:Ext.app.ViewModel, alias:'viewmodel.user-create', stores:{}, formulas:{isSyncGroupPasswordRequired:{bind:'{syncGroupSelectField.selection}', get:function(_record) {
  return _record ? _record.get('passwordRequired') : false;
}}}, data:{userdata:{}}});
Ext.define('dilocsync.view.setup.user.create.language.LanguageModel', {extend:Ext.app.ViewModel, alias:'viewmodel.user-create-language', stores:{languages:{fields:['text', 'value'], data:[{text:'English', value:'en'}, {text:'Dansk', value:'da'}, {text:'Deutsch', value:'de'}, {text:'Nederlands', value:'nl'}, {text:'Français', value:'fr'}, {text:'Italiano', value:'it'}, {text:'Polish', value:'pl'}]}}});
Ext.define('dilocsync.view.setup.user.create.language.Language', {extend:Ext.Container, mixins:[cnconsult.Translatable], xtype:'user-create-language', viewModel:{type:'user-create-language'}, layout:{type:'vbox'}, initialize:function() {
  this.setItems([{xtype:'component', cls:'dilocsync-header', html:this.tr('Select your language')}, {xtype:'selectfield', label:this.tr('Language'), floatedPicker:{minHeight:100}, bind:{value:'{userdata.languageCode}', store:'{languages}'}}]);
}});
Ext.define('dilocsync.view.setup.user.create.user.UserController', {extend:Ext.app.ViewController, alias:'controller.user-create-user', mixins:[cnconsult.Translatable], passwordValidator:function() {
  var passwordField = this.getView().down('[name\x3dpassword]');
  var passwordConfirmField = this.getView().down('[name\x3dconfirm_password]');
  if (passwordField && passwordConfirmField && passwordField.getValue() === passwordConfirmField.getValue()) {
    return true;
  } else {
    return this.tr("The given passwords don't match!");
  }
}, showEmailFieldValidationMessages:function(_message) {
  this.getView().down('[name\x3demail]').setError(_message);
}, showSyncGroupPasswordFieldValidationMessages:function(_message) {
  this.getView().down('[name\x3dsyncGroupPassword]').setError(_message);
}, showPasswordFieldValidationMessages:function(_messages) {
  var errors = [];
  var passwordField = this.getView().down('[name\x3dpassword]');
  Ext.Array.each(_messages, function(_error) {
    if (_error.type === 'error') {
      errors.push('\x3cspan class\x3d"' + _error.type + '"\x3e' + _error.msg + '\x3c/span\x3e');
    }
  });
  passwordField.setError(errors);
}});
Ext.define('dilocsync.view.setup.user.create.user.User', {extend:Ext.form.Panel, mixins:[cnconsult.Translatable], xtype:'user-create-user', controller:'user-create-user', padding:'0 16 0 16', initialize:function() {
  this.setItems([{xtype:'component', cls:'dilocsync-header', html:this.tr('Enter your personal informations')}, {xtype:'container'}]);
}, renderFields:function(_fieldConfig) {
  var items = [];
  var fieldset = this.down('container');
  var typeMap = {text:'textfield', password:'passwordfield', select:'selectfield'};
  for (var i = 0; i < _fieldConfig.fields.length; i++) {
    var field = _fieldConfig.fields[i];
    var fieldConfig = {xtype:typeMap[field.type], errorTarget:'under', name:field.name, label:field.label, required:field.required ? true : false, bind:{value:'{userdata.' + field.name + '}'}};
    if (Ext.Array.contains(['firstname', 'lastname'], field.name)) {
      fieldConfig.validators = {type:'length', min:2, minOnlyMessage:this.tr('You must enter at least two chars.'), emptyMessage:this.tr('Must be present')};
    }
    if (fieldConfig.name === 'email') {
      fieldConfig.xtype = 'emailfield';
      fieldConfig.validators = 'email';
    }
    if (fieldConfig.name === 'userIdCode') {
      fieldConfig.maxLength = 16;
    }
    if (fieldConfig.name === 'password') {
      fieldConfig.htmlErrorsTpl = ['\x3ctpl if\x3d"count \x3d\x3d 1"\x3e', '\x3ctpl for\x3d"errors"\x3e{.:htmlEncode}\x3c/tpl\x3e', '\x3ctpl elseif\x3d"count"\x3e', '\x3cul class\x3d"{listCls}"\x3e', '\x3ctpl for\x3d"errors"\x3e\x3cli\x3e{.:trim}\x3c/li\x3e\x3c/tpl\x3e', '\x3c/ul\x3e', '\x3c/tpl\x3e'];
    }
    if (fieldConfig.name === 'confirm_password') {
      delete fieldConfig.bind;
      fieldConfig.validators = {type:'controller', fn:'passwordValidator'};
    }
    if (fieldConfig.xtype === 'selectfield') {
      fieldConfig.usePicker = false;
      fieldConfig.options = [];
      fieldConfig.reference = 'syncGroupSelectField';
      for (var j = 0; j < field.values.length; j++) {
        var value = field.values[j];
        var selectOption = {text:value.name, value:value.id, passwordRequired:value.passwordRequired};
        fieldConfig.options.push(selectOption);
      }
    }
    if (fieldConfig.name === 'syncGroupPassword') {
      fieldConfig.bind.hidden = '{!isSyncGroupPasswordRequired}';
      fieldConfig.bind.required = '{isSyncGroupPasswordRequired}';
    }
    items.push(fieldConfig);
  }
  fieldset.removeAll();
  fieldset.add(items);
}});
Ext.define('dilocsync.view.setup.user.create.Create', {extend:Ext.Container, mixins:[cnconsult.Translatable], xtype:'user-create', viewModel:{type:'user-create'}, controller:'user-create', layout:'card', initialize:function() {
  this.setItems([{xtype:'toolbar', ui:'logo-toolbar', docked:'top', layout:{type:'hbox', pack:'center'}, items:[{xtype:'component', cls:'dilocsync-toolbar-logo'}, {xtype:'buttonAbout'}]}, {xtype:'user-create-language', padding:'0 16 0 16', reference:'language'}, {xtype:'user-create-user', reference:'user'}, {xtype:'toolbar', docked:'bottom', items:[{text:this.tr('Next'), ui:'toolbar-button', docked:'right', reference:'nextButton', handler:'onNextButtonTapped'}, {text:this.tr('Back'), ui:'toolbar-button', 
  docked:'left', reference:'backButton', handler:'onBackButtonTapped'}]}]);
}});
Ext.define('dilocsync.view.setup.user.knowledge.GroupList', {extend:Ext.dataview.List, xtype:'user-knowledge-group-list', mixins:[cnconsult.Translatable], itemTpl:['\x3cdiv class\x3d"knowledge-icon knowledge-icon-{iconName}"\x3e\x3c/div\x3e\x3cdiv class\x3d"dilocsync-knowledge-group-item"\x3e{name}\x3c/div\x3e'], initialize:function() {
  this.setEmptyText(this.tr('Currently there are no items.'));
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.setup.user.knowledge.Intro', {extend:Ext.Container, xtype:'user-knowledge-intro', mixins:[cnconsult.Translatable], padding:'8 16 8 16', initialize:function() {
  this.setHtml('\x3cdiv class\x3d"dilocsync-sub-header"\x3e' + this.tr('DiLoc|Sync® knowledges') + '\x3c/div\x3e\x3cdiv class\x3d"dilocsync-content"\x3e' + this.tr('With DiLoc|Sync® knowledges you can subscribe to knowledges you are really having. That ensures that you just get the documents you really need.\x3cbr/\x3eTo subscribe to a knowledge, just choose the regarding group on the left, search your needed knowledge and tab "subscribe".', 'German: Durch DiLoc|Sync® Kennisse haben Sie die Möglichkeit nur die Kenntnisse zu abonnieren, die Sie tatsächlich besitzen. Dadurch wird sichergestellt, dass Sie nur die Dokumente bekommen, die Sie wirklich benötigen.\x3cbr/\x3eUm eine Kenntnis zu abonnieren, müssen Sie lediglich auf der linken Seite die betreffende Kenntnisgruppe auswählen, die benötigte Kenntnis heraussuchen und den "Abonnieren-Button" betätigen.') + 
  '\x3c/div\x3e');
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.setup.user.knowledge.KnowledgeController', {extend:Ext.app.ViewController, alias:'controller.user-knowledge', mixins:[cnconsult.Translatable, dilocsync.view.components.button.AboutMixin], init:function() {
  this.loadKnowledges();
}, loadKnowledges:function() {
  var userData = dilocsync.core.Master.getPersonalization().getData();
  Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/syncuserknowledge/getUserKnowledges', params:{deviceIdCode:dilocsync.core.Master.deviceIdCode(), syncSecret:dilocsync.core.Master.getStorage().get('core:personalization:syncSecret'), emailOrIdCode:userData.email ? userData.email : userData.userIdCode}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData && responseData.hasOwnProperty('success') && responseData.success) {
      if (responseData.result.groups && responseData.result.groups.length > 0 && responseData.result.knowledges && responseData.result.knowledges.length > 0) {
        this.getStore('knowledgeGroups').loadData(responseData.result.groups);
        this.getStore('knowledges').loadData(responseData.result.knowledges);
      } else {
        cnconsult.Logger.log({prefix:'KnowledgeController-\x3eloadKnowledges', message:'No knowledges available'});
        this.redirectTo('init');
      }
    } else {
      cnconsult.Logger.log({prefix:'KnowledgeController-\x3eloadKnowledges', message:'Somehow an error occured', level:'error', dump:_response});
    }
  }, failure:function(_failure) {
    cnconsult.Logger.log({prefix:'KnowledgeController-\x3eloadKnowledges', message:'Somehow an error occured', level:'error', dump:_failure});
  }, scope:this});
}, onKnowledgeGroupTapped:function(_list, _location) {
  var view = Ext.is.Phone ? this.getView() : this.lookup('knowledgeContainer');
  if (Ext.is.Phone) {
    this.lookup('backButton').show();
  }
  this.getStore('knowledges').clearFilter();
  this.getStore('knowledges').filter('syncKnowledgeGroupId', _location.record.get('id'));
  view.setActiveItem(this.lookup('knowledgeList'));
}, onBackButtonTapped:function(_button) {
  _button.hide();
  this.getView().setActiveItem(this.lookup('groupList'));
}, onFinishButtonTapped:function() {
  var master = dilocsync.core.Master, storage = master.getStorage(), syncEngine = master.getSyncEngine();
  if (storage.get('knowledge:lastRoute') === 'usersettings') {
    if (storage.set('knowledge:needSync') && !syncEngine.isSyncing()) {
      syncEngine.startSync();
    }
    storage.set('knowledge:lastRoute', null);
    Ext.util.History.back();
  } else {
    this.redirectTo('init');
  }
  storage.set('knowledge:needSync', false);
}, onKnowledgeListItemTapped:function(_list, _location) {
  var record = _location.record;
  var isSubscribed = record.get('isSubscribed');
  var buttonTapped = _location.event ? _location.event.getTarget('.dilocsync-user-knowledge-list-item-subscription') : false;
  if (buttonTapped) {
    dilocsync.core.Master.getStorage().set('knowledge:needSync', true);
    if (isSubscribed) {
      this.doUnsubscribeUser(_location);
    } else {
      this.doSubscribeUser(_location);
    }
  }
}, doSubscribeUser:function(_location) {
  var vm = this.getViewModel();
  var record = _location.record;
  var knowledgeId = record.get('id');
  record.set('message', this.tr('Subscribing...'));
  Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/syncuserknowledge/subscribeUser', params:{deviceIdCode:dilocsync.core.Master.deviceIdCode(), syncSecret:dilocsync.core.Master.getStorage().get('core:personalization:syncSecret'), emailOrIdCode:vm.get('user.userEmail') ? vm.get('user.userEmail') : vm.get('user.userIdCode'), syncKnowledgeId:knowledgeId}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData && responseData.hasOwnProperty('success') && responseData.success) {
      if (record) {
        record.set('isSubscribed', true);
        record.set('message', this.tr('Subscribed!'));
        Ext.Function.defer(function() {
          record.set('message', '');
        }, 5000);
      }
    } else {
      cnconsult.Logger.log({prefix:'KnowledgeController-\x3edoSubscribeUser', message:'Somehow an error occured', level:'error', dump:_response});
    }
  }, failure:function(_failure) {
    cnconsult.Logger.log({prefix:'KnowledgeController-\x3edoSubscribeUser', message:'Somehow an error occured', level:'error', dump:_failure});
  }, scope:this});
}, doUnsubscribeUser:function(_location) {
  var vm = this.getViewModel();
  var record = _location.record;
  var knowledgeId = record.get('id');
  record.set('message', this.tr('Unsubscribing...'));
  Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/syncuserknowledge/unsubscribeUser', params:{deviceIdCode:dilocsync.core.Master.deviceIdCode(), syncSecret:dilocsync.core.Master.getStorage().get('core:personalization:syncSecret'), emailOrIdCode:vm.get('user.userEmail') ? vm.get('user.userEmail') : vm.get('user.userIdCode'), syncKnowledgeId:knowledgeId}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData && responseData.hasOwnProperty('success') && responseData.success) {
      if (record) {
        record.set('isSubscribed', false);
        record.set('message', this.tr('Unsubscribed!'));
        Ext.Function.defer(function() {
          record.set('message', '');
        }, 5000);
      }
    } else {
      cnconsult.Logger.log({prefix:'KnowledgeController-\x3edoUnsubscribeUser', message:'Somehow an error occured', level:'error', dump:_response});
    }
  }, failure:function(_failure) {
    cnconsult.Logger.log({prefix:'KnowledgeController-\x3edoUnsubscribeUser', message:'Somehow an error occured', level:'error', dump:_failure});
  }, scope:this});
}, onResize:function() {
  var listEl = this.lookup('groupList').el;
  var listWidth = listEl.getWidth();
  if (listWidth) {
    listEl.select('.dilocsync-knowledge-group-item').setWidth(listWidth - 55);
  }
}});
Ext.define('dilocsync.model.KnowledgeGroup', {extend:Ext.data.Model, fields:[{name:'id', type:'integer'}, {name:'customerId', type:'integer'}, {name:'remoteId'}, {name:'name', type:'string'}, {name:'description', type:'string'}, {name:'iconName', type:'string'}, {name:'subscribable', type:'boolean', defaultValue:false}, {name:'isMultilang', type:'boolean', defaultValue:false}, {name:'syncKnowledges'}]});
Ext.define('dilocsync.model.Knowledge', {extend:Ext.data.Model, fields:[{name:'id', type:'integer'}, {name:'remoteId', type:'integer'}, {name:'name', type:'string'}, {name:'description', type:'string'}, {name:'syncKnowledgeGroup', type:'integer'}, {name:'isSubscribed', type:'boolean', defaultValue:false}, {name:'message', type:'string'}]});
Ext.define('dilocsync.view.setup.user.knowledge.KnowledgeModel', {extend:Ext.app.ViewModel, alias:'viewmodel.user-knowledge', stores:{knowledgeGroups:{model:'dilocsync.model.KnowledgeGroup', sorters:'name'}, knowledges:{model:'dilocsync.model.Knowledge', sorters:'name'}}});
Ext.define('dilocsync.view.setup.user.knowledge.List', {extend:Ext.dataview.List, alias:'widget.user-knowledge-list', mixins:[cnconsult.Translatable], cls:'dilocsync-user-knowledge-list', initialize:function() {
  this.setEmptyText(this.tr('There are no knowledges to subscribe in this group.'));
  this.setItemTpl('\x3cdiv class\x3d"dilocsync-user-knowledge-list-item"\x3e' + '\t\x3cdiv class\x3d"dilocsync-user-knowledge-list-item-info"\x3e' + '\t\t\x3cdiv class\x3d"dilocsync-user-knowledge-list-item-name"\x3e{name}' + '\t\t\t\x3ctpl if\x3d"message"\x3e\x3cspan class\x3d"dilocsync-user-knowledge-list-item-message"\x3e\x3ci\x3e{message}\x3c/i\x3e\x3c/span\x3e\x3c/tpl\x3e' + '\t\t\x3c/div\x3e' + '\t\t\x3cdiv class\x3d"dilocsync-user-knowledge-list-item-description"\x3e{description}\x3c/div\x3e' + 
  '\t\x3c/div\x3e' + '\t\x3cdiv class\x3d"dilocsync-user-knowledge-list-item-subscription"\x3e' + '\t\t\x3ctpl if\x3d"isSubscribed"\x3e\x3cspan class\x3d"dilocsync-user-knowledge-list-item-subscription-unsubscribe"\x3e' + this.tr('Unsubscribe') + '\x3c/span\x3e' + '\t\t\x3ctpl else\x3e' + this.tr('Subscribe') + '\t\t\x3c/tpl\x3e' + '\t\x3c/div\x3e' + '\x3c/div\x3e');
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.setup.user.knowledge.Knowledge', {extend:Ext.Container, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'user-knowledge', viewModel:{type:'user-knowledge'}, controller:'user-knowledge', responsiveConfig:{'phone':{layout:'card', cls:'dilocsync-user-knowledge dilocsync-phone'}, 'tablet || desktop':{layout:'hbox', cls:'dilocsyc-user-knowledge dilocsync-tablet'}}, initialize:function() {
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.5;
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([{xtype:'toolbar', ui:'logo-toolbar', docked:'top', layout:{type:'hbox', pack:'center'}, items:[{xtype:'component', cls:'dilocsync-toolbar-logo'}, {xtype:'buttonAbout'}]}, {xtype:'user-knowledge-group-list', reference:'groupList', bind:{store:'{knowledgeGroups}'}, listeners:{childtap:'onKnowledgeGroupTapped'}}, {xtype:'user-knowledge-list', reference:'knowledgeList', bind:{store:'{knowledges}'}, listeners:{childtap:'onKnowledgeListItemTapped'}}, {xtype:'toolbar', docked:'bottom', 
    items:[{docked:'right', ui:'toolbar-button', reference:'finishButton', handler:'onFinishButtonTapped'}, {docked:'left', ui:'toolbar-button', hidden:true, reference:'backButton', handler:'onBackButtonTapped'}]}]);
  } else {
    this.setItems([{xtype:'toolbar', ui:'logo-toolbar', docked:'top', layout:{type:'hbox', pack:'center'}, items:[{xtype:'component', cls:'dilocsync-toolbar-logo'}, {xtype:'buttonAbout'}]}, {xtype:'user-knowledge-group-list', userCls:'dilocsync-user-knowledge-divider', ui:'knowledge-list', reference:'groupList', bind:{store:'{knowledgeGroups}'}, flex:1, listeners:{childtap:'onKnowledgeGroupTapped', resize:'onResize'}}, {xtype:'panel', flex:2, reference:'knowledgeContainer', layout:'card', resizable:{split:true, 
    edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, items:[{xtype:'user-knowledge-intro', reference:'knowledgeIntroduction'}, {xtype:'user-knowledge-list', reference:'knowledgeList', bind:{store:'{knowledges}'}, listeners:{childtap:'onKnowledgeListItemTapped'}}]}, {xtype:'toolbar', docked:'bottom', items:[{docked:'right', ui:'toolbar-button', reference:'finishButton', handler:'onFinishButtonTapped'}]}]);
  }
  if (this.lookup('title')) {
    this.lookup('title').setTitle(this.tr('Knowledges'));
  }
  if (this.lookup('finishButton')) {
    this.lookup('finishButton').setText(this.tr('Finish'));
  }
  if (this.lookup('backButton')) {
    this.lookup('backButton').setText(this.tr('Back'));
  }
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.BaseController', {extend:Ext.app.ViewController, alias:'controller.base', mixins:[cnconsult.Translatable], config:{hiddenViewers:[]}, control:{'panel[isPage\x3dtrue]:not(drivemode) filefolderlist list, panel[isPage\x3dtrue]:not(drivemode) filelist':{childlongpress:'onChildLongPress'}}, onChildLongPress:function(_list, _info) {
  var me = this;
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.BaseController', src:'Dokumente', action:'DateiAufSeiteÖffnen', trackedAt:new Date});
  if (_info.record.isNode && _info.record.isLeaf() || !_info.record.isNode) {
    _list.longPressed = true;
    dilocsync.util.MessageHelper.showPrompt(this.tr('Open file on page number', true), this.tr('Please enter the page number you like to open', true), function(_buttonId, _pageNumber) {
      if (_buttonId === 'ok') {
        if (Ext.os.deviceType === 'Phone') {
          me.getView().setActiveItem(me.lookup('viewer'));
        }
        me.showFile(_info.record, _list, parseInt(_pageNumber));
      }
    }, this);
  }
}, onShowFileFromList:function(_list, _location) {
  var onPage = 0;
  if (_location.record && _location.record.get('onPage') && Ext.isNumber(_location.record.get('onPage'))) {
    onPage = _location.record.get('onPage');
  }
  this.showFile(_location.record, _list, onPage);
}, onShowFileFromNestedList:function(_fileFolderList, _subList, _index, _target, _record) {
  this.showFile(_record, _subList, 0);
}, showFile:function(_record, _list, _pageNumber) {
  if (_record) {
    var master = dilocsync.core.Master;
    var activeList = _list ? _list.isXType('nestedlist') ? _list.down('list[hidden\x3dfalse]') : _list : null;
    if (activeList && activeList.longPressed) {
      activeList.longPressed = false;
    } else {
      var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(_record);
      var viewModel = this.lookup('viewer').getViewModel();
      var filePath = _record.get('path');
      if (_record.get('checksum') && _record.get('uuid')) {
        filePath = master.devicePath(rootFsEntryName + '/' + _record.get('checksum') + '.' + _record.get('fileType'));
      } else {
        if (_record.get('uuid') === 'imported') {
          filePath = 'imports/' + _record.get('name');
        } else {
          if (_record.get('path')) {
            var path = _record.get('path'), almanacPath, almanacFile;
            var almanac = master.getAlmanacForPath(path);
            if (almanac) {
              almanacPath = master.getAlmanacPath(path);
              path = path.replace(almanacPath, '');
              almanacFile = almanac.getFileByPath(path);
              if (almanacFile) {
                if (almanacFile.hasOwnProperty('uuid') && !_record.get('uuid')) {
                  _record.set('uuid', almanacFile.uuid);
                }
                _record.set('checksum', almanacFile.checksum);
                _record.save();
                filePath = master.devicePath(rootFsEntryName + '/' + almanacFile.checksum + '.' + _record.get('fileType'));
              } else {
                console.warn('No almanac file found for path.', path, almanac);
              }
            }
          }
        }
      }
      viewModel.set('name', _record.get('name'));
      viewModel.set('path', filePath);
      viewModel.set('record', _record);
      if (_pageNumber && Ext.isNumber(_pageNumber) && _pageNumber > 0) {
        _pageNumber--;
      } else {
        _pageNumber = 0;
      }
      viewModel.set('onPageNumber', _pageNumber);
    }
  }
}, onOpenFileFromList:function(_list, _location) {
  this.openFile(_location.record);
}, onOpenFileFromNestedList:function(_fileFolderList, _subList, _index, _target, _record) {
  this.openFile(_record);
}, openFile:function(_record) {
  var fileInfo = {checksum:_record.get('checksum'), alternativeFileType:_record.get('alternativeFileType'), fileType:_record.get('fileType'), name:_record.get('name')};
  dilocsync.util.ExternalFile.openFileExternallyWithRealFilename(this.getViewModel().get('path'), fileInfo);
}, showViewer:function(_record, _list) {
  this.showFile(_record, _list, 0);
  this.getView().setActiveItem(this.lookup('viewer'));
}, showViewerFromList:function(_list, _location) {
  this.showViewer(_location.record, _list);
}, showViewerFromNestedList:function(_fileFolderList, _subList, _index, _target, _record) {
  this.showViewer(_record, _subList);
}, showList:function() {
  this.getView().setActiveItem(this.lookup('listPanel'));
}, maximizeListPanel:function(_button) {
  _button.hide();
  this.lookup('listPanel').setFlex(1);
  this.lookup('viewer').hide();
  this.lookup('listPanel').addCls('dilocsync-file-list-maximized');
  this.getView().down('#minimize').show();
}, minimizeListPanel:function(_button) {
  _button.hide();
  this.lookup('viewer').show();
  this.lookup('listPanel').removeCls('dilocsync-file-list-maximized');
  this.getView().down('#maximize').show();
}, onResize:function() {
  var listEl = this.lookup('listPanel').el;
  var listWidth = listEl.getWidth();
  if (listWidth) {
    var almanacPath = null;
    var view = this.getView();
    if (view && view.pageConfig) {
      almanacPath = view.pageConfig.path;
    }
    if (!(almanacPath && almanacPath.startsWith('trainschedules'))) {
      listEl.select('.dilocsync-file-list-item-name').setWidth(listWidth - 85);
    }
  }
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.BaseController', src:'Dokumente', action:'onResize', trackedAt:new Date});
}, onHide:function() {
  var sideMenu = Ext.Viewport.down('sidemenu');
  if (sideMenu.isVisible()) {
    this.setHiddenViewers(sideMenu.getController().getHiddenViewers());
  } else {
    this.setHiddenViewers(dilocsync.util.FileViewerHelper.hideVisibleFileViewers());
  }
}, onShow:function() {
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    var viewer = this.lookup('viewer');
    if (viewer && viewer.xtype === 'externalfileopen') {
      viewer.getController().checkFileForBeingFavorite();
    }
  } else {
    var hiddenViewers = this.getHiddenViewers();
    dilocsync.util.FileViewerHelper.showHiddenFileViewers(hiddenViewers);
    Ext.Array.each(hiddenViewers, function(_viewer) {
      _viewer.getController().checkFileForBeingFavorite();
    });
    this.setHiddenViewers([]);
  }
}, updateResizeableSizes:function() {
  if (!Ext.is.Phone) {
    var viewer = this.lookup('viewer');
    var resizeable = viewer.getResizable();
    var elementWidth = dilocsync.util.Screen.getScreenWidth();
    var maxResizeWidth = elementWidth * 0.85;
    var minResizeWidth = elementWidth * 0.15;
    if (resizeable) {
      resizeable.setMinSize([minResizeWidth, null]);
      resizeable.setMaxSize([maxResizeWidth, null]);
    }
    this.resetPanelWidths();
  }
}, resetPanelWidths:function() {
  var viewer = this.lookup('viewer');
  var listPanel = this.lookup('listPanel');
  listPanel.setFlex(1);
  listPanel.setWidth('auto');
  viewer.setFlex(2);
  viewer.setWidth('auto');
}, downloadOnDemand:function(_record, _viewModel) {
  var master = dilocsync.core.Master;
  var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(_record);
  var isTrainScheduleFile = rootFsEntryName === 'train-schedule-data';
  if (!isTrainScheduleFile) {
    cnconsult.Logger.log({prefix:'Folder-\x3edownloadOnDemand', message:'Download for non train schedule file is currently not available', dump:{'record':_record.data}});
    return;
  }
  var viewModel = _viewModel;
  var almanac = master.getAlmanacForPath('trainschedules');
  viewModel.set('name', null);
  viewModel.set('path', null);
  viewModel.set('record', null);
  master.getSyncRoot().getDirectory(rootFsEntryName, {create:true}, Ext.bind(function(_directory) {
    var fileSystem = master.getFileSystem();
    fileSystem.root.getDirectory('sync', {create:true}, function(_syncRoot) {
      var downloadUrlPrefix = master.getBackendUrl() + '/clientsync/downloadFile?';
      downloadUrlPrefix += Ext.Object.toQueryString({syncSecret:master.getStorage().get('core:personalization:syncSecret'), syncDeviceIdCode:master.deviceIdCode()});
      var localUrlPrefix = _syncRoot.toURL();
      var fileTransfer = new FileTransfer;
      var url = downloadUrlPrefix + '\x26uuid\x3d' + _record.get('uuid');
      var fileName = _record.get('checksum') + '.' + _record.get('fileType');
      var localFilePath = localUrlPrefix + rootFsEntryName + '/' + fileName;
      fileTransfer.download(url, dilocsync.util.File.encodeURI(localFilePath), function(_fileEntry) {
        dilocsync.util.File.sha256OfFileEntry(_fileEntry, function(_hash) {
          cnconsult.Logger.log({prefix:'Folder-\x3edownloadOnDemand', message:'Sha256 of file is: ' + _hash});
          if (_record.get('checksum') !== _hash) {
            cnconsult.Logger.log({prefix:'Folder-\x3edownloadOnDemand', message:'Mismatching checksum of downloaded file and remote almanac checksum!', level:'error', dump:{'record':_record.data}});
          } else {
            var filePath = master.devicePath(rootFsEntryName + '/' + fileName);
            viewModel.set('name', _record.get('name'));
            viewModel.set('path', filePath);
            viewModel.set('record', _record);
            _record.set('loaded', true);
            if (almanac) {
              almanac.setFileLoaded(_record.get('path'));
              master.persistAlmanacByPath(almanac, almanac.path);
            }
            cnconsult.Logger.log({prefix:'Folder-\x3edownloadOnDemand', message:'File completely downloaded', dump:{'record':_record.data}});
          }
        });
      });
    }, function(error) {
      return cnconsult.Logger.log({prefix:'Folder-\x3edownloadOnDemand', message:'An unexpected error occurred while retrieving file.', level:'error', dump:{'record':_record.data, error:error}});
    });
  }, this));
}});
Ext.define('dilocsync.view.components.FileList', {extend:Ext.dataview.List, xtype:'filelist', config:{showPath:false}, cls:'dilocsync-file-list', ui:'file-list', mixins:[cnconsult.Translatable], grouped:true, initialize:function() {
  var me = this;
  this.setEmptyText(this.tr('Currently there are no items.'));
  this.setItemTpl(['\x3cdiv class\x3d"{icon:this.iconCls} dilocsync-file-list-icon"\x3e\x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-file-list-item"\x3e', '\x3cdiv class\x3d"dilocsync-file-list-item-name dilocsync-file-list-item-name-centered"\x3e\x3ctpl if\x3d"title"\x3e{title}\x3ctpl else\x3e{name}\x3c/tpl\x3e \x3ctpl if\x3d\'tags\'\x3e{tags:this.getTags}\x3c/tpl\x3e\x3c/div\x3e', "\x3ctpl if\x3d'this.showPath()'\x3e", '\x3cdiv class\x3d"dilocsync-file-list-item-size"\x3e', '{path:this.formatPath}', 
  '\x3c/div\x3e', '\x3c/tpl\x3e', '\x3ctpl if\x3d"validFrom || validTo" \x3e', '\x3cspan class\x3d"dilocsync-validity"\x3e', '\x3ctpl if\x3d"validFrom"\x3e', '\x26nbsp;', this.tr('Valid from'), '\x26nbsp;', '{validFrom:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3ctpl if\x3d"validTo"\x3e', '\x26nbsp;', '\x3ctpl if\x3d"!validFrom"\x3e', this.tr('Valid'), '\x26nbsp;', '\x3c/tpl\x3e', this.tr('until'), '\x26nbsp;', '{validTo:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3c/span\x3e', '\x3c/tpl\x3e', '\x3c/div\x3e', {showPath:function() {
    return me.getShowPath();
  }, getTags:function(_tags) {
    return dilocsync.util.File.tagMarkup(_tags);
  }, iconCls:function(_type) {
    return dilocsync.util.File.iconClsByType(_type);
  }, formatPath:function(_path) {
    var regExp = /.data/g;
    return _path.replace(regExp, '');
  }}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.fileviewer.FileViewerModel', {extend:Ext.app.ViewModel, alias:'viewmodel.fileviewer', data:{name:'-', record:null, path:null, onPageNumber:0, fileExists:true, enableDownloadOnDemand:false, showFileNotFoundComponent:false}, formulas:{isFileTypeSupported:{bind:'{record}', get:function(_record) {
  var supported = true;
  var fileType;
  if (_record && _record.get('path')) {
    fileType = dilocsync.util.File.extension(_record.get('path'));
    supported = dilocsync.util.FileViewerHelper.isFileTypeSupport(fileType);
  }
  return supported;
}}, hideFullScreenButton:{bind:'{record}', get:function(_record) {
  if (_record && _record.get('path')) {
    var fileType = dilocsync.util.File.extension(_record.get('path'));
    return dilocsync.util.File.isFileTypeVideo(fileType) || !dilocsync.util.FileViewerHelper.isFileTypeSupport(fileType);
  }
  return true;
}}, hideFavoritesButton:{bind:{record:'{record}', fileExists:'{fileExists}'}, get:function(_data) {
  if (_data.record && _data.fileExists) {
    var favoritesStore = Ext.getStore('Favorites');
    var favoriteRecord = favoritesStore.findRecord('uuid', _data.record.get('uuid'));
    if (!favoriteRecord) {
      favoriteRecord = favoritesStore.findRecord('path', _data.record.get('path'));
    }
    return favoriteRecord ? favoriteRecord.get('group') === 'remote' : false;
  }
  return true;
}}, fileTitle:{bind:{bindTo:'{record}', deep:true}, get:function(_record) {
  if (_record && _record.get('title')) {
    return _record.get('title');
  } else {
    if (_record && _record.get('name')) {
      return _record.get('name');
    } else {
      return ' - ';
    }
  }
}}}});
Ext.define('dilocsync.view.components.dossier.add.AddModel', {extend:Ext.app.ViewModel, alias:'viewmodel.dossierAdd', data:{filePath:null, fileType:null, fileName:null, openFileOnPage:null, record:null}});
Ext.define('dilocsync.view.components.dossier.add.AddController', {extend:Ext.app.ViewController, alias:'controller.dossierAdd', mixins:[cnconsult.Translatable], onCreateDossierTapped:function() {
  dilocsync.util.MessageHelper.showPrompt(this.tr('Create dossier'), this.tr('Please enter a name'), function(_buttonId, _dossierName) {
    if (_buttonId === 'ok') {
      dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.dossier.add.AddController', src:'Dokumente', action:'ArbeitsmappeErstellt', trackedAt:new Date});
      var dossierName = _dossierName.trim();
      var store = Ext.getStore('Dossiers');
      var record = store.findRecord('name', dossierName, 0, 0, false, true);
      if (!record) {
        var root = store.getRoot();
        root.appendChild({name:dossierName, createdAt:new Date});
        store.sync();
        store.sort();
      } else {
        Ext.create({xtype:'alert', type:'warning', renderTo:this.getView(), html:this.tr('A dossier with that name already exists.')});
        var dossierList = this.lookup('dossierList');
        dossierList.scrollToRecord(record);
      }
    }
  }, this);
}, onDossierItemTap:function(_list, _location) {
  if (_list.longPressed) {
    _list.longPressed = true;
  } else {
    var dossierTreeStore = Ext.getStore('Dossiers');
    var dossierNode = _location.record;
    var viewModel = this.getViewModel();
    var fileNode = dossierNode.findChildBy(function(_node) {
      return _node.get('filePath') === viewModel.get('filePath') && _node.get('openFileOnPage') === viewModel.get('openFileOnPage');
    });
    _list.longPressed = false;
    var record = viewModel.get('record');
    if (fileNode === null && record) {
      var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(record);
      dossierNode.appendChild(Ext.create('dilocsync.model.DossierItem', {uuid:record.get('uuid'), name:viewModel.get('fileName'), icon:viewModel.get('fileType'), fileType:viewModel.get('fileType'), filePath:viewModel.get('filePath'), path:record.get('path'), rootFsEntryName:rootFsEntryName, checksum:record.get('checksum'), openFileOnPage:viewModel.get('openFileOnPage'), addedAt:new Date, size:0, leaf:true, loaded:true}));
    } else {
      dossierNode.removeChild(fileNode, true, true);
      dossierTreeStore.remove(fileNode);
    }
    dossierTreeStore.sync();
  }
}, onDossierDelete:function(_list, _info) {
  dilocsync.util.MessageHelper.showMessage({title:this.tr('Delete Dossier'), message:this.tr('Do you really want to delete this dossier?'), buttons:[{itemId:'no', text:this.tr('No'), handler:function(_button) {
    _button.up('messagebox').destroy();
  }}, {itemId:'yes', text:this.tr('Yes'), handler:function(_button) {
    dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.dossier.add.AddController', src:'Dokumente', action:'ArbeitsmappeGelöscht', trackedAt:new Date});
    var store = Ext.getStore('Dossiers');
    var record = _info.record;
    record.remove(true, true);
    store.remove(record);
    store.sync();
    _button.up('messagebox').destroy();
  }, scope:this}]});
}, onBeforeShow:function() {
  var hiddenViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  this.getView().on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
}, onChildLongpress:function(_list, _location) {
  var record = _location.record;
  var dossierTreeStore = Ext.getStore('Dossiers');
  _list.longPressed = true;
  dilocsync.util.MessageHelper.showPrompt(this.tr('Rename dossier'), this.tr('Please enter a new name'), function(_buttonId, _dossierName) {
    _list.longPressed = false;
    var dossierName = _dossierName.trim();
    var recordInStore = dossierTreeStore.findRecord('name', dossierName, 0, 0, false, true);
    if (_buttonId === 'ok') {
      if (!recordInStore) {
        dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.dossier.add.AddController', src:'Dokumente', action:'ArbeitsmappeUmbenannt', trackedAt:new Date});
        record.set('name', dossierName);
        record.commit();
        dossierTreeStore.sync();
        dossierTreeStore.sort();
      } else {
        Ext.create({xtype:'alert', type:'warning', renderTo:this.getView(), html:this.tr('A dossier with that name already exists.')});
      }
    }
  }, this);
}});
Ext.define('dilocsync.view.components.dossier.add.Add', {extend:Ext.Dialog, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'dossierAdd', viewModel:{type:'dossierAdd'}, controller:'dossierAdd', cls:'dilocsync-dossier-add', layout:{type:'vbox', align:'stretch'}, closable:true, maskTapHandler:'destroy', responsiveConfig:{'phone':{width:'100%'}, 'tablet || desktop':{width:'50%', minHeight:500}}, maxHeight:'70%', listeners:{beforeshow:'onBeforeShow'}, initialize:function() {
  var viewModel = this.getViewModel();
  var fileName = viewModel.get('fileName');
  var openFileOnPage = viewModel.get('openFileOnPage');
  var dossierTreeStore = Ext.getStore('Dossiers');
  var chainedTreeStore = new Ext.data.ChainedStore({source:dossierTreeStore, filters:[{property:'parentId', value:'root'}]});
  dossierTreeStore.on('datachanged', function() {
    chainedTreeStore.fireEvent('refresh', chainedTreeStore);
  });
  this.setTitle(this.tr('Add page to dossier'));
  this.setItems([{xtype:'component', html:'\x3cul\x3e' + '\x3cli\x3e' + this.tr('Add \x3cb\x3e%1\x3c/b\x3e on page \x3cb\x3e%2\x3c/b\x3e to the following dossier(s) by tapping on a dossier.').arg(fileName, openFileOnPage) + '\x3c/li\x3e' + '\x3cli\x3e' + this.tr('Remove added file from dossier by tapping on the dossier.') + '\x3c/li\x3e' + '\x3cli\x3e' + this.tr('Delete dossier by swiping to the left on the dossier.') + '\x3c/li\x3e' + '\x3cli\x3e' + this.tr('Rename dossier with longpress on it') + 
  '\x3c/li\x3e' + '\x3c/ul\x3e'}, {xtype:'list', ui:'dossier-list', reference:'dossierList', flex:1, store:chainedTreeStore, deferEmptyText:false, height:'30%', autoScroll:true, emptyText:this.tr('\x3ch2\x3eNo Dossiers created yet.\x3c/h2\x3e\x3cbr/\x3eYou need to create a dossier before you can add the selected file to it.'), itemTpl:['\x3cdiv class\x3d"dilocsync-list-item-folder {[this.fileIsAddedCls(values.id)]}"\x3e', '\x3cdiv class\x3d"dilocsync-file-list-item-name"\x3e', '\x3cspan class\x3d"x-fa fa-folder fa-lg item-folder-color"\x3e\x3c/span\x3e', 
  '\x26nbsp;{name} \x3cspan class\x3d"file-exists"\x3e{[this.fileIsAddedText(values.id)]}\x3c/span\x3e', '\x3c/div\x3e', '\x3c/div\x3e', {fileIsAddedCls:Ext.Function.bind(function(_id) {
    return this.hasCurrentFile(_id) ? 'dilocsync-list-item-file-is-added' : '';
  }, this), fileIsAddedText:Ext.Function.bind(function(_id) {
    return this.hasCurrentFile(_id) ? this.tr('added') : '';
  }, this)}], plugins:{listswiper:{defaults:{ui:'action', width:48}, right:[{iconCls:'x-fa fa-trash', ui:'alt decline', commit:'onDossierDelete'}]}}, listeners:{childtap:'onDossierItemTap', childlongpress:'onChildLongpress'}}, {xtype:'button', itemId:'createDossier', text:this.tr('Create dossier'), handler:'onCreateDossierTapped', ui:'confirm'}]);
  this.callParent(arguments);
}, hasCurrentFile:function(_id) {
  var store = Ext.getStore('Dossiers');
  var record = store.getById(_id);
  var viewModel = this.getViewModel();
  var childNode = record.findChildBy(function(_node) {
    return _node.get('filePath') === viewModel.get('filePath') && _node.get('openFileOnPage') === viewModel.get('openFileOnPage');
  });
  return childNode !== null;
}});
Ext.define('dilocsync.view.components.fileviewer.FileViewerController', {extend:Ext.app.ViewController, alias:'controller.fileviewer', config:{viewerInFullscreen:false, nightMode:false, isVisible:false, continuous:false}, bindings:{loadFile:'{record}', checkFileForBeingFavorite:'{record}'}, init:function() {
  if (dilocsync.util.Platform.isPhonegap()) {
    Ext.Viewport.on('orientationchange', function() {
      if (this.getIsVisible()) {
        this.setRect();
      }
    }, this);
    dilocsync.core.Master.getSyncEngine().on('syncfinished', this.onSyncFinished, this);
  }
}, onSyncFinished:function(_success, _errorMessage, _syncReportAvailable, _reloadRequired) {
  var me = this;
  var fileRecord = me.getViewModel().get('record');
  if (_success && fileRecord && dilocsync.core.Master.isPhonegap()) {
    var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(fileRecord);
    var filePath = rootFsEntryName + '/' + fileRecord.get('checksum') + '.' + fileRecord.get('fileType');
    dilocsync.core.Master.getSyncRoot().getFile(filePath, {create:false}, function() {
    }, function() {
      me.reset();
    });
  }
}, onBack:function(_button) {
  this.getView().fireEvent('back', this.getView(), _button);
}, onResize:function() {
  if (dilocsync.util.Platform.isPhonegap() && this.getView().getFileViewer() && !this.getViewerInFullscreen()) {
    Ext.defer(this.setRect, 400, this);
  }
}, onFullscreenButtonTapped:function() {
  var fileViewer = this.getView().getFileViewer();
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.fileviewer.FileViewerController', src:'Dokumente', action:'VollbildmodusAktiviert', trackedAt:new Date});
  if (fileViewer) {
    fileViewer.enterFullscreen();
    this.setViewerInFullscreen(true);
  } else {
    cnconsult.Logger.log({prefix:'FileViewerController-\x3eonFullscreenButtonTapped', message:'No FileViewer plugin found for opening the file in the fullscreen!', level:'warn'});
  }
}, onOpenWithButtonTapped:function() {
  var record = this.getViewModel().get('record');
  var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(record);
  var fileInfo = {checksum:record.get('checksum'), alternativeFileType:record.get('alternativeFileType'), fileType:record.get('fileType'), name:record.get('name'), rootFsEntryName:rootFsEntryName};
  dilocsync.util.ExternalFile.openFileExternallyWithRealFilename(this.getViewModel().get('path'), fileInfo);
}, onFavoritesButtonTapped:function(_button) {
  var store = Ext.getStore('Favorites');
  var fileRecord = this.getViewModel().get('record');
  var favoriteRecord;
  var favoriteData;
  var parentPageView = this.getView().up('[isPage\x3dtrue]');
  if (fileRecord) {
    var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(fileRecord);
    var filePath = dilocsync.core.Master.devicePath(rootFsEntryName) + fileRecord.get('checksum') + '.' + fileRecord.get('fileType');
    favoriteData = {uuid:fileRecord.get('uuid'), name:fileRecord.get('title') ? fileRecord.get('title') : fileRecord.get('name'), path:filePath, fileType:fileRecord.get('fileType'), checksum:fileRecord.get('checksum'), validFrom:fileRecord.get('validFrom'), validTo:fileRecord.get('validTo'), icon:fileRecord.get('fileType'), markedAsFavoriteDate:new Date, group:'local', rootFsEntryName:rootFsEntryName};
    if (Ext.isObject(parentPageView) && parentPageView.hasOwnProperty('pageConfig') && Ext.isObject(parentPageView.pageConfig) && parentPageView.pageConfig.hasOwnProperty('path')) {
      var pagePath = parentPageView.pageConfig.path;
      favoriteData = Ext.apply(favoriteData, {almanacPath:'data/' + pagePath, almanacFilePath:fileRecord.get('path')});
    }
    favoriteRecord = store.findRecord('uuid', fileRecord.get('uuid'));
  }
  if (!favoriteRecord && favoriteData) {
    cnconsult.Logger.log({prefix:'FileViewerController-\x3eonFavoritesButtonTapped', message:'File is not marked as favorite yet, ADD it to the favorites store.'});
    dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.fileviewer.FileViewerController', src:'Dokumente', action:'FavoritHinzugefügt', trackedAt:new Date});
    store.add(favoriteData);
    _button.setIconCls('x-fa fa-star active');
  }
  if (favoriteRecord) {
    cnconsult.Logger.log({prefix:'FileViewerController-\x3eonFavoritesButtonTapped', message:'File is already marked as favorite. REMOVE it from the favorites store.'});
    dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.fileviewer.FileViewerController', src:'Dokumente', action:'FavoritGelöscht', trackedAt:new Date});
    store.remove(favoriteRecord);
    _button.setIconCls('x-fa fa-star');
    if (Ext.History.getToken() === 'favorites') {
      var fileViewer = this.getView().getFileViewer();
      var videoPlayerComponent = this.lookup('videoplayer');
      if (fileViewer) {
        fileViewer.hide();
      }
      if (videoPlayerComponent) {
        videoPlayerComponent.hide();
      }
      this.getViewModel().set({name:'-', record:null, path:null, onPageNumber:0, fileExists:true});
      _button.hide();
    }
  }
  store.sync();
  store.group();
}, checkFileForBeingFavorite:function() {
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var fileRecord = this.getViewModel().get('record');
  if (fileRecord && identity.options && !identity.options.disableFavorites) {
    var favoritesButton = this.lookup('favoritesButton');
    var favoritesStore = Ext.getStore('Favorites');
    if (favoritesButton && favoritesStore) {
      var favoriteRecord = favoritesStore.findRecord('uuid', fileRecord.get('uuid'));
      if (!favoriteRecord) {
        favoriteRecord = favoritesStore.findRecord('path', fileRecord.get('path'));
      }
      if (favoriteRecord && favoriteRecord.get('group') === 'local') {
        favoritesButton.setIconCls('x-fa fa-star active');
      } else {
        favoritesButton.setIconCls('x-fa fa-star');
      }
    } else {
      cnconsult.Logger.log({prefix:'FileViewerController-\x3echeckFileForBeingFavorite', message:'FavoritesButton or Favorites Store is missing!!!', level:'error', dump:{favoritesButton:favoritesButton, favoritesStore:favoritesStore}});
    }
  }
}, setRect:function() {
  var fileViewer = this.getView().getFileViewer();
  var element = this.lookup('viewer').element;
  if (element && fileViewer) {
    var box = element.getBox();
    var x = box.x;
    var y = box.y;
    var width = box.width;
    var height = box.height;
    if (dilocsync.util.Platform.isAndroid()) {
      var pixelRatio = 1;
      if (typeof window.devicePixelRatio !== undefined && window.devicePixelRatio > 0) {
        pixelRatio = window.devicePixelRatio;
      }
      if (screen.width === window.innerWidth || pixelRatio !== 1) {
        var factor = 1;
        if (pixelRatio > 0) {
          factor = pixelRatio;
        } else {
          factor = window.innerWidth / screen.width;
        }
        x = x * factor;
        y = y * factor;
        width = width * factor;
        height = height * factor;
      }
    }
    if (width !== 0 && height !== 0 && !this.getViewerInFullscreen()) {
      fileViewer.setRect({x:x, y:y, width:width, height:height});
    } else {
      cnconsult.Logger.log({prefix:'FileViewerController-\x3esetRect', message:'Width and height cannot be 0!', level:'warn', dump:{width:width, height:height, viewerInFullscreen:this.getViewerInFullscreen()}});
    }
  }
}, loadFile:function(_record) {
  if (_record && Ext.isObject(_record)) {
    var view = this.getView();
    var viewModel = this.getViewModel();
    var fileViewer = view.getFileViewer();
    var viewerComponent = this.lookup('viewer');
    var videoPlayerComponent = this.lookup('videoplayer');
    var unsupportedFileTypeComponent = this.lookup('unsupportedFileTypeComponent');
    var fileNotFoundComponent = this.lookup('fileNotFoundComponent');
    var enableDownloadOnDemandComponent = this.lookup('enableDownloadOnDemandComponent');
    var fileType = dilocsync.util.File.extension(_record.get('path'));
    var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(_record);
    var enableDownloadOnDemand = rootFsEntryName === 'train-schedule-data' || view.enableDownloadOnDemand;
    var openFileOnPage = viewModel.get('onPageNumber');
    var filePath;
    if (_record.get('uuid') === 'imported') {
      filePath = 'imports/' + _record.get('name');
    } else {
      filePath = rootFsEntryName + '/' + _record.get('checksum') + '.' + fileType.toLowerCase();
    }
    if (openFileOnPage === 0 && viewModel.get('lastOpenedFile') === filePath) {
      fileViewer.getCurrentPage(function(_lastOpenedPage) {
        openFileOnPage = _lastOpenedPage;
      }, this);
    }
    viewModel.set('lastOpenedFile', filePath);
    if (fileType) {
      if (dilocsync.util.FileViewerHelper.isFileTypeSupport(fileType)) {
        dilocsync.core.Master.devicePathExists(filePath, function(_realPath) {
          if (_realPath) {
            viewModel.set('fileExists', true);
            viewModel.set('enableDownloadOnDemand', false);
            viewModel.set('showFileNotFoundComponent', false);
            if (dilocsync.util.File.isFileTypeVideo(fileType)) {
              var path = dilocsync.util.Platform.convertFilePath(_realPath);
              unsupportedFileTypeComponent.hide();
              viewerComponent.hide();
              fileViewer.hide();
              videoPlayerComponent.show();
              var videoPlayerViewModel = videoPlayerComponent.getViewModel();
              videoPlayerViewModel.set('url', path);
            } else {
              videoPlayerComponent.hide();
              viewerComponent.show();
              fileViewer.loadFile(_realPath, openFileOnPage);
              if (unsupportedFileTypeComponent && !unsupportedFileTypeComponent.isHidden()) {
                unsupportedFileTypeComponent.hide();
              }
              if (fileNotFoundComponent && !fileNotFoundComponent.isHidden()) {
                fileNotFoundComponent.hide();
              }
              if (enableDownloadOnDemandComponent && !enableDownloadOnDemandComponent.isHidden()) {
                enableDownloadOnDemandComponent.hide();
              }
              this.setRect();
              fileViewer.show();
              this.setIsVisible(true);
            }
          } else {
            cnconsult.Logger.log({prefix:'FileViewerController-\x3eloadFile', message:'File not found!.', dump:{record:_record.data, filePath:filePath, realPath:_realPath}});
            viewModel.set('fileExists', false);
            if (enableDownloadOnDemand) {
              viewModel.set('enableDownloadOnDemand', enableDownloadOnDemand);
            } else {
              viewModel.set('showFileNotFoundComponent', true);
            }
            if (Sentry) {
              Sentry.withScope(function(_scope) {
                _scope.setExtra('path', filePath);
                Sentry.captureMessage('FileViewer: File not found!');
              });
            }
            viewerComponent.hide();
            fileViewer.hide();
          }
        }, this);
      } else {
        videoPlayerComponent.hide();
        fileViewer.hide();
        viewerComponent.hide();
        unsupportedFileTypeComponent.show();
      }
    } else {
      viewModel.set('fileExists', false);
      viewerComponent.hide();
      fileViewer.hide();
    }
  } else {
    cnconsult.Logger.log({prefix:'FileViewerController-\x3eloadFile', message:"No record set or record isn't an object.", dump:_record});
  }
}, showViewer:function() {
  var master = dilocsync.core.Master;
  var me = this;
  var fileViewer = this.getView().getFileViewer();
  var filePath = this.getViewModel().get('path');
  if (this.getViewModel().get('record')) {
    var record = this.getViewModel().get('record');
    if (record.get('checksum') && record.get('fileType')) {
      var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(record);
      filePath = rootFsEntryName + '/' + record.get('checksum') + '.' + record.get('fileType');
    } else {
      if (record.get('uuid') === 'imported') {
        filePath = 'imports/' + record.get('name');
      }
    }
  }
  var fileType = filePath ? dilocsync.util.File.extension(filePath) : '';
  if (fileViewer) {
    fileViewer.hide();
    if (dilocsync.util.File.isFileTypeVideo(fileType)) {
      this.lookup('videoplayer').show();
    } else {
      if (dilocsync.util.FileViewerHelper.isFileTypeSupport(fileType)) {
        master.devicePathExists(filePath, function(_realPath) {
          if (_realPath) {
            Ext.defer(function() {
              var lastOpenedPage = me.getViewModel().get('onPageNumber');
              fileViewer.loadFile(_realPath, lastOpenedPage);
              Ext.defer(me.setRect, 300, me);
              fileViewer.show();
              me.setIsVisible(true);
              me.getViewModel().set('onPageNumber', 0);
            }, 50, this);
          } else {
            fileViewer.hide();
          }
        });
      } else {
        fileViewer.hide();
      }
    }
  } else {
    cnconsult.Logger.log({prefix:'FileViewerController-\x3eshowViewer', message:'No FileViewer plugin found for showing the file!', level:'warn'});
  }
}, hideViewer:function() {
  var fileViewer = this.getView().getFileViewer(), viewModel = this.getViewModel(), filePath;
  if (fileViewer) {
    var videoPlayer = this.lookup('videoplayer');
    filePath = viewModel.get('path');
    videoPlayer.hide();
    if (filePath && fileViewer) {
      fileViewer.getCurrentPage(function(_lastOpenedPage) {
        viewModel.set('onPageNumber', _lastOpenedPage);
      }, this);
    } else {
      viewModel.set('onPageNumber', 0);
    }
    fileViewer.hide();
    this.setIsVisible(false);
  } else {
    cnconsult.Logger.log({prefix:'FileViewerController-\x3ehideViewer', message:'No FileViewer plugin found for hiding the file!', level:'warn'});
  }
}, exitFullScreen:function() {
  var fileViewer = this.getView().getFileViewer();
  if (fileViewer && this.getViewerInFullscreen()) {
    fileViewer.exitFullscreen();
    this.setViewerInFullscreen(false);
    if (dilocsync.util.Platform.isAndroid()) {
      this.setRect();
    }
    return true;
  }
  return false;
}, onDossierButtonTapped:function() {
  var me = this;
  var fileViewer = this.getView().getFileViewer();
  var viewModel = me.getViewModel();
  var record = viewModel.get('record');
  var filePath = record.get('path');
  var fileType = record.get('fileType');
  var fileName = record.get('title');
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.fileviewer.FileViewerController', src:'Dokumente', action:'ArbeitsmappeHinzufügenGeklickt', trackedAt:new Date});
  if (fileViewer) {
    fileViewer.getCurrentPage(function(_lastOpenedPage) {
      var view = Ext.create('dilocsync.view.components.dossier.add.Add', {viewModel:{data:{filePath:filePath, fileName:fileName, fileType:fileType, openFileOnPage:_lastOpenedPage + 1, record:record}}});
      view.show();
    }, this);
  }
}, toggleNightMode:function() {
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.fileviewer.FileViewerController', src:'Dokumente', action:this.getNightMode() ? 'Nachtmodus deaktiviert' : 'Nachtmodus aktiviert', trackedAt:new Date});
  var fileViewerHelper = dilocsync.util.FileViewerHelper;
  this.setNightMode(!fileViewerHelper.getViewersInNightMode());
  fileViewerHelper.enableNightMode(this.getNightMode());
}, updateToolbar:function() {
  this.setNightMode(dilocsync.util.FileViewerHelper.getViewersInNightMode());
  this.lookup('nightModeButton').setIconCls(this.getNightMode() ? 'x-fa fa-sun' : 'x-fa fa-moon');
  this.setContinuous(dilocsync.util.FileViewerHelper.getViewersScrollingContinuous());
  this.lookup('toggleScrollingButton').setIconCls(this.getContinuous() ? 'x-fa fa-arrows-alt-h' : 'x-fa fa-arrows-alt-v');
  if (this.getNightMode()) {
    this.lookup('actionToolbar').addCls('dilocsync-fileviewer-action-toolbar-nightmode');
  }
}, toggleScrolling:function() {
  this.setContinuous(!this.getContinuous());
  dilocsync.util.FileViewerHelper.toggleScrolling(this.getContinuous());
}, reset:function() {
  var fileViewer = this.getView().getFileViewer();
  fileViewer.hide();
  this.getViewModel().set({name:'-', record:null, path:null, onPageNumber:0, fileExists:true});
}});
Ext.define('dilocsync.view.components.videoplayer.VideoPlayer', {extend:Ext.Container, xtype:'videoplayer', viewModel:{type:'videoplayer'}, controller:'videoplayer', cls:'dilocsync-videoplayer', listeners:{hide:'pauseVideoPlayer'}, bind:{html:'\x3cdiv class\x3d"dilocsync-videoplayer-video"\x3e' + '\x3cvideo width\x3d"100%" height\x3d"100%" controls webkit-playsinline\x3d"true" playsinline\x3d"true"\x3e\n' + '  \x3csource src\x3d"{url}" type\x3d"video/mp4"\x3e\n' + 'Your browser does not support the video tag.\n' + 
'\x3c/video\x3e' + '\x3c/div\x3e'}});
Ext.define('dilocsync.view.components.fileviewer.FileViewer', {extend:Ext.Panel, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'fileviewer', viewModel:{type:'fileviewer'}, controller:'fileviewer', listeners:{resize:'onResize', beforeresizedragstart:'hideViewer', resizedragend:'showViewer', painted:'updateToolbar'}, cls:'dilocsync-fileviewer', config:{fileViewer:null, additionalToolbarItems:[], reopenHiddenFile:false, hideBackButton:false}, layout:{type:'vbox', align:'stretch'}, enableDownloadOnDemand:false, 
initialize:function() {
  var items = [];
  var viewer;
  var actionBar;
  var unSupported;
  var videoPlayer;
  var me = this;
  items.push({xtype:'component', itemId:'fileName', cls:'dilocsync-fileviewer-file-name', tpl:['{fileTitle}', '\x3cspan class\x3d"dilocsync-validity"\x3e', '\x3ctpl if\x3d"validFrom" \x3e', '\x26nbsp;', this.tr('Valid from'), '\x26nbsp;', '{validFrom:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3ctpl if\x3d"validTo" \x3e', '\x26nbsp;', '\x3ctpl if\x3d"!validFrom"\x3e', this.tr('Valid'), '\x26nbsp;', '\x3c/tpl\x3e', this.tr('until'), '\x26nbsp;', '{validTo:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3c/span\x3e'], 
  bind:{data:{fileTitle:'{fileTitle}', validFrom:'{record.validFrom}', validTo:'{record.validTo}'}, hidden:'{!record}'}});
  actionBar = {xtype:'toolbar', cls:'dilocsync-fileviewer-action-toolbar', reference:'actionToolbar', plugins:{responsive:true}, ui:'actions-toolbar', defaults:{ui:'toolbar-actions'}, responsiveConfig:{'phone':{items:Ext.Array.merge([{iconCls:'x-fa fa-chevron-left', reference:'backButton', handler:'onBack', hidden:this.getHideBackButton()}], this.defaultToolbarItems(), this.getAdditionalToolbarItems())}, 'tablet || desktop':{items:Ext.Array.merge(this.defaultToolbarItems(), this.getAdditionalToolbarItems())}}};
  items.push(actionBar);
  if (dilocsync.core.Master.isPhonegap()) {
    viewer = {xtype:'container', cls:'dilocsync-fileviewer-container', hidden:true, flex:1, reference:'viewer'};
  } else {
    viewer = {xtype:'container', cls:'dilocsync-fileviewer-container', flex:1, reference:'viewer', hidden:true, bind:{html:'selected file: {path}'}};
  }
  items.push(viewer);
  unSupported = {xtype:'component', cls:'dilocsync-fileviewer-unsupported-file', reference:'unsupportedFileTypeComponent', flex:1, hidden:true, bind:{html:'\x3cdiv class\x3d"dilocsync-fileviewer-unsupported-file-help"\x3e' + this.tr('Open file in external app') + '\x3c/div\x3e\x3cdiv class\x3d"dilocsync-fileviewer-unsupported-file-arrow"\x3e\x3c/div\x3e\x3cdiv class\x3d"dilocsync-fileviewer-unsupported-file-text"\x3e\x3cspan\x3e\x3ch1\x3e' + this.tr('Sorry') + '\x3c/h1\x3e\x3cp\x3e' + this.tr('This file type is currently not supported by DiLoc|Sync.') + 
  '\x3c/p\x3e\x3c/span\x3e\x3c/div\x3e', hidden:'{isFileTypeSupported}'}};
  items.push(unSupported);
  videoPlayer = {xtype:'videoplayer', reference:'videoplayer', flex:1, hidden:true};
  items.push(videoPlayer);
  var enableDownloadOnDemandComponent = {xtype:'container', cls:'dilocsync-fileviewer-file-not-found', reference:'enableDownloadOnDemandComponent', flex:1, layout:{type:'vbox', align:'center', pack:'center'}, bind:{hidden:'{!enableDownloadOnDemand}'}, items:[{xtype:'component', html:this.tr('\x3cdiv class\x3d"dilocsync-fileviewer-file-not-found"\x3e\x3cspan\x3e\x3ch1\x3e' + this.tr('Notice') + '\x3c/h1\x3e\x3cp\x3e' + this.tr('The selected file has not yet been downloaded...') + '\x3c/p\x3e\x3c/span\x3e\x3c/div\x3e')}, 
  {xtype:'button', text:this.tr('Download'), margin:'5', ui:'action', handler:function() {
    var viewModel = me.getViewModel();
    var record = viewModel.get('record');
    me.fireEvent('downloadOnDemand', record, viewModel);
  }}]};
  var fileNotFoundComponent = {xtype:'component', cls:'dilocsync-fileviewer-file-not-found', reference:'fileNotFoundComponent', flex:1, hidden:true, bind:{html:'\x3cdiv class\x3d"dilocsync-fileviewer-file-not-found"\x3e\x3cspan\x3e\x3ch1\x3e' + this.tr('File not found') + '\x3c/h1\x3e\x3cp\x3e' + this.tr('The selected file was not found anymore. It probably was deleted during a later synchronization.') + '\x3c/p\x3e\x3c/span\x3e\x3c/div\x3e', hidden:'{!showFileNotFoundComponent}'}};
  items.push(fileNotFoundComponent);
  items.push(enableDownloadOnDemandComponent);
  this.setItems(items);
  this.callParent(arguments);
}, defaultToolbarItems:function() {
  var master = dilocsync.core.Master, identity = master.getIdentity();
  var defaultToolbarItems = [{iconCls:'x-fa fa-external-link-alt', handler:'onOpenWithButtonTapped', hidden:true, bind:{hidden:'{!path || !fileExists}'}}, {xtype:'button', itemId:'nightButton', reference:'nightModeButton', iconCls:'x-fa fa-moon', handler:'toggleNightMode', hidden:true, bind:{hidden:'{!path  || !fileExists}'}}, {xtype:'button', reference:'toggleScrollingButton', iconCls:'x-fa fa-arrows-alt-v', handler:'toggleScrolling', hidden:true, bind:{hidden:'{!path  || !fileExists}'}}];
  if (identity.options && (typeof identity.options.disableFavorites === 'undefined' || !identity.options.disableFavorites)) {
    defaultToolbarItems.push({iconCls:'x-fa fa-star', itemId:'favoritesButton', cls:'dilocsync-favorites-button', reference:'favoritesButton', handler:'onFavoritesButtonTapped', hidden:true, bind:{hidden:'{hideFavoritesButton}'}});
  }
  if (identity.options && identity.options.enableWorkFolders === true && Ext.os.deviceType !== 'Phone') {
    var dossierButton = {iconCls:'x-fa fa-list-ul', itemId:'dossierButton', cls:'dilocsync-dossier-button', reference:'dossierButton', handler:'onDossierButtonTapped', hidden:true, bind:{hidden:'{!path || !fileExists}'}};
    defaultToolbarItems.push(dossierButton);
  }
  defaultToolbarItems.push({iconCls:'x-fa fa-expand', handler:'onFullscreenButtonTapped', hidden:true, bind:{hidden:'{hideFullScreenButton || !fileExists}'}});
  return defaultToolbarItems;
}, hide:function() {
  var controller = this.getController();
  if (controller.getIsVisible()) {
    this.setReopenHiddenFile(true);
    controller.hideViewer();
  }
  this.callParent(arguments);
}, show:function() {
  var controller = this.getController();
  if (this.getReopenHiddenFile()) {
    this.setReopenHiddenFile(false);
    controller.showViewer();
  }
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.confirmations.ConfirmationsController', {extend:dilocsync.view.pages.BaseController, alias:'controller.confirmations', mixins:[cnconsult.Translatable], init:function() {
  Ext.Viewport.on('orientationchange', this.updateResizeableSizes, this);
}, onConfirm:function() {
  var record = this.getViewModel().get('listPanel.selection');
  var config = {itemId:'confirmationMessageBox', title:this.getConfirmationTranslation(record.get('buttonText')), message:this.getConfirmationTranslation(record.get('confirmationText')), listeners:{hide:Ext.bind(this.checkIdenticalConfirmations, this, [record], true)}, buttons:[{text:this.tr('No'), itemId:'no', handler:function() {
    this.up('messagebox').destroy();
  }}, {text:this.tr('Yes'), itemId:'yes', handler:function() {
    var messagebox = this.up('messagebox');
    if (record.get('signatureRequired')) {
      var signature = messagebox.down('signaturepad').getValue();
      if (signature) {
        record.set('signature', signature);
      } else {
        messagebox.down('signaturepad').markInvalid();
        return;
      }
    }
    record.set('state', 'confirmed');
    record.set('confirmationTimestamp', Date.now() / 1000);
    record.store.sync();
    record.store.sort();
    messagebox.hide();
  }}]};
  if (record.get('signatureRequired')) {
    config.width = 500;
    config.items = {xtype:'signaturepad', label:config.message, required:true, labelWrap:true};
    delete config.message;
  }
  dilocsync.util.MessageHelper.showMessage(config);
}, getConfirmationTranslation:function(_text) {
  if (_text === '[received]') {
    return this.tr('Received');
  } else {
    if (_text === '[received-button]') {
      return this.tr('Received');
    } else {
      if (_text === '[received-question]') {
        return this.tr('Do you confirm that you received the file?');
      } else {
        if (_text === '[read]') {
          return this.tr('Read');
        } else {
          if (_text === '[read-button]') {
            return this.tr('Read');
          } else {
            if (_text === '[read-question]') {
              return this.tr('Do you confirm that you read the document?');
            } else {
              if (_text === '[read-understood]') {
                return this.tr('Read and understood');
              } else {
                if (_text === '[read-understood-button]') {
                  return this.tr('Read and understood');
                } else {
                  if (_text === '[read-understood-question]') {
                    return this.tr('Do you confirm that you read and understood the document?');
                  } else {
                    return _text;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}, checkIdenticalConfirmations:function(_confirmationMessageBox, _options, _record) {
  var identicalConfirmations = _record.store.queryBy(function(_confirmation) {
    return _confirmation.get('state') === 'unconfirmed' && _record.get('checksum') === _confirmation.get('checksum') && _record.get('confirmationText') === _confirmation.get('confirmationText') && _record.get('buttonText') === _confirmation.get('buttonText') && _record.get('signatureRequired') === _confirmation.get('signatureRequired');
  });
  if (identicalConfirmations.length > 0) {
    Ext.create('Ext.MessageBox', {title:this.tr('Identical confirmations'), maxWidth:'95%', maxHeight:'80%', listeners:{destroy:function() {
      return _confirmationMessageBox.destroy();
    }}, items:{xtype:'container', layout:'vbox', flex:1, items:[{xtype:'component', html:'\x3cdiv\x3e' + this.tr('The following confirmations are identical. Do you wish to confirm them as well?') + '\x3c/div\x3e'}, {xtype:'component', flex:1, scrollable:true, tpl:['\x3cul\x3e', '\x3ctpl for\x3d"."\x3e', '    \x3cli\x3e\x3cb\x3e{[values.get("path")]}\x3c/b\x3e\x3c/li\x3e', '\x3c/tpl\x3e', '\x3c/ul\x3e'], style:{wordBreak:'break-all'}, data:identicalConfirmations.getRange()}]}, buttons:[{text:this.tr('No'), 
    handler:function() {
      this.up('messagebox').destroy();
    }}, {text:this.tr('Yes'), handler:function() {
      identicalConfirmations.each(function(_confirmation) {
        _confirmation.set('state', _record.get('state'));
        _confirmation.set('confirmationTimestamp', _record.get('confirmationTimestamp'));
        _confirmation.set('signature', _record.get('signature'));
      });
      _record.store.sync();
      _record.store.sort();
      this.up('messagebox').destroy();
    }}]}).show();
  } else {
    _confirmationMessageBox.destroy();
  }
}});
Ext.define('dilocsync.view.pages.confirmations.ConfirmationsViewModel', {extend:Ext.app.ViewModel, alias:'viewmodel.confirmations', mixins:[cnconsult.Translatable], data:{confirmButtonText:''}, formulas:{updateButtonText:{bind:{bindTo:'{listPanel.selection}', deep:true}, get:function(_record) {
  if (_record) {
    this.set('confirmButtonText', this.getView().getController().getConfirmationTranslation(_record.get('buttonText')));
  }
}}, hideConfirmButton:{bind:{bindTo:'{listPanel.selection}', deep:true}, get:function(_record) {
  if (_record && _record.get('state') === 'unconfirmed') {
    return false;
  } else {
    return true;
  }
}}}});
Ext.define('dilocsync.view.pages.confirmations.Confirmations', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'confirmations', cls:'dilocsync-confirmations', controller:'confirmations', viewModel:{type:'confirmations'}, responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, getDesktopViewer:function() {
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    return {xtype:'externalfileopen', reference:'viewer', listeners:{resize:'onResize'}, resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, flex:2, additionalButtonItems:[{xtype:'button', iconCls:'x-fa fa-check', cls:'dilocsync-confirmations-button', itemId:'confirmationButton', hidden:true, align:'right', bind:{hidden:'{!fileExists || hideConfirmButton}', text:'{confirmButtonText}'}, handler:'onConfirm', scope:this.getController()}]};
  }
  return {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', additionalToolbarItems:['-\x3e', {xtype:'button', itemId:'confirmationButton', iconCls:'x-fa fa-check', cls:'dilocsync-confirmations-button', align:'right', hidden:true, bind:{hidden:'{!fileExists || hideConfirmButton}', text:'{confirmButtonText}'}, handler:'onConfirm', scope:this.getController()}], listeners:{resize:'onResize'}, resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, 
  null], minSize:[minResizeWidth, null]}, flex:2};
}, initialize:function() {
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([{xtype:'filelist', store:Ext.getStore('Confirmations'), showPath:true, items:[{xtype:'titlebar', title:this.tr('Confirmations'), docked:'top'}], reference:'listPanel', listeners:{childtap:'showViewerFromList'}}, {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', listeners:{back:'showList'}, additionalToolbarItems:['-\x3e', {xtype:'button', iconCls:'x-fa fa-check', cls:'dilocsync-confirmations-button', itemId:'confirmationButton', hidden:true, 
    align:'right', bind:{hidden:'{!fileExists || hideConfirmButton}', text:'{confirmButtonText}'}, handler:'onConfirm', scope:this.getController()}], hidden:true}]);
  } else {
    this.setItems([{xtype:'filelist', store:Ext.getStore('Confirmations'), showPath:true, items:[{xtype:'titlebar', title:this.tr('Confirmations'), docked:'top', defaults:{ui:'toolbar-button'}, items:[{itemId:'maximize', iconCls:'x-fa fa-expand', align:'right', handler:'maximizeListPanel'}, {itemId:'minimize', iconCls:'x-fa fa-compress', align:'right', handler:'minimizeListPanel', hidden:true}]}], reference:'listPanel', listeners:{childtap:'onShowFileFromList', childdoubletap:'onOpenFileFromList'}, 
    flex:1}, this.getDesktopViewer()]);
  }
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.dailyla.DailyLaModel', {extend:Ext.app.ViewModel, alias:'viewmodel.dailyla', data:{needsFileList:false, showFileList:false, areaPath:''}, stores:{treeMenuItems:{type:'tree'}}});
Ext.define('dilocsync.core.DailyLaChecker', {config:{basePath:'', areas:[], additionalAreas:[], areaPrefix:'', filesNeedToBeThereUntil:'00:00', today:null, tomorrow:null, yesterday:null}, constructor:function(_config) {
  this.initConfig(_config);
  this.initializeDates();
}, initializeDates:function() {
  var today = new Date;
  var tomorrow = new Date;
  var yesterday = new Date;
  tomorrow.setDate(today.getDate() + 1);
  yesterday.setDate(today.getDate() - 1);
  this.setToday(today);
  this.setTomorrow(tomorrow);
  this.setYesterday(yesterday);
}, getFilePathForAreaAndDate:function(_laArea, _date) {
  var filename = this.getFileNameForAreaAndName(_laArea, _date);
  var areaPrefix = this.getAreaPrefix() || '';
  return '/' + areaPrefix + _laArea + '/' + filename;
}, getFileNameForAreaAndName:function(_laArea, _date) {
  return _date + '_Tages-La_' + _laArea + '.pdf';
}, getAllFilePaths:function() {
  var filePaths = [];
  for (var $jscomp$iter$11 = $jscomp.makeIterator(dilocsync.util.Identity.filterDailyLaAreas(this.getAreas())), $jscomp$key$area = $jscomp$iter$11.next(); !$jscomp$key$area.done; $jscomp$key$area = $jscomp$iter$11.next()) {
    var area = $jscomp$key$area.value;
    {
      if (!this.getAdditionalAreas().includes(area)) {
        filePaths.push(this.getFilePathForAreaAndDate(area, Ext.Date.format(this.getToday(), 'Y-m-d')));
        filePaths.push(this.getFilePathForAreaAndDate(area, Ext.Date.format(this.getYesterday(), 'Y-m-d')));
        if (this.getFilesNeedToBeThereUntil()) {
          if (this.shouldFilesForTomorrowBeThere()) {
            cnconsult.Logger.log({prefix:'DailyLaChecker-\x3egetAllFilePaths', message:'We are in the timeframe, add tomorrow as required date'});
            filePaths.push(this.getFilePathForAreaAndDate(area, Ext.Date.format(this.getTomorrow(), 'Y-m-d')));
          }
        } else {
          filePaths.push(this.getFilePathForAreaAndDate(area, Ext.Date.format(this.getTomorrow(), 'Y-m-d')));
        }
      }
    }
  }
  return filePaths;
}, getMissingFiles:function() {
  this.initializeDates();
  var master = dilocsync.core.Master;
  var filePaths = this.getAllFilePaths();
  var missingFiles = [];
  var almanacName = 'data/' + this.getBasePath();
  var almanac = master.getAlmanacs()[almanacName];
  for (var i = 0; i < filePaths.length; i++) {
    var filePath = filePaths[i];
    if (almanac && !almanac.fileExists(filePath)) {
      missingFiles.push(filePath);
    }
  }
  this.getAdditionalAreas().forEach(function(area) {
    var additionalCountryAlmanacDirectory = almanac.getDirectoryForPath('/' + area);
    if (additionalCountryAlmanacDirectory) {
      if (Object.keys(additionalCountryAlmanacDirectory.files).length === 0) {
        missingFiles.push(area);
      }
    }
  });
  return missingFiles;
}, numMissingFiles:function() {
  var missingFiles = this.getMissingFiles();
  return missingFiles.length;
}, shouldFilesForTomorrowBeThere:function() {
  var now = new Date;
  var lowerLimit = new Date(Ext.Date.format(now, 'Y-m-d') + 'T' + this.getFilesNeedToBeThereUntil());
  var upperDayLimit = new Date(Ext.Date.format(now, 'Y-m-d') + 'T23:59:59');
  return now.getTime() >= lowerLimit.getTime() && now.getTime() <= upperDayLimit.getTime();
}});
Ext.define('dilocsync.util.Identity', {singleton:true, mixins:[cnconsult.Translatable], convertDriveModeConfigToMenuTreeConfig:function(_identity) {
  var me = this;
  var pageConfig = me.getPageConfigByType(_identity, 'drivemode');
  var treeConfig = {expanded:false, children:[]};
  if (Ext.isArray(pageConfig.config.sidePanels)) {
    Ext.Array.each(pageConfig.config.sidePanels, function(_item, _index) {
      var children = me.getSubMenuFromPanel(_item.type);
      var node = {text:_item.label, leaf:true};
      if (children.length > 0) {
        node.children = children;
        node.leaf = false;
      } else {
        node.config = Ext.apply({type:_item.type}, _item.config ? _item.config : {});
      }
      treeConfig.children.push(node);
    });
  }
  return treeConfig;
}, convertIdentityPageConfigToTreeMenu:function(_identity, _type, _sidePanelXtype) {
  var me = this;
  var pageConfig = me.getPageConfigByType(_identity, _type);
  var children = me.getSubMenuFromPanel(_sidePanelXtype);
  var treeConfig = {expanded:false, children:[{text:pageConfig.title}]};
  if (children.length > 0) {
    treeConfig.children[0].children = children;
    treeConfig.children[0].children.leaf = false;
  } else {
    treeConfig.children[0].children.leaf = true;
  }
  return treeConfig;
}, getSubMenuFromPanel:function(_sidePanelXtype) {
  var panels = Ext.isDefined(dilocsync.view.components.sidepanel.panels) ? dilocsync.view.components.sidepanel.panels : undefined;
  var children = [];
  if (Ext.isDefined(panels[_sidePanelXtype]) && Ext.isFunction(panels[_sidePanelXtype].getMenuTreeItems)) {
    children = panels[_sidePanelXtype].getMenuTreeItems();
  }
  return children;
}, getPageConfigByType:function(_identity, _type) {
  var page = null;
  if (_identity && Ext.isArray(_identity.pages)) {
    page = Ext.Array.findBy(_identity.pages, function(item) {
      return item.type && item.type === _type;
    });
  }
  return page;
}, getOption:function(_identity, _name) {
  if (Ext.isObject(_identity.options)) {
    if (_identity.options.hasOwnProperty(_name)) {
      return _identity.options[_name];
    }
  }
  return null;
}, filterPagesByType:function(_identity, _type) {
  var pages = [];
  if (Ext.isArray(_identity.pages)) {
    pages = Ext.Array.filter(_identity.pages, function(item) {
      return item.type && item.type === _type;
    });
  }
  return pages;
}, filterDailyLaAreas:function(_areas) {
  var storage = dilocsync.core.Master.getStorage();
  var subscribedAreas = storage.get('page:dailyla:subscribedAreas');
  if (Ext.isArray(subscribedAreas)) {
    return Ext.Array.intersect(_areas, subscribedAreas);
  }
  return _areas;
}, checkIfSyncIsRecommend:function() {
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var isSyncing = master.getSyncEngine().isSyncing();
  if (!isSyncing && identity && identity.hasOwnProperty('options') && identity.options.hasOwnProperty('syncAdviceThreshold')) {
    var lastSync = Ext.Date.parse(master.getStorage().get('core:syncengine:lastSyncTimestamp'), 'c');
    var syncAdviceThreshold = identity.options.syncAdviceThreshold;
    if (lastSync && syncAdviceThreshold) {
      var hoursSinceLastSync = (Date.now() - Ext.Date.format(lastSync, 'time')) / (60 * 60 * 1000);
      if (hoursSinceLastSync > syncAdviceThreshold) {
        dilocsync.util.MessageHelper.showSyncRecommendMessage();
      }
    }
  }
}});
Ext.define('dilocsync.mixin.DailyLa', {updateDates:function() {
  var menu = this.lookup('menu');
  var yesterdayButton = menu.down('button[nodeId\x3dyesterday]');
  var todayButton = menu.down('button[nodeId\x3dtoday]');
  var tomorrowButton = menu.down('button[nodeId\x3dtomorrow]');
  this.getChecker().initializeDates();
  if (yesterdayButton) {
    yesterdayButton.date = Ext.Date.format(this.getChecker().getYesterday(), 'Y-m-d');
  }
  if (todayButton) {
    todayButton.date = Ext.Date.format(this.getChecker().getToday(), 'Y-m-d');
  }
  if (tomorrowButton) {
    tomorrowButton.date = Ext.Date.format(this.getChecker().getTomorrow(), 'Y-m-d');
    tomorrowButton.setDisabled(!this.getChecker().shouldFilesForTomorrowBeThere());
  }
}});
Ext.define('dilocsync.view.pages.dailyla.DailyLaController', {extend:dilocsync.view.pages.BaseController, alias:'controller.dailyla', mixins:[dilocsync.mixin.DailyLa], bindings:{onNeedsFileList:'{needsFileList}', updateList:'{areaPath}'}, config:{checker:null}, init:function() {
  var master = dilocsync.core.Master;
  var treeConfig = this.treeConfig();
  var store = this.getStore('treeMenuItems');
  var pageConfig = this.getView().pageConfig;
  var checker = Ext.create('dilocsync.core.DailyLaChecker', {basePath:pageConfig.path, areas:pageConfig.subscribedAreas, areaPrefix:pageConfig.areaPrefix, filesNeedToBeThereUntil:pageConfig.filesNeedToBeThereUntil});
  store.setRoot(treeConfig);
  this.setChecker(checker);
  this.getView().on('initialize', function() {
    var menu = this.lookup('menu');
    Ext.TaskManager.start({run:this.updateDates, interval:60 * 1000, scope:this});
    menu.on({aftercreatemenu:{fn:this.initMenu, scope:this, single:true}});
  }, this);
  master.getSyncEngine().on('syncfinished', this.initMenu, this);
}, onNeedsFileList:function(_needsFileList) {
  var vm = this.getViewModel();
  var menu = this.lookup('menu');
  var listButton = menu.down('#toggleFileListButton');
  if (!listButton) {
    listButton = menu.add({itemId:'toggleFileListButton', ui:'treemenu-button', iconCls:'x-fa fa-list-alt', docked:'right', handler:'onToggleFileList', padding:'0 10 0 0'});
  }
  listButton.setHidden(!_needsFileList);
  if (!_needsFileList) {
    vm.set('showFileList', false);
    this.lookup('listPanel').hide();
  }
}, onToggleFileList:function() {
  var vm = this.getViewModel();
  var list = this.lookup('listPanel');
  vm.set('showFileList', !vm.get('showFileList'));
  if (list.isHidden()) {
    if (Ext.os.deviceType === 'Phone') {
      this.getView().setActiveItem(this.lookup('listPanel'));
    }
    list.show();
  } else {
    if (Ext.os.deviceType === 'Phone') {
      this.getView().setActiveItem(this.lookup('viewer'));
    }
    list.hide();
  }
}, updateList:function(_areaPath) {
  var list = this.lookup('listPanel');
  if (list && _areaPath) {
    list.setSubPath(_areaPath);
  }
}, treeConfig:function() {
  var children = [];
  var helper = dilocsync.util.Identity;
  var translatorBoy = dilocsync.util.TranslatorBoy;
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var page = helper.getPageConfigByType(identity, 'dailyla');
  var pageConfig = page.hasOwnProperty('config') ? page.config : false;
  var treeConfig = {expanded:false, children:[{text:page.title}]};
  if (pageConfig && Ext.isArray(pageConfig.subscribedAreas)) {
    var subscribedAreas = [].concat($jscomp.arrayFromIterable(pageConfig.subscribedAreas));
    if (Ext.isArray(pageConfig.additionalAreas)) {
      subscribedAreas.push.apply(subscribedAreas, $jscomp.arrayFromIterable(pageConfig.additionalAreas));
    }
    Ext.Array.each(helper.filterDailyLaAreas(subscribedAreas), function(_area) {
      if (pageConfig.subscribedAreas.includes(_area)) {
        children.push({text:_area, area:_area, leaf:false, children:[{text:translatorBoy.getYesterday(), area:_area, id:'yesterday', config:Ext.apply({type:'DailyLaPanel'}, pageConfig || {}), leaf:true}, {text:translatorBoy.getToday(), area:_area, id:'today', config:Ext.apply({type:'DailyLaPanel'}, pageConfig || {}), leaf:true}, {text:translatorBoy.getTomorrow(), area:_area, id:'tomorrow', config:Ext.apply({type:'DailyLaPanel'}, pageConfig || {}), leaf:true}]});
      } else {
        children.push({text:_area, area:_area, leaf:false, children:[{text:translatorBoy.getFiles(), area:_area, id:'files', config:Ext.apply({type:'DailyLaPanel'}, pageConfig || {}), leaf:true}]});
      }
    });
  }
  if (children.length > 0) {
    treeConfig.children[0].children = children;
    treeConfig.children[0].children.leaf = false;
  } else {
    treeConfig.children[0].children.leaf = true;
  }
  return treeConfig;
}, initMenu:function() {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var store = this.getStore('treeMenuItems');
  var menu = this.lookup('menu');
  var activeArea = storage.get('page:dailyla:lastArea');
  var viewedNodeId = storage.get('page:dailyla:lastViewedNodeId');
  var activeNode;
  if (!viewedNodeId) {
    viewedNodeId = 'today';
  }
  if (activeArea) {
    this.getViewModel().set('areaPath', activeArea);
    activeNode = store.getRoot().findChildBy(function(_record) {
      return _record.get('area') === activeArea && _record.get('id') === viewedNodeId;
    }, this, true);
  }
  if (!activeNode) {
    activeNode = store.getRoot().firstChild;
  }
  menu.createMenu(activeNode);
  if (this.getView() && this.getView().isVisible() && activeNode.isLeaf()) {
    this.showFileByNode(activeNode);
  }
}, onLeafItemTap:function(_menu, _button, _node) {
  dilocsync.core.Master.getStorage().set('page:dailyla:lastViewedNodeId', _node.get('id'));
  this.showFileByNode(_node);
}, showFileByNode:function(_node) {
  if (_node.get('id') === 'files' && this.lookup('listPanel').isHidden()) {
    this.getViewModel().set('needsFileList', true);
    this.onToggleFileList();
    return;
  }
  var master = dilocsync.core.Master;
  var checker = this.getChecker();
  var viewer = this.lookup('viewer');
  var area = _node.get('area');
  var areaPrefix = _node.get('config').hasOwnProperty('areaPrefix') ? _node.get('config').areaPrefix : '';
  if (areaPrefix) {
    console.log('Using areaPrefix:', areaPrefix);
    checker.setAreaPrefix(areaPrefix);
  }
  var nodeId = _node.get('id');
  var date = Ext.Date.format(checker['get' + Ext.String.capitalize(nodeId)](), 'Y-m-d');
  var path = dilocsync.core.Master.devicePath('/' + checker.getFilePathForAreaAndDate(area, date));
  var fileName = checker.getFileNameForAreaAndName(area, date);
  var record;
  var almanacName = 'data/' + checker.getBasePath();
  var almanac = master.getAlmanacs()[almanacName];
  var files = almanac.findFilesRecursively(fileName);
  var areaDirectory = almanac.getDirectoryForPath(areaPrefix + area);
  var areaFiles = areaDirectory ? areaDirectory.files : {};
  if (files.length > 0) {
    record = new dilocsync.model.AlmanacEntry(files[0]);
  } else {
    record = new dilocsync.model.AlmanacEntry({name:'', path:'', fileType:''});
  }
  if (record.get('checksum')) {
    path = master.devicePath('fs-data/' + record.get('checksum') + '.' + record.get('fileType'));
  }
  this.getViewModel().set({'needsFileList':this.checkNeedsFileList(areaFiles), 'areaPath':areaDirectory.path});
  if (Ext.os.deviceType === 'Phone' && viewer) {
    this.getView().setActiveItem(viewer);
  }
  viewer.getViewModel().set({'name':fileName, 'record':record, 'path':path});
}, checkNeedsFileList:function(_areaFiles) {
  var regexTestIfTagesLaFile = /^[\d]{4}[-][\d]{2}[-][\d]{2}_Tages\-La_(.*)\.pdf$/;
  var needsFileList = false;
  Ext.Object.each(_areaFiles, function(_fileName, _fileObject) {
    if (!regexTestIfTagesLaFile.test(_fileName)) {
      needsFileList = true;
      return false;
    }
  }, this);
  return needsFileList;
}, onRootLineItemTap:function(_menu, _button, _node) {
  var area = _node.get('area');
  var storage = dilocsync.core.Master.getStorage();
  if (area) {
    var master = dilocsync.core.Master;
    var checker = this.getChecker();
    var almanacName = 'data/' + checker.getBasePath();
    var almanac = master.getAlmanacs()[almanacName];
    var areaDirectory = almanac.getDirectoryForPath(area);
    var areaFiles = areaDirectory ? areaDirectory.files : {};
    var fileViewer = this.lookup('viewer');
    storage.set('page:dailyla:lastArea', area);
    storage.remove('page:dailyla:lastViewedNodeId');
    this.getViewModel().set({'needsFileList':this.checkNeedsFileList(areaFiles), 'areaPath':areaDirectory.path});
    if (fileViewer) {
      fileViewer.getController().reset();
    }
  }
}, onAfterCreateMenu:function(_menu, _activeNode) {
  var tomorrowButton = _menu.down('button[nodeId\x3dtomorrow]');
  if (tomorrowButton) {
    tomorrowButton.setDisabled(!this.getChecker().shouldFilesForTomorrowBeThere());
  }
}});
Ext.define('dilocsync.view.pages.dailyla.DailyLa', {extend:dilocsync.view.pages.Base, xtype:'dailyla', mixins:[cnconsult.Translatable, Ext.mixin.Responsive], viewModel:{type:'dailyla'}, controller:'dailyla', responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, getDesktopViewer:function() {
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    return {xtype:'externalfileopen', reference:'viewer', bind:{resizable:{split:'{showFileList}', edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}}, flex:2};
  }
  return {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), hideBackButton:true, reference:'viewer', bind:{resizable:{split:'{showFileList}', edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}}, flex:2};
}, initialize:function() {
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([{xtype:'horizontaltreemenu', reference:'menu', docked:'top', bind:{store:'{treeMenuItems}'}, listeners:{leafitemtap:'onLeafItemTap', rootlineitemtap:'onRootLineItemTap', aftercreatemenu:'onAfterCreateMenu'}}, {xtype:'filefolderpanel', folderTitle:this.pageConfig.title, path:this.pageConfig.path, reference:'listPanel', hidden:true, listeners:{showfile:'showViewer'}}, {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), hideBackButton:true, reference:'viewer', 
    listeners:{back:'showList'}}]);
  } else {
    this.setItems([{xtype:'horizontaltreemenu', reference:'menu', docked:'top', bind:{store:'{treeMenuItems}'}, listeners:{leafitemtap:'onLeafItemTap', rootlineitemtap:'onRootLineItemTap', aftercreatemenu:'onAfterCreateMenu'}}, {xtype:'filefolderpanel', folderTitle:this.pageConfig.title, path:this.pageConfig.path, reference:'listPanel', hidden:true, listeners:{showfile:'showFile', openfile:'openFile', resize:'onResize'}, flex:1}, this.getDesktopViewer()]);
  }
  this.callParent(arguments);
  if (Ext.os.deviceType !== 'Phone') {
    this.addMinMaximizeFeatureToToolbar();
  }
}, addMinMaximizeFeatureToToolbar:function() {
  var buttons = [{ui:'toolbar-button', itemId:'maximize', iconCls:'x-fa fa-expand', align:'right', handler:'maximizeListPanel', scope:this.getController()}, {ui:'toolbar-button', itemId:'minimize', iconCls:'x-fa fa-compress', align:'right', handler:'minimizeListPanel', scope:this.getController(), hidden:true}];
  this.lookup('listPanel').down('filefolderlist titlebar').add(buttons);
  this.lookup('listPanel').down('[reference\x3dsearchResultList] titlebar').add(buttons);
}, pageTappedAgain:function() {
  var list = this.down('filefolderlist');
  if (list) {
    list.goToNode(list.getStore().getRoot());
  }
}});
Ext.define('dilocsync.view.pages.driveinfo.DriveInfoController', {extend:Ext.app.ViewController, alias:'controller.driveinfopage', mixins:[cnconsult.Translatable], onFieldChange:function(_field, _value) {
  var storage = dilocsync.core.Master.getStorage();
  storage.set('page:driveInfo:' + _field.getItemId(), _value);
}, onLocoTypeChange:function(_field, _value) {
  Ext.select('.loco-type-item').removeCls('disabled');
  if (_value && _value.length >= 2) {
    var store = this.getViewModel().get('locoTypesStore');
    Ext.select('.loco-type-item').each(function(item) {
      var record = store.getByInternalId(item.dom.dataset.recordid);
      if (!_value.includes(record.get('id'))) {
        item.addCls('disabled');
      }
    });
  }
  this.onFieldChange(_field, _value);
}, onHide:function() {
}, onShow:function() {
}, onStartDriveAdvisory:function() {
  Ext.fireEvent('startDriveAdvisory');
}, onStopDriveAdvisory:function() {
  Ext.fireEvent('stopDriveAdvisory');
}, onStartGpsTracking:function() {
  Ext.fireEvent('startGpsTracking');
}, onStopGpsTracking:function() {
  Ext.fireEvent('stopGpsTracking');
}, onStartDigitalOrder:function(_button) {
  var $jscomp$this = this;
  var mode = dilocsync.core.Master.getStorage().get('page:driveInfo:digitalOrderMode');
  var cmp = this.lookup('digitalOrderMode');
  switch(mode) {
    case 'test':
      cmp.setHtml('\x3ch2 class\x3d"digital-order-mode test"\x3e' + this.tr('Test operation') + '\x3c/h2\x3e');
      break;
    case 'demo':
      cmp.setHtml('\x3ch2 class\x3d"digital-order-mode demo"\x3e' + this.tr('Simulation') + '\x3c/h2\x3e');
      break;
    default:
      cmp.setHtml('');
      break;
  }
  dilocsync.util.DigitalOrderHelper.start().then(function(_success) {
    if (_success && _button.getItemId() === 'drivemode') {
      $jscomp$this.redirectTo('drivemode');
    }
  });
}, onStopDigitalOrder:function() {
  this.lookup('digitalOrderMode').setHtml('');
  dilocsync.util.DigitalOrderHelper.stop();
}});
Ext.define('dilocsync.view.pages.driveinfo.DriveInfo', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable], xtype:'driveinfopage', controller:'driveinfopage', scrollable:'true', layout:'fit', initialize:function() {
  this.setItems([{xtype:'container', layout:{type:'vbox', align:'stretch'}, height:'100%', items:[{xtype:'container', flex:0.7, layout:'vbox', padding:'0 16 0 16', items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('Settings')}, {xtype:'textfield', label:this.tr('Trainnumber'), itemId:'trainNumber', bind:{value:'{trainNumber}', disabled:'{driveAdvisoryStarted || gpsTrackingStarted || digitalOrderStarted}'}, listeners:{change:'onFieldChange'}}]}, {xtype:'container', flex:2, layout:{type:'hbox', 
  align:'stretch'}, padding:'0 8 16 8', items:[{xtype:'container', flex:1, layout:'vbox', scrollable:true, cls:'feature-container', hidden:true, bind:{hidden:'{!enableDigitalOrder}'}, items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('Digital order ÖBB')}, {xtype:'component', reference:'digitalOrderMode', html:''}, {xtype:'datefield', dateFormat:'d.m.Y', label:this.tr('Schedule Date'), editable:false, bind:{value:'{digitalOrderDate}', disabled:'{digitalOrderStarted}'}, margin:'0 10 30 10'}, 
  {xtype:'selectfield', label:this.tr('EVU'), margin:'0 10 30 10', valueField:'token', displayField:'companyName', bind:{store:'{digitalOrderTokens}', value:'{digitalOrderToken}', disabled:'{digitalOrderStarted}'}}, {xtype:'selectfield', label:this.tr('Role'), value:'LeadingTrainDriver', options:[{text:this.tr('Leading train driver'), value:'LeadingTrainDriver'}, {text:this.tr('Non-leading train driver'), value:'NonLeadingTrainDriver'}, {text:this.tr('Attendant'), value:'Attendant'}], margin:'0 10 30 10', 
  bind:{value:'{digitalOrderUserRole}', disabled:'{digitalOrderStarted}'}}, {xtype:'container', flex:1}, {xtype:'container', layout:'hbox', items:[{xtype:'button', flex:1, cls:'dilocsync-start-drive', text:this.tr('Receive digital order'), bind:{disabled:'{!trainNumber || !digitalOrderToken}', hidden:'{digitalOrderStarted}'}, handler:'onStartDigitalOrder', margin:10}, {xtype:'button', flex:1, cls:'dilocsync-stop-drive', text:this.tr('Stop digital order'), hidden:true, bind:{hidden:'{!digitalOrderStarted}'}, 
  handler:'onStopDigitalOrder', margin:10}, {xtype:'button', itemId:'drivemode', cls:'dilocsync-start-drive', iconCls:'x-fa fa-columns', bind:{disabled:'{!trainNumber || !digitalOrderToken || digitalOrderStarted}'}, handler:'onStartDigitalOrder', margin:'10 10 10 0', padding:'0 15'}]}]}, {xtype:'container', flex:1, layout:'vbox', scrollable:true, cls:'feature-container', hidden:true, bind:{hidden:'{!enableGpsTracking}'}, items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('Railway knowledge')}, 
  {html:this.tr('Select up to 2 locomotion types that will be actively used during the ride.'), padding:'0 10 20 10'}, {xtype:'selectfield', label:this.tr('Locomotion type'), itemId:'locomotionType', itemCls:'loco-type-item', clearable:true, valueField:'id', displayField:'displayName', multiSelect:true, bind:{store:'{locoTypesStore}', value:'{locomotionType}', disabled:'{gpsTrackingStarted}', hidden:'{locoTypesStore.data.length \x3d\x3d\x3d 0}'}, listeners:{change:'onLocoTypeChange', expand:function() {
    if (Ext.select('.loco-type-item.x-selected').elements.length >= 2) {
      Ext.select('.loco-type-item:not(.x-selected)').addCls('disabled');
    }
  }}, margin:'0 10 20 10'}, {xtype:'container', flex:1}, {xtype:'button', cls:'dilocsync-start-drive', text:this.tr('Start GNSS tracking'), handler:'onStartGpsTracking', bind:{hidden:'{gpsTrackingStarted}', disabled:'{!trainNumber}'}, margin:10}, {xtype:'button', cls:'dilocsync-stop-drive', text:this.tr('Stop GNSS tracking'), handler:'onStopGpsTracking', hidden:true, bind:{hidden:'{!gpsTrackingStarted}'}, margin:10}]}, {xtype:'container', flex:1, layout:'vbox', scrollable:true, cls:'feature-container', 
  hidden:true, bind:{hidden:'{!enableDriveAdvisory}'}, items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('Drive advisory')}, {xtype:'datefield', dateFormat:'d.m.Y', label:this.tr('Schedule Date'), editable:false, bind:{value:'{trainDate}', disabled:'{driveAdvisoryStarted}'}, margin:'0 10 20 10'}, {xtype:'container', flex:1}, {xtype:'button', cls:'dilocsync-start-drive', text:this.tr('Start drive advisory'), handler:'onStartDriveAdvisory', bind:{hidden:'{driveAdvisoryStarted}', disabled:'{!trainNumber || driveAdvisoryPending}'}, 
  margin:10}, {xtype:'button', cls:'dilocsync-stop-drive', text:this.tr('Stop drive advisory'), handler:'onStopDriveAdvisory', hidden:true, bind:{hidden:'{!driveAdvisoryStarted}'}, margin:10}]}]}]}]);
  this.callParent(arguments);
  Ext.defer(function() {
    this.down('#trainNumber').focus();
  }, 100, this);
}});
Ext.define('dilocsync.view.components.sidepanel.SidePanelModel', {extend:Ext.app.ViewModel, alias:'viewmodel.sidepanel', stores:{treeMenuItems:{type:'tree'}}});
Ext.define('dilocsync.view.components.sidepanel.SidePanelController', {extend:Ext.app.ViewController, alias:'controller.sidepanel', mixins:[cnconsult.Translatable, dilocsync.mixin.DailyLa], control:{'filelist, filefolderlist, filefolderpanel, list':{showfile:'showFile'}, 'filefolderlist list, filelist':{childlongpress:'onChildLongPress'}, 'horizontaltreemenu':{leafitemtap:'pauseVideoPlayer', rootitemtap:'pauseVideoPlayer', rootlineitemtap:'onRootLineItemTap'}}, config:{lastActiveView:null, checker:null, 
lastViewInitialized:false}, init:function() {
  var me = this;
  var helper = dilocsync.util.Identity;
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var treeConfig = helper.convertDriveModeConfigToMenuTreeConfig(identity);
  var store = this.getStore('treeMenuItems');
  Ext.on('fileviewerrectconfigured', this.hideCloseButton, this);
  identity.pages.forEach(function(_page) {
    if (_page.type === 'drivemode') {
      _page.config.sidePanels.forEach(function(_item) {
        if (_item.type === 'DailyLaPanel') {
          var checker = Ext.create('dilocsync.core.DailyLaChecker', {basePath:_item.config.path, areas:_item.config.subscribedAreas, areaPrefix:_item.config.areaPrefix, filesNeedToBeThereUntil:_item.config.filesNeedToBeThereUntil});
          me.setChecker(checker);
          Ext.TaskManager.start({run:me.updateDates, interval:60 * 1000, scope:me});
        }
      });
    }
  });
  store.setRoot(treeConfig);
}, onRootLineItemTap:function(_menu, _button, _node) {
  var area = _node.get('area');
  var storage = dilocsync.core.Master.getStorage();
  var sidePanel = this.getView().getReference();
  if (area) {
    storage.set('page:dailyla:' + sidePanel + ':lastArea', area);
  }
  this.showOrHideToolbar(true);
}, pauseVideoPlayer:function() {
  var videoPlayer = this.getView().down('videoplayer');
  if (!videoPlayer) {
    return;
  }
  var videoPlayerController = videoPlayer.getController();
  if (videoPlayerController) {
    videoPlayerController.pauseVideoPlayer();
  }
}, initSidePanelView:function() {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var menu = this.lookup('menu');
  var store = this.getStore('treeMenuItems');
  var sidePanel = this.getView().getReference();
  var lastViewedNodeId = storage.get('page:drivemode:' + sidePanel + ':lastViewedNodeId');
  var lastViewedArea = storage.get('page:dailyla:' + sidePanel + ':lastArea');
  var root = store.getRoot();
  var lastViewedNode;
  if (Ext.Array.contains(['yesterday', 'today', 'tomorrow'], lastViewedNodeId) || Ext.String.startsWith(lastViewedNodeId, 'files_')) {
    lastViewedNode = root.findChildBy(function(_node) {
      return _node.get('id') === lastViewedNodeId && _node.get('area') === lastViewedArea;
    }, this, true);
  } else {
    if (lastViewedNodeId) {
      lastViewedNode = root.findChild('id', lastViewedNodeId, true);
    }
  }
  if (lastViewedNode && !this.lookup('viewer').isVisible()) {
    menu.createMenu(lastViewedNode);
    this.renderNodeView(lastViewedNode);
  }
}, onChildLongPress:function(_list, _info) {
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.sidepanel.SidePanelController', src:'Dokumente', action:'DokumentAufSeiteÖffnen', trackedAt:new Date});
  if (_info.record.isNode && _info.record.isLeaf() || !_info.record.isNode) {
    _list.longPressed = true;
    dilocsync.util.MessageHelper.showPrompt(this.tr('Open file on page number'), this.tr('Please enter the page number you like to open'), function(_buttonId, _pageNumber) {
      if (_buttonId === 'ok') {
        _list.fireEvent('showfile', _info.record, _list, parseInt(_pageNumber));
      }
    }, this);
  }
}, showFile:function(_record, _list, _pageNumber) {
  var $jscomp$this = this;
  var activeList = _list.isXType('nestedlist') ? _list.down('list[hidden\x3dfalse]') : _list;
  if (activeList.longPressed) {
    activeList.longPressed = false;
  } else {
    var master = dilocsync.core.Master;
    var view = this.getView();
    var viewer = this.lookup('viewer');
    var viewModel = viewer.getViewModel();
    var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(_record);
    var filePath = master.devicePath(rootFsEntryName + '/' + _record.get('checksum') + '.' + _record.get('fileType'));
    viewModel.set('name', _record.get('name'));
    viewModel.set('record', _record);
    viewModel.set('path', filePath);
    viewer.on('close', function() {
      $jscomp$this.closeViewer();
    });
    if (_record.get('icon') !== 'folder') {
      if (dilocsync.util.File.isFileTypeVideo(dilocsync.util.File.extension(_record.get('path')))) {
        this.hideCloseButton();
      }
      if (_pageNumber && Ext.isNumber(_pageNumber) && _pageNumber > 0) {
        viewModel.set('onPageNumber', _pageNumber - 1);
      } else {
        viewModel.set('onPageNumber', 0);
      }
    }
    this.setLastActiveView(view.getActiveItem());
    view.setActiveItem(viewer);
  }
}, closeViewer:function() {
  var viewer = this.lookup('viewer');
  var view = this.getView();
  var lastActiveView = this.getLastActiveView();
  view.setActiveItem(lastActiveView);
  this.pauseVideoPlayer();
  viewer.getController().reset();
  view.fireEvent('closeviewer', view);
}, onLeafItemTap:function(_menu, _button, _node) {
  this.renderNodeView(_node);
  this.onResize();
}, showOrHideToolbar:function(show) {
  var appMain = this.getView().up('app-main');
  if (appMain) {
    var toolbar = appMain.lookup('bottomToolbar');
    if (toolbar) {
      if (show) {
        toolbar.show();
      } else {
        toolbar.hide();
      }
    }
  }
}, renderNodeView:function(_node) {
  var sidePanel = this.getView();
  var xtype = _node.get('config').type;
  var panels = Ext.isDefined(dilocsync.view.components.sidepanel.panels) ? dilocsync.view.components.sidepanel.panels : undefined;
  var view;
  if (Ext.isDefined(panels[xtype]) && Ext.isFunction(panels[xtype].getNodeView)) {
    view = panels[xtype].getNodeView(sidePanel, _node);
    sidePanel.setActiveItem(view);
  }
  dilocsync.core.Master.getStorage().set('page:drivemode:' + sidePanel.getReference() + ':lastViewedNodeId', _node.id);
}, onResize:function() {
  var me = this;
  this.getView().getInnerItems().forEach(function(_view) {
    me.setListItemWidth(_view);
  });
}, setListItemWidth:function(_view) {
  var listWidth = _view.el.getWidth();
  _view.el.select('.dilocsync-file-list-item-name').setWidth(listWidth - 85);
}, onAfterCreateMenu:function(_menu, _activeNode) {
  var tomorrowButton = _menu.down('button[nodeId\x3dtomorrow]');
  if (tomorrowButton) {
    tomorrowButton.setDisabled(!this.getChecker().shouldFilesForTomorrowBeThere());
  }
  if (!this.getLastViewInitialized()) {
    this.setLastViewInitialized(true);
    this.initSidePanelView();
  }
}, hideCloseButton:function() {
  var menu = this.lookup('menu'), dailyLaButtons = ['yesterday', 'today', 'tomorrow'], viewer = this.lookup('viewer'), closeButton = null;
  if (viewer) {
    closeButton = viewer.down('#closeButton');
  }
  if (closeButton) {
    if (dailyLaButtons.includes(menu.getActiveItem().getActiveItem().nodeId)) {
      closeButton.hide();
    } else {
      closeButton.show();
    }
  }
}});
Ext.define('dilocsync.view.components.sidepanel.panels.ClarisPanel', {xtype:'ClarisPanel', statics:{getMenuTreeItems:function() {
  return [];
}, getNodeView:function(_sidePanel, _node) {
  var view = _sidePanel.down('#clarisIframe');
  if (!view) {
    view = Ext.create('Ext.Component', {itemId:'clarisIframe', html:'\x3ciframe src\x3d"http://127.0.0.1:9094/" class\x3d"dilocsync-claris-iframe" width\x3d"640" height\x3d"360" align\x3d"left" /\x3e'});
  }
  return view;
}}});
Ext.define('dilocsync.util.TranslatorBoy', {singleton:true, mixins:[cnconsult.Translatable], getYesterday:function() {
  return this.tr('Yesterday');
}, getToday:function() {
  return this.tr('Today');
}, getTomorrow:function() {
  return this.tr('Tomorrow');
}, getKnowledges:function() {
  return this.tr('Knowledges');
}, getFiles:function() {
  return this.tr('Files');
}});
Ext.define('dilocsync.view.components.sidepanel.panels.DailyLaPanel', {extend:Ext.Container, xtype:'DailyLaPanel', statics:{getMenuTreeItems:function() {
  var children = [];
  var helper = dilocsync.util.Identity;
  var translatorBoy = dilocsync.util.TranslatorBoy;
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var driveMode = helper.getPageConfigByType(identity, 'drivemode');
  var checkNeedsFileList = function(_areaFiles) {
    var regexTestIfTagesLaFile = /^[\d]{4}[-][\d]{2}[-][\d]{2}_Tages\-La_(.*)\.pdf$/;
    var needsFileList = false;
    Ext.Object.each(_areaFiles, function(_fileName, _fileObject) {
      if (!regexTestIfTagesLaFile.test(_fileName)) {
        needsFileList = true;
        return false;
      }
    }, this);
    return needsFileList;
  };
  if (driveMode && driveMode.hasOwnProperty('config') && driveMode.config.hasOwnProperty('sidePanels')) {
    var dailyLa = Ext.Array.findBy(driveMode.config.sidePanels, function(_item) {
      return _item.type && _item.type === 'DailyLaPanel';
    });
    if (dailyLa && dailyLa.hasOwnProperty('config')) {
      var dailyLaConfig = dailyLa.config;
      var checker = Ext.create('dilocsync.core.DailyLaChecker', {basePath:dailyLaConfig.path, areas:dailyLaConfig.subscribedAreas, areaPrefix:dailyLaConfig.areaPrefix, filesNeedToBeThereUntil:dailyLaConfig.filesNeedToBeThereUntil});
      if (Ext.isArray(dailyLaConfig.subscribedAreas)) {
        var subscribedAreas = [].concat($jscomp.arrayFromIterable(dailyLaConfig.subscribedAreas));
        if (Ext.isArray(dailyLaConfig.additionalAreas)) {
          subscribedAreas.push.apply(subscribedAreas, $jscomp.arrayFromIterable(dailyLaConfig.additionalAreas));
        }
        Ext.Array.each(helper.filterDailyLaAreas(subscribedAreas), function(_area) {
          var areaChildren = [];
          var isGermanDailyLa = dailyLaConfig.subscribedAreas.includes(_area);
          if (isGermanDailyLa) {
            areaChildren.push({text:translatorBoy.getYesterday(), area:_area, id:'yesterday', config:Ext.apply({type:'DailyLaPanel'}, dailyLaConfig || {}), leaf:true}, {text:translatorBoy.getToday(), area:_area, id:'today', config:Ext.apply({type:'DailyLaPanel'}, dailyLaConfig || {}), leaf:true}, {text:translatorBoy.getTomorrow(), area:_area, id:'tomorrow', config:Ext.apply({type:'DailyLaPanel'}, dailyLaConfig || {}), leaf:true});
          }
          var almanacName = 'data/' + checker.getBasePath();
          var almanac = master.getAlmanacs()[almanacName];
          if (almanac) {
            var areaDirectory = almanac.getDirectoryForPath(_area);
            var areaFiles = areaDirectory ? areaDirectory.files : {};
            var needsFileList = checkNeedsFileList(areaFiles);
            if (needsFileList) {
              if (isGermanDailyLa) {
                areaChildren.push({itemId:'toggleFileListButton', iconCls:'x-fa fa-list-alt', config:{type:'FolderPanel', path:dailyLaConfig.path, subPath:areaDirectory.path, folderTitle:_area}, leaf:true});
              } else {
                areaChildren.push({text:translatorBoy.getFiles(), area:_area, id:'files_' + btoa(_area).replace(/\W+/g, ''), config:{type:'FolderPanel', path:dailyLaConfig.path, subPath:areaDirectory.path, folderTitle:_area}, leaf:true});
              }
            }
          }
          children.push({text:_area, area:_area, leaf:false, children:areaChildren});
        });
      }
    }
  }
  return children;
}, getNodeView:function(_sidePanel, _node) {
  var master = dilocsync.core.Master;
  var checker = Ext.create('dilocsync.core.DailyLaChecker', {basePath:_node.get('config').path, areas:_node.get('config').subscribedAreas, areaPrefix:_node.get('config').areaPrefix, filesNeedToBeThereUntil:_node.get('config').filesNeedToBeThereUntil});
  var area = _node.get('area');
  var nodeId = _node.get('id');
  var date = Ext.Date.format(checker['_' + nodeId], 'Y-m-d');
  var fileName = checker.getFileNameForAreaAndName(area, date);
  var path = checker.getFilePathForAreaAndDate(area, date);
  var viewer = _sidePanel.lookup('viewer');
  var viewModel = viewer.getViewModel();
  var record;
  var almanacName = 'data/' + checker.getBasePath();
  var almanac = master.getAlmanacs()[almanacName];
  var files = almanac.findFilesRecursively(fileName);
  if (files.length > 0) {
    record = new dilocsync.model.AlmanacEntry(files[0]);
    if (record && record.get('checksum') && record.get('fileType')) {
      path = master.devicePath('fs-data/' + record.get('checksum') + '.' + record.get('fileType'));
    }
  } else {
    record = new dilocsync.model.AlmanacEntry({name:'', path:'', fileType:''});
  }
  viewModel.set('name', fileName);
  viewModel.set('record', record);
  viewModel.set('path', path);
  return viewer;
}}});
Ext.define('dilocsync.view.components.sidepanel.panels.FavoritesPanel', {xtype:'FavoritesPanel', statics:{getMenuTreeItems:function() {
  return [];
}, getNodeView:function(_sidePanel, _node) {
  var view = _sidePanel.down('#favoritesList'), store = Ext.getStore('Favorites');
  if (!view) {
    view = Ext.create('dilocsync.view.components.FileList', {itemId:'favoritesList', store:store, listeners:{childtap:function(_list, _location) {
      _list.fireEvent('showfile', _location.record, _list);
    }}});
  }
  return view;
}}});
Ext.define('dilocsync.model.SearchResult', {extend:dilocsync.model.AlmanacEntry, fields:[{name:'from', type:'string', defaultValue:'fileNameSearch'}, {name:'onPage', type:'integer', defaultValue:0}, {name:'searchResultCount', type:'integer', defaultValue:0}], hasMany:[{name:'searchResults', model:'dilocsync.model.SearchResult', associationKey:'searchResults'}], proxy:{type:'memory'}});
Ext.define('dilocsync.view.components.filefolderpanel.FileFolderPanelModel', {extend:Ext.app.ViewModel, alias:'viewmodel.filefolderpanel', data:{path:null, searchQuery:''}, stores:{searchResultStore:{model:'dilocsync.model.SearchResult', sorters:'name', groupDir:'ASC'}}});
Ext.define('dilocsync.view.components.filedetails.FileDetailsModel', {extend:Ext.app.ViewModel, alias:'viewmodel.fileDetails', data:{record:null}});
Ext.define('dilocsync.view.components.filedetails.FileDetailsController', {extend:Ext.app.ViewController, alias:'controller.fileDetails', mixins:[cnconsult.Translatable], closeWindow:function() {
  this.up('window').close();
  this.close();
  this.destroy();
}, onBeforeShow:function() {
  var hiddenViewers = dilocsync.util.FileViewerHelper.hideVisibleFileViewers();
  this.getView().on('destroy', dilocsync.util.FileViewerHelper.showHiddenFileViewers, this, {args:[hiddenViewers]});
}});
Ext.define('dilocsync.view.components.filedetails.FileDetails', {extend:Ext.Dialog, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'fileDetails', viewModel:{type:'fileDetails'}, controller:'fileDetails', layout:{type:'vbox', align:'stretch'}, cls:'dilocsync-filedetails', closable:true, maskTapHandler:'destroy', responsiveConfig:{'phone':{width:'100%'}, 'tablet || desktop':{width:'50%', minHeight:250}}, listeners:{beforeshow:'onBeforeShow'}, initialize:function() {
  var record = this.getViewModel().get('record');
  this.setTitle(this.tr('File details'));
  this.setItems([{cls:'dilocsync-file-folder-list', tpl:['\x3cdiv class\x3d"{icon:this.iconCls} dilocsync-file-folder-list-icon"\x3e\x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-file-folder-list-item"\x3e', '\x3cdiv class\x3d"dilocsync-file-list-item-name"\x3e\x3cspan class\x3d"dilocsync-file-attribute"\x3e', this.tr('Title'), '\x3c/span\x3e: {title}\x3cbr\x3e\x3cspan class\x3d"dilocsync-file-attribute"\x3e', this.tr('Name'), '\x3c/span\x3e: {name}', '\x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-file-folder-list-item-size"\x3e', 
  '\x3ctpl if\x3d\'icon !\x3d\x3d "folder" \x26\x26 icon !\x3d\x3d "directory"\'\x3e', '\x3ctpl if\x3d\'size\'\x3e\x3cspan class\x3d"dilocsync-file-attribute"\x3e', this.tr('Size'), '\x3c/span\x3e: {size:this.formatBytes}\x3c/tpl\x3e', '\x3ctpl if\x3d\'filePath\'\x3e\x3cspan class\x3d"dilocsync-file-attribute"\x3e', this.tr('Path'), '\x3c/span\x3e: {filePath:this.formatPath}\x3c/tpl\x3e', '\x3c/tpl\x3e', '\x3ctpl if\x3d"validFrom || validTo" \x3e', '\x3cspan class\x3d"dilocsync-validity"\x3e', '\x3ctpl if\x3d"validFrom"\x3e', 
  '\x26nbsp;', this.tr('Valid from'), '\x26nbsp;', '{validFrom:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3ctpl if\x3d"validTo"\x3e', '\x26nbsp;', '\x3ctpl if\x3d"!validFrom"\x3e', this.tr('Valid'), '\x26nbsp;', '\x3c/tpl\x3e', this.tr('until'), '\x26nbsp;', '{validTo:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3c/span\x3e', '\x3c/tpl\x3e', '\x3c/div\x3e', {iconCls:function(_type) {
    return dilocsync.util.File.iconClsByType(_type);
  }, formatBytes:function(_bytes) {
    return dilocsync.util.File.formatBytes(_bytes);
  }, formatPath:function(_path) {
    var regExp = /.*\/\/data/g;
    return _path.replace(regExp, '');
  }}], data:record.getData()}, {xtype:'component', margin:'20 0 0 0', bind:{html:'\x3cb\x3e' + this.tr('Tags') + '\x3c/b\x3e:\x3cbr\x3e' + dilocsync.util.File.tagMarkup(Ext.Array.pluck(record.tags().getRange(), 'data'))}}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.filefolderpanel.FileFolderPanelController', {extend:Ext.app.ViewController, alias:'controller.filefolderpanel', mixins:[cnconsult.Translatable], config:{bufferedSearch:null}, init:function() {
  var master = dilocsync.core.Master;
  var syncEngine = master.getSyncEngine();
  var view = this.getView();
  var identity = master.getIdentity();
  var bufferedSearchDelay = identity.options.hasOwnProperty('bufferedSearchDelay') ? identity.options.bufferedSearchDelay : 100;
  this.groupStore();
  view.on('initialize', this.onViewInitialize, this);
  syncEngine.on('syncfinished', this.onSyncFinished, this);
  this.setBufferedSearch(Ext.Function.createBuffered(this.doSearch, bufferedSearchDelay, this));
}, groupStore:function(_tagSearch) {
  _tagSearch = _tagSearch === undefined ? false : _tagSearch;
  this.getStore('searchResultStore').setGrouper({groupFn:Ext.bind(function(_record) {
    if (_tagSearch) {
      return this.tr('File tag search results');
    } else {
      if (_record.get('from') === 'fileNameSearch') {
        return this.tr('File name search results');
      } else {
        return this.tr('Full text search results');
      }
    }
  }, this)});
}, onViewInitialize:function() {
  var store = this.loadFilesStore();
  var list = this.lookup('fileFolderList');
  if (list && store) {
    list.setStore(store);
  }
}, onSyncFinished:function(_success, _errorMessage, _syncReportAvailable, _reloadRequired, _syncReportDirectories) {
  if (_success) {
    var path = 'data/' + this.getViewModel().get('path') + '/';
    var syncReportDirectoryMatch = false;
    if (Ext.isArray(_syncReportDirectories)) {
      syncReportDirectoryMatch = Ext.Array.findBy(_syncReportDirectories, function(_item) {
        return _item.path === path;
      }, this);
    }
    if (!syncReportDirectoryMatch || syncReportDirectoryMatch && _syncReportAvailable) {
      var view = this.getView();
      var list = this.lookup('fileFolderList');
      var currentActiveNodePath;
      var newStore;
      var oldStore;
      var newAlmanac;
      var oldAlmanac;
      var node;
      if (list) {
        view.setMasked({xtype:'loadmask', message:this.tr('Updating files ...')});
        if (list.getActiveItem() && list.getActiveItem().getStore() && list.getActiveItem().getStore().getNode()) {
          currentActiveNodePath = list.getActiveItem().getStore().getNode().get('path');
        }
        oldStore = list.getStore();
        newStore = this.loadFilesStore();
        list.setStore(newStore);
        oldAlmanac = list.getAlmanac();
        newAlmanac = this.getAlmanac(this.getViewModel().get('path'));
        list.setAlmanac(newAlmanac);
        if (oldStore) {
          oldStore.destroy();
        }
        if (oldAlmanac) {
          oldAlmanac.destroy();
        }
        this.expandNodes(newStore, currentActiveNodePath);
        if (currentActiveNodePath) {
          node = newStore.findNode('path', currentActiveNodePath);
          if (node) {
            list.goToNode(node);
          }
        }
        Ext.defer(view.unmask, 500, view);
      }
    }
  }
}, updateViewStore:function() {
  var view = this.getView();
  var list = this.lookup('fileFolderList');
  var currentActiveNodePath;
  var newStore;
  var oldStore;
  var node;
  if (list) {
    view.setMasked({xtype:'loadmask', message:this.tr('Updating files ...')});
    if (list.getActiveItem() && list.getActiveItem().getStore() && list.getActiveItem().getStore().getNode()) {
      currentActiveNodePath = list.getActiveItem().getStore().getNode().get('path');
    }
    oldStore = list.getStore();
    newStore = this.loadFilesStore();
    list.setStore(newStore);
    if (oldStore) {
      oldStore.destroy();
    }
    this.expandNodes(newStore, currentActiveNodePath);
    if (currentActiveNodePath) {
      node = newStore.findNode('path', currentActiveNodePath);
      if (node) {
        list.goToNode(node);
      }
    }
    Ext.defer(view.unmask, 500, view);
  }
}, expandNodes:function(_store, _path) {
  if (_store && _path) {
    var sections = Ext.Array.clean(_path.split('/'));
    var currentPath = '';
    Ext.Array.each(sections, function(_pathSection) {
      var currentNode;
      currentPath = currentPath + '/' + _pathSection;
      currentNode = _store.findNode('path', currentPath);
      if (currentNode && !currentNode.isLeaf()) {
        currentNode.expand();
      }
    }, this);
  }
}, loadFilesStore:function() {
  var path = this.getViewModel().get('path');
  var subPath = this.getView().getSubPath();
  var almanac = this.getAlmanac(path);
  var basePath = '/';
  var store;
  if (subPath) {
    basePath += subPath;
  }
  if (almanac) {
    store = new dilocsync.store.Files(almanac, '', basePath);
    store.load();
  } else {
    store = false;
  }
  return store;
}, onSearchChange:function(_field, _value) {
  this.getBufferedSearch()(_field, _value);
}, doSearch:function(_field, _value) {
  var view = this.getView();
  var activeItem = view.getActiveItem();
  var activeItemReference = activeItem.getReference();
  var searchResultListReference = 'searchResultList';
  var searchResultList = this.lookup(searchResultListReference);
  var fileFolderListReference = 'fileFolderList';
  var fileFolderList = this.lookup(fileFolderListReference);
  var searchResultStore = this.getStore('searchResultStore');
  searchResultStore.removeAll();
  if (_value.length >= 3) {
    this.groupStore(_value.startsWith('#'));
    if (activeItemReference !== searchResultListReference) {
      view.setActiveItem(searchResultList);
    }
    searchResultList.setMasked({xtype:'loadmask', indicator:true, message:this.tr('Searching...')});
    if (this.getView().getFullTextSearch() && this.getView().getFullTextSearch().readyToSearch()) {
      this.searchWithFullTextSearch(_value);
    } else {
      this.filterAlmanacDirectory(_value);
      searchResultStore.sync();
      searchResultList.unmask();
    }
  } else {
    if (activeItemReference !== fileFolderListReference) {
      view.setActiveItem(fileFolderList);
    }
  }
}, searchWithFullTextSearch:function(_searchWord) {
  cnconsult.Logger.log({prefix:'FileFolderPanelController-\x3esearchWithFullTextSearch', message:'Start full indexed search for ' + _searchWord});
  this.getView().getFullTextSearch().search(_searchWord, this.onFullTextSearchFinished, this);
  cnconsult.Logger.log({prefix:'FileFolderPanelController-\x3esearchWithFullTextSearch', message:'Start file name search for ' + _searchWord});
  this.filterAlmanacDirectory(_searchWord);
}, onFullTextSearchFinished:function(_fullTextSearchResults) {
  cnconsult.Logger.log({prefix:'FileFolderPanelController-\x3eonFullTextSearchFinished', message:'Full text search results', dump:_fullTextSearchResults});
  if (_fullTextSearchResults && _fullTextSearchResults.length > 0) {
    var fullTextSearchResults = [];
    var folderPath = this.getViewModel().get('path');
    var subPath = this.getView().getSubPath();
    var almanacPath;
    if (subPath) {
      folderPath += subPath;
    }
    almanacPath = folderPath;
    if (almanacPath.endsWith('/')) {
      almanacPath = 'data/' + almanacPath.slice(0, -1);
    }
    for (var fullTextSearchResultKey in _fullTextSearchResults) {
      if (_fullTextSearchResults.hasOwnProperty(fullTextSearchResultKey) && _fullTextSearchResults[fullTextSearchResultKey].filePath.indexOf(folderPath) !== -1) {
        var almanac = dilocsync.core.Master.getAlmanacForPath(almanacPath);
        var fullTextSearchResult = _fullTextSearchResults[fullTextSearchResultKey];
        var filePath = fullTextSearchResult.filePath.replace(almanacPath, '');
        var file = almanac.getFileByPath(filePath);
        var searchResultObject = {name:dilocsync.util.File.basename(fullTextSearchResult.filePath), path:fullTextSearchResult.filePath, icon:dilocsync.util.File.extension(fullTextSearchResult.filePath), onPage:fullTextSearchResult.pageIndex, from:'fullTextSearch', searchResultCount:0, searchResults:[]};
        if (file) {
          Ext.apply(searchResultObject, {title:file.title, checksum:file.checksum, size:file.size, tags:file.tags});
        }
        var filePathExistsObject = fullTextSearchResults.find(function(_object) {
          return _object.path === fullTextSearchResult.filePath;
        });
        if (filePathExistsObject) {
          if (filePathExistsObject.searchResults.length === 0) {
            filePathExistsObject.searchResults.push(Ext.clone(filePathExistsObject));
          }
          filePathExistsObject.searchResults.push(searchResultObject);
          filePathExistsObject.searchResultCount = filePathExistsObject.searchResults.length;
        } else {
          fullTextSearchResults.push(searchResultObject);
        }
      }
    }
    this.getStore('searchResultStore').add(fullTextSearchResults);
  }
  this.lookup('searchResultList').unmask();
}, filterAlmanacDirectory:function(_searchQuery) {
  var path = this.getViewModel().get('path');
  var master = dilocsync.core.Master;
  var almanac = this.getAlmanac(path);
  var almanacDirectory;
  if (almanac) {
    var subPath = this.getView().getSubPath();
    if (subPath) {
      almanacDirectory = almanac.getDirectoryForPath(subPath);
    } else {
      almanacDirectory = almanac.getDirectoryForPath('/');
    }
    if (almanacDirectory) {
      var results = almanacDirectory.findFilesRecursively(_searchQuery);
      var store = this.getStore('searchResultStore');
      store.removeAll();
      if (results.length > 0) {
        store.add(results);
      }
      store.sync();
    }
  } else {
    cnconsult.Logger.log({prefix:'FileFolderPanelController-\x3efilterAlmanacDirectory', message:'No almanac found for path! Cannot filter Almanac entries for path: ' + path, level:'error'});
  }
}, onSearchResultItemTap:function(_list, _location) {
  var onPage = 0;
  var record = _location.record;
  if (record.get('searchResultCount') > 0) {
    if (record.searchResults().getCount() === 0) {
      record.searchResults().add(record.data.searchResults);
    }
    _list.setStore(record.searchResults());
    this.lookup('searchResultTitlebar').setMargin('0 0 0');
    this.lookup('searchField').hide();
    this.lookup('subListToolbar').show();
  } else {
    if (record && record.get('onPage') && Ext.isNumber(record.get('onPage'))) {
      onPage = record.get('onPage') + 1;
    }
    this.showFile(record, _list, onPage);
  }
}, onSearchResultItemDoubleTap:function(_list, _location) {
  var record = _location.record;
  if (record.get('searchResultCount') > 0) {
    if (record.searchResults().getCount() === 0) {
      record.searchResults().add(record.data.searchResults);
    }
    _list.setStore(record.searchResults());
    this.lookup('searchResultTitlebar').setMargin('0 0 0');
    this.lookup('searchField').hide();
    this.lookup('subListToolbar').show();
  } else {
    this.openFile(record, _list);
  }
}, onFileTap:function(_fileFolderList, _subList, _index, _target, _record) {
  var onPage = 0;
  if (_subList.longPressed) {
    _subList.longPressed = false;
  } else {
    if (_record && _record.get('onPage') && Ext.isNumber(_record.get('onPage'))) {
      onPage = _record.get('onPage');
    }
    this.showFile(_record, _subList, onPage);
  }
}, onFileDoubleTap:function(_fileFolderList, _subList, _index, _target, _record) {
  if (!_record.isLeaf()) {
    return;
  }
  var details = Ext.create('dilocsync.view.components.filedetails.FileDetails', {viewModel:{data:{record:_record}}});
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.filefolderpanel.FileFolderPanelController', src:'Dokumente', action:'ZeigeDateiDetails', trackedAt:new Date});
  details.show();
}, showFile:function(_record, _view, _onPage) {
  _view = _view || this.getView();
  _onPage = _onPage || 0;
  this.getView().fireEvent('showfile', _record, _view, _onPage);
}, openFile:function(_record, _view) {
  _view = _view || this.getView();
  this.getView().fireEvent('openfile', _record, _view);
}, onListChange:function() {
  var almanacPath = this.getViewModel().get('path');
  if (!(almanacPath && almanacPath.startsWith('trainschedules'))) {
    var listEl = this.lookup('fileFolderList').el;
    var listWidth = listEl.getWidth();
    var elements = listEl.select('.dilocsync-file-list-item-name');
    elements.setWidth(listWidth - 85);
  }
}, onFullTextSearchInitialized:function() {
  this.lookup('fullTextSearchState').hide();
}, backToSearchList:function() {
  var me = this;
  var store = this.getStore('searchResultStore');
  store.clearGrouping();
  me.getView().down('searchresultlist').setStore(store);
  this.lookup('searchResultTitlebar').setMargin('0 0 36px');
  me.lookup('searchField').show();
  me.lookup('subListToolbar').hide();
  me.groupStore();
}, getAlmanac:function(_path) {
  var master = dilocsync.core.Master;
  var almanac;
  if (!Ext.String.startsWith(_path, 'data/') && !Ext.String.startsWith(_path, 'userfilebox/') && !Ext.String.startsWith(_path, 'forms') && !Ext.String.startsWith(_path, 'trainschedules')) {
    _path = 'data/' + _path;
  }
  if (Ext.String.endsWith(_path, '/')) {
    _path = _path.substring(0, _path.length - 1);
  }
  almanac = master.getAlmanacs()[_path];
  return almanac;
}});
Ext.define('dilocsync.view.components.SearchResultList', {extend:Ext.List, xtype:'searchresultlist', mixins:[cnconsult.Translatable], cls:'dilocsync-search-result-list', initialize:function() {
  this.setItemTpl(['\x3cdiv class\x3d"{icon:this.iconCls} dilocsync-search-result-list-icon"\x3e\x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-search-result-list-item"\x3e', '\t\x3cdiv class\x3d"dilocsync-file-list-item-name"\x3e\x3ctpl if\x3d"title"\x3e{title}\x3ctpl else\x3e{name}\x3c/tpl\x3e\x3ctpl if\x3d\'searchResultCount\'\x3e\x3cspan class\x3d"dilocsync-list-item-result-count"\x3e ({searchResultCount})\x3c/span\x3e\x3c/tpl\x3e\x3c/div\x3e', '\x3ctpl if\x3d"validFrom || validTo" \x3e', '\x3cspan class\x3d"dilocsync-validity"\x3e', 
  '\x3ctpl if\x3d"validFrom"\x3e', '\x26nbsp;', this.tr('Valid from'), '\x26nbsp;', '{validFrom:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3ctpl if\x3d"validTo"\x3e', '\x26nbsp;', '\x3ctpl if\x3d"!validFrom"\x3e', this.tr('Valid'), '\x26nbsp;', '\x3c/tpl\x3e', this.tr('until'), '\x26nbsp;', '{validTo:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3c/span\x3e', '\x3c/tpl\x3e', '\t\x3cdiv class\x3d"dilocsync-search-result-list-item-path"\x3e{path:this.formatPath}\x3c/div\x3e', '\t\x3ctpl if\x3d\'onPage \x26\x26 searchResultCount \x3d\x3d 0\'\x3e\x3cdiv class\x3d"dilocsync-search-result-list-item-path"\x3e{onPage:this.formatOnPage}\x3c/div\x3e\x3c/tpl\x3e', 
  '   \x3ctpl if\x3d"tags"\x3e\x3cdiv class\x3d"dilocsync-file-folder-list-item-tags"\x3e{tags:this.getTags}\x3c/div\x3e\x3c/tpl\x3e', '\x3c/div\x3e', {iconCls:function(_type) {
    return dilocsync.util.File.iconClsByType(_type);
  }, getTags:function(_tags) {
    return dilocsync.util.File.tagMarkup(_tags);
  }, formatPath:Ext.Function.bind(function(_path) {
    var path = dilocsync.util.File.dirname(_path);
    path = path.replace('/data/', '');
    path = path.replace('/data', '');
    path = path.replace('data/', '');
    if (path.startsWith('userfilebox/')) {
      path = this.tr('User file box');
    }
    if (path.length > 53) {
      path = '...' + path.substring(path.length - 50, path.length);
    }
    return path;
  }, this), formatOnPage:Ext.bind(function(_pageNumber) {
    return this.tr('Page: %1').arg(_pageNumber + 1);
  }, this)}]);
  this.setEmptyText(this.tr('Currently there are no items.'));
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.FileFolderList', {extend:Ext.NestedList, xtype:'filefolderlist', mixins:[cnconsult.Translatable], cls:'dilocsync-file-folder-list', displayField:'name', useTitleAsBackText:false, config:{indicateUnreadFiles:false, almanac:null}, initialize:function() {
  var me = this;
  this.setListConfig({emptyText:this.tr('Currently there are no items.'), itemTpl:['\x3cdiv class\x3d"{icon:this.iconCls} dilocsync-file-folder-list-icon"\x3e\x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-file-folder-list-item"\x3e', '\x3ctpl if\x3d\'this.indicateUnreadFiles() \x26\x26 icon !\x3d\x3d "folder" \x26\x26 !read\'\x3e', '\x3cdiv class\x3d"dilocsync-file-list-item-name dilocsync-list-item-unread"\x3e\x3ctpl if\x3d"title"\x3e{title}\x3ctpl else\x3e{name}\x3c/tpl\x3e\x3cspan class\x3d"dilocsync-list-item-unread-indicator"\x3e\x3c/span\x3e\x3c/div\x3e', 
  '\x3ctpl elseif\x3d\'this.indicateUnreadFiles() \x26\x26 icon \x3d\x3d\x3d "folder" \x26\x26 this.subFoldersWithUnreadFiles(path)\'\x3e', '\x3cdiv class\x3d"dilocsync-file-folder-list-folder-name-height dilocsync-file-list-item-name"\x3e\x3ctpl if\x3d"title"\x3e{title}\x3ctpl else\x3e{name}\x3c/tpl\x3e\x3cspan class\x3d"dilocsync-list-item-unread-indicator"\x3e\x3c/span\x3e\x3c/div\x3e', '\x3ctpl else\x3e', "\x3cdiv class\x3d\"{[values.icon \x3d\x3d\x3d 'folder' || values.icon \x3d\x3d\x3d 'directory' ? 'dilocsync-file-folder-list-folder-name-height' : '']} dilocsync-file-list-item-name\"\x3e\x3ctpl if\x3d\"title\"\x3e{title}\x3ctpl else\x3e{name}\x3c/tpl\x3e\x3c/div\x3e", 
  '\x3c/tpl\x3e', '\x3cdiv class\x3d"dilocsync-file-folder-list-item-size"\x3e', '\x3ctpl if\x3d\'icon !\x3d\x3d "folder" \x26\x26 icon !\x3d\x3d "directory"\'\x3e', "\x3ctpl if\x3d'size'\x3e{size:this.formatBytes}\x3c/tpl\x3e", "\x3ctpl if\x3d'filePath'\x3e{filePath:this.formatPath}\x3c/tpl\x3e", '\x3c/tpl\x3e', '\x3ctpl if\x3d"validFrom || validTo" \x3e', '\x3cspan class\x3d"dilocsync-validity"\x3e', '\x3ctpl if\x3d"validFrom"\x3e', '\x26nbsp;', this.tr('Valid from'), '\x26nbsp;', '{validFrom:date("d.m.Y")}', 
  '\x3c/tpl\x3e', '\x3ctpl if\x3d"validTo"\x3e', '\x26nbsp;', '\x3ctpl if\x3d"!validFrom"\x3e', this.tr('Valid'), '\x26nbsp;', '\x3c/tpl\x3e', this.tr('until'), '\x26nbsp;', '{validTo:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3c/span\x3e', '\x3c/tpl\x3e', '\x3ctpl if\x3d"openFileOnPage"\x3e', '\x3cspan class\x3d"dilocsync-validity"\x3e', this.tr('Page', this.xtype !== 'filefolderlist'), '\x26nbsp;', '{openFileOnPage}', '\x3c/span\x3e', '\x3c/tpl\x3e', '\x3c/div\x3e', '\x3ctpl if\x3d"tags"\x3e', '\x3cdiv class\x3d"dilocsync-file-folder-list-item-tags"\x3e{tags:this.getTags}\x3c/div\x3e', 
  '\x3c/tpl\x3e', {getTags:function(_tags) {
    return dilocsync.util.File.tagMarkup(_tags);
  }, iconCls:function(_type) {
    return dilocsync.util.File.iconClsByType(_type);
  }, formatBytes:function(_bytes) {
    return dilocsync.util.File.formatBytes(_bytes);
  }, formatPath:function(_path) {
    var regExp = /.*\/\/data/g;
    return _path.replace(regExp, '');
  }, indicateUnreadFiles:function() {
    return me.getIndicateUnreadFiles();
  }, subFoldersWithUnreadFiles:function(_path) {
    var parentDirectory = me.getAlmanac().getDirectoryForPath(_path);
    var countUnreadFilesRecursively = parentDirectory ? parentDirectory.countUnreadFilesRecursively() : 0;
    var markUnread = false;
    if (Ext.isDefined(countUnreadFilesRecursively) && countUnreadFilesRecursively > 0) {
      markUnread = true;
    }
    return markUnread;
  }}]});
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.filefolderpanel.FileFolderPanel', {extend:Ext.Panel, mixins:[cnconsult.Translatable], xtype:'filefolderpanel', viewModel:{type:'filefolderpanel'}, controller:'filefolderpanel', layout:{type:'card'}, config:{path:null, subPath:null, folderTitle:null, indicateUnreadFiles:false, fullTextSearch:null}, setPath:function(_path) {
  this.callParent(arguments);
  this.getViewModel().set('path', _path);
}, updateSubPath:function() {
  this.getController().updateViewStore();
}, initialize:function() {
  var title = this.getFolderTitle() ? this.getFolderTitle() : this.tr('Explorer');
  this.setItems([{xtype:'filefolderlist', reference:'fileFolderList', indicateUnreadFiles:this.getIndicateUnreadFiles(), almanac:this.getController().getAlmanac(this.getViewModel().get('path')), title:title, toolbar:{docked:'top', xtype:'titlebar', margin:'0 0 36 0'}, listeners:{leafitemtap:'onFileTap', itemdoubletap:'onFileDoubleTap', listchange:'onListChange'}}, {xtype:'container', reference:'searchResultList', layout:'fit', items:[{docked:'top', xtype:'titlebar', reference:'searchResultTitlebar', 
  margin:'0 0 36 0', title:this.tr('Search results'), inline:true}, {xtype:'searchresultlist', listeners:{childtap:'onSearchResultItemTap', childdoubletap:'onSearchResultItemDoubleTap'}, bind:{store:'{searchResultStore}'}}, {docked:'top', xtype:'toolbar', hidden:true, reference:'subListToolbar', ui:'actions-toolbar', defaults:{ui:'toolbar-actions'}, items:[{text:this.tr('Back'), iconCls:'x-fa fa-chevron-left', handler:'backToSearchList'}]}, {xtype:'component', docked:'bottom', reference:'fullTextSearchState', 
  height:'20px', hidden:true, html:'\x3cdiv class\x3d"fullTextSearchState"\x3e' + this.tr('Initializing full text search...') + '\x3c/div\x3e'}]}, this.searchFieldConfig()]);
  this.callParent(arguments);
  this.setFullTextSearch(dilocsync.core.Master.getFullTextSearch());
  if (this.getFullTextSearch()) {
    if (!this.getFullTextSearch().readyToSearch()) {
      this.lookup('fullTextSearchState').show();
    }
    var me = this;
    this.getFullTextSearch().on('databaseInitialized', 'onFullTextSearchInitialized', me.getController());
  }
}, searchFieldConfig:function() {
  return {xtype:'searchfield', reference:'searchField', top:52, width:'100%', focusable:true, cls:'dilocsync-file-folder-list-search', docked:'top', listeners:{change:{fn:'onSearchChange', buffer:500}}, bind:{value:'{searchQuery}'}};
}});
Ext.define('dilocsync.view.components.sidepanel.panels.FolderPanel', {extend:dilocsync.view.components.filefolderpanel.FileFolderPanel, xtype:'FolderPanel', statics:{getMenuTreeItems:function() {
  var helper = dilocsync.util.Identity;
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var pages = helper.filterPagesByType(identity, 'folder');
  var children = [];
  Ext.Array.each(pages, function(_page) {
    children.push({text:_page.config.title, config:{type:'FolderPanel', path:_page.config.path, folderTitle:_page.config.title}, leaf:true});
  });
  return children;
}, getNodeView:function(_sidePanel, _node) {
  var view = _sidePanel.down(_node.get('config').type + '[nodeId\x3d' + _node.getId() + ']');
  if (!view) {
    view = Ext.apply({xtype:_node.get('config').type, nodeId:_node.getId()}, _node.get('config'));
  }
  return view;
}}});
Ext.define('dilocsync.view.components.sidepanel.panels.ImportsPanel', {xtype:'ImportsPanel', statics:{getMenuTreeItems:function() {
  return [];
}, getNodeView:function(_sidePanel, _node) {
  var view = _sidePanel.down('#importsList'), store = Ext.getStore('Imports');
  if (!view) {
    view = Ext.create('dilocsync.view.components.FileList', {itemId:'importsList', store:store, listeners:{childtap:function(_list, _location) {
      _list.fireEvent('showfile', _location.record, _list);
    }}, plugins:{listswiper:{defaults:{ui:'action', width:48}, right:[{iconCls:'x-fa fa-trash', ui:'alt decline', commit:'onDeleteImportedDocument'}]}}});
  }
  return view;
}}});
Ext.define('dilocsync.util.Knowledges', {singleton:true, config:{activePath:null, viewerState:null}, constructor:function(config) {
  Ext.apply(this, config);
  this.initConfig(config);
}, createAlmanacFromKnowledgeAlmanacs:function(_basePath) {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var almanacsInfo = storage.get('core:almanacs');
  var basePath = _basePath;
  var almanacData = {directories:{}, files:{}};
  var almanac;
  Ext.Array.each(almanacsInfo, function(_almanacInfo) {
    if (_almanacInfo.path.indexOf(basePath) !== -1) {
      var knowledgePath = _almanacInfo.path.substring(basePath.length);
      if (knowledgePath) {
        var directories = Ext.Array.clean(knowledgePath.split('/'));
        var lastIndex = directories.length - 1;
        var currentDirectory = almanacData.directories;
        Ext.Array.each(directories, function(_directory, _index) {
          if (!currentDirectory.hasOwnProperty(_directory)) {
            currentDirectory[_directory] = {directories:{}, files:{}};
          }
          if (_index === lastIndex) {
            currentDirectory[_directory] = storage.get('core:almanac:' + _almanacInfo.path, {directories:{}, files:{}});
          } else {
            currentDirectory = currentDirectory[_directory].directories;
          }
        }, this);
      }
    }
  }, this);
  return Ext.create('dilocsync.core.Almanac', almanacData);
}, persistViewState:function(_activePath, _viewerViewState) {
  this.setActivePath(_activePath);
  this.setViewerState(_viewerViewState);
}});
Ext.define('dilocsync.view.components.sidepanel.panels.KnowledgePanel', {extend:dilocsync.view.components.filefolderpanel.FileFolderPanel, xtype:'KnowledgePanel', statics:{getMenuTreeItems:function() {
  return [];
}, getNodeView:function(_sidePanel, _node) {
  var translatorBoy = dilocsync.util.TranslatorBoy;
  var config = _node.get('config');
  var view = _sidePanel.down('#knowledgesList');
  if (!view) {
    view = Ext.widget('KnowledgePanel', {path:config.basePath});
    var list = view.down('filefolderlist');
    list.setTitle(translatorBoy.getKnowledges());
    list.setMasked(false);
  }
  return view;
}}});
Ext.define('dilocsync.view.components.sidepanel.panels.WebsitesPanel', {extend:Ext.Container, xtype:'WebsitesPanel', statics:{getMenuTreeItems:function() {
  return [];
}, getNodeView:function(_sidePanel, _node) {
  var view = _sidePanel.down('website');
  if (!view) {
    view = Ext.create('dilocsync.view.components.sidepanel.components.Websites');
  }
  return view;
}}});
Ext.define('dilocsync.view.components.sidepanel.panels.WorkFoldersPanel', {extend:Ext.Container, xtype:'WorkFoldersPanel', statics:{getMenuTreeItems:function() {
  return [];
}, getNodeView:function(_sidePanel, _node) {
  var view = _sidePanel.down('#dossiersList');
  var store;
  if (!view) {
    store = Ext.getStore('Dossiers');
    view = Ext.create('dilocsync.view.components.dossier.list.List', {listeners:{leafitemtap:function(_fileFolderList, _subList, _index, _target, _record) {
      _fileFolderList.fireEvent('showfile', _record, _fileFolderList, _record.get('openFileOnPage'));
    }}});
    view.setStore(store);
  }
  return view;
}}});
Ext.define('dilocsync.view.components.sidepanel.SidePanel', {extend:Ext.Panel, xtype:'sidepanel', mixins:[cnconsult.Translatable], viewModel:{type:'sidepanel'}, controller:'sidepanel', listeners:{resize:'onResize'}, layout:'card', initialize:function() {
  this.callParent();
  this.add([{xtype:'horizontaltreemenu', reference:'menu', docked:'top', bind:{store:'{treeMenuItems}'}, listeners:{leafitemtap:'onLeafItemTap', childtap:'closeViewer', aftercreatemenu:'onAfterCreateMenu'}}, {xtype:'container', cls:'dilocsync-sidepanel-help', html:this.tr('Please choose from the menu above to fill this side of the view!')}]);
}});
Ext.define('dilocsync.view.pages.drivemode.DriveMode', {extend:dilocsync.view.pages.Base, xtype:'drivemode', controller:'drivemode', cls:'dilocsync-drivemode', layout:{type:'hbox', align:'stretch'}, getFileViewerComponent:function(_panel, _primary) {
  var me = this;
  var controller = this.getController();
  var fileViewer = _primary ? dilocsync.util.FileViewerHelper.getPrimary() : dilocsync.util.FileViewerHelper.getSecondary();
  return {xtype:'fileviewer', fileViewer:fileViewer, reference:'viewer', listeners:{downloadOnDemand:Ext.bind(controller.downloadOnDemand, me)}, scope:me, additionalToolbarItems:[{xtype:'button', itemId:'expandButton', iconCls:'x-fa fa-window-maximize', handler:'toggleExpandViewer', scope:controller}, '-\x3e', {xtype:'button', itemId:'closeButton', iconCls:'x-fa fa-times', handler:'closeViewer', scope:_panel.getController()}]};
}, getExternalFileViewerComponent:function() {
  return {xtype:'externalfileopen', reference:'viewer', closable:true};
}, initialize:function() {
  var me = this;
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  var firstPanel = Ext.widget('sidepanel', {flex:1, reference:'firstpanel', resizable:{split:true, edges:'east', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, listeners:{beforeresizedragstart:'hideViewers', resizedragend:'showViewers'}});
  var secondPanel = Ext.widget('sidepanel', {flex:1, reference:'secondpanel'});
  var onlyExternalFileOpen = dilocsync.util.Platform.supportsOnlyExternalFileOpen();
  if (onlyExternalFileOpen) {
    firstPanel.add(this.getExternalFileViewerComponent(firstPanel));
    secondPanel.add(this.getExternalFileViewerComponent(secondPanel));
  } else {
    firstPanel.add(this.getFileViewerComponent(firstPanel, true));
    secondPanel.add(this.getFileViewerComponent(secondPanel, false));
  }
  this.setItems([firstPanel, {xtype:'panel', flex:1, layout:{type:'vbox', align:'stretch'}, items:[secondPanel, {xtype:'digitalorder', reference:'digitalorder', flex:1, hidden:true, resizable:{split:true, edges:'north'}, listeners:{beforeresizedragstart:'hideSecondViewer', resizedragend:'showViewers'}}]}]);
  this.callParent();
  var eastResizerListener = function() {
    firstPanel.getResizable().getEdge('east').on({'doubletap':{fn:function() {
      me.getController().hideViewers();
      me.setLayout('vbox');
      firstPanel.setFlex(1);
      firstPanel.setWidth('auto');
      firstPanel.getResizable().setEdges('south');
      southResizerListener();
      me.getController().showViewers();
    }, single:true}});
  };
  var southResizerListener = function() {
    firstPanel.getResizable().getEdge('south').on({'doubletap':{fn:function() {
      me.getController().hideViewers();
      me.setLayout('hbox');
      firstPanel.setFlex(1);
      firstPanel.setHeight('auto');
      firstPanel.getResizable().setEdges('east');
      eastResizerListener();
      me.getController().showViewers();
    }, single:true}});
  };
  eastResizerListener();
}});
Ext.define('dilocsync.view.pages.drivemode.DriveModeController', {extend:dilocsync.view.pages.BaseController, alias:'controller.drivemode', control:{'filelist, filefolderlist, filefolderpanel':{showfile:'checkExpandState'}, 'sidepanel':{closeviewer:'onCloseViewer'}}, config:{viewerExpanded:false, hiddenViewers:[]}, init:function() {
  Ext.Viewport.on('orientationchange', this.updateResizeableSizes, this);
  this.getView().on('added', function(_view) {
    _view.lookupViewModel().bind('{digitalOrderStarted}', function(_value) {
      _view.lookup('digitalorder').setHeight(null);
      _view.lookup('digitalorder').setHidden(!_value);
    });
    _view.lookupViewModel().bind('{digitalOrderUserRole}', function(_value) {
      _view.lookup('digitalorder').getViewModel().set('userRole', _value);
    });
  });
}, updateResizeableSizes:function() {
  var viewer = this.lookup('firstpanel');
  var resizeable = viewer.getResizable();
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  resizeable.setMinSize([minResizeWidth, null]);
  resizeable.setMaxSize([maxResizeWidth, null]);
}, toggleExpandViewer:function(_button) {
  var expanded = !this.getViewerExpanded();
  this.setExpandViewerMode(expanded);
}, onCloseViewer:function(view) {
  this.setExpandViewerMode(false);
}, setExpandViewerMode:function(expanded) {
  var sidePanels = this.getView().query('sidepanel');
  this.setViewerExpanded(expanded);
  Ext.Array.each(sidePanels, function(_sidePanel) {
    if (_sidePanel.down('#expandButton')) {
      _sidePanel.down('#expandButton').setIconCls(expanded ? 'x-fa fa-window-minimize' : 'x-fa fa-window-maximize');
    }
    if (_sidePanel.down('fileviewer') && _sidePanel.down('fileviewer').isVisible()) {
      _sidePanel.down('fileviewer').setFlex(1);
    }
    _sidePanel.down('horizontaltreemenu').setHidden(expanded);
  }, this);
  Ext.Viewport.down('[reference\x3dbottomToolbar]').setHidden(expanded);
  this.lookup('digitalorder').getViewModel().set('expanded', expanded);
}, checkExpandState:function(_record, _view) {
  var sidePanel = _view.up('sidepanel');
  if (this.getViewerExpanded()) {
    sidePanel.down('horizontaltreemenu').setHidden(true);
  }
}, hideViewers:function() {
  this.setHiddenViewers(dilocsync.util.FileViewerHelper.hideVisibleFileViewers());
}, hideSecondViewer:function() {
  var fileViewer = this.lookup('secondpanel').down('fileviewer');
  if (fileViewer) {
    var fvController = fileViewer.getController();
    if (fvController.getIsVisible()) {
      fvController.hideViewer();
      this.setHiddenViewers([fileViewer]);
    }
  }
}, showViewers:function() {
  dilocsync.util.FileViewerHelper.showHiddenFileViewers(this.getHiddenViewers());
  this.setHiddenViewers([]);
}});
Ext.define('dilocsync.view.pages.dynamicschedule.DynamicScheduleController', {extend:dilocsync.view.pages.BaseController, alias:'controller.dynamicschedule', init:function() {
}, onHide:function() {
  this.callParent(arguments);
  var appMain = this.getView().up('app-main');
  if (!appMain) {
    return;
  }
  var toolbar = appMain.lookup('bottomToolbar');
  if (!toolbar) {
    return;
  }
  toolbar.show();
}, onShow:function() {
  this.callParent(arguments);
  var appMain = this.getView().up('app-main');
  if (!appMain) {
    return;
  }
  var toolbar = appMain.lookup('bottomToolbar');
  if (!toolbar) {
    return;
  }
  toolbar.hide();
}});
Ext.define('dilocsync.view.pages.dynamicschedule.DynamicSchedule', {extend:dilocsync.view.pages.Base, xtype:'dynamicschedule', controller:'dynamicschedule', cls:'dilocsync-dynamicschedule', listeners:{'hide':'onHide', 'show':'onShow'}, initialize:function() {
  var dynamicScheduleAddress = 'https://cs.diloc.de/%C3%84d91la0X25jnZal3Oan5a3/schedule';
  var dynamicScheduleFrame = Ext.create('dilocsync.view.components.Iframe', {src:dynamicScheduleAddress, height:'100%', width:'100%'});
  var sideMenuButton = {xtype:'button', iconCls:'x-fa fa-angle-double-right', style:{position:'absolute', left:0, top:'50%', background:'transparent no-repeat', outline:'none'}, handler:function() {
    Ext.Viewport.showMenu('left');
  }};
  this.setItems([dynamicScheduleFrame, sideMenuButton]);
  this.callParent();
}});
Ext.define('dilocsync.view.pages.embeddedwebpage.EmbeddedWebPage', {extend:dilocsync.view.pages.Base, xtype:'embeddedwebpage', controller:'embeddedwebpage', scrollable:true, initialize:function() {
  this.setItems([{xtype:'component', height:'100%', flex:1, reference:'iframe', cls:'iframewebpage', html:'\x3cdiv style\x3d"overflow:scroll;-webkit-overflow-scrolling:touch;"\x3e\x3ciframe class\x3d"embedded-web-page-iframe" src\x3d"' + this.pageConfig.url + '"\x3e\x3c/iframe\x3e\x3c/div\x3e'}]);
  this.setIframeWidthAndHeigth();
  this.callParent(arguments);
}, setIframeWidthAndHeigth:function() {
  var elementWidth = Ext.Viewport.el.getWidth();
  var elementHeight = Ext.Viewport.el.getHeight() - Ext.Viewport.down('menusTabmenu').el.getHeight();
  var el = this.lookup('iframe').el;
  el.select('.embedded-web-page-iframe').setHeight(elementHeight);
  el.select('.embedded-web-page-iframe').setWidth(elementWidth);
}});
Ext.define('dilocsync.view.pages.embeddedwebpage.EmbeddedWebPageController', {extend:Ext.app.ViewController, alias:'controller.embeddedwebpage', onHide:function() {
}, onShow:function() {
}});
Ext.define('dilocsync.view.pages.favorites.FavoritesModel', {extend:Ext.app.ViewModel, alias:'viewmodel.favorites', stores:{}, data:{}});
Ext.define('dilocsync.view.pages.favorites.FavoritesController', {extend:dilocsync.view.pages.BaseController, alias:'controller.favorites', mixins:[cnconsult.Translatable], init:function() {
  Ext.Viewport.on('orientationchange', this.updateResizeableSizes, this);
  this.groupStore();
}, groupStore:function() {
  Ext.getStore('Favorites').setGrouper({groupFn:Ext.bind(function(_record) {
    if (_record.get('group') === 'remote') {
      return this.tr('Remote');
    } else {
      return this.tr('Local');
    }
  }, this)});
}, onShow:function() {
  var favoritesStore = Ext.getStore('Favorites');
  var viewer = this.lookup('viewer');
  var viewModel = viewer.lookupViewModel();
  var record = viewModel.get('record');
  if (record) {
    if (favoritesStore.findRecord('uuid', record.get('uuid')) || favoritesStore.findRecord('path', record.get('path'))) {
      this.callParent(arguments);
    } else {
      viewModel.set({name:'-', record:null, path:null, onPageNumber:0, fileExists:true});
    }
  }
}});
Ext.define('dilocsync.view.pages.favorites.Favorites', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'favorites', controller:'favorites', viewModel:{type:'favorites'}, responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, getDesktopViewer:function() {
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    return {xtype:'externalfileopen', reference:'viewer', listeners:{resize:'onResize'}, resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, flex:2};
  }
  return {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', listeners:{resize:'onResize'}, resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, flex:2};
}, initialize:function() {
  var elementWidth = screen.width;
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([{xtype:'filelist', store:Ext.getStore('Favorites'), items:[{xtype:'titlebar', title:this.tr('Favorites'), docked:'top'}], reference:'listPanel', listeners:{childtap:'showViewerFromList'}}, {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', listeners:{back:'showList'}}]);
  } else {
    this.setItems([{xtype:'filelist', store:Ext.getStore('Favorites'), items:[{xtype:'titlebar', title:this.tr('Favorites'), docked:'top', defaults:{ui:'toolbar-button'}, items:[{itemId:'maximize', iconCls:'x-fa fa-expand', align:'right', handler:'maximizeListPanel'}, {itemId:'minimize', iconCls:'x-fa fa-compress', align:'right', handler:'minimizeListPanel', hidden:true}]}], reference:'listPanel', listeners:{childtap:'onShowFileFromList', childoubletap:'onOpenFileFromList'}, flex:1}, this.getDesktopViewer()]);
  }
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.folder.FolderController', {extend:dilocsync.view.pages.BaseController, alias:'controller.folder', mixins:[cnconsult.Translatable], init:function() {
  Ext.Viewport.on('orientationchange', this.updateResizeableSizes, this);
  this.getView().on('activate', function() {
    if (this.getView().down('filefolderpanel').rendered) {
      this.getView().down('filefolderpanel').getController().updateViewStore();
    }
  }, this);
}, showFile:function(_record) {
  var viewer = this.lookup('viewer');
  this.callParent(arguments);
  if (!viewer.isVisible()) {
    var button = this.lookup('listPanel').down('filefolderlist titlebar').down('#minimize');
    if (button) {
      this.minimizeListPanel(button);
    }
  }
  if (this.getView().pageConfig.showUnreadFileBadge) {
    _record.set('read', true);
    this.markFileAsReadInAlmanac(_record.get('path'));
    if (_record.parentNode) {
      var almanac = this.getCurrentAlmanac();
      var path = _record.parentNode.get('path');
      var parentDirectory = almanac.getDirectoryForPath(path);
      var countUnreadFilesRecursively = parentDirectory ? parentDirectory.countUnreadFilesRecursively() : 0;
      var read = true;
      if (Ext.isDefined(countUnreadFilesRecursively) && countUnreadFilesRecursively > 0) {
        read = false;
      }
      _record.parentNode.set('read', read);
    }
  }
}, markFileAsReadInAlmanac:function(_path) {
  var master = dilocsync.core.Master;
  var almanac = this.getCurrentAlmanac();
  if (almanac) {
    almanac.markFileAsReadInAlmanac(_path);
    master.persistAlmanacByPath(almanac, this.getCurrentAlmanacPath());
  } else {
    cnconsult.Logger.log({prefix:'FolderController-\x3emarkFileAsReadInAlmanac', message:'No almanac found for path: ' + _path + ' and current almanac path: ' + this.getCurrentAlmanacPath(), level:'error'});
  }
}, getCurrentAlmanac:function() {
  var master = dilocsync.core.Master;
  return master.getAlmanacs()[this.getCurrentAlmanacPath()];
}, getCurrentAlmanacPath:function() {
  var almanacPath = this.getView().pageConfig.path;
  if (!Ext.String.startsWith(almanacPath, 'data/') && !Ext.String.startsWith(almanacPath, 'userfilebox/') && !Ext.String.startsWith(almanacPath, 'trainschedules/')) {
    almanacPath = 'data/' + almanacPath;
  }
  if (Ext.String.endsWith(almanacPath, '/')) {
    almanacPath = almanacPath.substring(0, almanacPath.length - 1);
  }
  return almanacPath;
}});
Ext.define('dilocsync.view.pages.folder.Folder', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'folder', controller:'folder', responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, getDesktopViewer:function() {
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    return {xtype:'externalfileopen', reference:'viewer', enableDownloadOnDemand:this.pageConfig.enableDownloadOnDemand && this.pageConfig.enableDownloadOnDemand === true, resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, flex:2, listeners:{downloadOnDemand:'downloadOnDemand'}};
  }
  return {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', enableDownloadOnDemand:this.pageConfig.enableDownloadOnDemand && this.pageConfig.enableDownloadOnDemand === true, resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, listeners:{downloadOnDemand:'downloadOnDemand'}, flex:2};
}, initialize:function() {
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([{xtype:'filefolderpanel', path:this.pageConfig.path, folderTitle:this.pageConfig.title, indicateUnreadFiles:this.pageConfig.showUnreadFileBadge && this.pageConfig.showUnreadFileBadge === true, reference:'listPanel', listeners:{showfile:'showViewer'}}, {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), enableDownloadOnDemand:this.pageConfig.enableDownloadOnDemand && this.pageConfig.enableDownloadOnDemand === true, reference:'viewer', listeners:{back:'showList', 
    downloadOnDemand:'downloadOnDemand'}}]);
  } else {
    this.setItems([{xtype:'filefolderpanel', path:this.pageConfig.path, folderTitle:this.pageConfig.title, indicateUnreadFiles:this.pageConfig.showUnreadFileBadge && this.pageConfig.showUnreadFileBadge === true, reference:'listPanel', listeners:{showfile:'showFile', openFile:'openFile', resize:'onResize'}, flex:1}, this.getDesktopViewer()]);
  }
  this.callParent(arguments);
  if (Ext.os.deviceType !== 'Phone') {
    this.addMinMaximizeFeatureToToolbar();
  }
}, addMinMaximizeFeatureToToolbar:function() {
  var buttons = [{ui:'toolbar-button', itemId:'maximize', iconCls:'x-fa fa-expand', align:'right', handler:'maximizeListPanel', scope:this.getController()}, {ui:'toolbar-button', itemId:'minimize', iconCls:'x-fa fa-compress', align:'right', handler:'minimizeListPanel', scope:this.getController(), hidden:true}];
  this.lookup('listPanel').down('filefolderlist titlebar').add(buttons);
  this.lookup('listPanel').down('[reference\x3dsearchResultList] titlebar').add(buttons);
}, pageTappedAgain:function() {
  var list = this.down('filefolderlist');
  if (list) {
    list.goToNode(list.getStore().getRoot());
  }
}});
Ext.define('dilocsync.view.pages.folder.Knowledges', {extend:dilocsync.view.pages.folder.Folder, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'knowledges', controller:'knowledges', initialize:function() {
  this.callParent(arguments);
  this.down('filefolderpanel filefolderlist').setTitle(this.tr('Knowledges'));
}});
Ext.define('dilocsync.view.pages.folder.KnowledgesController', {extend:dilocsync.view.pages.folder.FolderController, alias:'controller.knowledges', init:function() {
  var master = dilocsync.core.Master;
  var syncEngine = master.getSyncEngine();
  var view = this.getView();
  view.on('initialize', this.onViewInitialize, this);
  syncEngine.on('syncfinished', this.onSyncFinished, this);
}, onViewInitialize:function() {
  this.restoreState();
}, onSyncFinished:function(_success, _errorMessage, _syncReportAvailable, _reloadRequired, _syncReportDirectories) {
  var list = this.lookup('listPanel').down('filefolderlist');
  var currentActiveNodePath = list.getActiveItem().getStore().getNode().get('path');
  var visible = this.getView().isVisible();
  var viewerViewModel = this.lookup('viewer').getViewModel();
  if (currentActiveNodePath && viewerViewModel.get('path')) {
    dilocsync.util.Knowledges.persistViewState(currentActiveNodePath, viewerViewModel.get());
  }
  this.getView().destroy();
  if (visible) {
    this.redirectTo('knowledges', {force:true});
  }
}, restoreState:function() {
  if (dilocsync.util.Knowledges.getActivePath() && dilocsync.util.Knowledges.getViewerState()) {
    var list = this.lookup('listPanel').down('filefolderlist');
    var activePath = dilocsync.util.Knowledges.getActivePath();
    var viewerState = dilocsync.util.Knowledges.getViewerState();
    var viewerViewModel = this.lookup('viewer').getViewModel();
    var folders = activePath.substr(1).split('/');
    var nodePath = '', activeNode;
    for (var $jscomp$iter$12 = $jscomp.makeIterator(folders), $jscomp$key$folder = $jscomp$iter$12.next(); !$jscomp$key$folder.done; $jscomp$key$folder = $jscomp$iter$12.next()) {
      var folder = $jscomp$key$folder.value;
      {
        nodePath += '/' + folder;
        activeNode = list.getStore().findNode('path', nodePath);
        if (activeNode) {
          list.goToNode(activeNode);
        }
      }
    }
    if (activeNode) {
      dilocsync.util.Knowledges.setActivePath(null);
      if (viewerState && viewerViewModel) {
        viewerViewModel.set(viewerState);
      }
      dilocsync.util.Knowledges.setViewerState(null);
    }
  }
}});
Ext.define('dilocsync.view.components.FormsDialog', {extend:Ext.Dialog, mixins:[Ext.mixin.Responsive, cnconsult.Translatable], iconCls:'x-fa fa-file-import', closable:true, maskTapHandler:'close', layout:{type:'vbox', align:'stretch'}, responsiveConfig:{'phone':{width:'100%', height:'80%'}, 'tablet || desktop':{width:'70%', height:'75%'}}, initialize:function() {
  var $jscomp$this = this;
  this.setTitle(this.tr('Here you can fill out the form with data from a previous filled out form'));
  this.setItems([{xtype:'grid', collapsible:{collapsed:true}, scrollable:true, deferEmptyText:false, emptyText:this.tr('No completed forms available.'), flex:1, columns:[{text:this.tr('Name'), dataIndex:'name', flex:1}, {text:this.tr('Revision'), dataIndex:'version', flex:1}, {text:this.tr('Saved at'), dataIndex:'savedAt', flex:1, renderer:function(_timestamp) {
    return Ext.Date.format(new Date(_timestamp * 1000), 'd.m.Y, H:i');
  }}, {text:this.tr('State'), dataIndex:'syncState', flex:1, renderer:function(_syncState) {
    switch(_syncState) {
      case 'unsynced':
        return $jscomp$this.tr('Draft');
      case 'prepared':
        return $jscomp$this.tr('Awaiting synchronization');
      case 'synced':
        return $jscomp$this.tr('Synchronized');
    }
  }}], listeners:{childtap:function(_grid, _location) {
    if (_location.record) {
      $jscomp$this.hide();
      $jscomp$this.fireEvent('formselected', _location.record);
      Ext.defer(function() {
        $jscomp$this.destroy();
      }, 500);
    }
  }}, store:new Ext.data.ChainedStore({source:dilocsync.util.Helper.initStore('CompletedForms'), groupField:'name'})}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.forms.FormsController', {extend:dilocsync.view.pages.BaseController, alias:'controller.forms', mixins:[cnconsult.Translatable], init:function() {
  var $jscomp$this = this;
  Ext.Viewport.on('orientationchange', function() {
    this.onResizePanel();
    this.addSpacing();
    this.updateResizeableSizes();
  }, this);
  var formsStore = dilocsync.util.Helper.initStore('Forms');
  formsStore.on('datachanged', function(_store) {
    var currentSelection = $jscomp$this.getViewModel().get('formsList.selection');
    if (currentSelection) {
      var currentSelectedFormIndex = _store.findExact('id', currentSelection.get('id'));
      var formViewer = $jscomp$this.lookup('viewer');
      if (formViewer && currentSelectedFormIndex === -1) {
        if (Ext.History.getToken() === 'forms' && $jscomp$this.isFormDirty()) {
          dilocsync.util.MessageHelper.showConfirm($jscomp$this.tr('Form updated or deleted'), $jscomp$this.tr('You are editing an updated or deleted form. Your changes have been saved as a draft.') + '\x3cbr\x3e\x3cbr\x3e\x3cb\x3e' + $jscomp$this.tr('Do you want to open the saved draft now?') + '\x3c/b\x3e', function(_button) {
            if (_button === 'yes') {
              this.lookup('listPanel').down('[value\x3dcompletedForms]').setPressed(true);
              this.lookup('completedFormsList').getSelectable().selectRange(0, 0);
            }
          }, $jscomp$this);
          $jscomp$this.onSave($jscomp$this.getView().down('#draftButton'));
        }
        $jscomp$this.setEmptyMessage($jscomp$this.tr('Form has been updated or deleted'));
      }
    }
  });
  var completedFormsStore = dilocsync.util.Helper.initStore('CompletedForms');
  completedFormsStore.on('update', function() {
    var record = $jscomp$this.getViewModel().get('completedFormsList.selection');
    if (record) {
      $jscomp$this.getViewModel().set('recordState', record.get('syncState'));
    }
  });
  completedFormsStore.on('update', this.refreshGrouping);
  completedFormsStore.on('remove', this.refreshGrouping);
}, refreshGrouping:function(_store) {
  var grouper = _store.getGrouper();
  _store.setGrouper(null);
  _store.setGrouper(grouper);
}, showViewer:function(_list, _record) {
  this.showForm(_list, _record);
  this.getView().setActiveItem(this.lookup('viewer'));
}, showForm:function(_list, _record) {
  var $jscomp$this = this;
  var viewer = this.lookup('viewer');
  var vm = viewer.lookupViewModel();
  var formDataObj;
  vm.set('discardChanges', false);
  vm.set('recordState', _record.get('syncState'));
  if (!viewer.isVisible()) {
    var button = this.lookup('listPanel').down('titlebar').down('#minimize');
    if (button) {
      this.minimizeListPanel(button);
    }
  }
  var filePath = _record.get('path');
  if (vm.get('recordState') === 'unsynced') {
    var formsStore = dilocsync.util.Helper.initStore('Forms');
    var latestForm = formsStore.findRecord('id', _record.get('id'), 0, false, false, true);
    if (latestForm && _record.get('version') !== latestForm.get('version')) {
      filePath = latestForm.get('path');
      _record.set('newVersion', latestForm.get('version'));
    }
  }
  dilocsync.core.Master.getSyncRoot().getFile(filePath, {}, function(_formEntry) {
    _formEntry.file(function(_form) {
      var reader = new FileReader;
      reader.onload = function(_event) {
        formDataObj = Ext.decode(_event.target.result);
        vm.set('metaData', _record.getData());
        vm.set('formData', formDataObj);
        vm.set('record', _record);
        if (Ext.os.deviceType === 'Phone') {
          $jscomp$this.renderFormForPhone();
        } else {
          $jscomp$this.renderFormForTablet();
        }
        $jscomp$this.addSpacing();
        if (_record.isCompletedForm()) {
          $jscomp$this.updateDisabled(true);
          $jscomp$this.fillForm(_record);
        } else {
          vm.set('formDisabled', false);
        }
      };
      reader.onerror = function(_error) {
        cnconsult.Logger.log({prefix:'FormController-\x3eshowForm', message:'Failed to read form file', dump:_error});
        $jscomp$this.setEmptyMessage($jscomp$this.tr('Form does not exist. Either it was changed or deleted.'));
      };
      reader.readAsText(_form);
    });
  }, function(_error) {
    cnconsult.Logger.log({prefix:'FormController-\x3eshowForm', message:'Failed to load form. Maybe it was deleted', dump:_error});
    $jscomp$this.setEmptyMessage($jscomp$this.tr('Form does not exist. Either it was changed or deleted.'));
  });
}, beforeSelect:function(_list, _record) {
  var viewModel = this.getViewModel();
  var selectable = _list.getSelectable();
  if (this.isFormDirty() && !viewModel.get('discardChanges')) {
    dilocsync.util.MessageHelper.showConfirm(this.tr('Unsaved changes'), this.tr('You have unsaved changes. Do you really want to continue?'), function(_choice) {
      if (_choice === 'yes') {
        viewModel.set('discardChanges', true);
        selectable.select(_record);
      } else {
        selectable.select(viewModel.get('record'), false, true);
      }
    });
    return false;
  } else {
    return true;
  }
}, fillForm:function(_record) {
  var $jscomp$this = this;
  dilocsync.core.Master.getSyncRoot().getFile(_record.get('completedFormPath'), {}, function(_formEntry) {
    _formEntry.file(function(_form) {
      var reader = new FileReader;
      reader.onload = function(_event) {
        var formPanel = $jscomp$this.lookup('viewer');
        var formValues = Ext.decode(_event.target.result).data;
        formPanel.setValues(formValues);
        if (_record.get('newVersion')) {
          Ext.defer(function() {
            var migratedValues = formPanel.getValues();
            var notMigratedValues = [];
            for (var $jscomp$iter$13 = $jscomp.makeIterator(Object.entries(formValues)), $jscomp$key$$jscomp$destructuring$var8 = $jscomp$iter$13.next(); !$jscomp$key$$jscomp$destructuring$var8.done; $jscomp$key$$jscomp$destructuring$var8 = $jscomp$iter$13.next()) {
              var $jscomp$destructuring$var8 = $jscomp$key$$jscomp$destructuring$var8.value;
              {
                var $jscomp$destructuring$var9 = $jscomp.makeIterator($jscomp$destructuring$var8);
                var key = $jscomp$destructuring$var9.next().value;
                var value = $jscomp$destructuring$var9.next().value;
                if (value && (!migratedValues.hasOwnProperty(key) || value !== migratedValues[key])) {
                  if (Ext.isArray(value)) {
                    if (value.length > 0) {
                      var fileField = formPanel.getFields(key);
                      var fileNames = Ext.Array.pluck(value, 'name');
                      if (!fileField || fileNames.join(', ') !== fileField.getFileNames()) {
                        notMigratedValues.push.apply(notMigratedValues, $jscomp.arrayFromIterable(fileNames));
                      }
                    }
                  } else {
                    if (Ext.String.startsWith(value, 'data:image/png;base64')) {
                      notMigratedValues.push($jscomp$this.tr('Signature'));
                    } else {
                      notMigratedValues.push(value);
                    }
                  }
                }
              }
            }
            notMigratedValues.forEach(function(value, index) {
              notMigratedValues[index] = '\x3cli\x3e' + value + '\x3c/li\x3e';
            });
            dilocsync.util.MessageHelper.showAcknowledge($jscomp$this.tr('Form was updated to revision %1').arg(_record.get('newVersion')), notMigratedValues.length ? $jscomp$this.tr('The following values could not be transferred to the new version: %1').arg('\x3cul\x3e' + notMigratedValues.join('') + '\x3c/ul\x3e') : $jscomp$this.tr('All values could be transferred to the new version successfully'));
            _record.set('version', _record.get('newVersion'));
            delete _record.data.newVersion;
            $jscomp$this.onSave($jscomp$this.getView().down('#draftButton'));
          }, 500);
        }
      };
      reader.onerror = function(_error) {
        $jscomp$this.setEmptyMessage($jscomp$this.tr('Form does not exist. Either it was changed or deleted.'));
      };
      reader.readAsText(_form);
    });
  });
}, renderFormForPhone:function() {
  var view = this.lookup('viewer'), viewModel = view.lookupViewModel(), metaData, formData, groupData, metaDescription, metaTitleName, customField, itemsArr = [];
  if (view) {
    metaData = viewModel.get('metaData');
    formData = viewModel.get('formData');
    groupData = formData.groups;
    metaTitleName = metaData.name;
    if (view && view.items.length !== 0) {
      view.removeAll(true, true);
    }
    view.add({xtype:'component', docked:'top', cls:'dilocsync-fileviewer-file-name', html:metaTitleName});
    view.add({xtype:'toolbar', cls:'dilocsync-fileviewer-action-toolbar', reference:'actionToolbar', docked:'top', ui:'actions-toolbar', scrollable:'x', defaults:{ui:'toolbar-actions'}, items:Ext.Array.insert([{iconCls:'x-fa fa-chevron-left', reference:'backButton', handler:'onBack'}, {handler:'onBackBtnClick', iconCls:'x-fa fa-chevron-left', bind:{hidden:'{index \x3d\x3d\x3d 0}'}}, {xtype:'component', flex:1, bind:{html:'{groupTitle}'}}, {handler:'onNextBtnClick', iconCls:'x-fa fa-chevron-right', 
    bind:{hidden:'{!submitBtnHidden}'}}], 1, this.getToolbarButtons())});
    if (groupData) {
      for (var i = 0; i < groupData.length; i++) {
        itemsArr = [];
        if (i === 0) {
          view.lookupViewModel().set('groupTitle', groupData[i].name);
          itemsArr.push({xtype:'displayfield', value:metaData.description});
          itemsArr.push({xtype:'displayfield', style:'margin-top:0;', html:'\x3cspan class \x3d"fc-mandate-msg"\x3e\x3cspan style\x3d"color:red"\x3e * \x3c/span\x3e ' + this.tr('Mandatory field') + '\x3c/span\x3e'});
        }
        var group = groupData[i];
        for (var j = 0; j < group.fields.length; j++) {
          customField = this.preparingField(group.fields[j], group);
          itemsArr.push(customField);
        }
        view.add({xtype:'fieldset', innerCls:'fc-container-inner', cls:'fc-group-container', title:groupData[i].name, scrollable:'y', name:'groupfield', items:itemsArr});
      }
    }
  }
}, renderFormForTablet:function() {
  var view = this.lookup('viewer'), viewModel = view.lookupViewModel(), metaData = viewModel.get('metaData'), formData = viewModel.get('formData'), groupData, fieldWidth, fieldColumnWidth, itemsArr = [], customField, fieldSetObj, metaDescription, metaTitleName;
  if (view) {
    groupData = formData.groups;
    metaDescription = metaData.description ? metaData.description : '';
    metaTitleName = metaData.name;
    if (view.items.length !== 0) {
      view.removeAll(true, true);
    }
    view.add({xtype:'component', docked:'top', cls:'dilocsync-fileviewer-file-name', html:metaTitleName});
    view.add({xtype:'toolbar', cls:'dilocsync-fileviewer-action-toolbar', reference:'actionToolbar', docked:'top', ui:'actions-toolbar', scrollable:'x', defaults:{ui:'toolbar-actions'}, items:this.getToolbarButtons()});
    if (metaTitleName) {
      view.add({xtype:'displayfield', value:metaDescription, cls:'tablet-description'});
    }
    view.add({xtype:'displayfield', html:'\x3cdiv class\x3d"fc-field-marked"\x3e\x3cspan class\x3d"fc-asterik"\x3e * \x3c/span\x3e' + this.tr('Mandatory field') + '\x3c/div\x3e'});
    for (var j = 0; j < groupData.length; j++) {
      if (groupData[j].fields) {
        fieldSetObj = {xtype:'fieldset', title:groupData[j].name, name:groupData[j].identifier, cls:'fe-fields', items:[], fieldDefaults:{margin:2}};
        for (var i = 0; i < groupData[j].fields.length; i++) {
          fieldColumnWidth = groupData[j].fields[i].columnWidth;
          fieldWidth = this.onSettingFieldWidth(fieldColumnWidth);
          customField = this.preparingField(groupData[j].fields[i], groupData[j]);
          customField.width = fieldWidth;
          fieldSetObj.items.push(customField);
        }
        itemsArr.push(fieldSetObj);
      }
    }
    view.add(itemsArr);
  }
}, getToolbarButtons:function() {
  return [{text:this.tr('Edit draft'), iconCls:'x-fa fa-pencil-alt', handler:'onEdit', hidden:true, bind:{hidden:'{hideEditButton}', disabled:'{!formDisabled}'}}, {text:this.tr('Save as draft'), iconCls:'x-fa fa-clock', itemId:'draftButton', handler:'onSave', hidden:true, bind:{hidden:'{hideSaveButton}', disabled:'{formDisabled}'}}, {text:this.tr('Ready for synchronization'), iconCls:'x-fa fa-save', itemId:'saveButton', handler:'onSave', hidden:true, bind:{hidden:'{hideSaveButton}', disabled:'{formDisabled}'}}, 
  {text:this.tr('Submit now'), iconCls:'x-fa fa-paper-plane', itemId:'submitButton', handler:'onSave', hidden:true, bind:{hidden:'{hideSaveButton}', disabled:'{formDisabled}'}}, {text:this.tr('Delete draft'), iconCls:'x-fa fa-trash-alt', handler:'onDelete', hidden:true, bind:{hidden:'{hideDeleteButton}'}}, {text:this.tr('Revert to draft'), iconCls:'x-fa fa-undo', handler:'onUndo', hidden:true, bind:{hidden:'{hideUndoButton}'}}, '-\x3e', {text:this.tr('Fill form'), iconCls:'x-fa fa-file-import', handler:'onFill', 
  hidden:true, bind:{hidden:'{hideFillButton}'}}];
}, onBackBtnClick:function() {
  var formPanel = this.lookup('viewer'), viewModel = formPanel.lookupViewModel(), groupLength;
  formPanel.getLayout().previous();
  groupLength = viewModel.get('formData').groups.length;
  if (formPanel.getActiveItemIndex() !== groupLength - 1) {
    viewModel.set('submitBtnHidden', true);
  }
}, onNextBtnClick:function() {
  var formPanel = this.lookup('viewer'), fields = formPanel.getActiveItem() && formPanel.getActiveItem().query('field'), validateCard = true, viewModel = formPanel.lookupViewModel(), groupLength;
  Ext.Array.each(fields, function(field) {
    if (field.config && field.config.required && !field.isHidden() && !field.validate() && validateCard) {
      validateCard = false;
    }
  });
  if (formPanel && validateCard) {
    formPanel.getLayout().next();
    groupLength = viewModel.get('formData').groups.length;
    if (formPanel.getActiveItemIndex() === groupLength - 1) {
      viewModel.set('submitBtnHidden', false);
    }
  }
}, onSettingFieldWidth:function(_fieldColumnWidth) {
  return _fieldColumnWidth * 98 + '%';
}, preparingField:function(_field, _group) {
  var customField = {xtype:_field.type, label:_field.label, name:_group.identifier + '_' + _field.identifier, value:_field.defaultValue, required:_field.required, placeholder:_field.placeHolder, errorTarget:'under', requiredMessage:this.tr('There seems to be a problem'), labelAlign:'top', labelWrap:true};
  if (Ext.os.deviceType === 'Tablet' || Ext.os.deviceType === 'Desktop') {
    customField.cls = 'fe-preview-fields';
  } else {
    if (Ext.os.deviceType === 'Phone') {
    }
  }
  switch(customField.xtype) {
    case 'fieldcontainer':
    case 'displayfield':
      delete customField.name;
      break;
    case 'textfield':
      break;
    case 'textarea':
      customField.xtype = 'textareafield';
      break;
    case 'combobox':
      customField.store = _field.options;
      customField.displayField = 'name';
      customField.queryMode = 'local';
      break;
    case 'checkbox':
      if (Ext.os.deviceType === 'Tablet' || Ext.os.deviceType === 'Desktop') {
        customField.cls = 'fc-check-tablet';
      } else {
        if (Ext.os.deviceType === 'Phone') {
          customField.cls = 'fc-check';
        }
      }
      customField.value = true;
      customField.checked = _field.defaultValue;
      customField.labelAlign = 'right';
      customField.labelWrap = true;
      break;
    case 'numberfield':
      customField.decimals = 10;
      customField.listeners = {initialize:function(_field) {
        _field.inputElement.dom.setAttribute('inputmode', 'decimal');
      }};
      break;
    case 'timefield':
      if (!_field.format) {
        _field.format = 'H:i';
      }
      customField.picker = {meridiem:_field.format !== 'H:i'};
      customField.format = _field.format;
      customField.submitFormat = _field.format;
      break;
    case 'datefield':
      if (!_field.format) {
        _field.format = 'd.m.Y';
      }
      customField.dateFormat = _field.format;
      customField.edgePicker = {yearFrom:1900};
      customField.badFormatMessage = this.tr('The value should match in %1 format!').arg(_field.format);
      customField.submitFormat = _field.format;
      if (!_field.defaultValue) {
        customField.value = new Date;
      }
      break;
    case 'fileupload':
      customField.xtype = 'filefield';
      customField.accept = _field.accept;
      customField.multiple = _field.multiple;
      break;
  }
  return customField;
}, onSave:function(_btn) {
  var $jscomp$this = this;
  var master = dilocsync.core.Master;
  var formPanel = this.lookup('viewer');
  var viewModel = formPanel.lookupViewModel();
  if (_btn.getItemId() === 'draftButton' || formPanel.validate()) {
    var formValues = formPanel.getValues();
    var encodeFilesPromises = [];
    Ext.Object.each(formPanel.getFields(), function(_key, _field) {
      if (Ext.isObject(_field) && _field.xtype === 'filefield') {
        encodeFilesPromises.push(new Ext.Promise(function(_resolve, _reject) {
          _field.getEncodedFiles(function(_files) {
            formValues[_key] = _files;
            _resolve();
          }, _reject);
        }));
      }
    });
    Ext.Promise.all(encodeFilesPromises).then(function() {
      var record = viewModel.get('record');
      var completedForm = record.isCompletedForm() ? record : Ext.create('dilocsync.model.CompletedForm', record.getData());
      completedForm.setSavedAt();
      if (_btn.getItemId() === 'saveButton') {
        completedForm.set('syncState', 'prepared');
      }
      var metaObj = {meta:{savedAt:completedForm.get('savedAt'), formId:completedForm.get('id'), formVersion:completedForm.get('version')}, data:formValues};
      var writeFormData = new Ext.Promise(function(_resolve, _reject) {
        master.getSyncRoot().getFile(completedForm.get('completedFormPath'), {create:true}, function(_file) {
          _file.createWriter(function(_writer) {
            _writer.onerror = _reject;
            _writer.onwrite = _resolve;
            _writer.write(Ext.encode(metaObj));
          }, _reject);
        }, _reject);
      });
      writeFormData.then(function() {
        var store = dilocsync.util.Helper.initStore('CompletedForms');
        if (store.indexOf(completedForm) === -1) {
          store.add(completedForm);
        }
        store.sync();
        var submitPromise = _btn.getItemId() === 'submitButton' ? new Promise(function(_resolve, _reject) {
          $jscomp$this.getView().mask($jscomp$this.tr('Submitting form. Please wait...'));
          var syncTask = Ext.create('dilocsync.core.syncengine.tasks.db.SyncCompletedForms');
          syncTask.submitForm(completedForm, _resolve, master.getSyncRoot().toURL(), master.getBackendUrl() + '/formclientsync/submitForm', {syncSecret:master.getStorage().get('core:personalization:syncSecret')});
        }) : Promise.resolve();
        submitPromise.then(function() {
          $jscomp$this.getView().unmask();
          if (record.isCompletedForm()) {
            $jscomp$this.updateDisabled(true);
          } else {
            formPanel.reset(true);
          }
          if (_btn.getItemId() === 'submitButton') {
            if (completedForm.get('syncState') === 'synced') {
              cnconsult.Logger.log({prefix:'FormController-\x3eonSave', message:'Completed form successfully submitted to server'});
              Ext.create({xtype:'alert', renderTo:$jscomp$this.getView(), html:$jscomp$this.tr('Form successfully submitted.')});
            } else {
              cnconsult.Logger.log({prefix:'FormController-\x3eonSave', message:'Failed to submit completed form to server'});
              completedForm.set('syncState', 'prepared');
              completedForm.commit();
              dilocsync.util.MessageHelper.showAcknowledge($jscomp$this.tr('Info'), $jscomp$this.tr('The form could not be submitted directly.\x3cbr\x3e\x3cbr\x3e\x3cb\x3eIt has been saved and will be transferred at the next synchronization.\x3c/b\x3e'));
            }
            store.sync();
          } else {
            cnconsult.Logger.log({prefix:'FormController-\x3eonSave', message:'Completed form successfully saved on device'});
            Ext.create({xtype:'alert', renderTo:$jscomp$this.getView(), html:$jscomp$this.tr('Form successfully saved.')});
          }
        });
      })['catch'](function(_error) {
        cnconsult.Logger.log({prefix:'FormController-\x3eonSave', message:'Failed to save completed form on device', dump:_error});
        Ext.create({xtype:'alert', renderTo:$jscomp$this.getView(), html:$jscomp$this.tr('Failed to save form.'), type:'danger'});
      });
    })['catch'](function(_error) {
      cnconsult.Logger.log({prefix:'FormController-\x3eonSave', message:'Failed to add attachments to form data', dump:_error});
      Ext.create({xtype:'alert', renderTo:$jscomp$this.getView(), html:$jscomp$this.tr('Failed to save form.'), type:'danger'});
    });
  }
}, onFill:function() {
  var $jscomp$this = this;
  var dialog = Ext.create('dilocsync.view.components.FormsDialog');
  dialog.on('formselected', this.fillForm, this);
  dialog.on('show', function(_dialog) {
    _dialog.query('rowheader').forEach(function(_header) {
      var group = _header.getGroup();
      if (group && group.data.getConfig('groupKey') === $jscomp$this.getViewModel().get('record').get('name')) {
        group.expand();
      }
    });
  });
  dialog.show();
}, onEdit:function() {
  this.updateDisabled(false);
}, onUndo:function() {
  var viewModel = this.getViewModel();
  var record = viewModel.get('record');
  var store = record.store;
  record.set('syncState', 'unsynced');
  store.sync();
  store.sort();
}, isFormDirty:function() {
  if (this.getViewModel().get('formDisabled')) {
    return false;
  }
  var formPanel = this.lookup('viewer');
  for (var $jscomp$iter$15 = $jscomp.makeIterator(formPanel.query('fieldset')), $jscomp$key$fieldset = $jscomp$iter$15.next(); !$jscomp$key$fieldset.done; $jscomp$key$fieldset = $jscomp$iter$15.next()) {
    var fieldset = $jscomp$key$fieldset.value;
    {
      for (var $jscomp$iter$14 = $jscomp.makeIterator(fieldset.getItems().items), $jscomp$key$item = $jscomp$iter$14.next(); !$jscomp$key$item.done; $jscomp$key$item = $jscomp$iter$14.next()) {
        var item = $jscomp$key$item.value;
        {
          if (item.xtype !== 'title' && item.xtype !== 'fieldcontainer' && item.isDirty()) {
            return true;
          }
        }
      }
    }
  }
  return false;
}, onDelete:function() {
  var $jscomp$this = this;
  dilocsync.util.MessageHelper.showConfirm(this.tr('Delete form'), this.tr('Do you really want to delete this form?'), function(_choice) {
    if (_choice === 'yes') {
      var record = $jscomp$this.getViewModel().get('completedFormsList.selection');
      var store = record.store;
      record.drop();
      store.sync();
      $jscomp$this.setEmptyMessage($jscomp$this.tr('Form deleted.'));
    }
  });
}, onBack:function() {
  this.getView().setActiveItem(this.lookup('listPanel'));
}, getCurrentAlmanac:function() {
  var master = dilocsync.core.Master;
  return master.getAlmanacs()[this.getCurrentAlmanacPath()];
}, getCurrentAlmanacPath:function() {
  return this.getView().pageConfig.path;
}, beforeSwitchCard:function(_btn, _value, _oldValue) {
  var $jscomp$this = this;
  var btnValue = _btn.getValue();
  if (this.isFormDirty()) {
    if (_value) {
      dilocsync.util.MessageHelper.showConfirm(this.tr('Unsaved changes'), this.tr('You have unsaved changes. Do you really want to continue?'), function(_choice) {
        if (_choice === 'yes') {
          $jscomp$this.switchCard(btnValue);
          _btn.setPressed(true);
        }
      });
    }
    return false;
  } else {
    if (_value) {
      this.switchCard(btnValue);
    }
  }
}, switchCard:function(_value) {
  var cardPanel = this.lookup('cardPanel');
  if (_value === 'forms') {
    cardPanel.setActiveItem(0);
  } else {
    if (_value === 'completedForms') {
      cardPanel.setActiveItem(1);
    }
  }
  this.lookup('formsList').getSelectable().deselectAll();
  this.lookup('completedFormsList').getSelectable().deselectAll();
  this.setEmptyMessage(this.tr('Select a form from the list'));
}, setEmptyMessage:function(_message) {
  var formPanel = this.lookup('viewer');
  var container = {xtype:'container', fullscreen:true, layout:{type:'vbox', pack:'center', align:'center'}, style:{padding:'20px'}, items:[{xtype:'component', html:'\x3ch2\x3e' + _message + '\x3c/h2\x3e', style:'color:gray'}]};
  var record = this.getViewModel().get('completedFormsList.selection');
  if (record && record.get('syncState') === 'unsynced') {
    container.items.push({xtype:'button', text:this.tr('Delete draft'), iconCls:'x-fa fa-trash-alt', handler:'onDelete', style:{border:'1px black solid'}});
  }
  formPanel.removeAll(true, true);
  formPanel.add(container);
}, updateDisabled:function(_value) {
  this.lookup('viewer').updateDisabled(_value);
  this.getViewModel().set('formDisabled', _value);
}, onResizePanel:function() {
  var items = this.getView().query('signaturepad');
  for (var $jscomp$iter$16 = $jscomp.makeIterator(items), $jscomp$key$item = $jscomp$iter$16.next(); !$jscomp$key$item.done; $jscomp$key$item = $jscomp$iter$16.next()) {
    var item = $jscomp$key$item.value;
    {
      item.updateSize();
    }
  }
}, addSpacing:function() {
  var $jscomp$this = this;
  Ext.defer(function() {
    var viewer = $jscomp$this.lookup('viewer');
    var fieldset = viewer.down('fieldset:last');
    var field = fieldset.down('field:last');
    fieldset.setStyle('margin-bottom: ' + (viewer.innerElement.getHeight() - field.el.getHeight() - 30) + 'px');
  }, 100);
}, onChildLongPress:function(_list, _info) {
}, doRedirect:function() {
  var $jscomp$this = this;
  if (this.isFormDirty()) {
    dilocsync.util.MessageHelper.showConfirm(this.tr('Unsaved changes'), this.tr('Are you sure you want to discard your unsaved changes?'), function(_choice) {
      if (_choice === 'yes') {
        $jscomp$this.lookup('viewer').reset();
      }
    });
    return false;
  } else {
    return true;
  }
}});
Ext.define('dilocsync.view.pages.forms.FormsModel', {extend:Ext.app.ViewModel, alias:'viewmodel.forms', data:{index:0, metaData:{}, formData:{}, groupTitle:'', length:1, submitBtnHidden:true, record:null, recordState:null, discardChanges:false, formDisabled:false}, formulas:{groupTitle:{bind:{metaData:'{metaData}', index:'{index}'}, get:function(data) {
  return this.getView().getActiveItem().title;
}}, trackResetOnLoad:{bind:'{recordState}', get:function(_syncState) {
  return _syncState !== null;
}}, hideEditButton:{bind:'{recordState}', get:function(_syncState) {
  return _syncState !== 'unsynced';
}}, hideSaveButton:{bind:'{recordState}', get:function(_syncState) {
  return _syncState !== null && _syncState !== 'unsynced';
}}, hideDeleteButton:{bind:'{recordState}', get:function(_syncState) {
  return _syncState !== 'unsynced';
}}, hideUndoButton:{bind:'{recordState}', get:function(_syncState) {
  return _syncState !== 'prepared';
}}, hideFillButton:{bind:'{recordState}', get:function(_syncState) {
  return _syncState !== null;
}}}});
Ext.define('dilocsync.view.pages.forms.Forms', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'forms', viewModel:{type:'forms'}, controller:'forms', responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, initialize:function() {
  var elementWidth = Ext.os.is.iOS ? Ext.Viewport.el.getWidth() : screen.width;
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  var filelist = {xtype:'formlist', selectable:{deselectable:false}, listeners:{select:Ext.os.deviceType === 'Phone' ? 'showViewer' : 'showForm', beforeselect:'beforeSelect'}};
  var baseItem = {xtype:'container', reference:'listPanel', layout:{type:'hbox', align:'stretch'}, flex:1, items:[{xtype:'titlebar', title:this.tr('Forms'), docked:'top'}, {xtype:'toolbar', docked:'top', layout:{pack:'center'}, items:{xtype:'segmentedbutton', items:[{text:this.tr('Forms'), value:'forms', pressed:true, listeners:{beforepressedchange:'beforeSwitchCard'}}, {text:this.tr('Filled out'), value:'completedForms', listeners:{beforepressedchange:'beforeSwitchCard'}}]}}, {xtype:'panel', reference:'cardPanel', 
  fullscreen:true, layout:'card', items:[Ext.merge({}, filelist, {reference:'formsList', store:dilocsync.util.Helper.initStore('Forms')}), Ext.merge({}, filelist, {reference:'completedFormsList', store:dilocsync.util.Helper.initStore('CompletedForms')})]}]};
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([baseItem, {xtype:'formpanel', reference:'viewer', bind:{activeItemIndex:'{index}', trackResetOnLoad:'{trackResetOnLoad}'}, twoWayBindable:'activeItemIndex', layout:{type:'card', animation:{type:'slide'}}, listeners:{back:'showList'}}]);
  } else {
    this.setItems([baseItem, {xtype:'formpanel', reference:'viewer', resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, bind:{trackResetOnLoad:'{trackResetOnLoad}'}, items:{xtype:'component', centered:true, html:'\x3ch2\x3e' + this.tr('Select a form from the list') + '\x3c/h2\x3e', style:'color:gray'}, listeners:{resizedragend:'onResizePanel'}, flex:2}]);
  }
  this.callParent(arguments);
  if (Ext.os.deviceType !== 'Phone') {
    this.addMinMaximizeFeatureToToolbar();
  }
}, addMinMaximizeFeatureToToolbar:function() {
  var buttons = [{ui:'toolbar-button', itemId:'maximize', iconCls:'x-fa fa-expand', align:'right', handler:'maximizeListPanel', scope:this.getController()}, {ui:'toolbar-button', itemId:'minimize', iconCls:'x-fa fa-compress', align:'right', handler:'minimizeListPanel', scope:this.getController(), hidden:true}];
  this.lookup('listPanel').down('titlebar').add(buttons);
}});
Ext.define('dilocsync.view.pages.home.HomeController', {extend:dilocsync.view.pages.BaseController, alias:'controller.home', init:function() {
  dilocsync.core.Master.getSyncEngine().on('syncfinished', this.onSyncFinished, this);
  this.getView().on('initialize', this.fileViewerSetup, this);
}, onSyncFinished:function() {
  var news = this.lookup('news');
  var logo = this.lookup('logo');
  var importantDocuments = this.lookup('importantdocuments');
  if (news) {
    news.getController().onViewInitialize();
  }
  if (logo) {
    logo.getController().onViewInitialize();
  }
  if (importantDocuments) {
    importantDocuments.getController().onViewInitialize();
  }
  this.fileViewerSetup();
  if (!dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    var viewer = this.lookup('viewer');
    if (viewer.getFileViewer() === null) {
      viewer.setFileViewer(dilocsync.util.FileViewerHelper.getPrimary());
    }
  }
}, onChildLongPress:function(_list, _info) {
  var me = this;
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.home.HomeController', src:'Dokumente', action:'DokumentAufSeiteÖffnen', trackedAt:new Date});
  if (_info.record.isNode && _info.record.isLeaf() || !_info.record.isNode) {
    _list.longPressed = true;
    dilocsync.util.MessageHelper.showPrompt(this.tr('Open file on page number'), this.tr('Please enter the page number you like to open'), function(_buttonId, _pageNumber) {
      if (_buttonId === 'ok') {
        me.showViewer(_info.record, _list, parseInt(_pageNumber));
      }
    }, this);
  }
}, showViewer:function(_record, _list, _pageNumber) {
  var cardView = this.lookup('viewerContainer') ? this.lookup('viewerContainer') : this.getView();
  this.onShowFile(_record, _pageNumber);
  cardView.setActiveItem(this.lookup('viewer'));
}, hideViewer:function() {
  var cardView = this.lookup('viewerContainer');
  if (cardView) {
    cardView.setActiveItem(this.lookup('news'));
  } else {
    this.getView().setActiveItem(this.lookup('homeContainer'));
  }
  this.lookup('viewer').getController().hideViewer();
}, onShowFile:function(_record, _pageNumber) {
  var viewModel = this.lookup('viewer').getViewModel();
  viewModel.set('name', _record.get('name'));
  viewModel.set('path', _record.get('path'));
  viewModel.set('record', _record);
  if (_pageNumber && Ext.isNumber(_pageNumber)) {
    viewModel.set('onPageNumber', _pageNumber - 1);
  }
}, showHome:function() {
  this.getView().setActiveItem(this.lookup('homeContainer'));
}, showSearchPanel:function() {
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.home.HomeController', src:'Main', action:'SucheAnzeigen', trackedAt:new Date});
  this.redirectTo('search');
}, fileViewerSetup:function() {
  var $jscomp$this = this;
  var fileViewer = this.lookup('viewer');
  if (fileViewer) {
    fileViewer.on('close', function() {
      $jscomp$this.hideViewer();
    });
  }
}, onHide:function() {
  this.hideViewer();
}});
Ext.define('dilocsync.view.components.syncpanel.SyncPanelModel', {extend:Ext.app.ViewModel, alias:'viewmodel.syncpanel', data:{isSyncing:false, isAborting:false, message:'', singleProgress:0, completeProgress:0, remainingDownloadTime:'', wasHighPriorityFileSync:false}});
Ext.define('dilocsync.view.components.syncpanel.SyncPanelController', {extend:Ext.app.ViewController, alias:'controller.syncpanel', mixins:[cnconsult.Translatable], init:function() {
  var runner = new Ext.util.TaskRunner;
  var syncEngine = dilocsync.core.Master.getSyncEngine();
  if (syncEngine.isSyncing()) {
    this.getViewModel().set('isSyncing', true);
  }
  runner.start({run:function() {
    var lastSynced = syncEngine.lastSyncTimestamp();
    this.updateLastSyncedText(lastSynced);
  }, interval:60 * 1000, scope:this});
  syncEngine.on('syncstarted', this.onSyncStarted, this);
  syncEngine.on('syncfinished', this.onSyncFinished, this);
  syncEngine.on('syncprogress', this.onSyncProgress, this);
  syncEngine.on('syncaborted', this.onSyncAborted, this);
}, onSyncStarted:function() {
  this.getViewModel().set('isSyncing', true);
}, onSyncProgress:function(_message, _completePercent, _filePercent, _remainingDownloadTime) {
  var viewModel = this.getViewModel();
  if (!viewModel.get('isAborting')) {
    viewModel.set('message', _message);
    viewModel.set('singleProgress', _filePercent / 100);
    viewModel.set('completeProgress', _completePercent / 100);
    if (_remainingDownloadTime) {
      viewModel.set('remainingDownloadTime', this.humanReadableRemainingDownloadTime(_remainingDownloadTime));
    }
  }
}, onSyncFinished:function(_success, _errorMessage, _syncReportAvailable, _reloadRequired) {
  var syncEngine = dilocsync.core.Master.getSyncEngine();
  var viewModel = this.getViewModel();
  var lastSynced = syncEngine.lastSyncTimestamp();
  var title = this.tr('Sync finished');
  var text = this.tr('Synchronization finished successfully.');
  var hasHighPriorityFiles = false;
  if (syncEngine.hasOwnProperty('syncData')) {
    hasHighPriorityFiles = syncEngine.syncData.getHasHighPriorityFiles();
  }
  var almanacsSyncActions = syncEngine.syncData ? syncEngine.syncData.getAlmanacsSyncActions() : null;
  var hasNormalFilesToDownload = false;
  if (hasHighPriorityFiles) {
    Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
      if (Ext.Object.getSize(_almanacSyncActions.getFilesToDownload()) > 0) {
        hasNormalFilesToDownload = true;
      }
    }, this);
  }
  this.updateLastSyncedText(lastSynced);
  if (_success === true && _syncReportAvailable === true) {
    text += ' ' + this.tr('A synchronization report is available.');
  } else {
    if (_success === null) {
      text = this.tr('All files where already at the newest version.');
    } else {
      if (_success === false && _errorMessage !== 'noalert') {
        title = this.tr('Sync error');
        text = this.tr('Synchronization failed with message: %1').arg(_errorMessage);
      }
    }
  }
  if (_reloadRequired === true) {
    text += ' ' + this.tr('Important configuration changes were synchronized. The app will be restarted to apply the changes.');
  }
  if (_success === true && hasHighPriorityFiles) {
    text += ' \x3cbr\x3e' + this.tr('All necessary files for your drive were synced!');
    syncEngine.syncData.setHasHighPriorityFiles(false);
    viewModel.set('wasHighPriorityFileSync', true);
  } else {
    viewModel.set('wasHighPriorityFileSync', false);
  }
  if (_errorMessage !== 'noalert') {
    if (dilocsync.core.Master.getSyncEngine().wasLastSyncFromAutoSync() === false) {
      var buttonHandler = Ext.Function.bind(this.syncFinishedMessageButtonHandler, this, [_reloadRequired], true);
      var okayButton = {itemId:'ok', text:this.tr('Ok'), handler:buttonHandler};
      var openSyncReportButton = {itemId:'openSyncReport', text:this.tr('Open Sync Report'), handler:buttonHandler, scope:this};
      var startSync = {itemId:'startSync', text:this.tr('Sync other files'), handler:buttonHandler, scope:this};
      var messageButtons = [okayButton];
      if (_syncReportAvailable && !_reloadRequired) {
        messageButtons.push(openSyncReportButton);
      }
      if (hasHighPriorityFiles && hasNormalFilesToDownload && !_reloadRequired) {
        messageButtons.push(startSync);
      }
      dilocsync.util.MessageHelper.showMessage({title:title, message:text, buttons:messageButtons});
    }
  }
  viewModel.set('isSyncing', false);
  viewModel.set('isAborting', false);
  viewModel.set('remainingDownloadTime', '');
}, syncFinishedMessageButtonHandler:function(_button, _event, _reloadRequired) {
  if (_button.getItemId() === 'openSyncReport') {
    this.redirectTo('syncreports');
  }
  if (_button.getItemId() === 'startSync') {
    dilocsync.core.Master.getSyncEngine().startSync();
  }
  if (_reloadRequired) {
    this.redirectTo('home');
    dilocsync.core.Master.reloadApplication(false);
  }
  _button.up('messagebox').destroy();
}, onSyncAborted:function() {
  var viewModel = this.getViewModel();
  viewModel.set('message', this.tr('Aborting...'));
  viewModel.set('isAborting', true);
}, onSyncButtonTapped:function() {
  if (!dilocsync.core.Master.getSyncEngine().isSyncing()) {
    dilocsync.core.Master.getSyncEngine().startSync();
  }
}, onSyncCancelButtonTapped:function() {
  if (!this.getViewModel().get('isAborting')) {
    dilocsync.core.Master.getSyncEngine().abortSync();
  }
}, updateLastSyncedText:function(_lastSynced) {
  var now = new Date;
  var timeDiff = Ext.Date.diff(_lastSynced, now, Ext.Date.MINUTE);
  var message = '';
  var syncEngine = dilocsync.core.Master.getSyncEngine();
  if (!syncEngine.isSyncing()) {
    if (!_lastSynced) {
      if (syncEngine.isAborted()) {
        message = this.tr('Synchronisation aborted.');
      } else {
        message = this.tr('Never synchronized, please synchronize now.');
      }
    } else {
      if (timeDiff < 1) {
        message = this.tr('Last successful synchronisation: some moments ago.');
      } else {
        if (timeDiff >= 1 && timeDiff < 60) {
          if (timeDiff === 1) {
            message = this.tr('Last successful synchronisation: %1 minute ago.').arg(timeDiff);
          } else {
            message = this.tr('Last successful synchronisation: %1 minutes ago.').arg(timeDiff);
          }
        } else {
          if (timeDiff >= 60 && timeDiff < 1440) {
            timeDiff = Ext.Date.diff(_lastSynced, now, Ext.Date.HOUR);
            if (timeDiff === 1) {
              message = this.tr('Last successful synchronisation: %1 hour ago.').arg(timeDiff);
            } else {
              message = this.tr('Last successful synchronisation: %1 hours ago.').arg(timeDiff);
            }
          } else {
            if (timeDiff >= 1440) {
              timeDiff = Ext.Date.diff(_lastSynced, now, Ext.Date.DAY);
              if (timeDiff === 1) {
                message = this.tr('Last successful synchronisation: %1 day ago.').arg(timeDiff);
              } else {
                message = this.tr('Last successful synchronisation: %1 days ago.').arg(timeDiff);
              }
            }
          }
        }
      }
    }
    this.getViewModel().set('message', message);
  }
}, humanReadableRemainingDownloadTime:function(_remainingDownloadTime) {
  if (_remainingDownloadTime === null) {
    return this.tr('Remaining time is calculated');
  } else {
    if (typeof _remainingDownloadTime !== 'object' && _remainingDownloadTime !== 'infinity') {
      if (_remainingDownloadTime < 60) {
        return this.tr('Less than a minute remaining');
      } else {
        if (_remainingDownloadTime >= 60 && _remainingDownloadTime < 120) {
          return this.tr('1 minute remaining');
        } else {
          if (_remainingDownloadTime >= 3600) {
            return this.tr('More than an hour left');
          } else {
            return this.tr('%1 minutes remaining').arg(Math.round(_remainingDownloadTime / 60));
          }
        }
      }
    }
  }
  return '';
}});
Ext.define('dilocsync.view.components.syncpanel.SyncPanel', {extend:Ext.Container, mixins:[cnconsult.Translatable], xtype:'syncpanel', viewModel:{type:'syncpanel'}, controller:'syncpanel', cls:'dilocsync-sync-panel', initialize:function() {
  this.setItems([{xtype:'component', cls:'dilocsync-sub-header', html:this.tr('Synchronize')}, {xtype:'component', margin:'0 0 2 0', cls:'dilocsync-sync-panel-info-message', bind:{html:'{message}'}}, {xtype:'container', width:300, bind:{hidden:'{!isSyncing}'}, items:[{xtype:'component', cls:'x-fa fa-flag-checkered', height:24, width:24, docked:'left', hidden:false, bind:{hidden:'{!wasHighPriorityFileSync}'}}, {xtype:'progress', height:12, width:250, bind:{value:'{singleProgress}'}}, {xtype:'progress', 
  height:12, width:250, margin:'5 0 7 0', bind:{value:'{completeProgress}'}}, {xtype:'button', docked:'right', ui:'content-button', iconCls:'x-fa fa-times', handler:'onSyncCancelButtonTapped', bind:{disabled:'{isAborting}'}}]}, {xtype:'component', margin:'-7 0 0 0', width:250, cls:'dilocsync-sync-panel-remaining-time', bind:{html:'{remainingDownloadTime}', hidden:'{!isSyncing}'}}, {xtype:'container', width:300, bind:{hidden:'{isSyncing}'}, items:[{xtype:'component', cls:'x-fa fa-flag-checkered', 
  height:24, width:24, docked:'left', hidden:false, bind:{hidden:'{!wasHighPriorityFileSync}'}}, {xtype:'button', margin:'10 0 0 0', ui:'content-button', text:this.tr('Synchronize'), handler:'onSyncButtonTapped'}]}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.userinfo.UserInfoModel', {extend:Ext.app.ViewModel, alias:'viewmodel.userinfo', data:{userdata:{}}});
Ext.define('dilocsync.view.components.userinfo.UserInfoController', {extend:Ext.app.ViewController, alias:'controller.userinfo', init:function() {
  this.updateRegistryData();
  Ext.on({registryUpdated:this.updateRegistryData, scope:this});
}, updateRegistryData:function() {
  this.getViewModel().set('userdata', dilocsync.core.Master.getPersonalization().getData());
}});
Ext.define('dilocsync.view.components.userinfo.UserInfo', {extend:Ext.Container, mixins:[cnconsult.Translatable], xtype:'userinfo', viewModel:{type:'userinfo'}, controller:'userinfo', cls:'dilocsync-userinfo', initialize:function() {
  this.setItems([{xtype:'component', cls:'dilocsync-sub-header', html:this.tr('User information')}, {xtype:'component', cls:'dilocsync-userinfo-table', tpl:['\x3ctable class\x3d"userinfo"\x3e', '\x3ctr\x3e\x3ctd class\x3d"key"\x3e' + this.tr('Username') + ':\x3c/td\x3e\x3ctd class\x3d"value"\x3e{username}\x3ctpl if\x3d"values.userIdCode !\x3d null"\x3e ({userIdCode})\x3c/tpl\x3e\x3c/td\x3e\x3c/tr\x3e', '\x3ctr\x3e\x3ctd class\x3d"key"\x3e' + this.getGroupLabel() + ':\x3c/td\x3e\x3ctd class\x3d"value"\x3e{usergroup}\x3c/td\x3e\x3c/tr\x3e', 
  '\x3ctpl if\x3d"values.email !\x3d null"\x3e\x3ctr\x3e\x3ctd class\x3d"key"\x3e' + this.tr('Email') + ':\x3c/td\x3e\x3ctd class\x3d"value"\x3e{email}\x3c/td\x3e\x3c/tr\x3e\x3c/tpl\x3e', '\x3c/table\x3e'], bind:{data:'{userdata}'}}]);
  this.callParent(arguments);
}, getGroupLabel:function() {
  var identity = dilocsync.core.Master.getIdentity();
  if (identity && identity.options && identity.options.groupLabel) {
    return identity.options.groupLabel;
  } else {
    return this.tr('Group');
  }
}});
Ext.define('dilocsync.view.components.importantdocuments.ImportantDocumentsModel', {extend:Ext.app.ViewModel, alias:'viewmodel.importantdocuments'});
Ext.define('dilocsync.core.AlmanacProxy', {extend:Ext.data.proxy.Client, alias:'proxy.almanac', config:{almanac:null, pathPrefix:'', almanacDirectory:null}, read:function(_operation) {
  var me = this, reader = me.getReader(), directory, item, resultSet;
  if (this.getAlmanac()) {
    directory = this.getAlmanac().getDirectoryForPath(_operation.node.data.path);
  }
  if (directory) {
    this.setAlmanacDirectory(directory);
    item = directory.toNonRecursiveDirectoryItem(this.getPathPrefix());
    resultSet = reader.read(item, {recordCreator:reader.defaultRecordCreatorFromServer});
    _operation.process(resultSet, null, null, false);
    _operation.setCompleted();
  } else {
    cnconsult.Logger.log({prefix:'AlmanacProxy-\x3eread', message:'Error no almanac directory!', level:'error', dump:_operation.node.data.path});
  }
}});
Ext.define('dilocsync.util.Sorters', {singleton:true, pinned:function(_node1, _node2) {
  var node1isPinned = _node1.tags() && _node1.tags().findRecord('isPinned', true);
  var node2isPinned = _node2.tags() && _node2.tags().findRecord('isPinned', true);
  var node1isFolder = _node1.get('isFolder');
  var node2isFolder = _node2.get('isFolder');
  if (node1isFolder && !node2isFolder) {
    return 1;
  }
  if (!node1isFolder && node2isFolder) {
    return -1;
  }
  if (node1isFolder && node2isFolder || !node1isFolder && !node2isFolder) {
    if (node1isPinned && node2isPinned) {
      return 0;
    }
    if (!node1isPinned && node2isPinned) {
      return -1;
    }
    if (!node1isPinned && !node2isPinned) {
      return 0;
    }
    if (node1isPinned && !node2isPinned) {
      return 1;
    }
  }
}});
Ext.define('dilocsync.store.Files', {extend:Ext.data.TreeStore, model:'dilocsync.model.AlmanacEntry', defaultRootProperty:'items', constructor:function(_almanacDirectory, _pathPrefix, _basePath) {
  this.callParent();
  var almanacProxy = new dilocsync.core.AlmanacProxy({almanac:_almanacDirectory, pathPrefix:_pathPrefix});
  this.setProxy(almanacProxy);
  this.getModel().setProxy(almanacProxy);
  this.setRoot({path:_basePath});
  this.setFilters([dilocsync.util.Filters.visibleFrom, dilocsync.util.Filters.visibleTo]);
  this.setSorters([{sorterFn:dilocsync.util.Sorters.pinned, direction:'DESC'}, {property:'title', direction:'ASC'}]);
}});
Ext.define('dilocsync.view.components.importantdocuments.ImportantDocumentsController', {extend:Ext.app.ViewController, alias:'controller.importantdocuments', init:function() {
  var view = this.getView();
  view.on('initialize', this.onViewInitialize, this);
}, onViewInitialize:function() {
  var store = this.loadFilesStore();
  var list = this.lookup('list');
  if (list && store) {
    list.setStore(store);
    Ext.defer(function() {
      list.unmask();
    }, 1000, this);
  }
}, loadFilesStore:function() {
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var pathPrefix = master.devicePath('/');
  var store;
  if (identity.options) {
    if (identity.options.importantDocumentsPath) {
      var basePath = '/';
      var importantDocumentsPath = identity.options.importantDocumentsPath;
      if (importantDocumentsPath.endsWith('/')) {
        importantDocumentsPath = importantDocumentsPath.slice(0, -1);
      }
      var almanac = master.getAlmanacForPath('data/' + importantDocumentsPath);
      store = new dilocsync.store.Files(almanac, pathPrefix, basePath);
      store.setSorters('name');
      store.load({callback:function() {
        var taggedFiles = Ext.getStore('ImportantDocuments');
        if (taggedFiles) {
          taggedFiles.getRoot().eachChild(function(_record) {
            if (!store.findNode('uuid', _record.get('uuid'))) {
              store.getRoot().appendChild(_record.copy());
            }
          });
        }
        store.getRoot().sort();
        store.getRoot().expand();
      }});
      store.filterBy(function(_record) {
        return _record.get('icon') !== 'folder';
      });
    } else {
      store = Ext.getStore('ImportantDocuments');
      if (store) {
        store.getRoot().expand();
      }
    }
  }
  return store;
}, onFileTap:function(_list, _location) {
  var record = _location.record;
  if (_list.longPressed) {
    _list.longPressed = false;
  } else {
    this.showFile(record, _list);
  }
}, showFile:function(_record, _list) {
  this.getView().fireEvent('showfile', _record, this.getView(), _list);
}, onFileDoubleTap:function(_fileFolderList, _location, _eOpts) {
  var details = Ext.create('dilocsync.view.components.filedetails.FileDetails', {viewModel:{data:{record:_location.record}}});
  details.show();
}});
Ext.define('dilocsync.view.components.importantdocuments.ImportantDocuments', {extend:Ext.Panel, mixins:[cnconsult.Translatable], xtype:'importantdocuments', viewModel:{type:'importantdocuments'}, controller:'importantdocuments', cls:'dilocsync-important-documents', layout:{type:'vbox', align:'stretch'}, initialize:function() {
  this.setItems([{xtype:'component', cls:'dilocsync-sub-header', html:this.tr('Important Documents'), docked:'top'}, {xtype:'filelist', flex:1, scrollable:true, reference:'list', emptyText:this.tr('Currently there are no important documents.'), listeners:{childtap:'onFileTap', childdoubletap:'onFileDoubleTap'}}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.news.NewsController', {extend:Ext.app.ViewController, alias:'controller.news', init:function() {
  var view = this.getView();
  view.on('initialize', this.onViewInitialize, this);
}, onViewInitialize:function() {
  var master = dilocsync.core.Master;
  var identity = dilocsync.core.Master.getIdentity();
  var me = this;
  var almanac, newsFileName, almanacFile, filePath;
  if (identity.options && identity.options.newsFilename) {
    newsFileName = identity.options.newsFilename;
    almanac = master.getAlmanacForPath('customer-data');
    if (almanac) {
      almanacFile = almanac.getRootDirectory().files[newsFileName];
      if (almanacFile) {
        filePath = 'fs-data/' + almanacFile.checksum + '.' + dilocsync.util.File.extension(newsFileName).toLowerCase();
        master.getSyncRoot().getFile(filePath, {create:false}, function(_newsHtmlFileEntry) {
          _newsHtmlFileEntry.file(Ext.bind(function(_newsHtmlFile) {
            var reader = new FileReader;
            reader.onloadend = Ext.bind(function(_event) {
              try {
                var newsBody = /<body.*?>([\s\S]*)<\/body>/.exec(_event.target.result)[1];
                if (newsBody) {
                  me.getViewModel().set('news', newsBody);
                } else {
                  console.log('Could not decode news.');
                }
              } catch (e$96) {
                console.log('Caught exception while parsing news file.', e$96);
              }
            }, this);
            reader.readAsText(_newsHtmlFile);
          }));
        }, function(_error) {
          console.log('Error setting news. Could not open file.', _error);
        });
      } else {
        console.log('Error setting news. No almanac file found for given news file name!', newsFileName, almanac);
      }
    } else {
      console.log('Error setting news. No "customer-data" almanac found!');
    }
  }
}});
Ext.define('dilocsync.view.components.news.NewsModel', {extend:Ext.app.ViewModel, alias:'viewmodel.news', data:{news:''}});
Ext.define('dilocsync.view.components.news.News', {extend:Ext.Container, viewModel:{type:'news'}, controller:'news', xtype:'news', mixins:[cnconsult.Translatable], cls:'dilocsync-news', scrollable:true, layout:{type:'vbox', align:'stretch'}, initialize:function() {
  this.setItems([{xtype:'component', docked:'top', cls:'dilocsync-sub-header', html:this.tr('News')}, {xtype:'component', flex:1, bind:{html:'{news}'}}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.logo.LogoController', {extend:Ext.app.ViewController, alias:'controller.logo', init:function() {
  var view = this.getView();
  view.on('initialize', this.onViewInitialize, this);
}, onViewInitialize:function() {
  var $jscomp$this = this;
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  if (!identity.options || !identity.options.logoFilename) {
    return;
  }
  var logoFilename = identity.options.logoFilename;
  var almanac = master.getAlmanacForPath('customer-data');
  if (!almanac) {
    console.log('Error setting logo. No "customer-data" almanac found!');
    return;
  }
  var almanacFile = almanac.getRootDirectory().files[logoFilename];
  if (!almanacFile) {
    console.log('Error setting logo. No almanac file found for given logo file name!', logoFilename, almanac);
    return;
  }
  var rootFsEntryName = dilocsync.util.File.validateRootDirectoryName(almanacFile.rootFsEntryName);
  var filePath = rootFsEntryName + '/' + almanacFile.checksum + '.' + dilocsync.util.File.extension(logoFilename).toLowerCase();
  master.getSyncRoot().getFile(filePath, {}, function(_logoEntry) {
    _logoEntry.file(function(_logo) {
      var reader = new FileReader;
      reader.onload = function(_event) {
        $jscomp$this.getView().setSrc(_event.target.result);
      };
      reader.readAsDataURL(_logo);
    });
  });
}});
Ext.define('dilocsync.view.components.logo.Logo', {extend:Ext.Img, xtype:'logo', controller:'logo', cls:'dilocsync-logo'});
Ext.define('dilocsync.view.pages.home.Home', {extend:dilocsync.view.pages.Base, xtype:'home', mixins:[cnconsult.Translatable, Ext.mixin.Responsive], controller:'home', responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, getPhoneItems:function() {
  return [{xtype:'toolbar', ui:'logo-toolbar', docked:'top', items:[{xtype:'component', margin:'0 0 0 10', html:'\x3cspan class\x3d"x-fa fa-map-marker" aria-hidden\x3d"true"\x3e\x3c/span\x3e', bind:{hidden:'{!gpsTrackingStarted}', cls:'{gpsSignalClass}'}}, {xtype:'component', cls:'dilocsync-toolbar-logo'}, '-\x3e', {xtype:'button', ui:'toolbar-button', iconCls:'x-fa fa-search', handler:'showSearchPanel'}]}, {xtype:'container', reference:'homeContainer', scrollable:true, padding:16, margin:'20 0 0 0', 
  layout:{type:'vbox', align:'stretch'}, items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('Welcome to DiLoc|Sync')}, {xtype:'logo', reference:'logo', height:80}, {xtype:'syncpanel'}, {xtype:'news', reference:'news', height:400}, {xtype:'importantdocuments', reference:'importantdocuments', listeners:{showfile:'showViewer'}, height:400}, {xtype:'userinfo', margin:'0 0 50 0'}]}, {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', listeners:{back:'showHome'}}];
}, getDesktopViewer:function() {
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    return {xtype:'externalfileopen', reference:'viewer', closable:true, header:{style:{'padding-top':'0'}}};
  }
  return {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', additionalToolbarItems:[{xtype:'button', itemId:'escapeButton', align:'right', iconCls:'x-fa fa-times', handler:'hideViewer', scope:this.getController()}]};
}, getDesktopItems:function() {
  return [{xtype:'toolbar', ui:'logo-toolbar', docked:'top', items:[{xtype:'component', margin:'0 0 0 10', html:'\x3cspan class\x3d"x-fa fa-map-marker" aria-hidden\x3d"true"\x3e\x3c/span\x3e', bind:{hidden:'{!gpsTrackingStarted}', cls:'{gpsSignalClass}'}}, '-\x3e', {xtype:'component', cls:'dilocsync-toolbar-logo'}, '-\x3e', {xtype:'button', ui:'toolbar-button', iconCls:'x-fa fa-search', handler:'showSearchPanel'}]}, {xtype:'container', flex:1, layout:'vbox', margin:'0 20 20 20', items:[{xtype:'component', 
  cls:'dilocsync-header', html:this.tr('Welcome to DiLoc|Sync')}, {xtype:'importantdocuments', reference:'importantdocuments', listeners:{showfile:'showViewer', openFile:'openFile'}, flex:1}, {xtype:'userinfo', height:120}]}, {xtype:'container', flex:2, margin:'20 20 20 0', layout:{type:'vbox', align:'stretch'}, items:[{xtype:'container', height:80, layout:{type:'hbox', align:'strech'}, items:[{xtype:'logo', docked:'right', reference:'logo', width:'50%'}]}, {reference:'viewerContainer', flex:1, layout:'card', 
  items:[{xtype:'news', reference:'news'}, this.getDesktopViewer()]}, {xtype:'container', height:120, layout:{type:'hbox'}, items:[{xtype:'syncpanel', flex:3}]}]}];
}, initialize:function() {
  var items = Ext.os.deviceType === 'Phone' ? this.getPhoneItems() : this.getDesktopItems();
  this.setItems(items);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.imports.ImportsController', {extend:dilocsync.view.pages.BaseController, alias:'controller.imports', init:function() {
  Ext.Viewport.on('orientationchange', this.updateResizeableSizes, this);
}, onDeleteImportedDocument:function(_list, _info) {
  var store = Ext.getStore('Imports');
  var record = _info.record;
  var viewer = this.lookup('viewer');
  var favoritesStore = Ext.getStore('Favorites');
  dilocsync.util.MessageHelper.showConfirm(this.tr('Delete imported file'), this.tr("Do you really want to delete the imported file '%1'?").arg('\x3cb\x3e' + record.get('name') + '\x3c/b\x3e'), function(_btn) {
    if (_btn === 'yes') {
      var master = dilocsync.core.Master;
      var path = 'imports/' + record.get('name');
      master.devicePathExists(path, function(_realPath) {
        if (_realPath) {
          dilocsync.util.File.removeFile(_realPath).then(function(_result) {
            cnconsult.Logger.log({prefix:'ImportsController-\x3eonDeleteImportedDocument', message:'Imported file successfully deleted!'});
            dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.imports.ImportsController', src:'LokaleDokumente', action:'ImportiertesDokumentGelöscht', trackedAt:new Date});
            store.remove(record);
            store.sync();
            var favoriteRecord = favoritesStore.findRecord('uuid', record.get('uuid'));
            if (favoriteRecord) {
              favoritesStore.remove(favoriteRecord);
              favoritesStore.sync();
            }
            viewer.getViewModel().set({name:'-', record:null, path:null, onPageNumber:0, fileExists:true});
          })['catch'](function(_error) {
            cnconsult.Logger.log({prefix:'ImportsController-\x3eonDeleteImportedDocument', message:"Imported file couldn't be deleted!", level:'error', dump:_error});
          });
          console.log('Delete imported file: ' + _realPath);
        } else {
          cnconsult.Logger.log({prefix:'ImportsController-\x3eonDeleteImportedDocument', message:'Imports: File to import not found!', level:'error'});
        }
      });
    } else {
      viewer.getController().showViewer();
    }
  }, this, true);
}});
Ext.define('dilocsync.view.pages.imports.ImportsModel', {extend:Ext.app.ViewModel, alias:'viewmodel.imports'});
Ext.define('dilocsync.view.pages.imports.Imports', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'imports', viewModel:{type:'imports'}, controller:'imports', responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, initialize:function() {
  var elementWidth = screen.width;
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([{xtype:'filelist', store:Ext.getStore('Imports'), items:[{xtype:'titlebar', title:this.tr('Imported Documents'), docked:'top'}], reference:'listPanel', listeners:{childtap:'showViewerFromList'}}, {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', listeners:{back:'showList'}}]);
  } else {
    this.setItems([{xtype:'filelist', store:Ext.getStore('Imports'), items:[{xtype:'titlebar', title:this.tr('Imported documents'), docked:'top', defaults:{ui:'toolbar-button'}, items:[{itemId:'maximize', iconCls:'x-fa fa-expand', align:'right', handler:'maximizeListPanel'}, {itemId:'minimize', iconCls:'x-fa fa-compress', align:'right', handler:'minimizeListPanel', hidden:true}]}], reference:'listPanel', listeners:{childtap:'onShowFileFromList'}, flex:1}, {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), 
    reference:'viewer', listeners:{resize:'onResize'}, resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, flex:2}]);
  }
  this.callParent(arguments);
  var fileList = this.down('filelist');
  if (fileList) {
    fileList.setPlugins({listswiper:{defaults:{width:48}, right:[{iconCls:'x-fa fa-trash', ui:'alt decline', commit:'onDeleteImportedDocument'}]}});
  }
}});
Ext.define('dilocsync.view.pages.locbook.LocBookController', {extend:dilocsync.view.pages.BaseController, alias:'controller.locbook', init:function() {
  this.getView().on('initialize', this.loadLocBook, this);
}, loadLocBook:function() {
  var iframe = this.lookup('locbookiframe');
  if (iframe.getData().src === 'about:blank') {
    iframe.applySrc(this.getView().pageConfig.url, true);
  }
}});
Ext.define('dilocsync.view.pages.locbook.LocBookModel', {extend:Ext.app.ViewModel, alias:'viewmodel.locbook'});
Ext.define('dilocsync.view.pages.locbook.LocBook', {extend:dilocsync.view.pages.Base, xtype:'locbook', viewModel:{type:'locbook'}, controller:'locbook', initialize:function() {
  this.setItems([{xtype:'iframe', reference:'locbookiframe', height:'100%'}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.editride.EditRideModel', {extend:Ext.app.ViewModel, alias:'viewmodel.editride', data:{trackedStations:[]}});
Ext.define('dilocsync.view.components.editride.EditRide', {extend:Ext.Dialog, mixins:[Ext.mixin.Responsive, cnconsult.Translatable], viewModel:{type:'editride'}, closable:true, maskTapHandler:'destroy', layout:{type:'vbox', align:'stretch'}, responsiveConfig:{'phone':{width:'100%', height:'80%'}, 'tablet || desktop':{width:'90%', height:'90%'}}, initialize:function() {
  var trackedStations = Ext.create('Ext.data.ArrayStore');
  trackedStations.setData(this.getViewModel().get('trackedStations'));
  this.setTitle(this.tr('Ride details'));
  this.setItems([{xtype:'grid', flex:1, columns:[{text:this.tr('Id Code'), dataIndex:'idCode', flex:1}, {text:this.tr('Accuracy'), dataIndex:'accuracy', flex:1}, {text:this.tr('Distance'), dataIndex:'distanceBetweenStationAndLocation', flex:1}, {text:this.tr('Updates'), dataIndex:'updateCount', flex:0.4}], store:trackedStations}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.routeknowledge.RouteKnowledgeController', {extend:dilocsync.view.pages.BaseController, alias:'controller.routeknowledge', mixins:[cnconsult.Translatable], init:function() {
  if (!dilocsync.util.Platform.isWindows()) {
    var view = this.getView();
    view.on('initialize', this.loadRailwayKnowledgeManager, this);
  }
}, loadRailwayKnowledgeManager:function() {
  var iframe = this.lookup('railwayknowledgemanageriframe');
  var me = this;
  if (iframe.getData().src === 'about:blank') {
    var master = dilocsync.core.Master;
    var backendUrl = master.getBackendUrl();
    var store = master.getStorage();
    var view = this.getView();
    var viewModel = this.getViewModel();
    view.setMasked({xtype:'loadmask', message:this.tr('Loading Railwayknowledge Manager ...')});
    Ext.Ajax.request({url:backendUrl + '/syncrideknowledge/login', timeout:30000, params:{syncSecret:store.get('core:personalization:syncSecret'), deviceIdCode:store.get('core:deviceIdCode')}, success:function(_response) {
      _response = Ext.decode(_response.responseText, true);
      if (_response && _response.success) {
        var sessionId = _response.result;
        var platform = dilocsync.util.Platform.getPlatform() + '/';
        var url = '/app-railwayknowledge-manager/client-session-login/' + platform + sessionId;
        viewModel.set('errorMessage', '');
        var railwayKnowledgeManagerUrl = backendUrl.substring(0, backendUrl.lastIndexOf('/')) + url;
        if (dilocsync.util.Platform.isWindows()) {
          cordova.InAppBrowser.open(railwayKnowledgeManagerUrl, '_system');
        } else {
          iframe.applySrc(railwayKnowledgeManagerUrl, true);
          window.addEventListener('message', function(_message) {
            if (Ext.isObject(_message.data)) {
              if (_message.data.action === 'viewVideo' && _message.data.url) {
                cordova.InAppBrowser.open(_message.data.url, '_blank', 'location\x3dno,hardwareback\x3dno');
                return;
              }
              if (_message.data.message && _message.data.message === 'Session timeout') {
                me.onSessionTimeoutMessageReceived();
              }
            }
          });
        }
      } else {
        cnconsult.Logger.log({prefix:'RouteKnowledgeController-\x3eloadRailwayKnowledgeManager', message:'Server response while setting up session for Railwayknowledge Manager was not successful', level:'error', dump:_response});
        viewModel.set('errorMessage', this.tr('An error occurred while loading the Railwayknowledge Manager.\x3cbr\x3eIf this problem persists, contact the support.'));
      }
      view.unmask();
    }, failure:function(_response) {
      cnconsult.Logger.log({prefix:'RouteKnowledgeController-\x3eloadRailwayKnowledgeManager', message:'Ajax request failed while setting up session for Railwayknowledge Manager', level:'error', dump:_response});
      viewModel.set('errorMessage', this.tr('Failed to load the Railwayknowledge Manager.\x3cbr\x3ePlease make sure you have internet connection.'));
      view.unmask();
    }, scope:this});
  }
}, onSessionTimeoutMessageReceived:function() {
  var master = dilocsync.core.Master;
  var backendUrl = master.getBackendUrl();
  var store = master.getStorage();
  Ext.Ajax.request({url:backendUrl + '/syncrideknowledge/login', timeout:30000, params:{syncSecret:store.get('core:personalization:syncSecret'), deviceIdCode:store.get('core:deviceIdCode')}, success:function(_response) {
    _response = Ext.decode(_response.responseText, true);
    if (_response && _response.success) {
      var iframe = this.lookup('railwayknowledgemanageriframe');
      var sessionId = _response.result;
      if (iframe && iframe.element) {
        var iframeEl = iframe.element.dom.querySelector('iframe');
        if (iframeEl && iframeEl.contentWindow) {
          var origin = backendUrl.replace('/capsules/syncmanager/backend', '');
          iframeEl.contentWindow.postMessage(sessionId, origin);
        } else {
          cnconsult.Logger.log({prefix:'RouteKnowledge-\x3eonSessionTimeoutMessageReceived', message:'Iframe element or contentWindow is not available.', level:'error'});
        }
      } else {
        cnconsult.Logger.log({prefix:'RouteKnowledge-\x3eonSessionTimeoutMessageReceived', message:'', level:'error'});
        console.error('Iframe component or its associated element is not available.');
      }
    } else {
      cnconsult.Logger.log({prefix:'RouteKnowledge-\x3einitialize', message:'Server response while setting up session for Railwayknowledge Manager was not successful', level:'error', dump:_response});
    }
  }, failure:function(_response) {
    cnconsult.Logger.log({prefix:'RouteKnowledge-\x3einitialize', message:'Ajax request failed while setting up session for Railwayknowledge Manager', level:'error', dump:_response});
  }, scope:this});
}});
Ext.define('dilocsync.view.pages.routeknowledge.RouteKnowledgeModel', {extend:Ext.app.ViewModel, alias:'viewmodel.routeknowledge', data:{errorMessage:''}});
Ext.define('dilocsync.view.pages.routeknowledge.RouteKnowledge', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable], xtype:'routeknowledge', viewModel:{type:'routeknowledge'}, controller:'routeknowledge', initialize:function() {
  var isWindows = dilocsync.util.Platform.isWindows();
  this.setItems([{xtype:'iframe', reference:'railwayknowledgemanageriframe', height:'100%', bind:{hidden:isWindows ? true : '{errorMessage}'}}, {xtype:'container', layout:'center', height:'100%', bind:{hidden:isWindows ? '{errorMessage}' : true}, items:[{xtype:'container', layout:{type:'vbox', align:'center'}, items:[{html:'\x3ch3\x3e' + this.tr('Due to compatibility issues on Windows, the Railwayknowledge Manager cannot be displayed directly in the app.') + '\x3c/h3\x3e'}, {xtype:'button', padding:'10', 
  margin:'10 0', ui:'content-button', text:this.tr('Open Railwayknowledge Manager in browser'), handler:'loadRailwayKnowledgeManager'}]}]}, {xtype:'container', layout:'center', height:'100%', bind:{hidden:'{!errorMessage}'}, items:[{xtype:'panel', layout:{type:'vbox', align:'center'}, items:[{xtype:'component', margin:'0 0 40 0', html:'\x3ci class\x3d"fa fa-times-circle-o"\x3e\x3c/i\x3e', style:'font-size: 80px;color: #FF0000;'}, {xtype:'component', bind:{html:'\x3ch2\x3e{errorMessage}\x3c/h2\x3e'}, 
  style:'text-align: center;'}, {xtype:'button', padding:'10 0 10 0', margin:'10 0 10 0', width:140, ui:'content-button', text:this.tr('Try again'), handler:'loadRailwayKnowledgeManager'}]}]}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.search.SearchPanelModel', {extend:Ext.app.ViewModel, alias:'viewmodel.searchpanel', stores:{searchResultStore:{model:'dilocsync.model.SearchResult', sorters:'name', groupDir:'ASC'}}});
Ext.define('dilocsync.view.pages.search.SearchPanelController', {extend:dilocsync.view.pages.BaseController, alias:'controller.searchpanel', mixins:[cnconsult.Translatable], config:{bufferedSearch:null}, init:function() {
  this.groupStore();
  Ext.Viewport.on('orientationchange', this.updateResizeableSizes, this);
  var identity = dilocsync.core.Master.getIdentity();
  var bufferedSearchDelay = 100;
  if (identity.options && identity.options.hasOwnProperty('bufferedSearchDelay')) {
    bufferedSearchDelay = identity.options.bufferedSearchDelay;
  }
  this.setBufferedSearch(Ext.Function.createBuffered(this.doSearch, bufferedSearchDelay, this));
}, groupStore:function(_tagSearch) {
  _tagSearch = _tagSearch === undefined ? false : _tagSearch;
  this.getStore('searchResultStore').setGrouper({groupFn:Ext.bind(function(_record) {
    if (_tagSearch) {
      return this.tr('File tag search results');
    } else {
      if (_record.get('from') === 'fileNameSearch') {
        return this.tr('File name search results');
      } else {
        return this.tr('Full text search results');
      }
    }
  }, this)});
}, onSearchChange:function(_field, _value) {
  this.getBufferedSearch()(_field, _value);
}, doSearch:function(_field, _value) {
  var searchResultList = this.lookup('listPanel');
  var searchResultStore = this.getStore('searchResultStore');
  searchResultStore.removeAll();
  if (_value.length >= 3) {
    dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.search.SearchPanelController', src:'Home', action:'SucheStarten', trackedAt:new Date, extras:{_value:_value}});
    this.groupStore(_value.startsWith('#'));
    searchResultList.setMasked({xtype:'loadmask', indicator:true, message:this.tr('Searching...')});
    if (this.getView().getFullTextSearch() && this.getView().getFullTextSearch().readyToSearch()) {
      this.searchWithFullTextSearch(_value);
    } else {
      this.filterAlmanacDirectory(_value);
      searchResultStore.sync();
      searchResultList.unmask();
    }
  }
}, searchWithFullTextSearch:function(_searchWord) {
  cnconsult.Logger.log({prefix:'SearchPanelController-\x3esearchWithFullTextSearch', message:'Start full indexed search for: ' + _searchWord});
  this.getView().getFullTextSearch().search(_searchWord, this.onFullTextSearchFinished, this);
  cnconsult.Logger.log({prefix:'SearchPanelController-\x3esearchWithFullTextSearch', message:'Start file name search for: ' + _searchWord});
  this.filterAlmanacDirectory(_searchWord);
}, onFullTextSearchFinished:function(_fullTextSearchResults) {
  cnconsult.Logger.log({prefix:'SearchPanelController-\x3eonFullTextSearchFinished', message:'Sear results', dump:_fullTextSearchResults});
  if (_fullTextSearchResults && _fullTextSearchResults.length > 0) {
    var fullTextSearchResults = [];
    for (var fullTextSearchResultKey in _fullTextSearchResults) {
      if (_fullTextSearchResults.hasOwnProperty(fullTextSearchResultKey)) {
        var fullTextSearchResult = _fullTextSearchResults[fullTextSearchResultKey];
        var searchResultObject = {name:dilocsync.util.File.basename(fullTextSearchResult.filePath), path:fullTextSearchResult.filePath, icon:dilocsync.util.File.extension(fullTextSearchResult.filePath), onPage:fullTextSearchResult.pageIndex, from:'fullTextSearch', size:null, date:null, searchResultCount:0, searchResults:[]};
        var filePathExistsObject = fullTextSearchResults.find(function(_object) {
          return _object.path === fullTextSearchResult.filePath;
        });
        if (filePathExistsObject) {
          if (filePathExistsObject.searchResults.length === 0) {
            filePathExistsObject.searchResults.push(Ext.clone(filePathExistsObject));
          }
          filePathExistsObject.searchResults.push(searchResultObject);
          filePathExistsObject.searchResultCount = filePathExistsObject.searchResults.length;
        } else {
          fullTextSearchResults.push(searchResultObject);
        }
      }
    }
    this.getStore('searchResultStore').add(fullTextSearchResults);
  }
  this.lookup('listPanel').unmask();
}, filterAlmanacDirectory:function(_searchWord) {
  if (_searchWord) {
    var almanacs = dilocsync.core.Master.getAlmanacs();
    Ext.Object.each(almanacs, function(_key, _almanac) {
      if (_key && _key !== 'system') {
        var results = _almanac.getRootDirectory().findFilesRecursively(_searchWord);
        if (results.length > 0) {
          this.getStore('searchResultStore').add(results);
        }
      }
    }, this);
  }
}, onHideSearchPanel:function() {
  this.redirectTo('home');
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    var viewer = this.lookup('viewer');
    viewer.hide();
  }
  this.getView().hide();
}, onFullTextSearchInitialized:function() {
  this.lookup('fullTextSearchState').hide();
}, onListTap:function(_list, _location) {
  var onPage = 0;
  var record = _location.record;
  if (record.get('searchResultCount') > 0) {
    if (record.searchResults().getCount() === 0) {
      record.searchResults().add(record.data.searchResults);
    }
    _list.setStore(record.searchResults());
    this.lookup('searchField').hide();
    this.lookup('subListToolbar').show();
  } else {
    var viewer = this.lookup('viewer');
    if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
      viewer.show();
    }
    if (record && record.get('onPage') && Ext.isNumber(record.get('onPage'))) {
      onPage = record.get('onPage') + 1;
    }
    this.showFile(record, _list, onPage);
    if (Ext.os.deviceType === 'Phone') {
      this.getView().setActiveItem(viewer);
    }
  }
}, backToSearchList:function() {
  var me = this;
  var store = this.getStore('searchResultStore');
  store.clearGrouping();
  me.lookup('listPanel').setStore(store);
  me.lookup('searchField').show();
  me.lookup('subListToolbar').hide();
  me.groupStore();
}});
Ext.define('dilocsync.view.pages.search.SearchPanel', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'searchpanel', controller:'searchpanel', viewModel:{type:'searchpanel'}, cls:'dilocsync-search', responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, config:{fullTextSearch:null}, getViewer:function() {
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    return {xtype:'externalfileopen', reference:'viewer', closable:true, header:{style:{'padding-top':'0'}}, flex:2, hidden:true, listeners:{close:'onHideSearchPanel'}};
  }
  return {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', flex:2, additionalToolbarItems:[{xtype:'button', itemId:'hideSearchButton', align:'right', iconCls:'x-fa fa-times', handler:'onHideSearchPanel', scope:this.getController()}], listeners:{downloadOnDemand:'downloadOnDemand'}};
}, initialize:function() {
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  var searchResult = {xtype:'searchresultlist', reference:'listPanel', flex:1, bind:{store:'{searchResultStore}'}, listeners:{childtap:'onListTap'}, items:[{docked:'top', xtype:'titlebar', reference:'searchTitleBar', title:this.tr('Search')}, {xtype:'searchfield', reference:'searchField', cls:'dilocsync-file-folder-list-search', docked:'top', listeners:{change:{fn:'onSearchChange', buffer:300}, resize:'onResize'}}, {docked:'top', xtype:'toolbar', hidden:true, reference:'subListToolbar', ui:'actions-toolbar', 
  defaults:{ui:'toolbar-actions'}, items:[{text:this.tr('Back'), iconCls:'x-fa fa-chevron-left', handler:'backToSearchList'}]}, {xtype:'component', docked:'bottom', reference:'fullTextSearchState', height:'20px', hidden:true, html:'\x3cdiv class\x3d"fullTextSearchState"\x3e' + this.tr('Initializing full text search...') + '\x3c/div\x3e'}]};
  var fileViewer = this.getViewer();
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([searchResult, Ext.apply(fileViewer, {listeners:{back:'showList', downloadOnDemand:'downloadOnDemand'}})]);
  } else {
    this.setItems([searchResult, Ext.apply(fileViewer, {resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}})]);
  }
  this.callParent(arguments);
  if (Ext.os.deviceType !== 'Phone') {
    this.addMinMaximizeFeatureToToolbar();
  }
  this.setFullTextSearch(dilocsync.core.Master.getFullTextSearch());
  if (this.getFullTextSearch()) {
    if (!this.getFullTextSearch().readyToSearch()) {
      this.lookup('fullTextSearchState').show();
    }
    var me = this;
    this.getFullTextSearch().on('databaseInitialized', 'onFullTextSearchInitialized', me.getController());
  }
}, addMinMaximizeFeatureToToolbar:function() {
  var buttons = [{ui:'toolbar-button', itemId:'maximize', iconCls:'x-fa fa-expand', align:'right', handler:'maximizeListPanel', scope:this.getController()}, {ui:'toolbar-button', itemId:'minimize', iconCls:'x-fa fa-compress', align:'right', handler:'minimizeListPanel', scope:this.getController(), hidden:true}];
  this.lookup('searchTitleBar').add(buttons);
}});
Ext.define('dilocsync.view.pages.shiftjuggler.ShiftJugglerModel', {extend:Ext.app.ViewModel, alias:'viewmodel.shiftjuggler', data:{errorMessage:''}});
Ext.define('dilocsync.view.pages.shiftjuggler.ShiftJugglerController', {extend:Ext.app.ViewController, alias:'controller.shiftjuggler', mixins:[cnconsult.Translatable], startShiftJugglerSession:function() {
  if (this.isUserAuthenticated()) {
    this.retrieveTicket();
  } else {
    var master = dilocsync.core.Master;
    var store = master.getStorage();
    Fingerprint.isAvailable(Ext.bind(function(_authMethod) {
      console.log('The following auth method is available: ', _authMethod);
      Fingerprint.show({title:this.tr('DiLoc|Sync'), subtitle:this.tr('For device owners only'), description:this.tr('Please authenticate to access ShiftJuggler')}, Ext.bind(function(_result) {
        console.log('User successfully authenticated, starting shiftjuggler session.', _result);
        store.set('page:shiftjuggler:lastAuthentication', Math.floor(Date.now() / 1000));
        this.retrieveTicket();
      }, this), Ext.bind(function(_error) {
        console.log('Authentication of user failed', _error.message, _error);
        store.set('page:shiftjuggler:lastAuthentication', false);
        this.showErrorMessage(this.tr('You have to authenticate yourself.'));
      }, this));
    }, this), Ext.bind(function(_error) {
      console.error('Fingerprint.isAvailable error.', _error.message, _error);
      this.showErrorMessage(this.tr('Your device is not secured.\x3cbr\x3eTo access ShiftJuggler, you need a device which is secured with PIN or biometrical data.'));
    }, this), {allowBackup:true});
  }
}, retrieveTicket:function() {
  var master = dilocsync.core.Master;
  var store = master.getStorage();
  Ext.Ajax.request({url:master.getBackendUrl() + '/ssoTicket/generate', timeout:30000, params:{syncSecret:store.get('core:personalization:syncSecret'), deviceIdCode:store.get('core:deviceIdCode')}, success:function(_response) {
    _response = Ext.decode(_response.responseText, true);
    if (_response && _response.success) {
      this.loadShiftJugglerRedirectPage(_response.result.ssoticket);
    } else {
      console.log('Server response while retrieving sso-ticket was not successful', _response);
      this.showErrorMessage(this.tr('An error occurred while retrieving the authentication ticket.\x3cbr\x3eIf this problem persists, contact the support.'));
    }
  }, failure:function(_response) {
    console.log('Ajax request failed while retrieving sso-ticket from server', _response);
    this.showErrorMessage(this.tr('Failed to retrieve the authentication ticket from the server.\x3cbr\x3ePlease make sure you have internet connection.'));
  }, scope:this});
}, loadShiftJugglerRedirectPage:function(_ssoTicket) {
  var $jscomp$this = this;
  var backendUrl = dilocsync.core.Master.getBackendUrl();
  var redirectPageUrl = backendUrl.substring(0, backendUrl.lastIndexOf('/')) + '/app-shiftjuggler-redirect/';
  var ref = cordova.InAppBrowser.open(redirectPageUrl + '?ssoTicket\x3d' + _ssoTicket, '_blank', 'location\x3dno');
  ref.addEventListener('message', function(_message) {
    if (_message.data.hasOwnProperty('error')) {
      ref.close();
      switch(_message.data.error) {
        case 'sso-ticket-missing':
          $jscomp$this.showErrorMessage($jscomp$this.tr('The authentication ticket is missing.\x3cbr\x3ePlease try again.'));
          break;
        case 'sso-ticket-expired':
          $jscomp$this.showErrorMessage($jscomp$this.tr('The authentication ticket has expired.\x3cbr\x3ePlease try again.'));
          break;
        case 'invalid-shiftjuggler-url':
          $jscomp$this.showErrorMessage($jscomp$this.tr('Your company has an invalid URL to the ShiftJuggler page.'));
          break;
        default:
          break;
      }
    }
  });
  this.getView().showPage();
}, isUserAuthenticated:function() {
  var master = dilocsync.core.Master;
  var store = master.getStorage();
  var lastAuthentication = store.get('page:shiftjuggler:lastAuthentication');
  var now = Math.floor(Date.now() / 1000);
  var validFor = 60 * 60;
  return lastAuthentication && now - lastAuthentication < validFor;
}, showErrorMessage:function(_message) {
  this.getViewModel().set('errorMessage', _message);
  this.getView().showError();
}, onHide:function() {
}, onShow:function() {
}});
Ext.define('dilocsync.view.pages.shiftjuggler.ShiftJuggler', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable], xtype:'shiftjuggler', controller:'shiftjuggler', viewModel:{type:'shiftjuggler'}, layout:'card', initialize:function() {
  this.setItems([{xtype:'container', layout:'center', items:[{xtype:'panel', layout:{type:'vbox', align:'center'}, items:[{xtype:'component', margin:'0 0 40 0', html:'\x3cdiv class\x3d"shiftjuggler-logo"\x3e\x3c/div\x3e'}, {xtype:'component', html:'\x3ch3\x3e' + this.tr('Based on some restrictions, ShiftJuggler can currently only accessed via the In-App Browser.\x3cbr\x3ePlease click on the Button below to open ShiftJuggler.') + '\x3c/h3\x3e', style:'text-align: center;'}, {xtype:'button', padding:'10 0 10 0', 
  margin:'10 0 10 0', width:240, ui:'content-button', text:this.tr('Open ShiftJuggler'), handler:'startShiftJugglerSession'}]}]}, {xtype:'container', layout:'center', items:[{xtype:'panel', layout:{type:'vbox', align:'center'}, items:[{xtype:'component', margin:'0 0 40 0', html:'\x3ci class\x3d"fa fa-times-circle"\x3e\x3c/i\x3e', style:'font-size: 80px;color: #FF0000;'}, {xtype:'component', bind:{html:'\x3ch2\x3e{errorMessage}\x3c/h2\x3e'}, style:'text-align: center;'}, {xtype:'button', padding:'10 0 10 0', 
  margin:'10 0 10 0', width:140, ui:'content-button', text:this.tr('Try again'), handler:'startShiftJugglerSession'}]}]}]);
  this.callParent(arguments);
}, showPage:function() {
  this.setActiveItem(0);
}, showError:function() {
  this.setActiveItem(1);
}});
Ext.define('dilocsync.view.pages.syncreports.SyncReportsModel', {extend:Ext.app.ViewModel, alias:'viewmodel.syncreports'});
Ext.define('dilocsync.view.pages.syncreports.SyncReportsController', {extend:dilocsync.view.pages.BaseController, alias:'controller.syncreports', init:function() {
  Ext.Viewport.on('orientationchange', this.updateResizeableSizes, this);
}});
Ext.define('dilocsync.view.components.SyncReportList', {extend:Ext.NestedList, xtype:'syncreportlist', mixins:[cnconsult.Translatable], cls:'dilocsync-sync-report-list', displayField:'name', useTitleAsBackText:false, initialize:function() {
  var me = this;
  this.setListConfig({emptyText:this.tr('Currently there are no items.'), itemCls:'dilocsync-sync-report-list-item', itemTpl:['\x3cdiv class\x3d"dilocsync-sync-report-list-item dilocsync-sync-report-list-item-state-{state}"\x3e', '\x3cdiv class\x3d"dilocsync-sync-report-list-item-name"\x3e', '\x3cspan class\x3d"x-fa \x3ctpl if\x3d"metaUpdate"\x3efa-info dilocsync-sync-report-list-item-refresh\x3ctpl else\x3e{type:this.typeCls}\x3c/tpl\x3e"\x3e\x3c/span\x3e', '\x26nbsp;\x3ctpl if\x3d"title"\x3e{title}\x3ctpl else\x3e{name}\x3c/tpl\x3e', 
  '\x3ctpl if\x3d"unreadCount \x26gt; 0"\x3e\x3cspan class\x3d"dilocsync-sync-report-list-item-unreadcount"\x3e{unreadCount}\x3c/span\x3e\x3c/tpl\x3e', '\x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-sync-report-list-item-path"\x3e', '\x3ctpl if\x3d"path"\x3e{path:this.formatPath}\x3c/tpl\x3e', '\x3c/div\x3e', '\x3ctpl if\x3d"metaUpdate"\x3e', '\x3cdiv class\x3d"dilocsync-sync-report-list-item-meta-update"\x3e', this.tr('Content is the same, there are only meta-data changes!'), '\x3c/div\x3e', '\x3c/tpl\x3e', 
  '\x3ctpl if\x3d"validFrom || validTo" \x3e', '\x3cspan class\x3d"dilocsync-validity"\x3e', '\x3ctpl if\x3d"validFrom" \x3e', '\x26nbsp;', this.tr('Valid from'), '\x26nbsp;', '{validFrom:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3ctpl if\x3d"validTo" \x3e', '\x26nbsp;', '\x3ctpl if\x3d"!validFrom"\x3e', this.tr('Valid'), '\x26nbsp;', '\x3c/tpl\x3e', this.tr('until'), '\x26nbsp;', '{validTo:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3c/span\x3e', '\x3c/tpl\x3e', '\x3c/div\x3e', '\x3ctpl if\x3d"tags"\x3e', '\x3cdiv class\x3d"dilocsync-file-folder-list-item-tags"\x3e{tags:this.getTags}\x3c/div\x3e', 
  '\x3c/tpl\x3e', '\x3c/div\x3e', {typeCls:function(_type) {
    var cls = '';
    switch(_type) {
      case 'new':
        cls = 'fa-plus dilocsync-sync-report-list-item-new';
        break;
      case 'update':
        cls = 'fa-sync dilocsync-sync-report-list-item-refresh';
        break;
      case 'delete':
        cls = 'fa-minus dilocsync-sync-report-list-item-delete';
        break;
      case 'folder':
        cls = 'fa-folder';
        break;
    }
    return cls;
  }, formatPath:Ext.Function.bind(function(_path) {
    if (dilocsync.util.File.extension(_path)) {
      var path = dilocsync.util.File.dirname(_path);
      path = path.replace('/data/', '');
      path = path.replace('data/', '');
      if (path.startsWith('userfilebox/')) {
        path = this.tr('User file box');
      }
      if (path.length > 53) {
        path = '...' + path.substring(path.length - 50, path.length);
      }
      return path;
    } else {
      return '';
    }
  }, this), getTags:function(_tags) {
    return dilocsync.util.File.tagMarkup(_tags);
  }}]});
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.syncreports.SyncReports', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'syncreports', viewModel:{type:'syncreports'}, controller:'syncreports', responsiveConfig:{'phone':{layout:'card'}, 'tablet || desktop':{layout:{type:'hbox', align:'stretch'}}}, getDesktopViewer:function() {
  var elementWidth = dilocsync.util.Screen.getScreenWidth();
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  if (dilocsync.util.Platform.supportsOnlyExternalFileOpen()) {
    return {xtype:'externalfileopen', reference:'viewer', resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, flex:2};
  }
  return {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', resizable:{split:true, edges:'west', maxSize:[maxResizeWidth, null], minSize:[minResizeWidth, null]}, flex:2};
}, initialize:function() {
  var elementWidth = screen.width;
  var maxResizeWidth = elementWidth * 0.85;
  var minResizeWidth = elementWidth * 0.15;
  if (Ext.os.deviceType === 'Phone') {
    this.setItems([{xtype:'syncreportpanel', reference:'listPanel', listeners:{showfile:'showViewer'}}, {xtype:'fileviewer', fileViewer:dilocsync.util.FileViewerHelper.getPrimary(), reference:'viewer', listeners:{back:'showList'}}]);
  } else {
    this.setItems([{xtype:'syncreportpanel', reference:'listPanel', listeners:{showfile:'showFile', openfile:'openFile'}, flex:1}, this.getDesktopViewer()]);
  }
  this.callParent(arguments);
  if (Ext.os.deviceType !== 'Phone') {
    this.addMinMaximizeFeatureToToolbar();
  }
}, addMinMaximizeFeatureToToolbar:function() {
  var buttons = [{ui:'toolbar-button', itemId:'maximize', iconCls:'x-fa fa-expand', align:'right', handler:'maximizeListPanel', scope:this.getController()}, {ui:'toolbar-button', itemId:'minimize', iconCls:'x-fa fa-compress', align:'right', handler:'minimizeListPanel', scope:this.getController(), hidden:true}];
  this.lookup('listPanel').down('syncreportlist titlebar').add(buttons);
}});
Ext.define('dilocsync.view.pages.usersettings.UserSettingsController', {extend:Ext.app.ViewController, alias:'controller.usersettings', mixins:[cnconsult.Translatable], listen:{global:{'multiUserSettingsChanged':'onMultiUserSettingsChanged'}}, init:function() {
  this.hasKnowledges();
  this.onSyncFinished();
  dilocsync.core.Master.getSyncEngine().on('syncfinished', this.onSyncFinished, this);
}, onSyncFinished:function() {
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  this.getViewModel().set('identity', identity);
}, hasKnowledges:function() {
  var userData = dilocsync.core.Master.getPersonalization().getData();
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.usersettings.UserSettingsController', src:'Einstellungen', action:'KenntnisseAbfragen', trackedAt:new Date});
  Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/syncuserknowledge/getUserKnowledges', params:{deviceIdCode:dilocsync.core.Master.deviceIdCode(), syncSecret:dilocsync.core.Master.getStorage().get('core:personalization:syncSecret'), emailOrIdCode:userData.email ? userData.email : userData.userIdCode}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData && responseData.hasOwnProperty('success') && responseData.success) {
      if (responseData.result.groups && responseData.result.groups.length > 0 && responseData.result.knowledges && responseData.result.knowledges.length > 0) {
        this.lookup('knowledges').setHidden(false);
      } else {
        this.lookup('knowledges').setHidden(true);
      }
    } else {
      cnconsult.Logger.log({prefix:'UserSettingsController-\x3ehasKnowledges', message:'Somehow an error occured', level:'error', dump:_response});
    }
  }, failure:function(_failure) {
    cnconsult.Logger.log({prefix:'UserSettingsController-\x3ehasKnowledges', message:'Somehow an error occured', level:'error', dump:_failure});
  }, scope:this});
}, onSaveButtonClicked:function() {
  var userLanguageSettings = this.lookup('userSettingsLanguage');
  if (userLanguageSettings) {
    var languageCode = userLanguageSettings.getViewModel().get('userdata.languageCode');
    if (languageCode) {
      var maskHelper = dilocsync.util.MaskHelper;
      var master = dilocsync.core.Master;
      var messageHelper = dilocsync.util.MessageHelper;
      maskHelper.showLoadingMask(this.tr('Changing language...'));
      Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/syncusersettings/changeLanguage', params:{syncSecret:master.getStorage().get('core:personalization:syncSecret'), deviceIdCode:master.deviceIdCode(), emailOrIdCode:master.getStorage().get('core:personalization:email'), languageCode:languageCode}, success:function(_response) {
        var responseData = Ext.decode(_response.responseText, true);
        if (responseData && responseData.hasOwnProperty('success') && responseData.success && responseData.hasOwnProperty('result') && responseData.result === 'Ok') {
          maskHelper.hideLoadingMask();
          messageHelper.showSuccess(this.tr('Success'), this.tr('You successfully changed the language.'));
          master.getSyncEngine().startSync();
        } else {
          maskHelper.hideLoadingMask();
          messageHelper.showError(this.tr('An error occured while changing the language.'));
        }
      }, failure:function(_failure) {
        maskHelper.hideLoadingMask();
        messageHelper.showError(this.tr('An error occured while changing the language.'));
      }, scope:this});
    } else {
      dilocsync.util.MessageHelper.showError(this.tr('No language selected.'));
    }
  } else {
    dilocsync.util.MessageHelper.showError(this.tr('No language selected.'));
  }
}, onReInitFullTextSearch:function() {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var fullTextSearch = master.getFullTextSearch();
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.usersettings.UserSettingsController', src:'Einstellungen', action:'VolltextsucheReinitialisieren', trackedAt:new Date});
  if (fullTextSearch) {
    storage.set('fulltextsearch:lastUpdated', false);
    dilocsync.util.MessageHelper.showMessage({title:this.tr('Full-Text-Search'), message:this.tr('The reinitialization will be done after next app start. Restart your app to force it directly.'), buttons:[{text:this.tr('Ok'), itemId:'ok', handler:function() {
      this.up('messagebox').destroy();
    }}]});
  }
}, onModifyAreas:function() {
  var helper = dilocsync.util.Identity;
  var master = dilocsync.core.Master;
  var identity = this.getViewModel().get('identity');
  var page = helper.getPageConfigByType(identity, 'dailyla');
  var storage = master.getStorage();
  if (page) {
    var configuredAreas = [].concat($jscomp.arrayFromIterable(page.config.subscribedAreas));
    if (Ext.isArray(page.config.additionalAreas)) {
      configuredAreas.push.apply(configuredAreas, $jscomp.arrayFromIterable(page.config.additionalAreas));
    }
    var dialog = Ext.create('dilocsync.view.components.areadialog.AreaDialog', {viewModel:{data:{configuredAreas:configuredAreas, subscribedAreas:storage.get('page:dailyla:subscribedAreas')}}});
    dialog.on('save', function(_subscribedAreas) {
      storage.set('page:dailyla:subscribedAreas', _subscribedAreas);
      dialog.close();
      dilocsync.util.MessageHelper.showConfirm(this.tr('Saved successfully'), this.tr('The areas were saved successfully.\x3cbr\x3e\x3cbr\x3eThe changes will take effect on the next app start!\x3cbr\x3e\x3cbr\x3e\x3cb\x3eDo you want to reload the app now?\x3c/b\x3e'), function(_btn) {
        if (_btn === 'yes') {
          dilocsync.core.Master.reloadApplication(false);
        }
      }, this);
    }, this);
    dialog.show();
  } else {
    dilocsync.util.MessageHelper.showConfirm(this.tr('No daily la configuration found'), this.tr('No daily la configuration found. Please synchronize and try again.'), function() {
    }, this);
  }
}, removeLocalFavorites:function() {
  dilocsync.util.MessageHelper.showMessage({title:this.tr('Delete favorites'), message:this.tr('Do you really want to delete your local favorites?'), buttons:[{itemId:'no', text:this.tr('No'), handler:function(_button) {
    _button.up('messagebox').destroy();
  }}, {itemId:'yes', text:this.tr('Yes'), handler:function(_button) {
    dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.pages.usersettings.UserSettingsController', src:'Einstellungen', action:'LokaleFavoritenLöschen', trackedAt:new Date});
    var store = Ext.getStore('Favorites');
    if (store) {
      store.each(function(_record) {
        if (_record && _record.get('group') !== 'remote') {
          store.remove(_record);
        }
      });
      store.sync();
      store.group();
    }
    _button.up('messagebox').destroy();
  }, scope:this}]});
}, showEnableMultiUserSupportDialog:function() {
  dilocsync.util.MessageHelper.showMessage({title:this.tr('Enable MultiUserSupport'), message:this.tr('This option can not be deactivated by the client. You will be logged out upon activation. Do you really want to enable MultiUserSupport?'), buttons:[{itemId:'no', text:this.tr('No'), handler:function(_button) {
    _button.up('messagebox').destroy();
  }}, {itemId:'yes', text:this.tr('Yes'), handler:function(_button) {
    _button.up('messagebox').destroy();
    this.enableMultiUserSupport();
  }, scope:this}]});
}, enableMultiUserSupport:function() {
  Ext.Ajax.request({url:dilocsync.core.Master.getBackendUrl() + '/multiUserSupport/activate', params:{syncSecret:dilocsync.core.Master.getStorage().get('core:personalization:syncSecret'), deviceIdCode:dilocsync.core.Master.deviceIdCode()}, success:function(_response) {
    var responseData = Ext.decode(_response.responseText, true);
    if (responseData && responseData.hasOwnProperty('success') && responseData.success) {
      this.onMultiUserConfirmedByServer();
    } else {
      this.logAndConfirmError(_response, 'enableMultiUserSupport', 'Error while activating MultiUserSupport', 'An error occured while enabling MultiUserSupport.');
    }
  }, failure:function(_failure) {
    this.logAndConfirmError(_failure, 'enableMultiUserSupport', 'Error while activating MultiUserSupport', 'An error occured while enabling MultiUserSupport.');
  }, scope:this});
}, onMultiUserConfirmedByServer:function() {
  var storage = dilocsync.core.Master.getStorage();
  storage.removeAllUserSettings();
  storage.set('core:personalized', false);
  dilocsync.util.MultiUserSupport.setEnabled(true);
  var delayUntilSettingsAreSaved = 550;
  setTimeout(function() {
    return dilocsync.core.Master.reloadApplication();
  }, delayUntilSettingsAreSaved);
}, logAndConfirmError:function(err, prefix, title, msg) {
  cnconsult.Logger.log({prefix:'UserSettingsController-\x3e' + prefix, message:'Somehow an error occured', level:'error', dump:err});
  dilocsync.util.MessageHelper.showMessage({title:title, message:msg, buttons:[{itemId:'ok', text:this.tr('Ok'), handler:function(_button) {
    _button.up('messagebox').destroy();
  }}]});
}, onMultiUserSettingsChanged:function() {
  this.getViewModel().set('hideEnableMultiUserSupport', !dilocsync.util.MultiUserSupport.isAvailable());
}, onHide:function() {
}, onShow:function() {
}});
Ext.define('dilocsync.view.pages.usersettings.UserSettingsModel', {extend:Ext.app.ViewModel, alias:'viewmodel.usersettings', mixins:[cnconsult.Translatable], data:{hideFullTextSearchInitButton:true, hideEnableMultiUserSupport:true, disableEnableMultiUserSupportButton:false, identity:{}}, formulas:{hideFullTextSearchInitButton:function(_get) {
  return !dilocsync.util.Platform.supportsFullTextSearch();
}, hideEnableMultiUserSupport:function() {
  return !dilocsync.util.MultiUserSupport.isAvailable();
}, disableEnableMultiUserSupportButton:function() {
  return dilocsync.util.MultiUserSupport.isEnabled() || !dilocsync.util.Platform.supportsMultiuser();
}, hideLaRegionChooser:{bind:'{identity}', get:function(_value) {
  if (Ext.Object.isEmpty(_value)) {
    return true;
  }
  var helper = dilocsync.util.Identity;
  var page = helper.getPageConfigByType(_value, 'dailyla');
  return !page;
}}}});
Ext.define('dilocsync.view.pages.usersettings.UserSettings', {extend:dilocsync.view.pages.Base, mixins:[cnconsult.Translatable], scrollable:'true', xtype:'usersettings', bodyPadding:'8 16 8 16', viewModel:'usersettings', controller:'usersettings', cls:'dilocsync-usersettings', layout:{type:'vbox', align:'stretch'}, initialize:function() {
  this.setItems([{xtype:'toolbar', docked:'top', title:this.tr('User Settings')}, {xtype:'container', layout:{type:'hbox', align:'end'}, items:[{xtype:'user-create-language', reference:'userSettingsLanguage', flex:1, margin:'0 15 0 0'}, {xtype:'button', text:this.tr('Save language'), handler:'onSaveButtonClicked', ui:'content-button', width:135}]}, {xtype:'user-change-password', margin:'15 0 0 0', bodyPadding:0}, {xtype:'user-change-knowledge', hidden:true, reference:'knowledges', margin:'15 0 0 0'}, 
  {xtype:'container', layout:{type:'hbox'}, bind:{hidden:'{hideLaRegionChooser}'}, margin:'15 0 0 0', items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('Daily la areas'), margin:'0 15 0 0', flex:1}, {xtype:'button', text:this.tr('Change areas'), handler:'onModifyAreas', ui:'content-button', width:135}]}, {xtype:'container', layout:{type:'hbox'}, bind:{hidden:'{hideFullTextSearchInitButton}'}, hidden:true, reference:'reinitfulltextsearch', margin:'15 0 0 0', items:[{xtype:'component', 
  cls:'dilocsync-header', html:this.tr('Full-Text-Search'), margin:'0 15 0 0', flex:1}, {xtype:'button', text:this.tr('Reinitialize'), handler:'onReInitFullTextSearch', ui:'content-button', width:135}]}, {xtype:'container', layout:{type:'hbox'}, margin:'15 0 0 0', items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('Favorites'), margin:'0 15 0 0', flex:1}, {xtype:'button', text:this.tr('Delete favorites'), handler:'removeLocalFavorites', ui:'content-button', width:135}]}, {xtype:'container', 
  cls:'dilocsync-header multi-user-support', layout:{type:'hbox'}, margin:'15 0 0 0', bind:{hidden:'{hideEnableMultiUserSupport}'}, items:[{xtype:'component', cls:'dilocsync-header', html:this.tr('MultiUserSupport'), margin:'0 15 0 0', flex:1}, {xtype:'button', cls:'multi-user-support-activation', text:this.tr('Enable'), handler:'showEnableMultiUserSupportDialog', ui:'content-button', width:135, bind:{disabled:'{disableEnableMultiUserSupportButton}'}}]}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.website.List', {extend:Ext.dataview.List, xtype:'websitelist', mixins:[cnconsult.Translatable], cls:'dilocsync-website-list', ui:'website-list', itemTpl:['\x3cdiv class\x3d"dilocsync-website-list-icon"\x3e\x3cimg src\x3d"https://www.google.com/s2/favicons?domain\x3d{url}" /\x3e \x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-website-list-item"\x3e', '\x3cdiv class\x3d"dilocsync-website-list-item-title"\x3e{title}\x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-website-list-item-url"\x3e{url}\x3c/div\x3e', 
'\x3c/div\x3e'], initialize:function() {
  this.setEmptyText(this.tr('Currently there are no items.'));
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.website.WebsiteDataView', {extend:Ext.dataview.Component, xtype:'websiteDataView', mixins:[cnconsult.Translatable], cls:'dilocsync-website-data-view', padding:'0 0 0 20', itemConfig:{cls:'dilocsync-website-data-view-websites', viewModel:true, bind:{tpl:['\x3cdiv class\x3d"dilocsync-website-data-view-item dilocsync-website-data-view-title"\x3e{record.title}\x3c/div\x3e', '\x3cimg class\x3d"dilocsync-website-data-view-image" src\x3d"{record.previewImageUrl}" /\x3e', 
'\x3cdiv class\x3d"dilocsync-website-data-view-item dilocsync-website-data-view-url"\x3e{record.url}\x3c/div\x3e']}}, initialize:function() {
  this.setEmptyText(this.tr('Currently there are no items.'));
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.pages.website.WebsitesController', {extend:Ext.app.ViewController, alias:'controller.website', mixins:[cnconsult.Translatable], onWebsiteTapped:function(_view, _location) {
  if (dilocsync.core.Master.isOnline()) {
    var url = _location.record.data.url;
    if (url && url.indexOf('http') === -1) {
      url = dilocsync.core.Master.devicePath(url);
    }
    cordova.InAppBrowser.open(url, '_system', 'location\x3dyes');
  } else {
    dilocsync.util.MessageHelper.showError(this.tr('For opening a website you need to connect to the internet!'));
  }
}, onHide:function() {
}, onShow:function() {
}});
Ext.define('dilocsync.view.pages.website.Websites', {extend:dilocsync.view.pages.Base, xtype:'website', mixins:[cnconsult.Translatable], controller:'website', layout:'vbox', initialize:function() {
  var identity = dilocsync.core.Master.getIdentity();
  var store = Ext.getStore('websites');
  var view;
  if (identity.options && identity.options.websitesMode && identity.options.websitesMode === 'preview') {
    view = {xtype:'websiteDataView', itemId:'websiteDataView', listeners:{childtap:'onWebsiteTapped', childlongpress:'onWebsiteTapped'}, store:store, flex:1};
  } else {
    view = {xtype:'websitelist', listeners:{childtap:'onWebsiteTapped', childlongpress:'onWebsiteTapped'}, store:store, flex:1};
  }
  this.setItems([{xtype:'toolbar', docked:'top', title:this.tr('Websites')}, view]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.FormList', {extend:Ext.dataview.List, xtype:'formlist', cls:'dilocsync-file-list', ui:'file-list', mixins:[cnconsult.Translatable], deferEmptyText:false, grouped:true, initialize:function() {
  this.setEmptyText(this.tr('Currently there are no forms.'));
  this.setItemTpl(['\x3cdiv class\x3d"form-icon {icon}"\x3e\x3c/div\x3e', '\x3cdiv class\x3d"dilocsync-file-list-item"\x3e', '\x3cdiv class\x3d"dilocsync-file-list-item-name dilocsync-file-list-item-name-centered"\x3e{name}\x3c/div\x3e', '\x3ctpl if\x3d"syncedAt"\x3e', '\x3cspan class\x3d"form-info"\x3e', this.tr('Synchronized at') + ': {syncedAt:this.formatTimestamp}', '\x3c/span\x3e', '\x3ctpl elseif\x3d"savedAt"\x3e', '\x3cspan class\x3d"form-info"\x3e', this.tr('Saved at') + ': {savedAt:this.formatTimestamp}', 
  '\x3c/span\x3e', '\x3ctpl else\x3e', '\x3cspan class\x3d"form-info"\x3e', this.tr('Revision') + ': {version}', '\x3c/span\x3e', '\x3c/tpl\x3e', '\x3c/div\x3e', {formatTimestamp:function(_timestamp) {
    return Ext.Date.format(new Date(_timestamp * 1000), 'd.m.Y, H:i');
  }}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.HorizontalLine', {extend:Ext.field.Container, alias:'widget.horizontalline', layout:'vbox', items:[{xtype:'component', html:'\x3chr\x3e'}]});
Ext.define('dilocsync.view.components.HorizontalTreeMenu', {extend:Ext.Toolbar, xtype:'horizontaltreemenu', config:{store:null}, cls:'dilocsync-horizontal-tree-menu', scrollable:true, updateStore:function(_store, _oldStore) {
  var rootNode = _store.getRoot();
  if (_oldStore) {
    _oldStore.destroy();
    this.removeAll();
  }
  _store.on({'nodeexpand':{fn:this.createMenu, scope:this}});
  rootNode.expand();
}, createMenu:function(_node) {
  this.removeAll();
  if (_node.isLeaf()) {
    this.showChildItems(_node.parentNode, _node);
  } else {
    this.showChildItems(_node);
  }
  if (!_node.isRoot()) {
    if (_node.isLeaf()) {
      this.showRootLineItems(_node.parentNode, true);
    } else {
      this.showRootLineItems(_node, true);
    }
  }
  this.fireEvent('aftercreatemenu', this, _node);
}, showRootLineItems:function(_node, _isActiveNode) {
  var button;
  var divider;
  button = new Ext.Button({cls:_isActiveNode ? 'dilocsync-horizontal-tree-menu-root-line-item dilocsync-horizontal-tree-menu-root-line-item-active' : 'dilocsync-horizontal-tree-menu-root-line-item', ui:'treemenu-button', disabled:_isActiveNode, nodeId:_node.get('id'), node:_node, text:_node.isRoot() ? '' : _node.get('text'), iconCls:_node.isRoot() ? 'x-fa fa-bars' : _node.get('iconCls'), handler:this.onRootLineButtonTap, scope:this});
  divider = new Ext.Component({cls:'x-icon-el x-font-icon x-tool-type-right dilocsync-horizontal-tree-menu-root-line-item-divider'});
  this.insert(0, button);
  this.insert(1, divider);
  if (!_node.isRoot()) {
    this.showRootLineItems(_node.parentNode, false);
  }
}, showChildItems:function(_node, _activeNode) {
  var segmentedButton = Ext.create('Ext.Container', {itemId:'segment', cls:'dilocsync-horizontal-tree-menu-segmented-button'});
  _node.eachChild(function(_currentNode) {
    var button = new Ext.Button({ui:'treemenu-button', nodeId:_currentNode.get('id'), node:_currentNode, pressed:_activeNode && _activeNode.get('id') === _currentNode.get('id'), text:_currentNode.get('text'), iconCls:_currentNode.get('iconCls'), handler:this.onButtonTap, scope:this});
    segmentedButton.add(button);
  }, this);
  this.add(segmentedButton);
}, onRootLineButtonTap:function(_button) {
  var node = _button.node;
  node.collapse(true);
  node.expand();
}, onButtonTap:function(_button) {
  var node = _button.node;
  if (_button.node.isLeaf()) {
    var segment = _button.up('#segment');
    var buttons;
    if (segment) {
      buttons = segment.query('button[id!\x3d' + _button.getId() + ']');
    }
    if (Ext.isArray(buttons)) {
      Ext.Array.each(buttons, function(_currentButton) {
        _currentButton.setPressed(false);
      });
    }
    _button.setPressed(true);
    this.fireEvent('leafitemtap', this, _button, node);
  } else {
    node.expand();
    this.fireEvent('rootlineitemtap', this, _button, node);
  }
}});
Ext.define('dilocsync.view.components.Iframe', {extend:Ext.Component, xtype:'iframe', cls:'dilocsync-iframe', config:{src:'about:blank'}, data:{src:'about:blank'}, tpl:'\x3ciframe src\x3d"{src}" width\x3d"100%" height\x3d"100%" frameborder\x3d"0"\x3e\x3c/iframe\x3e', applySrc:function(_src) {
  this.setData({src:_src});
  return _src;
}, writeHtml:function(_html) {
  var contentWindow = this.el.down('iframe').el.dom.contentWindow;
  contentWindow.scrollTo(0, 0);
  contentWindow.document.open();
  contentWindow.document.write(_html);
  contentWindow.document.close();
}, addEventListener:function(_type, _listener, _options) {
  this.el.down('iframe').el.dom.contentWindow.addEventListener(_type, _listener, _options);
}});
Ext.define('dilocsync.view.components.SignaturePad', {extend:Ext.field.Container, alias:'widget.signaturepad', layout:{type:'vbox', align:'left'}, mixins:[cnconsult.Translatable], initialize:function() {
  this.signaturePadCanvasId = 'signature-pad-' + this.id;
  this.signaturePadContainer = Ext.create('Ext.Component', {style:'border-style: inset;', width:'100%', html:'\x3ccanvas id\x3d' + this.signaturePadCanvasId + '\x3e\x3c/canvas\x3e'});
  this.clearSignaturePadButton = Ext.create('Ext.Button', {text:this.tr('Clear'), ui:'action', alignSelf:'left'});
  this.add([this.signaturePadContainer, this.clearSignaturePadButton]);
  this.callParent(arguments);
}, afterRender:function() {
  var $jscomp$this = this;
  if (SignaturePad) {
    this.signaturePad = new SignaturePad(document.getElementById(this.signaturePadCanvasId), {backgroundColor:'rgba(255, 255, 255, 0)', penColor:'rgb(0, 0, 0)'});
    this.clearSignaturePadButton.on('tap', function() {
      $jscomp$this.signaturePad.clear();
    });
    this.updateSize();
  } else {
    console.error('The SignaturePad module is not loaded!');
  }
  this.callParent(arguments);
}, updateSize:function() {
  var $jscomp$this = this;
  var currentValue = this.getValue();
  var canvas = document.getElementById(this.signaturePadCanvasId);
  canvas.width = 1;
  Ext.defer(function() {
    canvas.width = $jscomp$this.getSize().width - 6;
    $jscomp$this.setValue(currentValue);
  }, 100);
}, setDisabled:function(_value) {
  this.callParent(arguments);
  if (this.signaturePad) {
    this.signaturePad[_value ? 'off' : 'on']();
    this.clearSignaturePadButton.setDisabled(_value);
  }
}, setValue:function(_value) {
  var $jscomp$this = this;
  if (this.signaturePad && _value) {
    Ext.defer(function() {
      var canvas = document.getElementById($jscomp$this.signaturePadCanvasId);
      $jscomp$this.signaturePad.clear();
      $jscomp$this.signaturePad.fromDataURL(_value, {width:canvas.width, height:canvas.height}, function() {
        if ($jscomp$this.lookupViewModel().get('trackResetOnLoad')) {
          $jscomp$this.resetOriginalValue();
        }
      });
    }, 100);
  }
}, getValue:function() {
  if (this.signaturePad && !this.signaturePad.isEmpty()) {
    return this.signaturePad.toDataURL();
  }
  return null;
}, reset:function() {
  if (this.signaturePad) {
    this.signaturePad.clear();
  }
}, markInvalid:function() {
  this.signaturePadContainer.setStyle('border: 2px solid red');
}});
Ext.define('dilocsync.view.components.alert.Alert', {extend:Ext.Container, xtype:'alert', cls:'alert', type:'success', alignment:'top-right', hidden:true, timeout:4000, showAnimation:{type:'slideIn', direction:'left'}, hideAnimation:{type:'slideOut', direction:'right'}, initialize:function() {
  var $jscomp$this = this;
  this.callParent(arguments);
  this.addCls('alert-' + this.getConfig('type'));
  this.addCls('alert-' + this.getConfig('alignment'));
  if (this.getConfig('alignment').endsWith('left')) {
    this.getConfig('showAnimation').setDirection('right');
    this.getConfig('hideAnimation').setDirection('left');
  }
  Ext.defer(function() {
    $jscomp$this.hide();
  }, this.getConfig('timeout'));
  Ext.defer(function() {
    $jscomp$this.destroy();
  }, this.getConfig('timeout') + 1000);
  Ext.defer(function() {
    $jscomp$this.show();
  }, 100);
}});
Ext.define('dilocsync.view.components.areadialog.AreaDialogController', {extend:Ext.app.ViewController, alias:'controller.areadialog', init:function() {
  var viewModel = this.getViewModel();
  var configuredAreas = viewModel.get('configuredAreas');
  var subscribedAreas = viewModel.get('subscribedAreas');
  var store = this.getStore('areas');
  for (var $jscomp$iter$17 = $jscomp.makeIterator(configuredAreas), $jscomp$key$area = $jscomp$iter$17.next(); !$jscomp$key$area.done; $jscomp$key$area = $jscomp$iter$17.next()) {
    var area = $jscomp$key$area.value;
    {
      store.add({'area':area, 'active':Ext.isArray(subscribedAreas) ? subscribedAreas.includes(area) : true});
    }
  }
}, onSavePressed:function() {
  var store = this.getStore('areas');
  var subscribedAreas = [];
  for (var $jscomp$iter$18 = $jscomp.makeIterator(store.getRange()), $jscomp$key$record = $jscomp$iter$18.next(); !$jscomp$key$record.done; $jscomp$key$record = $jscomp$iter$18.next()) {
    var record = $jscomp$key$record.value;
    {
      if (record.get('active')) {
        subscribedAreas.push(record.get('area'));
      }
    }
  }
  this.getView().fireEvent('save', subscribedAreas);
}});
Ext.define('dilocsync.view.components.areadialog.AreaDialogModel', {extend:Ext.app.ViewModel, alias:'viewmodel.areadialog', data:{configuredAreas:[], subscribedAreas:[]}, stores:{areas:{fields:['area', 'active']}}});
Ext.define('dilocsync.view.components.areadialog.AreaDialog', {extend:Ext.Dialog, mixins:[cnconsult.Translatable], viewModel:{type:'areadialog'}, controller:'areadialog', iconCls:'x-fa fa-edit', closable:true, maskTapHandler:'close', layout:{type:'vbox', align:'stretch'}, width:'40%', height:'60%', initialize:function() {
  this.setTitle(this.tr('Modify la area subscription') + '...');
  this.setItems([{xtype:'grid', scrollable:true, emptyText:this.tr('No areas to display'), deferEmptyText:false, flex:1, columns:[{text:this.tr('Area'), dataIndex:'area', flex:3}, {xtype:'checkcolumn', text:this.tr('Active'), dataIndex:'active', flex:1, disabled:true}], listeners:{childtap:function(_grid, _location) {
    var record = _location.record;
    if (record) {
      record.set('active', !record.get('active'));
    }
  }}, bind:{store:'{areas}'}}, {xtype:'button', text:this.tr('Save'), handler:'onSavePressed', ui:'content-button'}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.digitalorder.DigitalOrderController', {extend:Ext.app.ViewController, alias:'controller.digitalorder', mixins:[cnconsult.Translatable], listen:{global:{nightMode:function(_enable) {
  this.getViewModel().set('nightMode', _enable);
}, startDigitalOrder:function() {
  this.getViewModel().set('loggedOut', false);
}, loggedOut:function() {
  this.getViewModel().set('loggedOut', true);
}}}, init:function() {
  var $jscomp$this = this;
  var viewModel = this.getViewModel();
  var store = dilocsync.util.Helper.initStore('DigitalOrders');
  viewModel.setStores({digitalOrdersStore:store});
  store.on('load', function(_store) {
    return $jscomp$this.onLoad(_store);
  });
  store.on('update', function() {
    return $jscomp$this.updatePageStates();
  });
  this.getView().on('initialize', function() {
    return $jscomp$this.onLoad(store);
  });
  if (dilocsync.util.FileViewerHelper.getViewersInNightMode() || dilocsync.util.PdfViewerHelper.getViewersInNightMode()) {
    viewModel.set('nightMode', true);
  }
}, onLoad:function(_store) {
  var viewModel = this.getViewModel();
  var record = viewModel.get('record') || _store.getAt(0);
  viewModel.set('record', record);
  this.lookup('pagination').getViewModel().set({currentPage:_store.indexOf(record) + 1, pageCount:_store.getCount()});
  this.updatePageStates();
}, onShow:function() {
  var storage = dilocsync.core.Master.getStorage();
  this.getViewModel().set({operationMode:storage.get('page:driveInfo:digitalOrderMode'), trainNumber:storage.get('page:driveInfo:trainNumber')});
}, onPageChanged:function(_newPage) {
  var $jscomp$this = this;
  var viewModel = this.getViewModel();
  var iframe = this.lookup('iframe');
  var store = viewModel.get('digitalOrdersStore');
  var record = store.getAt(_newPage - 1);
  viewModel.set('record', record);
  if (record) {
    iframe.writeHtml(record.get('html'));
    iframe.addEventListener('load', function(ev) {
      return $jscomp$this.checkRead(ev.currentTarget);
    });
    iframe.addEventListener('scroll', function(ev) {
      return $jscomp$this.checkRead(ev.currentTarget);
    });
    iframe.addEventListener('resize', function(ev) {
      return $jscomp$this.checkRead(ev.currentTarget);
    });
  } else {
    iframe.applySrc('about:blank');
  }
}, updatePageStates:function() {
  var store = this.getViewModel().get('digitalOrdersStore');
  var pageStates = {};
  for (var i = 0; i < store.getCount(); i++) {
    switch(store.getAt(i).get('state')) {
      case 'New':
      case 'AcknowledgementReset':
        pageStates[i + 1] = 'error';
        break;
      case 'Acknowledged':
        pageStates[i + 1] = 'warning';
        break;
    }
  }
  this.lookup('pagination').getViewModel().set({pageStates:pageStates});
}, changeState:function() {
  var record = this.getViewModel().get('record');
  switch(record.get('state')) {
    case 'New':
    case 'AcknowledgementReset':
      record.acknowledge();
      break;
    case 'Acknowledged':
      record.markCompleted();
      break;
    case 'Completed':
      record.markUncompleted();
      break;
  }
}, checkRead:function(_iframe) {
  var doc = _iframe.document.documentElement;
  var values = {clientHeight:doc.clientHeight, scrollHeight:doc.scrollHeight, scrollTop:doc.scrollTop};
  if (dilocsync.util.Platform.isWindows()) {
    values.scrollTop = _iframe.document.body.scrollTop;
  }
  if (values.scrollHeight > 0 && values.scrollTop + values.clientHeight >= values.scrollHeight - 1) {
    var record = this.getViewModel().get('record');
    if (record && !record.get('read')) {
      record.set('read', true);
      record.commit();
    }
  }
}, toggleNightMode:function() {
  var viewModel = this.getViewModel();
  viewModel.set('nightMode', !viewModel.get('nightMode'));
  if (dilocsync.util.Platform.isWindows()) {
    dilocsync.util.PdfViewerHelper.enableNightMode(viewModel.get('nightMode'));
  } else {
    dilocsync.util.FileViewerHelper.enableNightMode(viewModel.get('nightMode'));
  }
}});
Ext.define('dilocsync.view.components.digitalorder.DigitalOrderModel', {extend:Ext.app.ViewModel, alias:'viewmodel.digitalorder', mixins:[cnconsult.Translatable], data:{record:null, userRole:null, expanded:false, nightMode:false, operationMode:null, trainNumber:null, loggedOut:false}, stores:{digitalOrdersStore:{}}, formulas:{trainInfo:{bind:'{trainNumber}', get:function(_trainNumber) {
  if (_trainNumber) {
    return this.tr('Train %1').arg('\x3cb\x3e' + _trainNumber + '\x3c/b\x3e') + ' -';
  }
  return '';
}}, panelHeader:{bind:{bindTo:'{record}', deep:true}, get:function(_record) {
  if (_record) {
    var stateText;
    switch(_record.get('state')) {
      case 'New':
        stateText = this.tr('New');
        break;
      case 'AcknowledgementReset':
        stateText = '\x3cspan\x3e' + this.tr('ACKNOWLEDGEMENT RESET!') + '\x3c/span\x3e';
        break;
      case 'Acknowledged':
        stateText = this.tr('Acknowledged');
        break;
      case 'Completed':
        stateText = this.tr('Completed');
        break;
      case 'Revoked':
        stateText = this.tr('Revoked');
        break;
    }
    var store = this.get('digitalOrdersStore');
    return this.tr('Order %1 of %2 - %3').arg('\x3cb\x3e' + (store.indexOf(_record) + 1) + '\x3c/b\x3e', '\x3cb\x3e' + store.getCount() + '\x3c/b\x3e', '\x3cb\x3e' + stateText + '\x3c/b\x3e');
  }
  return this.tr('No orders');
}}, modeText:{bind:'{operationMode}', get:function(_mode) {
  switch(_mode) {
    case 'test':
      return '- \x3cb class\x3d"mode--test"\x3e' + this.tr('Test') + '\x3c/b\x3e';
    case 'demo':
      return '- \x3cb class\x3d"mode--demo"\x3e' + this.tr('Demo') + '\x3c/b\x3e';
    default:
      return '';
  }
}}, buttonIcon:{bind:'{record.state}', get:function(_state) {
  switch(_state) {
    case 'New':
    case 'AcknowledgementReset':
      return 'x-fa fa-check';
    case 'Acknowledged':
      return 'x-fa fa-check-double';
    case 'Completed':
      return 'x-fa fa-undo-alt';
    default:
      return '';
  }
}}, statusCls:{bind:{bindTo:'{digitalOrdersStore}', deep:true}, get:function(_store) {
  if (_store) {
    if (_store.query('state', 'New').length > 0 || _store.query('state', 'AcknowledgementReset').length > 0) {
      return 'state--unconfirmed';
    } else {
      if (_store.query('state', 'Acknowledged').length > 0) {
        return 'state--acknowledged';
      }
    }
  }
  return '';
}}}});
Ext.define('dilocsync.view.components.digitalorder.DigitalOrder', {extend:Ext.Panel, xtype:'digitalorder', mixins:[cnconsult.Translatable], viewModel:{type:'digitalorder'}, controller:'digitalorder', cls:'digital-order', bind:{bodyCls:'{statusCls} {nightMode ? "night-mode" : ""}'}, listeners:{show:'onShow'}, layout:{type:'vbox', align:'stretch'}, initialize:function() {
  this.setItems([{xtype:'container', reference:'overlay', cls:'overlay', modal:true, centered:true, shadow:true, padding:20, width:'60%', items:[{xtype:'component', html:this.tr('Another user has taken over the role of "Leading train driver".') + '\x3cbr\x3e\x3cb\x3e' + this.tr('You have been forcibly logged out.') + '\x3c/b\x3e', margin:10}, {xtype:'button', text:this.tr('Ok'), ui:'content-button', margin:'0 20 0 0', padding:'0 20', handler:function() {
    dilocsync.util.DigitalOrderHelper.stop();
  }}, {xtype:'button', text:this.tr('Take over again'), ui:'content-button', padding:'0 10', handler:function() {
    dilocsync.util.DigitalOrderHelper.start(true);
  }}], bind:{hidden:'{!loggedOut}'}}, {bind:{html:'{trainInfo} {panelHeader} {modeText}', cls:'header', style:{opacity:"{record.state \x3d\x3d\x3d 'Completed' ? 0.5 : 1 }"}}}, {xtype:'container', layout:{type:'hbox', align:'stretch'}, flex:1, items:[{xtype:'iframe', reference:'iframe', flex:2, hidden:true, bind:{hidden:'{!record}', style:{opacity:"{record.state \x3d\x3d\x3d 'Completed' ? 0.5 : 1 }"}}}, {xtype:'container', items:[{xtype:'button', ui:'content-button', cls:'status-button', bind:{iconCls:'{buttonIcon}', 
  hidden:'{record.targetState}', disabled:'{!record.read}'}, handler:'changeState'}, {html:'\x3cspan class\x3d"loader"\x3e\x3c/span\x3e', hidden:true, bind:{hidden:'{!record.targetState}'}}, {xtype:'button', ui:'content-button', cls:'status-button', bind:{iconCls:'x-fa {nightMode ? "fa-sun" : "fa-moon"}'}, handler:'toggleNightMode'}], hidden:true, bind:{hidden:'{!record || record.isRevoked || userRole !\x3d\x3d "LeadingTrainDriver"}'}}, {html:'\x3ch3 class\x3d"no-data"\x3e' + this.tr('Currently there are no orders.') + 
  '\x3c/h3\x3e', bind:{hidden:'{record}'}}]}, {html:'\x3ci class\x3d"fa fa-angle-double-down"\x3e\x3c/i\x3e' + this.tr('More content') + '\x3ci class\x3d"fa fa-angle-double-down"\x3e\x3c/i\x3e', cls:'scroll-indicator', hidden:true, bind:{hidden:'{!record || record.isRevoked || record.read || userRole !\x3d\x3d "LeadingTrainDriver"}'}}, {xtype:'pagination', reference:'pagination', listeners:{pageChanged:'onPageChanged'}, hidden:true, bind:{hidden:'{!record}'}}, {xtype:'digitalordertoolbarslim', reference:'digitalordertoolbarslim', 
  docked:'bottom', hidden:true, bind:{hidden:'{!expanded}'}}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.digitalorder.toolbar.Toolbar', {extend:Ext.Container, xtype:'digitalordertoolbar', mixins:[cnconsult.Translatable], viewModel:{type:'digitalordertoolbar'}, controller:'digitalordertoolbar', cls:'digital-order-toolbar', initialize:function() {
  var $jscomp$this = this;
  this.setItems([{bind:{html:this.tr('Currently valid orders') + ':\x3cspan\x3e{currentOrders}\x3c/span\x3e\x3cspan class\x3d"warning"\x3e{notConfirmedOrders}\x3c/span\x3e', hidden:'{!digitalOrderStarted || loggedOut}', cls:'current-orders {notConfirmedOrders \x3e 0 ? "has-unconfirmed" : ""}'}}, {cls:'last-update', bind:{hidden:'{!digitalOrderStarted || loggedOut}'}, items:[{bind:{html:this.tr('Last updated') + ': {lastUpdateText}'}}, {xtype:'button', cls:'refresh-button', iconCls:'x-fa fa-sync-alt', 
  ui:'toolbar-button', bind:{hidden:'{!digitalOrderStarted || loggedOut}', disabled:'{isLoading}'}, handler:function() {
    Ext.getStore('DigitalOrders').load(true);
  }}]}, {xtype:'container', layout:{type:'hbox', align:'stretch'}, items:[{cls:'logged-out', html:this.tr('Forced logout!'), listeners:{click:{element:'element', fn:function() {
    $jscomp$this.getController().redirectTo('drivemode');
  }}}}], bind:{hidden:'{!loggedOut}'}}, {cls:'inactive', html:'\x3cspan class\x3d"x-fa fa-exclamation-triangle"\x3e\x3c/span\x3e' + this.tr('ÖBB-Befehl') + ':', bind:{hidden:'{digitalOrderStarted}'}}, {cls:'inactive', html:this.tr('Not logged in!'), bind:{hidden:'{digitalOrderStarted}'}}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.digitalorder.toolbar.ToolbarController', {extend:Ext.app.ViewController, alias:'controller.digitalordertoolbar', mixins:[cnconsult.Translatable], listen:{global:{startDigitalOrder:function() {
  this.getViewModel().set('loggedOut', false);
}, loggedOut:function() {
  this.getViewModel().set('loggedOut', true);
}}}, init:function() {
  var viewModel = this.getViewModel();
  var lastUpdatedTask = Ext.TaskManager.newTask({interval:1000 * 10, scope:this, run:function() {
    var lastUpdated = viewModel.get('lastUpdated');
    viewModel.set('lastUpdated', lastUpdated ? new Date(lastUpdated) : null);
    if (!viewModel.get('isLoading')) {
      Ext.getStore('DigitalOrders').load(true);
    }
  }});
  viewModel.bind('{digitalOrderStarted}', function(_digitalOrderStarted) {
    lastUpdatedTask[_digitalOrderStarted ? 'start' : 'stop']();
  });
  dilocsync.util.Helper.initStore('DigitalOrders').on({beforeload:{fn:function() {
    viewModel.set('isLoading', true);
  }}, load:{fn:function(_store) {
    viewModel.set({currentOrders:_store.getCount(), notConfirmedOrders:_store.query('state', 'New').length, lastUpdated:new Date, isLoading:false});
  }}, update:{fn:function(_store) {
    viewModel.set('notConfirmedOrders', _store.query('state', 'New').length);
  }}, refresh:{fn:function() {
    viewModel.set({lastUpdated:new Date, isLoading:false});
  }}, loaderror:{fn:function() {
    viewModel.set('isLoading', false);
  }}});
}});
Ext.define('dilocsync.view.components.digitalorder.toolbar.ToolbarModel', {extend:Ext.app.ViewModel, alias:'viewmodel.digitalordertoolbar', mixins:[cnconsult.Translatable], data:{currentOrders:0, notConfirmedOrders:0, lastUpdated:null, isLoading:false, loggedOut:false}, formulas:{lastUpdateText:{bind:{bindTo:'{lastUpdated}', deep:true}, get:function(_lastUpdated) {
  if (_lastUpdated === null) {
    return this.tr('Never');
  } else {
    var diff = ((new Date).getTime() - _lastUpdated.getTime()) / 1000;
    if (diff < 60) {
      return this.tr('Just now');
    } else {
      if (diff < 120) {
        return this.tr('1 minute ago');
      } else {
        if (diff < 3600) {
          return this.tr('%1 minutes ago').arg(Math.floor(diff / 60));
        } else {
          if (diff < 7200) {
            return this.tr('1 hour ago');
          } else {
            return this.tr('%1 hours ago').arg(Math.floor(diff / 60 / 60));
          }
        }
      }
    }
  }
}}}});
Ext.define('dilocsync.view.components.digitalorder.toolbar.ToolbarSlim', {extend:Ext.Container, xtype:'digitalordertoolbarslim', mixins:[cnconsult.Translatable], viewModel:{type:'digitalordertoolbar'}, cls:'digital-order-toolbar-slim', initialize:function() {
  this.setItems([{bind:{html:this.tr('Orders') + ':\x3cspan\x3e{currentOrders}\x3c/span\x3e\x3cspan class\x3d"warning"\x3e{notConfirmedOrders}\x3c/span\x3e', cls:'current-orders {notConfirmedOrders \x3e 0 ? "has-unconfirmed" : ""}'}}, {cls:'last-update', items:[{bind:{html:this.tr('Updated') + ': {lastUpdateText}'}}, {xtype:'button', cls:'refresh-button', iconCls:'x-fa fa-sync-alt', ui:'toolbar-button', bind:{disabled:'{isLoading}'}, handler:function() {
    Ext.getStore('DigitalOrders').load(true);
  }}]}]);
  this.callParent(arguments);
  this.on('initialize', function(_view) {
    Ext.Viewport.down('digitalordertoolbar').getViewModel().bind({currentOrders:'{currentOrders}', notConfirmedOrders:'{notConfirmedOrders}', lastUpdated:'{lastUpdated}', lastUpdateText:'{lastUpdateText}', isLoading:'{isLoading}'}, function(_values) {
      _view.getViewModel().set(_values);
    });
  });
}});
Ext.define('dilocsync.view.components.dossier.list.ListController', {extend:Ext.app.ViewController, alias:'controller.dossierList', mixins:[cnconsult.Translatable], init:function() {
  var view = this.getView();
  Ext.getStore('Dossiers').on('datachanged', function(store) {
    var activeView = view.getActiveItem();
    if (activeView) {
      activeView.getStore().sort('addedAt', 'DESC');
    }
    var currentNode = view.getLastNode();
    var storeNode = currentNode && store.getById(currentNode.id);
    if (currentNode && currentNode.id !== 'root' && (!storeNode || storeNode.erased)) {
      view.goToNode(store.getRoot());
    }
  });
}, onJumpToPage:function(_list, _info) {
  dilocsync.util.MessageHelper.showPrompt(this.tr('Open file on page number'), this.tr('Please enter the page number you like to open'), function(_buttonId, _pageNumber) {
    if (_buttonId === 'ok') {
      _list.fireEvent('showfile', _info.record, _list, parseInt(_pageNumber));
    }
  }, this);
}, onDeleteFromDossier:function(_list, _info) {
  var deleteTitle = _info.record.get('leaf') ? this.tr('Delete file from dossier') : this.tr('Delete dossier');
  var deleteMessage = _info.record.get('leaf') ? this.tr('Do you really want to delete this file from the dossier?') : this.tr('Do you really want to delete this dossier?');
  dilocsync.util.MessageHelper.showMessage({title:deleteTitle, message:deleteMessage, buttons:[{itemId:'no', text:this.tr('No'), handler:function(_button) {
    _button.up('messagebox').destroy();
  }}, {itemId:'yes', text:this.tr('Yes'), handler:function(_button) {
    var $jscomp$this = this;
    var store = Ext.getStore('Dossiers');
    var record = _info.record;
    var parent = record.parentNode;
    record.remove(true, true);
    store.remove(record);
    store.sync();
    if (!parent.hasChildNodes()) {
      Ext.defer(function() {
        $jscomp$this.getView().goToNode(store.getRoot());
      }, 200);
    }
    _button.up('messagebox').destroy();
  }, scope:this}]});
}});
Ext.define('dilocsync.view.components.dossier.list.List', {extend:dilocsync.view.components.FileFolderList, mixins:[cnconsult.Translatable], xtype:'dossierList', controller:'dossierList', itemId:'dossiersList', initialize:function() {
  this.setTitle(this.tr('Dossiers'));
  this.callParent(arguments);
  this.setListConfig(Ext.apply(this.getListConfig(), {emptyText:this.tr('Currently there are no dossiers.'), plugins:{listswiper:{defaults:{width:48}, right:[{iconCls:'x-fa fa-arrow-right', ui:'alt action', commit:'onJumpToPage'}, {iconCls:'x-fa fa-trash', ui:'alt decline', commit:'onDeleteFromDossier'}]}}}));
}});
Ext.define('dilocsync.view.components.pdfviewer.PdfViewerModel', {extend:Ext.app.ViewModel, alias:'viewmodel.pdfviewer'});
Ext.define('dilocsync.view.components.searchdialog.SearchDialogController', {extend:Ext.app.ViewController, alias:'controller.searchdialog', mixins:[cnconsult.Translatable], config:{bufferedSearch:null}, isIndexing:false, searchResults:[], init:function() {
  var $jscomp$this = this;
  this.setBufferedSearch(Ext.Function.createBuffered(this.doSearch, 500, this));
  this.getStore('searchResults').setGrouper({groupFn:function(_record) {
    return $jscomp$this.tr('Page %1').arg(_record.get('page'));
  }, property:'page', sorterFn:function(_record1, _record2) {
    var page1 = _record1.get('page').toString().match(/\d+/);
    var page2 = _record2.get('page').toString().match(/\d+/);
    return page1[0] - page2[0];
  }});
}, doSearch:function() {
  var $jscomp$this = this;
  if (!this.isIndexing) {
    var viewModel = this.getViewModel();
    var pdfDoc = viewModel.get('pdfDoc');
    var checksum = viewModel.get('checksum');
    var pdfViewerHelper = dilocsync.util.PdfViewerHelper;
    var promises = [];
    var indexPromise = new Promise(function(_resolve, _reject) {
      var cachedTextContent = pdfViewerHelper.loadCachedTextContent(checksum);
      if (cachedTextContent) {
        _resolve(cachedTextContent);
      } else {
        var pageCount = 1;
        $jscomp$this.isIndexing = true;
        var $jscomp$loop$106 = {};
        $jscomp$loop$106.i = 1;
        for (; $jscomp$loop$106.i <= pdfDoc.numPages; $jscomp$loop$106 = {i:$jscomp$loop$106.i}, $jscomp$loop$106.i++) {
          promises.push(new Promise(function($jscomp$loop$106) {
            return function(_resolve, _reject) {
              pdfDoc.getPage($jscomp$loop$106.i).then(function(page) {
                page.getTextContent().then(function(_content) {
                  viewModel.set('emptyText', $jscomp$this.tr('Pdf is indexing. Please wait... (%1%)').arg(Math.round(pageCount++ / pdfDoc.numPages * 100)));
                  _resolve({page:$jscomp$loop$106.i, items:_content.items});
                });
              });
            };
          }($jscomp$loop$106)));
        }
        Promise.all(promises).then(function(_results) {
          cachedTextContent = {};
          _results.forEach(function(_result) {
            cachedTextContent[_result.page] = Ext.Array.clean(Ext.Array.pluck(_result.items, 'str'));
          });
          pdfViewerHelper.cacheTextContent(checksum, cachedTextContent);
          _resolve(cachedTextContent);
        });
      }
    });
    indexPromise.then(function(_textContent) {
      $jscomp$this.isIndexing = false;
      var searchValue = $jscomp$this.lookup('searchField').getValue().trim().toLowerCase();
      var store = viewModel.getStore('searchResults');
      store.removeAll();
      if (searchValue.length > 2) {
        Ext.Object.each(_textContent, function(_page, _texts) {
          _texts.forEach(function(_text) {
            if (_text.toLowerCase().includes(searchValue)) {
              store.add({page:_page, text:_text});
            }
          });
        });
        if (store.getCount() === 0) {
          viewModel.set('emptyText', $jscomp$this.tr('No results found matching your search query'));
        }
      } else {
        viewModel.set('emptyText', '');
      }
      var grouper = store.getGrouper();
      store.setGrouper(null);
      store.setGrouper(grouper);
    });
  }
}});
Ext.define('dilocsync.view.components.searchdialog.SearchDialogModel', {extend:Ext.app.ViewModel, alias:'viewmodel.searchdialog', data:{pdfDoc:null, checksum:null, emptyText:''}, stores:{searchResults:{fields:['page', 'text']}}});
Ext.define('dilocsync.view.components.searchdialog.SearchDialog', {extend:Ext.Dialog, mixins:[cnconsult.Translatable], viewModel:{type:'searchdialog'}, controller:'searchdialog', iconCls:'x-fa fa-search', closable:true, maskTapHandler:'close', closeAction:'hide', layout:{type:'vbox', align:'stretch'}, width:'70%', height:'90%', initialize:function() {
  var $jscomp$this = this;
  this.setTitle(this.tr('Search') + '...');
  this.setItems([{xtype:'textfield', reference:'searchField', label:this.tr('Please enter at least 3 characters to search for'), listeners:{change:this.getController().getBufferedSearch()}}, {xtype:'grid', scrollable:true, deferEmptyText:false, hideHeaders:true, flex:1, style:'border: 1px solid black', columns:[{dataIndex:'text', flex:1}], listeners:{childtap:function(_grid, _location) {
    if (_location.record) {
      $jscomp$this.close();
      $jscomp$this.fireEvent('selectpage', _location.record.get('page'));
    }
  }}, bind:{store:'{searchResults}', emptyText:'{emptyText}'}}]);
  this.callParent(arguments);
  Ext.defer(function() {
    $jscomp$this.lookup('searchField').focus();
  }, 500);
}});
Ext.define('dilocsync.view.components.pdfviewer.PdfViewerController', {extend:Ext.app.ViewController, alias:'controller.pdfviewer', mixins:[cnconsult.Translatable], pdfjsLib:window['pdfjs-dist/build/pdf'], pdfDoc:null, pageNum:1, scale:1, renderPending:null, searchDialog:null, loadingTask:null, loadPdf:function(_path, _page) {
  var $jscomp$this = this;
  if (this.loadingTask) {
    this.loadingTask.destroy().then(function() {
      $jscomp$this.loadingTask = null;
      $jscomp$this.loadPdf(_path, _page);
    });
    return;
  }
  var view = this.getView();
  view.setMasked(true);
  this.scale = 1;
  this.pageNum = _page ? _page + 1 : 1;
  if (this.searchDialog) {
    this.searchDialog.destroy();
    this.searchDialog = null;
  }
  this.loadingTask = this.pdfjsLib.getDocument(_path);
  this.loadingTask.promise.then(function(pdfDoc_) {
    $jscomp$this.pdfDoc = pdfDoc_;
    cnconsult.Logger.log({prefix:'PdfViewerController-\x3eloadPdf', message:'Got pdf.'});
    $jscomp$this.renderPage();
  })['catch'](function(error) {
    cnconsult.Logger.log({prefix:'PdfViewerController-\x3eloadPdf', message:'Error while loading pdf.', level:'error', dump:error});
    var view = $jscomp$this.getView();
    view.setMasked(false);
  });
}, renderPage:function() {
  var $jscomp$this = this;
  var view = this.getView();
  if (this.pageRendering) {
    this.renderPending = true;
    view.setMasked(false);
  } else {
    var canvasCmp = this.lookup('canvasCmp').el;
    canvasCmp.select('.pdf-annotation').remove();
    view.setMasked(true);
    this.pageRendering = true;
    this.pdfDoc.getPage(this.pageNum).then(function(page) {
      var canvas = $jscomp$this.getView().el.down('canvas').dom;
      var viewport = page.getViewport({scale:$jscomp$this.scale});
      canvas.height = viewport.height;
      canvas.width = viewport.width;
      canvas.scrollIntoView();
      canvasCmp.select('#annotationLayer').setSize(viewport.width, viewport.height);
      $jscomp$this.lookup('zoom').setValue($jscomp$this.scale * 100 + '%');
      $jscomp$this.lookup('pageNumber').setHtml($jscomp$this.pageNum + '\x3cspan class\x3d"page-divider"\x3e\x3c/span\x3e' + $jscomp$this.pdfDoc.numPages);
      var renderTask = page.render({canvasContext:canvas.getContext('2d'), viewport:viewport});
      renderTask.promise.then(function() {
        page.getAnnotations().then(function(annotations) {
          annotations.forEach(function(annotation) {
            var promise = new Promise(function(_resolve, _reject) {
              if (Ext.isArray(annotation.dest)) {
                $jscomp$this.pdfDoc.getPageIndex(annotation.dest[0]).then(function(_index) {
                  _resolve(_index + 1);
                });
              } else {
                if (Ext.isString(annotation.dest)) {
                  $jscomp$this.pdfDoc.getDestination(annotation.dest).then(function(dest) {
                    $jscomp$this.pdfDoc.getPageIndex(dest[0]).then(function(_index) {
                      _resolve(_index + 1);
                    });
                  });
                } else {
                  if (annotation.url) {
                    _resolve(annotation.url);
                  } else {
                    _reject();
                  }
                }
              }
            });
            promise.then(function(_result) {
              var rect = $jscomp$this.pdfjsLib.Util.normalizeRect([annotation.rect[0], page.view[3] - annotation.rect[1] + page.view[1], annotation.rect[2], page.view[3] - annotation.rect[3] + page.view[1]]);
              var $jscomp$destructuring$var10 = $jscomp.makeIterator([annotation.rect[2] - annotation.rect[0], annotation.rect[3] - annotation.rect[1]]);
              var annotationWidth = $jscomp$destructuring$var10.next().value;
              var annotationHeight = $jscomp$destructuring$var10.next().value;
              var $jscomp$destructuring$var11 = $jscomp.makeIterator([page.view[2] - page.view[0], page.view[3] - page.view[1]]);
              var pageWidth = $jscomp$destructuring$var11.next().value;
              var pageHeight = $jscomp$destructuring$var11.next().value;
              var div = document.createElement('div');
              div.className = 'pdf-annotation';
              if (viewport.rotation === 90) {
                div.style.left = 100 - 100 * (rect[1] - page.view[1] + annotationHeight) / pageHeight + '%';
                div.style.top = 100 * (rect[0] - page.view[0]) / pageWidth + '%';
                div.style.width = 100 * annotationHeight / pageHeight + '%';
                div.style.height = 100 * annotationWidth / pageWidth + '%';
              } else {
                if (viewport.rotation === 180) {
                  div.style.left = 100 - 100 * (rect[0] - page.view[0] + annotationWidth) / pageHeight + '%';
                  div.style.top = 100 - 100 * (rect[1] - page.view[1] + annotationHeight) / pageWidth + '%';
                  div.style.width = 100 * annotationWidth / pageHeight + '%';
                  div.style.height = 100 * annotationHeight / pageWidth + '%';
                } else {
                  if (viewport.rotation === 270) {
                    div.style.left = 100 * (rect[1] - page.view[1]) / pageHeight + '%';
                    div.style.top = 100 - 100 * (rect[0] - page.view[0] + annotationWidth) / pageWidth + '%';
                    div.style.width = 100 * annotationHeight / pageHeight + '%';
                    div.style.height = 100 * annotationWidth / pageWidth + '%';
                  } else {
                    div.style.left = 100 * (rect[0] - page.view[0]) / pageWidth + '%';
                    div.style.top = 100 * (rect[1] - page.view[1]) / pageHeight + '%';
                    div.style.width = 100 * annotationWidth / pageWidth + '%';
                    div.style.height = 100 * annotationHeight / pageHeight + '%';
                  }
                }
              }
              if (Ext.isNumeric(_result)) {
                div.onclick = Ext.bind(function() {
                  this.pageNum = _result;
                  this.renderPage();
                }, $jscomp$this);
              } else {
                div.onclick = Ext.bind(function() {
                  cordova.InAppBrowser.open(_result, '_blank', 'location\x3dno');
                }, $jscomp$this);
              }
              canvasCmp.select('#annotationLayer').appendChild(div);
            });
          });
        });
        $jscomp$this.pageRendering = false;
        if ($jscomp$this.renderPending) {
          $jscomp$this.renderPending = false;
          $jscomp$this.renderPage();
          view.setMasked(false);
        } else {
          view.setMasked(false);
        }
      })['catch'](function(error) {
        view.setMasked(false);
        cnconsult.Logger.log({prefix:'PdfViewerController-\x3erenderPage', message:'Error in render task.', level:'error', dump:error});
      });
    })['catch'](function(error) {
      view.setMasked(false);
      cnconsult.Logger.log({prefix:'PdfViewerController-\x3erenderPage', message:'Error while rendering pdf.', level:'error', dump:error});
    });
  }
}, onSearch:function() {
  var $jscomp$this = this;
  if (!this.searchDialog) {
    this.searchDialog = Ext.create('dilocsync.view.components.searchdialog.SearchDialog', {viewModel:{data:{pdfDoc:this.pdfDoc, checksum:this.getView().up().getViewModel().get('record').get('checksum')}}});
    this.searchDialog.on('selectpage', function(_page) {
      $jscomp$this.pageNum = parseInt(_page);
      $jscomp$this.renderPage();
    });
  }
  this.searchDialog.show();
}, onZoomOut:function() {
  if (this.scale > 1) {
    this.scale -= 0.25;
    this.renderPage();
  }
}, onZoomIn:function() {
  if (this.scale < 4) {
    this.scale += 0.25;
    this.renderPage();
  }
}, onPrevPage:function() {
  if (this.pageNum > 1) {
    this.pageNum--;
    this.renderPage();
  }
}, onNextPage:function() {
  if (this.pageNum < this.pdfDoc.numPages) {
    this.pageNum++;
    this.renderPage();
  }
}, onPageNumberClick:function() {
  dilocsync.util.MessageHelper.showPrompt(this.tr('Open file on page number'), this.tr('Please enter the page number you like to open'), function(_buttonId, _pageNumber) {
    if (_buttonId === 'ok') {
      var pageNumber = Ext.Number.from(_pageNumber, 0);
      if (pageNumber > 0 && pageNumber <= this.pdfDoc.numPages) {
        this.pageNum = pageNumber;
        this.renderPage();
      }
    }
  }, this);
}, onFullscreen:function() {
  var view = this.getView();
  view.setStyle('z-index:' + view.getZIndex());
  view.addCls('dilocsync-pdfviewer-fullscreen');
  this.lookup('exitFullScreenButton').show();
}, onExitFullscreen:function() {
  this.getView().removeCls('dilocsync-pdfviewer-fullscreen');
  this.lookup('exitFullScreenButton').hide();
}});
Ext.define('dilocsync.view.components.pdfviewer.PdfViewer', {extend:Ext.Container, mixins:[cnconsult.Translatable], xtype:'pdfviewer', viewModel:{type:'pdfviewer'}, controller:'pdfviewer', reference:'pdfViewer', fullscreen:true, initialize:function() {
  this.setMasked({xtype:'loadmask', message:this.tr('Loading document')});
  this.setItems([{xtype:'toolbar', cls:'dilocsync-pdfviewer-toolbar', docked:'right', width:55, items:[{iconCls:'x-fa fa-times', reference:'exitFullScreenButton', handler:'onExitFullscreen', hidden:true}, '-\x3e', {iconCls:'x-fa fa-search', handler:'onSearch'}, '-\x3e', {iconCls:'x-fa fa-arrow-up', handler:'onPrevPage'}, {xtype:'displayfield', cls:'page-number', reference:'pageNumber', html:'-/-', listeners:{click:{element:'element', fn:'onPageNumberClick'}}}, {iconCls:'x-fa fa-arrow-down', handler:'onNextPage'}, 
  '-\x3e', {iconCls:'x-fa fa-plus', handler:'onZoomIn'}, {xtype:'displayfield', reference:'zoom', value:'100%'}, {iconCls:'x-fa fa-minus', handler:'onZoomOut'}, '-\x3e']}, {xtype:'component', reference:'canvasCmp', cls:'dilocsync-pdfviewer-component', html:'\x3cdiv id\x3d"annotationLayer"\x3e\x3ccanvas\x3e\x3c/canvas\x3e\x3c/div\x3e'}]);
}});
Ext.define('dilocsync.view.components.externalfileopen.ExternalFileOpen', {extend:Ext.Panel, xtype:'externalfileopen', mixins:[cnconsult.Translatable], viewModel:{type:'externalfileopen'}, controller:'externalfileopen', config:{fileViewer:null, additionalButtonItems:[], evilFileExtensions:['exe', 'bat', 'cmd', 'msi', 'com', 'reg', 'vbs', 'pif', 'scr', 'ps1', 'js', 'jar']}, layout:{type:'center'}, cls:'dilocsync-externalfileopen', closeAction:'hide', bind:{title:'{fileTitle}'}, listeners:{painted:'onPainted'}, 
header:{style:{'padding-top':'5px'}}, enableDownloadOnDemand:false, initialize:function() {
  var me = this;
  var fileIcon = {xtype:'component', itemId:'fileIcon', tpl:['\x3cdiv class\x3d"{fileType:this.iconCls}"\x3e\x3c/div\x3e', {iconCls:function(_type) {
    return dilocsync.util.File.iconClsByType(_type);
  }}], bind:{data:{fileType:'{record.fileType}'}}};
  var fileInfo = {xtype:'component', itemId:'fileInfo', cls:'dilocsync-fileviewer-file-name', tpl:['\x3cspan\x3e\x3ch2\x3e{fileTitle}\x3c/h2\x3e\x3c/span\x3e', '\x3ctpl if\x3d"size" \x3e', '{size:this.formatFileSize}', '\x3c/tpl\x3e', '\x3c/span\x3e', '\x3cspan class\x3d"dilocsync-validity"\x3e', '\x3ctpl if\x3d"validFrom" \x3e', '\x26nbsp;', this.tr('Valid from'), '\x26nbsp;', '{validFrom:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3ctpl if\x3d"validTo" \x3e', '\x26nbsp;', this.tr('until'), '\x26nbsp;', 
  '{validTo:date("d.m.Y")}', '\x3c/tpl\x3e', '\x3c/span\x3e', '\x3cdiv\x3e\x3ctpl if\x3d"tags"\x3e{tags:this.getTagMarkup}\x3c/tpl\x3e\x3c/div\x3e', {getTagMarkup:function(_tags) {
    return dilocsync.util.File.tagMarkup(_tags);
  }, formatFileSize:function(_size) {
    return dilocsync.util.File.formatBytes(_size);
  }}], bind:{data:{fileTitle:'{fileTitle}', size:'{record.size}', validFrom:'{record.validFrom}', validTo:'{record.validTo}', tags:'{tags}'}}};
  var fileInfoContainer = {xtype:'container', layout:'hbox', items:[fileIcon, fileInfo]};
  var buttonContainer = {xtype:'container', layout:'hbox', style:{padding:'20px'}, items:[{xtype:'button', text:this.tr('Open file'), handler:'onOpenWithButtonTapped', hidden:true, style:{border:'1px black solid', 'margin-right':'10px'}, bind:{hidden:'{!fileExists}'}}].concat(this.getAdditionalButtonItems())};
  var actionBar = {xtype:'toolbar', cls:'dilocsync-fileviewer-action-toolbar', reference:'actionToolbar', docked:'top', ui:'actions-toolbar', defaults:{ui:'toolbar-actions'}, items:this.defaultToolbarItems()};
  var externalFileOpen = {xtype:'container', reference:'viewer', layout:'vbox', hidden:true, bind:{hidden:'{!fileSelected || !fileExists}'}, items:[fileInfoContainer, buttonContainer]};
  var videoPlayer = {xtype:'videoplayer', reference:'videoplayer', flex:1, hidden:true};
  var enableDownloadOnDemandComponent = {xtype:'container', cls:'dilocsync-fileviewer-file-not-found', reference:'enableDownloadOnDemandComponent', flex:1, layout:{type:'vbox', align:'center', pack:'center'}, bind:{hidden:'{!enableDownloadOnDemand}'}, items:[{xtype:'component', html:this.tr('\x3cdiv class\x3d"dilocsync-fileviewer-file-not-found"\x3e\x3cspan\x3e\x3ch1\x3e' + this.tr('Notice') + '\x3c/h1\x3e\x3cp\x3e' + this.tr('The selected file has not yet been downloaded...') + '\x3c/p\x3e\x3c/span\x3e\x3c/div\x3e')}, 
  {xtype:'button', text:this.tr('Download'), margin:'5', ui:'action', handler:function() {
    var viewModel = me.getViewModel();
    var record = viewModel.get('record');
    me.fireEvent('downloadOnDemand', record, viewModel);
  }}]};
  var fileNotFoundComponent = {xtype:'component', cls:'dilocsync-fileviewer-file-not-found', reference:'fileNotFoundComponent', flex:1, hidden:true, bind:{html:'\x3cdiv class\x3d"dilocsync-fileviewer-file-not-found"\x3e\x3cspan\x3e\x3ch1\x3e' + this.tr('File not found') + '\x3c/h1\x3e\x3cp\x3e' + this.tr('The selected file was not found anymore. It probably was deleted during a later synchronization.') + '\x3c/p\x3e\x3c/span\x3e\x3c/div\x3e', hidden:'{!showFileNotFoundComponent}'}};
  var pdfViewer = {xtype:'pdfviewer', flex:1, hidden:true};
  this.setItems([actionBar, externalFileOpen, videoPlayer, pdfViewer, fileNotFoundComponent, enableDownloadOnDemandComponent]);
  this.callParent(arguments);
  this.setFileViewer(this.lookup('viewer'));
}, defaultToolbarItems:function() {
  var identity = dilocsync.core.Master.getIdentity();
  var defaultToolbarItems = [];
  defaultToolbarItems.push({iconCls:'x-fa fa-external-link-alt', handler:'onOpenWithButtonTapped', hidden:true, bind:{hidden:'{!path || !fileExists}'}}, {xtype:'button', itemId:'nightButton', reference:'nightModeButton', iconCls:'x-fa fa-moon', handler:'toggleNightMode', hidden:true, bind:{hidden:'{!path  || !fileExists}'}});
  if (identity.options && !identity.options.disableFavorites) {
    defaultToolbarItems.push({iconCls:'x-fa fa-star', itemId:'favoritesButton', cls:'dilocsync-favorites-button', reference:'favoritesButton', handler:'onFavoritesButtonTapped', hidden:true, bind:{hidden:'{hideFavoritesButton}'}});
  }
  if (identity.options && identity.options.enableWorkFolders) {
    defaultToolbarItems.push({iconCls:'x-fa fa-list-ul', itemId:'dossierButton', handler:'onDossierButtonTapped', hidden:true, bind:{hidden:'{!path || !fileExists}'}});
  }
  defaultToolbarItems.push({iconCls:'x-fa fa-expand', handler:'onFullscreenButtonTapped', hidden:true, bind:{hidden:'{hideFullscreenButton}'}});
  defaultToolbarItems.push.apply(defaultToolbarItems, ['-\x3e'].concat($jscomp.arrayFromIterable(this.getAdditionalButtonItems())));
  return defaultToolbarItems;
}});
Ext.define('dilocsync.util.PdfViewerHelper', {singleton:true, mixins:[Ext.mixin.Observable], config:{viewersInNightMode:false}, cachedTextContent:{}, init:function() {
  window['pdfjs-dist/build/pdf'].GlobalWorkerOptions.workerSrc = 'libs/pdf.worker.js';
  var storage = dilocsync.core.Master.getStorage();
  var fileViewerConfig = storage.get('core:pdfviewer:config', {});
  if (fileViewerConfig.nightMode) {
    this.enableNightMode(true);
  }
}, enableNightMode:function(_enable) {
  this.setViewersInNightMode(_enable);
  var viewers = Ext.ComponentQuery.query('externalfileopen');
  viewers.forEach(function(_viewer) {
    if (_enable) {
      _viewer.down('#nightButton').setIconCls('x-fa fa-sun');
      _viewer.down('toolbar[reference\x3dactionToolbar]').addCls('dilocsync-fileviewer-action-toolbar-nightmode');
      _viewer.el.down('canvas').addCls('dilocsync-pdfviewer-nightmode');
    } else {
      _viewer.down('#nightButton').setIconCls('x-fa fa-moon');
      _viewer.down('toolbar[reference\x3dactionToolbar]').removeCls('dilocsync-fileviewer-action-toolbar-nightmode');
      _viewer.el.down('canvas').removeCls('dilocsync-pdfviewer-nightmode');
    }
  });
  this.storePdfViewerConfig('nightMode', _enable);
  Ext.fireEvent('nightMode', _enable);
}, cacheTextContent:function(_checksum, _content) {
  this.cachedTextContent[_checksum] = _content;
}, loadCachedTextContent:function(_checksum) {
  return this.cachedTextContent[_checksum];
}, storePdfViewerConfig:function(_key, _value) {
  var storage = dilocsync.core.Master.getStorage();
  var currentConfig = storage.get('core:pdfviewer:config', {});
  currentConfig[_key] = _value;
  storage.set('core:pdfviewer:config', currentConfig);
}});
Ext.define('dilocsync.view.components.externalfileopen.ExternalFileOpenController', {extend:Ext.app.ViewController, alias:'controller.externalfileopen', mixins:[cnconsult.Translatable], bindings:{loadFile:'{record}', checkFileForBeingFavorite:'{record}'}, onOpenWithButtonTapped:function() {
  var view = this.getView();
  var viewModel = this.getViewModel();
  var record = viewModel.get('record');
  var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(record);
  var fileInfo = {checksum:record.get('checksum'), alternativeFileType:record.get('alternativeFileType'), fileType:record.get('fileType'), name:record.get('name'), rootFsEntryName:rootFsEntryName};
  if (view.getEvilFileExtensions().includes(fileInfo.fileType)) {
    dilocsync.util.MessageHelper.showConfirm(this.tr('Security warning'), this.tr('You want to open an executable file. This can be a security risk. Are you sure you want to open the file?'), function(_button) {
      if (_button === 'yes') {
        dilocsync.util.ExternalFile.openFileExternallyWithRealFilename(viewModel.get('path'), fileInfo);
      }
    }, this);
  } else {
    dilocsync.util.ExternalFile.openFileExternallyWithRealFilename(viewModel.get('path'), fileInfo);
  }
}, onFavoritesButtonTapped:function(_button) {
  var store = Ext.getStore('Favorites');
  var fileRecord = this.getViewModel().get('record');
  var favoriteRecord;
  var favoriteData;
  var parentPageView = this.getView().up('[isPage\x3dtrue]');
  if (fileRecord) {
    var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(fileRecord);
    var filePath = dilocsync.core.Master.devicePath(rootFsEntryName + '/') + fileRecord.get('checksum') + '.' + fileRecord.get('fileType');
    favoriteData = {uuid:fileRecord.get('uuid'), name:fileRecord.get('title') ? fileRecord.get('title') : fileRecord.get('name'), path:filePath, fileType:fileRecord.get('fileType'), checksum:fileRecord.get('checksum'), validFrom:fileRecord.get('validFrom'), validTo:fileRecord.get('validTo'), icon:fileRecord.get('fileType'), markedAsFavoriteDate:new Date, group:'local', rootFsEntryName:rootFsEntryName};
    if (Ext.isObject(parentPageView) && parentPageView.hasOwnProperty('pageConfig') && Ext.isObject(parentPageView.pageConfig) && parentPageView.pageConfig.hasOwnProperty('path')) {
      var pagePath = parentPageView.pageConfig.path;
      favoriteData = Ext.apply(favoriteData, {almanacPath:'data/' + pagePath, almanacFilePath:fileRecord.get('path')});
    }
    favoriteRecord = store.findRecord('uuid', fileRecord.get('uuid'));
  }
  if (!favoriteRecord && favoriteData) {
    cnconsult.Logger.log({prefix:'FileViewerController-\x3eonFavoritesButtonTapped', message:'File is not marked as favorite yet, ADD it to the favorites store.'});
    dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.externalfileopen.ExternalFileOpenController', src:'Dokumente', action:'FavoritHinzugefügt', trackedAt:new Date});
    store.add(favoriteData);
    _button.setIconCls('x-fa fa-star active');
  }
  if (favoriteRecord) {
    cnconsult.Logger.log({prefix:'FileViewerController-\x3eonFavoritesButtonTapped', message:'File is already marked as favorite. REMOVE it from the favorites store.'});
    dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.externalfileopen.ExternalFileOpenController', src:'Dokumente', action:'FavoritGelöscht', trackedAt:new Date});
    store.remove(favoriteRecord);
    _button.setIconCls('x-fa fa-star');
    if (Ext.History.getToken() === 'favorites') {
      var fileViewer = this.getView().getFileViewer();
      var videoPlayerComponent = this.lookup('videoplayer');
      if (fileViewer) {
        fileViewer.hide();
      }
      if (videoPlayerComponent) {
        videoPlayerComponent.hide();
      }
      this.getViewModel().set({name:'-', record:null, path:null, onPageNumber:0, fileExists:true});
      _button.hide();
    }
  }
  store.sync();
  store.group();
}, checkFileForBeingFavorite:function() {
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  var fileRecord = this.getViewModel().get('record');
  if (fileRecord && identity.options && !identity.options.disableFavorites) {
    var favoritesButton = this.lookup('favoritesButton');
    var favoritesStore = Ext.getStore('Favorites');
    if (favoritesButton && favoritesStore) {
      var favoriteRecord = favoritesStore.findRecord('uuid', fileRecord.get('uuid'));
      if (!favoriteRecord) {
        favoriteRecord = favoritesStore.findRecord('path', fileRecord.get('path'));
      }
      if (favoriteRecord && favoriteRecord.get('group') === 'local') {
        favoritesButton.setIconCls('x-fa fa-star active');
      } else {
        favoritesButton.setIconCls('x-fa fa-star');
      }
    } else {
      cnconsult.Logger.log({prefix:'FileViewerController-\x3echeckFileForBeingFavorite', message:'FavoritesButton or Favorites Store is missing!!!', level:'error', dump:{favoritesButton:favoritesButton, favoritesStore:favoritesStore}});
    }
  }
}, onDossierButtonTapped:function() {
  var fileViewer = this.lookup('pdfViewer');
  var record = this.getViewModel().get('record');
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.fileviewer.FileViewerController', src:'Dokumente', action:'ArbeitsmappeHinzufügenGeklickt', trackedAt:new Date});
  Ext.create('dilocsync.view.components.dossier.add.Add', {viewModel:{data:{filePath:record.get('path'), fileName:record.get('title'), fileType:record.get('fileType'), openFileOnPage:record.get('fileType') === 'pdf' ? fileViewer.getController().pageNum : 1, record:record}}}).show();
}, onFullscreenButtonTapped:function() {
  this.lookup('pdfViewer').getController().onFullscreen();
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.externalfileopen.ExternalFileOpenController', src:'Dokumente', action:'VollbildmodusAktiviert', trackedAt:new Date});
}, loadFile:function(_record) {
  if (!_record || !Ext.isObject(_record)) {
    console.warn("No record set or record isn't an object.", _record);
    return;
  }
  var view = this.getView();
  var viewModel = this.getViewModel();
  var viewerComponent = this.lookup('viewer');
  var videoPlayerComponent = this.lookup('videoplayer');
  var pdfViewerComponent = this.lookup('pdfViewer');
  var fileNotFoundComponent = this.lookup('fileNotFoundComponent');
  var enableDownloadOnDemandComponent = this.lookup('enableDownloadOnDemandComponent');
  var fileType = dilocsync.util.File.extension(_record.get('path'));
  var maxFileSizeForWindowsPdfViewer = dilocsync.util.Helper.getMaxFileSizeForWindowsPdfViewer();
  var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(_record);
  var enableDownloadOnDemand = rootFsEntryName === 'train-schedule-data' || view.enableDownloadOnDemand;
  var filePath = rootFsEntryName + '/' + _record.get('checksum') + '.' + fileType.toLowerCase();
  viewModel.set('fileSelected', true);
  if (fileType) {
    dilocsync.core.Master.devicePathExists(filePath, function(_realPath) {
      if (_realPath) {
        viewModel.set('fileExists', true);
        viewModel.set('enableDownloadOnDemand', false);
        viewModel.set('showFileNotFoundComponent', false);
        if (dilocsync.util.File.isFileTypeVideo(fileType)) {
          viewerComponent.hide();
          pdfViewerComponent.hide();
          videoPlayerComponent.show();
          var videoPlayerViewModel = videoPlayerComponent.getViewModel();
          videoPlayerViewModel.set('url', _realPath);
        } else {
          if (fileType.toLowerCase() === 'pdf' && Ext.Number.from(_record.get('size'), 0) < maxFileSizeForWindowsPdfViewer) {
            viewerComponent.hide();
            videoPlayerComponent.hide();
            pdfViewerComponent.show();
            pdfViewerComponent.getController().loadPdf(_realPath, viewModel.get('onPageNumber'));
            viewModel.set('onPageNumber', null);
          } else {
            videoPlayerComponent.hide();
            pdfViewerComponent.hide();
            viewerComponent.show();
            if (fileNotFoundComponent && !fileNotFoundComponent.isHidden()) {
              fileNotFoundComponent.hide();
            }
            if (enableDownloadOnDemandComponent && !enableDownloadOnDemandComponent.isHidden()) {
              enableDownloadOnDemandComponent.hide();
            }
          }
        }
      } else {
        viewModel.set('fileExists', false);
        cnconsult.Logger.log({prefix:'FileViewerController-\x3eloadFile', message:'File not found!.', dump:{record:_record.data, filePath:filePath, realPath:_realPath}});
        if (enableDownloadOnDemand) {
          viewModel.set('enableDownloadOnDemand', enableDownloadOnDemand);
        } else {
          viewModel.set('showFileNotFoundComponent', true);
        }
        if (Sentry) {
          Sentry.withScope(function(_scope) {
            _scope.setExtra('path', filePath);
            Sentry.captureMessage('ExternalFileOpen: File not found!');
          });
        }
        pdfViewerComponent.hide();
        viewerComponent.hide();
      }
    }, this);
  } else {
    viewModel.set('fileExists', false);
    pdfViewerComponent.hide();
    viewerComponent.hide();
  }
}, hideViewer:function() {
  var viewerComponent = this.lookup('viewer');
  var videoplayer = this.lookup('videoplayer');
  videoplayer.hide();
  viewerComponent.hide();
}, showViewer:function() {
  var master = dilocsync.core.Master;
  var filePath = this.getViewModel().get('path');
  var record = this.getViewModel().get('record');
  if (record) {
    if (record.get('checksum') && record.get('fileType')) {
      var rootFsEntryName = dilocsync.util.File.getRootDirectoryName(record);
      filePath = master.devicePath(rootFsEntryName + '/' + record.get('checksum') + '.' + record.get('fileType'));
    }
  }
  var fileType = filePath ? dilocsync.util.File.extension(filePath) : '';
  var viewerComponent = this.lookup('viewer');
  viewerComponent.hide();
  if (dilocsync.util.File.isFileTypeVideo(fileType)) {
    this.lookup('videoplayer').show();
  } else {
    if (filePath && dilocsync.util.FileViewerHelper.isFileTypeSupport(fileType)) {
      viewerComponent.show();
    } else {
      viewerComponent.hide();
    }
  }
}, toggleNightMode:function() {
  var pdfViewerHelper = dilocsync.util.PdfViewerHelper;
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.view.components.externalfileopen.ExternalFileOpenController', src:'Dokumente', action:pdfViewerHelper.getViewersInNightMode() ? 'Nachtmodus deaktiviert' : 'Nachtmodus aktiviert', trackedAt:new Date});
  pdfViewerHelper.enableNightMode(!pdfViewerHelper.getViewersInNightMode());
}, onPainted:function() {
  if (dilocsync.util.PdfViewerHelper.getViewersInNightMode()) {
    dilocsync.util.PdfViewerHelper.enableNightMode(true);
  }
}, reset:function() {
  this.getViewModel().set({name:'-', path:null, record:null, fileExists:true, fileSelected:false});
}});
Ext.define('dilocsync.view.components.externalfileopen.ExternalFileOpenModel', {extend:Ext.app.ViewModel, alias:'viewmodel.externalfileopen', data:{name:'-', record:null, path:null, fileExists:true, enableDownloadOnDemand:false, showFileNotFoundComponent:false, fileSelected:false, onPageNumber:null}, formulas:{fileTitle:{bind:'{record}', get:function(_record) {
  if (_record && _record.get('title')) {
    return _record.get('title');
  } else {
    if (_record && _record.get('name')) {
      return _record.get('name');
    } else {
      return ' - ';
    }
  }
}}, tags:{bind:'{record}', get:function(_record) {
  if (_record && _record.tags) {
    var tagList = _record.tags();
    var tags = [];
    tagList.each(function(_tag) {
      tags.push({name:_tag.get('name'), color:_tag.get('color')});
    });
    return tags;
  }
  return null;
}}, hideFavoritesButton:{bind:{record:'{record}', fileExists:'{fileExists}'}, get:function(_data) {
  if (_data.record && _data.fileExists) {
    var favoritesStore = Ext.getStore('Favorites');
    var favoriteRecord = favoritesStore.findRecord('uuid', _data.record.get('uuid'));
    if (!favoriteRecord) {
      favoriteRecord = favoritesStore.findRecord('path', _data.record.get('path'));
    }
    return favoriteRecord ? favoriteRecord.get('group') === 'remote' : false;
  }
  return true;
}}, hideFullscreenButton:{bind:{record:'{record}', fileExists:'{fileExists}'}, get:function(_data) {
  if (_data.record && _data.fileExists) {
    var fileType = dilocsync.util.File.extension(_data.record.get('path'));
    return fileType.toLowerCase() !== 'pdf';
  }
  return true;
}}}});
Ext.define('dilocsync.view.components.gpsridedialog.GpsRideDialogModel', {extend:Ext.app.ViewModel, alias:'viewmodel.gpsRideDialog', data:{gpsTrackingStarted:null, ride:null}, formulas:{rideStartedOn:{bind:'{ride}', get:function(_record) {
  if (_record) {
    return Ext.Date.format(new Date(_record.get('startStation').time * 1000), 'd.m.Y H:i');
  }
  return '-';
}}}});
Ext.define('dilocsync.view.components.gpsridedialog.GpsRideDialogController', {extend:Ext.app.ViewController, alias:'controller.gpsRideDialog', onButtonTapped:function(_btn) {
  var view = this.getView();
  view.fireEvent(_btn.getItemId());
  view.close();
}, onMaskTapped:function() {
  var view = this.getView();
  view.fireEvent('cancel');
  view.close();
}});
Ext.define('dilocsync.view.components.gpsridedialog.GpsRideDialog', {extend:Ext.Dialog, mixins:[cnconsult.Translatable, Ext.mixin.Responsive], xtype:'gpsRideDialog', viewModel:{type:'gpsRideDialog'}, controller:'gpsRideDialog', centered:true, maskTapHandler:'onMaskTapped', layout:{type:'vbox', align:'stretch'}, responsiveConfig:{'phone \x26\x26 portrait':{width:'80%', height:'60%'}, 'phone \x26\x26 landscape':{width:'70%', height:'90%'}, '(tablet \x26\x26 landscape) || desktop':{width:'50%', height:'50%'}, 
'tablet \x26\x26 portrait':{width:'80%', height:'30%'}}, initialize:function() {
  var items = [{xtype:'toolbar', docked:'bottom', items:['-\x3e', {xtype:'button', itemId:'cancel', text:this.tr('Cancel'), handler:'onButtonTapped', ui:'confirm'}]}];
  if (this.getViewModel().get('gpsTrackingStarted')) {
    this.setTitle(this.tr('Select option'));
    items.unshift({xtype:'container', reference:'stopRide', scrollable:true, flex:1, layout:{type:'vbox', align:'stretch'}, items:this.getStopRideItems()});
  } else {
    this.setTitle(this.tr('Unfinished Ride detected'));
    items.unshift({xtype:'container', reference:'startRide', scrollable:true, flex:1, layout:{type:'vbox', align:'stretch'}, items:this.getStartRideItems()});
  }
  this.setItems(items);
  this.callParent(arguments);
}, getStartRideItems:function() {
  return [{html:this.tr('The last started ride was not properly finished.\x3cbr\x3eDo you want to continue this ride or finish this ride by selecting its end station?'), margin:'0 0 5 0'}, {margin:'5 0', bind:{html:this.tr('Last ride: Started on %1 in %2').arg('\x3cb\x3e{rideStartedOn}\x3c/b\x3e', '\x3cb\x3e{ride.startStation.name}\x3c/b\x3e')}}, {xtype:'container', layout:{type:'hbox', pack:'center'}, items:[{xtype:'button', itemId:'continueRide', ui:'content-button', text:this.tr('Continue ride'), 
  iconCls:'x-fa fa-play', iconAlign:'top', handler:'onButtonTapped', width:'35%', margin:20, padding:20}, {xtype:'button', itemId:'stopRide', ui:'content-button', text:this.tr('End ride'), iconCls:'x-fa fa-stop', iconAlign:'top', handler:'onButtonTapped', width:'35%', margin:20, padding:20}]}];
}, getStopRideItems:function() {
  return [{html:this.tr('Do you want to pause or end the ride?'), margin:'0 0 5 0'}, {xtype:'container', layout:{type:'hbox', pack:'center'}, items:[{xtype:'button', itemId:'pauseRide', ui:'content-button', text:this.tr('Pause ride'), iconCls:'x-fa fa-pause', iconAlign:'top', handler:'onButtonTapped', width:'35%', margin:20, padding:20}, {xtype:'button', itemId:'stopRide', ui:'content-button', text:this.tr('Stop ride'), iconCls:'x-fa fa-stop', iconAlign:'top', handler:'onButtonTapped', width:'35%', 
  margin:20, padding:20}]}];
}});
Ext.define('dilocsync.view.components.liveticker.LiveTickerController', {extend:Ext.app.ViewController, alias:'controller.liveticker', mixins:[cnconsult.Translatable], init:function() {
  cnconsult.Logger.log({prefix:'LiveTickerController-\x3einit', message:'init LiveTicker'});
  var master = dilocsync.core.Master, syncEngine = master.getSyncEngine();
  this.setupLiveTicker();
  master.on({connectiononline:'updateLiveTicker', scope:this});
  syncEngine.on('syncfinished', this.updateLiveTicker, this);
}, config:{lastLiveTickerCheck:null, liveTickerUpdateRunning:false}, setupLiveTicker:function() {
  var task = Ext.TaskManager.start({run:this.updateLiveTicker, interval:5 * 60 * 1000, scope:this});
}, updateLiveTicker:function(_forceUpdate) {
  if (_forceUpdate || !this.getLastLiveTickerCheck() || !this.getLiveTickerUpdateRunning() && Ext.Date.diff(this.getLastLiveTickerCheck(), new Date, Ext.Date.MINUTE) >= 5) {
    this.setLiveTickerUpdateRunning(true);
    dilocsync.core.Master.loadTickerMessages(function(_messages) {
      var messageText = '';
      var liveTicker = this.getView();
      this.setLastLiveTickerCheck(new Date);
      this.setLiveTickerUpdateRunning(false);
      if (_messages) {
        if (liveTicker) {
          messageText = Ext.Array.clean(Ext.Array.pluck(_messages, 'message')).join(' *** ');
          if (messageText) {
            liveTicker.setMessage(messageText);
            liveTicker.show();
            this.showNotification(messageText);
          } else {
            liveTicker.setMessage('');
            liveTicker.hide();
          }
        }
      }
    }, this);
  }
  if (Ext.Date.diff(this.getLastLiveTickerCheck(), new Date, Ext.Date.MINUTE) >= 30) {
    this.setLiveTickerUpdateRunning(false);
  }
}, showNotification:function(_message) {
  if (dilocsync.core.Master.isPhonegap() && dilocsync.util.FileViewerHelper.isInFullscreen() && dilocsync.util.Platform.supportsLocalNotification()) {
    cordova.plugins.notification.local.schedule({title:this.tr('Liveticker'), text:_message, sound:'res://platform_default'});
  }
}});
Ext.define('dilocsync.view.components.pagination.PaginationController', {extend:Ext.app.ViewController, alias:'controller.pagination', mixins:[cnconsult.Translatable], init:function() {
  var $jscomp$this = this;
  var viewModel = this.getViewModel();
  viewModel.bind('{currentPage}', function(_currentPage) {
    var firstNumber = viewModel.get('firstNumber');
    var pageCount = viewModel.get('pageCount');
    if (firstNumber > 1 && _currentPage === 1) {
      viewModel.set('firstNumber', 1);
    } else {
      if (firstNumber > 1 && firstNumber === _currentPage) {
        viewModel.set('firstNumber', firstNumber - 1);
      } else {
        if (pageCount > _currentPage && firstNumber + 4 === _currentPage) {
          viewModel.set('firstNumber', firstNumber + 1);
        }
      }
    }
    $jscomp$this.getView().fireEvent('pageChanged', _currentPage);
  });
}, onPrevPage:function() {
  var viewModel = this.getViewModel();
  var currentPage = viewModel.get('currentPage');
  if (currentPage > 1) {
    this.onPageClick(currentPage - 1);
  }
}, onNextPage:function() {
  var viewModel = this.getViewModel();
  var currentPage = viewModel.get('currentPage');
  var pageCount = viewModel.get('pageCount');
  if (currentPage < pageCount) {
    this.onPageClick(currentPage + 1);
  }
}, onPageClick:function(_index) {
  this.getViewModel().set('currentPage', _index);
}});
Ext.define('dilocsync.view.components.pagination.PaginationModel', {extend:Ext.app.ViewModel, alias:'viewmodel.pagination', data:{currentPage:0, previousPage:0, pageCount:0, pageStates:{}, firstNumber:1}});
Ext.define('dilocsync.view.components.pagination.Pagination', {extend:Ext.Component, xtype:'pagination', mixins:[cnconsult.Translatable], viewModel:{type:'pagination'}, controller:'pagination', bind:{data:{pageCount:'{pageCount}', currentPage:'{currentPage}', pageStates:'{pageStates}', btn1:'{firstNumber}', btn2:'{firstNumber + 1}', btn3:'{firstNumber + 2}', btn4:'{firstNumber + 3}', btn5:'{firstNumber + 4}'}}, cls:'pagination', initialize:function() {
  this.setTpl(['\x3cul class\x3d"paginator"\x3e', '\x3cli class\x3d"{[this.liCls(values, \'prev\')]}"\x3e\x3c\x3c/li\x3e', '\x3ctpl if\x3d"values.pageCount \x26gt; 0"\x3e', '\x3cli class\x3d"{[this.liCls(values, values.btn1)]}"\x3e{btn1}\x3c/li\x3e', '\x3c/tpl\x3e', '\x3ctpl if\x3d"values.pageCount \x26gt; 1"\x3e', '\x3cli class\x3d"{[this.liCls(values, values.btn2)]}"\x3e{btn2}\x3c/li\x3e', '\x3c/tpl\x3e', '\x3ctpl if\x3d"values.pageCount \x26gt; 2"\x3e', '\x3cli class\x3d"{[this.liCls(values, values.btn3)]}"\x3e{btn3}\x3c/li\x3e', 
  '\x3c/tpl\x3e', '\x3ctpl if\x3d"values.pageCount \x26gt; 3"\x3e', '\x3cli class\x3d"{[this.liCls(values, values.btn4)]}"\x3e{btn4}\x3c/li\x3e', '\x3c/tpl\x3e', '\x3ctpl if\x3d"values.pageCount \x26gt; 4"\x3e', '\x3cli class\x3d"{[this.liCls(values, values.btn5)]}"\x3e{btn5}\x3c/li\x3e', '\x3c/tpl\x3e', '\x3cli class\x3d"{[this.liCls(values, \'next\')]}"\x3e\x3e\x3c/li\x3e', '\x3c/ul\x3e', {liCls:function(values, token) {
    var cls = [];
    if (values.currentPage === token) {
      cls.push('active');
    }
    if (Ext.isNumeric(token)) {
      cls.push('state--' + (values.pageStates[token] || 'ok'));
    } else {
      if (token === 'prev' && values.btn1 > 1) {
        var worstState;
        for (var i = values.btn1 - 1; i > 0; i--) {
          if (values.pageStates[i] === 'error') {
            worstState = 'error';
            break;
          } else {
            if (values.pageStates[i] === 'warning') {
              worstState = 'warning';
            }
          }
        }
        if (worstState) {
          cls.push('state--' + worstState);
        }
      } else {
        if (token === 'next' && values.btn5 < values.pageCount) {
          var worstState$97;
          for (var i$98 = values.btn5 + 1; i$98 <= values.pageCount; i$98++) {
            if (values.pageStates[i$98] === 'error') {
              worstState$97 = 'error';
              break;
            } else {
              if (values.pageStates[i$98] === 'warning') {
                worstState$97 = 'warning';
              }
            }
          }
          if (worstState$97) {
            cls.push('state--' + worstState$97);
          }
        }
      }
    }
    return cls.join(' ');
  }}]);
}, afterRender:function() {
  var $jscomp$this = this;
  this.el.on('click', function(event) {
    if (event.target.tagName === 'LI') {
      var text = event.target.textContent;
      if (text === '\x3c') {
        $jscomp$this.getController().onPrevPage();
      } else {
        if (text === '\x3e') {
          $jscomp$this.getController().onNextPage();
        } else {
          $jscomp$this.getController().onPageClick(parseInt(text));
        }
      }
    }
  });
}});
Ext.define('dilocsync.view.components.sidepanel.components.WebsitesController', {extend:Ext.app.ViewController, alias:'controller.sidePanelWebsites', onWebsiteTapped:function(_dataView, _location) {
  var title = _location.record.data.title;
  var url = _location.record.data.url;
  this.getView().down('iframe').setSrc(url);
  this.getView().down('titlebar').setTitle(title);
  this.getView().setActiveItem(1);
}, onBack:function() {
  this.getView().setActiveItem(0);
}, onWebsiteLongPress:function(_view, _location) {
  if (dilocsync.core.Master.isOnline()) {
    var url = _location.record.data.url;
    if (url && url.indexOf('http') === -1) {
      url = dilocsync.core.Master.devicePath(url);
    }
    cordova.InAppBrowser.open(url, '_system', 'location\x3dyes');
  } else {
    dilocsync.util.MessageHelper.showError(this.tr('For opening a website you need to connect to the internet!'));
  }
}});
Ext.define('dilocsync.view.components.sidepanel.components.Websites', {extend:Ext.Panel, xtype:'sidePanelWebsites', mixins:[cnconsult.Translatable], controller:'sidePanelWebsites', layout:'card', initialize:function() {
  var identity = dilocsync.core.Master.getIdentity();
  var store = Ext.getStore('websites');
  var view;
  if (identity.options && identity.options.websitesMode && identity.options.websitesMode === 'preview') {
    view = {xtype:'websiteDataView', itemId:'websiteDataView', listeners:{childtap:'onWebsiteTapped', childlongpress:'onWebsiteLongPress'}, store:store, flex:1};
  } else {
    view = {xtype:'websitelist', listeners:{childtap:'onWebsiteTapped', childlongpress:'onWebsiteLongPress'}, store:store, flex:1};
  }
  this.setItems([view, {xtype:'panel', layout:'fit', items:[{xtype:'titlebar', docked:'top', items:[{iconCls:'x-fa fa-chevron-left', reference:'backButton', handler:'onBack'}]}, {xtype:'iframe'}]}]);
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.syncreportpanel.SyncReportPanelModel', {extend:Ext.app.ViewModel, alias:'viewmodel.syncreportpanel', stores:{syncReports:{model:'dilocsync.model.SyncReportMetaData'}}, data:{reportMeta:null}});
Ext.define('dilocsync.view.components.syncreportpanel.SyncReportPanelController', {extend:Ext.app.ViewController, alias:'controller.syncreportpanel', mixins:[cnconsult.Translatable], init:function() {
  var syncEngine = dilocsync.core.Master.getSyncEngine();
  syncEngine.on('syncfinished', this.initStorage, this);
  syncEngine.on('syncaborted', this.initStorage, this);
  this.initStorage();
}, initStorage:function() {
  var syncReportStorage = dilocsync.core.Master.getSyncReportStorage();
  var storage = dilocsync.core.Master.getStorage();
  var showLastReportsCount = storage.get('syncreport:showLastReports', 10);
  var syncReportsStore = this.getStore('syncReports');
  var metaData = syncReportStorage.getLastReportMetaData(showLastReportsCount);
  syncReportsStore.setData(metaData);
  this.getViewModel().set('reportMeta', syncReportsStore.getAt(0));
}, onReportChange:function(_combo, _date, _oldDate) {
  var reportMeta = _combo.getSelection();
  this.setStoreToList(reportMeta);
}, onFileTap:function(_fileFolderList, _subList, _index, _target, _record) {
  _record.set('state', 'read');
  if (_record.get('type') === 'update' || _record.get('type') === 'new') {
    this.showFile(_record);
  } else {
    if (_record.get('type') === 'delete') {
      var viewer = this.getView().up().lookup('viewer');
      viewer.getController().hideViewer();
      viewer.getViewModel().set({record:null, path:null});
    }
  }
}, showFile:function(_record) {
  this.getView().fireEvent('showfile', _record, this.getView());
}, onCheckAll:function() {
  var combo = this.lookup('reports');
  var reportMeta = combo.getSelection();
  var syncReportStorage = dilocsync.core.Master.getSyncReportStorage();
  var syncReport = syncReportStorage.loadReport(reportMeta);
  if (syncReport) {
    dilocsync.util.MessageHelper.showMessage({title:this.tr('Sync Report'), message:this.tr('Do you really want to confirm all changes of the successful synchronization?'), buttons:[{itemId:'no', text:this.tr('No'), handler:function(_button) {
      _button.up('messagebox').destroy();
    }}, {itemId:'yes', text:this.tr('Yes'), handler:function(_button) {
      syncReport.markAsRead(reportMeta);
      this.setStoreToList(reportMeta);
      reportMeta.set('state', 'read');
      _button.up('messagebox').destroy();
    }, scope:this}]});
  }
}, setStoreToList:function(_syncMetaData) {
  var syncReportStorage = dilocsync.core.Master.getSyncReportStorage();
  var syncReport = syncReportStorage.loadReport(_syncMetaData);
  var store = syncReport.getTreeStore();
  var root = store.getRoot();
  var view = this.lookup('list');
  store.sort('type', 'DESC');
  root.expand();
  view.setStore(store);
}});
Ext.define('dilocsync.view.components.syncreportpanel.SyncReportPanel', {extend:Ext.Panel, mixins:[cnconsult.Translatable], xtype:'syncreportpanel', viewModel:{type:'syncreportpanel'}, controller:'syncreportpanel', cls:'dilocsync-sync-report-panel', layout:'vbox', initialize:function() {
  this.setItems([{xtype:'syncreportlist', reference:'list', title:this.tr('Sync-Reports'), listeners:{leafitemtap:'onFileTap'}, flex:1}]);
  this.down('syncreportlist').insertAfter({xtype:'container', cls:'dilocsync-sync-report-panel-switcher-container', docked:'top', layout:{type:'hbox', align:'stretch'}, items:[{xtype:'combobox', cls:'dilocsync-sync-report-panel-combo', forceSelection:true, autoSelect:true, reference:'reports', editable:false, bind:{store:'{syncReports}', selection:'{reportMeta}'}, queryMode:'local', valueField:'date', displayField:'formattedDate', itemTpl:new Ext.XTemplate('\x3cdiv class\x3d"dilocsync-sync-report-panel-switcher-item dilocsync-sync-report-panel-switcher-item-state-{state}"\x3e', 
  '\x3cspan class\x3d"x-fa fa-calendar"\x3e\x3c/span\x3e', '\x26nbsp;{date:date("d.m. H:i:s")}\x26nbsp;', '\x3ctpl if\x3d"wasHighPrioritySync"\x3e\x3cspan class\x3d"x-fa fa-flag-checkered"\x3e\x3c/span\x3e\x3c/tpl\x3e', '\x3ctpl if\x3d"reasonType\x3d\x3d\'abort\'"\x3e\x3cspan class\x3d"x-fa fa-ban"\x3e\x3c/span\x3e\x3c/tpl\x3e', '\x3ctpl if\x3d"reasonType\x3d\x3d\'error\'"\x3e\x3cspan class\x3d"x-fa fa-exclamation-triangle"\x3e\x3c/span\x3e\x3c/tpl\x3e', '\x3ctpl if\x3d"reasonType\x3d\x3d\'newVisible\'"\x3e\x3cspan class\x3d"x-fa fa-clock-o"\x3e\x3c/span\x3e\x3c/tpl\x3e', 
  '\x3c/div\x3e'), listeners:{select:{fn:'onReportChange', scope:this.getController()}}, flex:1}, {xtype:'button', iconCls:'x-fa fa-check', handler:'onCheckAll', disabled:true, bind:{disabled:'{!reportMeta || reportMeta.state \x3d\x3d\x3d "read"}'}}, {xtype:'component', docked:'bottom', cls:'dilocsync-sync-report-panel-reason', bind:{data:{reasonType:'{reportMeta.reasonType}', reason:'{reportMeta.reason}'}, hidden:'{!reportMeta.reason}'}, tpl:new Ext.XTemplate('\x3ctpl if\x3d"reasonType\x3d\x3d\'abort\'"\x3e\x3cspan class\x3d"x-fa fa-ban"\x3e\x3c/span\x3e\x26nbsp;', 
  this.tr('Sync was not completed! Reason: '), '\x3c/tpl\x3e', '\x3ctpl if\x3d"reasonType\x3d\x3d\'error\'"\x3e\x3cspan class\x3d"x-fa fa-exclamation-triangle"\x3e\x3c/span\x3e\x26nbsp;', this.tr('Sync was not completed! Reason: '), '\x3c/tpl\x3e', '\x3ctpl if\x3d"reasonType\x3d\x3d\'newVisible\'"\x3e\x3cspan class\x3d"x-fa fa-clock-o"\x3e\x3c/span\x3e\x26nbsp;', this.tr('New Sync-Report! Reason: '), '\x3c/tpl\x3e', '\x3ci\x3e{reason}\x3c/i\x3e')}, {xtype:'component', docked:'bottom', cls:'dilocsync-sync-report-panel-reason', 
  bind:{data:{wasHighPrioritySync:'{reportMeta.wasHighPrioritySync}'}, hidden:'{!reportMeta.wasHighPrioritySync}'}, tpl:new Ext.XTemplate('\x3cspan class\x3d"x-fa fa-flag-checkered"\x3e\x3c/span\x3e\x26nbsp;', this.tr('Sync contained important documents for your drive!'))}]}, this.down('syncreportlist titlebar'));
  this.callParent(arguments);
}});
Ext.define('dilocsync.view.components.videoplayer.VideoPlayerController', {extend:Ext.app.ViewController, alias:'controller.videoplayer', init:function() {
  Ext.util.History.on('change', this.pauseVideoPlayer, this);
}, pauseVideoPlayer:function() {
  var video = this.getView().el.down('video');
  if (video) {
    video.dom.pause();
  }
}});
Ext.define('dilocsync.view.components.videoplayer.VideoPlayerModel', {extend:Ext.app.ViewModel, alias:'viewmodel.videoplayer', data:{url:''}});
Ext.define('dilocsync.controller.Router', {extend:Ext.app.Controller, refs:[{ref:'mainView', selector:'app-main'}], routes:{'init':{before:'checkSetup', action:'showStartView'}, 'setup/device/registration':{action:'showView'}, 'setup/user/personalization':{action:'showView'}, 'setup/user/personalization/create':{action:'showView'}, 'setup/user/personalization/knowledges':{before:'checkSetup', action:'showView'}, 'search':{before:'checkSetup', action:'showView'}, 'home':{before:'checkSetup', action:'showView'}, 
'dynamicschedule':{before:'checkSetup', action:'showView'}, 'favorites':{before:'checkSetup', action:'showView'}, 'imports':{before:'checkSetup', action:'showView'}, 'about':{before:'checkSetup', action:'showView'}, 'routeknowledge':{before:'checkSetup', action:'showView'}, 'usersettings':{before:'checkSetup', action:'showView'}, 'driveinfo':{before:'checkSetup', action:'showView'}, 'drivemode':{before:'checkSetup', action:'showView'}, 'website':{before:'checkSetup', action:'showView'}, 'dailyla':{before:'checkSetup', 
action:'showView'}, 'confirmations':{before:'checkSetup', action:'showView'}, 'embeddedwebpage/:path':{conditions:{':path':'([%À-ſA-Za-z0-9\\/\\-\\_\\s,]+)'}, action:'showView'}, 'knowledges':{before:'checkSetup', action:'showView'}, 'syncreports':{before:'checkSetup', action:'showView'}, 'forms':{before:'checkSetup', action:'showView'}, 'folder/:path':{conditions:{':path':"([%À-ſA-Za-z0-9.\x26()|'\\+\\/\\-\\_\\s,]+)"}, before:'checkSetup', action:'showView'}, 'shiftjuggler':{before:'checkSetup', 
action:'showView'}, 'locbook':{before:'checkSetup', action:'showView'}}, listen:{global:{unmatchedroute:'onUnmatchedRoute'}}, onUnmatchedRoute:function(_token) {
  cnconsult.Logger.log({prefix:'Router-\x3eonUnmatchedRoute', message:'unmatched token', dump:_token});
  this.redirectTo('init');
}, showStartView:function() {
  this.redirectTo('home');
}, checkSetup:function() {
  var action = arguments[arguments.length - 1];
  var master = dilocsync.core.Master;
  var identity = master.getIdentity();
  if (!dilocsync.core.Master.getInitFinished()) {
    action.stop();
  } else {
    if (!dilocsync.core.Master.isRegistered()) {
      action.stop();
      this.redirectTo('setup/device/registration');
    } else {
      if (!dilocsync.core.Master.getPersonalization().isPersonalized()) {
        action.stop();
        this.redirectTo('setup/user/personalization');
      } else {
        if (identity && identity.options && identity.options.readConfirmationMessagePrio === 'major' && Ext.util.History.getToken() !== 'confirmations' && Ext.getStore('Confirmations') && Ext.getStore('Confirmations').countUnconfirmedFiles() > 0) {
          var unlockDate = master.getStorage().get('page:confirmations:unlockDate');
          if (unlockDate && Date.now() - unlockDate < 60 * 60 * 24 * 1000) {
            action.resume();
          } else {
            action.stop();
            dilocsync.util.Confirmations.showMessage();
          }
        } else {
          action.resume();
        }
      }
    }
  }
}, initAppMainView:function() {
  cnconsult.Logger.log({prefix:'Router-\x3einitAppMainView', message:'Router initViewport'});
  if (!Ext.Viewport.down('app-main')) {
    Ext.Viewport.removeAll();
    Ext.Viewport.add(Ext.create('dilocsync.view.main.Main'));
    Ext.Viewport.setMenu({xtype:'sidemenu'}, {side:'left', cover:true, reveal:false});
  }
}, showView:function() {
  var route = Ext.util.History.getToken();
  var menuItems = Ext.getStore('menuItems');
  var menuItem;
  if (menuItems.getCount() === 0) {
    menuItems.on({'datachanged':{fn:this.showView, scope:this, single:true}});
  } else {
    route = decodeURIComponent(route);
    menuItem = menuItems.findRecord('route', route);
    if (menuItem) {
      if (!menuItem.get('isSetupView')) {
        this.initAppMainView();
      }
      var viewXtype = menuItem.get('view');
      var mainView = this.getMainView() ? this.getMainView() : Ext.Viewport;
      route = route.split(',').join('');
      var view = mainView.down(viewXtype + '[route\x3d' + route + ']');
      var pageConfig = menuItem.get('config');
      menuItems.each(function(_record) {
        _record.set('pressed', false);
      });
      menuItem.set('pressed', true);
      if (!view) {
        view = Ext.widget(viewXtype, {route:route, pageConfig:pageConfig});
      } else {
        if (mainView.getActiveItem() === view && view.isPage) {
          view.pageTappedAgain();
        }
      }
      mainView.setActiveItem(view);
    } else {
      cnconsult.Logger.log({prefix:'Router-\x3eshowView', message:'No menu item config found for:', dump:route});
    }
  }
}});
Ext.define('dilocsync.store.Knowledges', {extend:Ext.data.TreeStore, model:'dilocsync.model.AlmanacEntry', defaultRootProperty:'items', sorters:['name'], folderSort:true, constructor:function() {
  this.callParent(arguments);
  this.setFilters([dilocsync.util.Filters.visibleFrom, dilocsync.util.Filters.visibleTo]);
}});
Ext.define('dilocsync.core.KnowledgeBuilder', {knowledgeData:{}, almanac:null, knowledgeBasePath:'', knowledgeCount:0, availableLanguages:['de', 'en', 'fr', 'it', 'nl', 'pl', 'cz', 'at', 'ch'], constructor:function(_almanac, _knowledgeBasePath) {
  this.almanac = _almanac;
  this.knowledgeBasePath = _knowledgeBasePath;
  var knowledgeBaseDirectory = _almanac.getDirectoryForPath(_knowledgeBasePath);
  if (knowledgeBaseDirectory) {
    for (var knowledgeGroupDirectoryName in knowledgeBaseDirectory.directories) {
      var knowledgeGroup = knowledgeBaseDirectory.directories[knowledgeGroupDirectoryName];
      for (var knowledgeDirectoryName in knowledgeGroup.directories) {
        if (knowledgeGroup.directories.hasOwnProperty(knowledgeDirectoryName)) {
          this.knowledgeCount++;
        }
      }
    }
  }
}, getKnowledgeStore:function(_collapseKnowledgeLimit) {
  var knowledgeData;
  var knowledgeTreeStore = Ext.create('dilocsync.store.Knowledges');
  if (typeof _collapseKnowledgeLimit !== 'undefined' && this.knowledgeCount <= _collapseKnowledgeLimit) {
    knowledgeData = this.buildCompleteCollapsedKnowledgeData();
  } else {
    knowledgeData = this.buildCompleteKnowledgeData();
  }
  knowledgeTreeStore.setRoot({items:knowledgeData});
  knowledgeTreeStore.load();
  return knowledgeTreeStore;
}, buildCompleteCollapsedKnowledgeData:function() {
  var knowledgeData = [];
  var knowledgeBaseDirectory = this.almanac.getDirectoryForPath(this.knowledgeBasePath);
  if (knowledgeBaseDirectory) {
    for (var knowledgeGroupDirectoryName in knowledgeBaseDirectory.directories) {
      var knowledgeGroup = knowledgeBaseDirectory.directories[knowledgeGroupDirectoryName];
      for (var knowledgeDirectoryName in knowledgeGroup.directories) {
        var singleKnowledgeData = this.buildSingleKnowledgeData(knowledgeGroup.directories[knowledgeDirectoryName], true);
        if (knowledgeGroup.directories[knowledgeDirectoryName].icon) {
          singleKnowledgeData.icon = knowledgeGroup.directories[knowledgeDirectoryName].icon;
        } else {
          singleKnowledgeData.icon = 'folder';
        }
        knowledgeData.push(singleKnowledgeData);
      }
    }
  }
  return knowledgeData;
}, buildCompleteKnowledgeData:function() {
  var knowledgeData = [];
  var knowledgeBaseDirectory = this.almanac.getDirectoryForPath(this.knowledgeBasePath);
  if (knowledgeBaseDirectory) {
    for (var knowledgeGroupDirectoryName in knowledgeBaseDirectory.directories) {
      var item = {};
      item.name = dilocsync.util.File.basename(knowledgeBaseDirectory.directories[knowledgeGroupDirectoryName].path);
      item.path = knowledgeBaseDirectory.directories[knowledgeGroupDirectoryName].path;
      if (knowledgeBaseDirectory.directories[knowledgeGroupDirectoryName].icon) {
        item.icon = knowledgeBaseDirectory.directories[knowledgeGroupDirectoryName].icon;
      } else {
        item.icon = 'folder';
      }
      item.items = [];
      var knowledgeGroup = knowledgeBaseDirectory.directories[knowledgeGroupDirectoryName];
      for (var knowledgeDirectoryName in knowledgeGroup.directories) {
        var singleKnowledgeData = this.buildSingleKnowledgeData(knowledgeGroup.directories[knowledgeDirectoryName], true);
        if (knowledgeGroup.directories[knowledgeDirectoryName].icon) {
          singleKnowledgeData.icon = knowledgeGroup.directories[knowledgeDirectoryName].icon;
        } else {
          singleKnowledgeData.icon = 'folder';
        }
        item.items.push(singleKnowledgeData);
      }
      knowledgeData.push(item);
    }
  }
  return knowledgeData;
}, buildSingleKnowledgeData:function(_singleKnowledgeDirectory, _removeLanguageSubDir) {
  var knowledgeData = [];
  if (this.isObjectEmpty(_singleKnowledgeDirectory.directories)) {
    knowledgeData = this.recursiveDirectoryBuilder(_singleKnowledgeDirectory);
  } else {
    for (var directoryName in _singleKnowledgeDirectory.directories) {
      if (_removeLanguageSubDir && this.availableLanguages.indexOf(directoryName) > -1) {
        if (dilocsync.core.Master.getUserLanguage() === directoryName) {
          knowledgeData = this.recursiveDirectoryBuilder(_singleKnowledgeDirectory.directories[directoryName], dilocsync.util.File.basename(_singleKnowledgeDirectory.path));
        }
      } else {
        knowledgeData = this.recursiveDirectoryBuilder(_singleKnowledgeDirectory);
      }
    }
  }
  return knowledgeData;
}, recursiveDirectoryBuilder:function(_directory, _name) {
  var item = {title:_directory.title, description:_directory.description, size:_directory.size, validFrom:_directory.validFrom, validTo:_directory.validTo, visibleFrom:_directory.visibleFrom, visibleTo:_directory.visibleTo, tags:_directory.tags, path:_directory.path, icon:'directory', items:[]};
  item.name = _name ? _name : dilocsync.util.File.basename(_directory.path);
  for (var directoryName in _directory.directories) {
    item.items.push(this.recursiveDirectoryBuilder(_directory.directories[directoryName]));
  }
  for (var filename in _directory.files) {
    if (_directory.files.hasOwnProperty(filename)) {
      var file = _directory.files[filename];
      item.items.push({name:filename, path:_directory.path + filename, icon:dilocsync.util.File.extension(filename).toLowerCase(), size:file.size, read:!!file.read, leaf:true, md5:file.md5, uuid:file.uuid, title:file.title, description:file.description, fileType:dilocsync.util.File.extension(filename).toLowerCase(), fileUuid:file.fileUuid, checksum:file.checksum, validFrom:file.validFrom, validTo:file.validTo, visibleFrom:file.visibleFrom, visibleTo:file.visibleTo, tags:file.tags});
    }
  }
  return item;
}, isObjectEmpty:function(_object) {
  return Ext.Object.isEmpty(_object);
}});
Ext.define('dilocsync.core.ProgressCalculator', {config:{maxValue:100}, currentValue:0, startingTime:0, fileCounter:0, constructor:function(_config) {
  this.initConfig(_config);
  this.startingTime = new Date;
}, increaseFileCounter:function() {
  this.fileCounter += 1;
}, increaseCurrentValue:function(_increase) {
  this.currentValue += _increase;
}, setCurrentValue:function(_currentValue) {
  this.currentValue = _currentValue;
}, percentage:function() {
  if (this.currentValue > this.config.maxValue) {
    return 100;
  }
  return Math.round(this.currentValue / this.config.maxValue * 100);
}, remainingDownloadTime:function() {
  if (this.fileCounter > 3) {
    var now = new Date, elapsedTime = now - this.startingTime;
    return Math.round((elapsedTime / this.currentValue * this.config.maxValue - elapsedTime) / 100);
  } else {
    return null;
  }
}});
Ext.define('dilocsync.core.repository.DocumentOwnershipTracker', {database:null, initialize:function() {
  var $jscomp$this = this;
  var databaseFileName = 'dilocsync.db';
  return this._openDatabaseAsync(databaseFileName).then(function(_db) {
    return $jscomp$this.database = _db;
  }).then(function() {
    return $jscomp$this._createDocumentOwnershipTableIfItDoesNotExist();
  });
}, addOwnerToDocument:function(documentChecksum, userId) {
  var query = 'INSERT OR IGNORE INTO DocumentOwnership (documentChecksum, userId) VALUES(?, ?)';
  return this._executeSqlAsync(query, [documentChecksum, userId]).then(function() {
    return undefined;
  });
}, getAllDocumentsForUser:function(userId) {
  return this._getValueFromRowsAsync('documentChecksum', 'userId \x3d ?', [userId]);
}, getOwnersForDocument:function(documentChecksum) {
  return this._getValueFromRowsAsync('userId', 'documentChecksum \x3d ?', [documentChecksum]);
}, getAllDocumentOwners:function() {
  return this._getValueFromRowsAsync('userId');
}, getAllDocuments:function() {
  return this._getValueFromRowsAsync('documentChecksum');
}, removeAllDocumentOwnershipsForUser:function(userId) {
  return this._deleteRowsAsync('userId \x3d ?', [userId]);
}, removeOwnerForDocument:function(documentChecksum, userId) {
  return this._deleteRowsAsync('documentChecksum \x3d ? AND userId \x3d ?', [documentChecksum, userId]);
}, removeAllDocumentOwnershipsOfDocument:function(_documentChecksum) {
  return this._deleteRowsAsync('documentChecksum \x3d ?', [_documentChecksum]);
}, clearDocumentOwnerships:function() {
  return this._deleteRowsAsync();
}, _getValueFromRowsAsync:function(_valueName, _whereConditions, _whereParams) {
  var $jscomp$this = this;
  _whereConditions = _whereConditions === undefined ? '' : _whereConditions;
  _whereParams = _whereParams === undefined ? [] : _whereParams;
  var query = 'SELECT DISTINCT ' + _valueName + ' FROM DocumentOwnership';
  if (_whereConditions) {
    query += ' WHERE ' + _whereConditions;
  }
  return this._executeSqlAsync(query, _whereParams).then(function(_rs) {
    return $jscomp$this._mapRowsToValue(_rs.rows, _valueName);
  });
}, _mapRowsToValue:function(_rows, _valueName) {
  var valueList = [];
  for (var i = 0; i < _rows.length; ++i) {
    valueList.push(_rows.item(i)[_valueName]);
  }
  return valueList;
}, _deleteRowsAsync:function(_whereConditions, _whereParams) {
  _whereConditions = _whereConditions === undefined ? '' : _whereConditions;
  _whereParams = _whereParams === undefined ? [] : _whereParams;
  var query = 'DELETE FROM DocumentOwnership';
  if (_whereConditions) {
    query += ' WHERE ' + _whereConditions;
  }
  return this._executeSqlAsync(query, _whereParams).then(function() {
    return undefined;
  });
}, _executeSqlAsync:function(_sqlQuery, _params) {
  var $jscomp$this = this;
  _params = _params === undefined ? [] : _params;
  return new Promise(function(_resolve, _reject) {
    $jscomp$this.database.executeSql(_sqlQuery, _params, function(_rs) {
      return _resolve(_rs);
    }, function(_err) {
      return _reject(_err);
    });
  });
}, _openDatabaseAsync:function(_databaseFileName) {
  return new Promise(function(_resolve, _reject) {
    window.sqlitePlugin.openDatabase({name:_databaseFileName, location:'default'}, function(_db) {
      return _resolve(_db);
    }, function(_err) {
      return _reject(_err);
    });
  });
}, _createDocumentOwnershipTableIfItDoesNotExist:function() {
  var query = 'CREATE TABLE IF NOT EXISTS DocumentOwnership (documentChecksum varchar(255), userId int, UNIQUE(documentChecksum, userId))';
  return this._executeSqlAsync(query);
}});
Ext.define('dilocsync.core.repository.MultiUserDocumentRepository', {constructor:function(_syncRootUrl, _listFiles, _fileExists, _removeFile, _settingsStorage, _documentOwnershipTracker) {
  this.syncRootUrl = _syncRootUrl;
  this.listFiles = _listFiles;
  this.fileExists = _fileExists;
  this.removeFile = _removeFile;
  this.settingsStorage = _settingsStorage;
  this.documentOwnershipTracker = _documentOwnershipTracker;
  this.fileSubdir = 'fs-data';
}, addOwnerForDocument:function(_documentChecksum, _userId) {
  return this.documentOwnershipTracker.addOwnerToDocument(_documentChecksum, _userId);
}, containsDocument:function(_fileChecksum, _fileExtension) {
  return this.fileExists(this.getUrlForLocalFile(_fileChecksum, _fileExtension));
}, clearDocumentOwnerships:function() {
  return this.documentOwnershipTracker.clearDocumentOwnerships();
}, removeNoLongerRequiredDocuments:function() {
  var $jscomp$this = this;
  return this._removeOwnershipsOfInactiveUsers().then(function() {
    return $jscomp$this._removeFilesWithoutOwners();
  }).then(function() {
    return $jscomp$this._removeOwnershipsOfNonExistingFiles();
  });
}, removeOwnerForDocument:function(_fileChecksum, _fileExtension, _userId) {
  var $jscomp$this = this;
  return this.documentOwnershipTracker.removeOwnerForDocument(_fileChecksum, _userId).then(function() {
    return $jscomp$this._removeFileIfOwnerless(_fileChecksum, _fileExtension);
  });
}, getUrlForLocalFile:function(_fileChecksum, _fileExtension) {
  return this._getUrlForFilesDirectory() + '/' + _fileChecksum + '.' + _fileExtension;
}, _getUrlForFilesDirectory:function() {
  return this.syncRootUrl + '/' + this.fileSubdir;
}, _daysSinceTimestamp:function(_timestamp) {
  var secondsSinceTimestamp = Date.now() / 1000 - _timestamp;
  return Math.floor(secondsSinceTimestamp / (60 * 60 * 24));
}, _isUserInactive:function(_userId, _daysUntilUserIsConsideredInactive) {
  var lastLogin = this.settingsStorage.getForUser('core:personalization:lastLogin', _userId);
  var daysSinceLastLogin = this._daysSinceTimestamp(lastLogin);
  return daysSinceLastLogin >= _daysUntilUserIsConsideredInactive;
}, _getInactiveUsers:function() {
  var $jscomp$this = this;
  var daysUntilUserIsConsideredInactive = this.settingsStorage.get('core:personalization:daysUntilUserIsConsideredInactive');
  return this.documentOwnershipTracker.getAllDocumentOwners().then(function(_documentOwners) {
    return _documentOwners.filter(function(_owner) {
      return $jscomp$this._isUserInactive(_owner, daysUntilUserIsConsideredInactive);
    });
  });
}, _removeAllDocumentOwnershipsForUser:function(_userId) {
  return this.documentOwnershipTracker.removeAllDocumentOwnershipsForUser(_userId)['catch'](function(_err) {
    cnconsult.Logger.log({level:'warning', prefix:'MultiUserDocumentRepository-\x3e_removeAllDocumentOwnershipsForUser', message:'Error trying to remove all documents ownerships for user ' + _userId, catchedError:_err});
    throw _err;
  });
}, _removeOwnershipsOfUsers:function(_users) {
  var $jscomp$this = this;
  return Promise.allSettled(_users.map(function(_user) {
    return $jscomp$this._removeAllDocumentOwnershipsForUser(_user);
  }));
}, _removeOwnershipsOfInactiveUsers:function() {
  var $jscomp$this = this;
  return this._getInactiveUsers().then(function(_inactiveUsers) {
    return $jscomp$this._removeOwnershipsOfUsers(_inactiveUsers);
  });
}, _getFilesWithoutOwners:function() {
  return Promise.all([this.listFiles(this._getUrlForFilesDirectory()), this.documentOwnershipTracker.getAllDocuments()]).then(function(_results) {
    var $jscomp$destructuring$var12 = $jscomp.makeIterator(_results);
    var filesOnDisk = $jscomp$destructuring$var12.next().value;
    var documentsWithOwners = $jscomp$destructuring$var12.next().value;
    return filesOnDisk.filter(function(_filePath) {
      return !documentsWithOwners.includes(dilocsync.util.File.getFileNameWithoutExtension(_filePath));
    });
  });
}, _removeFiles:function(_filesToRemove) {
  var $jscomp$this = this;
  var removePromises = _filesToRemove.map(function(_fileUrl) {
    return $jscomp$this.removeFile(_fileUrl);
  });
  return Promise.allSettled(removePromises).then(function(_outcomes) {
    var deleteFailedCounter = 0;
    for (var $jscomp$iter$19 = $jscomp.makeIterator(_outcomes), $jscomp$key$outcome = $jscomp$iter$19.next(); !$jscomp$key$outcome.done; $jscomp$key$outcome = $jscomp$iter$19.next()) {
      var outcome = $jscomp$key$outcome.value;
      {
        if (outcome.status === 'rejected') {
          deleteFailedCounter++;
        }
      }
    }
    if (deleteFailedCounter > 0) {
      throw new Error('Failed to delete ' + deleteFailedCounter + ' files.');
    }
  });
}, _getOwnershipsOfNonExistingFiles:function() {
  return Promise.all([this.listFiles(this._getUrlForFilesDirectory()), this.documentOwnershipTracker.getAllDocuments()]).then(function(_results) {
    var $jscomp$destructuring$var13 = $jscomp.makeIterator(_results);
    var filesOnDisk = $jscomp$destructuring$var13.next().value;
    var documentsWithOwners = $jscomp$destructuring$var13.next().value;
    var checksumsOnDisks = filesOnDisk.map(function(_filePath) {
      return dilocsync.util.File.getFileNameWithoutExtension(_filePath);
    });
    return documentsWithOwners.filter(function(_documentChecksum) {
      return !checksumsOnDisks.includes(_documentChecksum);
    });
  });
}, _removeOwnershipsOfDocuments:function(_documents) {
  var $jscomp$this = this;
  return Promise.all(_documents.map(function(_document) {
    return $jscomp$this.documentOwnershipTracker.removeAllDocumentOwnershipsOfDocument(_document);
  }));
}, _removeOwnershipsOfNonExistingFiles:function() {
  var $jscomp$this = this;
  return this._getOwnershipsOfNonExistingFiles().then(function(_documentsNotExistingOnFileSystem) {
    return $jscomp$this._removeOwnershipsOfDocuments(_documentsNotExistingOnFileSystem);
  });
}, _removeFilesWithoutOwners:function() {
  var $jscomp$this = this;
  return this._getFilesWithoutOwners().then(function(_filesWithoutOwners) {
    return $jscomp$this._removeFiles(_filesWithoutOwners);
  });
}, _removeFileIfOwnerless:function(_fileChecksum, _fileExtension) {
  var $jscomp$this = this;
  return this.documentOwnershipTracker.getOwnersForDocument(_fileChecksum).then(function(_owners) {
    if (_owners.length === 0) {
      return $jscomp$this.removeFile($jscomp$this.getUrlForLocalFile(_fileChecksum, _fileExtension));
    }
  });
}});
Ext.define('dilocsync.core.repository.SingleUserDocumentRepository', {require:['dilocsync.util.AlmanacSettings'], constructor:function(_syncRootUrl, _listFiles, _fileExists, _removeFile, _settingsStorage) {
  this.syncRootUrl = _syncRootUrl;
  this.listFiles = _listFiles;
  this.fileExists = _fileExists;
  this.removeFile = _removeFile;
  this.settingsStorage = _settingsStorage;
  this.fileSubdir = 'fs-data';
}, addOwnerForDocument:function() {
  return Promise.resolve();
}, containsDocument:function(_fileChecksum, _fileExtension) {
  return this.fileExists(this.getUrlForLocalFile(_fileChecksum, _fileExtension));
}, clearDocumentOwnerships:function() {
  return Promise.resolve();
}, removeNoLongerRequiredDocuments:function() {
  var $jscomp$this = this;
  return this._getFilesNotExistingInAlmanacs().then(function(_filesNotExistingInAlmanacs) {
    return $jscomp$this._removeFiles(_filesNotExistingInAlmanacs);
  });
}, removeOwnerForDocument:function(_fileChecksum, _fileExtension, _userId) {
  return this.removeFile(this.getUrlForLocalFile(_fileChecksum, _fileExtension));
}, getUrlForLocalFile:function(_fileChecksum, _fileExtension) {
  return this._getUrlForFilesDirectory() + '/' + _fileChecksum + '.' + _fileExtension;
}, _getUrlForFilesDirectory:function() {
  return this.syncRootUrl + '/' + this.fileSubdir;
}, _getFilesNotExistingInAlmanacs:function() {
  var userAlmanacs = this.settingsStorage.get('core:almanacs', []);
  var fileNamesInAlmanacs = dilocsync.util.AlmanacSettings.listAllFileNamesInAlmanacs(userAlmanacs, this.settingsStorage);
  return this.listFiles(this._getUrlForFilesDirectory()).then(function(_filesOnDisk) {
    return _filesOnDisk.filter(function(_f) {
      return !fileNamesInAlmanacs.has(dilocsync.util.File.basename(_f));
    });
  });
}, _removeFiles:function(_filesToRemove) {
  var $jscomp$this = this;
  var removePromises = _filesToRemove.map(function(_fileUrl) {
    return $jscomp$this.removeFile(_fileUrl);
  });
  return Promise.allSettled(removePromises).then(function(_outcomes) {
    var deleteFailedCounter = 0;
    for (var $jscomp$iter$20 = $jscomp.makeIterator(_outcomes), $jscomp$key$outcome = $jscomp$iter$20.next(); !$jscomp$key$outcome.done; $jscomp$key$outcome = $jscomp$iter$20.next()) {
      var outcome = $jscomp$key$outcome.value;
      {
        if (!outcome.value || outcome.status === 'rejected') {
          deleteFailedCounter++;
        }
      }
    }
    if (deleteFailedCounter > 0) {
      throw new Error('Failed to delete ' + deleteFailedCounter + ' files.');
    }
  });
}});
Ext.define('dilocsync.core.syncengine.tasks.SyncRides', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Syncing route knowledge rides...'), 0, 0, null);
  var routeKnowLedgeRidesStore = dilocsync.util.Helper.initStore('RouteKnowledgeRides');
  if (routeKnowLedgeRidesStore) {
    var rides = [];
    var indices = [];
    var routeKnowLedgeRidesStoreData = routeKnowLedgeRidesStore.getRange();
    routeKnowLedgeRidesStoreData.forEach(function(_record) {
      if (_record.get('submit')) {
        rides.push({syncVersion:dilocsync.core.Master.version, deviceType:dilocsync.core.Master.deviceType(), trainNumber:_record.get('trainNumber'), createdOn:_record.get('createdOn'), idCodes:_record.get('idCodes'), drivenSegments:_record.get('drivenSegments'), visitedStations:_record.get('visitedStations'), appVersion:_record.get('appVersion')});
        indices.push(routeKnowLedgeRidesStore.indexOf(_record));
      }
    });
    if (rides.length > 0) {
      cnconsult.Logger.log({prefix:'SyncRides-\x3eexecute', message:'Syncing Rides', level:'debug', dump:rides});
      Ext.Ajax.request({url:this.master.getBackendUrl() + '/syncrideknowledge/addRides', timeout:2 * 60000, params:{syncSecret:this.storage.get('core:personalization:syncSecret'), rides:Ext.encode(rides)}, success:function(_response) {
        cnconsult.Logger.log({prefix:'SyncRides-\x3eexecute', message:'Succes response', level:'debug', dump:_response});
        var response = Ext.decode(_response.responseText, true);
        if (response && response.success) {
          this.fireEvent('syncprogress', this.tr('Successfully uploaded the route knowledge rides!'), 0, 0, null);
          routeKnowLedgeRidesStore.remove(indices);
          routeKnowLedgeRidesStore.sync();
          Ext.callback(_next, _scope, [true]);
        } else {
          Ext.callback(_abort, _scope, [false, this.tr('Error occured when uploading the route knowledge rides!')]);
          Sentry.withScope(function(_scope) {
            _scope.setExtra('response', response);
            Sentry.captureMessage('Error occured when uploading the route knowledge rides!');
          });
        }
      }, failure:function(_response) {
        cnconsult.Logger.log({prefix:'SyncRides-\x3eexecute', message:'Error occurred when uploading the route knowledge rides', level:'error', dump:_response});
        Ext.callback(_abort, _scope, [false, this.tr('Error occured when uploading the route knowledge rides!')]);
      }, scope:this});
    } else {
      this.fireEvent('syncprogress', this.tr('There are no available route knowledge rides, syncing rides will be skipped.'), 0, 0, null);
      Ext.callback(_next, _scope);
    }
  } else {
    Ext.callback(_abort, _scope, [false, this.tr('The route knowledge rides store was not found, syncing rides will be aborted.')]);
  }
}});
Ext.define('dilocsync.model.TrackedActivity', {extend:Ext.data.Model, fields:[{name:'class', type:'string'}, {name:'action', type:'string'}, {name:'platformName', type:'string'}, {name:'platformVersion', type:'string'}, {name:'appVersion', type:'string'}, {name:'appVersionCode', type:'string'}, {name:'anonymousDeviceId', type:'string'}, {name:'trackedAt', type:'date'}, {name:'extras', allowNull:true}]});
Ext.define('dilocsync.store.TrackedActivities', {extend:Ext.data.Store, storeId:'TrackedActivities', model:'dilocsync.model.TrackedActivity', sync:function() {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var userActivities = this.getRange();
  var records = [];
  userActivities.forEach(function(_record) {
    return records.push(_record.getData());
  });
  Ext.Ajax.request({url:master.getBackendUrl() + '/activitytracker/trackSyncClientActivities', params:{syncSecret:storage.get('core:personalization:syncSecret'), deviceIdCode:master.deviceIdCode(), activities:Ext.encode(records)}, success:function(_response) {
    var response = Ext.decode(_response.responseText, true);
    if (response && response.success) {
      this.remove(userActivities);
    }
  }, failure:function(_response) {
    cnconsult.Logger.log({prefix:'Almanac-\x3egetFileByPath', message:'Error occured when uploading user activities.', level:'error', dump:_response});
  }, scope:this});
}});
Ext.define('dilocsync.core.syncengine.tasks.SyncUserActivities', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var trackedActivitiesStore = dilocsync.util.Helper.initStore('TrackedActivities');
  if (trackedActivitiesStore) {
    trackedActivitiesStore.sync();
  }
  Ext.callback(_next, _scope, [true]);
}});
Ext.define('dilocsync.core.syncengine.tasks.db.BuildKnowledgeAlmanac', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, abortCallback:null, callbackScope:null, nextCallback:null, execute:function(_next, _abort, _scope) {
  var knowledgeConfig = this.getKnowledgeConfig();
  this.fireEvent('syncprogress', this.tr('Preparing knowledge almanac ...'), 0, 0, null);
  this.nextCallback = _next;
  this.abortCallback = _abort;
  this.callbackScope = _scope;
  if (knowledgeConfig.basePath) {
    cnconsult.Logger.log({prefix:'BuildKnowledgeAlmanac-\x3eexecute', message:'Start creating knowledge almanacs.'});
    var knowledgeAlmanacPaths = this.getKnowledgeAlmanacPaths(knowledgeConfig.basePath);
    var almanac = Ext.create('dilocsync.core.Almanac', {});
    var userLang = this.master.getUserLanguage();
    Ext.Array.forEach(knowledgeAlmanacPaths, function(_path) {
      var knowledgeAlmanac = dilocsync.core.Master.getStorage().get('core:almanac:' + _path);
      if (_path.endsWith('/' + userLang)) {
        _path = _path.substr(0, _path.length - (userLang.length + 1));
      }
      this.addToAlmanacRecursively(almanac, knowledgeAlmanac, knowledgeConfig.basePath, _path);
    }, this);
    if (knowledgeAlmanacPaths.length <= knowledgeConfig.collapseLimit) {
      this.collapseAlmanac(almanac);
    }
    this.master.persistAlmanacByPath(almanac, knowledgeConfig.basePath);
    this.master.initAlmanacs();
  }
  Ext.callback(_next, _scope);
}, addToAlmanacRecursively:function(_almanac, _source, _basePath, _path) {
  if (_source) {
    var relativePath = _path.substring(_basePath.length);
    if (_source.title) {
      var dir = _almanac.getDirectoryForPath(relativePath);
      if (!dir) {
        dir = _almanac.createDirectory(relativePath);
      }
      if (dir) {
        dir.title = _source.title;
      }
    }
    if (_source.hasOwnProperty('files')) {
      Ext.Object.each(_source.files, function(_fileName, _fileProperties) {
        var filePath = relativePath + '/' + _fileName;
        _almanac.updateFile(filePath, _fileProperties.size, _fileProperties.checksum, _fileProperties);
      }, this);
    }
    for (var directoryName in _source.directories) {
      if (_source.directories.hasOwnProperty(directoryName) && Ext.isObject(_source.directories[directoryName])) {
        this.addToAlmanacRecursively(_almanac, _source.directories[directoryName], _basePath, _path + '/' + directoryName);
      }
    }
  }
}, collapseAlmanac:function(_almanac) {
  var rootDirectories = _almanac.rootDirectory.directories;
  _almanac.rootDirectory.directories = {};
  for (var $jscomp$iter$21 = $jscomp.makeIterator(Object.values(rootDirectories)), $jscomp$key$dir = $jscomp$iter$21.next(); !$jscomp$key$dir.done; $jscomp$key$dir = $jscomp$iter$21.next()) {
    var dir = $jscomp$key$dir.value;
    {
      Ext.apply(_almanac.rootDirectory.directories, dir.directories);
    }
  }
}, getKnowledgeConfig:function() {
  var identity = this.master.getIdentity();
  var basePath, collapseLimit;
  if (identity.hasOwnProperty('pages') && Ext.isArray(identity.pages)) {
    var pagesMap = Ext.Array.toValueMap(identity.pages, 'type');
    if (pagesMap.hasOwnProperty('knowledge') && pagesMap.knowledge.hasOwnProperty('config')) {
      if (pagesMap.knowledge.config.hasOwnProperty('path')) {
        basePath = pagesMap.knowledge.config.path;
      }
      if (pagesMap.knowledge.config.hasOwnProperty('collapseLimit')) {
        collapseLimit = pagesMap.knowledge.config.collapseLimit;
      }
    }
    return {basePath:basePath, collapseLimit:collapseLimit};
  }
}, getKnowledgeAlmanacPaths:function(_basePath) {
  var almanacs = dilocsync.core.Master.getStorage().get('core:almanacs', []);
  var almanacPaths = Ext.Array.pluck(almanacs, 'path');
  var knowledgeAlmanacPaths = [];
  Ext.Array.forEach(almanacPaths, function(_path) {
    if (Ext.String.startsWith(_path, _basePath)) {
      knowledgeAlmanacPaths.push(_path);
    }
  }, this);
  return knowledgeAlmanacPaths;
}});
Ext.define('dilocsync.core.syncengine.tasks.db.CheckForUndeletedFiles', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  try {
    if (this.doExecuteTask()) {
      this.fireEvent('syncprogress', this.tr('Checking if there are files that need to be removed from filesystem...'), 0, 0, null);
      var checker = dilocsync.util.UndeletedFileChecker;
      checker.checkForUndeletedFiles();
      cnconsult.Logger.log({prefix:'dilocsync.core.syncengine.tasks.db.CheckForUndeletedFiles-\x3eexecute', message:'Finished CheckForUndeletedFiles sync task'});
    } else {
      cnconsult.Logger.log({prefix:'dilocsync.core.syncengine.tasks.db.CheckForUndeletedFiles-\x3eexecute', message:'Skipping CheckForUndeletedFiles sync task for now'});
    }
  } catch (e$99) {
    cnconsult.Logger.log({prefix:'dilocsync.core.syncengine.tasks.db.CheckForUndeletedFiles-\x3eexecute', message:'An unexpected error occurred during execution.', level:'error', dump:e$99});
  } finally {
    Ext.callback(_next, _scope);
  }
}});
Ext.define('dilocsync.core.syncengine.tasks.db.Dossiers', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var almanacs = this.syncData.getLocalAlmanacs();
  var syncEngine = this.master.getSyncEngine();
  this.fireEvent('syncprogress', this.tr('Checking if there are files that need to be removed from dossiers...'), 0, 0, null);
  if (Ext.isArray(almanacs)) {
    Ext.Array.each(almanacs, function(_almanac) {
      _almanac.on('filedeleted', this.onFileDeleted, this);
    }, this);
    syncEngine.on('syncfinished', function() {
      Ext.Array.each(almanacs, function(_almanac) {
        _almanac.un('filedeleted', this.onFileDeleted, this);
      }, this);
    }, this);
  }
  Ext.callback(_next, _scope);
}, onFileDeleted:function(_path, _file, _fileInfo) {
  if (Ext.isObject(_fileInfo) && _fileInfo.hasOwnProperty('uuid')) {
    var dossierTreeStore = Ext.getStore('Dossiers');
    var dossiers = dossierTreeStore.getRange();
    var nodeDeleted = false;
    dossiers.forEach(function(dossierNode) {
      var childrenToRemove = dossierNode.childNodes.filter(function(child) {
        return child.get('uuid') === _fileInfo.uuid;
      });
      if (childrenToRemove.length > 0) {
        childrenToRemove.forEach(function(child) {
          return dossierNode.removeChild(child);
        });
        nodeDeleted = true;
      }
    });
    if (nodeDeleted) {
      dossierTreeStore.sync();
      dossierTreeStore.load();
    }
  }
}});
Ext.define('dilocsync.core.syncengine.tasks.db.Favorites', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var almanacs = this.syncData.getLocalAlmanacs();
  var syncEngine = this.master.getSyncEngine();
  this.fireEvent('syncprogress', this.tr('Checking if there are files which should be added or removed from favorites...'), 0, 0, null);
  if (Ext.isArray(almanacs)) {
    Ext.Array.each(almanacs, function(_almanac) {
      _almanac.on('fileadded', this.onFileAdded, this);
      _almanac.on('fileupdated', this.onFileUpdated, this);
      _almanac.on('filedeleted', this.onFileDeleted, this);
    }, this);
    syncEngine.on('syncfinished', function() {
      Ext.Array.each(almanacs, function(_almanac) {
        _almanac.on('fileadded', this.onFileAdded, this);
        _almanac.on('fileupdated', this.onFileUpdated, this);
        _almanac.on('filedeleted', this.onFileDeleted, this);
      }, this);
    }, this);
  }
  Ext.callback(_next, _scope);
}, onFileAdded:function(_path, _file, _fileInfo, _checksum) {
  this.addToFavorites(_path, _file, _fileInfo, _checksum);
}, onFileUpdated:function(_path, _file, _fileInfo, _checksum) {
  var store = Ext.getStore('Favorites');
  var record = store.findRecord('uuid', _fileInfo.uuid);
  var hasFavoriteTag = dilocsync.util.File.hasFavoriteTag(_fileInfo);
  if (!record && hasFavoriteTag) {
    this.addToFavorites(_path, _file, _fileInfo, _checksum);
  } else {
    if (record) {
      if (record.get('group') === 'remote' && !hasFavoriteTag) {
        this.removeFromFavorites(record);
      } else {
        record.set('name', _fileInfo.title ? _fileInfo.title : _file);
        store.sync();
        store.group();
      }
    }
  }
}, onFileDeleted:function(_path, _file, _fileInfo) {
  var store = Ext.getStore('Favorites');
  if (Ext.isObject(_fileInfo) && _fileInfo.hasOwnProperty('uuid')) {
    var record = store.findRecord('uuid', _fileInfo.uuid);
    if (record && record.get('group') === 'remote') {
      this.removeFromFavorites(record);
    }
  }
}, addToFavorites:function(_path, _file, _fileInfo, _checksum) {
  var store = Ext.getStore('Favorites');
  var hasFavoriteTag = dilocsync.util.File.hasFavoriteTag(_fileInfo);
  if (store && hasFavoriteTag) {
    var rootFsEntryName = dilocsync.util.File.validateRootDirectoryName(_fileInfo.rootFsEntryName);
    var filePath = dilocsync.core.Master.devicePath(rootFsEntryName + '/') + _checksum + '.' + _fileInfo.fileType;
    var title = _fileInfo.title ? _fileInfo.title : _file;
    var indexOfFavorite = store.findBy(function(record) {
      return record.get('name') === title && record.get('checksum') === _checksum;
    });
    if (indexOfFavorite === -1) {
      store.add({uuid:_fileInfo.uuid, name:_fileInfo.title ? _fileInfo.title : _file, path:filePath, fileType:_fileInfo.fileType, checksum:_checksum, icon:_fileInfo.fileType, markedAsFavoriteDate:new Date, group:'remote', rootFsEntryName:rootFsEntryName});
    }
    store.sync();
    store.group();
  }
}, removeFromFavorites:function(_record) {
  var store = Ext.getStore('Favorites');
  store.remove(_record);
  store.sync();
  store.group();
}});
Ext.define('dilocsync.core.syncengine.tasks.db.ImportantDocuments', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var almanacs = this.syncData.getLocalAlmanacs();
  var syncEngine = this.master.getSyncEngine();
  this.fireEvent('syncprogress', this.tr('Checking if there are files which should be added or removed from important documents...'), 0, 0, null);
  if (Ext.isArray(almanacs)) {
    if (!Ext.getStore('ImportantDocuments')) {
      var store = Ext.create('dilocsync.store.ImportantDocuments');
      store.load();
    }
    Ext.Array.each(almanacs, function(_almanac) {
      _almanac.on('fileadded', this.onFileAdded, this);
      _almanac.on('fileupdated', this.onFileUpdated, this);
      _almanac.on('filedeleted', this.onFileDeleted, this);
    }, this);
    syncEngine.on('syncfinished', function() {
      Ext.Array.each(almanacs, function(_almanac) {
        _almanac.on('fileadded', this.onFileAdded, this);
        _almanac.on('fileupdated', this.onFileUpdated, this);
        _almanac.on('filedeleted', this.onFileDeleted, this);
      }, this);
    }, this);
  }
  Ext.callback(_next, _scope);
}, onFileAdded:function(_path, _file, _fileInfo, _checksum) {
  var hasImportantTag = dilocsync.util.File.hasImportantTag(_fileInfo);
  if (hasImportantTag) {
    this.addToImportantDocuments(_path, _file, _fileInfo, _checksum);
  }
}, onFileUpdated:function(_path, _file, _fileInfo, _checksum) {
  if (_fileInfo && _fileInfo.hasOwnProperty('uuid')) {
    var store = Ext.getStore('ImportantDocuments');
    var record = store.findNode('uuid', _fileInfo.uuid);
    var hasImportantTag = dilocsync.util.File.hasImportantTag(_fileInfo);
    if (record) {
      this.removeFromImportantDocuments(record);
    }
    if (hasImportantTag) {
      this.addToImportantDocuments(_path, _file, _fileInfo, _checksum);
    }
  }
}, onFileDeleted:function(_path, _file, _fileInfo, _checksum) {
  if (_fileInfo && _fileInfo.hasOwnProperty('uuid')) {
    var store = Ext.getStore('ImportantDocuments');
    var record = store.findNode('uuid', _fileInfo.uuid);
    if (record) {
      this.removeFromImportantDocuments(record);
    }
  }
}, addToImportantDocuments:function(_path, _file, _fileInfo, _checksum) {
  var store = Ext.getStore('ImportantDocuments');
  if (store) {
    var rootFsEntryName = dilocsync.util.File.validateRootDirectoryName(_fileInfo.rootFsEntryName);
    var filePath = dilocsync.core.Master.devicePath(rootFsEntryName + '/') + _checksum + '.' + _fileInfo.fileType;
    var fileData = Ext.apply({name:_file, path:filePath, icon:_fileInfo.fileType}, _fileInfo);
    store.getRoot().appendChild(fileData);
    store.sync();
  }
}, removeFromImportantDocuments:function(_record) {
  var store = Ext.getStore('ImportantDocuments');
  store.getRoot().removeChild(_record);
  store.sync();
}});
Ext.define('dilocsync.core.syncengine.tasks.db.IndexFiles', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Checking if there are new files which should be indexed...'), 0, 0, null);
  var storage = dilocsync.core.Master.getStorage();
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var filesToIndex = [];
  if (Ext.isArray(almanacsSyncActions)) {
    Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
      var path;
      var filesToDownload = Ext.clone(_almanacSyncActions.getFilesToDownload());
      if (Ext.Object.getSize(_almanacSyncActions.getHighPriorityFilesToDownload()) > 0) {
        filesToDownload = Ext.Object.merge(filesToDownload, _almanacSyncActions.getHighPriorityFilesToDownload());
      }
      for (path in filesToDownload) {
        if (filesToDownload.hasOwnProperty(path)) {
          var file = filesToDownload[path];
          if (!path.startsWith(dilocsync.core.Master.devicePath(''))) {
            path = dilocsync.core.Master.devicePath('fs-data/' + file.checksum + '.' + file.fileType);
          }
          filesToIndex.push(path);
        }
      }
    }, this);
  }
  if (filesToIndex.length > 0 && filesToIndex.length < 100) {
    cnconsult.Logger.log({prefix:'IndexFiles-\x3eexecute', message:'There are ' + filesToIndex.length + ' files to index! Indexing will start onsyncfinish.'});
    storage.set('fulltextsearch:filesToIndex', Ext.encode(filesToIndex));
  } else {
    if (filesToIndex.length > 100) {
      cnconsult.Logger.log({prefix:'IndexFiles-\x3eexecute', message:'There are too much files (' + filesToIndex.length + ') to index. Skipping index them and resetting timestamp for indexing all directories + files on next app start!', level:'info'});
      storage.set('fulltextsearch:lastUpdated', false);
    }
  }
  Ext.callback(_next, _scope);
}});
Ext.define('dilocsync.core.syncengine.tasks.db.MigrateData', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, mixins:[cnconsult.Translatable], nextCallback:null, abortCallback:null, callbackScope:null, currentAlmanacFinished:false, execute:function(_next, _abort, _scope) {
  this.nextCallback = _next;
  this.abortCallback = _abort;
  this.callbackScope = _scope;
  this.fireEvent('syncprogress', this.tr('Migration data...'), 0, 0, null);
  if (this.isMigrationNeeded()) {
    this.doMigration();
  } else {
    Ext.callback(_next, _scope);
  }
}, isMigrationNeeded:function() {
  var storage = this.master.getStorage();
  var isMigrationNeeded = false;
  if (storage.get('core:syncengine:lastSyncTimestamp', false) && !storage.get('sync4DataMigrated', false)) {
    isMigrationNeeded = true;
  }
  return isMigrationNeeded;
}, doMigration:function() {
  var master = dilocsync.core.Master;
  dilocsync.util.MaskHelper.showLoadingMask(this.tr('App is currently migrating to the newest sync algorithm. This can take a while. Please do not close app or abort process.'));
  cnconsult.Logger.log({prefix:'MigrateData-\x3edoMigration', message:'Starting migrating: Loading new fs-data directory...'});
  master.getSyncRoot().getDirectory('fs-data', {create:true}, Ext.bind(function(_fsDataDirectory) {
    if (_fsDataDirectory) {
      cnconsult.Logger.log({prefix:'MigrateData-\x3edoMigration', message:'Loading old data directory...'});
      master.getSyncRoot().getDirectory('data', null, Ext.bind(function(_dataDirectory) {
        if (_dataDirectory) {
          cnconsult.Logger.log({prefix:'MigrateData-\x3edoMigration', message:'Directories loaded. Start iterating over almanacs...'});
          this.iterateOverAlmanacs(_fsDataDirectory, this.finishMigration, this);
        } else {
          cnconsult.Logger.log({prefix:'MigrateData-\x3edoMigration', message:"data directory couldn't be loaded! Continuing synchronisation...", level:'error'});
          this.finishMigration();
        }
      }, this), Ext.bind(function() {
        cnconsult.Logger.log({prefix:'MigrateData-\x3edoMigration', message:"Couldn't load data directory", level:'error'});
        this.finishMigration();
      }, this));
    } else {
      cnconsult.Logger.log({prefix:'MigrateData-\x3edoMigration', message:"fs-data directory couldn't be loaded! Continuing synchronisation...", level:'error'});
      this.finishMigration();
    }
  }, this), Ext.bind(function() {
    cnconsult.Logger.log({prefix:'MigrateData-\x3edoMigration', message:"Couldn't load fs-data directory", level:'error'});
    this.finishMigration();
  }, this));
}, finishMigration:function() {
  var master = dilocsync.core.Master;
  cnconsult.Logger.log({prefix:'MigrateData-\x3efinishMigration', message:'Exiting migration: deleting system directory...'});
  master.deleteSystemDirectory(function(_success) {
    cnconsult.Logger.log({prefix:'MigrateData-\x3efinishMigration', message:'deleting data directory. Success: ' + _success});
    master.deleteDataDirectory(function(_success) {
      master.getStorage().set('sync4DataMigrated', true);
      cnconsult.Logger.log({prefix:'MigrateData-\x3efinishMigration', message:'Data successfully migrated to sync4 (db-based)!. Success: ' + _success});
      dilocsync.util.MaskHelper.hideLoadingMask();
      Ext.callback(this.nextCallback, this.callbackScope);
    }, this);
  }, this);
}, iterateOverAlmanacs:function(_fsDataFolderEntry, _callback, _scope) {
  var almanacsInfoList = this.syncData.getAlmanacsInfoList();
  var remoteAlmanacs = this.syncData.getRemoteAlmanacs();
  var remoteAlmanacsMap = Ext.isArray(remoteAlmanacs) ? Ext.Array.toValueMap(remoteAlmanacs, 'identifier') : {};
  var i = 0;
  function migrateNextAlmanac() {
    if (i < almanacsInfoList.length) {
      var almanacInfo = almanacsInfoList[i];
      cnconsult.Logger.log({prefix:'MigrateData-\x3eiterateOverAlmanacs', message:'Checking almanacInfo : ' + almanacInfo.identifier, dump:almanacInfo});
      if (!Ext.Array.contains(['customer-data'], almanacInfo.identifier)) {
        cnconsult.Logger.log({prefix:'MigrateData-\x3eiterateOverAlmanacs', message:'Is no customer-data almanac. Going on...', dump:almanacInfo});
        var remoteAlmanac = remoteAlmanacsMap[almanacInfo.identifier];
        if (remoteAlmanac) {
          var almanac = new dilocsync.core.Almanac({root:remoteAlmanac.rootDirectory, identifier:remoteAlmanac.identifier, path:remoteAlmanac.path, createdAt:remoteAlmanac.createdAt, updatedAt:remoteAlmanac.updatedAt, version:remoteAlmanac.version});
          if (almanac && almanac.getRootDirectory()) {
            var filesToMigrate = [];
            this.findFilesToMigrateRecursively(almanac.getRootDirectory(), remoteAlmanac.path, filesToMigrate);
            this.migrateFiles(filesToMigrate, _fsDataFolderEntry, function() {
              cnconsult.Logger.log({prefix:'MigrateData-\x3eiterateOverAlmanacs', message:'Almanac migration finished. Persisting almanac with path: ' + remoteAlmanac.path});
              this.persistAlmanac(almanac, remoteAlmanac.path);
              i++;
              cnconsult.Logger.log({prefix:'MigrateData-\x3eiterateOverAlmanacs', message:'Go on migrating next almanac ..'});
              migrateNextAlmanac.apply(this);
            }, this);
          } else {
            cnconsult.Logger.log({prefix:'MigrateData-\x3eiterateOverAlmanacs', message:'No Almanac object build for identifier: : ' + almanacInfo.identifier, level:'error', dump:almanacInfo});
            i++;
            migrateNextAlmanac.apply(this);
          }
        } else {
          cnconsult.Logger.log({prefix:'MigrateData-\x3eiterateOverAlmanacs', message:'No remote almanac found for identifier: : ' + almanacInfo.identifier, level:'error', dump:almanacInfo});
          i++;
          migrateNextAlmanac.apply(this);
        }
      } else {
        cnconsult.Logger.log({prefix:'MigrateData-\x3eiterateOverAlmanacs', message:'Almanac ignored for identifier: : ' + almanacInfo.identifier, level:'info', dump:almanacInfo});
        i++;
        migrateNextAlmanac.apply(this);
      }
    } else {
      Ext.callback(_callback, _scope);
    }
  }
  migrateNextAlmanac.apply(this);
}, findFilesToMigrateRecursively:function(_directory, _almanacBasePath, _filesToMigrate) {
  var me = this;
  Ext.Object.each(_directory.files, function(_fileName, _fileInfo) {
    _filesToMigrate.push({fileName:_fileName, fileInfo:_fileInfo, fullPath:_almanacBasePath + _directory.path + _fileName});
  }, me);
  Ext.Object.each(_directory.directories, function(_directoryName, _subDirectory) {
    cnconsult.Logger.log({prefix:'MigrateData-\x3efindFilesToMigrateRecursively', message:'Finding files in sub directory: ' + _subDirectory, dump:{subDirectory:_subDirectory, almanacBasePath:_almanacBasePath}});
    me.findFilesToMigrateRecursively(_subDirectory, _almanacBasePath, _filesToMigrate);
  }, me);
}, migrateFiles:function(_filesToMigrate, _fsDataFolderEntry, _callback, _scope) {
  var master = dilocsync.core.Master;
  cnconsult.Logger.log({prefix:'MigrateData-\x3emigrateFiles', message:'files to migrate:', dump:_filesToMigrate});
  var i = 0;
  function migrateNextFile() {
    if (i < _filesToMigrate.length) {
      var file = _filesToMigrate[i];
      var filePath = file.fullPath;
      cnconsult.Logger.log({prefix:'MigrateData-\x3emigrateFiles', message:'Migrating filePath: ' + filePath, dump:{fileName:file.fileName, fileInfo:file.fileInfo}});
      master.getSyncRoot().getFile(filePath, null, Ext.bind(function(_fileEntry) {
        if (_fileEntry) {
          cnconsult.Logger.log({prefix:'MigrateData-\x3emigrateFiles', message:'File entry loaded. Start moving it...'});
          _fileEntry.moveTo(_fsDataFolderEntry, file.fileInfo.checksum + '.' + file.fileInfo.fileType, function() {
            cnconsult.Logger.log({prefix:'MigrateData-\x3emigrateFiles', message:'File moved to fs-data/' + file.fileInfo.checksum + '.' + file.fileInfo.fileType});
            i++;
            migrateNextFile.apply(this);
          }, function() {
            cnconsult.Logger.log({prefix:'MigrateData-\x3emigrateFiles', message:'ERROR during fileEntry moveTo new position', level:'error', dump:arguments});
            i++;
            migrateNextFile.apply(this);
          });
        } else {
          cnconsult.Logger.log({prefix:'MigrateData-\x3emigrateFiles', message:"Couldn't load file entry for path " + filePath, level:'error'});
          i++;
          migrateNextFile.apply(this);
        }
      }, this), Ext.bind(function() {
        cnconsult.Logger.log({prefix:'MigrateData-\x3emigrateFiles', message:"Couldn't load file entry for path " + filePath, level:'error'});
        i++;
        migrateNextFile.apply(this);
      }, this));
    } else {
      cnconsult.Logger.log({prefix:'MigrateData-\x3emigrateFiles', message:'we finished migrating all files of this Almanac...'});
      Ext.callback(_callback, _scope);
    }
  }
  migrateNextFile.apply(this);
}});
Ext.define('dilocsync.model.CompletedForm', {extend:dilocsync.model.Form, idProperty:'savedAt', fields:[{name:'savedAt', type:'integer'}, {name:'syncedAt', type:'integer'}, {name:'syncState', type:'string', defaultValue:'unsynced'}, {name:'completedFormPath', type:'string', calculate:function(_data) {
  return 'forms/' + _data.id + '/' + _data.version + '_' + _data.savedAt + '.json';
}}, {name:'icon', type:'string', calculate:function(_data) {
  return 'form-icon-completed-' + _data.syncState;
}}], setSavedAt:function() {
  this.set('savedAt', Date.now() / 1000);
}, setSyncedAt:function() {
  this.set('syncedAt', Date.now() / 1000);
}, removeFileEntry:function() {
  dilocsync.core.Master.getSyncRoot().getFile(this.get('completedFormPath'), {}, function(_file) {
    _file.remove();
  });
}});
Ext.define('dilocsync.store.CompletedForms', {extend:dilocsync.store.DiLocStorage, mixins:[cnconsult.Translatable], storeId:'CompletedForms', model:'dilocsync.model.CompletedForm', saveKey:'page:forms:completedForms', autoLoad:true, sorters:{property:'savedAt', direction:'DESC'}, listeners:{remove:function(_store, _records) {
  for (var $jscomp$iter$22 = $jscomp.makeIterator(_records), $jscomp$key$record = $jscomp$iter$22.next(); !$jscomp$key$record.done; $jscomp$key$record = $jscomp$iter$22.next()) {
    var record = $jscomp$key$record.value;
    {
      record.removeFileEntry();
    }
  }
}, datachanged:function(_store) {
  var draftCount = _store.countDrafts();
  var menuItem = Ext.getStore('menuItems').findRecord('view', 'forms');
  if (menuItem) {
    menuItem.set('badgeText', draftCount > 0 ? draftCount : '');
  }
}, update:function(_store, _record, _operation, _modifiedFieldNames) {
  if (Ext.isArray(_modifiedFieldNames) && _modifiedFieldNames.includes('savedAt')) {
    var path = Ext.valueFrom(_record.getPrevious('path'), _record.get('path'));
    var completedFormPath = Ext.String.insert(path, '_' + _record.getPrevious('savedAt'), -5);
    dilocsync.util.File.getRelativeFile(completedFormPath).then(function(_fileEntry) {
      _fileEntry.remove();
    })['catch'](function() {
    });
  }
}}, constructor:function() {
  var groupOrder = [this.tr('Draft'), 'unsynced', this.tr('Awaiting synchronization'), 'prepared', this.tr('Synchronized'), 'synced'];
  this.callParent(arguments);
  this.setGrouper({groupFn:function(_record) {
    switch(_record.get('syncState')) {
      case 'unsynced':
        return groupOrder[0];
      case 'prepared':
        return groupOrder[2];
      case 'synced':
        return groupOrder[4];
    }
  }, property:'syncState', sorterFn:function(_record1, _record2) {
    return groupOrder.indexOf(_record1.get('syncState')) - groupOrder.indexOf(_record2.get('syncState'));
  }});
}, countDrafts:function() {
  var draftCount = 0;
  for (var $jscomp$iter$23 = $jscomp.makeIterator(this.getRange()), $jscomp$key$record = $jscomp$iter$23.next(); !$jscomp$key$record.done; $jscomp$key$record = $jscomp$iter$23.next()) {
    var record = $jscomp$key$record.value;
    {
      if (record.get('syncState') === 'unsynced') {
        draftCount++;
      }
    }
  }
  return draftCount;
}});
Ext.define('dilocsync.core.syncengine.tasks.db.SyncCompletedForms', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var $jscomp$this = this;
  if (this.doExecuteTask()) {
    var store = dilocsync.util.Helper.initStore('CompletedForms');
    var completedForms = [];
    for (var $jscomp$iter$24 = $jscomp.makeIterator(store.getRange()), $jscomp$key$record = $jscomp$iter$24.next(); !$jscomp$key$record.done; $jscomp$key$record = $jscomp$iter$24.next()) {
      var record = $jscomp$key$record.value;
      {
        if (record.get('syncState') === 'prepared') {
          completedForms.push(record);
        }
      }
    }
    if (completedForms.length > 0) {
      this.fireEvent('syncprogress', this.tr('Uploading the completed forms...'), 0, 0, null);
      var walker = new dilocsync.core.AsyncWalk;
      var additionalParams = [this.master.getSyncRoot().toURL(), this.master.getBackendUrl() + '/formclientsync/submitForm', {syncSecret:this.storage.get('core:personalization:syncSecret')}];
      var submitForms = new Ext.Promise(function(_resolve, _reject) {
        walker.walkArray(completedForms, $jscomp$this.submitForm, $jscomp$this, _resolve, $jscomp$this, additionalParams);
      });
      submitForms.then(function() {
        store.sync();
        store.sort('savedAt', 'DESC');
        $jscomp$this.fireEvent('syncprogress', $jscomp$this.tr('Successfully uploaded the completed forms'), 0, 0, null);
        Ext.callback(_next, _scope, [true]);
      });
    } else {
      Ext.callback(_next, _scope, [true]);
    }
  } else {
    Ext.callback(_next, _scope);
  }
}, submitForm:function(_record, _callback, _syncRoot, _url, _params) {
  _params.formId = _record.get('id');
  var options = new FileUploadOptions;
  options.fileKey = 'form';
  options.fileName = _record.get('version') + '_' + _record.get('savedAt') + '.json';
  options.mimeType = 'application/json';
  options.params = _params;
  var fileTransfer = new FileTransfer;
  fileTransfer.onprogress = function(_progress) {
    console.log('upload progress of form file', _progress);
  };
  fileTransfer.upload(_syncRoot + _record.get('completedFormPath'), _url, function(_result) {
    var response = JSON.parse(_result.response);
    if (response.success) {
      _record.setSyncedAt();
      _record.set('syncState', 'synced');
      _record.commit();
      cnconsult.Logger.log({prefix:'SyncCompletedForms-\x3esubmitForm', message:'Form successfully uploaded to server', dump:_result});
      _callback();
    } else {
      cnconsult.Logger.log({prefix:'SyncCompletedForms-\x3esubmitForm', message:'Server response from uploading form was not successful', level:'error', dump:{form:_record, fileUploadResult:_result}});
      _callback();
    }
  }, function(_error) {
    cnconsult.Logger.log({prefix:'SyncCompletedForms-\x3esubmitForm', message:'Upload of form failed', level:'error', dump:{form:_record, fileTransferError:_error}});
    _callback();
  }, options);
}});
Ext.define('dilocsync.core.syncengine.tasks.db.SyncConfirmations', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Syncing confirmations...'), 0, 0, null);
  var identity = this.master.getIdentity();
  if (identity.options && (typeof identity.options.disableReadConfirmations === 'undefined' || !identity.options.disableReadConfirmations)) {
    var confirmationsStore = Ext.getStore('Confirmations');
    if (confirmationsStore) {
      var confirmedFiles = [];
      if (confirmationsStore) {
        var confirmedRecords = confirmationsStore.getConfirmedFiles();
        for (var i = 0; i < confirmedRecords.length; i++) {
          var confirmedData = confirmedRecords[i].getData();
          confirmedFiles.push({requestId:confirmedData.requestId, confirmationTimestamp:confirmedData.confirmationTimestamp, confirmationQuestion:confirmedData.confirmationText, signature:confirmedData.signature});
        }
      } else {
        cnconsult.Logger.log({prefix:'SyncConfirmations-\x3eexecute', message:'No ReadConfirmationStore created!'});
      }
      Ext.Ajax.request({url:this.master.getBackendUrl() + '/clientsync/syncConfirmations', timeout:2 * 60000, params:{syncSecret:this.storage.get('core:personalization:syncSecret'), confirmedFiles:Ext.encode(confirmedFiles)}, success:function(response) {
        response = Ext.decode(response.responseText, true);
        if (response && response.success) {
          var responseData = response.hasOwnProperty('data') ? response.data : response.result;
          var newFilesToConfirm = [];
          if (responseData) {
            if (responseData.deviceIdCode === this.master.deviceIdCode() && responseData.syncSecret === this.storage.get('core:personalization:syncSecret')) {
              for (var i = 0; i < responseData.confirmationRequests.length; i++) {
                var newFileToConfirm = responseData.confirmationRequests[i];
                newFilesToConfirm.push({requestId:newFileToConfirm.requestId, name:dilocsync.util.File.basename(newFileToConfirm.path), path:dilocsync.util.File.formatPath(newFileToConfirm.path), uuid:newFileToConfirm.uuid, checksum:newFileToConfirm.checksum, fileType:dilocsync.util.File.extension(newFileToConfirm.path).toLowerCase(), state:'unconfirmed', confirmationTimestamp:newFileToConfirm.confirmationTimestamp, confirmationText:newFileToConfirm.confirmationQuestion, buttonText:newFileToConfirm.buttonText, 
                visibleFrom:newFileToConfirm.visibleFrom, visibleTo:newFileToConfirm.visibleTo, signatureRequired:newFileToConfirm.signatureRequired, rootFsEntryName:'fs-data'});
              }
            }
          } else {
            cnconsult.Logger.log({prefix:'SyncConfirmations-\x3eexecute', message:'No data retrieved, need to be checked!', level:'warn', dump:responseData});
          }
          confirmationsStore.setData(newFilesToConfirm);
          confirmationsStore.sync();
          var grouper = confirmationsStore.getGrouper();
          confirmationsStore.setGrouper(null);
          confirmationsStore.setGrouper(grouper);
          Ext.callback(_next, _scope, [true]);
        } else {
          cnconsult.Logger.log({prefix:'responseData', message:'"An error occurred while syncing the confirmation requests.', level:'error', dump:response, useSentry:true});
          Ext.callback(_abort, _scope, [false, this.tr('An error occurred while syncing the confirmation requests.')]);
        }
      }, failure:function(response) {
        cnconsult.Logger.log({prefix:'SyncConfirmations-\x3eexecute', message:'An error occurred while syncing the confirmation requests.', level:'error', dump:response, useSentry:true});
        Ext.callback(_abort, _scope, [false, this.tr('An error occurred while syncing the confirmation requests.')]);
      }, scope:this});
    }
  } else {
    Ext.callback(_next, _scope);
  }
}});
Ext.define('dilocsync.core.syncengine.tasks.db.SyncFinish', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Finishing synchronization...'), 0, 0, null);
  Ext.Ajax.request({url:this.master.getBackendUrl() + '/clientsync/finished', params:{syncDeviceIdCode:this.master.deviceIdCode(), syncSecret:this.storage.get('core:personalization:syncSecret')}, success:function(response) {
    var reply = null;
    try {
      reply = Ext.decode(response.responseText);
      this.master.initAlmanacs();
    } catch (e$100) {
      cnconsult.Logger.log({prefix:'SyncFinish-\x3eexecute', message:'Unknown server-error finishing synchronization.', level:'error', catchedError:e$100, useSentry:true});
      Ext.callback(_abort, _scope, [false, this.tr('Unknown server-error finishing synchronization.')]);
    }
    if (reply && reply.success) {
      Ext.callback(_next, _scope);
    } else {
      if (reply && reply.backendError) {
        Ext.callback(_abort, _scope, [false, this.tr('Server-error finishing synchronization: %1').arg(reply.backendError)]);
      }
    }
  }, failure:function() {
    Ext.callback(_abort, _scope, [false, this.tr('Error finishing synchronization.')]);
  }, scope:this});
}});
Ext.define('dilocsync.store.LocomotionTypes', {extend:dilocsync.store.DiLocStorage, storeId:'LocomotionTypes', saveKey:'page:driveInfo:locomotionTypes', alias:'store.locomotiontypes', sorters:[{property:'typeShort', direction:'ASC'}], fields:[{name:'id', type:'int'}, {name:'typeShort', type:'string'}, {name:'typeLong', type:'string'}, {name:'displayName', calculate:function(data) {
  return data.typeShort + (data.typeLong ? ' (' + data.typeLong + ')' : '');
}}], autoLoad:true});
Ext.define('dilocsync.core.syncengine.tasks.db.SyncLocomotionTypes', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var $jscomp$this = this;
  if (this.doExecuteTask()) {
    this.fireEvent('syncprogress', this.tr('Syncing locomotion types...'), 0, 0, null);
    this.downloadLocomotionTypes().then(function(_locomotionTypes) {
      var locomotionTypesStore = dilocsync.util.Helper.initStore('LocomotionTypes');
      locomotionTypesStore.setData(_locomotionTypes.map(function(val) {
        return {id:val.id, typeShort:val.locoTypeShort, typeLong:val.locoTypeLong};
      }));
      locomotionTypesStore.sync();
      Ext.callback(_next, _scope, [true]);
    })['catch'](function(_err) {
      Ext.callback(_abort, _scope, [false, $jscomp$this.tr('An error occurred while syncing the locomotion types!')]);
    });
  } else {
    Ext.callback(_next, _scope);
  }
}, downloadLocomotionTypes:function() {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    Ext.Ajax.request({url:$jscomp$this.master.getBackendUrl() + '/locotypeknowledge/getLocoTypesForSyncClient', params:{syncSecret:$jscomp$this.storage.get('core:personalization:syncSecret'), deviceIdCode:$jscomp$this.master.deviceIdCode()}, success:function(_response) {
      var response = Ext.decode(_response.responseText, true);
      if (response && response.success) {
        _resolve(response.result);
      } else {
        _reject(response);
      }
    }, failure:function(_response) {
      _reject(_response);
    }, scope:$jscomp$this});
  });
}});
Ext.define('dilocsync.store.DigitalOrderTokens', {extend:dilocsync.store.DiLocStorage, storeId:'DigitalOrderTokens', saveKey:'page:driveInfo:digitalOrderTokens', alias:'store.digitalordertokens', fields:[{name:'companyName', type:'string'}, {name:'companyCode', type:'string'}, {name:'createdAt', type:'string'}, {name:'userId', type:'string'}, {name:'signature', type:'string'}, {name:'token', calculate:function(_data) {
  return 'DOP-JSON-HMAC-SHA512 ' + Ext.encode({companyCode:_data.companyCode, createdAt:_data.createdAt, userId:_data.userId, signature:_data.signature});
}}], autoLoad:true});
Ext.define('dilocsync.core.syncengine.tasks.db.SyncTokens', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, execute:function(_next, _abort, _scope) {
  var $jscomp$this = this;
  if (this.doExecuteTask()) {
    this.fireEvent('syncprogress', this.tr('Syncing tokens...'), 0, 0, null);
    this.getDigitalOrderConfig().then(function(_config) {
      $jscomp$this.storage.set('page:driveInfo:digitalOrderMode', _config.mode);
      $jscomp$this.storage.set('page:driveInfo:digitalOrderUrl', _config.url);
      var digitalOrderTokenStore = Ext.getStore('DigitalOrderTokens');
      digitalOrderTokenStore.setData(_config.accessData);
      digitalOrderTokenStore.sync();
      Ext.callback(_next, _scope, [true]);
    })['catch'](function(_err) {
      Ext.callback(_abort, _scope, [false, $jscomp$this.tr('An error occurred while syncing the tokens!')]);
    });
  } else {
    Ext.callback(_next, _scope);
  }
}, getDigitalOrderConfig:function() {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    Ext.Ajax.request({url:$jscomp$this.master.getBackendUrl() + '/clientsync/getDigitalOrderConfig', params:{syncSecret:$jscomp$this.storage.get('core:personalization:syncSecret'), deviceIdCode:$jscomp$this.master.deviceIdCode()}, success:function(_response) {
      var response = Ext.decode(_response.responseText, true);
      if (response && response.success) {
        _resolve(response.result);
      } else {
        _reject(response);
      }
    }, failure:function(_response) {
      _reject(_response);
    }, scope:$jscomp$this});
  });
}});
Ext.define('dilocsync.core.syncengine.tasks.db.SynchronizeFiles', {extend:dilocsync.core.syncengine.tasks.BaseSyncTask, documentRepository:null, nextCallback:null, abortCallback:null, callbackScope:null, overallProgress:null, fileProgress:null, deleteProgress:null, downloadUrlPrefix:'', localUrlPrefix:'', numDownloadErrors:0, notDownloadedFiles:null, filesExistCache:null, currentFileTransfer:null, constructor:function(_config) {
  this.documentRepository = _config.documentRepository;
  this.callParent([_config]);
}, abort:function() {
  if (this.currentFileTransfer) {
    this.currentFileTransfer.abort();
  }
  this.callParent();
}, execute:function(_next, _abort, _scope) {
  this.fireEvent('syncprogress', this.tr('Syncing files...'), 0, 0, null);
  if (this.abortNeeded) {
    Ext.callback(_abort, _scope, [false, 'noalert']);
    return;
  }
  this.nextCallback = _next;
  this.abortCallback = _abort;
  this.callbackScope = _scope;
  this.notDownloadedFiles = {};
  this.filesExistCache = {};
  this.initProgress();
  this.initDownloadUrlPrefix();
  this.initFileSystem();
  this.startProgress();
}, initProgress:function() {
  var downloadSize = this.syncData.getDownloadSize();
  this.overallProgress = new dilocsync.core.ProgressCalculator({maxValue:downloadSize});
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3einitProgress', message:'Starting sync, total download size is ' + downloadSize});
}, initDeleteProgress:function() {
  this.deleteProgress = new dilocsync.core.ProgressCalculator({maxValue:this.countFilesToDelete});
}, initDownloadUrlPrefix:function() {
  this.downloadUrlPrefix = this.master.getBackendUrl() + '/clientsync/downloadFile?';
  this.downloadUrlPrefix += Ext.Object.toQueryString({syncSecret:this.storage.get('core:personalization:syncSecret'), syncDeviceIdCode:this.master.deviceIdCode()});
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3einitDownloadUrlPrefix', message:'Url-Prefix is: ' + this.downloadUrlPrefix});
}, initFileSystem:function() {
  this.fileSystem = this.master.getFileSystem();
}, startProgress:function() {
  this.fileSystem.root.getDirectory('sync', {create:true}, Ext.bind(this.progressFiles, this), Ext.bind(this.errorSyncRoot, this));
}, progressFiles:function(_syncRoot) {
  var $jscomp$this = this;
  var hasHighPriorityFiles = this.syncData.getHasHighPriorityFiles();
  this.setLocalUrlPrefix(_syncRoot);
  if (hasHighPriorityFiles) {
    this.downloadFilesPromise(true).then(function() {
      return $jscomp$this.updateFilesMetaDataPromise();
    }).then(function() {
      return $jscomp$this.onCompleteCallback();
    })['catch'](function() {
      return $jscomp$this.onFailureCallback();
    });
  } else {
    this.processFilesNoLongerInRemoteAlmanac().then(function() {
      return $jscomp$this.deleteFilesOnlyFromFileSystemPromise();
    }).then(function() {
      return $jscomp$this.deleteFilesOnlyFromAlmanacPromise();
    }).then(function() {
      return $jscomp$this.downloadFilesPromise();
    }).then(function() {
      return $jscomp$this.prepareFilesExistCache();
    }).then(function() {
      return $jscomp$this.checkDownloadedFilesPromise();
    }).then(function() {
      return $jscomp$this.retryDownloadErrorFilesPromise();
    }).then(function() {
      return $jscomp$this.updateFilesMetaDataPromise();
    }).then(function() {
      return $jscomp$this.onCompleteCallback();
    })['catch'](function() {
      return $jscomp$this.onFailureCallback();
    });
  }
}, setLocalUrlPrefix:function(_syncRoot) {
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3esetLocalUrlPrefix', message:'Got syncroot: ' + _syncRoot.toURL()});
  this.localUrlPrefix = _syncRoot.toURL();
}, downloadFilesPromise:function(_highPriority) {
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      var files;
      if (_highPriority && Ext.Object.getSize(_almanacSyncActions.getHighPriorityFilesToDownload()) > 0) {
        files = _almanacSyncActions.getHighPriorityFilesToDownload();
      } else {
        files = _almanacSyncActions.getFilesToDownload();
      }
      if (Ext.Object.getSize(files) > 0) {
        walker.walkObject(files, me.processDownloadFile, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises);
}, prepareFilesExistCache:function() {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    $jscomp$this.master.getSyncRoot().getDirectory('fs-data', {}, function(_dir) {
      dilocsync.util.File.readEntriesFromDirectory(_dir).then(function(_entries) {
        for (var $jscomp$iter$25 = $jscomp.makeIterator(_entries), $jscomp$key$fileEntry = $jscomp$iter$25.next(); !$jscomp$key$fileEntry.done; $jscomp$key$fileEntry = $jscomp$iter$25.next()) {
          var fileEntry = $jscomp$key$fileEntry.value;
          {
            $jscomp$this.filesExistCache[fileEntry.name] = true;
          }
        }
        _resolve();
      })['catch'](_reject);
    }, _reject);
  });
}, checkDownloadedFilesPromise:function() {
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActionsBackup = this.syncData.getAlmanacsSyncActionsBackup();
  var promises = [];
  Ext.Array.each(almanacsSyncActionsBackup, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      var filesToCheck = Ext.apply(_almanacSyncActions.getFilesToDownload(), _almanacSyncActions.getFilesNeedMetaUpdate());
      if (Ext.Object.getSize(filesToCheck) > 0) {
        walker.walkObject(filesToCheck, me.checkFileExistence, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises);
}, checkFileExistence:function(_path, _fileInfo, _callback, _almanacSyncActions) {
  var fileName = _fileInfo.checksum + '.' + _fileInfo.fileType;
  if (!(fileName in this.filesExistCache)) {
    console.log('SynchronizeFiles -\x3e checkFileExistence: File does not exist on the device, add it to files to retry download!', fileName, _path, _fileInfo);
    this.numDownloadErrors++;
    this.notDownloadedFiles[_path] = {file:_fileInfo, almanacSyncActions:_almanacSyncActions};
  }
  _callback();
}, updateFilesMetaDataPromise:function() {
  var me = this;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      var almanac = _almanacSyncActions.getAlmanac();
      var almanacPath = _almanacSyncActions.getAlmanacPath();
      var files = _almanacSyncActions.getFilesNeedMetaUpdate();
      if (Ext.Object.getSize(files) > 0) {
        Ext.Object.each(files, function(_filePath, _fileInfo) {
          almanac.updateFile(_filePath, _fileInfo.size, _fileInfo.checksum, _fileInfo);
        }, me);
        me.persistAlmanac(almanac, almanacPath);
      }
      _resolve();
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises);
}, processFilesNoLongerInRemoteAlmanac:function() {
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  me.initDeleteProgress();
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      var files = _almanacSyncActions.getFilesToDelete();
      if (Ext.Object.getSize(files) > 0) {
        walker.walkObject(files, me.processFileNoLongerInRemoteAlmanac, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises);
}, deleteFilesOnlyFromFileSystemPromise:function() {
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      var files = _almanacSyncActions.getFilesOnlyToDeleteFromFileSystem();
      if (Ext.Object.getSize(files) > 0) {
        walker.walkObject(files, me.processDeleteFileOnlyFromDocumentRepositoryForUser, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises);
}, deleteFilesOnlyFromAlmanacPromise:function() {
  var me = this;
  var walker = new dilocsync.core.AsyncWalk;
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var promises = [];
  Ext.Array.each(almanacsSyncActions, function(_almanacSyncActions) {
    var promise = new Ext.Promise(function(_resolve, _reject) {
      var files = _almanacSyncActions.getFilesOnlyToDeleteFromAlmanac();
      if (Ext.Object.getSize(files) > 0) {
        walker.walkObject(files, me.processDeleteFileOnlyFromAlmanac, me, _resolve, me, [_almanacSyncActions]);
      } else {
        _resolve();
      }
    });
    promises.push(promise);
  }, me);
  return Ext.Promise.all(promises);
}, retryDownloadErrorFilesPromise:function() {
  var me = this;
  return new Ext.Promise(function(_resolve, _reject) {
    if (me.numDownloadErrors > 0) {
      var identity = me.master.getIdentity();
      if (identity && identity.options && identity.options.redownloadErrorFiles) {
        var walker = new dilocsync.core.AsyncWalk;
        cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eretryDownloadErrorFilesPromise', message:'There were download errors, trying to download them again'});
        me.numDownloadErrors = 0;
        if (Ext.Object.getSize(me.notDownloadedFiles) > 0) {
          walker.walkObject(me.notDownloadedFiles, me.processDownloadFile, me, _resolve, me, []);
        } else {
          _resolve();
        }
      } else {
        cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eretryDownloadErrorFilesPromise', message:'We had download errors!'});
        _reject();
      }
    } else {
      cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eretryDownloadErrorFilesPromise', message:'No download errors, sync finished successfully!'});
      _resolve();
    }
  });
}, onFailureCallback:function() {
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eonFailureCallback', message:'catch rejected promise during sync', level:'error', dump:arguments, trace:true, useSentry:true});
  Ext.callback(this.abortCallback, this.callbackScope, [false, this.tr('Some files failed to synchronize! This is most probably due to network errors. You should just try again.')]);
}, onCompleteCallback:function() {
  if (this.numDownloadErrors > 0) {
    cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eonCompleteCallback', message:'There were again download errors.'});
    Ext.callback(this.abortCallback, this.callbackScope, [false, this.tr('Some files failed to synchronize! This is most probably due to network errors. You should just try again.')]);
  } else {
    cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eonCompleteCallback', message:'No download errors, finishing sync process...'});
    var almanacSyncActions = this.syncData.getAlmanacsSyncActions(), hadNormalDownloadedFiles = false;
    Ext.Array.each(almanacSyncActions, function(_almanacSyncActions) {
      if (Ext.Object.getSize(_almanacSyncActions.getFilesToDownload()) > 0) {
        hadNormalDownloadedFiles = true;
      }
    }, this);
    if (!this.syncData.getHasHighPriorityFiles() || this.syncData.getHasHighPriorityFiles() && !hadNormalDownloadedFiles) {
      cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eonCompleteCallback', message:'No further files to download, save almanacs info list.', dump:this.syncData.getAlmanacsInfoList()});
      this.storage.set('core:almanacs', this.syncData.getAlmanacsInfoList());
    } else {
      cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eonCompleteCallback', message:'There are still some files to download. Continue but do not save almanacs info list.', dump:{almanacSyncActions:almanacSyncActions, almanacsInfoList:this.syncData.getAlmanacsInfoList()}});
    }
    Ext.callback(this.nextCallback, this.callbackScope);
  }
}, processDownloadFile:function(_path, _info, _callback, _almanacSyncActions) {
  if (this.abortNeeded) {
    Ext.callback(this.abortCallback, this.callbackScope, [false, 'noalert']);
    return;
  }
  var info = _info, almanacSyncActions = _almanacSyncActions;
  if (_info.hasOwnProperty('file') && _info.hasOwnProperty('almanacSyncActions')) {
    info = _info.file;
    almanacSyncActions = _info.almanacSyncActions;
    delete _info.almanacSyncActions;
  }
  var currentProgressText = this.tr('Downloading %1 ...').arg(dilocsync.util.File.basename(_path));
  var fileProgress = new dilocsync.core.ProgressCalculator({maxValue:info.size});
  var url = this.downloadUrlPrefix + '\x26uuid\x3d' + info.uuid;
  var fileName = info.checksum + '.' + info.fileType;
  var localFilePath = this.localUrlPrefix + 'fs-data/' + fileName;
  this.updateOverallProgress(_path, currentProgressText);
  var fileLoaded = 0;
  this.currentFileTransfer = new FileTransfer;
  this.currentFileTransfer.onprogress = Ext.bind(this.fileDownloadUpdateProgress, this, [fileProgress, currentProgressText], true);
  this.currentFileTransfer.download(url, dilocsync.util.File.encodeURI(localFilePath), Ext.bind(function(_fileEntry) {
    var $jscomp$this = this;
    console.log('finished download of file ' + _path + ' to ' + _fileEntry.toURL());
    this.fireEvent('syncprogress', currentProgressText, this.overallProgress.percentage(), 100, this.overallProgress.remainingDownloadTime(), true);
    dilocsync.util.File.sha256OfFileEntry(_fileEntry, function(_hash) {
      cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDownloadFile', message:'Sha256 of file is: ' + _hash});
      if (info.checksum !== _hash) {
        cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDownloadFile', message:'Mismatching checksum of downloaded file and remote almanac checksum!', level:'error', dump:{'path':_path, 'almanacChecksum':_info.checksum, 'calculatedChecksum':_hash}, useSentry:true});
        $jscomp$this.numDownloadErrors++;
        $jscomp$this.notDownloadedFiles[_path] = {file:_info, almanacSyncActions:_almanacSyncActions};
      } else {
        cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDownloadFile', message:'File completely downloaded, adding it to almanac: ' + _path});
        var almanac = almanacSyncActions.getAlmanac();
        var almanacPath = almanacSyncActions.getAlmanacPath();
        almanac.updateFile(_path, info.size, _hash, _info);
        $jscomp$this.persistAlmanac(almanac, almanacPath);
      }
      _callback();
    }, function(_errorEvent) {
      cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDownloadFile', message:'Sync-Error: Error getting hash of fileEntry!', level:'error', dump:{'path':_path, '_errorEvent':_errorEvent}, useSentry:true});
      $jscomp$this.numDownloadErrors++;
      _callback();
    });
  }, this), Ext.bind(function(error) {
    cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDownloadFile', message:'Sync-Error: Download error!', level:'error', catchedError:error, useSentry:true});
    this.numDownloadErrors++;
    this.notDownloadedFiles[_path] = {file:_info, almanacSyncActions:_almanacSyncActions};
    _callback();
  }, this));
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDownloadFile', message:'Starting download of file:  ' + _path});
}, fileDownloadUpdateProgress:function(_progressEvent, _fileProgress, _currentProgressText) {
  if (_progressEvent.lengthComputable) {
    this.overallProgress.increaseCurrentValue(_progressEvent.loaded - _fileProgress.currentValue);
    _fileProgress.setCurrentValue(_progressEvent.loaded);
    this.fireEvent('syncprogress', _currentProgressText, this.overallProgress.percentage(), _fileProgress.percentage(), this.overallProgress.remainingDownloadTime(), true);
  }
}, fileDownloadComplete:function(_path, _info, _callback, _downloadRequest, _almanacSyncActions) {
  if (_downloadRequest.status === 200) {
    this.fileSystem.root.getFile('sync/fs-data/' + _info.checksum + '.' + _info.fileType, {create:true}, Ext.bind(this.onGetFile, this, [_path, _info, _callback, _downloadRequest, _almanacSyncActions], true), Ext.bind(this.fileDownloadError, this, [_path, _info, _callback, _almanacSyncActions], true));
  } else {
    this.fileDownloadError({}, _path, _info, _callback, _almanacSyncActions);
  }
}, onGetFile:function(_fileEntry, _path, _info, _callback, _downloadRequest, _almanacSyncActions) {
  _fileEntry.createWriter(Ext.bind(this.onCreateWriter, this, [_fileEntry, _path, _info, _callback, _downloadRequest, _almanacSyncActions], true), Ext.bind(this.fileDownloadError, this, [_path, _info, _callback, _almanacSyncActions], true));
}, onCreateWriter:function(_fileWriter, _fileEntry, _path, _info, _callback, _downloadRequest, _almanacSyncActions) {
  var blob = _downloadRequest.response;
  _fileWriter.onwriteend = Ext.bind(this.onWriteEnd, this, [_fileEntry, _path, _info, _callback, _almanacSyncActions, blob], false);
  _fileWriter.onerror = Ext.bind(this.fileDownloadError, this, [_path, _info, _callback, _almanacSyncActions], true);
  _fileWriter.write(blob);
}, onWriteEnd:function(_fileEntry, _path, _info, _callback, _almanacSyncActions, _blob) {
  _fileEntry.file(Ext.bind(this.onWriteEndFileSuccess, this, [_path, _info, _callback, _almanacSyncActions, _blob], true), Ext.bind(this.onWriteEndFileFailure, this, [_path, _info, _callback, _almanacSyncActions], true));
}, onWriteEndFileSuccess:function(_file, _path, _info, _callback, _almanacSyncActions, _blob) {
  var me = this;
  this.fireEvent('syncprogress', this.tr('Checking %1 ...').arg(dilocsync.util.File.basename(_path)), this.overallProgress.percentage(), 100, this.overallProgress.remainingDownloadTime());
  crypto.subtle.digest('SHA-256', _blob).then(function(_checksumArrayBuffer) {
    var checksum = Array.prototype.map.call(new Uint8Array(_checksumArrayBuffer), function(x) {
      return ('00' + x.toString(16)).slice(-2);
    }).join('');
    me.checksumWorkerOnMessage({data:checksum}, _file, _path, _info, _callback, _almanacSyncActions);
  });
}, checksumWorkerOnMessage:function(_messageEvent, _file, _path, _info, _callback, _almanacSyncActions) {
  var almanac = _almanacSyncActions.getAlmanac();
  var almanacPath = _almanacSyncActions.getAlmanacPath();
  var checksum = _messageEvent.data;
  if (_info.checksum !== checksum) {
    cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3echecksumWorkerOnMessage', message:'Mismatching checksum of downloaded file and remote almanac checksum!', level:'error', dump:{'path':_path, 'almanacChecksum':_info.checksum, 'calculatedChecksum':checksum}, useSentry:true});
    this.numDownloadErrors++;
    this.notDownloadedFiles[_path] = {file:_info, almanacSyncActions:_almanacSyncActions};
  } else {
    almanac.updateFile(_path, _file.size, checksum, _info);
    this.persistAlmanac(almanac, almanacPath);
  }
  _callback();
}, onWriteEndFileFailure:function(_errorEvent, _path, _info, _callback, _almanacSyncActions) {
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eonWriteEndFileFailure', message:'Error getting file of fileEntry!', level:'error', catchedError:_errorEvent, useSentry:true});
  this.numDownloadErrors++;
  this.notDownloadedFiles[_path] = {file:_info, almanacSyncActions:_almanacSyncActions};
  _callback();
}, fileDownloadError:function(_progressEvent, _path, _info, _callback, _almanacSyncActions) {
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3efileDownloadError', message:'File download error', level:'error', dump:arguments, useSentry:true});
  this.numDownloadErrors++;
  this.notDownloadedFiles[_path] = {file:_info, almanacSyncActions:_almanacSyncActions};
  _callback();
}, updateOverallProgress:function(_path, _currentProgressText) {
  this.overallProgress.increaseFileCounter();
  this.fireEvent('syncprogress', _currentProgressText, this.overallProgress.percentage(), 0, this.overallProgress.remainingDownloadTime(), true);
}, _removeFile:function(_checksum, _fileExtension) {
  var currentUserId = this.storage.get('core:personalization:userid');
  return this.documentRepository.removeOwnerForDocument(_checksum, _fileExtension, currentUserId);
}, processDeleteFileOnlyFromDocumentRepositoryForUser:function(_path, _info, _callback, _almanacSyncActions) {
  this.deleteProgress.increaseCurrentValue(1);
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDeleteFileOnlyFromDocumentRepositoryForUser', message:'Removing file: ' + _path});
  return this._removeFile(_info.checksum, _info.fileType).then(function() {
    cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDeleteFileOnlyFromDocumentRepositoryForUser', message:'Removed file only from document repository: ' + _path});
    _callback();
  })['catch'](function(_err) {
    return _callback(_err);
  });
}, processFileNoLongerInRemoteAlmanac:function(_path, _info, _callback, _almanacSyncActions) {
  var $jscomp$this = this;
  this.deleteProgress.increaseCurrentValue(1);
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDeleteFile', message:'Deleting file ' + _path});
  var almanac = _almanacSyncActions.getAlmanac();
  var almanacPath = _almanacSyncActions.getAlmanacPath();
  var deleteFile = _info.hasOwnProperty('path') && _info.path.endsWith('/') ? Ext.Promise.resolve() : this._removeFile(_info.checksum, _info.fileType);
  deleteFile.then(function() {
    almanac.deletePath(_path);
    $jscomp$this.persistAlmanac(almanac, almanacPath);
    $jscomp$this.fireEvent('syncprogress', $jscomp$this.tr('Deleting files...'), 100, $jscomp$this.deleteProgress.percentage());
    _callback();
  })['catch'](function(_err) {
    return _callback(_err);
  });
}, processDeleteFileOnlyFromAlmanac:function(_path, _info, _callback, _almanacSyncActions) {
  this.deleteProgress.increaseCurrentValue(1);
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eprocessDeleteFileOnlyFromAlmanac', message:'Deleting file ' + _path + ' only from almanac'});
  var almanac = _almanacSyncActions.getAlmanac();
  var almanacPath = _almanacSyncActions.getAlmanacPath();
  almanac.deletePath(_path);
  this.persistAlmanac(almanac, almanacPath);
  _callback();
}, errorSyncRoot:function(_errorEvent) {
  cnconsult.Logger.log({prefix:'SynchronizeFiles-\x3eerrorSyncRoot', message:'Error retrieving syncroot!', level:'error', catchedError:_errorEvent, useSentry:true});
  Ext.callback(this.abortCallback, this.callbackScope, [false, this.tr('Unknown error during synchronization.')]);
}, countFilesToDelete:function() {
  var almanacsSyncActions = this.syncData.getAlmanacsSyncActions();
  var filesToDelete = {};
  Ext.Array.each(almanacsSyncActions, function(_syncActions) {
    Ext.apply(filesToDelete, _syncActions.getFilesToDelete());
  }, this);
  return Ext.Object.getSize(filesToDelete);
}});
Ext.define('dilocsync.model.DigitalOrder', {extend:Ext.data.Model, fields:[{name:'id', type:'string'}, {name:'state', type:'string', calculate:function(data) {
  switch(true) {
    case data.isRevoked:
      return 'Revoked';
    case data.isAcknowledgementReset:
      return 'AcknowledgementReset';
    case data.isAcknowledged && data.isCompleted:
      return 'Completed';
    case data.isAcknowledged:
      return 'Acknowledged';
    default:
      return 'New';
  }
}}, {name:'targetState', type:'string', allowNull:true}, {name:'styling', type:'string', defaultValue:''}, {name:'content', type:'string', convert:function(_value) {
  return _value.asHtml;
}}, {name:'html', type:'string', calculate:function(data) {
  var template = new Ext.XTemplate('\x3c!DOCTYPE HTML\x3e' + '\x3chtml lang\x3d"de"\x3e' + '\x3chead\x3e' + '\x3cmeta http-equiv\x3d"Content-Type" content\x3d"text/html; charset\x3dUTF-8"\x3e' + '\x3ctitle\x3eDiLoc|Sync\x3c/title\x3e' + '\x3cstyle\x3e{css}\x3c/style\x3e' + '\x3c/head\x3e' + '\x3cbody\x3e' + '\x3cmain\x3e{body}\x3c/main\x3e' + '\x3c/body\x3e' + '\x3c/html\x3e');
  return template.apply({css:window.Base64.decode(data.styling), body:window.Base64.decode(data.content)});
}}, {name:'isAcknowledged', type:'boolean', defaultValue:false}, {name:'isAcknowledgementReset', type:'boolean', defaultValue:false}, {name:'isCompleted', type:'boolean', defaultValue:false}, {name:'isRevoked', type:'boolean', defaultValue:false}, {name:'read', type:'boolean', defaultValue:false}], acknowledge:function() {
  this.set('targetState', 'Acknowledged', {dirty:false});
}, markCompleted:function() {
  this.set('targetState', 'Completed', {dirty:false});
}, markUncompleted:function() {
  this.set('targetState', 'Uncompleted', {dirty:false});
}});
Ext.define('dilocsync.model.DossierItem', {extend:Ext.data.TreeModel, identifier:'uuid', fields:[{name:'uuid', type:'string'}, {name:'fileType', type:'string'}, {name:'filePath', type:'string'}, {name:'path', type:'string'}, {name:'name', type:'string'}, {name:'checksum', type:'string'}, {name:'openFileOnPage', type:'integer', defaultValue:0}, {name:'addedAt', type:'date'}, {name:'size', type:'integer'}, {name:'icon', type:'string', defaultValue:'file'}, {name:'rootFsEntryName', type:'string'}, {name:'loaded', 
type:'boolean', defaultValue:false}]});
Ext.define('dilocsync.model.GeoStationModel', {extend:Ext.data.Model, alias:'model.geostationmodel', config:{fields:[{name:'idCode', type:'string'}, {name:'lat', type:'number'}, {name:'lon', type:'number'}, {name:'radius', type:'number'}, {name:'name', type:'string'}, {name:'possibleStations', type:'array'}]}});
Ext.define('dilocsync.model.ImportedDocument', {extend:Ext.data.Model, identifier:'uuid', fields:[{name:'uuid', type:'string'}, {name:'name', type:'string'}, {name:'fileType', type:'string'}, {name:'path', type:'string', calculate:function(_data) {
  return '/imports/' + _data.name;
}}, {name:'icon', type:'string'}, {name:'title', type:'string', calculate:function(_data) {
  return _data.name;
}}]});
Ext.define('dilocsync.model.Ride', {extend:Ext.data.Model, alias:'model.ride', config:{fields:[{name:'rideUid', type:'string'}, {name:'trainNumber', type:'string'}, {name:'locomotionType', allowNull:true}, {name:'startStation', allowNull:true}, {name:'endStation', allowNull:true}]}, submitStations:function() {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var url = master.getBackendUrl() + '/syncrideknowledge/submitStation';
  var syncSecret = storage.get('core:personalization:syncSecret');
  var rideUid = this.get('rideUid');
  var trainNumber = this.get('trainNumber');
  var locomotionType = Ext.Array.from(this.get('locomotionType'));
  var submitStartStation = this.doRequest(url, syncSecret, rideUid, trainNumber, locomotionType, this.get('startStation'), 'Start');
  var submitEndStation = this.doRequest(url, syncSecret, rideUid, trainNumber, locomotionType, this.get('endStation'), 'End');
  return new Promise(function(_resolve, _reject) {
    submitStartStation.then(function() {
      return submitEndStation.then(_resolve);
    })['catch'](_reject);
  });
}, doRequest:function(_url, _syncSecret, _rideUid, _trainNumber, _locomotionType, _station, _type) {
  return new Promise(function(_resolve, _reject) {
    if (!_station) {
      _reject();
    } else {
      if (_station.synced) {
        _resolve();
      } else {
        Ext.Ajax.request({url:_url, params:{syncSecret:_syncSecret, rideUid:_rideUid, trainNumber:_trainNumber, locomotionType:Ext.encode(_locomotionType), station:Ext.encode({identifier:_station.identifier, name:_station.name, lat:_station.latitude, lon:_station.longitude, time:_station.time}), type:_type}, success:function(_response) {
          var response = Ext.decode(_response.responseText, true);
          if (response && response.success) {
            _station.synced = true;
            _resolve();
          } else {
            _reject();
          }
        }, failure:function() {
          _reject();
        }});
      }
    }
  });
}});
Ext.define('dilocsync.store.DasCLog', {extend:Ext.data.Store, alias:'store.dascLog', storeId:'DasCLog', fields:[{name:'time', type:'string'}, {name:'message', type:'string'}, {name:'trainNumber', type:'string'}], sync:function() {
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var records = this.getRange();
  var advices = [];
  records.forEach(function(_record) {
    advices.push({time:_record.get('time'), message:_record.get('message'), trainNumber:_record.get('trainNumber')});
  });
  if (advices.length > 0) {
    Ext.Ajax.request({url:master.getBackendUrl() + '/trainbinding/submitAdvices', params:{syncSecret:storage.get('core:personalization:syncSecret'), deviceIdCode:master.deviceIdCode(), advices:Ext.encode(advices)}, success:function(_response) {
      var response = Ext.decode(_response.responseText, true);
      if (response && response.success) {
        this.remove(records);
      }
    }, failure:function(_response) {
      cnconsult.Logger.log({prefix:'DasCLog-\x3esync', message:'Error uploading the advices', level:'error', catchedError:_response});
    }, scope:this});
  }
}});
Ext.define('dilocsync.store.DigitalOrders', {extend:Ext.data.Store, alias:'store.digitalorders', storeId:'DigitalOrders', model:'dilocsync.model.DigitalOrder', version:0, constructor:function() {
  this.callParent(arguments);
  this.on('update', this.onUpdated, this);
}, load:function(_silent) {
  var $jscomp$this = this;
  _silent = _silent === undefined ? false : _silent;
  this.fireEvent('beforeload');
  return dilocsync.util.DigitalOrderHelper.list.current(this.version).then(function(_orderList) {
    if (_orderList) {
      return dilocsync.util.DigitalOrderHelper.list.confirm(_orderList.version).then(function(_orderList) {
        $jscomp$this.setOrderList(_orderList);
        return true;
      });
    } else {
      $jscomp$this.fireEvent('refresh', $jscomp$this);
      return true;
    }
  })['catch'](function(_error) {
    cnconsult.Logger.log({prefix:'DigitalOrders-\x3eload', message:'Failed to fetch current order list', level:'error', dump:_error});
    $jscomp$this.fireEvent('loaderror');
    if (!_silent) {
      dilocsync.util.MessageHelper.showDebug('Failed to fetch current order list: ' + _error.message);
    }
    return false;
  });
}, setOrderList:function(_orderList) {
  this.version = parseInt(_orderList.version);
  for (var $jscomp$iter$26 = $jscomp.makeIterator(_orderList.digitalOrders), $jscomp$key$digitalOrder = $jscomp$iter$26.next(); !$jscomp$key$digitalOrder.done; $jscomp$key$digitalOrder = $jscomp$iter$26.next()) {
    var digitalOrder = $jscomp$key$digitalOrder.value;
    {
      digitalOrder.styling = _orderList.usedStyling;
      var record = this.getById(digitalOrder.id);
      if (record) {
        if (!record.get('isAcknowledgementReset') && digitalOrder.isAcknowledgementReset) {
          digitalOrder.read = false;
        }
        record.mergeData(digitalOrder);
      } else {
        digitalOrder.read = digitalOrder.isAcknowledged;
        this.add(digitalOrder);
      }
    }
  }
  this.fireEvent('load', this);
}, reset:function() {
  this.removeAll();
  this.version = 0;
  this.fireEvent('load', this);
}, onUpdated:function(_store, _record, _operation, _modifiedFieldNames) {
  var $jscomp$this = this;
  if (Ext.Array.from(_modifiedFieldNames).includes('targetState')) {
    var task;
    switch(_record.get('targetState')) {
      case 'Acknowledged':
        task = dilocsync.util.DigitalOrderHelper.order.acknowledge(_record);
        break;
      case 'Completed':
        task = dilocsync.util.DigitalOrderHelper.order.markCompleted(_record);
        break;
      case 'Uncompleted':
        task = dilocsync.util.DigitalOrderHelper.order.markUncompleted(_record);
        break;
      default:
        return;
    }
    task.then(function(_orderList) {
      $jscomp$this.setOrderList(_orderList);
    })['catch'](function(_error) {
      cnconsult.Logger.log({prefix:'DigitalOrders-\x3eonUpdate', message:'Failed to update digital order', level:'error', dump:_error});
      dilocsync.util.MessageHelper.showDebug('Failed to update digital order: ' + _error.message);
    })['finally'](function() {
      _record.set('targetState', null, {dirty:false});
    });
  }
}});
Ext.define('dilocsync.store.GpsQueue', {extend:dilocsync.store.DiLocStorage, alias:'store.gpsQueue', storeId:'GpsQueue', fields:[{name:'lat', type:'float'}, {name:'lon', type:'float'}, {name:'accuracy', type:'float'}, {name:'time', type:'float'}], dirty:false, listeners:{datachanged:function() {
  this.dirty = true;
}}, sync:function() {
  if (this.dirty) {
    this.dirty = false;
    this.callParent(arguments);
  }
}, submitCoordinates:function() {
  var $jscomp$this = this;
  return new Promise(function(_resolve, _reject) {
    var master = dilocsync.core.Master;
    var storage = master.getStorage();
    var records = $jscomp$this.getRange();
    var coordinates = [];
    var rideUid = $jscomp$this.getSaveKey().split(':').pop();
    records.forEach(function(_record) {
      coordinates.push({lat:_record.get('lat'), lon:_record.get('lon'), accuracy:_record.get('accuracy'), time:_record.get('time')});
    });
    if (coordinates.length > 0) {
      Ext.Ajax.request({url:master.getBackendUrl() + '/syncrideknowledge/coordinates', params:{syncSecret:storage.get('core:personalization:syncSecret'), rideUid:rideUid, coordinates:Ext.encode(coordinates)}, success:function(_response) {
        var response = Ext.decode(_response.responseText, true);
        if (response && response.success) {
          this.remove(records);
          _resolve();
        } else {
          _reject();
        }
      }, failure:function() {
        _reject();
      }, scope:$jscomp$this});
    } else {
      _resolve();
    }
  });
}});
Ext.define('dilocsync.store.Imports', {extend:dilocsync.store.DiLocStorage, storeId:'Imports', model:'dilocsync.model.ImportedDocument', sorters:'name', groupDir:'ASC', saveKey:'page:imports:importedRecords'});
Ext.define('dilocsync.store.Rides', {extend:dilocsync.store.DiLocStorage, storeId:'Rides', model:'dilocsync.model.Ride', saveKey:'page:driveInfo:trackedRides', alias:'store.rides', autoLoad:true});
Ext.define('dilocsync.util.AlmanacSettings', {singleton:true, _listFileNamesInAlmanacDirectoryRecursively:function(_almanacDirectory) {
  var $jscomp$this = this;
  var fileNames = new Set;
  if (_almanacDirectory.hasOwnProperty('files')) {
    Object.values(_almanacDirectory.files).forEach(function(_fileInfo) {
      fileNames.add(_fileInfo.checksum + '.' + _fileInfo.fileType);
    });
  }
  if (_almanacDirectory.hasOwnProperty('directories')) {
    Object.keys(_almanacDirectory.directories).forEach(function(_directoryName) {
      var fileNamesInAlmanacDirectory = $jscomp$this._listFileNamesInAlmanacDirectoryRecursively(_almanacDirectory.directories[_directoryName]);
      for (var $jscomp$iter$27 = $jscomp.makeIterator(fileNamesInAlmanacDirectory), $jscomp$key$fileName = $jscomp$iter$27.next(); !$jscomp$key$fileName.done; $jscomp$key$fileName = $jscomp$iter$27.next()) {
        var fileName = $jscomp$key$fileName.value;
        {
          fileNames.add(fileName);
        }
      }
    });
  }
  return fileNames;
}, listAllFileNamesInAlmanacs:function(_almanacs, _settingsStorage) {
  var $jscomp$this = this;
  var fileNames = new Set;
  _almanacs.forEach(function(_almanac) {
    var almanacSettings = _settingsStorage.get('core:almanac:' + _almanac.path);
    if (almanacSettings) {
      var fileNamesInAlmanac = $jscomp$this._listFileNamesInAlmanacDirectoryRecursively(almanacSettings);
      for (var $jscomp$iter$28 = $jscomp.makeIterator(fileNamesInAlmanac), $jscomp$key$fileName = $jscomp$iter$28.next(); !$jscomp$key$fileName.done; $jscomp$key$fileName = $jscomp$iter$28.next()) {
        var fileName = $jscomp$key$fileName.value;
        {
          fileNames.add(fileName);
        }
      }
    }
  });
  return fileNames;
}});
Ext.define('dilocsync.util.ApplicationHelpers', {singleton:true, mixins:[cnconsult.Translatable], reloadApplicationWithAcknowledge:function() {
  var title = this.tr('Reload needed');
  var message = this.tr('The app needs to be reloaded!');
  dilocsync.util.MessageHelper.showAcknowledge(title, message, function() {
    return dilocsync.core.Master.reloadApplication();
  });
}});
Ext.define('dilocsync.util.Color', {singleton:true, getContrast:function(_hexColor) {
  if (_hexColor.slice(0, 1) === '#') {
    _hexColor = _hexColor.slice(1);
  }
  if (_hexColor.length === 3) {
    _hexColor = _hexColor.split('').map(function(hex) {
      return hex + hex;
    }).join('');
  }
  var r = parseInt(_hexColor.substring(0, 2), 16);
  var g = parseInt(_hexColor.substring(2, 4), 16);
  var b = parseInt(_hexColor.substring(4, 6), 16);
  var yiq = (r * 299 + g * 587 + b * 114) / 1000;
  return yiq >= 128 ? '#000000' : '#ffffff';
}});
Ext.define('dilocsync.util.DigitalOrderHelper', {singleton:true, mixins:[cnconsult.Translatable], config:{trainNumber:null, operationDate:null, selectedUserRole:null}, baseUrl:null, headers:{Authorization:null}, start:function(_override) {
  var $jscomp$this = this;
  _override = _override === undefined ? false : _override;
  if (!_override) {
    var viewModel = Ext.first('app-main').getViewModel();
    this.setTrainNumber(viewModel.get('trainNumber'));
    this.setOperationDate(Ext.Date.format(viewModel.get('digitalOrderDate'), 'Y-m-d'));
    this.setSelectedUserRole(viewModel.get('digitalOrderUserRole'));
    this.baseUrl = dilocsync.core.Master.getStorage().get('page:driveInfo:digitalOrderUrl') + '/v1/';
    this.headers.Authorization = viewModel.get('digitalOrderToken');
  }
  return this.takeLead(_override).then(function() {
    Ext.fireEvent('startDigitalOrder');
    return dilocsync.util.Helper.initStore('DigitalOrders').load();
  })['catch'](function(_error) {
    cnconsult.Logger.log({prefix:'DigitalOrderHelper-\x3estart', message:'Failed to start digital order', level:'error', dump:_error});
    if (!_override && _error.type === '500:RoleAlreadyInUse') {
      return new Promise(function(resolve, reject) {
        dilocsync.util.MessageHelper.showMessage({title:$jscomp$this.tr('The role is already taken by another client'), message:'\x3cb\x3e' + $jscomp$this.tr('By clicking on "Force logout", the current leading train driver will be logged out.') + '\x3c/b\x3e\x3cbr\x3e' + $jscomp$this.tr('By clicking on "Cancel", the electronic command will not be started, and you can review your entries.'), buttons:[{text:$jscomp$this.tr('Cancel'), handler:function(_button) {
          _button.up('messagebox').destroy();
          resolve(false);
        }}, {text:$jscomp$this.tr('Force logout'), style:'color:red', handler:function(_button) {
          _button.up('messagebox').destroy();
          resolve(dilocsync.util.DigitalOrderHelper.start(true));
        }, scope:$jscomp$this}]});
      });
    } else {
      dilocsync.util.MessageHelper.showDebug('Failed to start digital order: ' + _error.message);
    }
    return false;
  });
}, stop:function() {
  this.resignLead().then(function() {
    Ext.fireEvent('stopDigitalOrder');
    dilocsync.util.Helper.initStore('DigitalOrders').reset();
  })['catch'](function(_error) {
    cnconsult.Logger.log({prefix:'DigitalOrderHelper-\x3estop', message:'Failed to stop digital order', level:'error', dump:_error});
    dilocsync.util.MessageHelper.showDebug('Failed to stop digital order: ' + _error.message);
  });
}, takeLead:function(_force) {
  _force = _force === undefined ? false : _force;
  if (this.getSelectedUserRole() === 'LeadingTrainDriver') {
    return this._doPostRequest(this._buildUrl('trains', this.getTrainNumber(), 'operation-dates', this.getOperationDate(), 'take-lead'), {force:_force});
  } else {
    return Promise.resolve();
  }
}, resignLead:function() {
  if (this.getSelectedUserRole() === 'LeadingTrainDriver') {
    return this._doPostRequest(this._buildUrl('trains', this.getTrainNumber(), 'operation-dates', this.getOperationDate(), 'resign-lead'));
  } else {
    return Promise.resolve();
  }
}, list:{current:function(_version) {
  dilocsync.util.DigitalOrderHelper.headers['If-None-Match'] = _version;
  return dilocsync.util.DigitalOrderHelper._doGetRequest(dilocsync.util.DigitalOrderHelper._getListPath('current'));
}, confirm:function(_version) {
  return dilocsync.util.DigitalOrderHelper._doPostRequest(dilocsync.util.DigitalOrderHelper._getListPath(_version) + '/confirm-reception');
}}, order:{acknowledge:function(_record) {
  return dilocsync.util.DigitalOrderHelper._doPostRequest(dilocsync.util.DigitalOrderHelper._getOrderPath(_record) + '/acknowledge');
}, markCompleted:function(_record) {
  return dilocsync.util.DigitalOrderHelper._doPostRequest(dilocsync.util.DigitalOrderHelper._getOrderPath(_record) + '/mark-completed');
}, markUncompleted:function(_record) {
  return dilocsync.util.DigitalOrderHelper._doPostRequest(dilocsync.util.DigitalOrderHelper._getOrderPath(_record) + '/mark-uncompleted');
}}, _buildUrl:function() {
  return Ext.Array.from(arguments).join('/');
}, _getBasePath:function() {
  return this._buildUrl('trains', this.getTrainNumber(), 'operation-dates', this.getOperationDate());
}, _getListPath:function(_version) {
  return this._buildUrl(this._getBasePath(), 'digital-order-lists', this.getSelectedUserRole(), _version);
}, _getOrderPath:function(_record) {
  return this._buildUrl(this._getListPath(_record.store.version), 'digital-orders', _record.id);
}, _doGetRequest:function(_url, _params) {
  _params = _params === undefined ? {} : _params;
  return this._doRequest(_url, _params, 'GET');
}, _doPostRequest:function(_url, _params) {
  _params = _params === undefined ? {} : _params;
  return this._doRequest(_url, _params, 'POST');
}, _doRequest:function(_url, _params, _method) {
  var $jscomp$this = this;
  return new Promise(function(resolve, reject) {
    Ext.Ajax.request({url:$jscomp$this.baseUrl + _url, headers:$jscomp$this.headers, jsonData:_params, method:_method, success:function(response) {
      resolve(Ext.decode(response.responseText, true));
    }, failure:function(response) {
      reject(this._getError(response));
    }, scope:$jscomp$this});
  });
}, _getError:function(_response) {
  var messages = {'400:MissingOrInvalidParameter':this.tr('The request is invalid, there might be a parameter missing or in an unexpected format.'), '401:MissingOrInvalidAuthentication':this.tr('The authentication is missing or invalid.'), '404:NotFound':this.tr('The requested resource could not be found.'), '405:MethodNotAllowed':this.tr('The method is not allowed on the requested resource.'), '500:NotFound':this.tr('Referenced resource could not be found (e.g. digitalOrderList or digitalOrder).'), 
  '500:Timeout':this.tr('The connection to an external resource timed out.'), '500:Unauthorized':this.tr('The provided authentication token is not valid.'), '500:UnknownError':this.tr('An unknown internal server error occurred.'), '500:RoleAlreadyInUse':this.tr('The role is already taken by another client.'), '500:VersionMismatch':this.tr('The version used does not match the server version of the digital order list.'), '500:NotAllowed':this.tr('The action is not allowed. You might not be the active leading train driver.')};
  var error = Ext.decode(_response.responseText, true);
  var type = Ext.isObject(error) ? _response.status + ':' + error.code : null;
  var message = messages[type] || this.tr('Unknown error occurred');
  if (type === '500:NotAllowed') {
    Ext.fireEvent('loggedOut');
  }
  return {type:type, message:message};
}});
Ext.define('dilocsync.util.ExternalFile', {singleton:true, config:{fileDir:'fs-data/', externalFileDir:'fs-data/temp-external-open/'}, openFileExternally:function(_filePath, _showOpenWith) {
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.util.ExternalFile', src:'Dokumente', action:'DokumentExternGeöffnet', trackedAt:new Date});
  var options = {success:function(_success) {
    console.log('Successfully opened');
  }, error:function(_errorMessage) {
    console.log('Error opening file: ', _errorMessage);
  }};
  if (_showOpenWith) {
    var openWithOption = Ext.apply(options, {position:[900, 100]});
    cordova.plugins.fileOpener2.showOpenWithDialog(_filePath, '', openWithOption);
  } else {
    cordova.plugins.fileOpener2.open(_filePath, '', options);
  }
}, copyFileToTempDirectory:function(_fileInfo) {
  return new Promise(function(_resolve, _reject) {
    var master = dilocsync.core.Master;
    var fileToCopy = _fileInfo.checksum + '.' + (_fileInfo.alternativeFileType ? _fileInfo.alternativeFileType : _fileInfo.fileType);
    var rootFsEntryName = dilocsync.util.File.validateRootDirectoryName(_fileInfo.rootFsEntryName);
    rootFsEntryName += '/';
    var externalFileDirectory = 'fs-data/temp-external-open';
    master.getSyncRoot().getFile(rootFsEntryName + fileToCopy, {create:false}, function(_fileEntry) {
      master.getSyncRoot().getDirectory(externalFileDirectory, {create:true}, function(_directory) {
        _fileEntry.copyTo(_directory, _fileInfo.name, function(_tempFile) {
          var fileUrl = decodeURI(_tempFile.toURL());
          _resolve(fileUrl);
        }, _reject);
      }, _reject);
    }, _reject);
  });
}, openFileExternallyWithRealFilename:function(_filePath, _fileInfo) {
  var $jscomp$this = this;
  dilocsync.util.UserActivityTracker.addActivity({'class':'dilocsync.util.ExternalFile', src:'Dokumente', action:'DokumentExternMitEchtemDateinamenGeöffnet', trackedAt:new Date});
  if (!dilocsync.util.Platform.isPhonegap()) {
    console.log('fileOpener2 does not exist as we are not in the cordova enviroment!');
    return;
  }
  if (!_fileInfo.name.endsWith(_fileInfo.fileType)) {
    _fileInfo.name += '.' + _fileInfo.fileType;
  }
  var externalFileDirectory = 'fs-data/temp-external-open/';
  var copyPath = externalFileDirectory + _fileInfo.name;
  var showOpenWith = this.fileTypeSupportsOpenWith(_fileInfo.fileType);
  dilocsync.core.Master.devicePathExists(copyPath, function(_deviceFileCopyPath) {
    if (_deviceFileCopyPath) {
      $jscomp$this.openFileExternally(_deviceFileCopyPath, showOpenWith);
    } else {
      dilocsync.util.ExternalFile.copyFileToTempDirectory(_fileInfo).then(function(_fileUrl) {
        return $jscomp$this.openFileExternally(_fileUrl, showOpenWith);
      });
    }
  }, this);
}, fileTypeSupportsOpenWith:function(_fileType) {
  var supportedOpenWithFiletypes = ['xlsx', 'xls', 'xlsm', 'docx', 'doc'];
  return dilocsync.util.Platform.isIOS() && supportedOpenWithFiletypes.includes(_fileType);
}});
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
Ext.define('dilocsync.util.IndexedDBProxy', {extend:Ext.data.proxy.Client, alternateClassName:'Ext.data.DbEngineProxy', alias:'proxy.indexeddb', config:{databaseName:null, table:null, dbprocess:false}, constructor:function() {
  this.callParent(arguments);
  this.cache = {};
  if (this.getStorageObject() === undefined) {
    Ext.raise('INDEXED DB IS NOT SUPPORTED BY YOUR BROWSER');
  }
  this.initialize();
}, getStorageObject:function() {
  return window.indexedDB;
}, initialize:function() {
  console.log('SQL: DB proxy is being initialized....');
  var me = this;
  var request;
  request = window.indexedDB.open(me.config.databaseName);
  me.dbprocess = true;
  request.onerror = function(event) {
    me.dbprocess = false;
    throw 'SQL: db initializing was failed, DB could not be opened (no problem)';
  };
  request.onsuccess = function(event) {
    db = request.result;
    if (!Array.from(db.objectStoreNames).includes(me.config.table)) {
      db.close();
      me.dbprocess = false;
      var secondRequest = indexedDB.open(db.name, db.version + 1);
      secondRequest.onupgradeneeded = function(e) {
        var db = e.target.result;
        console.log('SQL: db ' + db.name + ' upgraded successfully to version:' + db.version);
        console.log('SQL: ' + me.config.table + ' table created');
        var objectStore = db.createObjectStore(me.config.table, {autoIncrement:true});
        db.close();
        me.dbprocess = false;
      };
      secondRequest.onsuccess = function(e) {
        console.log('SQL: NEW db ' + e.target.result.name + ' opened/created successfully in version:' + e.target.result.version);
        e.target.result.close();
        me.dbprocess = false;
      };
    } else {
      console.log('SQL: db ' + db.name + ' opened/created successfully in version:' + db.version);
      db.close();
      me.dbprocess = false;
    }
  };
  request.onupgradeneeded = function(event) {
    var db = event.target.result;
    db.createObjectStore(me.config.table, {autoIncrement:true});
    console.log('SQL: db ' + db.name + ' upgraded successfully to version:' + db.version);
    console.log('SQL: ' + me.config.table + ' table created');
    db.close();
    me.dbprocess = false;
  };
}, create:function(operation) {
  var me = this, records = operation.getRecords(), totalRecords = records.length, data = [], createdRecords = [], result, store, transaction, db, tx;
  var oRequest = indexedDB.open(me.config.databaseName);
  me.dbprocess = true;
  oRequest.onerror = function(event) {
    me.dbprocess = false;
    throw 'SQL: INSERT was failed, DB could not be opened';
  };
  oRequest.onsuccess = function(e) {
    db = e.target.result;
    operation.setStarted();
    tx = db.transaction([me.config.table], 'readwrite');
    Ext.each(records, function(record) {
      tx.objectStore(me.config.table).add(record.data);
    });
    tx.oncomplete = function(event) {
      console.log('SQL: data has been added to ' + me.config.table);
    };
    tx.onerror = function(event) {
      db.close();
      throw 'SQL: INSERT was failed, operation error';
    };
    operation.setCompleted();
    operation.setSuccessful(true);
    db.close();
    me.dbprocess = false;
  };
  oRequest.onupgradeneeded = function(event) {
    db = event.target.result;
    db.close();
    me.dbprocess = false;
  };
}, read:function(operation) {
  var me = this;
  var Model = me.getModel();
  var filters = operation.getFilters();
  var limit = -1;
  var page = operation.getPage();
  var passed = limit * (page - 1);
  var position = 0;
  operation.setStarted();
  var allRecords = [];
  var db;
  var request = window.indexedDB.open(me.config.databaseName);
  me.dbprocess = true;
  request.onerror = function(event) {
    me.dbprocess = false;
    throw 'SQL: SELECT was failed, DB could not be opened (tidak apa2 karena baru pertama kok)';
  };
  request.onsuccess = function(event) {
    position = position + 1;
    db = request.result;
    if (!Array.from(db.objectStoreNames).includes(me.config.table)) {
      db.close();
      me.dbprocess = false;
      throw 'SQL: objectstore does not exist. (no problem)';
    }
    var objectStore = db.transaction(me.config.table).objectStore(me.config.table);
    objectStore.openCursor().onsuccess = function(event) {
      var cursor = event.target.result;
      if (cursor) {
        var found = false;
        cursor.value.id = cursor.key;
        var row = cursor.value;
        if (filters != undefined) {
          if (filters.all != undefined) {
            var keys = Object.keys(cursor.value);
            for (var y = 0; y < keys.length; y++) {
              if (!['id'].includes(keys[y].toLowerCase()) && row[keys[y]].toString().toLowerCase().includes(filters.all.toLowerCase())) {
                found = true;
                break;
              }
            }
          } else {
            var filterKeys = Object.keys(filters);
            var totalMatching = filterKeys.length;
            for (var y$101 = 0; y$101 < filterKeys.length; y$101++) {
              if (filters[filterKeys[y$101].toLowerCase()].toString().toLowerCase() == row[filterKeys[y$101].toLowerCase()].toString().toLowerCase()) {
                totalMatching--;
              }
            }
            if (totalMatching == 0) {
              found = true;
            }
          }
        } else {
          found = true;
        }
        if (found) {
          if (passed != 0) {
            passed = passed - 1;
          } else {
            allRecords.push(new Model(cursor.value));
            limit = limit - 1;
          }
        }
        if (limit == 0) {
          cursor.advance(1000);
        } else {
          cursor['continue']();
        }
      } else {
        operation.setResultSet(new Ext.data.ResultSet({records:allRecords, total:allRecords.length, loaded:true}));
        operation.setSuccessful(true);
        db.close();
        me.dbprocess = false;
      }
    };
    db.close();
    me.dbprocess = false;
  };
}, clear:function() {
  var me = this;
  var db;
  var request = window.indexedDB.open(me.config.databaseName);
  me.dbprocess = true;
  request.onerror = function(event) {
    throw 'SQL: CLEAR was failed, DB could not be opened';
  };
  request.onsuccess = function(e) {
    db = e.target.result;
    var transaction = db.transaction([me.config.table], 'readwrite');
    var objectStore = transaction.objectStore(me.config.table);
    var objectStoreRequest = objectStore.clear();
    objectStoreRequest.onsuccess = function(event) {
      console.log('SQL: table ' + me.config.table + ' was cleared!');
    };
    db.close();
    me.dbprocess = false;
  };
}, erase:function(operation) {
  var me = this;
  var db;
  var request = window.indexedDB.open(me.config.databaseName);
  me.dbprocess = true;
  request.onerror = function(event) {
    me.dbprocess = false;
    throw 'SQL: DELETE was failed, DB could not be opened';
  };
  request.onsuccess = function(e) {
    db = e.target.result;
    var transaction = db.transaction([me.config.table], 'readwrite');
    var objectStore = transaction.objectStore(me.config.table);
    if (operation.getId() != undefined) {
      var search = objectStore.get(operation.getId());
      search.onsuccess = function(e) {
        var deletion = objectStore['delete'](operation.getId());
        deletion.onsuccess = function(e) {
          console.log('SQL: Data Deleted');
        };
        deletion.onerror = function(e) {
          throw 'SQL: DELETE was failed, operation error';
        };
      };
    } else {
      var where = Object.keys(operation.config)[0];
      objectStore.openCursor().onsuccess = function(event) {
        var cursor = event.target.result;
        if (cursor) {
          if (cursor.value[where] == operation.config[where]) {
            var deletion = objectStore['delete'](cursor.key);
            deletion.onsuccess = function(e) {
              console.log('SQL: Data Deleted');
            };
            deletion.onerror = function(e) {
              throw 'SQL: DELETE was failed, operation error';
            };
          }
          cursor['continue']();
        } else {
          db.close();
          me.dbprocess = false;
        }
      };
    }
    if (me.dbprocess) {
      db.close();
    }
    me.dbprocess = false;
  };
  operation.setSuccessful(true);
}, update:function(operation) {
  var me = this;
  var db;
  var request = window.indexedDB.open(me.config.databaseName);
  request.onerror = function(event) {
    throw 'SQL: UPDATE was failed, DB could not be opened';
  };
  request.onsuccess = function(e) {
    db = e.target.result;
    var transaction = db.transaction([me.config.table], 'readwrite');
    var objectStore = transaction.objectStore(me.config.table);
    if (operation.getId() != undefined) {
      var search = objectStore.get(operation.getId());
      search.onsuccess = function(e) {
        var newData = {};
        Ext.iterate(Object.keys(operation.config), function(key) {
          if (!['object', 'function', 'undefined'].includes(typeof operation.config[key])) {
            newData[key] = operation.config[key];
          }
        });
        var updating = objectStore.put(newData, operation.getId());
        updating.onsuccess = function(e) {
          console.log('SQL: Data Updated Successfully');
        };
        updating.onerror = function(e) {
          throw 'SQL: UPDATE was failed, operation error';
        };
      };
    } else {
      db.close();
      me.dbprocess = false;
      throw 'SQL: UPDATE was failed, key: [id] was needed as where!';
    }
    db.close();
    me.dbprocess = false;
  };
  operation.setSuccessful(true);
  me.read(operation);
}, destroy:function(operation) {
  var me = this;
  me.erase(operation);
}, remove:function() {
  console.log('not implemented yet');
}, getIds:function() {
  console.log('not implemented yet');
}, load:function() {
  console.log('not implemented yet');
}});
Ext.define('dilocsync.util.RideDataHandler', {ridesStore:null, gpsQueueStores:{}, isSyncing:false, needsSync:false, nextSubmitTimeout:null, constructor:function() {
  this.ridesStore = dilocsync.util.Helper.initStore('Rides');
}, setStartStationForCurrentRide:function(_startStation) {
  var storage = dilocsync.core.Master.getStorage();
  this.ridesStore.add({rideUid:storage.get('page:driveInfo:rideUid'), trainNumber:storage.get('page:driveInfo:trainNumber'), locomotionType:storage.get('page:driveInfo:locomotionType'), startStation:_startStation});
  this.ridesStore.sync();
  this.submitData();
}, setEndStationForCurrentRide:function(_endStation) {
  var storage = dilocsync.core.Master.getStorage();
  var rideUid = storage.get('page:driveInfo:rideUid');
  var record = this.ridesStore.findRecord('rideUid', rideUid, 0, false, false, true);
  record.set('endStation', _endStation);
  record.commit();
  this.ridesStore.sync();
  this.submitData();
}, addCoordinateForCurrentRide:function(_coordinate) {
  var storage = dilocsync.core.Master.getStorage();
  var rideUid = storage.get('page:driveInfo:rideUid');
  if (rideUid) {
    this.getGpsQueueForRide(rideUid).add(_coordinate);
  }
}, submitData:function() {
  clearTimeout(this.nextSubmitTimeout);
  if (this.isSyncing) {
    this.needsSync = true;
    return;
  }
  this.needsSync = false;
  this.isSyncing = true;
  var walker = Ext.create('dilocsync.core.AsyncWalk');
  walker.walkArray(this.ridesStore.getRange(), function(_ride, _callback) {
    var $jscomp$this = this;
    var rideUid = _ride.get('rideUid');
    var gpsQueue = this.getGpsQueueForRide(rideUid);
    gpsQueue.submitCoordinates().then(function() {
      _ride.submitStations().then(function() {
        cnconsult.Logger.log({prefix:'RideDataHandler-\x3esubmitData', message:'Ride completely submitted. Removing data from client.'});
        $jscomp$this.removeDataForRide(_ride);
      })['catch'](function() {
        cnconsult.Logger.log({prefix:'RideDataHandler-\x3esubmitData', message:'At least one station has not yet been submitted for ride: ' + rideUid, level:'info'});
      })['finally'](function() {
        $jscomp$this.ridesStore.sync();
        _callback();
      });
    })['catch'](function() {
      cnconsult.Logger.log({prefix:'RideDataHandler-\x3esubmitData', message:'Error uploading gps coordinates for ride: ' + rideUid, level:'error'});
      _callback();
    })['finally'](function() {
      gpsQueue.sync();
    });
  }, this, function() {
    var $jscomp$this = this;
    this.isSyncing = false;
    this.nextSubmitTimeout = setTimeout(function() {
      $jscomp$this.submitData();
    }, this.needsSync ? 0 : 1000 * 60);
  }, this);
}, getGpsQueueForRide:function(_rideUid) {
  if (!this.gpsQueueStores.hasOwnProperty(_rideUid)) {
    this.gpsQueueStores[_rideUid] = Ext.create('dilocsync.store.GpsQueue', {saveKey:'page:driveInfo:gpsCoordinates:' + _rideUid});
    this.gpsQueueStores[_rideUid].load();
  }
  return this.gpsQueueStores[_rideUid];
}, removeDataForRide:function(_ride) {
  var rideUid = _ride.get('rideUid');
  this.ridesStore.remove(_ride);
  var gpsQueue = this.getGpsQueueForRide(rideUid);
  dilocsync.core.Master.getStorage().remove(gpsQueue.getSaveKey());
  delete this.gpsQueueStores[rideUid];
  gpsQueue.destroy();
}});
Ext.define('dilocsync.util.Screen', {singleton:true, getScreenWidth:function() {
  return Ext.getViewportWidth();
}});
Ext.define('dilocsync.util.UndeletedFileChecker', {singleton:true, checkForUndeletedFiles:function() {
  var $jscomp$this = this;
  var storageKey = 'core:files:undeletedFileCheckerExecuted';
  var startTime = performance.now();
  var master = dilocsync.core.Master;
  var storage = master.getStorage();
  var almanacFiles = this.getAlmanacFiles();
  this.getFilesFromFileSystem().then(function(storedFiles) {
    var diff = storedFiles.filter(function(file) {
      return !almanacFiles.includes(file.name);
    });
    if (diff.length === 0) {
      cnconsult.Logger.log({prefix:'UndeletedFileChecker-\x3echeckForUndeletedFiles', message:'No deletable files found. Exiting.'});
      storage.set(storageKey, true);
      return;
    }
    var deletedFileEntryPromises = [];
    var documentRepository = master.getDocumentRepository();
    var currentUserId = storage.get('core:personalization:userid');
    diff.forEach(function(fileEntry) {
      deletedFileEntryPromises.push($jscomp$this.deleteFileEntry(fileEntry, documentRepository, currentUserId));
    });
    Promise.all(deletedFileEntryPromises).then(function(results) {
      var freedUpMemory = results.reduce(function(total, current) {
        return total + current;
      }, 0);
      storage.set(storageKey, true);
      var endTime = performance.now();
      Ext.Ajax.request({url:master.getBackendUrl() + '/clientsync/trackDeletedZombieFiles', params:{syncSecret:storage.get('core:personalization:syncSecret'), deviceIdCode:master.deviceIdCode(), freedUpMemory:freedUpMemory, deletedFileCount:diff.length, executionTime:endTime - startTime, multiUserEnabled:storage.get('core:personalization:multiUserSupportEnabled')}, success:function(_response) {
        cnconsult.Logger.log({prefix:'UndeletedFileChecker-\x3echeckForUndeletedFiles', message:'Response.', dump:Ext.decode(_response.responseText)});
      }, failure:function(_response) {
        cnconsult.Logger.log({prefix:'UndeletedFileChecker-\x3echeckForUndeletedFiles', message:'Error occurred when uploading data.', level:'error', dump:Ext.decode(_response.responseText)});
      }, scope:$jscomp$this});
    })['catch'](function(error) {
      cnconsult.Logger.log({prefix:'UndeletedFileChecker-\x3echeckForUndeletedFiles', message:'Error occurred when deleting data.', level:'error', dump:error});
    });
  });
}, deleteFileEntry:function(_fileEntry, _documentRepository, _currentUserId) {
  return new Promise(function(resolve, reject) {
    if (!_documentRepository) {
      reject('No document repository found');
    }
    _fileEntry.getMetadata(function(metadata) {
      var freedUpMemory = metadata.size;
      var fileParts = _fileEntry.name.split('.');
      if (fileParts.length !== 2) {
        reject('Unknown filename format: ' + _fileEntry.name);
      }
      var checksum = fileParts[0];
      var fileExtension = fileParts[1];
      _documentRepository.removeOwnerForDocument(checksum, fileExtension, _currentUserId).then(function() {
        return resolve(freedUpMemory);
      })['catch'](function(e) {
        return reject(e);
      });
    });
  });
}, getAlmanacFiles:function() {
  var storage = dilocsync.core.Master.getStorage();
  var almanacs = storage.get('core:almanacs');
  var almanacPaths = Ext.isArray(almanacs) ? Ext.Array.pluck(almanacs, 'path') : [];
  var almanacFiles = [];
  Ext.Array.each(almanacPaths, function(almanacPath) {
    var almanac = new dilocsync.core.Almanac(storage.get('core:almanac:' + almanacPath, 'nodefault-d28;['));
    var almanacRootDirectory = almanac.getRootDirectory();
    var files = almanacRootDirectory.getAllFiles();
    Ext.Object.each(files, function(fileName, file) {
      almanacFiles.push(file.checksum + '.' + file.fileType);
    }, this);
  }, this);
  return Ext.Array.unique(almanacFiles);
}, getFilesFromFileSystem:function() {
  return new Promise(function(resolve, reject) {
    dilocsync.core.Master.getSyncRoot().getDirectory('fs-data', {}, function(_dir) {
      dilocsync.util.File.readEntriesFromDirectory(_dir).then(function(_entries) {
        return resolve(_entries);
      })['catch'](reject);
    });
  });
}});
Ext.define('dilocsync.util.UserActivityTracker', {singleton:true, count:0, anonymousDeviceId:null, addActivity:function(_trackedActivity) {
  var trackedActivitiesStore = dilocsync.util.Helper.initStore('TrackedActivities');
  if (!this.anonymousDeviceId) {
    this.anonymousDeviceId = this.generateUuid();
  }
  _trackedActivity.anonymousDeviceId = this.anonymousDeviceId;
  _trackedActivity.platformName = dilocsync.util.Platform.getPlatform();
  _trackedActivity.platformVersion = dilocsync.util.Platform.getVersion();
  _trackedActivity.appVersion = dilocsync.core.Master.version;
  _trackedActivity.appVersionCode = dilocsync.core.Master.versionCode;
  _trackedActivity.application = 'sync-client';
  trackedActivitiesStore.add(_trackedActivity);
  cnconsult.Logger.log({prefix:'UserActivityTracker-\x3eaddActivity', message:'User activity recognized'});
}, generateUuid:function() {
  return ([10000000] + -1000 + -4000 + -8000 + -1.0E11).replace(/[018]/g, function(c) {
    return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16);
  });
}});
Ext.application({extend:dilocsync.Application, name:'dilocsync', controllers:['Init', 'Router'], launch:function() {
}, onProfilesReady:function() {
  var $jscomp$this = this;
  if (Ext.browser.is.PhoneGap) {
    document.addEventListener('deviceready', function() {
      $jscomp$this.superclass.onProfilesReady.call($jscomp$this);
    });
  } else {
    this.superclass.onProfilesReady.call(this);
  }
}});
"use strict";

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

(function (f) {
    if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object" && typeof module !== "undefined") {
        module.exports = f();
    } else if (typeof define === "function" && define.amd) {
        define([], f);
    } else {
        var g;if (typeof window !== "undefined") {
            g = window;
        } else if (typeof global !== "undefined") {
            g = global;
        } else if (typeof self !== "undefined") {
            g = self;
        } else {
            g = this;
        }g.Fashion = f();
    }
})(function () {
    var define, module, exports;return function () {
        function r(e, n, t) {
            function o(i, f) {
                if (!n[i]) {
                    if (!e[i]) {
                        var c = "function" == typeof require && require;if (!f && c) return c(i, !0);if (u) return u(i, !0);var a = new Error("Cannot find module '" + i + "'");throw a.code = "MODULE_NOT_FOUND", a;
                    }var p = n[i] = { exports: {} };e[i][0].call(p.exports, function (r) {
                        var n = e[i][1][r];return o(n || r);
                    }, p, p.exports, r, e, n, t);
                }return n[i].exports;
            }for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) {
                o(t[i]);
            }return o;
        }return r;
    }()({ 1: [function (require, module, exports) {
            var _Fashion$apply;

            var Fashion = require('./src/export/Base.js');
            var CssVariableManager = require('./src/export/css/CssVariableManager.js'),
                css = new CssVariableManager();

            Fashion.apply(Fashion, (_Fashion$apply = {
                css: css,
                CssExport: CssVariableManager,
                Types: require('./src/export/type/Types.js'),
                ValueParser: require('./src/export/parse/ValueParser.js'),
                Type: require('./src/export/type/Type.js'),
                Bool: require('./src/export/type/Bool.js'),
                Literal: require('./src/export/type/Literal.js'),
                ParentheticalExpression: require('./src/export/type/ParentheticalExpression.js'),
                Text: require('./src/export/type/Text.js'),
                Numeric: require('./src/export/type/Numeric.js'),
                List: require('./src/export/type/List.js'),
                Map: require('./src/export/type/Map.js'),
                Color: require('./src/export/type/Color.js'),
                ColorRGBA: require('./src/export/type/ColorRGBA.js'),
                ColorHSLA: require('./src/export/type/ColorHSLA.js'),
                ColorStop: require('./src/export/type/ColorStop.js'),
                FunctionCall: require('./src/export/type/FunctionCall.js'),
                LinearGradient: require('./src/export/type/LinearGradient.js'),
                RadialGradient: require('./src/export/type/RadialGradient.js'),
                Statics: require('./src/export/type/Statics.js'),
                SourceBuilder: require('./src/export/type/SourceBuilder.js')
            }, _defineProperty(_Fashion$apply, "Types", require('./src/export/type/Types.js')), _defineProperty(_Fashion$apply, "TypeVisitor", require('./src/export/type/TypeVisitor.js')), _defineProperty(_Fashion$apply, "Output", require('./src/export/Output.js')), _defineProperty(_Fashion$apply, "Runtime", require('./src/export/Runtime.js')), _Fashion$apply));

            module.exports = Fashion;
        }, { "./src/export/Base.js": 3, "./src/export/Output.js": 4, "./src/export/Runtime.js": 5, "./src/export/css/CssVariableManager.js": 6, "./src/export/parse/ValueParser.js": 7, "./src/export/type/Bool.js": 8, "./src/export/type/Color.js": 9, "./src/export/type/ColorHSLA.js": 10, "./src/export/type/ColorRGBA.js": 11, "./src/export/type/ColorStop.js": 12, "./src/export/type/FunctionCall.js": 13, "./src/export/type/LinearGradient.js": 14, "./src/export/type/List.js": 15, "./src/export/type/Literal.js": 16, "./src/export/type/Map.js": 17, "./src/export/type/Numeric.js": 18, "./src/export/type/ParentheticalExpression.js": 19, "./src/export/type/RadialGradient.js": 20, "./src/export/type/SourceBuilder.js": 21, "./src/export/type/Statics.js": 22, "./src/export/type/Text.js": 23, "./src/export/type/Type.js": 24, "./src/export/type/TypeVisitor.js": 25, "./src/export/type/Types.js": 26 }], 2: [function (require, module, exports) {
            "use strict";

            function getJsName(name) {
                return name.replace(/\-/g, '_').replace(/\//g, '_fs_').replace(/\\/g, '_bs_');
            }

            var NameConverter = function () {
                function NameConverter() {
                    _classCallCheck(this, NameConverter);

                    this.variableNameMap = {};
                }

                _createClass(NameConverter, [{
                    key: "convertName",
                    value: function convertName(name) {
                        var map = this.variableNameMap,
                            converted = map[name];

                        if (converted === undefined) {
                            converted = map[name] = getJsName(name);
                        }
                        return converted;
                    }
                }]);

                return NameConverter;
            }();

            var converter = new NameConverter();

            module.exports = {
                NameConverter: NameConverter,
                getJsName: function getJsName(name) {
                    return converter.convertName(name);
                }
            };
        }, {}], 3: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var NameConverter = require('./../NameConverter.js');

            var debugging = {
                trace: false
            };

            var Base = function Base(config) {
                _classCallCheck(this, Base);

                if (config) {
                    merge(this, config);
                }
            };

            var BaseSet = function () {
                function BaseSet() {
                    _classCallCheck(this, BaseSet);
                }

                _createClass(BaseSet, [{
                    key: "first",
                    value: function first() {
                        return _first(this.items);
                    }
                }, {
                    key: "last",
                    value: function last() {
                        return _last(this.items);
                    }
                }, {
                    key: "tail",
                    value: function tail() {
                        return _tail(this.items);
                    }
                }]);

                return BaseSet;
            }();

            BaseSet.prototype.items = null;

            function _chainFunc() {}

            function apply(target, source) {
                target = target || {};

                if (source) {
                    for (var name in source) {
                        target[name] = source[name];
                    }
                }

                return target;
            }

            function merge(destination, object) {
                destination = destination || {};
                var key, value, sourceKey;

                if (object) {
                    for (key in object) {
                        value = object[key];
                        if (value && value.constructor === Object) {
                            sourceKey = destination[key];
                            if (sourceKey && sourceKey.constructor === Object) {
                                merge(sourceKey, value);
                            } else {
                                destination[key] = value;
                            }
                        } else {
                            destination[key] = value;
                        }
                    }
                }

                return destination;
            }

            var chain = Object.create || function (Parent) {
                _chainFunc.prototype = Parent;
                return new _chainFunc();
            };

            function createMessage(message, source) {
                if (source && source.isFashionScanner) {
                    message += ': ' + source.currentFile + ':' + source.lineNumber;
                } else if (source) {
                    message += ': ' + source.file + ':' + source.lineNumber;
                }

                return message;
            }

            function isFunction(obj) {
                return obj && typeof obj === 'function';
            }

            function trace(message, source) {
                if (debugging.trace) {
                    console.log(createMessage('[DBG] ' + message, source));
                }
            }

            function debug(message, source) {
                console.log(createMessage('[DBG] ' + message, source));
            }

            function log(message, source) {
                console.log(createMessage('[LOG] ' + message, source));
            }

            function info(message, source) {
                console.log(createMessage('[INF] ' + message, source));
            }

            function warn(message, source) {
                console.log(createMessage('[WRN] ' + message, source));
            }

            function error(message, source) {
                console.log(createMessage('[ERR] ' + message, source));
            }

            function raise(message, extra) {
                if (Fashion.inspect) {
                    debugger;
                }

                if (typeof message !== 'string') {
                    extra = message;
                    message = extra.message;
                    delete extra.message;
                }

                var error = new Error(message);
                error.$isFashionError = true;
                throw apply(error, extra);
            }

            function raiseAt(message, source, stack) {
                var extra;

                if (source) {
                    message = createMessage(message, source);

                    if (source.isFashionScanner) {
                        extra = {
                            file: source.currentFile,
                            lineNumber: source.lineNumber
                        };
                    } else {
                        extra = {
                            node: source,
                            lineNumber: source.lineNumber,
                            file: source.file
                        };
                    }
                }

                if (stack) {
                    if (!extra) {
                        extra = {};
                    }
                    extra.fashionStack = stack;
                }

                raise(message, extra);
            }

            function filter(array, func) {
                var result = [];
                for (var i = 0; i < array.length; i++) {
                    var item = array[i];
                    if (func(item, i)) {
                        result.push(item);
                    }
                }
                return result;
            }

            function convert(array, func) {
                var converted = [];
                for (var i = 0; i < array.length; i++) {
                    converted.push(func(array[i]));
                }
                return converted;
            }

            function _first(array) {
                return array.length && array[0];
            }

            function _last(array) {
                return array.length && array[array.length - 1];
            }

            function _tail(array) {
                if (array.length > 2) {
                    return array.slice(1);
                }
                return [];
            }

            function getAllKeys(obj, stop) {
                var keys = [],
                    map = {},
                    i,
                    key,
                    n,
                    names;

                for (; obj && obj !== stop; obj = Object.getPrototypeOf(obj)) {
                    names = Object.getOwnPropertyNames(obj);

                    for (i = 0, n = names.length; i < n; ++i) {
                        key = names[i];

                        if (!map[key]) {
                            map[key] = true;
                            keys.push(key);
                        }
                    }
                }

                return keys;
            }

            function mixin(target, bases) {
                if (!Array.isArray(bases)) {
                    bases = Array.prototype.slice.call(arguments, 1);
                }

                var proto = target.prototype;

                for (var b = 0; b < bases.length; b++) {
                    var base = bases[b],
                        baseProto = base.prototype;

                    getAllKeys(baseProto, Base.prototype).forEach(function (name) {
                        if (name in baseProto) {
                            if (!(name in proto)) {
                                proto[name] = baseProto[name];
                            }
                        }
                    });
                }
            }

            function flatten(array, level, output) {
                output = output || [];
                level = typeof level === 'undefined' ? 1000 : level;

                for (var i = 0; i < array.length; i++) {
                    var item = array[i];
                    if (Array.isArray(item) && level) {
                        flatten(item, level - 1, output);
                    } else {
                        output.push(item);
                    }
                }
                return output;
            }

            module.exports = {
                EmptyArray: [],
                getJsName: NameConverter.getJsName,
                chain: chain,
                Base: Base,
                BaseSet: BaseSet,
                apply: apply,
                merge: merge,
                createMessage: createMessage,
                isFunction: isFunction,
                debugging: debugging,
                trace: trace,
                debug: debug,
                log: log,
                info: info,
                warn: warn,
                error: error,
                raise: raise,
                raiseAt: raiseAt,
                filter: filter,
                convert: convert,
                first: _first,
                last: _last,
                tail: _tail,
                mixin: mixin,
                flatten: flatten
            };
        }, { "./../NameConverter.js": 2 }], 4: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('./Base.js'),
                Base = Fashion.Base;

            var Output = function (_Base) {
                _inherits(Output, _Base);

                function Output() {
                    _classCallCheck(this, Output);

                    var _this = _possibleConstructorReturn(this, (Output.__proto__ || Object.getPrototypeOf(Output)).call(this));

                    _this.output = '';
                    return _this;
                }

                _createClass(Output, [{
                    key: "space",
                    value: function space() {
                        this.add(' ');
                    }
                }, {
                    key: "add",
                    value: function add(text) {
                        this.output += text;
                    }
                }, {
                    key: "addComment",
                    value: function addComment(text) {
                        this.output += text;
                    }
                }, {
                    key: "indent",
                    value: function indent() {
                        this.indentation += this.indentstr;
                    }
                }, {
                    key: "unindent",
                    value: function unindent() {
                        this.indentation = this.indentation.substr(this.indentstr.length);
                    }
                }, {
                    key: "addln",
                    value: function addln(ln) {
                        this.output += '\n' + this.indentation + (ln || '');
                    }
                }, {
                    key: "addCommentLn",
                    value: function addCommentLn(ln) {
                        if (ln && ln.indexOf('//') === 0) {
                            return;
                        }
                        this.addln(ln);
                    }
                }, {
                    key: "get",
                    value: function get() {
                        return this.output;
                    }
                }, {
                    key: "indentln",
                    value: function indentln(ln) {
                        this.addln(ln);
                        this.indent();
                    }
                }, {
                    key: "unindentln",
                    value: function unindentln(ln) {
                        this.unindent();
                        this.addln(ln);
                    }
                }, {
                    key: "reset",
                    value: function reset() {
                        this.indentation = '';
                        this.output = '';
                    }
                }]);

                return Output;
            }(Base);

            Fashion.apply(Output.prototype, {
                indentation: '',
                output: '',
                isCompressed: false,
                indentstr: '    ',
                splitThreshold: 1000000,
                selectorCount: 0
            });

            module.exports = Output;
        }, { "./Base.js": 3 }], 5: [function (require, module, exports) {
            "use strict";

            var Fashion = require('./Base.js'),
                Base = Fashion.Base;

            var Type = require('./type/Type.js');
            var List = require('./type/List.js');
            var Bool = require('./type/Bool.js');

            var Color = require('./type/Color.js');
            var ColorRGBA = require('./type/ColorRGBA.js');
            var Text = require('./type/Text.js');

            var Literal = require('./type/Literal.js');

            var Statics = require('./type/Statics.js');
            var TypeVisitor = require('./type/TypeVisitor.js');
            var Types = require('./type/Types.js');

            var Scope = function () {
                function Scope(prev) {
                    _classCallCheck(this, Scope);

                    this.prev = prev;
                    this.map = {};
                    this.sourceInfo = null;
                }

                _createClass(Scope, [{
                    key: "get",
                    value: function get(name) {
                        var map = this.map,
                            prev = this,
                            value;

                        while (map) {
                            value = map[name];
                            if (value) {
                                return value;
                            }
                            prev = prev.prev;
                            map = prev && prev.map;
                        }

                        return value;
                    }
                }, {
                    key: "has",
                    value: function has(name) {
                        //return name in this.map;
                        var map = this.map,
                            prev = this;

                        while (map) {
                            if (name in map) {
                                return true;
                            }
                            prev = prev.prev;
                            map = prev && prev.map;
                        }

                        return false;
                    }
                }, {
                    key: "put",
                    value: function put(name, value) {
                        this.map[name] = value;
                        return value;
                    }
                }, {
                    key: "addEntries",
                    value: function addEntries(names) {
                        if (this.prev) {
                            this.prev.addEntries(names);
                        }
                        for (var name in this.map) {
                            names[name] = this.map[name];
                        }
                    }
                }, {
                    key: "getEntries",
                    value: function getEntries(entries) {
                        entries = entries || {};
                        this.addEntries(entries);
                        return entries;
                    }
                }, {
                    key: "getSourceInfo",
                    value: function getSourceInfo() {
                        return this.sourceInfo;
                    }
                }, {
                    key: "getCallStack",
                    value: function getCallStack(stack) {
                        stack = stack || [];
                        if (this.sourceInfo) {
                            stack.push(this.sourceInfo);
                        }
                        if (this.prev) {
                            this.prev.getCallStack(stack);
                        }
                        return stack;
                    }
                }]);

                return Scope;
            }();

            Fashion.apply(Scope.prototype, {
                $isScope: true,
                map: undefined,
                prev: undefined,

                // placeholder used to track what to reset the _currentScope to,
                resetScope: undefined
            });

            var Runtime = function (_Base2) {
                _inherits(Runtime, _Base2);

                function Runtime(config) {
                    _classCallCheck(this, Runtime);

                    var _this2 = _possibleConstructorReturn(this, (Runtime.__proto__ || Object.getPrototypeOf(Runtime)).call(this, config));

                    var me = _this2;
                    me.mixins = {};
                    me.functions = {};
                    me.processors = [];
                    me.registered = {
                        runtime: me,
                        box: Statics.boxType,
                        unbox: Statics.unboxType,
                        isArray: function isArray(array) {
                            return Array.isArray(array);
                        },

                        getRuntime: function getRuntime() {
                            return this.runtime;
                        },

                        handleArgs: function handleArgs(args, keys) {
                            var scope = {},
                                index = 0,
                                key;

                            for (var a = 0; a < args.length; a++) {
                                var arg = args[a];
                                if (arg === undefined) {
                                    continue;
                                }

                                // Named arguments
                                if (arg === true || arg === false) {
                                    scope[keys[index]] = arg;
                                    index++;
                                } else if (arg.type === undefined) {
                                    for (key in arg) {
                                        scope[key.replace(/^\$/, '')] = arg[key];
                                    }
                                }
                                // Required arguments
                                else {
                                        key = keys[index];
                                        if (key instanceof Array) {
                                            key = key[0];
                                            scope[key] = scope[key] || new List();
                                            scope[key].add(arg);
                                        } else {
                                            scope[key] = arg;
                                            index++;
                                        }
                                    }
                            }
                            return scope;
                        },

                        sliceArgs: function sliceArgs(args, start, end) {
                            return this.getRuntime().sliceArgs(args, start, end).items;
                        },

                        tailArgs: function tailArgs(start, args) {
                            var tail = Array.prototype.slice.call(args, start);

                            if (tail.length == 1 && this.isArray(tail)) {
                                tail = tail[0];
                            }

                            return tail;
                        }
                    };
                    return _this2;
                }

                _createClass(Runtime, [{
                    key: "bool",
                    value: function bool(value) {
                        return new Bool(value);
                    }
                }, {
                    key: "color",
                    value: function color(name) {
                        var rgb = Color.map[name],
                            color = new ColorRGBA(rgb[0], rgb[1], rgb[2], rgb[3]);
                        color.stringified = name;
                        return color;
                    }
                }, {
                    key: "quote",
                    value: function quote(value) {
                        if (value.type === 'string') {
                            return value;
                        }

                        return new Text(value.toString());
                    }
                }, {
                    key: "unquote",
                    value: function unquote(value) {
                        if (value.$isFashionType) {
                            return value.unquote();
                        }
                        return new Literal(value.toString());
                    }
                }, {
                    key: "not",
                    value: function not(expression) {
                        return this.box(this.unbox(expression) == false);
                    }
                }, {
                    key: "operate",
                    value: function operate(operation, left, right) {
                        if (left == null || left.$isFashionNull) {
                            if (operation != '==' && operation != '!=') {
                                return Literal.Null;
                            }
                        }
                        if (right == null || right.$isFashionNull) {
                            if (operation != '==' && operation != '!=') {
                                return Literal.Null;
                            }
                        }
                        return left.operate(operation, right);
                    }
                }, {
                    key: "reset",
                    value: function reset() {
                        this._currentScope = null;
                        this._currentCallStackScope = this.createCallStackScope();
                        this._globalScope = this.createScope();
                        this._dynamics = {};
                    }
                }, {
                    key: "run",
                    value: function run(code, metadata) {
                        this.load(code);
                        this.compile(code);
                        return this.execute(metadata);
                    }
                }, {
                    key: "createTypesBlock",
                    value: function createTypesBlock(types) {
                        types = types || this.types;
                        var keys = Object.getOwnPropertyNames(types),
                            buff = [],
                            name;
                        for (var i = 0; i < keys.length; i++) {
                            name = keys[i];
                            buff.push(name + ' = Types.' + name);
                            buff.push("__" + name + ' = ' + name);
                        }

                        if (buff.length === 0) {
                            return '';
                        }
                        return 'var ' + buff.join(',\n    ') + ';\n';
                    }
                }, {
                    key: "createMethodBlock",
                    value: function createMethodBlock(proto) {
                        proto = proto || this.constructor.prototype;

                        var buff = [],
                            keys,
                            name;

                        while (proto) {
                            keys = Object.getOwnPropertyNames(proto);
                            for (var i = 0; i < keys.length; i++) {
                                name = keys[i];
                                if (typeof proto[name] === 'function') {
                                    buff.push("__rt_" + name + ' = __rt.' + name + '.bind(__rt)');
                                }
                            }
                            proto = Object.getPrototypeOf(proto);
                        }

                        if (buff.length === 0) {
                            return '';
                        }
                        return 'var ' + buff.join(',\n    ') + ';\n';
                    }
                }, {
                    key: "createPropertyBlock",
                    value: function createPropertyBlock() {
                        var keys = Object.getOwnPropertyNames(this),
                            buff = [],
                            name;
                        for (var i = 0; i < keys.length; i++) {
                            name = keys[i];
                            buff.push("__rt_" + name + ' = __rt.' + name);
                        }

                        if (buff.length === 0) {
                            return '';
                        }
                        return 'var ' + buff.join(',\n    ') + ';\n';
                    }
                }, {
                    key: "createPrefixedFunctionBody",
                    value: function createPrefixedFunctionBody(code) {
                        code = this.createTypesBlock() + this.createMethodBlock() + this.createPropertyBlock() + code;
                        return code;
                    }
                }, {
                    key: "createWrappedFn",
                    value: function createWrappedFn(code) {
                        return new Function('Types', '__rt', '__gs', '__udf', '__dyn', this.createPrefixedFunctionBody(code));
                    }
                }, {
                    key: "callWrappedFn",
                    value: function callWrappedFn(fn, dynamics) {
                        return fn(Fashion, this, this._globalScope, undefined, dynamics || {});
                    }
                }, {
                    key: "compile",
                    value: function compile(code) {
                        var me = this,
                            theFn;

                        //code = '"use strict";\n' + code;
                        this.code = code;

                        new Function();

                        theFn = this.createWrappedFn(code);

                        this.fn = function (rt, overrides, dyn) {
                            var runtime = rt || me,
                                dynamics = dyn || {};

                            runtime.reset();

                            if (overrides) {
                                if (overrides.$isScope) {
                                    runtime._globalScope = overrides;
                                } else {
                                    runtime._globalScope.map = overrides;
                                }
                            }

                            if (dyn) {
                                runtime._dynamics = dyn;
                            }
                            runtime._currentScope = runtime._globalScope;
                            runtime._scopeStack = [runtime._currentScope];
                            try {
                                theFn(me.types, runtime, runtime._globalScope, undefined, dynamics);
                            } catch (err) {
                                Fashion.raiseAt(err.message || err, null, runtime.getCallStack());
                            }

                            return runtime._globalScope;
                        };

                        return this.fn;
                    }
                }, {
                    key: "execute",
                    value: function execute(metadata) {
                        return this.fn(this, metadata);
                    }
                }, {
                    key: "load",
                    value: function load(code) {
                        this.code = code;
                        return this;
                    }
                }, {
                    key: "registerProcessor",
                    value: function registerProcessor(proc) {
                        this.processors.push(new TypeVisitor(proc));
                    }
                }, {
                    key: "register",
                    value: function register(methods) {
                        if (methods['dynamic']) {
                            Fashion.error('Cannot register javascript function named "dynamic"');
                            delete methods['dynamic'];
                        }
                        if (methods['require']) {
                            Fashion.error('Cannot register javascript function named "require"');
                            delete methods['require'];
                        }
                        Fashion.apply(this.registered, methods);
                    }
                }, {
                    key: "isRegistered",
                    value: function isRegistered(name) {
                        name = this.reserved[name] ? '__' + name : name;
                        return !!this.registered[name];
                    }
                }, {
                    key: "getGlobalScope",
                    value: function getGlobalScope() {
                        return this._globalScope;
                    }
                }, {
                    key: "getCurrentScope",
                    value: function getCurrentScope() {
                        return this._currentScope;
                    }
                }, {
                    key: "getRegisteredFunctions",
                    value: function getRegisteredFunctions() {
                        return this.registered;
                    }
                }, {
                    key: "getFunctions",
                    value: function getFunctions() {
                        return this.functions;
                    }
                }, {
                    key: "getMixins",
                    value: function getMixins() {
                        return this.mixins;
                    }
                }, {
                    key: "createScope",
                    value: function createScope(scope) {
                        var currScope = scope || this._currentScope,
                            newScope = new Scope(currScope);
                        return this.pushScope(newScope);
                    }
                }, {
                    key: "pushScope",
                    value: function pushScope(scope) {
                        scope.resetScope = this._currentScope;
                        this._currentScope = scope;
                        return scope;
                    }
                }, {
                    key: "popScope",
                    value: function popScope() {
                        this._currentScope = this._currentScope.resetScope;
                        return this._currentScope;
                    }
                }, {
                    key: "createCallStackScope",
                    value: function createCallStackScope(scope) {
                        var currScope = scope || this._currentCallStackScope,
                            newScope = new Scope(currScope);
                        return this.pushCallStackScope(newScope);
                    }
                }, {
                    key: "pushCallStackScope",
                    value: function pushCallStackScope(scope) {
                        scope.resetScope = this._currentCallStackScope;
                        this._currentCallStackScope = scope;
                        return scope;
                    }
                }, {
                    key: "popCallStackScope",
                    value: function popCallStackScope() {
                        this._currentCallStackScope = this._currentCallStackScope.resetScope;
                        return this._currentCallStackScope;
                    }
                }, {
                    key: "getCallStack",
                    value: function getCallStack() {
                        if (this._currentCallStackScope) {
                            return this._currentCallStackScope.getCallStack();
                        }
                        return null;
                    }
                }, {
                    key: "pushSourceInfo",
                    value: function pushSourceInfo(info) {
                        if (this._currentCallStackScope) {
                            this._currentCallStackScope.sourceInfo = info;
                        }
                        return true;
                    }
                }, {
                    key: "getSourceInfo",
                    value: function getSourceInfo() {
                        var stack = this._currentCallStackScope,
                            info = stack && stack.sourceInfo;

                        if (info && info.length) {
                            return {
                                lineNumber: info[0],
                                file: info[1]
                            };
                        }
                        return null;
                    }
                }, {
                    key: "get",
                    value: function get(name) {
                        var scope = this.getScopeForName(name),
                            res = scope.map[name];

                        if (typeof res === 'undefined') {
                            if (!(name in scope.map)) {
                                Fashion.raiseAt('Reference to undeclared variable : ' + name, null, this.getCallStack());
                            }
                        }

                        return this.box(res);
                    }
                }, {
                    key: "getScopeForName",
                    value: function getScopeForName(jsName) {
                        var scope = this._currentScope;
                        while (scope) {
                            if (jsName in scope.map) {
                                return scope;
                            }
                            scope = scope.prev;
                        }
                        return this._currentScope;
                    }
                }, {
                    key: "getDefault",
                    value: function getDefault(val) {
                        if (val == null || typeof val === 'undefined') {
                            // === null || undefined
                            return undefined;
                        }

                        if (val.$isFashionNull) {
                            if (this.constructor.allowNullDefaults) {
                                return val;
                            }
                            return undefined;
                        }

                        return this.box(val);
                    }
                }, {
                    key: "getGlobalDefault",
                    value: function getGlobalDefault(jsName) {
                        var obj = this._globalScope.get(jsName);
                        return this.getDefault(obj);
                    }
                }, {
                    key: "getLocalDefault",
                    value: function getLocalDefault(jsName) {
                        var obj = this._currentScope.get(jsName);
                        return this.getDefault(obj);
                    }
                }, {
                    key: "setGlobal",
                    value: function setGlobal(jsName, value, astNodeId) {
                        var currScope = this._globalScope;

                        if (!value || !value.$isFashionLiteral) {
                            value = this.box(value);
                        }

                        value.ast = value.ast || this.getAstNode(astNodeId);
                        currScope.map[jsName] = value;
                        return value;
                    }
                }, {
                    key: "setDynamic",
                    value: function setDynamic(name, value, astNodeId) {
                        var jsName = Fashion.getJsName(name),
                            currScope = this._globalScope,
                            newValue;

                        if (!value || !value.$isFashionLiteral) {
                            value = this.box(value);
                        }

                        value.ast = value.ast || this.getAstNode(astNodeId);

                        if (value.$referenceName || value.$constant) {
                            newValue = value.clone();
                            newValue.$previousReference = value;
                            value = newValue;
                            value.ast = this.getAstNode(astNodeId);
                        } else {
                            value.$referenceName = name;
                        }

                        currScope.map[jsName] = value;
                        return value;
                    }
                }, {
                    key: "setScoped",
                    value: function setScoped(jsName, value) {
                        var currScope = this.getScopeForName(jsName);

                        if (!value || !value.$isFashionLiteral) {
                            value = this.box(value);
                        }

                        currScope.map[jsName] = value;
                        return value;
                    }
                }, {
                    key: "set",
                    value: function set(jsName, value) {
                        var currScope = this._currentScope;

                        if (!value || !value.$isFashionLiteral) {
                            value = this.box(value);
                        }

                        currScope.map[jsName] = value;
                        return value;
                    }
                }, {
                    key: "getDocs",
                    value: function getDocs(id) {
                        if (this.docCache) {
                            return this.docCache.get(id);
                        }
                    }
                }, {
                    key: "getString",
                    value: function getString(id) {
                        if (this.stringCache) {
                            return this.stringCache.get(id);
                        }
                    }
                }, {
                    key: "getAstNode",
                    value: function getAstNode(id) {
                        if (this.nodeCache) {
                            return this.nodeCache.get(id);
                        }
                    }
                }, {
                    key: "applySpread",
                    value: function applySpread(arg) {
                        arg.spread = true;
                        return arg;
                    }
                }, {
                    key: "sliceArgs",
                    value: function sliceArgs(args, start, end) {
                        start = start || 0;
                        end = end || args.length;

                        var filtered = [],
                            newArgs = [],
                            separator = ', ',
                            spread,
                            a,
                            arg;

                        for (a = start; a < end; a++) {
                            arg = args[a];
                            if (!arg) {
                                if (!spread) {
                                    filtered.push(arg);
                                }
                                continue;
                            }
                            if (arg.spread && arg.$isFashionList) {
                                if (spread) {
                                    filtered.push(spread);
                                }
                                spread = arg;
                                separator = spread.separator || separator;
                            } else {
                                filtered.push(arg);
                            }
                        }

                        for (a = 0; a < filtered.length; a++) {
                            arg = filtered[a];
                            separator = arg && arg.splatSeparator || separator;
                            newArgs.push(filtered[a]);
                        }

                        if (spread) {
                            newArgs.push.apply(newArgs, spread.items);
                        }

                        return new List(newArgs, separator);
                    }
                }, {
                    key: "applySpreadArgs",
                    value: function applySpreadArgs(args, name) {
                        var newArgs = [],
                            hadSpread = false,
                            offset = 0,
                            arg,
                            a,
                            item,
                            i,
                            items,
                            key,
                            map,
                            defaults,
                            proc,
                            param,
                            paramName;

                        proc = this.context && this.context.preprocessor;
                        if (proc) {
                            defaults = proc.mixinDeclarations[name];

                            if (defaults) {
                                offset = 1;
                            } else {
                                defaults = proc.functionDeclarations[name];
                            }

                            defaults = defaults && defaults.parameters;
                        }

                        for (a = 0; a < args.length; a++) {
                            arg = args[a];
                            if (arg && arg.spread && arg.$isFashionMap && defaults) {
                                items = arg.items;
                                map = {};
                                for (key in arg.map) {
                                    map['$' + Fashion.getJsName(key)] = arg.map[key];
                                }

                                for (var p = 0; p < defaults.length; p++) {
                                    param = defaults[p];
                                    paramName = Fashion.getJsName(param.name);
                                    if (paramName in map) {
                                        newArgs.push(items[map[paramName]]);
                                        delete map[paramName];
                                    } else if (!param.varArgs) {
                                        newArgs.push(undefined);
                                    }
                                }
                                for (key in map) {
                                    item = items[map[key]];
                                    newArgs.push(item);
                                }
                                hadSpread = true;
                            } else if (arg && arg.spread && arg.$isFashionList) {
                                items = arg.getItems();
                                for (i = 0; i < items.length; i++) {
                                    item = items[i];
                                    item && (item.splatSeparator = arg.separator);
                                    newArgs.push(item);
                                }
                                hadSpread = true;
                            } else if (arg || !hadSpread) {
                                newArgs.push(arg);
                            }
                            // clear the flag indicating the spread argument
                            // so subsequent calls using this same variable will not
                            // be contaminated
                            arg && (arg.spread = undefined);
                        }

                        var misisngParams = this.context && this.context.missingParameters;

                        if (misisngParams && misisngParams == 'error') {
                            if (defaults) {
                                for (var d = 0; d < defaults.length; d++) {
                                    if (!defaults[d].hasOwnProperty('default') && !defaults[d].varArgs) {
                                        if (newArgs[d + offset] === undefined) {
                                            Fashion.raiseAt("No value supplied for argument : " + defaults[d].name, null, this.getCallStack());
                                        }
                                    }
                                }
                            }
                        }
                        return newArgs;
                    }
                }, {
                    key: "warn",
                    value: function warn(arg) {
                        Fashion.warn(arg, this.getSourceInfo());
                    }
                }, {
                    key: "error",
                    value: function error(arg) {
                        Fashion.raiseAt(arg, null, this.getCallStack());
                    }
                }, {
                    key: "debug",
                    value: function debug() {
                        Fashion.debug.apply(Fashion, arguments);
                    }
                }, {
                    key: "setCaches",
                    value: function setCaches(transpiler) {
                        this.docCache = transpiler.docCache;
                        this.stringCache = transpiler.stringCache;
                        this.nodeCache = transpiler.nodeCache;
                    }
                }, {
                    key: "copyRuntimeState",
                    value: function copyRuntimeState(runtime) {
                        this._dynamics = runtime._dynamics;
                        this.registered = runtime.registered;
                        this.functions = runtime.functions;
                        this.mixins = runtime.mixins;
                    }
                }, {
                    key: "test",
                    value: function test(val) {
                        val = this.unbox(val);
                        if (val == null || val === false) {
                            return false;
                        }
                        return true;
                    }
                }, {
                    key: "and",
                    value: function and(a, b) {
                        if (this.test(a)) {
                            return b;
                        }
                        return a;
                    }
                }, {
                    key: "or",
                    value: function or(a, b) {
                        if (this.test(a)) {
                            return a;
                        }
                        return b;
                    }
                }]);

                return Runtime;
            }(Base);

            Fashion.apply(Runtime.prototype, {
                box: Type.box,
                unbox: Type.unbox,
                Scope: Scope,

                isFashionRuntime: true,
                functions: null,
                code: null,
                fn: null,

                stringCache: null,
                docCache: null,
                types: Types,

                _globalScope: null,
                _currentScope: null,
                _dynamics: null,
                context: null,
                reserved: {
                    'if': true,
                    'else': true
                }
            });

            module.exports = Runtime;
        }, { "./Base.js": 3, "./type/Bool.js": 8, "./type/Color.js": 9, "./type/ColorRGBA.js": 11, "./type/List.js": 15, "./type/Literal.js": 16, "./type/Statics.js": 22, "./type/Text.js": 23, "./type/Type.js": 24, "./type/TypeVisitor.js": 25, "./type/Types.js": 26 }], 6: [function (require, module, exports) {
            "use strict";

            var Fashion = require('../Base.js');
            var Runtime = require('../Runtime.js');
            var ValueParser = require('../parse/ValueParser.js');
            var SourceBuilder = require('../type/SourceBuilder.js');

            var CssVariableManager = function () {
                function CssVariableManager() {
                    _classCallCheck(this, CssVariableManager);

                    this.reset();
                }

                _createClass(CssVariableManager, [{
                    key: "reset",
                    value: function reset() {
                        this.initFns = [];
                        this.calcFns = [];
                        this.variableMap = {};
                        this.runtime = null;
                    }
                }, {
                    key: "createRuntime",
                    value: function createRuntime() {
                        return new Runtime();
                    }
                }, {
                    key: "getRuntime",
                    value: function getRuntime() {
                        var me = this,
                            rt = me.runtime;
                        if (!rt) {
                            rt = me.createRuntime();
                            for (var i = 0; i < me.initFns.length; i++) {
                                me.initFns[i](rt);
                            }
                            me.runtime = rt;
                        }
                        return rt;
                    }
                }, {
                    key: "calculate",
                    value: function calculate(vars) {
                        var me = this,
                            rt = me.getRuntime(),
                            globals = {},
                            parser = new ValueParser(),
                            map = me.variableMap,
                            key,
                            scope,
                            sb,
                            name,
                            names,
                            jsName,
                            value,
                            wrapper;

                        scope = new rt.Scope();
                        for (name in vars) {
                            key = Fashion.getJsName(name.replace(me.nameRe, ''));
                            if (key.indexOf('$') !== 0) {
                                key = '$' + key;
                            }
                            scope.put(key, parser.parse(vars[name]));
                        }

                        rt._globalScope = scope;
                        rt._currentScope = scope;
                        for (var i = 0; i < me.calcFns.length; i++) {
                            me.calcFns[i](rt);
                        }

                        sb = new SourceBuilder();

                        vars = {};
                        for (name in map) {
                            names = map[name];
                            for (var i = 0; i < names.length; i++) {
                                key = names[i];
                                jsName = '$' + Fashion.getJsName(key);
                                value = scope.get(jsName);
                                if (value) {
                                    if (value.$isWrapper) {
                                        value = value.value;
                                    }
                                    vars[key] = sb.toSource(value);
                                }
                            }
                        }

                        return vars;
                    }
                }, {
                    key: "applyVariables",
                    value: function applyVariables(vars) {
                        var me = this,
                            map = me.variableMap;

                        for (var selector in map) {
                            var variables = map[selector];
                            var els = document.querySelectorAll(selector);
                            if (els) {
                                for (var i = 0; i < els.length; i++) {
                                    for (var j = 0; j < variables.length; j++) {
                                        var varName = variables[j];
                                        els[i].style.setProperty('--' + varName, vars[varName]);
                                    }
                                }
                            }
                        }
                    }
                }, {
                    key: "setVariables",
                    value: function setVariables(vars) {
                        this.applyVariables(this.calculate(vars));
                    }
                }, {
                    key: "register",
                    value: function register(init, calc, map) {
                        if (init) {
                            this.initFns.push(init);
                        }

                        if (calc) {
                            this.calcFns.push(calc);
                        }

                        if (map) {
                            var vars = this.variableMap;
                            for (var name in map) {
                                var curr = vars[name];
                                if (!curr) {
                                    vars[name] = map[name];
                                } else {
                                    curr.push.apply(curr, map[name]);
                                }
                            }
                        }
                    }
                }, {
                    key: "buildName",
                    value: function buildName(name) {
                        return name.replace(/^--/, '').replace(/^\$/, '');
                    }
                }, {
                    key: "buildJsName",
                    value: function buildJsName(name) {
                        return Fashion.getJsName(name);
                    }
                }, {
                    key: "buildNames",
                    value: function buildNames(names) {
                        var out = {},
                            name;
                        for (name in names) {
                            out[name] = this.buildName(names[name]);
                        }
                        return out;
                    }
                }, {
                    key: "buildJsNames",
                    value: function buildJsNames(names) {
                        var out = {},
                            name;
                        for (name in names) {
                            out[name] = this.buildJsName(names[name]);
                        }
                        return out;
                    }
                }, {
                    key: "getVariables",
                    value: function getVariables() {
                        var me = this,
                            map = me.variableMap,
                            out = {};

                        for (var selector in map) {
                            var variables = map[selector];
                            var els = document.querySelectorAll(selector);
                            if (els) {
                                for (var i = 0; i < els.length; i++) {
                                    for (var j = 0; j < variables.length; j++) {
                                        var varName = variables[j];
                                        out[varName] = els[i].style.getPropertyValue('--' + varName);
                                    }
                                }
                            }
                        }
                        return out;
                    }
                }]);

                return CssVariableManager;
            }();

            Fashion.apply(CssVariableManager.prototype, {
                $isExport: true,
                nameRe: /^--/
            });

            module.exports = CssVariableManager;
        }, { "../Base.js": 3, "../Runtime.js": 5, "../parse/ValueParser.js": 7, "../type/SourceBuilder.js": 21 }], 7: [function (require, module, exports) {
            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('../type/Type.js');
            var Statics = require('../type/Statics.js');
            var Types = require('../type/Types.js'),
                Color = Types.Color,
                Text = Types.Text,
                Numeric = Types.Numeric,
                List = Types.List,
                Bool = Types.Bool,
                Literal = Types.Literal,
                ColorRGBA = Types.ColorRGBA,
                ColorHSLA = Types.ColorHSLA,
                FunctionCall = Types.FunctionCall;

            var Parser = function () {
                function Parser() {
                    _classCallCheck(this, Parser);

                    this.index = 0;
                }

                _createClass(Parser, [{
                    key: "_advance",
                    value: function _advance() {
                        var me = this,
                            buff = '',
                            str = me.str,
                            len = str.length,
                            isString = false,
                            escaped = false,
                            isParen = 0,
                            ch;

                        while (me.index < len) {
                            ch = str[me.index];
                            me.index++;

                            // whitespace
                            if (ch <= ' ') {
                                if (!isString && !isParen) {
                                    if (buff.length) {
                                        break;
                                    }
                                    continue;
                                }
                            }

                            // terminal char
                            if (ch === ';' && !isString && !escaped) {
                                break;
                            }

                            if (ch === '(') {
                                isParen++;
                            }

                            if (ch === ')') {
                                isParen && isParen--;
                            }

                            if (ch === ',' && !isString && !escaped && !isParen) {
                                if (buff.length) {
                                    me.index--;
                                    break;
                                } else {
                                    return ch;
                                }
                            }

                            if (ch === '\\') {
                                if (isString) {
                                    escaped = 1;
                                    me.index++;
                                    continue;
                                }
                            }

                            if (ch === '"' || ch === "'") {
                                if (!isString) {
                                    isString = ch;
                                } else if (isString === ch) {
                                    isString = false;
                                }
                            }

                            escaped = false;
                            buff += ch;
                        }

                        return buff;
                    }
                }, {
                    key: "parseValue",
                    value: function parseValue(token) {
                        var rx = {
                            number: /^(\d+)(px|pt|pc|cm|mm|in|em|rem|ex)?$/g,
                            shortHexColor: /^#([A-Fa-f0-9]{3})$/,
                            longHexColor: /^#([A-Fa-f0-9]{6})$/,
                            functionCall: /^([A-Za-z0-9_]+)\((.*)\)$/,
                            parenList: /^\((.*?)\)$/

                        },
                            match,
                            value;

                        if (token[0] === '"' || token[0] === "'") {
                            value = token = token.substring(1, token.length - 1);
                            return new Text(value, token[0]);
                        }

                        if (token === 'true') {
                            return new Bool(true);
                        }

                        if (token === 'false') {
                            return new Bool(false);
                        }

                        if (token === 'null') {
                            return Literal.Null;
                        }

                        if (token === 'none') {
                            return Literal.None;
                        }

                        if (Fashion.Color.map[token]) {
                            var rgb = Color.map[token],
                                color = new ColorRGBA(rgb[0], rgb[1], rgb[2], rgb[3]);
                            color.stringified = token;
                            return color;
                        }

                        if (match = rx.number.exec(token)) {
                            return new Numeric(parseFloat(match[1]), match[2]);
                        }

                        if (match = rx.shortHexColor.exec(token)) {
                            return ColorRGBA.fromHex(match[1]);
                        }

                        if (match = rx.longHexColor.exec(token)) {
                            return ColorRGBA.fromHex(match[1]);
                        }

                        if (match = rx.functionCall.exec(token)) {
                            var name = match[1],
                                args = this.parse(match[2]).items;
                            if (name === 'hsla' || name === 'hsl') {
                                return new ColorHSLA(Type.unbox(args[0]), Type.unbox(args[1]), Type.unbox(args[2]), Type.unbox(args[3]) || 1);
                            } else if (name === 'rgba' || name === 'rgb') {
                                return new ColorRGBA(Type.unbox(args[0]), Type.unbox(args[1]), Type.unbox(args[2]), Type.unbox(args[3]) || 1);
                            }
                            return new FunctionCall(name, args);
                        }

                        if (match = rx.parenList.exec(token)) {
                            return new FunctionCall(this.parse(match[1]));
                        }

                        return new Fashion.Literal(token);
                    }
                }, {
                    key: "parse",
                    value: function parse(str) {
                        var me = this,
                            tokens = [],
                            values = [],
                            csv = null,
                            token;

                        me.str = str;
                        me.index = 0;

                        while (token = me._advance()) {
                            tokens.push(token);
                        }

                        for (var i = 0; i < tokens.length; i++) {
                            token = tokens[i].trim();
                            if (tokens[i + 1] === ',') {
                                csv = csv || [];
                                csv.push(me.parseValue(token));
                                i++;
                            } else if (csv) {
                                csv.push(me.parseValue(token));
                                values.push(new List(csv, ', '));
                                csv = null;
                            } else {
                                values.push(me.parseValue(token));
                            }
                        }

                        if (values.length === 1) {
                            return values[0];
                        }

                        return new List(values, ' ');
                    }
                }]);

                return Parser;
            }();

            // Fashion.apply(Parser.prototype, {
            //     regex:
            // });

            module.exports = Parser;
        }, { "../Base.js": 3, "../type/Statics.js": 22, "../type/Type.js": 24, "../type/Types.js": 26 }], 8: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');

            var Bool = function (_Type) {
                _inherits(Bool, _Type);

                function Bool(value) {
                    _classCallCheck(this, Bool);

                    var _this3 = _possibleConstructorReturn(this, (Bool.__proto__ || Object.getPrototypeOf(Bool)).call(this));

                    _this3.value = !!value;
                    return _this3;
                }

                _createClass(Bool, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.bool(this);
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        return this.value ? 'true' : 'false';
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new Bool(this.value);
                    }
                }]);

                return Bool;
            }(Type);

            Fashion.apply(Bool.prototype, {
                type: 'bool',
                $isFashionBool: true,
                value: null
            });

            Bool.True = new Bool(true);
            Bool.True.$constant = true;

            Bool.False = new Bool(false);
            Bool.False.$constant = true;

            module.exports = Bool;
        }, { "../Base.js": 3, "./Type.js": 24 }], 9: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');
            var Bool = require('./Bool.js');
            var Numeric = require('./Numeric.js');

            var Color = function (_Type2) {
                _inherits(Color, _Type2);

                function Color() {
                    _classCallCheck(this, Color);

                    return _possibleConstructorReturn(this, (Color.__proto__ || Object.getPrototypeOf(Color)).call(this));
                }

                _createClass(Color, [{
                    key: "toBoolean",
                    value: function toBoolean() {
                        return Bool.True;
                    }

                    // These two references need to be left out of the comment section above
                    // so as to prevent ordering issue during builds;

                }, {
                    key: "getRGBA",
                    value: function getRGBA() {
                        return this;
                    }
                }, {
                    key: "getHSLA",
                    value: function getHSLA() {
                        return this;
                    }
                }], [{
                    key: "component",
                    value: function component(color, _component) {
                        var unit = Color.units[_component],
                            type = Color.types[_component],
                            prop = Color.comps[_component],
                            targetColor;

                        if (type == 'hsla') {
                            targetColor = color.getHSLA();
                        } else {
                            targetColor = color.getRGBA();
                        }

                        return new Numeric(targetColor[prop], unit);
                    }
                }, {
                    key: "adjust",
                    value: function adjust(color, component, amount) {
                        var hsl = color.getHSLA().copy(),
                            prop = Color.comps[component],
                            value = amount.value;

                        //    if (component === 'saturation' && hsl.s === 0)  {
                        //        return color.clone();
                        //    }
                        //
                        hsl[prop] += value;

                        hsl.h = Color.constrainDegrees(hsl.h);
                        hsl.s = Color.constrainPercentage(hsl.s);
                        hsl.l = Color.constrainPercentage(hsl.l);

                        return hsl.getRGBA();
                    }
                }, {
                    key: "constrainChannel",
                    value: function constrainChannel(channel) {
                        return Math.max(0, Math.min(channel, 255));
                    }
                }, {
                    key: "constrainPercentage",
                    value: function constrainPercentage(per) {
                        return Math.max(0, Math.min(per, 100));
                    }
                }, {
                    key: "constrainDegrees",
                    value: function constrainDegrees(deg) {
                        deg = deg % 360;
                        return deg < 0 ? 360 + deg : deg;
                    }
                }, {
                    key: "constrainAlpha",
                    value: function constrainAlpha(alpha) {
                        if (alpha === undefined) {
                            return 1;
                        }
                        return Math.max(0, Math.min(alpha, 1));
                    }
                }]);

                return Color;
            }(Type);

            Fashion.apply(Color, {
                units: {
                    lightness: '%',
                    saturation: '%',
                    hue: 'deg'
                },

                types: {
                    red: 'rgba',
                    blue: 'rgba',
                    green: 'rgba',
                    alpha: 'rgba',
                    hue: 'hsla',
                    saturation: 'hsla',
                    lightness: 'hsla'
                },

                comps: {
                    red: 'r',
                    green: 'g',
                    blue: 'b',
                    alpha: 'a',
                    hue: 'h',
                    saturation: 's',
                    lightness: 'l'
                },

                map: {
                    aliceblue: [240, 248, 255],
                    antiquewhite: [250, 235, 215],
                    aqua: [0, 255, 255],
                    aquamarine: [127, 255, 212],
                    azure: [240, 255, 255],
                    beige: [245, 245, 220],
                    bisque: [255, 228, 196],
                    black: [0, 0, 0],
                    blanchedalmond: [255, 235, 205],
                    blue: [0, 0, 255],
                    blueviolet: [138, 43, 226],
                    brown: [165, 42, 42],
                    burlywood: [222, 184, 135],
                    cadetblue: [95, 158, 160],
                    chartreuse: [127, 255, 0],
                    chocolate: [210, 105, 30],
                    coral: [255, 127, 80],
                    cornflowerblue: [100, 149, 237],
                    cornsilk: [255, 248, 220],
                    crimson: [220, 20, 60],
                    cyan: [0, 255, 255],
                    darkblue: [0, 0, 139],
                    darkcyan: [0, 139, 139],
                    darkgoldenrod: [184, 132, 11],
                    darkgray: [169, 169, 169],
                    darkgreen: [0, 100, 0],
                    darkgrey: [169, 169, 169],
                    darkkhaki: [189, 183, 107],
                    darkmagenta: [139, 0, 139],
                    darkolivegreen: [85, 107, 47],
                    darkorange: [255, 140, 0],
                    darkorchid: [153, 50, 204],
                    darkred: [139, 0, 0],
                    darksalmon: [233, 150, 122],
                    darkseagreen: [143, 188, 143],
                    darkslateblue: [72, 61, 139],
                    darkslategray: [47, 79, 79],
                    darkslategrey: [47, 79, 79],
                    darkturquoise: [0, 206, 209],
                    darkviolet: [148, 0, 211],
                    deeppink: [255, 20, 147],
                    deepskyblue: [0, 191, 255],
                    dimgray: [105, 105, 105],
                    dimgrey: [105, 105, 105],
                    dodgerblue: [30, 144, 255],
                    firebrick: [178, 34, 34],
                    floralwhite: [255, 255, 240],
                    forestgreen: [34, 139, 34],
                    fuchsia: [255, 0, 255],
                    gainsboro: [220, 220, 220],
                    ghostwhite: [248, 248, 255],
                    gold: [255, 215, 0],
                    goldenrod: [218, 165, 32],
                    gray: [128, 128, 128],
                    green: [0, 128, 0],
                    greenyellow: [173, 255, 47],
                    grey: [128, 128, 128],
                    honeydew: [240, 255, 240],
                    hotpink: [255, 105, 180],
                    indianred: [205, 92, 92],
                    indigo: [75, 0, 130],
                    ivory: [255, 255, 240],
                    khaki: [240, 230, 140],
                    lavender: [230, 230, 250],
                    lavenderblush: [255, 240, 245],
                    lawngreen: [124, 252, 0],
                    lemonchiffon: [255, 250, 205],
                    lightblue: [173, 216, 230],
                    lightcoral: [240, 128, 128],
                    lightcyan: [224, 255, 255],
                    lightgoldenrodyellow: [250, 250, 210],
                    lightgray: [211, 211, 211],
                    lightgreen: [144, 238, 144],
                    lightgrey: [211, 211, 211],
                    lightpink: [255, 182, 193],
                    lightsalmon: [255, 160, 122],
                    lightseagreen: [32, 178, 170],
                    lightskyblue: [135, 206, 250],
                    lightslategray: [119, 136, 153],
                    lightslategrey: [119, 136, 153],
                    lightsteelblue: [176, 196, 222],
                    lightyellow: [255, 255, 224],
                    lime: [0, 255, 0],
                    limegreen: [50, 205, 50],
                    linen: [250, 240, 230],
                    magenta: [255, 0, 255],
                    maroon: [128, 0, 0],
                    mediumaquamarine: [102, 205, 170],
                    mediumblue: [0, 0, 205],
                    mediumorchid: [186, 85, 211],
                    mediumpurple: [147, 112, 219],
                    mediumseagreen: [60, 179, 113],
                    mediumslateblue: [123, 104, 238],
                    mediumspringgreen: [0, 250, 154],
                    mediumturquoise: [72, 209, 204],
                    mediumvioletred: [199, 21, 133],
                    midnightblue: [25, 25, 112],
                    mintcream: [245, 255, 250],
                    mistyrose: [255, 228, 225],
                    moccasin: [255, 228, 181],
                    navajowhite: [255, 222, 173],
                    navy: [0, 0, 128],
                    oldlace: [253, 245, 230],
                    olive: [128, 128, 0],
                    olivedrab: [107, 142, 35],
                    orange: [255, 165, 0],
                    orangered: [255, 69, 0],
                    orchid: [218, 112, 214],
                    palegoldenrod: [238, 232, 170],
                    palegreen: [152, 251, 152],
                    paleturquoise: [175, 238, 238],
                    palevioletred: [219, 112, 147],
                    papayawhip: [255, 239, 213],
                    peachpuff: [255, 218, 185],
                    peru: [205, 133, 63],
                    pink: [255, 192, 203],
                    plum: [221, 160, 203],
                    powderblue: [176, 224, 230],
                    purple: [128, 0, 128],
                    red: [255, 0, 0],
                    rosybrown: [188, 143, 143],
                    royalblue: [65, 105, 225],
                    saddlebrown: [139, 69, 19],
                    salmon: [250, 128, 114],
                    sandybrown: [244, 164, 96],
                    seagreen: [46, 139, 87],
                    seashell: [255, 245, 238],
                    sienna: [160, 82, 45],
                    silver: [192, 192, 192],
                    skyblue: [135, 206, 235],
                    slateblue: [106, 90, 205],
                    slategray: [119, 128, 144],
                    slategrey: [119, 128, 144],
                    snow: [255, 255, 250],
                    springgreen: [0, 255, 127],
                    steelblue: [70, 130, 180],
                    tan: [210, 180, 140],
                    teal: [0, 128, 128],
                    thistle: [216, 191, 216],
                    tomato: [255, 99, 71],
                    turquoise: [64, 224, 208],
                    violet: [238, 130, 238],
                    wheat: [245, 222, 179],
                    white: [255, 255, 255],
                    whitesmoke: [245, 245, 245],
                    yellow: [255, 255, 0],
                    yellowgreen: [154, 205, 5],
                    transparent: [0, 0, 0, 0]
                }
            });

            Fashion.apply(Color.prototype, {
                type: 'color',
                $isFashionColor: true,
                $isFashionRGBA: false,
                $isFashionHSLA: false,
                $canUnbox: false
            });

            module.exports = Color;
        }, { "../Base.js": 3, "./Bool.js": 8, "./Numeric.js": 18, "./Type.js": 24 }], 10: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Color = require('./Color.js');
            var ColorRGBA = require('./ColorRGBA.js');

            var ColorHSLA = function (_Color) {
                _inherits(ColorHSLA, _Color);

                function ColorHSLA(h, s, l, a) {
                    _classCallCheck(this, ColorHSLA);

                    var _this5 = _possibleConstructorReturn(this, (ColorHSLA.__proto__ || Object.getPrototypeOf(ColorHSLA)).call(this));

                    _this5.h = Color.constrainDegrees(h);
                    _this5.s = s;
                    _this5.l = l;
                    if (a !== undefined) {
                        _this5.a = a;
                    }
                    return _this5;
                }

                _createClass(ColorHSLA, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.hsla(this);
                    }
                }, {
                    key: "operate",
                    value: function operate(operation, right) {
                        return this.getRGBA().operate(operation, right);
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new ColorHSLA(this.h, this.s, this.l, this.a);
                    }
                }, {
                    key: "getRGBA",
                    value: function getRGBA() {
                        return ColorRGBA.fromHSLA(this);
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        return this.getRGBA().toString();
                    }
                }, {
                    key: "add",
                    value: function add(h, s, l, a) {
                        return new ColorHSLA(Color.constrainDegrees(this.h + h), Color.constrainPercentage(this.s + s), Color.constrainPercentage(this.l + l), Color.constrainAlpha(this.a * a));
                    }
                }, {
                    key: "subtract",
                    value: function subtract(h, s, l) {
                        return this.add(-h, -s, -l);
                    }
                }, {
                    key: "adjustLightness",
                    value: function adjustLightness(percent) {
                        this.l = Color.constrainPercentage(this.l + percent);
                        return this;
                    }
                }, {
                    key: "adjustHue",
                    value: function adjustHue(deg) {
                        this.h = Color.constrainDegrees(this.h + deg);
                        return this;
                    }
                }], [{
                    key: "fromRGBA",
                    value: function fromRGBA(rgba) {
                        if (rgba.$isFashionHSLA) {
                            return rgba.clone();
                        }

                        var r = rgba.r / 255,
                            g = rgba.g / 255,
                            b = rgba.b / 255,
                            a = rgba.a,
                            max = Math.max(r, g, b),
                            min = Math.min(r, g, b),
                            delta = max - min,
                            h = 0,
                            s = 0,
                            l = 0.5 * (max + min);

                        // min==max means achromatic (hue is undefined)
                        if (min != max) {
                            s = l < 0.5 ? delta / (max + min) : delta / (2 - max - min);
                            if (r == max) {
                                h = 60 * (g - b) / delta;
                            } else if (g == max) {
                                h = 120 + 60 * (b - r) / delta;
                            } else {
                                h = 240 + 60 * (r - g) / delta;
                            }
                            if (h < 0) {
                                h += 360;
                            }
                            if (h >= 360) {
                                h -= 360;
                            }
                        }

                        return new ColorHSLA(Color.constrainDegrees(h), Color.constrainPercentage(s * 100), Color.constrainPercentage(l * 100), a);
                    }
                }]);

                return ColorHSLA;
            }(Color);

            ColorRGBA.prototype.getHSLA = function () {
                return ColorHSLA.fromRGBA(this);
            };

            Fashion.apply(ColorHSLA.prototype, {
                type: 'hsla',
                $isFashionHSLA: true,
                h: null,
                s: null,
                l: null,
                a: 1
            });

            module.exports = ColorHSLA;
        }, { "../Base.js": 3, "./Color.js": 9, "./ColorRGBA.js": 11 }], 11: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Color = require('./Color.js');

            function hex2(v) {
                var s = v.toString(16);
                if (s.length < 2) {
                    s = '0' + s;
                }
                return s;
            }

            var ColorRGBA = function (_Color2) {
                _inherits(ColorRGBA, _Color2);

                function ColorRGBA(r, g, b, a) {
                    _classCallCheck(this, ColorRGBA);

                    var _this6 = _possibleConstructorReturn(this, (ColorRGBA.__proto__ || Object.getPrototypeOf(ColorRGBA)).call(this));

                    _this6.r = Math.min(0xff, Math.max(0, r));
                    _this6.g = Math.min(0xff, Math.max(0, g));
                    _this6.b = Math.min(0xff, Math.max(0, b));
                    if (a !== undefined) {
                        _this6.a = Math.min(1.0, Math.max(0.0, a));
                    }
                    return _this6;
                }

                _createClass(ColorRGBA, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.rgba(this);
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new ColorRGBA(this.r, this.g, this.b, this.a);
                    }
                }, {
                    key: "getHSLA",
                    value: function getHSLA() {
                        return null;
                    }
                }, {
                    key: "stringify",
                    value: function stringify() {
                        var me = this,
                            round = Math.round,
                            r = round(me.r),
                            g = round(me.g),
                            b = round(me.b),
                            a = me.a,
                            stringified = '';

                        // If there is no transparency we will use hex value
                        if (a === 1) {
                            stringified = '#' + hex2(r) + hex2(g) + hex2(b);
                        } else {
                            // Else use rgba
                            stringified = 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')';
                        }

                        stringified = stringified.toLowerCase();
                        return stringified;
                    }
                }, {
                    key: "getCompressedValue",
                    value: function getCompressedValue(lowerVal) {
                        var name = ColorRGBA.stringifiedMap[lowerVal],
                            shortName = ColorRGBA.shortFormMap[lowerVal];

                        if (name) {
                            lowerVal = lowerVal.length > name.length ? name : lowerVal;
                        }

                        if (ColorRGBA.useShortValues && shortName) {
                            lowerVal = lowerVal.length > shortName.length ? shortName : lowerVal;
                        }

                        return lowerVal;
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        if (!this.stringified) {
                            this.stringified = this.getCompressedValue(this.stringify());
                        }
                        return this.stringified;
                    }
                }, {
                    key: "toIeHexStr",
                    value: function toIeHexStr() {
                        var me = this,
                            round = Math.round,
                            r = round(me.r),
                            g = round(me.g),
                            b = round(me.b),
                            a = round(0xff * me.a);

                        return '#' + hex2(a) + hex2(r) + hex2(g) + hex2(b);
                    }
                }, {
                    key: "add",
                    value: function add(r, g, b, a) {
                        return new ColorRGBA(this.r + r, this.g + g, this.b + b, this.a * a);
                    }
                }, {
                    key: "subtract",
                    value: function subtract(r, g, b) {
                        return new ColorRGBA(this.r - r, this.g - g, this.b - b, this.a);
                    }
                }, {
                    key: "multiply",
                    value: function multiply(number) {
                        return new ColorRGBA(this.r * number, this.g * number, this.b * number, this.a);
                    }
                }, {
                    key: "divide",
                    value: function divide(number) {
                        return new ColorRGBA(this.r / number, this.g / number, this.b / number, this.a);
                    }
                }], [{
                    key: "fromHex",
                    value: function fromHex(value) {
                        if (value.charAt(0) == '#') {
                            value = value.substr(1);
                        }

                        var r, g, b;

                        if (value.length === 3) {
                            r = parseInt(value.charAt(0), 16);
                            g = parseInt(value.charAt(1), 16);
                            b = parseInt(value.charAt(2), 16);

                            r = (r << 4) + r;
                            g = (g << 4) + g;
                            b = (b << 4) + b;
                        } else {
                            r = parseInt(value.substring(0, 2), 16);
                            g = parseInt(value.substring(2, 4), 16);
                            b = parseInt(value.substring(4, 6), 16);
                        }

                        var result = new ColorRGBA(r, g, b);
                        if (ColorRGBA.preserveInputStrings) {
                            result.stringified = "#" + value;
                        }
                        return result;
                    }
                }, {
                    key: "fromHSLA",
                    value: function fromHSLA(color) {
                        if (color.$isFashionRGBA) {
                            return color.clone();
                        }

                        var hsla = color,
                            h = hsla.h / 360,
                            s = hsla.s / 100,
                            l = hsla.l / 100,
                            a = hsla.a;

                        var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s,
                            m1 = l * 2 - m2;

                        function hue(h) {
                            if (h < 0) ++h;
                            if (h > 1) --h;
                            if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
                            if (h * 2 < 1) return m2;
                            if (h * 3 < 2) return m1 + (m2 - m1) * (2 / 3 - h) * 6;
                            return m1;
                        }

                        var r = Color.constrainChannel(hue(h + 1 / 3) * 0xff),
                            g = Color.constrainChannel(hue(h) * 0xff),
                            b = Color.constrainChannel(hue(h - 1 / 3) * 0xff);

                        return new ColorRGBA(r, g, b, a);
                    }
                }]);

                return ColorRGBA;
            }(Color);

            Fashion.apply(ColorRGBA, {
                stringifiedMap: {
                    'rgba(0, 0, 0, 0)': 'transparent'
                },

                shortFormMap: {},

                useShortValues: true,
                preserveInputStrings: false
            });

            Fashion.apply(ColorRGBA.prototype, {
                type: 'rgba',
                $isFashionRGBA: true,
                r: null,
                g: null,
                b: null,
                a: 1,
                stringified: null,

                "+.number": function number(right) {
                    var value = right.value,
                        unit = right.unit;

                    switch (unit) {
                        case '%':
                            return this.getHSLA().adjustLightness(value).getRGBA();
                        case 'deg':
                            return this.getHSLA().adjustHue(value).getRGBA();
                        default:
                            return this.add(value, value, value, 1);
                    }
                },

                "+.rgba": function rgba(right) {
                    return this.add(right.r, right.g, right.b, right.a);
                },

                "+.hsla": function hsla(right) {
                    return this.getHSLA().add(right.h, right.s, right.l);
                },

                "-.number": function number(right) {
                    var value = right.value,
                        unit = right.unit;
                    switch (unit) {
                        case '%':
                            return this.getHSLA().adjustLightness(-value).getRGBA();
                        case 'deg':
                            return this.getHSLA().adjustHue(-value).getRGBA();
                        default:
                            return this.subtract(value, value, value);
                    }
                },

                "-.rgba": function rgba(right) {
                    return this.subtract(right.r, right.g, right.b);
                },

                "-.hsla": function hsla(right) {
                    return this.getHSLA().subtract(right.h, right.s, right.l);
                },

                "*.number": function number(right) {
                    return this.multiply(right.value);
                },

                "/.number": function number(right) {
                    return this.divide(right.value);
                },

                "*.rgba": function rgba(right) {
                    return new ColorRGBA(this.r * right.r, this.g * right.g, this.b * right.b, this.a * right.a);
                },

                "/.rgba": function rgba(right) {
                    return new ColorRGBA(Math.floor(this.r / right.r), Math.floor(this.g / right.g), Math.floor(this.b / right.b), Math.floor(this.a / right.a));
                }
            });

            module.exports = ColorRGBA;

            (function (ColorRGBA, stringifiedMap, colorMap, shortMap) {
                var colorChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],
                    names = Object.keys(colorMap),
                    i;

                names.sort();
                for (i = 0; i < names.length; i++) {
                    var name = names[i],
                        val = colorMap[name],
                        color = new ColorRGBA(val[0], val[1], val[2], val[3]),
                        str = color.stringify();

                    stringifiedMap[str] = name;
                }

                colorChars.forEach(function (short1) {
                    var long1 = short1 + short1;
                    colorChars.forEach(function (short2) {
                        var long2 = short2 + short2;
                        colorChars.forEach(function (short3) {
                            var long3 = short3 + short3,
                                shortName = '#' + short1 + short2 + short3,
                                longName = '#' + long1 + long2 + long3;

                            if (shortMap[longName]) {
                                var curr = shortMap[longName];
                                shortName = curr.length > shortName.length ? shortName : curr;
                                //if(curr.indexOf("#") === 0) {
                                //    short = (curr.length > short.length) ? short : curr;
                                //} else {
                                //    short = curr;
                                //}
                            }
                            shortMap[longName] = shortName;
                        });
                    });
                });
            })(ColorRGBA, ColorRGBA.stringifiedMap, Color.map, ColorRGBA.shortFormMap);
        }, { "../Base.js": 3, "./Color.js": 9 }], 12: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');
            var Numeric = require('./Numeric.js');

            var ColorStop = function (_Type3) {
                _inherits(ColorStop, _Type3);

                function ColorStop(color, stop) {
                    _classCallCheck(this, ColorStop);

                    var _this7 = _possibleConstructorReturn(this, (ColorStop.__proto__ || Object.getPrototypeOf(ColorStop)).call(this));

                    _this7.color = color;
                    _this7.stop = stop;
                    return _this7;
                }

                _createClass(ColorStop, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.colorstop(this);
                    }
                }, {
                    key: "descend",
                    value: function descend(visitor) {
                        visitor.visit(this.color);
                        visitor.visit(this.stop);
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        var string = this.color.toString(),
                            stop = this.stop;

                        if (stop) {
                            stop = stop.copy();
                            string += ' ';
                            if (!stop.unit) {
                                stop.value *= 100;
                                stop.unit = '%';
                            }
                            string += stop.toString();
                        }

                        return string;
                    }
                }, {
                    key: "toOriginalWebkitString",
                    value: function toOriginalWebkitString() {
                        var stop = this.stop;

                        if (!stop) {
                            stop = new Numeric(0, '%');
                        }

                        stop = stop.copy();
                        if (!stop.unit) {
                            stop.value *= 100;
                            stop.unit = '%';
                        }

                        return 'color-stop(' + stop.toString() + ', ' + this.color.toString() + ')';
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new ColorStop(this.color && this.color.clone(), this.stop && this.stop.clone());
                    }
                }]);

                return ColorStop;
            }(Type);

            Fashion.apply(ColorStop.prototype, {
                type: 'colorstop',
                $isFashionColorStop: true,
                $canUnbox: false,
                color: null,
                stop: null
            });

            module.exports = ColorStop;
        }, { "../Base.js": 3, "./Numeric.js": 18, "./Type.js": 24 }], 13: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');
            var List = require('./List.js');

            var FunctionCall = function (_Type4) {
                _inherits(FunctionCall, _Type4);

                function FunctionCall(name, args) {
                    _classCallCheck(this, FunctionCall);

                    var _this8 = _possibleConstructorReturn(this, (FunctionCall.__proto__ || Object.getPrototypeOf(FunctionCall)).call(this));

                    _this8.name = name;
                    if (Array.isArray(args)) {
                        args = new List(args);
                    }
                    _this8.args = args;
                    return _this8;
                }

                _createClass(FunctionCall, [{
                    key: "toString",
                    value: function toString() {
                        var args = this.args,
                            argsStr;
                        if (Array.isArray(args)) {
                            argsStr = args.join(', ');
                        } else {
                            argsStr = args.toString();
                        }
                        return this.name + "(" + argsStr + ')';
                    }
                }, {
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.functioncall(this);
                    }
                }, {
                    key: "descend",
                    value: function descend(visitor) {
                        this.args && visitor.visit(this.args);
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new FunctionCall(this.name, this.args && this.args.copy());
                    }
                }]);

                return FunctionCall;
            }(Type);

            Fashion.apply(FunctionCall.prototype, {
                type: 'functioncall',
                $isFashionFunctionCall: true,
                $canUnbox: false,
                name: null,
                args: null
            });

            module.exports = FunctionCall;
        }, { "../Base.js": 3, "./List.js": 15, "./Type.js": 24 }], 14: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');

            var LinearGradient = function (_Type5) {
                _inherits(LinearGradient, _Type5);

                function LinearGradient(position, stops) {
                    _classCallCheck(this, LinearGradient);

                    var _this9 = _possibleConstructorReturn(this, (LinearGradient.__proto__ || Object.getPrototypeOf(LinearGradient)).call(this));

                    _this9.position = position;
                    _this9.stops = stops;
                    return _this9;
                }

                _createClass(LinearGradient, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.lineargradient(this);
                    }
                }, {
                    key: "descend",
                    value: function descend(visitor) {
                        visitor.visit(this.position);
                        visitor.visit(this.stops);
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new LinearGradient(this.position && this.position.clone(), this.stops && this.stops.clone());
                    }
                }, {
                    key: "gradientPoints",
                    value: function gradientPoints(position) {}
                }, {
                    key: "operate",
                    value: function operate(operation, right) {
                        switch (operation) {
                            case "!=":
                                if (right.type == 'literal' && (right.value == 'null' || right.value == 'none')) {
                                    return true;
                                }
                            case "==":
                                if (right.type == 'literal' && (right.value == 'null' || right.value == 'none')) {
                                    return false;
                                }
                        }
                        return _get(LinearGradient.prototype.__proto__ || Object.getPrototypeOf(LinearGradient.prototype), "operate", this).call(this, operation, right);
                    }
                }, {
                    key: "supports",
                    value: function supports(prefix) {
                        return !!this.vendorPrefixes[prefix.toLowerCase()];
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        var string = 'linear-gradient(';
                        if (this.position) {
                            string += this.position + ', ';
                        }
                        return string + this.stops + ')';
                    }
                }, {
                    key: "toOriginalWebkitString",
                    value: function toOriginalWebkitString() {
                        // args = []
                        // args << grad_point(position_or_angle || Sass::Script::String.new("top"))
                        // args << linear_end_position(position_or_angle, color_stops)
                        // args << grad_color_stops(color_stops)
                        // args.each{|a| a.options = options}
                        // Sass::Script::String.new("-webkit-gradient(linear, #{args.join(', ')})")
                        //this.gradientPoints(this.position);
                        var args = [],
                            stops = this.stops.items,
                            ln = stops.length,
                            i;

                        args.push('top');
                        args.push('bottom');

                        for (i = 0; i < ln; i++) {
                            args.push(stops[i].toOriginalWebkitString());
                        }

                        return '-webkit-gradient(linear, ' + args.join(', ') + ')';
                    }
                }, {
                    key: "toPrefixedString",
                    value: function toPrefixedString(prefix) {
                        if (prefix === 'owg') {
                            return this.toOriginalWebkitString();
                        }
                        return prefix + this.toString();
                    }
                }]);

                return LinearGradient;
            }(Type);

            Fashion.apply(LinearGradient.prototype, {
                type: 'lineargradient',
                $isFashionLinearGradient: true,
                $canUnbox: false,
                position: null,
                stops: null,
                vendorPrefixes: {
                    webkit: true,
                    moz: true,
                    svg: true,
                    pie: true,
                    css2: true,
                    o: true,
                    owg: true
                }
            });

            module.exports = LinearGradient;
        }, { "../Base.js": 3, "./Type.js": 24 }], 15: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');

            var List = function (_Type6) {
                _inherits(List, _Type6);

                function List(items, separator) {
                    _classCallCheck(this, List);

                    var _this10 = _possibleConstructorReturn(this, (List.__proto__ || Object.getPrototypeOf(List)).call(this));

                    _this10.items = items || [];
                    _this10.separator = typeof separator === 'undefined' ? ' ' : separator;
                    return _this10;
                }

                _createClass(List, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.list(this);
                    }
                }, {
                    key: "descend",
                    value: function descend(visitor) {
                        for (var i = 0; i < this.items.length; i++) {
                            visitor.visit(this.items[i]);
                        }
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        var items = this.items,
                            len = items.length,
                            newItems = [];
                        for (var i = 0; i < len; i++) {
                            newItems.push(items[i].clone());
                        }
                        return new List(newItems, this.separator);
                    }
                }, {
                    key: "clone",
                    value: function clone(match, replace) {
                        if (replace && this.matches(match)) {
                            return replace.clone();
                        }
                        var items = this.items,
                            len = items.length,
                            newItems = [];

                        for (var i = 0; i < len; i++) {
                            var item = items[i];
                            if (item) {
                                newItems.push(item.clone(match, replace));
                            } else {
                                newItems.push(item);
                            }
                        }

                        var copy = new List(newItems, this.separator);
                        copy.$referenceName = this.$referenceName;
                        copy.$referenceBase = this.$referenceBase;
                        copy.$previousReference = this.$previousReference;
                        return copy;
                    }
                }, {
                    key: "add",
                    value: function add(item) {
                        return this.items.push(item);
                    }
                }, {
                    key: "get",
                    value: function get(index) {
                        return this.items[index - 1] || null;
                    }
                }, {
                    key: "operate",
                    value: function operate(operation, right) {
                        switch (operation) {
                            case '!=':
                                if (right.$isFashionLiteral) {
                                    if (right.value === 'null' || right.value === 'none') {
                                        return true;
                                    }
                                }
                                break;

                            case '==':
                                if (right.$isFashionLiteral) {
                                    if (right.value === 'null' || right.value === 'none') {
                                        return false;
                                    }
                                }
                                break;
                        }

                        return _get(List.prototype.__proto__ || Object.getPrototypeOf(List.prototype), "operate", this).call(this, operation, right);
                    }
                }, {
                    key: "supports",
                    value: function supports(prefix) {
                        for (var i = 0; i < this.items.length; i++) {
                            var item = this.items[i];

                            if (item.supports(prefix)) {
                                return true;
                            }
                        }

                        return false;
                    }
                }, {
                    key: "toBoolean",
                    value: function toBoolean() {
                        return !!this.items.length;
                    }
                }, {
                    key: "getItems",
                    value: function getItems() {
                        return this.items;
                        // return Fashion.filter(this.items, (item) => {
                        //     var unboxed = Type.unbox(item);
                        //     return unboxed !== null && unboxed !== undefined;
                        // });
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        return this.items.join(this.separator);
                    }
                }, {
                    key: "unquote",
                    value: function unquote() {
                        var items = [],
                            item;
                        for (var i = 0; i < this.items.length; i++) {
                            item = this.items[i];
                            if (item) {
                                items.push(item.unquote());
                            } else {
                                items.push(item);
                            }
                        }
                        return new List(items, this.separator);
                    }
                }, {
                    key: "toPrefixedString",
                    value: function toPrefixedString(prefix) {
                        var items = [];
                        for (var i = 0; i < this.items.length; i++) {
                            var item = this.items[i];
                            if (item) {
                                items.push(item.toPrefixedString(prefix));
                            }
                        }
                        return items.join(this.separator);
                    }

                    //----------------------------------------------------------------------
                    // Operations

                }, {
                    key: '==.list',
                    value: function list(right) {
                        var equals = this.separator == right.separator && this.items.length == right.items.length;

                        for (var i = 0; equals && i < this.items.length; ++i) {
                            equals = this.items[i].operate("==", right.items[i]);
                        }

                        return equals;
                    }
                }]);

                return List;
            }(Type);

            Fashion.apply(List.prototype, {
                type: 'list',
                $isFashionList: true,
                items: null,
                separator: null
            });

            module.exports = List;
        }, { "../Base.js": 3, "./Type.js": 24 }], 16: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');
            var Numeric = require('./Numeric.js');

            var Literal = function (_Type7) {
                _inherits(Literal, _Type7);

                function Literal(value) {
                    _classCallCheck(this, Literal);

                    var _this11 = _possibleConstructorReturn(this, (Literal.__proto__ || Object.getPrototypeOf(Literal)).call(this));

                    _this11.value = value;
                    return _this11;
                }

                _createClass(Literal, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.literal(this);
                    }
                }, {
                    key: "_getHash",
                    value: function _getHash() {
                        return this.value;
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        return this.value || '';
                    }
                }, {
                    key: "toBoolean",
                    value: function toBoolean() {
                        return this.value.length;
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new Literal(this.value);
                    }
                }, {
                    key: '+',
                    value: function _(right) {
                        return new Literal(this.value + right.getHash());
                    }
                }, {
                    key: '+.number',
                    value: function number(right) {
                        if (this.value === null) {
                            return right;
                        }
                        return new Literal(this.value + right.toString());
                    }
                }, {
                    key: '/',
                    value: function _(right) {
                        return new Literal(this.value + '/' + right.getHash());
                    }
                }, {
                    key: '-',
                    value: function _(right) {
                        return new Literal(this.value + '-' + right.getHash());
                    }
                }, {
                    key: '%',
                    value: function _(right) {
                        return new Literal(this.value + '%' + right.getHash());
                    }
                }, {
                    key: "normalizeStart",
                    value: function normalizeStart(startVal) {
                        var start = Type.unbox(startVal) || 0;
                        if (start > 0) {
                            start = start - 1;
                        }

                        if (start < 0) {
                            start = this.value.length + start;
                        }

                        if (start < 0) {
                            start = 0;
                        }

                        return start;
                    }
                }, {
                    key: "normalizeEnd",
                    value: function normalizeEnd(endVal) {
                        var end = Type.unbox(endVal) || -1;
                        if (end > 0) {
                            end = end - 1;
                        }
                        if (end < 0) {
                            end = this.value.length + end;
                        }

                        if (end < 0) {
                            end = 0;
                        }

                        if (end > 0) {
                            end = end + 1;
                        }
                        return end;
                    }
                }, {
                    key: "slice",
                    value: function slice(start, end) {
                        start = this.normalizeStart(start);
                        end = this.normalizeEnd(end);
                        return new Literal(this.value.slice(start, end));
                    }
                }, {
                    key: "toUpperCase",
                    value: function toUpperCase() {
                        return new Literal(this.value.toUpperCase());
                    }
                }, {
                    key: "toLowerCase",
                    value: function toLowerCase() {
                        return new Literal(this.value.toLowerCase());
                    }
                }, {
                    key: "indexOf",
                    value: function indexOf(str) {
                        var idx = this.value.indexOf(str.value);
                        if (idx === -1) {
                            return undefined;
                        }
                        return new Numeric(idx + 1);
                    }
                }, {
                    key: "insert",
                    value: function insert(str, startVal) {
                        var start = Type.unbox(startVal) || 0,
                            inserted = this.value;

                        if (start > 0) {
                            start = Math.min(start - 1, inserted.length);
                        }
                        if (start < 0) {
                            start = inserted.length + start + 1;
                            start = Math.max(start, 0);
                        }

                        inserted = inserted.substring(0, start) + str.value + inserted.substring(start);
                        return new Literal(Literal.deEscape(inserted));
                    }
                }, {
                    key: "toDisplayString",
                    value: function toDisplayString() {
                        var val = this.value;
                        if (val === null) {
                            return "null";
                        }
                        return this.toString();
                    }
                }], [{
                    key: "tryCoerce",
                    value: function tryCoerce(obj) {
                        if (obj.$isFashionNumber) {
                            return undefined;
                        }
                        if (obj.$isFashionString) {
                            return new Literal(obj.value);
                        }
                        if (obj.$isFashionLiteral) {
                            return obj;
                        }
                        return new Literal(obj.getHash());
                    }
                }, {
                    key: "deEscape",
                    value: function deEscape(str) {
                        var buff = '',
                            i,
                            ch;
                        for (i = 0; i < str.length; i++) {
                            ch = str.charAt(i);
                            if (ch === '\\') {
                                i++;
                                ch = str.charAt(i);
                            }
                            buff += ch;
                        }
                        return buff;
                    }
                }]);

                return Literal;
            }(Type);

            Fashion.apply(Literal.prototype, {
                type: 'literal',
                $isFashionLiteral: true,
                value: null
            });

            var FashionNull = function (_Literal) {
                _inherits(FashionNull, _Literal);

                function FashionNull(value) {
                    _classCallCheck(this, FashionNull);

                    return _possibleConstructorReturn(this, (FashionNull.__proto__ || Object.getPrototypeOf(FashionNull)).call(this, value || null));
                }

                _createClass(FashionNull, [{
                    key: "copy",
                    value: function copy() {
                        return new FashionNull(this.value);
                    }
                }]);

                return FashionNull;
            }(Literal);

            Fashion.apply(FashionNull.prototype, {
                $isFashionNull: true,
                $constant: true
            });

            FashionNull.prototype.$isFashionNull = true;

            Literal.Null = new FashionNull(null);
            Literal.None = new Literal('none');

            module.exports = Literal;
        }, { "../Base.js": 3, "./Numeric.js": 18, "./Type.js": 24 }], 17: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var List = require('./List.js');
            var Type = require('./Type.js');
            var Literal = require('./Literal.js'),
                Null = Literal.Null;

            var Numeric = require('./Numeric.js');

            var Map = function (_List) {
                _inherits(Map, _List);

                function Map(pairs) {
                    _classCallCheck(this, Map);

                    var _this13 = _possibleConstructorReturn(this, (Map.__proto__ || Object.getPrototypeOf(Map)).call(this, pairs));

                    _this13.map = {};
                    if (pairs) {
                        for (var i = 0; i < pairs.length - 1; i += 2) {
                            var key = _this13.toKey(pairs[i]),
                                value = pairs[i + 1];
                            _this13.map[key] = i + 1;
                        }
                    }
                    return _this13;
                }

                _createClass(Map, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.map(this);
                    }
                }, {
                    key: "descend",
                    value: function descend(visitor) {
                        for (var i = 0; i < this.items.length; i++) {
                            visitor.visit(this.items[i]);
                        }
                    }
                }, {
                    key: "get",
                    value: function get(key) {
                        if (key instanceof Numeric) {
                            key = Type.unbox(key);
                        }

                        if (typeof key === 'number') {
                            return new List([this.items[2 * key - 2], this.items[2 * key - 1]], ' ');
                        }

                        key = this.toKey(key);
                        return this.items[this.map[key]] || Null;
                    }
                }, {
                    key: "getItems",
                    value: function getItems() {
                        var values = [];
                        for (var i = 0; i < this.items.length - 1; i += 2) {
                            var key = this.toKey(this.items[i]);
                            values.push(this.map[key]);
                        }
                        return values;
                    }
                }, {
                    key: "put",
                    value: function put(key, value) {
                        var keyStr = this.toKey(key);
                        if (!this.map.hasOwnProperty(keyStr)) {
                            this.items.push(key, value);
                            this.map[keyStr] = this.items.length - 1;
                        } else {
                            this.items[this.map[keyStr]] = value;
                        }
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        var str = '',
                            count = 0;
                        for (var i = 0; i < this.items.length - 1; i += 2) {
                            var key = this.toKey(this.items[i]),
                                value = this.map[key];
                            if (value) {
                                if (count > 0) {
                                    str += ', ';
                                }
                                str += key + ": " + value.toString();
                                count++;
                            }
                        }
                        return str;
                    }
                }, {
                    key: "toKey",
                    value: function toKey(key) {
                        return this.unquoteKey(key).toString();
                    }
                }, {
                    key: "unquoteKey",
                    value: function unquoteKey(string) {
                        if (string.$isFashionType) {
                            return string.unquote();
                        }
                        return string;
                    }
                }, {
                    key: "remove",
                    value: function remove(key) {
                        key = this.toKey(key);
                        if (this.map[key]) {
                            var idx = this.map[key];
                            delete this.items[idx - 1];
                            delete this.items[idx];
                            delete this.map[key];
                        }
                    }
                }, {
                    key: "getKeys",
                    value: function getKeys() {
                        var keys = [];
                        for (var i = 0; i < this.items.length; i += 2) {
                            var k = this.items[i];
                            if (k) {
                                keys.push(k);
                            }
                        }
                        return keys;
                    }
                }, {
                    key: "getValues",
                    value: function getValues() {
                        var values = [];
                        for (var i = 1; i < this.items.length; i += 2) {
                            var v = this.items[i];
                            if (v) {
                                values.push(v);
                            }
                        }
                        return values;
                    }
                }, {
                    key: "hasKey",
                    value: function hasKey(key) {
                        key = this.toKey(key);
                        if (this.map.hasOwnProperty(key)) {
                            return true;
                        }
                        return false;
                    }
                }]);

                return Map;
            }(List);

            Fashion.apply(Map.prototype, {
                type: "map",
                $isFashionMap: true,
                $canUnbox: false,
                map: null
            });

            module.exports = Map;
        }, { "../Base.js": 3, "./List.js": 15, "./Literal.js": 16, "./Numeric.js": 18, "./Type.js": 24 }], 18: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');
            var Bool = require('./Bool.js');
            var Literal = require('./Literal.js');

            var Numeric = function (_Type8) {
                _inherits(Numeric, _Type8);

                function Numeric(value, unit, numeratorUnits, denominatorUnits) {
                    _classCallCheck(this, Numeric);

                    var _this14 = _possibleConstructorReturn(this, (Numeric.__proto__ || Object.getPrototypeOf(Numeric)).call(this));

                    _this14.value = value;
                    _this14.unit = unit;
                    if (unit && !numeratorUnits) {
                        _this14.numeratorUnits = [unit];
                    } else {
                        _this14.numeratorUnits = numeratorUnits || [];
                    }
                    _this14.denominatorUnits = denominatorUnits || [];
                    return _this14;
                }

                _createClass(Numeric, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.number(this);
                    }
                }, {
                    key: "unitless",
                    value: function unitless() {
                        if (this.numeratorUnits && this.numeratorUnits.length) {
                            return false;
                        }

                        if (this.denominatorUnits && this.denominatorUnits.length) {
                            return false;
                        }

                        return true;
                    }
                }, {
                    key: "getUnitStr",
                    value: function getUnitStr() {
                        this.normalizeUnits();
                        var unitStr = this.numeratorUnits.join('*');
                        if (this.denominatorUnits.length) {
                            unitStr += '/' + this.denominatorUnits.join('*');
                        }
                        return unitStr;
                    }
                }, {
                    key: "_getHash",
                    value: function _getHash() {
                        return this.value;
                    }
                }, {
                    key: "stringify",
                    value: function stringify() {
                        this.normalizeUnits();

                        var value = this.value,
                            valStr;

                        // prevent 0.020000000000000004 type numbers in output
                        valStr = Math.round(value * 100000) / 100000 + '';
                        //unitStr = valStr === '0' ? '' : this.getUnitStr();
                        return valStr + this.getUnitStr();
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        return this.stringify();
                    }
                }, {
                    key: "toBoolean",
                    value: function toBoolean() {
                        return this.unit ? true : !!this.value;
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new Numeric(this.value, this.unit);
                    }
                }, {
                    key: '-.literal',
                    value: function literal(right) {
                        if (this.value === 0 && this.unitless()) {
                            return new Literal(['-', right.toString()].join(''));
                        }
                        return new Literal([this.toString(), '-', right.toString()].join(''));
                    }
                }, {
                    key: '-.string',
                    value: function string(right) {
                        if (this.value === 0 && this.unitless()) {
                            return new Literal(['-', right.toString()].join(''));
                        }
                        return new Literal([this.toString(), '-', right.toString()].join(''));
                    }
                }, {
                    key: '-.number',
                    value: function number(right) {
                        var value = right.value;

                        if (right.unit == '%' && right.unit !== this.unit) {
                            value = this.value * (right.value / 100);
                        }

                        return new Numeric(this.value - value, this.unit || right.unit);
                    }
                }, {
                    key: '+.literal',
                    value: function literal(right) {
                        if (right.$isFashionString) {
                            return new Literal([this.toString(), right.value].join(''));
                        }

                        return new Literal([this.toString(), right.toString()].join(''));
                    }
                }, {
                    key: '+.number',
                    value: function number(right) {
                        var value = right.value;

                        if (right.unit == '%' && right.unit !== this.unit) {
                            value = this.value * (right.value / 100);
                        }

                        return new Numeric(this.value + value, this.unit || right.unit);
                    }
                }, {
                    key: '/',
                    value: function _(right) {
                        return new Numeric(this.value / right.value, this.unit == right.unit ? null : this.unit || right.unit);
                    }
                }, {
                    key: '*',
                    value: function _(right) {
                        return new Numeric(this.value * right.value, this.unit || right.unit);
                    }
                }, {
                    key: '%',
                    value: function _(right) {
                        return new Numeric(this.value % right.value, this.unit || right.unit);
                    }
                }, {
                    key: '**',
                    value: function _(right) {
                        return new Numeric(Math.pow(this.value, right.value), this.unit || right.unit);
                    }
                }, {
                    key: "operate",
                    value: function operate(operation, right) {
                        var unit = this.unit || right.unit,
                            normalized;

                        if (right.$isFashionRGBA || right.$isFashionHSLA) {
                            return new Literal(this + operation + right);
                        }

                        if (right.$isFashionNumber) {
                            return this.numericOperate(operation, right);
                        } else if (right.$isFashionLiteral) {
                            normalized = this.tryCoerce(right);

                            if (normalized) {
                                return this.performOperation(operation, normalized);
                            }
                        }

                        return _get(Numeric.prototype.__proto__ || Object.getPrototypeOf(Numeric.prototype), "operate", this).call(this, operation, right);
                    }
                }, {
                    key: "tryNormalize",
                    value: function tryNormalize(other) {
                        var value = other.value,
                            unit = other.unit;

                        if (other.$isFashionNumber) {
                            switch (this.unit) {
                                case 'mm':
                                    switch (unit) {
                                        case 'in':
                                            return new Numeric(value * 25.4, 'mm');
                                        case 'cm':
                                            return new Numeric(value * 2.54, 'mm');
                                    }
                                    break;

                                case 'cm':
                                    switch (unit) {
                                        case 'in':
                                            return new Numeric(value * 2.54, 'cm');
                                        case 'mm':
                                            return new Numeric(value / 10, 'cm');
                                    }
                                    break;

                                case 'in':
                                    switch (unit) {
                                        case 'mm':
                                            return new Numeric(value / 25.4, 'in');
                                        case 'cm':
                                            return new Numeric(value / 2.54, 'in');
                                    }
                                    break;

                                case 'ms':
                                    switch (unit) {
                                        case 's':
                                            return new Numeric(value * 1000, 'ms');
                                    }
                                    break;

                                case 's':
                                    switch (unit) {
                                        case 'ms':
                                            return new Numeric(value / 1000, 's');
                                    }
                                    break;

                                case 'Hz':
                                    switch (unit) {
                                        case 'kHz':
                                            return new Numeric(value * 1000, 'Hz');
                                    }
                                    break;

                                case 'kHz':
                                    switch (unit) {
                                        case 'Hz':
                                            return new Numeric(value / 1000, 'kHz');
                                    }
                                    break;
                                case '%':
                                    switch (unit) {
                                        default:
                                            return new Numeric(value);
                                    }
                                default:
                                    break;
                            }
                        }

                        return undefined;
                    }
                }, {
                    key: "normalize",
                    value: function normalize(other) {
                        var norm = this.tryNormalize(other);

                        if (norm === undefined) {
                            raise('Could not normalize ' + this + ' with ' + other);
                        }

                        return norm;
                    }
                }, {
                    key: "comparable",
                    value: function comparable(other) {
                        var unit1 = this.unit,
                            unit2 = other.unit;

                        if (!other.$isFashionNumber) {
                            return false;
                        }

                        return unit1 === unit2 || unit1 === 'mm' && (unit2 === 'in' || unit2 === 'cm') || unit1 === 'cm' && (unit2 === 'in' || unit2 === 'mm') || unit1 === 'in' && (unit2 === 'mm' || unit2 === 'cm') || unit1 === 'ms' && unit2 === 's' || unit1 === 's' && unit2 === 'ms' || unit1 === 'Hz' && unit2 === 'kHz' || unit1 === 'kHz' && unit2 === 'Hz';
                    }

                    //---------------------------------------------------------------

                }, {
                    key: "normalizeUnits",
                    value: function normalizeUnits() {
                        if (this.normalized) {
                            return;
                        }

                        this.normalized = true;

                        if (!this.unitless()) {
                            var clean = this.removeCommonUnits(this.numeratorUnits, this.denominatorUnits),
                                converted;

                            //var num = [],
                            //    den = [];
                            //
                            //for(var d = 0; d < clean.den.length; d++) {
                            //    var dn = clean.den[d];
                            //    if(this.convertable(dn)) {
                            //        converted = false;
                            //        for (var n = 0; n < clean.num.length; n++) {
                            //            var nm = clean.num[n];
                            //            if(this.convertable(nm)) {
                            //                this.value = this.value / this.conversionFactor(dn, nm);
                            //                converted = true;
                            //            } else {
                            //                num.push(nm);
                            //            }
                            //        }
                            //        if(!converted) {
                            //            den.push(dn);
                            //        }
                            //    }
                            //}
                            //
                            //this.numeratorUnits = num;
                            //this.denominatorUnits = den;

                            clean.num = Fashion.filter(clean.num, function (val) {
                                return !!val;
                            });
                            clean.den = Fashion.filter(clean.den, function (val) {
                                return !!val;
                            });
                            this.numeratorUnits = clean.num;
                            this.denominatorUnits = clean.den;
                        }
                    }
                }, {
                    key: "numericOperate",
                    value: function numericOperate(operation, right) {
                        this.normalizeUnits();
                        right.normalizeUnits();

                        var me = this,
                            other = right,
                            ops = Numeric.OPERATIONS,
                            moreOps = Numeric.NON_COERCE_OPERATIONS,
                            op = ops[operation],
                            result;

                        if (op) {
                            try {
                                if (me.unitless()) {
                                    me = me.coerceUnits(other.numeratorUnits, other.denominatorUnits);
                                } else {
                                    other = other.coerceUnits(me.numeratorUnits, me.denominatorUnits);
                                }
                            } catch (e) {
                                if (operation == '==') {
                                    return Bool.False;
                                }
                                if (operation == '!=') {
                                    return Bool.True;
                                }
                                throw e;
                            }
                        } else {
                            op = moreOps[operation];
                        }

                        if (op) {
                            result = op(me.value, other.value);
                        }

                        if (typeof result === 'number') {
                            var units = this.computeUnits(me, other, operation);
                            return new Numeric(result, units.num.length ? units.num[0] : null, units.num, units.den);
                        }

                        return new Bool(result);
                    }
                }, {
                    key: "computeUnits",
                    value: function computeUnits(left, right, op) {
                        switch (op) {
                            case '*':
                                return {
                                    num: left.numeratorUnits.slice().concat(right.numeratorUnits),
                                    den: left.denominatorUnits.slice().concat(right.denominatorUnits)
                                };
                            case '/':
                                return {
                                    num: left.numeratorUnits.slice().concat(right.denominatorUnits),
                                    den: left.denominatorUnits.slice().concat(right.numeratorUnits)
                                };
                            default:
                                return {
                                    num: left.numeratorUnits,
                                    den: left.denominatorUnits
                                };
                        }
                    }
                }, {
                    key: "coerceUnits",
                    value: function coerceUnits(units, denominatorUnits) {
                        var value = this.value;
                        if (!this.unitless()) {
                            value = value * this.coercionFactor(this.numeratorUnits, units) / this.coercionFactor(this.denominatorUnits, denominatorUnits);
                        }
                        return new Numeric(value, units && units[0], units, denominatorUnits);
                    }
                }, {
                    key: "coercionFactor",
                    value: function coercionFactor(units, otherUnits) {
                        var res = this.removeCommonUnits(units, otherUnits),
                            fromUnits = res.num,
                            toUnits = res.den;

                        if (fromUnits.length !== toUnits.length || !this.convertable(fromUnits || toUnits)) {
                            Fashion.raise('Incompatible units: ' + fromUnits.join('*') + ' and ' + toUnits.join('*'));
                        }

                        for (var i = 0; i < fromUnits.length; i++) {
                            var fromUnit = fromUnits[i];
                            for (var j = 0; j < toUnits.length; j++) {
                                var toUnit = toUnits[j],
                                    factor = this.conversionFactor(fromUnit, toUnit);

                                if (factor !== null) {
                                    return factor;
                                }
                            }
                        }

                        return 1;
                    }
                }, {
                    key: "conversionFactor",
                    value: function conversionFactor(fromUnit, toUnit) {
                        var cUnits = Numeric.CONVERTABLE_UNITS,
                            cTable = Numeric.CONVERSION_TABLE,
                            factor = null;

                        if (cUnits[fromUnit]) {
                            if (cUnits[toUnit]) {
                                factor = cTable[cUnits[fromUnit]][cUnits[toUnit]];
                            }
                        }

                        if (factor === null && cUnits[toUnit]) {
                            if (cUnits[fromUnit]) {
                                factor = 1.0 / cTable[cUnits[toUnit]][cUnits[fromUnit]];
                            }
                        }

                        return factor;
                    }
                }, {
                    key: "convertable",
                    value: function convertable(units) {
                        if (units && !Array.isArray(units)) {
                            units = [units];
                        }

                        if (units && units.length) {
                            var convertableUnits = Numeric.CONVERTABLE_UNITS;
                            for (var i = 0; i < units.length; i++) {
                                if (convertableUnits[units[i]] === undefined) {
                                    return false;
                                }
                            }
                        }
                        return true;
                    }
                }, {
                    key: "removeCommonUnits",
                    value: function removeCommonUnits(numUnits, denUnits) {
                        var map = {},
                            num = [],
                            den = [],
                            i,
                            unit,
                            unit;

                        for (i = 0; i < numUnits.length; i++) {
                            unit = numUnits[i];
                            map[unit] = (map[unit] || 0) + 1;
                        }

                        for (i = 0; i < denUnits.length; i++) {
                            unit = denUnits[i];
                            map[unit] = (map[unit] || 0) - 1;
                        }

                        for (i = 0; i < numUnits.length; i++) {
                            unit = numUnits[i];
                            if (map[unit] > 0) {
                                num.push(unit);
                                map[unit]--;
                            }
                        }

                        for (i = 0; i < denUnits.length; i++) {
                            unit = denUnits[i];
                            if (map[unit] < 0) {
                                den.push(unit);
                                map[unit]++;
                            }
                        }

                        return {
                            num: num,
                            den: den
                        };
                    }
                }], [{
                    key: "tryGetNumber",
                    value: function tryGetNumber(value) {
                        if (/^\d*$/.test(value)) {
                            value = parseFloat(value);
                        }

                        if (!isNaN(value)) {
                            return new Numeric(value);
                        }

                        return undefined;
                    }
                }, {
                    key: "tryCoerce",
                    value: function tryCoerce(obj) {
                        if (obj.$isFashionNumber) {
                            return obj;
                        }

                        if (obj.$isFashionLiteral) {
                            return this.tryGetNumber(obj.value);
                        }

                        return undefined;
                    }
                }]);

                return Numeric;
            }(Type);

            Fashion.apply(Numeric, {
                OPERATIONS: {
                    '!=': function _(l, r) {
                        return l != r;
                    },
                    '+': function _(l, r) {
                        return l + r;
                    },
                    '-': function _(l, r) {
                        return l - r;
                    },
                    '<=': function _(l, r) {
                        return l <= r;
                    },
                    '<': function _(l, r) {
                        return l < r;
                    },
                    '>': function _(l, r) {
                        return l > r;
                    },
                    '>=': function _(l, r) {
                        return l >= r;
                    },
                    '==': function _(l, r) {
                        return l == r;
                    },
                    '%': function _(l, r) {
                        return Math.abs(l % r);
                    }
                },

                NON_COERCE_OPERATIONS: {
                    '*': function _(l, r) {
                        return l * r;
                    },
                    '**': function _(l, r) {
                        return Math.pow(l, r);
                    },
                    '/': function _(l, r) {
                        return l / r;
                    }
                },

                CONVERTABLE_UNITS: {
                    'in': 0,
                    'cm': 1,
                    'pc': 2,
                    'mm': 3,
                    'pt': 4,
                    'px': 5
                },

                CONVERSION_TABLE: [[1, 2.54, 6, 25.4, 72, 96], // in
                [null, 1, 2.36220473, 10, 28.3464567, 37.795276], // cm
                [null, null, 1, 4.23333333, 12, 16], // pc
                [null, null, null, 1, 2.83464567, 3.7795276], // mm
                [null, null, null, null, 1, 1.3333333], // pt
                [null, null, null, null, null, 1] // px
                ]
            });

            Fashion.apply(Numeric.prototype, {
                type: 'number',
                $isFashionNumber: true,
                value: undefined,
                unit: undefined,

                numeratorUnits: undefined,
                denominatorUnits: undefined,
                normalized: false
            });

            module.exports = Numeric;
        }, { "../Base.js": 3, "./Bool.js": 8, "./Literal.js": 16, "./Type.js": 24 }], 19: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');

            var ParentheticalExpression = function (_Type9) {
                _inherits(ParentheticalExpression, _Type9);

                function ParentheticalExpression(value) {
                    _classCallCheck(this, ParentheticalExpression);

                    var _this15 = _possibleConstructorReturn(this, (ParentheticalExpression.__proto__ || Object.getPrototypeOf(ParentheticalExpression)).call(this));

                    _this15.value = value;
                    return _this15;
                }

                _createClass(ParentheticalExpression, [{
                    key: "toString",
                    value: function toString() {
                        return '(' + (this.value && this.value.toString()) + ')';
                    }
                }, {
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.parenthetical(this);
                    }
                }]);

                return ParentheticalExpression;
            }(Type);

            Fashion.apply(ParentheticalExpression.prototype, {
                value: null,
                type: 'parenthetical'
            });

            module.exports = ParentheticalExpression;
        }, { "../Base.js": 3, "./Type.js": 24 }], 20: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');

            var RadialGradient = function (_Type10) {
                _inherits(RadialGradient, _Type10);

                function RadialGradient(position, shape, stops) {
                    _classCallCheck(this, RadialGradient);

                    var _this16 = _possibleConstructorReturn(this, (RadialGradient.__proto__ || Object.getPrototypeOf(RadialGradient)).call(this));

                    _this16.position = position;
                    _this16.stops = stops;
                    _this16.shape = shape;
                    return _this16;
                }

                _createClass(RadialGradient, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.radialgradient(this);
                    }
                }, {
                    key: "descend",
                    value: function descend(visitor) {
                        visitor.visit(this.position);
                        visitor.visit(this.stops);
                        visitor.visit(this.shape);
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new RadialGradient(this.position, this.shape, this.stops);
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        var string = 'radial-gradient(';

                        if (this.position) {
                            string += this.position + ', ';
                        }

                        if (this.shape) {
                            string += this.shape + ', ';
                        }

                        return string + this.stops + ')';
                    }
                }, {
                    key: "toOriginalWebkitString",
                    value: function toOriginalWebkitString() {
                        var args = [],
                            stops = this.stops.items,
                            ln = stops.length,
                            i;

                        args.push('center 0%');
                        args.push('center 100%');

                        for (i = 0; i < ln; i++) {
                            args.push(stops[i].toOriginalWebkitString());
                        }

                        return '-webkit-gradient(radial, ' + args.join(', ') + ')';
                    }
                }, {
                    key: "supports",
                    value: function supports(prefix) {
                        return ['owg', 'webkit'].indexOf(prefix.toLowerCase()) !== -1;
                    }
                }, {
                    key: "toPrefixedString",
                    value: function toPrefixedString(prefix) {
                        if (prefix === 'owg') {
                            return this.toOriginalWebkitString();
                        }
                        return prefix + this.toString();
                    }
                }, {
                    key: "gradientPoints",
                    value: function gradientPoints(position) {
                        //position = (position.type === 'list') ? position.clone() : new Fashion.List([position]);
                        //console.log('gradientpoints', position);
                    }
                }]);

                return RadialGradient;
            }(Type);

            Fashion.apply(RadialGradient.prototype, {
                type: 'radialgradient',
                $isFashionRadialGradient: true,
                $canUnbox: false,
                position: null,
                stops: null,
                shape: null
            });

            module.exports = RadialGradient;
        }, { "../Base.js": 3, "./Type.js": 24 }], 21: [function (require, module, exports) {
            "use strict";

            var Fashion = require('../Base.js');
            var TypeVisitor = require('./TypeVisitor.js');
            var Output = require('../Output.js');

            var SourceBuilder = function (_TypeVisitor) {
                _inherits(SourceBuilder, _TypeVisitor);

                function SourceBuilder(cfg) {
                    _classCallCheck(this, SourceBuilder);

                    var _this17 = _possibleConstructorReturn(this, (SourceBuilder.__proto__ || Object.getPrototypeOf(SourceBuilder)).call(this, cfg));

                    _this17.nullFound = false;
                    return _this17;
                }

                _createClass(SourceBuilder, [{
                    key: "list",
                    value: function list(obj) {
                        var output = this.output,
                            items = obj.items,
                            len = output.output.length,
                            sep = obj.separator,
                            sepLen = sep && sep.length,
                            hasSpace = sep && sep.indexOf(' ') > -1,
                            prev = output.output,
                            delta;

                        for (var i = 0; i < items.length; i++) {
                            if (items[i] && !items[i].$isFashionNull) {
                                this.visit(items[i]);
                                delta = output.output.length - len;
                                if (!delta && sepLen && i > 0) {
                                    output.output = prev;
                                }
                                prev = output.output;
                                if (i < items.length - 1) {
                                    if (sepLen) {
                                        output.add(sep);
                                        if (!hasSpace) {
                                            output.space();
                                        }
                                    }
                                }
                                len = output.output.length;
                            } else {
                                this.nullFound = true;
                            }
                        }
                    }
                }, {
                    key: "map",
                    value: function map(obj) {
                        var output = this.output,
                            items = obj.items,
                            key,
                            value;

                        if (this.currDeclaration) {
                            Fashion.raise('(' + obj.toString() + ") isn't a valid CSS value.");
                        }

                        for (var i = 0; i < items.length - 1; i += 2) {
                            key = items[i];
                            value = items[i + 1];
                            if (key && value) {
                                if (i > 0) {
                                    output.add(',');
                                    output.space();
                                }

                                this.visit(key);
                                output.add(': ');
                                //output.space();
                                this.visit(value);
                            }
                        }
                    }
                }, {
                    key: "literal",
                    value: function literal(obj) {
                        obj.value && this.output.add(obj.value);
                    }
                }, {
                    key: "string",
                    value: function string(obj) {
                        var output = this.output;
                        output.add(obj.quoteChar);
                        output.add(obj.value);
                        output.add(obj.quoteChar);
                    }
                }, {
                    key: "functioncall",
                    value: function functioncall(obj) {
                        var output = this.output;
                        output.add(obj.name);
                        output.add('(');
                        this.visit(obj.args);
                        output.add(')');
                    }
                }, {
                    key: "parenthetical",
                    value: function parenthetical(obj) {
                        this.output.add('(');
                        this.visit(obj.value);
                        this.output.add(')');
                    }
                }, {
                    key: "number",
                    value: function number(obj) {
                        var val = obj.stringify();
                        if (val.indexOf('.') === '.' && !this.output.isCompressed) {
                            val = "0" + val;
                        }
                        this.output.add(val);
                    }
                }, {
                    key: "bool",
                    value: function bool(obj) {
                        this.output.add(obj.value ? 'true' : 'false');
                    }
                }, {
                    key: "hsla",
                    value: function hsla(obj) {
                        this.output.add(obj.toString());
                    }
                }, {
                    key: "rgba",
                    value: function rgba(obj) {
                        this.output.add(obj.toString());
                    }
                }, {
                    key: "colorstop",
                    value: function colorstop(obj) {
                        var output = this.output,
                            stop = obj.stop;

                        this.visit(obj.color);

                        if (stop) {
                            stop = stop.clone();
                            output.add(' ');
                            if (!stop.unit) {
                                stop.value *= 100;
                                stop.unit = '%';
                            }
                            this.visit(stop);
                        }
                    }
                }, {
                    key: "lineargradient",
                    value: function lineargradient(obj) {
                        var output = this.output;
                        output.add("linear-gradient(");
                        if (obj.position) {
                            this.visit(obj.position);
                            output.add(',');
                            output.space();
                        }
                        this.visit(obj.stops);
                        output.add(')');
                    }
                }, {
                    key: "radialgradient",
                    value: function radialgradient(obj) {
                        var output = this.output;
                        output.add("radial-gradient(");
                        if (obj.position) {
                            this.visit(obj.position);
                            output.add(',');
                            output.space();
                        }
                        if (obj.shape) {
                            this.visit(obj.shape);
                            output.add(',');
                            output.space();
                        }
                        this.visit(obj.stops);
                        output.add(')');
                    }
                }, {
                    key: "toSource",
                    value: function toSource(obj, output) {
                        this.output = output || new Output();
                        this.visit(obj);
                        return this.output.get();
                    }
                }], [{
                    key: "toSource",
                    value: function toSource(obj, output) {
                        var sb = new SourceBuilder();
                        return sb.toSource(obj, output);
                    }
                }]);

                return SourceBuilder;
            }(TypeVisitor);

            Fashion.apply(SourceBuilder.prototype, {
                output: null
            });

            module.exports = SourceBuilder;
        }, { "../Base.js": 3, "../Output.js": 4, "./TypeVisitor.js": 25 }], 22: [function (require, module, exports) {
            "use strict";

            var Fashion = require('../Base.js');
            var Type = require('./Type.js');
            var Text = require('./Text.js');
            var Numeric = require('./Numeric.js');

            var Bool = require('./Bool.js'),
                True = Bool.True,
                False = Bool.False;

            var Literal = require('./Literal.js'),
                Null = Literal.Null;

            module.exports = {
                unboxType: function unboxType(expression) {
                    var val = expression;
                    if (val && val.$isFashionType && val.$canUnbox) {
                        val = val.value;
                        if (expression.$isFashionString || expression.$isFashionLiteral) {
                            if (val === 'none' || val === 'null') {
                                val = null;
                            }
                        } else if (expression.$isFashionList) {
                            val = expression.items;
                        }
                    }
                    return val;
                },
                boxType: function boxType(expression) {
                    if (expression && expression.$isFashionType) {
                        return expression;
                    }

                    if (expression == null) {
                        // null || undefined
                        return Null;
                    }
                    if (expression === true) {
                        return True;
                    }
                    if (expression === false) {
                        return False;
                    }

                    var typeOf = typeof expression === "undefined" ? "undefined" : _typeof(expression);
                    switch (typeOf) {
                        case 'string':
                            return new Text(expression);
                        case 'number':
                            return new Numeric(expression);
                        default:
                            break;
                    }

                    return expression;
                }
            };

            Fashion.apply(Type, {
                box: module.exports.boxType,
                unbox: module.exports.unboxType
            });
        }, { "../Base.js": 3, "./Bool.js": 8, "./Literal.js": 16, "./Numeric.js": 18, "./Text.js": 23, "./Type.js": 24 }], 23: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');
            var Literal = require('./Literal.js');

            var Text = function (_Literal2) {
                _inherits(Text, _Literal2);

                function Text(value, quoteChar) {
                    _classCallCheck(this, Text);

                    var _this18 = _possibleConstructorReturn(this, (Text.__proto__ || Object.getPrototypeOf(Text)).call(this, value));

                    if (quoteChar !== undefined) {
                        if (Text.preferDoubleQuotes && quoteChar === '') {
                            _this18.quoteChar = '';
                        } else {
                            _this18.quoteChar = quoteChar;
                        }
                    }
                    return _this18;
                }

                _createClass(Text, [{
                    key: "doVisit",
                    value: function doVisit(visitor) {
                        visitor.string(this);
                    }
                }, {
                    key: "toString",
                    value: function toString() {
                        return this.quoteChar + this.value + this.quoteChar;
                    }
                }, {
                    key: "unquote",
                    value: function unquote() {
                        return new Literal(this.value);
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return new Text(this.value, this.quoteChar);
                    }
                }, {
                    key: "slice",
                    value: function slice(start, end) {
                        return new Text(_get(Text.prototype.__proto__ || Object.getPrototypeOf(Text.prototype), "slice", this).call(this, start, end).value, this.quoteChar);
                    }
                }, {
                    key: "toUpperCase",
                    value: function toUpperCase() {
                        return new Text(this.value.toUpperCase(), this.quoteChar);
                    }
                }, {
                    key: "toLowerCase",
                    value: function toLowerCase() {
                        return new Text(this.value.toLowerCase(), this.quoteChar);
                    }
                }, {
                    key: "insert",
                    value: function insert(str, startVal) {
                        return new Text(_get(Text.prototype.__proto__ || Object.getPrototypeOf(Text.prototype), "insert", this).call(this, str, startVal).value, this.quoteChar);
                    }
                }], [{
                    key: "tryCoerce",
                    value: function tryCoerce(obj) {
                        if (obj.$isFashionNumber) {
                            return undefined;
                        }
                        if (obj.$isFashionLiteral) {
                            return new Text(obj.value);
                        }

                        return new Text(obj.getHash());
                    }
                }]);

                return Text;
            }(Literal);

            Text.preferDoubleQuotes = false;

            Fashion.apply(Text.prototype, {
                type: 'string',
                $isFashionString: true,
                value: null,
                quoteChar: '"',

                '+': function _(right) {
                    return new Text(this.value + right.getHash());
                },
                '+.number': function number(right) {
                    return new Text(this.value + right.toString());
                },
                '/': function _(right) {
                    return new Text(this.value + '/' + right.getHash());
                }
            });

            module.exports = Text;
        }, { "../Base.js": 3, "./Literal.js": 16 }], 24: [function (require, module, exports) {
            /*
             * Copyright (c) 2012-2016. Sencha Inc.
             */

            "use strict";

            var Fashion = require('../Base.js');

            var Type = function () {
                function Type() {
                    _classCallCheck(this, Type);
                }

                _createClass(Type, [{
                    key: "coerce",
                    value: function coerce(obj) {
                        var converted = this.tryCoerce(obj);
                        return converted || obj;
                    }
                }, {
                    key: "_getHash",
                    value: function _getHash() {
                        if (this.visitTarget) {
                            return this.visitTarget.toString();
                        }
                        return this.toString();
                    }
                }, {
                    key: "getHash",
                    value: function getHash() {
                        if (this._hash == null) {
                            this._hash = this._getHash();
                        }
                        return this._hash;
                    }
                }, {
                    key: "tryCoerce",
                    value: function tryCoerce(obj) {
                        var me = this;

                        if (me.constructor === obj.constructor) {
                            return obj;
                        }

                        if (me.constructor.tryCoerce) {
                            return me.constructor.tryCoerce(obj);
                        }

                        return undefined;
                    }
                }, {
                    key: "supports",
                    value: function supports(prefix) {
                        return false;
                    }
                }, {
                    key: "operate",
                    value: function operate(operation, right) {
                        return this.performOperation(operation, this.coerce(right));
                    }
                }, {
                    key: "performOperation",
                    value: function performOperation(operation, right) {
                        // check for <op>.<type> name for class-specific impl,
                        // eg, ==.color or +.list
                        var method = this[operation + "." + right.type] || this[operation];

                        if (!method) {
                            Fashion.raise("Failed to find method for operation " + operation + " on type " + right.type + " with value " + right + ".");
                        }

                        var res = method.call(this, right);

                        if (!res || !res.$isFashionType) {
                            res = Type.box(res);
                        }

                        return res;
                    }
                }, {
                    key: '==',
                    value: function _(right) {
                        return this.getHash() === right.getHash();
                    }
                }, {
                    key: '!=',
                    value: function _(right) {
                        return this.getHash() !== right.getHash();
                    }
                }, {
                    key: '>=',
                    value: function _(right) {
                        return this.getHash() >= right.getHash();
                    }
                }, {
                    key: '<=',
                    value: function _(right) {
                        return this.getHash() <= right.getHash();
                    }
                }, {
                    key: '>',
                    value: function _(right) {
                        return this.getHash() > right.getHash();
                    }
                }, {
                    key: '<',
                    value: function _(right) {
                        return this.getHash() < right.getHash();
                    }
                }, {
                    key: '+',
                    value: function _(right) {
                        return this.getHash() + right.getHash();
                    }
                }, {
                    key: "copy",
                    value: function copy() {
                        return this;
                    }
                }, {
                    key: "matches",
                    value: function matches(match) {
                        if (match && match == this.toString()) {
                            return true;
                        }
                        return false;
                    }
                }, {
                    key: "clone",
                    value: function clone(match, replace) {
                        if (replace && this.matches(match)) {
                            return replace.copy();
                        }
                        var copy = this.copy();
                        copy.ast = this.ast;
                        copy.$referenceName = this.$referenceName;
                        copy.$referenceBase = this.$referenceBase;
                        copy.$previousReference = this.$previousReference;
                        return copy;
                    }
                }, {
                    key: "unquote",
                    value: function unquote() {
                        return this;
                    }
                }, {
                    key: "toPrefixedString",
                    value: function toPrefixedString(prefix) {
                        return this.toString();
                    }
                }, {
                    key: "doVisit",
                    value: function doVisit(visitor) {}
                }, {
                    key: "descend",
                    value: function descend(visitoir) {}

                    /**
                     * A mechanism that enables searching upwards in the type tree for comments with a
                     * particular control tag.  The search begins locally first on the specified node,
                     * and continues upwards until either an enable or disable tag is specified, or the
                     * the root of the tree is reached with no tags specified.
                     *
                     * By testing for both positive and negative matches locally, features can be enabled
                     * or disabled at specific points, potentially overriding state set at a more
                     * generic scope.  Ex:
                     *
                     *      //# fashion -ingline
                     *      @font-face {
                     *          src: url(foo.eot);
                     *          src: url(foo.svg);
                     *          //# fashion +inline
                     *          src: url(foo.ttf);
                     *      }
                     *
                     * @param tag The tag to search for.
                     * @param prefix An optional prefix, such as 'fashion warn'.  Defaults to 'fashion'
                     * @param enable A regex indicating a match for the enable state (+tag).
                     * @param disable A regex indicating a match for the disable state (-tag)
                     * @returns {any} true for enable | false for disable | null for unspecified
                     */

                }, {
                    key: "hasTag",
                    value: function hasTag(tag, prefix, enable, disable) {
                        prefix = prefix || "fashion";
                        enable = enable || new RegExp('^\\s*//#\\s*' + prefix + '\\s*\\+?' + tag + "\\s*$");
                        disable = disable || new RegExp('^\\s*//#\\s*' + prefix + '\\s*\\-' + tag + '\\s*$');
                        var docs = this.docs;
                        if (docs && docs.length) {
                            for (var d = 0; d < this.docs.length; d++) {
                                var doc = docs[d];
                                if (enable.test(doc)) {
                                    return true;
                                }
                                if (disable.test(doc)) {
                                    return false;
                                }
                            }
                        }

                        if (this.parentNode) {
                            return this.parentNode.hasTag(tag, prefix, enable, disable);
                        }

                        return null;
                    }
                }, {
                    key: "toDisplayString",
                    value: function toDisplayString() {
                        return '[' + this.constructor.name + ' : ' + this.toString() + ']';
                    }
                }]);

                return Type;
            }();

            Fashion.apply(Type.prototype, {
                visitTarget: undefined,
                $isFashionType: true,
                $canUnbox: true,

                $isFashionLiteral: false,
                $isFashionNumber: false,
                $isFashionString: false,
                $isFashionBool: false,

                $constant: false,

                /**
                 * if this value is a global variable, this field will store the global
                 * variable name by which this value is referenced.
                 */
                $referenceName: undefined,

                $referenceBase: undefined,
                $previousReference: undefined,

                value: undefined,
                unit: undefined,
                parentNode: undefined,
                docs: undefined,
                ast: undefined
            });

            module.exports = Type;
        }, { "../Base.js": 3 }], 25: [function (require, module, exports) {
            "use strict";

            var Fashion = require('../Base.js');

            var TypeVisitor = function () {
                function TypeVisitor(cfg) {
                    _classCallCheck(this, TypeVisitor);

                    if (cfg) {
                        Fashion.apply(this, cfg);
                    }
                }

                _createClass(TypeVisitor, [{
                    key: "literal",
                    value: function literal(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "bool",
                    value: function bool(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "string",
                    value: function string(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "number",
                    value: function number(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "map",
                    value: function map(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "functioncall",
                    value: function functioncall(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "parenthetical",
                    value: function parenthetical(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "list",
                    value: function list(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "hsla",
                    value: function hsla(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "rgba",
                    value: function rgba(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "colorstop",
                    value: function colorstop(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "lineargradient",
                    value: function lineargradient(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "radialgradient",
                    value: function radialgradient(obj) {
                        obj.descend(this);
                    }
                }, {
                    key: "visitItem",
                    value: function visitItem(obj) {
                        obj.doVisit(this);
                    }
                }, {
                    key: "visit",
                    value: function visit(obj) {
                        while (obj && obj.visitTarget !== undefined) {
                            obj = obj.visitTarget;
                        }
                        if (obj) {
                            if (Array.isArray(obj)) {
                                for (var i = 0; i < obj.length; i++) {
                                    this.visit(obj[i]);
                                }
                            } else {
                                this.visitItem(obj);
                            }
                        }
                    }

                    /**
                     * this is an extension point for allowing overrides of the entry visit method
                     * when called duing the post-processing mechanism in CSS.ts
                     * @param obj
                     */

                }, {
                    key: "execute",
                    value: function execute(obj, context) {
                        this.visit(obj);
                    }
                }]);

                return TypeVisitor;
            }();

            TypeVisitor.prototype.context = null;

            module.exports = TypeVisitor;
        }, { "../Base.js": 3 }], 26: [function (require, module, exports) {
            "use strict";

            var Bool = require('./Bool.js');
            var Literal = require('./Literal.js');

            var Types = {
                Bool: Bool,
                Literal: Literal,
                Text: require('./Text.js'),
                Numeric: require('./Numeric.js'),
                Color: require('./Color.js'),
                ColorRGBA: require('./ColorRGBA.js'),
                ColorHSLA: require('./ColorHSLA.js'),
                ColorStop: require('./ColorStop.js'),
                LinearGradient: require('./LinearGradient.js'),
                RadialGradient: require('./RadialGradient.js'),
                List: require('./List.js'),
                Map: require('./Map.js'),
                ParentheticalExpression: require('./ParentheticalExpression.js'),
                FunctionCall: require('./FunctionCall.js'),
                Null: Literal.Null,
                None: Literal.None,
                True: Bool.True,
                False: Bool.False
            };

            module.exports = Types;
        }, { "./Bool.js": 8, "./Color.js": 9, "./ColorHSLA.js": 10, "./ColorRGBA.js": 11, "./ColorStop.js": 12, "./FunctionCall.js": 13, "./LinearGradient.js": 14, "./List.js": 15, "./Literal.js": 16, "./Map.js": 17, "./Numeric.js": 18, "./ParentheticalExpression.js": 19, "./RadialGradient.js": 20, "./Text.js": 23 }] }, {}, [1])(1);
});
(function(Fashion){
	var __udf = undefined,
	    Types = Fashion.Types,
	    __strings = {
    _: "$color",
    $: "$color_name",
    A: "$colorLookup",
    a: "$color_variant"
},

	    __names = Fashion.css.buildNames(__strings),

	    __jsNames = Fashion.css.buildJsNames(__strings);
var Bool = Types.Bool,
    __Bool = Bool,
    Literal = Types.Literal,
    __Literal = Literal,
    Text = Types.Text,
    __Text = Text,
    Numeric = Types.Numeric,
    __Numeric = Numeric,
    Color = Types.Color,
    __Color = Color,
    ColorRGBA = Types.ColorRGBA,
    __ColorRGBA = ColorRGBA,
    ColorHSLA = Types.ColorHSLA,
    __ColorHSLA = ColorHSLA,
    ColorStop = Types.ColorStop,
    __ColorStop = ColorStop,
    LinearGradient = Types.LinearGradient,
    __LinearGradient = LinearGradient,
    RadialGradient = Types.RadialGradient,
    __RadialGradient = RadialGradient,
    List = Types.List,
    __List = List,
    Map = Types.Map,
    __Map = Map,
    ParentheticalExpression = Types.ParentheticalExpression,
    __ParentheticalExpression = ParentheticalExpression,
    FunctionCall = Types.FunctionCall,
    __FunctionCall = FunctionCall,
    Null = Types.Null,
    __Null = Null,
    None = Types.None,
    __None = None,
    True = Types.True,
    __True = True,
    False = Types.False,
    __False = False,
    Ruleset = Types.Ruleset,
    __Ruleset = Ruleset,
    Declaration = Types.Declaration,
    __Declaration = Declaration,
    SelectorPart = Types.SelectorPart,
    __SelectorPart = SelectorPart,
    CompoundSelector = Types.CompoundSelector,
    __CompoundSelector = CompoundSelector,
    MultiPartSelector = Types.MultiPartSelector,
    __MultiPartSelector = MultiPartSelector,
    SelectorList = Types.SelectorList,
    __SelectorList = SelectorList,
    SelectorProperty = Types.SelectorProperty,
    __SelectorProperty = SelectorProperty;

	Fashion.css.register(function(__rt) {
__rt.register({
    map_get:  function (map, key) {
                return map.get(key);
            },
    lighten:  function (color, amount) {
                if (color == null || color.$isFashionNull) {
                    return Literal.Null;
                }
                if (color.type !== 'hsla' && color.type !== 'rgba') {
                    Fashion.raise(color + ' is not a color for \'lighten\'');
                }
                if (amount.type !== 'number') {
                    Fashion.raise(amount + ' is not a number for \'lighten\'');
                }
                if (amount.value !== Color.constrainPercentage(amount.value)) {
                    Fashion.raise('Amount ' + amount + ' must be between 0% and 100% for \'lighten\'');
                }

                return Color.adjust(color, 'lightness', amount);
            },
    darken:  function (color, amount) {
                if (color == null || color.$isFashionNull) {
                    return Literal.Null;
                }
                if (color.type !== 'hsla' && color.type !== 'rgba') {
                    Fashion.raise(color + ' is not a color for \'darken\'');
                }
                if (amount.type !== 'number') {
                    Fashion.raise(amount + ' is not a number for \'darken\'');
                }

                if (amount.value !== Color.constrainPercentage(amount.value)) {
                    Fashion.raise('Amount ' + amount + ' must be between 0% and 100% for \'darken\'');
                }

                amount = amount.clone();
                amount.value *= -1;
                return Color.adjust(color, 'lightness', amount);
            },
    rgba:  function (red, green, blue, alpha, color) {
                var colorInst;

                if (!!red && !!color) {
                    Fashion.raise("Unsupported arguments to RGBA");
                }

                if (color && !red) {
                    if (color.$isFashionColor) {
                        colorInst = color;
                    } else {
                        Fashion.raise("Unsupported arguments to RGBA");
                    }
                } else if (red && red.$isFashionColor) {
                    colorInst = red;
                }

                if (colorInst) {
                    alpha = green || alpha;
                    colorInst = colorInst.getRGBA();
                    red = new Numeric(colorInst.r);
                    green = new Numeric(colorInst.g);
                    blue = new Numeric(colorInst.b);
                }

                if (!red || !red.$isFashionNumber) {
                    if (red == null || red.$isFashionNull) {
                        return Literal.Null;
                    }
                    Fashion.raise(red + ' is not a number for \'rgba\' red');
                }
                if (!green || !green.$isFashionNumber) {
                    if (green == null || green.$isFashionNull) {
                        return Literal.Null;
                    }
                    Fashion.raise(green + ' is not a number for \'rgba\' green');
                }
                if (!blue || !blue.$isFashionNumber) {
                    if (blue == null || blue.$isFashionNull) {
                        return Literal.Null;
                    }
                    Fashion.raise(blue + ' is not a number for \'rgba\' blue');
                }
                if (!alpha || !alpha.$isFashionNumber) {
                    if (alpha == null || alpha.$isFashionNull) {
                        return Literal.Null;
                    }
                    Fashion.raise(alpha + ' is not a number for \'rgba\' alpha');
                }

                if (red.unit == '%') {
                    red = new Numeric(Color.constrainPercentage(red.value) / 100 * 255);
                } else if (red.value !== Color.constrainChannel(red.value)) {
                    Fashion.raise('Color value ' + red + ' must be between 0 and 255 inclusive for \'rgba\'');
                }

                if (green.unit == '%') {
                    green = new Numeric(Color.constrainPercentage(green.value) / 100 * 255);
                } else if (green.value !== Color.constrainChannel(green.value)) {
                    Fashion.raise('Color value ' + green + ' must be between 0 and 255 inclusive for \'rgba\'');
                }

                if (blue.unit == '%') {
                    blue = new Numeric(Color.constrainPercentage(blue.value) / 100 * 255);
                } else if (blue.value !== Color.constrainChannel(blue.value)) {
                    Fashion.raise('Color value ' + blue + ' must be between 0 and 255 inclusive for \'rgba\'');
                }

                if (alpha.unit == '%') {
                    alpha = new Numeric(Color.constrainPercentage(alpha.value) / 100);
                } else if (alpha.value !== Color.constrainAlpha(alpha.value)) {
                    Fashion.raise('Alpha channel ' + alpha + ' must be between 0 and 1 inclusive for \'rgba\'');
                }

                return new ColorRGBA(red.value, green.value, blue.value, alpha.value);
            },
    mix:  function (color_1, color_2, weight) {
                if (color_1 == null || color_1.$isFashionNull) {
                    return Literal.Null;
                }
                if (color_2 == null || color_2.$isFashionNull) {
                    return Literal.Null;
                }
                
                weight = (weight !== undefined) ? weight : new Numeric(50, '%');

                if (color_1.type !== 'hsla' && color_1.type !== 'rgba') {
                    Fashion.raise('arg 1 ' + color_1 + ' is not a color for \'mix\'');
                }
                if (color_2.type !== 'hsla' && color_2.type !== 'rgba') {
                    Fashion.raise('arg 2 ' + color_2 + ' is not a color for \'mix\'');
                }
                if (weight.type !== 'number') {
                    Fashion.raise('arg 3 ' + weight + ' is not a number for \'mix\'');
                }
                if (weight.value !== Color.constrainPercentage(weight.value)) {
                    Fashion.raise('Weight ' + weight + ' must be between 0% and 100% for \'mix\'');
                }

                color_1 = color_1.getRGBA();
                color_2 = color_2.getRGBA();

                weight = weight.value / 100;

                var factor = (weight * 2) - 1,
                    alpha = color_1.a - color_2.a,
                    weight1 = (((factor * alpha == -1) ? factor : (factor + alpha) / (1 + factor * alpha)) + 1) / 2,
                    weight2 = 1 - weight1;

                return new ColorRGBA(
                    (weight1 * color_1.r) + (weight2 * color_2.r),
                    (weight1 * color_1.g) + (weight2 * color_2.g),
                    (weight1 * color_1.b) + (weight2 * color_2.b),
                    (weight * color_1.a) + ((1 - weight) * color_2.a)
                );
            }
});
var __rt_constructor = __rt.constructor.bind(__rt),
    __rt_bool = __rt.bool.bind(__rt),
    __rt_color = __rt.color.bind(__rt),
    __rt_quote = __rt.quote.bind(__rt),
    __rt_unquote = __rt.unquote.bind(__rt),
    __rt_not = __rt.not.bind(__rt),
    __rt_operate = __rt.operate.bind(__rt),
    __rt_reset = __rt.reset.bind(__rt),
    __rt_run = __rt.run.bind(__rt),
    __rt_createTypesBlock = __rt.createTypesBlock.bind(__rt),
    __rt_createMethodBlock = __rt.createMethodBlock.bind(__rt),
    __rt_createPropertyBlock = __rt.createPropertyBlock.bind(__rt),
    __rt_createPrefixedFunctionBody = __rt.createPrefixedFunctionBody.bind(__rt),
    __rt_createWrappedFn = __rt.createWrappedFn.bind(__rt),
    __rt_callWrappedFn = __rt.callWrappedFn.bind(__rt),
    __rt_compile = __rt.compile.bind(__rt),
    __rt_execute = __rt.execute.bind(__rt),
    __rt_load = __rt.load.bind(__rt),
    __rt_registerProcessor = __rt.registerProcessor.bind(__rt),
    __rt_register = __rt.register.bind(__rt),
    __rt_isRegistered = __rt.isRegistered.bind(__rt),
    __rt_getGlobalScope = __rt.getGlobalScope.bind(__rt),
    __rt_getCurrentScope = __rt.getCurrentScope.bind(__rt),
    __rt_getRegisteredFunctions = __rt.getRegisteredFunctions.bind(__rt),
    __rt_getFunctions = __rt.getFunctions.bind(__rt),
    __rt_getMixins = __rt.getMixins.bind(__rt),
    __rt_createScope = __rt.createScope.bind(__rt),
    __rt_pushScope = __rt.pushScope.bind(__rt),
    __rt_popScope = __rt.popScope.bind(__rt),
    __rt_createCallStackScope = __rt.createCallStackScope.bind(__rt),
    __rt_pushCallStackScope = __rt.pushCallStackScope.bind(__rt),
    __rt_popCallStackScope = __rt.popCallStackScope.bind(__rt),
    __rt_getCallStack = __rt.getCallStack.bind(__rt),
    __rt_pushSourceInfo = __rt.pushSourceInfo.bind(__rt),
    __rt_getSourceInfo = __rt.getSourceInfo.bind(__rt),
    __rt_get = __rt.get.bind(__rt),
    __rt_getScopeForName = __rt.getScopeForName.bind(__rt),
    __rt_getDefault = __rt.getDefault.bind(__rt),
    __rt_getGlobalDefault = __rt.getGlobalDefault.bind(__rt),
    __rt_getLocalDefault = __rt.getLocalDefault.bind(__rt),
    __rt_setGlobal = __rt.setGlobal.bind(__rt),
    __rt_setDynamic = __rt.setDynamic.bind(__rt),
    __rt_setScoped = __rt.setScoped.bind(__rt),
    __rt_set = __rt.set.bind(__rt),
    __rt_getDocs = __rt.getDocs.bind(__rt),
    __rt_getString = __rt.getString.bind(__rt),
    __rt_getAstNode = __rt.getAstNode.bind(__rt),
    __rt_applySpread = __rt.applySpread.bind(__rt),
    __rt_sliceArgs = __rt.sliceArgs.bind(__rt),
    __rt_applySpreadArgs = __rt.applySpreadArgs.bind(__rt),
    __rt_warn = __rt.warn.bind(__rt),
    __rt_error = __rt.error.bind(__rt),
    __rt_debug = __rt.debug.bind(__rt),
    __rt_setCaches = __rt.setCaches.bind(__rt),
    __rt_copyRuntimeState = __rt.copyRuntimeState.bind(__rt),
    __rt_test = __rt.test.bind(__rt),
    __rt_and = __rt.and.bind(__rt),
    __rt_or = __rt.or.bind(__rt),
    __rt_box = __rt.box.bind(__rt),
    __rt_unbox = __rt.unbox.bind(__rt),
    __rt_Scope = __rt.Scope.bind(__rt),
    __rt_constructor = __rt.constructor.bind(__rt),
    __rt___defineGetter__ = __rt.__defineGetter__.bind(__rt),
    __rt___defineSetter__ = __rt.__defineSetter__.bind(__rt),
    __rt_hasOwnProperty = __rt.hasOwnProperty.bind(__rt),
    __rt___lookupGetter__ = __rt.__lookupGetter__.bind(__rt),
    __rt___lookupSetter__ = __rt.__lookupSetter__.bind(__rt),
    __rt_propertyIsEnumerable = __rt.propertyIsEnumerable.bind(__rt),
    __rt_constructor = __rt.constructor.bind(__rt),
    __rt_toString = __rt.toString.bind(__rt),
    __rt_toLocaleString = __rt.toLocaleString.bind(__rt),
    __rt_valueOf = __rt.valueOf.bind(__rt),
    __rt_isPrototypeOf = __rt.isPrototypeOf.bind(__rt);
var __rt_context = __rt.context,
    __rt_mixins = __rt.mixins,
    __rt_functions = __rt.functions,
    __rt_processors = __rt.processors,
    __rt_registered = __rt.registered,
    __rt_deferredContent = __rt.deferredContent,
    __rt_registerSelectorHooks = __rt.registerSelectorHooks,
    __rt_registerAtRuleHook = __rt.registerAtRuleHook,
    __rt_registerStyleHooks = __rt.registerStyleHooks,
    __rt_registerFunctionCallHooks = __rt.registerFunctionCallHooks,
    __rt_docCache = __rt.docCache,
    __rt_stringCache = __rt.stringCache,
    __rt_nodeCache = __rt.nodeCache,
    __rt_code = __rt.code,
    __rt_fn = __rt.fn,
    __rt__currentScope = __rt._currentScope,
    __rt__currentCallStackScope = __rt._currentCallStackScope,
    __rt__globalScope = __rt._globalScope,
    __rt__dynamics = __rt._dynamics,
    __rt_css = __rt.css,
    __rt_rulesets = __rt.rulesets,
    __rt_extenders = __rt.extenders,
    __rt__scopeStack = __rt._scopeStack;
Fashion.apply(__rt.functions, {
    material_color:  function ($color_name, $color_variant) {
    __rt_createScope(__rt_functions.material_color && __rt_functions.material_color.createdScope);
    var $color_name = $color_name || __Null;
    __rt_set(__strings.$, $color_name, true);
    var $color_variant = $color_variant || new __Text("500", "'");
    __rt_set(__strings.a, $color_variant, true);
    __rt_set(__strings.A, __rt_box(__rt_registered.map_get.apply(__rt.registered, __rt_applySpreadArgs([
        __rt_get("$material_colors"), 
        __rt_get(__strings.$)]))));
    if(__rt_unbox(__rt_get(__strings.A))) {
        __rt_set(__strings._, __rt_box(__rt.registered.map_get.apply(__rt.registered, __rt_applySpreadArgs([
            __rt_get(__strings.A), 
            __rt_get(__strings.a)]))));
        if(__rt_unbox(__rt_get(__strings._))) {
            var $$$r = __rt_get(__strings._);
            __rt_popScope();
            return $$$r;
        }
        else {
            __rt_warn(__rt_unbox(__rt.operate("+",__rt.operate("+",__rt.operate("+",__rt.operate("+",new __Text("=> ERROR: COLOR NOT FOUND! <= | ", "\""), __rt_get(__strings.$)), new __Text(",", "\"")), __rt_get(__strings.a)), new __Text(" combination did not match any of the material design colors.", "\""))));
        }
    }
    else {
        __rt_warn(__rt_unbox(__rt.operate("+",__rt.operate("+",new __Text("=> ERROR: COLOR NOT FOUND! <= | ", "\""), __rt_get(__strings.$)), new __Text(" did not match any of the material design colors.", "\""))));
    }
    var $$$r = __ColorRGBA.fromHex("#ff0000");
    __rt_popScope();
    return $$$r;
},
    material_foreground_color:  function ($color_name) {
    __rt_createScope(__rt_functions.material_foreground_color && __rt_functions.material_foreground_color.createdScope);
    var $color_name = $color_name || __Null;
    __rt_set(__strings.$, $color_name, true);
    __rt_set(__strings._, __rt_box(__rt.registered.map_get.apply(__rt.registered, __rt_applySpreadArgs([
        __rt_get("$material_foreground_colors"), 
        __rt_get(__strings.$)]))));
    if(__rt_unbox(__rt_get(__strings._))) {
        var $$$r = __rt_get(__strings._);
        __rt_popScope();
        return $$$r;
    }
    else {
        __rt_warn(__rt_unbox(__rt.operate("+",__rt.operate("+",new __Text("=> ERROR: COLOR NOT FOUND! <= | ", "\""), __rt_get(__strings.$)), new __Text(" did not match any of the material design colors.", "\""))));
    }
    var $$$r = __ColorRGBA.fromHex("#ff0000");
    __rt_popScope();
    return $$$r;
}
});
},
 function(__rt) {
var __rt_constructor = __rt.constructor.bind(__rt),
    __rt_bool = __rt.bool.bind(__rt),
    __rt_color = __rt.color.bind(__rt),
    __rt_quote = __rt.quote.bind(__rt),
    __rt_unquote = __rt.unquote.bind(__rt),
    __rt_not = __rt.not.bind(__rt),
    __rt_operate = __rt.operate.bind(__rt),
    __rt_reset = __rt.reset.bind(__rt),
    __rt_run = __rt.run.bind(__rt),
    __rt_createTypesBlock = __rt.createTypesBlock.bind(__rt),
    __rt_createMethodBlock = __rt.createMethodBlock.bind(__rt),
    __rt_createPropertyBlock = __rt.createPropertyBlock.bind(__rt),
    __rt_createPrefixedFunctionBody = __rt.createPrefixedFunctionBody.bind(__rt),
    __rt_createWrappedFn = __rt.createWrappedFn.bind(__rt),
    __rt_callWrappedFn = __rt.callWrappedFn.bind(__rt),
    __rt_compile = __rt.compile.bind(__rt),
    __rt_execute = __rt.execute.bind(__rt),
    __rt_load = __rt.load.bind(__rt),
    __rt_registerProcessor = __rt.registerProcessor.bind(__rt),
    __rt_register = __rt.register.bind(__rt),
    __rt_isRegistered = __rt.isRegistered.bind(__rt),
    __rt_getGlobalScope = __rt.getGlobalScope.bind(__rt),
    __rt_getCurrentScope = __rt.getCurrentScope.bind(__rt),
    __rt_getRegisteredFunctions = __rt.getRegisteredFunctions.bind(__rt),
    __rt_getFunctions = __rt.getFunctions.bind(__rt),
    __rt_getMixins = __rt.getMixins.bind(__rt),
    __rt_createScope = __rt.createScope.bind(__rt),
    __rt_pushScope = __rt.pushScope.bind(__rt),
    __rt_popScope = __rt.popScope.bind(__rt),
    __rt_createCallStackScope = __rt.createCallStackScope.bind(__rt),
    __rt_pushCallStackScope = __rt.pushCallStackScope.bind(__rt),
    __rt_popCallStackScope = __rt.popCallStackScope.bind(__rt),
    __rt_getCallStack = __rt.getCallStack.bind(__rt),
    __rt_pushSourceInfo = __rt.pushSourceInfo.bind(__rt),
    __rt_getSourceInfo = __rt.getSourceInfo.bind(__rt),
    __rt_get = __rt.get.bind(__rt),
    __rt_getScopeForName = __rt.getScopeForName.bind(__rt),
    __rt_getDefault = __rt.getDefault.bind(__rt),
    __rt_getGlobalDefault = __rt.getGlobalDefault.bind(__rt),
    __rt_getLocalDefault = __rt.getLocalDefault.bind(__rt),
    __rt_setGlobal = __rt.setGlobal.bind(__rt),
    __rt_setDynamic = __rt.setDynamic.bind(__rt),
    __rt_setScoped = __rt.setScoped.bind(__rt),
    __rt_set = __rt.set.bind(__rt),
    __rt_getDocs = __rt.getDocs.bind(__rt),
    __rt_getString = __rt.getString.bind(__rt),
    __rt_getAstNode = __rt.getAstNode.bind(__rt),
    __rt_applySpread = __rt.applySpread.bind(__rt),
    __rt_sliceArgs = __rt.sliceArgs.bind(__rt),
    __rt_applySpreadArgs = __rt.applySpreadArgs.bind(__rt),
    __rt_warn = __rt.warn.bind(__rt),
    __rt_error = __rt.error.bind(__rt),
    __rt_debug = __rt.debug.bind(__rt),
    __rt_setCaches = __rt.setCaches.bind(__rt),
    __rt_copyRuntimeState = __rt.copyRuntimeState.bind(__rt),
    __rt_test = __rt.test.bind(__rt),
    __rt_and = __rt.and.bind(__rt),
    __rt_or = __rt.or.bind(__rt),
    __rt_box = __rt.box.bind(__rt),
    __rt_unbox = __rt.unbox.bind(__rt),
    __rt_Scope = __rt.Scope.bind(__rt),
    __rt_constructor = __rt.constructor.bind(__rt),
    __rt___defineGetter__ = __rt.__defineGetter__.bind(__rt),
    __rt___defineSetter__ = __rt.__defineSetter__.bind(__rt),
    __rt_hasOwnProperty = __rt.hasOwnProperty.bind(__rt),
    __rt___lookupGetter__ = __rt.__lookupGetter__.bind(__rt),
    __rt___lookupSetter__ = __rt.__lookupSetter__.bind(__rt),
    __rt_propertyIsEnumerable = __rt.propertyIsEnumerable.bind(__rt),
    __rt_constructor = __rt.constructor.bind(__rt),
    __rt_toString = __rt.toString.bind(__rt),
    __rt_toLocaleString = __rt.toLocaleString.bind(__rt),
    __rt_valueOf = __rt.valueOf.bind(__rt),
    __rt_isPrototypeOf = __rt.isPrototypeOf.bind(__rt);
var __rt_context = __rt.context,
    __rt_mixins = __rt.mixins,
    __rt_functions = __rt.functions,
    __rt_processors = __rt.processors,
    __rt_registered = __rt.registered,
    __rt_deferredContent = __rt.deferredContent,
    __rt_registerSelectorHooks = __rt.registerSelectorHooks,
    __rt_registerAtRuleHook = __rt.registerAtRuleHook,
    __rt_registerStyleHooks = __rt.registerStyleHooks,
    __rt_registerFunctionCallHooks = __rt.registerFunctionCallHooks,
    __rt_docCache = __rt.docCache,
    __rt_stringCache = __rt.stringCache,
    __rt_nodeCache = __rt.nodeCache,
    __rt_code = __rt.code,
    __rt_fn = __rt.fn,
    __rt__currentScope = __rt._currentScope,
    __rt__currentCallStackScope = __rt._currentCallStackScope,
    __rt__globalScope = __rt._globalScope,
    __rt__dynamics = __rt._dynamics,
    __rt_css = __rt.css,
    __rt_rulesets = __rt.rulesets,
    __rt_extenders = __rt.extenders,
    __rt__scopeStack = __rt._scopeStack;
__rt_setDynamic("$dark-mode", __rt_getGlobalDefault("$dark_mode") || __False, 0);
__rt_setDynamic("$base-color", __rt_getGlobalDefault("$base_color") || __ColorRGBA.fromHex("#333"), 1);
__rt_setDynamic("$base_color_name", __rt_getGlobalDefault("$base_color_name") || new __Text("blue", "'"), 2);
__rt_setDynamic("$material-colors", __rt_getGlobalDefault("$material_colors") || new __Map([new __Text("red", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#ffebee"), new __Text("100", "'"), __ColorRGBA.fromHex("#ffcdd2"), new __Text("200", "'"), __ColorRGBA.fromHex("#ef9a9a"), new __Text("300", "'"), __ColorRGBA.fromHex("#e57373"), new __Text("400", "'"), __ColorRGBA.fromHex("#ef5350"), new __Text("500", "'"), __ColorRGBA.fromHex("#f44336"), new __Text("600", "'"), __ColorRGBA.fromHex("#e53935"), new __Text("700", "'"), __ColorRGBA.fromHex("#d32f2f"), new __Text("800", "'"), __ColorRGBA.fromHex("#c62828"), new __Text("900", "'"), __ColorRGBA.fromHex("#b71c1c"), new __Text("a100", "'"), __ColorRGBA.fromHex("#ff8a80"), new __Text("a200", "'"), __ColorRGBA.fromHex("#ff5252"), new __Text("a400", "'"), __ColorRGBA.fromHex("#ff1744"), new __Text("a700", "'"), __ColorRGBA.fromHex("#d50000")]), new __Text("pink", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#fce4ec"), new __Text("100", "'"), __ColorRGBA.fromHex("#f8bbd0"), new __Text("200", "'"), __ColorRGBA.fromHex("#f48fb1"), new __Text("300", "'"), __ColorRGBA.fromHex("#f06292"), new __Text("400", "'"), __ColorRGBA.fromHex("#ec407a"), new __Text("500", "'"), __ColorRGBA.fromHex("#e91e63"), new __Text("600", "'"), __ColorRGBA.fromHex("#d81b60"), new __Text("700", "'"), __ColorRGBA.fromHex("#c2185b"), new __Text("800", "'"), __ColorRGBA.fromHex("#ad1457"), new __Text("900", "'"), __ColorRGBA.fromHex("#880e4f"), new __Text("a100", "'"), __ColorRGBA.fromHex("#ff80ab"), new __Text("a200", "'"), __ColorRGBA.fromHex("#ff4081"), new __Text("a400", "'"), __ColorRGBA.fromHex("#f50057"), new __Text("a700", "'"), __ColorRGBA.fromHex("#c51162")]), new __Text("purple", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#f3e5f5"), new __Text("100", "'"), __ColorRGBA.fromHex("#e1bee7"), new __Text("200", "'"), __ColorRGBA.fromHex("#ce93d8"), new __Text("300", "'"), __ColorRGBA.fromHex("#ba68c8"), new __Text("400", "'"), __ColorRGBA.fromHex("#ab47bc"), new __Text("500", "'"), __ColorRGBA.fromHex("#9c27b0"), new __Text("600", "'"), __ColorRGBA.fromHex("#8e24aa"), new __Text("700", "'"), __ColorRGBA.fromHex("#7b1fa2"), new __Text("800", "'"), __ColorRGBA.fromHex("#6a1b9a"), new __Text("900", "'"), __ColorRGBA.fromHex("#4a148c"), new __Text("a100", "'"), __ColorRGBA.fromHex("#ea80fc"), new __Text("a200", "'"), __ColorRGBA.fromHex("#e040fb"), new __Text("a400", "'"), __ColorRGBA.fromHex("#d500f9"), new __Text("a700", "'"), __ColorRGBA.fromHex("#aa00ff")]), new __Text("deep-purple", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#ede7f6"), new __Text("100", "'"), __ColorRGBA.fromHex("#d1c4e9"), new __Text("200", "'"), __ColorRGBA.fromHex("#b39ddb"), new __Text("300", "'"), __ColorRGBA.fromHex("#9575cd"), new __Text("400", "'"), __ColorRGBA.fromHex("#7e57c2"), new __Text("500", "'"), __ColorRGBA.fromHex("#673ab7"), new __Text("600", "'"), __ColorRGBA.fromHex("#5e35b1"), new __Text("700", "'"), __ColorRGBA.fromHex("#512da8"), new __Text("800", "'"), __ColorRGBA.fromHex("#4527a0"), new __Text("900", "'"), __ColorRGBA.fromHex("#311b92"), new __Text("a100", "'"), __ColorRGBA.fromHex("#b388ff"), new __Text("a200", "'"), __ColorRGBA.fromHex("#7c4dff"), new __Text("a400", "'"), __ColorRGBA.fromHex("#651fff"), new __Text("a700", "'"), __ColorRGBA.fromHex("#6200ea")]), new __Text("indigo", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#e8eaf6"), new __Text("100", "'"), __ColorRGBA.fromHex("#c5cae9"), new __Text("200", "'"), __ColorRGBA.fromHex("#9fa8da"), new __Text("300", "'"), __ColorRGBA.fromHex("#7986cb"), new __Text("400", "'"), __ColorRGBA.fromHex("#5c6bc0"), new __Text("500", "'"), __ColorRGBA.fromHex("#3f51b5"), new __Text("600", "'"), __ColorRGBA.fromHex("#3949ab"), new __Text("700", "'"), __ColorRGBA.fromHex("#303f9f"), new __Text("800", "'"), __ColorRGBA.fromHex("#283593"), new __Text("900", "'"), __ColorRGBA.fromHex("#1a237e"), new __Text("a100", "'"), __ColorRGBA.fromHex("#8c9eff"), new __Text("a200", "'"), __ColorRGBA.fromHex("#536dfe"), new __Text("a400", "'"), __ColorRGBA.fromHex("#3d5afe"), new __Text("a700", "'"), __ColorRGBA.fromHex("#304ffe")]), new __Text("blue", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#e3f2fd"), new __Text("100", "'"), __ColorRGBA.fromHex("#bbdefb"), new __Text("200", "'"), __ColorRGBA.fromHex("#90caf9"), new __Text("300", "'"), __ColorRGBA.fromHex("#64b5f6"), new __Text("400", "'"), __ColorRGBA.fromHex("#42a5f5"), new __Text("500", "'"), __ColorRGBA.fromHex("#2196f3"), new __Text("600", "'"), __ColorRGBA.fromHex("#1e88e5"), new __Text("700", "'"), __ColorRGBA.fromHex("#1976d2"), new __Text("800", "'"), __ColorRGBA.fromHex("#1565c0"), new __Text("900", "'"), __ColorRGBA.fromHex("#0d47a1"), new __Text("a100", "'"), __ColorRGBA.fromHex("#82b1ff"), new __Text("a200", "'"), __ColorRGBA.fromHex("#448aff"), new __Text("a400", "'"), __ColorRGBA.fromHex("#2979ff"), new __Text("a700", "'"), __ColorRGBA.fromHex("#2962ff")]), new __Text("light-blue", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#e1f5fe"), new __Text("100", "'"), __ColorRGBA.fromHex("#b3e5fc"), new __Text("200", "'"), __ColorRGBA.fromHex("#81d4fa"), new __Text("300", "'"), __ColorRGBA.fromHex("#4fc3f7"), new __Text("400", "'"), __ColorRGBA.fromHex("#29b6f6"), new __Text("500", "'"), __ColorRGBA.fromHex("#03a9f4"), new __Text("600", "'"), __ColorRGBA.fromHex("#039be5"), new __Text("700", "'"), __ColorRGBA.fromHex("#0288d1"), new __Text("800", "'"), __ColorRGBA.fromHex("#0277bd"), new __Text("900", "'"), __ColorRGBA.fromHex("#01579b"), new __Text("a100", "'"), __ColorRGBA.fromHex("#80d8ff"), new __Text("a200", "'"), __ColorRGBA.fromHex("#40c4ff"), new __Text("a400", "'"), __ColorRGBA.fromHex("#00b0ff"), new __Text("a700", "'"), __ColorRGBA.fromHex("#0091ea")]), new __Text("cyan", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#e0f7fa"), new __Text("100", "'"), __ColorRGBA.fromHex("#b2ebf2"), new __Text("200", "'"), __ColorRGBA.fromHex("#80deea"), new __Text("300", "'"), __ColorRGBA.fromHex("#4dd0e1"), new __Text("400", "'"), __ColorRGBA.fromHex("#26c6da"), new __Text("500", "'"), __ColorRGBA.fromHex("#00bcd4"), new __Text("600", "'"), __ColorRGBA.fromHex("#00acc1"), new __Text("700", "'"), __ColorRGBA.fromHex("#0097a7"), new __Text("800", "'"), __ColorRGBA.fromHex("#00838f"), new __Text("900", "'"), __ColorRGBA.fromHex("#006064"), new __Text("a100", "'"), __ColorRGBA.fromHex("#84ffff"), new __Text("a200", "'"), __ColorRGBA.fromHex("#18ffff"), new __Text("a400", "'"), __ColorRGBA.fromHex("#00e5ff"), new __Text("a700", "'"), __ColorRGBA.fromHex("#00b8d4")]), new __Text("teal", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#e0f2f1"), new __Text("100", "'"), __ColorRGBA.fromHex("#b2dfdb"), new __Text("200", "'"), __ColorRGBA.fromHex("#80cbc4"), new __Text("300", "'"), __ColorRGBA.fromHex("#4db6ac"), new __Text("400", "'"), __ColorRGBA.fromHex("#26a69a"), new __Text("500", "'"), __ColorRGBA.fromHex("#009688"), new __Text("600", "'"), __ColorRGBA.fromHex("#00897b"), new __Text("700", "'"), __ColorRGBA.fromHex("#00796b"), new __Text("800", "'"), __ColorRGBA.fromHex("#00695c"), new __Text("900", "'"), __ColorRGBA.fromHex("#004d40"), new __Text("a100", "'"), __ColorRGBA.fromHex("#a7ffeb"), new __Text("a200", "'"), __ColorRGBA.fromHex("#64ffda"), new __Text("a400", "'"), __ColorRGBA.fromHex("#1de9b6"), new __Text("a700", "'"), __ColorRGBA.fromHex("#00bfa5")]), new __Text("green", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#e8f5e9"), new __Text("100", "'"), __ColorRGBA.fromHex("#c8e6c9"), new __Text("200", "'"), __ColorRGBA.fromHex("#a5d6a7"), new __Text("300", "'"), __ColorRGBA.fromHex("#81c784"), new __Text("400", "'"), __ColorRGBA.fromHex("#66bb6a"), new __Text("500", "'"), __ColorRGBA.fromHex("#4caf50"), new __Text("600", "'"), __ColorRGBA.fromHex("#43a047"), new __Text("700", "'"), __ColorRGBA.fromHex("#388e3c"), new __Text("800", "'"), __ColorRGBA.fromHex("#2e7d32"), new __Text("900", "'"), __ColorRGBA.fromHex("#1b5e20"), new __Text("a100", "'"), __ColorRGBA.fromHex("#b9f6ca"), new __Text("a200", "'"), __ColorRGBA.fromHex("#69f0ae"), new __Text("a400", "'"), __ColorRGBA.fromHex("#00e676"), new __Text("a700", "'"), __ColorRGBA.fromHex("#00c853")]), new __Text("light-green", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#f1f8e9"), new __Text("100", "'"), __ColorRGBA.fromHex("#dcedc8"), new __Text("200", "'"), __ColorRGBA.fromHex("#c5e1a5"), new __Text("300", "'"), __ColorRGBA.fromHex("#aed581"), new __Text("400", "'"), __ColorRGBA.fromHex("#9ccc65"), new __Text("500", "'"), __ColorRGBA.fromHex("#8bc34a"), new __Text("600", "'"), __ColorRGBA.fromHex("#7cb342"), new __Text("700", "'"), __ColorRGBA.fromHex("#689f38"), new __Text("800", "'"), __ColorRGBA.fromHex("#558b2f"), new __Text("900", "'"), __ColorRGBA.fromHex("#33691e"), new __Text("a100", "'"), __ColorRGBA.fromHex("#ccff90"), new __Text("a200", "'"), __ColorRGBA.fromHex("#b2ff59"), new __Text("a400", "'"), __ColorRGBA.fromHex("#76ff03"), new __Text("a700", "'"), __ColorRGBA.fromHex("#64dd17")]), new __Text("lime", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#f9fbe7"), new __Text("100", "'"), __ColorRGBA.fromHex("#f0f4c3"), new __Text("200", "'"), __ColorRGBA.fromHex("#e6ee9c"), new __Text("300", "'"), __ColorRGBA.fromHex("#dce775"), new __Text("400", "'"), __ColorRGBA.fromHex("#d4e157"), new __Text("500", "'"), __ColorRGBA.fromHex("#cddc39"), new __Text("600", "'"), __ColorRGBA.fromHex("#c0ca33"), new __Text("700", "'"), __ColorRGBA.fromHex("#afb42b"), new __Text("800", "'"), __ColorRGBA.fromHex("#9e9d24"), new __Text("900", "'"), __ColorRGBA.fromHex("#827717"), new __Text("a100", "'"), __ColorRGBA.fromHex("#f4ff81"), new __Text("a200", "'"), __ColorRGBA.fromHex("#eeff41"), new __Text("a400", "'"), __ColorRGBA.fromHex("#c6ff00"), new __Text("a700", "'"), __ColorRGBA.fromHex("#aeea00")]), new __Text("yellow", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#fffde7"), new __Text("100", "'"), __ColorRGBA.fromHex("#fff9c4"), new __Text("200", "'"), __ColorRGBA.fromHex("#fff59d"), new __Text("300", "'"), __ColorRGBA.fromHex("#fff176"), new __Text("400", "'"), __ColorRGBA.fromHex("#ffee58"), new __Text("500", "'"), __ColorRGBA.fromHex("#ffeb3b"), new __Text("600", "'"), __ColorRGBA.fromHex("#fdd835"), new __Text("700", "'"), __ColorRGBA.fromHex("#fbc02d"), new __Text("800", "'"), __ColorRGBA.fromHex("#f9a825"), new __Text("900", "'"), __ColorRGBA.fromHex("#f57f17"), new __Text("a100", "'"), __ColorRGBA.fromHex("#ffff8d"), new __Text("a200", "'"), __ColorRGBA.fromHex("#ffff00"), new __Text("a400", "'"), __ColorRGBA.fromHex("#ffea00"), new __Text("a700", "'"), __ColorRGBA.fromHex("#ffd600")]), new __Text("amber", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#fff8e1"), new __Text("100", "'"), __ColorRGBA.fromHex("#ffecb3"), new __Text("200", "'"), __ColorRGBA.fromHex("#ffe082"), new __Text("300", "'"), __ColorRGBA.fromHex("#ffd54f"), new __Text("400", "'"), __ColorRGBA.fromHex("#ffca28"), new __Text("500", "'"), __ColorRGBA.fromHex("#ffc107"), new __Text("600", "'"), __ColorRGBA.fromHex("#ffb300"), new __Text("700", "'"), __ColorRGBA.fromHex("#ffa000"), new __Text("800", "'"), __ColorRGBA.fromHex("#ff8f00"), new __Text("900", "'"), __ColorRGBA.fromHex("#ff6f00"), new __Text("a100", "'"), __ColorRGBA.fromHex("#ffe57f"), new __Text("a200", "'"), __ColorRGBA.fromHex("#ffd740"), new __Text("a400", "'"), __ColorRGBA.fromHex("#ffc400"), new __Text("a700", "'"), __ColorRGBA.fromHex("#ffab00")]), new __Text("orange", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#fff3e0"), new __Text("100", "'"), __ColorRGBA.fromHex("#ffe0b2"), new __Text("200", "'"), __ColorRGBA.fromHex("#ffcc80"), new __Text("300", "'"), __ColorRGBA.fromHex("#ffb74d"), new __Text("400", "'"), __ColorRGBA.fromHex("#ffa726"), new __Text("500", "'"), __ColorRGBA.fromHex("#ff9800"), new __Text("600", "'"), __ColorRGBA.fromHex("#fb8c00"), new __Text("700", "'"), __ColorRGBA.fromHex("#f57c00"), new __Text("800", "'"), __ColorRGBA.fromHex("#ef6c00"), new __Text("900", "'"), __ColorRGBA.fromHex("#e65100"), new __Text("a100", "'"), __ColorRGBA.fromHex("#ffd180"), new __Text("a200", "'"), __ColorRGBA.fromHex("#ffab40"), new __Text("a400", "'"), __ColorRGBA.fromHex("#ff9100"), new __Text("a700", "'"), __ColorRGBA.fromHex("#ff6d00")]), new __Text("deep-orange", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#fbe9e7"), new __Text("100", "'"), __ColorRGBA.fromHex("#ffccbc"), new __Text("200", "'"), __ColorRGBA.fromHex("#ffab91"), new __Text("300", "'"), __ColorRGBA.fromHex("#ff8a65"), new __Text("400", "'"), __ColorRGBA.fromHex("#ff7043"), new __Text("500", "'"), __ColorRGBA.fromHex("#ff5722"), new __Text("600", "'"), __ColorRGBA.fromHex("#f4511e"), new __Text("700", "'"), __ColorRGBA.fromHex("#e64a19"), new __Text("800", "'"), __ColorRGBA.fromHex("#d84315"), new __Text("900", "'"), __ColorRGBA.fromHex("#bf360c"), new __Text("a100", "'"), __ColorRGBA.fromHex("#ff9e80"), new __Text("a200", "'"), __ColorRGBA.fromHex("#ff6e40"), new __Text("a400", "'"), __ColorRGBA.fromHex("#ff3d00"), new __Text("a700", "'"), __ColorRGBA.fromHex("#dd2c00")]), new __Text("brown", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#efebe9"), new __Text("100", "'"), __ColorRGBA.fromHex("#d7ccc8"), new __Text("200", "'"), __ColorRGBA.fromHex("#bcaaa4"), new __Text("300", "'"), __ColorRGBA.fromHex("#a1887f"), new __Text("400", "'"), __ColorRGBA.fromHex("#8d6e63"), new __Text("500", "'"), __ColorRGBA.fromHex("#795548"), new __Text("600", "'"), __ColorRGBA.fromHex("#6d4c41"), new __Text("700", "'"), __ColorRGBA.fromHex("#5d4037"), new __Text("800", "'"), __ColorRGBA.fromHex("#4e342e"), new __Text("900", "'"), __ColorRGBA.fromHex("#3e2723")]), new __Text("grey", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#fafafa"), new __Text("100", "'"), __ColorRGBA.fromHex("#f5f5f5"), new __Text("200", "'"), __ColorRGBA.fromHex("#eeeeee"), new __Text("300", "'"), __ColorRGBA.fromHex("#e0e0e0"), new __Text("400", "'"), __ColorRGBA.fromHex("#bdbdbd"), new __Text("500", "'"), __ColorRGBA.fromHex("#9e9e9e"), new __Text("600", "'"), __ColorRGBA.fromHex("#757575"), new __Text("700", "'"), __ColorRGBA.fromHex("#616161"), new __Text("800", "'"), __ColorRGBA.fromHex("#424242"), new __Text("900", "'"), __ColorRGBA.fromHex("#212121")]), new __Text("blue-grey", "'"), new __Map([new __Text("50", "'"), __ColorRGBA.fromHex("#eceff1"), new __Text("100", "'"), __ColorRGBA.fromHex("#cfd8dc"), new __Text("200", "'"), __ColorRGBA.fromHex("#b0bec5"), new __Text("300", "'"), __ColorRGBA.fromHex("#90a4ae"), new __Text("400", "'"), __ColorRGBA.fromHex("#78909c"), new __Text("500", "'"), __ColorRGBA.fromHex("#607d8b"), new __Text("600", "'"), __ColorRGBA.fromHex("#546e7a"), new __Text("700", "'"), __ColorRGBA.fromHex("#455a64"), new __Text("800", "'"), __ColorRGBA.fromHex("#37474f"), new __Text("900", "'"), __ColorRGBA.fromHex("#263238"), new __Text("1000", "'"), __ColorRGBA.fromHex("#11171a")])]), 3);
__rt_setDynamic("$base-highlight-color", __rt_getGlobalDefault("$base_highlight_color") || __rt_box((__rt_functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$base_color_name"), 
    new __Text("300", "'")]))), 4);
__rt_setDynamic("$base-light-color", __rt_getGlobalDefault("$base_light_color") || __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$base_color_name"), 
    new __Text("100", "'")]))), 5);
__rt_setDynamic("$base-dark-color", __rt_getGlobalDefault("$base_dark_color") || __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$base_color_name"), 
    new __Text("700", "'")]))), 6);
__rt_setDynamic("$base-pressed-color", __rt_getGlobalDefault("$base_pressed_color") || __rt_box(__rt_registered.darken.apply(__rt.registered, __rt_applySpreadArgs([
    (__rt_test(__rt_get("$dark_mode")) ? __rt_box(__rt.registered.darken.apply(__rt.registered, __rt_applySpreadArgs([
        __rt_get("$base_color"), 
        new __Numeric(15, "%")]))) : __rt_box(__rt.registered.lighten.apply(__rt.registered, __rt_applySpreadArgs([
        __rt_get("$base_color"), 
        new __Numeric(15, "%")])))), 
    new __Numeric(0, "%")]))), 7);
__rt_setDynamic("$base-focused-color", __rt_getGlobalDefault("$base_focused_color") || __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$base_color_name"), 
    new __Text("400", "'")]))), 8);
__rt_setDynamic("$base-invisible-color", __rt_getGlobalDefault("$base_invisible_color") || __rt_box(__rt.registered.rgba.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$base_color"), 
    new __Numeric(0), 
    __udf, 
    __udf, 
    __udf]))), 9);
__rt_setDynamic("$material-foreground-colors", __rt_getGlobalDefault("$material_foreground_colors") || new __Map([new __Text("red", "'"), __ColorRGBA.fromHex("#fff"), new __Text("pink", "'"), __ColorRGBA.fromHex("#fff"), new __Text("purple", "'"), __ColorRGBA.fromHex("#fff"), new __Text("deep-purple", "'"), __ColorRGBA.fromHex("#fff"), new __Text("indigo", "'"), __ColorRGBA.fromHex("#fff"), new __Text("blue", "'"), __ColorRGBA.fromHex("#fff"), new __Text("light-blue", "'"), __ColorRGBA.fromHex("#fff"), new __Text("cyan", "'"), __ColorRGBA.fromHex("#fff"), new __Text("teal", "'"), __ColorRGBA.fromHex("#fff"), new __Text("green", "'"), __ColorRGBA.fromHex("#fff"), new __Text("light-green", "'"), __ColorRGBA.fromHex("#222"), new __Text("lime", "'"), __ColorRGBA.fromHex("#222"), new __Text("yellow", "'"), __ColorRGBA.fromHex("#222"), new __Text("amber", "'"), __ColorRGBA.fromHex("#222"), new __Text("orange", "'"), __ColorRGBA.fromHex("#222"), new __Text("deep-orange", "'"), __ColorRGBA.fromHex("#fff"), new __Text("brown", "'"), __ColorRGBA.fromHex("#fff"), new __Text("grey", "'"), __ColorRGBA.fromHex("#222"), new __Text("blue-grey", "'"), __ColorRGBA.fromHex("#fff")]), 10);
__rt_setDynamic("$base-foreground-color", __rt_getGlobalDefault("$base_foreground_color") || __rt_box((__rt.functions.material_foreground_color || material_foreground_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$base_color_name")]))), 11);
__rt_setDynamic("$accent_color_name", __rt_getGlobalDefault("$accent_color_name") || new __Text("orange", "'"), 12);
__rt_setDynamic("$accent-color", __rt_getGlobalDefault("$accent_color") || __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$accent_color_name"), 
    new __Text("500", "'")]))), 13);
__rt_setDynamic("$accent-light-color", __rt_getGlobalDefault("$accent_light_color") || __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$accent_color_name"), 
    new __Text("100", "'")]))), 14);
__rt_setDynamic("$accent-dark-color", __rt_getGlobalDefault("$accent_dark_color") || __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$accent_color_name"), 
    new __Text("700", "'")]))), 15);
__rt_setDynamic("$accent-pressed-color", __rt_getGlobalDefault("$accent_pressed_color") || (__rt_test(__rt_get("$dark_mode")) ? __rt_box(__rt.registered.darken.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$accent_color"), 
    new __Numeric(15, "%")]))) : __rt_box(__rt.registered.lighten.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$accent_color"), 
    new __Numeric(15, "%")])))), 16);
__rt_setDynamic("$accent-invisible-color", __rt_getGlobalDefault("$accent_invisible_color") || __rt_box(__rt.registered.rgba.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$accent_color"), 
    new __Numeric(0), 
    __udf, 
    __udf, 
    __udf]))), 17);
__rt_setDynamic("$accent-foreground-color", __rt_getGlobalDefault("$accent_foreground_color") || __rt_box((__rt.functions.material_foreground_color || material_foreground_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    __rt_get("$accent_color_name")]))), 18);
__rt_setDynamic("$confirm-color", __rt_getGlobalDefault("$confirm_color") || __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    new __Text("light-green", "'"), 
    new __Text("600", "'")]))), 19);
__rt_setDynamic("$confirm-pressed-color", __rt_getGlobalDefault("$confirm_pressed_color") || (__rt_test(__rt_get("$dark_mode")) ? __rt_box(__rt.registered.darken.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$confirm_color"), 
    new __Numeric(15, "%")]))) : __rt_box(__rt.registered.lighten.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$confirm_color"), 
    new __Numeric(15, "%")])))), 20);
__rt_setDynamic("$secondary_color", __rt_getGlobalDefault("$secondary_color") || __ColorRGBA.fromHex("#DD0B2F"), 21);
__rt_setDynamic("$alert-color", __rt_getGlobalDefault("$alert_color") || __rt_get("$secondary_color"), 22);
__rt_setDynamic("$alert-pressed-color", __rt_getGlobalDefault("$alert_pressed_color") || (__rt_test(__rt_get("$dark_mode")) ? __rt_box(__rt.registered.darken.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$alert_color"), 
    new __Numeric(15, "%")]))) : __rt_box(__rt.registered.lighten.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$alert_color"), 
    new __Numeric(15, "%")])))), 23);
__rt_setDynamic(__strings._, __rt_getGlobalDefault(__strings._) || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#fff") : __ColorRGBA.fromHex("#111111")), 24);
__rt_setDynamic("$reverse-color", __rt_getGlobalDefault("$reverse_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#222") : __ColorRGBA.fromHex("#fff")), 25);
__rt_setDynamic("$highlight-color", __rt_getGlobalDefault("$highlight_color") || __rt_box(__rt.registered.rgba.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get(__strings._), 
    new __Numeric(0.54), 
    __udf, 
    __udf, 
    __udf]))), 26);
__rt_setDynamic("$disabled-color", __rt_getGlobalDefault("$disabled_color") || __rt_box(__rt.registered.rgba.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get(__strings._), 
    new __Numeric(0.38), 
    __udf, 
    __udf, 
    __udf]))), 27);
__rt_setDynamic("$reverse-disabled-color", __rt_getGlobalDefault("$reverse_disabled_color") || __rt_box(__rt.registered.rgba.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get("$reverse_color"), 
    new __Numeric(0.38), 
    __udf, 
    __udf, 
    __udf]))), 28);
__rt_setDynamic("$divider-color", __rt_getGlobalDefault("$divider_color") || __rt_box(__rt.registered.mix.apply(__rt.registered, __rt_applySpreadArgs([
    __rt_get(__strings._), 
    __rt_get("$reverse_color"), 
    new __Numeric(12, "%")]))), 29);
__rt_setDynamic("$selected-background-color", __rt_getGlobalDefault("$selected_background_color") || (__rt_test(__rt_get("$dark_mode")) ? __rt_get("$base_dark_color") : __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    new __Text("grey", "'"), 
    new __Text("300", "'")])))), 30);
__rt_setDynamic("$hovered-background-color", __rt_getGlobalDefault("$hovered_background_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#4d4d4d") : __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    new __Text("grey", "'"), 
    new __Text("200", "'")])))), 31);
__rt_setDynamic("$header-background-color", __rt_getGlobalDefault("$header_background_color") || (__rt_test(__rt_get("$dark_mode")) ? __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    new __Text("grey", "'"), 
    new __Text("800", "'")]))) : __rt_box((__rt.functions.material_color || material_color__fn).apply(__rt.functions, __rt_applySpreadArgs([
    new __Text("grey", "'"), 
    new __Text("100", "'")])))), 32);
__rt_setDynamic("$faded-color", __rt_getGlobalDefault("$faded_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#4d4d4d") : __ColorRGBA.fromHex("#e1e1e1")), 33);
__rt_setDynamic("$background-color", __rt_getGlobalDefault("$background_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#303030") : __ColorRGBA.fromHex("#fafafa")), 34);
__rt_setDynamic("$alt-background-color", __rt_getGlobalDefault("$alt_background_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#3a3a3a") : __ColorRGBA.fromHex("#f5f5f5")), 35);
__rt_setDynamic("$reverse-background-color", __rt_getGlobalDefault("$reverse_background_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#fafafa") : __ColorRGBA.fromHex("#303030")), 36);
__rt_setDynamic("$reverse-alt-background-color", __rt_getGlobalDefault("$reverse_alt_background_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#f5f5f5") : __ColorRGBA.fromHex("#3a3a3a")), 37);
__rt_setDynamic("$overlay-color", __rt_getGlobalDefault("$overlay_color") || (__rt_test(__rt_get("$dark_mode")) ? __rt_box(__rt.registered.rgba.apply(__rt.registered, __rt_applySpreadArgs([
    __ColorRGBA.fromHex("#fff"), 
    new __Numeric(0.03), 
    __udf, 
    __udf, 
    __udf]))) : __rt_box(__rt.registered.rgba.apply(__rt.registered, __rt_applySpreadArgs([
    __ColorRGBA.fromHex("#000"), 
    new __Numeric(0.03), 
    __udf, 
    __udf, 
    __udf])))), 38);
__rt_setDynamic("$content-padding", __rt_getGlobalDefault("$content_padding") || new __Numeric(16, "px"), 39);
__rt_setDynamic("$dataview_item_selected_background_color", __rt_getGlobalDefault("$dataview_item_selected_background_color") || __rt_get("$selected_background_color"), 40);
__rt_setDynamic("$dataitem_selected_background_color", __rt_getGlobalDefault("$dataitem_selected_background_color") || __rt_get("$dataview_item_selected_background_color"), 41);
__rt_setDynamic("$listitem-selected-background-color", __rt_getGlobalDefault("$listitem_selected_background_color") || __rt_get("$dataitem_selected_background_color"), 42);
__rt_setDynamic("$reverse-border-color", __rt_getGlobalDefault("$reverse_border_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#212121") : __ColorRGBA.fromHex("#e0e0e0")), 43);
__rt_setDynamic("$reverse-alt-border-color", __rt_getGlobalDefault("$reverse_alt_border_color") || (__rt_test(__rt_get("$dark_mode")) ? __ColorRGBA.fromHex("#3a3a3a") : __ColorRGBA.fromHex("#e0e0e0")), 44);
},
 {
	":root": [
		"dark-mode",
		"base-color",
		"base-highlight-color",
		"base-light-color",
		"base-dark-color",
		"base-pressed-color",
		"base-focused-color",
		"base-invisible-color",
		"base-foreground-color",
		"accent-color",
		"accent-light-color",
		"accent-dark-color",
		"accent-pressed-color",
		"accent-invisible-color",
		"accent-foreground-color",
		"confirm-color",
		"confirm-pressed-color",
		"alert-color",
		"alert-pressed-color",
		__names._,
		"reverse-color",
		"highlight-color",
		"disabled-color",
		"reverse-disabled-color",
		"divider-color",
		"selected-background-color",
		"hovered-background-color",
		"header-background-color",
		"faded-color",
		"background-color",
		"alt-background-color",
		"reverse-background-color",
		"reverse-alt-background-color",
		"overlay-color",
		"content-padding",
		"listitem-selected-background-color",
		"reverse-border-color",
		"reverse-alt-border-color"
	],
	"html": [
		"base_color_name",
		"accent_color_name",
		"secondary_color",
		"dataview_item_selected_background_color",
		"dataitem_selected_background_color"
	]});
})(Fashion);