<commit_before>/* General settings modification here.
 ** Copyright © 2014 Ngine Networks.
 */

function get_player_seat_by_nickname(seats, nick) {
    if (seats.seat1.player.nickname == nick) {
        seats.seat1.state = "available";
        return seats.seat1.player.seat_nb;
    } else if (seats.seat2.player.nickname == nick) {
        seats.seat2.state = "available";
        return seats.seat2.player.seat_nb;
    } else if (seats.seat3.player.nickname == nick) {
        seats.seat3.state = "available";
        return seats.seat3.player.seat_nb;
    } else if (seats.seat4.player.nickname == nick) {
        seats.seat4.state = "available";
        return seats.seat4.player.seat_nb;
    } else if (seats.seat5.player.nickname == nick) {
        seats.seat5.state = "available";
        return seats.seat5.player.seat_nb;
    } else if (seats.seat6.player.nickname == nick) {
        seats.seat6.state = "available";
        return seats.seat6.player.seat_nb;
    }
    return (-1);
}

function remove_from_seat_array(table, nick) {
    var idx = 0;

    console.log(nick + " will be kicked");
    while (idx < table.nicknames.length) {
        if (table.nicknames[idx] == nick) {
            table.nicknames.splice(idx, 1);
            return (1);
        }
        ++idx;
    }
    return (-1);
}

function remove_from_playing_seats(playing_seats, idx) {
    var i = 0;

    if (playing_seats.indexOf(idx) == -1)
        return (-1);
    while (i < playing_seats.length) {
        if (playing_seats[i] == idx) {
            playing_seats.splice(i, 1);
            return (1);
        }
        ++i;
    }
    return (-1);
}

function socket_listens_global_settings(socket, table, private_channel) {
    var socket_nickname;
    var player_seat_idx;

    socket.emit("player name info");
    socket.on("socket nickname on table", function(nickname) {
        if (nickname && socket_nickname != nickname)
            socket_nickname = nickname;
    });
    socket.on("disconnect", function() {
        if (socket_nickname) {
            console.log(table.game.moment);
            player_seat_idx = get_player_seat_by_nickname(table.seats, socket_nickname);
            if (player_seat_idx && (table.game.moment == "waiting" || table.game.moment == "waiting end game")) {
                console.log('in waiting dc');
                remove_from_seat_array(table, socket_nickname);
                remove_from_playing_seats(table.playing_seats, player_seat_idx);
                console.log("table playing seats " + table.playing_seats);
                io.to(table.id).emit("bet", player_seat_idx, 0);
                io.to(table.id).emit("kick player", player_seat_idx);
                if (table.players_nb > 0)
                    --table.players_nb;
            } else if (player_seat_idx) {
                console.log('in game dc');
                remove_from_seat_array(table, socket_nickname);
                remove_from_playing_seats(table.playing_seats, player_seat_idx);
                var seatPlayer = table.seats.seat + player_seat_idx;
                console.log(seatPlayer);
                console.log("table playing seats " + table.playing_seats);
                console.log(table);
                if (player_seat_idx == table.game.highlights_pos) {
                    io.to(table.id).emit("highlights", table.game.highlights_pos, "off");
                    table.game.highlights_pos = 0;
                    if (table.playing_seats.length == 1) {
                        console.log('one player left');
                    }
                    else if (table.game.round_nb > table.playing_seats.length) {
                        console.log("1");
                        next_moment(table, table.game);
                    } else if (table.game.round_nb == table.playing_seats.length) {
                        console.log("2");
                        switch_next_player(table)
                    } else {
                        console.log("3");
                        switch_next_player(table);
                    }
                }
                io.to(table.id).emit("bet", player_seat_idx, 0);
                io.to(table.id).emit("kick player", player_seat_idx);
                if (table.players_nb > 0)
                    --table.players_nb;
                if (table.playing_seats.length == 1) {
                    console.log('one player left');
                    return one_playing_player_left(table);
                }
            }
            socket.leave(private_channel);
            socket.disconnect();
        }
    });
}
<commit_msg>fix seat busy<commit_after>/* General settings modification here.
 ** Copyright © 2014 Ngine Networks.
 */

function get_player_seat_by_nickname(seats, nick) {
    if (seats.seat1.player.nickname == nick) {
        seats.seat1.state = "available";
        return seats.seat1.player.seat_nb;
    } else if (seats.seat2.player.nickname == nick) {
        seats.seat2.state = "available";
        return seats.seat2.player.seat_nb;
    } else if (seats.seat3.player.nickname == nick) {
        seats.seat3.state = "available";
        return seats.seat3.player.seat_nb;
    } else if (seats.seat4.player.nickname == nick) {
        seats.seat4.state = "available";
        return seats.seat4.player.seat_nb;
    } else if (seats.seat5.player.nickname == nick) {
        seats.seat5.state = "available";
        return seats.seat5.player.seat_nb;
    } else if (seats.seat6.player.nickname == nick) {
        seats.seat6.state = "available";
        return seats.seat6.player.seat_nb;
    }
    return (-1);
}

function remove_from_seat_array(table, nick) {
    var idx = 0;

    console.log(nick + " will be kicked");
    while (idx < table.nicknames.length) {
        if (table.nicknames[idx] == nick) {
            table.nicknames.splice(idx, 1);
            return (1);
        }
        ++idx;
    }
    return (-1);
}

function remove_from_playing_seats(playing_seats, idx) {
    var i = 0;

    if (playing_seats.indexOf(idx) == -1)
        return (-1);
    while (i < playing_seats.length) {
        if (playing_seats[i] == idx) {
            playing_seats.splice(i, 1);
            return (1);
        }
        ++i;
    }
    return (-1);
}

function socket_listens_global_settings(socket, table, private_channel) {
    var socket_nickname;
    var player_seat_idx;

    socket.emit("player name info");
    socket.on("socket nickname on table", function(nickname) {
        if (nickname && socket_nickname != nickname)
            socket_nickname = nickname;
    });
    socket.on("disconnect", function() {
        if (socket_nickname) {
            console.log(table.game.moment);
            player_seat_idx = get_player_seat_by_nickname(table.seats, socket_nickname);
            if (player_seat_idx && (table.game.moment == "waiting" || table.game.moment == "waiting end game")) {
                console.log('in waiting dc');
                remove_from_seat_array(table, socket_nickname);
                remove_from_playing_seats(table.playing_seats, player_seat_idx);
                console.log("table playing seats " + table.playing_seats);
                io.to(table.id).emit("bet", player_seat_idx, 0);
                io.to(table.id).emit("kick player", player_seat_idx);
                if (table.players_nb > 0)
                    --table.players_nb;
            } else if (player_seat_idx) {
                console.log('in game dc');
                remove_from_seat_array(table, socket_nickname);
                remove_from_playing_seats(table.playing_seats, player_seat_idx);
                var seatPlayer = get_seat(table.seats, player_seat_idx);
                console.log(seatPlayer);
                console.log("table playing seats " + table.playing_seats);
                console.log(table);
                if (player_seat_idx == table.game.highlights_pos) {
                    io.to(table.id).emit("highlights", table.game.highlights_pos, "off");
                    table.game.highlights_pos = 0;
                    if (table.playing_seats.length == 1) {
                        console.log('one player left');
                    }
                    else if (table.game.round_nb > table.playing_seats.length) {
                        console.log("1");
                        next_moment(table, table.game);
                    } else if (table.game.round_nb == table.playing_seats.length) {
                        console.log("2");
                        switch_next_player(table)
                    } else {
                        console.log("3");
                        switch_next_player(table);
                    }
                }
                io.to(table.id).emit("bet", player_seat_idx, 0);
                io.to(table.id).emit("kick player", player_seat_idx);
                if (table.players_nb > 0)
                    --table.players_nb;
                if (table.playing_seats.length == 1) {
                    return one_playing_player_left(table);
                }
            }
            socket.leave(private_channel);
            socket.disconnect();
        }
    });
}
<|endoftext|>


