<commit_before>/*
 * Copyright 2012 Amadeus s.a.s.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Download Manager manages file download synchronization thanks to the FileLoader and Cache. When multiple files are
 * associated to the same physical URL, makes sure listeneres are associated to the same loader Manage logical path /
 * physical URL mapping (the same physical URL can be used for multiple logical paths in case of multipart (packaged)
 * files) thanks to the Url Map.
 * @class aria.core.DownloadMgr
 * @extends aria.core.JsObject
 * @singleton
 */
Aria.classDefinition({
    $classpath : 'aria.core.DownloadMgr',
    $singleton : true,
    $dependencies : ['aria.utils.Type', 'aria.utils.Json'],
    $constructor : function () {

        /**
         * Download Manager Cache
         * @protected
         * @type aria.core.Cache
         */
        this._cache = null;

        /**
         * Map between path/packages and a given file to load.

         * '*' as a key will allow to match any class of a package

         * '**' as a key will allow to match any class and subpackages in a package
         * @protected
         * @type Object
         */
        this._urlMap = {};

        /**
         * Map between a package and a rootUrl where to find this package '*' as a key will allow to match any
         * subPackage of a package
         * @protected
         * @type Object
         */
        this._rootMap = {};

        /**
         * Json utils shortcut
         * @protected
         * @type aria.utils.Json
         */
        this._jsonUtils = aria.utils.Json;

        this._typeUtils = aria.utils.Type;

        /**
         * Map of URLs for which it is desired to bypass the browser cache.
         * @type Object
         */
        this._timestampURL = {};
    },
    $destructor : function () {
        this._cache = null;
        this._urlMap = null;
        this._rootMap = null;
        this._jsonUtils = null;
        this._timestampURL = null;
    },
    $prototype : {

        /**
         * Update the url map with the given structure
         * @param {Object} map
         */
        updateUrlMap : function (map) {
            this._jsonUtils.inject(map, this._urlMap, true);
        },

        /**
         * Update the url map with the given structure
         * @param {Object} map
         */
        updateRootMap : function (map) {
            this._jsonUtils.inject(map, this._rootMap, true);
        },

        /**
         * Mark the url as needing (or not) a timestamp when loading it next time (to bypass browser and server cache)
         * @param {String} url URL for which the timestamp setting will change
         * @param {Boolean} activate [optional, default true] if false, the timestamp will be disabled for the url,
         * otherwise it will be enabled
         */
        enableURLTimestamp : function (url, activate) {
            if (activate !== false) {
                this._timestampURL[url] = true;
            } else {
                delete this._timestampURL[url];
            }
        },

        /**
         * Add a timestamp to the given URL if it should bypass browser cache.
         * @param {String} url URL for which a timestamp should be added if necessary
         * @param {Boolean} force if true, the timestamp will always be added
         * @return {String} URL with the added timestamp if this is required
         */
        getURLWithTimestamp : function (url, force) {
            if (force || this._timestampURL[url]) {
                var timestamp = (new Date()).getTime();
                if (url.indexOf("?") != -1) {
                    return url + "&timestamp=" + timestamp;
                } else {
                    return url + "?timestamp=" + timestamp;
                }
            } else {
                return url;
            }
        },

        /**
         * Get a file from its logical path
         * @param {String} logicalPath file logical path e.g. aria/core/Sequencer.js
         * @param {aria.core.JsObject.Callback} cb callback description - warning callback may be called synchronously
         * if the file is already available
         *
         *

         *
         *     {
         *         fn: // {Function} callback function
         *         scope: // {Object} object context associated to the callback function (i.e. 'this' object)
         *         args: // {Object} optional argument object passed to the callback function when called
         *     }
         *

         *
         * When called the callback will be called with the following arguments: fn(evt,args) where evt corresponds to
         * aria.core.FileLoader.$events.fileReady
         * @param {Object} args Additional arguments for the file loader
         *
         *

         *     {
         *         fullLogicalPath: // {String} Full logical path of the file to be loaded.
         *                       // If not specified the root url will be resolved to the framework root
         *  }
         *

         */
        loadFile : function (logicalPath, cb, args) {
            // get the file item in the cache
            if (!this._cache) {
                this._cache = aria.core.Cache;
            }
            this.$assert(34, this._cache);
            this.$assert(35, cb.scope);
            this.$assert(36, cb.fn);

            var cache = this._cache, itm = cache.getItem("files", logicalPath, true), status = itm.status;

            // if file already loaded, directly call callback
            if (status == cache.STATUS_AVAILABLE || status == cache.STATUS_ERROR) {
                var evt = {
                    name : "fileReady",
                    src : this,
                    logicalPaths : [logicalPath],
                    url : null
                };
                return this.$callback(cb, evt);
            }

            // file is not loaded: create a file loader if not already done
            var loader = itm.loader;
            if (!loader) {
                this.$assert(63, aria.core.FileLoader);

                var url;
                if (args && args.fullLogicalPath) {
                    url = args.fullLogicalPath;
                } else {
                    url = this.resolveURL(logicalPath);
                }

                // register the loader in a Cache 'urls' category
                // we do so as multiple logical path can be associated to the same url
                // (packaged files served as multipart responses)
                var urlItm = cache.getItem("urls", url, true);

                if (urlItm.status == this._cache.STATUS_AVAILABLE) {
                    // this url has already been fetch, but file was not retrieved in it
                    var evt = {
                        name : "fileReady",
                        src : this,
                        logicalPaths : [logicalPath],
                        url : url,
                        downloadFailed : true
                    };
                    return this.$callback(cb, evt);
                }

                if (urlItm.loader) {
                    // this loader should be processing as 'files' entry in cache is empty
                    this.$assert(72, urlItm.status == cache.STATUS_LOADING);
                } else {
                    urlItm.loader = new aria.core.FileLoader(url);
                    urlItm.status = cache.STATUS_LOADING;

                    // register on complete to delete the object when not necessary anymore
                    urlItm.loader.$on({
                        'complete' : this._onFileLoaderComplete,
                        scope : this
                    });
                }
                loader = urlItm.loader;
                // double-reference loader in the 'files' category
                itm.loader = loader;
                url = urlItm = null;
            }

            // add caller as listener to the FileLoader
            loader.addLogicalPath(logicalPath);
            var cbArgs = (cb.args) ? cb.args : null;
            loader.$on({
                'fileReady' : {
                    fn : cb.fn,
                    args : cbArgs,
                    scope : cb.scope
                }
            });
            loader.loadFile();
            cbArgs = loader = null;
        },

        /**
         * Find node associated to a path in a map. May be a string, an object, a function or a instance of callback, or
         * null.
         * @protected
         * @param {Object} map
         * @param {Array} pathparts
         * @param {Boolean} doubleStar support double star ** notation
         * @return {Object} node and index in path
         */
        _extractTarget : function (map, pathparts, doubleStar) {
            for (var i = 0, l = pathparts.length; i < l; i++) {
                var part = pathparts[i];
                if (!this._typeUtils.isObject(map) || this._typeUtils.isInstanceOf(map, 'aria.core.JsObject')) {
                    break;
                }
                if (!map[part]) {
                    if (doubleStar) {
                        if (map['*'] && i == l - 1) {
                            map = map['*'];
                        } else {
                            map = map['**'];
                        }
                    } else {
                        map = map['*'];
                    }
                    break;
                }

                map = map[part];
            }
            return {
                node : map,
                index : i
            };
        },

        /**
         * Method transforming a logical path into a physical url (uses the _urlMap generated by the packager to
         * determine packaged files and MD5 extensions)
         * @param {String} logicalPath logical path of the file - e.g. aria/jsunit/TestCase.js
         * @param {Boolean} rootOnly Only apply the root map, if true it won't consider packaging and md5. Default false
         * @return {String} the absolute URL - e.g. http://host:port/yy/aria/jsunit/Package-123456789.txt
         */
        resolveURL : function (logicalPath, rootOnly) {
            var res = logicalPath, // default response: logical path
            rootPath = Aria.rootFolderPath, // default root path
            // Some files have multiple extensions, .tpl.txt, .tpl.css, strip only the last one
            lastIndex = logicalPath.lastIndexOf("."), extensionFreePath = logicalPath.substring(0, lastIndex), //
            urlMap = this._urlMap, rootMap = this._rootMap, pathparts = extensionFreePath.split('/'), extract;

            // extract target from urlMap
            if (rootOnly !== true) {
                extract = this._extractTarget(urlMap, pathparts, true);
                urlMap = extract.node;

                if (this._typeUtils.isString(urlMap)) {
                    res = urlMap;
                } else if (this._typeUtils.isInstanceOf(urlMap, 'aria.utils.Callback')) {
                    res = urlMap.call(logicalPath);
                } else if (this._typeUtils.isFunction(urlMap)) {
                    res = urlMap.call(null, logicalPath);
                }
            }

            // extract target from rootMap
            rootMap = this._extractTarget(rootMap, pathparts).node;

            if (this._typeUtils.isString(rootMap)) {
                rootPath = rootMap;
            } else if (this._typeUtils.isInstanceOf(rootMap, 'aria.utils.Callback')) {
                rootPath = rootMap.call(logicalPath);
            } else if (this._typeUtils.isFunction(rootMap)) {
                rootPath = rootMap.call(null, logicalPath);
            }

            return rootPath + res;
        },

        /**
         * Internal method called when a file loader can be disposed
         * @param {aria.core.FileLoader.$events.complete} evt
         * @private
         */
        _onFileLoaderComplete : function (evt) {
            var loader = evt.src, cache = this._cache, itm, lps = loader.getLogicalPaths();
            if (lps) {
                // remove loader ref from all 'files' entries
                var sz = lps.length;
                for (var i = 0; sz > i; i++) {
                    itm = cache.getItem("files", lps[i], false);
                    if (itm) {
                        this.$assert(120, itm.loader == loader);
                        itm.loader = null;
                    }
                }
            }
            // remove entry from "urls" category
            itm = cache.getItem("urls", loader.getURL(), false);
            if (itm) {
                this.$assert(128, itm.loader == loader);
                itm.loader = null;
                itm.status = this._cache.STATUS_AVAILABLE;
            }
            // dispose
            loader.$dispose();
            loader = cache = itm = lps = null;
        },

        /**
         * Function called by a file loader when a file content has been retrieved
         * @param {String} logicalPath the logical path of the file
         * @param {String} content the file content
         */
        loadFileContent : function (logicalPath, content, hasErrors) {
            if (!this._cache) {
                this._cache = aria.core.Cache;
            }
            var itm = this._cache.getItem("files", logicalPath, true);
            if (hasErrors) {
                itm.status = this._cache.STATUS_ERROR;
            } else {
                itm.value = content;
                itm.status = this._cache.STATUS_AVAILABLE;
            }
            itm = null;
        },

        /**
         * Get the file content from its logical path Return null if file is in error
         * @param {String} logicalPath
         * @return {String}
         */
        getFileContent : function (logicalPath) {
            var itm = this._cache.getItem("files", logicalPath, false);
            if (itm && itm.status == this._cache.STATUS_AVAILABLE) {
                return itm.value;
            }
            return null;
        },

        /**
         * Gets tpl file content based on its classpath or retrieves it from the cache if it has been already loaded
         * @param {String} classpath Classpath of the template
         * @param {aria.core.JsObject.Callback} cb Callback to be called after tpl content is downloaded
         */
        loadTplFileContent : function (classpath, cb) {
            var logicalPath = aria.core.ClassMgr.getBaseLogicalPath(classpath) + ".tpl";
            this.loadFile(logicalPath, {
                fn : this._onTplFileContentReceive,
                scope : this,
                args : {
                    origCb : cb
                }
            }, null);
        },

        /**
         * Internal method called when tpl content is loaded
         * @param {aria.core.FileLoader.$events.complete} evt
         * @param {Object} args Additonal arguments for the callback {origCb: {JSON callback} orignal callback to be
         * called after file load is complete}
         * @protected
         */
        _onTplFileContentReceive : function (evt, args) {
            var res = {
                content : null
            };
            if (evt.downloadFailed) {
                res.downloadFailed = evt.downloadFailed;
            }
            if (evt.logicalPaths.length > 0) {
                res.content = this.getFileContent(evt.logicalPaths[0]);
            }
            this.$callback(args.origCb, res);
        },

        /**
         * Remove the file content associated with logical path
         * @param {String} classpath
         * @param {Boolean} timestampNextTime if true, the next time the logical path is loaded, browser and server
         * cache will be bypassed by adding a timestamp to the url
         */
        clearFile : function (logicalPath, timestampNextTime) {
            var content = this._cache.content;
            delete content.files[logicalPath];
            var url = this.resolveURL(logicalPath);
            delete content.urls[url];
            if (timestampNextTime) {
                this.enableURLTimestamp(url, true); // browser cache will be bypassed next time the file is loaded
            }
        }
    }
});<commit_msg>Add the getPackages feature<commit_after>/*
 * Copyright 2012 Amadeus s.a.s.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Download Manager manages file download synchronization thanks to the FileLoader and Cache. When multiple files are
 * associated to the same physical URL, makes sure listeneres are associated to the same loader Manage logical path /
 * physical URL mapping (the same physical URL can be used for multiple logical paths in case of multipart (packaged)
 * files) thanks to the Url Map.
 * @class aria.core.DownloadMgr
 * @extends aria.core.JsObject
 * @singleton
 */
