<commit_before>/*
 * Copyright (C) 2014 Vanderbilt University, All rights reserved.
 *
 * Author: Zsolt Lattmann
 */

'use strict';
define(['plugin/PluginConfig',
    'plugin/PluginResult',
    'plugin/PluginMessage',
    'plugin/PluginNodeDescription'],
    function (PluginConfig, PluginResult, PluginMessage, PluginNodeDescription) {

        /**
         * Initializes a new instance of a plugin object, which should be a derived class.
         *
         * @constructor
         */
        var PluginBase = function () {
            // set by initialize
            this.logger = null;
            this.blobClient = null;
            this._currentConfig = null;

            // set by configure
            this.core = null;
            this.project = null;
            this.projectName = null;
            this.branchName = null;
            this.branchHash = null;
            this.commitHash = null;
            this.currentHash = null;
            this.rootNode = null;
            this.activeNode = null;
            this.activeSelection = [];
            this.META = null;

            this.result = null;
            this.isConfigured = false;
        };

        //--------------------------------------------------------------------------------------------------------------
        //---------- Methods must be overridden by the derived classes

        /**
         * Main function for the plugin to execute. This will perform the execution.
         * Notes:
         * - do NOT use console.log use this.logger.[error,warning,info,debug] instead
         * - do NOT put any user interaction logic UI, etc. inside this function
         * - callback always have to be called even if error happened
         *
         * @param {function(string, plugin.PluginResult)} callback - the result callback
         */
        PluginBase.prototype.main = function (callback) {
            throw new Error('implement this function in the derived class');
        };

        /**
         * Readable name of this plugin that can contain spaces.
         *
         * @returns {string}
         */
        PluginBase.prototype.getName = function () {
            throw new Error('implement this function in the derived class - getting type automatically is a bad idea,' +
                'when the js scripts are minified names are useless.');
        };

        //--------------------------------------------------------------------------------------------------------------
        //---------- Methods could be overridden by the derived classes

        /**
         * Current version of this plugin using semantic versioning.
         * @returns {string}
         */
        PluginBase.prototype.getVersion = function () {
            return '0.1.0';
        };

        /**
         * A detailed description of this plugin and its purpose. It can be one or more sentences.
         *
         * @returns {string}
         */
        PluginBase.prototype.getDescription = function () {
            return '';
        };

        /**
         * Configuration structure with names, descriptions, minimum, maximum values, default values and
         * type definitions.
         *
         * Example:
         *
         * [{
         *    "name": "logChildrenNames",
         *    "displayName": "Log Children Names",
         *    "description": '',
         *    "value": true, // this is the 'default config'
         *    "valueType": "boolean",
         *    "readOnly": false
         * },{
         *    "name": "logLevel",
         *    "displayName": "Logger level",
         *    "description": '',
         *    "value": "info",
         *    "valueType": "string",
         *    "valueItems": [
         *          "debug",
         *          "info",
         *          "warn",
         *          "error"
         *      ],
         *    "readOnly": false
         * },{
         *    "name": "maxChildrenToLog",
         *    "displayName": "Maximum children to log",
         *    "description": 'Set this parameter to blabla',
         *    "value": 4,
         *    "minValue": 1,
         *    "valueType": "number",
         *    "readOnly": false
         * }]
         *
         * @returns {object[]}
         */
        PluginBase.prototype.getConfigStructure = function () {
            return [];
        };

        //--------------------------------------------------------------------------------------------------------------
        //---------- Methods that can be used by the derived classes

        /**
         * Updates the current success flag with a new value.
         *
         * NewValue = OldValue && Value
         *
         * @param {boolean} value - apply this flag on current success value
         * @param {string|null} message - optional detailed message
         */
        PluginBase.prototype.updateSuccess = function (value, message) {
            var prevSuccess = this.result.getSuccess();
            var newSuccessValue = prevSuccess && value;

            this.result.setSuccess(newSuccessValue);
            var msg = '';
            if (message) {
                msg = ' - ' + message;
            }

            this.logger.debug('Success was updated from ' + prevSuccess + ' to ' + newSuccessValue + msg);
        };

        /**
         * WebGME can export the META types as path and this method updates the generated domain specific types with
         * webgme node objects. These can be used to define the base class of new objects created through the webgme API.
         *
         * @param {object} generatedMETA
         */
        PluginBase.prototype.updateMETA = function (generatedMETA) {
            var name;
            for (name in this.META) {
                if (this.META.hasOwnProperty(name)) {
                    generatedMETA[name] = this.META[name];
                }
            }

            // TODO: check if names are not the same
            // TODO: log if META is out of date
        };

        /**
         * Checks if the given node is of the given meta-type.
         * Usage: <tt>self.isMetaTypeOf(aNode, self.META['FCO']);</tt>
         * @param node - Node to be checked for type.
         * @param metaNode - Node object defining the meta type.
         * @returns {boolean} - True if the given object was of the META type.
         */
        PluginBase.prototype.isMetaTypeOf = function (node, metaNode) {
            var self = this;
            while (node) {
                if (self.core.getGuid(node) === self.core.getGuid(metaNode)) {
                    return true;
                }
                node = self.core.getBase(node);
            }
            return false;
        };

        /**
         * Finds and returns the node object defining the meta type for the given node.
         * @param node - Node to be checked for type.
         * @returns {Object} - Node object defining the meta type of node.
         */
        PluginBase.prototype.getMetaType = function (node) {
            var self = this,
                name;
            while (node) {
                name = self.core.getAttribute(node, 'name');
                if (self.META.hasOwnProperty(name) && self.core.getGuid(node) === self.core.getGuid(self.META[name])) {
                    break;
                }
                node = self.core.getBase(node);
            }
            return node;
        };

        /**
         * Returns true if node is a direct instance of a meta-type node (or a meta-type node itself).
         * @param node - Node to be checked.
         * @returns {boolean}
         */
        PluginBase.prototype.baseIsMeta = function (node) {
            var self = this,
                baseName,
                baseNode = self.core.getBase(node);
            if (!baseNode) {
                // FCO does not have a base node, by definition function returns true.
                return true;
            }
            baseName = self.core.getAttribute(baseNode, 'name');
            return self.META.hasOwnProperty(baseName) && self.core.getGuid(self.META[baseName]) === self.core.getGuid(baseNode);
        };

        /**
         * Gets the current configuration of the plugin that was set by the user and plugin manager.
         *
         * @returns {object}
         */
        PluginBase.prototype.getCurrentConfig = function () {
            return this._currentConfig;
        };

        /**
         * Creates a new message for the user and adds it to the result.
         *
         * @param {object} node - webgme object which is related to the message
         * @param {string} message - feedback to the user
         * @param {string} severity - severity level of the message: 'debug', 'info' (default), 'warning', 'error'.
         */
        PluginBase.prototype.createMessage = function (node, message, severity) {
            var severityLevel = severity || 'info';
            //this occurence of the function will always handle a single node

            var descriptor = new PluginNodeDescription({
                    name: node ? this.core.getAttribute(node, 'name') : "",
                    id: node ? this.core.getPath(node) : ""
                });
            var pluginMessage = new PluginMessage({
                    commitHash: this.currentHash,
                    activeNode: descriptor,
                    message: message,
                    severity: severityLevel
                });

            this.result.addMessage(pluginMessage);
        };

        /**
         * Saves all current changes if there is any to a new commit.
         * If the changes were started from a branch, then tries to fast forward the branch to the new commit.
         * Note: Does NOT handle any merges at this point.
         *
         * @param {string|null} message - commit message
         * @param callback
         */
        PluginBase.prototype.save = function (message, callback) {
            var self = this;

            this.logger.debug('Saving project');

            this.core.persist(this.rootNode,function(err){if (err) {self.logger.error(err);}});
            var newRootHash = self.core.getHash(self.rootNode);

            var commitMessage = '[Plugin] ' + self.getName() + ' (v' + self.getVersion() + ') updated the model.';
            if (message) {
                commitMessage += ' - ' + message;
            }
            self.currentHash = self.project.makeCommit([self.currentHash], newRootHash, commitMessage, function (err) {if (err) {self.logger.error(err);}});

            if (self.branchName) {
                // try to fast forward branch if there was a branch name defined

                // FIXME: what if master branch is already in a different state?

                self.project.getBranchNames(function (err, branchNames) {
                    if (branchNames.hasOwnProperty(self.branchName)) {
                        var branchHash = branchNames[self.branchName];
                        if (branchHash === self.branchHash) {
                            // the branch does not have any new commits
                            // try to fast forward branch to the current commit
                            self.project.setBranchHash(self.branchName, self.branchHash, self.currentHash, function (err) {
                                if (err) {
                                    // fast forward failed
                                    self.logger.error(err);
                                    self.logger.info('"' + self.branchName + '" was NOT updated');
                                    self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                                } else {
                                    // successful fast forward of branch to the new commit
                                    self.logger.info('"' + self.branchName + '" was updated to the new commit.');
                                    // roll starting point on success
                                    self.branchHash = self.currentHash;
                                }
                                callback(err);
                            });
                        } else {
                            // branch has changes a merge is required
                            // TODO: try auto-merge, if fails ...
                            self.logger.warn('Cannot fast forward "' + self.branchName + '" branch. Merge is required but not supported yet.');
                            self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                            callback(null);
                        }
                    } else {
                        // branch was deleted or not found, do nothing
                        self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                        callback(null);
                    }
                });
                // FIXME: is this call async??
                // FIXME: we are not tracking all commits that we make

            } else {
                // making commits, we have not started from a branch
                self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                callback(null);
            }

            // Commit changes.
/*            this.core.persist(this.rootNode, function (err) {
                // TODO: any error here?
                if (err) {
                    self.logger.error(err);
                }

                var newRootHash = self.core.getHash(self.rootNode);

                var commitMessage = '[Plugin] ' + self.getName() + ' (v' + self.getVersion() + ') updated the model.';
                if (message) {
                    commitMessage += ' - ' + message;
                }

                self.currentHash = self.project.makeCommit([self.currentHash], newRootHash, commitMessage, function (err) {
                    // TODO: any error handling here?
                    if (err) {
                        self.logger.error(err);
                    }

                    if (self.branchName) {
                        // try to fast forward branch if there was a branch name defined

                        // FIXME: what if master branch is already in a different state?

                        self.project.getBranchNames(function (err, branchNames) {
                            if (branchNames.hasOwnProperty(self.branchName)) {
                                var branchHash = branchNames[self.branchName];
                                if (branchHash === self.branchHash) {
                                    // the branch does not have any new commits
                                    // try to fast forward branch to the current commit
                                    self.project.setBranchHash(self.branchName, self.branchHash, self.currentHash, function (err) {
                                        if (err) {
                                            // fast forward failed
                                            self.logger.error(err);
                                            self.logger.info('"' + self.branchName + '" was NOT updated');
                                            self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                                        } else {
                                            // successful fast forward of branch to the new commit
                                            self.logger.info('"' + self.branchName + '" was updated to the new commit.');
                                            // roll starting point on success
                                            self.branchHash = self.currentHash;
                                        }
                                        callback(err);
                                    });
                                } else {
                                    // branch has changes a merge is required
                                    // TODO: try auto-merge, if fails ...
                                    self.logger.warn('Cannot fast forward "' + self.branchName + '" branch. Merge is required but not supported yet.');
                                    self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                                    callback(null);
                                }
                            } else {
                                // branch was deleted or not found, do nothing
                                self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                                callback(null);
                            }
                        });
                        // FIXME: is this call async??
                        // FIXME: we are not tracking all commits that we make

                    } else {
                        // making commits, we have not started from a branch
                        self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                        callback(null);
                    }
                });

            });*/
        };

        //--------------------------------------------------------------------------------------------------------------
        //---------- Methods that are used by the Plugin Manager. Derived classes should not use these methods

        /**
         * Initializes the plugin with objects that can be reused within the same plugin instance.
         *
         * @param {logManager} logger - logging capability to console (or file) based on PluginManager configuration
         * @param {blob.BlobClient} blobClient - virtual file system where files can be generated then saved as a zip file.
         */
        PluginBase.prototype.initialize = function (logger, blobClient) {
            if (logger) {
                this.logger = logger;
            } else {
                this.logger = console;
            }

            this.blobClient = blobClient;

            this._currentConfig = null;
            // initialize default configuration
            this.setCurrentConfig(this.getDefaultConfig());

            this.isConfigured = false;
        };

        /**
         * Configures this instance of the plugin for a specific execution. This function is called before the main by
         * the PluginManager.
         * Initializes the result with a new object.
         *
         * @param {PluginContext} config - specific context: project, branch, core, active object and active selection.
         */
        PluginBase.prototype.configure = function (config) {
            this.core = config.core;
            this.project = config.project;
            this.projectName = config.projectName;
            this.branchName = config.branchName;
            this.branchHash = config.branchName ? config.commitHash : null;
            this.commitHash = config.commitHash;
            this.currentHash = config.commitHash;
            this.rootNode = config.rootNode;
            this.activeNode = config.activeNode;
            this.activeSelection = config.activeSelection;
            this.META = config.META;

            this.result = new PluginResult();

            this.isConfigured = true;
        };

        /**
         * Gets the default configuration based on the configuration structure for this plugin.
         *
         * @returns {plugin.PluginConfig}
         */
        PluginBase.prototype.getDefaultConfig = function () {
            var configStructure = this.getConfigStructure();

            var defaultConfig = new PluginConfig();

            for (var i = 0; i < configStructure.length; i += 1) {
                defaultConfig[configStructure[i].name] = configStructure[i].value;
            }

            return defaultConfig;
        };

        /**
         * Sets the current configuration of the plugin.
         *
         * @param {object} newConfig - this is the actual configuration and NOT the configuration structure.
         */
        PluginBase.prototype.setCurrentConfig = function (newConfig) {
            this._currentConfig = newConfig;
        };

        return PluginBase;
    });<commit_msg>PluginBase: don't read current branch state when committing results<commit_after>/*
 * Copyright (C) 2014 Vanderbilt University, All rights reserved.
 *
 * Author: Zsolt Lattmann
 */

