<commit_before>/*
 *
 * Bancha Scaffolding Library
 * Copyright 2011-2014 codeQ e.U.
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @package       Bancha.scaffold
 * @copyright     Copyright 2011-2014 codeQ e.U.
 * @link          http://scaffold.bancha.io
 * @since         Bancha Scaffold v 1.0.0
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 * @author        Roland Schuetz <mail@rolandschuetz.at>
 * @version       Bancha Scaffold v PRECOMPILER_ADD_BANCHA_SCAFFOLD_RELEASE_VERSION
 *
 * For more information go to http://scaffold.bancha.io
 */

/**
 * @singleton
 * @class Bancha.scaffold.form.Config
 * **This is only available inside Ext JS.**
 *
 * This class is a config class for creating scaffoled {@link Ext.form.Panel}s.
 *
 * For more information see {@link Ext.form.Panel}.
 *
 * @author Roland Schuetz <mail@rolandschuetz.at>
 * @docauthor Roland Schuetz <mail@rolandschuetz.at>
 */
Ext.define('Bancha.scaffold.form.Config', {
    uses: [
        'Ext.window.MessageBox'
    ],

    /**
     * Create a new config instance
     */
    constructor: function(config) {
        config = config || {};
        var triggeredFrom = config.triggeredFrom || 'Unknown Origin',
            me = this,
            modelName;

        // if the config is just a model name or model, transform to a config object
        if (Ext.isString(config) || Bancha.scaffold.Util.isModel(config)) {
            config = {
                target: config // use the model as target
            };
        }

        //<debug>
        // check that a model is set
        if(!config.target) {
            Ext.Error.raise({
                plugin: 'Bancha Scaffold',
                msg: [
                    'Bancha Scaffold: If you set a form scaffold config object ',
                    'for '+triggeredFrom+', the target property must be set!'
                ].join('')
            });
        }
        //</debug>

        // check that the configured model is valid
        modelName = config.target;
        modelName = Ext.isString(modelName) ? modelName : Ext.ClassManager.getName(modelName);

        // make sure it's loaded
        Ext.syncRequire(modelName);

        //<debug>
        if (!Bancha.scaffold.Util.isModel(modelName)) {
            Ext.Error.raise({
                plugin: 'Bancha Scaffold',
                msg: [
                    'Bancha Scaffold: If you set a form scaffold config object ',
                    'for '+triggeredFrom+', the target property must be a model ',
                    'name or model class. Instead ' + config.target + ' of type ',
                    (typeof config.target) + ' was set.'
                ].join('')
            });
        }
        //</debug>

        // make sure that the model property is always a model class
        config.target = Bancha.scaffold.Util.getModel(modelName);

        if(Ext.isDefined(config.exclude) && !Ext.isArray(config.exclude)) {
            //<debug>
            Ext.Error.raise({
                plugin: 'Bancha Scaffold',
                model: modelName,
                msg: [
                    'Bancha Scaffold: When scaffolding a ' + triggeredFrom,
                    ' the form scaffold exclude config should be an array ',
                    'of field names to exclude.'
                ].join('')
            });
            //</debug>
            config.exclude = [];
        }

        // apply to the object
        Ext.apply(me, config);
    },

    statics: {
        /**
         * Set a new default for scaffolding forms
         */
        setDefault: function(configName, config) {
            // apply to the class prototype
            this.prototype[configName] = config;
        },
        /**
         * Set some defaults for scaffolding forms
         */
        setDefaults: function(config) {
            // apply to the class prototype
            Ext.apply(this.prototype, config);
        }
    },

    /**
     * @private
     * @cfg {String} triggeredFrom
     * (optional) Used for debugging messages as target
     */
    /**
     * @cfg {Ext.data.Model|String} target
     * The model to use
     */
    /**
     * @private
     * @property {Ext.data.Model} target
     * The model to use
     */
    /**
     * @cfg {String[]}
     * Exclude some model fields from scaffolding
     */
    exclude: [],
    /**
     * @cfg {String[]|false}
     * If this is set to an array, only those fields are displayed.
     *
     * The given order of fields is also applied, so to reorder your fields
     * simply defined something like _fields: ['field2','field1']_
     *
     * Note that the exclude setting are still applied.
     */
    fields: false,
    /**
     * @cfg
     * This config is applied to each scaffolded form field
     */
    fieldDefaults: {},
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.Date
     */
    datefieldDefaults: {},
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.File
     */
    fileuploadfieldDefaults: {
        emptyText: 'Select an file'
    },
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.Text
     */
    textfieldDefaults: {},
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.Number
     */
    numberfieldDefaults: {},
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.Checkbox
     */
    checkboxfieldDefaults: {
        uncheckedValue: false
    },
    /**
     * @cfg
     * The defaults class to create a stores for associated model selects for
     * form scaffolding.
     *
     * See also {@link Bancha.scaffold.Util#getStore}.
     *
     * Default: *"Ext.data.Store"*
     */
    storeDefaultClass: 'Ext.data.Store',
    /**
     * @cfg
     * Defaults for all stores for associated model selects created with
     * this scaffolding.
     *
     * See also {@link Bancha.scaffold.Util#getStore}.
     *
     * Default:
     *
     *     {
     *       autoLoad: true
     *     }
     */
    storeDefaults: {
        autoLoad: true
    },
    /**
     * @cfg
     * True to use only one store per model (singleton),
     * false to create a new store each time a associated
     * model is found and a selects field with a store is
     * build.
     *
     * See also {@link Bancha.scaffold.Util#getStore}.
     *
     * Default: *true*
     */
    oneStorePerModel: true,
    /**
     * @cfg {Function} transformFieldConfig
     * Used to add some custom behaviour.
     *
     * This function can be overwritten by any custom function.
     * @param {Object} fieldConfig the field config to transform
     * @param {String} modelType A standard model field type like 'string'
     * (also supports 'file' for compability with http://banchaproject.org)
     * @return {Object} Returns an Ext.form.field.* configuration object
     */
    transformFieldConfig: function (fieldConfig, modelType) {
        return fieldConfig;
    },
    /**
     * @cfg
     * Editable function to be called when the save button is pressed.
     * To change the default scaffolding behaviour just replace this function.
     *
     * The default scope provides two functions:
     *
     *  - this.getPanel() to get the form panel
     *  - this.getForm() to get the basic form
     */
    onSave: function () {
        var form = this.getForm(),
            msg;
        if (form.isValid()) {
            msg = form.hasUpload() ? 'Uploading files...' : 'Saving data..';
            form.submit({
                waitMsg: msg,
                success: function (form, action) {
                    Ext.MessageBox.alert('Success', action.result.msg || 'Successfully saved data.');
                },
                failure: function (form, action) {
                    Ext.MessageBox.alert('Failed', action.result.msg || 'Could not save data, unknown error.');
                }
            });
        }
    },
    /**
     * @cfg
     * Editable function to be called when the reset button is pressed.
     * To change the default scaffolding behaviour just replace this function.
     *
     * The default scope provides two functions:
     *
     *  - this.getPanel() to get the form panel
     *  - this.getForm() to get the basic form
     */
    onReset: function () {
        this.getForm().reset();
    },
    /**
     * @cfg {String[]|Ext.button.Button[]}
     * If an array of elements, a footer toolbar is rendered.
     *
     * 'reset' and 'save' will be replaced by scaffolded
     * buttons, other elements are treated like default Ext JS items.
     *
     * Inside your own buttons you can set the scope property to
     * 'scaffold-scope-me', this scope provides two functions:
     *  - this.getPanel() to get the form panel
     *  - this.getForm() to get the basic form
     *
     * Default: ['reset','save']
     */
    buttons: ['reset','save'],
    /**
     * @cfg
     * Default save button config, used in buttons.
     * If not defined scope and handler properties will be set by
     * the build function.
     */
    saveButtonConfig: {
        iconCls: 'icon-save',
        text: 'Save',
        formBind: true
    },
    /**
     * @cfg
     * Default reset button config, used in buttons config.
     * If not defined scope and handler properties will be set by
     * the build function.
     */
    resetButtonConfig: {
        iconCls: 'icon-reset',
        text: 'Reset'
    },
    /**
     * @cfg {Function}
     * Build the form api config, used only by buildConfig()
     * just for separation of concern, since this is the only
     * part which deals with proxies
     *
     * For Bancha projects with an CakePHP backend this function will
     * scaffold everything
     *
     * Otherwise it will use the initial config, if provided. If not,
     * it will use the model proxies load method. There is no generic
     * way to guess the submit method, please either modify this function
     * or provide a propery form api config.
     *
     * @param {Ext.data.Model} model the model used for scaffolding
     * @param {Object} initialApi the initial Ext.form.Panel api config
     * @return the final Ext.form.Panel api config
     */
    buildApiConfig: function (model, initialApi) {

        if(Bancha.getModel) {
            // the user is using the full Bancha stack
            // everything can be automatically done
            return Ext.form.Panel.buildBanchaApiConfig(model,initialApi);
        } else{

            if(initialApi) {
                // just use the configured api
                return initialApi;
            }

            //<debug>
            // warn the user that we can just guess part of the api
            if (Ext.global.console && Ext.isFunction(Ext.global.console.warn)) {
                Ext.global.console.warn([
                    'Bancha Scaffold: You have not defined any form api. If you want ',
                    'Bancha to guess it, please define Bancha.scaffold.form.Config.',
                    'buildApiConfig. Bancha Scaffold can only try to get the load ',
                    'function from the model proxy, but not the submit function.'
                ].join(''));
            }
            //</debug>
        }

        // try to find the proxy configuration for load
        var proxy = model.getProxy(),
            load = proxy && proxy.api && proxy.api.read ? proxy.api.read :
                    (proxy && proxy.directFn ? proxy.directFn : undefined);

        return load ? {load: load} : undefined;
    },
    /**
     * @cfg {String|Number|False}
     * Define a record id here to autolaod this record for editing in this form, or choose
     * false to create a new record onSave. You can also overwrite onSave to define your
     * own behavior
     * (Default: false)
     */
    loadRecord: false,
    /**
     * @cfg {Function}
     * The function will be executed before scaffolding as interceptor.
     * @param {Ext.data.Model} model the model used for scaffolding
     * @param {Bancha.scaffold.form.Config} config the scaffold full config for this call
     * @param {Object} initialPanelConfig please ignore, this is a legacy argument, may having some additional Ext.form.Panel configs
     * @return {Object|undefined} object with initial Ext.form.Panel configs
     */
    beforeBuild: function (model, config, initialPanelConfig) {},
    /**
     * @cfg {Function}
     * This function will be executed after acaffolding as interceptor.
     * @param {Object} formConfig the just build form panel config
     * @param {Ext.data.Model} model the model used for scaffolding
     * @param {Bancha.scaffold.form.Config} config the scaffold full config for this call
     * @param {Object} initialPanelConfig please ignore, this is a legacy argument, may having some additional Ext.form.Panel configs
     * @return {Object|undefined} object with final Ext.form.Panel configs or undefined to use the passed config
     */
    afterBuild: function (formConfig, model, config, initialPanelConfig) {}
});
<commit_msg>Improved form panel onSave logic<commit_after>/*
 *
 * Bancha Scaffolding Library
 * Copyright 2011-2014 codeQ e.U.
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @package       Bancha.scaffold
 * @copyright     Copyright 2011-2014 codeQ e.U.
 * @link          http://scaffold.bancha.io
 * @since         Bancha Scaffold v 1.0.0
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 * @author        Roland Schuetz <mail@rolandschuetz.at>
 * @version       Bancha Scaffold v PRECOMPILER_ADD_BANCHA_SCAFFOLD_RELEASE_VERSION
 *
 * For more information go to http://scaffold.bancha.io
 */