Aria.classDefinition({
    $classpath : 'aria.core.DownloadMgr',
    $singleton : true,
    $dependencies : ['aria.utils.Type', 'aria.utils.Json'],
    $constructor : function () {

        /**
         * Download Manager Cache
         * @protected
         * @type aria.core.Cache
         */
        this._cache = null;

        /**
         * Map between path/packages and a given file to load.

         * '*' as a key will allow to match any class of a package

         * '**' as a key will allow to match any class and subpackages in a package
         * @protected
         * @type Object
         */
        this._urlMap = {};

        /**
         * Map between a package and a rootUrl where to find this package '*' as a key will allow to match any
         * subPackage of a package
         * @protected
         * @type Object
         */
        this._rootMap = {};

        /**
         * Json utils shortcut
         * @protected
         * @type aria.utils.Json
         */
        this._jsonUtils = aria.utils.Json;

        this._typeUtils = aria.utils.Type;

        /**
         * Map of URLs for which it is desired to bypass the browser cache.
         * @type Object
         */
        this._timestampURL = {};
    },
    $destructor : function () {
        this._cache = null;
        this._urlMap = null;
        this._rootMap = null;
        this._jsonUtils = null;
        this._timestampURL = null;
    },
    $prototype : {

        /**
         * Update the url map with the given structure
         * @param {Object} map
         */
        updateUrlMap : function (map) {
            this._jsonUtils.inject(map, this._urlMap, true);
        },

        /**
         * Update the url map with the given structure
         * @param {Object} map
         */
        updateRootMap : function (map) {
            this._jsonUtils.inject(map, this._rootMap, true);
        },

        /**
         * Mark the url as needing (or not) a timestamp when loading it next time (to bypass browser and server cache)
         * @param {String} url URL for which the timestamp setting will change
         * @param {Boolean} activate [optional, default true] if false, the timestamp will be disabled for the url,
         * otherwise it will be enabled
         */
        enableURLTimestamp : function (url, activate) {
            if (activate !== false) {
                this._timestampURL[url] = true;
            } else {
                delete this._timestampURL[url];
            }
        },

        /**
         * Add a timestamp to the given URL if it should bypass browser cache.
         * @param {String} url URL for which a timestamp should be added if necessary
         * @param {Boolean} force if true, the timestamp will always be added
         * @return {String} URL with the added timestamp if this is required
         */
        getURLWithTimestamp : function (url, force) {
            if (force || this._timestampURL[url]) {
                var timestamp = (new Date()).getTime();
                if (url.indexOf("?") != -1) {
                    return url + "&timestamp=" + timestamp;
                } else {
                    return url + "?timestamp=" + timestamp;
                }
            } else {
                return url;
            }
        },

        /**
         * Return an url list from an array containing the starting url, this function is usefull to retrieve package
         * name with md5 from the name without it
         * @param {String|Array} urls starting url string
         * @return {Array} array of full url
         */
        getPackages : function (urls) {

            if (this._typeUtils.isString(urls)) {
                urls = [urls];
            }

            var _getPackages = function (urls, urlMap, packages) {
                if (urls.length === 0) {
                    // everything has been found, leave back the recursive loop
                    return;
                }
                for (var key in urlMap) {
                    var value = urlMap[key];
                    if (typeof(value) == 'string') {
                        // Check if something match
                        for (var i = 0, ii = urls.length; i < ii; i++) {
                            var file = urls[i];
                            if (value.substr(0, file.length) == file) {
                                packages[value] = true;
                                // remove found item from the url list, for performance reason
                                urls.slice(i, i);
                                break;
                            }
                        }
                    } else {
                        _getPackages(urls, urlMap[key], packages);
                    }
                }
            };

            // Clone urls array
            var urlClone = [];
            for (var i = 0, ii = urls.length; i < ii; i++) {
                urlClone.push(urls[i]);
            }

            var packages = {};
            _getPackages(urls, this._urlMap, packages);

            // return the keys only
            var keys = [];
            for (var key in packages) {
                keys.push(key);
            }
            return keys;
        },

        /**
         * Get a file from its logical path
         * @param {String} logicalPath file logical path e.g. aria/core/Sequencer.js
         * @param {aria.core.JsObject.Callback} cb callback description - warning callback may be called synchronously
         * if the file is already available
         *
         *

         *
         *     {
         *         fn: // {Function} callback function
         *         scope: // {Object} object context associated to the callback function (i.e. 'this' object)
         *         args: // {Object} optional argument object passed to the callback function when called
         *     }
         *

         *
         * When called the callback will be called with the following arguments: fn(evt,args) where evt corresponds to
         * aria.core.FileLoader.$events.fileReady
         * @param {Object} args Additional arguments for the file loader
         *
         *

         *     {
         *         fullLogicalPath: // {String} Full logical path of the file to be loaded.
         *                       // If not specified the root url will be resolved to the framework root
         *  }
         *

         */
        loadFile : function (logicalPath, cb, args) {
            // get the file item in the cache
            if (!this._cache) {
                this._cache = aria.core.Cache;
            }
            this.$assert(34, this._cache);
            this.$assert(35, cb.scope);
            this.$assert(36, cb.fn);

            var cache = this._cache, itm = cache.getItem("files", logicalPath, true), status = itm.status;

            // if file already loaded, directly call callback
            if (status == cache.STATUS_AVAILABLE || status == cache.STATUS_ERROR) {
                var evt = {
                    name : "fileReady",
                    src : this,
                    logicalPaths : [logicalPath],
                    url : null
                };
                return this.$callback(cb, evt);
            }

            // file is not loaded: create a file loader if not already done
            var loader = itm.loader;
            if (!loader) {
                this.$assert(63, aria.core.FileLoader);

                var url;
                if (args && args.fullLogicalPath) {
                    url = args.fullLogicalPath;
                } else {
                    url = this.resolveURL(logicalPath);
                }

                // register the loader in a Cache 'urls' category
                // we do so as multiple logical path can be associated to the same url
                // (packaged files served as multipart responses)
                var urlItm = cache.getItem("urls", url, true);

                if (urlItm.status == this._cache.STATUS_AVAILABLE) {
                    // this url has already been fetch, but file was not retrieved in it
                    var evt = {
                        name : "fileReady",
                        src : this,
                        logicalPaths : [logicalPath],
                        url : url,
                        downloadFailed : true
                    };
                    return this.$callback(cb, evt);
                }

                if (urlItm.loader) {
                    // this loader should be processing as 'files' entry in cache is empty
                    this.$assert(72, urlItm.status == cache.STATUS_LOADING);
                } else {
                    urlItm.loader = new aria.core.FileLoader(url);
                    urlItm.status = cache.STATUS_LOADING;

                    // register on complete to delete the object when not necessary anymore
                    urlItm.loader.$on({
                        'complete' : this._onFileLoaderComplete,
                        scope : this
                    });
                }
                loader = urlItm.loader;
                // double-reference loader in the 'files' category
                itm.loader = loader;
                url = urlItm = null;
            }

            // add caller as listener to the FileLoader
            loader.addLogicalPath(logicalPath);
            var cbArgs = (cb.args) ? cb.args : null;
            loader.$on({
                'fileReady' : {
                    fn : cb.fn,
                    args : cbArgs,
                    scope : cb.scope
                }
            });
            loader.loadFile();
            cbArgs = loader = null;
        },

        /**
         * Find node associated to a path in a map. May be a string, an object, a function or a instance of callback, or
         * null.
         * @protected
         * @param {Object} map
         * @param {Array} pathparts
         * @param {Boolean} doubleStar support double star ** notation
         * @return {Object} node and index in path
         */
        _extractTarget : function (map, pathparts, doubleStar) {
            for (var i = 0, l = pathparts.length; i < l; i++) {
                var part = pathparts[i];
                if (!this._typeUtils.isObject(map) || this._typeUtils.isInstanceOf(map, 'aria.core.JsObject')) {
                    break;
                }
                if (!map[part]) {
                    if (doubleStar) {
                        if (map['*'] && i == l - 1) {
                            map = map['*'];
                        } else {
                            map = map['**'];
                        }
                    } else {
                        map = map['*'];
                    }
                    break;
                }

                map = map[part];
            }
            return {
                node : map,
                index : i
            };
        },

        /**
         * Method transforming a logical path into a physical url (uses the _urlMap generated by the packager to
         * determine packaged files and MD5 extensions)
         * @param {String} logicalPath logical path of the file - e.g. aria/jsunit/TestCase.js
         * @param {Boolean} rootOnly Only apply the root map, if true it won't consider packaging and md5. Default false
         * @return {String} the absolute URL - e.g. http://host:port/yy/aria/jsunit/Package-123456789.txt
         */
        resolveURL : function (logicalPath, rootOnly) {
            var res = logicalPath, // default response: logical path
            rootPath = Aria.rootFolderPath, // default root path
            // Some files have multiple extensions, .tpl.txt, .tpl.css, strip only the last one
            lastIndex = logicalPath.lastIndexOf("."), extensionFreePath = logicalPath.substring(0, lastIndex), //
            urlMap = this._urlMap, rootMap = this._rootMap, pathparts = extensionFreePath.split('/'), extract;

            // extract target from urlMap
            if (rootOnly !== true) {
                extract = this._extractTarget(urlMap, pathparts, true);
                urlMap = extract.node;

                if (this._typeUtils.isString(urlMap)) {
                    res = urlMap;
                } else if (this._typeUtils.isInstanceOf(urlMap, 'aria.utils.Callback')) {
                    res = urlMap.call(logicalPath);
                } else if (this._typeUtils.isFunction(urlMap)) {
                    res = urlMap.call(null, logicalPath);
                }
            }

            // extract target from rootMap
            rootMap = this._extractTarget(rootMap, pathparts).node;

            if (this._typeUtils.isString(rootMap)) {
                rootPath = rootMap;
            } else if (this._typeUtils.isInstanceOf(rootMap, 'aria.utils.Callback')) {
                rootPath = rootMap.call(logicalPath);
            } else if (this._typeUtils.isFunction(rootMap)) {
                rootPath = rootMap.call(null, logicalPath);
            }

            return rootPath + res;
        },

        /**
         * Internal method called when a file loader can be disposed
         * @param {aria.core.FileLoader.$events.complete} evt
         * @private
         */
        _onFileLoaderComplete : function (evt) {
            var loader = evt.src, cache = this._cache, itm, lps = loader.getLogicalPaths();
            if (lps) {
                // remove loader ref from all 'files' entries
                var sz = lps.length;
                for (var i = 0; sz > i; i++) {
                    itm = cache.getItem("files", lps[i], false);
                    if (itm) {
                        this.$assert(120, itm.loader == loader);
                        itm.loader = null;
                    }
                }
            }
            // remove entry from "urls" category
            itm = cache.getItem("urls", loader.getURL(), false);
            if (itm) {
                this.$assert(128, itm.loader == loader);
                itm.loader = null;
                itm.status = this._cache.STATUS_AVAILABLE;
            }
            // dispose
            loader.$dispose();
            loader = cache = itm = lps = null;
        },

        /**
         * Function called by a file loader when a file content has been retrieved
         * @param {String} logicalPath the logical path of the file
         * @param {String} content the file content
         */
        loadFileContent : function (logicalPath, content, hasErrors) {
            if (!this._cache) {
                this._cache = aria.core.Cache;
            }
            var itm = this._cache.getItem("files", logicalPath, true);
            if (hasErrors) {
                itm.status = this._cache.STATUS_ERROR;
            } else {
                itm.value = content;
                itm.status = this._cache.STATUS_AVAILABLE;
            }
            itm = null;
        },

        /**
         * Get the file content from its logical path Return null if file is in error
         * @param {String} logicalPath
         * @return {String}
         */
        getFileContent : function (logicalPath) {
            var itm = this._cache.getItem("files", logicalPath, false);
            if (itm && itm.status == this._cache.STATUS_AVAILABLE) {
                return itm.value;
            }
            return null;
        },

        /**
         * Gets tpl file content based on its classpath or retrieves it from the cache if it has been already loaded
         * @param {String} classpath Classpath of the template
         * @param {aria.core.JsObject.Callback} cb Callback to be called after tpl content is downloaded
         */
        loadTplFileContent : function (classpath, cb) {
            var logicalPath = aria.core.ClassMgr.getBaseLogicalPath(classpath) + ".tpl";
            this.loadFile(logicalPath, {
                fn : this._onTplFileContentReceive,
                scope : this,
                args : {
                    origCb : cb
                }
            }, null);
        },

        /**
         * Internal method called when tpl content is loaded
         * @param {aria.core.FileLoader.$events.complete} evt
         * @param {Object} args Additonal arguments for the callback {origCb: {JSON callback} orignal callback to be
         * called after file load is complete}
         * @protected
         */
        _onTplFileContentReceive : function (evt, args) {
            var res = {
                content : null
            };
            if (evt.downloadFailed) {
                res.downloadFailed = evt.downloadFailed;
            }
            if (evt.logicalPaths.length > 0) {
                res.content = this.getFileContent(evt.logicalPaths[0]);
            }
            this.$callback(args.origCb, res);
        },

        /**
         * Remove the file content associated with logical path
         * @param {String} classpath
         * @param {Boolean} timestampNextTime if true, the next time the logical path is loaded, browser and server
         * cache will be bypassed by adding a timestamp to the url
         */
        clearFile : function (logicalPath, timestampNextTime) {
            var content = this._cache.content;
            delete content.files[logicalPath];
            var url = this.resolveURL(logicalPath);
            delete content.urls[url];
            if (timestampNextTime) {
                this.enableURLTimestamp(url, true); // browser cache will be bypassed next time the file is loaded
            }
        }
    }
});<|endoftext|>