'use strict';
define(['plugin/PluginConfig',
    'plugin/PluginResult',
    'plugin/PluginMessage',
    'plugin/PluginNodeDescription'],
    function (PluginConfig, PluginResult, PluginMessage, PluginNodeDescription) {

        /**
         * Initializes a new instance of a plugin object, which should be a derived class.
         *
         * @constructor
         */
        var PluginBase = function () {
            // set by initialize
            this.logger = null;
            this.blobClient = null;
            this._currentConfig = null;

            // set by configure
            this.core = null;
            this.project = null;
            this.projectName = null;
            this.branchName = null;
            this.branchHash = null;
            this.commitHash = null;
            this.currentHash = null;
            this.rootNode = null;
            this.activeNode = null;
            this.activeSelection = [];
            this.META = null;

            this.result = null;
            this.isConfigured = false;
        };

        //--------------------------------------------------------------------------------------------------------------
        //---------- Methods must be overridden by the derived classes

        /**
         * Main function for the plugin to execute. This will perform the execution.
         * Notes:
         * - do NOT use console.log use this.logger.[error,warning,info,debug] instead
         * - do NOT put any user interaction logic UI, etc. inside this function
         * - callback always have to be called even if error happened
         *
         * @param {function(string, plugin.PluginResult)} callback - the result callback
         */
        PluginBase.prototype.main = function (callback) {
            throw new Error('implement this function in the derived class');
        };

        /**
         * Readable name of this plugin that can contain spaces.
         *
         * @returns {string}
         */
        PluginBase.prototype.getName = function () {
            throw new Error('implement this function in the derived class - getting type automatically is a bad idea,' +
                'when the js scripts are minified names are useless.');
        };

        //--------------------------------------------------------------------------------------------------------------
        //---------- Methods could be overridden by the derived classes

        /**
         * Current version of this plugin using semantic versioning.
         * @returns {string}
         */
        PluginBase.prototype.getVersion = function () {
            return '0.1.0';
        };

        /**
         * A detailed description of this plugin and its purpose. It can be one or more sentences.
         *
         * @returns {string}
         */
        PluginBase.prototype.getDescription = function () {
            return '';
        };

        /**
         * Configuration structure with names, descriptions, minimum, maximum values, default values and
         * type definitions.
         *
         * Example:
         *
         * [{
         *    "name": "logChildrenNames",
         *    "displayName": "Log Children Names",
         *    "description": '',
         *    "value": true, // this is the 'default config'
         *    "valueType": "boolean",
         *    "readOnly": false
         * },{
         *    "name": "logLevel",
         *    "displayName": "Logger level",
         *    "description": '',
         *    "value": "info",
         *    "valueType": "string",
         *    "valueItems": [
         *          "debug",
         *          "info",
         *          "warn",
         *          "error"
         *      ],
         *    "readOnly": false
         * },{
         *    "name": "maxChildrenToLog",
         *    "displayName": "Maximum children to log",
         *    "description": 'Set this parameter to blabla',
         *    "value": 4,
         *    "minValue": 1,
         *    "valueType": "number",
         *    "readOnly": false
         * }]
         *
         * @returns {object[]}
         */
        PluginBase.prototype.getConfigStructure = function () {
            return [];
        };

        //--------------------------------------------------------------------------------------------------------------
        //---------- Methods that can be used by the derived classes

        /**
         * Updates the current success flag with a new value.
         *
         * NewValue = OldValue && Value
         *
         * @param {boolean} value - apply this flag on current success value
         * @param {string|null} message - optional detailed message
         */
        PluginBase.prototype.updateSuccess = function (value, message) {
            var prevSuccess = this.result.getSuccess();
            var newSuccessValue = prevSuccess && value;

            this.result.setSuccess(newSuccessValue);
            var msg = '';
            if (message) {
                msg = ' - ' + message;
            }

            this.logger.debug('Success was updated from ' + prevSuccess + ' to ' + newSuccessValue + msg);
        };

        /**
         * WebGME can export the META types as path and this method updates the generated domain specific types with
         * webgme node objects. These can be used to define the base class of new objects created through the webgme API.
         *
         * @param {object} generatedMETA
         */
        PluginBase.prototype.updateMETA = function (generatedMETA) {
            var name;
            for (name in this.META) {
                if (this.META.hasOwnProperty(name)) {
                    generatedMETA[name] = this.META[name];
                }
            }

            // TODO: check if names are not the same
            // TODO: log if META is out of date
        };

        /**
         * Checks if the given node is of the given meta-type.
         * Usage: <tt>self.isMetaTypeOf(aNode, self.META['FCO']);</tt>
         * @param node - Node to be checked for type.
         * @param metaNode - Node object defining the meta type.
         * @returns {boolean} - True if the given object was of the META type.
         */
        PluginBase.prototype.isMetaTypeOf = function (node, metaNode) {
            var self = this;
            while (node) {
                if (self.core.getGuid(node) === self.core.getGuid(metaNode)) {
                    return true;
                }
                node = self.core.getBase(node);
            }
            return false;
        };

        /**
         * Finds and returns the node object defining the meta type for the given node.
         * @param node - Node to be checked for type.
         * @returns {Object} - Node object defining the meta type of node.
         */
        PluginBase.prototype.getMetaType = function (node) {
            var self = this,
                name;
            while (node) {
                name = self.core.getAttribute(node, 'name');
                if (self.META.hasOwnProperty(name) && self.core.getGuid(node) === self.core.getGuid(self.META[name])) {
                    break;
                }
                node = self.core.getBase(node);
            }
            return node;
        };

        /**
         * Returns true if node is a direct instance of a meta-type node (or a meta-type node itself).
         * @param node - Node to be checked.
         * @returns {boolean}
         */
        PluginBase.prototype.baseIsMeta = function (node) {
            var self = this,
                baseName,
                baseNode = self.core.getBase(node);
            if (!baseNode) {
                // FCO does not have a base node, by definition function returns true.
                return true;
            }
            baseName = self.core.getAttribute(baseNode, 'name');
            return self.META.hasOwnProperty(baseName) && self.core.getGuid(self.META[baseName]) === self.core.getGuid(baseNode);
        };

        /**
         * Gets the current configuration of the plugin that was set by the user and plugin manager.
         *
         * @returns {object}
         */
        PluginBase.prototype.getCurrentConfig = function () {
            return this._currentConfig;
        };

        /**
         * Creates a new message for the user and adds it to the result.
         *
         * @param {object} node - webgme object which is related to the message
         * @param {string} message - feedback to the user
         * @param {string} severity - severity level of the message: 'debug', 'info' (default), 'warning', 'error'.
         */
        PluginBase.prototype.createMessage = function (node, message, severity) {
            var severityLevel = severity || 'info';
            //this occurence of the function will always handle a single node

            var descriptor = new PluginNodeDescription({
                    name: node ? this.core.getAttribute(node, 'name') : "",
                    id: node ? this.core.getPath(node) : ""
                });
            var pluginMessage = new PluginMessage({
                    commitHash: this.currentHash,
                    activeNode: descriptor,
                    message: message,
                    severity: severityLevel
                });

            this.result.addMessage(pluginMessage);
        };

        /**
         * Saves all current changes if there is any to a new commit.
         * If the changes were started from a branch, then tries to fast forward the branch to the new commit.
         * Note: Does NOT handle any merges at this point.
         *
         * @param {string|null} message - commit message
         * @param callback
         */
        PluginBase.prototype.save = function (message, callback) {
            var self = this;

            this.logger.debug('Saving project');

            this.core.persist(this.rootNode,function(err){if (err) {self.logger.error(err);}});
            var newRootHash = self.core.getHash(self.rootNode);

            var commitMessage = '[Plugin] ' + self.getName() + ' (v' + self.getVersion() + ') updated the model.';
            if (message) {
                commitMessage += ' - ' + message;
            }
            self.currentHash = self.project.makeCommit([self.currentHash], newRootHash, commitMessage, function (err) {if (err) {self.logger.error(err);}});

            if (self.branchName) {
                // try to fast forward branch if there was a branch name defined

                // FIXME: what if master branch is already in a different state?

                // try to fast forward branch to the current commit
                self.project.setBranchHash(self.branchName, self.branchHash, self.currentHash, function (err) {
                    if (err) {
                        // fast forward failed
                        // TODO: try auto-merge

                        self.logger.error(err);
                        self.logger.info('"' + self.branchName + '" was NOT updated');
                        self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                    } else {
                        // successful fast forward of branch to the new commit
                        self.logger.info('"' + self.branchName + '" was updated to the new commit.');
                        // roll starting point on success
                        self.branchHash = self.currentHash;
                    }
                    callback(err);
                });

                // FIXME: is this call async??
                // FIXME: we are not tracking all commits that we make

            } else {
                // making commits, we have not started from a branch
                self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                callback(null);
            }

            // Commit changes.
/*            this.core.persist(this.rootNode, function (err) {
                // TODO: any error here?
                if (err) {
                    self.logger.error(err);
                }

                var newRootHash = self.core.getHash(self.rootNode);

                var commitMessage = '[Plugin] ' + self.getName() + ' (v' + self.getVersion() + ') updated the model.';
                if (message) {
                    commitMessage += ' - ' + message;
                }

                self.currentHash = self.project.makeCommit([self.currentHash], newRootHash, commitMessage, function (err) {
                    // TODO: any error handling here?
                    if (err) {
                        self.logger.error(err);
                    }

                    if (self.branchName) {
                        // try to fast forward branch if there was a branch name defined

                        // FIXME: what if master branch is already in a different state?

                        self.project.getBranchNames(function (err, branchNames) {
                            if (branchNames.hasOwnProperty(self.branchName)) {
                                var branchHash = branchNames[self.branchName];
                                if (branchHash === self.branchHash) {
                                    // the branch does not have any new commits
                                    // try to fast forward branch to the current commit
                                    self.project.setBranchHash(self.branchName, self.branchHash, self.currentHash, function (err) {
                                        if (err) {
                                            // fast forward failed
                                            self.logger.error(err);
                                            self.logger.info('"' + self.branchName + '" was NOT updated');
                                            self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                                        } else {
                                            // successful fast forward of branch to the new commit
                                            self.logger.info('"' + self.branchName + '" was updated to the new commit.');
                                            // roll starting point on success
                                            self.branchHash = self.currentHash;
                                        }
                                        callback(err);
                                    });
                                } else {
                                    // branch has changes a merge is required
                                    // TODO: try auto-merge, if fails ...
                                    self.logger.warn('Cannot fast forward "' + self.branchName + '" branch. Merge is required but not supported yet.');
                                    self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                                    callback(null);
                                }
                            } else {
                                // branch was deleted or not found, do nothing
                                self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                                callback(null);
                            }
                        });
                        // FIXME: is this call async??
                        // FIXME: we are not tracking all commits that we make

                    } else {
                        // making commits, we have not started from a branch
                        self.logger.info('Project was saved to ' + self.currentHash + ' commit.');
                        callback(null);
                    }
                });

            });*/
        };

        //--------------------------------------------------------------------------------------------------------------
        //---------- Methods that are used by the Plugin Manager. Derived classes should not use these methods

        /**
         * Initializes the plugin with objects that can be reused within the same plugin instance.
         *
         * @param {logManager} logger - logging capability to console (or file) based on PluginManager configuration
         * @param {blob.BlobClient} blobClient - virtual file system where files can be generated then saved as a zip file.
         */
        PluginBase.prototype.initialize = function (logger, blobClient) {
            if (logger) {
                this.logger = logger;
            } else {
                this.logger = console;
            }

            this.blobClient = blobClient;

            this._currentConfig = null;
            // initialize default configuration
            this.setCurrentConfig(this.getDefaultConfig());

            this.isConfigured = false;
        };

        /**
         * Configures this instance of the plugin for a specific execution. This function is called before the main by
         * the PluginManager.
         * Initializes the result with a new object.
         *
         * @param {PluginContext} config - specific context: project, branch, core, active object and active selection.
         */
        PluginBase.prototype.configure = function (config) {
            this.core = config.core;
            this.project = config.project;
            this.projectName = config.projectName;
            this.branchName = config.branchName;
            this.branchHash = config.branchName ? config.commitHash : null;
            this.commitHash = config.commitHash;
            this.currentHash = config.commitHash;
            this.rootNode = config.rootNode;
            this.activeNode = config.activeNode;
            this.activeSelection = config.activeSelection;
            this.META = config.META;

            this.result = new PluginResult();

            this.isConfigured = true;
        };

        /**
         * Gets the default configuration based on the configuration structure for this plugin.
         *
         * @returns {plugin.PluginConfig}
         */
        PluginBase.prototype.getDefaultConfig = function () {
            var configStructure = this.getConfigStructure();

            var defaultConfig = new PluginConfig();

            for (var i = 0; i < configStructure.length; i += 1) {
                defaultConfig[configStructure[i].name] = configStructure[i].value;
            }

            return defaultConfig;
        };

        /**
         * Sets the current configuration of the plugin.
         *
         * @param {object} newConfig - this is the actual configuration and NOT the configuration structure.
         */
        PluginBase.prototype.setCurrentConfig = function (newConfig) {
            this._currentConfig = newConfig;
        };

        return PluginBase;
    });