<commit_before>(function() {
  var done, doneTimeout, countAsync, emberBdd;

  done = null;
  doneTimeout = null;
  isAsync = false;

  Ember.Test.MochaAdapter = Ember.Test.Adapter.extend({
    init: function() {
      this._super();
      window.Mocha.interfaces['ember-bdd'] = emberBdd;
      window.mocha.ui('ember-bdd');
    },
    asyncStart: function() {
      isAsync = true;
      clearTimeout(doneTimeout);
    },
    asyncEnd: function() {
      isAsync = false;
      if (done) {
        doneTimeout = setTimeout(function() {
          var d = done;
          done = null;
          d();
        });
      }
    },
    exception: function(reason) {
      var error, d;

      error = new Error(reason);
      if (done) {
        d = done;
        done = null;
        d(error);
      } else {
        setTimeout(function() {
          throw error;
        });
      }
    }
  });

  function fixAsync(suites, methodName) {
    return function(fn) {
      if (fn.length === 1) {
        suites[0][methodName](fn);
      } else {
        suites[0][methodName](function(d) {
          invoke(fn, d);
        });
      }
    };
  }

  function invoke(fn, d) {
    done = d;
    fn();
    if (!isAsync) {
      done = null;
      d();
    }
  }

  /**
    ember-bdd mocha interface.
    This interface allows
    the Ember.js tester
    to forget about sync / async
    and treat all tests the same.

    This interface, along with the adapter
    will take care of handling sync vs async
  */

  emberBdd = function(suite) {
    var suites = [suite];

    suite.on('pre-require', function(context, file, mocha) {

      context.before = fixAsync(suites, 'beforeAll');

      context.after = fixAsync(suites, 'afterAll');

      context.beforeEach = fixAsync(suites, 'beforeEach');

      context.afterEach = fixAsync(suites, 'afterEach');

      context.it = context.specify = function(title, fn){
        var suite = suites[0], test;
        if (suite.pending) {
          fn = null;
        }
        if (!fn || fn.length === 1) {
          test = new Mocha.Test(title, fn);
        } else {
          var method = function(d) {
            invoke(fn, d);
          };
          method.toString = function() {
            return fn.toString();
          }
          test = new Mocha.Test(title, method);
        }
        suite.addTest(test);
        return test;
      };

      context.describe = context.context = function(title, fn){
        var suite = Mocha.Suite.create(suites[0], title);
        suites.unshift(suite);
        fn.call(suite);
        suites.shift();
        return suite;
      };

      context.xdescribe =
      context.xcontext =
      context.describe.skip = function(title, fn){
        var suite = Mocha.Suite.create(suites[0], title);
        suite.pending = true;
        suites.unshift(suite);
        fn.call(suite);
        suites.shift();
      };

      context.describe.only = function(title, fn){
        var suite = context.describe(title, fn);
        mocha.grep(suite.fullTitle());
      };

      context.it.only = function(title, fn){
        var test = context.it(title, fn);
        mocha.grep(test.fullTitle());
      };

      context.xit =
      context.xspecify =
      context.it.skip = function(title){
        context.it(title);
      };

    });

  };

}());
<commit_msg>Preserve context when invoking hooks/tests<commit_after>(function() {
  var done, doneTimeout, countAsync, emberBdd;

  done = null;
  doneTimeout = null;
  isAsync = false;

  Ember.Test.MochaAdapter = Ember.Test.Adapter.extend({
    init: function() {
      this._super();
      window.Mocha.interfaces['ember-bdd'] = emberBdd;
      window.mocha.ui('ember-bdd');
    },
    asyncStart: function() {
      isAsync = true;
      clearTimeout(doneTimeout);
    },
    asyncEnd: function() {
      isAsync = false;
      if (done) {
        doneTimeout = setTimeout(function() {
          var d = done;
          done = null;
          d();
        });
      }
    },
    exception: function(reason) {
      var error, d;

      error = new Error(reason);
      if (done) {
        d = done;
        done = null;
        d(error);
      } else {
        setTimeout(function() {
          throw error;
        });
      }
    }
  });

  function fixAsync(suites, methodName) {
    return function(fn) {
      if (fn.length === 1) {
        suites[0][methodName](fn);
      } else {
        suites[0][methodName](function(d) {
          invoke(this, fn, d);
        });
      }
    };
  }

  function invoke(context, fn, d) {
    done = d;
    fn.call(context);
    if (!isAsync) {
      done = null;
      d();
    }
  }

  /**
    ember-bdd mocha interface.
    This interface allows
    the Ember.js tester
    to forget about sync / async
    and treat all tests the same.

    This interface, along with the adapter
    will take care of handling sync vs async
  */

  emberBdd = function(suite) {
    var suites = [suite];

    suite.on('pre-require', function(context, file, mocha) {

      context.before = fixAsync(suites, 'beforeAll');

      context.after = fixAsync(suites, 'afterAll');

      context.beforeEach = fixAsync(suites, 'beforeEach');

      context.afterEach = fixAsync(suites, 'afterEach');

      context.it = context.specify = function(title, fn){
        var suite = suites[0], test;
        if (suite.pending) {
          fn = null;
        }
        if (!fn || fn.length === 1) {
          test = new Mocha.Test(title, fn);
        } else {
          var method = function(d) {
            invoke(this, fn, d);
          };
          method.toString = function() {
            return fn.toString();
          }
          test = new Mocha.Test(title, method);
        }
        suite.addTest(test);
        return test;
      };

      context.describe = context.context = function(title, fn){
        var suite = Mocha.Suite.create(suites[0], title);
        suites.unshift(suite);
        fn.call(suite);
        suites.shift();
        return suite;
      };

      context.xdescribe =
      context.xcontext =
      context.describe.skip = function(title, fn){
        var suite = Mocha.Suite.create(suites[0], title);
        suite.pending = true;
        suites.unshift(suite);
        fn.call(suite);
        suites.shift();
      };

      context.describe.only = function(title, fn){
        var suite = context.describe(title, fn);
        mocha.grep(suite.fullTitle());
      };

      context.it.only = function(title, fn){
        var test = context.it(title, fn);
        mocha.grep(test.fullTitle());
      };

      context.xit =
      context.xspecify =
      context.it.skip = function(title){
        context.it(title);
      };

    });

  };

}());
<|endoftext|>


<commit_before>var fs = require("fs"),
    pth = require('path');

var ZipEntry = require("./zipEntry"),
    ZipFile =  require("./zipFile"),
    Utils = require("./util");

module.exports = function(/*String*/inPath) {
    var _zip = undefined,
        _filename = "";

    if (inPath && typeof inPath === "string") { // load zip file
        if (pth.existsSync(inPath)) {
            _filename = inPath;
            _zip = new ZipFile(fs.readFileSync(inPath));
        } else {
           throw Utils.Errors.INVALID_FILENAME;
        }
    } else { // create new zip file
        _zip = new ZipFile();
    }

    function getEntry(/*Object*/entry) {
        if (entry && _zip) {
            var item;
            // If entry was given as a file name
            if (typeof entry === "string")
                item = _zip.getEntry(entry);
            // if entry was given as a ZipEntry object
            if (typeof entry === "object" && entry.entryName != undefined && entry.header != undefined)
                item =  _zip.getEntry(entry.entryName);

            if (item) {
                return item;
            }
        }
        return null;
    }

    //process.on('uncaughtException', function (err) {
    //    console.log('Caught exception: ' + err);
    //});

    return {
        /**
         * Extracts the given entry from the archive and returns the content as a Buffer object
         * @param entry ZipEntry object or String with the full path of the entry
         *
         * @return Buffer or Null in case of error
         */
        readFile : function(/*Object*/entry) {
            var item = getEntry(entry);
            return item && item.getData() || null;
        },
        /**
         * Asynchronous readFile
         * @param entry ZipEntry object or String with the full path of the entry
         * @param callback
         *
         * @return Buffer or Null in case of error
         */
        readFileAsync : function(/*Object*/entry, /*Function*/callback) {
            var item = getEntry(entry);
            if (item) {
                item.getDataAsync(callback);
            } else {
                callback(null)
            }
        },
        /**
         * Extracts the given entry from the archive and returns the content as plain text in the given encoding
         * @param entry ZipEntry object or String with the full path of the entry
         * @param encoding Optional. If no encoding is specified utf8 is used
         *
         * @return String
         */
        readAsText : function(/*Object*/entry, /*String - Optional*/encoding) {
            var item = getEntry(entry);
            if (item) {
                var data = item.getData();
                if (data && data.length) {
                    return data.toString(encoding || "utf8");
                }
            }
            return "";
        },
        /**
         * Asynchronous readAsText
         * @param entry ZipEntry object or String with the full path of the entry
         * @param callback
         * @param encoding Optional. If no encoding is specified utf8 is used
         *
         * @return String
         */
        readAsTextAsync : function(/*Object*/entry, /*Function*/callback, /*String - Optional*/encoding) {
            var item = getEntry(entry);
            if (item) {
                item.getDataAsync(function(data) {
                    if (data && data.length) {
                        callback(data.toString(encoding || "utf8"));
                    } else {
                        callback("");
                    }
                })
            } else {
                callback("");
            }
        },

        /**
         * Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory
         *
         * @param entry
         */
        deleteFile : function(/*Object*/entry) { // @TODO: test deleteFile
            var item = getEntry(entry);
            if (item) {
                _zip.deleteEntry(item.entryName);
            }
        },

        /**
         * Adds a comment to the zip. The zip must be rewritten after adding the comment.
         *
         * @param comment
         */
        addZipComment : function(/*String*/comment) { // @TODO: test addZipComment
            _zip.comment = comment;
        },

        /**
         * Returns the zip comment
         *
         * @return String
         */
        getZipComment : function() {
            return _zip.comment || '';
        },

        /**
         * Adds a comment to a specified zipEntry. The zip must be rewritten after adding the comment
         * The comment cannot exceed 65535 characters in length
         *
         * @param entry
         * @param comment
         */
        addZipEntryComment : function(/*Object*/entry,/*String*/comment) {
            var item = getEntry(entry);
            if (item) {
                item.comment = comment;
            }
        },

        /**
         * Returns the comment of the specified entry
         *
         * @param entry
         * @return String
         */
        getZipEntryComment : function(/*Object*/entry) {
            var item = getEntry(entry);
            if (item) {
                return item.comment || '';
            }
            return ''
        },

        /**
         * Updates the content of an existing entry inside the archive. The zip must be rewritten after updating the content
         *
         * @param entry
         * @param content
         */
        updateFile : function(/*Object*/entry, /*Buffer*/content) {
            var item = getEntry(entry);
            if (item) {
                item.setData(content);
            }
        },

        /**
         * Adds a file from the disk to the archive
         *
         * @param localPath
         */
        addLocalFile : function(/*String*/localPath) {
             if (pth.existsSync(localPath)) {
                  // do stuff
             } else {
                 throw Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath);
             }
        },

        /**
         * Adds a local directory and all its nested files and directories to the archive
         *
         * @param localPath
         */
        addLocalFolder : function(/*String*/localPath) {
            if (localPath.charAt(localPath.length - 1) != "/")
                localPath += "/";

            if (pth.existsSync(localPath)) {
                var items = Utils.findFiles(localPath);
                if (items.length) {
                    items.forEach(function(path) {
                        var entry = new ZipEntry();
                        entry.entryName = path.replace(localPath, "");
                        var stats = fs.statSync(path);
                        if (stats.isDirectory()) {
                            entry.setData("");
                            entry.header.inAttr = stats.mode;
                            entry.header.attr = stats.mode
                        } else {
                            entry.setData(fs.readFileSync(path));
                            entry.header.inAttr = stats.mode;
                            entry.header.attr = stats.mode
                        }
                        entry.attr = stats.mode;
                        entry.header.time = stats.mtime;
                        _zip.setEntry(entry);
                    });
                }
            } else {
                throw Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath);
            }
        },

        /**
         * Allows you to programmatically create a entry (file or directory) in the zip file.
         * If you want to create a directory the entryName must end in / and a null buffer should be provided.
         * Comment and attributes are optional
         *
         * @param entryName
         * @param content
         * @param comment
         * @param attr
         */
        addFile : function(/*String*/entryName, /*Buffer*/content, /*String*/comment, /*Number*/attr) {
            var entry = new ZipEntry();
            entry.entryName = entryName;
            entry.comment = comment || "";
            entry.attr = attr || 0666;
            if (entry.isDirectory && content.length) {
                throw Utils.Errors.DIRECTORY_CONTENT_ERROR;
            }
            entry.setData(content);
            entry.header.time = new Date();
            _zip.setEntry(entry);
        },

        /**
         * Returns an array of ZipEntry objects representing the files and folders inside the archive
         *
         * @return Array
         */
        getEntries : function() {
            if (_zip) {
               return _zip.entries;
            } else {
                return [];
            }
        },

        /**
         * Returns a ZipEntry object representing the file or folder specified by ``name``.
         *
         * @param name
         * @return ZipEntry
         */
        getEntry : function(/*String*/name) {
            return getEntry(name);
        },

        /**
         * Extracts the given entry to the given targetPath
         * If the entry is a directory inside the archive, the entire directory and it's subdirectories will be extracted
         *
         * @param entry ZipEntry object or String with the full path of the entry
         * @param targetPath Target folder where to write the file
         * @param maintainEntryPath If maintainEntryPath is true and the entry is inside a folder, the entry folder
         *                          will be created in targetPath as well. Default is TRUE
         * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
         *                  Default is FALSE
         *
         * @return Boolean
         */
        extractEntryTo : function(/*Object*/entry, /*String*/targetPath, /*Boolean*/maintainEntryPath, /*Boolean*/overwrite) {
            overwrite = overwrite || false;
            maintainEntryPath = typeof maintainEntryPath == "undefned" ? true : maintainEntryPath;

            var item = getEntry(entry);
            if (!item) {
                throw Utils.Errors.NO_ENTRY;
            }

            var target = pth.resolve(targetPath, maintainEntryPath ? item.entryName : pth.basename(item.entryName));

            if (item.isDirectory) {
                target = pth.resolve(target, "..");
                var children = _zip.getEntryChildren(item);
                children.forEach(function(child) {
                    if (child.isDirectory) return;
                    var content = child.getData();
                    if (!content) {
                        throw Utils.Errors.CANT_EXTRACT_FILE;
                    }
                    Utils.writeFileTo(pth.resolve(targetPath, maintainEntryPath ? child.entryName : child.entryName.substr(item.entryName.length)), content, overwrite);
                });
                return true;
            }

            var content = item.getData();
            if (!content) throw Utils.Errors.CANT_EXTRACT_FILE;

            if (pth.existsSync(targetPath) && !overwrite) {
                throw Utils.Errors.CANT_OVERRIDE;
            }
            Utils.writeFileTo(target, content, overwrite);

            return true;
        },

        /**
         * Extracts the entire archive to the given location
         *
         * @param targetPath Target location
         * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
         *                  Default is FALSE
         */
        extractAllTo : function(/*String*/targetPath, /*Boolean*/overwrite) {
            overwrite = overwrite || false;
            if (!_zip) {
                throw Utils.Errors.NO_ZIP;
            }

            _zip.entries.forEach(function(entry) {
                if (entry.isDirectory) return;
                var content = entry.getData();
                if (!content) {
                    throw Utils.Errors.CANT_EXTRACT_FILE + "2";
                }
                Utils.writeFileTo(pth.resolve(targetPath, entry.entryName), content, overwrite);
            })
        },

        /**
         * Writes the newly created zip file to disk at the specified location or if a zip was opened and no ``targetFileName`` is provided, it will overwrite the opened zip
         *
         * @param targetFileName
         */
        writeZip : function(/*String*/targetFileName, /*Function*/callback) {

            if (arguments.length == 1) {
                if (typeof targetFileName == "function")
                    callback = targetFileName;
                    targetFileName = "";
            }

            if (!targetFileName && _filename) {
                targetFileName = _filename;
            }
            if (!targetFileName) return;

            var zipData = _zip.toBuffer();
            if (zipData) {
                Utils.writeFileTo(targetFileName, zipData, true);
            }
        },

        /**
         * Returns the content of the entire zip file as a Buffer object
         *
         * @return Buffer
         */
        toBuffer : function(/*Function*/callback) {
            this.valueOf = 2;
            if (typeof callback == "function") {
                _zip.toAsyncBuffer(callback);
                return null;
            }
            return _zip.toBuffer()
        }

        /*get lastError () {
            var x = function() { console.log("2", arguments); };
            x.prototype = 2
            return x; //
        } */
    }
};<commit_msg>Fixed writeZip bug<commit_after>var fs = require("fs"),
    pth = require('path');