<commit_before>(function ($, window, document, undefined) {
	var pluginName = "osSelector",
		defaults = {
			panelInput: '.reinstall-panel',
			osimageInput: '.reinstall-osimage'
		};

	function Plugin(element, options) {
		this.element = $(element);
		this.items = {};
		this.oslist = undefined;
		this.softlist = undefined;
		this.osparams = options.osparams;
		this.settings = $.extend({}, defaults, options);
		this._defaults = defaults;
		this._name = pluginName;
		this.init();
	}

	Plugin.prototype = {
		init: function () {
			this.oslist = this.element.find('.os-list');
			this.softlist = this.element.find('.soft-list');
			this.bindListeners();
			this.afterInit();
			this.enableInfoPopover();
		},
		bindListeners: function () {
			var _this = this;

			this.softlist.find('input').on('change', function () {
				var soft = $(this).val();
				var panel = $(this).data('panel');
				var os = _this.oslist.find('input.radio:checked').first().val();
				if (_this.osparams[os]['panel'][panel] !== undefined) {
					var osimage = _this.osparams[os]['panel'][panel]['softpack'][soft]['osimage'];
				} else {
					osimage = _this.osparams[os]['panel'][panel]['softpack'][soft]['osimage'];
				}
				$(_this.settings.osimageInput).val(osimage);
				if (panel != 'no') {
					$(_this.settings.panelInput).removeAttr('disabled');
					$(_this.settings.panelInput).val(panel);
				} else {
					$(_this.settings.panelInput).attr('disabled', 'disabled');
				}
			});

			$(this.oslist).on('change', function () {
				_this.update();
			});
		},
		update: function () {
			var _this = this;

			if (this.oslist.find('.radio:enabled:checked').length < 1) this.oslist.find('.radio:enabled').first().prop('checked', true);
			this.oslist.find('.radio:enabled').each(function () {
				if ($(this).prop('checked')) {
					_this.softlist.find('input').attr('disabled', 'disabled');
					_this.softlist.find('input').closest('label').addClass('disabled');
					_this.softlist.find('.softinfo-bttn').hide();

					var osName = $(this).val();
					for (var key in _this.osparams) {
						if (osName == key) {
							for (var panel in _this.osparams[key]['panel']) {
								for (var soft in _this.osparams[key]['panel'][panel]['softpack']) {
									var selectable = _this.osparams[key]['panel'][panel]['softpack'][soft];
									var $inputs = _this.softlist.filter('[data-panel="' + panel + '"]');
									if (selectable) {
										var $selectable_inputs = $inputs.find('input[value="' + soft + '"]');
										var soft_desc = selectable['html_desc'];

										$selectable_inputs.removeAttr('disabled');
										$selectable_inputs.closest('label').removeClass('disabled');
										if (soft_desc) {
											$selectable_inputs.closest('label').find('.soft-desc').html(soft_desc);
											$selectable_inputs.closest('label').find('.softinfo-bttn').show();
										}
									}
								}
							}
						}
					}
					if (_this.softlist.find('input:enabled:checked').length == 0) {
						_this.softlist.find('input:enabled').first().attr('checked', 'checked');
					}
					_this.softlist.find('input:checked').trigger('change').trigger('click');
				}
			});
		},
		afterInit: function () {
			this.oslist.find('input:enabled').first().attr('checked', 'checked').trigger('change');
		},
		enableInfoPopover: function () {
			var counter;

			$('.softinfo-bttn').popover({
				trigger: 'manual',
				html: true,
				title: function () {
					return $(this).parent().find('.panel_soft').val();
				},
				content: function () {
					return $(this).parent().find('.soft-desc').html();
				},
				container: 'body',
				placement: 'auto'
			}).on("mouseenter", function () {
				var _this = this;
				// clear the counter
				clearTimeout(counter);
				// Close all other Popovers
				$('.softinfo-bttn').not(_this).popover('hide');

				// start new timeout to show popover
				counter = setTimeout(function () {
					if ($(_this).is(':hover')) {
						$(_this).popover("show");
					}
					$(".popover").on("mouseleave", function () {
						$('.thumbcontainer').popover('hide');
					});
				}, 400);

			}).on("mouseleave", function () {
				var _this = this;

				setTimeout(function () {
					if (!$(".popover:hover").length) {
						if (!$(_this).is(':hover')) {
							$(_this).popover('hide');
						}
					}
				}, 200);
			}).on("click", function(event) {
				event.preventDefault();
			});
		}

	};

	$.fn[pluginName] = function (options) {
		this.each(function () {
			if (!$.data(this, "plugin_" + pluginName)) {
				$.data(this, "plugin_" + pluginName, new Plugin(this, options));
			}
		});
		return this;
	};
})(jQuery, window, document);
<commit_msg>Fixed OsSelection.js to prevent JS exception when accessing unexisting soft pack in array<commit_after>(function ($, window, document, undefined) {
	var pluginName = "osSelector",
		defaults = {
			panelInput: '.reinstall-panel',
			osimageInput: '.reinstall-osimage'
		};

	function Plugin(element, options) {
		this.element = $(element);
		this.items = {};
		this.oslist = undefined;
		this.softlist = undefined;
		this.osparams = options.osparams;
		this.settings = $.extend({}, defaults, options);
		this._defaults = defaults;
		this._name = pluginName;
		this.init();
	}

	Plugin.prototype = {
		init: function () {
			this.oslist = this.element.find('.os-list');
			this.softlist = this.element.find('.soft-list');
			this.bindListeners();
			this.afterInit();
			this.enableInfoPopover();
		},
		bindListeners: function () {
			var _this = this;

			this.softlist.find('input').on('change', function () {
				var soft = $(this).val();
				var panel = $(this).data('panel');
				var os = _this.oslist.find('input.radio:checked').first().val();
				if (_this.osparams[os]['panel'][panel] !== undefined) {
					var osimage = _this.osparams[os]['panel'][panel]['softpack'][soft]['osimage'];
				} else {
					osimage = null;
				}
				$(_this.settings.osimageInput).val(osimage);
				if (panel != 'no') {
					$(_this.settings.panelInput).removeAttr('disabled');
					$(_this.settings.panelInput).val(panel);
				} else {
					$(_this.settings.panelInput).attr('disabled', 'disabled');
				}
			});

			$(this.oslist).on('change', function () {
				_this.update();
			});
		},
		update: function () {
			var _this = this;

			if (this.oslist.find('.radio:enabled:checked').length < 1) {
				this.oslist.find('.radio:enabled').first().prop('checked', true);
			}

			this.oslist.find('.radio:enabled').each(function () {
				if ($(this).prop('checked')) {
					_this.softlist.find('input').attr('disabled', 'disabled');
					_this.softlist.find('input').closest('label').addClass('disabled');
					_this.softlist.find('.softinfo-bttn').hide();

					var osName = $(this).val();
					for (var key in _this.osparams) {
						if (osName == key) {
							for (var panel in _this.osparams[key]['panel']) {
								for (var soft in _this.osparams[key]['panel'][panel]['softpack']) {
									var selectable = _this.osparams[key]['panel'][panel]['softpack'][soft];
									var $inputs = _this.softlist.filter('[data-panel="' + panel + '"]');
									if (selectable) {
										var $selectable_inputs = $inputs.find('input[value="' + soft + '"]');
										var soft_desc = selectable['html_desc'];

										$selectable_inputs.removeAttr('disabled');
										$selectable_inputs.closest('label').removeClass('disabled');
										if (soft_desc) {
											$selectable_inputs.closest('label').find('.soft-desc').html(soft_desc);
											$selectable_inputs.closest('label').find('.softinfo-bttn').show();
										}
									}
								}
							}
						}
					}
					if (_this.softlist.find('input:enabled:checked').length == 0) {
						_this.softlist.find('input:enabled').first().prop('checked', true);
					}
					_this.softlist.find('input:checked').trigger('change').trigger('click');
				}
			});
		},
		afterInit: function () {
			this.oslist.find('input:enabled').first().prop('checked', true).trigger('change');
		},
		enableInfoPopover: function () {
			var counter;

			$('.softinfo-bttn').popover({
				trigger: 'manual',
				html: true,
				title: function () {
					return $(this).parent().find('.panel_soft').val();
				},
				content: function () {
					return $(this).parent().find('.soft-desc').html();
				},
				container: 'body',
				placement: 'auto'
			}).on("mouseenter", function () {
				var _this = this;
				// clear the counter
				clearTimeout(counter);
				// Close all other Popovers
				$('.softinfo-bttn').not(_this).popover('hide');

				// start new timeout to show popover
				counter = setTimeout(function () {
					if ($(_this).is(':hover')) {
						$(_this).popover("show");
					}
					$(".popover").on("mouseleave", function () {
						$('.thumbcontainer').popover('hide');
					});
				}, 400);

			}).on("mouseleave", function () {
				var _this = this;

				setTimeout(function () {
					if (!$(".popover:hover").length) {
						if (!$(_this).is(':hover')) {
							$(_this).popover('hide');
						}
					}
				}, 200);
			}).on("click", function(event) {
				event.preventDefault();
			});
		}

	};

	$.fn[pluginName] = function (options) {
		this.each(function () {
			if (!$.data(this, "plugin_" + pluginName)) {
				$.data(this, "plugin_" + pluginName, new Plugin(this, options));
			}
		});
		return this;
	};
})(jQuery, window, document);
<|endoftext|>


