<commit_before>var CloudCmd, Util, DOM, CloudFunc, ace, DiffProto, diff_match_patch, Zip, MenuIO;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.Edit = EditProto;

    function EditProto() {
        var Name        = 'Edit',
            Loading     = false,
            DIR         = CloudCmd.LIBDIRCLIENT + 'edit/',
            LIBDIR      = CloudCmd.LIBDIR,
            Info        = DOM.CurrentInfo,
            Menu,
            Value,
            Edit        = this,
            Diff,
            Emmet,
            Ace,
            Session,
            Modelist,
            Msg,
            Events      = DOM.Events,
            RESTful     = DOM.RESTful,
            Dialog      = DOM.Dialog,
            Images      = DOM.Images,
            Element, JSHintConfig, EditConfig,
            ConfigView  = {
                beforeClose: function() {
                    isChanged();

                    if (Menu)
                        Menu.hide();
                },
                afterShow: function() {
                    Ace.clearSelection();
                    Ace.moveCursorTo(0, 0);
                    Ace.focus();
                }
            };

       function init() {
            Loading   = true;
            Util.exec.series([
                CloudCmd.View,
                load,
                Edit.show
            ]);
        }

        this.show                       = function(value) {
            var mode, htmlMode, jsMode, isHTML, isJS, modesByName,
                isStr       = Util.isString(value),
                name        = Info.name,
                isDir       = Info.isDir;

            if (!Loading) {
                Images.showLoad();

                if (!Element) {
                    Element         = DOM.load({
                        name        : 'div',
                        style   :
                            'width      : 100%;'    +
                            'height     : 100%;'    +
                            'font       : 16px "Droid Sans Mono";' +
                            'position   : absolute;',
                        notAppend : true
                    });

                    initAce();

                    Events.add(Element, {
                            contextmenu :   setMenu,
                            drop        :   onDrop,
                            dragover    :   Events.preventDefault
                        });
                }

                modesByName = Modelist.modesByName;

                if (isDir)
                    mode    = modesByName.json.mode;
                else
                    mode    = Modelist.getModeForPath(name).mode;

                htmlMode    = modesByName.html.mode;
                jsMode      = modesByName.javascript.mode;

                isHTML      = mode === htmlMode;
                isJS        = mode === jsMode;

                Session.setMode(mode);
                setUseOfWorker(mode);
                setEmmet(isHTML);

                Util.exec.if(isStr, function() {
                    var UndoManager = ace.require('ace/undomanager').UndoManager;

                    Ace.setValue(Value);
                    CloudCmd.View.show(Element, ConfigView);

                    Session.setUndoManager(new UndoManager());
                }, function(callback) {
                    Info.getData(function(error, data) {
                        Value = data;

                        if (isJS && Session.getUseWorker())
                            setJsHintConfig();

                        callback();
                    });
                });
            }
        };

        this.hide                       =  function() {
            CloudCmd.View.hide();
        };

        this.goToLine                   = function() {
            var msg     = 'Enter line number:',
                cursor  = Ace.selection.getCursor(),
                number  = cursor.row + 1,
                line    = Dialog.prompt(msg, number);

            number      = line - 0;

            if (number)
                Ace.gotoLine(number);
        };

        function isChanged() {
            var is,
                value   = Ace.getValue(),
                isEqual = value === Value,
                msg     = 'Do you want to save changes to ' + name + '?';

            if (!isEqual) {
                is = Dialog.confirm(msg);

                if (is)
                    save();
            }
        }

        function setEmmet(isHTML) {
            getEditConfig(function(config) {
                var extensions  = config.extensions,
                    isEmmet     = extensions.emmet;

                if (isEmmet)
                    Util.exec.if(Emmet, function() {
                            if (Emmet)
                                Ace.setOption('enableEmmet', isHTML);
                        }, function(callback) {
                            var url;

                            if (!isHTML)
                                Util.exec(callback);
                            else {
                                url = CloudFunc.getJoinURL([
                                    DIR + 'emmet.js',
                                    DIR + 'ext-emmet.js'
                                ]);

                                DOM.load.js(url, function() {
                                    Emmet = ace.require('ace/ext/emmet');
                                    Emmet.setCore(window.emmet);
                                    Util.exec(callback);
                                });
                            }
                        });
                });
        }

        function setUseOfWorker(mode) {
            var isMatch,
                isStr   = Util.isString(mode),
                regStr  = 'coffee|css|html|javascript|json|lua|php|xquery',
                regExp  = new RegExp(regStr);

            if (isStr)
                isMatch = mode.match(regExp);

            Session.setUseWorker(isMatch);
        }

        function initAce() {
            Ace     = ace.edit(Element);
            Session = Ace.getSession();

            Ace.commands.addCommand({
                name    : 'hide',
                bindKey : { win: 'Esc',  mac: 'Esc' },
                exec    : function () {
                    Edit.hide();
                }
            });

            Ace.commands.addCommand({
                name    : 'goToLine',
                bindKey : { win: 'Ctrl-G',  mac: 'Command-G' },
                exec    : function () {
                    Edit.goToLine();
                }
            });

            Ace.commands.addCommand({
                name    : 'save',
                bindKey : { win: 'Ctrl-S',  mac: 'Command-S' },
                exec    : save
            });

            Ace.commands.addCommand({
                name    : 'saveMC',
                bindKey : { win: 'F2',  mac: 'F2' },
                exec    : save
            });

            ace.require('ace/ext/language_tools');
            Modelist = ace.require('ace/ext/modelist');

            getEditConfig(function(config) {
                var options      = config.options;

                Ace.setOptions(options);
            });
        }

        function save () {
            var path    = Info.path,
                value   = Ace.getValue();

            CloudCmd.getConfig(function(error, config) {
                var isDiff      = config.diff,
                    isZip       = config.zip;

                Util.exec.if(!isDiff, function(patch) {
                    var query           = '',
                        MAX_SIZE        = CloudFunc.MAX_FILE_SIZE,
                        patchLength     = patch.length,
                        length          = Value.length,
                        isLessMaxLength = length < MAX_SIZE,
                        isLessLength    = isLessMaxLength && patchLength < length,
                        isStr           = Util.isString(patch);

                    Value               = value;

                    if (isStr && patch && isLessLength)
                        query           = '?patch';
                    else
                        patch           = false;

                    Util.exec.if(!isZip || query, function(equal, data) {
                        var result  = data || patch || Value,
                            url     = path + query;

                        RESTful.write(url, result , onSave);
                    }, function(func) {
                        zip(value, function(error, data) {
                            if (error)
                                Util.log(error);

                            query = '?unzip';
                            func(null, data);
                        });
                    });

                }, Util.exec.with(doDiff, path));
            });
        }

        function doDiff(path, callback) {
            var value = Ace.getValue();

            diff(value, function(patch) {
                var isAllowed = DOM.Storage.isAllowed();

                Util.exec.if(!isAllowed, callback, function(func) {
                        DOM.checkStorageHash(path, function(error, equal) {
                            if (!equal)
                                patch = '';

                            func(patch);
                        });
                });
            });
        }

        function diff(newValue, callback) {
            var libs            = [
                    LIBDIR + 'diff/diff-match-patch.js',
                    LIBDIR + 'diff.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.load.js(url, function(error) {
                var patch,
                    isAllowed   = DOM.Storage.isAllowed();

                if (error) {
                    Dialog.alert(error);
                } else {
                    if (!Diff)
                        Diff        = new DiffProto(diff_match_patch);

                    Util.exec.if(!isAllowed, function() {
                        patch       = Diff.createPatch(Value, newValue);
                        Util.exec(callback, patch);
                    }, function(func) {
                        var path = Info.path;

                        DOM.getDataFromStorage(path, function(error, data) {
                            if (data)
                                Value   = data;

                            func();
                        });
                    });
                }
            });
        }

        function zip(value, callback) {
            var dir             = CloudCmd.LIBDIRCLIENT,
                libs            = [
                    dir + 'zip/dist/pako.js',
                    dir + 'zip.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.load.js(url, function() {
                Zip.pack(value, callback);
            });
        }

        function setJsHintConfig(callback) {
            var JSHINT_PATH = '/.jshintrc',
                func        = function() {
                    var worker  = Session.$worker;

                    if (worker)
                        worker.send('changeOptions', [JSHintConfig]);

                    Util.exec(callback);
                };

            Util.exec.if(JSHintConfig, func, function() {
                DOM.load.ajax({
                    url     :  JSHINT_PATH,
                    success : function(data) {
                        JSHintConfig = Util.parseJSON(data);
                        func();
                    }
                });
            });
        }

        function getEditConfig(callback) {
            var CONFIG_PATH = '/json/edit.json',
                func        = Util.exec.ret(callback);

            Util.exec.if(EditConfig, function() {
                func(EditConfig);
            }, function() {
                DOM.load.ajax({
                    url     : CONFIG_PATH,
                    success : function(data) {
                        EditConfig = data;
                        func(EditConfig);
                    }
                });
            });
        }

        function setMenu() {
            if (!Menu) {
                DOM.loadMenu(function(error) {
                    var position    = CloudCmd.MousePosition,
                        options     = {
                            beforeShow: function(params) {
                                params.x -= 18;
                                params.y -= 27;
                            },
                            afterClick: function() {
                                Ace.focus();
                            }
                    },
                    menuData    = {
                        'Save           Ctrl+S' : save,
                        'Go To Line     Ctrl+G' : function() {
                            Edit.goToLine();
                        },
                        'Select All     Ctrl+A' : function() {
                            Ace.selectAll();
                        },
                        'Delete         Del'    : function() {
                            Ace.remove('right');
                        },
                        'Close          Esc'    : Edit.hide
                    };

                    if (error) {
                        Dialog.alert(error);
                    } else if (!Menu) {
                        Menu        = new MenuIO(Element, options, menuData);
                        Menu.show(position.x, position.y);

                        Events.remove('contextMenu', Element, setMenu);
                    }
                });
            }
        }

        function load(callback) {
            var url     = CloudFunc.getJoinURL([
                    DIR + 'theme-tomorrow_night_blue.js',
                    DIR + 'ext-language_tools.js',
                    DIR + 'ext-searchbox.js',
                    DIR + 'ext-modelist.js'
                ]);

            Util.time(Name + ' load');

            DOM.loadRemote('ace', function() {
                DOM.load.js([url], function() {
                    Loading = false;

                    Util.timeEnd(Name + ' load');
                    Util.exec(callback);
                });

                DOM.load.style({
                    id      : 'msg-css',
                    inner   : '#js-view .msg {'     +
                                'z-index'           + ': 1;'                    +
                                'background-color'  + ': #7285B7;'              +
                                'color'             + ': #D1F1A9;'              +
                                'position'          + ': fixed;'                +
                                'left'              + ': 40%;'                  +
                                'top'               + ': 25px;'                 +
                                'padding'           + ': 5px;'                  +
                                'opacity'           + ': 0.9;'                  +
                                'transition'        + ': ease 0.5s;'            +
                            '}'
                });
            });
        }

        function onSave(text) {
            var ret,
                isError = Util.isContainStrAtBegin(text, 'error'),
                path    = Info.path,
                msg     = '\nShould I save file anyway?';

            if (!isError) {
                Edit.showMessage(text);
                DOM.saveDataToStorage(path, Value);
                DOM.setCurrentSize(Value.length);
            } else {
                ret     = Dialog.confirm(text + msg);

                if (ret)
                    RESTful.write(path, Value, onSave);
            }
        }

         function onDrop(event) {
            var reader, files,
                onLoad   =  function(event) {
                    var data    = event.target.result;

                    Ace.setValue(data);
                };

            event.preventDefault();

            files   = event.dataTransfer.files;

            Util.forEach(files, function(file) {
                reader  = new FileReader();
                Events.addLoad(reader, onLoad);
                reader.readAsBinaryString(file);
            });
        }

        this.showMessage    = function(text) {
            var msg, HIDE_TIME = 2000;

            /*
             * Msg should be created and removed
             * if it's not and just inner text
             * is changing, and hide and show of DOM
             * is called - bug occures: empty box
             * with no text inside.
             */
            msg = DOM.load({
                name        : 'div',
                className   : 'msg',
                parent      : Element,
                inner       : text,
                func        : alert
            });

            setTimeout(function() {
                DOM.remove(msg, Element);
            }, HIDE_TIME);
        };

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<commit_msg>chore(edit) rm Msg<commit_after>var CloudCmd, Util, DOM, CloudFunc, ace, DiffProto, diff_match_patch, Zip, MenuIO;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.Edit = EditProto;

    function EditProto() {
        var Name        = 'Edit',
            Loading     = false,
            DIR         = CloudCmd.LIBDIRCLIENT + 'edit/',
            LIBDIR      = CloudCmd.LIBDIR,
            Info        = DOM.CurrentInfo,
            Menu,
            Value,
            Edit        = this,
            Diff,
            Emmet,
            Ace,
            Session,
            Modelist,
            Events      = DOM.Events,
            RESTful     = DOM.RESTful,
            Dialog      = DOM.Dialog,
            Images      = DOM.Images,
            Element, JSHintConfig, EditConfig,
            ConfigView  = {
                beforeClose: function() {
                    isChanged();

                    if (Menu)
                        Menu.hide();
                },
                afterShow: function() {
                    Ace.clearSelection();
                    Ace.moveCursorTo(0, 0);
                    Ace.focus();
                }
            };

       function init() {
            Loading   = true;
            Util.exec.series([
                CloudCmd.View,
                load,
                Edit.show
            ]);
        }

        this.show                       = function(value) {
            var mode, htmlMode, jsMode, isHTML, isJS, modesByName,
                isStr       = Util.isString(value),
                name        = Info.name,
                isDir       = Info.isDir;

            if (!Loading) {
                Images.showLoad();

                if (!Element) {
                    Element         = DOM.load({
                        name        : 'div',
                        style   :
                            'width      : 100%;'    +
                            'height     : 100%;'    +
                            'font       : 16px "Droid Sans Mono";' +
                            'position   : absolute;',
                        notAppend : true
                    });

                    initAce();

                    Events.add(Element, {
                            contextmenu :   setMenu,
                            drop        :   onDrop,
                            dragover    :   Events.preventDefault
                        });
                }

                modesByName = Modelist.modesByName;

                if (isDir)
                    mode    = modesByName.json.mode;
                else
                    mode    = Modelist.getModeForPath(name).mode;

                htmlMode    = modesByName.html.mode;
                jsMode      = modesByName.javascript.mode;

                isHTML      = mode === htmlMode;
                isJS        = mode === jsMode;

                Session.setMode(mode);
                setUseOfWorker(mode);
                setEmmet(isHTML);

                Util.exec.if(isStr, function() {
                    var UndoManager = ace.require('ace/undomanager').UndoManager;

                    Ace.setValue(Value);
                    CloudCmd.View.show(Element, ConfigView);

                    Session.setUndoManager(new UndoManager());
                }, function(callback) {
                    Info.getData(function(error, data) {
                        Value = data;

                        if (isJS && Session.getUseWorker())
                            setJsHintConfig();

                        callback();
                    });
                });
            }
        };

        this.hide                       =  function() {
            CloudCmd.View.hide();
        };

        this.goToLine                   = function() {
            var msg     = 'Enter line number:',
                cursor  = Ace.selection.getCursor(),
                number  = cursor.row + 1,
                line    = Dialog.prompt(msg, number);

            number      = line - 0;

            if (number)
                Ace.gotoLine(number);
        };

        function isChanged() {
            var is,
                value   = Ace.getValue(),
                isEqual = value === Value,
                msg     = 'Do you want to save changes to ' + name + '?';

            if (!isEqual) {
                is = Dialog.confirm(msg);

                if (is)
                    save();
            }
        }

        function setEmmet(isHTML) {
            getEditConfig(function(config) {
                var extensions  = config.extensions,
                    isEmmet     = extensions.emmet;

                if (isEmmet)
                    Util.exec.if(Emmet, function() {
                            if (Emmet)
                                Ace.setOption('enableEmmet', isHTML);
                        }, function(callback) {
                            var url;

                            if (!isHTML)
                                Util.exec(callback);
                            else {
                                url = CloudFunc.getJoinURL([
                                    DIR + 'emmet.js',
                                    DIR + 'ext-emmet.js'
                                ]);

                                DOM.load.js(url, function() {
                                    Emmet = ace.require('ace/ext/emmet');
                                    Emmet.setCore(window.emmet);
                                    Util.exec(callback);
                                });
                            }
                        });
                });
        }

        function setUseOfWorker(mode) {
            var isMatch,
                isStr   = Util.isString(mode),
                regStr  = 'coffee|css|html|javascript|json|lua|php|xquery',
                regExp  = new RegExp(regStr);

            if (isStr)
                isMatch = mode.match(regExp);

            Session.setUseWorker(isMatch);
        }

        function initAce() {
            Ace     = ace.edit(Element);
            Session = Ace.getSession();

            Ace.commands.addCommand({
                name    : 'hide',
                bindKey : { win: 'Esc',  mac: 'Esc' },
                exec    : function () {
                    Edit.hide();
                }
            });

            Ace.commands.addCommand({
                name    : 'goToLine',
                bindKey : { win: 'Ctrl-G',  mac: 'Command-G' },
                exec    : function () {
                    Edit.goToLine();
                }
            });

            Ace.commands.addCommand({
                name    : 'save',
                bindKey : { win: 'Ctrl-S',  mac: 'Command-S' },
                exec    : save
            });

            Ace.commands.addCommand({
                name    : 'saveMC',
                bindKey : { win: 'F2',  mac: 'F2' },
                exec    : save
            });

            ace.require('ace/ext/language_tools');
            Modelist = ace.require('ace/ext/modelist');

            getEditConfig(function(config) {
                var options      = config.options;

                Ace.setOptions(options);
            });
        }

        function save () {
            var path    = Info.path,
                value   = Ace.getValue();

            CloudCmd.getConfig(function(error, config) {
                var isDiff      = config.diff,
                    isZip       = config.zip;

                Util.exec.if(!isDiff, function(patch) {
                    var query           = '',
                        MAX_SIZE        = CloudFunc.MAX_FILE_SIZE,
                        patchLength     = patch.length,
                        length          = Value.length,
                        isLessMaxLength = length < MAX_SIZE,
                        isLessLength    = isLessMaxLength && patchLength < length,
                        isStr           = Util.isString(patch);

                    Value               = value;

                    if (isStr && patch && isLessLength)
                        query           = '?patch';
                    else
                        patch           = false;

                    Util.exec.if(!isZip || query, function(equal, data) {
                        var result  = data || patch || Value,
                            url     = path + query;

                        RESTful.write(url, result , onSave);
                    }, function(func) {
                        zip(value, function(error, data) {
                            if (error)
                                Util.log(error);

                            query = '?unzip';
                            func(null, data);
                        });
                    });

                }, Util.exec.with(doDiff, path));
            });
        }

        function doDiff(path, callback) {
            var value = Ace.getValue();

            diff(value, function(patch) {
                var isAllowed = DOM.Storage.isAllowed();

                Util.exec.if(!isAllowed, callback, function(func) {
                        DOM.checkStorageHash(path, function(error, equal) {
                            if (!equal)
                                patch = '';

                            func(patch);
                        });
                });
            });
        }

        function diff(newValue, callback) {
            var libs            = [
                    LIBDIR + 'diff/diff-match-patch.js',
                    LIBDIR + 'diff.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.load.js(url, function(error) {
                var patch,
                    isAllowed   = DOM.Storage.isAllowed();

                if (error) {
                    Dialog.alert(error);
                } else {
                    if (!Diff)
                        Diff        = new DiffProto(diff_match_patch);

                    Util.exec.if(!isAllowed, function() {
                        patch       = Diff.createPatch(Value, newValue);
                        Util.exec(callback, patch);
                    }, function(func) {
                        var path = Info.path;

                        DOM.getDataFromStorage(path, function(error, data) {
                            if (data)
                                Value   = data;

                            func();
                        });
                    });
                }
            });
        }

        function zip(value, callback) {
            var dir             = CloudCmd.LIBDIRCLIENT,
                libs            = [
                    dir + 'zip/dist/pako.js',
                    dir + 'zip.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.load.js(url, function() {
                Zip.pack(value, callback);
            });
        }

        function setJsHintConfig(callback) {
            var JSHINT_PATH = '/.jshintrc',
                func        = function() {
                    var worker  = Session.$worker;

                    if (worker)
                        worker.send('changeOptions', [JSHintConfig]);

                    Util.exec(callback);
                };

            Util.exec.if(JSHintConfig, func, function() {
                DOM.load.ajax({
                    url     :  JSHINT_PATH,
                    success : function(data) {
                        JSHintConfig = Util.parseJSON(data);
                        func();
                    }
                });
            });
        }

        function getEditConfig(callback) {
            var CONFIG_PATH = '/json/edit.json',
                func        = Util.exec.ret(callback);

            Util.exec.if(EditConfig, function() {
                func(EditConfig);
            }, function() {
                DOM.load.ajax({
                    url     : CONFIG_PATH,
                    success : function(data) {
                        EditConfig = data;
                        func(EditConfig);
                    }
                });
            });
        }

        function setMenu() {
            if (!Menu) {
                DOM.loadMenu(function(error) {
                    var position    = CloudCmd.MousePosition,
                        options     = {
                            beforeShow: function(params) {
                                params.x -= 18;
                                params.y -= 27;
                            },
                            afterClick: function() {
                                Ace.focus();
                            }
                    },
                    menuData    = {
                        'Save           Ctrl+S' : save,
                        'Go To Line     Ctrl+G' : function() {
                            Edit.goToLine();
                        },
                        'Select All     Ctrl+A' : function() {
                            Ace.selectAll();
                        },
                        'Delete         Del'    : function() {
                            Ace.remove('right');
                        },
                        'Close          Esc'    : Edit.hide
                    };

                    if (error) {
                        Dialog.alert(error);
                    } else if (!Menu) {
                        Menu        = new MenuIO(Element, options, menuData);
                        Menu.show(position.x, position.y);

                        Events.remove('contextMenu', Element, setMenu);
                    }
                });
            }
        }

        function load(callback) {
            var url     = CloudFunc.getJoinURL([
                    DIR + 'theme-tomorrow_night_blue.js',
                    DIR + 'ext-language_tools.js',
                    DIR + 'ext-searchbox.js',
                    DIR + 'ext-modelist.js'
                ]);

            Util.time(Name + ' load');

            DOM.loadRemote('ace', function() {
                DOM.load.js([url], function() {
                    Loading = false;

                    Util.timeEnd(Name + ' load');
                    Util.exec(callback);
                });

                DOM.load.style({
                    id      : 'msg-css',
                    inner   : '#js-view .msg {'     +
                                'z-index'           + ': 1;'                    +
                                'background-color'  + ': #7285B7;'              +
                                'color'             + ': #D1F1A9;'              +
                                'position'          + ': fixed;'                +
                                'left'              + ': 40%;'                  +
                                'top'               + ': 25px;'                 +
                                'padding'           + ': 5px;'                  +
                                'opacity'           + ': 0.9;'                  +
                                'transition'        + ': ease 0.5s;'            +
                            '}'
                });
            });
        }

        function onSave(text) {
            var ret,
                isError = Util.isContainStrAtBegin(text, 'error'),
                path    = Info.path,
                msg     = '\nShould I save file anyway?';

            if (!isError) {
                Edit.showMessage(text);
                DOM.saveDataToStorage(path, Value);
                DOM.setCurrentSize(Value.length);
            } else {
                ret     = Dialog.confirm(text + msg);

                if (ret)
                    RESTful.write(path, Value, onSave);
            }
        }

         function onDrop(event) {
            var reader, files,
                onLoad   =  function(event) {
                    var data    = event.target.result;

                    Ace.setValue(data);
                };

            event.preventDefault();

            files   = event.dataTransfer.files;

            Util.forEach(files, function(file) {
                reader  = new FileReader();
                Events.addLoad(reader, onLoad);
                reader.readAsBinaryString(file);
            });
        }

        this.showMessage    = function(text) {
            var msg, HIDE_TIME = 2000;

            /*
             * Msg should be created and removed
             * if it's not and just inner text
             * is changing, and hide and show of DOM
             * is called - bug occures: empty box
             * with no text inside.
             */
            msg = DOM.load({
                name        : 'div',
                className   : 'msg',
                parent      : Element,
                inner       : text,
                func        : alert
            });

            setTimeout(function() {
                DOM.remove(msg, Element);
            }, HIDE_TIME);
        };

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<|endoftext|>