var ZipEntry = require("./zipEntry"),
    ZipFile =  require("./zipFile"),
    Utils = require("./util");

module.exports = function(/*String*/inPath) {
    var _zip = undefined,
        _filename = "";

    if (inPath && typeof inPath === "string") { // load zip file
        if (pth.existsSync(inPath)) {
            _filename = inPath;
            _zip = new ZipFile(fs.readFileSync(inPath));
        } else {
           throw Utils.Errors.INVALID_FILENAME;
        }
    } else { // create new zip file
        _zip = new ZipFile();
    }

    function getEntry(/*Object*/entry) {
        if (entry && _zip) {
            var item;
            // If entry was given as a file name
            if (typeof entry === "string")
                item = _zip.getEntry(entry);
            // if entry was given as a ZipEntry object
            if (typeof entry === "object" && entry.entryName != undefined && entry.header != undefined)
                item =  _zip.getEntry(entry.entryName);

            if (item) {
                return item;
            }
        }
        return null;
    }

    //process.on('uncaughtException', function (err) {
    //    console.log('Caught exception: ' + err);
    //});

    return {
        /**
         * Extracts the given entry from the archive and returns the content as a Buffer object
         * @param entry ZipEntry object or String with the full path of the entry
         *
         * @return Buffer or Null in case of error
         */
        readFile : function(/*Object*/entry) {
            var item = getEntry(entry);
            return item && item.getData() || null;
        },
        /**
         * Asynchronous readFile
         * @param entry ZipEntry object or String with the full path of the entry
         * @param callback
         *
         * @return Buffer or Null in case of error
         */
        readFileAsync : function(/*Object*/entry, /*Function*/callback) {
            var item = getEntry(entry);
            if (item) {
                item.getDataAsync(callback);
            } else {
                callback(null)
            }
        },
        /**
         * Extracts the given entry from the archive and returns the content as plain text in the given encoding
         * @param entry ZipEntry object or String with the full path of the entry
         * @param encoding Optional. If no encoding is specified utf8 is used
         *
         * @return String
         */
        readAsText : function(/*Object*/entry, /*String - Optional*/encoding) {
            var item = getEntry(entry);
            if (item) {
                var data = item.getData();
                if (data && data.length) {
                    return data.toString(encoding || "utf8");
                }
            }
            return "";
        },
        /**
         * Asynchronous readAsText
         * @param entry ZipEntry object or String with the full path of the entry
         * @param callback
         * @param encoding Optional. If no encoding is specified utf8 is used
         *
         * @return String
         */
        readAsTextAsync : function(/*Object*/entry, /*Function*/callback, /*String - Optional*/encoding) {
            var item = getEntry(entry);
            if (item) {
                item.getDataAsync(function(data) {
                    if (data && data.length) {
                        callback(data.toString(encoding || "utf8"));
                    } else {
                        callback("");
                    }
                })
            } else {
                callback("");
            }
        },

        /**
         * Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory
         *
         * @param entry
         */
        deleteFile : function(/*Object*/entry) { // @TODO: test deleteFile
            var item = getEntry(entry);
            if (item) {
                _zip.deleteEntry(item.entryName);
            }
        },

        /**
         * Adds a comment to the zip. The zip must be rewritten after adding the comment.
         *
         * @param comment
         */
        addZipComment : function(/*String*/comment) { // @TODO: test addZipComment
            _zip.comment = comment;
        },

        /**
         * Returns the zip comment
         *
         * @return String
         */
        getZipComment : function() {
            return _zip.comment || '';
        },

        /**
         * Adds a comment to a specified zipEntry. The zip must be rewritten after adding the comment
         * The comment cannot exceed 65535 characters in length
         *
         * @param entry
         * @param comment
         */
        addZipEntryComment : function(/*Object*/entry,/*String*/comment) {
            var item = getEntry(entry);
            if (item) {
                item.comment = comment;
            }
        },

        /**
         * Returns the comment of the specified entry
         *
         * @param entry
         * @return String
         */
        getZipEntryComment : function(/*Object*/entry) {
            var item = getEntry(entry);
            if (item) {
                return item.comment || '';
            }
            return ''
        },

        /**
         * Updates the content of an existing entry inside the archive. The zip must be rewritten after updating the content
         *
         * @param entry
         * @param content
         */
        updateFile : function(/*Object*/entry, /*Buffer*/content) {
            var item = getEntry(entry);
            if (item) {
                item.setData(content);
            }
        },

        /**
         * Adds a file from the disk to the archive
         *
         * @param localPath
         */
        addLocalFile : function(/*String*/localPath) {
             if (pth.existsSync(localPath)) {
                  // do stuff
             } else {
                 throw Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath);
             }
        },

        /**
         * Adds a local directory and all its nested files and directories to the archive
         *
         * @param localPath
         */
        addLocalFolder : function(/*String*/localPath) {
            if (localPath.charAt(localPath.length - 1) != "/")
                localPath += "/";

            if (pth.existsSync(localPath)) {
                var items = Utils.findFiles(localPath);
                if (items.length) {
                    items.forEach(function(path) {
                        var entry = new ZipEntry();
                        entry.entryName = path.replace(localPath, "");
                        var stats = fs.statSync(path);
                        if (stats.isDirectory()) {
                            entry.setData("");
                            entry.header.inAttr = stats.mode;
                            entry.header.attr = stats.mode
                        } else {
                            entry.setData(fs.readFileSync(path));
                            entry.header.inAttr = stats.mode;
                            entry.header.attr = stats.mode
                        }
                        entry.attr = stats.mode;
                        entry.header.time = stats.mtime;
                        _zip.setEntry(entry);
                    });
                }
            } else {
                throw Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath);
            }
        },

        /**
         * Allows you to programmatically create a entry (file or directory) in the zip file.
         * If you want to create a directory the entryName must end in / and a null buffer should be provided.
         * Comment and attributes are optional
         *
         * @param entryName
         * @param content
         * @param comment
         * @param attr
         */
        addFile : function(/*String*/entryName, /*Buffer*/content, /*String*/comment, /*Number*/attr) {
            var entry = new ZipEntry();
            entry.entryName = entryName;
            entry.comment = comment || "";
            entry.attr = attr || 0666;
            if (entry.isDirectory && content.length) {
                throw Utils.Errors.DIRECTORY_CONTENT_ERROR;
            }
            entry.setData(content);
            entry.header.time = new Date();
            _zip.setEntry(entry);
        },

        /**
         * Returns an array of ZipEntry objects representing the files and folders inside the archive
         *
         * @return Array
         */
        getEntries : function() {
            if (_zip) {
               return _zip.entries;
            } else {
                return [];
            }
        },

        /**
         * Returns a ZipEntry object representing the file or folder specified by ``name``.
         *
         * @param name
         * @return ZipEntry
         */
        getEntry : function(/*String*/name) {
            return getEntry(name);
        },

        /**
         * Extracts the given entry to the given targetPath
         * If the entry is a directory inside the archive, the entire directory and it's subdirectories will be extracted
         *
         * @param entry ZipEntry object or String with the full path of the entry
         * @param targetPath Target folder where to write the file
         * @param maintainEntryPath If maintainEntryPath is true and the entry is inside a folder, the entry folder
         *                          will be created in targetPath as well. Default is TRUE
         * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
         *                  Default is FALSE
         *
         * @return Boolean
         */
        extractEntryTo : function(/*Object*/entry, /*String*/targetPath, /*Boolean*/maintainEntryPath, /*Boolean*/overwrite) {
            overwrite = overwrite || false;
            maintainEntryPath = typeof maintainEntryPath == "undefned" ? true : maintainEntryPath;

            var item = getEntry(entry);
            if (!item) {
                throw Utils.Errors.NO_ENTRY;
            }

            var target = pth.resolve(targetPath, maintainEntryPath ? item.entryName : pth.basename(item.entryName));

            if (item.isDirectory) {
                target = pth.resolve(target, "..");
                var children = _zip.getEntryChildren(item);
                children.forEach(function(child) {
                    if (child.isDirectory) return;
                    var content = child.getData();
                    if (!content) {
                        throw Utils.Errors.CANT_EXTRACT_FILE;
                    }
                    Utils.writeFileTo(pth.resolve(targetPath, maintainEntryPath ? child.entryName : child.entryName.substr(item.entryName.length)), content, overwrite);
                });
                return true;
            }

            var content = item.getData();
            if (!content) throw Utils.Errors.CANT_EXTRACT_FILE;

            if (pth.existsSync(targetPath) && !overwrite) {
                throw Utils.Errors.CANT_OVERRIDE;
            }
            Utils.writeFileTo(target, content, overwrite);

            return true;
        },

        /**
         * Extracts the entire archive to the given location
         *
         * @param targetPath Target location
         * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
         *                  Default is FALSE
         */
        extractAllTo : function(/*String*/targetPath, /*Boolean*/overwrite) {
            overwrite = overwrite || false;
            if (!_zip) {
                throw Utils.Errors.NO_ZIP;
            }

            _zip.entries.forEach(function(entry) {
                if (entry.isDirectory) return;
                var content = entry.getData();
                if (!content) {
                    throw Utils.Errors.CANT_EXTRACT_FILE + "2";
                }
                Utils.writeFileTo(pth.resolve(targetPath, entry.entryName), content, overwrite);
            })
        },

        /**
         * Writes the newly created zip file to disk at the specified location or if a zip was opened and no ``targetFileName`` is provided, it will overwrite the opened zip
         *
         * @param targetFileName
         */
        writeZip : function(/*String*/targetFileName, /*Function*/callback) {

            if (arguments.length == 1) {
                if (typeof targetFileName == "function") {
                    callback = targetFileName;
                    targetFileName = "";
				}
            }

            if (!targetFileName && _filename) {
                targetFileName = _filename;
            }
            if (!targetFileName) return;

            var zipData = _zip.toBuffer();
            if (zipData) {
                Utils.writeFileTo(targetFileName, zipData, true);
            }
        },

        /**
         * Returns the content of the entire zip file as a Buffer object
         *
         * @return Buffer
         */
        toBuffer : function(/*Function*/callback) {
            this.valueOf = 2;
            if (typeof callback == "function") {
                _zip.toAsyncBuffer(callback);
                return null;
            }
            return _zip.toBuffer()
        }

        /*get lastError () {
            var x = function() { console.log("2", arguments); };
            x.prototype = 2
            return x; //
        } */
    }
};<|endoftext|>