/**
 * @singleton
 * @class Bancha.scaffold.form.Config
 * **This is only available inside Ext JS.**
 *
 * This class is a config class for creating scaffoled {@link Ext.form.Panel}s.
 *
 * For more information see {@link Ext.form.Panel}.
 *
 * @author Roland Schuetz <mail@rolandschuetz.at>
 * @docauthor Roland Schuetz <mail@rolandschuetz.at>
 */
Ext.define('Bancha.scaffold.form.Config', {
    uses: [
        'Ext.window.MessageBox'
    ],

    /**
     * Create a new config instance
     */
    constructor: function(config) {
        config = config || {};
        var triggeredFrom = config.triggeredFrom || 'Unknown Origin',
            me = this,
            modelName;

        // if the config is just a model name or model, transform to a config object
        if (Ext.isString(config) || Bancha.scaffold.Util.isModel(config)) {
            config = {
                target: config // use the model as target
            };
        }

        //<debug>
        // check that a model is set
        if(!config.target) {
            Ext.Error.raise({
                plugin: 'Bancha Scaffold',
                msg: [
                    'Bancha Scaffold: If you set a form scaffold config object ',
                    'for '+triggeredFrom+', the target property must be set!'
                ].join('')
            });
        }
        //</debug>

        // check that the configured model is valid
        modelName = config.target;
        modelName = Ext.isString(modelName) ? modelName : Ext.ClassManager.getName(modelName);

        // make sure it's loaded
        Ext.syncRequire(modelName);

        //<debug>
        if (!Bancha.scaffold.Util.isModel(modelName)) {
            Ext.Error.raise({
                plugin: 'Bancha Scaffold',
                msg: [
                    'Bancha Scaffold: If you set a form scaffold config object ',
                    'for '+triggeredFrom+', the target property must be a model ',
                    'name or model class. Instead ' + config.target + ' of type ',
                    (typeof config.target) + ' was set.'
                ].join('')
            });
        }
        //</debug>

        // make sure that the model property is always a model class
        config.target = Bancha.scaffold.Util.getModel(modelName);

        if(Ext.isDefined(config.exclude) && !Ext.isArray(config.exclude)) {
            //<debug>
            Ext.Error.raise({
                plugin: 'Bancha Scaffold',
                model: modelName,
                msg: [
                    'Bancha Scaffold: When scaffolding a ' + triggeredFrom,
                    ' the form scaffold exclude config should be an array ',
                    'of field names to exclude.'
                ].join('')
            });
            //</debug>
            config.exclude = [];
        }

        // apply to the object
        Ext.apply(me, config);
    },

    statics: {
        /**
         * Set a new default for scaffolding forms
         */
        setDefault: function(configName, config) {
            // apply to the class prototype
            this.prototype[configName] = config;
        },
        /**
         * Set some defaults for scaffolding forms
         */
        setDefaults: function(config) {
            // apply to the class prototype
            Ext.apply(this.prototype, config);
        }
    },

    /**
     * @private
     * @cfg {String} triggeredFrom
     * (optional) Used for debugging messages as target
     */
    /**
     * @cfg {Ext.data.Model|String} target
     * The model to use
     */
    /**
     * @private
     * @property {Ext.data.Model} target
     * The model to use
     */
    /**
     * @cfg {String[]}
     * Exclude some model fields from scaffolding
     */
    exclude: [],
    /**
     * @cfg {String[]|false}
     * If this is set to an array, only those fields are displayed.
     *
     * The given order of fields is also applied, so to reorder your fields
     * simply defined something like _fields: ['field2','field1']_
     *
     * Note that the exclude setting are still applied.
     */
    fields: false,
    /**
     * @cfg
     * This config is applied to each scaffolded form field
     */
    fieldDefaults: {},
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.Date
     */
    datefieldDefaults: {},
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.File
     */
    fileuploadfieldDefaults: {
        emptyText: 'Select an file'
    },
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.Text
     */
    textfieldDefaults: {},
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.Number
     */
    numberfieldDefaults: {},
    /**
     * @cfg
     * This config is applied to each scaffolded Ext.form.field.Checkbox
     */
    checkboxfieldDefaults: {
        uncheckedValue: false
    },
    /**
     * @cfg
     * The defaults class to create a stores for associated model selects for
     * form scaffolding.
     *
     * See also {@link Bancha.scaffold.Util#getStore}.
     *
     * Default: *"Ext.data.Store"*
     */
    storeDefaultClass: 'Ext.data.Store',
    /**
     * @cfg
     * Defaults for all stores for associated model selects created with
     * this scaffolding.
     *
     * See also {@link Bancha.scaffold.Util#getStore}.
     *
     * Default:
     *
     *     {
     *       autoLoad: true
     *     }
     */
    storeDefaults: {
        autoLoad: true
    },
    /**
     * @cfg
     * True to use only one store per model (singleton),
     * false to create a new store each time a associated
     * model is found and a selects field with a store is
     * build.
     *
     * See also {@link Bancha.scaffold.Util#getStore}.
     *
     * Default: *true*
     */
    oneStorePerModel: true,
    /**
     * @cfg {Function} transformFieldConfig
     * Used to add some custom behaviour.
     *
     * This function can be overwritten by any custom function.
     * @param {Object} fieldConfig the field config to transform
     * @param {String} modelType A standard model field type like 'string'
     * (also supports 'file' for compability with http://banchaproject.org)
     * @return {Object} Returns an Ext.form.field.* configuration object
     */
    transformFieldConfig: function (fieldConfig, modelType) {
        return fieldConfig;
    },
    /**
     * @cfg
     * Editable function to be called when the save button is pressed.
     * To change the default scaffolding behaviour just replace this function.
     *
     * The default scope provides two functions:
     *
     *  - this.getPanel() to get the form panel
     *  - this.getForm() to get the basic form
     */
    onSave: function () {
        var me = this,
            form = me.getForm(),
            config = me.getPanel().scaffold;

        form.submit({
            waitMsg: form.hasUpload() ? 'Uploading files...' : 'Saving data..',
            success: function (form, action) {
                Ext.MessageBox.alert('Success', action.result.msg || 'Successfully saved data.');

                // load result as record into form
                var rec = Ext.create(config.target.getName(), action.result.data);
                form.loadRecord(rec);

                if(config.onSaved) {
                    config.onSaved.call(me, me, true, action);
                }
            },
            failure: function (form, action) {
                if(action.result.msg || !action.result.errors) {
                    // if there is a server-side message or no server-side validation errors are send,
                    // show a warning alert. Otherwise the errors are rendered in the form and no alert
                    // is necessary.
                    Ext.MessageBox.alert('Failed', action.result.msg || 'Could not save data, unknown error.');
                }

                if(config.onSaved) {
                    config.onSaved.call(me, me, false, action);
                }
            }
        });
    },
    /**
     * @cfg
     * Editable function to be called when the record was saved to the server.
     * To change the default scaffolding behaviour just replace this function.
     *
     * The arguments are:
     *  - this: The scope described below
     *  - success: True if successfully saved
     *  - action: The request action
     *
     * The default scope provides two functions:
     *
     *  - this.getPanel() to get the form panel
     *  - this.getForm() to get the basic form
     *
     * Note:
     * This function is called by onSave, so if you override onSave this function
     * might note be called anymore.
     */
    onSaved: Ext.emptyFn,
    /**
     * @cfg
     * Editable function to be called when the reset button is pressed.
     * To change the default scaffolding behaviour just replace this function.
     *
     * The default scope provides two functions:
     *
     *  - this.getPanel() to get the form panel
     *  - this.getForm() to get the basic form
     */
    onReset: function () {
        this.getForm().reset();
    },
    /**
     * @cfg {String[]|Ext.button.Button[]}
     * If an array of elements, a footer toolbar is rendered.
     *
     * 'reset' and 'save' will be replaced by scaffolded
     * buttons, other elements are treated like default Ext JS items.
     *
     * Inside your own buttons you can set the scope property to
     * 'scaffold-scope-me', this scope provides two functions:
     *  - this.getPanel() to get the form panel
     *  - this.getForm() to get the basic form
     *
     * Default: ['reset','save']
     */
    buttons: ['reset','save'],
    /**
     * @cfg
     * Default save button config, used in buttons.
     * If not defined scope and handler properties will be set by
     * the build function.
     */
    saveButtonConfig: {
        iconCls: 'icon-save',
        text: 'Save',
        formBind: true
    },
    /**
     * @cfg
     * Default reset button config, used in buttons config.
     * If not defined scope and handler properties will be set by
     * the build function.
     */
    resetButtonConfig: {
        iconCls: 'icon-reset',
        text: 'Reset'
    },
    /**
     * @cfg {Function}
     * Build the form api config, used only by buildConfig()
     * just for separation of concern, since this is the only
     * part which deals with proxies
     *
     * For Bancha projects with an CakePHP backend this function will
     * scaffold everything
     *
     * Otherwise it will use the initial config, if provided. If not,
     * it will use the model proxies load method. There is no generic
     * way to guess the submit method, please either modify this function
     * or provide a propery form api config.
     *
     * @param {Ext.data.Model} model the model used for scaffolding
     * @param {Object} initialApi the initial Ext.form.Panel api config
     * @return the final Ext.form.Panel api config
     */
    buildApiConfig: function (model, initialApi) {

        if(Bancha.getModel) {
            // the user is using the full Bancha stack
            // everything can be automatically done
            return Ext.form.Panel.buildBanchaApiConfig(model,initialApi);
        } else{

            if(initialApi) {
                // just use the configured api
                return initialApi;
            }

            //<debug>
            // warn the user that we can just guess part of the api
            if (Ext.global.console && Ext.isFunction(Ext.global.console.warn)) {
                Ext.global.console.warn([
                    'Bancha Scaffold: You have not defined any form api. If you want ',
                    'Bancha to guess it, please define Bancha.scaffold.form.Config.',
                    'buildApiConfig. Bancha Scaffold can only try to get the load ',
                    'function from the model proxy, but not the submit function.'
                ].join(''));
            }
            //</debug>
        }

        // try to find the proxy configuration for load
        var proxy = model.getProxy(),
            load = proxy && proxy.api && proxy.api.read ? proxy.api.read :
                    (proxy && proxy.directFn ? proxy.directFn : undefined);

        return load ? {load: load} : undefined;
    },
    /**
     * @cfg {String|Number|False}
     * Define a record id here to autolaod this record for editing in this form, or choose
     * false to create a new record onSave. You can also overwrite onSave to define your
     * own behavior
     * (Default: false)
     */
    loadRecord: false,
    /**
     * @cfg {Function}
     * The function will be executed before scaffolding as interceptor.
     * @param {Ext.data.Model} model the model used for scaffolding
     * @param {Bancha.scaffold.form.Config} config the scaffold full config for this call
     * @param {Object} initialPanelConfig please ignore, this is a legacy argument, may having some additional Ext.form.Panel configs
     * @return {Object|undefined} object with initial Ext.form.Panel configs
     */
    beforeBuild: function (model, config, initialPanelConfig) {},
    /**
     * @cfg {Function}
     * This function will be executed after scaffolding as interceptor.
     * @param {Object} formConfig the just build form panel config
     * @param {Ext.data.Model} model the model used for scaffolding
     * @param {Bancha.scaffold.form.Config} config the scaffold full config for this call
     * @param {Object} initialPanelConfig please ignore, this is a legacy argument, may having some additional Ext.form.Panel configs
     * @return {Object|undefined} object with final Ext.form.Panel configs or undefined to use the passed config
     */
    afterBuild: function (formConfig, model, config, initialPanelConfig) {}
});
<|endoftext|>