<commit_before>var Stream = require('./stream');
var Socket = require('./socket');
var utils = require('./utils');

// export event emitter object (clone before use!)
module.exports = {

    /**
     * Call handlers of a specific event or pipe if handler is a stream.
     *
     * @public
     * @param {string} The event name.
     * @param {object} The data for the event handlers.
     */
    flow: function (eventName, readable, writable, context) {
        var events = this._events;

        context = context || {};

        // create streams
        var stream = Stream.Duplex(this, readable, writable);

        // compare event or test regex
        if (events[eventName]) {

            // index for events that must be removed
            var obsoleteEvents = [];

            // call handlers
            for (var i = 0, l = events[eventName].length; i < l; ++i) {
                config = events[eventName][i];

                if (config) {

                    // pass stream to flow to setup handlers
                    Flow.call(this, stream, config, context);

                    // remove from event buffer, if once is true
                    if (config['1']) {
                        config = undefined;
                        obsoleteEvents.push([eventName, i]);
                    }
                }
            }

            // remove obsolete events
            this._rm(obsoleteEvents);
        }

        // return transmitter to send and receive data
        return stream;
    },

    /**
     * Listen on an event.
     *
     * @public
     * @param {string} The even name regular expression pattern.
     * @param {function} The event handler.
     * @param {boolean} Event handler is removed after calling.
     * @param {boolean} If an event is emitted from the route method, the event
     *                  loop stops, when an event is found. This argument tells the
     *                  event loop to continue.
     */
    on: function (eventName, config) {

        var events = this._events;

        if (!events[eventName]) {
            events[eventName] = [];
        }

        events[eventName].push(config);
    },

    /**
     * Remove an event or a single event hanlder from the event loop.
     *
     * @public
     * @param {string} The even name regular expression pattern.
     * @param {function} The event handler.
     */
    off: function (event, config) {

        var events = this._events;

        if (events[event]) {

            if (config) {
                var rm = [];

                // TODO config is an object, how to compare?
                for (var i = 0; i < events[event].length; ++i) {
                    if (events[event][i] === config) {
                        events[event][i] = undefined;
                        rm.push([event, i]);
                    }
                }

                this._rm(rm);

            } else {
                delete events[event];
            }
        }
    },

    /**
     * Removes the collected events from an observable.
     *
     * @private
     * @param {object} The events of an observable.
     * @param {array} The infos for removing events.
     */
    _rm: function (rmObject) {

        if (rmObject.length) {
            var events = this._events;
            for (var i = 0, l = rmObject.length; i < l; ++i) {

                // remove handler
                events[rmObject[i][0]].splice(rmObject[i][1], 1);

                // remove event
                if (events[rmObject[i][0]].length === 0) {
                    delete events[rmObject[i][0]];
                }
            }
        }
    }
};