<commit_before>var adverbs = [
  'absolutel',
  'accidentall',
  'additionall',
  'allegedl',
  'alternativel',
  'angril',
  'anxiousl',
  'approximatel',
  'awkwardl',
  'badl',
  'barel',
  'beautifull',
  'blindl',
  'boldl',
  'bravel',
  'brightl',
  'briskl',
  'bristl',
  'bubbl',
  'busil',
  'calml',
  'carefull',
  'carelessl',
  'cautiousl',
  'cheerfull',
  'clearl',
  'closel',
  'coldl',
  'completel',
  'consequentl',
  'correctl',
  'courageousl',
  'crinkl',
  'cruell',
  'crumbl',
  'cuddl',
  'currentl',
  'dail',
  'daringl',
  'deadl',
  'definitel',
  'deliberatel',
  'doubtfull',
  'dumbl',
  'eagerl',
  'earl',
  'easil',
  'elegantl',
  'enormousl',
  'enthusiasticall',
  'equall',
  'especiall',
  'eventuall',
  'exactl',
  'exceedingl',
  'exclusivel',
  'extremel',
  'fairl',
  'faithfull',
  'fatall',
  'fiercel',
  'finall',
  'fondl',
  'foolishl',
  'fortunatel',
  'frankl',
  'franticall',
  'generousl',
  'gentl',
  'giggl',
  'gladl',
  'gracefull',
  'greedil',
  'happil',
  'hardl',
  'hastil',
  'healthil',
  'heartil',
  'honestl',
  'hourl',
  'hungril',
  'hurriedl',
  'immediatel',
  'impatientl',
  'inadequatel',
  'ingeniousl',
  'innocentl',
  'inquisitivel',
  'interestingl',
  'irritabl',
  'jiggl',
  'joyousl',
  'justl',
  'kindl',
  'largel',
  'latel',
  'lazil',
  'likel',
  'literall',
  'lonel',
  'loosel',
  'loudl',
  'loudl',
  'luckil',
  'madl',
  'man',
  'mentall',
  'mildl',
  'monthl',
  'mortall',
  'mostl',
  'mysteriousl',
  'neatl',
  'nervousl',
  'nightl',
  'noisil',
  'normall',
  'obedientl',
  'occasionall',
  'onl',
  'openl',
  'painfull',
  'particularl',
  'patientl',
  'perfectl',
  'politel',
  'poorl',
  'powerfull',
  'presumabl',
  'previousl',
  'promptl',
  'punctuall',
  'quarterl',
  'quickl',
  'quietl',
  'rapidl',
  'rarel',
  'reall',
  'recentl',
  'recklessl',
  'regularl',
  'relativel',
  'reluctantl',
  'remarkabl',
  'repeatedl',
  'rightfull',
  'roughl',
  'rudel',
  'sadl',
  'safel',
  'selfishl',
  'sensibl',
  'seriousl',
  'sharpl',
  'shortl',
  'shyl',
  'significantl',
  'silentl',
  'simpl',
  'sleepil',
  'slowl',
  'smartl',
  'smell',
  'smoothl',
  'softl',
  'solemnl',
  'sparkl',
  'speedil',
  'stealthil',
  'sternl',
  'stupidl',
  'substantiall',
  'successfull',
  'suddenl',
  'surprisingl',
  'suspiciousl',
  'swiftl',
  'tenderl',
  'tensel',
  'thoughtfull',
  'tightl',
  'timel',
  'truthfull',
  'unexpectedl',
  'unfortunatel',
  'usuall',
  'ver',
  'victoriousl',
  'violentl',
  'vivaciousl',
  'warml',
  'waverl',
  'weakl',
  'wearil',
  'weekl',
  'wildl',
  'wisel',
  'worldl',
  'wrinkl',
  'yearl'
];

var adverbRegex = new RegExp('\\b(' + adverbs.join('|') + ')(y)\\b', 'gi');
var matcher = require("./matcher");

module.exports = function (text) {
  return matcher(adverbRegex, text, "adverbs");
};
<commit_msg>Add helpfull to adverb list<commit_after>var adverbs = [
  'absolutel',
  'accidentall',
  'additionall',
  'allegedl',
  'alternativel',
  'angril',
  'anxiousl',
  'approximatel',
  'awkwardl',
  'badl',
  'barel',
  'beautifull',
  'blindl',
  'boldl',
  'bravel',
  'brightl',
  'briskl',
  'bristl',
  'bubbl',
  'busil',
  'calml',
  'carefull',
  'carelessl',
  'cautiousl',
  'cheerfull',
  'clearl',
  'closel',
  'coldl',
  'completel',
  'consequentl',
  'correctl',
  'courageousl',
  'crinkl',
  'cruell',
  'crumbl',
  'cuddl',
  'currentl',
  'dail',
  'daringl',
  'deadl',
  'definitel',
  'deliberatel',
  'doubtfull',
  'dumbl',
  'eagerl',
  'earl',
  'easil',
  'elegantl',
  'enormousl',
  'enthusiasticall',
  'equall',
  'especiall',
  'eventuall',
  'exactl',
  'exceedingl',
  'exclusivel',
  'extremel',
  'fairl',
  'faithfull',
  'fatall',
  'fiercel',
  'finall',
  'fondl',
  'foolishl',
  'fortunatel',
  'frankl',
  'franticall',
  'generousl',
  'gentl',
  'giggl',
  'gladl',
  'gracefull',
  'greedil',
  'happil',
  'hardl',
  'hastil',
  'healthil',
  'heartil',
  'helpfull',
  'honestl',
  'hourl',
  'hungril',
  'hurriedl',
  'immediatel',
  'impatientl',
  'inadequatel',
  'ingeniousl',
  'innocentl',
  'inquisitivel',
  'interestingl',
  'irritabl',
  'jiggl',
  'joyousl',
  'justl',
  'kindl',
  'largel',
  'latel',
  'lazil',
  'likel',
  'literall',
  'lonel',
  'loosel',
  'loudl',
  'loudl',
  'luckil',
  'madl',
  'man',
  'mentall',
  'mildl',
  'monthl',
  'mortall',
  'mostl',
  'mysteriousl',
  'neatl',
  'nervousl',
  'nightl',
  'noisil',
  'normall',
  'obedientl',
  'occasionall',
  'onl',
  'openl',
  'painfull',
  'particularl',
  'patientl',
  'perfectl',
  'politel',
  'poorl',
  'powerfull',
  'presumabl',
  'previousl',
  'promptl',
  'punctuall',
  'quarterl',
  'quickl',
  'quietl',
  'rapidl',
  'rarel',
  'reall',
  'recentl',
  'recklessl',
  'regularl',
  'relativel',
  'reluctantl',
  'remarkabl',
  'repeatedl',
  'rightfull',
  'roughl',
  'rudel',
  'sadl',
  'safel',
  'selfishl',
  'sensibl',
  'seriousl',
  'sharpl',
  'shortl',
  'shyl',
  'significantl',
  'silentl',
  'simpl',
  'sleepil',
  'slowl',
  'smartl',
  'smell',
  'smoothl',
  'softl',
  'solemnl',
  'sparkl',
  'speedil',
  'stealthil',
  'sternl',
  'stupidl',
  'substantiall',
  'successfull',
  'suddenl',
  'surprisingl',
  'suspiciousl',
  'swiftl',
  'tenderl',
  'tensel',
  'thoughtfull',
  'tightl',
  'timel',
  'truthfull',
  'unexpectedl',
  'unfortunatel',
  'usuall',
  'ver',
  'victoriousl',
  'violentl',
  'vivaciousl',
  'warml',
  'waverl',
  'weakl',
  'wearil',
  'weekl',
  'wildl',
  'wisel',
  'worldl',
  'wrinkl',
  'yearl'
];