<commit_before>/*! Sortable 0.1.9 - MIT | git://github.com/rubaxa/Sortable.git */
!function(a){"use strict";"function"==typeof define&&define.amd?define(a):"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=a():window.Sortable=a()}(function(){"use strict";function a(a,c){this.el=a,this.options=c=c||{},c.group=c.group||Math.random(),c.handle=c.handle||null,c.draggable=c.draggable||a.children[0]&&a.children[0].nodeName||(/[uo]l/i.test(a.nodeName)?"li":"*"),c.ghostClass=c.ghostClass||"sortable-ghost",c.onAdd=b(this,c.onAdd||D),c.onUpdate=b(this,c.onUpdate||D),c.onRemove=b(this,c.onRemove||D),a[w]=c.group;for(var d in this)"_"===d.charAt(0)&&(this[d]=b(this,this[d]));e(a,"add",c.onAdd),e(a,"update",c.onUpdate),e(a,"remove",c.onRemove),e(a,"mousedown",this._onTapStart),e(a,"touchstart",this._onTapStart),A&&e(a,"selectstart",this._onTapStart),e(a,"dragover",this._onDragOver),e(a,"dragenter",this._onDragOver),F.push(this._onDragOver)}function b(a,b){var c=E.call(arguments,2);return b.bind?b.bind.apply(b,[a].concat(c)):function(){return b.apply(a,c.concat(E.call(arguments)))}}function c(a,b,c){if("*"===b)return a;if(a){c=c||y,b=b.split(".");var d=b.shift().toUpperCase(),e=new RegExp("\\s("+b.join("|")+")\\s","g");do if(!(""!==d&&a.nodeName!=d||b.length&&((" "+a.className+" ").match(e)||[]).length!=b.length))return a;while(a!==c&&(a=a.parentNode))}return null}function d(a){a.dataTransfer.dropEffect="move",a.preventDefault()}function e(a,b,c){a.addEventListener(b,c,!1)}function f(a,b,c){a.removeEventListener(b,c,!1)}function g(a,b,c){if(a)if(a.classList)a.classList[c?"add":"remove"](b);else{var d=(" "+a.className+" ").replace(/\s+/g," ").replace(" "+b+" ","");a.className=d+(c?" "+b:"")}}function h(a,b,c){if(a&&a.style){if(void 0===c)return y.defaultView&&y.defaultView.getComputedStyle?c=y.defaultView.getComputedStyle(a,""):a.currentStyle&&(c=a.currentStyle),void 0===b?c:c[b];a.style[b]=c+("string"==typeof c?"":"px")}}function i(a,b,c){if(a){var d=a.getElementsByTagName(b),e=0,f=d.length;if(c)for(;f>e;e++)c(d[e],e);return d}return[]}function j(a){return a.draggable=!1}function k(){B=!1}function l(a,b){var c=a.lastElementChild.getBoundingClientRect();return b.clientY-(c.top+c.height)>5}var m,n,o,p,q,r,s,t,u,v,w="Sortable"+(new Date).getTime(),x=window,y=x.document,z=x.parseInt,A=!!y.createElement("div").dragDrop,B=!1,C=function(a,b){var c=y.createEvent("Event");return c.initEvent(a,!0,!0),c.item=b,c},D=function(){},E=[].slice,F=[];return a.prototype={constructor:a,_applyEffects:function(){g(m,this.options.ghostClass,!0)},_onTapStart:function(a){var b=a.touches&&a.touches[0],f=(b||a).target,g=this.options,h=this.el;if(g.handle&&(f=c(f,g.handle,h)),f=c(f,g.draggable,h),f&&"selectstart"==a.type&&"A"!=f.tagName&&"IMG"!=f.tagName&&f.dragDrop(),f&&!m&&f.parentNode===h){u=a,f.draggable=!0,i(f,"a",j),i(f,"img",j),b&&(u={target:f,clientX:b.clientX,clientY:b.clientY},this._onDragStart(u,!0),a.preventDefault()),e(this.el,"dragstart",this._onDragStart),e(this.el,"dragend",this._onDrop),e(y,"dragover",d);try{y.selection?y.selection.empty():window.getSelection().removeAllRanges()}catch(k){}}},_emulateDragOver:function(){if(v){h(n,"display","none");var a=y.elementFromPoint(v.clientX,v.clientY),b=a,c=this.options.group,d=F.length;if(b)do{if(b[w]===c){for(;d--;)F[d]({clientX:v.clientX,clientY:v.clientY,target:a,rootEl:b});break}a=b}while(b=b.parentNode);h(n,"display","")}},_onTouchMove:function(a){if(u){var b=a.touches[0],c=b.clientX-u.clientX,d=b.clientY-u.clientY;v=b,h(n,"webkitTransform","translate3d("+c+"px,"+d+"px,0)")}},_onDragStart:function(a,b){var c=a.target,d=a.dataTransfer;if(o=this.el,m=c,p=c.nextSibling,t=this.options.group,b){var f,g=c.getBoundingClientRect(),i=h(c);n=c.cloneNode(!0),h(n,"top",g.top-z(i.marginTop,10)),h(n,"left",g.left-z(i.marginLeft,10)),h(n,"width",g.width),h(n,"height",g.height),h(n,"opacity","0.8"),h(n,"position","fixed"),h(n,"zIndex","100000"),o.appendChild(n),f=n.getBoundingClientRect(),h(n,"width",2*g.width-f.width),h(n,"height",2*g.height-f.height),e(y,"touchmove",this._onTouchMove),e(y,"touchend",this._onDrop),this._loopId=setInterval(this._emulateDragOver,150)}else d.effectAllowed="move",d.setData("Text",c.textContent),e(y,"drop",this._onDrop);setTimeout(this._applyEffects)},_onDragOver:function(a){if(!B&&t===this.options.group&&(void 0===a.rootEl||a.rootEl===this.el)){var b=this.el,d=c(a.target,this.options.draggable,b);if(0===b.children.length||b.children[0]===n||b===a.target&&l(b,a))b.appendChild(m);else if(d&&d!==m&&void 0!==d.parentNode[w]){q!==d&&(q=d,r=h(d),s=d.getBoundingClientRect());var e,f=s,g=f.right-f.left,i=f.bottom-f.top,j=/left|right|inline/.test(r.cssFloat+r.display),o=(j?(a.clientX-f.left)/g:(a.clientY-f.top)/i)>.5,p=d.offsetWidth>m.offsetWidth,u=d.offsetHeight>m.offsetHeight,v=d.nextSibling;B=!0,setTimeout(k,30),e=j?d.previousElementSibling===m&&!p||o>.5&&p:d.nextElementSibling!==m&&!u||o>.5&&u,e&&!v?b.appendChild(m):d.parentNode.insertBefore(m,e?v:d)}}},_onDrop:function(a){clearInterval(this._loopId),f(y,"drop",this._onDrop),f(y,"dragover",d),f(this.el,"dragend",this._onDrop),f(this.el,"dragstart",this._onDragStart),f(this.el,"selectstart",this._onTapStart),f(y,"touchmove",this._onTouchMove),f(y,"touchend",this._onDrop),a&&(a.preventDefault(),a.stopPropagation(),n&&n.parentNode.removeChild(n),m&&(g(m,this.options.ghostClass,!1),o.contains(m)?m.nextSibling!==p&&m.dispatchEvent(C("update",m)):(o.dispatchEvent(C("remove",m)),m.dispatchEvent(C("add",m)))),o=m=n=p=u=v=q=r=t=null)},destroy:function(){var a=this.el,b=this.options;f(a,"add",b.onAdd),f(a,"update",b.onUpdate),f(a,"remove",b.onRemove),f(a,"mousedown",this._onTapStart),f(a,"touchstart",this._onTapStart),f(a,"selectstart",this._onTapStart),f(a,"dragover",this._onDragOver),f(a,"dragenter",this._onDragOver),Array.prototype.forEach.call(a.querySelectorAll("[draggable]"),function(a){a.removeAttribute("draggable")}),F.splice(F.indexOf(this._onDragOver),1),this._onDrop(),this.el=null}},a.utils={on:e,off:f,css:h,find:i,bind:b,closest:c,toggleClass:g},a.version="0.1.9",a});<commit_msg>updated Sortable.js<commit_after>/*! Sortable 0.7.2 - MIT | git://github.com/rubaxa/Sortable.git */
!function(a){"use strict";"function"==typeof define&&define.amd?define(a):"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=a():"undefined"!=typeof Package?Sortable=a():window.Sortable=a()}(function(){"use strict";function a(a,c){this.el=a,this.options=c=c||{};var d={group:Math.random(),sort:!0,disabled:!1,store:null,handle:null,draggable:a.children[0]&&a.children[0].nodeName||(/[uo]l/i.test(a.nodeName)?"li":"*"),ghostClass:"sortable-ghost",ignore:"a, img",filter:null,animation:0,setData:function(a,b){a.setData("Text",b.textContent)}};for(var f in d)!(f in c)&&(c[f]=d[f]);c.group.name||(c.group={name:c.group}),["pull","put"].forEach(function(a){a in c.group||(c.group[a]=!0)}),G.forEach(function(d){c[d]=b(this,c[d]||H),e(a,d.substr(2).toLowerCase(),c[d])},this),a[z]=c.group.name;for(var g in this)"_"===g.charAt(0)&&(this[g]=b(this,this[g]));e(a,"mousedown",this._onTapStart),e(a,"touchstart",this._onTapStart),D&&e(a,"selectstart",this._onTapStart),e(a,"dragover",this._onDragOver),e(a,"dragenter",this._onDragOver),J.push(this._onDragOver),c.store&&this.sort(c.store.get(this))}function b(a,b){var c=I.call(arguments,2);return b.bind?b.bind.apply(b,[a].concat(c)):function(){return b.apply(a,c.concat(I.call(arguments)))}}function c(a,b,c){if("*"===b)return a;if(a){c=c||B,b=b.split(".");var d=b.shift().toUpperCase(),e=new RegExp("\\s("+b.join("|")+")\\s","g");do if(!(""!==d&&a.nodeName!=d||b.length&&((" "+a.className+" ").match(e)||[]).length!=b.length))return a;while(a!==c&&(a=a.parentNode))}return null}function d(a){a.dataTransfer.dropEffect="move",a.preventDefault()}function e(a,b,c){a.addEventListener(b,c,!1)}function f(a,b,c){a.removeEventListener(b,c,!1)}function g(a,b,c){if(a)if(a.classList)a.classList[c?"add":"remove"](b);else{var d=(" "+a.className+" ").replace(/\s+/g," ").replace(" "+b+" ","");a.className=d+(c?" "+b:"")}}function h(a,b,c){var d=a&&a.style;if(d){if(void 0===c)return B.defaultView&&B.defaultView.getComputedStyle?c=B.defaultView.getComputedStyle(a,""):a.currentStyle&&(c=a.currentStyle),void 0===b?c:c[b];b in d||(b="-webkit-"+b),d[b]=c+("string"==typeof c?"":"px")}}function i(a,b,c){if(a){var d=a.getElementsByTagName(b),e=0,f=d.length;if(c)for(;f>e;e++)c(d[e],e);return d}return[]}function j(a){a.draggable=!1}function k(){E=!1}function l(a,b){var c=a.lastElementChild,d=c.getBoundingClientRect();return b.clientY-(d.top+d.height)>5&&c}function m(a){for(var b=a.tagName+a.className+a.src+a.href+a.textContent,c=b.length,d=0;c--;)d+=b.charCodeAt(c);return d.toString(36)}function n(a){for(var b=0;a=a.previousElementSibling;)b++;return b}var o,p,q,r,s,t,u,v,w,x,y,z="Sortable"+(new Date).getTime(),A=window,B=A.document,C=A.parseInt,D=!!B.createElement("div").dragDrop,E=!1,F=function(a,b,c,d,e,f){var g=B.createEvent("Event");g.initEvent(b,!0,!0),g.item=c||a,g.from=d||a,void 0!==e&&(g.oldIndex=e),void 0!==f&&(g.newIndex=f),a.dispatchEvent(g)},G="onAdd onUpdate onRemove onStart onEnd onFilter onSort".split(" "),H=function(){},I=[].slice,J=[];return a.prototype={constructor:a,_applyEffects:function(){g(o,this.options.ghostClass,!0)},_onTapStart:function(a){var b=a.touches&&a.touches[0],f=(b||a).target,g=this.options,k=this.el,l=g.filter;if(p=n(f),!("mousedown"===a.type&&0!==a.button||g.disabled)){if("function"==typeof l){if(l.call(this,f,this))return void F(k,"filter",f)}else if(l&&(l=l.split(",").filter(function(a){return c(f,a.trim(),k)}),l.length))return void F(k,"filter",f);if(g.handle&&(f=c(f,g.handle,k)),f=c(f,g.draggable,k),f&&"selectstart"==a.type&&"A"!=f.tagName&&"IMG"!=f.tagName&&f.dragDrop(),f&&!o&&f.parentNode===k){x=a,s=this.el,o=f,t=o.nextSibling,w=this.options.group,o.draggable=!0,g.ignore.split(",").forEach(function(a){i(f,a.trim(),j)}),b&&(x={target:f,clientX:b.clientX,clientY:b.clientY},this._onDragStart(x,!0),a.preventDefault()),e(B,"mouseup",this._onDrop),e(B,"touchend",this._onDrop),e(B,"touchcancel",this._onDrop),e(this.el,"dragstart",this._onDragStart),e(this.el,"dragend",this._onDrop),e(B,"dragover",d);try{B.selection?B.selection.empty():window.getSelection().removeAllRanges()}catch(m){}F(o,"start",void 0,void 0,p),"clone"==w.pull&&(r=o.cloneNode(!0),h(r,"display","none"),s.insertBefore(r,o))}}},_emulateDragOver:function(){if(y){h(q,"display","none");var a=B.elementFromPoint(y.clientX,y.clientY),b=a,c=this.options.group.name,d=J.length;if(b)do{if(b[z]===c){for(;d--;)J[d]({clientX:y.clientX,clientY:y.clientY,target:a,rootEl:b});break}a=b}while(b=b.parentNode);h(q,"display","")}},_onTouchMove:function(a){if(x){var b=a.touches[0],c=b.clientX-x.clientX,d=b.clientY-x.clientY,e="translate3d("+c+"px,"+d+"px,0)";y=b,h(q,"webkitTransform",e),h(q,"mozTransform",e),h(q,"msTransform",e),h(q,"transform",e),a.preventDefault()}},_onDragStart:function(a,b){var c=a.dataTransfer,d=this.options;if(this._offUpEvents(),b){var f,g=o.getBoundingClientRect(),i=h(o);q=o.cloneNode(!0),h(q,"top",g.top-C(i.marginTop,10)),h(q,"left",g.left-C(i.marginLeft,10)),h(q,"width",g.width),h(q,"height",g.height),h(q,"opacity","0.8"),h(q,"position","fixed"),h(q,"zIndex","100000"),s.appendChild(q),f=q.getBoundingClientRect(),h(q,"width",2*g.width-f.width),h(q,"height",2*g.height-f.height),e(B,"touchmove",this._onTouchMove),e(B,"touchend",this._onDrop),e(B,"touchcancel",this._onDrop),this._loopId=setInterval(this._emulateDragOver,150)}else c.effectAllowed="move",d.setData&&d.setData.call(this,c,o),e(B,"drop",this._onDrop);setTimeout(this._applyEffects)},_onDragOver:function(a){var b,d,e,f=this.el,g=this.options,i=g.group,j=i.put,m=w===i,n=g.sort;if(!E&&(m?n||(e=!s.contains(o)):w.pull&&j&&(w.name===i.name||j.indexOf&&~j.indexOf(w.name)))&&(void 0===a.rootEl||a.rootEl===this.el)){if(b=c(a.target,g.draggable,f),d=o.getBoundingClientRect(),r&&r.state!==m&&(h(r,"display",m?"none":""),!m&&r.state&&s.insertBefore(r,o),r.state=m),e)return void(r||t?s.insertBefore(o,r||t):n||s.appendChild(o));if(0===f.children.length||f.children[0]===q||f===a.target&&(b=l(f,a))){if(b){if(b.animated)return;x=b.getBoundingClientRect()}f.appendChild(o),this._animate(d,o),b&&this._animate(x,b)}else if(b&&!b.animated&&b!==o&&void 0!==b.parentNode[z]){u!==b&&(u=b,v=h(b));var p,x=b.getBoundingClientRect(),y=x.right-x.left,A=x.bottom-x.top,B=/left|right|inline/.test(v.cssFloat+v.display),C=b.offsetWidth>o.offsetWidth,D=b.offsetHeight>o.offsetHeight,F=(B?(a.clientX-x.left)/y:(a.clientY-x.top)/A)>.5,G=b.nextElementSibling;E=!0,setTimeout(k,30),p=B?b.previousElementSibling===o&&!C||F&&C:G!==o&&!D||F&&D,p&&!G?f.appendChild(o):b.parentNode.insertBefore(o,p?G:b),this._animate(d,o),this._animate(x,b)}}},_animate:function(a,b){var c=this.options.animation;if(c){var d=b.getBoundingClientRect();h(b,"transition","none"),h(b,"transform","translate3d("+(a.left-d.left)+"px,"+(a.top-d.top)+"px,0)"),b.offsetWidth,h(b,"transition","all "+c+"ms"),h(b,"transform","translate3d(0,0,0)"),clearTimeout(b.animated),b.animated=setTimeout(function(){h(b,"transition",""),b.animated=!1},c)}},_offUpEvents:function(){f(B,"mouseup",this._onDrop),f(B,"touchmove",this._onTouchMove),f(B,"touchend",this._onDrop),f(B,"touchcancel",this._onDrop)},_onDrop:function(a){if(clearInterval(this._loopId),f(B,"drop",this._onDrop),f(B,"dragover",d),f(this.el,"dragend",this._onDrop),f(this.el,"dragstart",this._onDragStart),f(this.el,"selectstart",this._onTapStart),this._offUpEvents(),a){if(a.preventDefault(),a.stopPropagation(),q&&q.parentNode.removeChild(q),o){var b=n(o);j(o),g(o,this.options.ghostClass,!1),s.contains(o)?o.nextSibling!==t&&(F(o,"update",void 0,void 0,p,b),F(o,"sort",void 0,void 0,p,b),r&&r.parentNode.removeChild(r)):(F(o,"sort",o,o.parentNode,p,b),F(s,"sort",o,void 0,p,b),F(o,"add",o,s,p,b),F(s,"remove",o,void 0,p,b)),F(s,"end",void 0,void 0,p,b)}s=o=q=t=r=x=y=u=v=w=null,this.options.store&&this.options.store.set(this)}},toArray:function(){for(var a,b=[],d=this.el.children,e=0,f=d.length;f>e;e++)a=d[e],c(a,this.options.draggable,this.el)&&b.push(a.getAttribute("data-id")||m(a));return b},sort:function(a){var b={},d=this.el;this.toArray().forEach(function(a,e){var f=d.children[e];c(f,this.options.draggable,d)&&(b[a]=f)},this),a.forEach(function(a){b[a]&&(d.removeChild(b[a]),d.appendChild(b[a]))})},closest:function(a,b){return c(a,b||this.options.draggable,this.el)},option:function(a,b){var c=this.options;return void 0===b?c[a]:void(c[a]=b)},destroy:function(){var a=this.el,b=this.options;G.forEach(function(c){f(a,c.substr(2).toLowerCase(),b[c])}),f(a,"mousedown",this._onTapStart),f(a,"touchstart",this._onTapStart),f(a,"selectstart",this._onTapStart),f(a,"dragover",this._onDragOver),f(a,"dragenter",this._onDragOver),Array.prototype.forEach.call(a.querySelectorAll("[draggable]"),function(a){a.removeAttribute("draggable")}),J.splice(J.indexOf(this._onDragOver),1),this._onDrop(),this.el=null}},a.utils={on:e,off:f,css:h,find:i,bind:b,closest:c,toggleClass:g,dispatchEvent:F,index:n},a.version="0.7.2",a.create=function(b,c){return new a(b,c)},a});
<|endoftext|>


<commit_before>'use strict';

define(['Dependency'], function (Dependency) {
    return {
        defaultStatePath: '/',
        states: {
            /* ======= Parents ======= */
            root: {
                name: 'root',
                abstract: true,
                template: '<ui-view/>',
                views: {
                    'header@': {
                        templateUrl: '/modules/common/header/main.html'
                    },
                    'navigation@': {
                        templateUrl: '/modules/common/sidenav/main.html'
                    }
                },
                resolve: new Dependency([
                    'modules/common/header/main',
                    'modules/common/sidenav/main'
                ])
            },
            settings: {
                name: 'settings',
                abstract: true,
                template: '<ui-view/>',
                views: {
                    'header@': {
                        templateUrl: '/modules/common/header/main.html'
                    },
                    'navigation@': {
                        templateUrl: '/modules/common/sidenav/settings.html'
                    }
                }
            },
            /* ======= Login ======= */
            login: {
                name: 'login',
                url: '/login',
                parent: '',
                views: {
                    '@': {
                        templateUrl: '/modules/login/index.html'
                    }
                },
                resolve: new Dependency([
                    'modules/login/index'
                ]),
                authenticate: false
            },
            /* ======= Statusboard ======= */
            statusboard: {
                name: 'statusboard',
                url: '/',
                parent: 'root',
                views: {
                    '@': {
                        templateUrl: '/modules/statusboard/index.html'
                    }
                },
                resolve: new Dependency([
                    'modules/statusboard/index'
                ]),
                authenticate: true
            },
            /* ======= Settings ======= */
            settings_item: {
                name: 'settings_item',
                url: '/settings/item',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/item/list.html'
                    }
                },
                resolve: new Dependency([
                    'modules/item/list'
                ]),
                authenticate: true
            },
            settings_item_add: {
                name: 'settings_item_add',
                url: '/settings/item/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/item/add.html'
                    }
                },
                resolve: new Dependency([
                    'modules/item/add'
                ]),
                authenticate: true
            },
            settings_item_view: {
                name: 'settings_item_view',
                url: '/settings/item/:itemId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/item/view.html'
                    }
                },
                resolve: new Dependency([
                    'modules/item/view'
                ]),
                authenticate: true
            },
            settings_item_edit: {
                name: 'settings_item_edit',
                url: '/settings/item/:itemId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/item/edit.html'
                    }
                },
                resolve: new Dependency([
                    'modules/item/edit'
                ]),
                authenticate: true
            },
            /* ======= Settings Broker======= */
            settings_broker: {
                name: 'settings_broker',
                url: '/settings/broker',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/broker/list.html'
                    }
                },
                resolve: new Dependency([
                    'modules/broker/list'
                ]),
                authenticate: true
            },
            settings_broker_add: {
                name: 'settings_broker_add',
                url: '/settings/broker/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/broker/add.html'
                    }
                },
                resolve: new Dependency([
                    'modules/broker/add'
                ]),
                authenticate: true
            },
            settings_broker_view: {
                name: 'settings_broker_view',
                url: '/settings/broker/:brokerId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/broker/view.html'
                    }
                },
                resolve: new Dependency([
                    'modules/broker/view'
                ]),
                authenticate: true
            },
            settings_broker_edit: {
                name: 'settings_broker_edit',
                url: '/settings/broker/:brokerId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/broker/edit.html'
                    }
                },
                resolve: new Dependency([
                    'modules/broker/edit'
                ]),
                authenticate: true
            },

            /* ======= Settings Supplier ======= */
            settings_supplier: {
                name: 'settings_supplier',
                url: '/settings/supplier',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/supplier/list.html'
                    }
                },
                resolve: new Dependency([
                    'modules/supplier/list'
                ]),
                authenticate: true
            },
            settings_supplier_add: {
                name: 'settings_supplier_add',
                url: '/settings/supplier/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/supplier/add.html'
                    }
                },
                resolve: new Dependency([
                    'modules/supplier/add'
                ]),
                authenticate: true
            },
            settings_supplier_view: {
                name: 'settings_supplier_view',
                url: '/settings/supplier/:supplierId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/supplier/view.html'
                    }
                },
                resolve: new Dependency([
                    'modules/supplier/view'
                ]),
                authenticate: true
            },
            settings_supplier_edit: {
                name: 'settings_supplier_edit',
                url: '/settings/supplier/:supplierId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/supplier/edit.html'
                    }
                },
                resolve: new Dependency([
                    'modules/supplier/edit'
                ]),
                authenticate: true
            },
            /* ======= Settings Forwarder ======= */
            settings_forwarder: {
                name: 'settings_forwarder',
                url: '/settings/forwarder',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/forwarder/list.html'
                    }
                },
                resolve: new Dependency([
                   'modules/forwarder/list'
                ]),
                authenticate: true
            },
            settings_forwarder_add: {
                name: 'settings_forwarder_add',
                url: '/settings/forwarder/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/forwarder/add.html'
                    }
                },
                resolve: new Dependency([
                   'modules/forwarder/add'
                ]),
                authenticate: true
            },
            settings_forwarder_view: {
                name: 'settings_forwarder_view',
                url: '/settings/forwarder/:forwarderId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/forwarder/view.html'
                    }
                },
                resolve: new Dependency([
                   'modules/forwarder/view'
               ]),
                authenticate: true
            },
            settings_forwarder_edit: {
                name: 'settings_forwarder_edit',
                url: '/settings/forwarder/:forwarderId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/forwarder/edit.html'
                    }
                },
                resolve: new Dependency([
                   'modules/forwarder/edit'
                ]),
                authenticate: true
            },
            /* ======= Settings User ======= */
            settings_user: {
                name: 'settings_user',
                url: '/settings/user',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/user/list.html'
                    }
                },
                resolve: new Dependency([
                   'modules/user/list'
                ]),
                authenticate: true
            },
            settings_user_add: {
                name: 'settings_user_add',
                url: '/settings/user/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/user/add.html'
                    }
                },
                resolve: new Dependency([
                   'modules/user/add'
                ]),
                authenticate: true
            },
            settings_user_view: {
                name: 'settings_user_view',
                url: '/settings/user/:userId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/user/view.html'
                    }
                },
                resolve: new Dependency([
                   'modules/user/view'
                ]),
                authenticate: true
            },
            settings_user_edit: {
                name: 'settings_user_edit',
                url: '/settings/user/:userId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/user/edit.html'
                    }
                },
                resolve: new Dependency([
                   'modules/user/edit'
                ]),
                authenticate: true
            },
             /* ======= Settings User ======= */
            initiate_import_planner: {
                name: 'initiate_import_planner',
                url: '/initiateimport/planner',
                parent: 'root',
                views: {
                    '@': {
                        templateUrl: '/modules/initiateimport/planner/list.html'
                    }
                },
                resolve: new Dependency([
                   'modules/initiateimport/planner/list'
                ]),
                authenticate: true
            }
        }
    };
});<commit_msg>login as temp default path<commit_after>'use strict';