/**
 * Create a new config event handler.
 *
 * @public
 * @param {object} The module instance.
 * @param {object} The "out" config.
 * @param {object} The adapter object (optional).
 */
function Flow (originStream, config, context, adapter) {
    var module_instance = this;

    // handle "to" config
    if (typeof config.to === 'string') {

        // get target module instance, or continue if not found
        // and check module instance acces for server side
        if (
            (!(module_instance = engine.instances[config.to])) ||
            (
                originStream[engine.session_role] &&
                !utils.roleAccess(
                    module_instance,
                    originStream[engine.session_role]
                )
            )
        ) {
            return console.error('Flow target instance "' + config.to + '" is not found.');
        }
    }

    // create a duplex stream for every event
    var stream = Stream.Duplex(module_instance);

    // pipe duplex streams in both directions
    stream.pipe(originStream).pipe(stream);

    // add data handler to stream
    if (
        config.data instanceof Array &&
        (config.data[0] = getMethodFromPath(config.data[0], module_instance))
    ) {
        stream.data(config.data[0], config.data[1]);
    }

    // emit stream to other flow handlers
    if (typeof config.emit === 'string') {
        module_instance.flow(config.emit, stream, context);
    }

    // pass stream to receiver function
    if (config.call) {

        // call event over network
        if (typeof config.call === 'string' && config.call.indexOf('/') > -1) {
            Socket.send.call(module_instance, config.call);

        // call local method
        } else if ((config.call = getMethodFromPath(config.call, module_instance))) {
            config.call.call(module_instance, stream, context, config);
        }
    }
}