var adverbRegex = new RegExp('\\b(' + adverbs.join('|') + ')(y)\\b', 'gi');
var matcher = require("./matcher");

module.exports = function (text) {
  return matcher(adverbRegex, text, "adverbs");
};
<|endoftext|>


<commit_before>var $ = require('jquery');
var cdb = require('cartodb.js');
var HeaderView = require('../common/views/dashboard_header_view');
var SupportView = require('../common/support_view');
var HeaderViewModel = require('./header_view_model');
var LocalStorage = require('../common/local_storage');
var OrganizationUserQuota = require('./organization_user_quota');
var DeleteAccount = require('./delete_org_user_view');
var AvatarSelector = require('../common/avatar_selector_view');
var ColorPickerView = require('./color_picker_view');
var OrganizationUsersView = require('./organization_users/organization_users_view');
var domainRegExp = /^[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.([a-zA-Z]{1,6}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,3})$/;
var RegenerateKeysDialog = require('../keys/regenerate_keys_dialog_view');
var GroupsRouter = require('./groups_admin/router');
var GroupsMainView = require('./groups_admin/groups_main_view');

if (window.trackJs) {
  window.trackJs.configure({
    userId: window.user_data.username
  });
}

/**
 *  Entry point for the new organization, bootstraps all
 *  dependency models and application.
 */

$(function() {
  cdb.init(function() {
    var self = this;

    cdb.templates.namespace = 'cartodb/';
    cdb.config.set('url_prefix', user_data.base_url);

    cdb.config.set(window.config); // import config

    $(document.body).bind('click', function () {
      cdb.god.trigger('closeDialogs');
    });

    var currentUser = new cdb.admin.User(window.user_data);

    if (window.organization_user_data) {
      var organizationUser = new cdb.admin.User(window.organization_user_data);
    }

    if (window.organization_data) {
      var organization = new cdb.admin.Organization(window.organization_data);
      var organizationUsers = organization.users;
    }

    var headerView = new HeaderView({
      el:             $('#header'), //pre-rendered in DOM by Rails app
      model:          currentUser,
      currentUserUrl: currentUser.viewUrl(),
      viewModel:      new HeaderViewModel(),
      localStorage:   new LocalStorage()
    });
    headerView.render();

    var supportView = new SupportView({
      el: $('#support-banner'),
      user: currentUser
    });
    supportView.render();

    // Avatar
    if (this.$('.js-avatarSelector').length > 0) {
      var avatarSelector = new AvatarSelector({
        el: this.$('.js-avatarSelector'),
        renderModel: new cdb.core.Model({
          inputName: this.$('.js-fileAvatar').attr('name'),
          name: currentUser.organization.get('name'),
          avatar_url: currentUser.organization.get('avatar_url'),
          id: currentUser.get('id')
        })
      });

      avatarSelector.render();
    }

    // Tooltips
    $('[data-title]').each(function(i,el) {
      new cdb.common.TipsyTooltip({
        el: el,
        title: function() {
          return $(this).attr('data-title');
        }
      })
    });

    // Color picker
    if (this.$('.js-colorPicker').length > 0) {
      new ColorPickerView({
        el: this.$('.js-colorPicker'),
        color: this.$('.js-colorPicker').data('color')
      }).bind('colorChosen', function(color) {
        this.$('.js-colorInput').val(color);
      }, this);
    }

    // Domain whitelisting
    if (this.$('.js-domains').length > 0) {
      this.$(".js-domainsList").tagit({
        allowSpaces: false,
        singleField: true,
        singleFieldNode: this.$('.js-whitelist'),
        fieldName: this.$('.js-whitelist').attr('name'),
        tagLimit: 10,
        readOnly: false,
        onBlur: function() {
          self.$('.js-domains').removeClass('is-focus')

          if ($(".tagit-choice").length > 0) {
            $('.js-placeholder').hide();
          }
          else {
            $('.js-placeholder').show();
          }

          if ($(".tagit-new").length > 0) {
            $(".tagit-new input").val('')
          }
        },
        onFocus: function() {
          self.$('.js-domains').addClass('is-focus')

          $('.js-placeholder').hide();
        },
        beforeTagAdded: function(ev, ui) {
          if (!domainRegExp.test(ui.tagLabel)) {
            return false;
          }

          if ($(".tagit-choice").length > 0) {
            $('.js-placeholder').hide();
          }
          else { $('.js-placeholder').show(); }
        },
        afterTagAdded: function(ev, ui) {
          if ($(".tagit-choice").length > 0) {
            $('.js-placeholder').hide();
          }
          else { $('.js-placeholder').show(); }
        }
      });
    }

    // User quota main view
    if (this.$('.js-userQuota').length > 0 && organization_user_data && this.$('#user_quota').length > 0) {
      new OrganizationUserQuota({
        el: this.$('.js-userQuota'),
        model: organizationUser
      })
    }

    // Organization users list
    if (this.$('.js-orgUsersList').length === 1) {
      var organizationUsers = new OrganizationUsersView({
        el: this.$('.js-orgUsersList'),
        organization: organization,
        organizationUsers: organizationUsers
      });
      organizationUsers.render();
    }

    // User deletion
    if (this.$('.js-deleteAccount').length > 0 && window.authenticity_token) {
      this.$('.js-deleteAccount').click(function(ev) {
        if (ev) {
          ev.preventDefault();
        }
        new DeleteAccount({
          organizationUser: organizationUser,
          authenticityToken: window.authenticity_token,
          clean_on_hide: true
        }).appendToBody();
      })
    }

    // API keys
    var regenerateApiKeyHandler = function(ev, scope, form_action) {
      if (ev) ev.preventDefault();
      var authenticity_token = $('[name=authenticity_token][value]').get(0).value;
      var dlg = new RegenerateKeysDialog({
        type: 'api',
        scope: scope,
        form_action: form_action,
        authenticity_token: authenticity_token
      });

      dlg.appendToBody();
    };

    $('.js-regenerateOrgUsersApiKey').bind('click', function(ev) {
      var current_username = $(this).attr('data-current_username');

      regenerateApiKeyHandler(ev, 'organization', '/u/' + current_username + '/organization/regenerate_api_keys');
    });

    $('.js-regenerateOrgUserApiKey').bind('click', function(ev) {
      var username = $(this).attr('data-username');
      var current_username = $(this).attr('data-current_username');

      regenerateApiKeyHandler(ev, 'organization_user', '/u/' + current_username + '/organization/users/' + username + '/regenerate_api_key');
    });

    var $groups = $('.js-groups-content');
    if ($groups) {
      if (!currentUser.isOrgAdmin()) {
        window.location = currentUser.viewUrl().accountSettings();
        return false;
      }

      var groups = new cdb.admin.OrganizationGroups([], {
        organization: currentUser.organization
      });
      var router = new GroupsRouter({
        rootUrl: currentUser.viewUrl().organization().groups(),
        groups: groups,
        user: currentUser
      });

      var groupsMainView = new GroupsMainView({
        el: $groups,
        groups: groups,
        router: router,
        user: currentUser
      });
      groupsMainView.render();
      window.groups = groupsMainView;

      router.enableAfterMainView();
    }
  });

});<commit_msg>Org user quota minor fix<commit_after>var $ = require('jquery');
var cdb = require('cartodb.js');
var HeaderView = require('../common/views/dashboard_header_view');
var SupportView = require('../common/support_view');
var HeaderViewModel = require('./header_view_model');
var LocalStorage = require('../common/local_storage');
var OrganizationUserQuota = require('./organization_user_quota');
var DeleteAccount = require('./delete_org_user_view');
var AvatarSelector = require('../common/avatar_selector_view');
var ColorPickerView = require('./color_picker_view');
var OrganizationUsersView = require('./organization_users/organization_users_view');
var domainRegExp = /^[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.([a-zA-Z]{1,6}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,3})$/;
var RegenerateKeysDialog = require('../keys/regenerate_keys_dialog_view');
var GroupsRouter = require('./groups_admin/router');
var GroupsMainView = require('./groups_admin/groups_main_view');

if (window.trackJs) {
  window.trackJs.configure({
    userId: window.user_data.username
  });
}

/**
 *  Entry point for the new organization, bootstraps all
 *  dependency models and application.
 */