define(['Dependency'], function (Dependency) {
    return {
        defaultStatePath: '/login',
        states: {
            /* ======= Parents ======= */
            root: {
                name: 'root',
                abstract: true,
                template: '<ui-view/>',
                views: {
                    'header@': {
                        templateUrl: '/modules/common/header/main.html'
                    },
                    'navigation@': {
                        templateUrl: '/modules/common/sidenav/main.html'
                    }
                },
                resolve: new Dependency([
                    'modules/common/header/main',
                    'modules/common/sidenav/main'
                ])
            },
            settings: {
                name: 'settings',
                abstract: true,
                template: '<ui-view/>',
                views: {
                    'header@': {
                        templateUrl: '/modules/common/header/main.html'
                    },
                    'navigation@': {
                        templateUrl: '/modules/common/sidenav/settings.html'
                    }
                }
            },
            /* ======= Login ======= */
            login: {
                name: 'login',
                url: '/login',
                parent: '',
                views: {
                    '@': {
                        templateUrl: '/modules/login/index.html'
                    }
                },
                resolve: new Dependency([
                    'modules/login/index'
                ]),
                authenticate: false
            },
            /* ======= Statusboard ======= */
            statusboard: {
                name: 'statusboard',
                url: '/statusboard',
                parent: 'root',
                views: {
                    '@': {
                        templateUrl: '/modules/statusboard/index.html'
                    }
                },
                resolve: new Dependency([
                    'modules/statusboard/index'
                ]),
                authenticate: true
            },
            /* ======= Settings ======= */
            settings_item: {
                name: 'settings_item',
                url: '/settings/item',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/item/list.html'
                    }
                },
                resolve: new Dependency([
                    'modules/item/list'
                ]),
                authenticate: true
            },
            settings_item_add: {
                name: 'settings_item_add',
                url: '/settings/item/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/item/add.html'
                    }
                },
                resolve: new Dependency([
                    'modules/item/add'
                ]),
                authenticate: true
            },
            settings_item_view: {
                name: 'settings_item_view',
                url: '/settings/item/:itemId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/item/view.html'
                    }
                },
                resolve: new Dependency([
                    'modules/item/view'
                ]),
                authenticate: true
            },
            settings_item_edit: {
                name: 'settings_item_edit',
                url: '/settings/item/:itemId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/item/edit.html'
                    }
                },
                resolve: new Dependency([
                    'modules/item/edit'
                ]),
                authenticate: true
            },
            /* ======= Settings Broker======= */
            settings_broker: {
                name: 'settings_broker',
                url: '/settings/broker',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/broker/list.html'
                    }
                },
                resolve: new Dependency([
                    'modules/broker/list'
                ]),
                authenticate: true
            },
            settings_broker_add: {
                name: 'settings_broker_add',
                url: '/settings/broker/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/broker/add.html'
                    }
                },
                resolve: new Dependency([
                    'modules/broker/add'
                ]),
                authenticate: true
            },
            settings_broker_view: {
                name: 'settings_broker_view',
                url: '/settings/broker/:brokerId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/broker/view.html'
                    }
                },
                resolve: new Dependency([
                    'modules/broker/view'
                ]),
                authenticate: true
            },
            settings_broker_edit: {
                name: 'settings_broker_edit',
                url: '/settings/broker/:brokerId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/broker/edit.html'
                    }
                },
                resolve: new Dependency([
                    'modules/broker/edit'
                ]),
                authenticate: true
            },

            /* ======= Settings Supplier ======= */
            settings_supplier: {
                name: 'settings_supplier',
                url: '/settings/supplier',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/supplier/list.html'
                    }
                },
                resolve: new Dependency([
                    'modules/supplier/list'
                ]),
                authenticate: true
            },
            settings_supplier_add: {
                name: 'settings_supplier_add',
                url: '/settings/supplier/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/supplier/add.html'
                    }
                },
                resolve: new Dependency([
                    'modules/supplier/add'
                ]),
                authenticate: true
            },
            settings_supplier_view: {
                name: 'settings_supplier_view',
                url: '/settings/supplier/:supplierId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/supplier/view.html'
                    }
                },
                resolve: new Dependency([
                    'modules/supplier/view'
                ]),
                authenticate: true
            },
            settings_supplier_edit: {
                name: 'settings_supplier_edit',
                url: '/settings/supplier/:supplierId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/supplier/edit.html'
                    }
                },
                resolve: new Dependency([
                    'modules/supplier/edit'
                ]),
                authenticate: true
            },
            /* ======= Settings Forwarder ======= */
            settings_forwarder: {
                name: 'settings_forwarder',
                url: '/settings/forwarder',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/forwarder/list.html'
                    }
                },
                resolve: new Dependency([
                   'modules/forwarder/list'
                ]),
                authenticate: true
            },
            settings_forwarder_add: {
                name: 'settings_forwarder_add',
                url: '/settings/forwarder/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/forwarder/add.html'
                    }
                },
                resolve: new Dependency([
                   'modules/forwarder/add'
                ]),
                authenticate: true
            },
            settings_forwarder_view: {
                name: 'settings_forwarder_view',
                url: '/settings/forwarder/:forwarderId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/forwarder/view.html'
                    }
                },
                resolve: new Dependency([
                   'modules/forwarder/view'
               ]),
                authenticate: true
            },
            settings_forwarder_edit: {
                name: 'settings_forwarder_edit',
                url: '/settings/forwarder/:forwarderId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/forwarder/edit.html'
                    }
                },
                resolve: new Dependency([
                   'modules/forwarder/edit'
                ]),
                authenticate: true
            },
            /* ======= Settings User ======= */
            settings_user: {
                name: 'settings_user',
                url: '/settings/user',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/user/list.html'
                    }
                },
                resolve: new Dependency([
                   'modules/user/list'
                ]),
                authenticate: true
            },
            settings_user_add: {
                name: 'settings_user_add',
                url: '/settings/user/add',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/user/add.html'
                    }
                },
                resolve: new Dependency([
                   'modules/user/add'
                ]),
                authenticate: true
            },
            settings_user_view: {
                name: 'settings_user_view',
                url: '/settings/user/:userId',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/user/view.html'
                    }
                },
                resolve: new Dependency([
                   'modules/user/view'
                ]),
                authenticate: true
            },
            settings_user_edit: {
                name: 'settings_user_edit',
                url: '/settings/user/:userId/edit',
                parent: 'settings',
                views: {
                    '@': {
                        templateUrl: '/modules/user/edit.html'
                    }
                },
                resolve: new Dependency([
                   'modules/user/edit'
                ]),
                authenticate: true
            },
             /* ======= Settings User ======= */
            initiate_import_planner: {
                name: 'initiate_import_planner',
                url: '/initiateimport/planner',
                parent: 'root',
                views: {
                    '@': {
                        templateUrl: '/modules/initiateimport/planner/list.html'
                    }
                },
                resolve: new Dependency([
                   'modules/initiateimport/planner/list'
                ]),
                authenticate: true
            }
        }
    };
});<|endoftext|>