/**
 * Return a function or undefined.
 */
function getMethodFromPath (path, module_instance) {

    var _path;

    if (
        typeof path === 'string' &&
        typeof (_path = utils.path(path, [engine.handlers, module_instance, global])) !== 'function'
    ) {
        console.error('Flow method is not a function. Value for "' + path + '" is:', _path);
        return;
    }

    if (typeof path === 'function') {
        return path;
    }
}
<commit_msg>flow emitter just handles event streams<commit_after>var Stream = require('./stream');
var Socket = require('./socket');
var utils = require('./utils');

// export event emitter object (clone before use!)
module.exports = {

    /**
     * Call handlers of a specific event or pipe if handler is a stream.
     *
     * @public
     * @param {string} The event name.
     * @param {object} The data for the event handlers.
     */
    flow: function (eventName, context) {
        var events = this._events;

        context = context || {};

        // create streams
        var stream = Stream(this);

        // compare event or test regex
        if (events[eventName]) {

            // index for events that must be removed
            var obsoleteEvents = [];

            // call handlers
            for (var i = 0, l = events[eventName].length; i < l; ++i) {
                config = events[eventName][i];

                if (config) {

                    // pass stream to flow to setup handlers
                    Flow.call(this, stream, config, context);

                    // remove from event buffer, if once is true
                    if (config['1']) {
                        config = undefined;
                        obsoleteEvents.push([eventName, i]);
                    }
                }
            }

            // remove obsolete events
            this._rm(obsoleteEvents);
        }

        // return transmitter to send and receive data
        return stream;
    },

    /**
     * Listen on an event.
     *
     * @public
     * @param {string} The even name regular expression pattern.
     * @param {function} The event handler.
     * @param {boolean} Event handler is removed after calling.
     * @param {boolean} If an event is emitted from the route method, the event
     *                  loop stops, when an event is found. This argument tells the
     *                  event loop to continue.
     */
    on: function (eventName, config) {

        var events = this._events;

        if (!events[eventName]) {
            events[eventName] = [];
        }

        events[eventName].push(config);
    },

    /**
     * Remove an event or a single event hanlder from the event loop.
     *
     * @public
     * @param {string} The even name regular expression pattern.
     * @param {function} The event handler.
     */
    off: function (event, config) {

        var events = this._events;

        if (events[event]) {

            if (config) {
                var rm = [];

                // TODO config is an object, how to compare?
                for (var i = 0; i < events[event].length; ++i) {
                    if (events[event][i] === config) {
                        events[event][i] = undefined;
                        rm.push([event, i]);
                    }
                }

                this._rm(rm);

            } else {
                delete events[event];
            }
        }
    },

    /**
     * Removes the collected events from an observable.
     *
     * @private
     * @param {object} The events of an observable.
     * @param {array} The infos for removing events.
     */
    _rm: function (rmObject) {

        if (rmObject.length) {
            var events = this._events;
            for (var i = 0, l = rmObject.length; i < l; ++i) {

                // remove handler
                events[rmObject[i][0]].splice(rmObject[i][1], 1);

                // remove event
                if (events[rmObject[i][0]].length === 0) {
                    delete events[rmObject[i][0]];
                }
            }
        }
    }
};

/**
 * Create a new config event handler.
 *
 * @public
 * @param {object} The module instance.
 * @param {object} The "out" config.
 * @param {object} The adapter object (optional).
 */
function Flow (originStream, config, context, adapter) {
    var module_instance = this;

    // handle "to" config
    if (typeof config.to === 'string') {

        // get target module instance, or continue if not found
        // and check module instance acces for server side
        if (
            (!(module_instance = engine.instances[config.to])) ||
            (
                originStream[engine.session_role] &&
                !utils.roleAccess(
                    module_instance,
                    originStream[engine.session_role]
                )
            )
        ) {
            return console.error('Flow target instance "' + config.to + '" is not found.');
        }
    }

    // create a duplex stream for every event
    var stream = Stream(module_instance);

    // TODO
    // * if the origin stream ends, destroy all event streams
    // * if an event stream ends, destroy origin stream,
    //   if no other event streams are open

    // pipe duplex streams in both directions
    stream.pipe(originStream).pipe(stream);

    // add data handler to stream
    if (
        config.data instanceof Array &&
        (config.data[0] = getMethodFromPath(config.data[0], module_instance))
    ) {
        stream.data(config.data[0], config.data[1]);
    }

    // emit stream to other flow handlers
    if (typeof config.emit === 'string') {
        module_instance.flow(config.emit, stream, context);
    }

    // pass stream to receiver function
    if (config.call) {

        // call event over network
        if (typeof config.call === 'string' && config.call.indexOf('/') > -1) {
            Socket.send.call(module_instance, config.call);

        // call local method
        } else if ((config.call = getMethodFromPath(config.call, module_instance))) {
            config.call.call(module_instance, stream, context, config);
        }
    }
}

/**
 * Return a function or undefined.
 */
function getMethodFromPath (path, module_instance) {

    var _path;

    if (
        typeof path === 'string' &&
        typeof (_path = utils.path(path, [engine.handlers, module_instance, global])) !== 'function'
    ) {
        console.error('Flow method is not a function. Value for "' + path + '" is:', _path);
        return;
    }

    if (typeof path === 'function') {
        return path;
    }
}
<|endoftext|>


<commit_before>var CloudCmd, Util, DOM, CloudFunc, $;