<|endoftext|>


<commit_before>// install   :      cordova plugin add org.apache.cordova.statusbar
// link      :      https://github.com/apache/cordova-plugin-statusbar/

angular.module('ngCordova.plugins.statusbar', [])

  .factory('$cordovaStatusbar', [function () {

    return {
      overlaysWebView: function (bool) {
        return StatusBar.overlaysWebView(!!bool);
      },

      style: function (style) {
        switch (style) {
          // Default
          case 0:
            return StatusBar.styleDefault();

          // LightContent
          case 1:
            return StatusBar.styleLightContent();

          // BlackTranslucent
          case 2:
            return StatusBar.styleBlackTranslucent();

          // BlackOpaque
          case 3:
            return StatusBar.styleBlackOpaque();

          default:
            return StatusBar.styleDefault();
        }
      },

      // supported names:
      // black, darkGray, lightGray, white, gray, red, green,
      // blue, cyan, yellow, magenta, orange, purple, brown
      styleColor: function (color) {
        return StatusBar.backgroundColorByName(color);
      },

      styleHex: function (colorHex) {
        return StatusBar.backgroundColorByHexString(colorHex);
      },

      hide: function () {
        return StatusBar.hide();
      },

      show: function () {
        return StatusBar.show();
      },

      isVisible: function () {
        return StatusBar.isVisible;
      }
    };
  }]);
<commit_msg>Add statusbar styles to a "constant" key value obj<commit_after>// install   :      cordova plugin add org.apache.cordova.statusbar
// link      :      https://github.com/apache/cordova-plugin-statusbar/

angular.module('ngCordova.plugins.statusbar', [])

  .factory('$cordovaStatusbar', [function () {

    return {
      overlaysWebView: function (bool) {
        return StatusBar.overlaysWebView(!!bool);
      },

      STYLES: {
        DEFAULT: 0,
        LIGHT_CONTENT: 1,
        BLACK_TRANSLUCENT: 2,
        BLACK_OPAQUE: 3
      },

      style: function (style) {
        switch (style) {
          // Default
          case 0:
            return StatusBar.styleDefault();

          // LightContent
          case 1:
            return StatusBar.styleLightContent();

          // BlackTranslucent
          case 2:
            return StatusBar.styleBlackTranslucent();

          // BlackOpaque
          case 3:
            return StatusBar.styleBlackOpaque();

          default:
            return StatusBar.styleDefault();
        }
      },

      // supported names:
      // black, darkGray, lightGray, white, gray, red, green,
      // blue, cyan, yellow, magenta, orange, purple, brown
      styleColor: function (color) {
        return StatusBar.backgroundColorByName(color);
      },

      styleHex: function (colorHex) {
        return StatusBar.backgroundColorByHexString(colorHex);
      },

      hide: function () {
        return StatusBar.hide();
      },

      show: function () {
        return StatusBar.show();
      },

      isVisible: function () {
        return StatusBar.isVisible;
      }
    };
  }]);
<|endoftext|>


<commit_before>/*
* Project: Gorin Notify
* Description: Turns standard Bootstrap alerts into "Growl-like" notifications.
* License: MIT License
* Website: https://gonrin.com/ui/
*/

/* global define:false, require: false, jQuery:false */