<commit_before>/**
 * @ngdoc directive
 * @memberOf 'd3.cloud'
 * @name d3-cloud
 * @description
 *   Angular directive wrapping the d3-cloud library.
 *
 * @attr {Object}    events       Optional. An object with a property for each event callback function to be supported. Default: {}.
 * @attr {Function}  filter       Optional. A function that filters words. Takes words array and returns array of words which will be displayed. Default: returns array from parameter.
 * @attr {String}    font         Optional. The name of the font to use. Default: Impact.
 * @attr {Array}     ignoreList   Deprecated. Optional. An array of word names to ignore. Default: [].
 * @attr {Integer}   padding      Optional. The padding to apply between words. Default: 5.
 * @attr {Function}  rotate       Optional. A function reference that calculates rotation per word. Takes word object, and index in 'words' array. Default: alternating 45 degree left/right.
 * @attr {Integer}   slope-base   Optional. The minimum size for words. Default: 2.
 * @attr {Integer}   slope-factor Optional. The scale factor applied to scores. Default: 30.
 * @attr {Array}     words        A binding to an array of objects with name, score and optional color properties.
 *
 * @example
 *   <d3-cloud events="ctrl.wordEvents" font="Impact" filter="ctrl.filter" padding="5"
 *     rotate="ctrl.rotateWord" slope-base="2" slope-factor="30" words="ctrl.words">
 *   </d3-cloud>
 */