(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.View = ViewProto;

    function ViewProto(CallBack) {
        var Name        = 'View',
            Loading     = false,
            FocusWas    = false,
            Events      = DOM.Events,
            Info        = DOM.CurrentInfo,
            Key         = CloudCmd.Key,
            Images      = DOM.Images,
            View        = Util.exec.bind(Util),
            Element, TemplateAudio, Overlay,
            Config      = {
                beforeShow      : function(callback) {
                    Images.hide();
                    Key.unsetBind();
                    showOverlay();
                    Util.exec(callback);
                },
                beforeClose     : function(callback) {
                    Key.setBind();
                    Util.exec(callback);
                    hideOverlay();
                },
                afterShow       : function(callback) {
                    if (!FocusWas) {
                        Element.focus();
                        FocusWas = true;
                    }

                    Util.exec(callback);
                },
                afterClose      : function(callback) {
                    FocusWas = false;

                    Util.exec(callback);
                },
                fitToView       : true,
                loop            : false,
                openEffect      : 'none',
                closeEffect     : 'none',
                autoSize        : false,
                height          : '100%',
                width           : '100%',
                minWidth        : 0,
                minHeight       : 0,
                padding         : 0,
                preload         : 0,
                keys            : null,
                mouseWheel      : false,
                arrows          : false,
                helpers         : {
                    overlay : null,
                    title   : null
                }
            };

        View.show   = show;
        View.hide   = hide;

        function init() {
            var func = CallBack || Util.exec.with(show, null);

            Loading = true;

            Util.exec.series([
                DOM.loadJquery,
                load,
                function(callback) {
                    Loading = false;
                    Util.exec(callback);
                },
                func
            ]);

            Config.parent = Overlay = DOM.load({
                id          : 'js-view',
                name        : 'div',
                className   : 'fancybox-overlay fancybox-overlay-fixed'
            });

            Events.addClick(Util.exec.with(onOverLayClick, Overlay), Overlay);
            Events.addKey(listener);
        }

        /**
         * function shows FancyBox
         */
        function show(data, options) {
            var path, element, type,
                config = {};

            if (!Loading) {
                Element         = $('
');

                if (data) {
                    element    = $(Element).append(data);

                    Util.copyObj(config, Config);

                    if (options)
                        Object.keys(options).forEach(function(name) {
                            var func,
                                isConfig        = !!config[name],
                                series          = Util.exec.series,
                                item            = options[name],
                                isFunc          = Util.isFunction(item);

                            if (isFunc && isConfig) {
                                func            = config[name];
                                config[name]    = function() {
                                    series([func, item]);
                                };
                            } else {
                                config[name]    = options[name];
                            }
                        });

                    $.fancybox(element, config);

                } else {
                    Images.showLoad();
                    path    = CloudFunc.FS + Info.path;
                    type    = getType(path);

                    switch(type) {
                    default:
                        Info.getData(function(error, data) {
                                var element = document.createTextNode(data);
                                /* add margin only for view text documents */
                                Element.css('margin', '2%');

                                $.fancybox(Element.append(element), Config);
                            });
                        break;

                    case 'image':
                        config = Util.copyObj({
                                autoSize    : true,
                                type        : 'image'
                            }, Config);

                        $.fancybox.open(path, config);
                        break;

                    case 'media':
                         getMediaElement(path, function(element) {
                            var media       = DOM.getByDataName('js-media', element),
                                onKey       = Util.exec.with(onMediaKey, media);

                            $.fancybox.open(element, {
                                parent      : Overlay,
                                beforeShow  : function() {
                                    Config.beforeShow();
                                    Events.addKey(onKey);
                                },
                                beforeClose : function() {
                                    Config.beforeClose();
                                    Events.rmKey(onKey);
                                },
                                helpers: {
                                    overlay : null,
                                    title   : null
                                }
                            });
                        });
                        break;
                    }
                }
            }
        }

        function hide() {
            $.fancybox.close();
        }

        function isImage(name) {
            var isMatch;

            isMatch = Util.checkExt(name, [
                'jp(e|g|eg)',
                'gif',
                'png',
                'bmp',
                'webp',
                'svg',
                'ico'
            ]);

            return isMatch;
        }

        function isMedia(name) {
            var isMatch;

            isMatch     = isAudio(name) || isVideo(name);

            return isMatch;
        }

        function isAudio(name) {
            var isMatch;

            isMatch     = Util.checkExt(name, ['mp3', 'ogg']);

            return isMatch;
        }

        function isVideo(name) {
            var isMatch;

            isMatch = Util.checkExt(name, ['mp4', 'avi']);

            return isMatch;
        }

        function getType(name) {
            var type;

            if (isImage(name))
                type    = 'image';
            else if (isMedia(name))
                type    = 'media';

            return type;
        }

        function getMediaElement(src, callback) {
            Util.checkArgs(arguments, ['src', 'callback']);

            DOM.Files.get('view/media-tmpl', function(error, template) {
                var rendered, element, type, is,
                    name = Info.name;

                if (error) {
                    Util.log(error);
                } else {
                    if (!TemplateAudio)
                        TemplateAudio   = template;

                    is      = isAudio(name);
                    type    =  is ? 'audio' : 'video';

                    rendered    = Util.render(TemplateAudio, {
                        src : src,
                        type: type,
                        name: Info.name
                    });

                    element     = $(rendered)[0];
                    callback(element);
                }
            });
        }

        function onMediaKey(media, event) {
            var key = event.keyCode;

            if (key === Key.SPACE) {
                if (media.paused)
                    media.play();
                else
                    media.pause();
            }
        }

        /**
         * function loads css and js of FancyBox
         * @callback   -  executes, when everything loaded
         */
        function load(callback) {
            Util.time(Name + ' load');

            DOM.loadRemote('fancybox', function() {
                DOM.load.css('/css/view.css', callback);

                DOM.load.style({
                    id:'view-css',
                    inner : '#fancybox-loading {'   +
                            'display: none'         +
                        '}'
                    });
            });
        }

        function onOverLayClick(overlay, event) {
            var isCurrent, isFiles, isFilesPassive,
                files       = Util.slice(Info.files),
                filesPassive= Util.slice(Info.filesPassive),
                position    = CloudCmd.MousePosition,
                element     = event.target,
                isOverlay   = element === overlay;

            if (isOverlay) {
                hideOverlay();
                element     = DOM.getCurrentByPosition(position);

                if (element) {
                    isFiles         = ~files.indexOf(element);
                    isFilesPassive  = ~filesPassive.indexOf(element);

                    if (isFiles || isFilesPassive) {
                        isCurrent = DOM.isCurrentFile(element);

                        if (!isCurrent)
                            DOM.setCurrentFile(element);
                    }
                }

                View.hide();
            }
        }

        function hideOverlay() {
            DOM.removeClass(Overlay, 'view-overlay');
        }

        function showOverlay() {
            DOM.addClass(Overlay, 'view-overlay');
        }

        function listener(event) {
            var keyCode = event.keyCode,
                ESC     = Key.ESC;

            if (keyCode === ESC)
                hide();
        }

        init();

        return View;
    }

})(CloudCmd, Util, DOM, CloudFunc);
<commit_msg>fix(view) css: add prefix<commit_after>var CloudCmd, Util, DOM, CloudFunc, $;

(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.View = ViewProto;

    function ViewProto(CallBack) {
        var Name        = 'View',
            Loading     = false,
            FocusWas    = false,
            Events      = DOM.Events,
            Info        = DOM.CurrentInfo,
            Key         = CloudCmd.Key,
            Images      = DOM.Images,
            View        = Util.exec.bind(Util),
            Element, TemplateAudio, Overlay,
            Config      = {
                beforeShow      : function(callback) {
                    Images.hide();
                    Key.unsetBind();
                    showOverlay();
                    Util.exec(callback);
                },
                beforeClose     : function(callback) {
                    Key.setBind();
                    Util.exec(callback);
                    hideOverlay();
                },
                afterShow       : function(callback) {
                    if (!FocusWas) {
                        Element.focus();
                        FocusWas = true;
                    }

                    Util.exec(callback);
                },
                afterClose      : function(callback) {
                    FocusWas = false;

                    Util.exec(callback);
                },
                fitToView       : true,
                loop            : false,
                openEffect      : 'none',
                closeEffect     : 'none',
                autoSize        : false,
                height          : '100%',
                width           : '100%',
                minWidth        : 0,
                minHeight       : 0,
                padding         : 0,
                preload         : 0,
                keys            : null,
                mouseWheel      : false,
                arrows          : false,
                helpers         : {
                    overlay : null,
                    title   : null
                }
            };

        View.show   = show;
        View.hide   = hide;

        function init() {
            var func = CallBack || Util.exec.with(show, null);

            Loading = true;

            Util.exec.series([
                DOM.loadJquery,
                load,
                function(callback) {
                    Loading = false;
                    Util.exec(callback);
                },
                func
            ]);

            Config.parent = Overlay = DOM.load({
                id          : 'js-view',
                name        : 'div',
                className   : 'fancybox-overlay fancybox-overlay-fixed'
            });

            Events.addClick(Util.exec.with(onOverLayClick, Overlay), Overlay);
            Events.addKey(listener);
        }

        /**
         * function shows FancyBox
         */
        function show(data, options) {
            var path, element, type,
                config = {};

            if (!Loading) {
                Element         = $('
');

                if (data) {
                    element    = $(Element).append(data);

                    Util.copyObj(config, Config);

                    if (options)
                        Object.keys(options).forEach(function(name) {
                            var func,
                                isConfig        = !!config[name],
                                series          = Util.exec.series,
                                item            = options[name],
                                isFunc          = Util.isFunction(item);

                            if (isFunc && isConfig) {
                                func            = config[name];
                                config[name]    = function() {
                                    series([func, item]);
                                };
                            } else {
                                config[name]    = options[name];
                            }
                        });

                    $.fancybox(element, config);

                } else {
                    Images.showLoad();
                    path    = CloudFunc.FS + Info.path;
                    type    = getType(path);

                    switch(type) {
                    default:
                        Info.getData(function(error, data) {
                                var element = document.createTextNode(data);
                                /* add margin only for view text documents */
                                Element.css('margin', '2%');

                                $.fancybox(Element.append(element), Config);
                            });
                        break;

                    case 'image':
                        config = Util.copyObj({
                                autoSize    : true,
                                type        : 'image'
                            }, Config);

                        $.fancybox.open(path, config);
                        break;

                    case 'media':
                         getMediaElement(path, function(element) {
                            var media       = DOM.getByDataName('js-media', element),
                                onKey       = Util.exec.with(onMediaKey, media);

                            $.fancybox.open(element, {
                                parent      : Overlay,
                                beforeShow  : function() {
                                    Config.beforeShow();
                                    Events.addKey(onKey);
                                },
                                beforeClose : function() {
                                    Config.beforeClose();
                                    Events.rmKey(onKey);
                                },
                                helpers: {
                                    overlay : null,
                                    title   : null
                                }
                            });
                        });
                        break;
                    }
                }
            }
        }

        function hide() {
            $.fancybox.close();
        }

        function isImage(name) {
            var isMatch;

            isMatch = Util.checkExt(name, [
                'jp(e|g|eg)',
                'gif',
                'png',
                'bmp',
                'webp',
                'svg',
                'ico'
            ]);

            return isMatch;
        }

        function isMedia(name) {
            var isMatch;

            isMatch     = isAudio(name) || isVideo(name);

            return isMatch;
        }

        function isAudio(name) {
            var isMatch;

            isMatch     = Util.checkExt(name, ['mp3', 'ogg']);

            return isMatch;
        }

        function isVideo(name) {
            var isMatch;

            isMatch = Util.checkExt(name, ['mp4', 'avi']);

            return isMatch;
        }

        function getType(name) {
            var type;

            if (isImage(name))
                type    = 'image';
            else if (isMedia(name))
                type    = 'media';

            return type;
        }

        function getMediaElement(src, callback) {
            Util.checkArgs(arguments, ['src', 'callback']);

            DOM.Files.get('view/media-tmpl', function(error, template) {
                var rendered, element, type, is,
                    name = Info.name;

                if (error) {
                    Util.log(error);
                } else {
                    if (!TemplateAudio)
                        TemplateAudio   = template;

                    is      = isAudio(name);
                    type    =  is ? 'audio' : 'video';

                    rendered    = Util.render(TemplateAudio, {
                        src : src,
                        type: type,
                        name: Info.name
                    });

                    element     = $(rendered)[0];
                    callback(element);
                }
            });
        }

        function onMediaKey(media, event) {
            var key = event.keyCode;

            if (key === Key.SPACE) {
                if (media.paused)
                    media.play();
                else
                    media.pause();
            }
        }

        /**
         * function loads css and js of FancyBox
         * @callback   -  executes, when everything loaded
         */
        function load(callback) {
            Util.time(Name + ' load');

            DOM.loadRemote('fancybox', function() {
                var prefix = CloudCmd.PREFIX;

                DOM.load.css(prefix + '/css/view.css', callback);

                DOM.load.style({
                    id:'view-css',
                    inner : '#fancybox-loading {'   +
                            'display: none'         +
                        '}'
                    });
            });
        }

        function onOverLayClick(overlay, event) {
            var isCurrent, isFiles, isFilesPassive,
                files       = Util.slice(Info.files),
                filesPassive= Util.slice(Info.filesPassive),
                position    = CloudCmd.MousePosition,
                element     = event.target,
                isOverlay   = element === overlay;

            if (isOverlay) {
                hideOverlay();
                element     = DOM.getCurrentByPosition(position);

                if (element) {
                    isFiles         = ~files.indexOf(element);
                    isFilesPassive  = ~filesPassive.indexOf(element);

                    if (isFiles || isFilesPassive) {
                        isCurrent = DOM.isCurrentFile(element);

                        if (!isCurrent)
                            DOM.setCurrentFile(element);
                    }
                }

                View.hide();
            }
        }

        function hideOverlay() {
            DOM.removeClass(Overlay, 'view-overlay');
        }

        function showOverlay() {
            DOM.addClass(Overlay, 'view-overlay');
        }

        function listener(event) {
            var keyCode = event.keyCode,
                ESC     = Key.ESC;

            if (keyCode === ESC)
                hide();
        }

        init();

        return View;
    }

})(CloudCmd, Util, DOM, CloudFunc);
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2014 Felipe Ribeiro
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
'use strict';