$(function() {
  cdb.init(function() {
    var self = this;

    cdb.templates.namespace = 'cartodb/';
    cdb.config.set('url_prefix', user_data.base_url);

    cdb.config.set(window.config); // import config

    $(document.body).bind('click', function () {
      cdb.god.trigger('closeDialogs');
    });

    var currentUser = new cdb.admin.User(window.user_data);

    if (window.organization_user_data) {
      var organizationUser = new cdb.admin.User(window.organization_user_data);
    }

    if (window.organization_data) {
      var organization = new cdb.admin.Organization(window.organization_data);
      var organizationUsers = organization.users;
    }

    var headerView = new HeaderView({
      el:             $('#header'), //pre-rendered in DOM by Rails app
      model:          currentUser,
      currentUserUrl: currentUser.viewUrl(),
      viewModel:      new HeaderViewModel(),
      localStorage:   new LocalStorage()
    });
    headerView.render();

    var supportView = new SupportView({
      el: $('#support-banner'),
      user: currentUser
    });
    supportView.render();

    // Avatar
    if (this.$('.js-avatarSelector').length > 0) {
      var avatarSelector = new AvatarSelector({
        el: this.$('.js-avatarSelector'),
        renderModel: new cdb.core.Model({
          inputName: this.$('.js-fileAvatar').attr('name'),
          name: currentUser.organization.get('name'),
          avatar_url: currentUser.organization.get('avatar_url'),
          id: currentUser.get('id')
        })
      });

      avatarSelector.render();
    }

    // Tooltips
    $('[data-title]').each(function(i,el) {
      new cdb.common.TipsyTooltip({
        el: el,
        title: function() {
          return $(this).attr('data-title');
        }
      })
    });

    // Color picker
    if (this.$('.js-colorPicker').length > 0) {
      new ColorPickerView({
        el: this.$('.js-colorPicker'),
        color: this.$('.js-colorPicker').data('color')
      }).bind('colorChosen', function(color) {
        this.$('.js-colorInput').val(color);
      }, this);
    }

    // Domain whitelisting
    if (this.$('.js-domains').length > 0) {
      this.$(".js-domainsList").tagit({
        allowSpaces: false,
        singleField: true,
        singleFieldNode: this.$('.js-whitelist'),
        fieldName: this.$('.js-whitelist').attr('name'),
        tagLimit: 10,
        readOnly: false,
        onBlur: function() {
          self.$('.js-domains').removeClass('is-focus')

          if ($(".tagit-choice").length > 0) {
            $('.js-placeholder').hide();
          }
          else {
            $('.js-placeholder').show();
          }

          if ($(".tagit-new").length > 0) {
            $(".tagit-new input").val('')
          }
        },
        onFocus: function() {
          self.$('.js-domains').addClass('is-focus')

          $('.js-placeholder').hide();
        },
        beforeTagAdded: function(ev, ui) {
          if (!domainRegExp.test(ui.tagLabel)) {
            return false;
          }

          if ($(".tagit-choice").length > 0) {
            $('.js-placeholder').hide();
          }
          else { $('.js-placeholder').show(); }
        },
        afterTagAdded: function(ev, ui) {
          if ($(".tagit-choice").length > 0) {
            $('.js-placeholder').hide();
          }
          else { $('.js-placeholder').show(); }
        }
      });
    }

    // User quota main view
    if (organization_user_data) {
      new OrganizationUserQuota({
        el: this.$('.js-userQuota'),
        model: organizationUser
      })
    }

    // Organization users list
    if (this.$('.js-orgUsersList').length === 1) {
      var organizationUsers = new OrganizationUsersView({
        el: this.$('.js-orgUsersList'),
        organization: organization,
        organizationUsers: organizationUsers
      });
      organizationUsers.render();
    }

    // User deletion
    if (this.$('.js-deleteAccount').length > 0 && window.authenticity_token) {
      this.$('.js-deleteAccount').click(function(ev) {
        if (ev) {
          ev.preventDefault();
        }
        new DeleteAccount({
          organizationUser: organizationUser,
          authenticityToken: window.authenticity_token,
          clean_on_hide: true
        }).appendToBody();
      })
    }

    // API keys
    var regenerateApiKeyHandler = function(ev, scope, form_action) {
      if (ev) ev.preventDefault();
      var authenticity_token = $('[name=authenticity_token][value]').get(0).value;
      var dlg = new RegenerateKeysDialog({
        type: 'api',
        scope: scope,
        form_action: form_action,
        authenticity_token: authenticity_token
      });

      dlg.appendToBody();
    };

    $('.js-regenerateOrgUsersApiKey').bind('click', function(ev) {
      var current_username = $(this).attr('data-current_username');

      regenerateApiKeyHandler(ev, 'organization', '/u/' + current_username + '/organization/regenerate_api_keys');
    });

    $('.js-regenerateOrgUserApiKey').bind('click', function(ev) {
      var username = $(this).attr('data-username');
      var current_username = $(this).attr('data-current_username');

      regenerateApiKeyHandler(ev, 'organization_user', '/u/' + current_username + '/organization/users/' + username + '/regenerate_api_key');
    });

    var $groups = $('.js-groups-content');
    if ($groups) {
      if (!currentUser.isOrgAdmin()) {
        window.location = currentUser.viewUrl().accountSettings();
        return false;
      }

      var groups = new cdb.admin.OrganizationGroups([], {
        organization: currentUser.organization
      });
      var router = new GroupsRouter({
        rootUrl: currentUser.viewUrl().organization().groups(),
        groups: groups,
        user: currentUser
      });

      var groupsMainView = new GroupsMainView({
        el: $groups,
        groups: groups,
        router: router,
        user: currentUser
      });
      groupsMainView.render();
      window.groups = groupsMainView;

      router.enableAfterMainView();
    }
  });

});<|endoftext|>