<commit_before>(function(window, undefined){

    window.MockEventGlobals = {
        namespace: '',
        setTimeout: 0,
        setInterval: 0,
        verbose: true,
        on: true
    }

    var mockHandlers = [];
    var missed = [];

    var baseHandler = {

        id: null,
        url: '',
        namespace: MockEventGlobals.namespace,
        setInterval: MockEventGlobals.setInterval,
        responses: [],
        response: null,
        proxy: null,
        on: MockEventGlobals.on,
        allResponses: [],

        initialize: function(){

            if(this.url.indexOf(this.namespace) < 0){
                this.url = this.namespace + this.url;
            }

            this.allResponses = this.allResponses.concat(this.responses);
        },
        headers: function(){
            return {
                'Access-Control-Allow-Credentials': true,
                'Access-Control-Allow-Headers': 'Content-type,Authorization',
                'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
                'Access-Control-Allow-Origin': window.location.protocol + '//' + window.location.host,
                'Access-Control-Expose-Headers': '*',
                'Cache-Control': 'no-cache',
                'Connection': 'keep-alive',
                'Content-type': 'text/event-stream',
                'Date': (new Date()).toString()
            }
        },
        urlMatches: function(url){
            if (_.isFunction(this.url.test)) {
                // The user provided a regex for the url, test it
                if (!this.url.test(url)) {
                    return false;
                }
            } else {
                var star = this.url.indexOf('*');
                if (this.url !== url && star === -1 ||
                        !new RegExp(this.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, '\\$&').replace(/\*/g, '.+')).test(url)) {
                    return false;
                }
            }
            return true;
        },
        clear: function(){
            mockHandlers[this.id] = null;
            delete this;
        },
        dispatchEvent: function(event){
            return window.dispatchEvent(event);
        },
        send: function(response){
            if(!(response.name && response.data)){
                this.dispatchError('`name` and `data` are required on mock handler response object');
            } else {
                var evt = new Event(response.name)
                evt.data = JSON.stringify(response.data);
                this.dispatchEvent(evt);
            }
        },
        errorEventName: function(){
            return 'mock-event-'+this.id+'-error';
        },
        dispatchError: function(errorMessage){
                var evt = new Event(this.errorEventName());
                evt.error = new Error(errorMessage);
                this.dispatchEvent(evt);
        },
        stream: function(responses){
            /* Handling the stream output via this.setInterval attribute,
            ironically it's being handled with the `setTimeout` function. */
            var self = this;

            var streamIt = function(){
                if(responses.length){
                    var response = responses.shift();
                    if(self.readyState === self.OPEN){
                        self.lastResponseId = response.id;
                        self.send(response);
                        self.stream(responses);
                    } else {
                        if(MockEventGlobals.verbose){
                            console.warn("Missed response because EventSource.close()", response);
                        }
                    }
                } else {
                    clearTimeout(timeoutId);
                    timeoutId = false;
                }
            };

            if(!timeoutId){
                if(self.setInterval instanceof Array){
                    var min = self.setInterval[0];
                    var max = self.setInterval[1];
                    var timeoutValue = Math.random() * (max - min) + min;
                    var timeoutId = setTimeout(streamIt, timeoutValue);
                } else {
                    var timeoutValue = self.setInterval;
                    var timeoutId = setTimeout(streamIt, timeoutValue);
                }

                // Logging on `verbose` = True
                if(MockEventGlobals.verbose && responses.length){
                    console.debug("Send stream in " + timeoutValue + " milliseconds.");
                }
            }
        },

        stop: function(){
            this.on = false;
            clearInterval(this.intervalId);
            this.intervalId = false;
        },
        start: function(){
            this.on = true;

            // If you don't have a `last-event-id`
            // Then we start you from 0
            if(!this.lastResponseId){
                delete this.responses;
                this.responses = _.clone(this.allResponses);
            }
            this.stream();
        }
    };

    window.EventSource = function(url, settings){
        var self = this;

        self.url = url;
        self.settings = settings;

        self.CONNECTING = 0;
        self.OPEN = 1;
        self.CLOSED = 2;

        self.readyState = null;

        self.headers = function(){
            return {
                'Accept': 'text/event-stream',
                'Accept-Encoding': 'gzip, deflate, sdch',
                'Accept-Language': window.navigator.languages.join(','),
                'Cache-Control': 'no-cache',
                'Connection': 'keep-alive',
                'Cookie': docCookies.cookiesToString(),
                'Host': window.location.host,
                'Last-event-id': this.handler.lastResponseId || '',
                'Origin': window.location.protocol + '//' + window.location.host,
                'Referer': window.location.protocol + '//' + window.location.host,
                'User-Agent': window.navigator.userAgent
            }
        };

        // Creates event of type `error`
        self.error = function(message){
            var evt = new Event('error');
            evt.error = new Error(message);
            if(self.onerror){
                self.onerror(evt);
            }
        };

        self.close = function(){
            self.readyState = self.CLOSED;
        };

        self.addEventListener = function(name, fn){
            return window.addEventListener(name, fn, false);
        };

        self.listenForErrors = function(mockHandler){
            self.addEventListener(mockHandler.errorEventName(), function(event){
                self.error(event.error);
            });
        }

        self.responses = [];

        // Properties are set in several statements
        // waiting for all properties to be set
        setTimeout(function(){

            // No `MockEvent` instances detected
            if(mockHandlers.length === 0) missed.push(self);

            _.each(mockHandlers, function(mockHandler){
                if(!mockHandler.urlMatches(self.url)){
                    missed.push(self);
                    return;
                }
                self.handler = mockHandler;

                // mockHandler dispatches error event
                // EventSource calls `onerror` method
                self.listenForErrors(mockHandler);

                if(self.readyState === null){
                    self.readyState = self.CONNECTING;
                }

                if(self.readyState == self.CONNECTING){
                    if(self.onopen){
                        self.onopen({
                            message: "You're open!",
                            apology:"I didn't know what else to say."
                        });
                    }
                    self.readyState = self.OPEN;
                }

                if(!(mockHandler.allResponses.length || mockHandler.response)){
                    self.error('Handler ' + mockHandler.url + ' requires response type attribute');
                }

                if(mockHandler.response){
                    mockHandler.response(mockHandler, self);
                }

                if(mockHandler.responses){
                    mockHandler.stream(_.clone(mockHandler.responses));
                }
            })

        }, MockEventGlobals.setTimeout);
    };
    window.MockEvent = function(settings){
        var i = mockHandlers.length;
        mockHandlers[i] = _.extend({}, baseHandler, settings, {id: i});
        mockHandlers[i].initialize();  // Combines namespace` + `url`
        return mockHandlers[i];
    };

    MockEvent.clear = function(i) {
        if ( i || i === 0 ) {
            mockHandlers[i] = null;
        } else {
            mockHandlers = [];
        }
    };

    MockEvent.handlers = function(i){
        if ( i || i === 0 ) {
            return mockHandlers[i];
        } else {
            return mockHandlers;
        }
    };

    MockEvent.missed = function(){
        return missed;
    };

})(window);
<commit_msg>Sets verbose option to `false` by default<commit_after>(function(window, undefined){

    window.MockEventGlobals = {
        namespace: '',
        setTimeout: 0,
        setInterval: 0,
        verbose: false,
        on: true
    }

    var mockHandlers = [];
    var missed = [];

    var baseHandler = {

        id: null,
        url: '',
        namespace: MockEventGlobals.namespace,
        setInterval: MockEventGlobals.setInterval,
        responses: [],
        response: null,
        proxy: null,
        on: MockEventGlobals.on,
        allResponses: [],

        initialize: function(){

            if(this.url.indexOf(this.namespace) < 0){
                this.url = this.namespace + this.url;
            }

            this.allResponses = this.allResponses.concat(this.responses);
        },
        headers: function(){
            return {
                'Access-Control-Allow-Credentials': true,
                'Access-Control-Allow-Headers': 'Content-type,Authorization',
                'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
                'Access-Control-Allow-Origin': window.location.protocol + '//' + window.location.host,
                'Access-Control-Expose-Headers': '*',
                'Cache-Control': 'no-cache',
                'Connection': 'keep-alive',
                'Content-type': 'text/event-stream',
                'Date': (new Date()).toString()
            }
        },
        urlMatches: function(url){
            if (_.isFunction(this.url.test)) {
                // The user provided a regex for the url, test it
                if (!this.url.test(url)) {
                    return false;
                }
            } else {
                var star = this.url.indexOf('*');
                if (this.url !== url && star === -1 ||
                        !new RegExp(this.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, '\\$&').replace(/\*/g, '.+')).test(url)) {
                    return false;
                }
            }
            return true;
        },
        clear: function(){
            mockHandlers[this.id] = null;
            delete this;
        },
        dispatchEvent: function(event){
            return window.dispatchEvent(event);
        },
        send: function(response){
            if(!(response.name && response.data)){
                this.dispatchError('`name` and `data` are required on mock handler response object');
            } else {
                var evt = new Event(response.name)
                evt.data = JSON.stringify(response.data);
                this.dispatchEvent(evt);
            }
        },
        errorEventName: function(){
            return 'mock-event-'+this.id+'-error';
        },
        dispatchError: function(errorMessage){
                var evt = new Event(this.errorEventName());
                evt.error = new Error(errorMessage);
                this.dispatchEvent(evt);
        },
        stream: function(responses){
            /* Handling the stream output via this.setInterval attribute,
            ironically it's being handled with the `setTimeout` function. */
            var self = this;

            var streamIt = function(){
                if(responses.length){
                    var response = responses.shift();
                    if(self.readyState === self.OPEN){
                        self.lastResponseId = response.id;
                        self.send(response);
                        self.stream(responses);
                    } else {
                        if(MockEventGlobals.verbose){
                            console.warn("Missed response because EventSource.close()", response);
                        }
                    }
                } else {
                    clearTimeout(timeoutId);
                    timeoutId = false;
                }
            };

            if(!timeoutId){
                if(self.setInterval instanceof Array){
                    var min = self.setInterval[0];
                    var max = self.setInterval[1];
                    var timeoutValue = Math.random() * (max - min) + min;
                    var timeoutId = setTimeout(streamIt, timeoutValue);
                } else {
                    var timeoutValue = self.setInterval;
                    var timeoutId = setTimeout(streamIt, timeoutValue);
                }

                // Logging on `verbose` = True
                if(MockEventGlobals.verbose && responses.length){
                    console.debug("Send stream in " + timeoutValue + " milliseconds.");
                }
            }
        },

        stop: function(){
            this.on = false;
            clearInterval(this.intervalId);
            this.intervalId = false;
        },
        start: function(){
            this.on = true;

            // If you don't have a `last-event-id`
            // Then we start you from 0
            if(!this.lastResponseId){
                delete this.responses;
                this.responses = _.clone(this.allResponses);
            }
            this.stream();
        }
    };

    window.EventSource = function(url, settings){
        var self = this;

        self.url = url;
        self.settings = settings;

        self.CONNECTING = 0;
        self.OPEN = 1;
        self.CLOSED = 2;

        self.readyState = null;

        self.headers = function(){
            return {
                'Accept': 'text/event-stream',
                'Accept-Encoding': 'gzip, deflate, sdch',
                'Accept-Language': window.navigator.languages.join(','),
                'Cache-Control': 'no-cache',
                'Connection': 'keep-alive',
                'Cookie': docCookies.cookiesToString(),
                'Host': window.location.host,
                'Last-event-id': this.handler.lastResponseId || '',
                'Origin': window.location.protocol + '//' + window.location.host,
                'Referer': window.location.protocol + '//' + window.location.host,
                'User-Agent': window.navigator.userAgent
            }
        };

        // Creates event of type `error`
        self.error = function(message){
            var evt = new Event('error');
            evt.error = new Error(message);
            if(self.onerror){
                self.onerror(evt);
            }
        };

        self.close = function(){
            self.readyState = self.CLOSED;
        };

        self.addEventListener = function(name, fn){
            return window.addEventListener(name, fn, false);
        };

        self.listenForErrors = function(mockHandler){
            self.addEventListener(mockHandler.errorEventName(), function(event){
                self.error(event.error);
            });
        }

        self.responses = [];

        // Properties are set in several statements
        // waiting for all properties to be set
        setTimeout(function(){

            // No `MockEvent` instances detected
            if(mockHandlers.length === 0) missed.push(self);

            _.each(mockHandlers, function(mockHandler){
                if(!mockHandler.urlMatches(self.url)){
                    missed.push(self);
                    return;
                }
                self.handler = mockHandler;

                // mockHandler dispatches error event
                // EventSource calls `onerror` method
                self.listenForErrors(mockHandler);

                if(self.readyState === null){
                    self.readyState = self.CONNECTING;
                }

                if(self.readyState == self.CONNECTING){
                    if(self.onopen){
                        self.onopen({
                            message: "You're open!",
                            apology:"I didn't know what else to say."
                        });
                    }
                    self.readyState = self.OPEN;
                }

                if(!(mockHandler.allResponses.length || mockHandler.response)){
                    self.error('Handler ' + mockHandler.url + ' requires response type attribute');
                }

                if(mockHandler.response){
                    mockHandler.response(mockHandler, self);
                }

                if(mockHandler.responses){
                    mockHandler.stream(_.clone(mockHandler.responses));
                }
            })

        }, MockEventGlobals.setTimeout);
    };
    window.MockEvent = function(settings){
        var i = mockHandlers.length;
        mockHandlers[i] = _.extend({}, baseHandler, settings, {id: i});
        mockHandlers[i].initialize();  // Combines namespace` + `url`
        return mockHandlers[i];
    };

    MockEvent.clear = function(i) {
        if ( i || i === 0 ) {
            mockHandlers[i] = null;
        } else {
            mockHandlers = [];
        }
    };

    MockEvent.handlers = function(i){
        if ( i || i === 0 ) {
            return mockHandlers[i];
        } else {
            return mockHandlers;
        }
    };

    MockEvent.missed = function(){
        return missed;
    };

})(window);
<|endoftext|>