/**
 * Calculates the edit distance between two strings
 * considering the same cost of 1 to every operation
 * (addition, deletion, substitution)
 *
 * It uses dynamic programing and creates a matrix
 * where every cell [i,j] represents the distance between
 * the substrings a[0..i] and b[0..j]
 *
 * O(a.length * b.length)
 *
 * @param String
 * @param String
 * @return Number
 */
var levenshtein = function (a, b) {
  var editDistance = [];
  var i, j;

  // Initialize the edit distance matrix. The first collumn contains
  // the values comparing the string a to an empty string b
  for (i = 0; i <= a.length; i++) {
    editDistance[i] = [];
    editDistance[i][0] = i;
  }

  // And the first line the values comparint the string b to an empty string a
  for (j = 0; j <= b.length; j++) {
    editDistance[0][j] = j;
  }
  for (i = 1; i <= a.length; i++) {
    for (j = 1; j <= b.length; j++) {
      // Finds the minimum cost for keeping the two strings equal
      editDistance[i][j] =
        Math.min(
          editDistance[i - 1][j - 1], // if we replace a[i] by b[j]
          editDistance[i - 1][j], // if we delete the char from b
          editDistance[i][j - 1] // if we add the char from b
        ) +
        (a[i - 1] != b[j - 1] ? 1 : 0);
    }
  }

  return editDistance[a.length][b.length];
};

module.exports = levenshtein;
<commit_msg>Fix typo<commit_after>/**
 * Copyright (C) 2014 Felipe Ribeiro
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
'use strict';

/**
 * Calculates the edit distance between two strings
 * considering the same cost of 1 to every operation
 * (addition, deletion, substitution)
 *
 * It uses dynamic programing and creates a matrix
 * where every cell [i,j] represents the distance between
 * the substrings a[0..i] and b[0..j]
 *
 * O(a.length * b.length)
 *
 * @param String
 * @param String
 * @return Number
 */
var levenshtein = function (a, b) {
  var editDistance = [];
  var i, j;

  // Initialize the edit distance matrix. The first collumn contains
  // the values comparing the string a to an empty string b
  for (i = 0; i <= a.length; i++) {
    editDistance[i] = [];
    editDistance[i][0] = i;
  }

  // And the first line the values comparint the string b to an empty string a
  for (j = 0; j <= b.length; j++) {
    editDistance[0][j] = j;
  }
  for (i = 1; i <= a.length; i++) {
    for (j = 1; j <= b.length; j++) {
      // Finds the minimum cost for keeping the two strings equal
      editDistance[i][j] =
        Math.min(
          editDistance[i - 1][j - 1], // if we replace a[i] by b[j]
          editDistance[i - 1][j], // if we delete the char from a
          editDistance[i][j - 1] // if we add the char from b
        ) +
        (a[i - 1] != b[j - 1] ? 1 : 0);
    }
  }

  return editDistance[a.length][b.length];
};

module.exports = levenshtein;
<|endoftext|>


<commit_before>import React, {useState, useMemo, useContext} from 'react';
import {Platform} from 'react-native';
import {StateNavigator} from 'navigation';
import {NavigationHandler, NavigationContext} from 'navigation-react';
import {NavigationStack, TabBar, TabBarItem, NavigationBar} from 'navigation-react-native';
import Home from './Home';
import Notifications from './Notifications';

const useStateNavigator = start => {
  const {stateNavigator} = useContext(NavigationContext);
  return useMemo(() => {
    const navigator = new StateNavigator(stateNavigator);
    navigator.navigate(start);
    return navigator;
  }, [])
};

const Stack = ({stateNavigator}) => (
  <NavigationHandler stateNavigator={stateNavigator}>
    <NavigationStack />
  </NavigationHandler>
);

export default ({tweets, notifications}) => {
  const [notified, setNotified] = useState(false);
  const homeNavigator = useStateNavigator('home');
  const notificationsNavigator = useStateNavigator('notifications');
  return (
    <>
      <NavigationBar hidden={true} />
      <TabBar primary={true} selectedTintColor="#1da1f2">
        <TabBarItem title="Home" image={require('./home.png')}>
          {Platform.OS === 'android'
            ? <Home tweets={tweets} />
            : <Stack stateNavigator={homeNavigator} />}
        </TabBarItem>
        <TabBarItem
          title="Notifications"
          image={require('./notifications.png')}
          badge={!notified ? notifications.length : null}
          onPress={() => {setNotified(true)}}>
          {Platform.OS === 'android'
            ? <Notifications notifications={notifications} />
            : <Stack stateNavigator={notificationsNavigator} />}
        </TabBarItem>
      </TabBar>
    </>
  );
}
<commit_msg>Kept default selected tab tint on ios<commit_after>import React, {useState, useMemo, useContext} from 'react';
import {Platform} from 'react-native';
import {StateNavigator} from 'navigation';
import {NavigationHandler, NavigationContext} from 'navigation-react';
import {NavigationStack, TabBar, TabBarItem, NavigationBar} from 'navigation-react-native';
import Home from './Home';
import Notifications from './Notifications';

const useStateNavigator = start => {
  const {stateNavigator} = useContext(NavigationContext);
  return useMemo(() => {
    const navigator = new StateNavigator(stateNavigator);
    navigator.navigate(start);
    return navigator;
  }, [])
};

const Stack = ({stateNavigator}) => (
  <NavigationHandler stateNavigator={stateNavigator}>
    <NavigationStack />
  </NavigationHandler>
);

export default ({tweets, notifications}) => {
  const [notified, setNotified] = useState(false);
  const homeNavigator = useStateNavigator('home');
  const notificationsNavigator = useStateNavigator('notifications');
  return (
    <>
      <NavigationBar hidden={true} />
      <TabBar
        primary={true}
        selectedTintColor={Platform.OS === 'android' ? '#1da1f2' : null}>
        <TabBarItem title="Home" image={require('./home.png')}>
          {Platform.OS === 'android'
            ? <Home tweets={tweets} />
            : <Stack stateNavigator={homeNavigator} />}
        </TabBarItem>
        <TabBarItem
          title="Notifications"
          image={require('./notifications.png')}
          badge={!notified ? notifications.length : null}
          onPress={() => {setNotified(true)}}>
          {Platform.OS === 'android'
            ? <Notifications notifications={notifications} />
            : <Stack stateNavigator={notificationsNavigator} />}
        </TabBarItem>
      </TabBar>
    </>
  );
}
<|endoftext|>