(function (factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD. Register as an anonymous module.
		define(['jquery'], factory);
	} else if (typeof exports === 'object') {
		// Node/CommonJS
		factory(require('jquery'));
	} else {
		// Browser globals
		factory(jQuery);
	}
}(function ($) {
	// Create the defaults once
	var defaults = {
		element: 'body',
		position: null,
		type: "info",
		allow_dismiss: true,
		allow_duplicates: true,
		newest_on_top: false,
		showProgressbar: false,
		placement: {
			from: "top",
			align: "right"
		},
		offset: 50,
		spacing: 10,
		z_index: 10031,
		delay: 3000,
		timer: 1000,
		url_target: '_blank',
		mouse_over: null,
		animate: {
			enter: 'animated fadeInDown',
			exit: 'animated fadeOutUp'
		},
		onShow: null,
		onShown: null,
		onClose: null,
		onClosed: null,
		icon_type: 'class',
		template: '
<button type="button" aria-hidden="true" class="close" gonrin-notify="dismiss">×</button> {1} {2}

'
	};

	String.format = function () {
		var str = arguments[0];
		for (var i = 1; i < arguments.length; i++) {
			str = str.replace(RegExp("\\{" + (i - 1) + "\\}", "gm"), arguments[i]);
		}
		return str;
	};

	function isDuplicateNotification(notification) {
		var isDupe = false;

		$('[gonrin-notify="container"]').each(function (i, el) {
			var $el = $(el);
			var title = $el.find('[gonrin-notify="title"]').text().trim();
			var message = $el.find('[gonrin-notify="message"]').html().trim();

			// The input string might be different than the actual parsed HTML string!
			// (
 vs
 for example)
			// So we have to force-parse this as HTML here!
			var isSameTitle = title === $("
" + notification.settings.content.title + "
").html().trim();
			var isSameMsg = message === $("
" + notification.settings.content.message + "
").html().trim();
			var isSameType = $el.hasClass('alert-' + notification.settings.type);

			if (isSameTitle && isSameMsg && isSameType) {
				//we found the dupe. Set the var and stop checking.
				isDupe = true;
			}
			return !isDupe;
		});

		return isDupe;
	}

	function Notify(element, content, options) {
		// Setup Content of Notify
		var contentObj = {
			content: {
				message: typeof content === 'object' ? content.message : content,
				title: content.title ? content.title : '',
				icon: content.icon ? content.icon : '',
				url: content.url ? content.url : '#',
				target: content.target ? content.target : '-'
			}
		};

		options = $.extend(true, {}, contentObj, options);
		this.settings = $.extend(true, {}, defaults, options);
		this._defaults = defaults;
		if (this.settings.content.target === "-") {
			this.settings.content.target = this.settings.url_target;
		}
		this.animations = {
			start: 'webkitAnimationStart oanimationstart MSAnimationStart animationstart',
			end: 'webkitAnimationEnd oanimationend MSAnimationEnd animationend'
		};

		if (typeof this.settings.offset === 'number') {
			this.settings.offset = {
				x: this.settings.offset,
				y: this.settings.offset
			};
		}

		//if duplicate messages are not allowed, then only continue if this new message is not a duplicate of one that it already showing
		if (this.settings.allow_duplicates || (!this.settings.allow_duplicates && !isDuplicateNotification(this))) {
			this.init();
		}
	}

	$.extend(Notify.prototype, {
		init: function () {
			var self = this;

			this.buildNotify();
			if (this.settings.content.icon) {
				this.setIcon();
			}
			if (this.settings.content.url != "#") {
				this.styleURL();
			}
			this.styleDismiss();
			this.placement();
			this.bind();

			this.notify = {
				$ele: this.$ele,
				update: function (command, update) {
					var commands = {};
					if (typeof command === "string") {
						commands[command] = update;
					} else {
						commands = command;
					}
					for (var cmd in commands) {
						switch (cmd) {
							case "type":
								this.$ele.removeClass('alert-' + self.settings.type);
								this.$ele.find('[gonrin-notify="progressbar"] > .progress-bar').removeClass('progress-bar-' + self.settings.type);
								self.settings.type = commands[cmd];
								this.$ele.addClass('alert-' + commands[cmd]).find('[gonrin-notify="progressbar"] > .progress-bar').addClass('progress-bar-' + commands[cmd]);
								break;
							case "icon":
								var $icon = this.$ele.find('[gonrin-notify="icon"]');
								if (self.settings.icon_type.toLowerCase() === 'class') {
									$icon.removeClass(self.settings.content.icon).addClass(commands[cmd]);
								} else {
									if (!$icon.is('img')) {
										$icon.find('img');
									}
									$icon.attr('src', commands[cmd]);
								}
								break;
							case "progress":
								var newDelay = self.settings.delay - (self.settings.delay * (commands[cmd] / 100));
								this.$ele.data('notify-delay', newDelay);
								this.$ele.find('[gonrin-notify="progressbar"] > div').attr('aria-valuenow', commands[cmd]).css('width', commands[cmd] + '%');
								break;
							case "url":
								this.$ele.find('[gonrin-notify="url"]').attr('href', commands[cmd]);
								break;
							case "target":
								this.$ele.find('[gonrin-notify="url"]').attr('target', commands[cmd]);
								break;
							default:
								this.$ele.find('[gonrin-notify="' + cmd + '"]').html(commands[cmd]);
						}
					}
					var posX = this.$ele.outerHeight() + parseInt(self.settings.spacing) + parseInt(self.settings.offset.y);
					self.reposition(posX);
				},
				close: function () {
					self.close();
				}
			};

		},
		buildNotify: function () {
			var content = this.settings.content;
			this.$ele = $(String.format(this.settings.template, this.settings.type, content.title, content.message, content.url, content.target));
			this.$ele.attr('gonrin-notify-position', this.settings.placement.from + '-' + this.settings.placement.align);
			if (!this.settings.allow_dismiss) {
				this.$ele.find('[gonrin-notify="dismiss"]').css('display', 'none');
			}
			if ((this.settings.delay <= 0 && !this.settings.showProgressbar) || !this.settings.showProgressbar) {
				this.$ele.find('[gonrin-notify="progressbar"]').remove();
			}
		},
		setIcon: function () {
			if (this.settings.icon_type.toLowerCase() === 'class') {
				this.$ele.find('[gonrin-notify="icon"]').addClass(this.settings.content.icon);
			} else {
				if (this.$ele.find('[gonrin-notify="icon"]').is('img')) {
					this.$ele.find('[gonrin-notify="icon"]').attr('src', this.settings.content.icon);
				} else {
					this.$ele.find('[gonrin-notify="icon"]').append('');
				}
			}
		},
		styleDismiss: function () {
			this.$ele.find('[gonrin-notify="dismiss"]').css({
				position: 'absolute',
				right: '10px',
				top: '5px',
				zIndex: this.settings.z_index + 2
			});
		},
		styleURL: function () {
			this.$ele.find('[gonrin-notify="url"]').css({
				backgroundImage: 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)',
				height: '100%',
				left: 0,
				position: 'absolute',
				top: 0,
				width: '100%',
				zIndex: this.settings.z_index + 1
			});
		},
		placement: function () {
			var self = this,
				offsetAmt = this.settings.offset.y,
				css = {
					display: 'inline-block',
					margin: '0px auto',
					position: this.settings.position ? this.settings.position : (this.settings.element === 'body' ? 'fixed' : 'absolute'),
					transition: 'all .5s ease-in-out',
					zIndex: this.settings.z_index
				},
				hasAnimation = false,
				settings = this.settings;

			$('[gonrin-notify-position="' + this.settings.placement.from + '-' + this.settings.placement.align + '"]:not([data-closing="true"])').each(function () {
				offsetAmt = Math.max(offsetAmt, parseInt($(this).css(settings.placement.from)) + parseInt($(this).outerHeight()) + parseInt(settings.spacing));
			});
			if (this.settings.newest_on_top === true) {
				offsetAmt = this.settings.offset.y;
			}
			css[this.settings.placement.from] = offsetAmt + 'px';

			switch (this.settings.placement.align) {
				case "left":
				case "right":
					css[this.settings.placement.align] = this.settings.offset.x + 'px';
					break;
				case "center":
					css.left = 0;
					css.right = 0;
					break;
			}
			this.$ele.css(css).addClass(this.settings.animate.enter);
			$.each(Array('webkit-', 'moz-', 'o-', 'ms-', ''), function (index, prefix) {
				self.$ele[0].style[prefix + 'AnimationIterationCount'] = 1;
			});

			$(this.settings.element).append(this.$ele);

			if (this.settings.newest_on_top === true) {
				offsetAmt = (parseInt(offsetAmt) + parseInt(this.settings.spacing)) + this.$ele.outerHeight();
				this.reposition(offsetAmt);
			}

			if ($.isFunction(self.settings.onShow)) {
				self.settings.onShow.call(this.$ele);
			}

			this.$ele.one(this.animations.start, function () {
				hasAnimation = true;
			}).one(this.animations.end, function () {
				if ($.isFunction(self.settings.onShown)) {
					self.settings.onShown.call(this);
				}
			});

			setTimeout(function () {
				if (!hasAnimation) {
					if ($.isFunction(self.settings.onShown)) {
						self.settings.onShown.call(this);
					}
				}
			}, 600);
		},
		bind: function () {
			var self = this;

			this.$ele.find('[gonrin-notify="dismiss"]').on('click', function () {
				self.close();
			});

			this.$ele.mouseover(function () {
				$(this).data('data-hover', "true");
			}).mouseout(function () {
				$(this).data('data-hover', "false");
			});
			this.$ele.data('data-hover', "false");

			if (this.settings.delay > 0) {
				self.$ele.data('notify-delay', self.settings.delay);
				var timer = setInterval(function () {
					var delay = parseInt(self.$ele.data('notify-delay')) - self.settings.timer;
					if ((self.$ele.data('data-hover') === 'false' && self.settings.mouse_over === "pause") || self.settings.mouse_over != "pause") {
						var percent = ((self.settings.delay - delay) / self.settings.delay) * 100;
						self.$ele.data('notify-delay', delay);
						self.$ele.find('[gonrin-notify="progressbar"] > div').attr('aria-valuenow', percent).css('width', percent + '%');
					}
					if (delay <= -(self.settings.timer)) {
						clearInterval(timer);
						self.close();
					}
				}, self.settings.timer);
			}
		},
		close: function () {
			var self = this,
				posX = parseInt(this.$ele.css(this.settings.placement.from)),
				hasAnimation = false;

			this.$ele.attr('data-closing', 'true').addClass(this.settings.animate.exit);
			self.reposition(posX);

			if ($.isFunction(self.settings.onClose)) {
				self.settings.onClose.call(this.$ele);
			}

			this.$ele.one(this.animations.start, function () {
				hasAnimation = true;
			}).one(this.animations.end, function () {
				$(this).remove();
				if ($.isFunction(self.settings.onClosed)) {
					self.settings.onClosed.call(this);
				}
			});

			setTimeout(function () {
				if (!hasAnimation) {
					self.$ele.remove();
					if (self.settings.onClosed) {
						self.settings.onClosed(self.$ele);
					}
				}
			}, 600);
		},
		reposition: function (posX) {
			var self = this,
				notifies = '[gonrin-notify-position="' + this.settings.placement.from + '-' + this.settings.placement.align + '"]:not([data-closing="true"])',
				$elements = this.$ele.nextAll(notifies);
			if (this.settings.newest_on_top === true) {
				$elements = this.$ele.prevAll(notifies);
			}
			$elements.each(function () {
				$(this).css(self.settings.placement.from, posX);
				posX = (parseInt(posX) + parseInt(self.settings.spacing)) + $(this).outerHeight();
			});
		}
	});

	$.notify = function (content, options) {
		var plugin = new Notify(this, content, options);
		return plugin.notify;
	};
	$.notifyDefaults = function (options) {
		defaults = $.extend(true, {}, defaults, options);
		return defaults;
	};
	$.notifyClose = function (command) {
		if (typeof command === "undefined" || command === "all") {
			$('[gonrin-notify]').find('[gonrin-notify="dismiss"]').trigger('click');
		} else {
			$('[gonrin-notify-position="' + command + '"]').find('[gonrin-notify="dismiss"]').trigger('click');
		}
	};

}));
<commit_msg>change z-index for nofify<commit_after>/*
* Project: Gorin Notify
* Description: Turns standard Bootstrap alerts into "Growl-like" notifications.
* License: MIT License
* Website: https://gonrin.com/ui/
*/