<commit_before>/*jshint node:true*/

'use strict';

var path = require('path');
var existsSync = require('exists-sync');
var chalk = require('chalk');
var EOL = require('os').EOL;

module.exports = {
  normalizeEntityName: function() {
    // this prevents an error when the entityName is
    // not specified (since that doesn't actually matter
    // to us
  },

  fileMapTokens: function() {
    return {
      __root__: function(options) {
        if (options.inAddon) {
          return path.join('tests', 'dummy');
        }

        return '/';
      }
    };
  },

  afterInstall: function() {
    this.insertIntoFile('.jshintrc', '    "server",', {
      after: '"predef": [\n'
    });

    this.insertIntoFile('tests/.jshintrc', '    "server",', {
      after: '"predef": [\n'
    });

    if (existsSync('tests/helpers/destroy-app.js')) {
      this.insertIntoFile('tests/helpers/destroy-app.js', '  server.shutdown();', {
        after: "Ember.run(application, 'destroy');\n"
      });
    } else {
      this.ui.writeLine(
        EOL +
        chalk.yellow(
          '******************************************************' + EOL +
          'destroy-app.js helper is not present. Please read this' + EOL +
          'https://gist.github.com/blimmer/35d3efbb64563029505a'   + EOL +
          'to see how to fix the problem.'                         + EOL +
          '******************************************************' + EOL
        )
      );
    }

    return this.addPackagesToProject([
      { name: 'ember-lodash', target: '0.0.5' }
    ]).then(function() {
      return this.addBowerPackagesToProject([
        { name: 'pretender', target: '~0.10.1' },
        { name: 'Faker', target: '~3.0.0' }
      ]);
    }.bind(this));
  }
};
<commit_msg>Remove ember-lodash from blueprint<commit_after>/*jshint node:true*/