<commit_before>var cdb = require('cartodb.js');
var BaseDialog = require('../../../views/base_dialog/view');
var pluralizeString = require('../../../view_helpers/pluralize_string');
var Utils = require('cdb.Utils');

/**
 *  When a Twitter import finishes, this dialog displays
 *  all the info about the price/cost etc.
 *
 */

module.exports = BaseDialog.extend({

  className: 'Dialog BackgroundPollingDetails GeocodingResultDetails is-opening',

  initialize: function() {
    this.elder('initialize');
    this.user = this.options.user;
  },

  render_content: function() {
    var proccessedRows = this.model.get('processed_rows') || 0;
    var proccessableRows = this.model.get('processable_rows') || 0;
    var realRows = this.model.get('real_rows');
    var googleUser = this.user.featureEnabled('google_maps');
    var price = this.model.get('price');
    var template = '';
    var error = this.model.get('error');

    // Select template
    if (this.model.hasCompleted()) {
      if (realRows === 0) {
        template = 'geocoding_no_result_details';
      } else {
        template = 'geocoding_success_details';
      }
    } else {
      template = 'geocoding_error_details';
    }

    var d = {
      id: this.model.get('id'),
      kind: this.model.get('kind'),
      realRows: realRows,
      geometryType: this.model.get('geometry_type'),
      remainingQuota: this.model.get('remaining_quota'),
      monthlyUse: this.user.get('geocoding').monthly_use,
      quota: this.user.get('geocoding').quota,
      blockPrice: this.user.get('geocoding').block_price,
      geocodingPrice: price,
      googleUser: googleUser,
      tableName: this.model.get('table_name'),
      state: this.model.get('state') || '',
      proccessedRows: proccessedRows,
      processableRows: proccessableRows,
      realRowsPluralize: pluralizeString('row', 'rows', realRows),
      proccessableRowsPluralize: pluralizeString('row', 'rows', proccessableRows),
      customHosted: cdb.config.get('custom_com_hosted'),
      errorTitle: error.title,
      errorDescription: error.description
    }
    return cdb.templates.getTemplate('common/background_polling/views/geocodings/' + template)(d);
  }

});
<commit_msg>Improved geocoding-result-view description<commit_after>var cdb = require('cartodb.js');
var BaseDialog = require('../../../views/base_dialog/view');
var pluralizeString = require('../../../view_helpers/pluralize_string');
var Utils = require('cdb.Utils');

/**
 *  When a geocoding proccess finishes, this dialog displays
 *  all the info about the task (price, rows, errors, etc).
 *
 */

module.exports = BaseDialog.extend({

  className: 'Dialog BackgroundPollingDetails GeocodingResultDetails is-opening',

  initialize: function() {
    this.elder('initialize');
    this.user = this.options.user;
  },

  render_content: function() {
    var proccessedRows = this.model.get('processed_rows') || 0;
    var proccessableRows = this.model.get('processable_rows') || 0;
    var realRows = this.model.get('real_rows') || 0;
    var googleUser = this.user.featureEnabled('google_maps');
    var price = this.model.get('price');
    var template = '';
    var error = this.model.get('error') || {};

    // Select template
    if (this.model.hasCompleted()) {
      if (realRows === 0) {
        template = 'geocoding_no_result_details';
      } else {
        template = 'geocoding_success_details';
      }
    } else {
      template = 'geocoding_error_details';
    }

    var d = {
      id: this.model.get('id'),
      kind: this.model.get('kind'),
      realRows: realRows,
      geometryType: this.model.get('geometry_type'),
      remainingQuota: this.model.get('remaining_quota'),
      monthlyUse: this.user.get('geocoding').monthly_use,
      quota: this.user.get('geocoding').quota,
      blockPrice: this.user.get('geocoding').block_price,
      geocodingPrice: price,
      googleUser: googleUser,
      tableName: this.model.get('table_name'),
      state: this.model.get('state') || '',
      proccessedRows: proccessedRows,
      processableRows: proccessableRows,
      realRowsPluralize: pluralizeString('row', 'rows', realRows),
      proccessableRowsPluralize: pluralizeString('row', 'rows', proccessableRows),
      customHosted: cdb.config.get('custom_com_hosted'),
      errorTitle: error.title,
      errorDescription: error.description
    }
    return cdb.templates.getTemplate('common/background_polling/views/geocodings/' + template)(d);
  }

});
<|endoftext|>


<commit_before>'use strict';