<commit_before>
  /**
   *  Actions menu view, aka LayersPanel
   *
   *  - It needs at least visualization and user models.
   *    Globalerror to show connection or fetching errors.
   *
   *    var menu = new cdb.admin.LayersPanel({
   *      vis: vis_model,
   *      user: user_model,
   *      globalError: globalError_obj
   *    });
   */

  cdb.admin.LayersPanel = cdb.ui.common.TabPane.extend({

    className: 'table_panel',
    animation_time: 300,

    _MAX_LAYERS: 4,
    _MIN_LAYERS: 1,

    _TEXTS: {
      visualization: {
        msg:    _t('If you want to add multiple layers you need to create a visualization first.'),
        error:  _t('Error adding that table into the new visualization')
      },
      remove: {
        title:  _t('Delete this layer'),
        desc:   _t('You are about to delete this layer. Doing so won\'t remove your table, \
                only this visualization will be affected.'),
        ok:     _t('Delete layer')
      },
      cant_remove: {
        title:  _t('Delete this layer'),
        desc:   _t('You can\'t remove all layers from the visualization, it needs at least one to make it work.'),
        ok:     _t('Close')
      },
      error: {
        default: _t('Something went wrong, try again later')
      }
    },

    events: {
      'click .add_layer': '_addLayerDialog'
    },

    initialize: function() {
      this.layer_panels = []; // Layer panels added in the current visualization
      this.vis = this.options.vis;
      this.map = this.vis.map;
      this.globalError = this.options.globalError;

      // View bindings
      _.bindAll(this, 'sortLayers', 'manageLayers', '_checkResize');
      this.map.layers.bind('add',    this._newLayer, this);
      this.map.layers.bind('reset',  this._resetLayers, this);
      this.map.layers.bind('add remove', this.updateLayerPositionLabel, this);
      $(window).bind('resize', this._checkResize);
      this.add_related_model(this.map);
      this.bindSort(); // Bind sort movement

      this._addLayers(this.map.layers);

      // Setting several pane parameters
      this.isOpen = true;
      this.activeWorkView = 'table';

      cdb.ui.common.TabPane.prototype.initialize.call(this);
    },

    /* Layer panel functions */

    _resetLayers: function() {
      //clean all views
      this.removeTabs();
      // Empty layers array
      this.layer_panels = [];
      // Add again the layers
      this._addLayers(this.map.layers);
    },

    _addLayers: function(layers) {
      // Add 'add layer' button first
      this._addLayerAddButton();

      // Add layers
      var self = this;
      layers.each(function(l, pos) {
        self._addLayer(l, pos);
      });

      // Set default layer
      this._setDefaultLayer();
    },

    _newLayer: function(layer) {
      this._addLayer(layer);
    },

    _addLayer: function(layer, pos) {
      var self = this;
      if (layer.get('type') == 'CartoDB') {

        var v = new cdb.admin.LayerPanelView({
          model: layer,
          vis: self.vis,
          user: self.options.user,
          globalError: self.options.globalError
        });

        v.bind('toggle',    self._toggle, self);
        v.bind('switchTo',  self._switchTo, self);
        v.bind('delete',    self._remove, self);

        self.addTab(layer.cid, v);
        v.setActiveWorkView(self.activeWorkView);

        self.layer_panels.push(v);

        // no pos -> new layer -> set as current
        if (!pos) {
          self._switchTo(v);
        }

        self._checkLayers();
      }
    },

    _removeLayer: function(cid) {
      var layer_view = this.getPane(cid);
      var self = this;

      this.layer_panels = _.filter(this.layer_panels, function(view) {
        if (view != layer_view) return view;
      });

      var tabBind = function(cid) {
        var view = self.getPane(cid);
        self.trigger('switch', view);
        self.vis.save('active_layer_id', view.dataLayer.id);
        self.unbind('tabEnabled', tabBind);
      }

      this.bind('tabEnabled', tabBind);

      this.removeTab(cid);

      this._checkLayers();
      this.manageLayers();
    },

    _setDefaultLayer: function() {
      var layer;
      var layer_id = this.vis.get('active_layer_id');

      // No layer_id, get last layer
      if (!layer_id) {
        var layer = _.last(this.layer_panels);
      }

      // Get layer from layer_id
      if (!layer) {
        for (var i in this.layer_panels) {
          var lyr = this.layer_panels[i];
          if (lyr.dataLayer.id == layer_id) {
            layer = lyr;
            break;
          }
        }
      }

      // Any layer? Switch to it
      if (layer) {
        this._switchTo(layer, true);
      }
    },

    // Check how many layers-view there are in the panel
    _checkLayers: function() {
      if (this.map.layers.getLayersByType('CartoDB').length >= this._MAX_LAYERS) {
        this._hideLayerButton();
      } else {
        this._showLayerButton();
      }
    },

    /* Add layer functions */

    _addLayerAddButton: function() {
      this.$('.add_layer').remove();
      var template = this.getTemplate('table/views/add_layer');
      this.$el.prepend(template());
    },

    _showLayerButton: function() {
      this.$('section.add_layer').show();
    },

    _hideLayerButton: function() {
      this.$('section.add_layer').hide();
    },

    _addLayerDialog: function(e) {
      this.killEvent(e);
      var self = this;

      this.new_layer_dlg && this.new_layer_dlg.clean();
      this.new_layer_dlg = new cdb.admin.NewLayerDialog({
        model: self.vis,
        ok: function(tableName, private_vis) {

          var userName = self.options.user.get('name');

          if(!self.vis.isVisualization()) {
            self.create_vis_dialog && self.create_vis_dialog.clean();
            self.create_vis_dialog = new cdb.admin.CreateVizDialog({
              model: self.vis,
              msg: self._TEXTS.visualization.msg
            });

            self.create_vis_dialog.ok = function(vis) {
              self.map.addCartodbLayerFromTable(tableName, userName, {
                success: function() {
                  // Get scenario param (table or map)
                  var last_route = window.table_router.history.length > 0 && _.last(window.table_router.history).split('/');
                  // Create url
                  var url = "/viz/" + self.vis.get("id") + "/" + ( last_route[2] || 'table' );
                  // Navigate
                  window.table_router.navigate(url, { trigger: false });
                  window.table_router.addToHistory();
                },
                error: function() {
                  self.create_vis_dialog.onCreationError(null, self._TEXTS.visualization.error)
                }
              });
            }

            self.create_vis_dialog.appendToBody().open();
          } else {
            // It needs a privacy change?
            if (private_vis) {
              self.vis.set('privacy', 'PRIVATE');
            }

            // Add new layer
            self.map.addCartodbLayerFromTable(tableName, userName);
          }

        }
      })
      this.new_layer_dlg.appendToBody().open();
    },

    bindSort: function() {
      this.unbindSort();

      this.$el.sortable({
        axis:                 "y",
        items:                "> .layer_panel",
        handle:               ".layer_info a.info",
        contaiment:           "parent",
        opacity:              0.5,
        start:                this.startSort,
        update:               this.sortLayers,
        forcePlaceholderSize: false
      });
    },

    startSort: function(ev, ui) {
      // Set same height for placeholder
      var active_height = $(ui.item).outerHeight();
      $(ui.placeholder).outerHeight(active_height);
    },

    unbindSort: function() {
      this.$el.sortable('destroy')
    },

    updateLayerPositionLabel: function() {
      _.each(this.layer_panels, function(layer) {
        layer.setLayerOrder(layer.model);
      });
    },

    sortLayers: function() {
      var self = this;
      // set the new order in layer collection from layer view
      // positions
      var order = 1;
      this.$el.children().each(function(index, element) {
        var id = element.getAttribute('model-id');
        if(id) {
          var dataLayer = self.map.layers.get(id);
          if(dataLayer) {
            // use silent, save after all are sorted, see below
            dataLayer.set({ 'order': order }, { silent: true });
            order++;
          }
        }
      })

      // layers don't need to be reset when they are sorted
      // and save the new layers order to the server
      var count = _.after(this.map.layers.size(), function() {
        self.updateLayerPositionLabel();
        self.map.layers.bind('reset',  self._resetLayers, self);
      });

      this.map.layers.unbind('reset', this._resetLayers, this);
      this.map.layers.saveLayers({ success: count, error: count });
    },

    /* Magic layers */
    manageLayers: function() {
      var cartodb_layers = this.map.layers.getLayersByType('CartoDB').length;
      // If there isn't any layer added
      if (cartodb_layers == 0) return false;

      var $active_layer = this.activePane.$el;

      // Move rest of panels
      this.$el.find('.layer_panel').removeClass('active');

      // Add active class
      $active_layer.addClass('active');

      // Set rest of layer_panels to height 60px
      // Decide later about compress them
      // TODO: not use jquery
      this.$el.find('.layer_panel').not('.layer_panel.active').css({ height: 66 });

      // Get previous siblings and calculate space
      // TODO: not use jquery
      var pre_size = $active_layer.prevAll('.layer_panel').size();
      var t_s = (pre_size == 0) ? 0 : (pre_size * 53);

      // Get next siblings and calculate space
      // TODO: not use jquery
      var next_size = $active_layer.nextAll('.layer_panel').size();
      var b_s = (next_size == 0) ? 0 : (next_size * 53);

      // Set available space for the active layer_space
      // TODO: not use jquery
      var offset = 0;
      switch (cartodb_layers) {
        case 1:   offset = -15; break;
        case 2:   offset = 0; break;
        case 3:   offset = 10; break;
        case 4:   offset = 58; break;
        default:  offset = 0;
      }
      $active_layer.css({ height: this.$el.height() - (t_s + b_s) + offset })
      console.log(offset);
    },

    /* testing resize event */
    _checkResize: function(e) {
      if (this.resize) clearTimeout(this.resize);
      var self = this;
      this.resize = setTimeout(self.manageLayers, 100);
    },

    show: function(modName) {
      var width = 600,
          action = 'show';

      // Select the tab
      var mod = this.getActivePane();
      mod.tabs.activate(modName);
      mod.panels.active(modName);

      switch (modName) {
        case 'filters_mod':
        case 'wizards_mod':
        case 'infowindow_mod':
          width = 450;
          action = 'narrow';
          break;
        default:
      }

      // Show panel -> trigger
      cdb.god.trigger('panel_action', action);

      this.isOpen = true;
      this.$el.animate({
          width: width,
          right: 0
      }, this.animation_time, function() {
        cdb.god.trigger("end_" + action);
      });
    },

    hide: function(modName) {
      var panel_width = this.$el.width();

      // Hide the tab
      var mod = this.getActivePane();
      //mod.tabs.deactivate(modName);

      // Hide panel -> trigger
      cdb.god.trigger("panel_action", "hide");

      this.isOpen = false;
      this.$el.animate({
        right: 63 - panel_width
      }, this.animation_time);
    },

    _switchTo: function(l, notOpen) {
      // Check if this layer is already opened
      if (this.activePane == l && !notOpen && this.isOpen) {
        this.hide();
        return false;
      }
      // If not, activate it
      this.active(l.dataLayer.cid);
      if(this.vis.get('active_layer_id') != l.dataLayer.id) {
        this.vis.save('active_layer_id', l.dataLayer.id);
      }
      this.trigger('switch', l);
      // Check if panel width is correct
      // only if panel is clicked and
      // not set from default layer
      if (!notOpen) {
        var modName = l.panels.activeTab;
        this.show(modName);
      }
      this.manageLayers();
    },

    _toggle: function(modName) {
      // only hide if we click on active tab
      if (this.isOpen && modName == this.getActivePane().panels.activeTab) {
        this.hide(modName);
      } else {
        this.show(modName);
      }
    },

    // We need to review this method, it is not easy to
    // make operations when the view is cleaning/removing
    // For now the model destroy is happening here
    _remove: function(layer_view) {
      var cid = layer_view.dataLayer.cid;
      var self = this;
      var permitted = true;

      // Check if there is at least 1 layer
      // if not, don't let user do it
      if (this.map.layers.getLayersByType('CartoDB').length <= this._MIN_LAYERS) {
        permitted = false;
      }

      this.remove_dlg && this.remove_dlg.clean();
      this.remove_dlg = new cdb.admin.BaseDialog({
        title: self._TEXTS[permitted ? 'remove' : 'cant_remove'].title,
        description: self._TEXTS[permitted ? 'remove' : 'cant_remove'].desc,
        template_name: 'common/views/confirm_dialog',
        clean_on_hide: true,
        enter_to_confirm: true,
        ok_button_classes: "right button grey",
        ok_title: self._TEXTS[permitted ? 'remove' : 'cant_remove'].ok,
        cancel_button_classes: "underline margin15 " + (permitted ? '' : 'hide'),
        modal_type: "confirmation",
        width: 500
      });

      if (permitted) {
        // If user confirms, app removes this panel view,
        // including the map layer
        this.remove_dlg.ok = function() {
          // Destroy layer model
          layer_view.model.destroy({
            success: function() {
              self._removeLayer(cid)
            },
            error: function(){
              self.globalError.showError(that._TEXTS.error.default, 'error', 3000);
            }
          });
        }
      }

      // Show it up
      this.remove_dlg
        .appendToBody()
        .open();
    },

    setActiveWorkView: function(workView) {
      this.hide();
      this.activeWorkView = workView;

      // Set active work view for all panes,
      // not only for the current one
      this.each(function(tab, pane){
        pane.setActiveWorkView(workView);
      })
    },

    clean: function() {
      $(window).unbind('resize', this._checkResize);
      if (this.resize) clearTimeout(this.resize);
      this.unbindSort();
      cdb.ui.common.TabPane.prototype.clean.call(this);
    }
  });
