From bb86d71b6f1c4dc2c1a564f7225f2b714ce854b2 Mon Sep 17 00:00:00 2001
From: "florian.azizian" <florian.azizian@maarch.org>
Date: Mon, 10 Feb 2020 23:56:30 +0100
Subject: [PATCH] clean old code

---
 .../indexing_searching/ajaxShowCodePostal.php |    26 -
 .../indexing_searching/ajaxShowVille.php      |    26 -
 apps/maarch_entreprise/js/RSVP.js             |  1026 --
 apps/maarch_entreprise/js/functions.js        |    41 -
 apps/maarch_entreprise/js/jio.js              | 12842 ----------------
 apps/maarch_entreprise/js/render.js           |  2350 ---
 apps/maarch_entreprise/merged_jsAbstract.php  |     4 -
 .../xml/IVS/requests_definitions.xml          |    12 -
 .../xml/IVS/validation_rules.xml              |    12 -
 core/class/usergroups_controler.php           |     4 +-
 modules/basket/basket_tables.php              |     5 -
 .../class/class_modules_tools_Abstract.php    |   225 +-
 modules/basket/css/module.css                 |   113 -
 modules/basket/lang/en.php                    |    43 -
 modules/basket/lang/fr.php                    |    43 -
 modules/basket/lang/nl.php                    |    63 -
 src/frontend/app/about-us.component.html      |     8 +-
 17 files changed, 8 insertions(+), 16835 deletions(-)
 delete mode 100755 apps/maarch_entreprise/indexing_searching/ajaxShowCodePostal.php
 delete mode 100755 apps/maarch_entreprise/indexing_searching/ajaxShowVille.php
 delete mode 100755 apps/maarch_entreprise/js/RSVP.js
 delete mode 100755 apps/maarch_entreprise/js/jio.js
 delete mode 100755 apps/maarch_entreprise/js/render.js
 delete mode 100755 modules/basket/basket_tables.php

diff --git a/apps/maarch_entreprise/indexing_searching/ajaxShowCodePostal.php b/apps/maarch_entreprise/indexing_searching/ajaxShowCodePostal.php
deleted file mode 100755
index c60c44661a0..00000000000
--- a/apps/maarch_entreprise/indexing_searching/ajaxShowCodePostal.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-require_once("core" . DIRECTORY_SEPARATOR . "class" . DIRECTORY_SEPARATOR . "class_request.php");
-
-$row = 1;
-$handle = fopen($_SESSION['config']['corepath'] . "apps" . DIRECTORY_SEPARATOR . $_SESSION['config']['app_id'] .
-    DIRECTORY_SEPARATOR . "tools/referentiel/code_postaux_v201410.csv", "r");
-
-$request = new request();
-
-echo "<ul>\n";
-while (($data = fgetcsv($handle, 1000, ";")) !== false) {
-    $num = count($data);
-
-    for ($c = 0; $c < $num; $c++) {
-        $pos = stripos($data[3], $_POST['what']);
-        if ($pos === 0) {
-            echo '<li id="' . $data[2] . ',' . $request->show_string(trim($data[3])) . '">' . $data[2] . ' - ' . $request->show_string(trim($data[3])) . '</li>';
-            break;
-        }
-    }
-    $row++;
-}
-echo "</ul>";
-fclose($handle);
-?>
\ No newline at end of file
diff --git a/apps/maarch_entreprise/indexing_searching/ajaxShowVille.php b/apps/maarch_entreprise/indexing_searching/ajaxShowVille.php
deleted file mode 100755
index 0a4a0a2c619..00000000000
--- a/apps/maarch_entreprise/indexing_searching/ajaxShowVille.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-require_once("core" . DIRECTORY_SEPARATOR . "class" . DIRECTORY_SEPARATOR . "class_request.php");
-
-$row = 1;
-$handle = fopen($_SESSION['config']['corepath'] . "apps" . DIRECTORY_SEPARATOR . $_SESSION['config']['app_id'] .
-    DIRECTORY_SEPARATOR . "tools/referentiel/code_postaux_v201410.csv", "r");
-
-$request = new request();
-
-echo "<ul>\n";
-while (($data = fgetcsv($handle, 1000, ";")) !== false) {
-    $num = count($data);
-
-    for ($c = 0; $c < $num; $c++) {
-        $pos = stripos($data[2], $_POST['what']);
-        if ($pos === 0) {
-            echo '<li id="' . $data[2] . ',' . $request->show_string(trim($data[3])) . '">' . $data[2] . ' - ' . $request->show_string(trim($data[3])) . '</li>';
-            break;
-        }
-    }
-    $row++;
-}
-echo "</ul>";
-fclose($handle);
-?>
\ No newline at end of file
diff --git a/apps/maarch_entreprise/js/RSVP.js b/apps/maarch_entreprise/js/RSVP.js
deleted file mode 100755
index 666e3092596..00000000000
--- a/apps/maarch_entreprise/js/RSVP.js
+++ /dev/null
@@ -1,1026 +0,0 @@
-(function(globals) {
-var define, requireModule;
-
-(function() {
-  var registry = {}, seen = {};
-
-  define = function(name, deps, callback) {
-    registry[name] = { deps: deps, callback: callback };
-  };
-
-  requireModule = function(name) {
-    if (seen[name]) { return seen[name]; }
-    seen[name] = {};
-
-    var mod = registry[name];
-    if (!mod) {
-      throw new Error("Module '" + name + "' not found.");
-    }
-
-    var deps = mod.deps,
-        callback = mod.callback,
-        reified = [],
-        exports;
-
-    for (var i=0, l=deps.length; i<l; i++) {
-      if (deps[i] === 'exports') {
-        reified.push(exports = {});
-      } else {
-        reified.push(requireModule(deps[i]));
-      }
-    }
-
-    var value = callback.apply(this, reified);
-    return seen[name] = exports || value;
-  };
-})();
-
-define("rsvp/all",
-  ["rsvp/promise","exports"],
-  function(__dependency1__, __exports__) {
-    "use strict";
-    var Promise = __dependency1__.Promise;
-    /* global toString */
-
-
-    function promiseAtLeast(expected_count, promises) {
-      if (Object.prototype.toString.call(promises) !== "[object Array]") {
-        throw new TypeError('You must pass an array to all.');
-      }
-
-      function canceller() {
-        var promise;
-        for (var i = 0; i < promises.length; i++) {
-          promise = promises[i];
-
-          if (promise && typeof promise.then === 'function' &&
-              typeof promise.cancel === 'function') {
-            promise.cancel();
-          }
-        }
-      }
-
-      return new Promise(function(resolve, reject, notify) {
-        var results = [], remaining = promises.length,
-        promise, remaining_count = promises.length - expected_count;
-
-        if (remaining === 0) {
-          if (expected_count === 1) {
-            resolve();
-          } else {
-            resolve([]);
-          }
-        }
-
-        function resolver(index) {
-          return function(value) {
-            resolveAll(index, value);
-          };
-        }
-
-        function resolveAll(index, value) {
-          results[index] = value;
-          if (--remaining === remaining_count) {
-            if (remaining_count === 0) {
-              resolve(results);
-            } else {
-              resolve(value);
-              canceller();
-            }
-          }
-        }
-
-        function notifier(index) {
-          return function(value) {
-            notify({"index": index, "value": value});
-          };
-        }
-
-        function cancelAll(rejectionValue) {
-          reject(rejectionValue);
-          canceller();
-        }
-
-        for (var i = 0; i < promises.length; i++) {
-          promise = promises[i];
-
-          if (promise && typeof promise.then === 'function') {
-            promise.then(resolver(i), cancelAll, notifier(i));
-          } else {
-            resolveAll(i, promise);
-          }
-        }
-      }, canceller
-      );
-    }
-
-    function all(promises) {
-      return promiseAtLeast(promises.length, promises);
-    }
-
-    function any(promises) {
-      return promiseAtLeast(1, promises);
-    }
-
-
-    __exports__.all = all;
-    __exports__.any = any;
-  });
-define("rsvp/async",
-  ["exports"],
-  function(__exports__) {
-    "use strict";
-    var browserGlobal = (typeof window !== 'undefined') ? window : {};
-    var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
-    var async;
-    var local = (typeof global !== 'undefined') ? global : this;
-
-    function checkNativePromise() {
-      if (typeof Promise === "function" &&
-          typeof Promise.resolve === "function") {
-        try {
-          /* global Promise */
-          var promise = new Promise(function(){});
-          if ({}.toString.call(promise) === "[object Promise]") {
-            return true;
-          }
-        } catch (e) {}
-      }
-      return false;
-    }
-
-    function useNativePromise() {
-      var nativePromise = Promise.resolve();
-      return function(callback, arg) {
-        nativePromise.then(function () {
-          callback(arg);
-        });
-      };
-    }
-
-    // old node
-    function useNextTick() {
-      return function(callback, arg) {
-        process.nextTick(function() {
-          callback(arg);
-        });
-      };
-    }
-
-    // node >= 0.10.x
-    function useSetImmediate() {
-      return function(callback, arg) {
-        /* global  setImmediate */
-        setImmediate(function(){
-          callback(arg);
-        });
-      };
-    }
-
-    function useMutationObserver() {
-      var queue = [];
-
-      var observer = new BrowserMutationObserver(function() {
-        var toProcess = queue.slice();
-        queue = [];
-
-        toProcess.forEach(function(tuple) {
-          var callback = tuple[0], arg= tuple[1];
-          callback(arg);
-        });
-      });
-
-      var element = document.createElement('div');
-      observer.observe(element, { attributes: true });
-
-      // Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
-      window.addEventListener('unload', function(){
-        observer.disconnect();
-        observer = null;
-      }, false);
-
-      return function(callback, arg) {
-        queue.push([callback, arg]);
-        element.setAttribute('drainQueue', 'drainQueue');
-      };
-    }
-
-    function useSetTimeout() {
-      return function(callback, arg) {
-        local.setTimeout(function() {
-          callback(arg);
-        }, 1);
-      };
-    }
-
-    if (typeof setImmediate === 'function') {
-      async = useSetImmediate();
-    } else if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
-      async = useNextTick();
-    } else if (BrowserMutationObserver) {
-      async = useMutationObserver();
-    } else if (checkNativePromise()) {
-      async = useNativePromise();
-    } else {
-      async = useSetTimeout();
-    }
-
-
-    __exports__.async = async;
-  });
-define("rsvp/cancellation_error",
-  ["exports"],
-  function(__exports__) {
-    "use strict";
-    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
-    function CancellationError(message) {
-      this.name = "cancel";
-      if ((message !== undefined) && (typeof message !== "string")) {
-        throw new TypeError('You must pass a string.');
-      }
-      this.message = message || "Default Message";
-    }
-    CancellationError.prototype = new Error();
-    CancellationError.prototype.constructor = CancellationError;
-
-
-    __exports__.CancellationError = CancellationError;
-  });
-define("rsvp/config",
-  ["rsvp/async","exports"],
-  function(__dependency1__, __exports__) {
-    "use strict";
-    var async = __dependency1__.async;
-
-    var config = {};
-    config.async = async;
-
-
-    __exports__.config = config;
-  });
-define("rsvp/defer",
-  ["rsvp/promise","exports"],
-  function(__dependency1__, __exports__) {
-    "use strict";
-    var Promise = __dependency1__.Promise;
-
-    function defer() {
-      var deferred = {
-        // pre-allocate shape
-        resolve: undefined,
-        reject:  undefined,
-        promise: undefined
-      };
-
-      deferred.promise = new Promise(function(resolve, reject) {
-        deferred.resolve = resolve;
-        deferred.reject = reject;
-      });
-
-      return deferred;
-    }
-
-
-    __exports__.defer = defer;
-  });
-define("rsvp/events",
-  ["exports"],
-  function(__exports__) {
-    "use strict";
-    var Event = function(type, options) {
-      this.type = type;
-
-      for (var option in options) {
-        if (!options.hasOwnProperty(option)) { continue; }
-
-        this[option] = options[option];
-      }
-    };
-
-    var indexOf = function(callbacks, callback) {
-      for (var i=0, l=callbacks.length; i<l; i++) {
-        if (callbacks[i][0] === callback) { return i; }
-      }
-
-      return -1;
-    };
-
-    var callbacksFor = function(object) {
-      var callbacks = object._promiseCallbacks;
-
-      if (!callbacks) {
-        callbacks = object._promiseCallbacks = {};
-      }
-
-      return callbacks;
-    };
-
-    var EventTarget = {
-      mixin: function(object) {
-        object.on = this.on;
-        object.off = this.off;
-        object.trigger = this.trigger;
-        return object;
-      },
-
-      on: function(eventNames, callback, binding) {
-        var allCallbacks = callbacksFor(this), callbacks, eventName;
-        eventNames = eventNames.split(/\s+/);
-        binding = binding || this;
-
-        while (eventName = eventNames.shift()) {
-          callbacks = allCallbacks[eventName];
-
-          if (!callbacks) {
-            callbacks = allCallbacks[eventName] = [];
-          }
-
-          if (indexOf(callbacks, callback) === -1) {
-            callbacks.push([callback, binding]);
-          }
-        }
-      },
-
-      off: function(eventNames, callback) {
-        var allCallbacks = callbacksFor(this), callbacks, eventName, index;
-        eventNames = eventNames.split(/\s+/);
-
-        while (eventName = eventNames.shift()) {
-          if (!callback) {
-            allCallbacks[eventName] = [];
-            continue;
-          }
-
-          callbacks = allCallbacks[eventName];
-
-          index = indexOf(callbacks, callback);
-
-          if (index !== -1) { callbacks.splice(index, 1); }
-        }
-      },
-
-      trigger: function(eventName, options) {
-        var allCallbacks = callbacksFor(this),
-            callbacks, callbackTuple, callback, binding, event;
-
-        if (callbacks = allCallbacks[eventName]) {
-          // Don't cache the callbacks.length since it may grow
-          for (var i=0; i<callbacks.length; i++) {
-            callbackTuple = callbacks[i];
-            callback = callbackTuple[0];
-            binding = callbackTuple[1];
-
-            if (typeof options !== 'object') {
-              options = { detail: options };
-            }
-
-            event = new Event(eventName, options);
-            callback.call(binding, event);
-          }
-        }
-      }
-    };
-
-
-    __exports__.EventTarget = EventTarget;
-  });
-define("rsvp/hash",
-  ["rsvp/defer","exports"],
-  function(__dependency1__, __exports__) {
-    "use strict";
-    var defer = __dependency1__.defer;
-
-    function size(object) {
-      var s = 0;
-
-      for (var prop in object) {
-        s++;
-      }
-
-      return s;
-    }
-
-    function hash(promises) {
-      var results = {}, deferred = defer(), remaining = size(promises);
-
-      if (remaining === 0) {
-        deferred.resolve({});
-      }
-
-      var resolver = function(prop) {
-        return function(value) {
-          resolveAll(prop, value);
-        };
-      };
-
-      var resolveAll = function(prop, value) {
-        results[prop] = value;
-        if (--remaining === 0) {
-          deferred.resolve(results);
-        }
-      };
-
-      var rejectAll = function(error) {
-        deferred.reject(error);
-      };
-
-      for (var prop in promises) {
-        if (promises[prop] && typeof promises[prop].then === 'function') {
-          promises[prop].then(resolver(prop), rejectAll);
-        } else {
-          resolveAll(prop, promises[prop]);
-        }
-      }
-
-      return deferred.promise;
-    }
-
-
-    __exports__.hash = hash;
-  });
-define("rsvp/node",
-  ["rsvp/promise","rsvp/all","exports"],
-  function(__dependency1__, __dependency2__, __exports__) {
-    "use strict";
-    var Promise = __dependency1__.Promise;
-    var all = __dependency2__.all;
-
-    function makeNodeCallbackFor(resolve, reject) {
-      return function (error, value) {
-        if (error) {
-          reject(error);
-        } else if (arguments.length > 2) {
-          resolve(Array.prototype.slice.call(arguments, 1));
-        } else {
-          resolve(value);
-        }
-      };
-    }
-
-    function denodeify(nodeFunc) {
-      return function()  {
-        var nodeArgs = Array.prototype.slice.call(arguments), resolve, reject;
-        var thisArg = this;
-
-        var promise = new Promise(function(nodeResolve, nodeReject) {
-          resolve = nodeResolve;
-          reject = nodeReject;
-        });
-
-        all(nodeArgs).then(function(nodeArgs) {
-          nodeArgs.push(makeNodeCallbackFor(resolve, reject));
-
-          try {
-            nodeFunc.apply(thisArg, nodeArgs);
-          } catch(e) {
-            reject(e);
-          }
-        });
-
-        return promise;
-      };
-    }
-
-
-    __exports__.denodeify = denodeify;
-  });
-define("rsvp/promise",
-  ["rsvp/config","rsvp/events","rsvp/cancellation_error","exports"],
-  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
-    "use strict";
-    var config = __dependency1__.config;
-    var EventTarget = __dependency2__.EventTarget;
-    var CancellationError = __dependency3__.CancellationError;
-
-    function objectOrFunction(x) {
-      return isFunction(x) || (typeof x === "object" && x !== null);
-    }
-
-    function isFunction(x){
-      return typeof x === "function";
-    }
-
-    var Promise = function(resolver, canceller) {
-      var promise = this,
-      resolved = false;
-
-      if (typeof resolver !== 'function') {
-        throw new TypeError('You must pass a resolver function as the sole argument to the promise constructor');
-      }
-
-      if ((canceller !== undefined) && (typeof canceller !== 'function')) {
-        throw new TypeError('You can only pass a canceller function' +
-          ' as the second argument to the promise constructor');
-      }
-
-      if (!(promise instanceof Promise)) {
-        return new Promise(resolver, canceller);
-      }
-
-      var resolvePromise = function(value) {
-        if (resolved) { return; }
-        resolved = true;
-        resolve(promise, value);
-      };
-
-      var rejectPromise = function(value) {
-        if (resolved) { return; }
-        resolved = true;
-        reject(promise, value);
-      };
-
-      var notifyPromise = function(value) {
-        if (resolved) { return; }
-        notify(promise, value);
-      };
-
-      this.on('promise:failed', function(event) {
-        this.trigger('error', { detail: event.detail });
-      }, this);
-
-      this.on('error', onerror);
-
-      this.cancel = function () {
-        // For now, simply reject the promise and does not propagate the cancel
-        // to parent or children
-        if (resolved) { return; }
-        if (canceller !== undefined) {
-          try {
-            canceller();
-          } catch (e) {
-            rejectPromise(e);
-            return;
-          }
-        }
-        // Trigger cancel?
-        rejectPromise(new CancellationError());
-      };
-
-      try {
-        resolver(resolvePromise, rejectPromise, notifyPromise);
-      } catch(e) {
-        rejectPromise(e);
-      }
-    };
-
-    function onerror(event) {
-      if (config.onerror) {
-        config.onerror(event.detail);
-      }
-    }
-
-    var invokeCallback = function(type, promise, callback, event) {
-      var hasCallback = isFunction(callback),
-          value, error, succeeded, failed;
-
-      if (promise.isFulfilled) { return; }
-      if (promise.isRejected) { return; }
-
-      if (hasCallback) {
-        try {
-          value = callback(event.detail);
-          succeeded = true;
-        } catch(e) {
-          failed = true;
-          error = e;
-        }
-      } else {
-        value = event.detail;
-        succeeded = true;
-      }
-
-      if (handleThenable(promise, value)) {
-        return;
-      } else if (hasCallback && succeeded) {
-        resolve(promise, value);
-      } else if (failed) {
-        reject(promise, error);
-      } else if (type === 'resolve') {
-        resolve(promise, value);
-      } else if (type === 'reject') {
-        reject(promise, value);
-      }
-    };
-
-
-    var invokeNotifyCallback = function(promise, callback, event) {
-      var value;
-      if (typeof callback === 'function') {
-        try {
-          value = callback(event.detail);
-        } catch (e) {
-          // stop propagating
-          return;
-        }
-        notify(promise, value);
-      } else {
-        notify(promise, event.detail);
-      }
-    };
-
-    Promise.prototype = {
-      constructor: Promise,
-
-      isRejected: undefined,
-      isFulfilled: undefined,
-      rejectedReason: undefined,
-      fulfillmentValue: undefined,
-
-      then: function(done, fail, progress) {
-        this.off('error', onerror);
-
-        var thenPromise = new this.constructor(function() {},
-            function () {
-              thenPromise.trigger('promise:cancelled', {});
-            });
-
-        if (this.isFulfilled) {
-          config.async(function(promise) {
-            invokeCallback('resolve', thenPromise, done, { detail: promise.fulfillmentValue });
-          }, this);
-        }
-
-        if (this.isRejected) {
-          config.async(function(promise) {
-            invokeCallback('reject', thenPromise, fail, { detail: promise.rejectedReason });
-          }, this);
-        }
-
-        this.on('promise:resolved', function(event) {
-          invokeCallback('resolve', thenPromise, done, event);
-        });
-
-        this.on('promise:failed', function(event) {
-          invokeCallback('reject', thenPromise, fail, event);
-        });
-
-        this.on('promise:notified', function (event) {
-          invokeNotifyCallback(thenPromise, progress, event);
-        });
-
-        return thenPromise;
-      },
-
-      fail: function(fail) {
-        return this.then(null, fail);
-      },
-
-      always: function(fail) {
-        return this.then(fail, fail);
-      }
-    };
-
-    EventTarget.mixin(Promise.prototype);
-
-    function resolve(promise, value) {
-      if (promise === value) {
-        fulfill(promise, value);
-      } else if (!handleThenable(promise, value)) {
-        fulfill(promise, value);
-      }
-    }
-
-    function handleThenable(promise, value) {
-      var then = null,
-      resolved;
-
-      try {
-        if (promise === value) {
-          throw new TypeError("A promises callback cannot return that same promise.");
-        }
-
-        if (objectOrFunction(value)) {
-          then = value.then;
-
-          if (isFunction(then)) {
-            if (isFunction(value.on)) {
-              value.on('promise:notified', function (event) {
-                notify(promise, event.detail);
-              });
-            }
-            promise.on('promise:cancelled', function(event) {
-              if (isFunction(value.cancel)) {
-                value.cancel();
-              }
-            });
-            then.call(value, function(val) {
-              if (resolved) { return true; }
-              resolved = true;
-
-              if (value !== val) {
-                resolve(promise, val);
-              } else {
-                fulfill(promise, val);
-              }
-            }, function(val) {
-              if (resolved) { return true; }
-              resolved = true;
-
-              reject(promise, val);
-            });
-
-            return true;
-          }
-        }
-      } catch (error) {
-        reject(promise, error);
-        return true;
-      }
-
-      return false;
-    }
-
-    function fulfill(promise, value) {
-      config.async(function() {
-        if (promise.isFulfilled) { return; }
-        if (promise.isRejected) { return; }
-        promise.trigger('promise:resolved', { detail: value });
-        promise.isFulfilled = true;
-        promise.fulfillmentValue = value;
-      });
-    }
-
-    function reject(promise, value) {
-      config.async(function() {
-        if (promise.isFulfilled) { return; }
-        if (promise.isRejected) { return; }
-        promise.trigger('promise:failed', { detail: value });
-        promise.isRejected = true;
-        promise.rejectedReason = value;
-      });
-    }
-
-    function notify(promise, value) {
-      config.async(function() {
-        promise.trigger('promise:notified', { detail: value });
-      });
-    }
-
-
-    __exports__.Promise = Promise;
-  });
-define("rsvp/queue",
-  ["rsvp/promise","rsvp/resolve","exports"],
-  function(__dependency1__, __dependency2__, __exports__) {
-    "use strict";
-    var Promise = __dependency1__.Promise;
-    var resolve = __dependency2__.resolve;
-
-    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
-    function ResolvedQueueError(message) {
-      this.name = "resolved";
-      if ((message !== undefined) && (typeof message !== "string")) {
-        throw new TypeError('You must pass a string.');
-      }
-      this.message = message || "Default Message";
-    }
-    ResolvedQueueError.prototype = new Error();
-    ResolvedQueueError.prototype.constructor = ResolvedQueueError;
-
-    var Queue = function() {
-      var queue = this,
-        promise_list = [],
-        promise,
-        fulfill,
-        reject,
-        notify,
-        resolved;
-
-      if (!(this instanceof Queue)) {
-        return new Queue();
-      }
-
-      function canceller() {
-        for (var i = 0; i < 2; i++) {
-          promise_list[i].cancel();
-        }
-      }
-
-      promise = new Promise(function(done, fail, progress) {
-        fulfill = function (fulfillmentValue) {
-          if (resolved) {return;}
-          queue.isFulfilled = true;
-          queue.fulfillmentValue = fulfillmentValue;
-          resolved = true;
-          return done(fulfillmentValue);
-        };
-        reject = function (rejectedReason) {
-          if (resolved) {return;}
-          queue.isRejected = true;
-          queue.rejectedReason = rejectedReason ;
-          resolved = true;
-          return fail(rejectedReason);
-        };
-        notify = progress;
-      }, canceller);
-
-      promise_list.push(resolve());
-      promise_list.push(promise_list[0].then(function () {
-        promise_list.splice(0, 2);
-        if (promise_list.length === 0) {
-          fulfill();
-        }
-      }));
-
-      queue.cancel = function () {
-        if (resolved) {return;}
-        resolved = true;
-        promise.cancel();
-        promise.fail(function (rejectedReason) {
-          queue.isRejected = true;
-          queue.rejectedReason = rejectedReason;
-        });
-      };
-      queue.then = function () {
-        return promise.then.apply(promise, arguments);
-      };
-
-      queue.push = function(done, fail, progress) {
-        var last_promise = promise_list[promise_list.length - 1],
-          next_promise;
-
-        if (resolved) {
-          throw new ResolvedQueueError();
-        }
-
-        next_promise = last_promise.then(done, fail, progress);
-        promise_list.push(next_promise);
-
-        // Handle pop
-        last_promise = next_promise.then(function (fulfillmentValue) {
-          promise_list.splice(0, 2);
-          if (promise_list.length === 0) {
-            fulfill(fulfillmentValue);
-          } else {
-            return fulfillmentValue;
-          }
-        }, function (rejectedReason) {
-          promise_list.splice(0, 2);
-          if (promise_list.length === 0) {
-            reject(rejectedReason);
-          } else {
-            throw rejectedReason;
-          }
-        }, function (notificationValue) {
-          if (promise_list[promise_list.length - 1] === last_promise) {
-            notify(notificationValue);
-          }
-          return notificationValue;
-        });
-        promise_list.push(last_promise);
-
-        return this;
-      };
-    };
-
-    Queue.prototype = Object.create(Promise.prototype);
-    Queue.prototype.constructor = Queue;
-
-
-    __exports__.Queue = Queue;
-    __exports__.ResolvedQueueError = ResolvedQueueError;
-  });
-define("rsvp/reject",
-  ["rsvp/promise","exports"],
-  function(__dependency1__, __exports__) {
-    "use strict";
-    var Promise = __dependency1__.Promise;
-
-    function reject(reason) {
-      return new Promise(function (resolve, reject) {
-        reject(reason);
-      });
-    }
-
-
-    __exports__.reject = reject;
-  });
-define("rsvp/resolve",
-  ["rsvp/promise","exports"],
-  function(__dependency1__, __exports__) {
-    "use strict";
-    var Promise = __dependency1__.Promise;
-
-    function resolve(thenable) {
-      return new Promise(function(resolve, reject) {
-        if (typeof thenable === "object" && thenable !== null) {
-          var then = thenable.then;
-          if ((then !== undefined) && (typeof then === "function")) {
-            return then.apply(thenable, [resolve, reject]);
-          }
-        }
-        return resolve(thenable);
-      }, function () {
-        if ((thenable !== undefined) && (thenable.cancel !== undefined)) {
-          thenable.cancel();
-        }
-      });
-    }
-
-
-    __exports__.resolve = resolve;
-  });
-define("rsvp/rethrow",
-  ["exports"],
-  function(__exports__) {
-    "use strict";
-    var local = (typeof global === "undefined") ? this : global;
-
-    function rethrow(reason) {
-      local.setTimeout(function() {
-        throw reason;
-      });
-      throw reason;
-    }
-
-
-    __exports__.rethrow = rethrow;
-  });
-define("rsvp/timeout",
-  ["rsvp/promise","exports"],
-  function(__dependency1__, __exports__) {
-    "use strict";
-    var Promise = __dependency1__.Promise;
-
-    function promiseSetTimeout(millisecond, should_reject, message) {
-      var timeout_id;
-
-      function resolver(resolve, reject) {
-        timeout_id = setTimeout(function () {
-          if (should_reject) {
-            reject(message);
-          } else {
-            resolve(message);
-          }
-        }, millisecond);
-      }
-      function canceller() {
-        clearTimeout(timeout_id);
-      }
-      return new Promise(resolver, canceller);
-    }
-
-    function delay(millisecond, message) {
-      return promiseSetTimeout(millisecond, false, message);
-    }
-
-    function timeout(millisecond) {
-      return promiseSetTimeout(millisecond, true,
-                               "Timed out after " + millisecond + " ms");
-    }
-
-    Promise.prototype.delay = function(millisecond) {
-      return this.then(function (fulfillmentValue) {
-        return delay(millisecond, fulfillmentValue);
-      });
-    };
-
-
-    __exports__.delay = delay;
-    __exports__.timeout = timeout;
-  });
-define("rsvp",
-  ["rsvp/events","rsvp/cancellation_error","rsvp/promise","rsvp/node","rsvp/all","rsvp/queue","rsvp/timeout","rsvp/hash","rsvp/rethrow","rsvp/defer","rsvp/config","rsvp/resolve","rsvp/reject","exports"],
-  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) {
-    "use strict";
-    var EventTarget = __dependency1__.EventTarget;
-    var CancellationError = __dependency2__.CancellationError;
-    var Promise = __dependency3__.Promise;
-    var denodeify = __dependency4__.denodeify;
-    var all = __dependency5__.all;
-    var any = __dependency5__.any;
-    var Queue = __dependency6__.Queue;
-    var ResolvedQueueError = __dependency6__.ResolvedQueueError;
-    var delay = __dependency7__.delay;
-    var timeout = __dependency7__.timeout;
-    var hash = __dependency8__.hash;
-    var rethrow = __dependency9__.rethrow;
-    var defer = __dependency10__.defer;
-    var config = __dependency11__.config;
-    var resolve = __dependency12__.resolve;
-    var reject = __dependency13__.reject;
-
-    function configure(name, value) {
-      config[name] = value;
-    }
-
-
-    __exports__.CancellationError = CancellationError;
-    __exports__.Promise = Promise;
-    __exports__.EventTarget = EventTarget;
-    __exports__.all = all;
-    __exports__.any = any;
-    __exports__.Queue = Queue;
-    __exports__.ResolvedQueueError = ResolvedQueueError;
-    __exports__.delay = delay;
-    __exports__.timeout = timeout;
-    __exports__.hash = hash;
-    __exports__.rethrow = rethrow;
-    __exports__.defer = defer;
-    __exports__.denodeify = denodeify;
-    __exports__.configure = configure;
-    __exports__.resolve = resolve;
-    __exports__.reject = reject;
-  });
-window.RSVP = requireModule("rsvp");
-})(window);
\ No newline at end of file
diff --git a/apps/maarch_entreprise/js/functions.js b/apps/maarch_entreprise/js/functions.js
index d41384a1514..d5424b1f6ff 100755
--- a/apps/maarch_entreprise/js/functions.js
+++ b/apps/maarch_entreprise/js/functions.js
@@ -592,47 +592,6 @@ var BrowserDetect = {
 
 BrowserDetect.init();
 
-/**
- * Resize frames in a modal
- *
- * @param  id_modal String Modal identifier
- * @param  id_frame String Frame identifier of the frame to resize
- * @param  resize_width Integer New width
- * @param  resize_height Integer New Height
- */
-function resize_frame_view(id_modal, id_frame, resize_width, resize_height) {
-    var modal = $(id_modal);
-    if (modal) {
-        if ($('divList')) {
-            $('divList').style.display = 'none';
-        }
-        var newwidth = modal.getWidth();
-        var newheight = modal.getHeight() - 30;
-        var frame2 = $(id_frame);
-        var windowSize = new Array();
-        if (frame2 != null) {
-            windowSize = getWindowSize();
-            newwidth = windowSize[0] - 40;
-            frame2.style.width = newwidth + "px";
-        }
-        if (resize_height == true && frame2 != null) {
-            newheight = windowSize[1] - 90;
-            frame2.style.height = newheight + "px";
-        }
-    }
-}
-
-function getWindowSize() {
-    if (window.innerWidth || window.innerHeight) {
-        var width = window.innerWidth;
-        var height = window.innerHeight;
-    } else {
-        var width = $(document.documentElement).getWidth();
-        var height = $(document.documentElement).getHeight();
-    }
-    return [width, height];
-}
-
 /*************** Tabs functions *****************/
 
 function opentab(eleframe, url) {
diff --git a/apps/maarch_entreprise/js/jio.js b/apps/maarch_entreprise/js/jio.js
deleted file mode 100755
index 49d37876b84..00000000000
--- a/apps/maarch_entreprise/js/jio.js
+++ /dev/null
@@ -1,12842 +0,0 @@
-/*! URI.js v1.12.0 http://medialize.github.com/URI.js/ */
-/* build contains: IPv6.js, punycode.js, SecondLevelDomains.js, URI.js, URI.fragmentQuery.js */
-(function(e,k){"object"===typeof exports?module.exports=k():"function"===typeof define&&define.amd?define(k):e.IPv6=k(e)})(this,function(e){var k=e&&e.IPv6;return{best:function(e){e=e.toLowerCase().split(":");var k=e.length,d=8;""===e[0]&&""===e[1]&&""===e[2]?(e.shift(),e.shift()):""===e[0]&&""===e[1]?e.shift():""===e[k-1]&&""===e[k-2]&&e.pop();k=e.length;-1!==e[k-1].indexOf(".")&&(d=7);var g;for(g=0;g<k&&""!==e[g];g++);if(g<d)for(e.splice(g,1,"0000");e.length<d;)e.splice(g,0,"0000");for(g=0;g<d;g++){for(var k=
-e[g].split(""),q=0;3>q;q++)if("0"===k[0]&&1<k.length)k.splice(0,1);else break;e[g]=k.join("")}var k=-1,l=q=0,r=-1,z=!1;for(g=0;g<d;g++)z?"0"===e[g]?l+=1:(z=!1,l>q&&(k=r,q=l)):"0"==e[g]&&(z=!0,r=g,l=1);l>q&&(k=r,q=l);1<q&&e.splice(k,q,"");k=e.length;d="";""===e[0]&&(beststr=":");for(g=0;g<k;g++){d+=e[g];if(g===k-1)break;d+=":"}""===e[k-1]&&(d+=":");return d},noConflict:function(){e.IPv6===this&&(e.IPv6=k);return this}}});
-(function(e){function k(a){throw RangeError(p[a]);}function u(a,b){for(var c=a.length;c--;)a[c]=b(a[c]);return a}function m(a,b){return u(a.split(h),b).join(".")}function d(a){for(var b=[],c=0,d=a.length,h,p;c<d;)h=a.charCodeAt(c++),55296<=h&&56319>=h&&c<d?(p=a.charCodeAt(c++),56320==(p&64512)?b.push(((h&1023)<<10)+(p&1023)+65536):(b.push(h),c--)):b.push(h);return b}function g(a){return u(a,function(a){var b="";65535<a&&(a-=65536,b+=x(a>>>10&1023|55296),a=56320|a&1023);return b+=x(a)}).join("")}function q(a,
-b){return a+22+75*(26>a)-((0!=b)<<5)}function l(a,b,c){var d=0;a=c?A(a/H):a>>1;for(a+=A(a/b);a>n*y>>1;d+=s)a=A(a/n);return A(d+(n+1)*a/(a+I))}function r(b){var c=[],d=b.length,h,p=0,e=F,f=G,n,x,q,t,m;n=b.lastIndexOf(a);0>n&&(n=0);for(x=0;x<n;++x)128<=b.charCodeAt(x)&&k("not-basic"),c.push(b.charCodeAt(x));for(n=0<n?n+1:0;n<d;){x=p;h=1;for(q=s;;q+=s){n>=d&&k("invalid-input");t=b.charCodeAt(n++);t=10>t-48?t-22:26>t-65?t-65:26>t-97?t-97:s;(t>=s||t>A((w-p)/h))&&k("overflow");p+=t*h;m=q<=f?v:q>=f+y?y:
-q-f;if(t<m)break;t=s-m;h>A(w/t)&&k("overflow");h*=t}h=c.length+1;f=l(p-x,h,0==x);A(p/h)>w-e&&k("overflow");e+=A(p/h);p%=h;c.splice(p++,0,e)}return g(c)}function z(b){var c,h,p,e,f,n,g,m,r,t=[],B,u,z;b=d(b);B=b.length;c=F;h=0;f=G;for(n=0;n<B;++n)r=b[n],128>r&&t.push(x(r));for((p=e=t.length)&&t.push(a);p<B;){g=w;for(n=0;n<B;++n)r=b[n],r>=c&&r<g&&(g=r);u=p+1;g-c>A((w-h)/u)&&k("overflow");h+=(g-c)*u;c=g;for(n=0;n<B;++n)if(r=b[n],r<c&&++h>w&&k("overflow"),r==c){m=h;for(g=s;;g+=s){r=g<=f?v:g>=f+y?y:g-f;
-if(m<r)break;z=m-r;m=s-r;t.push(x(q(r+z%m,0)));m=A(z/m)}t.push(x(q(m,0)));f=l(h,u,p==e);h=0;++p}++h;++c}return t.join("")}var D="object"==typeof exports&&exports,E="object"==typeof module&&module&&module.exports==D&&module,C="object"==typeof global&&global;if(C.global===C||C.window===C)e=C;var f,w=2147483647,s=36,v=1,y=26,I=38,H=700,G=72,F=128,a="-",b=/^xn--/,c=/[^ -~]/,h=/\x2E|\u3002|\uFF0E|\uFF61/g,p={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)",
-"invalid-input":"Invalid input"},n=s-v,A=Math.floor,x=String.fromCharCode,B;f={version:"1.2.3",ucs2:{decode:d,encode:g},decode:r,encode:z,toASCII:function(a){return m(a,function(a){return c.test(a)?"xn--"+z(a):a})},toUnicode:function(a){return m(a,function(a){return b.test(a)?r(a.slice(4).toLowerCase()):a})}};if("function"==typeof define&&"object"==typeof define.amd&&define.amd)define(function(){return f});else if(D&&!D.nodeType)if(E)E.exports=f;else for(B in f)f.hasOwnProperty(B)&&(D[B]=f[B]);else e.punycode=
-f})(this);
-(function(e,k){"object"===typeof exports?module.exports=k():"function"===typeof define&&define.amd?define(k):e.SecondLevelDomains=k(e)})(this,function(e){var k=e&&e.SecondLevelDomains,u=Object.prototype.hasOwnProperty,m={list:{ac:"com|gov|mil|net|org",ae:"ac|co|gov|mil|name|net|org|pro|sch",af:"com|edu|gov|net|org",al:"com|edu|gov|mil|net|org",ao:"co|ed|gv|it|og|pb",ar:"com|edu|gob|gov|int|mil|net|org|tur",at:"ac|co|gv|or",au:"asn|com|csiro|edu|gov|id|net|org",ba:"co|com|edu|gov|mil|net|org|rs|unbi|unmo|unsa|untz|unze",bb:"biz|co|com|edu|gov|info|net|org|store|tv",
-bh:"biz|cc|com|edu|gov|info|net|org",bn:"com|edu|gov|net|org",bo:"com|edu|gob|gov|int|mil|net|org|tv",br:"adm|adv|agr|am|arq|art|ato|b|bio|blog|bmd|cim|cng|cnt|com|coop|ecn|edu|eng|esp|etc|eti|far|flog|fm|fnd|fot|fst|g12|ggf|gov|imb|ind|inf|jor|jus|lel|mat|med|mil|mus|net|nom|not|ntr|odo|org|ppg|pro|psc|psi|qsl|rec|slg|srv|tmp|trd|tur|tv|vet|vlog|wiki|zlg",bs:"com|edu|gov|net|org",bz:"du|et|om|ov|rg",ca:"ab|bc|mb|nb|nf|nl|ns|nt|nu|on|pe|qc|sk|yk",ck:"biz|co|edu|gen|gov|info|net|org",cn:"ac|ah|bj|com|cq|edu|fj|gd|gov|gs|gx|gz|ha|hb|he|hi|hl|hn|jl|js|jx|ln|mil|net|nm|nx|org|qh|sc|sd|sh|sn|sx|tj|tw|xj|xz|yn|zj",
-co:"com|edu|gov|mil|net|nom|org",cr:"ac|c|co|ed|fi|go|or|sa",cy:"ac|biz|com|ekloges|gov|ltd|name|net|org|parliament|press|pro|tm","do":"art|com|edu|gob|gov|mil|net|org|sld|web",dz:"art|asso|com|edu|gov|net|org|pol",ec:"com|edu|fin|gov|info|med|mil|net|org|pro",eg:"com|edu|eun|gov|mil|name|net|org|sci",er:"com|edu|gov|ind|mil|net|org|rochest|w",es:"com|edu|gob|nom|org",et:"biz|com|edu|gov|info|name|net|org",fj:"ac|biz|com|info|mil|name|net|org|pro",fk:"ac|co|gov|net|nom|org",fr:"asso|com|f|gouv|nom|prd|presse|tm",
-gg:"co|net|org",gh:"com|edu|gov|mil|org",gn:"ac|com|gov|net|org",gr:"com|edu|gov|mil|net|org",gt:"com|edu|gob|ind|mil|net|org",gu:"com|edu|gov|net|org",hk:"com|edu|gov|idv|net|org",id:"ac|co|go|mil|net|or|sch|web",il:"ac|co|gov|idf|k12|muni|net|org","in":"ac|co|edu|ernet|firm|gen|gov|i|ind|mil|net|nic|org|res",iq:"com|edu|gov|i|mil|net|org",ir:"ac|co|dnssec|gov|i|id|net|org|sch",it:"edu|gov",je:"co|net|org",jo:"com|edu|gov|mil|name|net|org|sch",jp:"ac|ad|co|ed|go|gr|lg|ne|or",ke:"ac|co|go|info|me|mobi|ne|or|sc",
-kh:"com|edu|gov|mil|net|org|per",ki:"biz|com|de|edu|gov|info|mob|net|org|tel",km:"asso|com|coop|edu|gouv|k|medecin|mil|nom|notaires|pharmaciens|presse|tm|veterinaire",kn:"edu|gov|net|org",kr:"ac|busan|chungbuk|chungnam|co|daegu|daejeon|es|gangwon|go|gwangju|gyeongbuk|gyeonggi|gyeongnam|hs|incheon|jeju|jeonbuk|jeonnam|k|kg|mil|ms|ne|or|pe|re|sc|seoul|ulsan",kw:"com|edu|gov|net|org",ky:"com|edu|gov|net|org",kz:"com|edu|gov|mil|net|org",lb:"com|edu|gov|net|org",lk:"assn|com|edu|gov|grp|hotel|int|ltd|net|ngo|org|sch|soc|web",
-lr:"com|edu|gov|net|org",lv:"asn|com|conf|edu|gov|id|mil|net|org",ly:"com|edu|gov|id|med|net|org|plc|sch",ma:"ac|co|gov|m|net|org|press",mc:"asso|tm",me:"ac|co|edu|gov|its|net|org|priv",mg:"com|edu|gov|mil|nom|org|prd|tm",mk:"com|edu|gov|inf|name|net|org|pro",ml:"com|edu|gov|net|org|presse",mn:"edu|gov|org",mo:"com|edu|gov|net|org",mt:"com|edu|gov|net|org",mv:"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro",mw:"ac|co|com|coop|edu|gov|int|museum|net|org",mx:"com|edu|gob|net|org",my:"com|edu|gov|mil|name|net|org|sch",
-nf:"arts|com|firm|info|net|other|per|rec|store|web",ng:"biz|com|edu|gov|mil|mobi|name|net|org|sch",ni:"ac|co|com|edu|gob|mil|net|nom|org",np:"com|edu|gov|mil|net|org",nr:"biz|com|edu|gov|info|net|org",om:"ac|biz|co|com|edu|gov|med|mil|museum|net|org|pro|sch",pe:"com|edu|gob|mil|net|nom|org|sld",ph:"com|edu|gov|i|mil|net|ngo|org",pk:"biz|com|edu|fam|gob|gok|gon|gop|gos|gov|net|org|web",pl:"art|bialystok|biz|com|edu|gda|gdansk|gorzow|gov|info|katowice|krakow|lodz|lublin|mil|net|ngo|olsztyn|org|poznan|pwr|radom|slupsk|szczecin|torun|warszawa|waw|wroc|wroclaw|zgora",
-pr:"ac|biz|com|edu|est|gov|info|isla|name|net|org|pro|prof",ps:"com|edu|gov|net|org|plo|sec",pw:"belau|co|ed|go|ne|or",ro:"arts|com|firm|info|nom|nt|org|rec|store|tm|www",rs:"ac|co|edu|gov|in|org",sb:"com|edu|gov|net|org",sc:"com|edu|gov|net|org",sh:"co|com|edu|gov|net|nom|org",sl:"com|edu|gov|net|org",st:"co|com|consulado|edu|embaixada|gov|mil|net|org|principe|saotome|store",sv:"com|edu|gob|org|red",sz:"ac|co|org",tr:"av|bbs|bel|biz|com|dr|edu|gen|gov|info|k12|name|net|org|pol|tel|tsk|tv|web",tt:"aero|biz|cat|co|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel",
-tw:"club|com|ebiz|edu|game|gov|idv|mil|net|org",mu:"ac|co|com|gov|net|or|org",mz:"ac|co|edu|gov|org",na:"co|com",nz:"ac|co|cri|geek|gen|govt|health|iwi|maori|mil|net|org|parliament|school",pa:"abo|ac|com|edu|gob|ing|med|net|nom|org|sld",pt:"com|edu|gov|int|net|nome|org|publ",py:"com|edu|gov|mil|net|org",qa:"com|edu|gov|mil|net|org",re:"asso|com|nom",ru:"ac|adygeya|altai|amur|arkhangelsk|astrakhan|bashkiria|belgorod|bir|bryansk|buryatia|cbg|chel|chelyabinsk|chita|chukotka|chuvashia|com|dagestan|e-burg|edu|gov|grozny|int|irkutsk|ivanovo|izhevsk|jar|joshkar-ola|kalmykia|kaluga|kamchatka|karelia|kazan|kchr|kemerovo|khabarovsk|khakassia|khv|kirov|koenig|komi|kostroma|kranoyarsk|kuban|kurgan|kursk|lipetsk|magadan|mari|mari-el|marine|mil|mordovia|mosreg|msk|murmansk|nalchik|net|nnov|nov|novosibirsk|nsk|omsk|orenburg|org|oryol|penza|perm|pp|pskov|ptz|rnd|ryazan|sakhalin|samara|saratov|simbirsk|smolensk|spb|stavropol|stv|surgut|tambov|tatarstan|tom|tomsk|tsaritsyn|tsk|tula|tuva|tver|tyumen|udm|udmurtia|ulan-ude|vladikavkaz|vladimir|vladivostok|volgograd|vologda|voronezh|vrn|vyatka|yakutia|yamal|yekaterinburg|yuzhno-sakhalinsk",
-rw:"ac|co|com|edu|gouv|gov|int|mil|net",sa:"com|edu|gov|med|net|org|pub|sch",sd:"com|edu|gov|info|med|net|org|tv",se:"a|ac|b|bd|c|d|e|f|g|h|i|k|l|m|n|o|org|p|parti|pp|press|r|s|t|tm|u|w|x|y|z",sg:"com|edu|gov|idn|net|org|per",sn:"art|com|edu|gouv|org|perso|univ",sy:"com|edu|gov|mil|net|news|org",th:"ac|co|go|in|mi|net|or",tj:"ac|biz|co|com|edu|go|gov|info|int|mil|name|net|nic|org|test|web",tn:"agrinet|com|defense|edunet|ens|fin|gov|ind|info|intl|mincom|nat|net|org|perso|rnrt|rns|rnu|tourism",tz:"ac|co|go|ne|or",
-ua:"biz|cherkassy|chernigov|chernovtsy|ck|cn|co|com|crimea|cv|dn|dnepropetrovsk|donetsk|dp|edu|gov|if|in|ivano-frankivsk|kh|kharkov|kherson|khmelnitskiy|kiev|kirovograd|km|kr|ks|kv|lg|lugansk|lutsk|lviv|me|mk|net|nikolaev|od|odessa|org|pl|poltava|pp|rovno|rv|sebastopol|sumy|te|ternopil|uzhgorod|vinnica|vn|zaporizhzhe|zhitomir|zp|zt",ug:"ac|co|go|ne|or|org|sc",uk:"ac|bl|british-library|co|cym|gov|govt|icnet|jet|lea|ltd|me|mil|mod|national-library-scotland|nel|net|nhs|nic|nls|org|orgn|parliament|plc|police|sch|scot|soc",
-us:"dni|fed|isa|kids|nsn",uy:"com|edu|gub|mil|net|org",ve:"co|com|edu|gob|info|mil|net|org|web",vi:"co|com|k12|net|org",vn:"ac|biz|com|edu|gov|health|info|int|name|net|org|pro",ye:"co|com|gov|ltd|me|net|org|plc",yu:"ac|co|edu|gov|org",za:"ac|agric|alt|bourse|city|co|cybernet|db|edu|gov|grondar|iaccess|imt|inca|landesign|law|mil|net|ngo|nis|nom|olivetti|org|pix|school|tm|web",zm:"ac|co|com|edu|gov|net|org|sch"},has_expression:null,is_expression:null,has:function(d){return!!d.match(m.has_expression)},
-is:function(d){return!!d.match(m.is_expression)},get:function(d){return(d=d.match(m.has_expression))&&d[1]||null},noConflict:function(){e.SecondLevelDomains===this&&(e.SecondLevelDomains=k);return this},init:function(){var d="",e;for(e in m.list)u.call(m.list,e)&&(d+="|("+("("+m.list[e]+")."+e)+")");m.has_expression=RegExp("\\.("+d.substr(1)+")$","i");m.is_expression=RegExp("^("+d.substr(1)+")$","i")}};m.init();return m});
-(function(e,k){"object"===typeof exports?module.exports=k(require("./punycode"),require("./IPv6"),require("./SecondLevelDomains")):"function"===typeof define&&define.amd?define(["./punycode","./IPv6","./SecondLevelDomains"],k):e.URI=k(e.punycode,e.IPv6,e.SecondLevelDomains,e)})(this,function(e,k,u,m){function d(a,b){if(!(this instanceof d))return new d(a,b);void 0===a&&(a="undefined"!==typeof location?location.href+"":"");this.href(a);return void 0!==b?this.absoluteTo(b):this}function g(a){return a.replace(/([.*+?^=!:${}()|[\]\/\\])/g,
-"\\$1")}function q(a){return void 0===a?"Undefined":String(Object.prototype.toString.call(a)).slice(8,-1)}function l(a){return"Array"===q(a)}function r(a,b){var c,d;if(l(b)){c=0;for(d=b.length;c<d;c++)if(!r(a,b[c]))return!1;return!0}var p=q(b);c=0;for(d=a.length;c<d;c++)if("RegExp"===p){if("string"===typeof a[c]&&a[c].match(b))return!0}else if(a[c]===b)return!0;return!1}function z(a,b){if(!l(a)||!l(b)||a.length!==b.length)return!1;a.sort();b.sort();for(var c=0,d=a.length;c<d;c++)if(a[c]!==b[c])return!1;
-return!0}function D(a){return escape(a)}function E(a){return encodeURIComponent(a).replace(/[!'()*]/g,D).replace(/\*/g,"%2A")}var C=m&&m.URI;d.version="1.12.0";var f=d.prototype,w=Object.prototype.hasOwnProperty;d._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:d.duplicateQueryParameters,escapeQuerySpace:d.escapeQuerySpace}};d.duplicateQueryParameters=!1;d.escapeQuerySpace=!0;d.protocol_expression=
-/^[a-z][a-z0-9.+-]*$/i;d.idn_expression=/[^a-z0-9\.-]/i;d.punycode_expression=/(xn--)/i;d.ip4_expression=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;d.ip6_expression=/^\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|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[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|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[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|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[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|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[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|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[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|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[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|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
-d.find_uri_expression=/\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u2018\u2019]))/ig;d.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u201e\u2018\u2019]+$/};d.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"};d.invalid_hostname_characters=
-/[^a-zA-Z0-9\.-]/;d.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src"};d.getDomAttribute=function(a){if(a&&a.nodeName){var b=a.nodeName.toLowerCase();return"input"===b&&"image"!==a.type?void 0:d.domAttributes[b]}};d.encode=E;d.decode=decodeURIComponent;d.iso8859=function(){d.encode=escape;d.decode=unescape};d.unicode=function(){d.encode=E;d.decode=decodeURIComponent};d.characters=
-{pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/ig,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}}};d.encodeQuery=
-function(a,b){var c=d.encode(a+"");return b?c.replace(/%20/g,"+"):c};d.decodeQuery=function(a,b){a+="";try{return d.decode(b?a.replace(/\+/g,"%20"):a)}catch(c){return a}};d.recodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;b<c;b++)a[b]=d.encodePathSegment(d.decode(a[b]));return a.join("/")};d.decodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;b<c;b++)a[b]=d.decodePathSegment(a[b]);return a.join("/")};var s={encode:"encode",decode:"decode"},v,y=function(a,b){return function(c){return d[b](c+
-"").replace(d.characters[a][b].expression,function(c){return d.characters[a][b].map[c]})}};for(v in s)d[v+"PathSegment"]=y("pathname",s[v]);d.encodeReserved=y("reserved","encode");d.parse=function(a,b){var c;b||(b={});c=a.indexOf("#");-1<c&&(b.fragment=a.substring(c+1)||null,a=a.substring(0,c));c=a.indexOf("?");-1<c&&(b.query=a.substring(c+1)||null,a=a.substring(0,c));"//"===a.substring(0,2)?(b.protocol=null,a=a.substring(2),a=d.parseAuthority(a,b)):(c=a.indexOf(":"),-1<c&&(b.protocol=a.substring(0,
-c)||null,b.protocol&&!b.protocol.match(d.protocol_expression)?b.protocol=void 0:"file"===b.protocol?a=a.substring(c+3):"//"===a.substring(c+1,c+3)?(a=a.substring(c+3),a=d.parseAuthority(a,b)):(a=a.substring(c+1),b.urn=!0)));b.path=a;return b};d.parseHost=function(a,b){var c=a.indexOf("/"),d;-1===c&&(c=a.length);"["===a.charAt(0)?(d=a.indexOf("]"),b.hostname=a.substring(1,d)||null,b.port=a.substring(d+2,c)||null):a.indexOf(":")!==a.lastIndexOf(":")?(b.hostname=a.substring(0,c)||null,b.port=null):(d=
-a.substring(0,c).split(":"),b.hostname=d[0]||null,b.port=d[1]||null);b.hostname&&"/"!==a.substring(c).charAt(0)&&(c++,a="/"+a);return a.substring(c)||"/"};d.parseAuthority=function(a,b){a=d.parseUserinfo(a,b);return d.parseHost(a,b)};d.parseUserinfo=function(a,b){var c=a.indexOf("/"),h=-1<c?a.lastIndexOf("@",c):a.indexOf("@");-1<h&&(-1===c||h<c)?(c=a.substring(0,h).split(":"),b.username=c[0]?d.decode(c[0]):null,c.shift(),b.password=c[0]?d.decode(c.join(":")):null,a=a.substring(h+1)):(b.username=null,
-b.password=null);return a};d.parseQuery=function(a,b){if(!a)return{};a=a.replace(/&+/g,"&").replace(/^\?*&*|&+$/g,"");if(!a)return{};for(var c={},h=a.split("&"),p=h.length,n,e,f=0;f<p;f++)n=h[f].split("="),e=d.decodeQuery(n.shift(),b),n=n.length?d.decodeQuery(n.join("="),b):null,c[e]?("string"===typeof c[e]&&(c[e]=[c[e]]),c[e].push(n)):c[e]=n;return c};d.build=function(a){var b="";a.protocol&&(b+=a.protocol+":");a.urn||!b&&!a.hostname||(b+="//");b+=d.buildAuthority(a)||"";"string"===typeof a.path&&
-("/"!==a.path.charAt(0)&&"string"===typeof a.hostname&&(b+="/"),b+=a.path);"string"===typeof a.query&&a.query&&(b+="?"+a.query);"string"===typeof a.fragment&&a.fragment&&(b+="#"+a.fragment);return b};d.buildHost=function(a){var b="";if(a.hostname)d.ip6_expression.test(a.hostname)?b=a.port?b+("["+a.hostname+"]:"+a.port):b+a.hostname:(b+=a.hostname,a.port&&(b+=":"+a.port));else return"";return b};d.buildAuthority=function(a){return d.buildUserinfo(a)+d.buildHost(a)};d.buildUserinfo=function(a){var b=
-"";a.username&&(b+=d.encode(a.username),a.password&&(b+=":"+d.encode(a.password)),b+="@");return b};d.buildQuery=function(a,b,c){var h="",p,e,f,k;for(e in a)if(w.call(a,e)&&e)if(l(a[e]))for(p={},f=0,k=a[e].length;f<k;f++)void 0!==a[e][f]&&void 0===p[a[e][f]+""]&&(h+="&"+d.buildQueryParameter(e,a[e][f],c),!0!==b&&(p[a[e][f]+""]=!0));else void 0!==a[e]&&(h+="&"+d.buildQueryParameter(e,a[e],c));return h.substring(1)};d.buildQueryParameter=function(a,b,c){return d.encodeQuery(a,c)+(null!==b?"="+d.encodeQuery(b,
-c):"")};d.addQuery=function(a,b,c){if("object"===typeof b)for(var h in b)w.call(b,h)&&d.addQuery(a,h,b[h]);else if("string"===typeof b)void 0===a[b]?a[b]=c:("string"===typeof a[b]&&(a[b]=[a[b]]),l(c)||(c=[c]),a[b]=a[b].concat(c));else throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");};d.removeQuery=function(a,b,c){var h;if(l(b))for(c=0,h=b.length;c<h;c++)a[b[c]]=void 0;else if("object"===typeof b)for(h in b)w.call(b,h)&&d.removeQuery(a,h,b[h]);else if("string"===
-typeof b)if(void 0!==c)if(a[b]===c)a[b]=void 0;else{if(l(a[b])){h=a[b];var p={},e,f;if(l(c))for(e=0,f=c.length;e<f;e++)p[c[e]]=!0;else p[c]=!0;e=0;for(f=h.length;e<f;e++)void 0!==p[h[e]]&&(h.splice(e,1),f--,e--);a[b]=h}}else a[b]=void 0;else throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");};d.hasQuery=function(a,b,c,h){if("object"===typeof b){for(var e in b)if(w.call(b,e)&&!d.hasQuery(a,e,b[e]))return!1;return!0}if("string"!==typeof b)throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");
-switch(q(c)){case "Undefined":return b in a;case "Boolean":return a=Boolean(l(a[b])?a[b].length:a[b]),c===a;case "Function":return!!c(a[b],b,a);case "Array":return l(a[b])?(h?r:z)(a[b],c):!1;case "RegExp":return l(a[b])?h?r(a[b],c):!1:Boolean(a[b]&&a[b].match(c));case "Number":c=String(c);case "String":return l(a[b])?h?r(a[b],c):!1:a[b]===c;default:throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter");}};d.commonPath=function(a,b){var c=
-Math.min(a.length,b.length),d;for(d=0;d<c;d++)if(a.charAt(d)!==b.charAt(d)){d--;break}if(1>d)return a.charAt(0)===b.charAt(0)&&"/"===a.charAt(0)?"/":"";if("/"!==a.charAt(d)||"/"!==b.charAt(d))d=a.substring(0,d).lastIndexOf("/");return a.substring(0,d+1)};d.withinString=function(a,b,c){c||(c={});var h=c.start||d.findUri.start,e=c.end||d.findUri.end,f=c.trim||d.findUri.trim,k=/[a-z0-9-]=["']?$/i;for(h.lastIndex=0;;){var g=h.exec(a);if(!g)break;g=g.index;if(c.ignoreHtml){var l=a.slice(Math.max(g-3,0),
-g);if(l&&k.test(l))continue}var l=g+a.slice(g).search(e),q=a.slice(g,l).replace(f,"");c.ignore&&c.ignore.test(q)||(l=g+q.length,q=b(q,g,l,a),a=a.slice(0,g)+q+a.slice(l),h.lastIndex=g+q.length)}h.lastIndex=0;return a};d.ensureValidHostname=function(a){if(a.match(d.invalid_hostname_characters)){if(!e)throw new TypeError("Hostname '"+a+"' contains characters other than [A-Z0-9.-] and Punycode.js is not available");if(e.toASCII(a).match(d.invalid_hostname_characters))throw new TypeError("Hostname '"+
-a+"' contains characters other than [A-Z0-9.-]");}};d.noConflict=function(a){if(a)return a={URI:this.noConflict()},URITemplate&&"function"==typeof URITemplate.noConflict&&(a.URITemplate=URITemplate.noConflict()),k&&"function"==typeof k.noConflict&&(a.IPv6=k.noConflict()),SecondLevelDomains&&"function"==typeof SecondLevelDomains.noConflict&&(a.SecondLevelDomains=SecondLevelDomains.noConflict()),a;m.URI===this&&(m.URI=C);return this};f.build=function(a){if(!0===a)this._deferred_build=!0;else if(void 0===
-a||this._deferred_build)this._string=d.build(this._parts),this._deferred_build=!1;return this};f.clone=function(){return new d(this)};f.valueOf=f.toString=function(){return this.build(!1)._string};s={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"};y=function(a){return function(b,c){if(void 0===b)return this._parts[a]||"";this._parts[a]=b||null;this.build(!c);return this}};for(v in s)f[v]=y(s[v]);s={query:"?",fragment:"#"};y=function(a,b){return function(c,
-d){if(void 0===c)return this._parts[a]||"";null!==c&&(c+="",c.charAt(0)===b&&(c=c.substring(1)));this._parts[a]=c;this.build(!d);return this}};for(v in s)f[v]=y(v,s[v]);s={search:["?","query"],hash:["#","fragment"]};y=function(a,b){return function(c,d){var e=this[a](c,d);return"string"===typeof e&&e.length?b+e:e}};for(v in s)f[v]=y(s[v][1],s[v][0]);f.pathname=function(a,b){if(void 0===a||!0===a){var c=this._parts.path||(this._parts.hostname?"/":"");return a?d.decodePath(c):c}this._parts.path=a?d.recodePath(a):
-"/";this.build(!b);return this};f.path=f.pathname;f.href=function(a,b){var c;if(void 0===a)return this.toString();this._string="";this._parts=d._parts();var h=a instanceof d,e="object"===typeof a&&(a.hostname||a.path||a.pathname);a.nodeName&&(e=d.getDomAttribute(a),a=a[e]||"",e=!1);!h&&e&&void 0!==a.pathname&&(a=a.toString());if("string"===typeof a)this._parts=d.parse(a,this._parts);else if(h||e)for(c in h=h?a._parts:a,h)w.call(this._parts,c)&&(this._parts[c]=h[c]);else throw new TypeError("invalid input");
-this.build(!b);return this};f.is=function(a){var b=!1,c=!1,h=!1,e=!1,f=!1,g=!1,k=!1,l=!this._parts.urn;this._parts.hostname&&(l=!1,c=d.ip4_expression.test(this._parts.hostname),h=d.ip6_expression.test(this._parts.hostname),b=c||h,f=(e=!b)&&u&&u.has(this._parts.hostname),g=e&&d.idn_expression.test(this._parts.hostname),k=e&&d.punycode_expression.test(this._parts.hostname));switch(a.toLowerCase()){case "relative":return l;case "absolute":return!l;case "domain":case "name":return e;case "sld":return f;
-case "ip":return b;case "ip4":case "ipv4":case "inet4":return c;case "ip6":case "ipv6":case "inet6":return h;case "idn":return g;case "url":return!this._parts.urn;case "urn":return!!this._parts.urn;case "punycode":return k}return null};var I=f.protocol,H=f.port,G=f.hostname;f.protocol=function(a,b){if(void 0!==a&&a&&(a=a.replace(/:(\/\/)?$/,""),!a.match(d.protocol_expression)))throw new TypeError("Protocol '"+a+"' contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return I.call(this,
-a,b)};f.scheme=f.protocol;f.port=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a&&(0===a&&(a=null),a&&(a+="",":"===a.charAt(0)&&(a=a.substring(1)),a.match(/[^0-9]/))))throw new TypeError("Port '"+a+"' contains characters other than [0-9]");return H.call(this,a,b)};f.hostname=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a){var c={};d.parseHost(a,c);a=c.hostname}return G.call(this,a,b)};f.host=function(a,b){if(this._parts.urn)return void 0===a?"":this;
-if(void 0===a)return this._parts.hostname?d.buildHost(this._parts):"";d.parseHost(a,this._parts);this.build(!b);return this};f.authority=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a)return this._parts.hostname?d.buildAuthority(this._parts):"";d.parseAuthority(a,this._parts);this.build(!b);return this};f.userinfo=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.username)return"";var c=d.buildUserinfo(this._parts);return c.substring(0,
-c.length-1)}"@"!==a[a.length-1]&&(a+="@");d.parseUserinfo(a,this._parts);this.build(!b);return this};f.resource=function(a,b){var c;if(void 0===a)return this.path()+this.search()+this.hash();c=d.parse(a);this._parts.path=c.path;this._parts.query=c.query;this._parts.fragment=c.fragment;this.build(!b);return this};f.subdomain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.length-this.domain().length-
-1;return this._parts.hostname.substring(0,c)||""}c=this._parts.hostname.length-this.domain().length;c=this._parts.hostname.substring(0,c);c=RegExp("^"+g(c));a&&"."!==a.charAt(a.length-1)&&(a+=".");a&&d.ensureValidHostname(a);this._parts.hostname=this._parts.hostname.replace(c,a);this.build(!b);return this};f.domain=function(a,b){if(this._parts.urn)return void 0===a?"":this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.match(/\./g);
-if(c&&2>c.length)return this._parts.hostname;c=this._parts.hostname.length-this.tld(b).length-1;c=this._parts.hostname.lastIndexOf(".",c-1)+1;return this._parts.hostname.substring(c)||""}if(!a)throw new TypeError("cannot set domain empty");d.ensureValidHostname(a);!this._parts.hostname||this.is("IP")?this._parts.hostname=a:(c=RegExp(g(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a));this.build(!b);return this};f.tld=function(a,b){if(this._parts.urn)return void 0===a?"":
-this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.lastIndexOf("."),c=this._parts.hostname.substring(c+1);return!0!==b&&u&&u.list[c.toLowerCase()]?u.get(this._parts.hostname)||c:c}if(a)if(a.match(/[^a-zA-Z0-9-]/))if(u&&u.is(a))c=RegExp(g(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a);else throw new TypeError("TLD '"+a+"' contains characters other than [A-Z0-9]");else{if(!this._parts.hostname||
-this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");c=RegExp(g(this.tld())+"$");this._parts.hostname=this._parts.hostname.replace(c,a)}else throw new TypeError("cannot set TLD empty");this.build(!b);return this};f.directory=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var c=this._parts.path.length-this.filename().length-1,c=this._parts.path.substring(0,
-c)||(this._parts.hostname?"/":"");return a?d.decodePath(c):c}c=this._parts.path.length-this.filename().length;c=this._parts.path.substring(0,c);c=RegExp("^"+g(c));this.is("relative")||(a||(a="/"),"/"!==a.charAt(0)&&(a="/"+a));a&&"/"!==a.charAt(a.length-1)&&(a+="/");a=d.recodePath(a);this._parts.path=this._parts.path.replace(c,a);this.build(!b);return this};f.filename=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";
-var c=this._parts.path.lastIndexOf("/"),c=this._parts.path.substring(c+1);return a?d.decodePathSegment(c):c}c=!1;"/"===a.charAt(0)&&(a=a.substring(1));a.match(/\.?\//)&&(c=!0);var h=RegExp(g(this.filename())+"$");a=d.recodePath(a);this._parts.path=this._parts.path.replace(h,a);c?this.normalizePath(b):this.build(!b);return this};f.suffix=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this.filename(),h=c.lastIndexOf(".");
-if(-1===h)return"";c=c.substring(h+1);c=/^[a-z0-9%]+$/i.test(c)?c:"";return a?d.decodePathSegment(c):c}"."===a.charAt(0)&&(a=a.substring(1));if(c=this.suffix())h=a?RegExp(g(c)+"$"):RegExp(g("."+c)+"$");else{if(!a)return this;this._parts.path+="."+d.recodePath(a)}h&&(a=d.recodePath(a),this._parts.path=this._parts.path.replace(h,a));this.build(!b);return this};f.segment=function(a,b,c){var d=this._parts.urn?":":"/",e=this.path(),f="/"===e.substring(0,1),e=e.split(d);void 0!==a&&"number"!==typeof a&&
-(c=b,b=a,a=void 0);if(void 0!==a&&"number"!==typeof a)throw Error("Bad segment '"+a+"', must be 0-based integer");f&&e.shift();0>a&&(a=Math.max(e.length+a,0));if(void 0===b)return void 0===a?e:e[a];if(null===a||void 0===e[a])if(l(b)){e=[];a=0;for(var g=b.length;a<g;a++)if(b[a].length||e.length&&e[e.length-1].length)e.length&&!e[e.length-1].length&&e.pop(),e.push(b[a])}else{if(b||"string"===typeof b)""===e[e.length-1]?e[e.length-1]=b:e.push(b)}else b||"string"===typeof b&&b.length?e[a]=b:e.splice(a,
-1);f&&e.unshift("");return this.path(e.join(d),c)};f.segmentCoded=function(a,b,c){var e,f;"number"!==typeof a&&(c=b,b=a,a=void 0);if(void 0===b){a=this.segment(a,b,c);if(l(a))for(e=0,f=a.length;e<f;e++)a[e]=d.decode(a[e]);else a=void 0!==a?d.decode(a):void 0;return a}if(l(b))for(e=0,f=b.length;e<f;e++)b[e]=d.decode(b[e]);else b="string"===typeof b?d.encode(b):b;return this.segment(a,b,c)};var F=f.query;f.query=function(a,b){if(!0===a)return d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);
-if("function"===typeof a){var c=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace),e=a.call(this,c);this._parts.query=d.buildQuery(e||c,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);this.build(!b);return this}return void 0!==a&&"string"!==typeof a?(this._parts.query=d.buildQuery(a,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this):F.call(this,a,b)};f.setQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);
-if("object"===typeof a)for(var f in a)w.call(a,f)&&(e[f]=a[f]);else if("string"===typeof a)e[a]=void 0!==b?b:null;else throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");this._parts.query=d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.addQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);d.addQuery(e,a,void 0===b?null:b);this._parts.query=
-d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.removeQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);d.removeQuery(e,a,b);this._parts.query=d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.hasQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);
-return d.hasQuery(e,a,b,c)};f.setSearch=f.setQuery;f.addSearch=f.addQuery;f.removeSearch=f.removeQuery;f.hasSearch=f.hasQuery;f.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()};f.normalizeProtocol=function(a){"string"===typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),
-this.build(!a));return this};f.normalizeHostname=function(a){this._parts.hostname&&(this.is("IDN")&&e?this._parts.hostname=e.toASCII(this._parts.hostname):this.is("IPv6")&&k&&(this._parts.hostname=k.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!a));return this};f.normalizePort=function(a){"string"===typeof this._parts.protocol&&this._parts.port===d.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!a));return this};f.normalizePath=
-function(a){if(this._parts.urn||!this._parts.path||"/"===this._parts.path)return this;var b,c=this._parts.path,e="",f,g;"/"!==c.charAt(0)&&(b=!0,c="/"+c);c=c.replace(/(\/(\.\/)+)|(\/\.$)/g,"/").replace(/\/{2,}/g,"/");b&&(e=c.substring(1).match(/^(\.\.\/)+/)||"")&&(e=e[0]);for(;;){f=c.indexOf("/..");if(-1===f)break;else if(0===f){c=c.substring(3);continue}g=c.substring(0,f).lastIndexOf("/");-1===g&&(g=f);c=c.substring(0,g)+c.substring(f+3)}b&&this.is("relative")&&(c=e+c.substring(1));c=d.recodePath(c);
-this._parts.path=c;this.build(!a);return this};f.normalizePathname=f.normalizePath;f.normalizeQuery=function(a){"string"===typeof this._parts.query&&(this._parts.query.length?this.query(d.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!a));return this};f.normalizeFragment=function(a){this._parts.fragment||(this._parts.fragment=null,this.build(!a));return this};f.normalizeSearch=f.normalizeQuery;f.normalizeHash=f.normalizeFragment;f.iso8859=function(){var a=
-d.encode,b=d.decode;d.encode=escape;d.decode=decodeURIComponent;this.normalize();d.encode=a;d.decode=b;return this};f.unicode=function(){var a=d.encode,b=d.decode;d.encode=E;d.decode=unescape;this.normalize();d.encode=a;d.decode=b;return this};f.readable=function(){var a=this.clone();a.username("").password("").normalize();var b="";a._parts.protocol&&(b+=a._parts.protocol+"://");a._parts.hostname&&(a.is("punycode")&&e?(b+=e.toUnicode(a._parts.hostname),a._parts.port&&(b+=":"+a._parts.port)):b+=a.host());
-a._parts.hostname&&a._parts.path&&"/"!==a._parts.path.charAt(0)&&(b+="/");b+=a.path(!0);if(a._parts.query){for(var c="",f=0,g=a._parts.query.split("&"),k=g.length;f<k;f++){var l=(g[f]||"").split("="),c=c+("&"+d.decodeQuery(l[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"));void 0!==l[1]&&(c+="="+d.decodeQuery(l[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}b+="?"+c.substring(1)}return b+=d.decodeQuery(a.hash(),!0)};f.absoluteTo=function(a){var b=this.clone(),c=["protocol","username",
-"password","hostname","port"],e,f;if(this._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");a instanceof d||(a=new d(a));b._parts.protocol||(b._parts.protocol=a._parts.protocol);if(this._parts.hostname)return b;for(e=0;f=c[e];e++)b._parts[f]=a._parts[f];b._parts.path?".."===b._parts.path.substring(-2)&&(b._parts.path+="/"):(b._parts.path=a._parts.path,b._parts.query||(b._parts.query=a._parts.query));"/"!==b.path().charAt(0)&&(a=a.directory(),b._parts.path=(a?
-a+"/":"")+b._parts.path,b.normalizePath());b.build();return b};f.relativeTo=function(a){var b=this.clone().normalize(),c,e,f,g;if(b._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");a=(new d(a)).normalize();c=b._parts;e=a._parts;f=b.path();g=a.path();if("/"!==f.charAt(0))throw Error("URI is already relative");if("/"!==g.charAt(0))throw Error("Cannot calculate a URI relative to another relative URI");c.protocol===e.protocol&&(c.protocol=null);if(c.username===
-e.username&&c.password===e.password&&null===c.protocol&&null===c.username&&null===c.password&&c.hostname===e.hostname&&c.port===e.port)c.hostname=null,c.port=null;else return b.build();if(f===g)return c.path="",b.build();a=d.commonPath(b.path(),a.path());if(!a)return b.build();e=e.path.substring(a.length).replace(/[^\/]*$/,"").replace(/.*?\//g,"../");c.path=e+c.path.substring(a.length);return b.build()};f.equals=function(a){var b=this.clone();a=new d(a);var c={},e={},f={},g;b.normalize();a.normalize();
-if(b.toString()===a.toString())return!0;c=b.query();e=a.query();b.query("");a.query("");if(b.toString()!==a.toString()||c.length!==e.length)return!1;c=d.parseQuery(c,this._parts.escapeQuerySpace);e=d.parseQuery(e,this._parts.escapeQuerySpace);for(g in c)if(w.call(c,g)){if(!l(c[g])){if(c[g]!==e[g])return!1}else if(!z(c[g],e[g]))return!1;f[g]=!0}for(g in e)if(w.call(e,g)&&!f[g])return!1;return!0};f.duplicateQueryParameters=function(a){this._parts.duplicateQueryParameters=!!a;return this};f.escapeQuerySpace=
-function(a){this._parts.escapeQuerySpace=!!a;return this};return d});
-(function(e,k){"object"===typeof exports?module.exports=k(require("./URI")):"function"===typeof define&&define.amd?define(["./URI"],k):k(e.URI)})(this,function(e){var k=e.prototype,u=k.fragment;e.fragmentPrefix="?";var m=e._parts;e._parts=function(){var d=m();d.fragmentPrefix=e.fragmentPrefix;return d};k.fragmentPrefix=function(d){this._parts.fragmentPrefix=d;return this};k.fragment=function(d,g){var k=this._parts.fragmentPrefix,l=this._parts.fragment||"";return!0===d?l.substring(0,k.length)!==k?
-{}:e.parseQuery(l.substring(k.length)):void 0!==d&&"string"!==typeof d?(this._parts.fragment=k+e.buildQuery(d),this.build(!g),this):u.call(this,d,g)};k.addFragment=function(d,g,k){var l=this._parts.fragmentPrefix,m=e.parseQuery((this._parts.fragment||"").substring(l.length));e.addQuery(m,d,g);this._parts.fragment=l+e.buildQuery(m);"string"!==typeof d&&(k=g);this.build(!k);return this};k.removeFragment=function(d,g,k){var l=this._parts.fragmentPrefix,m=e.parseQuery((this._parts.fragment||"").substring(l.length));
-e.removeQuery(m,d,g);this._parts.fragment=l+e.buildQuery(m);"string"!==typeof d&&(k=g);this.build(!k);return this};k.addHash=k.addFragment;k.removeHash=k.removeFragment;return{}});
-;/*global unescape, module, define, window, global*/
-
-/*
- UriTemplate Copyright (c) 2012-2013 Franz Antesberger. All Rights Reserved.
- Available via the MIT license.
-*/
-
-(function (exportCallback) {
-    "use strict";
-
-var UriTemplateError = (function () {
-
-    function UriTemplateError (options) {
-        this.options = options;
-    }
-
-    UriTemplateError.prototype.toString = function () {
-        if (JSON && JSON.stringify) {
-            return JSON.stringify(this.options);
-        }
-        else {
-            return this.options;
-        }
-    };
-
-    return UriTemplateError;
-}());
-
-var objectHelper = (function () {
-    function isArray (value) {
-        return Object.prototype.toString.apply(value) === '[object Array]';
-    }
-
-    function isString (value) {
-        return Object.prototype.toString.apply(value) === '[object String]';
-    }
-    
-    function isNumber (value) {
-        return Object.prototype.toString.apply(value) === '[object Number]';
-    }
-    
-    function isBoolean (value) {
-        return Object.prototype.toString.apply(value) === '[object Boolean]';
-    }
-    
-    function join (arr, separator) {
-        var
-            result = '',
-            first = true,
-            index;
-        for (index = 0; index < arr.length; index += 1) {
-            if (first) {
-                first = false;
-            }
-            else {
-                result += separator;
-            }
-            result += arr[index];
-        }
-        return result;
-    }
-
-    function map (arr, mapper) {
-        var
-            result = [],
-            index = 0;
-        for (; index < arr.length; index += 1) {
-            result.push(mapper(arr[index]));
-        }
-        return result;
-    }
-
-    function filter (arr, predicate) {
-        var
-            result = [],
-            index = 0;
-        for (; index < arr.length; index += 1) {
-            if (predicate(arr[index])) {
-                result.push(arr[index]);
-            }
-        }
-        return result;
-    }
-
-    function deepFreezeUsingObjectFreeze (object) {
-        if (typeof object !== "object" || object === null) {
-            return object;
-        }
-        Object.freeze(object);
-        var property, propertyName;
-        for (propertyName in object) {
-            if (object.hasOwnProperty(propertyName)) {
-                property = object[propertyName];
-                // be aware, arrays are 'object', too
-                if ((typeof property === "object") && !(property instanceof RegExp)) {
-                    deepFreeze(property);
-                }
-            }
-        }
-        return object;
-    }
-
-    function deepFreeze (object) {
-        if (typeof Object.freeze === 'function') {
-            return deepFreezeUsingObjectFreeze(object);
-        }
-        return object;
-    }
-
-
-    return {
-        isArray: isArray,
-        isString: isString,
-        isNumber: isNumber,
-        isBoolean: isBoolean,
-        join: join,
-        map: map,
-        filter: filter,
-        deepFreeze: deepFreeze
-    };
-}());
-
-var charHelper = (function () {
-
-    function isAlpha (chr) {
-        return (chr >= 'a' && chr <= 'z') || ((chr >= 'A' && chr <= 'Z'));
-    }
-
-    function isDigit (chr) {
-        return chr >= '0' && chr <= '9';
-    }
-
-    function isHexDigit (chr) {
-        return isDigit(chr) || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F');
-    }
-
-    return {
-        isAlpha: isAlpha,
-        isDigit: isDigit,
-        isHexDigit: isHexDigit
-    };
-}());
-
-var pctEncoder = (function () {
-    var utf8 = {
-        encode: function (chr) {
-            // see http://ecmanaut.blogspot.de/2006/07/encoding-decoding-utf8-in-javascript.html
-            return unescape(encodeURIComponent(chr));
-        },
-        numBytes: function (firstCharCode) {
-            if (firstCharCode <= 0x7F) {
-                return 1;
-            }
-            else if (0xC2 <= firstCharCode && firstCharCode <= 0xDF) {
-                return 2;
-            }
-            else if (0xE0 <= firstCharCode && firstCharCode <= 0xEF) {
-                return 3;
-            }
-            else if (0xF0 <= firstCharCode && firstCharCode <= 0xF4) {
-                return 4;
-            }
-            // no valid first octet
-            return 0;
-        },
-        isValidFollowingCharCode: function (charCode) {
-            return 0x80 <= charCode && charCode <= 0xBF;
-        }
-    };
-
-    /**
-     * encodes a character, if needed or not.
-     * @param chr
-     * @return pct-encoded character
-     */
-    function encodeCharacter (chr) {
-        var
-            result = '',
-            octets = utf8.encode(chr),
-            octet,
-            index;
-        for (index = 0; index < octets.length; index += 1) {
-            octet = octets.charCodeAt(index);
-            result += '%' + (octet < 0x10 ? '0' : '') + octet.toString(16).toUpperCase();
-        }
-        return result;
-    }
-
-    /**
-     * Returns, whether the given text at start is in the form 'percent hex-digit hex-digit', like '%3F'
-     * @param text
-     * @param start
-     * @return {boolean|*|*}
-     */
-    function isPercentDigitDigit (text, start) {
-        return text.charAt(start) === '%' && charHelper.isHexDigit(text.charAt(start + 1)) && charHelper.isHexDigit(text.charAt(start + 2));
-    }
-
-    /**
-     * Parses a hex number from start with length 2.
-     * @param text a string
-     * @param start the start index of the 2-digit hex number
-     * @return {Number}
-     */
-    function parseHex2 (text, start) {
-        return parseInt(text.substr(start, 2), 16);
-    }
-
-    /**
-     * Returns whether or not the given char sequence is a correctly pct-encoded sequence.
-     * @param chr
-     * @return {boolean}
-     */
-    function isPctEncoded (chr) {
-        if (!isPercentDigitDigit(chr, 0)) {
-            return false;
-        }
-        var firstCharCode = parseHex2(chr, 1);
-        var numBytes = utf8.numBytes(firstCharCode);
-        if (numBytes === 0) {
-            return false;
-        }
-        for (var byteNumber = 1; byteNumber < numBytes; byteNumber += 1) {
-            if (!isPercentDigitDigit(chr, 3*byteNumber) || !utf8.isValidFollowingCharCode(parseHex2(chr, 3*byteNumber + 1))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Reads as much as needed from the text, e.g. '%20' or '%C3%B6'. It does not decode!
-     * @param text
-     * @param startIndex
-     * @return the character or pct-string of the text at startIndex
-     */
-    function pctCharAt(text, startIndex) {
-        var chr = text.charAt(startIndex);
-        if (!isPercentDigitDigit(text, startIndex)) {
-            return chr;
-        }
-        var utf8CharCode = parseHex2(text, startIndex + 1);
-        var numBytes = utf8.numBytes(utf8CharCode);
-        if (numBytes === 0) {
-            return chr;
-        }
-        for (var byteNumber = 1; byteNumber < numBytes; byteNumber += 1) {
-            if (!isPercentDigitDigit(text, startIndex + 3 * byteNumber) || !utf8.isValidFollowingCharCode(parseHex2(text, startIndex + 3 * byteNumber + 1))) {
-                return chr;
-            }
-        }
-        return text.substr(startIndex, 3 * numBytes);
-    }
-
-    return {
-        encodeCharacter: encodeCharacter,
-        isPctEncoded: isPctEncoded,
-        pctCharAt: pctCharAt
-    };
-}());
-
-var rfcCharHelper = (function () {
-
-    /**
-     * Returns if an character is an varchar character according 2.3 of rfc 6570
-     * @param chr
-     * @return (Boolean)
-     */
-    function isVarchar (chr) {
-        return charHelper.isAlpha(chr) || charHelper.isDigit(chr) || chr === '_' || pctEncoder.isPctEncoded(chr);
-    }
-
-    /**
-     * Returns if chr is an unreserved character according 1.5 of rfc 6570
-     * @param chr
-     * @return {Boolean}
-     */
-    function isUnreserved (chr) {
-        return charHelper.isAlpha(chr) || charHelper.isDigit(chr) || chr === '-' || chr === '.' || chr === '_' || chr === '~';
-    }
-
-    /**
-     * Returns if chr is an reserved character according 1.5 of rfc 6570
-     * or the percent character mentioned in 3.2.1.
-     * @param chr
-     * @return {Boolean}
-     */
-    function isReserved (chr) {
-        return chr === ':' || chr === '/' || chr === '?' || chr === '#' || chr === '[' || chr === ']' || chr === '@' || chr === '!' || chr === '$' || chr === '&' || chr === '(' ||
-            chr === ')' || chr === '*' || chr === '+' || chr === ',' || chr === ';' || chr === '=' || chr === "'";
-    }
-
-    return {
-        isVarchar: isVarchar,
-        isUnreserved: isUnreserved,
-        isReserved: isReserved
-    };
-
-}());
-
-/**
- * encoding of rfc 6570
- */
-var encodingHelper = (function () {
-
-    function encode (text, passReserved) {
-        var
-            result = '',
-            index,
-            chr = '';
-        if (typeof text === "number" || typeof text === "boolean") {
-            text = text.toString();
-        }
-        for (index = 0; index < text.length; index += chr.length) {
-            chr = text.charAt(index);
-            result += rfcCharHelper.isUnreserved(chr) || (passReserved && rfcCharHelper.isReserved(chr)) ? chr : pctEncoder.encodeCharacter(chr);
-        }
-        return result;
-    }
-
-    function encodePassReserved (text) {
-        return encode(text, true);
-    }
-
-    function encodeLiteralCharacter (literal, index) {
-        var chr = pctEncoder.pctCharAt(literal, index);
-        if (chr.length > 1) {
-            return chr;
-        }
-        else {
-            return rfcCharHelper.isReserved(chr) || rfcCharHelper.isUnreserved(chr) ? chr : pctEncoder.encodeCharacter(chr);
-        }
-    }
-
-    function encodeLiteral (literal) {
-        var
-            result = '',
-            index,
-            chr = '';
-        for (index = 0; index < literal.length; index += chr.length) {
-            chr = pctEncoder.pctCharAt(literal, index);
-            if (chr.length > 1) {
-                result += chr;
-            }
-            else {
-                result += rfcCharHelper.isReserved(chr) || rfcCharHelper.isUnreserved(chr) ? chr : pctEncoder.encodeCharacter(chr);
-            }
-        }
-        return result;
-    }
-
-    return {
-        encode: encode,
-        encodePassReserved: encodePassReserved,
-        encodeLiteral: encodeLiteral,
-        encodeLiteralCharacter: encodeLiteralCharacter
-    };
-
-}());
-
-
-// the operators defined by rfc 6570
-var operators = (function () {
-
-    var
-        bySymbol = {};
-
-    function create (symbol) {
-        bySymbol[symbol] = {
-            symbol: symbol,
-            separator: (symbol === '?') ? '&' : (symbol === '' || symbol === '+' || symbol === '#') ? ',' : symbol,
-            named: symbol === ';' || symbol === '&' || symbol === '?',
-            ifEmpty: (symbol === '&' || symbol === '?') ? '=' : '',
-            first: (symbol === '+' ) ? '' : symbol,
-            encode: (symbol === '+' || symbol === '#') ? encodingHelper.encodePassReserved : encodingHelper.encode,
-            toString: function () {
-                return this.symbol;
-            }
-        };
-    }
-
-    create('');
-    create('+');
-    create('#');
-    create('.');
-    create('/');
-    create(';');
-    create('?');
-    create('&');
-    return {
-        valueOf: function (chr) {
-            if (bySymbol[chr]) {
-                return bySymbol[chr];
-            }
-            if ("=,!@|".indexOf(chr) >= 0) {
-                return null;
-            }
-            return bySymbol[''];
-        }
-    };
-}());
-
-
-/**
- * Detects, whether a given element is defined in the sense of rfc 6570
- * Section 2.3 of the RFC makes clear defintions:
- * * undefined and null are not defined.
- * * the empty string is defined
- * * an array ("list") is defined, if it is not empty (even if all elements are not defined)
- * * an object ("map") is defined, if it contains at least one property with defined value
- * @param object
- * @return {Boolean}
- */
-function isDefined (object) {
-    var
-        propertyName;
-    if (object === null || object === undefined) {
-        return false;
-    }
-    if (objectHelper.isArray(object)) {
-        // Section 2.3: A variable defined as a list value is considered undefined if the list contains zero members
-        return object.length > 0;
-    }
-    if (typeof object === "string" || typeof object === "number" || typeof object === "boolean") {
-        // falsy values like empty strings, false or 0 are "defined"
-        return true;
-    }
-    // else Object
-    for (propertyName in object) {
-        if (object.hasOwnProperty(propertyName) && isDefined(object[propertyName])) {
-            return true;
-        }
-    }
-    return false;
-}
-
-var LiteralExpression = (function () {
-    function LiteralExpression (literal) {
-        this.literal = encodingHelper.encodeLiteral(literal);
-    }
-
-    LiteralExpression.prototype.expand = function () {
-        return this.literal;
-    };
-
-    LiteralExpression.prototype.toString = LiteralExpression.prototype.expand;
-
-    return LiteralExpression;
-}());
-
-var parse = (function () {
-
-    function parseExpression (expressionText) {
-        var
-            operator,
-            varspecs = [],
-            varspec = null,
-            varnameStart = null,
-            maxLengthStart = null,
-            index,
-            chr = '';
-
-        function closeVarname () {
-            var varname = expressionText.substring(varnameStart, index);
-            if (varname.length === 0) {
-                throw new UriTemplateError({expressionText: expressionText, message: "a varname must be specified", position: index});
-            }
-            varspec = {varname: varname, exploded: false, maxLength: null};
-            varnameStart = null;
-        }
-
-        function closeMaxLength () {
-            if (maxLengthStart === index) {
-                throw new UriTemplateError({expressionText: expressionText, message: "after a ':' you have to specify the length", position: index});
-            }
-            varspec.maxLength = parseInt(expressionText.substring(maxLengthStart, index), 10);
-            maxLengthStart = null;
-        }
-
-        operator = (function (operatorText) {
-            var op = operators.valueOf(operatorText);
-            if (op === null) {
-                throw new UriTemplateError({expressionText: expressionText, message: "illegal use of reserved operator", position: index, operator: operatorText});
-            }
-            return op;
-        }(expressionText.charAt(0)));
-        index = operator.symbol.length;
-
-        varnameStart = index;
-
-        for (; index < expressionText.length; index += chr.length) {
-            chr = pctEncoder.pctCharAt(expressionText, index);
-
-            if (varnameStart !== null) {
-                // the spec says: varname =  varchar *( ["."] varchar )
-                // so a dot is allowed except for the first char
-                if (chr === '.') {
-                    if (varnameStart === index) {
-                        throw new UriTemplateError({expressionText: expressionText, message: "a varname MUST NOT start with a dot", position: index});
-                    }
-                    continue;
-                }
-                if (rfcCharHelper.isVarchar(chr)) {
-                    continue;
-                }
-                closeVarname();
-            }
-            if (maxLengthStart !== null) {
-                if (index === maxLengthStart && chr === '0') {
-                    throw new UriTemplateError({expressionText: expressionText, message: "A :prefix must not start with digit 0", position: index});
-                }
-                if (charHelper.isDigit(chr)) {
-                    if (index - maxLengthStart >= 4) {
-                        throw new UriTemplateError({expressionText: expressionText, message: "A :prefix must have max 4 digits", position: index});
-                    }
-                    continue;
-                }
-                closeMaxLength();
-            }
-            if (chr === ':') {
-                if (varspec.maxLength !== null) {
-                    throw new UriTemplateError({expressionText: expressionText, message: "only one :maxLength is allowed per varspec", position: index});
-                }
-                if (varspec.exploded) {
-                    throw new UriTemplateError({expressionText: expressionText, message: "an exploeded varspec MUST NOT be varspeced", position: index});
-                }
-                maxLengthStart = index + 1;
-                continue;
-            }
-            if (chr === '*') {
-                if (varspec === null) {
-                    throw new UriTemplateError({expressionText: expressionText, message: "exploded without varspec", position: index});
-                }
-                if (varspec.exploded) {
-                    throw new UriTemplateError({expressionText: expressionText, message: "exploded twice", position: index});
-                }
-                if (varspec.maxLength) {
-                    throw new UriTemplateError({expressionText: expressionText, message: "an explode (*) MUST NOT follow to a prefix", position: index});
-                }
-                varspec.exploded = true;
-                continue;
-            }
-            // the only legal character now is the comma
-            if (chr === ',') {
-                varspecs.push(varspec);
-                varspec = null;
-                varnameStart = index + 1;
-                continue;
-            }
-            throw new UriTemplateError({expressionText: expressionText, message: "illegal character", character: chr, position: index});
-        } // for chr
-        if (varnameStart !== null) {
-            closeVarname();
-        }
-        if (maxLengthStart !== null) {
-            closeMaxLength();
-        }
-        varspecs.push(varspec);
-        return new VariableExpression(expressionText, operator, varspecs);
-    }
-
-    function escape_regexp_string(string) {
-      // http://simonwillison.net/2006/Jan/20/escape/
-      return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
-    }
-
-    function parse (uriTemplateText) {
-        // assert filled string
-        var
-            index,
-            chr,
-            expressions = [],
-            expression,
-            braceOpenIndex = null,
-            regexp_string = '',
-            can_match = true,
-            literalStart = 0;
-        for (index = 0; index < uriTemplateText.length; index += 1) {
-            chr = uriTemplateText.charAt(index);
-            if (literalStart !== null) {
-                if (chr === '}') {
-                    throw new UriTemplateError({templateText: uriTemplateText, message: "unopened brace closed", position: index});
-                }
-                if (chr === '{') {
-                    if (literalStart < index) {
-                        expression = new LiteralExpression(uriTemplateText.substring(literalStart, index));
-                        expressions.push(expression);
-                        regexp_string += escape_regexp_string(
-                            expression.literal);
-                    }
-                    literalStart = null;
-                    braceOpenIndex = index;
-                }
-                continue;
-            }
-
-            if (braceOpenIndex !== null) {
-                // here just { is forbidden
-                if (chr === '{') {
-                    throw new UriTemplateError({templateText: uriTemplateText, message: "brace already opened", position: index});
-                }
-                if (chr === '}') {
-                    if (braceOpenIndex + 1 === index) {
-                        throw new UriTemplateError({templateText: uriTemplateText, message: "empty braces", position: braceOpenIndex});
-                    }
-                    try {
-                        expression = parseExpression(uriTemplateText.substring(braceOpenIndex + 1, index));
-                    }
-                    catch (error) {
-                        if (error.prototype === UriTemplateError.prototype) {
-                            throw new UriTemplateError({templateText: uriTemplateText, message: error.options.message, position: braceOpenIndex + error.options.position, details: error.options});
-                        }
-                        throw error;
-                    }
-                    expressions.push(expression);
-                    if (expression.operator.symbol.length === 0) {
-                      regexp_string += "([^/]+)";
-                    } else {
-                      can_match = false;
-                    }
-                    braceOpenIndex = null;
-                    literalStart = index + 1;
-                }
-                continue;
-            }
-            throw new Error('reached unreachable code');
-        }
-        if (braceOpenIndex !== null) {
-            throw new UriTemplateError({templateText: uriTemplateText, message: "unclosed brace", position: braceOpenIndex});
-        }
-        if (literalStart < uriTemplateText.length) {
-            expression = new LiteralExpression(uriTemplateText.substring(literalStart));
-            expressions.push(expression);
-            regexp_string += escape_regexp_string(expression.literal);
-        }
-        if (can_match === false) {
-          regexp_string = undefined;
-        }
-        return new UriTemplate(uriTemplateText, expressions, regexp_string);
-    }
-
-    return parse;
-}());
-
-var VariableExpression = (function () {
-    // helper function if JSON is not available
-    function prettyPrint (value) {
-        return (JSON && JSON.stringify) ? JSON.stringify(value) : value;
-    }
-
-    function isEmpty (value) {
-        if (!isDefined(value)) {
-            return true;
-        }
-        if (objectHelper.isString(value)) {
-            return value === '';
-        }
-        if (objectHelper.isNumber(value) || objectHelper.isBoolean(value)) {
-            return false;
-        }
-        if (objectHelper.isArray(value)) {
-            return value.length === 0;
-        }
-        for (var propertyName in value) {
-            if (value.hasOwnProperty(propertyName)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    function propertyArray (object) {
-        var
-            result = [],
-            propertyName;
-        for (propertyName in object) {
-            if (object.hasOwnProperty(propertyName)) {
-                result.push({name: propertyName, value: object[propertyName]});
-            }
-        }
-        return result;
-    }
-
-    function VariableExpression (templateText, operator, varspecs) {
-        this.templateText = templateText;
-        this.operator = operator;
-        this.varspecs = varspecs;
-    }
-
-    VariableExpression.prototype.toString = function () {
-        return this.templateText;
-    };
-
-    function expandSimpleValue(varspec, operator, value) {
-        var result = '';
-        value = value.toString();
-        if (operator.named) {
-            result += encodingHelper.encodeLiteral(varspec.varname);
-            if (value === '') {
-                result += operator.ifEmpty;
-                return result;
-            }
-            result += '=';
-        }
-        if (varspec.maxLength !== null) {
-            value = value.substr(0, varspec.maxLength);
-        }
-        result += operator.encode(value);
-        return result;
-    }
-
-    function valueDefined (nameValue) {
-        return isDefined(nameValue.value);
-    }
-
-    function expandNotExploded(varspec, operator, value) {
-        var
-            arr = [],
-            result = '';
-        if (operator.named) {
-            result += encodingHelper.encodeLiteral(varspec.varname);
-            if (isEmpty(value)) {
-                result += operator.ifEmpty;
-                return result;
-            }
-            result += '=';
-        }
-        if (objectHelper.isArray(value)) {
-            arr = value;
-            arr = objectHelper.filter(arr, isDefined);
-            arr = objectHelper.map(arr, operator.encode);
-            result += objectHelper.join(arr, ',');
-        }
-        else {
-            arr = propertyArray(value);
-            arr = objectHelper.filter(arr, valueDefined);
-            arr = objectHelper.map(arr, function (nameValue) {
-                return operator.encode(nameValue.name) + ',' + operator.encode(nameValue.value);
-            });
-            result += objectHelper.join(arr, ',');
-        }
-        return result;
-    }
-
-    function expandExplodedNamed (varspec, operator, value) {
-        var
-            isArray = objectHelper.isArray(value),
-            arr = [];
-        if (isArray) {
-            arr = value;
-            arr = objectHelper.filter(arr, isDefined);
-            arr = objectHelper.map(arr, function (listElement) {
-                var tmp = encodingHelper.encodeLiteral(varspec.varname);
-                if (isEmpty(listElement)) {
-                    tmp += operator.ifEmpty;
-                }
-                else {
-                    tmp += '=' + operator.encode(listElement);
-                }
-                return tmp;
-            });
-        }
-        else {
-            arr = propertyArray(value);
-            arr = objectHelper.filter(arr, valueDefined);
-            arr = objectHelper.map(arr, function (nameValue) {
-                var tmp = encodingHelper.encodeLiteral(nameValue.name);
-                if (isEmpty(nameValue.value)) {
-                    tmp += operator.ifEmpty;
-                }
-                else {
-                    tmp += '=' + operator.encode(nameValue.value);
-                }
-                return tmp;
-            });
-        }
-        return objectHelper.join(arr, operator.separator);
-    }
-
-    function expandExplodedUnnamed (operator, value) {
-        var
-            arr = [],
-            result = '';
-        if (objectHelper.isArray(value)) {
-            arr = value;
-            arr = objectHelper.filter(arr, isDefined);
-            arr = objectHelper.map(arr, operator.encode);
-            result += objectHelper.join(arr, operator.separator);
-        }
-        else {
-            arr = propertyArray(value);
-            arr = objectHelper.filter(arr, function (nameValue) {
-                return isDefined(nameValue.value);
-            });
-            arr = objectHelper.map(arr, function (nameValue) {
-                return operator.encode(nameValue.name) + '=' + operator.encode(nameValue.value);
-            });
-            result += objectHelper.join(arr, operator.separator);
-        }
-        return result;
-    }
-
-
-    VariableExpression.prototype.expand = function (variables) {
-        var
-            expanded = [],
-            index,
-            varspec,
-            value,
-            valueIsArr,
-            oneExploded = false,
-            operator = this.operator;
-
-        // expand each varspec and join with operator's separator
-        for (index = 0; index < this.varspecs.length; index += 1) {
-            varspec = this.varspecs[index];
-            value = variables[varspec.varname];
-            // if (!isDefined(value)) {
-            // if (variables.hasOwnProperty(varspec.name)) {
-            if (value === null || value === undefined) {
-                continue;
-            }
-            if (varspec.exploded) {
-                oneExploded = true;
-            }
-            valueIsArr = objectHelper.isArray(value);
-            if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
-                expanded.push(expandSimpleValue(varspec, operator, value));
-            }
-            else if (varspec.maxLength && isDefined(value)) {
-                // 2.4.1 of the spec says: "Prefix modifiers are not applicable to variables that have composite values."
-                throw new Error('Prefix modifiers are not applicable to variables that have composite values. You tried to expand ' + this + " with " + prettyPrint(value));
-            }
-            else if (!varspec.exploded) {
-                if (operator.named || !isEmpty(value)) {
-                    expanded.push(expandNotExploded(varspec, operator, value));
-                }
-            }
-            else if (isDefined(value)) {
-                if (operator.named) {
-                    expanded.push(expandExplodedNamed(varspec, operator, value));
-                }
-                else {
-                    expanded.push(expandExplodedUnnamed(operator, value));
-                }
-            }
-        }
-
-        if (expanded.length === 0) {
-            return "";
-        }
-        else {
-            return operator.first + objectHelper.join(expanded, operator.separator);
-        }
-    };
-
-    return VariableExpression;
-}());
-
-var UriTemplate = (function () {
-    function UriTemplate (templateText, expressions, regexp_string) {
-        this.templateText = templateText;
-        this.expressions = expressions;
-
-        if (regexp_string !== undefined) {
-          this.regexp = new RegExp("^" + regexp_string + "$");
-        }
-
-        objectHelper.deepFreeze(this);
-    }
-
-    UriTemplate.prototype.toString = function () {
-        return this.templateText;
-    };
-
-    UriTemplate.prototype.expand = function (variables) {
-        // this.expressions.map(function (expression) {return expression.expand(variables);}).join('');
-        var
-            index,
-            result = '';
-        for (index = 0; index < this.expressions.length; index += 1) {
-            result += this.expressions[index].expand(variables);
-        }
-        return result;
-    };
-
-    UriTemplate.prototype.extract = function (text) {
-      var expression_index,
-          extracted_index = 1,
-          expression,
-          varspec,
-          matched = true,
-          variables = {},
-          result;
-
-      if ((this.regexp !== undefined) && (this.regexp.test(text))) {
-        result = this.regexp.exec(text);
-        for (expression_index = 0; expression_index < this.expressions.length; expression_index += 1) {
-          expression = this.expressions[expression_index];
-          if (expression.literal === undefined) {
-            if ((expression.operator !== undefined) && (expression.operator.symbol.length === 0) && (expression.varspecs.length === 1)) {
-              varspec = expression.varspecs[0];
-              if ((varspec.exploded === false) && (varspec.maxLength === null)) {
-                if (result[extracted_index].indexOf(',') === -1) {
-                  variables[varspec.varname] = decodeURIComponent(result[extracted_index]);
-                  extracted_index += 1;
-                } else {
-                  matched = false;
-                }
-              } else {
-                matched = false;
-              }
-            } else {
-              matched = false;
-            }
-          }
-        }
-        if (matched) {
-          return variables;
-        }
-      }
-      return false;
-    };
-
-    UriTemplate.parse = parse;
-    UriTemplate.UriTemplateError = UriTemplateError;
-    return UriTemplate;
-}());
-
-    exportCallback(UriTemplate);
-
-}(function (UriTemplate) {
-        "use strict";
-        // export UriTemplate, when module is present, or pass it to window or global
-        if (typeof module !== "undefined") {
-            module.exports = UriTemplate;
-        }
-        else if (typeof define === "function") {
-            define([],function() {
-                return UriTemplate;
-            });
-        }
-        else if (typeof window !== "undefined") {
-            window.UriTemplate = UriTemplate;
-        }
-        else {
-            global.UriTemplate = UriTemplate;
-        }
-    }
-));
-;// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
-// This work is free. You can redistribute it and/or modify it
-// under the terms of the WTFPL, Version 2
-// For more information see LICENSE.txt or http://www.wtfpl.net/
-//
-// For more information, the home page:
-// http://pieroxy.net/blog/pages/lz-string/testing.html
-//
-// LZ-based compression algorithm, version 1.4.4
-var LZString = (function() {
-
-// private property
-var f = String.fromCharCode;
-var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
-var baseReverseDic = {};
-
-function getBaseValue(alphabet, character) {
-  if (!baseReverseDic[alphabet]) {
-    baseReverseDic[alphabet] = {};
-    for (var i=0 ; i<alphabet.length ; i++) {
-      baseReverseDic[alphabet][alphabet.charAt(i)] = i;
-    }
-  }
-  return baseReverseDic[alphabet][character];
-}
-
-var LZString = {
-  compressToBase64 : function (input) {
-    if (input == null) return "";
-    var res = LZString._compress(input, 6, function(a){return keyStrBase64.charAt(a);});
-    switch (res.length % 4) { // To produce valid Base64
-    default: // When could this happen ?
-    case 0 : return res;
-    case 1 : return res+"===";
-    case 2 : return res+"==";
-    case 3 : return res+"=";
-    }
-  },
-
-  decompressFromBase64 : function (input) {
-    if (input == null) return "";
-    if (input == "") return null;
-    return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrBase64, input.charAt(index)); });
-  },
-
-  compressToUTF16 : function (input) {
-    if (input == null) return "";
-    return LZString._compress(input, 15, function(a){return f(a+32);}) + " ";
-  },
-
-  decompressFromUTF16: function (compressed) {
-    if (compressed == null) return "";
-    if (compressed == "") return null;
-    return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; });
-  },
-
-  //compress into uint8array (UCS-2 big endian format)
-  compressToUint8Array: function (uncompressed) {
-    var compressed = LZString.compress(uncompressed);
-    var buf=new Uint8Array(compressed.length*2); // 2 bytes per character
-
-    for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) {
-      var current_value = compressed.charCodeAt(i);
-      buf[i*2] = current_value >>> 8;
-      buf[i*2+1] = current_value % 256;
-    }
-    return buf;
-  },
-
-  //decompress from uint8array (UCS-2 big endian format)
-  decompressFromUint8Array:function (compressed) {
-    if (compressed===null || compressed===undefined){
-        return LZString.decompress(compressed);
-    } else {
-        var buf=new Array(compressed.length/2); // 2 bytes per character
-        for (var i=0, TotalLen=buf.length; i<TotalLen; i++) {
-          buf[i]=compressed[i*2]*256+compressed[i*2+1];
-        }
-
-        var result = [];
-        buf.forEach(function (c) {
-          result.push(f(c));
-        });
-        return LZString.decompress(result.join(''));
-
-    }
-
-  },
-
-
-  //compress into a string that is already URI encoded
-  compressToEncodedURIComponent: function (input) {
-    if (input == null) return "";
-    return LZString._compress(input, 6, function(a){return keyStrUriSafe.charAt(a);});
-  },
-
-  //decompress from an output of compressToEncodedURIComponent
-  decompressFromEncodedURIComponent:function (input) {
-    if (input == null) return "";
-    if (input == "") return null;
-    input = input.replace(/ /g, "+");
-    return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrUriSafe, input.charAt(index)); });
-  },
-
-  compress: function (uncompressed) {
-    return LZString._compress(uncompressed, 16, function(a){return f(a);});
-  },
-  _compress: function (uncompressed, bitsPerChar, getCharFromInt) {
-    if (uncompressed == null) return "";
-    var i, value,
-        context_dictionary= {},
-        context_dictionaryToCreate= {},
-        context_c="",
-        context_wc="",
-        context_w="",
-        context_enlargeIn= 2, // Compensate for the first entry which should not count
-        context_dictSize= 3,
-        context_numBits= 2,
-        context_data=[],
-        context_data_val=0,
-        context_data_position=0,
-        ii;
-
-    for (ii = 0; ii < uncompressed.length; ii += 1) {
-      context_c = uncompressed.charAt(ii);
-      if (!Object.prototype.hasOwnProperty.call(context_dictionary,context_c)) {
-        context_dictionary[context_c] = context_dictSize++;
-        context_dictionaryToCreate[context_c] = true;
-      }
-
-      context_wc = context_w + context_c;
-      if (Object.prototype.hasOwnProperty.call(context_dictionary,context_wc)) {
-        context_w = context_wc;
-      } else {
-        if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
-          if (context_w.charCodeAt(0)<256) {
-            for (i=0 ; i<context_numBits ; i++) {
-              context_data_val = (context_data_val << 1);
-              if (context_data_position == bitsPerChar-1) {
-                context_data_position = 0;
-                context_data.push(getCharFromInt(context_data_val));
-                context_data_val = 0;
-              } else {
-                context_data_position++;
-              }
-            }
-            value = context_w.charCodeAt(0);
-            for (i=0 ; i<8 ; i++) {
-              context_data_val = (context_data_val << 1) | (value&1);
-              if (context_data_position == bitsPerChar-1) {
-                context_data_position = 0;
-                context_data.push(getCharFromInt(context_data_val));
-                context_data_val = 0;
-              } else {
-                context_data_position++;
-              }
-              value = value >> 1;
-            }
-          } else {
-            value = 1;
-            for (i=0 ; i<context_numBits ; i++) {
-              context_data_val = (context_data_val << 1) | value;
-              if (context_data_position ==bitsPerChar-1) {
-                context_data_position = 0;
-                context_data.push(getCharFromInt(context_data_val));
-                context_data_val = 0;
-              } else {
-                context_data_position++;
-              }
-              value = 0;
-            }
-            value = context_w.charCodeAt(0);
-            for (i=0 ; i<16 ; i++) {
-              context_data_val = (context_data_val << 1) | (value&1);
-              if (context_data_position == bitsPerChar-1) {
-                context_data_position = 0;
-                context_data.push(getCharFromInt(context_data_val));
-                context_data_val = 0;
-              } else {
-                context_data_position++;
-              }
-              value = value >> 1;
-            }
-          }
-          context_enlargeIn--;
-          if (context_enlargeIn == 0) {
-            context_enlargeIn = Math.pow(2, context_numBits);
-            context_numBits++;
-          }
-          delete context_dictionaryToCreate[context_w];
-        } else {
-          value = context_dictionary[context_w];
-          for (i=0 ; i<context_numBits ; i++) {
-            context_data_val = (context_data_val << 1) | (value&1);
-            if (context_data_position == bitsPerChar-1) {
-              context_data_position = 0;
-              context_data.push(getCharFromInt(context_data_val));
-              context_data_val = 0;
-            } else {
-              context_data_position++;
-            }
-            value = value >> 1;
-          }
-
-
-        }
-        context_enlargeIn--;
-        if (context_enlargeIn == 0) {
-          context_enlargeIn = Math.pow(2, context_numBits);
-          context_numBits++;
-        }
-        // Add wc to the dictionary.
-        context_dictionary[context_wc] = context_dictSize++;
-        context_w = String(context_c);
-      }
-    }
-
-    // Output the code for w.
-    if (context_w !== "") {
-      if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
-        if (context_w.charCodeAt(0)<256) {
-          for (i=0 ; i<context_numBits ; i++) {
-            context_data_val = (context_data_val << 1);
-            if (context_data_position == bitsPerChar-1) {
-              context_data_position = 0;
-              context_data.push(getCharFromInt(context_data_val));
-              context_data_val = 0;
-            } else {
-              context_data_position++;
-            }
-          }
-          value = context_w.charCodeAt(0);
-          for (i=0 ; i<8 ; i++) {
-            context_data_val = (context_data_val << 1) | (value&1);
-            if (context_data_position == bitsPerChar-1) {
-              context_data_position = 0;
-              context_data.push(getCharFromInt(context_data_val));
-              context_data_val = 0;
-            } else {
-              context_data_position++;
-            }
-            value = value >> 1;
-          }
-        } else {
-          value = 1;
-          for (i=0 ; i<context_numBits ; i++) {
-            context_data_val = (context_data_val << 1) | value;
-            if (context_data_position == bitsPerChar-1) {
-              context_data_position = 0;
-              context_data.push(getCharFromInt(context_data_val));
-              context_data_val = 0;
-            } else {
-              context_data_position++;
-            }
-            value = 0;
-          }
-          value = context_w.charCodeAt(0);
-          for (i=0 ; i<16 ; i++) {
-            context_data_val = (context_data_val << 1) | (value&1);
-            if (context_data_position == bitsPerChar-1) {
-              context_data_position = 0;
-              context_data.push(getCharFromInt(context_data_val));
-              context_data_val = 0;
-            } else {
-              context_data_position++;
-            }
-            value = value >> 1;
-          }
-        }
-        context_enlargeIn--;
-        if (context_enlargeIn == 0) {
-          context_enlargeIn = Math.pow(2, context_numBits);
-          context_numBits++;
-        }
-        delete context_dictionaryToCreate[context_w];
-      } else {
-        value = context_dictionary[context_w];
-        for (i=0 ; i<context_numBits ; i++) {
-          context_data_val = (context_data_val << 1) | (value&1);
-          if (context_data_position == bitsPerChar-1) {
-            context_data_position = 0;
-            context_data.push(getCharFromInt(context_data_val));
-            context_data_val = 0;
-          } else {
-            context_data_position++;
-          }
-          value = value >> 1;
-        }
-
-
-      }
-      context_enlargeIn--;
-      if (context_enlargeIn == 0) {
-        context_enlargeIn = Math.pow(2, context_numBits);
-        context_numBits++;
-      }
-    }
-
-    // Mark the end of the stream
-    value = 2;
-    for (i=0 ; i<context_numBits ; i++) {
-      context_data_val = (context_data_val << 1) | (value&1);
-      if (context_data_position == bitsPerChar-1) {
-        context_data_position = 0;
-        context_data.push(getCharFromInt(context_data_val));
-        context_data_val = 0;
-      } else {
-        context_data_position++;
-      }
-      value = value >> 1;
-    }
-
-    // Flush the last char
-    while (true) {
-      context_data_val = (context_data_val << 1);
-      if (context_data_position == bitsPerChar-1) {
-        context_data.push(getCharFromInt(context_data_val));
-        break;
-      }
-      else context_data_position++;
-    }
-    return context_data.join('');
-  },
-
-  decompress: function (compressed) {
-    if (compressed == null) return "";
-    if (compressed == "") return null;
-    return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); });
-  },
-
-  _decompress: function (length, resetValue, getNextValue) {
-    var dictionary = [],
-        next,
-        enlargeIn = 4,
-        dictSize = 4,
-        numBits = 3,
-        entry = "",
-        result = [],
-        i,
-        w,
-        bits, resb, maxpower, power,
-        c,
-        data = {val:getNextValue(0), position:resetValue, index:1};
-
-    for (i = 0; i < 3; i += 1) {
-      dictionary[i] = i;
-    }
-
-    bits = 0;
-    maxpower = Math.pow(2,2);
-    power=1;
-    while (power!=maxpower) {
-      resb = data.val & data.position;
-      data.position >>= 1;
-      if (data.position == 0) {
-        data.position = resetValue;
-        data.val = getNextValue(data.index++);
-      }
-      bits |= (resb>0 ? 1 : 0) * power;
-      power <<= 1;
-    }
-
-    switch (next = bits) {
-      case 0:
-          bits = 0;
-          maxpower = Math.pow(2,8);
-          power=1;
-          while (power!=maxpower) {
-            resb = data.val & data.position;
-            data.position >>= 1;
-            if (data.position == 0) {
-              data.position = resetValue;
-              data.val = getNextValue(data.index++);
-            }
-            bits |= (resb>0 ? 1 : 0) * power;
-            power <<= 1;
-          }
-        c = f(bits);
-        break;
-      case 1:
-          bits = 0;
-          maxpower = Math.pow(2,16);
-          power=1;
-          while (power!=maxpower) {
-            resb = data.val & data.position;
-            data.position >>= 1;
-            if (data.position == 0) {
-              data.position = resetValue;
-              data.val = getNextValue(data.index++);
-            }
-            bits |= (resb>0 ? 1 : 0) * power;
-            power <<= 1;
-          }
-        c = f(bits);
-        break;
-      case 2:
-        return "";
-    }
-    dictionary[3] = c;
-    w = c;
-    result.push(c);
-    while (true) {
-      if (data.index > length) {
-        return "";
-      }
-
-      bits = 0;
-      maxpower = Math.pow(2,numBits);
-      power=1;
-      while (power!=maxpower) {
-        resb = data.val & data.position;
-        data.position >>= 1;
-        if (data.position == 0) {
-          data.position = resetValue;
-          data.val = getNextValue(data.index++);
-        }
-        bits |= (resb>0 ? 1 : 0) * power;
-        power <<= 1;
-      }
-
-      switch (c = bits) {
-        case 0:
-          bits = 0;
-          maxpower = Math.pow(2,8);
-          power=1;
-          while (power!=maxpower) {
-            resb = data.val & data.position;
-            data.position >>= 1;
-            if (data.position == 0) {
-              data.position = resetValue;
-              data.val = getNextValue(data.index++);
-            }
-            bits |= (resb>0 ? 1 : 0) * power;
-            power <<= 1;
-          }
-
-          dictionary[dictSize++] = f(bits);
-          c = dictSize-1;
-          enlargeIn--;
-          break;
-        case 1:
-          bits = 0;
-          maxpower = Math.pow(2,16);
-          power=1;
-          while (power!=maxpower) {
-            resb = data.val & data.position;
-            data.position >>= 1;
-            if (data.position == 0) {
-              data.position = resetValue;
-              data.val = getNextValue(data.index++);
-            }
-            bits |= (resb>0 ? 1 : 0) * power;
-            power <<= 1;
-          }
-          dictionary[dictSize++] = f(bits);
-          c = dictSize-1;
-          enlargeIn--;
-          break;
-        case 2:
-          return result.join('');
-      }
-
-      if (enlargeIn == 0) {
-        enlargeIn = Math.pow(2, numBits);
-        numBits++;
-      }
-
-      if (dictionary[c]) {
-        entry = dictionary[c];
-      } else {
-        if (c === dictSize) {
-          entry = w + w.charAt(0);
-        } else {
-          return null;
-        }
-      }
-      result.push(entry);
-
-      // Add w+entry[0] to the dictionary.
-      dictionary[dictSize++] = w + entry.charAt(0);
-      enlargeIn--;
-
-      w = entry;
-
-      if (enlargeIn == 0) {
-        enlargeIn = Math.pow(2, numBits);
-        numBits++;
-      }
-
-    }
-  }
-};
-  return LZString;
-})();
-
-if (typeof define === 'function' && define.amd) {
-  define(function () { return LZString; });
-} else if( typeof module !== 'undefined' && module != null ) {
-  module.exports = LZString
-}
-;//! moment.js
-//! version : 2.13.0
-//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
-//! license : MIT
-//! momentjs.com
-
-;(function (global, factory) {
-    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
-    typeof define === 'function' && define.amd ? define(factory) :
-    global.moment = factory()
-}(this, function () { 'use strict';
-
-    var hookCallback;
-
-    function utils_hooks__hooks () {
-        return hookCallback.apply(null, arguments);
-    }
-
-    // This is done to register the method called with moment()
-    // without creating circular dependencies.
-    function setHookCallback (callback) {
-        hookCallback = callback;
-    }
-
-    function isArray(input) {
-        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
-    }
-
-    function isDate(input) {
-        return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
-    }
-
-    function map(arr, fn) {
-        var res = [], i;
-        for (i = 0; i < arr.length; ++i) {
-            res.push(fn(arr[i], i));
-        }
-        return res;
-    }
-
-    function hasOwnProp(a, b) {
-        return Object.prototype.hasOwnProperty.call(a, b);
-    }
-
-    function extend(a, b) {
-        for (var i in b) {
-            if (hasOwnProp(b, i)) {
-                a[i] = b[i];
-            }
-        }
-
-        if (hasOwnProp(b, 'toString')) {
-            a.toString = b.toString;
-        }
-
-        if (hasOwnProp(b, 'valueOf')) {
-            a.valueOf = b.valueOf;
-        }
-
-        return a;
-    }
-
-    function create_utc__createUTC (input, format, locale, strict) {
-        return createLocalOrUTC(input, format, locale, strict, true).utc();
-    }
-
-    function defaultParsingFlags() {
-        // We need to deep clone this object.
-        return {
-            empty           : false,
-            unusedTokens    : [],
-            unusedInput     : [],
-            overflow        : -2,
-            charsLeftOver   : 0,
-            nullInput       : false,
-            invalidMonth    : null,
-            invalidFormat   : false,
-            userInvalidated : false,
-            iso             : false,
-            parsedDateParts : [],
-            meridiem        : null
-        };
-    }
-
-    function getParsingFlags(m) {
-        if (m._pf == null) {
-            m._pf = defaultParsingFlags();
-        }
-        return m._pf;
-    }
-
-    var some;
-    if (Array.prototype.some) {
-        some = Array.prototype.some;
-    } else {
-        some = function (fun) {
-            var t = Object(this);
-            var len = t.length >>> 0;
-
-            for (var i = 0; i < len; i++) {
-                if (i in t && fun.call(this, t[i], i, t)) {
-                    return true;
-                }
-            }
-
-            return false;
-        };
-    }
-
-    function valid__isValid(m) {
-        if (m._isValid == null) {
-            var flags = getParsingFlags(m);
-            var parsedParts = some.call(flags.parsedDateParts, function (i) {
-                return i != null;
-            });
-            m._isValid = !isNaN(m._d.getTime()) &&
-                flags.overflow < 0 &&
-                !flags.empty &&
-                !flags.invalidMonth &&
-                !flags.invalidWeekday &&
-                !flags.nullInput &&
-                !flags.invalidFormat &&
-                !flags.userInvalidated &&
-                (!flags.meridiem || (flags.meridiem && parsedParts));
-
-            if (m._strict) {
-                m._isValid = m._isValid &&
-                    flags.charsLeftOver === 0 &&
-                    flags.unusedTokens.length === 0 &&
-                    flags.bigHour === undefined;
-            }
-        }
-        return m._isValid;
-    }
-
-    function valid__createInvalid (flags) {
-        var m = create_utc__createUTC(NaN);
-        if (flags != null) {
-            extend(getParsingFlags(m), flags);
-        }
-        else {
-            getParsingFlags(m).userInvalidated = true;
-        }
-
-        return m;
-    }
-
-    function isUndefined(input) {
-        return input === void 0;
-    }
-
-    // Plugins that add properties should also add the key here (null value),
-    // so we can properly clone ourselves.
-    var momentProperties = utils_hooks__hooks.momentProperties = [];
-
-    function copyConfig(to, from) {
-        var i, prop, val;
-
-        if (!isUndefined(from._isAMomentObject)) {
-            to._isAMomentObject = from._isAMomentObject;
-        }
-        if (!isUndefined(from._i)) {
-            to._i = from._i;
-        }
-        if (!isUndefined(from._f)) {
-            to._f = from._f;
-        }
-        if (!isUndefined(from._l)) {
-            to._l = from._l;
-        }
-        if (!isUndefined(from._strict)) {
-            to._strict = from._strict;
-        }
-        if (!isUndefined(from._tzm)) {
-            to._tzm = from._tzm;
-        }
-        if (!isUndefined(from._isUTC)) {
-            to._isUTC = from._isUTC;
-        }
-        if (!isUndefined(from._offset)) {
-            to._offset = from._offset;
-        }
-        if (!isUndefined(from._pf)) {
-            to._pf = getParsingFlags(from);
-        }
-        if (!isUndefined(from._locale)) {
-            to._locale = from._locale;
-        }
-
-        if (momentProperties.length > 0) {
-            for (i in momentProperties) {
-                prop = momentProperties[i];
-                val = from[prop];
-                if (!isUndefined(val)) {
-                    to[prop] = val;
-                }
-            }
-        }
-
-        return to;
-    }
-
-    var updateInProgress = false;
-
-    // Moment prototype object
-    function Moment(config) {
-        copyConfig(this, config);
-        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
-        // Prevent infinite loop in case updateOffset creates new moment
-        // objects.
-        if (updateInProgress === false) {
-            updateInProgress = true;
-            utils_hooks__hooks.updateOffset(this);
-            updateInProgress = false;
-        }
-    }
-
-    function isMoment (obj) {
-        return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
-    }
-
-    function absFloor (number) {
-        if (number < 0) {
-            return Math.ceil(number);
-        } else {
-            return Math.floor(number);
-        }
-    }
-
-    function toInt(argumentForCoercion) {
-        var coercedNumber = +argumentForCoercion,
-            value = 0;
-
-        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
-            value = absFloor(coercedNumber);
-        }
-
-        return value;
-    }
-
-    // compare two arrays, return the number of differences
-    function compareArrays(array1, array2, dontConvert) {
-        var len = Math.min(array1.length, array2.length),
-            lengthDiff = Math.abs(array1.length - array2.length),
-            diffs = 0,
-            i;
-        for (i = 0; i < len; i++) {
-            if ((dontConvert && array1[i] !== array2[i]) ||
-                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
-                diffs++;
-            }
-        }
-        return diffs + lengthDiff;
-    }
-
-    function warn(msg) {
-        if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
-                (typeof console !==  'undefined') && console.warn) {
-            console.warn('Deprecation warning: ' + msg);
-        }
-    }
-
-    function deprecate(msg, fn) {
-        var firstTime = true;
-
-        return extend(function () {
-            if (utils_hooks__hooks.deprecationHandler != null) {
-                utils_hooks__hooks.deprecationHandler(null, msg);
-            }
-            if (firstTime) {
-                warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
-                firstTime = false;
-            }
-            return fn.apply(this, arguments);
-        }, fn);
-    }
-
-    var deprecations = {};
-
-    function deprecateSimple(name, msg) {
-        if (utils_hooks__hooks.deprecationHandler != null) {
-            utils_hooks__hooks.deprecationHandler(name, msg);
-        }
-        if (!deprecations[name]) {
-            warn(msg);
-            deprecations[name] = true;
-        }
-    }
-
-    utils_hooks__hooks.suppressDeprecationWarnings = false;
-    utils_hooks__hooks.deprecationHandler = null;
-
-    function isFunction(input) {
-        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
-    }
-
-    function isObject(input) {
-        return Object.prototype.toString.call(input) === '[object Object]';
-    }
-
-    function locale_set__set (config) {
-        var prop, i;
-        for (i in config) {
-            prop = config[i];
-            if (isFunction(prop)) {
-                this[i] = prop;
-            } else {
-                this['_' + i] = prop;
-            }
-        }
-        this._config = config;
-        // Lenient ordinal parsing accepts just a number in addition to
-        // number + (possibly) stuff coming from _ordinalParseLenient.
-        this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
-    }
-
-    function mergeConfigs(parentConfig, childConfig) {
-        var res = extend({}, parentConfig), prop;
-        for (prop in childConfig) {
-            if (hasOwnProp(childConfig, prop)) {
-                if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
-                    res[prop] = {};
-                    extend(res[prop], parentConfig[prop]);
-                    extend(res[prop], childConfig[prop]);
-                } else if (childConfig[prop] != null) {
-                    res[prop] = childConfig[prop];
-                } else {
-                    delete res[prop];
-                }
-            }
-        }
-        return res;
-    }
-
-    function Locale(config) {
-        if (config != null) {
-            this.set(config);
-        }
-    }
-
-    var keys;
-
-    if (Object.keys) {
-        keys = Object.keys;
-    } else {
-        keys = function (obj) {
-            var i, res = [];
-            for (i in obj) {
-                if (hasOwnProp(obj, i)) {
-                    res.push(i);
-                }
-            }
-            return res;
-        };
-    }
-
-    // internal storage for locale config files
-    var locales = {};
-    var globalLocale;
-
-    function normalizeLocale(key) {
-        return key ? key.toLowerCase().replace('_', '-') : key;
-    }
-
-    // pick the locale from the array
-    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
-    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
-    function chooseLocale(names) {
-        var i = 0, j, next, locale, split;
-
-        while (i < names.length) {
-            split = normalizeLocale(names[i]).split('-');
-            j = split.length;
-            next = normalizeLocale(names[i + 1]);
-            next = next ? next.split('-') : null;
-            while (j > 0) {
-                locale = loadLocale(split.slice(0, j).join('-'));
-                if (locale) {
-                    return locale;
-                }
-                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
-                    //the next array item is better than a shallower substring of this one
-                    break;
-                }
-                j--;
-            }
-            i++;
-        }
-        return null;
-    }
-
-    function loadLocale(name) {
-        var oldLocale = null;
-        // TODO: Find a better way to register and load all the locales in Node
-        if (!locales[name] && (typeof module !== 'undefined') &&
-                module && module.exports) {
-            try {
-                oldLocale = globalLocale._abbr;
-                require('./locale/' + name);
-                // because defineLocale currently also sets the global locale, we
-                // want to undo that for lazy loaded locales
-                locale_locales__getSetGlobalLocale(oldLocale);
-            } catch (e) { }
-        }
-        return locales[name];
-    }
-
-    // This function will load locale and then set the global locale.  If
-    // no arguments are passed in, it will simply return the current global
-    // locale key.
-    function locale_locales__getSetGlobalLocale (key, values) {
-        var data;
-        if (key) {
-            if (isUndefined(values)) {
-                data = locale_locales__getLocale(key);
-            }
-            else {
-                data = defineLocale(key, values);
-            }
-
-            if (data) {
-                // moment.duration._locale = moment._locale = data;
-                globalLocale = data;
-            }
-        }
-
-        return globalLocale._abbr;
-    }
-
-    function defineLocale (name, config) {
-        if (config !== null) {
-            config.abbr = name;
-            if (locales[name] != null) {
-                deprecateSimple('defineLocaleOverride',
-                        'use moment.updateLocale(localeName, config) to change ' +
-                        'an existing locale. moment.defineLocale(localeName, ' +
-                        'config) should only be used for creating a new locale');
-                config = mergeConfigs(locales[name]._config, config);
-            } else if (config.parentLocale != null) {
-                if (locales[config.parentLocale] != null) {
-                    config = mergeConfigs(locales[config.parentLocale]._config, config);
-                } else {
-                    // treat as if there is no base config
-                    deprecateSimple('parentLocaleUndefined',
-                            'specified parentLocale is not defined yet');
-                }
-            }
-            locales[name] = new Locale(config);
-
-            // backwards compat for now: also set the locale
-            locale_locales__getSetGlobalLocale(name);
-
-            return locales[name];
-        } else {
-            // useful for testing
-            delete locales[name];
-            return null;
-        }
-    }
-
-    function updateLocale(name, config) {
-        if (config != null) {
-            var locale;
-            if (locales[name] != null) {
-                config = mergeConfigs(locales[name]._config, config);
-            }
-            locale = new Locale(config);
-            locale.parentLocale = locales[name];
-            locales[name] = locale;
-
-            // backwards compat for now: also set the locale
-            locale_locales__getSetGlobalLocale(name);
-        } else {
-            // pass null for config to unupdate, useful for tests
-            if (locales[name] != null) {
-                if (locales[name].parentLocale != null) {
-                    locales[name] = locales[name].parentLocale;
-                } else if (locales[name] != null) {
-                    delete locales[name];
-                }
-            }
-        }
-        return locales[name];
-    }
-
-    // returns locale data
-    function locale_locales__getLocale (key) {
-        var locale;
-
-        if (key && key._locale && key._locale._abbr) {
-            key = key._locale._abbr;
-        }
-
-        if (!key) {
-            return globalLocale;
-        }
-
-        if (!isArray(key)) {
-            //short-circuit everything else
-            locale = loadLocale(key);
-            if (locale) {
-                return locale;
-            }
-            key = [key];
-        }
-
-        return chooseLocale(key);
-    }
-
-    function locale_locales__listLocales() {
-        return keys(locales);
-    }
-
-    var aliases = {};
-
-    function addUnitAlias (unit, shorthand) {
-        var lowerCase = unit.toLowerCase();
-        aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
-    }
-
-    function normalizeUnits(units) {
-        return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
-    }
-
-    function normalizeObjectUnits(inputObject) {
-        var normalizedInput = {},
-            normalizedProp,
-            prop;
-
-        for (prop in inputObject) {
-            if (hasOwnProp(inputObject, prop)) {
-                normalizedProp = normalizeUnits(prop);
-                if (normalizedProp) {
-                    normalizedInput[normalizedProp] = inputObject[prop];
-                }
-            }
-        }
-
-        return normalizedInput;
-    }
-
-    function makeGetSet (unit, keepTime) {
-        return function (value) {
-            if (value != null) {
-                get_set__set(this, unit, value);
-                utils_hooks__hooks.updateOffset(this, keepTime);
-                return this;
-            } else {
-                return get_set__get(this, unit);
-            }
-        };
-    }
-
-    function get_set__get (mom, unit) {
-        return mom.isValid() ?
-            mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
-    }
-
-    function get_set__set (mom, unit, value) {
-        if (mom.isValid()) {
-            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
-        }
-    }
-
-    // MOMENTS
-
-    function getSet (units, value) {
-        var unit;
-        if (typeof units === 'object') {
-            for (unit in units) {
-                this.set(unit, units[unit]);
-            }
-        } else {
-            units = normalizeUnits(units);
-            if (isFunction(this[units])) {
-                return this[units](value);
-            }
-        }
-        return this;
-    }
-
-    function zeroFill(number, targetLength, forceSign) {
-        var absNumber = '' + Math.abs(number),
-            zerosToFill = targetLength - absNumber.length,
-            sign = number >= 0;
-        return (sign ? (forceSign ? '+' : '') : '-') +
-            Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
-    }
-
-    var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
-
-    var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
-
-    var formatFunctions = {};
-
-    var formatTokenFunctions = {};
-
-    // token:    'M'
-    // padded:   ['MM', 2]
-    // ordinal:  'Mo'
-    // callback: function () { this.month() + 1 }
-    function addFormatToken (token, padded, ordinal, callback) {
-        var func = callback;
-        if (typeof callback === 'string') {
-            func = function () {
-                return this[callback]();
-            };
-        }
-        if (token) {
-            formatTokenFunctions[token] = func;
-        }
-        if (padded) {
-            formatTokenFunctions[padded[0]] = function () {
-                return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
-            };
-        }
-        if (ordinal) {
-            formatTokenFunctions[ordinal] = function () {
-                return this.localeData().ordinal(func.apply(this, arguments), token);
-            };
-        }
-    }
-
-    function removeFormattingTokens(input) {
-        if (input.match(/\[[\s\S]/)) {
-            return input.replace(/^\[|\]$/g, '');
-        }
-        return input.replace(/\\/g, '');
-    }
-
-    function makeFormatFunction(format) {
-        var array = format.match(formattingTokens), i, length;
-
-        for (i = 0, length = array.length; i < length; i++) {
-            if (formatTokenFunctions[array[i]]) {
-                array[i] = formatTokenFunctions[array[i]];
-            } else {
-                array[i] = removeFormattingTokens(array[i]);
-            }
-        }
-
-        return function (mom) {
-            var output = '', i;
-            for (i = 0; i < length; i++) {
-                output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
-            }
-            return output;
-        };
-    }
-
-    // format date using native date object
-    function formatMoment(m, format) {
-        if (!m.isValid()) {
-            return m.localeData().invalidDate();
-        }
-
-        format = expandFormat(format, m.localeData());
-        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
-
-        return formatFunctions[format](m);
-    }
-
-    function expandFormat(format, locale) {
-        var i = 5;
-
-        function replaceLongDateFormatTokens(input) {
-            return locale.longDateFormat(input) || input;
-        }
-
-        localFormattingTokens.lastIndex = 0;
-        while (i >= 0 && localFormattingTokens.test(format)) {
-            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
-            localFormattingTokens.lastIndex = 0;
-            i -= 1;
-        }
-
-        return format;
-    }
-
-    var match1         = /\d/;            //       0 - 9
-    var match2         = /\d\d/;          //      00 - 99
-    var match3         = /\d{3}/;         //     000 - 999
-    var match4         = /\d{4}/;         //    0000 - 9999
-    var match6         = /[+-]?\d{6}/;    // -999999 - 999999
-    var match1to2      = /\d\d?/;         //       0 - 99
-    var match3to4      = /\d\d\d\d?/;     //     999 - 9999
-    var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
-    var match1to3      = /\d{1,3}/;       //       0 - 999
-    var match1to4      = /\d{1,4}/;       //       0 - 9999
-    var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
-
-    var matchUnsigned  = /\d+/;           //       0 - inf
-    var matchSigned    = /[+-]?\d+/;      //    -inf - inf
-
-    var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
-    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
-
-    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
-
-    // any word (or two) characters or numbers including two/three word month in arabic.
-    // includes scottish gaelic two word and hyphenated months
-    var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
-
-
-    var regexes = {};
-
-    function addRegexToken (token, regex, strictRegex) {
-        regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
-            return (isStrict && strictRegex) ? strictRegex : regex;
-        };
-    }
-
-    function getParseRegexForToken (token, config) {
-        if (!hasOwnProp(regexes, token)) {
-            return new RegExp(unescapeFormat(token));
-        }
-
-        return regexes[token](config._strict, config._locale);
-    }
-
-    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
-    function unescapeFormat(s) {
-        return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
-            return p1 || p2 || p3 || p4;
-        }));
-    }
-
-    function regexEscape(s) {
-        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
-    }
-
-    var tokens = {};
-
-    function addParseToken (token, callback) {
-        var i, func = callback;
-        if (typeof token === 'string') {
-            token = [token];
-        }
-        if (typeof callback === 'number') {
-            func = function (input, array) {
-                array[callback] = toInt(input);
-            };
-        }
-        for (i = 0; i < token.length; i++) {
-            tokens[token[i]] = func;
-        }
-    }
-
-    function addWeekParseToken (token, callback) {
-        addParseToken(token, function (input, array, config, token) {
-            config._w = config._w || {};
-            callback(input, config._w, config, token);
-        });
-    }
-
-    function addTimeToArrayFromToken(token, input, config) {
-        if (input != null && hasOwnProp(tokens, token)) {
-            tokens[token](input, config._a, config, token);
-        }
-    }
-
-    var YEAR = 0;
-    var MONTH = 1;
-    var DATE = 2;
-    var HOUR = 3;
-    var MINUTE = 4;
-    var SECOND = 5;
-    var MILLISECOND = 6;
-    var WEEK = 7;
-    var WEEKDAY = 8;
-
-    var indexOf;
-
-    if (Array.prototype.indexOf) {
-        indexOf = Array.prototype.indexOf;
-    } else {
-        indexOf = function (o) {
-            // I know
-            var i;
-            for (i = 0; i < this.length; ++i) {
-                if (this[i] === o) {
-                    return i;
-                }
-            }
-            return -1;
-        };
-    }
-
-    function daysInMonth(year, month) {
-        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
-    }
-
-    // FORMATTING
-
-    addFormatToken('M', ['MM', 2], 'Mo', function () {
-        return this.month() + 1;
-    });
-
-    addFormatToken('MMM', 0, 0, function (format) {
-        return this.localeData().monthsShort(this, format);
-    });
-
-    addFormatToken('MMMM', 0, 0, function (format) {
-        return this.localeData().months(this, format);
-    });
-
-    // ALIASES
-
-    addUnitAlias('month', 'M');
-
-    // PARSING
-
-    addRegexToken('M',    match1to2);
-    addRegexToken('MM',   match1to2, match2);
-    addRegexToken('MMM',  function (isStrict, locale) {
-        return locale.monthsShortRegex(isStrict);
-    });
-    addRegexToken('MMMM', function (isStrict, locale) {
-        return locale.monthsRegex(isStrict);
-    });
-
-    addParseToken(['M', 'MM'], function (input, array) {
-        array[MONTH] = toInt(input) - 1;
-    });
-
-    addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
-        var month = config._locale.monthsParse(input, token, config._strict);
-        // if we didn't find a month name, mark the date as invalid.
-        if (month != null) {
-            array[MONTH] = month;
-        } else {
-            getParsingFlags(config).invalidMonth = input;
-        }
-    });
-
-    // LOCALES
-
-    var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/;
-    var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
-    function localeMonths (m, format) {
-        return isArray(this._months) ? this._months[m.month()] :
-            this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
-    }
-
-    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
-    function localeMonthsShort (m, format) {
-        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
-            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
-    }
-
-    function units_month__handleStrictParse(monthName, format, strict) {
-        var i, ii, mom, llc = monthName.toLocaleLowerCase();
-        if (!this._monthsParse) {
-            // this is not used
-            this._monthsParse = [];
-            this._longMonthsParse = [];
-            this._shortMonthsParse = [];
-            for (i = 0; i < 12; ++i) {
-                mom = create_utc__createUTC([2000, i]);
-                this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
-                this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
-            }
-        }
-
-        if (strict) {
-            if (format === 'MMM') {
-                ii = indexOf.call(this._shortMonthsParse, llc);
-                return ii !== -1 ? ii : null;
-            } else {
-                ii = indexOf.call(this._longMonthsParse, llc);
-                return ii !== -1 ? ii : null;
-            }
-        } else {
-            if (format === 'MMM') {
-                ii = indexOf.call(this._shortMonthsParse, llc);
-                if (ii !== -1) {
-                    return ii;
-                }
-                ii = indexOf.call(this._longMonthsParse, llc);
-                return ii !== -1 ? ii : null;
-            } else {
-                ii = indexOf.call(this._longMonthsParse, llc);
-                if (ii !== -1) {
-                    return ii;
-                }
-                ii = indexOf.call(this._shortMonthsParse, llc);
-                return ii !== -1 ? ii : null;
-            }
-        }
-    }
-
-    function localeMonthsParse (monthName, format, strict) {
-        var i, mom, regex;
-
-        if (this._monthsParseExact) {
-            return units_month__handleStrictParse.call(this, monthName, format, strict);
-        }
-
-        if (!this._monthsParse) {
-            this._monthsParse = [];
-            this._longMonthsParse = [];
-            this._shortMonthsParse = [];
-        }
-
-        // TODO: add sorting
-        // Sorting makes sure if one month (or abbr) is a prefix of another
-        // see sorting in computeMonthsParse
-        for (i = 0; i < 12; i++) {
-            // make the regex if we don't have it already
-            mom = create_utc__createUTC([2000, i]);
-            if (strict && !this._longMonthsParse[i]) {
-                this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
-                this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
-            }
-            if (!strict && !this._monthsParse[i]) {
-                regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
-                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
-            }
-            // test the regex
-            if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
-                return i;
-            } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
-                return i;
-            } else if (!strict && this._monthsParse[i].test(monthName)) {
-                return i;
-            }
-        }
-    }
-
-    // MOMENTS
-
-    function setMonth (mom, value) {
-        var dayOfMonth;
-
-        if (!mom.isValid()) {
-            // No op
-            return mom;
-        }
-
-        if (typeof value === 'string') {
-            if (/^\d+$/.test(value)) {
-                value = toInt(value);
-            } else {
-                value = mom.localeData().monthsParse(value);
-                // TODO: Another silent failure?
-                if (typeof value !== 'number') {
-                    return mom;
-                }
-            }
-        }
-
-        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
-        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
-        return mom;
-    }
-
-    function getSetMonth (value) {
-        if (value != null) {
-            setMonth(this, value);
-            utils_hooks__hooks.updateOffset(this, true);
-            return this;
-        } else {
-            return get_set__get(this, 'Month');
-        }
-    }
-
-    function getDaysInMonth () {
-        return daysInMonth(this.year(), this.month());
-    }
-
-    var defaultMonthsShortRegex = matchWord;
-    function monthsShortRegex (isStrict) {
-        if (this._monthsParseExact) {
-            if (!hasOwnProp(this, '_monthsRegex')) {
-                computeMonthsParse.call(this);
-            }
-            if (isStrict) {
-                return this._monthsShortStrictRegex;
-            } else {
-                return this._monthsShortRegex;
-            }
-        } else {
-            return this._monthsShortStrictRegex && isStrict ?
-                this._monthsShortStrictRegex : this._monthsShortRegex;
-        }
-    }
-
-    var defaultMonthsRegex = matchWord;
-    function monthsRegex (isStrict) {
-        if (this._monthsParseExact) {
-            if (!hasOwnProp(this, '_monthsRegex')) {
-                computeMonthsParse.call(this);
-            }
-            if (isStrict) {
-                return this._monthsStrictRegex;
-            } else {
-                return this._monthsRegex;
-            }
-        } else {
-            return this._monthsStrictRegex && isStrict ?
-                this._monthsStrictRegex : this._monthsRegex;
-        }
-    }
-
-    function computeMonthsParse () {
-        function cmpLenRev(a, b) {
-            return b.length - a.length;
-        }
-
-        var shortPieces = [], longPieces = [], mixedPieces = [],
-            i, mom;
-        for (i = 0; i < 12; i++) {
-            // make the regex if we don't have it already
-            mom = create_utc__createUTC([2000, i]);
-            shortPieces.push(this.monthsShort(mom, ''));
-            longPieces.push(this.months(mom, ''));
-            mixedPieces.push(this.months(mom, ''));
-            mixedPieces.push(this.monthsShort(mom, ''));
-        }
-        // Sorting makes sure if one month (or abbr) is a prefix of another it
-        // will match the longer piece.
-        shortPieces.sort(cmpLenRev);
-        longPieces.sort(cmpLenRev);
-        mixedPieces.sort(cmpLenRev);
-        for (i = 0; i < 12; i++) {
-            shortPieces[i] = regexEscape(shortPieces[i]);
-            longPieces[i] = regexEscape(longPieces[i]);
-            mixedPieces[i] = regexEscape(mixedPieces[i]);
-        }
-
-        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
-        this._monthsShortRegex = this._monthsRegex;
-        this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
-        this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
-    }
-
-    function checkOverflow (m) {
-        var overflow;
-        var a = m._a;
-
-        if (a && getParsingFlags(m).overflow === -2) {
-            overflow =
-                a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
-                a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
-                a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
-                a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
-                a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
-                a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
-                -1;
-
-            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
-                overflow = DATE;
-            }
-            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
-                overflow = WEEK;
-            }
-            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
-                overflow = WEEKDAY;
-            }
-
-            getParsingFlags(m).overflow = overflow;
-        }
-
-        return m;
-    }
-
-    // iso 8601 regex
-    // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
-    var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
-    var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
-
-    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
-
-    var isoDates = [
-        ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
-        ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
-        ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
-        ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
-        ['YYYY-DDD', /\d{4}-\d{3}/],
-        ['YYYY-MM', /\d{4}-\d\d/, false],
-        ['YYYYYYMMDD', /[+-]\d{10}/],
-        ['YYYYMMDD', /\d{8}/],
-        // YYYYMM is NOT allowed by the standard
-        ['GGGG[W]WWE', /\d{4}W\d{3}/],
-        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
-        ['YYYYDDD', /\d{7}/]
-    ];
-
-    // iso time formats and regexes
-    var isoTimes = [
-        ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
-        ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
-        ['HH:mm:ss', /\d\d:\d\d:\d\d/],
-        ['HH:mm', /\d\d:\d\d/],
-        ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
-        ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
-        ['HHmmss', /\d\d\d\d\d\d/],
-        ['HHmm', /\d\d\d\d/],
-        ['HH', /\d\d/]
-    ];
-
-    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
-
-    // date from iso format
-    function configFromISO(config) {
-        var i, l,
-            string = config._i,
-            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
-            allowTime, dateFormat, timeFormat, tzFormat;
-
-        if (match) {
-            getParsingFlags(config).iso = true;
-
-            for (i = 0, l = isoDates.length; i < l; i++) {
-                if (isoDates[i][1].exec(match[1])) {
-                    dateFormat = isoDates[i][0];
-                    allowTime = isoDates[i][2] !== false;
-                    break;
-                }
-            }
-            if (dateFormat == null) {
-                config._isValid = false;
-                return;
-            }
-            if (match[3]) {
-                for (i = 0, l = isoTimes.length; i < l; i++) {
-                    if (isoTimes[i][1].exec(match[3])) {
-                        // match[2] should be 'T' or space
-                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
-                        break;
-                    }
-                }
-                if (timeFormat == null) {
-                    config._isValid = false;
-                    return;
-                }
-            }
-            if (!allowTime && timeFormat != null) {
-                config._isValid = false;
-                return;
-            }
-            if (match[4]) {
-                if (tzRegex.exec(match[4])) {
-                    tzFormat = 'Z';
-                } else {
-                    config._isValid = false;
-                    return;
-                }
-            }
-            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
-            configFromStringAndFormat(config);
-        } else {
-            config._isValid = false;
-        }
-    }
-
-    // date from iso format or fallback
-    function configFromString(config) {
-        var matched = aspNetJsonRegex.exec(config._i);
-
-        if (matched !== null) {
-            config._d = new Date(+matched[1]);
-            return;
-        }
-
-        configFromISO(config);
-        if (config._isValid === false) {
-            delete config._isValid;
-            utils_hooks__hooks.createFromInputFallback(config);
-        }
-    }
-
-    utils_hooks__hooks.createFromInputFallback = deprecate(
-        'moment construction falls back to js Date. This is ' +
-        'discouraged and will be removed in upcoming major ' +
-        'release. Please refer to ' +
-        'https://github.com/moment/moment/issues/1407 for more info.',
-        function (config) {
-            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
-        }
-    );
-
-    function createDate (y, m, d, h, M, s, ms) {
-        //can't just apply() to create a date:
-        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
-        var date = new Date(y, m, d, h, M, s, ms);
-
-        //the date constructor remaps years 0-99 to 1900-1999
-        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
-            date.setFullYear(y);
-        }
-        return date;
-    }
-
-    function createUTCDate (y) {
-        var date = new Date(Date.UTC.apply(null, arguments));
-
-        //the Date.UTC function remaps years 0-99 to 1900-1999
-        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
-            date.setUTCFullYear(y);
-        }
-        return date;
-    }
-
-    // FORMATTING
-
-    addFormatToken('Y', 0, 0, function () {
-        var y = this.year();
-        return y <= 9999 ? '' + y : '+' + y;
-    });
-
-    addFormatToken(0, ['YY', 2], 0, function () {
-        return this.year() % 100;
-    });
-
-    addFormatToken(0, ['YYYY',   4],       0, 'year');
-    addFormatToken(0, ['YYYYY',  5],       0, 'year');
-    addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
-
-    // ALIASES
-
-    addUnitAlias('year', 'y');
-
-    // PARSING
-
-    addRegexToken('Y',      matchSigned);
-    addRegexToken('YY',     match1to2, match2);
-    addRegexToken('YYYY',   match1to4, match4);
-    addRegexToken('YYYYY',  match1to6, match6);
-    addRegexToken('YYYYYY', match1to6, match6);
-
-    addParseToken(['YYYYY', 'YYYYYY'], YEAR);
-    addParseToken('YYYY', function (input, array) {
-        array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
-    });
-    addParseToken('YY', function (input, array) {
-        array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
-    });
-    addParseToken('Y', function (input, array) {
-        array[YEAR] = parseInt(input, 10);
-    });
-
-    // HELPERS
-
-    function daysInYear(year) {
-        return isLeapYear(year) ? 366 : 365;
-    }
-
-    function isLeapYear(year) {
-        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
-    }
-
-    // HOOKS
-
-    utils_hooks__hooks.parseTwoDigitYear = function (input) {
-        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
-    };
-
-    // MOMENTS
-
-    var getSetYear = makeGetSet('FullYear', true);
-
-    function getIsLeapYear () {
-        return isLeapYear(this.year());
-    }
-
-    // start-of-first-week - start-of-year
-    function firstWeekOffset(year, dow, doy) {
-        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
-            fwd = 7 + dow - doy,
-            // first-week day local weekday -- which local weekday is fwd
-            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
-
-        return -fwdlw + fwd - 1;
-    }
-
-    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
-    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
-        var localWeekday = (7 + weekday - dow) % 7,
-            weekOffset = firstWeekOffset(year, dow, doy),
-            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
-            resYear, resDayOfYear;
-
-        if (dayOfYear <= 0) {
-            resYear = year - 1;
-            resDayOfYear = daysInYear(resYear) + dayOfYear;
-        } else if (dayOfYear > daysInYear(year)) {
-            resYear = year + 1;
-            resDayOfYear = dayOfYear - daysInYear(year);
-        } else {
-            resYear = year;
-            resDayOfYear = dayOfYear;
-        }
-
-        return {
-            year: resYear,
-            dayOfYear: resDayOfYear
-        };
-    }
-
-    function weekOfYear(mom, dow, doy) {
-        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
-            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
-            resWeek, resYear;
-
-        if (week < 1) {
-            resYear = mom.year() - 1;
-            resWeek = week + weeksInYear(resYear, dow, doy);
-        } else if (week > weeksInYear(mom.year(), dow, doy)) {
-            resWeek = week - weeksInYear(mom.year(), dow, doy);
-            resYear = mom.year() + 1;
-        } else {
-            resYear = mom.year();
-            resWeek = week;
-        }
-
-        return {
-            week: resWeek,
-            year: resYear
-        };
-    }
-
-    function weeksInYear(year, dow, doy) {
-        var weekOffset = firstWeekOffset(year, dow, doy),
-            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
-        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
-    }
-
-    // Pick the first defined of two or three arguments.
-    function defaults(a, b, c) {
-        if (a != null) {
-            return a;
-        }
-        if (b != null) {
-            return b;
-        }
-        return c;
-    }
-
-    function currentDateArray(config) {
-        // hooks is actually the exported moment object
-        var nowValue = new Date(utils_hooks__hooks.now());
-        if (config._useUTC) {
-            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
-        }
-        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
-    }
-
-    // convert an array to a date.
-    // the array should mirror the parameters below
-    // note: all values past the year are optional and will default to the lowest possible value.
-    // [year, month, day , hour, minute, second, millisecond]
-    function configFromArray (config) {
-        var i, date, input = [], currentDate, yearToUse;
-
-        if (config._d) {
-            return;
-        }
-
-        currentDate = currentDateArray(config);
-
-        //compute day of the year from weeks and weekdays
-        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
-            dayOfYearFromWeekInfo(config);
-        }
-
-        //if the day of the year is set, figure out what it is
-        if (config._dayOfYear) {
-            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
-
-            if (config._dayOfYear > daysInYear(yearToUse)) {
-                getParsingFlags(config)._overflowDayOfYear = true;
-            }
-
-            date = createUTCDate(yearToUse, 0, config._dayOfYear);
-            config._a[MONTH] = date.getUTCMonth();
-            config._a[DATE] = date.getUTCDate();
-        }
-
-        // Default to current date.
-        // * if no year, month, day of month are given, default to today
-        // * if day of month is given, default month and year
-        // * if month is given, default only year
-        // * if year is given, don't default anything
-        for (i = 0; i < 3 && config._a[i] == null; ++i) {
-            config._a[i] = input[i] = currentDate[i];
-        }
-
-        // Zero out whatever was not defaulted, including time
-        for (; i < 7; i++) {
-            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
-        }
-
-        // Check for 24:00:00.000
-        if (config._a[HOUR] === 24 &&
-                config._a[MINUTE] === 0 &&
-                config._a[SECOND] === 0 &&
-                config._a[MILLISECOND] === 0) {
-            config._nextDay = true;
-            config._a[HOUR] = 0;
-        }
-
-        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
-        // Apply timezone offset from input. The actual utcOffset can be changed
-        // with parseZone.
-        if (config._tzm != null) {
-            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
-        }
-
-        if (config._nextDay) {
-            config._a[HOUR] = 24;
-        }
-    }
-
-    function dayOfYearFromWeekInfo(config) {
-        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
-
-        w = config._w;
-        if (w.GG != null || w.W != null || w.E != null) {
-            dow = 1;
-            doy = 4;
-
-            // TODO: We need to take the current isoWeekYear, but that depends on
-            // how we interpret now (local, utc, fixed offset). So create
-            // a now version of current config (take local/utc/offset flags, and
-            // create now).
-            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
-            week = defaults(w.W, 1);
-            weekday = defaults(w.E, 1);
-            if (weekday < 1 || weekday > 7) {
-                weekdayOverflow = true;
-            }
-        } else {
-            dow = config._locale._week.dow;
-            doy = config._locale._week.doy;
-
-            weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
-            week = defaults(w.w, 1);
-
-            if (w.d != null) {
-                // weekday -- low day numbers are considered next week
-                weekday = w.d;
-                if (weekday < 0 || weekday > 6) {
-                    weekdayOverflow = true;
-                }
-            } else if (w.e != null) {
-                // local weekday -- counting starts from begining of week
-                weekday = w.e + dow;
-                if (w.e < 0 || w.e > 6) {
-                    weekdayOverflow = true;
-                }
-            } else {
-                // default to begining of week
-                weekday = dow;
-            }
-        }
-        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
-            getParsingFlags(config)._overflowWeeks = true;
-        } else if (weekdayOverflow != null) {
-            getParsingFlags(config)._overflowWeekday = true;
-        } else {
-            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
-            config._a[YEAR] = temp.year;
-            config._dayOfYear = temp.dayOfYear;
-        }
-    }
-
-    // constant that refers to the ISO standard
-    utils_hooks__hooks.ISO_8601 = function () {};
-
-    // date from string and format string
-    function configFromStringAndFormat(config) {
-        // TODO: Move this to another part of the creation flow to prevent circular deps
-        if (config._f === utils_hooks__hooks.ISO_8601) {
-            configFromISO(config);
-            return;
-        }
-
-        config._a = [];
-        getParsingFlags(config).empty = true;
-
-        // This array is used to make a Date, either with `new Date` or `Date.UTC`
-        var string = '' + config._i,
-            i, parsedInput, tokens, token, skipped,
-            stringLength = string.length,
-            totalParsedInputLength = 0;
-
-        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
-
-        for (i = 0; i < tokens.length; i++) {
-            token = tokens[i];
-            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
-            // console.log('token', token, 'parsedInput', parsedInput,
-            //         'regex', getParseRegexForToken(token, config));
-            if (parsedInput) {
-                skipped = string.substr(0, string.indexOf(parsedInput));
-                if (skipped.length > 0) {
-                    getParsingFlags(config).unusedInput.push(skipped);
-                }
-                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
-                totalParsedInputLength += parsedInput.length;
-            }
-            // don't parse if it's not a known token
-            if (formatTokenFunctions[token]) {
-                if (parsedInput) {
-                    getParsingFlags(config).empty = false;
-                }
-                else {
-                    getParsingFlags(config).unusedTokens.push(token);
-                }
-                addTimeToArrayFromToken(token, parsedInput, config);
-            }
-            else if (config._strict && !parsedInput) {
-                getParsingFlags(config).unusedTokens.push(token);
-            }
-        }
-
-        // add remaining unparsed input length to the string
-        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
-        if (string.length > 0) {
-            getParsingFlags(config).unusedInput.push(string);
-        }
-
-        // clear _12h flag if hour is <= 12
-        if (getParsingFlags(config).bigHour === true &&
-                config._a[HOUR] <= 12 &&
-                config._a[HOUR] > 0) {
-            getParsingFlags(config).bigHour = undefined;
-        }
-
-        getParsingFlags(config).parsedDateParts = config._a.slice(0);
-        getParsingFlags(config).meridiem = config._meridiem;
-        // handle meridiem
-        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
-
-        configFromArray(config);
-        checkOverflow(config);
-    }
-
-
-    function meridiemFixWrap (locale, hour, meridiem) {
-        var isPm;
-
-        if (meridiem == null) {
-            // nothing to do
-            return hour;
-        }
-        if (locale.meridiemHour != null) {
-            return locale.meridiemHour(hour, meridiem);
-        } else if (locale.isPM != null) {
-            // Fallback
-            isPm = locale.isPM(meridiem);
-            if (isPm && hour < 12) {
-                hour += 12;
-            }
-            if (!isPm && hour === 12) {
-                hour = 0;
-            }
-            return hour;
-        } else {
-            // this is not supposed to happen
-            return hour;
-        }
-    }
-
-    // date from string and array of format strings
-    function configFromStringAndArray(config) {
-        var tempConfig,
-            bestMoment,
-
-            scoreToBeat,
-            i,
-            currentScore;
-
-        if (config._f.length === 0) {
-            getParsingFlags(config).invalidFormat = true;
-            config._d = new Date(NaN);
-            return;
-        }
-
-        for (i = 0; i < config._f.length; i++) {
-            currentScore = 0;
-            tempConfig = copyConfig({}, config);
-            if (config._useUTC != null) {
-                tempConfig._useUTC = config._useUTC;
-            }
-            tempConfig._f = config._f[i];
-            configFromStringAndFormat(tempConfig);
-
-            if (!valid__isValid(tempConfig)) {
-                continue;
-            }
-
-            // if there is any input that was not parsed add a penalty for that format
-            currentScore += getParsingFlags(tempConfig).charsLeftOver;
-
-            //or tokens
-            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
-
-            getParsingFlags(tempConfig).score = currentScore;
-
-            if (scoreToBeat == null || currentScore < scoreToBeat) {
-                scoreToBeat = currentScore;
-                bestMoment = tempConfig;
-            }
-        }
-
-        extend(config, bestMoment || tempConfig);
-    }
-
-    function configFromObject(config) {
-        if (config._d) {
-            return;
-        }
-
-        var i = normalizeObjectUnits(config._i);
-        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
-            return obj && parseInt(obj, 10);
-        });
-
-        configFromArray(config);
-    }
-
-    function createFromConfig (config) {
-        var res = new Moment(checkOverflow(prepareConfig(config)));
-        if (res._nextDay) {
-            // Adding is smart enough around DST
-            res.add(1, 'd');
-            res._nextDay = undefined;
-        }
-
-        return res;
-    }
-
-    function prepareConfig (config) {
-        var input = config._i,
-            format = config._f;
-
-        config._locale = config._locale || locale_locales__getLocale(config._l);
-
-        if (input === null || (format === undefined && input === '')) {
-            return valid__createInvalid({nullInput: true});
-        }
-
-        if (typeof input === 'string') {
-            config._i = input = config._locale.preparse(input);
-        }
-
-        if (isMoment(input)) {
-            return new Moment(checkOverflow(input));
-        } else if (isArray(format)) {
-            configFromStringAndArray(config);
-        } else if (format) {
-            configFromStringAndFormat(config);
-        } else if (isDate(input)) {
-            config._d = input;
-        } else {
-            configFromInput(config);
-        }
-
-        if (!valid__isValid(config)) {
-            config._d = null;
-        }
-
-        return config;
-    }
-
-    function configFromInput(config) {
-        var input = config._i;
-        if (input === undefined) {
-            config._d = new Date(utils_hooks__hooks.now());
-        } else if (isDate(input)) {
-            config._d = new Date(input.valueOf());
-        } else if (typeof input === 'string') {
-            configFromString(config);
-        } else if (isArray(input)) {
-            config._a = map(input.slice(0), function (obj) {
-                return parseInt(obj, 10);
-            });
-            configFromArray(config);
-        } else if (typeof(input) === 'object') {
-            configFromObject(config);
-        } else if (typeof(input) === 'number') {
-            // from milliseconds
-            config._d = new Date(input);
-        } else {
-            utils_hooks__hooks.createFromInputFallback(config);
-        }
-    }
-
-    function createLocalOrUTC (input, format, locale, strict, isUTC) {
-        var c = {};
-
-        if (typeof(locale) === 'boolean') {
-            strict = locale;
-            locale = undefined;
-        }
-        // object construction must be done this way.
-        // https://github.com/moment/moment/issues/1423
-        c._isAMomentObject = true;
-        c._useUTC = c._isUTC = isUTC;
-        c._l = locale;
-        c._i = input;
-        c._f = format;
-        c._strict = strict;
-
-        return createFromConfig(c);
-    }
-
-    function local__createLocal (input, format, locale, strict) {
-        return createLocalOrUTC(input, format, locale, strict, false);
-    }
-
-    var prototypeMin = deprecate(
-         'moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
-         function () {
-             var other = local__createLocal.apply(null, arguments);
-             if (this.isValid() && other.isValid()) {
-                 return other < this ? this : other;
-             } else {
-                 return valid__createInvalid();
-             }
-         }
-     );
-
-    var prototypeMax = deprecate(
-        'moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
-        function () {
-            var other = local__createLocal.apply(null, arguments);
-            if (this.isValid() && other.isValid()) {
-                return other > this ? this : other;
-            } else {
-                return valid__createInvalid();
-            }
-        }
-    );
-
-    // Pick a moment m from moments so that m[fn](other) is true for all
-    // other. This relies on the function fn to be transitive.
-    //
-    // moments should either be an array of moment objects or an array, whose
-    // first element is an array of moment objects.
-    function pickBy(fn, moments) {
-        var res, i;
-        if (moments.length === 1 && isArray(moments[0])) {
-            moments = moments[0];
-        }
-        if (!moments.length) {
-            return local__createLocal();
-        }
-        res = moments[0];
-        for (i = 1; i < moments.length; ++i) {
-            if (!moments[i].isValid() || moments[i][fn](res)) {
-                res = moments[i];
-            }
-        }
-        return res;
-    }
-
-    // TODO: Use [].sort instead?
-    function min () {
-        var args = [].slice.call(arguments, 0);
-
-        return pickBy('isBefore', args);
-    }
-
-    function max () {
-        var args = [].slice.call(arguments, 0);
-
-        return pickBy('isAfter', args);
-    }
-
-    var now = function () {
-        return Date.now ? Date.now() : +(new Date());
-    };
-
-    function Duration (duration) {
-        var normalizedInput = normalizeObjectUnits(duration),
-            years = normalizedInput.year || 0,
-            quarters = normalizedInput.quarter || 0,
-            months = normalizedInput.month || 0,
-            weeks = normalizedInput.week || 0,
-            days = normalizedInput.day || 0,
-            hours = normalizedInput.hour || 0,
-            minutes = normalizedInput.minute || 0,
-            seconds = normalizedInput.second || 0,
-            milliseconds = normalizedInput.millisecond || 0;
-
-        // representation for dateAddRemove
-        this._milliseconds = +milliseconds +
-            seconds * 1e3 + // 1000
-            minutes * 6e4 + // 1000 * 60
-            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
-        // Because of dateAddRemove treats 24 hours as different from a
-        // day when working around DST, we need to store them separately
-        this._days = +days +
-            weeks * 7;
-        // It is impossible translate months into days without knowing
-        // which months you are are talking about, so we have to store
-        // it separately.
-        this._months = +months +
-            quarters * 3 +
-            years * 12;
-
-        this._data = {};
-
-        this._locale = locale_locales__getLocale();
-
-        this._bubble();
-    }
-
-    function isDuration (obj) {
-        return obj instanceof Duration;
-    }
-
-    // FORMATTING
-
-    function offset (token, separator) {
-        addFormatToken(token, 0, 0, function () {
-            var offset = this.utcOffset();
-            var sign = '+';
-            if (offset < 0) {
-                offset = -offset;
-                sign = '-';
-            }
-            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
-        });
-    }
-
-    offset('Z', ':');
-    offset('ZZ', '');
-
-    // PARSING
-
-    addRegexToken('Z',  matchShortOffset);
-    addRegexToken('ZZ', matchShortOffset);
-    addParseToken(['Z', 'ZZ'], function (input, array, config) {
-        config._useUTC = true;
-        config._tzm = offsetFromString(matchShortOffset, input);
-    });
-
-    // HELPERS
-
-    // timezone chunker
-    // '+10:00' > ['10',  '00']
-    // '-1530'  > ['-15', '30']
-    var chunkOffset = /([\+\-]|\d\d)/gi;
-
-    function offsetFromString(matcher, string) {
-        var matches = ((string || '').match(matcher) || []);
-        var chunk   = matches[matches.length - 1] || [];
-        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
-        var minutes = +(parts[1] * 60) + toInt(parts[2]);
-
-        return parts[0] === '+' ? minutes : -minutes;
-    }
-
-    // Return a moment from input, that is local/utc/zone equivalent to model.
-    function cloneWithOffset(input, model) {
-        var res, diff;
-        if (model._isUTC) {
-            res = model.clone();
-            diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
-            // Use low-level api, because this fn is low-level api.
-            res._d.setTime(res._d.valueOf() + diff);
-            utils_hooks__hooks.updateOffset(res, false);
-            return res;
-        } else {
-            return local__createLocal(input).local();
-        }
-    }
-
-    function getDateOffset (m) {
-        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
-        // https://github.com/moment/moment/pull/1871
-        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
-    }
-
-    // HOOKS
-
-    // This function will be called whenever a moment is mutated.
-    // It is intended to keep the offset in sync with the timezone.
-    utils_hooks__hooks.updateOffset = function () {};
-
-    // MOMENTS
-
-    // keepLocalTime = true means only change the timezone, without
-    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
-    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
-    // +0200, so we adjust the time as needed, to be valid.
-    //
-    // Keeping the time actually adds/subtracts (one hour)
-    // from the actual represented time. That is why we call updateOffset
-    // a second time. In case it wants us to change the offset again
-    // _changeInProgress == true case, then we have to adjust, because
-    // there is no such time in the given timezone.
-    function getSetOffset (input, keepLocalTime) {
-        var offset = this._offset || 0,
-            localAdjust;
-        if (!this.isValid()) {
-            return input != null ? this : NaN;
-        }
-        if (input != null) {
-            if (typeof input === 'string') {
-                input = offsetFromString(matchShortOffset, input);
-            } else if (Math.abs(input) < 16) {
-                input = input * 60;
-            }
-            if (!this._isUTC && keepLocalTime) {
-                localAdjust = getDateOffset(this);
-            }
-            this._offset = input;
-            this._isUTC = true;
-            if (localAdjust != null) {
-                this.add(localAdjust, 'm');
-            }
-            if (offset !== input) {
-                if (!keepLocalTime || this._changeInProgress) {
-                    add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
-                } else if (!this._changeInProgress) {
-                    this._changeInProgress = true;
-                    utils_hooks__hooks.updateOffset(this, true);
-                    this._changeInProgress = null;
-                }
-            }
-            return this;
-        } else {
-            return this._isUTC ? offset : getDateOffset(this);
-        }
-    }
-
-    function getSetZone (input, keepLocalTime) {
-        if (input != null) {
-            if (typeof input !== 'string') {
-                input = -input;
-            }
-
-            this.utcOffset(input, keepLocalTime);
-
-            return this;
-        } else {
-            return -this.utcOffset();
-        }
-    }
-
-    function setOffsetToUTC (keepLocalTime) {
-        return this.utcOffset(0, keepLocalTime);
-    }
-
-    function setOffsetToLocal (keepLocalTime) {
-        if (this._isUTC) {
-            this.utcOffset(0, keepLocalTime);
-            this._isUTC = false;
-
-            if (keepLocalTime) {
-                this.subtract(getDateOffset(this), 'm');
-            }
-        }
-        return this;
-    }
-
-    function setOffsetToParsedOffset () {
-        if (this._tzm) {
-            this.utcOffset(this._tzm);
-        } else if (typeof this._i === 'string') {
-            this.utcOffset(offsetFromString(matchOffset, this._i));
-        }
-        return this;
-    }
-
-    function hasAlignedHourOffset (input) {
-        if (!this.isValid()) {
-            return false;
-        }
-        input = input ? local__createLocal(input).utcOffset() : 0;
-
-        return (this.utcOffset() - input) % 60 === 0;
-    }
-
-    function isDaylightSavingTime () {
-        return (
-            this.utcOffset() > this.clone().month(0).utcOffset() ||
-            this.utcOffset() > this.clone().month(5).utcOffset()
-        );
-    }
-
-    function isDaylightSavingTimeShifted () {
-        if (!isUndefined(this._isDSTShifted)) {
-            return this._isDSTShifted;
-        }
-
-        var c = {};
-
-        copyConfig(c, this);
-        c = prepareConfig(c);
-
-        if (c._a) {
-            var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
-            this._isDSTShifted = this.isValid() &&
-                compareArrays(c._a, other.toArray()) > 0;
-        } else {
-            this._isDSTShifted = false;
-        }
-
-        return this._isDSTShifted;
-    }
-
-    function isLocal () {
-        return this.isValid() ? !this._isUTC : false;
-    }
-
-    function isUtcOffset () {
-        return this.isValid() ? this._isUTC : false;
-    }
-
-    function isUtc () {
-        return this.isValid() ? this._isUTC && this._offset === 0 : false;
-    }
-
-    // ASP.NET json date format regex
-    var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;
-
-    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
-    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
-    // and further modified to allow for strings containing both week and day
-    var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;
-
-    function create__createDuration (input, key) {
-        var duration = input,
-            // matching against regexp is expensive, do it on demand
-            match = null,
-            sign,
-            ret,
-            diffRes;
-
-        if (isDuration(input)) {
-            duration = {
-                ms : input._milliseconds,
-                d  : input._days,
-                M  : input._months
-            };
-        } else if (typeof input === 'number') {
-            duration = {};
-            if (key) {
-                duration[key] = input;
-            } else {
-                duration.milliseconds = input;
-            }
-        } else if (!!(match = aspNetRegex.exec(input))) {
-            sign = (match[1] === '-') ? -1 : 1;
-            duration = {
-                y  : 0,
-                d  : toInt(match[DATE])        * sign,
-                h  : toInt(match[HOUR])        * sign,
-                m  : toInt(match[MINUTE])      * sign,
-                s  : toInt(match[SECOND])      * sign,
-                ms : toInt(match[MILLISECOND]) * sign
-            };
-        } else if (!!(match = isoRegex.exec(input))) {
-            sign = (match[1] === '-') ? -1 : 1;
-            duration = {
-                y : parseIso(match[2], sign),
-                M : parseIso(match[3], sign),
-                w : parseIso(match[4], sign),
-                d : parseIso(match[5], sign),
-                h : parseIso(match[6], sign),
-                m : parseIso(match[7], sign),
-                s : parseIso(match[8], sign)
-            };
-        } else if (duration == null) {// checks for null or undefined
-            duration = {};
-        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
-            diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
-
-            duration = {};
-            duration.ms = diffRes.milliseconds;
-            duration.M = diffRes.months;
-        }
-
-        ret = new Duration(duration);
-
-        if (isDuration(input) && hasOwnProp(input, '_locale')) {
-            ret._locale = input._locale;
-        }
-
-        return ret;
-    }
-
-    create__createDuration.fn = Duration.prototype;
-
-    function parseIso (inp, sign) {
-        // We'd normally use ~~inp for this, but unfortunately it also
-        // converts floats to ints.
-        // inp may be undefined, so careful calling replace on it.
-        var res = inp && parseFloat(inp.replace(',', '.'));
-        // apply sign while we're at it
-        return (isNaN(res) ? 0 : res) * sign;
-    }
-
-    function positiveMomentsDifference(base, other) {
-        var res = {milliseconds: 0, months: 0};
-
-        res.months = other.month() - base.month() +
-            (other.year() - base.year()) * 12;
-        if (base.clone().add(res.months, 'M').isAfter(other)) {
-            --res.months;
-        }
-
-        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
-
-        return res;
-    }
-
-    function momentsDifference(base, other) {
-        var res;
-        if (!(base.isValid() && other.isValid())) {
-            return {milliseconds: 0, months: 0};
-        }
-
-        other = cloneWithOffset(other, base);
-        if (base.isBefore(other)) {
-            res = positiveMomentsDifference(base, other);
-        } else {
-            res = positiveMomentsDifference(other, base);
-            res.milliseconds = -res.milliseconds;
-            res.months = -res.months;
-        }
-
-        return res;
-    }
-
-    function absRound (number) {
-        if (number < 0) {
-            return Math.round(-1 * number) * -1;
-        } else {
-            return Math.round(number);
-        }
-    }
-
-    // TODO: remove 'name' arg after deprecation is removed
-    function createAdder(direction, name) {
-        return function (val, period) {
-            var dur, tmp;
-            //invert the arguments, but complain about it
-            if (period !== null && !isNaN(+period)) {
-                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
-                tmp = val; val = period; period = tmp;
-            }
-
-            val = typeof val === 'string' ? +val : val;
-            dur = create__createDuration(val, period);
-            add_subtract__addSubtract(this, dur, direction);
-            return this;
-        };
-    }
-
-    function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
-        var milliseconds = duration._milliseconds,
-            days = absRound(duration._days),
-            months = absRound(duration._months);
-
-        if (!mom.isValid()) {
-            // No op
-            return;
-        }
-
-        updateOffset = updateOffset == null ? true : updateOffset;
-
-        if (milliseconds) {
-            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
-        }
-        if (days) {
-            get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
-        }
-        if (months) {
-            setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
-        }
-        if (updateOffset) {
-            utils_hooks__hooks.updateOffset(mom, days || months);
-        }
-    }
-
-    var add_subtract__add      = createAdder(1, 'add');
-    var add_subtract__subtract = createAdder(-1, 'subtract');
-
-    function moment_calendar__calendar (time, formats) {
-        // We want to compare the start of today, vs this.
-        // Getting start-of-today depends on whether we're local/utc/offset or not.
-        var now = time || local__createLocal(),
-            sod = cloneWithOffset(now, this).startOf('day'),
-            diff = this.diff(sod, 'days', true),
-            format = diff < -6 ? 'sameElse' :
-                diff < -1 ? 'lastWeek' :
-                diff < 0 ? 'lastDay' :
-                diff < 1 ? 'sameDay' :
-                diff < 2 ? 'nextDay' :
-                diff < 7 ? 'nextWeek' : 'sameElse';
-
-        var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);
-
-        return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
-    }
-
-    function clone () {
-        return new Moment(this);
-    }
-
-    function isAfter (input, units) {
-        var localInput = isMoment(input) ? input : local__createLocal(input);
-        if (!(this.isValid() && localInput.isValid())) {
-            return false;
-        }
-        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
-        if (units === 'millisecond') {
-            return this.valueOf() > localInput.valueOf();
-        } else {
-            return localInput.valueOf() < this.clone().startOf(units).valueOf();
-        }
-    }
-
-    function isBefore (input, units) {
-        var localInput = isMoment(input) ? input : local__createLocal(input);
-        if (!(this.isValid() && localInput.isValid())) {
-            return false;
-        }
-        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
-        if (units === 'millisecond') {
-            return this.valueOf() < localInput.valueOf();
-        } else {
-            return this.clone().endOf(units).valueOf() < localInput.valueOf();
-        }
-    }
-
-    function isBetween (from, to, units, inclusivity) {
-        inclusivity = inclusivity || '()';
-        return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
-            (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
-    }
-
-    function isSame (input, units) {
-        var localInput = isMoment(input) ? input : local__createLocal(input),
-            inputMs;
-        if (!(this.isValid() && localInput.isValid())) {
-            return false;
-        }
-        units = normalizeUnits(units || 'millisecond');
-        if (units === 'millisecond') {
-            return this.valueOf() === localInput.valueOf();
-        } else {
-            inputMs = localInput.valueOf();
-            return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
-        }
-    }
-
-    function isSameOrAfter (input, units) {
-        return this.isSame(input, units) || this.isAfter(input,units);
-    }
-
-    function isSameOrBefore (input, units) {
-        return this.isSame(input, units) || this.isBefore(input,units);
-    }
-
-    function diff (input, units, asFloat) {
-        var that,
-            zoneDelta,
-            delta, output;
-
-        if (!this.isValid()) {
-            return NaN;
-        }
-
-        that = cloneWithOffset(input, this);
-
-        if (!that.isValid()) {
-            return NaN;
-        }
-
-        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
-
-        units = normalizeUnits(units);
-
-        if (units === 'year' || units === 'month' || units === 'quarter') {
-            output = monthDiff(this, that);
-            if (units === 'quarter') {
-                output = output / 3;
-            } else if (units === 'year') {
-                output = output / 12;
-            }
-        } else {
-            delta = this - that;
-            output = units === 'second' ? delta / 1e3 : // 1000
-                units === 'minute' ? delta / 6e4 : // 1000 * 60
-                units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
-                units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
-                units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
-                delta;
-        }
-        return asFloat ? output : absFloor(output);
-    }
-
-    function monthDiff (a, b) {
-        // difference in months
-        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
-            // b is in (anchor - 1 month, anchor + 1 month)
-            anchor = a.clone().add(wholeMonthDiff, 'months'),
-            anchor2, adjust;
-
-        if (b - anchor < 0) {
-            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
-            // linear across the month
-            adjust = (b - anchor) / (anchor - anchor2);
-        } else {
-            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
-            // linear across the month
-            adjust = (b - anchor) / (anchor2 - anchor);
-        }
-
-        //check for negative zero, return zero if negative zero
-        return -(wholeMonthDiff + adjust) || 0;
-    }
-
-    utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
-    utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
-
-    function toString () {
-        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
-    }
-
-    function moment_format__toISOString () {
-        var m = this.clone().utc();
-        if (0 < m.year() && m.year() <= 9999) {
-            if (isFunction(Date.prototype.toISOString)) {
-                // native implementation is ~50x faster, use it when we can
-                return this.toDate().toISOString();
-            } else {
-                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
-            }
-        } else {
-            return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
-        }
-    }
-
-    function format (inputString) {
-        if (!inputString) {
-            inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
-        }
-        var output = formatMoment(this, inputString);
-        return this.localeData().postformat(output);
-    }
-
-    function from (time, withoutSuffix) {
-        if (this.isValid() &&
-                ((isMoment(time) && time.isValid()) ||
-                 local__createLocal(time).isValid())) {
-            return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
-        } else {
-            return this.localeData().invalidDate();
-        }
-    }
-
-    function fromNow (withoutSuffix) {
-        return this.from(local__createLocal(), withoutSuffix);
-    }
-
-    function to (time, withoutSuffix) {
-        if (this.isValid() &&
-                ((isMoment(time) && time.isValid()) ||
-                 local__createLocal(time).isValid())) {
-            return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
-        } else {
-            return this.localeData().invalidDate();
-        }
-    }
-
-    function toNow (withoutSuffix) {
-        return this.to(local__createLocal(), withoutSuffix);
-    }
-
-    // If passed a locale key, it will set the locale for this
-    // instance.  Otherwise, it will return the locale configuration
-    // variables for this instance.
-    function locale (key) {
-        var newLocaleData;
-
-        if (key === undefined) {
-            return this._locale._abbr;
-        } else {
-            newLocaleData = locale_locales__getLocale(key);
-            if (newLocaleData != null) {
-                this._locale = newLocaleData;
-            }
-            return this;
-        }
-    }
-
-    var lang = deprecate(
-        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
-        function (key) {
-            if (key === undefined) {
-                return this.localeData();
-            } else {
-                return this.locale(key);
-            }
-        }
-    );
-
-    function localeData () {
-        return this._locale;
-    }
-
-    function startOf (units) {
-        units = normalizeUnits(units);
-        // the following switch intentionally omits break keywords
-        // to utilize falling through the cases.
-        switch (units) {
-        case 'year':
-            this.month(0);
-            /* falls through */
-        case 'quarter':
-        case 'month':
-            this.date(1);
-            /* falls through */
-        case 'week':
-        case 'isoWeek':
-        case 'day':
-        case 'date':
-            this.hours(0);
-            /* falls through */
-        case 'hour':
-            this.minutes(0);
-            /* falls through */
-        case 'minute':
-            this.seconds(0);
-            /* falls through */
-        case 'second':
-            this.milliseconds(0);
-        }
-
-        // weeks are a special case
-        if (units === 'week') {
-            this.weekday(0);
-        }
-        if (units === 'isoWeek') {
-            this.isoWeekday(1);
-        }
-
-        // quarters are also special
-        if (units === 'quarter') {
-            this.month(Math.floor(this.month() / 3) * 3);
-        }
-
-        return this;
-    }
-
-    function endOf (units) {
-        units = normalizeUnits(units);
-        if (units === undefined || units === 'millisecond') {
-            return this;
-        }
-
-        // 'date' is an alias for 'day', so it should be considered as such.
-        if (units === 'date') {
-            units = 'day';
-        }
-
-        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
-    }
-
-    function to_type__valueOf () {
-        return this._d.valueOf() - ((this._offset || 0) * 60000);
-    }
-
-    function unix () {
-        return Math.floor(this.valueOf() / 1000);
-    }
-
-    function toDate () {
-        return this._offset ? new Date(this.valueOf()) : this._d;
-    }
-
-    function toArray () {
-        var m = this;
-        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
-    }
-
-    function toObject () {
-        var m = this;
-        return {
-            years: m.year(),
-            months: m.month(),
-            date: m.date(),
-            hours: m.hours(),
-            minutes: m.minutes(),
-            seconds: m.seconds(),
-            milliseconds: m.milliseconds()
-        };
-    }
-
-    function toJSON () {
-        // new Date(NaN).toJSON() === null
-        return this.isValid() ? this.toISOString() : null;
-    }
-
-    function moment_valid__isValid () {
-        return valid__isValid(this);
-    }
-
-    function parsingFlags () {
-        return extend({}, getParsingFlags(this));
-    }
-
-    function invalidAt () {
-        return getParsingFlags(this).overflow;
-    }
-
-    function creationData() {
-        return {
-            input: this._i,
-            format: this._f,
-            locale: this._locale,
-            isUTC: this._isUTC,
-            strict: this._strict
-        };
-    }
-
-    // FORMATTING
-
-    addFormatToken(0, ['gg', 2], 0, function () {
-        return this.weekYear() % 100;
-    });
-
-    addFormatToken(0, ['GG', 2], 0, function () {
-        return this.isoWeekYear() % 100;
-    });
-
-    function addWeekYearFormatToken (token, getter) {
-        addFormatToken(0, [token, token.length], 0, getter);
-    }
-
-    addWeekYearFormatToken('gggg',     'weekYear');
-    addWeekYearFormatToken('ggggg',    'weekYear');
-    addWeekYearFormatToken('GGGG',  'isoWeekYear');
-    addWeekYearFormatToken('GGGGG', 'isoWeekYear');
-
-    // ALIASES
-
-    addUnitAlias('weekYear', 'gg');
-    addUnitAlias('isoWeekYear', 'GG');
-
-    // PARSING
-
-    addRegexToken('G',      matchSigned);
-    addRegexToken('g',      matchSigned);
-    addRegexToken('GG',     match1to2, match2);
-    addRegexToken('gg',     match1to2, match2);
-    addRegexToken('GGGG',   match1to4, match4);
-    addRegexToken('gggg',   match1to4, match4);
-    addRegexToken('GGGGG',  match1to6, match6);
-    addRegexToken('ggggg',  match1to6, match6);
-
-    addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
-        week[token.substr(0, 2)] = toInt(input);
-    });
-
-    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
-        week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
-    });
-
-    // MOMENTS
-
-    function getSetWeekYear (input) {
-        return getSetWeekYearHelper.call(this,
-                input,
-                this.week(),
-                this.weekday(),
-                this.localeData()._week.dow,
-                this.localeData()._week.doy);
-    }
-
-    function getSetISOWeekYear (input) {
-        return getSetWeekYearHelper.call(this,
-                input, this.isoWeek(), this.isoWeekday(), 1, 4);
-    }
-
-    function getISOWeeksInYear () {
-        return weeksInYear(this.year(), 1, 4);
-    }
-
-    function getWeeksInYear () {
-        var weekInfo = this.localeData()._week;
-        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
-    }
-
-    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
-        var weeksTarget;
-        if (input == null) {
-            return weekOfYear(this, dow, doy).year;
-        } else {
-            weeksTarget = weeksInYear(input, dow, doy);
-            if (week > weeksTarget) {
-                week = weeksTarget;
-            }
-            return setWeekAll.call(this, input, week, weekday, dow, doy);
-        }
-    }
-
-    function setWeekAll(weekYear, week, weekday, dow, doy) {
-        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
-            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
-
-        this.year(date.getUTCFullYear());
-        this.month(date.getUTCMonth());
-        this.date(date.getUTCDate());
-        return this;
-    }
-
-    // FORMATTING
-
-    addFormatToken('Q', 0, 'Qo', 'quarter');
-
-    // ALIASES
-
-    addUnitAlias('quarter', 'Q');
-
-    // PARSING
-
-    addRegexToken('Q', match1);
-    addParseToken('Q', function (input, array) {
-        array[MONTH] = (toInt(input) - 1) * 3;
-    });
-
-    // MOMENTS
-
-    function getSetQuarter (input) {
-        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
-    }
-
-    // FORMATTING
-
-    addFormatToken('w', ['ww', 2], 'wo', 'week');
-    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
-
-    // ALIASES
-
-    addUnitAlias('week', 'w');
-    addUnitAlias('isoWeek', 'W');
-
-    // PARSING
-
-    addRegexToken('w',  match1to2);
-    addRegexToken('ww', match1to2, match2);
-    addRegexToken('W',  match1to2);
-    addRegexToken('WW', match1to2, match2);
-
-    addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
-        week[token.substr(0, 1)] = toInt(input);
-    });
-
-    // HELPERS
-
-    // LOCALES
-
-    function localeWeek (mom) {
-        return weekOfYear(mom, this._week.dow, this._week.doy).week;
-    }
-
-    var defaultLocaleWeek = {
-        dow : 0, // Sunday is the first day of the week.
-        doy : 6  // The week that contains Jan 1st is the first week of the year.
-    };
-
-    function localeFirstDayOfWeek () {
-        return this._week.dow;
-    }
-
-    function localeFirstDayOfYear () {
-        return this._week.doy;
-    }
-
-    // MOMENTS
-
-    function getSetWeek (input) {
-        var week = this.localeData().week(this);
-        return input == null ? week : this.add((input - week) * 7, 'd');
-    }
-
-    function getSetISOWeek (input) {
-        var week = weekOfYear(this, 1, 4).week;
-        return input == null ? week : this.add((input - week) * 7, 'd');
-    }
-
-    // FORMATTING
-
-    addFormatToken('D', ['DD', 2], 'Do', 'date');
-
-    // ALIASES
-
-    addUnitAlias('date', 'D');
-
-    // PARSING
-
-    addRegexToken('D',  match1to2);
-    addRegexToken('DD', match1to2, match2);
-    addRegexToken('Do', function (isStrict, locale) {
-        return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
-    });
-
-    addParseToken(['D', 'DD'], DATE);
-    addParseToken('Do', function (input, array) {
-        array[DATE] = toInt(input.match(match1to2)[0], 10);
-    });
-
-    // MOMENTS
-
-    var getSetDayOfMonth = makeGetSet('Date', true);
-
-    // FORMATTING
-
-    addFormatToken('d', 0, 'do', 'day');
-
-    addFormatToken('dd', 0, 0, function (format) {
-        return this.localeData().weekdaysMin(this, format);
-    });
-
-    addFormatToken('ddd', 0, 0, function (format) {
-        return this.localeData().weekdaysShort(this, format);
-    });
-
-    addFormatToken('dddd', 0, 0, function (format) {
-        return this.localeData().weekdays(this, format);
-    });
-
-    addFormatToken('e', 0, 0, 'weekday');
-    addFormatToken('E', 0, 0, 'isoWeekday');
-
-    // ALIASES
-
-    addUnitAlias('day', 'd');
-    addUnitAlias('weekday', 'e');
-    addUnitAlias('isoWeekday', 'E');
-
-    // PARSING
-
-    addRegexToken('d',    match1to2);
-    addRegexToken('e',    match1to2);
-    addRegexToken('E',    match1to2);
-    addRegexToken('dd',   function (isStrict, locale) {
-        return locale.weekdaysMinRegex(isStrict);
-    });
-    addRegexToken('ddd',   function (isStrict, locale) {
-        return locale.weekdaysShortRegex(isStrict);
-    });
-    addRegexToken('dddd',   function (isStrict, locale) {
-        return locale.weekdaysRegex(isStrict);
-    });
-
-    addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
-        var weekday = config._locale.weekdaysParse(input, token, config._strict);
-        // if we didn't get a weekday name, mark the date as invalid
-        if (weekday != null) {
-            week.d = weekday;
-        } else {
-            getParsingFlags(config).invalidWeekday = input;
-        }
-    });
-
-    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
-        week[token] = toInt(input);
-    });
-
-    // HELPERS
-
-    function parseWeekday(input, locale) {
-        if (typeof input !== 'string') {
-            return input;
-        }
-
-        if (!isNaN(input)) {
-            return parseInt(input, 10);
-        }
-
-        input = locale.weekdaysParse(input);
-        if (typeof input === 'number') {
-            return input;
-        }
-
-        return null;
-    }
-
-    // LOCALES
-
-    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
-    function localeWeekdays (m, format) {
-        return isArray(this._weekdays) ? this._weekdays[m.day()] :
-            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
-    }
-
-    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
-    function localeWeekdaysShort (m) {
-        return this._weekdaysShort[m.day()];
-    }
-
-    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
-    function localeWeekdaysMin (m) {
-        return this._weekdaysMin[m.day()];
-    }
-
-    function day_of_week__handleStrictParse(weekdayName, format, strict) {
-        var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
-        if (!this._weekdaysParse) {
-            this._weekdaysParse = [];
-            this._shortWeekdaysParse = [];
-            this._minWeekdaysParse = [];
-
-            for (i = 0; i < 7; ++i) {
-                mom = create_utc__createUTC([2000, 1]).day(i);
-                this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
-                this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
-                this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
-            }
-        }
-
-        if (strict) {
-            if (format === 'dddd') {
-                ii = indexOf.call(this._weekdaysParse, llc);
-                return ii !== -1 ? ii : null;
-            } else if (format === 'ddd') {
-                ii = indexOf.call(this._shortWeekdaysParse, llc);
-                return ii !== -1 ? ii : null;
-            } else {
-                ii = indexOf.call(this._minWeekdaysParse, llc);
-                return ii !== -1 ? ii : null;
-            }
-        } else {
-            if (format === 'dddd') {
-                ii = indexOf.call(this._weekdaysParse, llc);
-                if (ii !== -1) {
-                    return ii;
-                }
-                ii = indexOf.call(this._shortWeekdaysParse, llc);
-                if (ii !== -1) {
-                    return ii;
-                }
-                ii = indexOf.call(this._minWeekdaysParse, llc);
-                return ii !== -1 ? ii : null;
-            } else if (format === 'ddd') {
-                ii = indexOf.call(this._shortWeekdaysParse, llc);
-                if (ii !== -1) {
-                    return ii;
-                }
-                ii = indexOf.call(this._weekdaysParse, llc);
-                if (ii !== -1) {
-                    return ii;
-                }
-                ii = indexOf.call(this._minWeekdaysParse, llc);
-                return ii !== -1 ? ii : null;
-            } else {
-                ii = indexOf.call(this._minWeekdaysParse, llc);
-                if (ii !== -1) {
-                    return ii;
-                }
-                ii = indexOf.call(this._weekdaysParse, llc);
-                if (ii !== -1) {
-                    return ii;
-                }
-                ii = indexOf.call(this._shortWeekdaysParse, llc);
-                return ii !== -1 ? ii : null;
-            }
-        }
-    }
-
-    function localeWeekdaysParse (weekdayName, format, strict) {
-        var i, mom, regex;
-
-        if (this._weekdaysParseExact) {
-            return day_of_week__handleStrictParse.call(this, weekdayName, format, strict);
-        }
-
-        if (!this._weekdaysParse) {
-            this._weekdaysParse = [];
-            this._minWeekdaysParse = [];
-            this._shortWeekdaysParse = [];
-            this._fullWeekdaysParse = [];
-        }
-
-        for (i = 0; i < 7; i++) {
-            // make the regex if we don't have it already
-
-            mom = create_utc__createUTC([2000, 1]).day(i);
-            if (strict && !this._fullWeekdaysParse[i]) {
-                this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
-                this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
-                this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
-            }
-            if (!this._weekdaysParse[i]) {
-                regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
-                this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
-            }
-            // test the regex
-            if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
-                return i;
-            } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
-                return i;
-            } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
-                return i;
-            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
-                return i;
-            }
-        }
-    }
-
-    // MOMENTS
-
-    function getSetDayOfWeek (input) {
-        if (!this.isValid()) {
-            return input != null ? this : NaN;
-        }
-        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
-        if (input != null) {
-            input = parseWeekday(input, this.localeData());
-            return this.add(input - day, 'd');
-        } else {
-            return day;
-        }
-    }
-
-    function getSetLocaleDayOfWeek (input) {
-        if (!this.isValid()) {
-            return input != null ? this : NaN;
-        }
-        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
-        return input == null ? weekday : this.add(input - weekday, 'd');
-    }
-
-    function getSetISODayOfWeek (input) {
-        if (!this.isValid()) {
-            return input != null ? this : NaN;
-        }
-        // behaves the same as moment#day except
-        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
-        // as a setter, sunday should belong to the previous week.
-        return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
-    }
-
-    var defaultWeekdaysRegex = matchWord;
-    function weekdaysRegex (isStrict) {
-        if (this._weekdaysParseExact) {
-            if (!hasOwnProp(this, '_weekdaysRegex')) {
-                computeWeekdaysParse.call(this);
-            }
-            if (isStrict) {
-                return this._weekdaysStrictRegex;
-            } else {
-                return this._weekdaysRegex;
-            }
-        } else {
-            return this._weekdaysStrictRegex && isStrict ?
-                this._weekdaysStrictRegex : this._weekdaysRegex;
-        }
-    }
-
-    var defaultWeekdaysShortRegex = matchWord;
-    function weekdaysShortRegex (isStrict) {
-        if (this._weekdaysParseExact) {
-            if (!hasOwnProp(this, '_weekdaysRegex')) {
-                computeWeekdaysParse.call(this);
-            }
-            if (isStrict) {
-                return this._weekdaysShortStrictRegex;
-            } else {
-                return this._weekdaysShortRegex;
-            }
-        } else {
-            return this._weekdaysShortStrictRegex && isStrict ?
-                this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
-        }
-    }
-
-    var defaultWeekdaysMinRegex = matchWord;
-    function weekdaysMinRegex (isStrict) {
-        if (this._weekdaysParseExact) {
-            if (!hasOwnProp(this, '_weekdaysRegex')) {
-                computeWeekdaysParse.call(this);
-            }
-            if (isStrict) {
-                return this._weekdaysMinStrictRegex;
-            } else {
-                return this._weekdaysMinRegex;
-            }
-        } else {
-            return this._weekdaysMinStrictRegex && isStrict ?
-                this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
-        }
-    }
-
-
-    function computeWeekdaysParse () {
-        function cmpLenRev(a, b) {
-            return b.length - a.length;
-        }
-
-        var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
-            i, mom, minp, shortp, longp;
-        for (i = 0; i < 7; i++) {
-            // make the regex if we don't have it already
-            mom = create_utc__createUTC([2000, 1]).day(i);
-            minp = this.weekdaysMin(mom, '');
-            shortp = this.weekdaysShort(mom, '');
-            longp = this.weekdays(mom, '');
-            minPieces.push(minp);
-            shortPieces.push(shortp);
-            longPieces.push(longp);
-            mixedPieces.push(minp);
-            mixedPieces.push(shortp);
-            mixedPieces.push(longp);
-        }
-        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
-        // will match the longer piece.
-        minPieces.sort(cmpLenRev);
-        shortPieces.sort(cmpLenRev);
-        longPieces.sort(cmpLenRev);
-        mixedPieces.sort(cmpLenRev);
-        for (i = 0; i < 7; i++) {
-            shortPieces[i] = regexEscape(shortPieces[i]);
-            longPieces[i] = regexEscape(longPieces[i]);
-            mixedPieces[i] = regexEscape(mixedPieces[i]);
-        }
-
-        this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
-        this._weekdaysShortRegex = this._weekdaysRegex;
-        this._weekdaysMinRegex = this._weekdaysRegex;
-
-        this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
-        this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
-        this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
-    }
-
-    // FORMATTING
-
-    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
-
-    // ALIASES
-
-    addUnitAlias('dayOfYear', 'DDD');
-
-    // PARSING
-
-    addRegexToken('DDD',  match1to3);
-    addRegexToken('DDDD', match3);
-    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
-        config._dayOfYear = toInt(input);
-    });
-
-    // HELPERS
-
-    // MOMENTS
-
-    function getSetDayOfYear (input) {
-        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
-        return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
-    }
-
-    // FORMATTING
-
-    function hFormat() {
-        return this.hours() % 12 || 12;
-    }
-
-    function kFormat() {
-        return this.hours() || 24;
-    }
-
-    addFormatToken('H', ['HH', 2], 0, 'hour');
-    addFormatToken('h', ['hh', 2], 0, hFormat);
-    addFormatToken('k', ['kk', 2], 0, kFormat);
-
-    addFormatToken('hmm', 0, 0, function () {
-        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
-    });
-
-    addFormatToken('hmmss', 0, 0, function () {
-        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
-            zeroFill(this.seconds(), 2);
-    });
-
-    addFormatToken('Hmm', 0, 0, function () {
-        return '' + this.hours() + zeroFill(this.minutes(), 2);
-    });
-
-    addFormatToken('Hmmss', 0, 0, function () {
-        return '' + this.hours() + zeroFill(this.minutes(), 2) +
-            zeroFill(this.seconds(), 2);
-    });
-
-    function meridiem (token, lowercase) {
-        addFormatToken(token, 0, 0, function () {
-            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
-        });
-    }
-
-    meridiem('a', true);
-    meridiem('A', false);
-
-    // ALIASES
-
-    addUnitAlias('hour', 'h');
-
-    // PARSING
-
-    function matchMeridiem (isStrict, locale) {
-        return locale._meridiemParse;
-    }
-
-    addRegexToken('a',  matchMeridiem);
-    addRegexToken('A',  matchMeridiem);
-    addRegexToken('H',  match1to2);
-    addRegexToken('h',  match1to2);
-    addRegexToken('HH', match1to2, match2);
-    addRegexToken('hh', match1to2, match2);
-
-    addRegexToken('hmm', match3to4);
-    addRegexToken('hmmss', match5to6);
-    addRegexToken('Hmm', match3to4);
-    addRegexToken('Hmmss', match5to6);
-
-    addParseToken(['H', 'HH'], HOUR);
-    addParseToken(['a', 'A'], function (input, array, config) {
-        config._isPm = config._locale.isPM(input);
-        config._meridiem = input;
-    });
-    addParseToken(['h', 'hh'], function (input, array, config) {
-        array[HOUR] = toInt(input);
-        getParsingFlags(config).bigHour = true;
-    });
-    addParseToken('hmm', function (input, array, config) {
-        var pos = input.length - 2;
-        array[HOUR] = toInt(input.substr(0, pos));
-        array[MINUTE] = toInt(input.substr(pos));
-        getParsingFlags(config).bigHour = true;
-    });
-    addParseToken('hmmss', function (input, array, config) {
-        var pos1 = input.length - 4;
-        var pos2 = input.length - 2;
-        array[HOUR] = toInt(input.substr(0, pos1));
-        array[MINUTE] = toInt(input.substr(pos1, 2));
-        array[SECOND] = toInt(input.substr(pos2));
-        getParsingFlags(config).bigHour = true;
-    });
-    addParseToken('Hmm', function (input, array, config) {
-        var pos = input.length - 2;
-        array[HOUR] = toInt(input.substr(0, pos));
-        array[MINUTE] = toInt(input.substr(pos));
-    });
-    addParseToken('Hmmss', function (input, array, config) {
-        var pos1 = input.length - 4;
-        var pos2 = input.length - 2;
-        array[HOUR] = toInt(input.substr(0, pos1));
-        array[MINUTE] = toInt(input.substr(pos1, 2));
-        array[SECOND] = toInt(input.substr(pos2));
-    });
-
-    // LOCALES
-
-    function localeIsPM (input) {
-        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
-        // Using charAt should be more compatible.
-        return ((input + '').toLowerCase().charAt(0) === 'p');
-    }
-
-    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
-    function localeMeridiem (hours, minutes, isLower) {
-        if (hours > 11) {
-            return isLower ? 'pm' : 'PM';
-        } else {
-            return isLower ? 'am' : 'AM';
-        }
-    }
-
-
-    // MOMENTS
-
-    // Setting the hour should keep the time, because the user explicitly
-    // specified which hour he wants. So trying to maintain the same hour (in
-    // a new timezone) makes sense. Adding/subtracting hours does not follow
-    // this rule.
-    var getSetHour = makeGetSet('Hours', true);
-
-    // FORMATTING
-
-    addFormatToken('m', ['mm', 2], 0, 'minute');
-
-    // ALIASES
-
-    addUnitAlias('minute', 'm');
-
-    // PARSING
-
-    addRegexToken('m',  match1to2);
-    addRegexToken('mm', match1to2, match2);
-    addParseToken(['m', 'mm'], MINUTE);
-
-    // MOMENTS
-
-    var getSetMinute = makeGetSet('Minutes', false);
-
-    // FORMATTING
-
-    addFormatToken('s', ['ss', 2], 0, 'second');
-
-    // ALIASES
-
-    addUnitAlias('second', 's');
-
-    // PARSING
-
-    addRegexToken('s',  match1to2);
-    addRegexToken('ss', match1to2, match2);
-    addParseToken(['s', 'ss'], SECOND);
-
-    // MOMENTS
-
-    var getSetSecond = makeGetSet('Seconds', false);
-
-    // FORMATTING
-
-    addFormatToken('S', 0, 0, function () {
-        return ~~(this.millisecond() / 100);
-    });
-
-    addFormatToken(0, ['SS', 2], 0, function () {
-        return ~~(this.millisecond() / 10);
-    });
-
-    addFormatToken(0, ['SSS', 3], 0, 'millisecond');
-    addFormatToken(0, ['SSSS', 4], 0, function () {
-        return this.millisecond() * 10;
-    });
-    addFormatToken(0, ['SSSSS', 5], 0, function () {
-        return this.millisecond() * 100;
-    });
-    addFormatToken(0, ['SSSSSS', 6], 0, function () {
-        return this.millisecond() * 1000;
-    });
-    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
-        return this.millisecond() * 10000;
-    });
-    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
-        return this.millisecond() * 100000;
-    });
-    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
-        return this.millisecond() * 1000000;
-    });
-
-
-    // ALIASES
-
-    addUnitAlias('millisecond', 'ms');
-
-    // PARSING
-
-    addRegexToken('S',    match1to3, match1);
-    addRegexToken('SS',   match1to3, match2);
-    addRegexToken('SSS',  match1to3, match3);
-
-    var token;
-    for (token = 'SSSS'; token.length <= 9; token += 'S') {
-        addRegexToken(token, matchUnsigned);
-    }
-
-    function parseMs(input, array) {
-        array[MILLISECOND] = toInt(('0.' + input) * 1000);
-    }
-
-    for (token = 'S'; token.length <= 9; token += 'S') {
-        addParseToken(token, parseMs);
-    }
-    // MOMENTS
-
-    var getSetMillisecond = makeGetSet('Milliseconds', false);
-
-    // FORMATTING
-
-    addFormatToken('z',  0, 0, 'zoneAbbr');
-    addFormatToken('zz', 0, 0, 'zoneName');
-
-    // MOMENTS
-
-    function getZoneAbbr () {
-        return this._isUTC ? 'UTC' : '';
-    }
-
-    function getZoneName () {
-        return this._isUTC ? 'Coordinated Universal Time' : '';
-    }
-
-    var momentPrototype__proto = Moment.prototype;
-
-    momentPrototype__proto.add               = add_subtract__add;
-    momentPrototype__proto.calendar          = moment_calendar__calendar;
-    momentPrototype__proto.clone             = clone;
-    momentPrototype__proto.diff              = diff;
-    momentPrototype__proto.endOf             = endOf;
-    momentPrototype__proto.format            = format;
-    momentPrototype__proto.from              = from;
-    momentPrototype__proto.fromNow           = fromNow;
-    momentPrototype__proto.to                = to;
-    momentPrototype__proto.toNow             = toNow;
-    momentPrototype__proto.get               = getSet;
-    momentPrototype__proto.invalidAt         = invalidAt;
-    momentPrototype__proto.isAfter           = isAfter;
-    momentPrototype__proto.isBefore          = isBefore;
-    momentPrototype__proto.isBetween         = isBetween;
-    momentPrototype__proto.isSame            = isSame;
-    momentPrototype__proto.isSameOrAfter     = isSameOrAfter;
-    momentPrototype__proto.isSameOrBefore    = isSameOrBefore;
-    momentPrototype__proto.isValid           = moment_valid__isValid;
-    momentPrototype__proto.lang              = lang;
-    momentPrototype__proto.locale            = locale;
-    momentPrototype__proto.localeData        = localeData;
-    momentPrototype__proto.max               = prototypeMax;
-    momentPrototype__proto.min               = prototypeMin;
-    momentPrototype__proto.parsingFlags      = parsingFlags;
-    momentPrototype__proto.set               = getSet;
-    momentPrototype__proto.startOf           = startOf;
-    momentPrototype__proto.subtract          = add_subtract__subtract;
-    momentPrototype__proto.toArray           = toArray;
-    momentPrototype__proto.toObject          = toObject;
-    momentPrototype__proto.toDate            = toDate;
-    momentPrototype__proto.toISOString       = moment_format__toISOString;
-    momentPrototype__proto.toJSON            = toJSON;
-    momentPrototype__proto.toString          = toString;
-    momentPrototype__proto.unix              = unix;
-    momentPrototype__proto.valueOf           = to_type__valueOf;
-    momentPrototype__proto.creationData      = creationData;
-
-    // Year
-    momentPrototype__proto.year       = getSetYear;
-    momentPrototype__proto.isLeapYear = getIsLeapYear;
-
-    // Week Year
-    momentPrototype__proto.weekYear    = getSetWeekYear;
-    momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
-
-    // Quarter
-    momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
-
-    // Month
-    momentPrototype__proto.month       = getSetMonth;
-    momentPrototype__proto.daysInMonth = getDaysInMonth;
-
-    // Week
-    momentPrototype__proto.week           = momentPrototype__proto.weeks        = getSetWeek;
-    momentPrototype__proto.isoWeek        = momentPrototype__proto.isoWeeks     = getSetISOWeek;
-    momentPrototype__proto.weeksInYear    = getWeeksInYear;
-    momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
-
-    // Day
-    momentPrototype__proto.date       = getSetDayOfMonth;
-    momentPrototype__proto.day        = momentPrototype__proto.days             = getSetDayOfWeek;
-    momentPrototype__proto.weekday    = getSetLocaleDayOfWeek;
-    momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
-    momentPrototype__proto.dayOfYear  = getSetDayOfYear;
-
-    // Hour
-    momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
-
-    // Minute
-    momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
-
-    // Second
-    momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
-
-    // Millisecond
-    momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
-
-    // Offset
-    momentPrototype__proto.utcOffset            = getSetOffset;
-    momentPrototype__proto.utc                  = setOffsetToUTC;
-    momentPrototype__proto.local                = setOffsetToLocal;
-    momentPrototype__proto.parseZone            = setOffsetToParsedOffset;
-    momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
-    momentPrototype__proto.isDST                = isDaylightSavingTime;
-    momentPrototype__proto.isDSTShifted         = isDaylightSavingTimeShifted;
-    momentPrototype__proto.isLocal              = isLocal;
-    momentPrototype__proto.isUtcOffset          = isUtcOffset;
-    momentPrototype__proto.isUtc                = isUtc;
-    momentPrototype__proto.isUTC                = isUtc;
-
-    // Timezone
-    momentPrototype__proto.zoneAbbr = getZoneAbbr;
-    momentPrototype__proto.zoneName = getZoneName;
-
-    // Deprecations
-    momentPrototype__proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
-    momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
-    momentPrototype__proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
-    momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
-
-    var momentPrototype = momentPrototype__proto;
-
-    function moment__createUnix (input) {
-        return local__createLocal(input * 1000);
-    }
-
-    function moment__createInZone () {
-        return local__createLocal.apply(null, arguments).parseZone();
-    }
-
-    var defaultCalendar = {
-        sameDay : '[Today at] LT',
-        nextDay : '[Tomorrow at] LT',
-        nextWeek : 'dddd [at] LT',
-        lastDay : '[Yesterday at] LT',
-        lastWeek : '[Last] dddd [at] LT',
-        sameElse : 'L'
-    };
-
-    function locale_calendar__calendar (key, mom, now) {
-        var output = this._calendar[key];
-        return isFunction(output) ? output.call(mom, now) : output;
-    }
-
-    var defaultLongDateFormat = {
-        LTS  : 'h:mm:ss A',
-        LT   : 'h:mm A',
-        L    : 'MM/DD/YYYY',
-        LL   : 'MMMM D, YYYY',
-        LLL  : 'MMMM D, YYYY h:mm A',
-        LLLL : 'dddd, MMMM D, YYYY h:mm A'
-    };
-
-    function longDateFormat (key) {
-        var format = this._longDateFormat[key],
-            formatUpper = this._longDateFormat[key.toUpperCase()];
-
-        if (format || !formatUpper) {
-            return format;
-        }
-
-        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
-            return val.slice(1);
-        });
-
-        return this._longDateFormat[key];
-    }
-
-    var defaultInvalidDate = 'Invalid date';
-
-    function invalidDate () {
-        return this._invalidDate;
-    }
-
-    var defaultOrdinal = '%d';
-    var defaultOrdinalParse = /\d{1,2}/;
-
-    function ordinal (number) {
-        return this._ordinal.replace('%d', number);
-    }
-
-    function preParsePostFormat (string) {
-        return string;
-    }
-
-    var defaultRelativeTime = {
-        future : 'in %s',
-        past   : '%s ago',
-        s  : 'a few seconds',
-        m  : 'a minute',
-        mm : '%d minutes',
-        h  : 'an hour',
-        hh : '%d hours',
-        d  : 'a day',
-        dd : '%d days',
-        M  : 'a month',
-        MM : '%d months',
-        y  : 'a year',
-        yy : '%d years'
-    };
-
-    function relative__relativeTime (number, withoutSuffix, string, isFuture) {
-        var output = this._relativeTime[string];
-        return (isFunction(output)) ?
-            output(number, withoutSuffix, string, isFuture) :
-            output.replace(/%d/i, number);
-    }
-
-    function pastFuture (diff, output) {
-        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
-        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
-    }
-
-    var prototype__proto = Locale.prototype;
-
-    prototype__proto._calendar       = defaultCalendar;
-    prototype__proto.calendar        = locale_calendar__calendar;
-    prototype__proto._longDateFormat = defaultLongDateFormat;
-    prototype__proto.longDateFormat  = longDateFormat;
-    prototype__proto._invalidDate    = defaultInvalidDate;
-    prototype__proto.invalidDate     = invalidDate;
-    prototype__proto._ordinal        = defaultOrdinal;
-    prototype__proto.ordinal         = ordinal;
-    prototype__proto._ordinalParse   = defaultOrdinalParse;
-    prototype__proto.preparse        = preParsePostFormat;
-    prototype__proto.postformat      = preParsePostFormat;
-    prototype__proto._relativeTime   = defaultRelativeTime;
-    prototype__proto.relativeTime    = relative__relativeTime;
-    prototype__proto.pastFuture      = pastFuture;
-    prototype__proto.set             = locale_set__set;
-
-    // Month
-    prototype__proto.months            =        localeMonths;
-    prototype__proto._months           = defaultLocaleMonths;
-    prototype__proto.monthsShort       =        localeMonthsShort;
-    prototype__proto._monthsShort      = defaultLocaleMonthsShort;
-    prototype__proto.monthsParse       =        localeMonthsParse;
-    prototype__proto._monthsRegex      = defaultMonthsRegex;
-    prototype__proto.monthsRegex       = monthsRegex;
-    prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
-    prototype__proto.monthsShortRegex  = monthsShortRegex;
-
-    // Week
-    prototype__proto.week = localeWeek;
-    prototype__proto._week = defaultLocaleWeek;
-    prototype__proto.firstDayOfYear = localeFirstDayOfYear;
-    prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
-
-    // Day of Week
-    prototype__proto.weekdays       =        localeWeekdays;
-    prototype__proto._weekdays      = defaultLocaleWeekdays;
-    prototype__proto.weekdaysMin    =        localeWeekdaysMin;
-    prototype__proto._weekdaysMin   = defaultLocaleWeekdaysMin;
-    prototype__proto.weekdaysShort  =        localeWeekdaysShort;
-    prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
-    prototype__proto.weekdaysParse  =        localeWeekdaysParse;
-
-    prototype__proto._weekdaysRegex      = defaultWeekdaysRegex;
-    prototype__proto.weekdaysRegex       =        weekdaysRegex;
-    prototype__proto._weekdaysShortRegex = defaultWeekdaysShortRegex;
-    prototype__proto.weekdaysShortRegex  =        weekdaysShortRegex;
-    prototype__proto._weekdaysMinRegex   = defaultWeekdaysMinRegex;
-    prototype__proto.weekdaysMinRegex    =        weekdaysMinRegex;
-
-    // Hours
-    prototype__proto.isPM = localeIsPM;
-    prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
-    prototype__proto.meridiem = localeMeridiem;
-
-    function lists__get (format, index, field, setter) {
-        var locale = locale_locales__getLocale();
-        var utc = create_utc__createUTC().set(setter, index);
-        return locale[field](utc, format);
-    }
-
-    function listMonthsImpl (format, index, field) {
-        if (typeof format === 'number') {
-            index = format;
-            format = undefined;
-        }
-
-        format = format || '';
-
-        if (index != null) {
-            return lists__get(format, index, field, 'month');
-        }
-
-        var i;
-        var out = [];
-        for (i = 0; i < 12; i++) {
-            out[i] = lists__get(format, i, field, 'month');
-        }
-        return out;
-    }
-
-    // ()
-    // (5)
-    // (fmt, 5)
-    // (fmt)
-    // (true)
-    // (true, 5)
-    // (true, fmt, 5)
-    // (true, fmt)
-    function listWeekdaysImpl (localeSorted, format, index, field) {
-        if (typeof localeSorted === 'boolean') {
-            if (typeof format === 'number') {
-                index = format;
-                format = undefined;
-            }
-
-            format = format || '';
-        } else {
-            format = localeSorted;
-            index = format;
-            localeSorted = false;
-
-            if (typeof format === 'number') {
-                index = format;
-                format = undefined;
-            }
-
-            format = format || '';
-        }
-
-        var locale = locale_locales__getLocale(),
-            shift = localeSorted ? locale._week.dow : 0;
-
-        if (index != null) {
-            return lists__get(format, (index + shift) % 7, field, 'day');
-        }
-
-        var i;
-        var out = [];
-        for (i = 0; i < 7; i++) {
-            out[i] = lists__get(format, (i + shift) % 7, field, 'day');
-        }
-        return out;
-    }
-
-    function lists__listMonths (format, index) {
-        return listMonthsImpl(format, index, 'months');
-    }
-
-    function lists__listMonthsShort (format, index) {
-        return listMonthsImpl(format, index, 'monthsShort');
-    }
-
-    function lists__listWeekdays (localeSorted, format, index) {
-        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
-    }
-
-    function lists__listWeekdaysShort (localeSorted, format, index) {
-        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
-    }
-
-    function lists__listWeekdaysMin (localeSorted, format, index) {
-        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
-    }
-
-    locale_locales__getSetGlobalLocale('en', {
-        ordinalParse: /\d{1,2}(th|st|nd|rd)/,
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (toInt(number % 100 / 10) === 1) ? 'th' :
-                (b === 1) ? 'st' :
-                (b === 2) ? 'nd' :
-                (b === 3) ? 'rd' : 'th';
-            return number + output;
-        }
-    });
-
-    // Side effect imports
-    utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
-    utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);
-
-    var mathAbs = Math.abs;
-
-    function duration_abs__abs () {
-        var data           = this._data;
-
-        this._milliseconds = mathAbs(this._milliseconds);
-        this._days         = mathAbs(this._days);
-        this._months       = mathAbs(this._months);
-
-        data.milliseconds  = mathAbs(data.milliseconds);
-        data.seconds       = mathAbs(data.seconds);
-        data.minutes       = mathAbs(data.minutes);
-        data.hours         = mathAbs(data.hours);
-        data.months        = mathAbs(data.months);
-        data.years         = mathAbs(data.years);
-
-        return this;
-    }
-
-    function duration_add_subtract__addSubtract (duration, input, value, direction) {
-        var other = create__createDuration(input, value);
-
-        duration._milliseconds += direction * other._milliseconds;
-        duration._days         += direction * other._days;
-        duration._months       += direction * other._months;
-
-        return duration._bubble();
-    }
-
-    // supports only 2.0-style add(1, 's') or add(duration)
-    function duration_add_subtract__add (input, value) {
-        return duration_add_subtract__addSubtract(this, input, value, 1);
-    }
-
-    // supports only 2.0-style subtract(1, 's') or subtract(duration)
-    function duration_add_subtract__subtract (input, value) {
-        return duration_add_subtract__addSubtract(this, input, value, -1);
-    }
-
-    function absCeil (number) {
-        if (number < 0) {
-            return Math.floor(number);
-        } else {
-            return Math.ceil(number);
-        }
-    }
-
-    function bubble () {
-        var milliseconds = this._milliseconds;
-        var days         = this._days;
-        var months       = this._months;
-        var data         = this._data;
-        var seconds, minutes, hours, years, monthsFromDays;
-
-        // if we have a mix of positive and negative values, bubble down first
-        // check: https://github.com/moment/moment/issues/2166
-        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
-                (milliseconds <= 0 && days <= 0 && months <= 0))) {
-            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
-            days = 0;
-            months = 0;
-        }
-
-        // The following code bubbles up values, see the tests for
-        // examples of what that means.
-        data.milliseconds = milliseconds % 1000;
-
-        seconds           = absFloor(milliseconds / 1000);
-        data.seconds      = seconds % 60;
-
-        minutes           = absFloor(seconds / 60);
-        data.minutes      = minutes % 60;
-
-        hours             = absFloor(minutes / 60);
-        data.hours        = hours % 24;
-
-        days += absFloor(hours / 24);
-
-        // convert days to months
-        monthsFromDays = absFloor(daysToMonths(days));
-        months += monthsFromDays;
-        days -= absCeil(monthsToDays(monthsFromDays));
-
-        // 12 months -> 1 year
-        years = absFloor(months / 12);
-        months %= 12;
-
-        data.days   = days;
-        data.months = months;
-        data.years  = years;
-
-        return this;
-    }
-
-    function daysToMonths (days) {
-        // 400 years have 146097 days (taking into account leap year rules)
-        // 400 years have 12 months === 4800
-        return days * 4800 / 146097;
-    }
-
-    function monthsToDays (months) {
-        // the reverse of daysToMonths
-        return months * 146097 / 4800;
-    }
-
-    function as (units) {
-        var days;
-        var months;
-        var milliseconds = this._milliseconds;
-
-        units = normalizeUnits(units);
-
-        if (units === 'month' || units === 'year') {
-            days   = this._days   + milliseconds / 864e5;
-            months = this._months + daysToMonths(days);
-            return units === 'month' ? months : months / 12;
-        } else {
-            // handle milliseconds separately because of floating point math errors (issue #1867)
-            days = this._days + Math.round(monthsToDays(this._months));
-            switch (units) {
-                case 'week'   : return days / 7     + milliseconds / 6048e5;
-                case 'day'    : return days         + milliseconds / 864e5;
-                case 'hour'   : return days * 24    + milliseconds / 36e5;
-                case 'minute' : return days * 1440  + milliseconds / 6e4;
-                case 'second' : return days * 86400 + milliseconds / 1000;
-                // Math.floor prevents floating point math errors here
-                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
-                default: throw new Error('Unknown unit ' + units);
-            }
-        }
-    }
-
-    // TODO: Use this.as('ms')?
-    function duration_as__valueOf () {
-        return (
-            this._milliseconds +
-            this._days * 864e5 +
-            (this._months % 12) * 2592e6 +
-            toInt(this._months / 12) * 31536e6
-        );
-    }
-
-    function makeAs (alias) {
-        return function () {
-            return this.as(alias);
-        };
-    }
-
-    var asMilliseconds = makeAs('ms');
-    var asSeconds      = makeAs('s');
-    var asMinutes      = makeAs('m');
-    var asHours        = makeAs('h');
-    var asDays         = makeAs('d');
-    var asWeeks        = makeAs('w');
-    var asMonths       = makeAs('M');
-    var asYears        = makeAs('y');
-
-    function duration_get__get (units) {
-        units = normalizeUnits(units);
-        return this[units + 's']();
-    }
-
-    function makeGetter(name) {
-        return function () {
-            return this._data[name];
-        };
-    }
-
-    var milliseconds = makeGetter('milliseconds');
-    var seconds      = makeGetter('seconds');
-    var minutes      = makeGetter('minutes');
-    var hours        = makeGetter('hours');
-    var days         = makeGetter('days');
-    var months       = makeGetter('months');
-    var years        = makeGetter('years');
-
-    function weeks () {
-        return absFloor(this.days() / 7);
-    }
-
-    var round = Math.round;
-    var thresholds = {
-        s: 45,  // seconds to minute
-        m: 45,  // minutes to hour
-        h: 22,  // hours to day
-        d: 26,  // days to month
-        M: 11   // months to year
-    };
-
-    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
-    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
-        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
-    }
-
-    function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
-        var duration = create__createDuration(posNegDuration).abs();
-        var seconds  = round(duration.as('s'));
-        var minutes  = round(duration.as('m'));
-        var hours    = round(duration.as('h'));
-        var days     = round(duration.as('d'));
-        var months   = round(duration.as('M'));
-        var years    = round(duration.as('y'));
-
-        var a = seconds < thresholds.s && ['s', seconds]  ||
-                minutes <= 1           && ['m']           ||
-                minutes < thresholds.m && ['mm', minutes] ||
-                hours   <= 1           && ['h']           ||
-                hours   < thresholds.h && ['hh', hours]   ||
-                days    <= 1           && ['d']           ||
-                days    < thresholds.d && ['dd', days]    ||
-                months  <= 1           && ['M']           ||
-                months  < thresholds.M && ['MM', months]  ||
-                years   <= 1           && ['y']           || ['yy', years];
-
-        a[2] = withoutSuffix;
-        a[3] = +posNegDuration > 0;
-        a[4] = locale;
-        return substituteTimeAgo.apply(null, a);
-    }
-
-    // This function allows you to set a threshold for relative time strings
-    function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
-        if (thresholds[threshold] === undefined) {
-            return false;
-        }
-        if (limit === undefined) {
-            return thresholds[threshold];
-        }
-        thresholds[threshold] = limit;
-        return true;
-    }
-
-    function humanize (withSuffix) {
-        var locale = this.localeData();
-        var output = duration_humanize__relativeTime(this, !withSuffix, locale);
-
-        if (withSuffix) {
-            output = locale.pastFuture(+this, output);
-        }
-
-        return locale.postformat(output);
-    }
-
-    var iso_string__abs = Math.abs;
-
-    function iso_string__toISOString() {
-        // for ISO strings we do not use the normal bubbling rules:
-        //  * milliseconds bubble up until they become hours
-        //  * days do not bubble at all
-        //  * months bubble up until they become years
-        // This is because there is no context-free conversion between hours and days
-        // (think of clock changes)
-        // and also not between days and months (28-31 days per month)
-        var seconds = iso_string__abs(this._milliseconds) / 1000;
-        var days         = iso_string__abs(this._days);
-        var months       = iso_string__abs(this._months);
-        var minutes, hours, years;
-
-        // 3600 seconds -> 60 minutes -> 1 hour
-        minutes           = absFloor(seconds / 60);
-        hours             = absFloor(minutes / 60);
-        seconds %= 60;
-        minutes %= 60;
-
-        // 12 months -> 1 year
-        years  = absFloor(months / 12);
-        months %= 12;
-
-
-        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
-        var Y = years;
-        var M = months;
-        var D = days;
-        var h = hours;
-        var m = minutes;
-        var s = seconds;
-        var total = this.asSeconds();
-
-        if (!total) {
-            // this is the same as C#'s (Noda) and python (isodate)...
-            // but not other JS (goog.date)
-            return 'P0D';
-        }
-
-        return (total < 0 ? '-' : '') +
-            'P' +
-            (Y ? Y + 'Y' : '') +
-            (M ? M + 'M' : '') +
-            (D ? D + 'D' : '') +
-            ((h || m || s) ? 'T' : '') +
-            (h ? h + 'H' : '') +
-            (m ? m + 'M' : '') +
-            (s ? s + 'S' : '');
-    }
-
-    var duration_prototype__proto = Duration.prototype;
-
-    duration_prototype__proto.abs            = duration_abs__abs;
-    duration_prototype__proto.add            = duration_add_subtract__add;
-    duration_prototype__proto.subtract       = duration_add_subtract__subtract;
-    duration_prototype__proto.as             = as;
-    duration_prototype__proto.asMilliseconds = asMilliseconds;
-    duration_prototype__proto.asSeconds      = asSeconds;
-    duration_prototype__proto.asMinutes      = asMinutes;
-    duration_prototype__proto.asHours        = asHours;
-    duration_prototype__proto.asDays         = asDays;
-    duration_prototype__proto.asWeeks        = asWeeks;
-    duration_prototype__proto.asMonths       = asMonths;
-    duration_prototype__proto.asYears        = asYears;
-    duration_prototype__proto.valueOf        = duration_as__valueOf;
-    duration_prototype__proto._bubble        = bubble;
-    duration_prototype__proto.get            = duration_get__get;
-    duration_prototype__proto.milliseconds   = milliseconds;
-    duration_prototype__proto.seconds        = seconds;
-    duration_prototype__proto.minutes        = minutes;
-    duration_prototype__proto.hours          = hours;
-    duration_prototype__proto.days           = days;
-    duration_prototype__proto.weeks          = weeks;
-    duration_prototype__proto.months         = months;
-    duration_prototype__proto.years          = years;
-    duration_prototype__proto.humanize       = humanize;
-    duration_prototype__proto.toISOString    = iso_string__toISOString;
-    duration_prototype__proto.toString       = iso_string__toISOString;
-    duration_prototype__proto.toJSON         = iso_string__toISOString;
-    duration_prototype__proto.locale         = locale;
-    duration_prototype__proto.localeData     = localeData;
-
-    // Deprecations
-    duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
-    duration_prototype__proto.lang = lang;
-
-    // Side effect imports
-
-    // FORMATTING
-
-    addFormatToken('X', 0, 0, 'unix');
-    addFormatToken('x', 0, 0, 'valueOf');
-
-    // PARSING
-
-    addRegexToken('x', matchSigned);
-    addRegexToken('X', matchTimestamp);
-    addParseToken('X', function (input, array, config) {
-        config._d = new Date(parseFloat(input, 10) * 1000);
-    });
-    addParseToken('x', function (input, array, config) {
-        config._d = new Date(toInt(input));
-    });
-
-    // Side effect imports
-
-
-    utils_hooks__hooks.version = '2.13.0';
-
-    setHookCallback(local__createLocal);
-
-    utils_hooks__hooks.fn                    = momentPrototype;
-    utils_hooks__hooks.min                   = min;
-    utils_hooks__hooks.max                   = max;
-    utils_hooks__hooks.now                   = now;
-    utils_hooks__hooks.utc                   = create_utc__createUTC;
-    utils_hooks__hooks.unix                  = moment__createUnix;
-    utils_hooks__hooks.months                = lists__listMonths;
-    utils_hooks__hooks.isDate                = isDate;
-    utils_hooks__hooks.locale                = locale_locales__getSetGlobalLocale;
-    utils_hooks__hooks.invalid               = valid__createInvalid;
-    utils_hooks__hooks.duration              = create__createDuration;
-    utils_hooks__hooks.isMoment              = isMoment;
-    utils_hooks__hooks.weekdays              = lists__listWeekdays;
-    utils_hooks__hooks.parseZone             = moment__createInZone;
-    utils_hooks__hooks.localeData            = locale_locales__getLocale;
-    utils_hooks__hooks.isDuration            = isDuration;
-    utils_hooks__hooks.monthsShort           = lists__listMonthsShort;
-    utils_hooks__hooks.weekdaysMin           = lists__listWeekdaysMin;
-    utils_hooks__hooks.defineLocale          = defineLocale;
-    utils_hooks__hooks.updateLocale          = updateLocale;
-    utils_hooks__hooks.locales               = locale_locales__listLocales;
-    utils_hooks__hooks.weekdaysShort         = lists__listWeekdaysShort;
-    utils_hooks__hooks.normalizeUnits        = normalizeUnits;
-    utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
-    utils_hooks__hooks.prototype             = momentPrototype;
-
-    var _moment = utils_hooks__hooks;
-
-    return _moment;
-
-}));;/**
- * Parse a text request to a json query object tree
- *
- * @param  {String} string The string to parse
- * @return {Object} The json query tree
- */
-function parseStringToObject(string) {
-
-var arrayExtend = function () {
-  var j, i, newlist = [], list_list = arguments;
-  for (j = 0; j < list_list.length; j += 1) {
-    for (i = 0; i < list_list[j].length; i += 1) {
-      newlist.push(list_list[j][i]);
-    }
-  }
-  return newlist;
-
-}, mkSimpleQuery = function (key, value, operator) {
-  var object = {"type": "simple", "key": key, "value": value};
-  if (operator !== undefined) {
-    object.operator = operator;
-  }
-  return object;
-
-}, mkNotQuery = function (query) {
-  if (query.operator === "NOT") {
-    return query.query_list[0];
-  }
-  return {"type": "complex", "operator": "NOT", "query_list": [query]};
-
-}, mkComplexQuery = function (operator, query_list) {
-  var i, query_list2 = [];
-  for (i = 0; i < query_list.length; i += 1) {
-    if (query_list[i].operator === operator) {
-      query_list2 = arrayExtend(query_list2, query_list[i].query_list);
-    } else {
-      query_list2.push(query_list[i]);
-    }
-  }
-  return {type:"complex",operator:operator,query_list:query_list2};
-
-}, simpleQuerySetKey = function (query, key) {
-  var i;
-  if (query.type === "complex") {
-    for (i = 0; i < query.query_list.length; ++i) {
-      simpleQuerySetKey (query.query_list[i],key);
-    }
-    return true;
-  }
-  if (query.type === "simple" && !query.key) {
-    query.key = key;
-    return true;
-  }
-  return false;
-},
-  error_offsets = [],
-  error_lookaheads = [],
-  error_count = 0,
-  result;
-;/* parser generated by jison 0.4.16 */
-/*
-  Returns a Parser object of the following structure:
-
-  Parser: {
-    yy: {}
-  }
-
-  Parser.prototype: {
-    yy: {},
-    trace: function(),
-    symbols_: {associative list: name ==> number},
-    terminals_: {associative list: number ==> name},
-    productions_: [...],
-    performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
-    table: [...],
-    defaultActions: {...},
-    parseError: function(str, hash),
-    parse: function(input),
-
-    lexer: {
-        EOF: 1,
-        parseError: function(str, hash),
-        setInput: function(input),
-        input: function(),
-        unput: function(str),
-        more: function(),
-        less: function(n),
-        pastInput: function(),
-        upcomingInput: function(),
-        showPosition: function(),
-        test_match: function(regex_match_array, rule_index),
-        next: function(),
-        lex: function(),
-        begin: function(condition),
-        popState: function(),
-        _currentRules: function(),
-        topState: function(),
-        pushState: function(condition),
-
-        options: {
-            ranges: boolean           (optional: true ==> token location info will include a .range[] member)
-            flex: boolean             (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
-            backtrack_lexer: boolean  (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
-        },
-
-        performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
-        rules: [...],
-        conditions: {associative list: name ==> set},
-    }
-  }
-
-
-  token location info (@$, _$, etc.): {
-    first_line: n,
-    last_line: n,
-    first_column: n,
-    last_column: n,
-    range: [start_number, end_number]       (where the numbers are indexes into the input string, regular zero-based)
-  }
-
-
-  the parseError function receives a 'hash' object with these members for lexer and parser errors: {
-    text:        (matched text)
-    token:       (the produced terminal token, if any)
-    line:        (yylineno)
-  }
-  while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
-    loc:         (yylloc)
-    expected:    (string describing the set of expected tokens)
-    recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
-  }
-*/
-var parser = (function(){
-var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,7],$V2=[1,8],$V3=[1,10],$V4=[1,12],$V5=[1,6,7,15],$V6=[1,6,7,9,12,14,15,16,19,21],$V7=[1,6,7,9,11,12,14,15,16,19,21],$V8=[2,17];
-var parser = {trace: function trace() { },
-yy: {},
-symbols_: {"error":2,"begin":3,"search_text":4,"end":5,"EOF":6,"NEWLINE":7,"and_expression":8,"OR":9,"boolean_expression":10,"AND":11,"NOT":12,"expression":13,"LEFT_PARENTHESE":14,"RIGHT_PARENTHESE":15,"WORD":16,"DEFINITION":17,"value":18,"OPERATOR":19,"string":20,"QUOTE":21,"QUOTED_STRING":22,"$accept":0,"$end":1},
-terminals_: {2:"error",6:"EOF",7:"NEWLINE",9:"OR",11:"AND",12:"NOT",14:"LEFT_PARENTHESE",15:"RIGHT_PARENTHESE",16:"WORD",17:"DEFINITION",19:"OPERATOR",21:"QUOTE",22:"QUOTED_STRING"},
-productions_: [0,[3,2],[5,0],[5,1],[5,1],[4,1],[4,2],[4,3],[8,1],[8,3],[10,2],[10,1],[13,3],[13,3],[13,1],[18,2],[18,1],[20,1],[20,3]],
-performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
-/* this == yyval */
-
-var $0 = $$.length - 1;
-switch (yystate) {
-case 1:
- return $$[$0-1]; 
-break;
-case 5: case 8: case 11: case 14: case 16:
- this.$ = $$[$0]; 
-break;
-case 6:
- this.$ = mkComplexQuery('OR', [$$[$0-1], $$[$0]]); 
-break;
-case 7:
- this.$ = mkComplexQuery('OR', [$$[$0-2], $$[$0]]); 
-break;
-case 9:
- this.$ = mkComplexQuery('AND', [$$[$0-2], $$[$0]]); 
-break;
-case 10:
- this.$ = mkNotQuery($$[$0]); 
-break;
-case 12:
- this.$ = $$[$0-1]; 
-break;
-case 13:
- simpleQuerySetKey($$[$0], $$[$0-2]); this.$ = $$[$0]; 
-break;
-case 15:
- $$[$0].operator = $$[$0-1] ; this.$ = $$[$0]; 
-break;
-case 17:
- this.$ = mkSimpleQuery('', $$[$0]); 
-break;
-case 18:
- this.$ = mkSimpleQuery('', $$[$0-1]); 
-break;
-}
-},
-table: [{3:1,4:2,8:3,10:4,12:$V0,13:6,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},{1:[3]},{1:[2,2],5:13,6:[1,14],7:[1,15]},o($V5,[2,5],{8:3,10:4,13:6,18:9,20:11,4:16,9:[1,17],12:$V0,14:$V1,16:$V2,19:$V3,21:$V4}),o($V6,[2,8],{11:[1,18]}),{13:19,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},o($V7,[2,11]),{4:20,8:3,10:4,12:$V0,13:6,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},o($V7,$V8,{17:[1,21]}),o($V7,[2,14]),{16:[1,23],20:22,21:$V4},o($V7,[2,16]),{22:[1,24]},{1:[2,1]},{1:[2,3]},{1:[2,4]},o($V5,[2,6]),{4:25,8:3,10:4,12:$V0,13:6,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},{8:26,10:4,12:$V0,13:6,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},o($V7,[2,10]),{15:[1,27]},{13:28,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},o($V7,[2,15]),o($V7,$V8),{21:[1,29]},o($V5,[2,7]),o($V6,[2,9]),o($V7,[2,12]),o($V7,[2,13]),o($V7,[2,18])],
-defaultActions: {13:[2,1],14:[2,3],15:[2,4]},
-parseError: function parseError(str, hash) {
-    if (hash.recoverable) {
-        this.trace(str);
-    } else {
-        function _parseError (msg, hash) {
-            this.message = msg;
-            this.hash = hash;
-        }
-        _parseError.prototype = new Error();
-
-        throw new _parseError(str, hash);
-    }
-},
-parse: function parse(input) {
-    var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
-    var args = lstack.slice.call(arguments, 1);
-    var lexer = Object.create(this.lexer);
-    var sharedState = { yy: {} };
-    for (var k in this.yy) {
-        if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
-            sharedState.yy[k] = this.yy[k];
-        }
-    }
-    lexer.setInput(input, sharedState.yy);
-    sharedState.yy.lexer = lexer;
-    sharedState.yy.parser = this;
-    if (typeof lexer.yylloc == 'undefined') {
-        lexer.yylloc = {};
-    }
-    var yyloc = lexer.yylloc;
-    lstack.push(yyloc);
-    var ranges = lexer.options && lexer.options.ranges;
-    if (typeof sharedState.yy.parseError === 'function') {
-        this.parseError = sharedState.yy.parseError;
-    } else {
-        this.parseError = Object.getPrototypeOf(this).parseError;
-    }
-    function popStack(n) {
-        stack.length = stack.length - 2 * n;
-        vstack.length = vstack.length - n;
-        lstack.length = lstack.length - n;
-    }
-    _token_stack:
-        var lex = function () {
-            var token;
-            token = lexer.lex() || EOF;
-            if (typeof token !== 'number') {
-                token = self.symbols_[token] || token;
-            }
-            return token;
-        };
-    var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
-    while (true) {
-        state = stack[stack.length - 1];
-        if (this.defaultActions[state]) {
-            action = this.defaultActions[state];
-        } else {
-            if (symbol === null || typeof symbol == 'undefined') {
-                symbol = lex();
-            }
-            action = table[state] && table[state][symbol];
-        }
-                    if (typeof action === 'undefined' || !action.length || !action[0]) {
-                var errStr = '';
-                expected = [];
-                for (p in table[state]) {
-                    if (this.terminals_[p] && p > TERROR) {
-                        expected.push('\'' + this.terminals_[p] + '\'');
-                    }
-                }
-                if (lexer.showPosition) {
-                    errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
-                } else {
-                    errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
-                }
-                this.parseError(errStr, {
-                    text: lexer.match,
-                    token: this.terminals_[symbol] || symbol,
-                    line: lexer.yylineno,
-                    loc: yyloc,
-                    expected: expected
-                });
-            }
-        if (action[0] instanceof Array && action.length > 1) {
-            throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
-        }
-        switch (action[0]) {
-        case 1:
-            stack.push(symbol);
-            vstack.push(lexer.yytext);
-            lstack.push(lexer.yylloc);
-            stack.push(action[1]);
-            symbol = null;
-            if (!preErrorSymbol) {
-                yyleng = lexer.yyleng;
-                yytext = lexer.yytext;
-                yylineno = lexer.yylineno;
-                yyloc = lexer.yylloc;
-                if (recovering > 0) {
-                    recovering--;
-                }
-            } else {
-                symbol = preErrorSymbol;
-                preErrorSymbol = null;
-            }
-            break;
-        case 2:
-            len = this.productions_[action[1]][1];
-            yyval.$ = vstack[vstack.length - len];
-            yyval._$ = {
-                first_line: lstack[lstack.length - (len || 1)].first_line,
-                last_line: lstack[lstack.length - 1].last_line,
-                first_column: lstack[lstack.length - (len || 1)].first_column,
-                last_column: lstack[lstack.length - 1].last_column
-            };
-            if (ranges) {
-                yyval._$.range = [
-                    lstack[lstack.length - (len || 1)].range[0],
-                    lstack[lstack.length - 1].range[1]
-                ];
-            }
-            r = this.performAction.apply(yyval, [
-                yytext,
-                yyleng,
-                yylineno,
-                sharedState.yy,
-                action[1],
-                vstack,
-                lstack
-            ].concat(args));
-            if (typeof r !== 'undefined') {
-                return r;
-            }
-            if (len) {
-                stack = stack.slice(0, -1 * len * 2);
-                vstack = vstack.slice(0, -1 * len);
-                lstack = lstack.slice(0, -1 * len);
-            }
-            stack.push(this.productions_[action[1]][0]);
-            vstack.push(yyval.$);
-            lstack.push(yyval._$);
-            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
-            stack.push(newState);
-            break;
-        case 3:
-            return true;
-        }
-    }
-    return true;
-}};
-/* generated by jison-lex 0.3.4 */
-var lexer = (function(){
-var lexer = ({
-
-EOF:1,
-
-parseError:function parseError(str, hash) {
-        if (this.yy.parser) {
-            this.yy.parser.parseError(str, hash);
-        } else {
-            throw new Error(str);
-        }
-    },
-
-// resets the lexer, sets new input
-setInput:function (input, yy) {
-        this.yy = yy || this.yy || {};
-        this._input = input;
-        this._more = this._backtrack = this.done = false;
-        this.yylineno = this.yyleng = 0;
-        this.yytext = this.matched = this.match = '';
-        this.conditionStack = ['INITIAL'];
-        this.yylloc = {
-            first_line: 1,
-            first_column: 0,
-            last_line: 1,
-            last_column: 0
-        };
-        if (this.options.ranges) {
-            this.yylloc.range = [0,0];
-        }
-        this.offset = 0;
-        return this;
-    },
-
-// consumes and returns one char from the input
-input:function () {
-        var ch = this._input[0];
-        this.yytext += ch;
-        this.yyleng++;
-        this.offset++;
-        this.match += ch;
-        this.matched += ch;
-        var lines = ch.match(/(?:\r\n?|\n).*/g);
-        if (lines) {
-            this.yylineno++;
-            this.yylloc.last_line++;
-        } else {
-            this.yylloc.last_column++;
-        }
-        if (this.options.ranges) {
-            this.yylloc.range[1]++;
-        }
-
-        this._input = this._input.slice(1);
-        return ch;
-    },
-
-// unshifts one char (or a string) into the input
-unput:function (ch) {
-        var len = ch.length;
-        var lines = ch.split(/(?:\r\n?|\n)/g);
-
-        this._input = ch + this._input;
-        this.yytext = this.yytext.substr(0, this.yytext.length - len);
-        //this.yyleng -= len;
-        this.offset -= len;
-        var oldLines = this.match.split(/(?:\r\n?|\n)/g);
-        this.match = this.match.substr(0, this.match.length - 1);
-        this.matched = this.matched.substr(0, this.matched.length - 1);
-
-        if (lines.length - 1) {
-            this.yylineno -= lines.length - 1;
-        }
-        var r = this.yylloc.range;
-
-        this.yylloc = {
-            first_line: this.yylloc.first_line,
-            last_line: this.yylineno + 1,
-            first_column: this.yylloc.first_column,
-            last_column: lines ?
-                (lines.length === oldLines.length ? this.yylloc.first_column : 0)
-                 + oldLines[oldLines.length - lines.length].length - lines[0].length :
-              this.yylloc.first_column - len
-        };
-
-        if (this.options.ranges) {
-            this.yylloc.range = [r[0], r[0] + this.yyleng - len];
-        }
-        this.yyleng = this.yytext.length;
-        return this;
-    },
-
-// When called from action, caches matched text and appends it on next action
-more:function () {
-        this._more = true;
-        return this;
-    },
-
-// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
-reject:function () {
-        if (this.options.backtrack_lexer) {
-            this._backtrack = true;
-        } else {
-            return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
-                text: "",
-                token: null,
-                line: this.yylineno
-            });
-
-        }
-        return this;
-    },
-
-// retain first n characters of the match
-less:function (n) {
-        this.unput(this.match.slice(n));
-    },
-
-// displays already matched input, i.e. for error messages
-pastInput:function () {
-        var past = this.matched.substr(0, this.matched.length - this.match.length);
-        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
-    },
-
-// displays upcoming input, i.e. for error messages
-upcomingInput:function () {
-        var next = this.match;
-        if (next.length < 20) {
-            next += this._input.substr(0, 20-next.length);
-        }
-        return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
-    },
-
-// displays the character position where the lexing error occurred, i.e. for error messages
-showPosition:function () {
-        var pre = this.pastInput();
-        var c = new Array(pre.length + 1).join("-");
-        return pre + this.upcomingInput() + "\n" + c + "^";
-    },
-
-// test the lexed token: return FALSE when not a match, otherwise return token
-test_match:function (match, indexed_rule) {
-        var token,
-            lines,
-            backup;
-
-        if (this.options.backtrack_lexer) {
-            // save context
-            backup = {
-                yylineno: this.yylineno,
-                yylloc: {
-                    first_line: this.yylloc.first_line,
-                    last_line: this.last_line,
-                    first_column: this.yylloc.first_column,
-                    last_column: this.yylloc.last_column
-                },
-                yytext: this.yytext,
-                match: this.match,
-                matches: this.matches,
-                matched: this.matched,
-                yyleng: this.yyleng,
-                offset: this.offset,
-                _more: this._more,
-                _input: this._input,
-                yy: this.yy,
-                conditionStack: this.conditionStack.slice(0),
-                done: this.done
-            };
-            if (this.options.ranges) {
-                backup.yylloc.range = this.yylloc.range.slice(0);
-            }
-        }
-
-        lines = match[0].match(/(?:\r\n?|\n).*/g);
-        if (lines) {
-            this.yylineno += lines.length;
-        }
-        this.yylloc = {
-            first_line: this.yylloc.last_line,
-            last_line: this.yylineno + 1,
-            first_column: this.yylloc.last_column,
-            last_column: lines ?
-                         lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
-                         this.yylloc.last_column + match[0].length
-        };
-        this.yytext += match[0];
-        this.match += match[0];
-        this.matches = match;
-        this.yyleng = this.yytext.length;
-        if (this.options.ranges) {
-            this.yylloc.range = [this.offset, this.offset += this.yyleng];
-        }
-        this._more = false;
-        this._backtrack = false;
-        this._input = this._input.slice(match[0].length);
-        this.matched += match[0];
-        token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
-        if (this.done && this._input) {
-            this.done = false;
-        }
-        if (token) {
-            return token;
-        } else if (this._backtrack) {
-            // recover context
-            for (var k in backup) {
-                this[k] = backup[k];
-            }
-            return false; // rule action called reject() implying the next rule should be tested instead.
-        }
-        return false;
-    },
-
-// return next match in input
-next:function () {
-        if (this.done) {
-            return this.EOF;
-        }
-        if (!this._input) {
-            this.done = true;
-        }
-
-        var token,
-            match,
-            tempMatch,
-            index;
-        if (!this._more) {
-            this.yytext = '';
-            this.match = '';
-        }
-        var rules = this._currentRules();
-        for (var i = 0; i < rules.length; i++) {
-            tempMatch = this._input.match(this.rules[rules[i]]);
-            if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
-                match = tempMatch;
-                index = i;
-                if (this.options.backtrack_lexer) {
-                    token = this.test_match(tempMatch, rules[i]);
-                    if (token !== false) {
-                        return token;
-                    } else if (this._backtrack) {
-                        match = false;
-                        continue; // rule action called reject() implying a rule MISmatch.
-                    } else {
-                        // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
-                        return false;
-                    }
-                } else if (!this.options.flex) {
-                    break;
-                }
-            }
-        }
-        if (match) {
-            token = this.test_match(match, rules[index]);
-            if (token !== false) {
-                return token;
-            }
-            // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
-            return false;
-        }
-        if (this._input === "") {
-            return this.EOF;
-        } else {
-            return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
-                text: "",
-                token: null,
-                line: this.yylineno
-            });
-        }
-    },
-
-// return next match that has a token
-lex:function lex() {
-        var r = this.next();
-        if (r) {
-            return r;
-        } else {
-            return this.lex();
-        }
-    },
-
-// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
-begin:function begin(condition) {
-        this.conditionStack.push(condition);
-    },
-
-// pop the previously active lexer condition state off the condition stack
-popState:function popState() {
-        var n = this.conditionStack.length - 1;
-        if (n > 0) {
-            return this.conditionStack.pop();
-        } else {
-            return this.conditionStack[0];
-        }
-    },
-
-// produce the lexer rule set which is active for the currently active lexer condition state
-_currentRules:function _currentRules() {
-        if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
-            return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
-        } else {
-            return this.conditions["INITIAL"].rules;
-        }
-    },
-
-// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
-topState:function topState(n) {
-        n = this.conditionStack.length - 1 - Math.abs(n || 0);
-        if (n >= 0) {
-            return this.conditionStack[n];
-        } else {
-            return "INITIAL";
-        }
-    },
-
-// alias for begin(condition)
-pushState:function pushState(condition) {
-        this.begin(condition);
-    },
-
-// return the number of states currently on the stack
-stateStackSize:function stateStackSize() {
-        return this.conditionStack.length;
-    },
-options: {},
-performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
-var YYSTATE=YY_START;
-switch($avoiding_name_collisions) {
-case 0:this.begin("letsquote"); return "QUOTE";
-break;
-case 1:this.popState(); this.begin("endquote"); return "QUOTED_STRING";
-break;
-case 2:this.popState(); return "QUOTE";
-break;
-case 3:/* skip whitespace */
-break;
-case 4:return "LEFT_PARENTHESE";
-break;
-case 5:return "RIGHT_PARENTHESE";
-break;
-case 6:return "AND";
-break;
-case 7:return "OR";
-break;
-case 8:return "NOT";
-break;
-case 9:return "DEFINITION";
-break;
-case 10:return 19;
-break;
-case 11:return 16;
-break;
-case 12:return 6;
-break;
-}
-},
-rules: [/^(?:")/,/^(?:(\\"|[^"])*)/,/^(?:")/,/^(?:[^\S]+)/,/^(?:\()/,/^(?:\))/,/^(?:AND\b)/,/^(?:OR\b)/,/^(?:NOT\b)/,/^(?::)/,/^(?:(!?=|<=?|>=?))/,/^(?:[^\s\n"():><!=]+)/,/^(?:$)/],
-conditions: {"endquote":{"rules":[2],"inclusive":false},"letsquote":{"rules":[1],"inclusive":false},"INITIAL":{"rules":[0,3,4,5,6,7,8,9,10,11,12],"inclusive":true}}
-});
-return lexer;
-})();
-parser.lexer = lexer;
-function Parser () {
-  this.yy = {};
-}
-Parser.prototype = parser;parser.Parser = Parser;
-return new Parser;
-})();;  return parser.parse(string);
-} // parseStringToObject
-
-;/*global RSVP, window, parseStringToObject*/
-/*jslint nomen: true, maxlen: 90*/
-(function (RSVP, window, parseStringToObject) {
-  "use strict";
-
-  var query_class_dict = {},
-    regexp_escape = /[\-\[\]{}()*+?.,\\\^$|#\s]/g,
-    regexp_percent = /%/g,
-    regexp_underscore = /_/g,
-    regexp_operator = /^(?:AND|OR|NOT)$/i,
-    regexp_comparaison = /^(?:!?=|<=?|>=?)$/i;
-
-  /**
-   * Convert metadata values to array of strings. ex:
-   *
-   *     "a" -> ["a"],
-   *     {"content": "a"} -> ["a"]
-   *
-   * @param  {Any} value The metadata value
-   * @return {Array} The value in string array format
-   */
-  function metadataValueToStringArray(value) {
-    var i, new_value = [];
-    if (value === undefined) {
-      return undefined;
-    }
-    if (!Array.isArray(value)) {
-      value = [value];
-    }
-    for (i = 0; i < value.length; i += 1) {
-      if (typeof value[i] === 'object') {
-        new_value[i] = value[i].content;
-      } else {
-        new_value[i] = value[i];
-      }
-    }
-    return new_value;
-  }
-
-  /**
-   * A sort function to sort items by key
-   *
-   * @param  {String} key The key to sort on
-   * @param  {String} [way="ascending"] 'ascending' or 'descending'
-   * @return {Function} The sort function
-   */
-  function sortFunction(key, way) {
-    var result;
-    if (way === 'descending') {
-      result = 1;
-    } else if (way === 'ascending') {
-      result = -1;
-    } else {
-      throw new TypeError("Query.sortFunction(): " +
-                          "Argument 2 must be 'ascending' or 'descending'");
-    }
-    return function (a, b) {
-      // this comparison is 5 times faster than json comparison
-      var i, l;
-      a = metadataValueToStringArray(a[key]) || [];
-      b = metadataValueToStringArray(b[key]) || [];
-      l = a.length > b.length ? a.length : b.length;
-      for (i = 0; i < l; i += 1) {
-        if (a[i] === undefined) {
-          return result;
-        }
-        if (b[i] === undefined) {
-          return -result;
-        }
-        if (a[i] > b[i]) {
-          return -result;
-        }
-        if (a[i] < b[i]) {
-          return result;
-        }
-      }
-      return 0;
-    };
-  }
-
-  /**
-   * Sort a list of items, according to keys and directions.
-   *
-   * @param  {Array} sort_on_option List of couples [key, direction]
-   * @param  {Array} list The item list to sort
-   * @return {Array} The filtered list
-   */
-  function sortOn(sort_on_option, list) {
-    var sort_index;
-    if (!Array.isArray(sort_on_option)) {
-      throw new TypeError("jioquery.sortOn(): " +
-                          "Argument 1 is not of type 'array'");
-    }
-    for (sort_index = sort_on_option.length - 1; sort_index >= 0;
-         sort_index -= 1) {
-      list.sort(sortFunction(
-        sort_on_option[sort_index][0],
-        sort_on_option[sort_index][1]
-      ));
-    }
-    return list;
-  }
-
-  /**
-   * Limit a list of items, according to index and length.
-   *
-   * @param  {Array} limit_option A couple [from, length]
-   * @param  {Array} list The item list to limit
-   * @return {Array} The filtered list
-   */
-  function limit(limit_option, list) {
-    if (!Array.isArray(limit_option)) {
-      throw new TypeError("jioquery.limit(): " +
-                          "Argument 1 is not of type 'array'");
-    }
-    if (!Array.isArray(list)) {
-      throw new TypeError("jioquery.limit(): " +
-                          "Argument 2 is not of type 'array'");
-    }
-    list.splice(0, limit_option[0]);
-    if (limit_option[1]) {
-      list.splice(limit_option[1]);
-    }
-    return list;
-  }
-
-  /**
-   * Filter a list of items, modifying them to select only wanted keys.
-   *
-   * @param  {Array} select_option Key list to keep
-   * @param  {Array} list The item list to filter
-   * @return {Array} The filtered list
-   */
-  function select(select_option, list) {
-    var i, j, new_item;
-    if (!Array.isArray(select_option)) {
-      throw new TypeError("jioquery.select(): " +
-                          "Argument 1 is not of type Array");
-    }
-    if (!Array.isArray(list)) {
-      throw new TypeError("jioquery.select(): " +
-                          "Argument 2 is not of type Array");
-    }
-    for (i = 0; i < list.length; i += 1) {
-      new_item = {};
-      for (j = 0; j < select_option.length; j += 1) {
-        if (list[i].hasOwnProperty([select_option[j]])) {
-          new_item[select_option[j]] = list[i][select_option[j]];
-        }
-      }
-      for (j in new_item) {
-        if (new_item.hasOwnProperty(j)) {
-          list[i] = new_item;
-          break;
-        }
-      }
-    }
-    return list;
-  }
-
-  /**
-   * The query to use to filter a list of objects.
-   * This is an abstract class.
-   *
-   * @class Query
-   * @constructor
-   */
-  function Query() {
-
-    /**
-     * Called before parsing the query. Must be overridden!
-     *
-     * @method onParseStart
-     * @param  {Object} object The object shared in the parse process
-     * @param  {Object} option Some option gave in parse()
-     */
-  //   this.onParseStart = emptyFunction;
-
-    /**
-     * Called when parsing a simple query. Must be overridden!
-     *
-     * @method onParseSimpleQuery
-     * @param  {Object} object The object shared in the parse process
-     * @param  {Object} option Some option gave in parse()
-     */
-  //   this.onParseSimpleQuery = emptyFunction;
-
-    /**
-     * Called when parsing a complex query. Must be overridden!
-     *
-     * @method onParseComplexQuery
-     * @param  {Object} object The object shared in the parse process
-     * @param  {Object} option Some option gave in parse()
-     */
-  //   this.onParseComplexQuery = emptyFunction;
-
-    /**
-     * Called after parsing the query. Must be overridden!
-     *
-     * @method onParseEnd
-     * @param  {Object} object The object shared in the parse process
-     * @param  {Object} option Some option gave in parse()
-     */
-  //   this.onParseEnd = emptyFunction;
-
-    return;
-  }
-
-  /**
-   * Filter the item list with matching item only
-   *
-   * @method exec
-   * @param  {Array} item_list The list of object
-   * @param  {Object} [option] Some operation option
-   * @param  {Array} [option.select_list] A object keys to retrieve
-   * @param  {Array} [option.sort_on] Couples of object keys and "ascending"
-   *                 or "descending"
-   * @param  {Array} [option.limit] Couple of integer, first is an index and
-   *                 second is the length.
-   */
-  Query.prototype.exec = function (item_list, option) {
-    if (!Array.isArray(item_list)) {
-      throw new TypeError("Query().exec(): Argument 1 is not of type 'array'");
-    }
-    if (option === undefined) {
-      option = {};
-    }
-    if (typeof option !== 'object') {
-      throw new TypeError("Query().exec(): " +
-                          "Optional argument 2 is not of type 'object'");
-    }
-    var context = this,
-      i;
-    for (i = item_list.length - 1; i >= 0; i -= 1) {
-      if (!context.match(item_list[i])) {
-        item_list.splice(i, 1);
-      }
-    }
-
-    if (option.sort_on) {
-      sortOn(option.sort_on, item_list);
-    }
-
-    if (option.limit) {
-      limit(option.limit, item_list);
-    }
-
-    select(option.select_list || [], item_list);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return item_list;
-      });
-  };
-
-  /**
-   * Test if an item matches this query
-   *
-   * @method match
-   * @param  {Object} item The object to test
-   * @return {Boolean} true if match, false otherwise
-   */
-  Query.prototype.match = function () {
-    return true;
-  };
-
-  /**
-   * Browse the Query in deep calling parser method in each step.
-   *
-   * `onParseStart` is called first, on end `onParseEnd` is called.
-   * It starts from the simple queries at the bottom of the tree calling the
-   * parser method `onParseSimpleQuery`, and go up calling the
-   * `onParseComplexQuery` method.
-   *
-   * @method parse
-   * @param  {Object} option Any options you want (except 'parsed')
-   * @return {Any} The parse result
-   */
-  Query.prototype.parse = function (option) {
-    var that = this,
-      object;
-    /**
-     * The recursive parser.
-     *
-     * @param  {Object} object The object shared in the parse process
-     * @param  {Object} options Some options usable in the parseMethods
-     * @return {Any} The parser result
-     */
-    function recParse(object, option) {
-      var query = object.parsed,
-        queue = new RSVP.Queue(),
-        i;
-
-      function enqueue(j) {
-        queue
-          .push(function () {
-            object.parsed = query.query_list[j];
-            return recParse(object, option);
-          })
-          .push(function () {
-            query.query_list[j] = object.parsed;
-          });
-      }
-
-      if (query.type === "complex") {
-
-
-        for (i = 0; i < query.query_list.length; i += 1) {
-          enqueue(i);
-        }
-
-        return queue
-          .push(function () {
-            object.parsed = query;
-            return that.onParseComplexQuery(object, option);
-          });
-
-      }
-      if (query.type === "simple") {
-        return that.onParseSimpleQuery(object, option);
-      }
-    }
-    object = {
-      parsed: JSON.parse(JSON.stringify(that.serialized()))
-    };
-    return new RSVP.Queue()
-      .push(function () {
-        return that.onParseStart(object, option);
-      })
-      .push(function () {
-        return recParse(object, option);
-      })
-      .push(function () {
-        return that.onParseEnd(object, option);
-      })
-      .push(function () {
-        return object.parsed;
-      });
-
-  };
-
-  /**
-   * Convert this query to a parsable string.
-   *
-   * @method toString
-   * @return {String} The string version of this query
-   */
-  Query.prototype.toString = function () {
-    return "";
-  };
-
-  /**
-   * Convert this query to an jsonable object in order to be remake thanks to
-   * QueryFactory class.
-   *
-   * @method serialized
-   * @return {Object} The jsonable object
-   */
-  Query.prototype.serialized = function () {
-    return undefined;
-  };
-
-  /**
-   * Provides static methods to create Query object
-   *
-   * @class QueryFactory
-   */
-  function QueryFactory() {
-    return;
-  }
-
-  /**
-   * Escapes regexp special chars from a string.
-   *
-   * @param  {String} string The string to escape
-   * @return {String} The escaped string
-   */
-  function stringEscapeRegexpCharacters(string) {
-    return string.replace(regexp_escape, "\\$&");
-  }
-
-  /**
-   * Inherits the prototype methods from one constructor into another. The
-   * prototype of `constructor` will be set to a new object created from
-   * `superConstructor`.
-   *
-   * @param  {Function} constructor The constructor which inherits the super one
-   * @param  {Function} superConstructor The super constructor
-   */
-  function inherits(constructor, superConstructor) {
-    constructor.super_ = superConstructor;
-    constructor.prototype = Object.create(superConstructor.prototype, {
-      "constructor": {
-        "configurable": true,
-        "enumerable": false,
-        "writable": true,
-        "value": constructor
-      }
-    });
-  }
-
-  /**
-   * Convert a search text to a regexp.
-   *
-   * @param  {String} string The string to convert
-   * @param  {Boolean} [use_wildcard_character=true] Use wildcard "%" and "_"
-   * @return {RegExp} The search text regexp
-   */
-  function searchTextToRegExp(string, use_wildcard_characters) {
-    if (typeof string !== 'string') {
-      throw new TypeError("jioquery.searchTextToRegExp(): " +
-                          "Argument 1 is not of type 'string'");
-    }
-    if (use_wildcard_characters === false) {
-      return new RegExp("^" + stringEscapeRegexpCharacters(string) + "$");
-    }
-    return new RegExp("^" + stringEscapeRegexpCharacters(string)
-      .replace(regexp_percent, '.*')
-      .replace(regexp_underscore, '.') + "$");
-  }
-
-  /**
-   * The ComplexQuery inherits from Query, and compares one or several metadata
-   * values.
-   *
-   * @class ComplexQuery
-   * @extends Query
-   * @param  {Object} [spec={}] The specifications
-   * @param  {String} [spec.operator="AND"] The compare method to use
-   * @param  {String} spec.key The metadata key
-   * @param  {String} spec.value The value of the metadata to compare
-   */
-  function ComplexQuery(spec, key_schema) {
-    Query.call(this);
-
-    /**
-     * Logical operator to use to compare object values
-     *
-     * @attribute operator
-     * @type String
-     * @default "AND"
-     * @optional
-     */
-    this.operator = spec.operator;
-
-    /**
-     * The sub Query list which are used to query an item.
-     *
-     * @attribute query_list
-     * @type Array
-     * @default []
-     * @optional
-     */
-    this.query_list = spec.query_list || [];
-    this.query_list = this.query_list.map(
-      // decorate the map to avoid sending the index as key_schema argument
-      function (o) { return QueryFactory.create(o, key_schema); }
-    );
-
-  }
-  inherits(ComplexQuery, Query);
-
-  ComplexQuery.prototype.operator = "AND";
-  ComplexQuery.prototype.type = "complex";
-
-  /**
-   * #crossLink "Query/match:method"
-   */
-  ComplexQuery.prototype.match = function (item) {
-    var operator = this.operator;
-    if (!(regexp_operator.test(operator))) {
-      operator = "AND";
-    }
-    return this[operator.toUpperCase()](item);
-  };
-
-  /**
-   * #crossLink "Query/toString:method"
-   */
-  ComplexQuery.prototype.toString = function () {
-    var str_list = [], this_operator = this.operator;
-    if (this.operator === "NOT") {
-      str_list.push("NOT (");
-      str_list.push(this.query_list[0].toString());
-      str_list.push(")");
-      return str_list.join(" ");
-    }
-    this.query_list.forEach(function (query) {
-      str_list.push("(");
-      str_list.push(query.toString());
-      str_list.push(")");
-      str_list.push(this_operator);
-    });
-    str_list.length -= 1;
-    return str_list.join(" ");
-  };
-
-  /**
-   * #crossLink "Query/serialized:method"
-   */
-  ComplexQuery.prototype.serialized = function () {
-    var s = {
-      "type": "complex",
-      "operator": this.operator,
-      "query_list": []
-    };
-    this.query_list.forEach(function (query) {
-      s.query_list.push(
-        typeof query.toJSON === "function" ? query.toJSON() : query
-      );
-    });
-    return s;
-  };
-  ComplexQuery.prototype.toJSON = ComplexQuery.prototype.serialized;
-
-  /**
-   * Comparison operator, test if all sub queries match the
-   * item value
-   *
-   * @method AND
-   * @param  {Object} item The item to match
-   * @return {Boolean} true if all match, false otherwise
-   */
-  ComplexQuery.prototype.AND = function (item) {
-    var result = true,
-      i = 0;
-
-    while (result && (i !== this.query_list.length)) {
-      result = this.query_list[i].match(item);
-      i += 1;
-    }
-    return result;
-
-  };
-
-  /**
-   * Comparison operator, test if one of the sub queries matches the
-   * item value
-   *
-   * @method OR
-   * @param  {Object} item The item to match
-   * @return {Boolean} true if one match, false otherwise
-   */
-  ComplexQuery.prototype.OR = function (item) {
-    var result = false,
-      i = 0;
-
-    while ((!result) && (i !== this.query_list.length)) {
-      result = this.query_list[i].match(item);
-      i += 1;
-    }
-
-    return result;
-  };
-
-  /**
-   * Comparison operator, test if the sub query does not match the
-   * item value
-   *
-   * @method NOT
-   * @param  {Object} item The item to match
-   * @return {Boolean} true if one match, false otherwise
-   */
-  ComplexQuery.prototype.NOT = function (item) {
-    return !this.query_list[0].match(item);
-  };
-
-  /**
-   * Creates Query object from a search text string or a serialized version
-   * of a Query.
-   *
-   * @method create
-   * @static
-   * @param  {Object,String} object The search text or the serialized version
-   *         of a Query
-   * @return {Query} A Query object
-   */
-  QueryFactory.create = function (object, key_schema) {
-    if (object === "") {
-      return new Query();
-    }
-    if (typeof object === "string") {
-      object = parseStringToObject(object);
-    }
-    if (typeof (object || {}).type === "string" &&
-        query_class_dict[object.type]) {
-      return new query_class_dict[object.type](object, key_schema);
-    }
-    throw new TypeError("QueryFactory.create(): " +
-                        "Argument 1 is not a search text or a parsable object");
-  };
-
-  function objectToSearchText(query) {
-    var str_list = [];
-    if (query.type === "complex") {
-      str_list.push("(");
-      (query.query_list || []).forEach(function (sub_query) {
-        str_list.push(objectToSearchText(sub_query));
-        str_list.push(query.operator);
-      });
-      str_list.length -= 1;
-      str_list.push(")");
-      return str_list.join(" ");
-    }
-    if (query.type === "simple") {
-      return (query.key ? query.key + ": " : "") +
-        (query.operator || "") + ' "' + query.value + '"';
-    }
-    throw new TypeError("This object is not a query");
-  }
-
-  function checkKeySchema(key_schema) {
-    var prop;
-
-    if (key_schema !== undefined) {
-      if (typeof key_schema !== 'object') {
-        throw new TypeError("SimpleQuery().create(): " +
-                            "key_schema is not of type 'object'");
-      }
-      // key_set is mandatory
-      if (key_schema.key_set === undefined) {
-        throw new TypeError("SimpleQuery().create(): " +
-                            "key_schema has no 'key_set' property");
-      }
-      for (prop in key_schema) {
-        if (key_schema.hasOwnProperty(prop)) {
-          switch (prop) {
-          case 'key_set':
-          case 'cast_lookup':
-          case 'match_lookup':
-            break;
-          default:
-            throw new TypeError("SimpleQuery().create(): " +
-                               "key_schema has unknown property '" + prop + "'");
-          }
-        }
-      }
-    }
-  }
-
-  /**
-   * The SimpleQuery inherits from Query, and compares one metadata value
-   *
-   * @class SimpleQuery
-   * @extends Query
-   * @param  {Object} [spec={}] The specifications
-   * @param  {String} [spec.operator="="] The compare method to use
-   * @param  {String} spec.key The metadata key
-   * @param  {String} spec.value The value of the metadata to compare
-   */
-  function SimpleQuery(spec, key_schema) {
-    Query.call(this);
-
-    checkKeySchema(key_schema);
-
-    this._key_schema = key_schema || {};
-
-    /**
-     * Operator to use to compare object values
-     *
-     * @attribute operator
-     * @type String
-     * @optional
-     */
-    this.operator = spec.operator;
-
-    /**
-     * Key of the object which refers to the value to compare
-     *
-     * @attribute key
-     * @type String
-     */
-    this.key = spec.key;
-
-    /**
-     * Value is used to do the comparison with the object value
-     *
-     * @attribute value
-     * @type String
-     */
-    this.value = spec.value;
-
-  }
-  inherits(SimpleQuery, Query);
-
-  SimpleQuery.prototype.type = "simple";
-
-  function checkKey(key) {
-    var prop;
-
-    if (key.read_from === undefined) {
-      throw new TypeError("Custom key is missing the read_from property");
-    }
-
-    for (prop in key) {
-      if (key.hasOwnProperty(prop)) {
-        switch (prop) {
-        case 'read_from':
-        case 'cast_to':
-        case 'equal_match':
-          break;
-        default:
-          throw new TypeError("Custom key has unknown property '" +
-                              prop + "'");
-        }
-      }
-    }
-  }
-
-  /**
-   * #crossLink "Query/match:method"
-   */
-  SimpleQuery.prototype.match = function (item) {
-    var object_value = null,
-      equal_match = null,
-      cast_to = null,
-      matchMethod = null,
-      operator = this.operator,
-      value = null,
-      key = this.key;
-
-    if (!(regexp_comparaison.test(operator))) {
-      // `operator` is not correct, we have to change it to "like" or "="
-      if (regexp_percent.test(this.value)) {
-        // `value` contains a non escaped `%`
-        operator = "like";
-      } else {
-        // `value` does not contain non escaped `%`
-        operator = "=";
-      }
-    }
-
-    matchMethod = this[operator];
-
-    if (this._key_schema.key_set && this._key_schema.key_set[key] !== undefined) {
-      key = this._key_schema.key_set[key];
-    }
-
-    if (typeof key === 'object') {
-      checkKey(key);
-      object_value = item[key.read_from];
-
-      equal_match = key.equal_match;
-
-      // equal_match can be a string
-      if (typeof equal_match === 'string') {
-        // XXX raise error if equal_match not in match_lookup
-        equal_match = this._key_schema.match_lookup[equal_match];
-      }
-
-      // equal_match overrides the default '=' operator
-      if (equal_match !== undefined) {
-        matchMethod = (operator === "=" || operator === "like" ?
-                       equal_match : matchMethod);
-      }
-
-      value = this.value;
-      cast_to = key.cast_to;
-      if (cast_to) {
-        // cast_to can be a string
-        if (typeof cast_to === 'string') {
-          // XXX raise error if cast_to not in cast_lookup
-          cast_to = this._key_schema.cast_lookup[cast_to];
-        }
-
-        try {
-          value = cast_to(value);
-        } catch (e) {
-          value = undefined;
-        }
-
-        try {
-          object_value = cast_to(object_value);
-        } catch (e) {
-          object_value = undefined;
-        }
-      }
-    } else {
-      object_value = item[key];
-      value = this.value;
-    }
-    if (object_value === undefined || value === undefined) {
-      return false;
-    }
-    return matchMethod(object_value, value);
-  };
-
-  /**
-   * #crossLink "Query/toString:method"
-   */
-  SimpleQuery.prototype.toString = function () {
-    return (this.key ? this.key + ":" : "") +
-      (this.operator ? " " + this.operator : "") + ' "' + this.value + '"';
-  };
-
-  /**
-   * #crossLink "Query/serialized:method"
-   */
-  SimpleQuery.prototype.serialized = function () {
-    var object = {
-      "type": "simple",
-      "key": this.key,
-      "value": this.value
-    };
-    if (this.operator !== undefined) {
-      object.operator = this.operator;
-    }
-    return object;
-  };
-  SimpleQuery.prototype.toJSON = SimpleQuery.prototype.serialized;
-
-  /**
-   * Comparison operator, test if this query value matches the item value
-   *
-   * @method =
-   * @param  {String} object_value The value to compare
-   * @param  {String} comparison_value The comparison value
-   * @return {Boolean} true if match, false otherwise
-   */
-  SimpleQuery.prototype["="] = function (object_value, comparison_value) {
-    var value, i;
-    if (!Array.isArray(object_value)) {
-      object_value = [object_value];
-    }
-    for (i = 0; i < object_value.length; i += 1) {
-      value = object_value[i];
-      if (typeof value === 'object' && value.hasOwnProperty('content')) {
-        value = value.content;
-      }
-      if (typeof value.cmp === "function") {
-        return (value.cmp(comparison_value) === 0);
-      }
-      if (comparison_value.toString() === value.toString()) {
-        return true;
-      }
-    }
-    return false;
-  };
-
-  /**
-   * Comparison operator, test if this query value matches the item value
-   *
-   * @method like
-   * @param  {String} object_value The value to compare
-   * @param  {String} comparison_value The comparison value
-   * @return {Boolean} true if match, false otherwise
-   */
-  SimpleQuery.prototype.like = function (object_value, comparison_value) {
-    var value, i;
-    if (!Array.isArray(object_value)) {
-      object_value = [object_value];
-    }
-    for (i = 0; i < object_value.length; i += 1) {
-      value = object_value[i];
-      if (typeof value === 'object' && value.hasOwnProperty('content')) {
-        value = value.content;
-      }
-      if (typeof value.cmp === "function") {
-        return (value.cmp(comparison_value) === 0);
-      }
-      if (
-        searchTextToRegExp(comparison_value.toString()).test(value.toString())
-      ) {
-        return true;
-      }
-    }
-    return false;
-  };
-
-  /**
-   * Comparison operator, test if this query value does not match the item value
-   *
-   * @method !=
-   * @param  {String} object_value The value to compare
-   * @param  {String} comparison_value The comparison value
-   * @return {Boolean} true if not match, false otherwise
-   */
-  SimpleQuery.prototype["!="] = function (object_value, comparison_value) {
-    var value, i;
-    if (!Array.isArray(object_value)) {
-      object_value = [object_value];
-    }
-    for (i = 0; i < object_value.length; i += 1) {
-      value = object_value[i];
-      if (typeof value === 'object' && value.hasOwnProperty('content')) {
-        value = value.content;
-      }
-      if (typeof value.cmp === "function") {
-        return (value.cmp(comparison_value) !== 0);
-      }
-      if (comparison_value.toString() === value.toString()) {
-        return false;
-      }
-    }
-    return true;
-  };
-
-  /**
-   * Comparison operator, test if this query value is lower than the item value
-   *
-   * @method <
-   * @param  {Number, String} object_value The value to compare
-   * @param  {Number, String} comparison_value The comparison value
-   * @return {Boolean} true if lower, false otherwise
-   */
-  SimpleQuery.prototype["<"] = function (object_value, comparison_value) {
-    var value;
-    if (!Array.isArray(object_value)) {
-      object_value = [object_value];
-    }
-    value = object_value[0];
-    if (typeof value === 'object' && value.hasOwnProperty('content')) {
-      value = value.content;
-    }
-    if (typeof value.cmp === "function") {
-      return (value.cmp(comparison_value) < 0);
-    }
-    return (value < comparison_value);
-  };
-
-  /**
-   * Comparison operator, test if this query value is equal or lower than the
-   * item value
-   *
-   * @method <=
-   * @param  {Number, String} object_value The value to compare
-   * @param  {Number, String} comparison_value The comparison value
-   * @return {Boolean} true if equal or lower, false otherwise
-   */
-  SimpleQuery.prototype["<="] = function (object_value, comparison_value) {
-    var value;
-    if (!Array.isArray(object_value)) {
-      object_value = [object_value];
-    }
-    value = object_value[0];
-    if (typeof value === 'object' && value.hasOwnProperty('content')) {
-      value = value.content;
-    }
-    if (typeof value.cmp === "function") {
-      return (value.cmp(comparison_value) <= 0);
-    }
-    return (value <= comparison_value);
-  };
-
-  /**
-   * Comparison operator, test if this query value is greater than the item
-   * value
-   *
-   * @method >
-   * @param  {Number, String} object_value The value to compare
-   * @param  {Number, String} comparison_value The comparison value
-   * @return {Boolean} true if greater, false otherwise
-   */
-  SimpleQuery.prototype[">"] = function (object_value, comparison_value) {
-    var value;
-    if (!Array.isArray(object_value)) {
-      object_value = [object_value];
-    }
-    value = object_value[0];
-    if (typeof value === 'object' && value.hasOwnProperty('content')) {
-      value = value.content;
-    }
-    if (typeof value.cmp === "function") {
-      return (value.cmp(comparison_value) > 0);
-    }
-    return (value > comparison_value);
-  };
-
-  /**
-   * Comparison operator, test if this query value is equal or greater than the
-   * item value
-   *
-   * @method >=
-   * @param  {Number, String} object_value The value to compare
-   * @param  {Number, String} comparison_value The comparison value
-   * @return {Boolean} true if equal or greater, false otherwise
-   */
-  SimpleQuery.prototype[">="] = function (object_value, comparison_value) {
-    var value;
-    if (!Array.isArray(object_value)) {
-      object_value = [object_value];
-    }
-    value = object_value[0];
-    if (typeof value === 'object' && value.hasOwnProperty('content')) {
-      value = value.content;
-    }
-    if (typeof value.cmp === "function") {
-      return (value.cmp(comparison_value) >= 0);
-    }
-    return (value >= comparison_value);
-  };
-
-  query_class_dict.simple = SimpleQuery;
-  query_class_dict.complex = ComplexQuery;
-
-  Query.parseStringToObject = parseStringToObject;
-  Query.objectToSearchText = objectToSearchText;
-
-  window.Query = Query;
-  window.SimpleQuery = SimpleQuery;
-  window.ComplexQuery = ComplexQuery;
-  window.QueryFactory = QueryFactory;
-
-}(RSVP, window, parseStringToObject));
-;/*global window, moment */
-/*jslint nomen: true, maxlen: 200*/
-(function (window, moment) {
-  "use strict";
-
-//   /**
-//    * Add a secured (write permission denied) property to an object.
-//    *
-//    * @param  {Object} object The object to fill
-//    * @param  {String} key The object key where to store the property
-//    * @param  {Any} value The value to store
-//    */
-//   function _export(key, value) {
-//     Object.defineProperty(to_export, key, {
-//       "configurable": false,
-//       "enumerable": true,
-//       "writable": false,
-//       "value": value
-//     });
-//   }
-
-  var YEAR = 'year',
-    MONTH = 'month',
-    DAY = 'day',
-    HOUR = 'hour',
-    MIN = 'minute',
-    SEC = 'second',
-    MSEC = 'millisecond',
-    precision_grade = {
-      'year': 0,
-      'month': 1,
-      'day': 2,
-      'hour': 3,
-      'minute': 4,
-      'second': 5,
-      'millisecond': 6
-    },
-    lesserPrecision = function (p1, p2) {
-      return (precision_grade[p1] < precision_grade[p2]) ? p1 : p2;
-    },
-    JIODate;
-
-
-  JIODate = function (str) {
-    // in case of forgotten 'new'
-    if (!(this instanceof JIODate)) {
-      return new JIODate(str);
-    }
-
-    if (str instanceof JIODate) {
-      this.mom = str.mom.clone();
-      this._precision = str._precision;
-      return;
-    }
-
-    if (str === undefined) {
-      this.mom = moment();
-      this.setPrecision(MSEC);
-      return;
-    }
-
-    this.mom = null;
-    this._str = str;
-
-    // http://www.w3.org/TR/NOTE-datetime
-    // http://dotat.at/tmp/ISO_8601-2004_E.pdf
-
-    // XXX these regexps fail to detect many invalid dates.
-
-    if (str.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+\-][0-2]\d:[0-5]\d|Z)/)
-          || str.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d/)) {
-      // ISO, milliseconds
-      this.mom = moment(str);
-      this.setPrecision(MSEC);
-    } else if (str.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)
-          || str.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/)) {
-      // ISO, seconds
-      this.mom = moment(str);
-      this.setPrecision(SEC);
-    } else if (str.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)
-          || str.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d/)) {
-      // ISO, minutes
-      this.mom = moment(str);
-      this.setPrecision(MIN);
-    } else if (str.match(/\d\d\d\d-\d\d-\d\d \d\d/)) {
-      this.mom = moment(str);
-      this.setPrecision(HOUR);
-    } else if (str.match(/\d\d\d\d-\d\d-\d\d/)) {
-      this.mom = moment(str);
-      this.setPrecision(DAY);
-    } else if (str.match(/\d\d\d\d-\d\d/)) {
-      this.mom = moment(str);
-      this.setPrecision(MONTH);
-    } else if (str.match(/\d\d\d\d/)) {
-      // Creating a moment with only the year will show this deprecation
-      // warning:
-      //
-      // Deprecation warning: moment construction falls back to js Date. This is
-      // discouraged and will be removed in upcoming major release. Please refer
-      // to https://github.com/moment/moment/issues/1407 for more info.
-      //
-      // TL;DR: parsing year-only strings with momentjs falls back to native
-      // Date and it won't correctly represent the year in local time if UTF
-      // offset is negative.
-      //
-      // The solution is to use the format parameter, so momentjs won't fall
-      // back to the native Date and we will have the correct year in local
-      // time.
-      //
-      this.mom = moment(str, 'YYYY');
-      this.setPrecision(YEAR);
-    }
-
-    if (!this.mom) {
-      throw new Error("Cannot parse: " + str);
-    }
-
-  };
-
-
-  JIODate.prototype.setPrecision = function (prec) {
-    this._precision = prec;
-  };
-
-
-  JIODate.prototype.getPrecision = function () {
-    return this._precision;
-  };
-
-
-  JIODate.prototype.cmp = function (other) {
-    var m1 = this.mom,
-      m2 = other.mom,
-      p = lesserPrecision(this._precision, other._precision);
-    return m1.isBefore(m2, p) ? -1 : (m1.isSame(m2, p) ? 0 : +1);
-  };
-
-
-  JIODate.prototype.toPrecisionString = function (precision) {
-    var fmt;
-
-    precision = precision || this._precision;
-
-    fmt = {
-      'millisecond': 'YYYY-MM-DD HH:mm:ss.SSS',
-      'second': 'YYYY-MM-DD HH:mm:ss',
-      'minute': 'YYYY-MM-DD HH:mm',
-      'hour': 'YYYY-MM-DD HH',
-      'day': 'YYYY-MM-DD',
-      'month': 'YYYY-MM',
-      'year': 'YYYY'
-    }[precision];
-
-    if (!fmt) {
-      throw new TypeError("Unsupported precision value '" + precision + "'");
-    }
-
-    return this.mom.format(fmt);
-  };
-
-
-  JIODate.prototype.toString = function () {
-    return this._str;
-  };
-
-
-//   _export('JIODate', JIODate);
-// 
-//   _export('YEAR', YEAR);
-//   _export('MONTH', MONTH);
-//   _export('DAY', DAY);
-//   _export('HOUR', HOUR);
-//   _export('MIN', MIN);
-//   _export('SEC', SEC);
-//   _export('MSEC', MSEC);
-
-  window.jiodate = {
-    JIODate: JIODate,
-    YEAR: YEAR,
-    MONTH: MONTH,
-    DAY: DAY,
-    HOUR: HOUR,
-    MIN: MIN,
-    SEC: SEC,
-    MSEC: MSEC
-  };
-}(window, moment));
-;/*global window, RSVP, Blob, XMLHttpRequest, QueryFactory, Query, atob,
-  FileReader, ArrayBuffer, Uint8Array, navigator */
-(function (window, RSVP, Blob, QueryFactory, Query, atob,
-           FileReader, ArrayBuffer, Uint8Array, navigator) {
-  "use strict";
-
-  if (window.openDatabase === undefined) {
-    window.openDatabase = function () {
-      throw new Error('WebSQL is not supported by ' + navigator.userAgent);
-    };
-  }
-
-  var util = {},
-    jIO;
-
-  function jIOError(message, status_code) {
-    if ((message !== undefined) && (typeof message !== "string")) {
-      throw new TypeError('You must pass a string.');
-    }
-    this.message = message || "Default Message";
-    this.status_code = status_code || 500;
-  }
-  jIOError.prototype = new Error();
-  jIOError.prototype.constructor = jIOError;
-  util.jIOError = jIOError;
-
-  /**
-   * Send request with XHR and return a promise. xhr.onload: The promise is
-   * resolved when the status code is lower than 400 with the xhr object as
-   * first parameter. xhr.onerror: reject with xhr object as first
-   * parameter. xhr.onprogress: notifies the xhr object.
-   *
-   * @param  {Object} param The parameters
-   * @param  {String} [param.type="GET"] The request method
-   * @param  {String} [param.dataType=""] The data type to retrieve
-   * @param  {String} param.url The url
-   * @param  {Any} [param.data] The data to send
-   * @param  {Function} [param.beforeSend] A function called just before the
-   *    send request. The first parameter of this function is the XHR object.
-   * @return {Promise} The promise
-   */
-  function ajax(param) {
-    var xhr = new XMLHttpRequest();
-    return new RSVP.Promise(function (resolve, reject, notify) {
-      var k;
-      xhr.open(param.type || "GET", param.url, true);
-      xhr.responseType = param.dataType || "";
-      if (typeof param.headers === 'object' && param.headers !== null) {
-        for (k in param.headers) {
-          if (param.headers.hasOwnProperty(k)) {
-            xhr.setRequestHeader(k, param.headers[k]);
-          }
-        }
-      }
-      xhr.addEventListener("load", function (e) {
-        if (e.target.status >= 400) {
-          return reject(e);
-        }
-        resolve(e);
-      });
-      xhr.addEventListener("error", reject);
-      xhr.addEventListener("progress", notify);
-      if (typeof param.xhrFields === 'object' && param.xhrFields !== null) {
-        for (k in param.xhrFields) {
-          if (param.xhrFields.hasOwnProperty(k)) {
-            xhr[k] = param.xhrFields[k];
-          }
-        }
-      }
-      if (typeof param.beforeSend === 'function') {
-        param.beforeSend(xhr);
-      }
-      xhr.send(param.data);
-    }, function () {
-      xhr.abort();
-    });
-  }
-  util.ajax = ajax;
-
-  function readBlobAsText(blob, encoding) {
-    var fr = new FileReader();
-    return new RSVP.Promise(function (resolve, reject, notify) {
-      fr.addEventListener("load", resolve);
-      fr.addEventListener("error", reject);
-      fr.addEventListener("progress", notify);
-      fr.readAsText(blob, encoding);
-    }, function () {
-      fr.abort();
-    });
-  }
-  util.readBlobAsText = readBlobAsText;
-
-  function readBlobAsArrayBuffer(blob) {
-    var fr = new FileReader();
-    return new RSVP.Promise(function (resolve, reject, notify) {
-      fr.addEventListener("load", resolve);
-      fr.addEventListener("error", reject);
-      fr.addEventListener("progress", notify);
-      fr.readAsArrayBuffer(blob);
-    }, function () {
-      fr.abort();
-    });
-  }
-  util.readBlobAsArrayBuffer = readBlobAsArrayBuffer;
-
-  function readBlobAsDataURL(blob) {
-    var fr = new FileReader();
-    return new RSVP.Promise(function (resolve, reject, notify) {
-      fr.addEventListener("load", resolve);
-      fr.addEventListener("error", reject);
-      fr.addEventListener("progress", notify);
-      fr.readAsDataURL(blob);
-    }, function () {
-      fr.abort();
-    });
-  }
-  util.readBlobAsDataURL = readBlobAsDataURL;
-
-  function stringify(obj) {
-    // Implement a stable JSON.stringify
-    // Object's keys are alphabetically ordered
-    var key,
-      key_list,
-      i,
-      value,
-      result_list;
-    if (obj === undefined) {
-      return undefined;
-    }
-    if (obj.constructor === Object) {
-      key_list = Object.keys(obj).sort();
-      result_list = [];
-      for (i = 0; i < key_list.length; i += 1) {
-        key = key_list[i];
-        value = stringify(obj[key]);
-        if (value !== undefined) {
-          result_list.push(stringify(key) + ':' + value);
-        }
-      }
-      return '{' + result_list.join(',') + '}';
-    }
-    if (obj.constructor === Array) {
-      result_list = [];
-      for (i = 0; i < obj.length; i += 1) {
-        result_list.push(stringify(obj[i]));
-      }
-      return '[' + result_list.join(',') + ']';
-    }
-    return JSON.stringify(obj);
-  }
-  util.stringify = stringify;
-
-
-  // https://gist.github.com/davoclavo/4424731
-  function dataURItoBlob(dataURI) {
-    if (dataURI === 'data:') {
-      return new Blob();
-    }
-    // convert base64 to raw binary data held in a string
-    var byteString = atob(dataURI.split(',')[1]),
-    // separate out the mime component
-      mimeString = dataURI.split(',')[0].split(':')[1],
-    // write the bytes of the string to an ArrayBuffer
-      arrayBuffer = new ArrayBuffer(byteString.length),
-      _ia = new Uint8Array(arrayBuffer),
-      i;
-    mimeString = mimeString.slice(0, mimeString.length - ";base64".length);
-    for (i = 0; i < byteString.length; i += 1) {
-      _ia[i] = byteString.charCodeAt(i);
-    }
-    return new Blob([arrayBuffer], {type: mimeString});
-  }
-
-  util.dataURItoBlob = dataURItoBlob;
-
-  // tools
-  function checkId(argument_list, storage, method_name) {
-    if (typeof argument_list[0] !== 'string' || argument_list[0] === '') {
-      throw new jIO.util.jIOError(
-        "Document id must be a non empty string on '" + storage.__type +
-          "." + method_name + "'.",
-        400
-      );
-    }
-  }
-
-  function checkAttachmentId(argument_list, storage, method_name) {
-    if (typeof argument_list[1] !== 'string' || argument_list[1] === '') {
-      throw new jIO.util.jIOError(
-        "Attachment id must be a non empty string on '" + storage.__type +
-          "." + method_name + "'.",
-        400
-      );
-    }
-  }
-
-  function declareMethod(klass, name, precondition_function, post_function) {
-    klass.prototype[name] = function () {
-      var argument_list = arguments,
-        context = this,
-        precondition_result;
-
-      return new RSVP.Queue()
-        .push(function () {
-          if (precondition_function !== undefined) {
-            return precondition_function.apply(
-              context.__storage,
-              [argument_list, context, name]
-            );
-          }
-        })
-        .push(function (result) {
-          var storage_method = context.__storage[name];
-          precondition_result = result;
-          if (storage_method === undefined) {
-            throw new jIO.util.jIOError(
-              "Capacity '" + name + "' is not implemented on '" +
-                context.__type + "'",
-              501
-            );
-          }
-          return storage_method.apply(
-            context.__storage,
-            argument_list
-          );
-        })
-        .push(function (result) {
-          if (post_function !== undefined) {
-            return post_function.call(
-              context,
-              argument_list,
-              result,
-              precondition_result
-            );
-          }
-          return result;
-        });
-    };
-    // Allow chain
-    return this;
-  }
-
-
-
-
-  /////////////////////////////////////////////////////////////////
-  // jIO Storage Proxy
-  /////////////////////////////////////////////////////////////////
-  function JioProxyStorage(type, storage) {
-    if (!(this instanceof JioProxyStorage)) {
-      return new JioProxyStorage();
-    }
-    this.__type = type;
-    this.__storage = storage;
-  }
-
-  declareMethod(JioProxyStorage, "put", checkId, function (argument_list) {
-    return argument_list[0];
-  });
-  declareMethod(JioProxyStorage, "get", checkId);
-  declareMethod(JioProxyStorage, "bulk");
-  declareMethod(JioProxyStorage, "remove", checkId, function (argument_list) {
-    return argument_list[0];
-  });
-
-  JioProxyStorage.prototype.post = function () {
-    var context = this,
-      argument_list = arguments;
-    return new RSVP.Queue()
-      .push(function () {
-        var storage_method = context.__storage.post;
-        if (storage_method === undefined) {
-          throw new jIO.util.jIOError(
-            "Capacity 'post' is not implemented on '" + context.__type + "'",
-            501
-          );
-        }
-        return context.__storage.post.apply(context.__storage, argument_list);
-      });
-  };
-
-  declareMethod(JioProxyStorage, 'putAttachment', function (argument_list,
-                                                            storage,
-                                                            method_name) {
-    checkId(argument_list, storage, method_name);
-    checkAttachmentId(argument_list, storage, method_name);
-
-    var options = argument_list[3] || {};
-
-    if (typeof argument_list[2] === 'string') {
-      argument_list[2] = new Blob([argument_list[2]], {
-        "type": options._content_type || options._mimetype ||
-                "text/plain;charset=utf-8"
-      });
-    } else if (!(argument_list[2] instanceof Blob)) {
-      throw new jIO.util.jIOError(
-        'Attachment content is not a blob',
-        400
-      );
-    }
-  });
-
-  declareMethod(JioProxyStorage, 'removeAttachment', function (argument_list,
-                                                               storage,
-                                                               method_name) {
-    checkId(argument_list, storage, method_name);
-    checkAttachmentId(argument_list, storage, method_name);
-  });
-
-  declareMethod(JioProxyStorage, 'getAttachment', function (argument_list,
-                                                            storage,
-                                                            method_name) {
-    var result = "blob";
-//     if (param.storage_spec.type !== "indexeddb" &&
-//         param.storage_spec.type !== "dav" &&
-//         (param.kwargs._start !== undefined
-//          || param.kwargs._end !== undefined)) {
-//       restCommandRejecter(param, [
-//         'bad_request',
-//         'unsupport',
-//         '_start, _end not support'
-//       ]);
-//       return false;
-//     }
-    checkId(argument_list, storage, method_name);
-    checkAttachmentId(argument_list, storage, method_name);
-    // Drop optional parameters, which are only used in postfunction
-    if (argument_list[2] !== undefined) {
-      result = argument_list[2].format || result;
-      delete argument_list[2].format;
-    }
-    return result;
-  }, function (argument_list, blob, convert) {
-    var result;
-    if (!(blob instanceof Blob)) {
-      throw new jIO.util.jIOError(
-        "'getAttachment' (" + argument_list[0] + " , " +
-          argument_list[1] + ") on '" + this.__type +
-          "' does not return a Blob.",
-        501
-      );
-    }
-    if (convert === "blob") {
-      result = blob;
-    } else if (convert === "data_url") {
-      result = new RSVP.Queue()
-        .push(function () {
-          return jIO.util.readBlobAsDataURL(blob);
-        })
-        .push(function (evt) {
-          return evt.target.result;
-        });
-    } else if (convert === "array_buffer") {
-      result = new RSVP.Queue()
-        .push(function () {
-          return jIO.util.readBlobAsArrayBuffer(blob);
-        })
-        .push(function (evt) {
-          return evt.target.result;
-        });
-    } else if (convert === "text") {
-      result = new RSVP.Queue()
-        .push(function () {
-          return jIO.util.readBlobAsText(blob);
-        })
-        .push(function (evt) {
-          return evt.target.result;
-        });
-    } else if (convert === "json") {
-      result = new RSVP.Queue()
-        .push(function () {
-          return jIO.util.readBlobAsText(blob);
-        })
-        .push(function (evt) {
-          return JSON.parse(evt.target.result);
-        });
-    } else {
-      throw new jIO.util.jIOError(
-        this.__type + ".getAttachment format: '" + convert +
-          "' is not supported",
-        400
-      );
-    }
-    return result;
-  });
-
-  JioProxyStorage.prototype.buildQuery = function () {
-    var storage_method = this.__storage.buildQuery,
-      context = this,
-      argument_list = arguments;
-    if (storage_method === undefined) {
-      throw new jIO.util.jIOError(
-        "Capacity 'buildQuery' is not implemented on '" + this.__type + "'",
-        501
-      );
-    }
-    return new RSVP.Queue()
-      .push(function () {
-        return storage_method.apply(
-          context.__storage,
-          argument_list
-        );
-      });
-  };
-
-  JioProxyStorage.prototype.hasCapacity = function (name) {
-    var storage_method = this.__storage.hasCapacity,
-      capacity_method = this.__storage[name];
-    if (capacity_method !== undefined) {
-      return true;
-    }
-    if ((storage_method === undefined) ||
-        !storage_method.apply(this.__storage, arguments)) {
-      throw new jIO.util.jIOError(
-        "Capacity '" + name + "' is not implemented on '" + this.__type + "'",
-        501
-      );
-    }
-    return true;
-  };
-
-  JioProxyStorage.prototype.allDocs = function (options) {
-    var context = this;
-    if (options === undefined) {
-      options = {};
-    }
-    return new RSVP.Queue()
-      .push(function () {
-        if (context.hasCapacity("list") &&
-            ((options.query === undefined) || context.hasCapacity("query")) &&
-            ((options.sort_on === undefined) || context.hasCapacity("sort")) &&
-            ((options.select_list === undefined) ||
-             context.hasCapacity("select")) &&
-            ((options.include_docs === undefined) ||
-             context.hasCapacity("include")) &&
-            ((options.limit === undefined) || context.hasCapacity("limit"))) {
-          return context.buildQuery(options);
-        }
-      })
-      .push(function (result) {
-        return {
-          data: {
-            rows: result,
-            total_rows: result.length
-          }
-        };
-      });
-  };
-
-  declareMethod(JioProxyStorage, "allAttachments", checkId);
-  declareMethod(JioProxyStorage, "repair");
-
-  JioProxyStorage.prototype.repair = function () {
-    var context = this,
-      argument_list = arguments;
-    return new RSVP.Queue()
-      .push(function () {
-        var storage_method = context.__storage.repair;
-        if (storage_method !== undefined) {
-          return context.__storage.repair.apply(context.__storage,
-                                                argument_list);
-        }
-      });
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // Storage builder
-  /////////////////////////////////////////////////////////////////
-  function JioBuilder() {
-    if (!(this instanceof JioBuilder)) {
-      return new JioBuilder();
-    }
-    this.__storage_types = {};
-  }
-
-  JioBuilder.prototype.createJIO = function (storage_spec, util) {
-
-    if (typeof storage_spec.type !== 'string') {
-      throw new TypeError("Invalid storage description");
-    }
-    if (!this.__storage_types[storage_spec.type]) {
-      throw new TypeError("Unknown storage '" + storage_spec.type + "'");
-    }
-
-    return new JioProxyStorage(
-      storage_spec.type,
-      new this.__storage_types[storage_spec.type](storage_spec, util)
-    );
-
-  };
-
-  JioBuilder.prototype.addStorage = function (type, Constructor) {
-    if (typeof type !== 'string') {
-      throw new TypeError(
-        "jIO.addStorage(): Argument 1 is not of type 'string'"
-      );
-    }
-    if (typeof Constructor !== 'function') {
-      throw new TypeError("jIO.addStorage(): " +
-                          "Argument 2 is not of type 'function'");
-    }
-    if (this.__storage_types[type] !== undefined) {
-      throw new TypeError("jIO.addStorage(): Storage type already exists");
-    }
-    this.__storage_types[type] = Constructor;
-  };
-
-  JioBuilder.prototype.util = util;
-  JioBuilder.prototype.QueryFactory = QueryFactory;
-  JioBuilder.prototype.Query = Query;
-
-  /////////////////////////////////////////////////////////////////
-  // global
-  /////////////////////////////////////////////////////////////////
-  jIO = new JioBuilder();
-  window.jIO = jIO;
-
-}(window, RSVP, Blob, QueryFactory, Query, atob,
-  FileReader, ArrayBuffer, Uint8Array, navigator));
-;/*
- * Rusha, a JavaScript implementation of the Secure Hash Algorithm, SHA-1,
- * as defined in FIPS PUB 180-1, tuned for high performance with large inputs.
- * (http://github.com/srijs/rusha)
- *
- * Inspired by Paul Johnstons implementation (http://pajhome.org.uk/crypt/md5).
- *
- * Copyright (c) 2013 Sam Rijs (http://awesam.de).
- * Released under the terms of the MIT license as follows:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-(function () {
-    // If we'e running in Node.JS, export a module.
-    if (typeof module !== 'undefined') {
-        module.exports = Rusha;
-    } else if (typeof window !== 'undefined') {
-        window.Rusha = Rusha;
-    }
-    // If we're running in a webworker, accept
-    // messages containing a jobid and a buffer
-    // or blob object, and return the hash result.
-    if (typeof FileReaderSync !== 'undefined') {
-        var reader = new FileReaderSync(), hasher = new Rusha(4 * 1024 * 1024);
-        self.onmessage = function onMessage(event) {
-            var hash, data = event.data.data;
-            try {
-                hash = hasher.digest(data);
-                self.postMessage({
-                    id: event.data.id,
-                    hash: hash
-                });
-            } catch (e) {
-                self.postMessage({
-                    id: event.data.id,
-                    error: e.name
-                });
-            }
-        };
-    }
-    var util = {
-            getDataType: function (data) {
-                if (typeof data === 'string') {
-                    return 'string';
-                }
-                if (data instanceof Array) {
-                    return 'array';
-                }
-                if (typeof global !== 'undefined' && global.Buffer && global.Buffer.isBuffer(data)) {
-                    return 'buffer';
-                }
-                if (data instanceof ArrayBuffer) {
-                    return 'arraybuffer';
-                }
-                if (data.buffer instanceof ArrayBuffer) {
-                    return 'view';
-                }
-                if (data instanceof Blob) {
-                    return 'blob';
-                }
-                throw new Error('Unsupported data type.');
-            }
-        };
-    // The Rusha object is a wrapper around the low-level RushaCore.
-    // It provides means of converting different inputs to the
-    // format accepted by RushaCore as well as other utility methods.
-    function Rusha(chunkSize) {
-        'use strict';
-        // Private object structure.
-        var self$2 = { fill: 0 };
-        // Calculate the length of buffer that the sha1 routine uses
-        // including the padding.
-        var padlen = function (len) {
-            for (len += 9; len % 64 > 0; len += 1);
-            return len;
-        };
-        var padZeroes = function (bin, len) {
-            for (var i = len >> 2; i < bin.length; i++)
-                bin[i] = 0;
-        };
-        var padData = function (bin, chunkLen, msgLen) {
-            bin[chunkLen >> 2] |= 128 << 24 - (chunkLen % 4 << 3);
-            bin[((chunkLen >> 2) + 2 & ~15) + 14] = msgLen >> 29;
-            bin[((chunkLen >> 2) + 2 & ~15) + 15] = msgLen << 3;
-        };
-        // Convert a binary string and write it to the heap.
-        // A binary string is expected to only contain char codes < 256.
-        var convStr = function (H8, H32, start, len, off) {
-            var str = this, i, om = off % 4, lm = len % 4, j = len - lm;
-            if (j > 0) {
-                switch (om) {
-                case 0:
-                    H8[off + 3 | 0] = str.charCodeAt(start);
-                case 1:
-                    H8[off + 2 | 0] = str.charCodeAt(start + 1);
-                case 2:
-                    H8[off + 1 | 0] = str.charCodeAt(start + 2);
-                case 3:
-                    H8[off | 0] = str.charCodeAt(start + 3);
-                }
-            }
-            for (i = om; i < j; i = i + 4 | 0) {
-                H32[off + i >> 2] = str.charCodeAt(start + i) << 24 | str.charCodeAt(start + i + 1) << 16 | str.charCodeAt(start + i + 2) << 8 | str.charCodeAt(start + i + 3);
-            }
-            switch (lm) {
-            case 3:
-                H8[off + j + 1 | 0] = str.charCodeAt(start + j + 2);
-            case 2:
-                H8[off + j + 2 | 0] = str.charCodeAt(start + j + 1);
-            case 1:
-                H8[off + j + 3 | 0] = str.charCodeAt(start + j);
-            }
-        };
-        // Convert a buffer or array and write it to the heap.
-        // The buffer or array is expected to only contain elements < 256.
-        var convBuf = function (H8, H32, start, len, off) {
-            var buf = this, i, om = off % 4, lm = len % 4, j = len - lm;
-            if (j > 0) {
-                switch (om) {
-                case 0:
-                    H8[off + 3 | 0] = buf[start];
-                case 1:
-                    H8[off + 2 | 0] = buf[start + 1];
-                case 2:
-                    H8[off + 1 | 0] = buf[start + 2];
-                case 3:
-                    H8[off | 0] = buf[start + 3];
-                }
-            }
-            for (i = 4 - om; i < j; i = i += 4 | 0) {
-                H32[off + i >> 2] = buf[start + i] << 24 | buf[start + i + 1] << 16 | buf[start + i + 2] << 8 | buf[start + i + 3];
-            }
-            switch (lm) {
-            case 3:
-                H8[off + j + 1 | 0] = buf[start + j + 2];
-            case 2:
-                H8[off + j + 2 | 0] = buf[start + j + 1];
-            case 1:
-                H8[off + j + 3 | 0] = buf[start + j];
-            }
-        };
-        var convBlob = function (H8, H32, start, len, off) {
-            var blob = this, i, om = off % 4, lm = len % 4, j = len - lm;
-            var buf = new Uint8Array(reader.readAsArrayBuffer(blob.slice(start, start + len)));
-            if (j > 0) {
-                switch (om) {
-                case 0:
-                    H8[off + 3 | 0] = buf[0];
-                case 1:
-                    H8[off + 2 | 0] = buf[1];
-                case 2:
-                    H8[off + 1 | 0] = buf[2];
-                case 3:
-                    H8[off | 0] = buf[3];
-                }
-            }
-            for (i = 4 - om; i < j; i = i += 4 | 0) {
-                H32[off + i >> 2] = buf[i] << 24 | buf[i + 1] << 16 | buf[i + 2] << 8 | buf[i + 3];
-            }
-            switch (lm) {
-            case 3:
-                H8[off + j + 1 | 0] = buf[j + 2];
-            case 2:
-                H8[off + j + 2 | 0] = buf[j + 1];
-            case 1:
-                H8[off + j + 3 | 0] = buf[j];
-            }
-        };
-        var convFn = function (data) {
-            switch (util.getDataType(data)) {
-            case 'string':
-                return convStr.bind(data);
-            case 'array':
-                return convBuf.bind(data);
-            case 'buffer':
-                return convBuf.bind(data);
-            case 'arraybuffer':
-                return convBuf.bind(new Uint8Array(data));
-            case 'view':
-                return convBuf.bind(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
-            case 'blob':
-                return convBlob.bind(data);
-            }
-        };
-        var slice = function (data, offset) {
-            switch (util.getDataType(data)) {
-            case 'string':
-                return data.slice(offset);
-            case 'array':
-                return data.slice(offset);
-            case 'buffer':
-                return data.slice(offset);
-            case 'arraybuffer':
-                return data.slice(offset);
-            case 'view':
-                return data.buffer.slice(offset);
-            }
-        };
-        // Convert an ArrayBuffer into its hexadecimal string representation.
-        var hex = function (arrayBuffer) {
-            var i, x, hex_tab = '0123456789abcdef', res = [], binarray = new Uint8Array(arrayBuffer);
-            for (i = 0; i < binarray.length; i++) {
-                x = binarray[i];
-                res[i] = hex_tab.charAt(x >> 4 & 15) + hex_tab.charAt(x >> 0 & 15);
-            }
-            return res.join('');
-        };
-        var ceilHeapSize = function (v) {
-            // The asm.js spec says:
-            // The heap object's byteLength must be either
-            // 2^n for n in [12, 24) or 2^24 * n for n ≥ 1.
-            // Also, byteLengths smaller than 2^16 are deprecated.
-            var p;
-            // If v is smaller than 2^16, the smallest possible solution
-            // is 2^16.
-            if (v <= 65536)
-                return 65536;
-            // If v < 2^24, we round up to 2^n,
-            // otherwise we round up to 2^24 * n.
-            if (v < 16777216) {
-                for (p = 1; p < v; p = p << 1);
-            } else {
-                for (p = 16777216; p < v; p += 16777216);
-            }
-            return p;
-        };
-        // Initialize the internal data structures to a new capacity.
-        var init = function (size) {
-            if (size % 64 > 0) {
-                throw new Error('Chunk size must be a multiple of 128 bit');
-            }
-            self$2.maxChunkLen = size;
-            self$2.padMaxChunkLen = padlen(size);
-            // The size of the heap is the sum of:
-            // 1. The padded input message size
-            // 2. The extended space the algorithm needs (320 byte)
-            // 3. The 160 bit state the algoritm uses
-            self$2.heap = new ArrayBuffer(ceilHeapSize(self$2.padMaxChunkLen + 320 + 20));
-            self$2.h32 = new Int32Array(self$2.heap);
-            self$2.h8 = new Int8Array(self$2.heap);
-            self$2.core = RushaCore({
-                Int32Array: Int32Array,
-                DataView: DataView
-            }, {}, self$2.heap);
-            self$2.buffer = null;
-        };
-        // Iinitializethe datastructures according
-        // to a chunk siyze.
-        init(chunkSize || 64 * 1024);
-        var initState = function (heap, padMsgLen) {
-            var io = new Int32Array(heap, padMsgLen + 320, 5);
-            io[0] = 1732584193;
-            io[1] = -271733879;
-            io[2] = -1732584194;
-            io[3] = 271733878;
-            io[4] = -1009589776;
-        };
-        var padChunk = function (chunkLen, msgLen) {
-            var padChunkLen = padlen(chunkLen);
-            var view = new Int32Array(self$2.heap, 0, padChunkLen >> 2);
-            padZeroes(view, chunkLen);
-            padData(view, chunkLen, msgLen);
-            return padChunkLen;
-        };
-        // Write data to the heap.
-        var write = function (data, chunkOffset, chunkLen) {
-            convFn(data)(self$2.h8, self$2.h32, chunkOffset, chunkLen, 0);
-        };
-        // Initialize and call the RushaCore,
-        // assuming an input buffer of length len * 4.
-        var coreCall = function (data, chunkOffset, chunkLen, msgLen, finalize) {
-            var padChunkLen = chunkLen;
-            if (finalize) {
-                padChunkLen = padChunk(chunkLen, msgLen);
-            }
-            write(data, chunkOffset, chunkLen);
-            self$2.core.hash(padChunkLen, self$2.padMaxChunkLen);
-        };
-        var getRawDigest = function (heap, padMaxChunkLen) {
-            var io = new Int32Array(heap, padMaxChunkLen + 320, 5);
-            var out = new Int32Array(5);
-            var arr = new DataView(out.buffer);
-            arr.setInt32(0, io[0], false);
-            arr.setInt32(4, io[1], false);
-            arr.setInt32(8, io[2], false);
-            arr.setInt32(12, io[3], false);
-            arr.setInt32(16, io[4], false);
-            return out;
-        };
-        // Calculate the hash digest as an array of 5 32bit integers.
-        var rawDigest = this.rawDigest = function (str) {
-                var msgLen = str.byteLength || str.length || str.size || 0;
-                initState(self$2.heap, self$2.padMaxChunkLen);
-                var chunkOffset = 0, chunkLen = self$2.maxChunkLen, last;
-                for (chunkOffset = 0; msgLen > chunkOffset + chunkLen; chunkOffset += chunkLen) {
-                    coreCall(str, chunkOffset, chunkLen, msgLen, false);
-                }
-                coreCall(str, chunkOffset, msgLen - chunkOffset, msgLen, true);
-                return getRawDigest(self$2.heap, self$2.padMaxChunkLen);
-            };
-        // The digest and digestFrom* interface returns the hash digest
-        // as a hex string.
-        this.digest = this.digestFromString = this.digestFromBuffer = this.digestFromArrayBuffer = function (str) {
-            return hex(rawDigest(str).buffer);
-        };
-    }
-    ;
-    // The low-level RushCore module provides the heart of Rusha,
-    // a high-speed sha1 implementation working on an Int32Array heap.
-    // At first glance, the implementation seems complicated, however
-    // with the SHA1 spec at hand, it is obvious this almost a textbook
-    // implementation that has a few functions hand-inlined and a few loops
-    // hand-unrolled.
-    function RushaCore(stdlib, foreign, heap) {
-        'use asm';
-        var H = new stdlib.Int32Array(heap);
-        function hash(k, x) {
-            // k in bytes
-            k = k | 0;
-            x = x | 0;
-            var i = 0, j = 0, y0 = 0, z0 = 0, y1 = 0, z1 = 0, y2 = 0, z2 = 0, y3 = 0, z3 = 0, y4 = 0, z4 = 0, t0 = 0, t1 = 0;
-            y0 = H[x + 320 >> 2] | 0;
-            y1 = H[x + 324 >> 2] | 0;
-            y2 = H[x + 328 >> 2] | 0;
-            y3 = H[x + 332 >> 2] | 0;
-            y4 = H[x + 336 >> 2] | 0;
-            for (i = 0; (i | 0) < (k | 0); i = i + 64 | 0) {
-                z0 = y0;
-                z1 = y1;
-                z2 = y2;
-                z3 = y3;
-                z4 = y4;
-                for (j = 0; (j | 0) < 64; j = j + 4 | 0) {
-                    t1 = H[i + j >> 2] | 0;
-                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + ((t1 + y4 | 0) + 1518500249 | 0) | 0;
-                    y4 = y3;
-                    y3 = y2;
-                    y2 = y1 << 30 | y1 >>> 2;
-                    y1 = y0;
-                    y0 = t0;
-                    ;
-                    H[k + j >> 2] = t1;
-                }
-                for (j = k + 64 | 0; (j | 0) < (k + 80 | 0); j = j + 4 | 0) {
-                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
-                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + ((t1 + y4 | 0) + 1518500249 | 0) | 0;
-                    y4 = y3;
-                    y3 = y2;
-                    y2 = y1 << 30 | y1 >>> 2;
-                    y1 = y0;
-                    y0 = t0;
-                    ;
-                    H[j >> 2] = t1;
-                }
-                for (j = k + 80 | 0; (j | 0) < (k + 160 | 0); j = j + 4 | 0) {
-                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
-                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y4 | 0) + 1859775393 | 0) | 0;
-                    y4 = y3;
-                    y3 = y2;
-                    y2 = y1 << 30 | y1 >>> 2;
-                    y1 = y0;
-                    y0 = t0;
-                    ;
-                    H[j >> 2] = t1;
-                }
-                for (j = k + 160 | 0; (j | 0) < (k + 240 | 0); j = j + 4 | 0) {
-                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
-                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | y1 & y3 | y2 & y3) | 0) + ((t1 + y4 | 0) - 1894007588 | 0) | 0;
-                    y4 = y3;
-                    y3 = y2;
-                    y2 = y1 << 30 | y1 >>> 2;
-                    y1 = y0;
-                    y0 = t0;
-                    ;
-                    H[j >> 2] = t1;
-                }
-                for (j = k + 240 | 0; (j | 0) < (k + 320 | 0); j = j + 4 | 0) {
-                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
-                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y4 | 0) - 899497514 | 0) | 0;
-                    y4 = y3;
-                    y3 = y2;
-                    y2 = y1 << 30 | y1 >>> 2;
-                    y1 = y0;
-                    y0 = t0;
-                    ;
-                    H[j >> 2] = t1;
-                }
-                y0 = y0 + z0 | 0;
-                y1 = y1 + z1 | 0;
-                y2 = y2 + z2 | 0;
-                y3 = y3 + z3 | 0;
-                y4 = y4 + z4 | 0;
-            }
-            H[x + 320 >> 2] = y0;
-            H[x + 324 >> 2] = y1;
-            H[x + 328 >> 2] = y2;
-            H[x + 332 >> 2] = y3;
-            H[x + 336 >> 2] = y4;
-        }
-        return { hash: hash };
-    }
-}());;/*
- * JIO extension for resource replication.
- * Copyright (C) 2013, 2015  Nexedi SA
- *
- *   This library is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU Lesser General Public License as published by
- *   the Free Software Foundation, either version 3 of the License, or
- *   (at your option) any later version.
- *
- *   This library is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*jslint nomen: true*/
-/*global jIO, RSVP, Rusha*/
-
-(function (jIO, RSVP, Rusha, stringify) {
-  "use strict";
-
-  var rusha = new Rusha(),
-    CONFLICT_THROW = 0,
-    CONFLICT_KEEP_LOCAL = 1,
-    CONFLICT_KEEP_REMOTE = 2,
-    CONFLICT_CONTINUE = 3;
-
-  /****************************************************
-   Use a local jIO to read/write/search documents
-   Synchronize in background those document with a remote jIO.
-   Synchronization status is stored for each document as an local attachment.
-  ****************************************************/
-
-  function generateHash(content) {
-    // XXX Improve performance by moving calculation to WebWorker
-    return rusha.digestFromString(content);
-  }
-
-  function ReplicateStorage(spec) {
-    this._query_options = spec.query || {};
-
-    this._local_sub_storage = jIO.createJIO(spec.local_sub_storage);
-    this._remote_sub_storage = jIO.createJIO(spec.remote_sub_storage);
-
-    this._signature_hash = "_replicate_" + generateHash(
-      stringify(spec.local_sub_storage) +
-        stringify(spec.remote_sub_storage) +
-        stringify(this._query_options)
-    );
-    this._signature_sub_storage = jIO.createJIO({
-      type: "document",
-      document_id: this._signature_hash,
-      sub_storage: spec.signature_storage || spec.local_sub_storage
-    });
-
-    this._use_remote_post = spec.use_remote_post || false;
-
-    this._conflict_handling = spec.conflict_handling || 0;
-    // 0: no resolution (ie, throw an Error)
-    // 1: keep the local state
-    //    (overwrites the remote document with local content)
-    //    (delete remote document if local is deleted)
-    // 2: keep the remote state
-    //    (overwrites the local document with remote content)
-    //    (delete local document if remote is deleted)
-    // 3: keep both copies (leave documents untouched, no signature update)
-    if ((this._conflict_handling !== CONFLICT_THROW) &&
-        (this._conflict_handling !== CONFLICT_KEEP_LOCAL) &&
-        (this._conflict_handling !== CONFLICT_KEEP_REMOTE) &&
-        (this._conflict_handling !== CONFLICT_CONTINUE)) {
-      throw new jIO.util.jIOError("Unsupported conflict handling: " +
-                                  this._conflict_handling, 400);
-    }
-
-    this._check_local_modification = spec.check_local_modification;
-    if (this._check_local_modification === undefined) {
-      this._check_local_modification = true;
-    }
-    this._check_local_creation = spec.check_local_creation;
-    if (this._check_local_creation === undefined) {
-      this._check_local_creation = true;
-    }
-    this._check_local_deletion = spec.check_local_deletion;
-    if (this._check_local_deletion === undefined) {
-      this._check_local_deletion = true;
-    }
-    this._check_remote_modification = spec.check_remote_modification;
-    if (this._check_remote_modification === undefined) {
-      this._check_remote_modification = true;
-    }
-    this._check_remote_creation = spec.check_remote_creation;
-    if (this._check_remote_creation === undefined) {
-      this._check_remote_creation = true;
-    }
-    this._check_remote_deletion = spec.check_remote_deletion;
-    if (this._check_remote_deletion === undefined) {
-      this._check_remote_deletion = true;
-    }
-  }
-
-  ReplicateStorage.prototype.remove = function (id) {
-    if (id === this._signature_hash) {
-      throw new jIO.util.jIOError(this._signature_hash + " is frozen",
-                                  403);
-    }
-    return this._local_sub_storage.remove.apply(this._local_sub_storage,
-                                                arguments);
-  };
-  ReplicateStorage.prototype.post = function () {
-    return this._local_sub_storage.post.apply(this._local_sub_storage,
-                                              arguments);
-  };
-  ReplicateStorage.prototype.put = function (id) {
-    if (id === this._signature_hash) {
-      throw new jIO.util.jIOError(this._signature_hash + " is frozen",
-                                  403);
-    }
-    return this._local_sub_storage.put.apply(this._local_sub_storage,
-                                             arguments);
-  };
-  ReplicateStorage.prototype.get = function () {
-    return this._local_sub_storage.get.apply(this._local_sub_storage,
-                                             arguments);
-  };
-  ReplicateStorage.prototype.hasCapacity = function () {
-    return this._local_sub_storage.hasCapacity.apply(this._local_sub_storage,
-                                                     arguments);
-  };
-  ReplicateStorage.prototype.buildQuery = function () {
-    // XXX Remove signature document?
-    return this._local_sub_storage.buildQuery.apply(this._local_sub_storage,
-                                                    arguments);
-  };
-
-  ReplicateStorage.prototype.repair = function () {
-    var context = this,
-      argument_list = arguments,
-      skip_document_dict = {};
-
-    // Do not sync the signature document
-    skip_document_dict[context._signature_hash] = null;
-
-    function propagateModification(source, destination, doc, hash, id,
-                                   options) {
-      var result,
-        post_id,
-        to_skip = true;
-      if (options === undefined) {
-        options = {};
-      }
-      if (options.use_post) {
-        result = destination.post(doc)
-          .push(function (new_id) {
-            to_skip = false;
-            post_id = new_id;
-            return source.put(post_id, doc);
-          })
-          .push(function () {
-            return source.remove(id);
-          })
-          .push(function () {
-            return context._signature_sub_storage.remove(id);
-          })
-          .push(function () {
-            to_skip = true;
-            return context._signature_sub_storage.put(post_id, {
-              "hash": hash
-            });
-          })
-          .push(function () {
-            skip_document_dict[post_id] = null;
-          });
-      } else {
-        result = destination.put(id, doc)
-          .push(function () {
-            return context._signature_sub_storage.put(id, {
-              "hash": hash
-            });
-          });
-      }
-      return result
-        .push(function () {
-          if (to_skip) {
-            skip_document_dict[id] = null;
-          }
-        });
-    }
-
-    function propagateDeletion(destination, id) {
-      return destination.remove(id)
-        .push(function () {
-          return context._signature_sub_storage.remove(id);
-        })
-        .push(function () {
-          skip_document_dict[id] = null;
-        });
-    }
-
-    function checkAndPropagate(status_hash, local_hash, doc,
-                               source, destination, id,
-                               conflict_force, conflict_revert,
-                               conflict_ignore,
-                               options) {
-      return destination.get(id)
-        .push(function (remote_doc) {
-          return [remote_doc, generateHash(stringify(remote_doc))];
-        }, function (error) {
-          if ((error instanceof jIO.util.jIOError) &&
-              (error.status_code === 404)) {
-            return [null, null];
-          }
-          throw error;
-        })
-        .push(function (remote_list) {
-          var remote_doc = remote_list[0],
-            remote_hash = remote_list[1];
-
-          if (local_hash === remote_hash) {
-            // Same modifications on both side
-            if (local_hash === null) {
-              // Deleted on both side, drop signature
-              return context._signature_sub_storage.remove(id)
-                .push(function () {
-                  skip_document_dict[id] = null;
-                });
-            }
-
-            return context._signature_sub_storage.put(id, {
-              "hash": local_hash
-            })
-              .push(function () {
-                skip_document_dict[id] = null;
-              });
-          }
-
-          if ((remote_hash === status_hash) || (conflict_force === true)) {
-            // Modified only locally. No conflict or force
-            if (local_hash === null) {
-              // Deleted locally
-              return propagateDeletion(destination, id);
-            }
-            return propagateModification(source, destination, doc,
-                                         local_hash, id,
-                                         {use_post: ((options.use_post) &&
-                                                     (remote_hash === null))});
-          }
-
-          // Conflict cases
-          if (conflict_ignore === true) {
-            return;
-          }
-
-          if ((conflict_revert === true) || (local_hash === null)) {
-            // Automatically resolve conflict or force revert
-            if (remote_hash === null) {
-              // Deleted remotely
-              return propagateDeletion(source, id);
-            }
-            return propagateModification(
-              destination,
-              source,
-              remote_doc,
-              remote_hash,
-              id,
-              {use_post: ((options.use_revert_post) &&
-                          (local_hash === null))}
-            );
-          }
-
-          // Minimize conflict if it can be resolved
-          if (remote_hash === null) {
-            // Copy remote modification remotely
-            return propagateModification(source, destination, doc,
-                                         local_hash, id,
-                                         {use_post: options.use_post});
-          }
-          throw new jIO.util.jIOError("Conflict on '" + id + "': " +
-                                      stringify(doc || '') + " !== " +
-                                      stringify(remote_doc || ''),
-                                      409);
-        });
-    }
-
-    function checkLocalDeletion(queue, destination, id, source,
-                                conflict_force, conflict_revert,
-                                conflict_ignore, options) {
-      var status_hash;
-      queue
-        .push(function () {
-          return context._signature_sub_storage.get(id);
-        })
-        .push(function (result) {
-          status_hash = result.hash;
-          return checkAndPropagate(status_hash, null, null,
-                                   source, destination, id,
-                                   conflict_force, conflict_revert,
-                                   conflict_ignore,
-                                   options);
-        });
-    }
-
-    function checkSignatureDifference(queue, source, destination, id,
-                                      conflict_force, conflict_revert,
-                                      conflict_ignore,
-                                      is_creation, is_modification,
-                                      getMethod, options) {
-      queue
-        .push(function () {
-          // Optimisation to save a get call to signature storage
-          if (is_creation === true) {
-            return RSVP.all([
-              getMethod(id),
-              {hash: null}
-            ]);
-          }
-          if (is_modification === true) {
-            return RSVP.all([
-              getMethod(id),
-              context._signature_sub_storage.get(id)
-            ]);
-          }
-          throw new jIO.util.jIOError("Unexpected call of"
-                                      + " checkSignatureDifference",
-                                      409);
-        })
-        .push(function (result_list) {
-          var doc = result_list[0],
-            local_hash = generateHash(stringify(doc)),
-            status_hash = result_list[1].hash;
-
-          if (local_hash !== status_hash) {
-            return checkAndPropagate(status_hash, local_hash, doc,
-                                     source, destination, id,
-                                     conflict_force, conflict_revert,
-                                     conflict_ignore,
-                                     options);
-          }
-        });
-    }
-
-    function checkBulkSignatureDifference(queue, source, destination, id_list,
-                                          document_status_list, options,
-                                          conflict_force, conflict_revert,
-                                          conflict_ignore) {
-      queue
-        .push(function () {
-          return source.bulk(id_list);
-        })
-        .push(function (result_list) {
-          var i,
-            sub_queue = new RSVP.Queue();
-
-          function getResult(j) {
-            return function (id) {
-              if (id !== id_list[j].parameter_list[0]) {
-                throw new Error("Does not access expected ID " + id);
-              }
-              return result_list[j];
-            };
-          }
-
-          for (i = 0; i < result_list.length; i += 1) {
-            checkSignatureDifference(sub_queue, source, destination,
-                               id_list[i].parameter_list[0],
-                               conflict_force, conflict_revert,
-                               conflict_ignore,
-                               document_status_list[i].is_creation,
-                               document_status_list[i].is_modification,
-                               getResult(i), options);
-          }
-          return sub_queue;
-        });
-    }
-
-    function pushStorage(source, destination, options) {
-      var queue = new RSVP.Queue();
-      if (!options.hasOwnProperty("use_post")) {
-        options.use_post = false;
-      }
-      if (!options.hasOwnProperty("use_revert_post")) {
-        options.use_revert_post = false;
-      }
-      return queue
-        .push(function () {
-          return RSVP.all([
-            source.allDocs(context._query_options),
-            context._signature_sub_storage.allDocs()
-          ]);
-        })
-        .push(function (result_list) {
-          var i,
-            local_dict = {},
-            document_list = [],
-            document_status_list = [],
-            signature_dict = {},
-            is_modification,
-            is_creation,
-            key;
-          for (i = 0; i < result_list[0].data.total_rows; i += 1) {
-            if (!skip_document_dict.hasOwnProperty(
-                result_list[0].data.rows[i].id
-              )) {
-              local_dict[result_list[0].data.rows[i].id] = i;
-            }
-          }
-          for (i = 0; i < result_list[1].data.total_rows; i += 1) {
-            if (!skip_document_dict.hasOwnProperty(
-                result_list[1].data.rows[i].id
-              )) {
-              signature_dict[result_list[1].data.rows[i].id] = i;
-            }
-          }
-          for (key in local_dict) {
-            if (local_dict.hasOwnProperty(key)) {
-              is_modification = signature_dict.hasOwnProperty(key)
-                && options.check_modification;
-              is_creation = !signature_dict.hasOwnProperty(key)
-                && options.check_creation;
-              if (is_modification === true || is_creation === true) {
-                if (options.use_bulk_get === true) {
-                  document_list.push({
-                    method: "get",
-                    parameter_list: [key]
-                  });
-                  document_status_list.push({
-                    is_creation: is_creation,
-                    is_modification: is_modification
-                  });
-                } else {
-                  checkSignatureDifference(queue, source, destination, key,
-                                           options.conflict_force,
-                                           options.conflict_revert,
-                                           options.conflict_ignore,
-                                           is_creation, is_modification,
-                                           source.get.bind(source),
-                                           options);
-                }
-              }
-            }
-          }
-          if (options.check_deletion === true) {
-            for (key in signature_dict) {
-              if (signature_dict.hasOwnProperty(key)) {
-                if (!local_dict.hasOwnProperty(key)) {
-                  checkLocalDeletion(queue, destination, key, source,
-                                     options.conflict_force,
-                                     options.conflict_revert,
-                                     options.conflict_ignore,
-                                     options);
-                }
-              }
-            }
-          }
-          if ((options.use_bulk_get === true) && (document_list.length !== 0)) {
-            checkBulkSignatureDifference(queue, source, destination,
-                                         document_list, document_status_list,
-                                         options,
-                                         options.conflict_force,
-                                         options.conflict_revert,
-                                         options.conflict_ignore);
-          }
-        });
-    }
-
-    return new RSVP.Queue()
-      .push(function () {
-        // Ensure that the document storage is usable
-        return context._signature_sub_storage.__storage._sub_storage.get(
-          context._signature_hash
-        );
-      })
-      .push(undefined, function (error) {
-        if ((error instanceof jIO.util.jIOError) &&
-            (error.status_code === 404)) {
-          return context._signature_sub_storage.__storage._sub_storage.put(
-            context._signature_hash,
-            {}
-          );
-        }
-        throw error;
-      })
-
-      .push(function () {
-        return RSVP.all([
-// Don't repair local_sub_storage twice
-//           context._signature_sub_storage.repair.apply(
-//             context._signature_sub_storage,
-//             argument_list
-//           ),
-          context._local_sub_storage.repair.apply(
-            context._local_sub_storage,
-            argument_list
-          ),
-          context._remote_sub_storage.repair.apply(
-            context._remote_sub_storage,
-            argument_list
-          )
-        ]);
-      })
-
-      .push(function () {
-        if (context._check_local_modification ||
-            context._check_local_creation ||
-            context._check_local_deletion) {
-          return pushStorage(context._local_sub_storage,
-                             context._remote_sub_storage,
-                             {
-              use_post: context._use_remote_post,
-              conflict_force: (context._conflict_handling ===
-                               CONFLICT_KEEP_LOCAL),
-              conflict_revert: (context._conflict_handling ===
-                                CONFLICT_KEEP_REMOTE),
-              conflict_ignore: (context._conflict_handling ===
-                                CONFLICT_CONTINUE),
-              check_modification: context._check_local_modification,
-              check_creation: context._check_local_creation,
-              check_deletion: context._check_local_deletion
-            });
-        }
-      })
-      .push(function () {
-        // Autoactivate bulk if substorage implements it
-        // Keep it like this until the bulk API is stabilized
-        var use_bulk_get = false;
-        try {
-          use_bulk_get = context._remote_sub_storage.hasCapacity("bulk");
-        } catch (error) {
-          if (!((error instanceof jIO.util.jIOError) &&
-               (error.status_code === 501))) {
-            throw error;
-          }
-        }
-        if (context._check_remote_modification ||
-            context._check_remote_creation ||
-            context._check_remote_deletion) {
-          return pushStorage(context._remote_sub_storage,
-                             context._local_sub_storage, {
-              use_bulk_get: use_bulk_get,
-              use_revert_post: context._use_remote_post,
-              conflict_force: (context._conflict_handling ===
-                               CONFLICT_KEEP_REMOTE),
-              conflict_revert: (context._conflict_handling ===
-                                CONFLICT_KEEP_LOCAL),
-              conflict_ignore: (context._conflict_handling ===
-                                CONFLICT_CONTINUE),
-              check_modification: context._check_remote_modification,
-              check_creation: context._check_remote_creation,
-              check_deletion: context._check_remote_deletion
-            });
-        }
-      });
-  };
-
-  jIO.addStorage('replicate', ReplicateStorage);
-
-}(jIO, RSVP, Rusha, jIO.util.stringify));
-;/*
- * Copyright 2015, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-
-/*jslint nomen: true*/
-/*global Rusha*/
-
-/**
- * JIO Sha Storage. Type = 'sha'.
- */
-
-(function (Rusha) {
-  "use strict";
-
-  var rusha = new Rusha();
-
-  function ShaStorage(spec) {
-    this._sub_storage = jIO.createJIO(spec.sub_storage);
-  }
-
-  ShaStorage.prototype.post = function (param) {
-    return this._sub_storage.put(
-      rusha.digestFromString(JSON.stringify(param)),
-      param
-    );
-  };
-
-  ShaStorage.prototype.get = function () {
-    return this._sub_storage.get.apply(this._sub_storage, arguments);
-  };
-  ShaStorage.prototype.remove = function () {
-    return this._sub_storage.remove.apply(this._sub_storage, arguments);
-  };
-  ShaStorage.prototype.hasCapacity = function () {
-    return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments);
-  };
-  ShaStorage.prototype.buildQuery = function () {
-    return this._sub_storage.buildQuery.apply(this._sub_storage, arguments);
-  };
-  ShaStorage.prototype.getAttachment = function () {
-    return this._sub_storage.getAttachment.apply(this._sub_storage, arguments);
-  };
-  ShaStorage.prototype.putAttachment = function () {
-    return this._sub_storage.putAttachment.apply(this._sub_storage, arguments);
-  };
-  ShaStorage.prototype.removeAttachment = function () {
-    return this._sub_storage.removeAttachment.apply(this._sub_storage,
-                                                    arguments);
-  };
-  ShaStorage.prototype.allAttachments = function () {
-    return this._sub_storage.allAttachments.apply(this._sub_storage, arguments);
-  };
-  ShaStorage.prototype.repair = function () {
-    return this._sub_storage.repair.apply(this._sub_storage, arguments);
-  };
-
-  jIO.addStorage('sha', ShaStorage);
-
-}(Rusha));
-;/*jslint nomen: true*/
-(function (jIO) {
-  "use strict";
-
-  /**
-   * The jIO UUIDStorage extension
-   *
-   * @class UUIDStorage
-   * @constructor
-   */
-  function UUIDStorage(spec) {
-    this._sub_storage = jIO.createJIO(spec.sub_storage);
-  }
-
-  UUIDStorage.prototype.get = function () {
-    return this._sub_storage.get.apply(this._sub_storage, arguments);
-  };
-  UUIDStorage.prototype.allAttachments = function () {
-    return this._sub_storage.allAttachments.apply(this._sub_storage, arguments);
-  };
-  UUIDStorage.prototype.post = function (param) {
-
-    function S4() {
-      return ('0000' + Math.floor(
-        Math.random() * 0x10000 /* 65536 */
-      ).toString(16)).slice(-4);
-    }
-
-    var id = S4() + S4() + "-" +
-      S4() + "-" +
-      S4() + "-" +
-      S4() + "-" +
-      S4() + S4() + S4();
-
-    return this.put(id, param);
-  };
-  UUIDStorage.prototype.put = function () {
-    return this._sub_storage.put.apply(this._sub_storage, arguments);
-  };
-  UUIDStorage.prototype.remove = function () {
-    return this._sub_storage.remove.apply(this._sub_storage, arguments);
-  };
-  UUIDStorage.prototype.getAttachment = function () {
-    return this._sub_storage.getAttachment.apply(this._sub_storage, arguments);
-  };
-  UUIDStorage.prototype.putAttachment = function () {
-    return this._sub_storage.putAttachment.apply(this._sub_storage, arguments);
-  };
-  UUIDStorage.prototype.removeAttachment = function () {
-    return this._sub_storage.removeAttachment.apply(this._sub_storage,
-                                                    arguments);
-  };
-  UUIDStorage.prototype.repair = function () {
-    return this._sub_storage.repair.apply(this._sub_storage, arguments);
-  };
-  UUIDStorage.prototype.hasCapacity = function (name) {
-    return this._sub_storage.hasCapacity(name);
-  };
-  UUIDStorage.prototype.buildQuery = function () {
-    return this._sub_storage.buildQuery.apply(this._sub_storage,
-                                              arguments);
-  };
-
-  jIO.addStorage('uuid', UUIDStorage);
-
-}(jIO));
-;/*
- * Copyright 2013, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-
-/*jslint nomen: true*/
-/*global jIO, RSVP*/
-
-/**
- * JIO Memory Storage. Type = 'memory'.
- * Memory browser "database" storage.
- *
- * Storage Description:
- *
- *     {
- *       "type": "memory"
- *     }
- *
- * @class MemoryStorage
- */
-
-(function (jIO, JSON, RSVP) {
-  "use strict";
-
-  /**
-   * The JIO MemoryStorage extension
-   *
-   * @class MemoryStorage
-   * @constructor
-   */
-  function MemoryStorage() {
-    this._database = {};
-  }
-
-  MemoryStorage.prototype.put = function (id, metadata) {
-    if (!this._database.hasOwnProperty(id)) {
-      this._database[id] = {
-        attachments: {}
-      };
-    }
-    this._database[id].doc = JSON.stringify(metadata);
-    return id;
-  };
-
-  MemoryStorage.prototype.get = function (id) {
-    try {
-      return JSON.parse(this._database[id].doc);
-    } catch (error) {
-      if (error instanceof TypeError) {
-        throw new jIO.util.jIOError(
-          "Cannot find document: " + id,
-          404
-        );
-      }
-      throw error;
-    }
-  };
-
-  MemoryStorage.prototype.allAttachments = function (id) {
-    var key,
-      attachments = {};
-    try {
-      for (key in this._database[id].attachments) {
-        if (this._database[id].attachments.hasOwnProperty(key)) {
-          attachments[key] = {};
-        }
-      }
-    } catch (error) {
-      if (error instanceof TypeError) {
-        throw new jIO.util.jIOError(
-          "Cannot find document: " + id,
-          404
-        );
-      }
-      throw error;
-    }
-    return attachments;
-  };
-
-  MemoryStorage.prototype.remove = function (id) {
-    delete this._database[id];
-    return id;
-  };
-
-  MemoryStorage.prototype.getAttachment = function (id, name) {
-    try {
-      var result = this._database[id].attachments[name];
-      if (result === undefined) {
-        throw new jIO.util.jIOError(
-          "Cannot find attachment: " + id + " , " + name,
-          404
-        );
-      }
-      return jIO.util.dataURItoBlob(result);
-    } catch (error) {
-      if (error instanceof TypeError) {
-        throw new jIO.util.jIOError(
-          "Cannot find attachment: " + id + " , " + name,
-          404
-        );
-      }
-      throw error;
-    }
-  };
-
-  MemoryStorage.prototype.putAttachment = function (id, name, blob) {
-    var attachment_dict;
-    try {
-      attachment_dict = this._database[id].attachments;
-    } catch (error) {
-      if (error instanceof TypeError) {
-        throw new jIO.util.jIOError("Cannot find document: " + id, 404);
-      }
-      throw error;
-    }
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.readBlobAsDataURL(blob);
-      })
-      .push(function (evt) {
-        attachment_dict[name] = evt.target.result;
-      });
-  };
-
-  MemoryStorage.prototype.removeAttachment = function (id, name) {
-    try {
-      delete this._database[id].attachments[name];
-    } catch (error) {
-      if (error instanceof TypeError) {
-        throw new jIO.util.jIOError(
-          "Cannot find document: " + id,
-          404
-        );
-      }
-      throw error;
-    }
-  };
-
-
-  MemoryStorage.prototype.hasCapacity = function (name) {
-    return ((name === "list") || (name === "include"));
-  };
-
-  MemoryStorage.prototype.buildQuery = function (options) {
-    var rows = [],
-      i;
-    for (i in this._database) {
-      if (this._database.hasOwnProperty(i)) {
-        if (options.include_docs === true) {
-          rows.push({
-            id: i,
-            value: {},
-            doc: JSON.parse(this._database[i].doc)
-          });
-        } else {
-          rows.push({
-            id: i,
-            value: {}
-          });
-        }
-
-      }
-    }
-    return rows;
-  };
-
-  jIO.addStorage('memory', MemoryStorage);
-
-}(jIO, JSON, RSVP));
-;/*jslint nomen: true*/
-/*global RSVP, Blob, LZString, DOMException*/
-(function (RSVP, Blob, LZString, DOMException) {
-  "use strict";
-
-  /**
-   * The jIO ZipStorage extension
-   *
-   * @class ZipStorage
-   * @constructor
-   */
-
-  var MIME_TYPE = "application/x-jio-utf16_lz_string";
-
-  function ZipStorage(spec) {
-    this._sub_storage = jIO.createJIO(spec.sub_storage);
-  }
-
-  ZipStorage.prototype.get = function () {
-    return this._sub_storage.get.apply(this._sub_storage,
-                                        arguments);
-  };
-
-  ZipStorage.prototype.post = function () {
-    return this._sub_storage.post.apply(this._sub_storage,
-                                        arguments);
-  };
-
-  ZipStorage.prototype.put = function () {
-    return this._sub_storage.put.apply(this._sub_storage,
-                                       arguments);
-  };
-
-  ZipStorage.prototype.remove = function () {
-    return this._sub_storage.remove.apply(this._sub_storage,
-                                          arguments);
-  };
-
-  ZipStorage.prototype.hasCapacity = function () {
-    return this._sub_storage.hasCapacity.apply(this._sub_storage,
-                                               arguments);
-  };
-
-  ZipStorage.prototype.buildQuery = function () {
-    return this._sub_storage.buildQuery.apply(this._sub_storage,
-                                              arguments);
-  };
-
-  ZipStorage.prototype.getAttachment = function (id, name) {
-    var that = this;
-    return that._sub_storage.getAttachment(id, name)
-      .push(function (blob) {
-        if (blob.type !== MIME_TYPE) {
-          return blob;
-        }
-        return new RSVP.Queue()
-          .push(function () {
-            return jIO.util.readBlobAsText(blob, 'utf16');
-          })
-          .push(function (evt) {
-            var result =
-              LZString.decompressFromUTF16(evt.target.result);
-            if (result === '') {
-              return blob;
-            }
-            try {
-              return jIO.util.dataURItoBlob(
-                result
-              );
-            } catch (error) {
-              if (error instanceof DOMException) {
-                return blob;
-              }
-              throw error;
-            }
-          });
-      });
-  };
-
-  function myEndsWith(str, query) {
-    return (str.indexOf(query) === str.length - query.length);
-  }
-
-  ZipStorage.prototype.putAttachment = function (id, name, blob) {
-    var that = this;
-    if ((blob.type.indexOf("text/") === 0) || myEndsWith(blob.type, "xml") ||
-        myEndsWith(blob.type, "json")) {
-      return new RSVP.Queue()
-        .push(function () {
-          return jIO.util.readBlobAsDataURL(blob);
-        })
-        .push(function (data) {
-          var result = LZString.compressToUTF16(data.target.result);
-          blob = new Blob([result],
-                          {type: MIME_TYPE});
-          return that._sub_storage.putAttachment(id, name, blob);
-        });
-    }
-    return this._sub_storage.putAttachment.apply(this._sub_storage,
-                                                 arguments);
-  };
-
-  ZipStorage.prototype.removeAttachment = function () {
-    return this._sub_storage.removeAttachment.apply(this._sub_storage,
-                                                    arguments);
-  };
-
-  ZipStorage.prototype.allAttachments = function () {
-    return this._sub_storage.allAttachments.apply(this._sub_storage,
-                                                  arguments);
-  };
-
-  jIO.addStorage('zip', ZipStorage);
-}(RSVP, Blob, LZString, DOMException));
-;/*
- * Copyright 2013, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-/**
- * JIO Dropbox Storage. Type = "dropbox".
- * Dropbox "database" storage.
- */
-/*global Blob, jIO, RSVP, UriTemplate*/
-/*jslint nomen: true*/
-
-(function (jIO, RSVP, Blob, UriTemplate) {
-  "use strict";
-  var UPLOAD_URL = "https://content.dropboxapi.com/1/files_put/" +
-      "{+root}{+id}{+name}{?access_token}",
-    upload_template = UriTemplate.parse(UPLOAD_URL),
-    CREATE_DIR_URL = "https://api.dropboxapi.com/1/fileops/create_folder" +
-      "{?access_token,root,path}",
-    create_dir_template = UriTemplate.parse(CREATE_DIR_URL),
-    REMOVE_URL = "https://api.dropboxapi.com/1/fileops/delete/" +
-      "{?access_token,root,path}",
-    remote_template = UriTemplate.parse(REMOVE_URL),
-    GET_URL = "https://content.dropboxapi.com/1/files" +
-      "{/root,id}{+name}{?access_token}",
-    get_template = UriTemplate.parse(GET_URL),
-    //LIST_URL = 'https://api.dropboxapi.com/1/metadata/sandbox/';
-    METADATA_URL = "https://api.dropboxapi.com/1/metadata" +
-      "{/root}{+id}{?access_token}",
-    metadata_template = UriTemplate.parse(METADATA_URL);
-
-  function restrictDocumentId(id) {
-    if (id.indexOf("/") !== 0) {
-      throw new jIO.util.jIOError("id " + id + " is forbidden (no begin /)",
-                                  400);
-    }
-    if (id.lastIndexOf("/") !== (id.length - 1)) {
-      throw new jIO.util.jIOError("id " + id + " is forbidden (no end /)",
-                                  400);
-    }
-    return id;
-  }
-
-  function restrictAttachmentId(id) {
-    if (id.indexOf("/") !== -1) {
-      throw new jIO.util.jIOError("attachment " + id + " is forbidden",
-                                  400);
-    }
-  }
-
-  /**
-   * The JIO Dropbox Storage extension
-   *
-   * @class DropboxStorage
-   * @constructor
-   */
-  function DropboxStorage(spec) {
-    if (typeof spec.access_token !== 'string' || !spec.access_token) {
-      throw new TypeError("Access Token' must be a string " +
-                          "which contains more than one character.");
-    }
-    if (typeof spec.root !== 'string' || !spec.root ||
-        (spec.root !== "dropbox" && spec.root !== "sandbox")) {
-      throw new TypeError("root must be 'dropbox' or 'sandbox'");
-    }
-    this._access_token = spec.access_token;
-    this._root = spec.root;
-  }
-
-  DropboxStorage.prototype.put = function (id, param) {
-    var that = this;
-    id = restrictDocumentId(id);
-    if (Object.getOwnPropertyNames(param).length > 0) {
-      // Reject if param has some properties
-      throw new jIO.util.jIOError("Can not store properties: " +
-                                  Object.getOwnPropertyNames(param), 400);
-    }
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          type: "POST",
-          url: create_dir_template.expand({
-            access_token: that._access_token,
-            root: that._root,
-            path: id
-          })
-        });
-      })
-      .push(undefined, function (err) {
-        if ((err.target !== undefined) &&
-            (err.target.status === 405)) {
-          // Directory already exists, no need to fail
-          return;
-        }
-        throw err;
-      });
-  };
-
-  DropboxStorage.prototype.remove = function (id) {
-    id = restrictDocumentId(id);
-    return jIO.util.ajax({
-      type: "POST",
-      url: remote_template.expand({
-        access_token: this._access_token,
-        root: this._root,
-        path: id
-      })
-    });
-  };
-
-  DropboxStorage.prototype.get = function (id) {
-    var that = this;
-
-    if (id === "/") {
-      return {};
-    }
-    id = restrictDocumentId(id);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          type: "GET",
-          url: metadata_template.expand({
-            access_token: that._access_token,
-            root: that._root,
-            id: id
-          })
-        });
-      })
-      .push(function (evt) {
-        var obj = JSON.parse(evt.target.response ||
-                             evt.target.responseText);
-        if (obj.is_dir) {
-          return {};
-        }
-        throw new jIO.util.jIOError("Not a directory: " + id, 404);
-      }, function (error) {
-        if (error.target !== undefined && error.target.status === 404) {
-          throw new jIO.util.jIOError("Cannot find document: " + id, 404);
-        }
-        throw error;
-      });
-  };
-
-  DropboxStorage.prototype.allAttachments = function (id) {
-
-    var that = this;
-    id = restrictDocumentId(id);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          type: "GET",
-          url: metadata_template.expand({
-            access_token: that._access_token,
-            root: that._root,
-            id: id
-          })
-        });
-      })
-      .push(function (evt) {
-        var obj = JSON.parse(evt.target.response || evt.target.responseText),
-          i,
-          result = {};
-        if (!obj.is_dir) {
-          throw new jIO.util.jIOError("Not a directory: " + id, 404);
-        }
-        for (i = 0; i < obj.contents.length; i += 1) {
-          if (!obj.contents[i].is_dir) {
-            result[obj.contents[i].path.split("/").pop()] = {};
-          }
-        }
-        return result;
-      }, function (error) {
-        if (error.target !== undefined && error.target.status === 404) {
-          throw new jIO.util.jIOError("Cannot find document: " + id, 404);
-        }
-        throw error;
-      });
-  };
-
-  //currently, putAttachment will fail with files larger than 150MB,
-  //due to the Dropbox API. the API provides the "chunked_upload" method
-  //to pass this limit, but upload process becomes more complex to implement.
-  //
-  //putAttachment will also create a folder if you try to put an attachment
-  //to an inexisting foler.
-
-  DropboxStorage.prototype.putAttachment = function (id, name, blob) {
-    id = restrictDocumentId(id);
-    restrictAttachmentId(name);
-
-    return jIO.util.ajax({
-      type: "PUT",
-      url: upload_template.expand({
-        root: this._root,
-        id: id,
-        name: name,
-        access_token: this._access_token
-      }),
-      dataType: blob.type,
-      data: blob
-    });
-  };
-
-  DropboxStorage.prototype.getAttachment = function (id, name) {
-    var that = this;
-
-    id = restrictDocumentId(id);
-    restrictAttachmentId(name);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          type: "GET",
-          dataType: "blob",
-          url: get_template.expand({
-            root: that._root,
-            id: id,
-            name: name,
-            access_token: that._access_token
-          })
-        });
-      })
-      .push(function (evt) {
-        return new Blob(
-          [evt.target.response || evt.target.responseText],
-          {"type": evt.target.getResponseHeader('Content-Type') ||
-            "application/octet-stream"}
-        );
-      }, function (error) {
-        if (error.target !== undefined && error.target.status === 404) {
-          throw new jIO.util.jIOError("Cannot find attachment: " +
-                                      id + ", " + name, 404);
-        }
-        throw error;
-      });
-  };
-
-  //removeAttachment removes also directories.(due to Dropbox API)
-
-  DropboxStorage.prototype.removeAttachment = function (id, name) {
-    var that = this;
-    id = restrictDocumentId(id);
-    restrictAttachmentId(name);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          type: "POST",
-          url: remote_template.expand({
-            access_token: that._access_token,
-            root: that._root,
-            path: id + name
-          })
-        });
-      }).push(undefined, function (error) {
-        if (error.target !== undefined && error.target.status === 404) {
-          throw new jIO.util.jIOError("Cannot find attachment: " +
-                                      id + ", " + name, 404);
-        }
-        throw error;
-      });
-  };
-
-  jIO.addStorage('dropbox', DropboxStorage);
-
-}(jIO, RSVP, Blob, UriTemplate));
-;/*
- * Copyright 2013, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-
-/*jslint nomen: true*/
-/*global jIO, RSVP, DOMParser, Blob */
-
-// JIO Dav Storage Description :
-// {
-//   type: "dav",
-//   url: {string},
-//   basic_login: {string} // Basic authentication
-// }
-
-// NOTE: to get the authentication type ->
-// curl --verbose  -X OPTION http://domain/
-// In the headers: "WWW-Authenticate: Basic realm="DAV-upload"
-
-(function (jIO, RSVP, DOMParser, Blob) {
-  "use strict";
-
-  function ajax(storage, options) {
-    if (options === undefined) {
-      options = {};
-    }
-    if (storage._authorization !== undefined) {
-      if (options.headers === undefined) {
-        options.headers = {};
-      }
-      options.headers.Authorization = storage._authorization;
-    }
-
-    if (storage._with_credentials !== undefined) {
-      if (options.xhrFields === undefined) {
-        options.xhrFields = {};
-      }
-      options.xhrFields.withCredentials = storage._with_credentials;
-    }
-//       if (start !== undefined) {
-//         if (end !== undefined) {
-//           headers.Range = "bytes=" + start + "-" + end;
-//         } else {
-//           headers.Range = "bytes=" + start + "-";
-//         }
-//       }
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax(options);
-      });
-  }
-
-  function restrictDocumentId(id) {
-    if (id.indexOf("/") !== 0) {
-      throw new jIO.util.jIOError("id " + id + " is forbidden (no begin /)",
-                                  400);
-    }
-    if (id.lastIndexOf("/") !== (id.length - 1)) {
-      throw new jIO.util.jIOError("id " + id + " is forbidden (no end /)",
-                                  400);
-    }
-    return id;
-  }
-
-  function restrictAttachmentId(id) {
-    if (id.indexOf("/") !== -1) {
-      throw new jIO.util.jIOError("attachment " + id + " is forbidden",
-                                  400);
-    }
-  }
-
-  /**
-   * The JIO WebDAV Storage extension
-   *
-   * @class DavStorage
-   * @constructor
-   */
-  function DavStorage(spec) {
-    if (typeof spec.url !== 'string') {
-      throw new TypeError("DavStorage 'url' is not of type string");
-    }
-    this._url = spec.url;
-    // XXX digest login
-    if (typeof spec.basic_login === 'string') {
-      this._authorization = "Basic " + spec.basic_login;
-    }
-    this._with_credentials = spec.with_credentials;
-  }
-
-  DavStorage.prototype.put = function (id, param) {
-    var that = this;
-    id = restrictDocumentId(id);
-    if (Object.getOwnPropertyNames(param).length > 0) {
-      // Reject if param has some properties
-      throw new jIO.util.jIOError("Can not store properties: " +
-                                  Object.getOwnPropertyNames(param), 400);
-    }
-    return new RSVP.Queue()
-      .push(function () {
-        return ajax(that, {
-          type: "MKCOL",
-          url: that._url + id
-        });
-      })
-      .push(undefined, function (err) {
-        if ((err.target !== undefined) &&
-            (err.target.status === 405)) {
-          return;
-        }
-        throw err;
-      });
-  };
-
-  DavStorage.prototype.remove = function (id) {
-    id = restrictDocumentId(id);
-    return ajax(this, {
-      type: "DELETE",
-      url: this._url + id
-    });
-  };
-
-  DavStorage.prototype.get = function (id) {
-    var context = this;
-    id = restrictDocumentId(id);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return ajax(context, {
-          type: "PROPFIND",
-          url: context._url + id,
-          dataType: "text",
-          headers: {
-            // Increasing this value is a performance killer
-            Depth: "1"
-          }
-        });
-      })
-      .push(function () {
-        return {};
-      }, function (error) {
-        if ((error.target !== undefined) &&
-            (error.target.status === 404)) {
-          throw new jIO.util.jIOError("Cannot find document", 404);
-        }
-        throw error;
-      });
-  };
-
-  DavStorage.prototype.allAttachments = function (id) {
-
-    var context = this;
-    id = restrictDocumentId(id);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return ajax(context, {
-          type: "PROPFIND",
-          url: context._url + id,
-          dataType: "text",
-          headers: {
-            // Increasing this value is a performance killer
-            Depth: "1"
-          }
-        });
-      })
-
-
-      .push(function (response) {
-        // Extract all meta informations and return them to JSON
-
-        var i,
-          attachment = {},
-          id,
-          attachment_list = new DOMParser().parseFromString(
-            response.target.responseText,
-            "text/xml"
-          ).querySelectorAll(
-            "D\\:response, response"
-          );
-
-        // exclude parent folder and browse
-        for (i = 1; i < attachment_list.length; i += 1) {
-          // XXX Only get files for now
-          id = attachment_list[i].querySelector("D\\:href, href").
-            textContent.split('/').slice(-1)[0];
-          // XXX Ugly
-          if ((id !== undefined) && (id !== "")) {
-            attachment[id] = {};
-          }
-        }
-        return attachment;
-
-      }, function (error) {
-        if ((error.target !== undefined) &&
-            (error.target.status === 404)) {
-          throw new jIO.util.jIOError("Cannot find document", 404);
-        }
-        throw error;
-      });
-
-  };
-
-
-  DavStorage.prototype.putAttachment = function (id, name, blob) {
-    var that = this;
-    id = restrictDocumentId(id);
-    restrictAttachmentId(name);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return ajax(that, {
-          type: "PUT",
-          url: that._url + id + name,
-          data: blob
-        });
-      })
-      .push(undefined, function (error) {
-        if (error.target.status === 403 || error.target.status === 424) {
-          throw new jIO.util.jIOError("Cannot access subdocument", 404);
-        }
-        throw error;
-      });
-  };
-
-  DavStorage.prototype.getAttachment = function (id, name) {
-    var context = this;
-    id = restrictDocumentId(id);
-    restrictAttachmentId(name);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return ajax(context, {
-          type: "GET",
-          url: context._url + id + name,
-          dataType: "blob"
-        });
-      })
-      .push(function (response) {
-        return new Blob(
-          [response.target.response || response.target.responseText],
-          {"type": response.target.getResponseHeader('Content-Type') ||
-                   "application/octet-stream"}
-        );
-      }, function (error) {
-        if ((error.target !== undefined) &&
-            (error.target.status === 404)) {
-          throw new jIO.util.jIOError("Cannot find attachment: "
-                                      + id + " , " + name,
-                                      404);
-        }
-        throw error;
-      });
-
-  };
-
-  DavStorage.prototype.removeAttachment = function (id, name) {
-    var context = this;
-    id = restrictDocumentId(id);
-    restrictAttachmentId(name);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return ajax(context, {
-          type: "DELETE",
-          url: context._url + id + name
-        });
-      })
-      .push(undefined, function (error) {
-        if ((error.target !== undefined) &&
-            (error.target.status === 404)) {
-          throw new jIO.util.jIOError("Cannot find attachment: "
-                                      + id + " , " + name,
-                                      404);
-        }
-        throw error;
-      });
-  };
-
-  // JIO COMMANDS //
-
-  // wedDav methods rfc4918 (short summary)
-  // COPY     Reproduces single resources (files) and collections (directory
-  //          trees). Will overwrite files (if specified by request) but will
-  //          respond 209 (Conflict) if it would overwrite a tree
-  // DELETE   deletes files and directory trees
-  // GET      just the vanilla HTTP/1.1 behaviour
-  // HEAD     ditto
-  // LOCK     locks a resources
-  // MKCOL    creates a directory
-  // MOVE     Moves (rename or copy) a file or a directory tree. Will
-  //          'overwrite' files (if specified by the request) but will respond
-  //          209 (Conflict) if it would overwrite a tree.
-  // OPTIONS  If WebDAV is enabled and available for the path this reports the
-  //          WebDAV extension methods
-  // PROPFIND Retrieves the requested file characteristics, DAV lock status
-  //          and 'dead' properties for individual files, a directory and its
-  //          child files, or a directory tree
-  // PROPPATCHset and remove 'dead' meta-data properties
-  // PUT      Update or create resource or collections
-  // UNLOCK   unlocks a resource
-
-  // Notes: all Ajax requests should be CORS (cross-domain)
-  // adding custom headers triggers preflight OPTIONS request!
-  // http://remysharp.com/2011/04/21/getting-cors-working/
-
-  jIO.addStorage('dav', DavStorage);
-
-}(jIO, RSVP, DOMParser, Blob));
-;/*
- * Copyright 2015, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-/**
- * JIO Google Drive Storage. Type = "gdrive".
- * Google Drive "database" storage.
- */
-/*global jIO, Blob, RSVP, UriTemplate, JSON*/
-/*jslint nomen: true*/
-
-(function (jIO, Blob, RSVP, UriTemplate, JSON) {
-  "use strict";
-
-  var UPLOAD_URL = "https://www.googleapis.com{/upload}/drive/v2/files{/id}" +
-      "{?uploadType,access_token}",
-    upload_template = UriTemplate.parse(UPLOAD_URL),
-    REMOVE_URL = "https://www.googleapis.com/drive/v2/" +
-      "files{/id,trash}{?access_token}",
-    remove_template = UriTemplate.parse(REMOVE_URL),
-    LIST_URL = "https://www.googleapis.com/drive/v2/files" +
-      "?prettyPrint=false{&pageToken}&q=trashed=false" +
-      "&fields=nextPageToken,items(id){&access_token}",
-    list_template = UriTemplate.parse(LIST_URL),
-    GET_URL = "https://www.googleapis.com/drive/v2/files{/id}{?alt}",
-    get_template = UriTemplate.parse(GET_URL);
-
-  function handleError(error, id) {
-    if (error.target.status === 404) {
-      throw new jIO.util.jIOError(
-        "Cannot find document: " + id,
-        404
-      );
-    }
-    throw error;
-  }
-
-  function listPage(result, token) {
-    var i,
-      obj;
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          "type": "GET",
-          "url": list_template.expand({
-            pageToken : (result.nextPageToken || ""),
-            access_token: token
-          })
-        });
-      })
-      .push(function (data) {
-        obj = JSON.parse(data.target.response || data.target.responseText);
-        for (i = 0; i < obj.items.length; i += 1) {
-          obj.items[i].value = {};
-          result.push(obj.items[i]);
-        }
-        result.nextPageToken = obj.nextPageToken;
-        return result;
-      }, handleError);
-  }
-
-  function checkName(name) {
-    if (name !== "enclosure") {
-      throw new jIO.util.jIOError("Only support 'enclosure' attachment", 400);
-    }
-  }
-
-  /**
-   * The JIO Google Drive Storage extension
-   *
-   * @class GdriveStorage
-   * @constructor
-   */
-  function GdriveStorage(spec) {
-    if (spec === undefined || spec.access_token === undefined ||
-        typeof spec.access_token !== 'string') {
-      throw new TypeError("Access Token must be a string " +
-                          "which contains more than one character.");
-    }
-    if (spec.trashing !== undefined &&
-        (spec.trashing !== true && spec.trashing !== false)) {
-      throw new TypeError("trashing parameter" +
-                          " must be a boolean (true or false)");
-    }
-    this._trashing = spec.trashing || true;
-    this._access_token = spec.access_token;
-    return;
-  }
-
-  function recursiveAllDocs(result, accessToken) {
-    return new RSVP.Queue()
-      .push(function () {
-        return listPage(result, accessToken);
-      })
-      .push(function () {
-        if (result.nextPageToken) {
-          return recursiveAllDocs(result, accessToken);
-        }
-        return result;
-      });
-  }
-
-  GdriveStorage.prototype.hasCapacity = function (name) {
-    return (name === "list");
-  };
-
-  GdriveStorage.prototype.buildQuery = function () {
-    return recursiveAllDocs([], this._access_token);
-  };
-
-  function sendMetaData(id, param, token) {
-    var boundary = "-------314159265358979323846";
-
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          "type": id ? "PUT" : "POST",
-          "url": upload_template.expand({
-            access_token: token,
-            id: id || [],
-            upload: id ? [] : "upload",
-            uploadType: "multipart"
-          }),
-          headers: {
-            "Content-Type" : 'multipart/related; boundary="' + boundary + '"'
-          },
-          data: '--' + boundary + '\n' +
-            'Content-Type: application/json; charset=UTF-8\n\n' +
-            JSON.stringify(param) + '\n\n--' + boundary + "--"
-        });
-      })
-      .push(function (result) {
-        var obj = JSON.parse(result.target.responseText);
-
-        return obj.id;
-      },
-            function (error) {handleError(error, id); });
-  }
-
-  GdriveStorage.prototype.put = function (id, param) {
-    return sendMetaData(id, param, this._access_token);
-  };
-
-  GdriveStorage.prototype.post = function (param) {
-    return sendMetaData(undefined, param, this._access_token);
-  };
-
-  function sendData(id, blob, token) {
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          "type": "PUT",
-          "url": upload_template.expand({
-            access_token: token,
-            upload: "upload",
-            id: id,
-            uploadType: "media"
-          }),
-          data: blob
-        });
-      })
-      .push(function (data) {
-        data = JSON.parse(data.target.responseText);
-        if (data.mimeType === "application/vnd.google-apps.folder") {
-          throw new jIO.util.jIOError("cannot put attachments to folder", 400);
-        }
-        return data;
-      }, function (error) {handleError(error, id); });
-  }
-
-  GdriveStorage.prototype.putAttachment = function (id, name, blob) {
-    checkName(name);
-    return sendData(id, blob, this._access_token);
-  };
-
-  GdriveStorage.prototype.remove = function (id) {
-    var that  = this;
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          type: that._trashing ? "POST" : "DELETE",
-          url: remove_template.expand({
-            id : id,
-            access_token : that._access_token,
-            trash : that._trashing ? "trash" : []
-          })
-        });
-      })
-      .push(undefined, function (error) {handleError(error, id); });
-  };
-
-  function getData(id, attach, token) {
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          type: "GET",
-          dataType: attach ? "blob" : "json",
-          url: get_template.expand({
-            id: id,
-            alt: attach ? "media" : [],
-            access_token: token
-          }),
-          headers: {
-            "Authorization" : "Bearer " + token
-          }
-        });
-      })
-      .push(function (evt) {
-        return evt.target.response ||
-          (attach ? new Blob([evt.target.responseText],
-                             {"type" :
-                              evt.target.responseHeaders["Content-Type"]}) :
-              JSON.parse(evt.target.responseText));
-      }, function (error) {handleError(error, id); });
-  }
-
-  GdriveStorage.prototype.get = function (id) {
-    return getData(id, false, this._access_token);
-  };
-
-  GdriveStorage.prototype.getAttachment = function (id, name) {
-    checkName(name);
-    return getData(id, true, this._access_token);
-  };
-
-  GdriveStorage.prototype.allAttachments = function (id) {
-    var token = this._access_token;
-
-    return new RSVP.Queue()
-      .push(function () {
-        return getData(id, false, token);
-      })
-      .push(function (data) {
-        if (data.mimeType === "application/vnd.google-apps.folder") {
-          return {};
-        }
-        return {"enclosure": {}};
-      });
-  };
-
-  jIO.addStorage('gdrive', GdriveStorage);
-
-}(jIO, Blob, RSVP, UriTemplate, JSON));
-;/*jslint nomen: true */
-/*global RSVP*/
-
-/**
- * JIO Union Storage. Type = 'union'.
- * This provide a unified access other multiple storage.
- * New document are created in the first sub storage.
- * Document are searched in each sub storage until it is found.
- * 
- *
- * Storage Description:
- *
- *     {
- *       "type": "union",
- *       "storage_list": [
- *         sub_storage_description_1,
- *         sub_storage_description_2,
- *
- *         sub_storage_description_X,
- *       ]
- *     }
- *
- * @class UnionStorage
- */
-
-(function (jIO, RSVP) {
-  "use strict";
-
-  /**
-   * The JIO UnionStorage extension
-   *
-   * @class UnionStorage
-   * @constructor
-   */
-  function UnionStorage(spec) {
-    if (!Array.isArray(spec.storage_list)) {
-      throw new jIO.util.jIOError("storage_list is not an Array", 400);
-    }
-    var i;
-    this._storage_list = [];
-    for (i = 0; i < spec.storage_list.length; i += 1) {
-      this._storage_list.push(jIO.createJIO(spec.storage_list[i]));
-    }
-  }
-
-  UnionStorage.prototype._getWithStorageIndex = function () {
-    var i,
-      index = 0,
-      context = this,
-      arg = arguments,
-      result = this._storage_list[0].get.apply(this._storage_list[0], arg);
-
-    function handle404(j) {
-      result
-        .push(undefined, function (error) {
-          if ((error instanceof jIO.util.jIOError) &&
-              (error.status_code === 404)) {
-            return context._storage_list[j].get.apply(context._storage_list[j],
-                                                      arg)
-              .push(function (doc) {
-                index = j;
-                return doc;
-              });
-          }
-          throw error;
-        });
-    }
-
-    for (i = 1; i < this._storage_list.length; i += 1) {
-      handle404(i);
-    }
-    return result
-      .push(function (doc) {
-        return [index, doc];
-      });
-  };
-
-  /*
-   * Get a document
-   * Try on each substorage on after the other
-   */
-  UnionStorage.prototype.get = function () {
-    return this._getWithStorageIndex.apply(this, arguments)
-      .push(function (result) {
-        return result[1];
-      });
-  };
-
-  /*
-   * Get attachments list
-   * Try on each substorage on after the other
-   */
-  UnionStorage.prototype.allAttachments = function () {
-    var argument_list = arguments,
-      context = this;
-    return this._getWithStorageIndex.apply(this, arguments)
-      .push(function (result) {
-        var sub_storage = context._storage_list[result[0]];
-        return sub_storage.allAttachments.apply(sub_storage, argument_list);
-      });
-  };
-
-  /*
-   * Post a document
-   * Simply store on the first substorage
-   */
-  UnionStorage.prototype.post = function () {
-    return this._storage_list[0].post.apply(this._storage_list[0], arguments);
-  };
-
-  /*
-   * Put a document
-   * Search the document location, and modify it in its storage.
-   */
-  UnionStorage.prototype.put = function () {
-    var arg = arguments,
-      context = this;
-    return this._getWithStorageIndex(arg[0])
-      .push(undefined, function (error) {
-        if ((error instanceof jIO.util.jIOError) &&
-            (error.status_code === 404)) {
-          // Document does not exist, create in first substorage
-          return [0];
-        }
-        throw error;
-      })
-      .push(function (result) {
-        // Storage found, modify in it directly
-        var sub_storage = context._storage_list[result[0]];
-        return sub_storage.put.apply(sub_storage, arg);
-      });
-  };
-
-  /*
-   * Remove a document
-   * Search the document location, and remove it from its storage.
-   */
-  UnionStorage.prototype.remove = function () {
-    var arg = arguments,
-      context = this;
-    return this._getWithStorageIndex(arg[0])
-      .push(function (result) {
-        // Storage found, remove from it directly
-        var sub_storage = context._storage_list[result[0]];
-        return sub_storage.remove.apply(sub_storage, arg);
-      });
-  };
-
-  UnionStorage.prototype.buildQuery = function () {
-    var promise_list = [],
-      i,
-      id_dict = {},
-      len = this._storage_list.length,
-      sub_storage;
-    for (i = 0; i < len; i += 1) {
-      sub_storage = this._storage_list[i];
-      promise_list.push(sub_storage.buildQuery.apply(sub_storage, arguments));
-    }
-    return new RSVP.Queue()
-      .push(function () {
-        return RSVP.all(promise_list);
-      })
-      .push(function (result_list) {
-        var result = [],
-          sub_result,
-          sub_result_len,
-          j;
-        len = result_list.length;
-        for (i = 0; i < len; i += 1) {
-          sub_result = result_list[i];
-          sub_result_len = sub_result.length;
-          for (j = 0; j < sub_result_len; j += 1) {
-            if (!id_dict.hasOwnProperty(sub_result[j].id)) {
-              id_dict[sub_result[j].id] = null;
-              result.push(sub_result[j]);
-            }
-          }
-        }
-        return result;
-      });
-  };
-
-  UnionStorage.prototype.hasCapacity = function (name) {
-    var i,
-      len,
-      result,
-      sub_storage;
-    if ((name === "list") ||
-            (name === "query") ||
-            (name === "select")) {
-      result = true;
-      len = this._storage_list.length;
-      for (i = 0; i < len; i += 1) {
-        sub_storage = this._storage_list[i];
-        result = result && sub_storage.hasCapacity(name);
-      }
-      return result;
-    }
-    return false;
-  };
-
-  UnionStorage.prototype.repair = function () {
-    var i,
-      promise_list = [];
-    for (i = 0; i < this._storage_list.length; i += 1) {
-      promise_list.push(this._storage_list[i].repair.apply(
-        this._storage_list[i],
-        arguments
-      ));
-    }
-    return RSVP.all(promise_list);
-  };
-
-  UnionStorage.prototype.getAttachment = function () {
-    var argument_list = arguments,
-      context = this;
-    return this._getWithStorageIndex.apply(this, arguments)
-      .push(function (result) {
-        var sub_storage = context._storage_list[result[0]];
-        return sub_storage.getAttachment.apply(sub_storage, argument_list);
-      });
-  };
-
-  UnionStorage.prototype.putAttachment = function () {
-    var argument_list = arguments,
-      context = this;
-    return this._getWithStorageIndex.apply(this, arguments)
-      .push(function (result) {
-        var sub_storage = context._storage_list[result[0]];
-        return sub_storage.putAttachment.apply(sub_storage, argument_list);
-      });
-  };
-
-  UnionStorage.prototype.removeAttachment = function () {
-    var argument_list = arguments,
-      context = this;
-    return this._getWithStorageIndex.apply(this, arguments)
-      .push(function (result) {
-        var sub_storage = context._storage_list[result[0]];
-        return sub_storage.removeAttachment.apply(sub_storage, argument_list);
-      });
-  };
-
-  jIO.addStorage('union', UnionStorage);
-
-}(jIO, RSVP));
-;/*
- * Copyright 2013, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-// JIO ERP5 Storage Description :
-// {
-//   type: "erp5"
-//   url: {string}
-// }
-
-/*jslint nomen: true, unparam: true */
-/*global jIO, UriTemplate, FormData, RSVP, URI, Blob,
-         SimpleQuery, ComplexQuery*/
-
-(function (jIO, UriTemplate, FormData, RSVP, URI, Blob,
-           SimpleQuery, ComplexQuery) {
-  "use strict";
-
-  function getSiteDocument(storage) {
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.ajax({
-          "type": "GET",
-          "url": storage._url,
-          "xhrFields": {
-            withCredentials: true
-          }
-        });
-      })
-      .push(function (event) {
-        return JSON.parse(event.target.responseText);
-      });
-  }
-
-  function getDocumentAndHateoas(storage, id, options) {
-    if (options === undefined) {
-      options = {};
-    }
-    return getSiteDocument(storage)
-      .push(function (site_hal) {
-        // XXX need to get modified metadata
-        return new RSVP.Queue()
-          .push(function () {
-            return jIO.util.ajax({
-              "type": "GET",
-              "url": UriTemplate.parse(site_hal._links.traverse.href)
-                                .expand({
-                  relative_url: id,
-                  view: options._view
-                }),
-              "xhrFields": {
-                withCredentials: true
-              }
-            });
-          })
-          .push(undefined, function (error) {
-            if ((error.target !== undefined) &&
-                (error.target.status === 404)) {
-              throw new jIO.util.jIOError("Cannot find document: " + id, 404);
-            }
-            throw error;
-          });
-      });
-  }
-
-  var allowed_field_dict = {
-    "StringField": null,
-    "EmailField": null,
-    "IntegerField": null,
-    "FloatField": null,
-    "TextAreaField": null
-  };
-
-  function extractPropertyFromFormJSON(json) {
-    return new RSVP.Queue()
-      .push(function () {
-        var form = json._embedded._view,
-          converted_json = {
-            portal_type: json._links.type.name
-          },
-          form_data_json = {},
-          field,
-          key,
-          prefix_length,
-          result;
-
-        if (json._links.hasOwnProperty('parent')) {
-          converted_json.parent_relative_url =
-            new URI(json._links.parent.href).segment(2);
-        }
-
-        form_data_json.form_id = {
-          "key": [form.form_id.key],
-          "default": form.form_id["default"]
-        };
-        // XXX How to store datetime
-        for (key in form) {
-          if (form.hasOwnProperty(key)) {
-            field = form[key];
-            prefix_length = 0;
-            if (key.indexOf('my_') === 0 && field.editable) {
-              prefix_length = 3;
-            }
-            if (key.indexOf('your_') === 0) {
-              prefix_length = 5;
-            }
-            if ((prefix_length !== 0) &&
-                (allowed_field_dict.hasOwnProperty(field.type))) {
-              form_data_json[key.substring(prefix_length)] = {
-                "default": field["default"],
-                "key": field.key
-              };
-              converted_json[key.substring(prefix_length)] = field["default"];
-            }
-          }
-        }
-
-        result = {
-          data: converted_json,
-          form_data: form_data_json
-        };
-        if (form.hasOwnProperty('_actions') &&
-            form._actions.hasOwnProperty('put')) {
-          result.action_href = form._actions.put.href;
-        }
-        return result;
-      });
-  }
-
-  function extractPropertyFromForm(context, id) {
-    return context.getAttachment(id, "view")
-      .push(function (blob) {
-        return jIO.util.readBlobAsText(blob);
-      })
-      .push(function (evt) {
-        return JSON.parse(evt.target.result);
-      })
-      .push(function (json) {
-        return extractPropertyFromFormJSON(json);
-      });
-  }
-
-  // XXX docstring
-  function ERP5Storage(spec) {
-    if (typeof spec.url !== "string" || !spec.url) {
-      throw new TypeError("ERP5 'url' must be a string " +
-                          "which contains more than one character.");
-    }
-    this._url = spec.url;
-    this._default_view_reference = spec.default_view_reference;
-  }
-
-  function convertJSONToGet(json) {
-    var key,
-      result = json.data;
-    // Remove all ERP5 hateoas links / convert them into jIO ID
-    for (key in result) {
-      if (result.hasOwnProperty(key)) {
-        if (!result[key]) {
-          delete result[key];
-        }
-      }
-    }
-    return result;
-  }
-
-  ERP5Storage.prototype.get = function (id) {
-    return extractPropertyFromForm(this, id)
-      .push(function (result) {
-        return convertJSONToGet(result);
-      });
-  };
-
-  ERP5Storage.prototype.bulk = function (request_list) {
-    var i,
-      storage = this,
-      bulk_list = [];
-
-
-    for (i = 0; i < request_list.length; i += 1) {
-      if (request_list[i].method !== "get") {
-        throw new Error("ERP5Storage: not supported " +
-                        request_list[i].method + " in bulk");
-      }
-      bulk_list.push({
-        relative_url: request_list[i].parameter_list[0],
-        view: storage._default_view_reference
-      });
-    }
-    return getSiteDocument(storage)
-      .push(function (site_hal) {
-        var form_data = new FormData();
-        form_data.append("bulk_list", JSON.stringify(bulk_list));
-        return jIO.util.ajax({
-          "type": "POST",
-          "url": site_hal._actions.bulk.href,
-          "data": form_data,
-//           "headers": {
-//             "Content-Type": "application/json"
-//           },
-          "xhrFields": {
-            withCredentials: true
-          }
-        });
-      })
-      .push(function (response) {
-        var result_list = [],
-          hateoas = JSON.parse(response.target.responseText);
-
-        function pushResult(json) {
-          return extractPropertyFromFormJSON(json)
-            .push(function (json2) {
-              return convertJSONToGet(json2);
-            });
-        }
-
-        for (i = 0; i < hateoas.result_list.length; i += 1) {
-          result_list.push(pushResult(hateoas.result_list[i]));
-        }
-        return RSVP.all(result_list);
-      });
-  };
-
-  ERP5Storage.prototype.post = function (data) {
-    var context = this,
-      new_id;
-
-    return getSiteDocument(this)
-      .push(function (site_hal) {
-        var form_data = new FormData();
-        form_data.append("portal_type", data.portal_type);
-        form_data.append("parent_relative_url", data.parent_relative_url);
-        return jIO.util.ajax({
-          type: "POST",
-          url: site_hal._actions.add.href,
-          data: form_data,
-          xhrFields: {
-            withCredentials: true
-          }
-        });
-      })
-      .push(function (evt) {
-        var location = evt.target.getResponseHeader("X-Location"),
-          uri = new URI(location);
-        new_id = uri.segment(2);
-        return context.put(new_id, data);
-      })
-      .push(function () {
-        return new_id;
-      });
-  };
-
-  ERP5Storage.prototype.put = function (id, data) {
-    var context = this;
-
-    return extractPropertyFromForm(context, id)
-      .push(function (result) {
-        var key,
-          json = result.form_data,
-          form_data = {};
-        form_data[json.form_id.key] = json.form_id["default"];
-
-        // XXX How to store datetime:!!!!!
-        for (key in data) {
-          if (data.hasOwnProperty(key)) {
-            if (key === "form_id") {
-              throw new jIO.util.jIOError(
-                "ERP5: forbidden property: " + key,
-                400
-              );
-            }
-            if ((key !== "portal_type") && (key !== "parent_relative_url")) {
-              if (!json.hasOwnProperty(key)) {
-                throw new jIO.util.jIOError(
-                  "ERP5: can not store property: " + key,
-                  400
-                );
-              }
-              form_data[json[key].key] = data[key];
-            }
-          }
-        }
-        if (!result.hasOwnProperty('action_href')) {
-          throw new jIO.util.jIOError(
-            "ERP5: can not modify document: " + id,
-            403
-          );
-        }
-        return context.putAttachment(
-          id,
-          result.action_href,
-          new Blob([JSON.stringify(form_data)], {type: "application/json"})
-        );
-      });
-  };
-
-  ERP5Storage.prototype.allAttachments = function (id) {
-    var context = this;
-    return getDocumentAndHateoas(this, id)
-      .push(function () {
-        if (context._default_view_reference === undefined) {
-          return {
-            links: {}
-          };
-        }
-        return {
-          view: {},
-          links: {}
-        };
-      });
-  };
-
-  ERP5Storage.prototype.getAttachment = function (id, action, options) {
-    if (options === undefined) {
-      options = {};
-    }
-    if (action === "view") {
-      if (this._default_view_reference === undefined) {
-        throw new jIO.util.jIOError(
-          "Cannot find attachment view for: " + id,
-          404
-        );
-      }
-      return getDocumentAndHateoas(this, id,
-                                   {"_view": this._default_view_reference})
-        .push(function (response) {
-          var result = JSON.parse(response.target.responseText);
-          // Remove all ERP5 hateoas links / convert them into jIO ID
-
-          // XXX Change default action to an jio urn with attachment name inside
-          // if Base_edit, do put URN
-          // if others, do post URN (ie, unique new attachment name)
-          // XXX Except this attachment name should be generated when
-          return new Blob(
-            [JSON.stringify(result)],
-            {"type": 'application/hal+json'}
-          );
-        });
-    }
-    if (action === "links") {
-      return getDocumentAndHateoas(this, id)
-        .push(function (response) {
-          return new Blob(
-            [JSON.stringify(JSON.parse(response.target.responseText))],
-            {"type": 'application/hal+json'}
-          );
-        });
-    }
-    if (action.indexOf(this._url) === 0) {
-      return new RSVP.Queue()
-        .push(function () {
-          var start,
-            end,
-            range,
-            request_options = {
-              "type": "GET",
-              "dataType": "blob",
-              "url": action,
-              "xhrFields": {
-                withCredentials: true
-              }
-            };
-          if (options.start !== undefined ||  options.end !== undefined) {
-            start = options.start || 0;
-            end = options.end;
-            if (end !== undefined && end < 0) {
-              throw new jIO.util.jIOError("end must be positive",
-                                          400);
-            }
-            if (start < 0) {
-              range = "bytes=" + start;
-            } else if (end === undefined) {
-              range = "bytes=" + start + "-";
-            } else {
-              if (start > end) {
-                throw new jIO.util.jIOError("start is greater than end",
-                                            400);
-              }
-              range = "bytes=" + start + "-" + end;
-            }
-            request_options.headers = {Range: range};
-          }
-          return jIO.util.ajax(request_options);
-        })
-        .push(function (evt) {
-          if (evt.target.response === undefined) {
-            return new Blob(
-              [evt.target.responseText],
-              {"type": evt.target.getResponseHeader("Content-Type")}
-            );
-          }
-          return evt.target.response;
-        });
-    }
-    throw new jIO.util.jIOError("ERP5: not support get attachment: " + action,
-                                400);
-  };
-
-  ERP5Storage.prototype.putAttachment = function (id, name, blob) {
-    // Assert we use a callable on a document from the ERP5 site
-    if (name.indexOf(this._url) !== 0) {
-      throw new jIO.util.jIOError("Can not store outside ERP5: " +
-                                  name, 400);
-    }
-
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.readBlobAsText(blob);
-      })
-      .push(function (evt) {
-        var form_data = JSON.parse(evt.target.result),
-          data = new FormData(),
-          array,
-          i,
-          key,
-          value;
-        for (key in form_data) {
-          if (form_data.hasOwnProperty(key)) {
-            if (Array.isArray(form_data[key])) {
-              array = form_data[key];
-            } else {
-              array = [form_data[key]];
-            }
-            for (i = 0; i < array.length; i += 1) {
-              value = array[i];
-              if (typeof value === "object") {
-                data.append(key, jIO.util.dataURItoBlob(value.url),
-                            value.file_name);
-              } else {
-                data.append(key, value);
-              }
-            }
-          }
-        }
-        return jIO.util.ajax({
-          "type": "POST",
-          "url": name,
-          "data": data,
-          "xhrFields": {
-            withCredentials: true
-          }
-        });
-      });
-  };
-
-  ERP5Storage.prototype.hasCapacity = function (name) {
-    return ((name === "list") || (name === "query") ||
-            (name === "select") || (name === "limit") ||
-            (name === "sort"));
-  };
-
-  function isSingleLocalRoles(parsed_query) {
-    if ((parsed_query instanceof SimpleQuery) &&
-        (parsed_query.key === 'local_roles')) {
-      // local_roles:"Assignee"
-      return parsed_query.value;
-    }
-  }
-
-  function isMultipleLocalRoles(parsed_query) {
-    var i,
-      sub_query,
-      is_multiple = true,
-      local_role_list = [];
-    if ((parsed_query instanceof ComplexQuery) &&
-        (parsed_query.operator === 'OR')) {
-
-      for (i = 0; i < parsed_query.query_list.length; i += 1) {
-        sub_query = parsed_query.query_list[i];
-        if ((sub_query instanceof SimpleQuery) &&
-            (sub_query.key === 'local_roles')) {
-          local_role_list.push(sub_query.value);
-        } else {
-          is_multiple = false;
-        }
-      }
-      if (is_multiple) {
-        // local_roles:"Assignee" OR local_roles:"Assignor"
-        return local_role_list;
-      }
-    }
-  }
-
-  ERP5Storage.prototype.buildQuery = function (options) {
-//     if (typeof options.query !== "string") {
-//       options.query = (options.query ?
-//                        jIO.Query.objectToSearchText(options.query) :
-//                        undefined);
-//     }
-    return getSiteDocument(this)
-      .push(function (site_hal) {
-        var query = options.query,
-          i,
-          parsed_query,
-          sub_query,
-          result_list,
-          local_roles,
-          sort_list = [];
-        if (options.query) {
-          parsed_query = jIO.QueryFactory.create(options.query);
-
-          result_list = isSingleLocalRoles(parsed_query);
-          if (result_list) {
-            query = undefined;
-            local_roles = result_list;
-          } else {
-
-            result_list = isMultipleLocalRoles(parsed_query);
-            if (result_list) {
-              query = undefined;
-              local_roles = result_list;
-            } else if ((parsed_query instanceof ComplexQuery) &&
-                       (parsed_query.operator === 'AND')) {
-
-              // portal_type:"Person" AND local_roles:"Assignee"
-              for (i = 0; i < parsed_query.query_list.length; i += 1) {
-                sub_query = parsed_query.query_list[i];
-
-                result_list = isSingleLocalRoles(sub_query);
-                if (result_list) {
-                  local_roles = result_list;
-                  parsed_query.query_list.splice(i, 1);
-                  query = jIO.Query.objectToSearchText(parsed_query);
-                  i = parsed_query.query_list.length;
-                } else {
-                  result_list = isMultipleLocalRoles(sub_query);
-                  if (result_list) {
-                    local_roles = result_list;
-                    parsed_query.query_list.splice(i, 1);
-                    query = jIO.Query.objectToSearchText(parsed_query);
-                    i = parsed_query.query_list.length;
-                  }
-                }
-              }
-            }
-
-          }
-        }
-
-        if (options.sort_on) {
-          for (i = 0; i < options.sort_on.length; i += 1) {
-            sort_list.push(JSON.stringify(options.sort_on[i]));
-          }
-        }
-
-        return jIO.util.ajax({
-          "type": "GET",
-          "url": UriTemplate.parse(site_hal._links.raw_search.href)
-                            .expand({
-              query: query,
-              // XXX Force erp5 to return embedded document
-              select_list: options.select_list || ["title", "reference"],
-              limit: options.limit,
-              sort_on: sort_list,
-              local_roles: local_roles
-            }),
-          "xhrFields": {
-            withCredentials: true
-          }
-        });
-      })
-      .push(function (response) {
-        return JSON.parse(response.target.responseText);
-      })
-      .push(function (catalog_json) {
-        var data = catalog_json._embedded.contents,
-          count = data.length,
-          i,
-          uri,
-          item,
-          result = [];
-        for (i = 0; i < count; i += 1) {
-          item = data[i];
-          uri = new URI(item._links.self.href);
-          delete item._links;
-          result.push({
-            id: uri.segment(2),
-            value: item
-          });
-        }
-        return result;
-      });
-  };
-
-  jIO.addStorage("erp5", ERP5Storage);
-
-}(jIO, UriTemplate, FormData, RSVP, URI, Blob,
-  SimpleQuery, ComplexQuery));
-;/*jslint nomen: true*/
-/*global RSVP*/
-(function (jIO, RSVP) {
-  "use strict";
-
-  /**
-   * The jIO QueryStorage extension
-   *
-   * @class QueryStorage
-   * @constructor
-   */
-  function QueryStorage(spec) {
-    this._sub_storage = jIO.createJIO(spec.sub_storage);
-    this._key_schema = spec.key_schema;
-  }
-
-  QueryStorage.prototype.get = function () {
-    return this._sub_storage.get.apply(this._sub_storage, arguments);
-  };
-  QueryStorage.prototype.allAttachments = function () {
-    return this._sub_storage.allAttachments.apply(this._sub_storage, arguments);
-  };
-  QueryStorage.prototype.post = function () {
-    return this._sub_storage.post.apply(this._sub_storage, arguments);
-  };
-  QueryStorage.prototype.put = function () {
-    return this._sub_storage.put.apply(this._sub_storage, arguments);
-  };
-  QueryStorage.prototype.remove = function () {
-    return this._sub_storage.remove.apply(this._sub_storage, arguments);
-  };
-  QueryStorage.prototype.getAttachment = function () {
-    return this._sub_storage.getAttachment.apply(this._sub_storage, arguments);
-  };
-  QueryStorage.prototype.putAttachment = function () {
-    return this._sub_storage.putAttachment.apply(this._sub_storage, arguments);
-  };
-  QueryStorage.prototype.removeAttachment = function () {
-    return this._sub_storage.removeAttachment.apply(this._sub_storage,
-                                                    arguments);
-  };
-  QueryStorage.prototype.repair = function () {
-    return this._sub_storage.repair.apply(this._sub_storage, arguments);
-  };
-
-  QueryStorage.prototype.hasCapacity = function (name) {
-    var this_storage_capacity_list = ["limit",
-                                      "sort",
-                                      "select",
-                                      "query"];
-
-    if (this_storage_capacity_list.indexOf(name) !== -1) {
-      return true;
-    }
-    if (name === "list") {
-      return this._sub_storage.hasCapacity(name);
-    }
-    return false;
-  };
-  QueryStorage.prototype.buildQuery = function (options) {
-    var substorage = this._sub_storage,
-      context = this,
-      sub_options = {},
-      is_manual_query_needed = false,
-      is_manual_include_needed = false;
-
-    if (substorage.hasCapacity("list")) {
-
-      // Can substorage handle the queries if needed?
-      try {
-        if (((options.query === undefined) ||
-             (substorage.hasCapacity("query"))) &&
-            ((options.sort_on === undefined) ||
-             (substorage.hasCapacity("sort"))) &&
-            ((options.select_list === undefined) ||
-             (substorage.hasCapacity("select"))) &&
-            ((options.limit === undefined) ||
-             (substorage.hasCapacity("limit")))) {
-          sub_options.query = options.query;
-          sub_options.sort_on = options.sort_on;
-          sub_options.select_list = options.select_list;
-          sub_options.limit = options.limit;
-        }
-      } catch (error) {
-        if ((error instanceof jIO.util.jIOError) &&
-            (error.status_code === 501)) {
-          is_manual_query_needed = true;
-        } else {
-          throw error;
-        }
-      }
-
-      // Can substorage include the docs if needed?
-      try {
-        if ((is_manual_query_needed ||
-            (options.include_docs === true)) &&
-            (substorage.hasCapacity("include"))) {
-          sub_options.include_docs = true;
-        }
-      } catch (error) {
-        if ((error instanceof jIO.util.jIOError) &&
-            (error.status_code === 501)) {
-          is_manual_include_needed = true;
-        } else {
-          throw error;
-        }
-      }
-
-      return substorage.buildQuery(sub_options)
-
-        // Include docs if needed
-        .push(function (result) {
-          var include_query_list = [result],
-            len,
-            i;
-
-          function safeGet(j) {
-            var id = result[j].id;
-            return substorage.get(id)
-              .push(function (doc) {
-                // XXX Can delete user data!
-                doc._id = id;
-                return doc;
-              }, function (error) {
-                // Document may have been dropped after listing
-                if ((error instanceof jIO.util.jIOError) &&
-                    (error.status_code === 404)) {
-                  return;
-                }
-                throw error;
-              });
-          }
-
-          if (is_manual_include_needed) {
-            len = result.length;
-            for (i = 0; i < len; i += 1) {
-              include_query_list.push(safeGet(i));
-            }
-            result = RSVP.all(include_query_list);
-          }
-          return result;
-        })
-        .push(function (result) {
-          var original_result,
-            len,
-            i;
-          if (is_manual_include_needed) {
-            original_result = result[0];
-            len = original_result.length;
-            for (i = 0; i < len; i += 1) {
-              original_result[i].doc = result[i + 1];
-            }
-            result = original_result;
-          }
-          return result;
-
-        })
-
-        // Manual query if needed
-        .push(function (result) {
-          var data_rows = [],
-            len,
-            i;
-          if (is_manual_query_needed) {
-            len = result.length;
-            for (i = 0; i < len; i += 1) {
-              result[i].doc.__id = result[i].id;
-              data_rows.push(result[i].doc);
-            }
-            if (options.select_list) {
-              options.select_list.push("__id");
-            }
-            result = jIO.QueryFactory.create(options.query || "",
-                                             context._key_schema).
-              exec(data_rows, options);
-          }
-          return result;
-        })
-
-        // reconstruct filtered rows, preserving the order from docs
-        .push(function (result) {
-          var new_result = [],
-            element,
-            len,
-            i;
-          if (is_manual_query_needed) {
-            len = result.length;
-            for (i = 0; i < len; i += 1) {
-              element = {
-                id: result[i].__id,
-                value: options.select_list ? result[i] : {},
-                doc: {}
-              };
-              if (options.select_list) {
-                // Does not work if user manually request __id
-                delete element.value.__id;
-              }
-              if (options.include_docs) {
-                // XXX To implement
-                throw new Error("QueryStorage does not support include docs");
-              }
-              new_result.push(element);
-            }
-            result = new_result;
-          }
-          return result;
-        });
-
-    }
-  };
-
-  jIO.addStorage('query', QueryStorage);
-
-}(jIO, RSVP));
-;/*jslint nomen: true*/
-/*global RSVP, Blob*/
-(function (jIO, RSVP, Blob) {
-  "use strict";
-
-  /**
-   * The jIO FileSystemBridgeStorage extension
-   *
-   * @class FileSystemBridgeStorage
-   * @constructor
-   */
-  function FileSystemBridgeStorage(spec) {
-    this._sub_storage = jIO.createJIO(spec.sub_storage);
-  }
-  var DOCUMENT_EXTENSION = ".json",
-    DOCUMENT_KEY = "/.jio_documents/",
-    ROOT = "/";
-
-  function endsWith(str, suffix) {
-    return str.indexOf(suffix, str.length - suffix.length) !== -1;
-  }
-
-  FileSystemBridgeStorage.prototype.get = function (id) {
-    var context = this;
-    return new RSVP.Queue()
-
-      // First, try to get explicit reference to the document
-
-      .push(function () {
-        // First get the document itself if it exists
-        return context._sub_storage.getAttachment(
-          DOCUMENT_KEY,
-          id + DOCUMENT_EXTENSION,
-          {format: "json"}
-        );
-      })
-      .push(undefined, function (error) {
-        if ((error instanceof jIO.util.jIOError) &&
-            (error.status_code === 404)) {
-
-          // Second, try to get default attachment
-          return context._sub_storage.allAttachments(ROOT)
-            .push(function (attachment_dict) {
-              if (attachment_dict.hasOwnProperty(id)) {
-                return {};
-              }
-              throw new jIO.util.jIOError("Cannot find document " + id,
-                                          404);
-            });
-        }
-        throw error;
-      });
-  };
-
-  FileSystemBridgeStorage.prototype.allAttachments = function (id) {
-    var context = this;
-    return context._sub_storage.allAttachments(ROOT)
-      .push(function (attachment_dict) {
-        if (attachment_dict.hasOwnProperty(id)) {
-          return {
-            enclosure: {}
-          };
-        }
-        // Second get the document itself if it exists
-        return context._sub_storage.getAttachment(
-          DOCUMENT_KEY,
-          id + DOCUMENT_EXTENSION
-        )
-          .push(function () {
-            return {};
-          }, function (error) {
-            if ((error instanceof jIO.util.jIOError) &&
-                (error.status_code === 404)) {
-              throw new jIO.util.jIOError("Cannot find document " + id,
-                                          404);
-            }
-            throw error;
-          });
-      });
-
-  };
-
-  FileSystemBridgeStorage.prototype.put = function (doc_id, param) {
-    var context = this;
-    // XXX Handle conflict!
-
-    return context._sub_storage.putAttachment(
-      DOCUMENT_KEY,
-      doc_id + DOCUMENT_EXTENSION,
-      new Blob([JSON.stringify(param)], {type: "application/json"})
-    )
-      .push(undefined, function (error) {
-        if ((error instanceof jIO.util.jIOError) &&
-            (error.status_code === 404)) {
-          return context._sub_storage.put(DOCUMENT_KEY, {})
-            .push(function () {
-              return context._sub_storage.putAttachment(
-                DOCUMENT_KEY,
-                doc_id + DOCUMENT_EXTENSION,
-                new Blob([JSON.stringify(param)],
-                         {type: "application/json"})
-              );
-            });
-        }
-        throw error;
-      })
-      .push(function () {
-        return doc_id;
-      });
-
-  };
-
-  FileSystemBridgeStorage.prototype.remove = function (doc_id) {
-    var context = this,
-      got_error = false;
-    return new RSVP.Queue()
-
-      // First, try to remove enclosure
-      .push(function () {
-        return context._sub_storage.removeAttachment(
-          ROOT,
-          doc_id
-        );
-      })
-
-      .push(undefined, function (error) {
-        if ((error instanceof jIO.util.jIOError) &&
-            (error.status_code === 404)) {
-          got_error = true;
-          return;
-        }
-        throw error;
-      })
-
-      // Second, try to remove explicit doc
-      .push(function () {
-        return context._sub_storage.removeAttachment(
-          DOCUMENT_KEY,
-          doc_id + DOCUMENT_EXTENSION
-        );
-      })
-
-      .push(undefined, function (error) {
-        if ((!got_error) && (error instanceof jIO.util.jIOError) &&
-            (error.status_code === 404)) {
-          return doc_id;
-        }
-        throw error;
-      });
-
-  };
-
-  FileSystemBridgeStorage.prototype.hasCapacity = function (capacity) {
-    return (capacity === "list");
-  };
-
-  FileSystemBridgeStorage.prototype.buildQuery = function () {
-    var result_dict = {},
-      context = this;
-    return new RSVP.Queue()
-
-      // First, get list of explicit documents
-
-      .push(function () {
-        return context._sub_storage.allAttachments(DOCUMENT_KEY);
-      })
-      .push(function (result) {
-        var key;
-        for (key in result) {
-          if (result.hasOwnProperty(key)) {
-            if (endsWith(key, DOCUMENT_EXTENSION)) {
-              result_dict[key.substring(
-                0,
-                key.length - DOCUMENT_EXTENSION.length
-              )] = null;
-            }
-          }
-        }
-      }, function (error) {
-        if ((error instanceof jIO.util.jIOError) &&
-            (error.status_code === 404)) {
-          return;
-        }
-        throw error;
-      })
-
-      // Second, get list of enclosure
-
-      .push(function () {
-        return context._sub_storage.allAttachments(ROOT);
-      })
-      .push(function (result) {
-        var key;
-        for (key in result) {
-          if (result.hasOwnProperty(key)) {
-            result_dict[key] = null;
-          }
-        }
-      })
-
-      // Finally, build the result
-
-      .push(function () {
-        var result = [],
-          key;
-        for (key in result_dict) {
-          if (result_dict.hasOwnProperty(key)) {
-            result.push({
-              id: key,
-              value: {}
-            });
-          }
-        }
-        return result;
-      });
-
-  };
-
-  FileSystemBridgeStorage.prototype.getAttachment = function (id, name) {
-    if (name !== "enclosure") {
-      throw new jIO.util.jIOError("Only support 'enclosure' attachment",
-                                  400);
-    }
-
-    return this._sub_storage.getAttachment(ROOT, id);
-  };
-
-  FileSystemBridgeStorage.prototype.putAttachment = function (id, name, blob) {
-    if (name !== "enclosure") {
-      throw new jIO.util.jIOError("Only support 'enclosure' attachment",
-                                  400);
-    }
-
-    return this._sub_storage.putAttachment(
-      ROOT,
-      id,
-      blob
-    );
-  };
-
-  FileSystemBridgeStorage.prototype.removeAttachment = function (id, name) {
-    if (name !== "enclosure") {
-      throw new jIO.util.jIOError("Only support 'enclosure' attachment",
-                                  400);
-    }
-
-    return this._sub_storage.removeAttachment(ROOT, id);
-  };
-
-  FileSystemBridgeStorage.prototype.repair = function () {
-    return this._sub_storage.repair.apply(this._sub_storage, arguments);
-  };
-
-  jIO.addStorage('drivetojiomapping', FileSystemBridgeStorage);
-
-}(jIO, RSVP, Blob));
-;/*jslint nomen: true*/
-/*global Blob, atob, btoa, RSVP*/
-(function (jIO, Blob, atob, btoa, RSVP) {
-  "use strict";
-
-  /**
-   * The jIO DocumentStorage extension
-   *
-   * @class DocumentStorage
-   * @constructor
-   */
-  function DocumentStorage(spec) {
-    this._sub_storage = jIO.createJIO(spec.sub_storage);
-    this._document_id = spec.document_id;
-    this._repair_attachment = spec.repair_attachment || false;
-  }
-
-  var DOCUMENT_EXTENSION = ".json",
-    DOCUMENT_REGEXP = new RegExp("^jio_document/([\\w=]+)" +
-                                 DOCUMENT_EXTENSION + "$"),
-    ATTACHMENT_REGEXP = new RegExp("^jio_attachment/([\\w=]+)/([\\w=]+)$");
-
-  function getSubAttachmentIdFromParam(id, name) {
-    if (name === undefined) {
-      return 'jio_document/' + btoa(id) + DOCUMENT_EXTENSION;
-    }
-    return 'jio_attachment/' + btoa(id) + "/" + btoa(name);
-  }
-
-  DocumentStorage.prototype.get = function (id) {
-    return this._sub_storage.getAttachment(
-      this._document_id,
-      getSubAttachmentIdFromParam(id),
-      {format: "json"}
-    );
-  };
-
-  DocumentStorage.prototype.allAttachments = function (id) {
-    return this._sub_storage.allAttachments(this._document_id)
-      .push(function (result) {
-        var attachments = {},
-          exec,
-          key;
-        for (key in result) {
-          if (result.hasOwnProperty(key)) {
-            if (ATTACHMENT_REGEXP.test(key)) {
-              exec = ATTACHMENT_REGEXP.exec(key);
-              try {
-                if (atob(exec[1]) === id) {
-                  attachments[atob(exec[2])] = {};
-                }
-              } catch (error) {
-                // Check if unable to decode base64 data
-                if (!error instanceof ReferenceError) {
-                  throw error;
-                }
-              }
-            }
-          }
-        }
-        return attachments;
-      });
-  };
-
-  DocumentStorage.prototype.put = function (doc_id, param) {
-    return this._sub_storage.putAttachment(
-      this._document_id,
-      getSubAttachmentIdFromParam(doc_id),
-      new Blob([JSON.stringify(param)], {type: "application/json"})
-    )
-      .push(function () {
-        return doc_id;
-      });
-
-  };
-
-  DocumentStorage.prototype.remove = function (id) {
-    var context = this;
-    return this.allAttachments(id)
-      .push(function (result) {
-        var key,
-          promise_list = [];
-        for (key in result) {
-          if (result.hasOwnProperty(key)) {
-            promise_list.push(context.removeAttachment(id, key));
-          }
-        }
-        return RSVP.all(promise_list);
-      })
-      .push(function () {
-        return context._sub_storage.removeAttachment(
-          context._document_id,
-          getSubAttachmentIdFromParam(id)
-        );
-      })
-      .push(function () {
-        return id;
-      });
-  };
-
-  DocumentStorage.prototype.repair = function () {
-    var context = this;
-    return this._sub_storage.repair.apply(this._sub_storage, arguments)
-      .push(function (result) {
-        if (context._repair_attachment) {
-          return context._sub_storage.allAttachments(context._document_id)
-            .push(function (result_dict) {
-              var promise_list = [],
-                id_dict = {},
-                attachment_dict = {},
-                id,
-                attachment,
-                exec,
-                key;
-              for (key in result_dict) {
-                if (result_dict.hasOwnProperty(key)) {
-                  id = undefined;
-                  attachment = undefined;
-                  if (DOCUMENT_REGEXP.test(key)) {
-                    try {
-                      id = atob(DOCUMENT_REGEXP.exec(key)[1]);
-                    } catch (error) {
-                      // Check if unable to decode base64 data
-                      if (!error instanceof ReferenceError) {
-                        throw error;
-                      }
-                    }
-                    if (id !== undefined) {
-                      id_dict[id] = null;
-                    }
-                  } else if (ATTACHMENT_REGEXP.test(key)) {
-                    exec = ATTACHMENT_REGEXP.exec(key);
-                    try {
-                      id = atob(exec[1]);
-                      attachment = atob(exec[2]);
-                    } catch (error) {
-                      // Check if unable to decode base64 data
-                      if (!error instanceof ReferenceError) {
-                        throw error;
-                      }
-                    }
-                    if (attachment !== undefined) {
-                      if (!id_dict.hasOwnProperty(id)) {
-                        if (!attachment_dict.hasOwnProperty(id)) {
-                          attachment_dict[id] = {};
-                        }
-                        attachment_dict[id][attachment] = null;
-                      }
-                    }
-                  }
-                }
-              }
-              for (id in attachment_dict) {
-                if (attachment_dict.hasOwnProperty(id)) {
-                  if (!id_dict.hasOwnProperty(id)) {
-                    for (attachment in attachment_dict[id]) {
-                      if (attachment_dict[id].hasOwnProperty(attachment)) {
-                        promise_list.push(context.removeAttachment(
-                          id,
-                          attachment
-                        ));
-                      }
-                    }
-                  }
-                }
-              }
-              return RSVP.all(promise_list);
-            });
-        }
-        return result;
-      });
-  };
-
-  DocumentStorage.prototype.hasCapacity = function (capacity) {
-    return (capacity === "list");
-  };
-
-  DocumentStorage.prototype.buildQuery = function () {
-    return this._sub_storage.allAttachments(this._document_id)
-      .push(function (attachment_dict) {
-        var result = [],
-          key;
-        for (key in attachment_dict) {
-          if (attachment_dict.hasOwnProperty(key)) {
-            if (DOCUMENT_REGEXP.test(key)) {
-              try {
-                result.push({
-                  id: atob(DOCUMENT_REGEXP.exec(key)[1]),
-                  value: {}
-                });
-              } catch (error) {
-                // Check if unable to decode base64 data
-                if (!error instanceof ReferenceError) {
-                  throw error;
-                }
-              }
-            }
-          }
-        }
-        return result;
-      });
-  };
-
-  DocumentStorage.prototype.getAttachment = function (id, name) {
-    return this._sub_storage.getAttachment(
-      this._document_id,
-      getSubAttachmentIdFromParam(id, name)
-    );
-  };
-
-  DocumentStorage.prototype.putAttachment = function (id, name, blob) {
-    return this._sub_storage.putAttachment(
-      this._document_id,
-      getSubAttachmentIdFromParam(id, name),
-      blob
-    );
-  };
-
-  DocumentStorage.prototype.removeAttachment = function (id, name) {
-    return this._sub_storage.removeAttachment(
-      this._document_id,
-      getSubAttachmentIdFromParam(id, name)
-    );
-  };
-
-  jIO.addStorage('document', DocumentStorage);
-
-}(jIO, Blob, atob, btoa, RSVP));
-;/*
- * Copyright 2013, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-
-/*jslint nomen: true*/
-/*global jIO, sessionStorage, localStorage, RSVP */
-
-/**
- * JIO Local Storage. Type = 'local'.
- * Local browser "database" storage.
- *
- * Storage Description:
- *
- *     {
- *       "type": "local",
- *       "sessiononly": false
- *     }
- *
- * @class LocalStorage
- */
-
-(function (jIO, sessionStorage, localStorage, RSVP) {
-  "use strict";
-
-  function LocalStorage(spec) {
-    if (spec.sessiononly === true) {
-      this._storage = sessionStorage;
-    } else {
-      this._storage = localStorage;
-    }
-  }
-
-  function restrictDocumentId(id) {
-    if (id !== "/") {
-      throw new jIO.util.jIOError("id " + id + " is forbidden (!== /)",
-                                  400);
-    }
-  }
-
-  LocalStorage.prototype.get = function (id) {
-    restrictDocumentId(id);
-    return {};
-  };
-
-  LocalStorage.prototype.allAttachments = function (id) {
-    restrictDocumentId(id);
-
-    var attachments = {},
-      key;
-
-    for (key in this._storage) {
-      if (this._storage.hasOwnProperty(key)) {
-        attachments[key] = {};
-      }
-    }
-    return attachments;
-  };
-
-  LocalStorage.prototype.getAttachment = function (id, name) {
-    restrictDocumentId(id);
-
-    var textstring = this._storage.getItem(name);
-
-    if (textstring === null) {
-      throw new jIO.util.jIOError(
-        "Cannot find attachment " + name,
-        404
-      );
-    }
-    return jIO.util.dataURItoBlob(textstring);
-  };
-
-  LocalStorage.prototype.putAttachment = function (id, name, blob) {
-    var context = this;
-    restrictDocumentId(id);
-
-    // the document already exists
-    // download data
-    return new RSVP.Queue()
-      .push(function () {
-        return jIO.util.readBlobAsDataURL(blob);
-      })
-      .push(function (e) {
-        context._storage.setItem(name, e.target.result);
-      });
-  };
-
-  LocalStorage.prototype.removeAttachment = function (id, name) {
-    restrictDocumentId(id);
-    return this._storage.removeItem(name);
-  };
-
-
-  LocalStorage.prototype.hasCapacity = function (name) {
-    return (name === "list");
-  };
-
-  LocalStorage.prototype.buildQuery = function () {
-    return [{
-      id: "/",
-      value: {}
-    }];
-  };
-
-  jIO.addStorage('local', LocalStorage);
-
-}(jIO, sessionStorage, localStorage, RSVP));
-;/*
- * Copyright 2014, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-
-/**
- * JIO Indexed Database Storage.
- *
- * A local browser "database" storage greatly more powerful than localStorage.
- *
- * Description:
- *
- *    {
- *      "type": "indexeddb",
- *      "database": <string>
- *    }
- *
- * The database name will be prefixed by "jio:", so if the database property is
- * "hello", then you can manually reach this database with
- * `indexedDB.open("jio:hello");`. (Or
- * `indexedDB.deleteDatabase("jio:hello");`.)
- *
- * For more informations:
- *
- * - http://www.w3.org/TR/IndexedDB/
- * - https://developer.mozilla.org/en-US/docs/IndexedDB/Using_IndexedDB
- */
-
-/*jslint nomen: true */
-/*global indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest,
-        DOMError, Event*/
-
-(function (indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest,
-           DOMError) {
-  "use strict";
-
-  // Read only as changing it can lead to data corruption
-  var UNITE = 2000000;
-
-  function IndexedDBStorage(description) {
-    if (typeof description.database !== "string" ||
-        description.database === "") {
-      throw new TypeError("IndexedDBStorage 'database' description property " +
-                          "must be a non-empty string");
-    }
-    this._database_name = "jio:" + description.database;
-  }
-
-  IndexedDBStorage.prototype.hasCapacity = function (name) {
-    return ((name === "list") || (name === "include"));
-  };
-
-  function buildKeyPath(key_list) {
-    return key_list.join("_");
-  }
-
-  function handleUpgradeNeeded(evt) {
-    var db = evt.target.result,
-      store;
-
-    store = db.createObjectStore("metadata", {
-      keyPath: "_id",
-      autoIncrement: false
-    });
-    // It is not possible to use openKeyCursor on keypath directly
-    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=19955
-    store.createIndex("_id", "_id", {unique: true});
-
-    store = db.createObjectStore("attachment", {
-      keyPath: "_key_path",
-      autoIncrement: false
-    });
-    store.createIndex("_id", "_id", {unique: false});
-
-    store = db.createObjectStore("blob", {
-      keyPath: "_key_path",
-      autoIncrement: false
-    });
-    store.createIndex("_id_attachment",
-                      ["_id", "_attachment"], {unique: false});
-    store.createIndex("_id", "_id", {unique: false});
-  }
-
-  function openIndexedDB(jio_storage) {
-    var db_name = jio_storage._database_name;
-    function resolver(resolve, reject) {
-      // Open DB //
-      var request = indexedDB.open(db_name);
-      request.onerror = function (error) {
-        if (request.result) {
-          request.result.close();
-        }
-        if ((error !== undefined) &&
-            (error.target instanceof IDBOpenDBRequest) &&
-            (error.target.error instanceof DOMError)) {
-          reject("Connection to: " + db_name + " failed: " +
-                 error.target.error.message);
-        } else {
-          reject(error);
-        }
-      };
-
-      request.onabort = function () {
-        request.result.close();
-        reject("Aborting connection to: " + db_name);
-      };
-
-      request.ontimeout = function () {
-        request.result.close();
-        reject("Connection to: " + db_name + " timeout");
-      };
-
-      request.onblocked = function () {
-        request.result.close();
-        reject("Connection to: " + db_name + " was blocked");
-      };
-
-      // Create DB if necessary //
-      request.onupgradeneeded = handleUpgradeNeeded;
-
-      request.onversionchange = function () {
-        request.result.close();
-        reject(db_name + " was upgraded");
-      };
-
-      request.onsuccess = function () {
-        resolve(request.result);
-      };
-    }
-    // XXX Canceller???
-    return new RSVP.Queue()
-      .push(function () {
-        return new RSVP.Promise(resolver);
-      });
-  }
-
-  function openTransaction(db, stores, flag, autoclosedb) {
-    var tx = db.transaction(stores, flag);
-    if (autoclosedb !== false) {
-      tx.oncomplete = function () {
-        db.close();
-      };
-    }
-    tx.onabort = function () {
-      db.close();
-    };
-    return tx;
-  }
-
-  function handleCursor(request, callback) {
-    function resolver(resolve, reject) {
-      // Open DB //
-      request.onerror = function (error) {
-        if (request.transaction) {
-          request.transaction.abort();
-        }
-        reject(error);
-      };
-
-      request.onsuccess = function (evt) {
-        var cursor = evt.target.result;
-        if (cursor) {
-          // XXX Wait for result
-          try {
-            callback(cursor);
-          } catch (error) {
-            reject(error);
-          }
-
-          // continue to next iteration
-          cursor["continue"]();
-        } else {
-          resolve();
-        }
-      };
-    }
-    // XXX Canceller???
-    return new RSVP.Promise(resolver);
-  }
-
-  IndexedDBStorage.prototype.buildQuery = function (options) {
-    var result_list = [];
-
-    function pushIncludedMetadata(cursor) {
-      result_list.push({
-        "id": cursor.key,
-        "value": {},
-        "doc": cursor.value.doc
-      });
-    }
-
-    function pushMetadata(cursor) {
-      result_list.push({
-        "id": cursor.key,
-        "value": {}
-      });
-    }
-    return openIndexedDB(this)
-      .push(function (db) {
-        var tx = openTransaction(db, ["metadata"], "readonly");
-        if (options.include_docs === true) {
-          return handleCursor(tx.objectStore("metadata").index("_id")
-                              .openCursor(), pushIncludedMetadata);
-        }
-        return handleCursor(tx.objectStore("metadata").index("_id")
-                            .openKeyCursor(), pushMetadata);
-      })
-      .push(function () {
-        return result_list;
-      });
-
-  };
-
-  function handleGet(request) {
-    function resolver(resolve, reject) {
-      request.onerror = reject;
-      request.onsuccess = function () {
-        if (request.result) {
-          resolve(request.result);
-        }
-        // XXX How to get ID
-        reject(new jIO.util.jIOError("Cannot find document", 404));
-      };
-    }
-    return new RSVP.Promise(resolver);
-  }
-
-  IndexedDBStorage.prototype.get = function (id) {
-    return openIndexedDB(this)
-      .push(function (db) {
-        var transaction = openTransaction(db, ["metadata"],
-                                          "readonly");
-        return handleGet(transaction.objectStore("metadata").get(id));
-      })
-      .push(function (result) {
-        return result.doc;
-      });
-  };
-
-  IndexedDBStorage.prototype.allAttachments = function (id) {
-    var attachment_dict = {};
-
-    function addEntry(cursor) {
-      attachment_dict[cursor.value._attachment] = {};
-    }
-
-    return openIndexedDB(this)
-      .push(function (db) {
-        var transaction = openTransaction(db, ["metadata", "attachment"],
-                                          "readonly");
-        return RSVP.all([
-          handleGet(transaction.objectStore("metadata").get(id)),
-          handleCursor(transaction.objectStore("attachment").index("_id")
-                       .openCursor(IDBKeyRange.only(id)), addEntry)
-        ]);
-      })
-      .push(function () {
-        return attachment_dict;
-      });
-  };
-
-  function handleRequest(request) {
-    function resolver(resolve, reject) {
-      request.onerror = reject;
-      request.onsuccess = function () {
-        resolve(request.result);
-      };
-    }
-    return new RSVP.Promise(resolver);
-  }
-
-  IndexedDBStorage.prototype.put = function (id, metadata) {
-    return openIndexedDB(this)
-      .push(function (db) {
-        var transaction = openTransaction(db, ["metadata"], "readwrite");
-        return handleRequest(transaction.objectStore("metadata").put({
-          "_id": id,
-          "doc": metadata
-        }));
-      });
-  };
-
-  function deleteEntry(cursor) {
-    cursor["delete"]();
-  }
-
-  IndexedDBStorage.prototype.remove = function (id) {
-    return openIndexedDB(this)
-      .push(function (db) {
-        var transaction = openTransaction(db, ["metadata", "attachment",
-                                          "blob"], "readwrite");
-        return RSVP.all([
-          handleRequest(transaction
-                        .objectStore("metadata")["delete"](id)),
-          // XXX Why not possible to delete with KeyCursor?
-          handleCursor(transaction.objectStore("attachment").index("_id")
-                       .openCursor(IDBKeyRange.only(id)), deleteEntry),
-          handleCursor(transaction.objectStore("blob").index("_id")
-                       .openCursor(IDBKeyRange.only(id)), deleteEntry)
-        ]);
-      });
-  };
-
-  IndexedDBStorage.prototype.getAttachment = function (id, name, options) {
-    var transaction,
-      type,
-      start,
-      end;
-    if (options === undefined) {
-      options = {};
-    }
-    return openIndexedDB(this)
-      .push(function (db) {
-        transaction = openTransaction(db, ["attachment", "blob"], "readonly");
-        // XXX Should raise if key is not good
-        return handleGet(transaction.objectStore("attachment")
-                         .get(buildKeyPath([id, name])));
-      })
-      .push(function (attachment) {
-        var total_length = attachment.info.length,
-          i,
-          promise_list = [],
-          store = transaction.objectStore("blob"),
-          start_index,
-          end_index;
-
-        type = attachment.info.content_type;
-        start = options.start || 0;
-        end = options.end || total_length;
-        if (end > total_length) {
-          end = total_length;
-        }
-
-        if (start < 0 || end < 0) {
-          throw new jIO.util.jIOError("_start and _end must be positive",
-                                      400);
-        }
-        if (start > end) {
-          throw new jIO.util.jIOError("_start is greater than _end",
-                                      400);
-        }
-
-        start_index = Math.floor(start / UNITE);
-        end_index =  Math.floor(end / UNITE);
-        if (end % UNITE === 0) {
-          end_index -= 1;
-        }
-
-        for (i = start_index; i <= end_index; i += 1) {
-          promise_list.push(
-            handleGet(store.get(buildKeyPath([id,
-                                name, i])))
-          );
-        }
-        return RSVP.all(promise_list);
-      })
-      .push(function (result_list) {
-        var array_buffer_list = [],
-          blob,
-          i,
-          index,
-          len = result_list.length;
-        for (i = 0; i < len; i += 1) {
-          array_buffer_list.push(result_list[i].blob);
-        }
-        if ((options.start === undefined) && (options.end === undefined)) {
-          return new Blob(array_buffer_list, {type: type});
-        }
-        index = Math.floor(start / UNITE) * UNITE;
-        blob = new Blob(array_buffer_list, {type: "application/octet-stream"});
-        return blob.slice(start - index, end - index,
-                          "application/octet-stream");
-      });
-  };
-
-  function removeAttachment(transaction, id, name) {
-    return RSVP.all([
-      // XXX How to get the right attachment
-      handleRequest(transaction.objectStore("attachment")["delete"](
-        buildKeyPath([id, name])
-      )),
-      handleCursor(transaction.objectStore("blob").index("_id_attachment")
-                   .openCursor(IDBKeyRange.only(
-          [id, name]
-        )),
-          deleteEntry
-        )
-    ]);
-  }
-
-  IndexedDBStorage.prototype.putAttachment = function (id, name, blob) {
-    var blob_part = [],
-      transaction,
-      db;
-
-    return openIndexedDB(this)
-      .push(function (database) {
-        db = database;
-
-        // Split the blob first
-        return jIO.util.readBlobAsArrayBuffer(blob);
-      })
-      .push(function (event) {
-        var array_buffer = event.target.result,
-          total_size = blob.size,
-          handled_size = 0;
-
-        while (handled_size < total_size) {
-          blob_part.push(array_buffer.slice(handled_size,
-                                            handled_size + UNITE));
-          handled_size += UNITE;
-        }
-
-        // Remove previous attachment
-        transaction = openTransaction(db, ["attachment", "blob"], "readwrite");
-        return removeAttachment(transaction, id, name);
-      })
-      .push(function () {
-
-        var promise_list = [
-            handleRequest(transaction.objectStore("attachment").put({
-              "_key_path": buildKeyPath([id, name]),
-              "_id": id,
-              "_attachment": name,
-              "info": {
-                "content_type": blob.type,
-                "length": blob.size
-              }
-            }))
-          ],
-          len = blob_part.length,
-          blob_store = transaction.objectStore("blob"),
-          i;
-        for (i = 0; i < len; i += 1) {
-          promise_list.push(
-            handleRequest(blob_store.put({
-              "_key_path": buildKeyPath([id, name,
-                                         i]),
-              "_id" : id,
-              "_attachment" : name,
-              "_part" : i,
-              "blob": blob_part[i]
-            }))
-          );
-        }
-        // Store all new data
-        return RSVP.all(promise_list);
-      });
-  };
-
-  IndexedDBStorage.prototype.removeAttachment = function (id, name) {
-    return openIndexedDB(this)
-      .push(function (db) {
-        var transaction = openTransaction(db, ["attachment", "blob"],
-                                          "readwrite");
-        return removeAttachment(transaction, id, name);
-      });
-  };
-
-  jIO.addStorage("indexeddb", IndexedDBStorage);
-}(indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest, DOMError));
-;/*
- * Copyright 2015, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-
-/*jslint nomen: true*/
-/*global jIO, RSVP, DOMException, Blob, crypto, Uint8Array, ArrayBuffer*/
-
-(function (jIO, RSVP, DOMException, Blob, crypto, Uint8Array, ArrayBuffer) {
-  "use strict";
-
-
-  // you the cryptography system used by this storage is AES-GCM.
-  // here is an example of how to generate a key to the json format.
-
-  // var key,
-  //     jsonKey;
-  // crypto.subtle.generateKey({name: "AES-GCM",length: 256},
-  //                           (true), ["encrypt", "decrypt"])
-  // .then(function(res){key = res;});
-  //
-  // window.crypto.subtle.exportKey("jwk", key)
-  // .then(function(res){jsonKey = val})
-  //
-  //var storage = jIO.createJIO({type: "crypt", key: jsonKey,
-  //                             sub_storage: {...}});
-
-  // find more informations about this cryptography system on
-  // https://github.com/diafygi/webcrypto-examples#aes-gcm
-
-  /**
-   * The JIO Cryptography Storage extension
-   *
-   * @class CryptStorage
-   * @constructor
-   */
-
-  var MIME_TYPE = "application/x-jio-aes-gcm-encryption";
-
-  function CryptStorage(spec) {
-    this._key = spec.key;
-    this._jsonKey = true;
-    this._sub_storage = jIO.createJIO(spec.sub_storage);
-  }
-
-  function convertKey(that) {
-    return new RSVP.Queue()
-      .push(function () {
-        return crypto.subtle.importKey("jwk", that._key,
-                                       "AES-GCM", false,
-                                       ["encrypt", "decrypt"]);
-      })
-      .push(function (res) {
-        that._key = res;
-        that._jsonKey = false;
-        return;
-      });
-  }
-
-  CryptStorage.prototype.get = function () {
-    return this._sub_storage.get.apply(this._sub_storage,
-                                       arguments);
-  };
-
-  CryptStorage.prototype.post = function () {
-    return this._sub_storage.post.apply(this._sub_storage,
-                                        arguments);
-  };
-
-  CryptStorage.prototype.put = function () {
-    return this._sub_storage.put.apply(this._sub_storage,
-                                       arguments);
-  };
-
-  CryptStorage.prototype.remove = function () {
-    return this._sub_storage.remove.apply(this._sub_storage,
-                                          arguments);
-  };
-
-  CryptStorage.prototype.hasCapacity = function () {
-    return this._sub_storage.hasCapacity.apply(this._sub_storage,
-                                               arguments);
-  };
-
-  CryptStorage.prototype.buildQuery = function () {
-    return this._sub_storage.buildQuery.apply(this._sub_storage,
-                                              arguments);
-  };
-
-
-  CryptStorage.prototype.putAttachment = function (id, name, blob) {
-    var initializaton_vector = crypto.getRandomValues(new Uint8Array(12)),
-      that = this;
-
-    return new RSVP.Queue()
-      .push(function () {
-        if (that._jsonKey === true) {
-          return convertKey(that);
-        }
-        return;
-      })
-      .push(function () {
-        return jIO.util.readBlobAsDataURL(blob);
-      })
-      .push(function (dataURL) {
-        //string->arraybuffer
-        var strLen = dataURL.currentTarget.result.length,
-          buf = new ArrayBuffer(strLen),
-          bufView = new Uint8Array(buf),
-          i;
-
-        dataURL = dataURL.currentTarget.result;
-        for (i = 0; i < strLen; i += 1) {
-          bufView[i] = dataURL.charCodeAt(i);
-        }
-        return crypto.subtle.encrypt({
-          name : "AES-GCM",
-          iv : initializaton_vector
-        },
-                                     that._key, buf);
-      })
-      .push(function (coded) {
-        var blob = new Blob([initializaton_vector, coded], {type: MIME_TYPE});
-        return that._sub_storage.putAttachment(id, name, blob);
-      });
-  };
-
-  CryptStorage.prototype.getAttachment = function (id, name) {
-    var that = this;
-
-    return that._sub_storage.getAttachment(id, name)
-      .push(function (blob) {
-        if (blob.type !== MIME_TYPE) {
-          return blob;
-        }
-        return new RSVP.Queue()
-          .push(function () {
-            if (that._jsonKey === true) {
-              return convertKey(that);
-            }
-            return;
-          })
-          .push(function () {
-            return jIO.util.readBlobAsArrayBuffer(blob);
-          })
-          .push(function (coded) {
-            var initializaton_vector;
-
-            coded = coded.currentTarget.result;
-            initializaton_vector = new Uint8Array(coded.slice(0, 12));
-            return new RSVP.Queue()
-              .push(function () {
-                return crypto.subtle.decrypt({
-                  name : "AES-GCM",
-                  iv : initializaton_vector
-                },
-                                             that._key, coded.slice(12));
-              })
-              .push(function (arr) {
-                //arraybuffer->string
-                arr = String.fromCharCode.apply(null, new Uint8Array(arr));
-                return jIO.util.dataURItoBlob(arr);
-              })
-              .push(undefined, function (error) {
-                if (error instanceof DOMException) {
-                  return blob;
-                }
-                throw error;
-              });
-          });
-      });
-  };
-
-  CryptStorage.prototype.removeAttachment = function () {
-    return this._sub_storage.removeAttachment.apply(this._sub_storage,
-                                                    arguments);
-  };
-
-  CryptStorage.prototype.allAttachments = function () {
-    return this._sub_storage.allAttachments.apply(this._sub_storage,
-                                                  arguments);
-  };
-
-  jIO.addStorage('crypt', CryptStorage);
-
-}(jIO, RSVP, DOMException, Blob, crypto, Uint8Array, ArrayBuffer));
-;/*
- * Copyright 2013, Nexedi SA
- * Released under the LGPL license.
- * http://www.gnu.org/licenses/lgpl.html
- */
-/**
- * JIO Websql Storage. Type = "websql".
- * websql "database" storage.
- */
-/*global Blob, jIO, RSVP, openDatabase*/
-/*jslint nomen: true*/
-
-(function (jIO, RSVP, Blob, openDatabase) {
-
-  "use strict";
-
-  /**
-   * The JIO Websql Storage extension
-   *
-   * @class WebSQLStorage
-   * @constructor
-   */
-
-  function queueSql(db, query_list, argument_list) {
-    return new RSVP.Promise(function (resolve, reject) {
-      /*jslint unparam: true*/
-      db.transaction(function (tx) {
-        var len = query_list.length,
-          result_list = [],
-          i;
-
-        function resolveTransaction(tx, result) {
-          result_list.push(result);
-          if (result_list.length === len) {
-            resolve(result_list);
-          }
-        }
-        function rejectTransaction(tx, error) {
-          reject(error);
-          return true;
-        }
-        for (i = 0; i < len; i += 1) {
-          tx.executeSql(query_list[i], argument_list[i], resolveTransaction,
-                        rejectTransaction);
-        }
-      }, function (tx, error) {
-        reject(error);
-      });
-      /*jslint unparam: false*/
-    });
-  }
-
-  function initDatabase(db) {
-    var query_list = [
-      "CREATE TABLE IF NOT EXISTS document" +
-        "(id VARCHAR PRIMARY KEY NOT NULL, data TEXT)",
-      "CREATE TABLE IF NOT EXISTS attachment" +
-        "(id VARCHAR, attachment VARCHAR, part INT, blob TEXT)",
-      "CREATE TRIGGER IF NOT EXISTS removeAttachment " +
-        "BEFORE DELETE ON document FOR EACH ROW " +
-        "BEGIN DELETE from attachment WHERE id = OLD.id;END;",
-      "CREATE INDEX IF NOT EXISTS index_document ON document (id);",
-      "CREATE INDEX IF NOT EXISTS index_attachment " +
-        "ON attachment (id, attachment);"
-    ];
-    return new RSVP.Queue()
-      .push(function () {
-        return queueSql(db, query_list, []);
-      });
-  }
-
-  function WebSQLStorage(spec) {
-    if (typeof spec.database !== 'string' || !spec.database) {
-      throw new TypeError("database must be a string " +
-                          "which contains more than one character.");
-    }
-    this._database = openDatabase("jio:" + spec.database,
-                                  '1.0', '', 2 * 1024 * 1024);
-    if (spec.blob_length &&
-        (typeof spec.blob_length !== "number" ||
-         spec.blob_length < 20)) {
-      throw new TypeError("blob_len parameter must be a number >= 20");
-    }
-    this._blob_length = spec.blob_length || 2000000;
-    this._init_db_promise = initDatabase(this._database);
-  }
-
-  WebSQLStorage.prototype.put = function (id, param) {
-    var db = this._database,
-      that = this,
-      data_string = JSON.stringify(param);
-
-    return new RSVP.Queue()
-      .push(function () {
-        return that._init_db_promise;
-      })
-      .push(function () {
-        return queueSql(db, ["INSERT OR REPLACE INTO " +
-                            "document(id, data) VALUES(?,?)"],
-                       [[id, data_string]]);
-      })
-      .push(function () {
-        return id;
-      });
-  };
-
-  WebSQLStorage.prototype.remove = function (id) {
-    var db = this._database,
-      that = this;
-
-    return new RSVP.Queue()
-      .push(function () {
-        return that._init_db_promise;
-      })
-      .push(function () {
-        return queueSql(db, ["DELETE FROM document WHERE id = ?"], [[id]]);
-      })
-      .push(function (result_list) {
-        if (result_list[0].rowsAffected === 0) {
-          throw new jIO.util.jIOError("Cannot find document", 404);
-        }
-        return id;
-      });
-
-  };
-
-  WebSQLStorage.prototype.get = function (id) {
-    var db = this._database,
-      that = this;
-
-    return new RSVP.Queue()
-      .push(function () {
-        return that._init_db_promise;
-      })
-      .push(function () {
-        return queueSql(db, ["SELECT data FROM document WHERE id = ?"],
-                        [[id]]);
-      })
-      .push(function (result_list) {
-        if (result_list[0].rows.length === 0) {
-          throw new jIO.util.jIOError("Cannot find document", 404);
-        }
-        return JSON.parse(result_list[0].rows[0].data);
-      });
-  };
-
-  WebSQLStorage.prototype.allAttachments = function (id) {
-    var db = this._database,
-      that = this;
-
-    return new RSVP.Queue()
-      .push(function () {
-        return that._init_db_promise;
-      })
-      .push(function () {
-        return queueSql(db, [
-          "SELECT id FROM document WHERE id = ?",
-          "SELECT DISTINCT attachment FROM attachment WHERE id = ?"
-        ], [[id], [id]]);
-      })
-      .push(function (result_list) {
-        if (result_list[0].rows.length === 0) {
-          throw new jIO.util.jIOError("Cannot find document", 404);
-        }
-
-        var len = result_list[1].rows.length,
-          obj = {},
-          i;
-
-        for (i = 0; i < len; i += 1) {
-          obj[result_list[1].rows[i].attachment] = {};
-        }
-        return obj;
-      });
-  };
-
-  function sendBlobPart(blob, argument_list, index, queue) {
-    queue.push(function () {
-      return jIO.util.readBlobAsDataURL(blob);
-    })
-      .push(function (strBlob) {
-        argument_list[index + 2].push(strBlob.currentTarget.result);
-        return;
-      });
-  }
-
-  WebSQLStorage.prototype.putAttachment = function (id, name, blob) {
-    var db = this._database,
-      that = this,
-      part_size = this._blob_length;
-
-    return new RSVP.Queue()
-      .push(function () {
-        return that._init_db_promise;
-      })
-      .push(function () {
-        return queueSql(db, ["SELECT id FROM document WHERE id = ?"], [[id]]);
-      })
-      .push(function (result) {
-        var query_list = [],
-          argument_list = [],
-          blob_size = blob.size,
-          queue = new RSVP.Queue(),
-          i,
-          index;
-
-        if (result[0].rows.length === 0) {
-          throw new jIO.util.jIOError("Cannot access subdocument", 404);
-        }
-        query_list.push("DELETE FROM attachment WHERE id = ? " +
-                        "AND attachment = ?");
-        argument_list.push([id, name]);
-        query_list.push("INSERT INTO attachment(id, attachment, part, blob)" +
-                     "VALUES(?, ?, ?, ?)");
-        argument_list.push([id, name, -1,
-                            blob.type || "application/octet-stream"]);
-
-        for (i = 0, index = 0; i < blob_size; i += part_size, index += 1) {
-          query_list.push("INSERT INTO attachment(id, attachment, part, blob)" +
-                       "VALUES(?, ?, ?, ?)");
-          argument_list.push([id, name, index]);
-          sendBlobPart(blob.slice(i, i + part_size), argument_list, index,
-                       queue);
-        }
-        queue.push(function () {
-          return queueSql(db, query_list, argument_list);
-        });
-        return queue;
-      });
-  };
-
-  WebSQLStorage.prototype.getAttachment = function (id, name, options) {
-    var db = this._database,
-      that = this,
-      part_size = this._blob_length,
-      start,
-      end,
-      start_index,
-      end_index;
-
-    if (options === undefined) { options = {}; }
-    start = options.start || 0;
-    end = options.end || -1;
-
-    if (start < 0 || (options.end !== undefined && options.end < 0)) {
-      throw new jIO.util.jIOError("_start and _end must be positive",
-                                  400);
-    }
-    if (start > end && end !== -1) {
-      throw new jIO.util.jIOError("_start is greater than _end",
-                                  400);
-    }
-
-    start_index = Math.floor(start / part_size);
-    if (start === 0) { start_index -= 1; }
-    end_index =  Math.floor(end / part_size);
-    if (end % part_size === 0) {
-      end_index -= 1;
-    }
-
-    return new RSVP.Queue()
-      .push(function () {
-        return that._init_db_promise;
-      })
-      .push(function () {
-        var command = "SELECT part, blob FROM attachment WHERE id = ? AND " +
-          "attachment = ? AND part >= ?",
-          argument_list = [id, name, start_index];
-
-        if (end !== -1) {
-          command += " AND part <= ?";
-          argument_list.push(end_index);
-        }
-        return queueSql(db, [command], [argument_list]);
-      })
-      .push(function (response_list) {
-        var i,
-          response,
-          blob_array = [],
-          blob,
-          type;
-
-        response = response_list[0].rows;
-        if (response.length === 0) {
-          throw new jIO.util.jIOError("Cannot find document", 404);
-        }
-        for (i = 0; i < response.length; i += 1) {
-          if (response[i].part === -1) {
-            type = response[i].blob;
-            start_index += 1;
-          } else {
-            blob_array.push(jIO.util.dataURItoBlob(response[i].blob));
-          }
-        }
-        if ((start === 0) && (options.end === undefined)) {
-          return new Blob(blob_array, {type: type});
-        }
-        blob = new Blob(blob_array, {});
-        return blob.slice(start - (start_index * part_size),
-                          end === -1 ? blob.size :
-                          end - (start_index * part_size),
-                          "application/octet-stream");
-      });
-  };
-
-  WebSQLStorage.prototype.removeAttachment = function (id, name) {
-    var db = this._database,
-      that = this;
-
-    return new RSVP.Queue()
-      .push(function () {
-        return that._init_db_promise;
-      })
-      .push(function () {
-        return queueSql(db, ["DELETE FROM attachment WHERE " +
-                            "id = ? AND attachment = ?"], [[id, name]]);
-      })
-      .push(function (result) {
-        if (result[0].rowsAffected === 0) {
-          throw new jIO.util.jIOError("Cannot find document", 404);
-        }
-        return name;
-      });
-  };
-
-  WebSQLStorage.prototype.hasCapacity = function (name) {
-    return (name === "list" || (name === "include"));
-  };
-
-  WebSQLStorage.prototype.buildQuery = function (options) {
-    var db = this._database,
-      that = this,
-      query =  "SELECT id";
-
-    return new RSVP.Queue()
-      .push(function () {
-        return that._init_db_promise;
-      })
-      .push(function () {
-        if (options === undefined) { options = {}; }
-        if (options.include_docs === true) {
-          query += ", data AS doc";
-        }
-        query += " FROM document";
-        return queueSql(db, [query], [[]]);
-      })
-      .push(function (result) {
-        var array = [],
-          len = result[0].rows.length,
-          i;
-
-        for (i = 0; i < len; i += 1) {
-          array.push(result[0].rows[i]);
-          array[i].value = {};
-          if (array[i].doc !== undefined) {
-            array[i].doc = JSON.parse(array[i].doc);
-          }
-        }
-        return array;
-      });
-  };
-
-  jIO.addStorage('websql', WebSQLStorage);
-
-}(jIO, RSVP, Blob, openDatabase));
diff --git a/apps/maarch_entreprise/js/render.js b/apps/maarch_entreprise/js/render.js
deleted file mode 100755
index d5997c0b88e..00000000000
--- a/apps/maarch_entreprise/js/render.js
+++ /dev/null
@@ -1,2350 +0,0 @@
-/*
- * js_channel is a very lightweight abstraction on top of
- * postMessage which defines message formats and semantics
- * to support interactions more rich than just message passing
- * js_channel supports:
- *  + query/response - traditional rpc
- *  + query/update/response - incremental async return of results
- *    to a query
- *  + notifications - fire and forget
- *  + error handling
- *
- * js_channel is based heavily on json-rpc, but is focused at the
- * problem of inter-iframe RPC.
- *
- * Message types:
- *  There are 5 types of messages that can flow over this channel,
- *  and you may determine what type of message an object is by
- *  examining its parameters:
- *  1. Requests
- *    + integer id
- *    + string method
- *    + (optional) any params
- *  2. Callback Invocations (or just "Callbacks")
- *    + integer id
- *    + string callback
- *    + (optional) params
- *  3. Error Responses (or just "Errors)
- *    + integer id
- *    + string error
- *    + (optional) string message
- *  4. Responses
- *    + integer id
- *    + (optional) any result
- *  5. Notifications
- *    + string method
- *    + (optional) any params
- */
-
-;var Channel = (function() {
-    "use strict";
-
-    // current transaction id, start out at a random *odd* number between 1 and a million
-    // There is one current transaction counter id per page, and it's shared between
-    // channel instances.  That means of all messages posted from a single javascript
-    // evaluation context, we'll never have two with the same id.
-    var s_curTranId = Math.floor(Math.random()*1000001);
-
-    // no two bound channels in the same javascript evaluation context may have the same origin, scope, and window.
-    // futher if two bound channels have the same window and scope, they may not have *overlapping* origins
-    // (either one or both support '*').  This restriction allows a single onMessage handler to efficiently
-    // route messages based on origin and scope.  The s_boundChans maps origins to scopes, to message
-    // handlers.  Request and Notification messages are routed using this table.
-    // Finally, channels are inserted into this table when built, and removed when destroyed.
-    var s_boundChans = { };
-
-    // add a channel to s_boundChans, throwing if a dup exists
-    function s_addBoundChan(win, origin, scope, handler) {
-        function hasWin(arr) {
-            for (var i = 0; i < arr.length; i++) if (arr[i].win === win) return true;
-            return false;
-        }
-
-        // does she exist?
-        var exists = false;
-
-
-        if (origin === '*') {
-            // we must check all other origins, sadly.
-            for (var k in s_boundChans) {
-                if (!s_boundChans.hasOwnProperty(k)) continue;
-                if (k === '*') continue;
-                if (typeof s_boundChans[k][scope] === 'object') {
-                    exists = hasWin(s_boundChans[k][scope]);
-                    if (exists) break;
-                }
-            }
-        } else {
-            // we must check only '*'
-            if ((s_boundChans['*'] && s_boundChans['*'][scope])) {
-                exists = hasWin(s_boundChans['*'][scope]);
-            }
-            if (!exists && s_boundChans[origin] && s_boundChans[origin][scope])
-            {
-                exists = hasWin(s_boundChans[origin][scope]);
-            }
-        }
-        if (exists) throw "A channel is already bound to the same window which overlaps with origin '"+ origin +"' and has scope '"+scope+"'";
-
-        if (typeof s_boundChans[origin] != 'object') s_boundChans[origin] = { };
-        if (typeof s_boundChans[origin][scope] != 'object') s_boundChans[origin][scope] = [ ];
-        s_boundChans[origin][scope].push({win: win, handler: handler});
-    }
-
-    function s_removeBoundChan(win, origin, scope) {
-        var arr = s_boundChans[origin][scope];
-        for (var i = 0; i < arr.length; i++) {
-            if (arr[i].win === win) {
-                arr.splice(i,1);
-            }
-        }
-        if (s_boundChans[origin][scope].length === 0) {
-            delete s_boundChans[origin][scope];
-        }
-    }
-
-    function s_isArray(obj) {
-        if (Array.isArray) return Array.isArray(obj);
-        else {
-            return (obj.constructor.toString().indexOf("Array") != -1);
-        }
-    }
-
-    // No two outstanding outbound messages may have the same id, period.  Given that, a single table
-    // mapping "transaction ids" to message handlers, allows efficient routing of Callback, Error, and
-    // Response messages.  Entries are added to this table when requests are sent, and removed when
-    // responses are received.
-    var s_transIds = { };
-
-    // class singleton onMessage handler
-    // this function is registered once and all incoming messages route through here.  This
-    // arrangement allows certain efficiencies, message data is only parsed once and dispatch
-    // is more efficient, especially for large numbers of simultaneous channels.
-    var s_onMessage = function(e) {
-        try {
-          var m = JSON.parse(e.data);
-          if (typeof m !== 'object' || m === null) throw "malformed";
-        } catch(e) {
-          // just ignore any posted messages that do not consist of valid JSON
-          return;
-        }
-
-        var w = e.source;
-        var o = e.origin;
-        var s, i, meth;
-
-        if (typeof m.method === 'string') {
-            var ar = m.method.split('::');
-            if (ar.length == 2) {
-                s = ar[0];
-                meth = ar[1];
-            } else {
-                meth = m.method;
-            }
-        }
-
-        if (typeof m.id !== 'undefined') i = m.id;
-
-        // w is message source window
-        // o is message origin
-        // m is parsed message
-        // s is message scope
-        // i is message id (or undefined)
-        // meth is unscoped method name
-        // ^^ based on these factors we can route the message
-
-        // if it has a method it's either a notification or a request,
-        // route using s_boundChans
-        if (typeof meth === 'string') {
-            var delivered = false;
-            if (s_boundChans[o] && s_boundChans[o][s]) {
-                for (var j = 0; j < s_boundChans[o][s].length; j++) {
-                    if (s_boundChans[o][s][j].win === w) {
-                        s_boundChans[o][s][j].handler(o, meth, m);
-                        delivered = true;
-                        break;
-                    }
-                }
-            }
-
-            if (!delivered && s_boundChans['*'] && s_boundChans['*'][s]) {
-                for (var j = 0; j < s_boundChans['*'][s].length; j++) {
-                    if (s_boundChans['*'][s][j].win === w) {
-                        s_boundChans['*'][s][j].handler(o, meth, m);
-                        break;
-                    }
-                }
-            }
-        }
-        // otherwise it must have an id (or be poorly formed
-        else if (typeof i != 'undefined') {
-            if (s_transIds[i]) s_transIds[i](o, meth, m);
-        }
-    };
-
-    // Setup postMessage event listeners
-    if (window.addEventListener) window.addEventListener('message', s_onMessage, false);
-    else if(window.attachEvent) window.attachEvent('onmessage', s_onMessage);
-
-    /* a messaging channel is constructed from a window and an origin.
-     * the channel will assert that all messages received over the
-     * channel match the origin
-     *
-     * Arguments to Channel.build(cfg):
-     *
-     *   cfg.window - the remote window with which we'll communicate
-     *   cfg.origin - the expected origin of the remote window, may be '*'
-     *                which matches any origin
-     *   cfg.scope  - the 'scope' of messages.  a scope string that is
-     *                prepended to message names.  local and remote endpoints
-     *                of a single channel must agree upon scope. Scope may
-     *                not contain double colons ('::').
-     *   cfg.debugOutput - A boolean value.  If true and window.console.log is
-     *                a function, then debug strings will be emitted to that
-     *                function.
-     *   cfg.debugOutput - A boolean value.  If true and window.console.log is
-     *                a function, then debug strings will be emitted to that
-     *                function.
-     *   cfg.postMessageObserver - A function that will be passed two arguments,
-     *                an origin and a message.  It will be passed these immediately
-     *                before messages are posted.
-     *   cfg.gotMessageObserver - A function that will be passed two arguments,
-     *                an origin and a message.  It will be passed these arguments
-     *                immediately after they pass scope and origin checks, but before
-     *                they are processed.
-     *   cfg.onReady - A function that will be invoked when a channel becomes "ready",
-     *                this occurs once both sides of the channel have been
-     *                instantiated and an application level handshake is exchanged.
-     *                the onReady function will be passed a single argument which is
-     *                the channel object that was returned from build().
-     */
-    return {
-        build: function(cfg) {
-            var debug = function(m) {
-                if (cfg.debugOutput && window.console && window.console.log) {
-                    // try to stringify, if it doesn't work we'll let javascript's built in toString do its magic
-                    try { if (typeof m !== 'string') m = JSON.stringify(m); } catch(e) { }
-                    console.log("["+chanId+"] " + m);
-                }
-            };
-
-            /* browser capabilities check */
-            if (!window.postMessage) throw("jschannel cannot run this browser, no postMessage");
-            if (!window.JSON || !window.JSON.stringify || ! window.JSON.parse) {
-                throw("jschannel cannot run this browser, no JSON parsing/serialization");
-            }
-
-            /* basic argument validation */
-            if (typeof cfg != 'object') throw("Channel build invoked without a proper object argument");
-
-            if (!cfg.window || !cfg.window.postMessage) throw("Channel.build() called without a valid window argument");
-
-            /* we'd have to do a little more work to be able to run multiple channels that intercommunicate the same
-             * window...  Not sure if we care to support that */
-            if (window === cfg.window) throw("target window is same as present window -- not allowed");
-
-            // let's require that the client specify an origin.  if we just assume '*' we'll be
-            // propagating unsafe practices.  that would be lame.
-            var validOrigin = false;
-            if (typeof cfg.origin === 'string') {
-                var oMatch;
-                if (cfg.origin === "*") validOrigin = true;
-                // allow valid domains under http and https.  Also, trim paths off otherwise valid origins.
-                else if (null !== (oMatch = cfg.origin.match(/^https?:\/\/(?:[-a-zA-Z0-9_\.])+(?::\d+)?/))) {
-                    cfg.origin = oMatch[0].toLowerCase();
-                    validOrigin = true;
-                }
-            }
-
-            if (!validOrigin) throw ("Channel.build() called with an invalid origin");
-
-            if (typeof cfg.scope !== 'undefined') {
-                if (typeof cfg.scope !== 'string') throw 'scope, when specified, must be a string';
-                if (cfg.scope.split('::').length > 1) throw "scope may not contain double colons: '::'";
-            }
-
-            /* private variables */
-            // generate a random and psuedo unique id for this channel
-            var chanId = (function () {
-                var text = "";
-                var alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-                for(var i=0; i < 5; i++) text += alpha.charAt(Math.floor(Math.random() * alpha.length));
-                return text;
-            })();
-
-            // registrations: mapping method names to call objects
-            var regTbl = { };
-            // current oustanding sent requests
-            var outTbl = { };
-            // current oustanding received requests
-            var inTbl = { };
-            // are we ready yet?  when false we will block outbound messages.
-            var ready = false;
-            var pendingQueue = [ ];
-
-            var createTransaction = function(id,origin,callbacks) {
-                var shouldDelayReturn = false;
-                var completed = false;
-
-                return {
-                    origin: origin,
-                    invoke: function(cbName, v) {
-                        // verify in table
-                        if (!inTbl[id]) throw "attempting to invoke a callback of a nonexistent transaction: " + id;
-                        // verify that the callback name is valid
-                        var valid = false;
-                        for (var i = 0; i < callbacks.length; i++) if (cbName === callbacks[i]) { valid = true; break; }
-                        if (!valid) throw "request supports no such callback '" + cbName + "'";
-
-                        // send callback invocation
-                        postMessage({ id: id, callback: cbName, params: v});
-                    },
-                    error: function(error, message) {
-                        completed = true;
-                        // verify in table
-                        if (!inTbl[id]) throw "error called for nonexistent message: " + id;
-
-                        // remove transaction from table
-                        delete inTbl[id];
-
-                        // send error
-                        postMessage({ id: id, error: error, message: message });
-                    },
-                    complete: function(v) {
-                        completed = true;
-                        // verify in table
-                        if (!inTbl[id]) throw "complete called for nonexistent message: " + id;
-                        // remove transaction from table
-                        delete inTbl[id];
-                        // send complete
-                        postMessage({ id: id, result: v });
-                    },
-                    delayReturn: function(delay) {
-                        if (typeof delay === 'boolean') {
-                            shouldDelayReturn = (delay === true);
-                        }
-                        return shouldDelayReturn;
-                    },
-                    completed: function() {
-                        return completed;
-                    }
-                };
-            };
-
-            var setTransactionTimeout = function(transId, timeout, method) {
-              return window.setTimeout(function() {
-                if (outTbl[transId]) {
-                  // XXX: what if client code raises an exception here?
-                  var msg = "timeout (" + timeout + "ms) exceeded on method '" + method + "'";
-                  (1,outTbl[transId].error)("timeout_error", msg);
-                  delete outTbl[transId];
-                  delete s_transIds[transId];
-                }
-              }, timeout);
-            };
-
-            var onMessage = function(origin, method, m) {
-                // if an observer was specified at allocation time, invoke it
-                if (typeof cfg.gotMessageObserver === 'function') {
-                    // pass observer a clone of the object so that our
-                    // manipulations are not visible (i.e. method unscoping).
-                    // This is not particularly efficient, but then we expect
-                    // that message observers are primarily for debugging anyway.
-                    try {
-                        cfg.gotMessageObserver(origin, m);
-                    } catch (e) {
-                        debug("gotMessageObserver() raised an exception: " + e.toString());
-                    }
-                }
-
-                // now, what type of message is this?
-                if (m.id && method) {
-                    // a request!  do we have a registered handler for this request?
-                    if (regTbl[method]) {
-                        var trans = createTransaction(m.id, origin, m.callbacks ? m.callbacks : [ ]);
-                        inTbl[m.id] = { };
-                        try {
-                            // callback handling.  we'll magically create functions inside the parameter list for each
-                            // callback
-                            if (m.callbacks && s_isArray(m.callbacks) && m.callbacks.length > 0) {
-                                for (var i = 0; i < m.callbacks.length; i++) {
-                                    var path = m.callbacks[i];
-                                    var obj = m.params;
-                                    var pathItems = path.split('/');
-                                    for (var j = 0; j < pathItems.length - 1; j++) {
-                                        var cp = pathItems[j];
-                                        if (typeof obj[cp] !== 'object') obj[cp] = { };
-                                        obj = obj[cp];
-                                    }
-                                    obj[pathItems[pathItems.length - 1]] = (function() {
-                                        var cbName = path;
-                                        return function(params) {
-                                            return trans.invoke(cbName, params);
-                                        };
-                                    })();
-                                }
-                            }
-                            var resp = regTbl[method](trans, m.params);
-                            if (!trans.delayReturn() && !trans.completed()) trans.complete(resp);
-                        } catch(e) {
-                            // automagic handling of exceptions:
-                            var error = "runtime_error";
-                            var message = null;
-                            // * if it's a string then it gets an error code of 'runtime_error' and string is the message
-                            if (typeof e === 'string') {
-                                message = e;
-                            } else if (typeof e === 'object') {
-                                // either an array or an object
-                                // * if it's an array of length two, then  array[0] is the code, array[1] is the error message
-                                if (e && s_isArray(e) && e.length == 2) {
-                                    error = e[0];
-                                    message = e[1];
-                                }
-                                // * if it's an object then we'll look form error and message parameters
-                                else if (typeof e.error === 'string') {
-                                    error = e.error;
-                                    if (!e.message) message = "";
-                                    else if (typeof e.message === 'string') message = e.message;
-                                    else e = e.message; // let the stringify/toString message give us a reasonable verbose error string
-                                }
-                            }
-
-                            // message is *still* null, let's try harder
-                            if (message === null) {
-                                try {
-                                    message = JSON.stringify(e);
-                                    /* On MSIE8, this can result in 'out of memory', which
-                                     * leaves message undefined. */
-                                    if (typeof(message) == 'undefined')
-                                      message = e.toString();
-                                } catch (e2) {
-                                    message = e.toString();
-                                }
-                            }
-
-                            trans.error(error,message);
-                        }
-                    }
-                } else if (m.id && m.callback) {
-                    if (!outTbl[m.id] ||!outTbl[m.id].callbacks || !outTbl[m.id].callbacks[m.callback])
-                    {
-                        debug("ignoring invalid callback, id:"+m.id+ " (" + m.callback +")");
-                    } else {
-                        // XXX: what if client code raises an exception here?
-                        outTbl[m.id].callbacks[m.callback](m.params);
-                    }
-                } else if (m.id) {
-                    if (!outTbl[m.id]) {
-                        debug("ignoring invalid response: " + m.id);
-                    } else {
-                        // XXX: what if client code raises an exception here?
-                        if (m.error) {
-                            (1,outTbl[m.id].error)(m.error, m.message);
-                        } else {
-                            if (m.result !== undefined) (1,outTbl[m.id].success)(m.result);
-                            else (1,outTbl[m.id].success)();
-                        }
-                        delete outTbl[m.id];
-                        delete s_transIds[m.id];
-                    }
-                } else if (method) {
-                    // tis a notification.
-                    if (regTbl[method]) {
-                        // yep, there's a handler for that.
-                        // transaction has only origin for notifications.
-                        regTbl[method]({ origin: origin }, m.params);
-                        // if the client throws, we'll just let it bubble out
-                        // what can we do?  Also, here we'll ignore return values
-                    }
-                }
-            };
-
-            // now register our bound channel for msg routing
-            s_addBoundChan(cfg.window, cfg.origin, ((typeof cfg.scope === 'string') ? cfg.scope : ''), onMessage);
-
-            // scope method names based on cfg.scope specified when the Channel was instantiated
-            var scopeMethod = function(m) {
-                if (typeof cfg.scope === 'string' && cfg.scope.length) m = [cfg.scope, m].join("::");
-                return m;
-            };
-
-            // a small wrapper around postmessage whose primary function is to handle the
-            // case that clients start sending messages before the other end is "ready"
-            var postMessage = function(msg, force) {
-                if (!msg) throw "postMessage called with null message";
-
-                // delay posting if we're not ready yet.
-                var verb = (ready ? "post  " : "queue ");
-                debug(verb + " message: " + JSON.stringify(msg));
-                if (!force && !ready) {
-                    pendingQueue.push(msg);
-                } else {
-                    if (typeof cfg.postMessageObserver === 'function') {
-                        try {
-                            cfg.postMessageObserver(cfg.origin, msg);
-                        } catch (e) {
-                            debug("postMessageObserver() raised an exception: " + e.toString());
-                        }
-                    }
-
-                    cfg.window.postMessage(JSON.stringify(msg), cfg.origin);
-                }
-            };
-
-            var onReady = function(trans, type) {
-                debug('ready msg received');
-                if (ready) throw "received ready message while in ready state.  help!";
-
-                if (type === 'ping') {
-                    chanId += '-R';
-                } else {
-                    chanId += '-L';
-                }
-
-                obj.unbind('__ready'); // now this handler isn't needed any more.
-                ready = true;
-                debug('ready msg accepted.');
-
-                if (type === 'ping') {
-                    obj.notify({ method: '__ready', params: 'pong' });
-                }
-
-                // flush queue
-                while (pendingQueue.length) {
-                    postMessage(pendingQueue.pop());
-                }
-
-                // invoke onReady observer if provided
-                if (typeof cfg.onReady === 'function') cfg.onReady(obj);
-            };
-
-            var obj = {
-                // tries to unbind a bound message handler.  returns false if not possible
-                unbind: function (method) {
-                    if (regTbl[method]) {
-                        if (!(delete regTbl[method])) throw ("can't delete method: " + method);
-                        return true;
-                    }
-                    return false;
-                },
-                bind: function (method, cb) {
-                    if (!method || typeof method !== 'string') throw "'method' argument to bind must be string";
-                    if (!cb || typeof cb !== 'function') throw "callback missing from bind params";
-
-                    if (regTbl[method]) throw "method '"+method+"' is already bound!";
-                    regTbl[method] = cb;
-                    return this;
-                },
-                call: function(m) {
-                    if (!m) throw 'missing arguments to call function';
-                    if (!m.method || typeof m.method !== 'string') throw "'method' argument to call must be string";
-                    if (!m.success || typeof m.success !== 'function') throw "'success' callback missing from call";
-
-                    // now it's time to support the 'callback' feature of jschannel.  We'll traverse the argument
-                    // object and pick out all of the functions that were passed as arguments.
-                    var callbacks = { };
-                    var callbackNames = [ ];
-
-                    var pruneFunctions = function (path, obj) {
-                        if (typeof obj === 'object') {
-                            for (var k in obj) {
-                                if (!obj.hasOwnProperty(k)) continue;
-                                var np = path + (path.length ? '/' : '') + k;
-                                if (typeof obj[k] === 'function') {
-                                    callbacks[np] = obj[k];
-                                    callbackNames.push(np);
-                                    delete obj[k];
-                                } else if (typeof obj[k] === 'object') {
-                                    pruneFunctions(np, obj[k]);
-                                }
-                            }
-                        }
-                    };
-                    pruneFunctions("", m.params);
-
-                    // build a 'request' message and send it
-                    var msg = { id: s_curTranId, method: scopeMethod(m.method), params: m.params };
-                    if (callbackNames.length) msg.callbacks = callbackNames;
-
-                    if (m.timeout)
-                      // XXX: This function returns a timeout ID, but we don't do anything with it.
-                      // We might want to keep track of it so we can cancel it using clearTimeout()
-                      // when the transaction completes.
-                      setTransactionTimeout(s_curTranId, m.timeout, scopeMethod(m.method));
-
-                    // insert into the transaction table
-                    outTbl[s_curTranId] = { callbacks: callbacks, error: m.error, success: m.success };
-                    s_transIds[s_curTranId] = onMessage;
-
-                    // increment current id
-                    s_curTranId++;
-
-                    postMessage(msg);
-                },
-                notify: function(m) {
-                    if (!m) throw 'missing arguments to notify function';
-                    if (!m.method || typeof m.method !== 'string') throw "'method' argument to notify must be string";
-
-                    // no need to go into any transaction table
-                    postMessage({ method: scopeMethod(m.method), params: m.params });
-                },
-                destroy: function () {
-                    s_removeBoundChan(cfg.window, cfg.origin, ((typeof cfg.scope === 'string') ? cfg.scope : ''));
-                    if (window.removeEventListener) window.removeEventListener('message', onMessage, false);
-                    else if(window.detachEvent) window.detachEvent('onmessage', onMessage);
-                    ready = false;
-                    regTbl = { };
-                    inTbl = { };
-                    outTbl = { };
-                    cfg.origin = null;
-                    pendingQueue = [ ];
-                    debug("channel destroyed");
-                    chanId = "";
-                }
-            };
-
-            obj.bind('__ready', onReady);
-            setTimeout(function() {
-                postMessage({ method: scopeMethod('__ready'), params: "ping" }, true);
-            }, 0);
-
-            return obj;
-        }
-    };
-})();
-;/*
- * DOMParser HTML extension
- * 2012-09-04
- *
- * By Eli Grey, http://eligrey.com
- * Public domain.
- * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
- */
-/*! @source https://gist.github.com/1129031 */
-(function (DOMParser) {
-  "use strict";
-  var DOMParser_proto = DOMParser.prototype,
-    real_parseFromString = DOMParser_proto.parseFromString;
-
-  // Firefox/Opera/IE throw errors on unsupported types
-  try {
-    // WebKit returns null on unsupported types
-    if ((new DOMParser()).parseFromString("", "text/html")) {
-      // text/html parsing is natively supported
-      return;
-    }
-  } catch (ignore) {}
-
-  DOMParser_proto.parseFromString = function (markup, type) {
-    var result, doc, doc_elt, first_elt;
-    if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
-      doc = document.implementation.createHTMLDocument("");
-      doc_elt = doc.documentElement;
-
-      doc_elt.innerHTML = markup;
-      first_elt = doc_elt.firstElementChild;
-
-      if (doc_elt.childElementCount === 1
-          && first_elt.localName.toLowerCase() === "html") {
-        doc.replaceChild(first_elt, doc_elt);
-      }
-
-      result = doc;
-    } else {
-      result = real_parseFromString.apply(this, arguments);
-    }
-    return result;
-  };
-}(DOMParser));
-
-;// IE does not support have Document.prototype.contains.
-if (typeof document.contains !== 'function') {
-  Document.prototype.contains = function(node) {
-    if (node === this || node.parentNode === this)
-      return true;
-    return this.documentElement.contains(node);
- }
-}
-;/*! RenderJs */
-/*jslint nomen: true*/
-
-/*
- * renderJs - Generic Gadget library renderer.
- * http://www.renderjs.org/documentation
- */
-(function (document, window, RSVP, DOMParser, Channel, MutationObserver,
-           Node, FileReader, Blob, navigator, Event, URL) {
-  "use strict";
-
-  function readBlobAsDataURL(blob) {
-    var fr = new FileReader();
-    return new RSVP.Promise(function (resolve, reject) {
-      fr.addEventListener("load", function (evt) {
-        resolve(evt.target.result);
-      });
-      fr.addEventListener("error", reject);
-      fr.readAsDataURL(blob);
-    }, function () {
-      fr.abort();
-    });
-  }
-
-  function loopEventListener(target, type, useCapture, callback,
-                             prevent_default) {
-    //////////////////////////
-    // Infinite event listener (promise is never resolved)
-    // eventListener is removed when promise is cancelled/rejected
-    //////////////////////////
-    var handle_event_callback,
-      callback_promise;
-
-    if (prevent_default === undefined) {
-      prevent_default = true;
-    }
-
-    function cancelResolver() {
-      if ((callback_promise !== undefined) &&
-          (typeof callback_promise.cancel === "function")) {
-        callback_promise.cancel();
-      }
-    }
-
-    function canceller() {
-      if (handle_event_callback !== undefined) {
-        target.removeEventListener(type, handle_event_callback, useCapture);
-      }
-      cancelResolver();
-    }
-    function itsANonResolvableTrap(resolve, reject) {
-      var result;
-      handle_event_callback = function (evt) {
-        if (prevent_default) {
-          evt.stopPropagation();
-          evt.preventDefault();
-        }
-
-        cancelResolver();
-
-        try {
-          result = callback(evt);
-        } catch (e) {
-          result = RSVP.reject(e);
-        }
-
-        callback_promise = result;
-        new RSVP.Queue()
-          .push(function () {
-            return result;
-          })
-          .push(undefined, function (error) {
-            if (!(error instanceof RSVP.CancellationError)) {
-              canceller();
-              reject(error);
-            }
-          });
-      };
-
-      target.addEventListener(type, handle_event_callback, useCapture);
-    }
-    return new RSVP.Promise(itsANonResolvableTrap, canceller);
-  }
-
-  function ajax(url) {
-    var xhr;
-    function resolver(resolve, reject) {
-      function handler() {
-        try {
-          if (xhr.readyState === 0) {
-            // UNSENT
-            reject(xhr);
-          } else if (xhr.readyState === 4) {
-            // DONE
-            if ((xhr.status < 200) || (xhr.status >= 300) ||
-                (!/^text\/html[;]?/.test(
-                  xhr.getResponseHeader("Content-Type") || ""
-                ))) {
-              reject(xhr);
-            } else {
-              resolve(xhr);
-            }
-          }
-        } catch (e) {
-          reject(e);
-        }
-      }
-
-      xhr = new XMLHttpRequest();
-      xhr.open("GET", url);
-      xhr.onreadystatechange = handler;
-      xhr.setRequestHeader('Accept', 'text/html');
-      xhr.withCredentials = true;
-      xhr.send();
-    }
-
-    function canceller() {
-      if ((xhr !== undefined) && (xhr.readyState !== xhr.DONE)) {
-        xhr.abort();
-      }
-    }
-    return new RSVP.Promise(resolver, canceller);
-  }
-
-  var gadget_model_defer_dict = {},
-    javascript_registration_dict = {},
-    stylesheet_registration_dict = {},
-    gadget_loading_klass_list = [],
-    loading_klass_promise,
-    renderJS,
-    Monitor,
-    scope_increment = 0,
-    isAbsoluteOrDataURL = new RegExp('^(?:[a-z]+:)?//|data:', 'i'),
-    is_page_unloaded = false,
-    error_list = [];
-
-  window.addEventListener('error', function (error) {
-    error_list.push(error);
-  });
-
-  window.addEventListener('beforeunload', function () {
-    // XXX If another listener cancel the page unload,
-    // it will not restore renderJS crash report
-    is_page_unloaded = true;
-  });
-
-  /////////////////////////////////////////////////////////////////
-  // Helper functions
-  /////////////////////////////////////////////////////////////////
-  function removeHash(url) {
-    var index = url.indexOf('#');
-    if (index > 0) {
-      url = url.substring(0, index);
-    }
-    return url;
-  }
-
-  function letsCrash(e) {
-    var i,
-      body,
-      container,
-      paragraph,
-      link,
-      error;
-    if (is_page_unloaded) {
-      /*global console*/
-      console.info('-- Error dropped, as page is unloaded');
-      console.info(e);
-      return;
-    }
-
-    error_list.push(e);
-    // Add error handling stack
-    error_list.push(new Error('stopping renderJS'));
-
-    body = document.getElementsByTagName('body')[0];
-    while (body.firstChild) {
-      body.removeChild(body.firstChild);
-    }
-
-    container = document.createElement("section");
-    paragraph = document.createElement("h1");
-    paragraph.textContent = 'Unhandled Error';
-    container.appendChild(paragraph);
-
-    paragraph = document.createElement("p");
-    paragraph.textContent = 'Please report this error to the support team';
-    container.appendChild(paragraph);
-
-    paragraph = document.createElement("p");
-    paragraph.textContent = 'Location: ';
-    link = document.createElement("a");
-    link.href = link.textContent = window.location.toString();
-    paragraph.appendChild(link);
-    container.appendChild(paragraph);
-
-    paragraph = document.createElement("p");
-    paragraph.textContent = 'User-agent: ' + navigator.userAgent;
-    container.appendChild(paragraph);
-
-    paragraph = document.createElement("p");
-    paragraph.textContent = 'Date: ' + new Date(Date.now()).toISOString();
-    container.appendChild(paragraph);
-
-    body.appendChild(container);
-
-    for (i = 0; i < error_list.length; i += 1) {
-      error = error_list[i];
-
-      if (error instanceof Event) {
-        error = {
-          string: error.toString(),
-          message: error.message,
-          type: error.type,
-          target: error.target
-        };
-        if (error.target !== undefined) {
-          error_list.splice(i + 1, 0, error.target);
-        }
-      }
-
-      if (error instanceof XMLHttpRequest) {
-        error = {
-          message: error.toString(),
-          readyState: error.readyState,
-          status: error.status,
-          statusText: error.statusText,
-          response: error.response,
-          responseUrl: error.responseUrl,
-          response_headers: error.getAllResponseHeaders()
-        };
-      }
-      if (error.constructor === Array ||
-          error.constructor === String ||
-          error.constructor === Object) {
-        try {
-          error = JSON.stringify(error);
-        } catch (ignore) {
-        }
-      }
-
-      container = document.createElement("section");
-
-      paragraph = document.createElement("h2");
-      paragraph.textContent = error.message || error;
-      container.appendChild(paragraph);
-
-      if (error.fileName !== undefined) {
-        paragraph = document.createElement("p");
-        paragraph.textContent = 'File: ' +
-          error.fileName +
-          ': ' + error.lineNumber;
-        container.appendChild(paragraph);
-      }
-
-      if (error.stack !== undefined) {
-        paragraph = document.createElement("pre");
-        paragraph.textContent = 'Stack: ' + error.stack;
-        container.appendChild(paragraph);
-      }
-
-      body.appendChild(container);
-    }
-    // XXX Do not crash the application if it fails
-    // Where to write the error?
-    /*global console*/
-    console.error(e.stack);
-    console.error(e);
-  }
-
-  /////////////////////////////////////////////////////////////////
-  // Service Monitor promise
-  /////////////////////////////////////////////////////////////////
-  function ResolvedMonitorError(message) {
-    this.name = "resolved";
-    if ((message !== undefined) && (typeof message !== "string")) {
-      throw new TypeError('You must pass a string.');
-    }
-    this.message = message || "Default Message";
-  }
-  ResolvedMonitorError.prototype = new Error();
-  ResolvedMonitorError.prototype.constructor = ResolvedMonitorError;
-
-  Monitor = function () {
-    var monitor = this,
-      promise_list = [],
-      promise,
-      reject,
-      notify,
-      resolved;
-
-    if (!(this instanceof Monitor)) {
-      return new Monitor();
-    }
-
-    function canceller() {
-      var len = promise_list.length,
-        i;
-      for (i = 0; i < len; i += 1) {
-        promise_list[i].cancel();
-      }
-      // Clean it to speed up other canceller run
-      promise_list = [];
-    }
-
-    promise = new RSVP.Promise(function (done, fail, progress) {
-      reject = function (rejectedReason) {
-        if (resolved) {
-          return;
-        }
-        monitor.isRejected = true;
-        monitor.rejectedReason = rejectedReason;
-        resolved = true;
-        canceller();
-        return fail(rejectedReason);
-      };
-      notify = progress;
-    }, canceller);
-
-    monitor.cancel = function () {
-      if (resolved) {
-        return;
-      }
-      resolved = true;
-      promise.cancel();
-      promise.fail(function (rejectedReason) {
-        monitor.isRejected = true;
-        monitor.rejectedReason = rejectedReason;
-      });
-    };
-    monitor.then = function () {
-      return promise.then.apply(promise, arguments);
-    };
-    monitor.fail = function () {
-      return promise.fail.apply(promise, arguments);
-    };
-
-    monitor.monitor = function (promise_to_monitor) {
-      if (resolved) {
-        throw new ResolvedMonitorError();
-      }
-      var queue = new RSVP.Queue()
-        .push(function () {
-          return promise_to_monitor;
-        })
-        .push(function (fulfillmentValue) {
-          // Promise to monitor is fullfilled, remove it from the list
-          var len = promise_list.length,
-            sub_promise_to_monitor,
-            new_promise_list = [],
-            i;
-          for (i = 0; i < len; i += 1) {
-            sub_promise_to_monitor = promise_list[i];
-            if (!(sub_promise_to_monitor.isFulfilled ||
-                sub_promise_to_monitor.isRejected)) {
-              new_promise_list.push(sub_promise_to_monitor);
-            }
-          }
-          promise_list = new_promise_list;
-        }, function (rejectedReason) {
-          if (rejectedReason instanceof RSVP.CancellationError) {
-            if (!(promise_to_monitor.isFulfilled &&
-                  promise_to_monitor.isRejected)) {
-              // The queue could be cancelled before the first push is run
-              promise_to_monitor.cancel();
-            }
-          }
-          reject(rejectedReason);
-          throw rejectedReason;
-        }, function (notificationValue) {
-          notify(notificationValue);
-          return notificationValue;
-        });
-
-      promise_list.push(queue);
-
-      return this;
-    };
-  };
-
-  Monitor.prototype = Object.create(RSVP.Promise.prototype);
-  Monitor.prototype.constructor = Monitor;
-
-  /////////////////////////////////////////////////////////////////
-  // RenderJSGadget
-  /////////////////////////////////////////////////////////////////
-  function RenderJSGadget() {
-    if (!(this instanceof RenderJSGadget)) {
-      return new RenderJSGadget();
-    }
-  }
-  RenderJSGadget.prototype.__title = "";
-  RenderJSGadget.prototype.__interface_list = [];
-  RenderJSGadget.prototype.__path = "";
-  RenderJSGadget.prototype.__html = "";
-  RenderJSGadget.prototype.__required_css_list = [];
-  RenderJSGadget.prototype.__required_js_list = [];
-
-  function createMonitor(g) {
-    if (g.__monitor !== undefined) {
-      g.__monitor.cancel();
-    }
-    g.__monitor = new Monitor();
-    g.__job_dict = {};
-    g.__job_list = [];
-    g.__job_triggered = false;
-    g.__monitor.fail(function (error) {
-      if (!(error instanceof RSVP.CancellationError)) {
-        return g.aq_reportServiceError(error);
-      }
-    }).fail(function (error) {
-      // Crash the application if the acquisition generates an error.
-      return letsCrash(error);
-    });
-  }
-
-  function clearGadgetInternalParameters() {
-    this.__sub_gadget_dict = {};
-    createMonitor(this);
-  }
-
-  function loadSubGadgetDOMDeclaration() {
-    var element_list = this.element.querySelectorAll('[data-gadget-url]'),
-      element,
-      promise_list = [],
-      scope,
-      url,
-      sandbox,
-      i,
-      context = this;
-
-    function prepareReportGadgetDeclarationError(scope) {
-      return function (error) {
-        var aq_dict = context.__acquired_method_dict || {},
-          method_name = 'reportGadgetDeclarationError';
-        if (aq_dict.hasOwnProperty(method_name)) {
-          return aq_dict[method_name].apply(context,
-                                            [arguments, scope]);
-        }
-        throw error;
-      };
-    }
-
-    for (i = 0; i < element_list.length; i += 1) {
-      element = element_list[i];
-      scope = element.getAttribute("data-gadget-scope");
-      url = element.getAttribute("data-gadget-url");
-      sandbox = element.getAttribute("data-gadget-sandbox");
-      if (url !== null) {
-        promise_list.push(
-          context.declareGadget(url, {
-            element: element,
-            scope: scope || undefined,
-            sandbox: sandbox || undefined
-          })
-            .push(undefined, prepareReportGadgetDeclarationError(scope))
-        );
-      }
-    }
-
-    return RSVP.all(promise_list);
-  }
-
-  RenderJSGadget.__ready_list = [clearGadgetInternalParameters,
-                                 loadSubGadgetDOMDeclaration];
-  RenderJSGadget.ready = function (callback) {
-    this.__ready_list.push(callback);
-    return this;
-  };
-  RenderJSGadget.setState = function (state_dict) {
-    var json_state = JSON.stringify(state_dict);
-    this.__ready_list.unshift(function () {
-      this.state = JSON.parse(json_state);
-    });
-    return this;
-  };
-  RenderJSGadget.onStateChange = function (callback) {
-    this.prototype.__state_change_callback = callback;
-    return this;
-  };
-
-  RenderJSGadget.__service_list = [];
-  RenderJSGadget.declareService = function (callback) {
-    this.__service_list.push(callback);
-    return this;
-  };
-  RenderJSGadget.onEvent = function (type, callback, use_capture,
-                                     prevent_default) {
-    this.__service_list.push(function () {
-      return loopEventListener(this.element, type, use_capture,
-                               callback.bind(this), prevent_default);
-    });
-    return this;
-  };
-
-  function runJob(gadget, name, callback, argument_list) {
-    var job_promise = new RSVP.Queue()
-      .push(function () {
-        return callback.apply(gadget, argument_list);
-      });
-    if (gadget.__job_dict.hasOwnProperty(name)) {
-      gadget.__job_dict[name].cancel();
-    }
-    gadget.__job_dict[name] = job_promise;
-    gadget.__monitor.monitor(new RSVP.Queue()
-      .push(function () {
-        return job_promise;
-      })
-      .push(undefined, function (error) {
-        if (!(error instanceof RSVP.CancellationError)) {
-          throw error;
-        }
-      }));
-  }
-
-  function startService(gadget) {
-    gadget.__monitor.monitor(new RSVP.Queue()
-      .push(function () {
-        var i,
-          service_list = gadget.constructor.__service_list,
-          job_list = gadget.__job_list;
-        for (i = 0; i < service_list.length; i += 1) {
-          gadget.__monitor.monitor(service_list[i].apply(gadget));
-        }
-        for (i = 0; i < job_list.length; i += 1) {
-          runJob(gadget, job_list[i][0], job_list[i][1], job_list[i][2]);
-        }
-        gadget.__job_list = [];
-        gadget.__job_triggered = true;
-      })
-      );
-  }
-
-  /////////////////////////////////////////////////////////////////
-  // RenderJSGadget.declareJob
-  // gadget internal method, which trigger execution
-  // of a function inside a service
-  /////////////////////////////////////////////////////////////////
-  RenderJSGadget.declareJob = function (name, callback) {
-    this.prototype[name] = function () {
-      var context = this,
-        argument_list = arguments;
-
-      if (context.__job_triggered) {
-        runJob(context, name, callback, argument_list);
-      } else {
-        context.__job_list.push([name, callback, argument_list]);
-      }
-    };
-    // Allow chain
-    return this;
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // RenderJSGadget.declareMethod
-  /////////////////////////////////////////////////////////////////
-  RenderJSGadget.declareMethod = function (name, callback) {
-    this.prototype[name] = function () {
-      var context = this,
-        argument_list = arguments;
-
-      return new RSVP.Queue()
-        .push(function () {
-          return callback.apply(context, argument_list);
-        });
-    };
-    // Allow chain
-    return this;
-  };
-
-  RenderJSGadget
-    .declareMethod('getInterfaceList', function () {
-      // Returns the list of gadget prototype
-      return this.__interface_list;
-    })
-    .declareMethod('getRequiredCSSList', function () {
-      // Returns a list of CSS required by the gadget
-      return this.__required_css_list;
-    })
-    .declareMethod('getRequiredJSList', function () {
-      // Returns a list of JS required by the gadget
-      return this.__required_js_list;
-    })
-    .declareMethod('getPath', function () {
-      // Returns the path of the code of a gadget
-      return this.__path;
-    })
-    .declareMethod('getTitle', function () {
-      // Returns the title of a gadget
-      return this.__title;
-    })
-    .declareMethod('getElement', function () {
-      // Returns the DOM Element of a gadget
-      // XXX Kept for compatibility. Use element property directly
-      if (this.element === undefined) {
-        throw new Error("No element defined");
-      }
-      return this.element;
-    })
-    .declareMethod('changeState', function (state_dict) {
-      var key,
-        modified = false,
-        previous_cancelled = this.hasOwnProperty('__modification_dict'),
-        modification_dict,
-        context = this;
-      if (previous_cancelled) {
-        modification_dict = this.__modification_dict;
-        modified = true;
-      } else {
-        modification_dict = {};
-        this.__modification_dict = modification_dict;
-      }
-      for (key in state_dict) {
-        if (state_dict.hasOwnProperty(key) &&
-            (state_dict[key] !== this.state[key])) {
-          this.state[key] = state_dict[key];
-          modification_dict[key] = state_dict[key];
-          modified = true;
-        }
-      }
-      if (modified && this.__state_change_callback !== undefined) {
-        return new RSVP.Queue()
-          .push(function () {
-            return context.__state_change_callback(modification_dict);
-          })
-          .push(function (result) {
-            delete context.__modification_dict;
-            return result;
-          });
-      }
-    });
-
-  /////////////////////////////////////////////////////////////////
-  // RenderJSGadget.declareAcquiredMethod
-  /////////////////////////////////////////////////////////////////
-  function acquire(child_gadget, method_name, argument_list) {
-    var gadget = this,
-      key,
-      gadget_scope;
-
-    for (key in gadget.__sub_gadget_dict) {
-      if (gadget.__sub_gadget_dict.hasOwnProperty(key)) {
-        if (gadget.__sub_gadget_dict[key] === child_gadget) {
-          gadget_scope = key;
-        }
-      }
-    }
-    return new RSVP.Queue()
-      .push(function () {
-        // Do not specify default __acquired_method_dict on prototype
-        // to prevent modifying this default value (with
-        // allowPublicAcquiredMethod for example)
-        var aq_dict = gadget.__acquired_method_dict || {};
-        if (aq_dict.hasOwnProperty(method_name)) {
-          return aq_dict[method_name].apply(gadget,
-                                            [argument_list, gadget_scope]);
-        }
-        throw new renderJS.AcquisitionError("aq_dynamic is not defined");
-      })
-      .push(undefined, function (error) {
-        if (error instanceof renderJS.AcquisitionError) {
-          return gadget.__aq_parent(method_name, argument_list);
-        }
-        throw error;
-      });
-  }
-
-  RenderJSGadget.declareAcquiredMethod =
-    function (name, method_name_to_acquire) {
-      this.prototype[name] = function () {
-        var argument_list = Array.prototype.slice.call(arguments, 0),
-          gadget = this;
-        return new RSVP.Queue()
-          .push(function () {
-            return gadget.__aq_parent(method_name_to_acquire, argument_list);
-          });
-      };
-
-      // Allow chain
-      return this;
-    };
-  RenderJSGadget.declareAcquiredMethod("aq_reportServiceError",
-                                       "reportServiceError");
-  RenderJSGadget.declareAcquiredMethod("aq_reportGadgetDeclarationError",
-                                       "reportGadgetDeclarationError");
-
-  /////////////////////////////////////////////////////////////////
-  // RenderJSGadget.allowPublicAcquisition
-  /////////////////////////////////////////////////////////////////
-  RenderJSGadget.allowPublicAcquisition =
-    function (method_name, callback) {
-      this.prototype.__acquired_method_dict[method_name] = callback;
-
-      // Allow chain
-      return this;
-    };
-
-  // Set aq_parent on gadget_instance which call acquire on parent_gadget
-  function setAqParent(gadget_instance, parent_gadget) {
-    gadget_instance.__aq_parent = function (method_name, argument_list) {
-      return acquire.apply(parent_gadget, [gadget_instance, method_name,
-                                           argument_list]);
-    };
-  }
-
-  /////////////////////////////////////////////////////////////////
-  // RenderJSEmbeddedGadget
-  /////////////////////////////////////////////////////////////////
-  // Class inheritance
-  function RenderJSEmbeddedGadget() {
-    if (!(this instanceof RenderJSEmbeddedGadget)) {
-      return new RenderJSEmbeddedGadget();
-    }
-    RenderJSGadget.call(this);
-  }
-  RenderJSEmbeddedGadget.__ready_list = RenderJSGadget.__ready_list.slice();
-  RenderJSEmbeddedGadget.__service_list =
-    RenderJSGadget.__service_list.slice();
-  RenderJSEmbeddedGadget.ready =
-    RenderJSGadget.ready;
-  RenderJSEmbeddedGadget.setState =
-    RenderJSGadget.setState;
-  RenderJSEmbeddedGadget.onStateChange =
-    RenderJSGadget.onStateChange;
-  RenderJSEmbeddedGadget.declareService =
-    RenderJSGadget.declareService;
-  RenderJSEmbeddedGadget.onEvent =
-    RenderJSGadget.onEvent;
-  RenderJSEmbeddedGadget.prototype = new RenderJSGadget();
-  RenderJSEmbeddedGadget.prototype.constructor = RenderJSEmbeddedGadget;
-
-  /////////////////////////////////////////////////////////////////
-  // privateDeclarePublicGadget
-  /////////////////////////////////////////////////////////////////
-  function privateDeclarePublicGadget(url, options, parent_gadget) {
-
-    return new RSVP.Queue()
-      .push(function () {
-        return renderJS.declareGadgetKlass(url)
-          // gadget loading should not be interrupted
-          // if not, gadget's definition will not be complete
-          //.then will return another promise
-          //so loading_klass_promise can't be cancel
-          .then(function (result) {
-            return result;
-          });
-      })
-      // Get the gadget class and instanciate it
-      .push(function (Klass) {
-        if (options.element === undefined) {
-          options.element = document.createElement("div");
-        }
-        var i,
-          gadget_instance,
-          template_node_list = Klass.__template_element.body.childNodes,
-          fragment = document.createDocumentFragment();
-        gadget_instance = new Klass();
-        gadget_instance.element = options.element;
-        gadget_instance.state = {};
-        for (i = 0; i < template_node_list.length; i += 1) {
-          fragment.appendChild(
-            template_node_list[i].cloneNode(true)
-          );
-        }
-        gadget_instance.element.appendChild(fragment);
-        setAqParent(gadget_instance, parent_gadget);
-        return gadget_instance;
-      });
-  }
-
-  /////////////////////////////////////////////////////////////////
-  // RenderJSIframeGadget
-  /////////////////////////////////////////////////////////////////
-  function RenderJSIframeGadget() {
-    if (!(this instanceof RenderJSIframeGadget)) {
-      return new RenderJSIframeGadget();
-    }
-    RenderJSGadget.call(this);
-  }
-  RenderJSIframeGadget.__ready_list = RenderJSGadget.__ready_list.slice();
-  RenderJSIframeGadget.ready =
-    RenderJSGadget.ready;
-  RenderJSIframeGadget.setState =
-    RenderJSGadget.setState;
-  RenderJSIframeGadget.onStateChange =
-    RenderJSGadget.onStateChange;
-  RenderJSIframeGadget.__service_list = RenderJSGadget.__service_list.slice();
-  RenderJSIframeGadget.declareService =
-    RenderJSGadget.declareService;
-  RenderJSIframeGadget.onEvent =
-    RenderJSGadget.onEvent;
-  RenderJSIframeGadget.prototype = new RenderJSGadget();
-  RenderJSIframeGadget.prototype.constructor = RenderJSIframeGadget;
-
-  /////////////////////////////////////////////////////////////////
-  // privateDeclareIframeGadget
-  /////////////////////////////////////////////////////////////////
-  function privateDeclareIframeGadget(url, options, parent_gadget) {
-    var gadget_instance,
-      iframe,
-      iframe_loading_deferred = RSVP.defer();
-    if (options.element === undefined) {
-      throw new Error("DOM element is required to create Iframe Gadget " +
-                      url);
-    }
-
-    // Check if the element is attached to the DOM
-    if (!document.contains(options.element)) {
-      throw new Error("The parent element is not attached to the DOM for " +
-                      url);
-    }
-
-    gadget_instance = new RenderJSIframeGadget();
-    setAqParent(gadget_instance, parent_gadget);
-    iframe = document.createElement("iframe");
-    iframe.addEventListener('error', function (error) {
-      iframe_loading_deferred.reject(error);
-    });
-    iframe.addEventListener('load', function () {
-      return RSVP.timeout(5000)
-        .fail(function () {
-          iframe_loading_deferred.reject(
-            new Error('Timeout while loading: ' + url)
-          );
-        });
-    });
-//    gadget_instance.element.setAttribute("seamless", "seamless");
-    iframe.setAttribute("src", url);
-    gadget_instance.__path = url;
-    gadget_instance.element = options.element;
-    gadget_instance.state = {};
-    // Attach it to the DOM
-    options.element.appendChild(iframe);
-
-    // XXX Manage unbind when deleting the gadget
-
-    // Create the communication channel with the iframe
-    gadget_instance.__chan = Channel.build({
-      window: iframe.contentWindow,
-      origin: "*",
-      scope: "renderJS"
-    });
-
-    // Create new method from the declareMethod call inside the iframe
-    gadget_instance.__chan.bind("declareMethod",
-                                function (trans, method_name) {
-        gadget_instance[method_name] = function () {
-          var argument_list = arguments,
-            wait_promise = new RSVP.Promise(function (resolve, reject) {
-              gadget_instance.__chan.call({
-                method: "methodCall",
-                params: [
-                  method_name,
-                  Array.prototype.slice.call(argument_list, 0)],
-                success: function (s) {
-                  resolve(s);
-                },
-                error: function (e) {
-                  reject(e);
-                }
-              });
-            });
-          return new RSVP.Queue()
-            .push(function () {
-              return wait_promise;
-            });
-        };
-        return "OK";
-      });
-
-    // Wait for the iframe to be loaded before continuing
-    gadget_instance.__chan.bind("ready", function (trans) {
-      iframe_loading_deferred.resolve(gadget_instance);
-      return "OK";
-    });
-    gadget_instance.__chan.bind("failed", function (trans, params) {
-      iframe_loading_deferred.reject(params);
-      return "OK";
-    });
-    gadget_instance.__chan.bind("acquire", function (trans, params) {
-      gadget_instance.__aq_parent.apply(gadget_instance, params)
-        .then(function (g) {
-          trans.complete(g);
-        }).fail(function (e) {
-          trans.error(e.toString());
-        });
-      trans.delayReturn(true);
-    });
-
-    return iframe_loading_deferred.promise;
-  }
-
-  /////////////////////////////////////////////////////////////////
-  // privateDeclareDataUrlGadget
-  /////////////////////////////////////////////////////////////////
-  function privateDeclareDataUrlGadget(url, options, parent_gadget) {
-
-    return new RSVP.Queue()
-      .push(function () {
-        return ajax(url);
-      })
-      .push(function (xhr) {
-        // Insert a "base" element, in order to resolve all relative links
-        // which could get broken with a data url
-        var doc = (new DOMParser()).parseFromString(xhr.responseText,
-                                                    'text/html'),
-          base = doc.createElement('base'),
-          blob;
-        base.href = url;
-        doc.head.insertBefore(base, doc.head.firstChild);
-        blob = new Blob([doc.documentElement.outerHTML],
-                        {type: "text/html;charset=UTF-8"});
-        return readBlobAsDataURL(blob);
-      })
-      .push(function (data_url) {
-        return privateDeclareIframeGadget(data_url, options, parent_gadget);
-      });
-  }
-
-  /////////////////////////////////////////////////////////////////
-  // RenderJSGadget.declareGadget
-  /////////////////////////////////////////////////////////////////
-  RenderJSGadget
-    .declareMethod('declareGadget', function (url, options) {
-      var parent_gadget = this;
-
-      if (options === undefined) {
-        options = {};
-      }
-      if (options.sandbox === undefined) {
-        options.sandbox = "public";
-      }
-
-      // transform url to absolute url if it is relative
-      url = renderJS.getAbsoluteURL(url, this.__path);
-
-      return new RSVP.Queue()
-        .push(function () {
-          var method;
-          if (options.sandbox === "public") {
-            method = privateDeclarePublicGadget;
-          } else if (options.sandbox === "iframe") {
-            method = privateDeclareIframeGadget;
-          } else if (options.sandbox === "dataurl") {
-            method = privateDeclareDataUrlGadget;
-          } else {
-            throw new Error("Unsupported sandbox options '" +
-                            options.sandbox + "'");
-          }
-          return method(url, options, parent_gadget);
-        })
-        // Set the HTML context
-        .push(function (gadget_instance) {
-          var i,
-            scope,
-            queue = new RSVP.Queue();
-          // Trigger calling of all ready callback
-          function ready_wrapper() {
-            return gadget_instance;
-          }
-          function ready_executable_wrapper(fct) {
-            return function () {
-              return fct.call(gadget_instance, gadget_instance);
-            };
-          }
-          for (i = 0; i < gadget_instance.constructor.__ready_list.length;
-               i += 1) {
-            // Put a timeout?
-            queue.push(ready_executable_wrapper(
-              gadget_instance.constructor.__ready_list[i]
-            ));
-            // Always return the gadget instance after ready function
-            queue.push(ready_wrapper);
-          }
-
-          // Store local reference to the gadget instance
-          scope = options.scope;
-          if (scope === undefined) {
-            scope = 'RJS_' + scope_increment;
-            scope_increment += 1;
-            while (parent_gadget.__sub_gadget_dict.hasOwnProperty(scope)) {
-              scope = 'RJS_' + scope_increment;
-              scope_increment += 1;
-            }
-          }
-          parent_gadget.__sub_gadget_dict[scope] = gadget_instance;
-          gadget_instance.element.setAttribute("data-gadget-scope",
-                                               scope);
-
-          // Put some attribute to ease page layout comprehension
-          gadget_instance.element.setAttribute("data-gadget-url", url);
-          gadget_instance.element.setAttribute("data-gadget-sandbox",
-                                               options.sandbox);
-          gadget_instance.element._gadget = gadget_instance;
-
-          if (document.contains(gadget_instance.element)) {
-            // Put a timeout
-            queue.push(startService);
-          }
-          // Always return the gadget instance after ready function
-          queue.push(ready_wrapper);
-
-          return queue;
-        });
-    })
-    .declareMethod('getDeclaredGadget', function (gadget_scope) {
-      if (!this.__sub_gadget_dict.hasOwnProperty(gadget_scope)) {
-        throw new Error("Gadget scope '" + gadget_scope + "' is not known.");
-      }
-      return this.__sub_gadget_dict[gadget_scope];
-    })
-    .declareMethod('dropGadget', function (gadget_scope) {
-      if (!this.__sub_gadget_dict.hasOwnProperty(gadget_scope)) {
-        throw new Error("Gadget scope '" + gadget_scope + "' is not known.");
-      }
-      // http://perfectionkills.com/understanding-delete/
-      delete this.__sub_gadget_dict[gadget_scope];
-    });
-
-  /////////////////////////////////////////////////////////////////
-  // renderJS selector
-  /////////////////////////////////////////////////////////////////
-  renderJS = function (selector) {
-    var result;
-    if (selector === window) {
-      // window is the 'this' value when loading a javascript file
-      // In this case, use the current loading gadget constructor
-      result = gadget_loading_klass_list[0];
-    }
-    if (result === undefined) {
-      throw new Error("Unknown selector '" + selector + "'");
-    }
-    return result;
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // renderJS.AcquisitionError
-  /////////////////////////////////////////////////////////////////
-  renderJS.AcquisitionError = function (message) {
-    this.name = "AcquisitionError";
-    if ((message !== undefined) && (typeof message !== "string")) {
-      throw new TypeError('You must pass a string.');
-    }
-    this.message = message || "Acquisition failed";
-  };
-  renderJS.AcquisitionError.prototype = new Error();
-  renderJS.AcquisitionError.prototype.constructor =
-    renderJS.AcquisitionError;
-
-  /////////////////////////////////////////////////////////////////
-  // renderJS.getAbsoluteURL
-  /////////////////////////////////////////////////////////////////
-  renderJS.getAbsoluteURL = function (url, base_url) {
-    if (base_url && url) {
-      return new URL(url, base_url).href;
-    }
-    return url;
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // renderJS.declareJS
-  /////////////////////////////////////////////////////////////////
-  renderJS.declareJS = function (url, container, pop) {
-    // https://www.html5rocks.com/en/tutorials/speed/script-loading/
-    // Prevent infinite recursion if loading render.js
-    // more than once
-    var result;
-    if (javascript_registration_dict.hasOwnProperty(url)) {
-      result = RSVP.resolve();
-    } else {
-      javascript_registration_dict[url] = null;
-      result = new RSVP.Promise(function (resolve, reject) {
-        var newScript;
-        newScript = document.createElement('script');
-        newScript.async = false;
-        newScript.type = 'text/javascript';
-        newScript.onload = function () {
-          if (pop === true) {
-            // Drop the current loading klass info used by selector
-            gadget_loading_klass_list.shift();
-          }
-          resolve();
-        };
-        newScript.onerror = function (e) {
-          if (pop === true) {
-            // Drop the current loading klass info used by selector
-            gadget_loading_klass_list.shift();
-          }
-          reject(e);
-        };
-        newScript.src = url;
-        container.appendChild(newScript);
-      });
-    }
-    return result;
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // renderJS.declareCSS
-  /////////////////////////////////////////////////////////////////
-  renderJS.declareCSS = function (url, container) {
-    // https://github.com/furf/jquery-getCSS/blob/master/jquery.getCSS.js
-    // No way to cleanly check if a css has been loaded
-    // So, always resolve the promise...
-    // http://requirejs.org/docs/faq-advanced.html#css
-    var result;
-    if (stylesheet_registration_dict.hasOwnProperty(url)) {
-      result = RSVP.resolve();
-    } else {
-      result = new RSVP.Promise(function (resolve, reject) {
-        var link;
-        link = document.createElement('link');
-        link.rel = 'stylesheet';
-        link.type = 'text/css';
-        link.href = url;
-        link.onload = function () {
-          stylesheet_registration_dict[url] = null;
-          resolve();
-        };
-        link.onerror = function (e) {
-          reject(e);
-        };
-        container.appendChild(link);
-      });
-    }
-    return result;
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // renderJS.declareGadgetKlass
-  /////////////////////////////////////////////////////////////////
-
-  function parse(xhr, url) {
-    var tmp_constructor,
-      key,
-      parsed_html;
-    // Class inheritance
-    tmp_constructor = function () {
-      RenderJSGadget.call(this);
-    };
-    tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice();
-    tmp_constructor.__service_list = RenderJSGadget.__service_list.slice();
-    tmp_constructor.declareMethod =
-      RenderJSGadget.declareMethod;
-    tmp_constructor.declareJob =
-      RenderJSGadget.declareJob;
-    tmp_constructor.declareAcquiredMethod =
-      RenderJSGadget.declareAcquiredMethod;
-    tmp_constructor.allowPublicAcquisition =
-      RenderJSGadget.allowPublicAcquisition;
-    tmp_constructor.ready =
-      RenderJSGadget.ready;
-    tmp_constructor.setState =
-      RenderJSGadget.setState;
-    tmp_constructor.onStateChange =
-      RenderJSGadget.onStateChange;
-    tmp_constructor.declareService =
-      RenderJSGadget.declareService;
-    tmp_constructor.onEvent =
-      RenderJSGadget.onEvent;
-    tmp_constructor.prototype = new RenderJSGadget();
-    tmp_constructor.prototype.constructor = tmp_constructor;
-    tmp_constructor.prototype.__path = url;
-    tmp_constructor.prototype.__acquired_method_dict = {};
-    // https://developer.mozilla.org/en-US/docs/HTML_in_XMLHttpRequest
-    // https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
-    // https://developer.mozilla.org/en-US/docs/Code_snippets/HTML_to_DOM
-    tmp_constructor.__template_element =
-      (new DOMParser()).parseFromString(xhr.responseText, "text/html");
-    parsed_html = renderJS.parseGadgetHTMLDocument(
-      tmp_constructor.__template_element,
-      url
-    );
-    for (key in parsed_html) {
-      if (parsed_html.hasOwnProperty(key)) {
-        tmp_constructor.prototype['__' + key] = parsed_html[key];
-      }
-    }
-    return tmp_constructor;
-  }
-
-  renderJS.declareGadgetKlass = function (url) {
-    if (gadget_model_defer_dict.hasOwnProperty(url)) {
-      // Return klass object if it already exists
-      return gadget_model_defer_dict[url].promise;
-    }
-
-    var tmp_constructor,
-      defer = RSVP.defer();
-
-    gadget_model_defer_dict[url] = defer;
-
-    // Change the global variable to update the loading queue
-    loading_klass_promise = defer.promise;
-
-    // Fetch the HTML page and parse it
-    return new RSVP.Queue()
-      .push(function () {
-        return ajax(url);
-      })
-      .push(function (result) {
-        tmp_constructor = parse(result, url);
-        var fragment = document.createDocumentFragment(),
-          promise_list = [],
-          i,
-          js_list = tmp_constructor.prototype.__required_js_list,
-          css_list = tmp_constructor.prototype.__required_css_list;
-        // Load JS
-        if (js_list.length) {
-          gadget_loading_klass_list.push(tmp_constructor);
-          for (i = 0; i < js_list.length - 1; i += 1) {
-            promise_list.push(renderJS.declareJS(js_list[i], fragment));
-          }
-          promise_list.push(renderJS.declareJS(js_list[i], fragment, true));
-        }
-        // Load CSS
-        for (i = 0; i < css_list.length; i += 1) {
-          promise_list.push(renderJS.declareCSS(css_list[i], fragment));
-        }
-        document.head.appendChild(fragment);
-        return RSVP.all(promise_list);
-      })
-      .push(function () {
-        defer.resolve(tmp_constructor);
-        return tmp_constructor;
-      })
-      .push(undefined, function (e) {
-        // Drop the current loading klass info used by selector
-        // even in case of error
-        defer.reject(e);
-        throw e;
-      });
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // renderJS.clearGadgetKlassList
-  /////////////////////////////////////////////////////////////////
-  // For test purpose only
-  renderJS.clearGadgetKlassList = function () {
-    gadget_model_defer_dict = {};
-    javascript_registration_dict = {};
-    stylesheet_registration_dict = {};
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // renderJS.parseGadgetHTMLDocument
-  /////////////////////////////////////////////////////////////////
-  renderJS.parseGadgetHTMLDocument = function (document_element, url) {
-    var settings = {
-        title: "",
-        interface_list: [],
-        required_css_list: [],
-        required_js_list: []
-      },
-      i,
-      element;
-
-    if (!url || !isAbsoluteOrDataURL.test(url)) {
-      throw new Error("The url should be absolute: " + url);
-    }
-
-    if (document_element.nodeType === 9) {
-      settings.title = document_element.title;
-
-      if (document_element.head !== null) {
-        for (i = 0; i < document_element.head.children.length; i += 1) {
-          element = document_element.head.children[i];
-          if (element.href !== null) {
-            // XXX Manage relative URL during extraction of URLs
-            // element.href returns absolute URL in firefox but "" in chrome;
-            if (element.rel === "stylesheet") {
-              settings.required_css_list.push(
-                renderJS.getAbsoluteURL(element.getAttribute("href"), url)
-              );
-            } else if (element.nodeName === "SCRIPT" &&
-                       (element.type === "text/javascript" ||
-                        !element.type)) {
-              settings.required_js_list.push(
-                renderJS.getAbsoluteURL(element.getAttribute("src"), url)
-              );
-            } else if (element.rel ===
-                       "http://www.renderjs.org/rel/interface") {
-              settings.interface_list.push(
-                renderJS.getAbsoluteURL(element.getAttribute("href"), url)
-              );
-            }
-          }
-        }
-      }
-    } else {
-      throw new Error("The first parameter should be an HTMLDocument");
-    }
-    return settings;
-  };
-
-  /////////////////////////////////////////////////////////////////
-  // global
-  /////////////////////////////////////////////////////////////////
-  window.rJS = window.renderJS = renderJS;
-  window.__RenderJSGadget = RenderJSGadget;
-  window.__RenderJSEmbeddedGadget = RenderJSEmbeddedGadget;
-  window.__RenderJSIframeGadget = RenderJSIframeGadget;
-
-  ///////////////////////////////////////////////////
-  // Bootstrap process. Register the self gadget.
-  ///////////////////////////////////////////////////
-
-  function bootstrap() {
-    var url = removeHash(window.location.href),
-      TmpConstructor,
-      root_gadget,
-      loading_gadget_promise = new RSVP.Queue(),
-      declare_method_count = 0,
-      embedded_channel,
-      notifyReady,
-      notifyDeclareMethod,
-      gadget_ready = false,
-      iframe_top_gadget,
-      last_acquisition_gadget,
-      declare_method_list_waiting = [],
-      gadget_failed = false,
-      gadget_error,
-      connection_ready = false;
-
-    // Create the gadget class for the current url
-    if (gadget_model_defer_dict.hasOwnProperty(url)) {
-      throw new Error("bootstrap should not be called twice");
-    }
-    loading_klass_promise = new RSVP.Promise(function (resolve, reject) {
-
-      last_acquisition_gadget = new RenderJSGadget();
-      last_acquisition_gadget.__acquired_method_dict = {
-        reportServiceError: function (param_list) {
-          letsCrash(param_list[0]);
-        }
-      };
-      // Stop acquisition on the last acquisition gadget
-      // Do not put this on the klass, as their could be multiple instances
-      last_acquisition_gadget.__aq_parent = function (method_name) {
-        throw new renderJS.AcquisitionError(
-          "No gadget provides " + method_name
-        );
-      };
-
-      //we need to determine tmp_constructor's value before exit bootstrap
-      //because of function : renderJS
-      //but since the channel checking is async,
-      //we can't use code structure like:
-      // if channel communication is ok
-      //    tmp_constructor = RenderJSGadget
-      // else
-      //    tmp_constructor = RenderJSEmbeddedGadget
-      if (window.self === window.top) {
-        // XXX Copy/Paste from declareGadgetKlass
-        TmpConstructor = function () {
-          RenderJSGadget.call(this);
-        };
-        TmpConstructor.declareMethod = RenderJSGadget.declareMethod;
-        TmpConstructor.declareJob = RenderJSGadget.declareJob;
-        TmpConstructor.declareAcquiredMethod =
-          RenderJSGadget.declareAcquiredMethod;
-        TmpConstructor.allowPublicAcquisition =
-          RenderJSGadget.allowPublicAcquisition;
-        TmpConstructor.__ready_list = RenderJSGadget.__ready_list.slice();
-        TmpConstructor.ready = RenderJSGadget.ready;
-        TmpConstructor.setState = RenderJSGadget.setState;
-        TmpConstructor.onStateChange = RenderJSGadget.onStateChange;
-        TmpConstructor.__service_list = RenderJSGadget.__service_list.slice();
-        TmpConstructor.declareService =
-          RenderJSGadget.declareService;
-        TmpConstructor.onEvent =
-          RenderJSGadget.onEvent;
-        TmpConstructor.prototype = new RenderJSGadget();
-        TmpConstructor.prototype.constructor = TmpConstructor;
-        TmpConstructor.prototype.__path = url;
-        gadget_model_defer_dict[url] = {
-          promise: RSVP.resolve(TmpConstructor)
-        };
-
-        // Create the root gadget instance and put it in the loading stack
-        root_gadget = new TmpConstructor();
-
-        setAqParent(root_gadget, last_acquisition_gadget);
-
-      } else {
-        // Create the root gadget instance and put it in the loading stack
-        TmpConstructor = RenderJSEmbeddedGadget;
-        TmpConstructor.__ready_list = RenderJSGadget.__ready_list.slice();
-        TmpConstructor.__service_list = RenderJSGadget.__service_list.slice();
-        TmpConstructor.prototype.__path = url;
-        root_gadget = new RenderJSEmbeddedGadget();
-        setAqParent(root_gadget, last_acquisition_gadget);
-
-        // Create the communication channel
-        embedded_channel = Channel.build({
-          window: window.parent,
-          origin: "*",
-          scope: "renderJS",
-          onReady: function () {
-            var k;
-            iframe_top_gadget = false;
-            //Default: Define __aq_parent to inform parent window
-            root_gadget.__aq_parent =
-              TmpConstructor.prototype.__aq_parent = function (method_name,
-                argument_list, time_out) {
-                return new RSVP.Promise(function (resolve, reject) {
-                  embedded_channel.call({
-                    method: "acquire",
-                    params: [
-                      method_name,
-                      argument_list
-                    ],
-                    success: function (s) {
-                      resolve(s);
-                    },
-                    error: function (e) {
-                      reject(e);
-                    },
-                    timeout: time_out
-                  });
-                });
-              };
-
-            // Channel is ready, so now declare Function
-            notifyDeclareMethod = function (name) {
-              declare_method_count += 1;
-              embedded_channel.call({
-                method: "declareMethod",
-                params: name,
-                success: function () {
-                  declare_method_count -= 1;
-                  notifyReady();
-                },
-                error: function () {
-                  declare_method_count -= 1;
-                }
-              });
-            };
-            for (k = 0; k < declare_method_list_waiting.length; k += 1) {
-              notifyDeclareMethod(declare_method_list_waiting[k]);
-            }
-            declare_method_list_waiting = [];
-            // If Gadget Failed Notify Parent
-            if (gadget_failed) {
-              embedded_channel.notify({
-                method: "failed",
-                params: gadget_error
-              });
-              return;
-            }
-            connection_ready = true;
-            notifyReady();
-            //the channel is ok
-            //so bind calls to renderJS method on the instance
-            embedded_channel.bind("methodCall", function (trans, v) {
-              root_gadget[v[0]].apply(root_gadget, v[1])
-                .then(function (g) {
-                  trans.complete(g);
-                }).fail(function (e) {
-                  trans.error(e.toString());
-                });
-              trans.delayReturn(true);
-            });
-          }
-        });
-
-        // Notify parent about gadget instanciation
-        notifyReady = function () {
-          if ((declare_method_count === 0) && (gadget_ready === true)) {
-            embedded_channel.notify({method: "ready"});
-          }
-        };
-
-        // Inform parent gadget about declareMethod calls here.
-        notifyDeclareMethod = function (name) {
-          declare_method_list_waiting.push(name);
-        };
-
-        notifyDeclareMethod("getInterfaceList");
-        notifyDeclareMethod("getRequiredCSSList");
-        notifyDeclareMethod("getRequiredJSList");
-        notifyDeclareMethod("getPath");
-        notifyDeclareMethod("getTitle");
-
-        // Surcharge declareMethod to inform parent window
-        TmpConstructor.declareMethod = function (name, callback) {
-          var result = RenderJSGadget.declareMethod.apply(
-              this,
-              [name, callback]
-            );
-          notifyDeclareMethod(name);
-          return result;
-        };
-
-        TmpConstructor.declareService =
-          RenderJSGadget.declareService;
-        TmpConstructor.declareJob =
-          RenderJSGadget.declareJob;
-        TmpConstructor.onEvent =
-          RenderJSGadget.onEvent;
-        TmpConstructor.declareAcquiredMethod =
-          RenderJSGadget.declareAcquiredMethod;
-        TmpConstructor.allowPublicAcquisition =
-          RenderJSGadget.allowPublicAcquisition;
-
-        iframe_top_gadget = true;
-      }
-
-      TmpConstructor.prototype.__acquired_method_dict = {};
-      gadget_loading_klass_list.push(TmpConstructor);
-
-      function init() {
-        // XXX HTML properties can only be set when the DOM is fully loaded
-        var settings = renderJS.parseGadgetHTMLDocument(document, url),
-          j,
-          key,
-          fragment = document.createDocumentFragment();
-        for (key in settings) {
-          if (settings.hasOwnProperty(key)) {
-            TmpConstructor.prototype['__' + key] = settings[key];
-          }
-        }
-        TmpConstructor.__template_element = document.createElement("div");
-        root_gadget.element = document.body;
-        root_gadget.state = {};
-        for (j = 0; j < root_gadget.element.childNodes.length; j += 1) {
-          fragment.appendChild(
-            root_gadget.element.childNodes[j].cloneNode(true)
-          );
-        }
-        TmpConstructor.__template_element.appendChild(fragment);
-        RSVP.all([root_gadget.getRequiredJSList(),
-                  root_gadget.getRequiredCSSList()])
-          .then(function (all_list) {
-            var i,
-              js_list = all_list[0],
-              css_list = all_list[1];
-            for (i = 0; i < js_list.length; i += 1) {
-              javascript_registration_dict[js_list[i]] = null;
-            }
-            for (i = 0; i < css_list.length; i += 1) {
-              stylesheet_registration_dict[css_list[i]] = null;
-            }
-            gadget_loading_klass_list.shift();
-          }).then(function () {
-
-            // select the target node
-            var target = document.querySelector('body'),
-              // create an observer instance
-              observer = new MutationObserver(function (mutations) {
-                var i, k, len, len2, node, added_list;
-                mutations.forEach(function (mutation) {
-                  if (mutation.type === 'childList') {
-
-                    len = mutation.removedNodes.length;
-                    for (i = 0; i < len; i += 1) {
-                      node = mutation.removedNodes[i];
-                      if (node.nodeType === Node.ELEMENT_NODE) {
-                        if (node.hasAttribute("data-gadget-url") &&
-                            (node._gadget !== undefined)) {
-                          createMonitor(node._gadget);
-                        }
-                        added_list =
-                          node.querySelectorAll("[data-gadget-url]");
-                        len2 = added_list.length;
-                        for (k = 0; k < len2; k += 1) {
-                          node = added_list[k];
-                          if (node._gadget !== undefined) {
-                            createMonitor(node._gadget);
-                          }
-                        }
-                      }
-                    }
-
-                    len = mutation.addedNodes.length;
-                    for (i = 0; i < len; i += 1) {
-                      node = mutation.addedNodes[i];
-                      if (node.nodeType === Node.ELEMENT_NODE) {
-                        if (node.hasAttribute("data-gadget-url") &&
-                            (node._gadget !== undefined)) {
-                          if (document.contains(node)) {
-                            startService(node._gadget);
-                          }
-                        }
-                        added_list =
-                          node.querySelectorAll("[data-gadget-url]");
-                        len2 = added_list.length;
-                        for (k = 0; k < len2; k += 1) {
-                          node = added_list[k];
-                          if (document.contains(node)) {
-                            if (node._gadget !== undefined) {
-                              startService(node._gadget);
-                            }
-                          }
-                        }
-                      }
-                    }
-
-                  }
-                });
-              }),
-              // configuration of the observer:
-              config = {
-                childList: true,
-                subtree: true,
-                attributes: false,
-                characterData: false
-              };
-
-            // pass in the target node, as well as the observer options
-            observer.observe(target, config);
-
-            return root_gadget;
-          }).then(resolve, function (e) {
-            reject(e);
-            console.error(e);
-            throw e;
-          });
-      }
-      document.addEventListener('DOMContentLoaded', init, false);
-    });
-
-    loading_gadget_promise
-      .push(function () {
-        return loading_klass_promise;
-      })
-      .push(function (root_gadget) {
-        var i;
-
-        function ready_wrapper() {
-          return root_gadget;
-        }
-        function ready_executable_wrapper(fct) {
-          return function (g) {
-            return fct.call(g, g);
-          };
-        }
-        TmpConstructor.ready(function () {
-          return startService(this);
-        });
-
-        loading_gadget_promise.push(ready_wrapper);
-        for (i = 0; i < TmpConstructor.__ready_list.length; i += 1) {
-          // Put a timeout?
-          loading_gadget_promise
-            .push(ready_executable_wrapper(TmpConstructor.__ready_list[i]))
-            // Always return the gadget instance after ready function
-            .push(ready_wrapper);
-        }
-      });
-    if (window.self === window.top) {
-      loading_gadget_promise
-        .fail(function (e) {
-          letsCrash(e);
-          throw e;
-        });
-    } else {
-      // Inform parent window that gadget is correctly loaded
-      loading_gadget_promise
-        .then(function () {
-          gadget_ready = true;
-          if (connection_ready) {
-            notifyReady();
-          }
-        })
-        .fail(function (e) {
-          //top gadget in iframe
-          if (iframe_top_gadget) {
-            gadget_failed = true;
-            gadget_error = e.toString();
-            letsCrash(e);
-          } else {
-            embedded_channel.notify({method: "failed", params: e.toString()});
-          }
-          throw e;
-        });
-    }
-
-  }
-  bootstrap();
-
-}(document, window, RSVP, DOMParser, Channel, MutationObserver, Node,
-  FileReader, Blob, navigator, Event, URL));
diff --git a/apps/maarch_entreprise/merged_jsAbstract.php b/apps/maarch_entreprise/merged_jsAbstract.php
index 4b290c31169..232e14834a4 100755
--- a/apps/maarch_entreprise/merged_jsAbstract.php
+++ b/apps/maarch_entreprise/merged_jsAbstract.php
@@ -67,10 +67,6 @@ class MergedJsAbstract
         include 'apps/maarch_entreprise/js/indexing.js';
         readfile('apps/maarch_entreprise/js/angularFunctions.js');
 
-        // include('apps/maarch_entreprise/js/RSVP.js');
-        // include('apps/maarch_entreprise/js/render.js');
-        // include('apps/maarch_entreprise/js/jio.js');
-
         echo "\n";
     }
 
diff --git a/apps/maarch_entreprise/xml/IVS/requests_definitions.xml b/apps/maarch_entreprise/xml/IVS/requests_definitions.xml
index 85ece34b844..6bc9aa266e4 100755
--- a/apps/maarch_entreprise/xml/IVS/requests_definitions.xml
+++ b/apps/maarch_entreprise/xml/IVS/requests_definitions.xml
@@ -80,18 +80,6 @@
       <parameter name="display" value="true"/>
       <parameter name="selectedObject"/>
     </requestDefinition>
-    <requestDefinition method="POST" path="/apps/maarch_entreprise/index.php" validationRule="ajax_ShowTown" >
-      <parameter name="dir" value="indexing_searching"/>
-      <parameter name="page" value="ajaxShowVille"/>
-      <parameter name="display" value="true"/>
-      <parameter name="id"/>
-    </requestDefinition>
-    <requestDefinition method="POST" path="/apps/maarch_entreprise/index.php" validationRule="ajax_ShowCP" >
-      <parameter name="dir" value="indexing_searching"/>
-      <parameter name="page" value="ajaxShowCodePostal"/>
-      <parameter name="display" value="true"/>
-      <parameter name="id"/>
-    </requestDefinition>
     <requestDefinition method="POST" path="/apps/maarch_entreprise/index.php" validationRule="choose_file" >
       <parameter name="dir" value="indexing_searching"/>
       <parameter name="page" value="choose_file"/>
diff --git a/apps/maarch_entreprise/xml/IVS/validation_rules.xml b/apps/maarch_entreprise/xml/IVS/validation_rules.xml
index 26aef881b68..690143a50fb 100755
--- a/apps/maarch_entreprise/xml/IVS/validation_rules.xml
+++ b/apps/maarch_entreprise/xml/IVS/validation_rules.xml
@@ -287,18 +287,6 @@
       <parameter name="url" type="string" />
     </validationRule>
     
-    <validationRule name="ajax_ShowTown" extends="standardForm" mode="error">  
-      <parameter name="what" type="identifier" />
-      <parameter name="dir" type="identifier" />
-      <parameter name="id" type="integer" />
-    </validationRule>
-
-    <validationRule name="ajax_ShowCP" extends="standardForm" mode="error">  
-      <parameter name="what" type="safetext" />
-      <parameter name="dir" type="identifier" />
-      <parameter name="id" type="integer" />
-    </validationRule>
-    
     <validationRule name="type_id_integer" extends="standardForm" mode="error">  
       <parameter name="type_id" type="integer" />
       <parameter name="dir" type="identifier" />
diff --git a/core/class/usergroups_controler.php b/core/class/usergroups_controler.php
index 899854ed7a9..900a40af317 100755
--- a/core/class/usergroups_controler.php
+++ b/core/class/usergroups_controler.php
@@ -33,7 +33,6 @@
 // Loads the required class
 try {
     require_once 'core/core_tables.php';
-    require_once 'modules/basket/basket_tables.php';
     require_once 'core/class/usergroups.php';
     require_once 'core/class/ObjectControlerAbstract.php';
     require_once 'core/class/ObjectControlerIF.php';
@@ -150,8 +149,7 @@ class usergroups_controler extends ObjectControler implements ObjectControlerIF
         }
         $baskets = array();
         $db = new Database();
-        $query = 'select basket_id from ' . GROUPBASKET_TABLE
-               . " where group_id = ?";
+        $query = 'select basket_id from groupbasket where group_id = ?';
         try {
             $stmt = $db->query($query, array($groupId));
         } catch (Exception $e) {
diff --git a/modules/basket/basket_tables.php b/modules/basket/basket_tables.php
deleted file mode 100755
index cf60b620cee..00000000000
--- a/modules/basket/basket_tables.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-define('BASKET_TABLE', 'baskets');
-define('GROUPBASKET_TABLE', 'groupbasket');
-define('ACTIONS_GROUPBASKET_TABLE', 'actions_groupbaskets');
-
diff --git a/modules/basket/class/class_modules_tools_Abstract.php b/modules/basket/class/class_modules_tools_Abstract.php
index d5a1fd602fb..11ba1f51631 100755
--- a/modules/basket/class/class_modules_tools_Abstract.php
+++ b/modules/basket/class/class_modules_tools_Abstract.php
@@ -42,7 +42,6 @@
 require_once 'core/class/SecurityControler.php';
 require_once 'core/class/class_security.php';
 require_once 'core/core_tables.php';
-require_once 'modules/basket/basket_tables.php';
 require_once 'modules/entities/entities_tables.php';
 
 
@@ -152,8 +151,7 @@ abstract class basket_Abstract extends Database
         $stmt = $db->query(
             "select agb.id_action, agb.where_clause, agb.used_in_basketlist, "
             . "agb.used_in_action_page, a.label_action, a.id_status, "
-            . "a.action_page from actions a, "
-            . ACTIONS_GROUPBASKET_TABLE . " agb where a.id = agb.id_action and "
+            . "a.action_page from actions a, actions_groupbaskets agb where a.id = agb.id_action and "
             . "agb.group_id = ? and agb.basket_id = ? and "
             . "agb.default_action_list ='N'",
             array($groupId,$basketId)
@@ -201,8 +199,7 @@ abstract class basket_Abstract extends Database
     {
         $db = new Database();
         $stmt = $db->query(
-            "select agb.id_action from actions a, "
-            . ACTIONS_GROUPBASKET_TABLE . " agb where a.id = agb.id_action "
+            "select agb.id_action from actions a, actions_groupbaskets agb where a.id = agb.id_action "
             . "and agb.group_id = ? and agb.basket_id = ? "
             . "and agb.default_action_list ='Y'",
             array($groupId,$basketId)
@@ -293,221 +290,6 @@ abstract class basket_Abstract extends Database
         }
         return $jsonActions;
     }
-    /**
-     * Builds the basket results list (using class_list_show.php method)
-     *
-     * @param   $paramsList  array  Parameters array used to display the result
-     *                              list
-     * @param   $actions actions  Array to be displayed in the list
-     * @param   $lineTxt  string String to be displayed at the bottom of the
-     *                       list to describe the default action
-     */
-    public function basket_list_doc($paramsList, $actions, $lineTxt)
-    {
-        ////////////////////////////////////////////////////////////////////////
-        //$this->show_array($paramsList);
-        ////////////////////////////////////////////////////////////////////////
-        $actionForm = '';
-        $boolCheckForm = false;
-        $method = '';
-        $actionsList = array();
-        // Browse the actions array to build the jason string that will be used
-        // to display the actions in the list
-        if (count($actions) > 0) {
-            for ($i = 0; $i < count($actions); $i ++) {
-                if ($actions[$i]['MASS_USE'] == 'Y') {
-                    array_push(
-                        $actionsList,
-                        array(
-                            'VALUE' => $actions[$i]['ID'],
-                            'LABEL' => addslashes($actions[$i]['LABEL']),
-                        )
-                    );
-                }
-            }
-        }
-
-        $jsonActions = $this->translates_actions_to_json($actions);
-
-        if (count($actionsList) > 0) {
-            $actionForm = $_SESSION['config']['businessappurl']
-            . 'index.php?display=true&page=manage_action'
-            . '&module=core';
-            $boolCheckForm = true;
-            $method = 'get';
-        }
-
-        $doAction = false;
-        if (! empty($_SESSION['current_basket']['default_action'])) {
-            $doAction = true;
-        }
-
-        $list = new list_show();
-        if (! isset($paramsList['link_in_line'])) {
-            $paramsList['link_in_line'] = false;
-        }
-        if (! isset($paramsList['template'])) {
-            $paramsList['template'] = false;
-        }
-        if (! isset($paramsList['template_list'])) {
-            $paramsList['template_list'] = array();
-        }
-        if (! isset($paramsList['actual_template'])) {
-            $paramsList['actual_template'] = '';
-        }
-        if (! isset($paramsList['bool_export'])) {
-            $paramsList['bool_export'] = false;
-        }
-        if (! isset($paramsList['comp_link'])) {
-            $paramsList['comp_link'] = '';
-        }
-        $str = '';
-        // Displays the list using list_doc method from class_list_shows
-        $str .= $list->list_doc(
-            $paramsList['values'],
-            count($paramsList['values']),
-            $paramsList['title'],
-            $paramsList['what'],
-            $paramsList['page_name'],
-            $paramsList['key'],
-            $paramsList['detail_destination'],
-            $paramsList['view_doc'],
-            false,
-            $method,
-            $actionForm,
-            '',
-            $paramsList['bool_details'],
-            $paramsList['bool_order'],
-            $paramsList['bool_frame'],
-            $paramsList['bool_export'],
-            false,
-            false,
-            true,
-            $boolCheckForm,
-            '',
-            $paramsList['module'],
-            false,
-            '',
-            '',
-            $paramsList['css'],
-            $paramsList['comp_link'],
-            $paramsList['link_in_line'],
-            true,
-            $actionsList,
-            $paramsList['hidden_fields'],
-            $jsonActions,
-            $doAction,
-            $_SESSION['current_basket']['default_action'],
-            $paramsList['open_details_popup'],
-            $paramsList['do_actions_arr'],
-            $paramsList['template'],
-            $paramsList['template_list'],
-            $paramsList['actual_template'],
-            true
-        );
-
-        // Displays the text line if needed
-        if (count($paramsList['values']) > 0 && ($paramsList['link_in_line']
-        || $doAction)
-        ) {
-            $str .= "<em>".$lineTxt."</em>";
-        }
-        if (! isset($paramsList['mode_string'])
-        || $paramsList['mode_string'] == false
-        ) {
-            echo $str;
-        } else {
-            return $str;
-        }
-    }
-
-    /**
-     * Returns the actions for the current basket for a given mode.
-     * The mode can be "MASS_USE" or "PAGE_USE".
-     *
-     * @param   $resId  string  Resource identifier
-     *   (used in PAGE_USE mode to test the action where_clause)
-     * @param   $collId  string Collection identifier
-     *   (used in PAGE_USE mode to test the action where_clause)
-     * @param   $mode  string  "PAGE_USE" or "MASS_USE"
-     * @param   $testWhere  boolean
-     * @return array  Actions to be displayed
-     */
-    public function get_actions_from_current_basket($resId, $collId, $mode, $testWhere = true)
-    {
-        $arr = [];
-
-        if ($_SESSION['category_id'] == '') {
-            $_SESSION['category_id'] = $_SESSION['coll_categories'][$collId]['default_category'];
-        }
-
-        if (empty($resId) || empty($collId) || (strtoupper($mode) != 'MASS_USE' && strtoupper($mode) != 'PAGE_USE')) {
-            return $arr;
-        } else {
-            $sec = new security();
-            $db = new Database();
-            $table = $sec->retrieve_view_from_coll_id($collId);
-            if (empty($table)) {
-                $table = $sec->retrieve_table_from_coll_id($collId);
-            }
-            if (empty($table)) {
-                // If the view and the table of the collection is empty,
-                return $arr;
-            }
-            // If mode "PAGE_USE", add the action 'end_action' to validate the current action
-            if ($mode == 'PAGE_USE') {
-                $db = new Database();
-                $stmt = $db->query("SELECT label_action FROM actions WHERE id= ?", [$_SESSION['current_basket']['default_action']]);
-                $label_action = $stmt->fetchObject();
-                $arr[] = ['VALUE' => 'end_action', 'LABEL' => $label_action->label_action.' (par défaut)'];
-            }
-
-            // Browsing the current basket actions to build the actions array
-            for ($i = 0; $i < count($_SESSION['current_basket']['actions']); $i++) {
-                $noFilterOnCat = true;
-                if (!empty($_SESSION['current_basket']['actions'][$i]['CATEGORIES'])
-                    && is_array($_SESSION['current_basket']['actions'][$i]['CATEGORIES'])
-                    && count($_SESSION['current_basket']['actions'][$i]['CATEGORIES']) > 0) {
-                    $noFilterOnCat = false;
-                }
-                $categoryIdForActions = '';
-                $cl = 0;
-                if (!empty($_SESSION['current_basket']['actions'][$i]['CATEGORIES']) && is_array($_SESSION['current_basket']['actions'][$i]['CATEGORIES'])) {
-                    $cl = count($_SESSION['current_basket']['actions'][$i]['CATEGORIES']);
-                }
-
-                for ($cptCat=0; $cptCat < $cl; $cptCat++) {
-                    if ($_SESSION['current_basket']['actions'][$i]['CATEGORIES'][$cptCat] == $_SESSION['category_id']) {
-                        $categoryIdForActions = $_SESSION['category_id'];
-                    }
-                }
-                if ($noFilterOnCat || $categoryIdForActions != '') {
-                    // If in mode "PAGE_USE", testing the action where clause on the res_id before adding the action
-                    if (
-                        strtoupper($mode) == 'PAGE_USE'
-                        && $_SESSION['current_basket']['actions'][$i]['PAGE_USE'] == 'Y'
-                        && $testWhere && strtoupper($resId) != 'NONE'
-                    ) {
-                        $where = ' where res_id = ' . $resId;
-                        if (!empty($_SESSION['current_basket']['actions'][$i]['WHERE'])) {
-                            $where = $where . ' and ' . $_SESSION['current_basket']['actions'][$i]['WHERE'];
-                        }
-                        $stmt = $db->query('select res_id from ' . $table . ' ' . $where);
-                        if ($stmt->rowCount() > 0) {
-                            $arr[] = ['VALUE' => $_SESSION['current_basket']['actions'][$i]['ID'], 'LABEL' => $_SESSION['current_basket']['actions'][$i]['LABEL']];
-                        }
-                    } elseif (strtoupper($mode) == 'PAGE_USE' && $_SESSION['current_basket']['actions'][$i]['PAGE_USE'] == 'Y') {
-                        $arr[] = ['VALUE' => $_SESSION['current_basket']['actions'][$i]['ID'], 'LABEL' => $_SESSION['current_basket']['actions'][$i]['LABEL']];
-                    } elseif (strtoupper($mode) == 'MASS_USE' && $_SESSION['current_basket']['actions'][$i]['MASS_USE'] == 'Y') {
-                        // If "MASS_USE" adding the actions in the array
-                        $arr[] = ['VALUE' => $_SESSION['current_basket']['actions'][$i]['ID'], 'LABEL' => $_SESSION['current_basket']['actions'][$i]['LABEL']];
-                    }
-                }
-            }
-        }
-
-        return $arr;
-    }
 
     /**
      * Returns in an array all the data of a basket for a user
@@ -525,8 +307,7 @@ abstract class basket_Abstract extends Database
         $secCtrl = new SecurityControler();
         $stmt = $db->query(
             "select basket_id, coll_id, basket_name, basket_desc, "
-            . "basket_clause, is_visible, color, basket_res_order from "
-            . BASKET_TABLE . " where basket_id = ? and enabled = 'Y'",
+            . "basket_clause, is_visible, color, basket_res_order from baskets where basket_id = ? and enabled = 'Y'",
             array($basketId)
         );
         $res = $stmt->fetchObject();
diff --git a/modules/basket/css/module.css b/modules/basket/css/module.css
index e4e7e84a681..81165765597 100755
--- a/modules/basket/css/module.css
+++ b/modules/basket/css/module.css
@@ -10,16 +10,6 @@
 	text-align:left;
 }
 
-/* admin modules board */
-#bask_admin_baskets {
-	background:  url(static.php?module=basket&filename=manage_baskets.gif) no-repeat 2px top;
-}
-
-#bask_admin_entities {
-	background:  url(static.php?module=basket&filename=manage_entities.gif) no-repeat 2px top;
-}
-
-
 /* show baskets or no in the nav bar */
 #nav #baskets {
 	text-align: right;
@@ -30,53 +20,6 @@
 	height:20px;
 }
 
-#nav #no_baskets {
-	text-align: right;
-	float: right;
-	padding: 3px 20px 6px 25px;
-	height:20px;
-	color: #FFFFFF;
-}
-
-/* basket on the welcome page */
-
-#welcome_desc #basket
-{
-	margin-left: 150px;
-}
-/*
-#baskets_list
-{
-	width: 300px;
-	height: 45px;
-	padding-top: 10px;
-	padding-bottom: 10px;
-	float:right;
-	margin-top: 20px;
-}
-*/
-
-/* box on admin */
-
-#add_box_diff_list .tit {
-	color: #F99830;
-}
-
-#add_box_diff_list {
-	/*border: 1px solid #999;*/
-	background-color: White;
-	float: right;
-	width: 465px;
-/*	margin: 0 10px 0 0;
-	padding: 20px 25px;*/
-}
-
-
-
-#add_box_diff_list .frameform2 {
-	height: 360px;
-}
-
 .title
 {
 text-align:center;
@@ -84,57 +27,6 @@ font-size:16px;
 font-weight:bold;
 }
 
-.listingbasket {
-	margin: 10px 12px 0 12px;
-	width: 95%;
-}
-
-.listingbasket th {
-	color: #135F7F;
-}
-
-.listingbasket th .add {
-	font-weight: normal;
-}
-
-
-.listingbasket th, .listingbasket td {
-	text-align: left;
-	padding: 5px 10px 6px 20px;
-	vertical-align: middle;
-}
-.listingbasket td {
-	background-color: #135F7F33;
-}
-.listingbasket .col td {
-	background-color: #DEEDF3;
-}
-
-.listingbasket .price {
-	text-align: right;
-	padding-right: 0;
-	padding-bottom: 0;
-
-}
-
-.listingbasket tfoot .price {
-	background-color: transparent;
-}
-.listingbasket a:hover
-{
-	color: #666665;
-}
-.listingbasket td  input[type="radio"]{
-	background-color: #135F7F33;
-}
-.listingbasket .col td  input[type="radio"]{
-	background-color: #DEEDF3;
-}
-.listingbasket td  input
-{
-	width: 200px;
-}
-
 /*Automplete*/
 div.autocomplete {
   position: absolute;
@@ -175,8 +67,3 @@ div.autocomplete ul li span.informal {
 {
 	margin-left:10px;
 }
-
-#manage_groupbasket li
-{
-	text-align: left;
-}
diff --git a/modules/basket/lang/en.php b/modules/basket/lang/en.php
index b6884618bd8..ad91095b1a0 100755
--- a/modules/basket/lang/en.php
+++ b/modules/basket/lang/en.php
@@ -20,10 +20,6 @@
  */
 
 /*********************** SERVICES ***********************************/
-if (!defined("_ADMIN_BASKETS"))
-    define("_ADMIN_BASKETS", "Baskets");
-if (!defined("_USE_BASKETS"))
-    define("_USE_BASKETS", "Use the baskets");
 if (!defined("_DIFFUSION_LIST"))
     define("_DIFFUSION_LIST", "Diffusion List");
 
@@ -38,18 +34,6 @@ if (!defined("_THE_ID"))
     define("_THE_ID", "The ID ");
 if (!defined("_THE_DESC"))
     define("_THE_DESC", "The description ");
-if (!defined("_BELONGS_TO_NO_GROUP"))
-    define("_BELONGS_TO_NO_GROUP", "Does not belong to any group");
-if (!defined("_SYSTEM_BASKET_MESSAGE"))
-    define("_SYSTEM_BASKET_MESSAGE", "This basket is a system basket, you cannot modify the table and the where clause either. They are displayed for information");
-if (!defined("_BASKET_MISSING"))
-    define("_BASKET_MISSING", "The basket doesn't exist");
-if (!defined("_BASKET_UPDATED"))
-    define("_BASKET_UPDATED", "Modified basket");
-if (!defined("_BASKET_UPDATE"))
-    define("_BASKET_UPDATE", "Basket modification");
-if (!defined("_BASKET_ADDED"))
-    define("_BASKET_ADDED", "Added new basket");
 if (!defined("_DELETED_BASKET"))
     define("_DELETED_BASKET", "Deleted basket");
 if (!defined("_BASKET_DELETION"))
@@ -353,8 +337,6 @@ if (!defined("_ARCHIVE_LIST"))
     define("_ARCHIVE_LIST", "Archiving units list");
 if (!defined("_COUNT_LIST"))
     define("_COUNT_LIST", "Copies list");
-if (!defined("_FILTER_BY_ENTITY"))
-    define("_FILTER_BY_ENTITY", "Filter by department");
 if (!defined("_FILTER_BY"))
     define("_FILTER_BY", "Filter by");
 if (!defined("_OTHER_BASKETS"))
@@ -393,28 +375,3 @@ if (!defined("_COMBINATED_ACTION"))
     define("_COMBINATED_ACTION", "Combined action");
 if (!defined("_END_OF_THE_WF"))
     define("_END_OF_THE_WF", "Workflow end");
-
-if (!defined("_BASKET_VISIBLE_ONLY_ON_SEARCH"))
-    define("_BASKET_VISIBLE_ONLY_ON_SEARCH", "Only search basket");
-
-if (!defined("_MANAGE_SECONDARY_USER_BASKETS"))
-    define("_MANAGE_SECONDARY_USER_BASKETS", "Manage the access to the second groups.");
-if (!defined("_MANAGE_SECONDARY_USER_BASKETS_TEXT"))
-    define("_MANAGE_SECONDARY_USER_BASKETS_TEXT", "Allows to manage the access to user's secondary groups baskets ");
-if (!defined("_MANAGE_SECONDARY_USER_BASKETS_HELP"))
-    define("_MANAGE_SECONDARY_USER_BASKETS_HELP", "The user must have a second group at least with baskets to access to this function.");
-if (!defined("_MANAGE_SECONDARY_USER_BASKETS_HELP_COMPL"))
-    define("_MANAGE_SECONDARY_USER_BASKETS_HELP_COMPL", "(Add a secondary group with baskets, then save the user before coming back to this screen.");
-if (!defined("_MANAGE_BASKET_ORDER"))
-    define("_MANAGE_BASKET_ORDER", "Manage baskets order");
-if (!defined("_MOVE_UP_TOP"))
-    define("_MOVE_UP_TOP", "Move up to the bottom of the list");
-if (!defined("_MOVE_UP_ONE_LEVEL"))
-    define("_MOVE_UP_ONE_LEVEL", "Move a lign up");
-if (!defined("_MOVE_DOWN_ONE_LEVEL"))
-    define("_MOVE_DOWN_ONE_LEVEL", "Move down one lign");
-if (!defined("_MOVE_DOWN_BOTTOM"))
-    define("_MOVE_DOWN_BOTTOM", "Move down on the bottom of the list");
-
-if (!defined("_BASKET_ORDER_EDITED"))
-    define("_BASKET_ORDER_EDITED", "Modified baskets orders");
diff --git a/modules/basket/lang/fr.php b/modules/basket/lang/fr.php
index 010cacfc275..8050a70ab5b 100755
--- a/modules/basket/lang/fr.php
+++ b/modules/basket/lang/fr.php
@@ -20,10 +20,6 @@
  */
 
 /*********************** SERVICES ***********************************/
-if (!defined("_ADMIN_BASKETS"))
-    define("_ADMIN_BASKETS", "Bannettes");
-if (!defined("_USE_BASKETS"))
-    define("_USE_BASKETS", "Utiliser les bannettes");
 if (!defined("_DIFFUSION_LIST"))
     define("_DIFFUSION_LIST", "Liste de diffusion");
 
@@ -38,18 +34,6 @@ if (!defined("_THE_ID"))
     define("_THE_ID", "L'identifiant ");
 if (!defined("_THE_DESC"))
     define("_THE_DESC", "La description ");
-if (!defined("_BELONGS_TO_NO_GROUP"))
-    define("_BELONGS_TO_NO_GROUP", "n'appartient à aucun groupe");
-if (!defined("_SYSTEM_BASKET_MESSAGE"))
-    define("_SYSTEM_BASKET_MESSAGE", "Cette bannette est une bannette système, vous ne pouvez pas modifier la table et la where clause. Elles sont affichées à titre indicatif");
-if (!defined("_BASKET_MISSING"))
-    define("_BASKET_MISSING", "La Bannette n'existe pas");
-if (!defined("_BASKET_UPDATED"))
-    define("_BASKET_UPDATED", "Bannette modifiée");
-if (!defined("_BASKET_UPDATE"))
-    define("_BASKET_UPDATE", "Modification de la bannette");
-if (!defined("_BASKET_ADDED"))
-    define("_BASKET_ADDED", "Nouvelle bannette ajoutée");
 if (!defined("_DELETED_BASKET"))
     define("_DELETED_BASKET", "Bannette supprimée");
 if (!defined("_BASKET_DELETION"))
@@ -353,8 +337,6 @@ if (!defined("_ARCHIVE_LIST"))
     define("_ARCHIVE_LIST", "Liste d'unités d'archive");
 if (!defined("_COUNT_LIST"))
     define("_COUNT_LIST", "Liste des copies");
-if (!defined("_FILTER_BY_ENTITY"))
-    define("_FILTER_BY_ENTITY", "Filtrer par entité");
 if (!defined("_FILTER_BY"))
     define("_FILTER_BY", "Filtrer par");
 if (!defined("_OTHER_BASKETS"))
@@ -393,28 +375,3 @@ if (!defined("_COMBINATED_ACTION"))
     define("_COMBINATED_ACTION", "Action combinée");
 if (!defined("_END_OF_THE_WF"))
     define("_END_OF_THE_WF", "Fin du workflow");
-
-if (!defined("_BASKET_VISIBLE_ONLY_ON_SEARCH"))
-    define("_BASKET_VISIBLE_ONLY_ON_SEARCH", "Bannette de recherche uniquement");
-
-if (!defined("_MANAGE_SECONDARY_USER_BASKETS"))
-    define("_MANAGE_SECONDARY_USER_BASKETS", "Gérer l'accès aux bannettes des groupes secondaires.");
-if (!defined("_MANAGE_SECONDARY_USER_BASKETS_TEXT"))
-    define("_MANAGE_SECONDARY_USER_BASKETS_TEXT", "Permet de gérer l'accès à des bannettes des groupes secondaires de l'utilisateur.");
-if (!defined("_MANAGE_SECONDARY_USER_BASKETS_HELP"))
-    define("_MANAGE_SECONDARY_USER_BASKETS_HELP", "L'utilisateur doit avoir au moins un groupe secondaire ayant des bannettes pour accéder à cette fonctionnalité.");
-if (!defined("_MANAGE_SECONDARY_USER_BASKETS_HELP_COMPL"))
-    define("_MANAGE_SECONDARY_USER_BASKETS_HELP_COMPL", "(Ajouter un groupe secondaire ayant des bannettes puis enregistrer l'utilisateur avant de revenir sur cet écran).");
-if (!defined("_MANAGE_BASKET_ORDER"))
-    define("_MANAGE_BASKET_ORDER", "Gérer l'ordre des bannettes");
-if (!defined("_MOVE_UP_TOP"))
-    define("_MOVE_UP_TOP", "Remonter tout en haut de la liste");
-if (!defined("_MOVE_UP_ONE_LEVEL"))
-    define("_MOVE_UP_ONE_LEVEL", "Monter d'une ligne");
-if (!defined("_MOVE_DOWN_ONE_LEVEL"))
-    define("_MOVE_DOWN_ONE_LEVEL", "Descendre d'une ligne");
-if (!defined("_MOVE_DOWN_BOTTOM"))
-    define("_MOVE_DOWN_BOTTOM", "Descendre tout en bas de la liste");
-
-if (!defined("_BASKET_ORDER_EDITED"))
-    define("_BASKET_ORDER_EDITED", "Ordre des bannettes modifié");
diff --git a/modules/basket/lang/nl.php b/modules/basket/lang/nl.php
index 5c6591ef655..e426afc0f8e 100755
--- a/modules/basket/lang/nl.php
+++ b/modules/basket/lang/nl.php
@@ -6,12 +6,6 @@
  */
 
 /*********************** SERVICES ***********************************/
-if (!defined('_ADMIN_BASKETS')) {
-    define('_ADMIN_BASKETS', 'Bakjes');
-}
-if (!defined('_USE_BASKETS')) {
-    define('_USE_BASKETS', 'De bakjes gebruiken');
-}
 if (!defined('_DIFFUSION_LIST')) {
     define('_DIFFUSION_LIST', 'Verdelingslijst');
 }
@@ -30,24 +24,6 @@ if (!defined('_THE_ID')) {
 if (!defined('_THE_DESC')) {
     define('_THE_DESC', 'De beschrijving');
 }
-if (!defined('_BELONGS_TO_NO_GROUP')) {
-    define('_BELONGS_TO_NO_GROUP', 'behoort tot geen enkele groep');
-}
-if (!defined('_SYSTEM_BASKET_MESSAGE')) {
-    define('_SYSTEM_BASKET_MESSAGE', 'Dit bakje is een systeembakje u kunt de tabel en de WHERE clause niet wijzigen Ze worden ter informatie weergegeven');
-}
-if (!defined('_BASKET_MISSING')) {
-    define('_BASKET_MISSING', 'Het Bakje bestaat niet');
-}
-if (!defined('_BASKET_UPDATED')) {
-    define('_BASKET_UPDATED', 'Bakje gewijzigd');
-}
-if (!defined('_BASKET_UPDATE')) {
-    define('_BASKET_UPDATE', 'Wijziging van het bakje');
-}
-if (!defined('_BASKET_ADDED')) {
-    define('_BASKET_ADDED', 'Nieuwe bakje toegevoegd');
-}
 if (!defined('_DELETED_BASKET')) {
     define('_DELETED_BASKET', 'Bakje verwijderd');
 }
@@ -483,9 +459,6 @@ if (!defined('_ARCHIVE_LIST')) {
 if (!defined('_COUNT_LIST')) {
     define('_COUNT_LIST', 'Lijst van de kopieën');
 }
-if (!defined('_FILTER_BY_ENTITY')) {
-    define('_FILTER_BY_ENTITY', 'Filteren op dienst');
-}
 if (!defined('_FILTER_BY')) {
     define('_FILTER_BY', 'Filteren op');
 }
@@ -540,39 +513,6 @@ if (!defined('_COMBINATED_ACTION')) {
 if (!defined('_END_OF_THE_WF')) {
     define('_END_OF_THE_WF', 'Einde van de workflow');
 }
-if (!defined('_BASKET_VISIBLE_ONLY_ON_SEARCH')) {
-    define('_BASKET_VISIBLE_ONLY_ON_SEARCH', 'Enkel opzoekingsbakje');
-}
-if (!defined('_MANAGE_SECONDARY_USER_BASKETS')) {
-    define('_MANAGE_SECONDARY_USER_BASKETS', 'De toegang tot de bakjes van de secundaire groepen beheren.');
-}
-if (!defined('_MANAGE_SECONDARY_USER_BASKETS_TEXT')) {
-    define('_MANAGE_SECONDARY_USER_BASKETS_TEXT', 'Om de toegang tot de bakjes van de secundaire groepen van de gebruiker te beheren.');
-}
-if (!defined('_MANAGE_SECONDARY_USER_BASKETS_HELP')) {
-    define('_MANAGE_SECONDARY_USER_BASKETS_HELP', 'De gebruiker moet minstens een secundaire groep met bakjes hebben om tot deze functie toegang te hebben.');
-}
-if (!defined('_MANAGE_SECONDARY_USER_BASKETS_HELP_COMPL')) {
-    define('_MANAGE_SECONDARY_USER_BASKETS_HELP_COMPL', '(Een secundaire groep met bakjes toevoegen daarna de gebruiker registreren vooraleer naar dit scherm terug te keren).');
-}
-if (!defined('_MANAGE_BASKET_ORDER')) {
-    define('_MANAGE_BASKET_ORDER', 'De volgorde van de bakjes beheren');
-}
-if (!defined('_MOVE_UP_TOP')) {
-    define('_MOVE_UP_TOP', 'Helemaal bovenaan de lijst gaan');
-}
-if (!defined('_MOVE_UP_ONE_LEVEL')) {
-    define('_MOVE_UP_ONE_LEVEL', 'Een lijn hoger');
-}
-if (!defined('_MOVE_DOWN_ONE_LEVEL')) {
-    define('_MOVE_DOWN_ONE_LEVEL', 'Een lijn lager');
-}
-if (!defined('_MOVE_DOWN_BOTTOM')) {
-    define('_MOVE_DOWN_BOTTOM', 'Helemaal onderaan de lijst gaan');
-}
-if (!defined('_BASKET_ORDER_EDITED')) {
-    define('_BASKET_ORDER_EDITED', 'Volgorde van de bakjes gewijzigd');
-}
 if (!defined('_ALL_BASKETS')) {
     define('_ALL_BASKETS', 'Mijn volledige perimeter');
 }
@@ -630,9 +570,6 @@ if (!defined('_REDIRECT_TO_DEP_OK')) {
 if (!defined('_AUTHORISED_ENTITIES')) {
     define('_AUTHORISED_ENTITIES', 'Lijst van de toegelaten eenheden');
 }
-if (!defined('_FILTER_BY_ENTITY')) {
-    define('_FILTER_BY_ENTITY', 'Filteren op eenheid');
-}
 if (!defined('_SPREAD_SEARCH_TO_BASKETS')) {
     define('_SPREAD_SEARCH_TO_BASKETS', 'Omvang van de opzoeking');
 }
diff --git a/src/frontend/app/about-us.component.html b/src/frontend/app/about-us.component.html
index 1717ab7c6cd..52fd392861e 100755
--- a/src/frontend/app/about-us.component.html
+++ b/src/frontend/app/about-us.component.html
@@ -41,9 +41,9 @@
                         <li><a target="blank" href="http://logging.apache.org/log4php/">log4php</a></li>
                         <li><a target="blank" href="http://chir.ag/tech/download/pdfb">Pdfb</a></li>
                         <li><a target="blank" href="http://www.foolabs.com/xpdf/">Pdftotext</a></li>
-                        <li><a target="blank" href="http://www.prototypejs.org/">Prototype</a></li>
-                        <li><a target="blank" href="http://script.aculo.us/">Script.aculo.us</a></li>
-                        <li><a target="blank" href="http://tafel.developpez.com">Tafel Tree</a></li>
+                        <!-- <li><a target="blank" href="http://www.prototypejs.org/">Prototype</a></li>
+                        <li><a target="blank" href="http://script.aculo.us/">Script.aculo.us</a></li> -->
+                        <!-- <li><a target="blank" href="http://tafel.developpez.com">Tafel Tree</a></li> -->
                         <li><a target="blank" href="http://www.tinybutstrong.com/">Tiny But Strong</a></li>
                         <li><a target="blank" href="http://www.tinymce.com/">TinyMCE</a></li>
                         <li><a target="blank" href="http://framework.zend.com/">Zend Lucene Search</a></li>
@@ -55,7 +55,7 @@
                     <hr/>
                     <ul>
                         <li>Florian AZIZIAN, Damien BUREL, Bruno CARLIN, Carole COTIN, Prosper DE LAURE, Driss DEMIRAY, Gaël DE VILLEBLANCHE, Emmanuel DILLARD, Mathieu DONZEL, Jean-Louis ERCOLANI, Claire FIGUERAS, Laurent GIOVANNONI, 
-                            Henri QUENEAU, Kader KANE, Yves-Christian KPAKPO, Alexandre MORIN, Sébastien NANABONDJA, Fodé NDIAYE, Cédric NDOUMBA, Alex ORLUC, Alexis RAGOT, Alexandre STEFANOVIC, Serge THIERRY-MIEG, 
+                            Guillaume HEURTIER, Henri QUENEAU, Kader KANE, Yves-Christian KPAKPO, Alexandre MORIN, Sébastien NANABONDJA, Fodé NDIAYE, Cédric NDOUMBA, Alex ORLUC, Alexis RAGOT, Alexandre STEFANOVIC, Serge THIERRY-MIEG, 
                             Cyril VAZQUEZ, Arnaud VEBER, Loic VINET</li>
                         <br>
                         <li><em>{{lang.thanksToCommunity}}</em></li>
-- 
GitLab