require([
	'jquery',
	'config',
	'connectors',
	'legacy/scrobbler',
	'customPatterns',
	'bootstrap'
], function ($, config, connectors, legacyScrobbler, customPatterns) {

	$(function () {

		// preload values and attach listeners

		$('#use-notifications')
			.attr('checked', (localStorage.useNotifications == 1))
			.click(function () {
				localStorage.useNotifications = this.checked ? 1 : 0;
			});

		$('#use-autocorrect')
			.attr('checked', (localStorage.useAutocorrect == 1))
			.click(function () {
				localStorage.useAutocorrect = this.checked ? 1 : 0;
			});

		$('button#authorize').click(function () {
			legacyScrobbler.authorize();
		});

		$('input#toggle').click(function () {
			var negatedCheckState = !$(this).is(':checked');

			// First set each to the negated value and then trigger click
			$('input[id^="conn"]').each(function (index, connector) {
				$(connector).prop('checked', negatedCheckState);
				$(connector).trigger('click');
			});
		});

		$('button#add-pattern').click(function() {
			$('#conn-conf-list').append(createNewConfigInput());
		});

		// generate connectors and their checkboxes
		createConnectors();

		// Set the toggle init state
		toggleInitState();
	});

	function toggleInitState() {
		var checkedState = true;

		$('input[id^="conn"]').each(function () {
			if (!$(this).is(':checked')) {
				checkedState = false;
				return false;
			}
		});

		$('input#toggle').prop('checked', checkedState);
	}

	function listConnectors() {
		// prevent mutation of original
		var conns = connectors.slice(0);

		// sort alphabetically
		conns.sort(function (a, b) {
			return a.label.localeCompare(b.label);
		});

		return conns;
	}

	function createNewConfigInput(value) {
		value = typeof value === 'undefined' ? '' : value;

		var newElt = $('

');

		var input = $('<input type="text">').val(value);

		newElt.append(input);

		var closeBtn = $(
		'' +
		'' +
		'').click(function(ev) {
			ev.preventDefault();

			$(this).closest('li').remove();
		});

		newElt.append(closeBtn);

		return newElt;
	}

	function createConnectors() {
		var parent = $('ul#connectors');

		var conns = listConnectors();

		conns.forEach(function (connector, index) {

			var newEl = $('
\r\n' +
			'\r\n' +
			'\r\n' +
			'\r\n' +
			'<input type="checkbox" id="conn-' + index + '">\r\n' +
			'' + connector.label + '\r\n' +
			'
');

			var domEl = newEl.appendTo(parent);
			var checkbox = domEl.find('input');

			checkbox.attr('checked', config.isConnectorEnabled(connector.label));

			checkbox.click(function () {
				var box = $(this);
				var disabledArray = JSON.parse(localStorage.disabledConnectors);

				// always remove, to prevent duplicates
				var index = disabledArray.indexOf(connector.label);
				if (index > -1) {
					disabledArray.splice(index, 1);
				}

				if (!box.is(':checked')) {
					disabledArray.push(connector.label);
				}

				localStorage.disabledConnectors = JSON.stringify(disabledArray);
				console.log(localStorage.disabledConnectors);
			});
		});

		$('button#conn-conf-ok').click(function() {
			var modal = $(this).closest('#conn-conf-modal');

			var index = modal.data('conn');
			var connector = conns[index];

			var patterns = [];
			$('#conn-conf-list').find('input:text').each(function() {
				var pattern = $(this).val();
				if (pattern.length > 0) {
					patterns.push(pattern);
				}
			});

			if (patterns.length > 0) {
				customPatterns.setPatterns(connector.label, patterns);
			} else {
				customPatterns.resetPatterns(connector.label);
			}

			modal.modal('hide');
		});

		$('button#conn-conf-reset').click(function() {
			var modal = $('#conn-conf-modal');

			var index = modal.data('conn');
			var connector = conns[index];

			customPatterns.resetPatterns(connector.label);

			modal.modal('hide');
		});

		$('body').on('click', 'a.conn-config', function(event) {
			event.preventDefault();

			var modal = $('#conn-conf-modal');
			var index = $(event.currentTarget).data('conn');
			var connector = conns[index];

			modal.data('conn', index);
			modal.find('.conn-conf-title').html(connector.label);

			var patterns = customPatterns.getAllPatterns(function(allPatterns) {
				var patterns = allPatterns[connector.label] || [];

				var inputs = $('

');
				for (var i = 0; i < patterns.length; i++) {
					var value = patterns[i];
					var input = createNewConfigInput(value);

					inputs.append(input);
				}

				modal.find('.conn-conf-patterns').html(inputs);

				modal.modal('show');
			});
		});
	}

});
<commit_msg>satisfy Mr. Grunt<commit_after>'use strict';

require([
	'jquery',
	'config',
	'connectors',
	'legacy/scrobbler',
	'customPatterns',
	'bootstrap'
], function ($, config, connectors, legacyScrobbler, customPatterns) {

	$(function () {

		// preload values and attach listeners

		$('#use-notifications')
			.attr('checked', (localStorage.useNotifications == 1))
			.click(function () {
				localStorage.useNotifications = this.checked ? 1 : 0;
			});

		$('#use-autocorrect')
			.attr('checked', (localStorage.useAutocorrect == 1))
			.click(function () {
				localStorage.useAutocorrect = this.checked ? 1 : 0;
			});

		$('button#authorize').click(function () {
			legacyScrobbler.authorize();
		});

		$('input#toggle').click(function () {
			var negatedCheckState = !$(this).is(':checked');

			// First set each to the negated value and then trigger click
			$('input[id^="conn"]').each(function (index, connector) {
				$(connector).prop('checked', negatedCheckState);
				$(connector).trigger('click');
			});
		});

		$('button#add-pattern').click(function() {
			$('#conn-conf-list').append(createNewConfigInput());
		});

		// generate connectors and their checkboxes
		createConnectors();

		// Set the toggle init state
		toggleInitState();
	});

	function toggleInitState() {
		var checkedState = true;

		$('input[id^="conn"]').each(function () {
			if (!$(this).is(':checked')) {
				checkedState = false;
				return false;
			}
		});

		$('input#toggle').prop('checked', checkedState);
	}

	function listConnectors() {
		// prevent mutation of original
		var conns = connectors.slice(0);

		// sort alphabetically
		conns.sort(function (a, b) {
			return a.label.localeCompare(b.label);
		});

		return conns;
	}

	function createNewConfigInput(value) {
		value = typeof value === 'undefined' ? '' : value;

		var newElt = $('

');

		var input = $('<input type="text">').val(value);

		newElt.append(input);

		var closeBtn = $(
		'' +
		'' +
		'').click(function(ev) {
			ev.preventDefault();

			$(this).closest('li').remove();
		});

		newElt.append(closeBtn);

		return newElt;
	}

	function createConnectors() {
		var parent = $('ul#connectors');

		var conns = listConnectors();

		conns.forEach(function (connector, index) {

			var newEl = $('
\r\n' +
			'\r\n' +
			'\r\n' +
			'\r\n' +
			'<input type="checkbox" id="conn-' + index + '">\r\n' +
			'' + connector.label + '\r\n' +
			'
');

			var domEl = newEl.appendTo(parent);
			var checkbox = domEl.find('input');

			checkbox.attr('checked', config.isConnectorEnabled(connector.label));

			checkbox.click(function () {
				var box = $(this);
				var disabledArray = JSON.parse(localStorage.disabledConnectors);

				// always remove, to prevent duplicates
				var index = disabledArray.indexOf(connector.label);
				if (index > -1) {
					disabledArray.splice(index, 1);
				}

				if (!box.is(':checked')) {
					disabledArray.push(connector.label);
				}

				localStorage.disabledConnectors = JSON.stringify(disabledArray);
				console.log(localStorage.disabledConnectors);
			});
		});

		$('button#conn-conf-ok').click(function() {
			var modal = $(this).closest('#conn-conf-modal');

			var index = modal.data('conn');
			var connector = conns[index];

			var patterns = [];
			$('#conn-conf-list').find('input:text').each(function() {
				var pattern = $(this).val();
				if (pattern.length > 0) {
					patterns.push(pattern);
				}
			});

			if (patterns.length > 0) {
				customPatterns.setPatterns(connector.label, patterns);
			} else {
				customPatterns.resetPatterns(connector.label);
			}

			modal.modal('hide');
		});

		$('button#conn-conf-reset').click(function() {
			var modal = $('#conn-conf-modal');

			var index = modal.data('conn');
			var connector = conns[index];

			customPatterns.resetPatterns(connector.label);

			modal.modal('hide');
		});

		$('body').on('click', 'a.conn-config', function(event) {
			event.preventDefault();

			var modal = $('#conn-conf-modal');
			var index = $(event.currentTarget).data('conn');
			var connector = conns[index];

			modal.data('conn', index);
			modal.find('.conn-conf-title').html(connector.label);

			customPatterns.getAllPatterns(function(allPatterns) {
				var patterns = allPatterns[connector.label] || [];

				var inputs = $('

');
				for (var i = 0; i < patterns.length; i++) {
					var value = patterns[i];
					var input = createNewConfigInput(value);

					inputs.append(input);
				}

				modal.find('.conn-conf-patterns').html(inputs);

				modal.modal('show');
			});
		});
	}

});
<|endoftext|>


<commit_before>/**
 * This file is part of Shoop.
 *
 * Copyright (c) 2012-2015, Shoop Ltd. All rights reserved.
 *
 * This source code is licensed under the AGPLv3 license found in the
 * LICENSE file in the root directory of this source tree.
 */
var bowerFiles = require("./bower-files");
var root = require("path").resolve(__dirname + "/..");
module.exports = {
    "vendor": {
        "files": bowerFiles("./static_src/vendor")
    },
    "base": {
        "base": "./static_src/base",
        "es6": true,
        "files": [
            "js/materialize.js",
            "js/main-menu.js",
            "js/search.js",
            "js/tooltip.js",
            "js/timesince.js",
            "js/messages.js",
            "js/browse-widget.js",
            "js/side-nav.js",
            "js/content-blocks.js",
            "js/remarkable-field.js",
            "js/form-utils.js",
            "js/jquery.form-submission-attributes.polyfill.js",
            "js/datetimepicker.js"
        ]
    },
    "dashboard": {
        "es6": true,
        "files": bowerFiles("./static_src/dashboard")
    },
    "media-browser": {
        "webpack": root + "/modules/media/webpack.config.js",
        "watch": [
            "./modules/media/static_src/media/**/*.js"
        ]
    },
    "remarkable": {
        "webpack": root + "/static_src/remarkable/webpack.config.js",
        "watch": [
            "./static_src/remarkable/*.js"
        ]
    },
    "picotable": {
        "es6": true,
        "base": "./static_src/picotable",
        "files": [
            "picotable.js"
        ]
    },
    "product-variation-variable-editor": {
        "base": root + "/modules/products/static_src",
        "es6": true,
        "files": [
            "product-variation-variable-editor.js"
        ]
    },
    "product": {
        "base": "./static_src/product",
        "es6": true,
        "files": [
            "edit_media.js"
        ]
    },
    "order-creator": {
        "webpack": root + "/modules/orders/static_src/create/webpack.config.js",
        "watch": [
            root + "/modules/orders/static_src/create/**/*.js"
        ]
    }
};
<commit_msg>Revert "Admin js-packages: Turn on es6 switch for dashboard"<commit_after>/**
 * This file is part of Shoop.
 *
 * Copyright (c) 2012-2015, Shoop Ltd. All rights reserved.
 *
 * This source code is licensed under the AGPLv3 license found in the
 * LICENSE file in the root directory of this source tree.
 */
var bowerFiles = require("./bower-files");
var root = require("path").resolve(__dirname + "/..");
module.exports = {
    "vendor": {
        "files": bowerFiles("./static_src/vendor")
    },
    "base": {
        "base": "./static_src/base",
        "es6": true,
        "files": [
            "js/materialize.js",
            "js/main-menu.js",
            "js/search.js",
            "js/tooltip.js",
            "js/timesince.js",
            "js/messages.js",
            "js/browse-widget.js",
            "js/side-nav.js",
            "js/content-blocks.js",
            "js/remarkable-field.js",
            "js/form-utils.js",
            "js/jquery.form-submission-attributes.polyfill.js",
            "js/datetimepicker.js"
        ]
    },
    "dashboard": {
        "files": bowerFiles("./static_src/dashboard")
    },
    "media-browser": {
        "webpack": root + "/modules/media/webpack.config.js",
        "watch": [
            "./modules/media/static_src/media/**/*.js"
        ]
    },
    "remarkable": {
        "webpack": root + "/static_src/remarkable/webpack.config.js",
        "watch": [
            "./static_src/remarkable/*.js"
        ]
    },
    "picotable": {
        "es6": true,
        "base": "./static_src/picotable",
        "files": [
            "picotable.js"
        ]
    },
    "product-variation-variable-editor": {
        "base": root + "/modules/products/static_src",
        "es6": true,
        "files": [
            "product-variation-variable-editor.js"
        ]
    },
    "product": {
        "base": "./static_src/product",
        "es6": true,
        "files": [
            "edit_media.js"
        ]
    },
    "order-creator": {
        "webpack": root + "/modules/orders/static_src/create/webpack.config.js",
        "watch": [
            root + "/modules/orders/static_src/create/**/*.js"
        ]
    }
};
<|endoftext|>