'use strict';

var path = require('path');
var existsSync = require('exists-sync');
var chalk = require('chalk');
var EOL = require('os').EOL;

module.exports = {
  normalizeEntityName: function() {
    // this prevents an error when the entityName is
    // not specified (since that doesn't actually matter
    // to us
  },

  fileMapTokens: function() {
    return {
      __root__: function(options) {
        if (options.inAddon) {
          return path.join('tests', 'dummy');
        }

        return '/';
      }
    };
  },

  afterInstall: function() {
    this.insertIntoFile('.jshintrc', '    "server",', {
      after: '"predef": [\n'
    });

    this.insertIntoFile('tests/.jshintrc', '    "server",', {
      after: '"predef": [\n'
    });

    if (existsSync('tests/helpers/destroy-app.js')) {
      this.insertIntoFile('tests/helpers/destroy-app.js', '  server.shutdown();', {
        after: "Ember.run(application, 'destroy');\n"
      });
    } else {
      this.ui.writeLine(
        EOL +
        chalk.yellow(
          '******************************************************' + EOL +
          'destroy-app.js helper is not present. Please read this' + EOL +
          'https://gist.github.com/blimmer/35d3efbb64563029505a'   + EOL +
          'to see how to fix the problem.'                         + EOL +
          '******************************************************' + EOL
        )
      );
    }

    return this.addBowerPackagesToProject([
      { name: 'pretender', target: '~0.10.1' },
      { name: 'Faker', target: '~3.0.0' }
    ]);
  }
};
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import {months} from '../../utils/dates';
import './DateInput.scss';

const setTwoDigits = number => {
  const num = number / 1;
  const result = number < 10 ? `0${num}` : num;
  return result;
};

class DateInput extends Component {
  constructor(props) {
    super(props);
    this.handleOnChange = this.handleOnChange.bind(this);
    this.handleOnClickButton = this.handleOnClickButton.bind(this);
    this.state = {
      isOpen: false
    };
  }

  isSeparator(value, i) {
    const isSeparator = (value.length === i) && (value[i - 1] !== '/');
    return isSeparator;
  }

  handleOnChange(e) {
    e.stopPropagation();
    const {changeHandler} = this.props;
    const datePattern = /^\d{2}[/-]\d{2}[/-]\d{4}/;
    const targetValue = e.target.value;
    const value = datePattern.exec(targetValue);
    const selStart = e.target.selectionStart;
    if (value) {
      const isoDate = (new Date(value)).toISOString();
      changeHandler(isoDate);
    } else if (this.isSeparator(targetValue, 2) || this.isSeparator(targetValue, 5)) {
      e.target.value += '/';
    } else if (targetValue.length === 3 && selStart === 2) {
      e.target.setSelectionRange(3, 3);
    } else if (targetValue.length === 6 && selStart === 5) {
      e.target.setSelectionRange(6, 6);
    }
  }

  handleOnClickButton() {
    const {isOpen} = this.state;
    this.setState({
      isOpen: !isOpen
    });
  }

  formatDate(isoDate) {
    const date = new Date(isoDate);
    const day = setTwoDigits(date.getDate());
    const month = setTwoDigits(date.getMonth() + 1);
    const year = date.getFullYear();
    return `${day}/${month}/${year}`;
  }

  getMonthHeader() {
    const {month, year} = this.state;
    return (
      {`${month} ${year}`}
    );
  }

  layRemainingDays(days, startingLabel) {
    const fullWeek = [0, 1, 2, 3, 4, 5, 6];
    const midWeekRows = [2, 3, 4];
    const midRows = midWeekRows.map((mw, ri) => (

        {fullWeek.map((d, i) => <button className="date-input__calendar-day boxed" key={`${ri}${i}`}>
          {startingLabel + 7 * ri + i}
        </button>)}

    ));
    days.splice(0, 3 * 7);
    let lastRow = null;
    if (days.length) {
      const hiddenDayCount = days.length - 7;
      const hiddenDays = (new Array(hiddenDayCount)).fill(1);
      const dayLabel = startingLabel + 7 * 3;
      lastRow = (

          {days.map((d, i) => <button className="date-input__calendar-day boxed" key={`l${i}`}>
            {dayLabel + i}
          </button>)}
          {hiddenDays.map((d, i) => <div className="date-input__calendar-day hidden" key={`v5${i}`} />) }

      );
    }
    return [midRows, lastRow];
    //

    //   {fullWeek.map((d, i) => <button className="date-input__calendar-day boxed" key={`v2${i}`} />)}
    //

    //

    //   {fullWeek.map((d, i) => <button className="date-input__calendar-day boxed" key={`v3${i}`} />)}
    //

    //

    //   {fullWeek.map((d, i) => <button className="date-input__calendar-day boxed" key={`v4${i}`} />)}
    //

    //

    //   {fullWeek.map((d, i) => <button className="date-input__calendar-day boxed" key={`v5${i}`} />)}
    //

  }