/* global define:false, require: false, jQuery:false */

(function (factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD. Register as an anonymous module.
		define(['jquery'], factory);
	} else if (typeof exports === 'object') {
		// Node/CommonJS
		factory(require('jquery'));
	} else {
		// Browser globals
		factory(jQuery);
	}
}(function ($) {
	// Create the defaults once
	var defaults = {
		element: 'body',
		position: null,
		type: "info",
		allow_dismiss: true,
		allow_duplicates: true,
		newest_on_top: false,
		showProgressbar: false,
		placement: {
			from: "top",
			align: "right"
		},
		offset: 50,
		spacing: 10,
		z_index: 1131,
		delay: 3000,
		timer: 1000,
		url_target: '_blank',
		mouse_over: null,
		animate: {
			enter: 'animated fadeInDown',
			exit: 'animated fadeOutUp'
		},
		onShow: null,
		onShown: null,
		onClose: null,
		onClosed: null,
		icon_type: 'class',
		template: '
<button type="button" aria-hidden="true" class="close" gonrin-notify="dismiss">×</button> {1} {2}

'
	};

	String.format = function () {
		var str = arguments[0];
		for (var i = 1; i < arguments.length; i++) {
			str = str.replace(RegExp("\\{" + (i - 1) + "\\}", "gm"), arguments[i]);
		}
		return str;
	};

	function isDuplicateNotification(notification) {
		var isDupe = false;

		$('[gonrin-notify="container"]').each(function (i, el) {
			var $el = $(el);
			var title = $el.find('[gonrin-notify="title"]').text().trim();
			var message = $el.find('[gonrin-notify="message"]').html().trim();

			// The input string might be different than the actual parsed HTML string!
			// (
 vs
 for example)
			// So we have to force-parse this as HTML here!
			var isSameTitle = title === $("
" + notification.settings.content.title + "
").html().trim();
			var isSameMsg = message === $("
" + notification.settings.content.message + "
").html().trim();
			var isSameType = $el.hasClass('alert-' + notification.settings.type);

			if (isSameTitle && isSameMsg && isSameType) {
				//we found the dupe. Set the var and stop checking.
				isDupe = true;
			}
			return !isDupe;
		});

		return isDupe;
	}

	function Notify(element, content, options) {
		// Setup Content of Notify
		var contentObj = {
			content: {
				message: typeof content === 'object' ? content.message : content,
				title: content.title ? content.title : '',
				icon: content.icon ? content.icon : '',
				url: content.url ? content.url : '#',
				target: content.target ? content.target : '-'
			}
		};

		options = $.extend(true, {}, contentObj, options);
		this.settings = $.extend(true, {}, defaults, options);
		this._defaults = defaults;
		if (this.settings.content.target === "-") {
			this.settings.content.target = this.settings.url_target;
		}
		this.animations = {
			start: 'webkitAnimationStart oanimationstart MSAnimationStart animationstart',
			end: 'webkitAnimationEnd oanimationend MSAnimationEnd animationend'
		};

		if (typeof this.settings.offset === 'number') {
			this.settings.offset = {
				x: this.settings.offset,
				y: this.settings.offset
			};
		}

		//if duplicate messages are not allowed, then only continue if this new message is not a duplicate of one that it already showing
		if (this.settings.allow_duplicates || (!this.settings.allow_duplicates && !isDuplicateNotification(this))) {
			this.init();
		}
	}

	$.extend(Notify.prototype, {
		init: function () {
			var self = this;

			this.buildNotify();
			if (this.settings.content.icon) {
				this.setIcon();
			}
			if (this.settings.content.url != "#") {
				this.styleURL();
			}
			this.styleDismiss();
			this.placement();
			this.bind();

			this.notify = {
				$ele: this.$ele,
				update: function (command, update) {
					var commands = {};
					if (typeof command === "string") {
						commands[command] = update;
					} else {
						commands = command;
					}
					for (var cmd in commands) {
						switch (cmd) {
							case "type":
								this.$ele.removeClass('alert-' + self.settings.type);
								this.$ele.find('[gonrin-notify="progressbar"] > .progress-bar').removeClass('progress-bar-' + self.settings.type);
								self.settings.type = commands[cmd];
								this.$ele.addClass('alert-' + commands[cmd]).find('[gonrin-notify="progressbar"] > .progress-bar').addClass('progress-bar-' + commands[cmd]);
								break;
							case "icon":
								var $icon = this.$ele.find('[gonrin-notify="icon"]');
								if (self.settings.icon_type.toLowerCase() === 'class') {
									$icon.removeClass(self.settings.content.icon).addClass(commands[cmd]);
								} else {
									if (!$icon.is('img')) {
										$icon.find('img');
									}
									$icon.attr('src', commands[cmd]);
								}
								break;
							case "progress":
								var newDelay = self.settings.delay - (self.settings.delay * (commands[cmd] / 100));
								this.$ele.data('notify-delay', newDelay);
								this.$ele.find('[gonrin-notify="progressbar"] > div').attr('aria-valuenow', commands[cmd]).css('width', commands[cmd] + '%');
								break;
							case "url":
								this.$ele.find('[gonrin-notify="url"]').attr('href', commands[cmd]);
								break;
							case "target":
								this.$ele.find('[gonrin-notify="url"]').attr('target', commands[cmd]);
								break;
							default:
								this.$ele.find('[gonrin-notify="' + cmd + '"]').html(commands[cmd]);
						}
					}
					var posX = this.$ele.outerHeight() + parseInt(self.settings.spacing) + parseInt(self.settings.offset.y);
					self.reposition(posX);
				},
				close: function () {
					self.close();
				}
			};

		},
		buildNotify: function () {
			var content = this.settings.content;
			this.$ele = $(String.format(this.settings.template, this.settings.type, content.title, content.message, content.url, content.target));
			this.$ele.attr('gonrin-notify-position', this.settings.placement.from + '-' + this.settings.placement.align);
			if (!this.settings.allow_dismiss) {
				this.$ele.find('[gonrin-notify="dismiss"]').css('display', 'none');
			}
			if ((this.settings.delay <= 0 && !this.settings.showProgressbar) || !this.settings.showProgressbar) {
				this.$ele.find('[gonrin-notify="progressbar"]').remove();
			}
		},
		setIcon: function () {
			if (this.settings.icon_type.toLowerCase() === 'class') {
				this.$ele.find('[gonrin-notify="icon"]').addClass(this.settings.content.icon);
			} else {
				if (this.$ele.find('[gonrin-notify="icon"]').is('img')) {
					this.$ele.find('[gonrin-notify="icon"]').attr('src', this.settings.content.icon);
				} else {
					this.$ele.find('[gonrin-notify="icon"]').append('');
				}
			}
		},
		styleDismiss: function () {
			this.$ele.find('[gonrin-notify="dismiss"]').css({
				position: 'absolute',
				right: '10px',
				top: '5px',
				zIndex: this.settings.z_index + 2
			});
		},
		styleURL: function () {
			this.$ele.find('[gonrin-notify="url"]').css({
				backgroundImage: 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)',
				height: '100%',
				left: 0,
				position: 'absolute',
				top: 0,
				width: '100%',
				zIndex: this.settings.z_index + 1
			});
		},
		placement: function () {
			var self = this,
				offsetAmt = this.settings.offset.y,
				css = {
					display: 'inline-block',
					margin: '0px auto',
					position: this.settings.position ? this.settings.position : (this.settings.element === 'body' ? 'fixed' : 'absolute'),
					transition: 'all .5s ease-in-out',
					zIndex: this.settings.z_index
				},
				hasAnimation = false,
				settings = this.settings;

			$('[gonrin-notify-position="' + this.settings.placement.from + '-' + this.settings.placement.align + '"]:not([data-closing="true"])').each(function () {
				offsetAmt = Math.max(offsetAmt, parseInt($(this).css(settings.placement.from)) + parseInt($(this).outerHeight()) + parseInt(settings.spacing));
			});
			if (this.settings.newest_on_top === true) {
				offsetAmt = this.settings.offset.y;
			}
			css[this.settings.placement.from] = offsetAmt + 'px';

			switch (this.settings.placement.align) {
				case "left":
				case "right":
					css[this.settings.placement.align] = this.settings.offset.x + 'px';
					break;
				case "center":
					css.left = 0;
					css.right = 0;
					break;
			}
			this.$ele.css(css).addClass(this.settings.animate.enter);
			$.each(Array('webkit-', 'moz-', 'o-', 'ms-', ''), function (index, prefix) {
				self.$ele[0].style[prefix + 'AnimationIterationCount'] = 1;
			});

			$(this.settings.element).append(this.$ele);

			if (this.settings.newest_on_top === true) {
				offsetAmt = (parseInt(offsetAmt) + parseInt(this.settings.spacing)) + this.$ele.outerHeight();
				this.reposition(offsetAmt);
			}

			if ($.isFunction(self.settings.onShow)) {
				self.settings.onShow.call(this.$ele);
			}

			this.$ele.one(this.animations.start, function () {
				hasAnimation = true;
			}).one(this.animations.end, function () {
				if ($.isFunction(self.settings.onShown)) {
					self.settings.onShown.call(this);
				}
			});

			setTimeout(function () {
				if (!hasAnimation) {
					if ($.isFunction(self.settings.onShown)) {
						self.settings.onShown.call(this);
					}
				}
			}, 600);
		},
		bind: function () {
			var self = this;

			this.$ele.find('[gonrin-notify="dismiss"]').on('click', function () {
				self.close();
			});

			this.$ele.mouseover(function () {
				$(this).data('data-hover', "true");
			}).mouseout(function () {
				$(this).data('data-hover', "false");
			});
			this.$ele.data('data-hover', "false");

			if (this.settings.delay > 0) {
				self.$ele.data('notify-delay', self.settings.delay);
				var timer = setInterval(function () {
					var delay = parseInt(self.$ele.data('notify-delay')) - self.settings.timer;
					if ((self.$ele.data('data-hover') === 'false' && self.settings.mouse_over === "pause") || self.settings.mouse_over != "pause") {
						var percent = ((self.settings.delay - delay) / self.settings.delay) * 100;
						self.$ele.data('notify-delay', delay);
						self.$ele.find('[gonrin-notify="progressbar"] > div').attr('aria-valuenow', percent).css('width', percent + '%');
					}
					if (delay <= -(self.settings.timer)) {
						clearInterval(timer);
						self.close();
					}
				}, self.settings.timer);
			}
		},
		close: function () {
			var self = this,
				posX = parseInt(this.$ele.css(this.settings.placement.from)),
				hasAnimation = false;

			this.$ele.attr('data-closing', 'true').addClass(this.settings.animate.exit);
			self.reposition(posX);

			if ($.isFunction(self.settings.onClose)) {
				self.settings.onClose.call(this.$ele);
			}

			this.$ele.one(this.animations.start, function () {
				hasAnimation = true;
			}).one(this.animations.end, function () {
				$(this).remove();
				if ($.isFunction(self.settings.onClosed)) {
					self.settings.onClosed.call(this);
				}
			});

			setTimeout(function () {
				if (!hasAnimation) {
					self.$ele.remove();
					if (self.settings.onClosed) {
						self.settings.onClosed(self.$ele);
					}
				}
			}, 600);
		},
		reposition: function (posX) {
			var self = this,
				notifies = '[gonrin-notify-position="' + this.settings.placement.from + '-' + this.settings.placement.align + '"]:not([data-closing="true"])',
				$elements = this.$ele.nextAll(notifies);
			if (this.settings.newest_on_top === true) {
				$elements = this.$ele.prevAll(notifies);
			}
			$elements.each(function () {
				$(this).css(self.settings.placement.from, posX);
				posX = (parseInt(posX) + parseInt(self.settings.spacing)) + $(this).outerHeight();
			});
		}
	});

	$.notify = function (content, options) {
		var plugin = new Notify(this, content, options);
		return plugin.notify;
	};
	$.notifyDefaults = function (options) {
		defaults = $.extend(true, {}, defaults, options);
		return defaults;
	};
	$.notifyClose = function (command) {
		if (typeof command === "undefined" || command === "all") {
			$('[gonrin-notify]').find('[gonrin-notify="dismiss"]').trigger('click');
		} else {
			$('[gonrin-notify-position="' + command + '"]').find('[gonrin-notify="dismiss"]').trigger('click');
		}
	};

}));
<|endoftext|>