<commit_msg>removed console.log<commit_after>
  /**
   *  Actions menu view, aka LayersPanel
   *
   *  - It needs at least visualization and user models.
   *    Globalerror to show connection or fetching errors.
   *
   *    var menu = new cdb.admin.LayersPanel({
   *      vis: vis_model,
   *      user: user_model,
   *      globalError: globalError_obj
   *    });
   */

  cdb.admin.LayersPanel = cdb.ui.common.TabPane.extend({

    className: 'table_panel',
    animation_time: 300,

    _MAX_LAYERS: 4,
    _MIN_LAYERS: 1,

    _TEXTS: {
      visualization: {
        msg:    _t('If you want to add multiple layers you need to create a visualization first.'),
        error:  _t('Error adding that table into the new visualization')
      },
      remove: {
        title:  _t('Delete this layer'),
        desc:   _t('You are about to delete this layer. Doing so won\'t remove your table, \
                only this visualization will be affected.'),
        ok:     _t('Delete layer')
      },
      cant_remove: {
        title:  _t('Delete this layer'),
        desc:   _t('You can\'t remove all layers from the visualization, it needs at least one to make it work.'),
        ok:     _t('Close')
      },
      error: {
        default: _t('Something went wrong, try again later')
      }
    },

    events: {
      'click .add_layer': '_addLayerDialog'
    },

    initialize: function() {
      this.layer_panels = []; // Layer panels added in the current visualization
      this.vis = this.options.vis;
      this.map = this.vis.map;
      this.globalError = this.options.globalError;

      // View bindings
      _.bindAll(this, 'sortLayers', 'manageLayers', '_checkResize');
      this.map.layers.bind('add',    this._newLayer, this);
      this.map.layers.bind('reset',  this._resetLayers, this);
      this.map.layers.bind('add remove', this.updateLayerPositionLabel, this);
      $(window).bind('resize', this._checkResize);
      this.add_related_model(this.map);
      this.bindSort(); // Bind sort movement

      this._addLayers(this.map.layers);

      // Setting several pane parameters
      this.isOpen = true;
      this.activeWorkView = 'table';

      cdb.ui.common.TabPane.prototype.initialize.call(this);
    },

    /* Layer panel functions */

    _resetLayers: function() {
      //clean all views
      this.removeTabs();
      // Empty layers array
      this.layer_panels = [];
      // Add again the layers
      this._addLayers(this.map.layers);
    },

    _addLayers: function(layers) {
      // Add 'add layer' button first
      this._addLayerAddButton();

      // Add layers
      var self = this;
      layers.each(function(l, pos) {
        self._addLayer(l, pos);
      });

      // Set default layer
      this._setDefaultLayer();
    },

    _newLayer: function(layer) {
      this._addLayer(layer);
    },

    _addLayer: function(layer, pos) {
      var self = this;
      if (layer.get('type') == 'CartoDB') {

        var v = new cdb.admin.LayerPanelView({
          model: layer,
          vis: self.vis,
          user: self.options.user,
          globalError: self.options.globalError
        });

        v.bind('toggle',    self._toggle, self);
        v.bind('switchTo',  self._switchTo, self);
        v.bind('delete',    self._remove, self);

        self.addTab(layer.cid, v);
        v.setActiveWorkView(self.activeWorkView);

        self.layer_panels.push(v);

        // no pos -> new layer -> set as current
        if (!pos) {
          self._switchTo(v);
        }

        self._checkLayers();
      }
    },

    _removeLayer: function(cid) {
      var layer_view = this.getPane(cid);
      var self = this;

      this.layer_panels = _.filter(this.layer_panels, function(view) {
        if (view != layer_view) return view;
      });

      var tabBind = function(cid) {
        var view = self.getPane(cid);
        self.trigger('switch', view);
        self.vis.save('active_layer_id', view.dataLayer.id);
        self.unbind('tabEnabled', tabBind);
      }

      this.bind('tabEnabled', tabBind);

      this.removeTab(cid);

      this._checkLayers();
      this.manageLayers();
    },

    _setDefaultLayer: function() {
      var layer;
      var layer_id = this.vis.get('active_layer_id');

      // No layer_id, get last layer
      if (!layer_id) {
        var layer = _.last(this.layer_panels);
      }

      // Get layer from layer_id
      if (!layer) {
        for (var i in this.layer_panels) {
          var lyr = this.layer_panels[i];
          if (lyr.dataLayer.id == layer_id) {
            layer = lyr;
            break;
          }
        }
      }

      // Any layer? Switch to it
      if (layer) {
        this._switchTo(layer, true);
      }
    },

    // Check how many layers-view there are in the panel
    _checkLayers: function() {
      if (this.map.layers.getLayersByType('CartoDB').length >= this._MAX_LAYERS) {
        this._hideLayerButton();
      } else {
        this._showLayerButton();
      }
    },

    /* Add layer functions */

    _addLayerAddButton: function() {
      this.$('.add_layer').remove();
      var template = this.getTemplate('table/views/add_layer');
      this.$el.prepend(template());
    },

    _showLayerButton: function() {
      this.$('section.add_layer').show();
    },

    _hideLayerButton: function() {
      this.$('section.add_layer').hide();
    },

    _addLayerDialog: function(e) {
      this.killEvent(e);
      var self = this;

      this.new_layer_dlg && this.new_layer_dlg.clean();
      this.new_layer_dlg = new cdb.admin.NewLayerDialog({
        model: self.vis,
        ok: function(tableName, private_vis) {

          var userName = self.options.user.get('name');

          if(!self.vis.isVisualization()) {
            self.create_vis_dialog && self.create_vis_dialog.clean();
            self.create_vis_dialog = new cdb.admin.CreateVizDialog({
              model: self.vis,
              msg: self._TEXTS.visualization.msg
            });

            self.create_vis_dialog.ok = function(vis) {
              self.map.addCartodbLayerFromTable(tableName, userName, {
                success: function() {
                  // Get scenario param (table or map)
                  var last_route = window.table_router.history.length > 0 && _.last(window.table_router.history).split('/');
                  // Create url
                  var url = "/viz/" + self.vis.get("id") + "/" + ( last_route[2] || 'table' );
                  // Navigate
                  window.table_router.navigate(url, { trigger: false });
                  window.table_router.addToHistory();
                },
                error: function() {
                  self.create_vis_dialog.onCreationError(null, self._TEXTS.visualization.error)
                }
              });
            }

            self.create_vis_dialog.appendToBody().open();
          } else {
            // It needs a privacy change?
            if (private_vis) {
              self.vis.set('privacy', 'PRIVATE');
            }

            // Add new layer
            self.map.addCartodbLayerFromTable(tableName, userName);
          }

        }
      })
      this.new_layer_dlg.appendToBody().open();
    },

    bindSort: function() {
      this.unbindSort();

      this.$el.sortable({
        axis:                 "y",
        items:                "> .layer_panel",
        handle:               ".layer_info a.info",
        contaiment:           "parent",
        opacity:              0.5,
        start:                this.startSort,
        update:               this.sortLayers,
        forcePlaceholderSize: false
      });
    },

    startSort: function(ev, ui) {
      // Set same height for placeholder
      var active_height = $(ui.item).outerHeight();
      $(ui.placeholder).outerHeight(active_height);
    },

    unbindSort: function() {
      this.$el.sortable('destroy')
    },

    updateLayerPositionLabel: function() {
      _.each(this.layer_panels, function(layer) {
        layer.setLayerOrder(layer.model);
      });
    },

    sortLayers: function() {
      var self = this;
      // set the new order in layer collection from layer view
      // positions
      var order = 1;
      this.$el.children().each(function(index, element) {
        var id = element.getAttribute('model-id');
        if(id) {
          var dataLayer = self.map.layers.get(id);
          if(dataLayer) {
            // use silent, save after all are sorted, see below
            dataLayer.set({ 'order': order }, { silent: true });
            order++;
          }
        }
      })

      // layers don't need to be reset when they are sorted
      // and save the new layers order to the server
      var count = _.after(this.map.layers.size(), function() {
        self.updateLayerPositionLabel();
        self.map.layers.bind('reset',  self._resetLayers, self);
      });

      this.map.layers.unbind('reset', this._resetLayers, this);
      this.map.layers.saveLayers({ success: count, error: count });
    },

    /* Magic layers */
    manageLayers: function() {
      var cartodb_layers = this.map.layers.getLayersByType('CartoDB').length;
      // If there isn't any layer added
      if (cartodb_layers == 0) return false;

      var $active_layer = this.activePane.$el;

      // Move rest of panels
      this.$el.find('.layer_panel').removeClass('active');

      // Add active class
      $active_layer.addClass('active');

      // Set rest of layer_panels to height 60px
      // Decide later about compress them
      // TODO: not use jquery
      this.$el.find('.layer_panel').not('.layer_panel.active').css({ height: 66 });

      // Get previous siblings and calculate space
      // TODO: not use jquery
      var pre_size = $active_layer.prevAll('.layer_panel').size();
      var t_s = (pre_size == 0) ? 0 : (pre_size * 53);

      // Get next siblings and calculate space
      // TODO: not use jquery
      var next_size = $active_layer.nextAll('.layer_panel').size();
      var b_s = (next_size == 0) ? 0 : (next_size * 53);

      // Set available space for the active layer_space
      // TODO: not use jquery
      var offset = 0;
      switch (cartodb_layers) {
        case 1:   offset = -15; break;
        case 2:   offset = 0; break;
        case 3:   offset = 10; break;
        case 4:   offset = 58; break;
        default:  offset = 0;
      }
      $active_layer.css({ height: this.$el.height() - (t_s + b_s) + offset })
    },

    /* testing resize event */
    _checkResize: function(e) {
      if (this.resize) clearTimeout(this.resize);
      var self = this;
      this.resize = setTimeout(self.manageLayers, 100);
    },

    show: function(modName) {
      var width = 600,
          action = 'show';

      // Select the tab
      var mod = this.getActivePane();
      mod.tabs.activate(modName);
      mod.panels.active(modName);

      switch (modName) {
        case 'filters_mod':
        case 'wizards_mod':
        case 'infowindow_mod':
          width = 450;
          action = 'narrow';
          break;
        default:
      }

      // Show panel -> trigger
      cdb.god.trigger('panel_action', action);

      this.isOpen = true;
      this.$el.animate({
          width: width,
          right: 0
      }, this.animation_time, function() {
        cdb.god.trigger("end_" + action);
      });
    },

    hide: function(modName) {
      var panel_width = this.$el.width();

      // Hide the tab
      var mod = this.getActivePane();
      //mod.tabs.deactivate(modName);

      // Hide panel -> trigger
      cdb.god.trigger("panel_action", "hide");

      this.isOpen = false;
      this.$el.animate({
        right: 63 - panel_width
      }, this.animation_time);
    },

    _switchTo: function(l, notOpen) {
      // Check if this layer is already opened
      if (this.activePane == l && !notOpen && this.isOpen) {
        this.hide();
        return false;
      }
      // If not, activate it
      this.active(l.dataLayer.cid);
      if(this.vis.get('active_layer_id') != l.dataLayer.id) {
        this.vis.save('active_layer_id', l.dataLayer.id);
      }
      this.trigger('switch', l);
      // Check if panel width is correct
      // only if panel is clicked and
      // not set from default layer
      if (!notOpen) {
        var modName = l.panels.activeTab;
        this.show(modName);
      }
      this.manageLayers();
    },

    _toggle: function(modName) {
      // only hide if we click on active tab
      if (this.isOpen && modName == this.getActivePane().panels.activeTab) {
        this.hide(modName);
      } else {
        this.show(modName);
      }
    },

    // We need to review this method, it is not easy to
    // make operations when the view is cleaning/removing
    // For now the model destroy is happening here
    _remove: function(layer_view) {
      var cid = layer_view.dataLayer.cid;
      var self = this;
      var permitted = true;

      // Check if there is at least 1 layer
      // if not, don't let user do it
      if (this.map.layers.getLayersByType('CartoDB').length <= this._MIN_LAYERS) {
        permitted = false;
      }

      this.remove_dlg && this.remove_dlg.clean();
      this.remove_dlg = new cdb.admin.BaseDialog({
        title: self._TEXTS[permitted ? 'remove' : 'cant_remove'].title,
        description: self._TEXTS[permitted ? 'remove' : 'cant_remove'].desc,
        template_name: 'common/views/confirm_dialog',
        clean_on_hide: true,
        enter_to_confirm: true,
        ok_button_classes: "right button grey",
        ok_title: self._TEXTS[permitted ? 'remove' : 'cant_remove'].ok,
        cancel_button_classes: "underline margin15 " + (permitted ? '' : 'hide'),
        modal_type: "confirmation",
        width: 500
      });

      if (permitted) {
        // If user confirms, app removes this panel view,
        // including the map layer
        this.remove_dlg.ok = function() {
          // Destroy layer model
          layer_view.model.destroy({
            success: function() {
              self._removeLayer(cid)
            },
            error: function(){
              self.globalError.showError(that._TEXTS.error.default, 'error', 3000);
            }
          });
        }
      }

      // Show it up
      this.remove_dlg
        .appendToBody()
        .open();
    },

    setActiveWorkView: function(workView) {
      this.hide();
      this.activeWorkView = workView;

      // Set active work view for all panes,
      // not only for the current one
      this.each(function(tab, pane){
        pane.setActiveWorkView(workView);
      })
    },

    clean: function() {
      $(window).unbind('resize', this._checkResize);
      if (this.resize) clearTimeout(this.resize);
      this.unbindSort();
      cdb.ui.common.TabPane.prototype.clean.call(this);
    }
  });
<|endoftext|>