  layMonthDays() {
    const {date, month} = this.state;
    const monthDate = new Date(date.toISOString());
    monthDate.setDate(1);
    const hiddenDays = (new Array(monthDate.getDay())).fill(1);
    const visibleDays = (new Array(7 - monthDate.getDay())).fill(1);
    const dayCount = months.filter(m => m.name === month)[0].dayCount;
    const remainingDayCount = dayCount - visibleDays.length;
    const remainingDays = (new Array(remainingDayCount)).fill(1);
    return (

          {hiddenDays.map((d, i) =>
)}
          {visibleDays.map((d, i) => <button className="date-input__calendar-day boxed" key={`v1${i}`} >
            {i + 1}
          </button>)}

        {this.layRemainingDays(remainingDays, visibleDays.length + 1)}

    );
  }
  componentWillMount() {
    const date = new Date();
    this.setState({
      date,
      day: date.getDate(),
      month: months[date.getMonth()].name,
      year: date.getFullYear()
    });
  }
  renderCalendar() {
    return (

          <button className="date-input__month-nav">

          </button>

            {this.getMonthHeader()}

          <button className="date-input__month-nav">

          </button>

Sun

Mon

Tue

Wed

Thu

Fri

Sat

          {this.layMonthDays()}

    );
  }

  render() {
    const {isOpen} = this.state;
    const {name, id, disabled, value} = this.props;
    const formattedValue = value && this.formatDate(value);
    return (
      <div className={`date-input${isOpen ? ' date-input--open' : ''}`}>

          <input
            id={id}
            name={name}
            ref={c => { if (c) { this.input = c; } }}
            className="date-input__input"
            placeholder="dd/mm/yyyy"
            defaultValue={formattedValue}
            disabled={disabled}
            onChange={this.handleOnChange} />
          <button className="date-input__calendar-button" onClick={this.handleOnClickButton} disabled={disabled}>

          </button>

        {this.renderCalendar()}

    );
  }
}

DateInput.propTypes = {
  name: PropTypes.string.isRequired,
  value: PropTypes.string,
  disabled: PropTypes.bool,
  id: PropTypes.string,
  changeHandler: PropTypes.func.isRequired
};

export default DateInput;
<commit_msg>DateInput: Updated dayCount for leap years.<commit_after>import React, {Component, PropTypes} from 'react';
import {months} from '../../utils/dates';
import './DateInput.scss';

const setTwoDigits = number => {
  const num = number / 1;
  const result = number < 10 ? `0${num}` : num;
  return result;
};

class DateInput extends Component {
  constructor(props) {
    super(props);
    this.handleOnChange = this.handleOnChange.bind(this);
    this.handleOnClickButton = this.handleOnClickButton.bind(this);
    this.state = {
      isOpen: false
    };
  }

  isSeparator(value, i) {
    const isSeparator = (value.length === i) && (value[i - 1] !== '/');
    return isSeparator;
  }

  handleOnChange(e) {
    e.stopPropagation();
    const {changeHandler} = this.props;
    const datePattern = /^\d{2}[/-]\d{2}[/-]\d{4}/;
    const targetValue = e.target.value;
    const value = datePattern.exec(targetValue);
    const selStart = e.target.selectionStart;
    if (value) {
      const isoDate = (new Date(value)).toISOString();
      changeHandler(isoDate);
    } else if (this.isSeparator(targetValue, 2) || this.isSeparator(targetValue, 5)) {
      e.target.value += '/';
    } else if (targetValue.length === 3 && selStart === 2) {
      e.target.setSelectionRange(3, 3);
    } else if (targetValue.length === 6 && selStart === 5) {
      e.target.setSelectionRange(6, 6);
    }
  }

  handleOnClickButton() {
    const {isOpen} = this.state;
    this.setState({
      isOpen: !isOpen
    });
  }

  formatDate(isoDate) {
    const date = new Date(isoDate);
    const day = setTwoDigits(date.getDate());
    const month = setTwoDigits(date.getMonth() + 1);
    const year = date.getFullYear();
    return `${day}/${month}/${year}`;
  }

  getMonthHeader() {
    const {month, year} = this.state;
    return (
      {`${month} ${year}`}
    );
  }

  layRemainingDays(days, startingLabel) {
    const fullWeek = [0, 1, 2, 3, 4, 5, 6];
    const midWeekRows = [2, 3, 4];
    const midRows = midWeekRows.map((mw, ri) => (

        {fullWeek.map((d, i) => <button className="date-input__calendar-day boxed" key={`${ri}${i}`}>
          {startingLabel + 7 * ri + i}
        </button>)}

    ));
    days.splice(0, 3 * 7);
    let lastRow = null;
    if (days.length) {
      const hiddenDayCount = days.length - 7;
      const hiddenDays = (new Array(hiddenDayCount)).fill(1);
      const dayLabel = startingLabel + 7 * 3;
      lastRow = (

          {days.map((d, i) => <button className="date-input__calendar-day boxed" key={`l${i}`}>
            {dayLabel + i}
          </button>)}
          {hiddenDays.map((d, i) => <div className="date-input__calendar-day hidden" key={`v5${i}`} />) }

      );
    }
    return [midRows, lastRow];
  }

  layMonthDays() {
    const {date, month, year} = this.state;
    const monthDate = new Date(date.toISOString());
    monthDate.setDate(1);
    const hiddenDays = (new Array(monthDate.getDay())).fill(1);
    const visibleDays = (new Array(7 - monthDate.getDay())).fill(1);
    let dayCount = months.filter(m => m.name === month)[0].dayCount;
    const isLeapYear = year % 4;
    dayCount = (month === 'February' && isLeapYear) ? dayCount + 1 : dayCount;
    const remainingDayCount = dayCount - visibleDays.length;
    const remainingDays = (new Array(remainingDayCount)).fill(1);
    return (

          {hiddenDays.map((d, i) =>
)}
          {visibleDays.map((d, i) => <button className="date-input__calendar-day boxed" key={`v1${i}`} >
            {i + 1}
          </button>)}

        {this.layRemainingDays(remainingDays, visibleDays.length + 1)}

    );
  }
  componentWillMount() {
    const date = new Date();
    this.setState({
      date,
      day: date.getDate(),
      month: months[date.getMonth()].name,
      year: date.getFullYear()
    });
  }
  renderCalendar() {
    return (

          <button className="date-input__month-nav">

          </button>

            {this.getMonthHeader()}

          <button className="date-input__month-nav">

          </button>

Sun

Mon

Tue

Wed

Thu

Fri

Sat

          {this.layMonthDays()}

    );
  }

  render() {
    const {isOpen} = this.state;
    const {name, id, disabled, value} = this.props;
    const formattedValue = value && this.formatDate(value);
    return (
      <div className={`date-input${isOpen ? ' date-input--open' : ''}`}>

          <input
            id={id}
            name={name}
            ref={c => { if (c) { this.input = c; } }}
            className="date-input__input"
            placeholder="dd/mm/yyyy"
            defaultValue={formattedValue}
            disabled={disabled}
            onChange={this.handleOnChange} />
          <button className="date-input__calendar-button" onClick={this.handleOnClickButton} disabled={disabled}>

          </button>

        {this.renderCalendar()}

    );
  }
}

DateInput.propTypes = {
  name: PropTypes.string.isRequired,
  value: PropTypes.string,
  disabled: PropTypes.bool,
  id: PropTypes.string,
  changeHandler: PropTypes.func.isRequired
};

export default DateInput;
<|endoftext|>


<commit_before>/* ======================================================================
   qcode.contextMenu plugin:
   Create and open a custom context menu
   Only one context menu can be open at a time

   Usages:
   qcode.contextMenu(options) // same as "create"
   qcode.contextMenu('create', options) // menu opens automatically
   qcode.contextMenu('open' or 'close' or 'destroy')

   Arguments:
   options: {
       position: [x,y],
       menuItems: [
           {
               label: htmlString,
               action: function
           }
           ...
       ],
       classes: { // optional class overrides
           div: 'context-menu',
           open: 'context-menu--open',
           ul: 'context-menu__list',
           li: 'context-menu__item'
       }
   }
*/

var qcode = qcode || {};