/* global d3 */
(function () {

  'use strict';

  angular.module('d3.cloud')
    .directive('d3Cloud', ['$log', d3CloudDirective]);

  d3CloudDirective.$inject = [];

  function d3CloudDirective($log) {
    return {
      restrict: 'E',
      replace: 'true',
      scope: {
        events: '=?',
        font: '@',
        ignoreList: '=?',
        filter: '&?',
        padding: '@',
        rotate: '&?',
        slopeBase: '@',
        slopeFactor: '@',
        words: '='
      },
      templateUrl: function () {
        return '/d3-cloud-ng/d3-cloud.html';
      },
      controller: 'd3CloudController',
      controllerAs: 'ctrl',
      link: function ($scope, $element, $attrs) {
        $scope.events = $scope.events || {};
        $scope.font = $scope.font || 'Impact';
        $scope.ignoreList = $scope.ignoreList || [];
        if ($scope.ignoreList.length > 0) {
          $log.warn('You are using deprecated ignoreList. Please use custom filter function instead.');
        }
        $scope.filter = $scope.filter || function (word) {
            return $scope.ignoreList.indexOf(word.name) === -1;
          };
        var padding = $attrs.padding ? Number($scope.padding) : 5;
        var rotate = $scope.rotate && function (d, i) {
            return $scope.rotate({word: $scope.words[i]});
          } || function () {
            return ~~(Math.random() * 2) * 90 - 45;
          };
        var slopeBase = $attrs.slopeBase ? Number($scope.slopeBase) : 2;
        var slopeFactor = $attrs.slopeFactor ? Number($scope.slopeFactor) : 30;

        $scope.createCloud = function (words) {
          var cloudWidth = $element[0].clientWidth + 0;
          var cloudHeight = $element[0].clientHeight + 0;
          var minScore = 0;
          var maxScore = 1;
          var slope = 1;

          words.map(function (d) {
            if (minScore > d.score) {
              minScore = d.score;
            }
            if (maxScore < d.score) {
              maxScore = d.score;
            }
          });

          if (maxScore !== minScore) {
            slope = slopeFactor / (maxScore - minScore);
          }

          $scope.cloud = d3.layout.cloud().size([cloudWidth, cloudHeight]);
          $scope.cloud
            .words(words.map(function (d) {
              var result = {
                text: d.name,
                size: d.score * slope + slopeBase
              };
              if (d.color) {
                result.color = d.color;
              }
              return result;
            }))
            .padding(padding)
            .rotate(rotate)
            .font($scope.font)
            .fontSize(function (d) {
              return d.size;
            })
            .on('end', draw)
            .start();
        };

        $scope.updateCloud = function (words) {

          var cloudHeight = $element[0].clientHeight + 0;
          var cloudWidth = $element[0].clientWidth + 0;
          var minScore = 0;
          var maxScore = 1;
          var slope = 1;

          words.map(function (d) {
            if (minScore > d.score) {
              minScore = d.score;
            }
            if (maxScore < d.score) {
              maxScore = d.score;
            }
          });

          if (maxScore !== minScore) {
            slope = slopeFactor / (maxScore - minScore);
          }

          $scope.cloud = d3.layout.cloud().size([cloudWidth, cloudHeight]);
          $scope.cloud
            .words(words.map(function (d) {
              var result = {
                text: d.name,
                size: d.score * slope + slopeBase
              };
              if (d.color) {
                result.color = d.color;
              }
              return result;
            }))
            .padding(padding)
            .rotate(rotate)
            .font($scope.font)
            .fontSize(function (d) {
              return d.size;
            })
            .on('end', update)
            .start();
        };

        if (!$scope.cloud && $scope.words && $scope.words.length) {
          $scope.createCloud($scope.words);
        }

        function update(data) {
          var size = $scope.cloud.size();
          var fill = (d3.schemeCategory20 ? d3.schemeCategory20 : d3.scale.category20());
          var words = d3.select($element[0]).select('svg')
            .selectAll('g')
            .attr('transform', 'translate(' + size[0] / 2 + ',' + size[1] / 2 + ')')
            .selectAll('text')
            .data(data);

          // append new text elements
          words.enter().append('text');

          // update all words in the word cloud (when you append
          // nodes from the 'enter' selection, d3 will add the new
          // nodes to the 'update' selection, thus all of them will
          // be updated here.
          words.style('font-size', function (d) {
            return d.size + 'px';
          })
            .style('font-family', $scope.font)
            .style('fill', function (d, i) {
              if (data[i].color) {
                return data[i].color;
              }
              return fill(i);
            })
            .attr('text-anchor', 'middle')
            .attr('transform', function (d) {
              return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')';
            })
            .on($scope.events)
            .text(function (d) {
              return d.text;
            });
          words.exit().remove(); // new line to remove all unused words
        }

        function draw(words) {
          var size = $scope.cloud.size();
          var fill = (d3.schemeCategory20 ? d3.schemeCategory20 : d3.scale.category20());
          d3.select($element[0]).append('svg')
            .attr('width', size[0])
            .attr('height', size[1])
            .append('g')
            .attr('transform', 'translate(' + size[0] / 2 + ',' + size[1] / 2 + ')')
            .selectAll('text')
            .data(words)
            .enter().append('text')
            .style('font-size', function (d) {
              return d.size + 'px';
            })
            .style('font-family', $scope.font)
            .style('fill', function (d, i) {
              if (words[i].color) {
                return words[i].color;
              }
              return fill(i);
            })
            .attr('text-anchor', 'middle')
            .attr('transform', function (d) {
              return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')';
            })
            .on($scope.events)
            .text(function (d) {
              return d.text;
            });
        }
      }
    };
  }

}());
<commit_msg>update filter function documentation<commit_after>/**
 * @ngdoc directive
 * @memberOf 'd3.cloud'
 * @name d3-cloud
 * @description
 *   Angular directive wrapping the d3-cloud library.
 *
 * @attr {Object}    events       Optional. An object with a property for each event callback function to be supported. Default: {}.
 * @attr {Function}  filter       Optional. A function that filters words. Takes word object and returns true if word should be shown otherwise returns false.
 * @attr {String}    font         Optional. The name of the font to use. Default: Impact.
 * @attr {Array}     ignoreList   Deprecated. Optional. An array of word names to ignore. Default: [].
 * @attr {Integer}   padding      Optional. The padding to apply between words. Default: 5.
 * @attr {Function}  rotate       Optional. A function reference that calculates rotation per word. Takes word object, and index in 'words' array. Default: alternating 45 degree left/right.
 * @attr {Integer}   slope-base   Optional. The minimum size for words. Default: 2.
 * @attr {Integer}   slope-factor Optional. The scale factor applied to scores. Default: 30.
 * @attr {Array}     words        A binding to an array of objects with name, score and optional color properties.
 *
 * @example
 *   <d3-cloud events="ctrl.wordEvents" font="Impact" filter="ctrl.filter" padding="5"
 *     rotate="ctrl.rotateWord" slope-base="2" slope-factor="30" words="ctrl.words">
 *   </d3-cloud>
 */