<commit_before>angular
	.module('scraper', [ 'ui.router', 'angularFileUpload', 'ngSanitize', 'ngCsv'])

	.config(function($stateProvider, $urlRouterProvider) {

		// $urlRouterProvider.when('', 'home');
		$urlRouterProvider.otherwise('/home')

	  	$stateProvider
		    .state('index', {
		      url: "/home",
      		  templateUrl: "./assets/landing.html"
		    })
		    .state('tnt', {
		      url: "/tnt",
		      templateUrl: './assets/radio.html',
		      abstract: true
		    })
		    .state('tnt.view', {
		    	url: '/other',
				views: {
					'tnt': {
						templateUrl: './assets/tnt.html',
						controller: 'tnt',
						controllerAs: 'tnt'
					},
					'tntlast': {
						templateUrl: './assets/tntlast.html',
						controller: 'tntlast',
						controllerAs: 'tntlast'
					}
				}
		    })
		    .state('startrack', {
		      url: "/startrack",
      		  templateUrl: "./assets/startrack.html",
      		  controller: "startrack",
      		  controllerAs: "startrack"
		    })
	})

	.factory('Add', function ($http, $location, $rootScope) {
		return {

			ship: function shipFile(data) {
				console.log('DATA COMING IN');
				console.log(data);
				return $http.post('/api/load', data).success(function (data) {
					console.log('DATA FIRED OUT');
					console.log(data);
				}).error(function (err) {
					console.info('error', err)
				});
			},
			exportExcel: function () {
				$http({method: 'GET', url: "/api/export",
				headers: {'Content-Type': "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
		        responseType: "arraybuffer"}).
		        success(function(data, status, headers, config) {
		            saveAs(new Blob([data],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}), "excel111.xlsx");
		        }).error(function(data, status, headers, config) {

				});
			}

		};
	})