(function() {
    "use strict";

    /* ------------------------------------------------------------
       Closure vars to track DOM elements and config
    */
    var menuDiv, menuUL;
    var menuLIs = [];
    var config = {
        classes: {
            div: 'context-menu',
            open: 'context-menu--open',
            ul: 'context-menu__list',
            li: 'context-menu__item'
        }
    };

    /* ------------------------------------------------------------
       Public methods to expose through interface function
    */
    var methods = {

        create: function(options) {
            /* Create the context menu, set up event listeners, then open. */

            // Extend config object with user-defined options
            $.extend(config, options);

            // Opening a new menu destroys any existing menu
            if ( typeof menuDiv !== "undefined" ) {
                methods.destroy();
            }

            // Create menu div
            menuDiv = $('<div>')
                    .addClass(config.classes.div);

            // Create menu ul and append to menu div
            menuUL = $('<ul>')
                    .addClass(config.classes.ul)
                    .appendTo(menuDiv);

            // Add menu items to menu ul
            config.menuItems.forEach(itemAdd);

            // Update the menu position
            positionSet();

            // Set up arrow-key navigation
            menuDiv.navigate('li');

            // Event listeners to close the menu,
            // if elsewhere on the page is clicked or focussed.
            // Also append the menu div to the page body
            $('body')
                    .on('click.context-menu focusin.context-menu',
                        function(event) {
                            if ( ! menuDiv.is(event.target)
                                 && menuDiv.find(event.target).length == 0
                               ) {
                                methods.close();
                                methods.destroy();
                            }
                        })
                    .append(menuDiv);

            // Event listener to close the menu on page scroll
            $(document).on('scroll.context-menu', function() {
                methods.close();
                methods.destroy();
            });

            // Open the menu
            methods.open();

            // Give the first menu item focus by default
            menuLIs[0].focus();
        },

        destroy: function() {
            /* Destroy the context menu div and remove all event listeners */
            // (Do nothing if no context menu exists)
            if ( typeof menuDiv !== "undefined" ) {
                menuDiv.remove();
                menuDiv = undefined;
                menuUL = undefined;
                menuLIs = [];
                $('body').off('.context-menu');
                $(document).off('.context-menu');
            }
        },

        open: function() {
            /* Open the context menu */
            menuDiv.addClass(config.classes.open);
        },

        close: function() {
            /* Close the context menu */
            // (Do nothing if no context menu exists)
            if ( typeof menuDiv !== "undefined" ) {
                menuDiv.removeClass(config.classes.open);
            }
        }
    }

    /* ------------------------------------------------------------
       Internal functions
    */
    function itemAdd(itemConfig) {
        /* Add a menu item using itemConfig object */
        menuLIs.push(
            $('<li>')
                    .attr('tabIndex', 0)
                    .addClass(config.classes.li)
                    .html(itemConfig.label)
                    .on('click.context-menu', itemConfig.action)
                    .on('click.context-menu', methods.close)
                    .on('mouseenter.context-menu', function() {
                        $(this).focus();
                    })
                    .appendTo(menuUL)
        );
    }
    function positionSet() {
        /* Update the menu position from the config object */
        menuDiv.css({
            top: config.position[1],
            left: config.position[0]
        });
    }

    /* ------------------------------------------------------------
       Interface function
    */
    qcode.contextMenu = function() {
        if ( typeof arguments[0] === "string" ) {
            var method = arguments[0];
            var remainingArgs = Array.prototype.slice.call(arguments,1);
            return methods[method].apply(this, remainingArgs);
        } else {
            return methods.create.apply(this, arguments);
        }
    }
})();<commit_msg>Improved event listeners<commit_after>/* ======================================================================
   qcode.contextMenu plugin:
   Create and open a custom context menu
   Only one context menu can be open at a time

   Usages:
   qcode.contextMenu(options) // same as "create"
   qcode.contextMenu('create', options) // menu opens automatically
   qcode.contextMenu('open' or 'close' or 'destroy')

   Arguments:
   options: {
       position: [x,y],
       menuItems: [
           {
               label: htmlString,
               action: function
           }
           ...
       ],
       classes: { // optional class overrides
           div: 'context-menu',
           open: 'context-menu--open',
           ul: 'context-menu__list',
           li: 'context-menu__item'
       }
   }
*/

var qcode = qcode || {};

(function() {
    "use strict";

    /* ------------------------------------------------------------
       Closure vars to track DOM elements and config
    */
    var menuDiv, menuUL;
    var menuLIs = [];
    var config = {
        classes: {
            div: 'context-menu',
            open: 'context-menu--open',
            ul: 'context-menu__list',
            li: 'context-menu__item'
        }
    };

    /* ------------------------------------------------------------
       Public methods to expose through interface function
    */
    var methods = {

        create: function(options) {
            /* Create the context menu, set up event listeners, then open. */

            // Extend config object with user-defined options
            $.extend(config, options);

            // Opening a new menu destroys any existing menu
            if ( typeof menuDiv !== "undefined" ) {
                methods.destroy();
            }

            // Create menu div
            menuDiv = $('<div>')
                    .addClass(config.classes.div);

            // Create menu ul and append to menu div
            menuUL = $('<ul>')
                    .addClass(config.classes.ul)
                    .appendTo(menuDiv);

            // Add menu items to menu ul
            config.menuItems.forEach(itemAdd);

            // Update the menu position
            positionSet();

            // Set up arrow-key navigation
            menuDiv.navigate('li');

            // Append the menu div to the page body
            $('body').append(menuDiv);

            // Event listeners to close the menu on blur
            menuDiv.on('focusout.context-menu', function() {
                window.setZeroTimeout(function() {
                    if ( menuDiv.find(document.activeElement).length === 0 ) {
                        methods.close();
                        methods.destroy();
                    }
                });
            });
            $(window).on('blur.context-menu', function() {
                methods.close();
                methods.destroy();
            });

            // Event listener to close the menu on page scroll
            $(document).on('scroll.context-menu', function() {
                methods.close();
                methods.destroy();
            });

            // Open the menu
            methods.open();

            // Give the first menu item focus by default
            menuLIs[0].focus();
        },

        destroy: function() {
            /* Destroy the context menu div and remove all event listeners */
            // (Do nothing if no context menu exists)
            if ( typeof menuDiv !== "undefined" ) {
                menuDiv.remove();
                menuDiv = undefined;
                menuUL = undefined;
                menuLIs = [];
                $(window).off('.context-menu');
                $('body').off('.context-menu');
                $(document).off('.context-menu');
            }
        },

        open: function() {
            /* Open the context menu */
            menuDiv.addClass(config.classes.open);
        },

        close: function() {
            /* Close the context menu */
            // (Do nothing if no context menu exists)
            if ( typeof menuDiv !== "undefined" ) {
                menuDiv.removeClass(config.classes.open);
            }
        }
    }

    /* ------------------------------------------------------------
       Internal functions
    */
    function itemAdd(itemConfig) {
        /* Add a menu item using itemConfig object */
        menuLIs.push(
            $('<li>')
                    .attr('tabIndex', 0)
                    .addClass(config.classes.li)
                    .html(itemConfig.label)
                    .on('click.context-menu', itemConfig.action)
                    .on('click.context-menu', methods.close)
                    .on('mouseenter.context-menu', function() {
                        $(this).focus();
                    })
                    .appendTo(menuUL)
        );
    }
    function positionSet() {
        /* Update the menu position from the config object */
        menuDiv.css({
            top: config.position[1],
            left: config.position[0]
        });
    }

    /* ------------------------------------------------------------
       Interface function
    */
    qcode.contextMenu = function() {
        if ( typeof arguments[0] === "string" ) {
            var method = arguments[0];
            var remainingArgs = Array.prototype.slice.call(arguments,1);
            return methods[method].apply(this, remainingArgs);
        } else {
            return methods.create.apply(this, arguments);
        }
    }
})();<|endoftext|>


<commit_before>'use strict';

////////////////////////////////////////////////////////////////////////////////
/// @brief basic initialisation
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                load files required during startup
// -----------------------------------------------------------------------------

(function () {
  var startupPath = global.STARTUP_PATH;
  var load = global.SYS_LOAD;

  if (startupPath === "") {
    startupPath = ".";
  }

  load(startupPath + "/common/bootstrap/modules.js");
  load(startupPath + "/common/bootstrap/module-internal.js");
  load(startupPath + "/common/bootstrap/module-fs.js");
  load(startupPath + "/common/bootstrap/module-console.js");
  load(startupPath + "/common/bootstrap/errors.js");
  load(startupPath + "/common/bootstrap/monkeypatches.js");
  load(startupPath + "/server/bootstrap/module-internal.js");
}());

// common globals
global.Buffer = require("buffer").Buffer;
global.process = require("process");
global.setInterval = function () {};
global.clearInterval = function () {};
global.setTimeout = function () {};
global.clearTimeout = function () {};

// extend prototypes for internally defined classes
require("org/arangodb");

// load the actions from the actions directory
require("org/arangodb/actions").startup();

// initialize AQL
require("org/arangodb/aql");

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>rollback pseudo-optimization because of its side-effects<commit_after>'use strict';

////////////////////////////////////////////////////////////////////////////////
/// @brief basic initialisation
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                load files required during startup
// -----------------------------------------------------------------------------

(function () {
  var startupPath = global.STARTUP_PATH;
  var load = global.SYS_LOAD;

  if (startupPath === "") {
    startupPath = ".";
  }

  load(startupPath + "/common/bootstrap/modules.js");
  load(startupPath + "/common/bootstrap/module-internal.js");
  load(startupPath + "/common/bootstrap/module-fs.js");
  load(startupPath + "/common/bootstrap/module-console.js");
  load(startupPath + "/common/bootstrap/errors.js");
  load(startupPath + "/common/bootstrap/monkeypatches.js");
  load(startupPath + "/server/bootstrap/module-internal.js");
}());

// common globals
global.Buffer = require("buffer").Buffer;
global.process = require("process");
global.setInterval = function () {};
global.clearInterval = function () {};
global.setTimeout = function () {};
global.clearTimeout = function () {};

// extend prototypes for internally defined classes
require("org/arangodb");

// load the actions from the actions directory
require("org/arangodb/actions").startup();

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>