/* global d3 */
(function () {

  'use strict';

  angular.module('d3.cloud')
    .directive('d3Cloud', ['$log', d3CloudDirective]);

  d3CloudDirective.$inject = [];

  function d3CloudDirective($log) {
    return {
      restrict: 'E',
      replace: 'true',
      scope: {
        events: '=?',
        font: '@',
        ignoreList: '=?',
        filter: '&?',
        padding: '@',
        rotate: '&?',
        slopeBase: '@',
        slopeFactor: '@',
        words: '='
      },
      templateUrl: function () {
        return '/d3-cloud-ng/d3-cloud.html';
      },
      controller: 'd3CloudController',
      controllerAs: 'ctrl',
      link: function ($scope, $element, $attrs) {
        $scope.events = $scope.events || {};
        $scope.font = $scope.font || 'Impact';
        $scope.ignoreList = $scope.ignoreList || [];
        if ($scope.ignoreList.length > 0) {
          $log.warn('You are using deprecated ignoreList. Please use custom filter function instead.');
        }
        $scope.filter = $scope.filter || function (word) {
            return $scope.ignoreList.indexOf(word.name) === -1;
          };
        var padding = $attrs.padding ? Number($scope.padding) : 5;
        var rotate = $scope.rotate && function (d, i) {
            return $scope.rotate({word: $scope.words[i]});
          } || function () {
            return ~~(Math.random() * 2) * 90 - 45;
          };
        var slopeBase = $attrs.slopeBase ? Number($scope.slopeBase) : 2;
        var slopeFactor = $attrs.slopeFactor ? Number($scope.slopeFactor) : 30;

        $scope.createCloud = function (words) {
          var cloudWidth = $element[0].clientWidth + 0;
          var cloudHeight = $element[0].clientHeight + 0;
          var minScore = 0;
          var maxScore = 1;
          var slope = 1;

          words.map(function (d) {
            if (minScore > d.score) {
              minScore = d.score;
            }
            if (maxScore < d.score) {
              maxScore = d.score;
            }
          });

          if (maxScore !== minScore) {
            slope = slopeFactor / (maxScore - minScore);
          }

          $scope.cloud = d3.layout.cloud().size([cloudWidth, cloudHeight]);
          $scope.cloud
            .words(words.map(function (d) {
              var result = {
                text: d.name,
                size: d.score * slope + slopeBase
              };
              if (d.color) {
                result.color = d.color;
              }
              return result;
            }))
            .padding(padding)
            .rotate(rotate)
            .font($scope.font)
            .fontSize(function (d) {
              return d.size;
            })
            .on('end', draw)
            .start();
        };

        $scope.updateCloud = function (words) {

          var cloudHeight = $element[0].clientHeight + 0;
          var cloudWidth = $element[0].clientWidth + 0;
          var minScore = 0;
          var maxScore = 1;
          var slope = 1;

          words.map(function (d) {
            if (minScore > d.score) {
              minScore = d.score;
            }
            if (maxScore < d.score) {
              maxScore = d.score;
            }
          });

          if (maxScore !== minScore) {
            slope = slopeFactor / (maxScore - minScore);
          }

          $scope.cloud = d3.layout.cloud().size([cloudWidth, cloudHeight]);
          $scope.cloud
            .words(words.map(function (d) {
              var result = {
                text: d.name,
                size: d.score * slope + slopeBase
              };
              if (d.color) {
                result.color = d.color;
              }
              return result;
            }))
            .padding(padding)
            .rotate(rotate)
            .font($scope.font)
            .fontSize(function (d) {
              return d.size;
            })
            .on('end', update)
            .start();
        };

        if (!$scope.cloud && $scope.words && $scope.words.length) {
          $scope.createCloud($scope.words);
        }

        function update(data) {
          var size = $scope.cloud.size();
          var fill = (d3.schemeCategory20 ? d3.schemeCategory20 : d3.scale.category20());
          var words = d3.select($element[0]).select('svg')
            .selectAll('g')
            .attr('transform', 'translate(' + size[0] / 2 + ',' + size[1] / 2 + ')')
            .selectAll('text')
            .data(data);

          // append new text elements
          words.enter().append('text');

          // update all words in the word cloud (when you append
          // nodes from the 'enter' selection, d3 will add the new
          // nodes to the 'update' selection, thus all of them will
          // be updated here.
          words.style('font-size', function (d) {
            return d.size + 'px';
          })
            .style('font-family', $scope.font)
            .style('fill', function (d, i) {
              if (data[i].color) {
                return data[i].color;
              }
              return fill(i);
            })
            .attr('text-anchor', 'middle')
            .attr('transform', function (d) {
              return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')';
            })
            .on($scope.events)
            .text(function (d) {
              return d.text;
            });
          words.exit().remove(); // new line to remove all unused words
        }

        function draw(words) {
          var size = $scope.cloud.size();
          var fill = (d3.schemeCategory20 ? d3.schemeCategory20 : d3.scale.category20());
          d3.select($element[0]).append('svg')
            .attr('width', size[0])
            .attr('height', size[1])
            .append('g')
            .attr('transform', 'translate(' + size[0] / 2 + ',' + size[1] / 2 + ')')
            .selectAll('text')
            .data(words)
            .enter().append('text')
            .style('font-size', function (d) {
              return d.size + 'px';
            })
            .style('font-family', $scope.font)
            .style('fill', function (d, i) {
              if (words[i].color) {
                return words[i].color;
              }
              return fill(i);
            })
            .attr('text-anchor', 'middle')
            .attr('transform', function (d) {
              return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')';
            })
            .on($scope.events)
            .text(function (d) {
              return d.text;
            });
        }
      }
    };
  }

}());
<|endoftext|>