<commit_msg>route<commit_after>angular
	.module('scraper', [ 'ui.router', 'angularFileUpload', 'ngSanitize', 'ngCsv'])

	.config(function($stateProvider, $urlRouterProvider) {

		$urlRouterProvider.when('', '/home');
		$urlRouterProvider.otherwise('/home')

	  	$stateProvider
		    .state('index', {
		      url: "/home",
      		  templateUrl: "./assets/landing.html"
		    })
		    .state('tnt', {
		      url: "/tnt",
		      templateUrl: './assets/radio.html',
		      abstract: true
		    })
		    .state('tnt.view', {
		    	url: '/other',
				views: {
					'tnt': {
						templateUrl: './assets/tnt.html',
						controller: 'tnt',
						controllerAs: 'tnt'
					},
					'tntlast': {
						templateUrl: './assets/tntlast.html',
						controller: 'tntlast',
						controllerAs: 'tntlast'
					}
				}
		    })
		    .state('startrack', {
		      url: "/startrack",
      		  templateUrl: "./assets/startrack.html",
      		  controller: "startrack",
      		  controllerAs: "startrack"
		    })
	})

	.factory('Add', function ($http, $location, $rootScope) {
		return {

			ship: function shipFile(data) {
				console.log('DATA COMING IN');
				console.log(data);
				return $http.post('/api/load', data).success(function (data) {
					console.log('DATA FIRED OUT');
					console.log(data);
				}).error(function (err) {
					console.info('error', err)
				});
			},
			exportExcel: function () {
				$http({method: 'GET', url: "/api/export",
				headers: {'Content-Type': "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
		        responseType: "arraybuffer"}).
		        success(function(data, status, headers, config) {
		            saveAs(new Blob([data],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}), "excel111.xlsx");
		        }).error(function(data, status, headers, config) {

				});
			}

		};
	})

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016  Jones Magloire @Joxit
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
var registryUI = {}
registryUI.url = function() {
  return registryUI.getRegistryServer(0);
}
registryUI.getRegistryServer = function(i) {
  try {
    var res = JSON.parse(localStorage.getItem('registryServer'));
    if (res instanceof Array) {
      return (!isNaN(i)) ? res[i] : res.map(function(url) {
        return url.trim().replace(/\/*$/, '');
      });
    }
  } catch (e) {}
  return (!isNaN(i)) ? '' : [];
}
registryUI.addServer = function(url) {
  var registryServer = registryUI.getRegistryServer();
  url = url.trim().replace(/\/*$/, '');
  var index = registryServer.indexOf(url);
  if (index != -1) {
    return;
  }
  registryServer.push(url);
  localStorage.setItem('registryServer', JSON.stringify(registryServer));
}
registryUI.changeServer = function(url) {
  var registryServer = registryUI.getRegistryServer();
  url = url.trim().replace(/\/*$/, '');
  var index = registryServer.indexOf(url);
  if (index == -1) {
    return;
  }
  registryServer.splice(index, 1);
  registryServer = [url].concat(registryServer);
  localStorage.setItem('registryServer', JSON.stringify(registryServer));
}
registryUI.removeServer = function(url) {
  var registryServer = registryUI.getRegistryServer();
  url = url.trim().replace(/\/*$/, '');
  var index = registryServer.indexOf(url);
  if (index == -1) {
    return;
  }
  registryServer.splice(index, 1);
  localStorage.setItem('registryServer', JSON.stringify(registryServer));
}
registryUI.isImageRemoveActivated = true;
registryUI.catalog = {};
registryUI.taglist = {};

riot.mount('add');
riot.mount('change');
riot.mount('remove');
riot.mount('menu');
riot.mount('app');
<commit_msg>[query-param] Add url query param for sharing<commit_after>/*
 * Copyright (C) 2016  Jones Magloire @Joxit
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
var registryUI = {}
registryUI.URL_QUERY_PARAM_REGEX = /[&?]url=/;
registryUI.URL_PARAM_REGEX = /^url=/;

registryUI.url = function() {
  if (!registryUI._url) {
    var url = registryUI.getUrlQueryParam();
    if (url) {
      try {
        registryUI._url = registryUI.decodeURI(url);
        return registryUI._url;
      } catch (e) {
        console.log(e);
      }
    }
    registryUI._url = registryUI.getRegistryServer(0);
  }
  return registryUI._url;
}
registryUI.getRegistryServer = function(i) {
  try {
    var res = JSON.parse(localStorage.getItem('registryServer'));
    if (res instanceof Array) {
      return (!isNaN(i)) ? res[i] : res.map(function(url) {
        return url.trim().replace(/\/*$/, '');
      });
    }
  } catch (e) {}
  return (!isNaN(i)) ? '' : [];
}
registryUI.addServer = function(url) {
  var registryServer = registryUI.getRegistryServer();
  url = url.trim().replace(/\/*$/, '');
  var index = registryServer.indexOf(url);
  if (index != -1) {
    return;
  }
  registryServer.push(url);
  if (!registryUI._url) {
    registryUI.updateHistory(url);
  }
  localStorage.setItem('registryServer', JSON.stringify(registryServer));
}
registryUI.changeServer = function(url) {
  var registryServer = registryUI.getRegistryServer();
  url = url.trim().replace(/\/*$/, '');
  var index = registryServer.indexOf(url);
  if (index == -1) {
    return;
  }
  registryServer.splice(index, 1);
  registryServer = [url].concat(registryServer);
  registryUI.updateHistory(url);
  localStorage.setItem('registryServer', JSON.stringify(registryServer));
}
registryUI.removeServer = function(url) {
  var registryServer = registryUI.getRegistryServer();
  url = url.trim().replace(/\/*$/, '');
  var index = registryServer.indexOf(url);
  if (index == -1) {
    return;
  }
  registryServer.splice(index, 1);
  localStorage.setItem('registryServer', JSON.stringify(registryServer));
}

registryUI.updateHistory = function(url) {
  history.pushState(null, '', '?url=' + registryUI.encodeURI(url) + window.location.hash);
  registryUI._url = url;
}

registryUI.getUrlQueryParam = function () {
  var search = window.location.search;
  if (registryUI.URL_QUERY_PARAM_REGEX.test(search)) {
    var param = search.split(/^\?|&/).find(function(param) {
      return param && registryUI.URL_PARAM_REGEX.test(param);
    });
    return param ? param.replace(registryUI.URL_PARAM_REGEX, '') : param;
  }
};

registryUI.encodeURI = function(url) {
  return url.indexOf('&') < 0 ? window.encodeURI(url) : btoa(url);
};

registryUI.decodeURI = function(url) {
  return url.startsWith('http') ? window.decodeURI(url) : atob(url);
};

registryUI.isImageRemoveActivated = true;
registryUI.catalog = {};
registryUI.taglist = {};

riot.mount('add');
riot.mount('change');
riot.mount('remove');
riot.mount('menu');
riot.mount('app');
<|endoftext|>


<commit_before>/*
 * This file is part of the Sonatra package.
 *
 * (c) François Pluchino <francois.pluchino@sonatra.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

+function ($) {
    'use strict';

    // HAMMER SCROLL CLASS DEFINITION
    // ==============================

    var HammerScroll = function (element, options) {
        this.guid        = jQuery.guid;
        this.options     = $.extend({}, HammerScroll.DEFAULTS, options);
        this.$element    = $(element);
        this.$content    = wrapContent.apply(this);

        if (null != this.$element.css('right')) {
            this.$element.css('right', 0);
        }

        this.$element.css('overflow-y', 'hidden');
        this.$element.on('DOMMouseScroll mousewheel', $.proxy(onMouseScroll, this));

        if (!this.options.eventDelegated) {
            this.hammer = new Hammer(this.$element.get(0), {
                tap: false,
                transform: false,
                release: false,
                hold: false,
                swipe: false,
                drag_block_vertical: true,
                drag_lock_to_axis: true,
                drag_min_distance: 3
            })

            .on('drag', $.proxy(this.onDrag, this))
            .on('dragend', $.proxy(this.onDragEnd, this));
        }
    };

    HammerScroll.DEFAULTS = {
        contentWrapperClass: 'hammer-scroll-content',
        maxBounce:          100,
        eventDelegated:      false
    };

    /**
     * On drag action.
     *
     * @param Event event The hammer event
     */
    HammerScroll.prototype.onDrag = function (event) {
        if (undefined == this.dragStartPosition) {
            this.dragStartPosition = -this.$element.scrollTop();
        }

        if ('up' == event.gesture.direction || 'down' == event.gesture.direction) {
            var wrapperHeight = this.$element.innerHeight();
            var height = this.$content.outerHeight();
            var vertical = -Math.round(event.gesture.deltaY + this.dragStartPosition);
            this.$element.scrollTop(vertical);
            var scrollTop = this.$element.scrollTop();

            if (scrollTop == 0 && vertical < 0) {
                delete this.dragBottomPosition;

                if (vertical < -this.options.maxBounce) {
                    vertical = -this.options.maxBounce;
                }

            } else if ((height - scrollTop) == wrapperHeight && vertical > 0) {
                if (undefined == this.dragBottomPosition) {
                    this.dragBottomPosition = vertical;

                } else {
                    vertical = -this.dragBottomPosition + vertical;
                }

                if (vertical > this.options.maxBounce) {
                    vertical = this.options.maxBounce;
                }

            } else if (height < wrapperHeight) {
                delete this.dragBottomPosition;

                if (vertical > this.options.maxBounce) {
                    vertical = this.options.maxBounce;
                }

            } else {
                delete this.dragBottomPosition;
                vertical = 0;
            }

            this.$content.css('-webkit-transition', 'none');
            this.$content.css('transition', 'none');
            this.$content.css('-webkit-transform', 'translate3d(0px, ' + -vertical +'px, 0px)');
            this.$content.css('transform', 'translate3d(0px, ' + -vertical +'px, 0px)');
        }
    };

    /**
     * On drag end action.
     *
     * @param Event event The hammer event
     */
    HammerScroll.prototype.onDragEnd = function (event) {
        this.$content.css('-webkit-transition', '');
        this.$content.css('transition', '');
        this.$content.css('-webkit-transform', '');
        this.$content.css('transform', '');

        delete this.dragStartPosition;
        delete this.dragBottomPosition;
        this.$content.removeClass('hammer-scroll-content-on-drag');
    };

    HammerScroll.prototype.destroy = function () {
        this.$content = unwrapContent.apply(this);
        this.$element.css('overflow-y', '');
        this.$element.off('DOMMouseScroll mousewheel', $.proxy(onMouseScroll, this));

        if (!this.options.eventDelegated) {
            this.hammer.dispose();
        }
    };

    function wrapContent () {
        var $content = $([
            '

'
        ].join(''));

        this.$element.children().each(function () {
            $content.append(this);
        });

        this.$element.append($content);

        return $content;
    }

    function unwrapContent () {
        var self = this;

        this.$content.children().each(function () {
            self.$element.append(this);
        });
        this.$content.remove();

        return null;
    }

    function onMouseScroll (event) {
        var delta = (event.originalEvent.type == 'DOMMouseScroll' ?
                event.originalEvent.detail * -40 :
                event.originalEvent.wheelDelta);

        event.stopPropagation();
        event.preventDefault();
        this.$element.scrollTop(this.$element.scrollTop() - delta);
    }

    // HAMMER SCROLL PLUGIN DEFINITION
    // ===============================

    var old = $.fn.hammerScroll;

    $.fn.hammerScroll = function (option, _relatedTarget) {
        return this.each(function () {
            var $this   = $(this);
            var data    = $this.data('st.hammerscroll');
            var options = typeof option == 'object' && option;

            if (!data && option == 'destroy') {
                return;
            }

            if (!data) {
                $this.data('st.hammerscroll', (data = new HammerScroll(this, options)));
            }

            if (typeof option == 'string') {
                data[option]();
            }
        });
    };

    $.fn.hammerScroll.Constructor = HammerScroll;

    // HAMMER SCROLL NO CONFLICT
    // =========================

    $.fn.hammerScroll.noConflict = function () {
        $.fn.hammerScroll = old;

        return this;
    };

    // HAMMER SCROLL DATA-API
    // ======================

    $(window).on('load', function () {
        $('[data-hammer-scroll="true"]').each(function () {
            var $this = $(this);
            $this.hammerScroll($this.data());
        });
    });

}(jQuery);
<commit_msg>Removes unused css class<commit_after>/*
 * This file is part of the Sonatra package.
 *
 * (c) François Pluchino <francois.pluchino@sonatra.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

+function ($) {
    'use strict';

    // HAMMER SCROLL CLASS DEFINITION
    // ==============================

    var HammerScroll = function (element, options) {
        this.guid        = jQuery.guid;
        this.options     = $.extend({}, HammerScroll.DEFAULTS, options);
        this.$element    = $(element);
        this.$content    = wrapContent.apply(this);

        if (null != this.$element.css('right')) {
            this.$element.css('right', 0);
        }

        this.$element.css('overflow-y', 'hidden');
        this.$element.on('DOMMouseScroll mousewheel', $.proxy(onMouseScroll, this));

        if (!this.options.eventDelegated) {
            this.hammer = new Hammer(this.$element.get(0), {
                tap: false,
                transform: false,
                release: false,
                hold: false,
                swipe: false,
                drag_block_vertical: true,
                drag_lock_to_axis: true,
                drag_min_distance: 3
            })

            .on('drag', $.proxy(this.onDrag, this))
            .on('dragend', $.proxy(this.onDragEnd, this));
        }
    };

    HammerScroll.DEFAULTS = {
        contentWrapperClass: 'hammer-scroll-content',
        maxBounce:          100,
        eventDelegated:      false
    };

    /**
     * On drag action.
     *
     * @param Event event The hammer event
     */
    HammerScroll.prototype.onDrag = function (event) {
        if (undefined == this.dragStartPosition) {
            this.dragStartPosition = -this.$element.scrollTop();
        }

        if ('up' == event.gesture.direction || 'down' == event.gesture.direction) {
            var wrapperHeight = this.$element.innerHeight();
            var height = this.$content.outerHeight();
            var vertical = -Math.round(event.gesture.deltaY + this.dragStartPosition);
            this.$element.scrollTop(vertical);
            var scrollTop = this.$element.scrollTop();

            if (scrollTop == 0 && vertical < 0) {
                delete this.dragBottomPosition;

                if (vertical < -this.options.maxBounce) {
                    vertical = -this.options.maxBounce;
                }

            } else if ((height - scrollTop) == wrapperHeight && vertical > 0) {
                if (undefined == this.dragBottomPosition) {
                    this.dragBottomPosition = vertical;

                } else {
                    vertical = -this.dragBottomPosition + vertical;
                }

                if (vertical > this.options.maxBounce) {
                    vertical = this.options.maxBounce;
                }

            } else if (height < wrapperHeight) {
                delete this.dragBottomPosition;

                if (vertical > this.options.maxBounce) {
                    vertical = this.options.maxBounce;
                }

            } else {
                delete this.dragBottomPosition;
                vertical = 0;
            }

            this.$content.css('-webkit-transition', 'none');
            this.$content.css('transition', 'none');
            this.$content.css('-webkit-transform', 'translate3d(0px, ' + -vertical +'px, 0px)');
            this.$content.css('transform', 'translate3d(0px, ' + -vertical +'px, 0px)');
        }
    };

    /**
     * On drag end action.
     *
     * @param Event event The hammer event
     */
    HammerScroll.prototype.onDragEnd = function (event) {
        this.$content.css('-webkit-transition', '');
        this.$content.css('transition', '');
        this.$content.css('-webkit-transform', '');
        this.$content.css('transform', '');

        delete this.dragStartPosition;
        delete this.dragBottomPosition;
    };

    HammerScroll.prototype.destroy = function () {
        this.$content = unwrapContent.apply(this);
        this.$element.css('overflow-y', '');
        this.$element.off('DOMMouseScroll mousewheel', $.proxy(onMouseScroll, this));

        if (!this.options.eventDelegated) {
            this.hammer.dispose();
        }
    };

    function wrapContent () {
        var $content = $([
            '

'
        ].join(''));

        this.$element.children().each(function () {
            $content.append(this);
        });

        this.$element.append($content);

        return $content;
    }

    function unwrapContent () {
        var self = this;

        this.$content.children().each(function () {
            self.$element.append(this);
        });
        this.$content.remove();

        return null;
    }

    function onMouseScroll (event) {
        var delta = (event.originalEvent.type == 'DOMMouseScroll' ?
                event.originalEvent.detail * -40 :
                event.originalEvent.wheelDelta);

        event.stopPropagation();
        event.preventDefault();
        this.$element.scrollTop(this.$element.scrollTop() - delta);
    }

    // HAMMER SCROLL PLUGIN DEFINITION
    // ===============================

    var old = $.fn.hammerScroll;

    $.fn.hammerScroll = function (option, _relatedTarget) {
        return this.each(function () {
            var $this   = $(this);
            var data    = $this.data('st.hammerscroll');
            var options = typeof option == 'object' && option;

            if (!data && option == 'destroy') {
                return;
            }

            if (!data) {
                $this.data('st.hammerscroll', (data = new HammerScroll(this, options)));
            }

            if (typeof option == 'string') {
                data[option]();
            }
        });
    };

    $.fn.hammerScroll.Constructor = HammerScroll;

    // HAMMER SCROLL NO CONFLICT
    // =========================

    $.fn.hammerScroll.noConflict = function () {
        $.fn.hammerScroll = old;

        return this;
    };

    // HAMMER SCROLL DATA-API
    // ======================

    $(window).on('load', function () {
        $('[data-hammer-scroll="true"]').each(function () {
            var $this = $(this);
            $this.hammerScroll($this.data());
        });
    });

}(jQuery);
<|endoftext|>


<commit_before>define(['./counter', './template', './storage'], function (counter, template, storage) {
    // Task constructor
    var Task = function (description, status) {
            this.description = description;
            this.isComplete = status || false;
        },
        allTasks = [];

    function removeTask (item, element) {
        var temp = allTasks.indexOf(item);

        if (temp > -1) {
            // If item is on list remove it
            allTasks.splice(temp, 1);
        }
        // Remove item from DOM
        element.parentNode.removeChild(element);
        // Update counter
        counter.update();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function addDeleteHandler (item, element) {
        element.querySelector('.destroy').addEventListener('click', function () {
            removeTask(item, element);
        });
    }
    function changeStatus (item, element, isClicked) {
        // Toggle class 'completed' on task
        element.classList.toggle('completed');
        if (!isClicked) {
            element.querySelector('.toggle').checked = !element.querySelector('.toggle').checked;
        }
        // change Status of element on Array
        item.isComplete = !item.isComplete;
        // update counter
        counter.update();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function addSwitch (item, element) {
        element.querySelector('.toggle').addEventListener('click', function () {
            changeStatus(item, element, true);
        });
    }
    function editContent (item, element, event) {
        // Set description to the input value
        item.description = event.target.value = event.target.value.trim();
        // Set description in DOM
        element.querySelector('label').innerText = item.description;
        // Remove editing class
        element.classList.remove('editing');
        // Update localSorage
        storage.saveData(allTasks);
    }
    function editTask (item, element) {
        var editItem = element.querySelector('.edit');
        element.classList.add('editing');
        // Focus the input
        editItem.focus();
        // Save on /enter
        element.querySelector('.edit').addEventListener('keypress', function (e) {
            if (e.keyCode === 13) {
                editContent(item, element, e);
            }
        });
        editItem.addEventListener('focusout', function (e) {
            editContent(item, element, e);
        });
    }
    function addEditHandler (item, element) {
        element.querySelector('label').addEventListener('dblclick', function () {
            editTask(item, element);
        });
    }
    function addItemHandlers (item, element) {
        addDeleteHandler(item, element);
        addEditHandler(item, element);
        addSwitch(item, element);
    }
    function prepareTask (desc, status) {
        var el;
        // create HTML with template
        template.create(desc);
        // set el as the freshly created element of html with temporary class
        el = document.querySelector('.new-temporary-class');
        // Check status and set to completed if it's completed (in case of loading from localStorage)
        if (status) {
            el.classList.add('completed');
            el.querySelector('.toggle').click();
        }
        // Remove tempporary class
        el.classList.remove('new-temporary-class');
        // Returns new task Element
        return el;
    }
    function addNewTask (description, status) {
        var newTask = new Task(description, status),
            taskElement = prepareTask(description, status);

        // Add to local Array with tasks
        allTasks.push(newTask);
        // Add events
        addItemHandlers(newTask, taskElement);
        // Update counter
        counter.update();
        // Update localSorage
        storage.saveData(allTasks);
    }
    _e('.new-todo').addEventListener('keypress', function (e) {
        if (e.keyCode === 13) {
            addNewTask(e.target.value.trim());
            e.target.value = '';
        }
    });
    if (storage.getData().length > 0) {
        storage.getData().forEach(function (item) {
            addNewTask(item.description, item.isComplete);
        });
    }
    return {
        add: addNewTask,
        remove: removeTask,
        edit: editTask,
        taskList: allTasks,
        change: changeStatus
    };
});
<commit_msg>change element for cached one<commit_after>define(['./counter', './template', './storage'], function (counter, template, storage) {
    // Task constructor
    var Task = function (description, status) {
            this.description = description;
            this.isComplete = status || false;
        },
        allTasks = [];

    function removeTask (item, element) {
        var temp = allTasks.indexOf(item);

        if (temp > -1) {
            // If item is on list remove it
            allTasks.splice(temp, 1);
        }
        // Remove item from DOM
        element.parentNode.removeChild(element);
        // Update counter
        counter.update();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function addDeleteHandler (item, element) {
        element.querySelector('.destroy').addEventListener('click', function () {
            removeTask(item, element);
        });
    }
    function changeStatus (item, element, isClicked) {
        // Toggle class 'completed' on task
        element.classList.toggle('completed');
        if (!isClicked) {
            element.querySelector('.toggle').checked = !element.querySelector('.toggle').checked;
        }
        // change Status of element on Array
        item.isComplete = !item.isComplete;
        // update counter
        counter.update();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function addSwitch (item, element) {
        element.querySelector('.toggle').addEventListener('click', function () {
            changeStatus(item, element, true);
        });
    }
    function editContent (item, element, event) {
        // Set description to the input value
        item.description = event.target.value = event.target.value.trim();
        // Set description in DOM
        element.querySelector('label').innerText = item.description;
        // Remove editing class
        element.classList.remove('editing');
        // Update localSorage
        storage.saveData(allTasks);
    }
    function editTask (item, element) {
        var editItem = element.querySelector('.edit');
        element.classList.add('editing');
        // Focus the input
        editItem.focus();
        // Save on /enter
        editItem.addEventListener('keypress', function (e) {
            if (e.keyCode === 13) {
                editContent(item, element, e);
            }
        });
        editItem.addEventListener('focusout', function (e) {
            editContent(item, element, e);
        });
    }
    function addEditHandler (item, element) {
        element.querySelector('label').addEventListener('dblclick', function () {
            editTask(item, element);
        });
    }
    function addItemHandlers (item, element) {
        addDeleteHandler(item, element);
        addEditHandler(item, element);
        addSwitch(item, element);
    }
    function prepareTask (desc, status) {
        var el;
        // create HTML with template
        template.create(desc);
        // set el as the freshly created element of html with temporary class
        el = document.querySelector('.new-temporary-class');
        // Check status and set to completed if it's completed (in case of loading from localStorage)
        if (status) {
            el.classList.add('completed');
            el.querySelector('.toggle').click();
        }
        // Remove tempporary class
        el.classList.remove('new-temporary-class');
        // Returns new task Element
        return el;
    }
    function addNewTask (description, status) {
        var newTask = new Task(description, status),
            taskElement = prepareTask(description, status);

        // Add to local Array with tasks
        allTasks.push(newTask);
        // Add events
        addItemHandlers(newTask, taskElement);
        // Update counter
        counter.update();
        // Update localSorage
        storage.saveData(allTasks);
    }
    _e('.new-todo').addEventListener('keypress', function (e) {
        if (e.keyCode === 13) {
            addNewTask(e.target.value.trim());
            e.target.value = '';
        }
    });
    if (storage.getData().length > 0) {
        storage.getData().forEach(function (item) {
            addNewTask(item.description, item.isComplete);
        });
    }
    return {
        add: addNewTask,
        remove: removeTask,
        edit: editTask,
        taskList: allTasks,
        change: changeStatus
    };
});
<|endoftext|>