<commit_before>/**
 * The LandRights layer module.
 *
 * @return LandRightsLayer class (extends CartoDBLayerClass)
 */
define([
  'abstract/layer/CartoDBLayerClass',
], function(CartoDBLayerClass) {

  'use strict';

  var LandRightsLayer = CartoDBLayerClass.extend({

    options: {
      sql: 'SELECT the_geom_webmercator,name, country, national_legal_term, legal_recognition, ROUND(area_ha) AS area_ha, category,  \'{tableName}\' as layer FROM {tableName}',
      infowindow: true,
      interactivity: 'name, country, national_legal_term, legal_recognition, area_ha, category'
    }

  });

  return LandRightsLayer;

});
<commit_msg>switch land rights table to synced<commit_after>/**
 * The LandRights layer module.
 *
 * @return LandRightsLayer class (extends CartoDBLayerClass)
 */
define([
  'abstract/layer/CartoDBLayerClass',
], function(CartoDBLayerClass) {

  'use strict';

  var LandRightsLayer = CartoDBLayerClass.extend({

    options: {
      sql: 'SELECT the_geom_webmercator,name, country, legal_term, recognized, ROUND(area_ha::text::float) AS area_ha, category,  \'{tableName}\' as layer FROM {tableName}',
      infowindow: true,
      interactivity: 'name, country, legal_term, recognized, area_ha, category'
    }

  });

  return LandRightsLayer;

});
<|endoftext|>


<commit_before>/***

 For instructions see:
 https://github.com/ghacksuserjs/ghacks-user.js/wiki/3.1-Resetting-Inactive-Prefs-[Scripts]

***/

(function() {
  let ops = [
    /* --- 57-alpha --- */
    /* commented out */
    'browser.storageManager.enabled',
    'dom.storageManager.enabled',
    /* removed from the user.js */
    'browser.search.geoip.timeout',
    'geo.wifi.xhr.timeout',
    'gfx.layerscope.enabled',
    'media.webspeech.recognition.enable',
    /* moved to RFP ALTERNATIVES */
    'dom.w3c_touch_events.enabled',
    'media.video_stats.enabled',
    /* moved to DEPRECATED/REMOVED */
    'browser.bookmarks.showRecentlyBookmarked',
    'browser.casting.enabled',
    'devtools.webide.autoinstallFxdtAdapters',
    'media.eme.chromium-api.enabled',
    'social.directories',
    'social.enabled',
    'social.remote-install.enabled',
    'social.share.activationPanelEnabled',
    'social.shareDirectory',
    'social.toast-notifications.enabled',
    'social.whitelist',
    /* reset parrot: check your open about:config after running the script */
    '_user.js.parrot'
  ]

  if("undefined" === typeof(Services)) {
    alert("about:config needs to be the active tab!");
    return;
  }

  let c = 0;
  for (let i = 0, len = ops.length; i < len; i++) {
    if (Services.prefs.prefHasUserValue(ops[i])) {
      Services.prefs.clearUserPref(ops[i]);
      if (!Services.prefs.prefHasUserValue(ops[i])) {
        console.log("reset", ops[i]);
        c++;
      } else { console.log("failed to reset", ops[i]); }
    }
  }

  focus();

  let d = (c==1) ? " pref" : " prefs";
  if (c > 0) {
    alert("successfully reset " + c + d + "\n\nfor details check the Browser Console (Ctrl+Shift+J)");
  } else { alert("nothing to reset"); }

})();
<commit_msg>Delete ghacks-clear-57-[changes-only].js<commit_after><|endoftext|>


<commit_before>(function (Handsontable) {
  'use strict';

  function ContextMenu(instance, customOptions){
    this.instance = instance;
    var contextMenu = this;

    this.menu = createMenu();
    this.enabled = true;

    this.bindMouseEvents();
    this.bindTableEvents();

    this.instance.addHook('afterDestroy', function () {
       contextMenu.destroy();
    });

    this.defaultOptions = {
      items: {
        'row_above': {
          name: 'Insert row above',
          callback: function(key, selection){
            this.alter("insert_row", selection.start.row());
          },
          disabled: function () {
            return this.countRows() >= this.getSettings().maxRows;
          }
        },
        'row_below': {
          name: 'Insert row below',
          callback: function(key, selection){
            this.alter("insert_row", selection.end.row() + 1);
          },
          disabled: function () {
            return this.countRows() >= this.getSettings().maxRows;
          }
        },
        "hsep1": ContextMenu.SEPARATOR,
        'col_left': {
          name: 'Insert column on the left',
          callback: function(key, selection){
            this.alter("insert_col", selection.start.col());
          },
          disabled: function () {
            return this.countCols() >= this.getSettings().maxCols;
          }
        },
        'col_right': {
          name: 'Insert column on the right',
          callback: function(key, selection){
            this.alter("insert_col", selection.end.col() + 1);
          },
          disabled: function () {
            return this.countCols() >= this.getSettings().maxCols;
          }
        },
        "hsep2": ContextMenu.SEPARATOR,
        'remove_row': {
          name: 'Remove row',
          callback: function(key, selection){
            var amount = selection.end.row() - selection.start.row() + 1;
            this.alter("remove_row", selection.start.row(), amount);
          }
        },
        'remove_col': {
          name: 'Remove column',
          callback: function(key, selection){
            var amount = selection.end.col() - selection.start.col() + 1;
            this.alter("remove_col", selection.start.col(), amount);
          }
        },
        "hsep3": ContextMenu.SEPARATOR,
        'undo': {
          name: 'Undo',
          callback: function(){
            this.undo();
          },
          disabled: function () {
            return this.undoRedo && !this.undoRedo.isUndoAvailable();
          }
        },
        'redo': {
          name: 'Redo',
          callback: function(){
            this.redo();
          },
          disabled: function () {
            return this.undoRedo && !this.undoRedo.isRedoAvailable();
          }
        }

      }
    };

    this.options = {};
    Handsontable.helper.extend(this.options, this.defaultOptions);

    this.updateOptions(customOptions);

    function createMenu(){

      var menu = $('body > .htContextMenu')[0];

      if(!menu){
        menu = document.createElement('DIV');
        Handsontable.Dom.addClass(menu, 'htContextMenu');
        document.getElementsByTagName('body')[0].appendChild(menu);
      }

      return menu;
    }
  }

  ContextMenu.prototype.bindMouseEvents = function (){

    function contextMenuOpenListener(event){

      event.preventDefault();

      if(event.target.nodeName != 'TD' && !(Handsontable.Dom.hasClass(event.target, 'current') && Handsontable.Dom.hasClass(event.target, 'wtBorder'))){
        return;
      }

      this.show(event.pageY, event.pageX);

      $(document).on('mousedown.htContextMenu', Handsontable.helper.proxy(ContextMenu.prototype.close, this));
    }

    this.instance.rootElement.on('contextmenu.htContextMenu', Handsontable.helper.proxy(contextMenuOpenListener, this));

    $(this.menu).on('mousedown', Handsontable.helper.proxy(this.performAction, this));
  };

  ContextMenu.prototype.bindTableEvents = function () {
    var that = this;

    this._afterScrollCallback = function () {
      that.close();
    };

    this.instance.addHook('afterScrollVertically', this._afterScrollCallback);
    this.instance.addHook('afterScrollHorizontally', this._afterScrollCallback);
  };

  ContextMenu.prototype.unbindTableEvents = function () {
    var that = this;

    if(this._afterScrollCallback){
      this.instance.removeHook('afterScrollVertically', this._afterScrollCallback);
      this.instance.removeHook('afterScrollHorizontally', this._afterScrollCallback);
      this._afterScrollCallback = null;
    }

  };

  ContextMenu.prototype.performAction = function (){

    var hot = $(this.menu).handsontable('getInstance');
    var selectedItemIndex = hot.getSelected()[0];
    var selectedItem = hot.getData()[selectedItemIndex];

    if (selectedItem.disabled === true || (typeof selectedItem.disabled == 'function' && selectedItem.disabled.call(this.instance) === true)){
      return;
    }

    if(typeof selectedItem.callback != 'function'){
      return;
    }

    var corners = this.instance.getSelected();
    var normalizedSelection = ContextMenu.utils.normalizeSelection(corners);

    selectedItem.callback.call(this.instance, selectedItem.key, normalizedSelection);

  };

  ContextMenu.prototype.unbindMouseEvents = function () {
    this.instance.rootElement.off('contextmenu.htContextMenu');
    $(document).off('mousedown.htContextMenu');
  };

  ContextMenu.prototype.show = function(top, left){

    this.menu.style.display = 'block';

    $(this.menu).handsontable({
      data: ContextMenu.utils.convertItemsToArray(this.getItems()),
      colHeaders: false,
      colWidths: [160],
      readOnly: true,
      copyPaste: false,
      columns: [
        {
          data: 'name',
          renderer: Handsontable.helper.proxy(this.renderer, this)
        }
      ],
      beforeKeyDown: Handsontable.helper.proxy(this.onBeforeKeyDown, this)
    });

    this.setMenuPosition(top, left);

    $(this.menu).handsontable('listen');

  };

  ContextMenu.prototype.renderer = function(instance, TD, row, col, prop, value, cellProperties){
    var contextMenu = this;
    var item = instance.getData()[row];
    var wrapper = document.createElement('DIV');

    Handsontable.Dom.empty(TD);
    TD.appendChild(wrapper);

    if(itemIsSeparator(item)){
      Handsontable.Dom.addClass(TD, 'htSeparator');
    } else {
      Handsontable.Dom.fastInnerText(wrapper, value);
    }

    if (itemIsDisabled(item, contextMenu.instance)){
      Handsontable.Dom.addClass(TD, 'htDisabled');

      $(wrapper).on('mouseenter', function () {
        instance.deselectCell();
      });

    } else {
      Handsontable.Dom.removeClass(TD, 'htDisabled');

      $(wrapper).on('mouseenter', function () {
        instance.selectCell(row, col);
      });

    }

    function itemIsSeparator(item){
      return new RegExp(ContextMenu.SEPARATOR, 'i').test(item.name);
    }

    function itemIsDisabled(item, instance){
      return item.disabled === true || (typeof item.disabled == 'function' && item.disabled.call(contextMenu.instance) === true);
    }
  };

  ContextMenu.prototype.onBeforeKeyDown = function (event) {
    var contextMenu = this;
    var instance = $(contextMenu.menu).handsontable('getInstance');
    var selection = instance.getSelected();

    switch(event.keyCode){

      case Handsontable.helper.keyCode.ESCAPE:
        contextMenu.close();
        event.preventDefault();
        event.stopImmediatePropagation();
        break;

      case Handsontable.helper.keyCode.ENTER:
        if(instance.getSelected()){
          contextMenu.performAction();
          contextMenu.close();
        }
        break;

      case Handsontable.helper.keyCode.ARROW_DOWN:
        if(!selection){

          selectFirstCell(instance);

        } else {

          selectNextCell(selection[0], selection[1], instance);

        }

        event.preventDefault();
        event.stopImmediatePropagation();

        break;

      case Handsontable.helper.keyCode.ARROW_UP:
        if(!selection){

          selectLastCell(instance);

        }  else {

          selectPrevCell(selection[0], selection[1], instance);

        }

        event.preventDefault();
        event.stopImmediatePropagation();

        break;

    }

    function selectFirstCell(instance) {

      var firstCell = instance.getCell(0, 0);

      if(ContextMenu.utils.isSeparator(firstCell) || ContextMenu.utils.isDisabled(firstCell)){
        selectNextCell(0, 0, instance);
      } else {
        instance.selectCell(0, 0);
      }

    }

    function selectLastCell(instance) {

      var lastRow = instance.countRows() - 1;
      var lastCell = instance.getCell(lastRow, 0);

      if(ContextMenu.utils.isSeparator(lastCell) || ContextMenu.utils.isDisabled(lastCell)){
        selectPrevCell(lastRow, 0, instance);
      } else {
        instance.selectCell(lastRow, 0);
      }

    }

    function selectNextCell(row, col, instance){
      var nextRow = row + 1;
      var nextCell =  nextRow < instance.countRows() ? instance.getCell(nextRow, col) : null;

      if(!nextCell){
        return;
      }

      if(ContextMenu.utils.isSeparator(nextCell) || ContextMenu.utils.isDisabled(nextCell)){
        selectNextCell(nextRow, col, instance);
      } else {
        instance.selectCell(nextRow, col);
      }
    }

    function selectPrevCell(row, col, instance) {

      var prevRow = row - 1;
      var prevCell = prevRow >= 0 ? instance.getCell(prevRow, col) : null;

      if (!prevCell) {
        return;
      }

      if(ContextMenu.utils.isSeparator(prevCell) || ContextMenu.utils.isDisabled(prevCell)){
        selectPrevCell(prevRow, col, instance);
      } else {
        instance.selectCell(prevRow, col);
      }

    }

  };

  ContextMenu.prototype.getItems = function () {
    var items = {};
    function Item(rawItem){
      if(typeof rawItem == 'string'){
        this.name = rawItem;
      } else {
        Handsontable.helper.extend(this, rawItem);
      }
    }
    Item.prototype = this.options;

    for(var itemName in this.options.items){
      if(this.options.items.hasOwnProperty(itemName) && (!this.itemsFilter || this.itemsFilter.indexOf(itemName) != -1)){
        items[itemName] = new Item(this.options.items[itemName]);
      }
    }

    return items;

  };

  ContextMenu.prototype.updateOptions = function(newOptions){
    newOptions = newOptions || {};

    if(newOptions.items){
      for(var itemName in newOptions.items){
        var item = {};

        if(newOptions.items.hasOwnProperty(itemName)) {
          if(this.defaultOptions.items.hasOwnProperty(itemName)
            && Handsontable.helper.isObject(newOptions.items[itemName])){
            Handsontable.helper.extend(item, this.defaultOptions.items[itemName]);
            Handsontable.helper.extend(item, newOptions.items[itemName]);
            newOptions.items[itemName] = item;
          }
        }

      }
    }

    Handsontable.helper.extend(this.options, newOptions);
  };

  ContextMenu.prototype.setMenuPosition = function (cursorY, cursorX) {

    var cursor = {
      top:  cursorY,
      topRelative: cursorY - window.pageYOffset,
      left: cursorX,
      leftRelative:cursorX - window.pageXOffset
    };

    if(this.menuFitsBelowCursor(cursor)){
      this.positionMenuBelowCursor(cursor);
    } else {
      this.positionMenuAboveCursor(cursor);
    }

    if(this.menuFitsOnRightOfCursor(cursor)){
      this.positionMenuOnRightOfCursor(cursor);
    } else {
      this.positionMenuOnLeftOfCursor(cursor);
    }

  };

  ContextMenu.prototype.menuFitsBelowCursor = function (cursor) {
    return cursor.topRelative + this.menu.offsetHeight <= document.documentElement.scrollTop + document.documentElement.clientHeight;
  };

  ContextMenu.prototype.menuFitsOnRightOfCursor = function (cursor) {
    return cursor.leftRelative + this.menu.offsetWidth <= document.documentElement.scrollLeft + document.documentElement.clientWidth;
  };

  ContextMenu.prototype.positionMenuBelowCursor = function (cursor) {
    this.menu.style.top = cursor.top + 'px';
  };

  ContextMenu.prototype.positionMenuAboveCursor = function (cursor) {
    this.menu.style.top = (cursor.top - this.menu.offsetHeight) + 'px';
  };

  ContextMenu.prototype.positionMenuOnRightOfCursor = function (cursor) {
    this.menu.style.left = cursor.left + 'px';
  };

  ContextMenu.prototype.positionMenuOnLeftOfCursor = function (cursor) {
    this.menu.style.left = (cursor.left - this.menu.offsetWidth) + 'px';
  };

  ContextMenu.utils = {};
  ContextMenu.utils.convertItemsToArray = function (items) {
    var itemArray = [];
    var item;
    for(var itemName in items){
      if(items.hasOwnProperty(itemName)){
        if(typeof items[itemName] == 'string'){
          item = {name: items[itemName]};
        } else if (items[itemName].visible !== false) {
          item = items[itemName];
        } else {
          continue;
        }

        item.key = itemName;
        itemArray.push(item);
      }
    }

    return itemArray;
  };

  ContextMenu.utils.normalizeSelection = function(corners){
    var selection = {
      start: new Handsontable.SelectionPoint(),
      end: new Handsontable.SelectionPoint()
    };

    selection.start.row(Math.min(corners[0], corners[2]));
    selection.start.col(Math.min(corners[1], corners[3]));

    selection.end.row(Math.max(corners[0], corners[2]));
    selection.end.col(Math.max(corners[1], corners[3]));

    return selection;
  };

  ContextMenu.utils.isSeparator = function (cell) {
    return Handsontable.Dom.hasClass(cell, 'htSeparator');
  };

  ContextMenu.utils.isDisabled = function (cell) {
    return Handsontable.Dom.hasClass(cell, 'htDisabled');
  };

  ContextMenu.prototype.close = function () {
    this.hide();
    $(document).off('mousedown.htContextMenu');
    this.instance.listen();
  };

  ContextMenu.prototype.hide = function(){
    this.menu.style.display = 'none';
    $(this.menu).handsontable('destroy');
  };

  ContextMenu.prototype.enable = function () {
    if(!this.enabled){
      this.enabled = true;
      this.bindMouseEvents();
    }
  };

  ContextMenu.prototype.disable = function () {
    if(this.enabled){
      this.enabled = false;
      this.close();
      this.unbindMouseEvents();
      this.unbindTableEvents();
    }
  };

  ContextMenu.prototype.destroy = function () {
    this.close();
    this.unbindMouseEvents();
    this.unbindTableEvents();

    if(!this.isMenuEnabledByOtherHotInstance()){
      this.removeMenu();
    }

  };

  ContextMenu.prototype.isMenuEnabledByOtherHotInstance = function () {
    var hotContainers = $('.handsontable');
    var menuEnabled = false;

    for(var i = 0, len = hotContainers.length; i < len; i++){
      var instance = $(hotContainers[i]).handsontable('getInstance');
      if(instance && instance.getSettings().contextMenu){
        menuEnabled = true;
        break;
      }
    }

    return menuEnabled;
  };

  ContextMenu.prototype.removeMenu = function () {
    if(this.menu.parentNode){
      this.menu.parentNode.removeChild(this.menu);
    }
  }

  ContextMenu.prototype.filterItems = function(itemsToLeave){
    this.itemsFilter = itemsToLeave;
  };

  ContextMenu.SEPARATOR = "---------";

  function init(){
    var instance = this;
    var contextMenuSetting = instance.getSettings().contextMenu;
    var customOptions = Handsontable.helper.isObject(contextMenuSetting) ? contextMenuSetting : {};

    if(contextMenuSetting){
      if(!instance.contextMenu){
        instance.contextMenu = new ContextMenu(instance, customOptions);
      }

      instance.contextMenu.enable();

      if(Handsontable.helper.isArray(contextMenuSetting)){
        instance.contextMenu.filterItems(contextMenuSetting);
      }

    }  else if(instance.contextMenu){
      instance.contextMenu.destroy();
      delete instance.contextMenu;
    }

  }

  Handsontable.PluginHooks.add('afterInit', init);
  Handsontable.PluginHooks.add('afterUpdateSettings', init);

  Handsontable.ContextMenu = ContextMenu;

})(Handsontable);
<commit_msg>Fixed vertical positioning of contextMenu in IE<commit_after>(function (Handsontable) {
  'use strict';

  function ContextMenu(instance, customOptions){
    this.instance = instance;
    var contextMenu = this;

    this.menu = createMenu();
    this.enabled = true;

    this.bindMouseEvents();
    this.bindTableEvents();

    this.instance.addHook('afterDestroy', function () {
       contextMenu.destroy();
    });

    this.defaultOptions = {
      items: {
        'row_above': {
          name: 'Insert row above',
          callback: function(key, selection){
            this.alter("insert_row", selection.start.row());
          },
          disabled: function () {
            return this.countRows() >= this.getSettings().maxRows;
          }
        },
        'row_below': {
          name: 'Insert row below',
          callback: function(key, selection){
            this.alter("insert_row", selection.end.row() + 1);
          },
          disabled: function () {
            return this.countRows() >= this.getSettings().maxRows;
          }
        },
        "hsep1": ContextMenu.SEPARATOR,
        'col_left': {
          name: 'Insert column on the left',
          callback: function(key, selection){
            this.alter("insert_col", selection.start.col());
          },
          disabled: function () {
            return this.countCols() >= this.getSettings().maxCols;
          }
        },
        'col_right': {
          name: 'Insert column on the right',
          callback: function(key, selection){
            this.alter("insert_col", selection.end.col() + 1);
          },
          disabled: function () {
            return this.countCols() >= this.getSettings().maxCols;
          }
        },
        "hsep2": ContextMenu.SEPARATOR,
        'remove_row': {
          name: 'Remove row',
          callback: function(key, selection){
            var amount = selection.end.row() - selection.start.row() + 1;
            this.alter("remove_row", selection.start.row(), amount);
          }
        },
        'remove_col': {
          name: 'Remove column',
          callback: function(key, selection){
            var amount = selection.end.col() - selection.start.col() + 1;
            this.alter("remove_col", selection.start.col(), amount);
          }
        },
        "hsep3": ContextMenu.SEPARATOR,
        'undo': {
          name: 'Undo',
          callback: function(){
            this.undo();
          },
          disabled: function () {
            return this.undoRedo && !this.undoRedo.isUndoAvailable();
          }
        },
        'redo': {
          name: 'Redo',
          callback: function(){
            this.redo();
          },
          disabled: function () {
            return this.undoRedo && !this.undoRedo.isRedoAvailable();
          }
        }

      }
    };

    this.options = {};
    Handsontable.helper.extend(this.options, this.defaultOptions);

    this.updateOptions(customOptions);

    function createMenu(){

      var menu = $('body > .htContextMenu')[0];

      if(!menu){
        menu = document.createElement('DIV');
        Handsontable.Dom.addClass(menu, 'htContextMenu');
        document.getElementsByTagName('body')[0].appendChild(menu);
      }

      return menu;
    }
  }

  ContextMenu.prototype.bindMouseEvents = function (){

    function contextMenuOpenListener(event){

      event.preventDefault();

      if(event.target.nodeName != 'TD' && !(Handsontable.Dom.hasClass(event.target, 'current') && Handsontable.Dom.hasClass(event.target, 'wtBorder'))){
        return;
      }

      this.show(event.pageY, event.pageX);

      $(document).on('mousedown.htContextMenu', Handsontable.helper.proxy(ContextMenu.prototype.close, this));
    }

    this.instance.rootElement.on('contextmenu.htContextMenu', Handsontable.helper.proxy(contextMenuOpenListener, this));

    $(this.menu).on('mousedown', Handsontable.helper.proxy(this.performAction, this));
  };

  ContextMenu.prototype.bindTableEvents = function () {
    var that = this;

    this._afterScrollCallback = function () {
      that.close();
    };

    this.instance.addHook('afterScrollVertically', this._afterScrollCallback);
    this.instance.addHook('afterScrollHorizontally', this._afterScrollCallback);
  };

  ContextMenu.prototype.unbindTableEvents = function () {
    var that = this;

    if(this._afterScrollCallback){
      this.instance.removeHook('afterScrollVertically', this._afterScrollCallback);
      this.instance.removeHook('afterScrollHorizontally', this._afterScrollCallback);
      this._afterScrollCallback = null;
    }

  };

  ContextMenu.prototype.performAction = function (){

    var hot = $(this.menu).handsontable('getInstance');
    var selectedItemIndex = hot.getSelected()[0];
    var selectedItem = hot.getData()[selectedItemIndex];

    if (selectedItem.disabled === true || (typeof selectedItem.disabled == 'function' && selectedItem.disabled.call(this.instance) === true)){
      return;
    }

    if(typeof selectedItem.callback != 'function'){
      return;
    }

    var corners = this.instance.getSelected();
    var normalizedSelection = ContextMenu.utils.normalizeSelection(corners);

    selectedItem.callback.call(this.instance, selectedItem.key, normalizedSelection);

  };

  ContextMenu.prototype.unbindMouseEvents = function () {
    this.instance.rootElement.off('contextmenu.htContextMenu');
    $(document).off('mousedown.htContextMenu');
  };

  ContextMenu.prototype.show = function(top, left){

    this.menu.style.display = 'block';

    $(this.menu).handsontable({
      data: ContextMenu.utils.convertItemsToArray(this.getItems()),
      colHeaders: false,
      colWidths: [160],
      readOnly: true,
      copyPaste: false,
      columns: [
        {
          data: 'name',
          renderer: Handsontable.helper.proxy(this.renderer, this)
        }
      ],
      beforeKeyDown: Handsontable.helper.proxy(this.onBeforeKeyDown, this)
    });

    this.setMenuPosition(top, left);

    $(this.menu).handsontable('listen');

  };

  ContextMenu.prototype.renderer = function(instance, TD, row, col, prop, value, cellProperties){
    var contextMenu = this;
    var item = instance.getData()[row];
    var wrapper = document.createElement('DIV');

    Handsontable.Dom.empty(TD);
    TD.appendChild(wrapper);

    if(itemIsSeparator(item)){
      Handsontable.Dom.addClass(TD, 'htSeparator');
    } else {
      Handsontable.Dom.fastInnerText(wrapper, value);
    }

    if (itemIsDisabled(item, contextMenu.instance)){
      Handsontable.Dom.addClass(TD, 'htDisabled');

      $(wrapper).on('mouseenter', function () {
        instance.deselectCell();
      });

    } else {
      Handsontable.Dom.removeClass(TD, 'htDisabled');

      $(wrapper).on('mouseenter', function () {
        instance.selectCell(row, col);
      });

    }

    function itemIsSeparator(item){
      return new RegExp(ContextMenu.SEPARATOR, 'i').test(item.name);
    }

    function itemIsDisabled(item, instance){
      return item.disabled === true || (typeof item.disabled == 'function' && item.disabled.call(contextMenu.instance) === true);
    }
  };

  ContextMenu.prototype.onBeforeKeyDown = function (event) {
    var contextMenu = this;
    var instance = $(contextMenu.menu).handsontable('getInstance');
    var selection = instance.getSelected();

    switch(event.keyCode){

      case Handsontable.helper.keyCode.ESCAPE:
        contextMenu.close();
        event.preventDefault();
        event.stopImmediatePropagation();
        break;

      case Handsontable.helper.keyCode.ENTER:
        if(instance.getSelected()){
          contextMenu.performAction();
          contextMenu.close();
        }
        break;

      case Handsontable.helper.keyCode.ARROW_DOWN:
        if(!selection){

          selectFirstCell(instance);

        } else {

          selectNextCell(selection[0], selection[1], instance);

        }

        event.preventDefault();
        event.stopImmediatePropagation();

        break;

      case Handsontable.helper.keyCode.ARROW_UP:
        if(!selection){

          selectLastCell(instance);

        }  else {

          selectPrevCell(selection[0], selection[1], instance);

        }

        event.preventDefault();
        event.stopImmediatePropagation();

        break;

    }

    function selectFirstCell(instance) {

      var firstCell = instance.getCell(0, 0);

      if(ContextMenu.utils.isSeparator(firstCell) || ContextMenu.utils.isDisabled(firstCell)){
        selectNextCell(0, 0, instance);
      } else {
        instance.selectCell(0, 0);
      }

    }

    function selectLastCell(instance) {

      var lastRow = instance.countRows() - 1;
      var lastCell = instance.getCell(lastRow, 0);

      if(ContextMenu.utils.isSeparator(lastCell) || ContextMenu.utils.isDisabled(lastCell)){
        selectPrevCell(lastRow, 0, instance);
      } else {
        instance.selectCell(lastRow, 0);
      }

    }

    function selectNextCell(row, col, instance){
      var nextRow = row + 1;
      var nextCell =  nextRow < instance.countRows() ? instance.getCell(nextRow, col) : null;

      if(!nextCell){
        return;
      }

      if(ContextMenu.utils.isSeparator(nextCell) || ContextMenu.utils.isDisabled(nextCell)){
        selectNextCell(nextRow, col, instance);
      } else {
        instance.selectCell(nextRow, col);
      }
    }

    function selectPrevCell(row, col, instance) {

      var prevRow = row - 1;
      var prevCell = prevRow >= 0 ? instance.getCell(prevRow, col) : null;

      if (!prevCell) {
        return;
      }

      if(ContextMenu.utils.isSeparator(prevCell) || ContextMenu.utils.isDisabled(prevCell)){
        selectPrevCell(prevRow, col, instance);
      } else {
        instance.selectCell(prevRow, col);
      }

    }

  };

  ContextMenu.prototype.getItems = function () {
    var items = {};
    function Item(rawItem){
      if(typeof rawItem == 'string'){
        this.name = rawItem;
      } else {
        Handsontable.helper.extend(this, rawItem);
      }
    }
    Item.prototype = this.options;

    for(var itemName in this.options.items){
      if(this.options.items.hasOwnProperty(itemName) && (!this.itemsFilter || this.itemsFilter.indexOf(itemName) != -1)){
        items[itemName] = new Item(this.options.items[itemName]);
      }
    }

    return items;

  };

  ContextMenu.prototype.updateOptions = function(newOptions){
    newOptions = newOptions || {};

    if(newOptions.items){
      for(var itemName in newOptions.items){
        var item = {};

        if(newOptions.items.hasOwnProperty(itemName)) {
          if(this.defaultOptions.items.hasOwnProperty(itemName)
            && Handsontable.helper.isObject(newOptions.items[itemName])){
            Handsontable.helper.extend(item, this.defaultOptions.items[itemName]);
            Handsontable.helper.extend(item, newOptions.items[itemName]);
            newOptions.items[itemName] = item;
          }
        }

      }
    }

    Handsontable.helper.extend(this.options, newOptions);
  };

  ContextMenu.prototype.setMenuPosition = function (cursorY, cursorX) {

    var cursor = {
      top:  cursorY,
      topRelative: cursorY - document.documentElement.scrollTop,
      left: cursorX,
      leftRelative:cursorX - document.documentElement.scrollLeft
    };

    if(this.menuFitsBelowCursor(cursor)){
      this.positionMenuBelowCursor(cursor);
    } else {
      this.positionMenuAboveCursor(cursor);
    }

    if(this.menuFitsOnRightOfCursor(cursor)){
      this.positionMenuOnRightOfCursor(cursor);
    } else {
      this.positionMenuOnLeftOfCursor(cursor);
    }

  };

  ContextMenu.prototype.menuFitsBelowCursor = function (cursor) {
    return cursor.topRelative + this.menu.offsetHeight <= document.documentElement.scrollTop + document.documentElement.clientHeight;
  };

  ContextMenu.prototype.menuFitsOnRightOfCursor = function (cursor) {
    return cursor.leftRelative + this.menu.offsetWidth <= document.documentElement.scrollLeft + document.documentElement.clientWidth;
  };

  ContextMenu.prototype.positionMenuBelowCursor = function (cursor) {
    this.menu.style.top = cursor.top + 'px';
  };

  ContextMenu.prototype.positionMenuAboveCursor = function (cursor) {
    this.menu.style.top = (cursor.top - this.menu.offsetHeight) + 'px';
  };

  ContextMenu.prototype.positionMenuOnRightOfCursor = function (cursor) {
    this.menu.style.left = cursor.left + 'px';
  };

  ContextMenu.prototype.positionMenuOnLeftOfCursor = function (cursor) {
    this.menu.style.left = (cursor.left - this.menu.offsetWidth) + 'px';
  };

  ContextMenu.utils = {};
  ContextMenu.utils.convertItemsToArray = function (items) {
    var itemArray = [];
    var item;
    for(var itemName in items){
      if(items.hasOwnProperty(itemName)){
        if(typeof items[itemName] == 'string'){
          item = {name: items[itemName]};
        } else if (items[itemName].visible !== false) {
          item = items[itemName];
        } else {
          continue;
        }

        item.key = itemName;
        itemArray.push(item);
      }
    }

    return itemArray;
  };

  ContextMenu.utils.normalizeSelection = function(corners){
    var selection = {
      start: new Handsontable.SelectionPoint(),
      end: new Handsontable.SelectionPoint()
    };

    selection.start.row(Math.min(corners[0], corners[2]));
    selection.start.col(Math.min(corners[1], corners[3]));

    selection.end.row(Math.max(corners[0], corners[2]));
    selection.end.col(Math.max(corners[1], corners[3]));

    return selection;
  };

  ContextMenu.utils.isSeparator = function (cell) {
    return Handsontable.Dom.hasClass(cell, 'htSeparator');
  };

  ContextMenu.utils.isDisabled = function (cell) {
    return Handsontable.Dom.hasClass(cell, 'htDisabled');
  };

  ContextMenu.prototype.close = function () {
    this.hide();
    $(document).off('mousedown.htContextMenu');
    this.instance.listen();
  };

  ContextMenu.prototype.hide = function(){
    this.menu.style.display = 'none';
    $(this.menu).handsontable('destroy');
  };

  ContextMenu.prototype.enable = function () {
    if(!this.enabled){
      this.enabled = true;
      this.bindMouseEvents();
    }
  };

  ContextMenu.prototype.disable = function () {
    if(this.enabled){
      this.enabled = false;
      this.close();
      this.unbindMouseEvents();
      this.unbindTableEvents();
    }
  };

  ContextMenu.prototype.destroy = function () {
    this.close();
    this.unbindMouseEvents();
    this.unbindTableEvents();

    if(!this.isMenuEnabledByOtherHotInstance()){
      this.removeMenu();
    }

  };

  ContextMenu.prototype.isMenuEnabledByOtherHotInstance = function () {
    var hotContainers = $('.handsontable');
    var menuEnabled = false;

    for(var i = 0, len = hotContainers.length; i < len; i++){
      var instance = $(hotContainers[i]).handsontable('getInstance');
      if(instance && instance.getSettings().contextMenu){
        menuEnabled = true;
        break;
      }
    }

    return menuEnabled;
  };

  ContextMenu.prototype.removeMenu = function () {
    if(this.menu.parentNode){
      this.menu.parentNode.removeChild(this.menu);
    }
  }

  ContextMenu.prototype.filterItems = function(itemsToLeave){
    this.itemsFilter = itemsToLeave;
  };

  ContextMenu.SEPARATOR = "---------";

  function init(){
    var instance = this;
    var contextMenuSetting = instance.getSettings().contextMenu;
    var customOptions = Handsontable.helper.isObject(contextMenuSetting) ? contextMenuSetting : {};

    if(contextMenuSetting){
      if(!instance.contextMenu){
        instance.contextMenu = new ContextMenu(instance, customOptions);
      }

      instance.contextMenu.enable();

      if(Handsontable.helper.isArray(contextMenuSetting)){
        instance.contextMenu.filterItems(contextMenuSetting);
      }

    }  else if(instance.contextMenu){
      instance.contextMenu.destroy();
      delete instance.contextMenu;
    }

  }

  Handsontable.PluginHooks.add('afterInit', init);
  Handsontable.PluginHooks.add('afterUpdateSettings', init);

  Handsontable.ContextMenu = ContextMenu;

})(Handsontable);
<|endoftext|>


<commit_before>/**
 * Can't be in angular-land since we need to make sure it can update even if we push a broken client out.
 */
(function()
{
	var Updater = require( 'nwjs-snappy-updater' ).Updater;
	var path = require( 'path' );

	var CHECK_ENDPOINT = 'http://d.gamejolt.net/data/client/manifest.json';
	var CHECK_INTERVAL = 15 * 60 * 1000; // 15min currently

	function Client_Updater()
	{
		var _this = this;

		this.check();
		window.setInterval( function()
		{
			_this.check();
		}, CHECK_INTERVAL );
	}

	Client_Updater.prototype.check = function()
	{
		console.log( 'Checking for client update.' );

		var os = require( 'os' );
		var packageJson;

		// Mac exec path looks like:
		// root/blah.app/Contents/Frameworks/nwjs Helper.app/Contents/MacOS/nwjs
		// The other OSes are just the root dir.
		var cwd = path.dirname( process.execPath );
		if ( os.type() == 'Darwin' ) {
			cwd = path.resolve( cwd, '../../../../Resources' )
			packageJson = require( path.join( cwd, 'app.nw', 'package.json' ) );
		}
		else {
			packageJson = require( path.join( cwd, 'package.json' ) );
		}

		var updater = new Updater( packageJson.version, CHECK_ENDPOINT, {
			cwd: cwd,
		} );

		return updater.check()
			.then( function( hasNew )
			{
				if ( !hasNew ) {
					console.log( 'Client is up to date.' );
					return;
				}

				console.log( 'New version of client. Updating...' );

				return updater.update()
					.then( function()
					{
						console.log( 'Updated! Reloading...' );
						var gui = require( 'nw.gui' );
						var win = gui.Window.get();
						win.reloadDev();
					} );
			} )
			.catch( function( err )
			{
				console.log( err );
			} );
	};

	var clientUpdater = new Client_Updater();
})();
<commit_msg>You can now skip auto-updating by adding a log to package.json. `"no-auto-update": true` Closes https://github.com/gamejolt/issue-tracker/issues/501<commit_after>/**
 * Can't be in angular-land since we need to make sure it can update even if we push a broken client out.
 */
(function()
{
	var Updater = require( 'nwjs-snappy-updater' ).Updater;
	var path = require( 'path' );

	var CHECK_ENDPOINT = 'http://d.gamejolt.net/data/client/manifest.json';
	var CHECK_INTERVAL = 15 * 60 * 1000; // 15min currently

	function Client_Updater()
	{
		var _this = this;

		this.check();
		window.setInterval( function()
		{
			_this.check();
		}, CHECK_INTERVAL );
	}

	Client_Updater.prototype.check = function()
	{
		console.log( 'Checking for client update.' );

		var cwd = path.dirname( process.mainModule.filename );
		var packageJson = require( path.resolve( cwd, 'package.json' ) );

		if ( packageJson['no-auto-update'] === true ) {
			console.log( 'Skip update. Package says not to auto-update.' );
			return;
		}

		var updater = new Updater( packageJson.version, CHECK_ENDPOINT, {
			cwd: cwd,
		} );

		return updater.check()
			.then( function( hasNew )
			{
				if ( !hasNew ) {
					console.log( 'Client is up to date.' );
					return;
				}

				console.log( 'New version of client. Updating...' );

				return updater.update()
					.then( function()
					{
						console.log( 'Updated! Reloading...' );
						var gui = require( 'nw.gui' );
						var win = gui.Window.get();
						win.reloadDev();
					} );
			} )
			.catch( function( err )
			{
				console.log( err );
			} );
	};

	var clientUpdater = new Client_Updater();
})();
<|endoftext|>


<commit_before>// Copyright 2019-2020, University of Colorado Boulder

/**
 * Launch an instance of the simulation using puppeteer, gather the phet-io api of the simulation, see phetioEngine.getPhetioElementsBaseline
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Chris Klusendorf (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 */

'use strict';

const http = require( 'http' );
const fs = require( 'fs' );
const puppeteer = require( 'puppeteer' );

/**
 * @param {string} repo
 * @param {boolean} [fromBuiltVersion] - if the built file should be used to generate the API (otherwise uses unbuilt)
 */
module.exports = async ( repo, fromBuiltVersion = false ) => {

  // Consider using https://github.com/cloudhead/node-static or reading https://nodejs.org/en/knowledge/HTTP/servers/how-to-serve-static-files/
  const server = http.createServer( ( req, res ) => {

    // Trim query string
    const tail = req.url.indexOf( '?' ) >= 0 ? req.url.substring( 0, req.url.indexOf( '?' ) ) : req.url;
    const path = `${process.cwd()}/..${tail}`;

    // See https://gist.github.com/aolde/8104861
    const mimeTypes = {
      html: 'text/html',
      jpeg: 'image/jpeg',
      jpg: 'image/jpeg',
      png: 'image/png',
      js: 'text/javascript',
      css: 'text/css',
      gif: 'image/gif',
      mp3: 'audio/mpeg',
      wav: 'audio/wav'
    };
    const mimeType = mimeTypes[ path.split( '.' ).pop() ] || 'text/plain';

    fs.readFile( path, function( err, data ) {
      if ( err ) {
        res.writeHead( 404 );
        res.end( JSON.stringify( err ) );
      }
      else {
        res.writeHead( 200, { 'Content-Type': mimeType } );
        res.end( data );
      }
    } );
  } );
  server.listen( 0 );

  const port = server.address().port;

  return new Promise( async ( resolve, reject ) => {

    const browser = await puppeteer.launch();
    const page = await browser.newPage();

    // Fail if this takes too long
    const id = setTimeout( () => reject( 'Timeout in generatePhetioAPI' ), 30000 );

    page.on( 'console', async msg => {

      if ( msg.text().indexOf( '"phetioFullAPI": true,' ) >= 0 ) {

        const fullAPI = msg.text();
        await browser.close();
        clearTimeout( id );
        resolve( fullAPI );
      }

      else if ( msg.type() === 'error' ) {
        const location = msg.location ? ':\n  ' + msg.location().url : '';
        const message = msg.text() + location;
        console.error( 'Error from sim:', message );
      }
    } );

    const failCallback = msg => {
      clearTimeout( id );
      reject( msg );
    };
    page.on( 'error', failCallback );
    page.on( 'pageerror', failCallback );

    try {
      const relativePath = fromBuiltVersion ?
                           `build/phet-io/${repo}_all_phet-io.html` :
                           `${repo}_en.html`;
      const url = `http://localhost:${port}/${repo}/${relativePath}?brand=phet-io&phetioStandalone&phetioPrintAPI`;
      await page.goto( url );
    }
    catch( e ) {
      clearTimeout( id );
      reject( e );
    }
  } );
};<commit_msg>Async improvements for generatePhetioAPI, see https://github.com/phetsims/chipper/issues/958<commit_after>// Copyright 2019-2020, University of Colorado Boulder

/**
 * Launch an instance of the simulation using puppeteer, gather the phet-io api of the simulation, see phetioEngine.getPhetioElementsBaseline
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Chris Klusendorf (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 */

'use strict';

const http = require( 'http' );
const fs = require( 'fs' );
const puppeteer = require( 'puppeteer' );

/**
 * @param {string} repo
 * @param {boolean} [fromBuiltVersion] - if the built file should be used to generate the API (otherwise uses unbuilt)
 */
module.exports = async ( repo, fromBuiltVersion = false ) => {

  // Consider using https://github.com/cloudhead/node-static or reading https://nodejs.org/en/knowledge/HTTP/servers/how-to-serve-static-files/
  const server = http.createServer( ( req, res ) => {

    // Trim query string
    const tail = req.url.indexOf( '?' ) >= 0 ? req.url.substring( 0, req.url.indexOf( '?' ) ) : req.url;
    const path = `${process.cwd()}/..${tail}`;

    // See https://gist.github.com/aolde/8104861
    const mimeTypes = {
      html: 'text/html',
      jpeg: 'image/jpeg',
      jpg: 'image/jpeg',
      png: 'image/png',
      js: 'text/javascript',
      css: 'text/css',
      gif: 'image/gif',
      mp3: 'audio/mpeg',
      wav: 'audio/wav'
    };
    const mimeType = mimeTypes[ path.split( '.' ).pop() ] || 'text/plain';

    fs.readFile( path, function( err, data ) {
      if ( err ) {
        res.writeHead( 404 );
        res.end( JSON.stringify( err ) );
      }
      else {
        res.writeHead( 200, { 'Content-Type': mimeType } );
        res.end( data );
      }
    } );
  } );
  server.listen( 0 );

  const port = server.address().port;

  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  return await new Promise( ( resolve, reject ) => {

    // Fail if this takes too long.  Doesn't need to be cleared since only the first resolve/reject is used
    setTimeout( () => reject( 'Timeout in generatePhetioAPI' ), 30000 );

    page.on( 'console', async msg => {

      if ( msg.text().indexOf( '"phetioFullAPI": true,' ) >= 0 ) {

        const fullAPI = msg.text();
        await browser.close();
        resolve( fullAPI );
      }

      else if ( msg.type() === 'error' ) {
        const location = msg.location ? ':\n  ' + msg.location().url : '';
        const message = msg.text() + location;
        console.error( 'Error from sim:', message );
      }
    } );

    page.on( 'error', reject );
    page.on( 'pageerror', reject );

    const relativePath = fromBuiltVersion ?
                         `build/phet-io/${repo}_all_phet-io.html` :
                         `${repo}_en.html`;
    const url = `http://localhost:${port}/${repo}/${relativePath}?brand=phet-io&phetioStandalone&phetioPrintAPI`;
    page.goto( url ).catch( reject );
  } );
};<|endoftext|>


<commit_before>define([
    'config/anthill',
    'modules/Router'
], function defineSetting(AntHill, Router) {

    /**
     * Define Setting
     * @class Setting
     * @param {*} scope
     * @param {String} name
     * @constructor
     * @extends AntHill
     */
    var Setting = function Setting(scope, name) {

        /**
         * Define scope
         * @property Setting
         * @type {*}
         */
        this.scope = scope;

        /**
         * Define setting mode
         * @property Setting
         * @type {String}
         */
        this.mode = this.scope.controller.getMode();

        /**
         * Define storage modes
         * @property Setting
         * @type {{localStorage: Storage, serverStorage: Storage}}
         */
        this.STORAGE_MODES = {
            localStorage: window.localStorage,
            serverStorage: this.serverStorage()
        };

        /**
         * Define setting storage
         * @property Setting
         * @type {{
         *      development: Storage,
         *      authorize: Storage,
         *      consumption: Storage,
         *      test: Storage
         * }}
         */
        this.storage = {
            development: this.STORAGE_MODES.serverStorage,
            authorize: this.STORAGE_MODES.serverStorage,
            consumption: this.STORAGE_MODES.serverStorage,
            test: this.STORAGE_MODES.localStorage
        };

        /**
         * Define cache
         * @property Setting
         * @type {Storage}
         */
        this.cache = this.STORAGE_MODES.localStorage;

        this.activateOnSave(false);

        /**
         * Get storage namespace
         * @property Setting
         * @returns {String}
         */
        this.getNameSpace = function getNameSpace() {
            return name;
        };

        this.init();
    };

    return Setting.extend('Setting', {

        /**
         * Activate on save
         * @memberOf Setting
         * @param {boolean} activate
         */
        activateOnSave: function activateOnSave(activate) {

            /**
             * Define activate
             * @property Setting
             * @type {boolean}
             */
            this.activate = activate;
        },

        /**
         * Set initial state
         * @memberOf Setting
         * @param {boolean} state
         */
        setInititalState: function setInititalState(state) {

            /**
             * Change state
             * @property Setting
             * @type {boolean}
             */
            this.initial = state;
        },

        /**
         * Get initial state
         * @memberOf Setting
         * @returns {boolean}
         */
        getInititalState: function getInititalState() {
            return this.initial;
        },

        /**
         * Get token
         * @memberOf Setting
         * @returns {String}
         */
        getToken: function getToken() {
            return this.token;
        },

        /**
         * Init storage
         * @memberOf Setting
         */
        init: function init() {

            this.setInititalState(true);

            /**
             * Load storage
             * @memberOf Setting
             * @type {{token: string}}
             */
            var storage = this.load();

            /**
             * Define base
             * @type {*}
             */
            var base = this.base;

            if (!base.isDefined(storage.token)) {

                /**
                 * Define token
                 * @property Setting
                 * @type {String}
                 */
                this.token = base.lib.generator.UUID();

                this.save(storage);
            }

            this.setInititalState(false);
        },

        /**
         * Clear local storage
         * @memberOf Setting
         */
        clear: function clear() {
            this.getStorage().clear();
        },

        /**
         * Get Storage
         * @memberOf Setting
         * @returns {*}
         */
        getStorage: function getStorage() {

            /**
             * Define storage
             * @type {*}
             */
            var storage = this.storage[this.mode];

            if (this.getInititalState() || this.scope.model.getConfig('loading')) {
                storage = this.cache;
            }

            return storage;
        },

        /**
         * Import data
         * @memberOf Setting
         * @param data
         */
        importData: function importData(data) {

            this.activateOnSave(true);
            this.updateData(data);
        },

        /**
         * Update data
         * @memberOf Setting
         * @param data
         */
        updateData: function updateData(data) {

            /**
             * Set data
             * @type {*}
             */
            this.getStorage().setItem(
                this.getNameSpace(),
                this.compress(
                    JSON.stringify(data)
                )
            );
        },

        /**
         * Save
         * @memberOf Setting
         * @param [opts]
         */
        save: function save(opts) {

            /**
             * Init opts
             * @type {*}
             */
            opts = this.base.define(opts, {}, true);

            var data = this.load(),
                _dt = this.base.lib.datetime;

            if (this.base.isDefined(data.createdAt)) {

                /**
                 * Load created at
                 * @type {*}
                 */
                opts.createdAt = data.createdAt;

            } else {

                /**
                 * Define created at
                 * @type {*}
                 */
                opts.createdAt = _dt.timestamp();
            }

            /**
             * Define updated at
             * @type {*}
             */
            opts.updatedAt = _dt.timestamp();

            /**
             * Define token
             * @type {*}
             */
            opts.token = this.token;

            this.importData(opts);

            this.scope.logger.debug('Save', opts);
        },

        /**
         * Load
         * @memberOf Setting
         */
        load: function load() {

            /**
             * Define compressed data
             * @type {string|*}
             */
            var compressed = this.getStorage().getItem(
                this.getNameSpace()
            ), data;

            try {

                /**
                 * Define data
                 * @type {*}
                 */
                data = JSON.parse(
                    this.decompress(compressed) || '{}'
                );

            } catch (e) {

                this.scope.logger.warn('Unable to parse JSON', e);
                data = {};
            }

            this.scope.logger.debug('Load', data);

            return data;
        },

        /**
         * Compress json
         * @memberOf Setting
         * @param {string} json
         * @returns {string}
         */
        compress: function compress(json) {
            this.scope.logger.debug('compress', json);
            return LZString.compressToBase64(json);
        },

        /**
         * Decompress json
         * @memberOf Setting
         * @param {string} compress
         * @returns {string}
         */
        decompress: function decompress(compress) {
            this.scope.logger.debug('decompress', compress);
            return LZString.decompressFromBase64(compress)
        },

        /**
         * Define server side storage
         * @memberOf Setting
         * @returns {{
         *      setting: Setting,
         *      setItem: Function,
         *      getItem: Function
         *      clear: Function
         * }}
         */
        serverStorage: function serverStorage() {

            return {

                /**
                 * Define scope
                 * @type {Setting}
                 */
                setting: this,

                /**
                 * Set storage item
                 * @memberOf {STORAGE_MODES}
                 */
                setItem: function setItem(key, value) {

                    /**
                     * Get scope
                     * @type {Application}
                     */
                    var scope = this.setting.scope;

                    /**
                     * Get create update site route
                     * @type {{string[]}}
                     */
                    var route = scope.config.routes.updateSiteContent,
                        opts = {

                            dataType: 'json',

                            url: route[0] + key,
                            method: route[1],

                            data: scope.controller.prepareXhrData({
                                author_site_storage: {
                                    content: value
                                },
                                activate: this.setting.activate
                            })
                        };

                    $.ajax(opts).done(

                        function done(data, type, xhr) {

                            this.setting.cache.setItem(key, value);
                            this.setting.activateOnSave(false);

                            scope.logger.debug(data.notice, arguments);

                            scope.observer.publish(
                                scope.eventmanager.eventList.updateStorageVersion,
                                data.version
                            );

                            scope.observer.publish(
                                scope.eventmanager.eventList.afterUpdateStorage
                            );

                        }.bind(this)
                    );
                },

                /**
                 * Get storage item
                 * @memberOf {STORAGE_MODES}
                 * @return {string}
                 */
                getItem: function getItem(key) {

                    /**
                     * Get cached data
                     * @type {string}
                     */
                    return this.setting.cache.getItem(key);
                },

                /**
                 * Clear storage
                 * @memberOf {STORAGE_MODES}
                 */
                clear: function clear() {
                    this.setting.save();
                }
            }
        }

    }, AntHill.prototype, Router);
});<commit_msg>fix loading items b4 send xhr<commit_after>define([
    'config/anthill',
    'modules/Router'
], function defineSetting(AntHill, Router) {

    /**
     * Define Setting
     * @class Setting
     * @param {*} scope
     * @param {String} name
     * @constructor
     * @extends AntHill
     */
    var Setting = function Setting(scope, name) {

        /**
         * Define scope
         * @property Setting
         * @type {*}
         */
        this.scope = scope;

        /**
         * Define setting mode
         * @property Setting
         * @type {String}
         */
        this.mode = this.scope.controller.getMode();

        /**
         * Define storage modes
         * @property Setting
         * @type {{localStorage: Storage, serverStorage: Storage}}
         */
        this.STORAGE_MODES = {
            localStorage: window.localStorage,
            serverStorage: this.serverStorage()
        };

        /**
         * Define setting storage
         * @property Setting
         * @type {{
         *      development: Storage,
         *      authorize: Storage,
         *      consumption: Storage,
         *      test: Storage
         * }}
         */
        this.storage = {
            development: this.STORAGE_MODES.serverStorage,
            authorize: this.STORAGE_MODES.serverStorage,
            consumption: this.STORAGE_MODES.serverStorage,
            test: this.STORAGE_MODES.localStorage
        };

        /**
         * Define cache
         * @property Setting
         * @type {Storage}
         */
        this.cache = this.STORAGE_MODES.localStorage;

        this.activateOnSave(false);

        /**
         * Get storage namespace
         * @property Setting
         * @returns {String}
         */
        this.getNameSpace = function getNameSpace() {
            return name;
        };

        this.init();
    };

    return Setting.extend('Setting', {

        /**
         * Activate on save
         * @memberOf Setting
         * @param {boolean} activate
         */
        activateOnSave: function activateOnSave(activate) {

            /**
             * Define activate
             * @property Setting
             * @type {boolean}
             */
            this.activate = activate;
        },

        /**
         * Set initial state
         * @memberOf Setting
         * @param {boolean} state
         */
        setInititalState: function setInititalState(state) {

            /**
             * Change state
             * @property Setting
             * @type {boolean}
             */
            this.initial = state;
        },

        /**
         * Get initial state
         * @memberOf Setting
         * @returns {boolean}
         */
        getInititalState: function getInititalState() {
            return this.initial;
        },

        /**
         * Get token
         * @memberOf Setting
         * @returns {String}
         */
        getToken: function getToken() {
            return this.token;
        },

        /**
         * Init storage
         * @memberOf Setting
         */
        init: function init() {

            this.setInititalState(true);

            /**
             * Load storage
             * @memberOf Setting
             * @type {{token: string}}
             */
            var storage = this.load();

            /**
             * Define base
             * @type {*}
             */
            var base = this.base;

            if (!base.isDefined(storage.token)) {

                /**
                 * Define token
                 * @property Setting
                 * @type {String}
                 */
                this.token = base.lib.generator.UUID();

                this.save(storage);
            }

            this.setInititalState(false);
        },

        /**
         * Clear local storage
         * @memberOf Setting
         */
        clear: function clear() {
            this.getStorage().clear();
        },

        /**
         * Get Storage
         * @memberOf Setting
         * @returns {*}
         */
        getStorage: function getStorage() {

            /**
             * Define storage
             * @type {*}
             */
            var storage = this.storage[this.mode];

            if (this.getInititalState() || this.scope.model.getConfig('loading')) {
                storage = this.cache;
            }

            return storage;
        },

        /**
         * Import data
         * @memberOf Setting
         * @param data
         */
        importData: function importData(data) {

            this.activateOnSave(true);
            this.updateData(data);
        },

        /**
         * Update data
         * @memberOf Setting
         * @param data
         */
        updateData: function updateData(data) {

            /**
             * Set data
             * @type {*}
             */
            this.getStorage().setItem(
                this.getNameSpace(),
                this.compress(
                    JSON.stringify(data)
                )
            );
        },

        /**
         * Save
         * @memberOf Setting
         * @param [opts]
         */
        save: function save(opts) {

            /**
             * Init opts
             * @type {*}
             */
            opts = this.base.define(opts, {}, true);

            var data = this.load(),
                _dt = this.base.lib.datetime;

            if (this.base.isDefined(data.createdAt)) {

                /**
                 * Load created at
                 * @type {*}
                 */
                opts.createdAt = data.createdAt;

            } else {

                /**
                 * Define created at
                 * @type {*}
                 */
                opts.createdAt = _dt.timestamp();
            }

            /**
             * Define updated at
             * @type {*}
             */
            opts.updatedAt = _dt.timestamp();

            /**
             * Define token
             * @type {*}
             */
            opts.token = this.token;

            this.importData(opts);

            this.scope.logger.debug('Save', opts);
        },

        /**
         * Load
         * @memberOf Setting
         */
        load: function load() {

            /**
             * Define compressed data
             * @type {string|*}
             */
            var compressed = this.getStorage().getItem(
                this.getNameSpace()
            ), data;

            try {

                /**
                 * Define data
                 * @type {*}
                 */
                data = JSON.parse(
                    this.decompress(compressed) || '{}'
                );

            } catch (e) {

                this.scope.logger.warn('Unable to parse JSON', e);
                data = {};
            }

            this.scope.logger.debug('Load', data);

            return data;
        },

        /**
         * Compress json
         * @memberOf Setting
         * @param {string} json
         * @returns {string}
         */
        compress: function compress(json) {
            this.scope.logger.debug('compress', json);
            return LZString.compressToBase64(json);
        },

        /**
         * Decompress json
         * @memberOf Setting
         * @param {string} compress
         * @returns {string}
         */
        decompress: function decompress(compress) {
            this.scope.logger.debug('decompress', compress);
            return LZString.decompressFromBase64(compress)
        },

        /**
         * Define server side storage
         * @memberOf Setting
         * @returns {{
         *      setting: Setting,
         *      setItem: Function,
         *      getItem: Function
         *      clear: Function
         * }}
         */
        serverStorage: function serverStorage() {

            return {

                /**
                 * Define scope
                 * @type {Setting}
                 */
                setting: this,

                /**
                 * Set storage item
                 * @memberOf {STORAGE_MODES}
                 */
                setItem: function setItem(key, value) {

                    /**
                     * Get scope
                     * @type {Application}
                     */
                    var scope = this.setting.scope;

                    /**
                     * Get create update site route
                     * @type {{string[]}}
                     */
                    var route = scope.config.routes.updateSiteContent,
                        opts = {

                            dataType: 'json',

                            url: route[0] + key,
                            method: route[1],

                            data: scope.controller.prepareXhrData({
                                author_site_storage: {
                                    content: value
                                },
                                activate: this.setting.activate
                            })
                        };

                    /**
                     * Get current page
                     * @type {Page}
                     */
                    var page = scope.controller.getPage(),
                        isLoadedContent = page.controller.isLoadedContent();

                    if (!isLoadedContent) {
                        scope.logger.debug('Skip XHR until content was loaded');
                        return false;
                    }

                    $.ajax(opts).done(

                        function done(data, type, xhr) {

                            this.setting.cache.setItem(key, value);
                            this.setting.activateOnSave(false);

                            scope.logger.debug(data.notice, arguments);

                            scope.observer.publish(
                                scope.eventmanager.eventList.updateStorageVersion,
                                data.version
                            );

                            scope.observer.publish(
                                scope.eventmanager.eventList.afterUpdateStorage
                            );

                        }.bind(this)
                    );
                },

                /**
                 * Get storage item
                 * @memberOf {STORAGE_MODES}
                 * @return {string}
                 */
                getItem: function getItem(key) {

                    /**
                     * Get cached data
                     * @type {string}
                     */
                    return this.setting.cache.getItem(key);
                },

                /**
                 * Clear storage
                 * @memberOf {STORAGE_MODES}
                 */
                clear: function clear() {
                    this.setting.save();
                }
            }
        }

    }, AntHill.prototype, Router);
});<|endoftext|>


<commit_before>/**********************************************************************************************
 * 名称: jQuery元素对齐某元素
 * 作者: hisland
 * 邮件: hisland@qq.com
 * 时间: 2011-2-17 15:7:59
 * 版本: v2
 *
 * 2011-4-12 15:3:54:
 *		元素设置data-offset="x, y", 默认[0, 0], 属性使对齐可以加一定的偏移
 *		元素设置data-adjust-type="force", 默认[view], 属性使强制左/右/上/下对齐[force]或者以显示完全为主要对齐[view](某些情况强制对齐一边浮动元素都不能显示全)
 *
 * 使用方法:
 *			$('').adjustElement(target);
 *			$('').adjustElement(target, callback);
 */

KISSY.add('adjustElement', function(S, undef) {
	var $ = jQuery;

	function adjustElement(target, callback){
		var elm = this.eq(0);
		target = $(target).eq(0);

		if(!target.length){
			alert('adjustElement: 必须有个 target');
			return elm;
		}

		var  me_width = elm.outerWidth()
			,me_height = elm.outerHeight()
			,offset = [0, 0]
			,tmp

			,t_width = target.outerWidth()
			,t_height = target.outerHeight()
			,t_offset = target.offset()

			,p_width = document.documentElement.clientWidth
			,p_height = document.documentElement.clientHeight;

		//得到偏移
		$.each((elm.attr('data-offset')+'').split(/[,\s]+/), function(i, v){
			v -= 0;
			if(!isNaN(v)){
				offset[i] = v;
			}
		});

		//强制左/右/上/下对齐
		if(elm.attr('data-adjust-type') == 'force'){
			//设置水平位置
			if(t_offset.left + offset[0] + me_width > p_width){
				elm.css('left', p_width - me_width - 5);//窗口右边线对齐
			}else{
				elm.css('left', t_offset.left + offset[0]);//target左对齐
			}

			//设置垂直位置
			if(me_height + offset[1] + t_offset.top > p_height){
				elm.css('top', t_offset.top - me_height -1);//target顶边对齐
			}else{
				elm.css('top', t_offset.top + offset[1] + t_height + 1);//target底边对齐
			}

		//以显示完全为主要
		}else{
			//设置水平位置
			if(me_width > p_width){
				elm.css('left', 0);//窗口左边线对齐
			}else if(t_offset.left + offset[0] + me_width > p_width){
				elm.css('left', p_width - me_width - 5);//窗口右边线对齐
			}else{
				elm.css('left', t_offset.left + offset[0]);//target左对齐
			}

			//设置垂直位置
			if(me_height > p_height){
				elm.css('top', 0);//窗口顶边线对齐
			}else if(me_height + offset[1] + t_offset.top > p_height){
				elm.css('top', p_height - me_height -1);//窗口底边线对齐
			}else{
				elm.css('top', t_offset.top + offset[1] + t_height + 1);//target底边对齐
			}
		}

		//有回调的回调
		$.isFunction(callback) && callback.call(elm);

		return elm;
	}

	//注册到jq原型上
	$.fn.extend({
		adjustElement: adjustElement
	});
}, {
	requires: ['jquery-1.4.2']
});
<commit_msg>修正 adjustElement.js 当浏览器有滚动条时的位置计算不正确<commit_after>/**********************************************************************************************
 * 名称: jQuery元素对齐某元素
 * 作者: hisland
 * 邮件: hisland@qq.com
 * 时间: 2011-2-17 15:7:59
 * 版本: v2
 *
 * 2011-4-12 15:3:54:
 *		元素设置data-offset="x, y", 默认[0, 0], 属性使对齐可以加一定的偏移
 *		元素设置data-adjust-type="force", 默认[view], 属性使强制左/右/上/下对齐[force]或者以显示完全为主要对齐[view](某些情况强制对齐一边浮动元素都不能显示全)
 *
 * 使用方法:
 *			$('').adjustElement(target);
 *			$('').adjustElement(target, callback);
 */

KISSY.add('adjustElement', function(S, undef) {
	var $ = jQuery;

	function adjustElement(target, callback){
		var elm = this.eq(0);
		target = $(target).eq(0);

		if(!target.length){
			alert('adjustElement: 必须有个 target');
			return elm;
		}

		var  me_width = elm.outerWidth()
			,me_height = elm.outerHeight()
			,offset = [0, 0]
			,tmp

			,t_width = target.outerWidth()
			,t_height = target.outerHeight()
			,t_offset = target.offset()

			,p_width = document.documentElement.clientWidth + document.documentElement.scrollLeft
			,p_height = document.documentElement.clientHeight + document.documentElement.scrollTop;

		//得到偏移
		$.each((elm.attr('data-offset')+'').split(/[,\s]+/), function(i, v){
			v -= 0;
			if(!isNaN(v)){
				offset[i] = v;
			}
		});

		//强制左/右/上/下对齐
		if(elm.attr('data-adjust-type') == 'force'){
			//设置水平位置
			if(t_offset.left + offset[0] + me_width > p_width){
				elm.css('left', p_width - me_width - 5);//窗口右边线对齐
			}else{
				elm.css('left', t_offset.left + offset[0]);//target左对齐
			}

			//设置垂直位置
			if(me_height + offset[1] + t_offset.top > p_height){
				elm.css('top', t_offset.top - me_height -1);//target顶边对齐
			}else{
				elm.css('top', t_offset.top + offset[1] + t_height + 1);//target底边对齐
			}

		//以显示完全为主要
		}else{
			//设置水平位置
			if(me_width > p_width){
				elm.css('left', 0);//窗口左边线对齐
			}else if(t_offset.left + offset[0] + me_width > p_width){
				elm.css('left', p_width - me_width - 5);//窗口右边线对齐
			}else{
				elm.css('left', t_offset.left + offset[0]);//target左对齐
			}

			//设置垂直位置
			if(me_height > p_height){
				elm.css('top', 0);//窗口顶边线对齐
			}else if(me_height + offset[1] + t_offset.top > p_height){
				elm.css('top', p_height - me_height -1);//窗口底边线对齐
			}else{
				elm.css('top', t_offset.top + offset[1] + t_height + 1);//target底边对齐
			}
		}

		//有回调的回调
		$.isFunction(callback) && callback.call(elm);

		return elm;
	}

	//注册到jq原型上
	$.fn.extend({
		adjustElement: adjustElement
	});
}, {
	requires: ['jquery-1.4.2']
});
<|endoftext|>


<commit_before>// Placeholder manifest file.
// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js'

var index = 1;
var delay = 5000;
var timer;

$(document).ready(function() {
  slider();
  setTimeout(slider(), 5000);
});

function slider() {
  count = $("#showcase_inner_container > img").size();
  document.getElementById("showcase_inner_container").className = "showcase_img";
  $("#showcase_inner_container").css("transform", "translateX(" + (index * -663) + "px)");

  if (index == count) {
    index = 0;
    delay = 1;
    document.getElementById("showcase_inner_container").className = "showcase_img_reset";
    $("#showcase_inner_container").css("transform", "translateX(" + (index * -663) + "px)");
  }

  delay = 5000;
  console.log(index + " : " + (index * -663) + "px  :  " + delay);
  index += 1;
}

function repeat() {
  setTimeout(repeat, delay);
  slider();
}
<commit_msg>Fix showcase.<commit_after>// Placeholder manifest file.
// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js'

var index = 1;
var delay = 5000;
var timer;

$(document).ready(function() {
  repeat();
});

function slider() {
  count = $("#showcase_inner_container > img").size();
  document.getElementById("showcase_inner_container").className = "showcase_img";
  $("#showcase_inner_container").css("transform", "translateX(" + (index * -663) + "px)");

  if (index == count) {
    index = 0;
    delay = 1;
    document.getElementById("showcase_inner_container").className = "showcase_img_reset";
    $("#showcase_inner_container").css("transform", "translateX(" + (index * -663) + "px)");
  }

  delay = 5000;
  console.log(index + " : " + (index * -663) + "px  :  " + delay);
  index += 1;
}

function repeat() {
  setTimeout(repeat, delay);
  slider();
}
<|endoftext|>


<commit_before>var data = ["", "", "", "", "", "", "", "", "", "", ""];

//Array size
var arrElementWidth = 150;
var arrElementHeight = 40;

//Key size
var keyWidth = 50;
var keyHeight = arrElementHeight;
var keyMargin = 5;

var width = 800;
var height = data.length * (arrElementHeight+5);

//Hash function block size
var blockWidth = keyWidth + keyMargin + arrElementWidth;
var blockHeight = data.length * (arrElementHeight + 5);
var blockMargin = 30;

//Animation
var cmd = [];
var currentCmd = 0;

//PH - Code TODO get code from another source
var codeContent = [
    "",
    "function countingSort(array, maxValue) {",
    "    if (array.constructor !== Array || array.length == 0)",
    "        return [];",
    "",
    "    var valueCount = Array.apply(null, Array(maxValue)).map(Number.prototype.valueOf, 0);",
    "    var value;",
    "",
    "    for (var i = 0; i < array.length; i++) {",
    "        value = array[i];",
    "        valueCount[value] += 1;",
    "    }",
    "",
    "    var result = new Array(array.list);",
    "    var index = 0;",
    "    for (var i = 0; i < valueCount.length; i++) {",
    "        for (var j = 0; j < valueCount[i]; j++) {",
    "            result[index] = i;",
    "            index++;",
    "        }",
    "    }",
    "",
    "    return result;",
    "}"
];

var code = d3.select("#code-text");
var drawingArea = d3.select(".drawingArea")
    .append("svg:svg")
    .attr("width", width)
    .attr("height", height);
var bucket = drawingArea.append("g");
var keys = drawingArea.append("g");

//Create unsorted array
bucket.selectAll("rect")
    .data(data)
    .enter()
    .append("svg:rect")
    .attr("x", function(d, index) { return width - arrElementWidth; })
    .attr("y", function(d, index) { return index * (arrElementHeight + 5); })
    .attr("height", arrElementHeight)
    .attr("width", arrElementWidth)
    .attr("fill", "rgb(0, 127, 127)")
    .attr("class", function(d, index) { return "element" + index; });

bucket.selectAll("text")
    .data(data)
    .enter()
    .append("text")
    .text(function(d) { return d; })
    .attr("x", function(d, index) { return width - arrElementWidth/2; })
    .attr("y", function(d, index) { return 2*arrElementHeight/3 + index * (arrElementHeight+5); })
    .attr("width", arrElementWidth)
    .attr("height", arrElementHeight)
    .attr("class", function(d, index) { return "element" + index; });

keys.selectAll("rect")
    .data(data)
    .enter()
    .append("svg:rect")
    .attr("x", function(d, index) { return width - arrElementWidth - keyWidth - keyMargin; })
    .attr("y", function(d, index) { return index * (arrElementHeight + 5); })
    .attr("height", arrElementHeight)
    .attr("width", keyWidth)
    .attr("fill", "rgb(0, 127, 127)");

keys.selectAll("text")
    .data(data)
    .enter()
    .append("text")
    .text(function(d, index) { return index; })
    .attr("x", function(d, index) { return width + keyWidth/2 - arrElementWidth - keyWidth - keyMargin; })
    .attr("y", function(d, index) { return 2*arrElementHeight/3 + index * (arrElementHeight+5); })
    .attr("width", keyWidth)
    .attr("height", arrElementHeight);

var hashFunctionBlock = drawingArea.append("g")
    .append("rect")
    .attr("width", blockWidth)
    .attr("height", blockHeight)
    .attr("x", width - arrElementWidth - keyWidth - blockWidth - blockMargin)
    .attr("fill", "cornflowerblue");

$( document ).ready(function() {
    initCode();
});

function highlight(index, array) {
    pointArrow(index);
    array.selectAll("rect").filter(":nth-child(" + (index+1) + ")")
        .data(data)
        .transition()
        .duration(500)
        .attr("fill", "rgb(255, 0, 0)");
}

function clearHighlight(array) {
    array.selectAll("rect")
        .data(data)
        .transition()
        .duration(500)
        .attr("fill", function(d) { return "rgb(0, 127, 127)"; });
}

function add(value) {
    drawingArea.append("rect")
        .attr("width", arrElementWidth)
        .attr("height", arrElementHeight)
        .attr("fill", "rgb(0, 127, 127)")
        .attr("opacity", "0")
        .attr("class", "newElement")
        .attr("y", height/2);

    drawingArea.append("text")
        .attr("width", arrElementWidth)
        .attr("height", arrElementHeight)
        .attr("x", arrElementWidth/2)
        .attr("y", height/2 + 2*arrElementHeight/3)
        .text(value)
        .attr("opacity", "0")
        .attr("class", "newElement");

    drawingArea.selectAll(".newElement").transition()
        .duration(1000)
        .attr("opacity", "1");
}

function moveToHashFunctionBlock() {
    //console.log(drawingArea.select("#newElement"));
    drawingArea.selectAll(".newElement").filter("rect")
        .transition()
        .duration(1000)
        .attr("x", width + 10 - blockWidth - arrElementWidth - keyWidth - blockMargin);
        //.attr("transform", "translate(" + (width + 10 - blockWidth - arrElementWidth - keyWidth - blockMargin) + ")");

    drawingArea.selectAll(".newElement").filter("text")
        .transition()
        .duration(1000)
        .attr("x", width + 10 - blockWidth - arrElementWidth/2 - keyWidth - blockMargin);
}

function checkIfKeyFree(index) {
    drawingArea.selectAll(".newElement")
        .transition()
        .duration(1000)
        //.attr(width + 10 - blockWidth - arrElementWidth - keyWidth - blockMargin)
        .attr("y", index * (arrElementHeight + 5));
        //.attr("transform", "translate(" + (width - blockWidth - arrElementWidth - keyWidth - blockMargin) + ", " + (index * (arrElementHeight + 5))  + ")" );
}

function replaceElement(index) {
    bucket.selectAll(".element" + index).remove();

    drawingArea.selectAll(".newElement").filter("rect")
        .transition()
        .duration(1000)
        .attr("x", width - arrElementWidth)
        .attr("y", index * (arrElementHeight + 5))
        .attr("class", index + "element");

    drawingArea.selectAll(".newElement").filter("text")
        .transition()
        .duration(1000)
        .attr("x", width - arrElementWidth/2)
        .attr("y", 2*arrElementHeight/3 + index * (arrElementHeight+5))
        .attr("class", index + "element");

    drawingArea.selectAll(".newElement").classed(".newElement", false);
}

function runCommand() {
    console.log(cmd[currentCmd]);
    unHighlightCode();
    switch(cmd[currentCmd].substring(0, Math.min(cmd[currentCmd].length, 4))) {
        case "high":
            //clearHighlight();
            eval(cmd[currentCmd]);
            break;
        case "code":
            eval(cmd[currentCmd]);
            break;
        case "clea":
            eval(cmd[currentCmd]);
            break;
        default:
            console.log("Unknown command" + cmd[currentCmd].substring(0, Math.min(cmd[currentCmd].length, 4)));
    }
    currentCmd++;
}

function play() {
    setTimeout(function(){
        runCommand();
        //Run next command if there is one
        if(currentCmd < cmd.length) play();
    }, 1000);
}

function initCode() {
    code.selectAll("span")
        .data(codeContent)
        .enter()
        .append("span")
        .attr("id", function(d, i) { return "codeLine" + i})
        .text(function (d) { return d })
        .append("br");

    //Restart code highlightning
    hljs.initHighlighting.called = false;
    hljs.initHighlighting();
}

function codeLineHighlight(lineNr) {
    //console.log(code);
    code.selectAll("span").filter("#codeLine" + lineNr)
        .transition()
        .duration(500)
        .style("background-color", "yellow");
}

function unHighlightCode() {
    code.selectAll("span")
        .transition()
        .duration(500)
        .style("background-color", "transparent");
}

<commit_msg>hasharrow<commit_after>var data = ["", "", "", "", "", "", "", "", "", "", ""];

//Array size
var arrElementWidth = 150;
var arrElementHeight = 40;

//Key size
var keyWidth = 50;
var keyHeight = arrElementHeight;
var keyMargin = 5;

var width = 800;
var height = data.length * (arrElementHeight+5);

//Hash function block size
var blockWidth = keyWidth + keyMargin + arrElementWidth;
var blockHeight = data.length * (arrElementHeight + 5);
var blockMargin = 30;

//Animation
var cmd = [];
var currentCmd = 0;

var lineData;

//PH - Code TODO get code from another source
var codeContent = [
    "",
    "function countingSort(array, maxValue) {",
    "    if (array.constructor !== Array || array.length == 0)",
    "        return [];",
    "",
    "    var valueCount = Array.apply(null, Array(maxValue)).map(Number.prototype.valueOf, 0);",
    "    var value;",
    "",
    "    for (var i = 0; i < array.length; i++) {",
    "        value = array[i];",
    "        valueCount[value] += 1;",
    "    }",
    "",
    "    var result = new Array(array.list);",
    "    var index = 0;",
    "    for (var i = 0; i < valueCount.length; i++) {",
    "        for (var j = 0; j < valueCount[i]; j++) {",
    "            result[index] = i;",
    "            index++;",
    "        }",
    "    }",
    "",
    "    return result;",
    "}"
];

var code = d3.select("#code-text");
var drawingArea = d3.select(".drawingArea")
    .append("svg:svg")
    .attr("width", width)
    .attr("height", height);
var bucket = drawingArea.append("g");
var keys = drawingArea.append("g");

//Create unsorted array
bucket.selectAll("rect")
    .data(data)
    .enter()
    .append("svg:rect")
    .attr("x", function(d, index) { return width - arrElementWidth; })
    .attr("y", function(d, index) { return index * (arrElementHeight + 5); })
    .attr("height", arrElementHeight)
    .attr("width", arrElementWidth)
    .attr("fill", "rgb(0, 127, 127)")
    .attr("class", function(d, index) { return "element" + index; });

bucket.selectAll("text")
    .data(data)
    .enter()
    .append("text")
    .text(function(d) { return d; })
    .attr("x", function(d, index) { return width - arrElementWidth/2; })
    .attr("y", function(d, index) { return 2*arrElementHeight/3 + index * (arrElementHeight+5); })
    .attr("width", arrElementWidth)
    .attr("height", arrElementHeight)
    .attr("class", function(d, index) { return "element" + index; });

keys.selectAll("rect")
    .data(data)
    .enter()
    .append("svg:rect")
    .attr("x", function(d, index) { return width - arrElementWidth - keyWidth - keyMargin; })
    .attr("y", function(d, index) { return index * (arrElementHeight + 5); })
    .attr("height", arrElementHeight)
    .attr("width", keyWidth)
    .attr("fill", "rgb(0, 127, 127)");

keys.selectAll("text")
    .data(data)
    .enter()
    .append("text")
    .text(function(d, index) { return index; })
    .attr("x", function(d, index) { return width + keyWidth/2 - arrElementWidth - keyWidth - keyMargin; })
    .attr("y", function(d, index) { return 2*arrElementHeight/3 + index * (arrElementHeight+5); })
    .attr("width", keyWidth)
    .attr("height", arrElementHeight);

var hashFunctionBlock = drawingArea.append("g")
    .append("rect")
    .attr("width", blockWidth)
    .attr("height", blockHeight)
    .attr("x", width - arrElementWidth - keyWidth - blockWidth - blockMargin)
    .attr("fill", "cornflowerblue");

var arrow = drawingArea.append("path")
    .attr("class", "arrow");

function updateArrow(index) {
    //The data for our line
    var lineData = [{ "x": 0,   "y": height/2},
        { "x": width + 10 - blockWidth - arrElementWidth - keyWidth - blockMargin,  "y": height/2},
        { "x": width - arrElementWidth,  "y": index * (arrElementHeight + 5)}];

    var lineFunction = d3.line()
        .x(function(d) { return d.x; })
        .y(function(d) { return d.y; })
        .interpolate("linear");

    arrow.attr("d", lineFunction(lineData));
}

$( document ).ready(function() {
    initCode();
});

function highlight(index, array) {
    pointArrow(index);
    array.selectAll("rect").filter(":nth-child(" + (index+1) + ")")
        .data(data)
        .transition()
        .duration(500)
        .attr("fill", "rgb(255, 0, 0)");
}

function clearHighlight(array) {
    array.selectAll("rect")
        .data(data)
        .transition()
        .duration(500)
        .attr("fill", function(d) { return "rgb(0, 127, 127)"; });
}

function add(value) {
    drawingArea.append("rect")
        .attr("width", arrElementWidth)
        .attr("height", arrElementHeight)
        .attr("fill", "rgb(0, 127, 127)")
        .attr("opacity", "0")
        .attr("class", "newElement")
        .attr("y", height/2);

    drawingArea.append("text")
        .attr("width", arrElementWidth)
        .attr("height", arrElementHeight)
        .attr("x", arrElementWidth/2)
        .attr("y", height/2 + 2*arrElementHeight/3)
        .text(value)
        .attr("opacity", "0")
        .attr("class", "newElement");

    drawingArea.selectAll(".newElement").transition()
        .duration(1000)
        .attr("opacity", "1");
}

function moveToHashFunctionBlock() {
    //console.log(drawingArea.select("#newElement"));
    drawingArea.selectAll(".newElement").filter("rect")
        .transition()
        .duration(1000)
        .attr("x", width + 10 - blockWidth - arrElementWidth - keyWidth - blockMargin);
        //.attr("transform", "translate(" + (width + 10 - blockWidth - arrElementWidth - keyWidth - blockMargin) + ")");

    drawingArea.selectAll(".newElement").filter("text")
        .transition()
        .duration(1000)
        .attr("x", width + 10 - blockWidth - arrElementWidth/2 - keyWidth - blockMargin);
}

function checkIfKeyFree(index) {
    drawingArea.selectAll(".newElement")
        .transition()
        .duration(1000)
        //.attr(width + 10 - blockWidth - arrElementWidth - keyWidth - blockMargin)
        .attr("y", index * (arrElementHeight + 5));
        //.attr("transform", "translate(" + (width - blockWidth - arrElementWidth - keyWidth - blockMargin) + ", " + (index * (arrElementHeight + 5))  + ")" );
}

function replaceElement(index) {
    bucket.selectAll(".element" + index).remove();

    drawingArea.selectAll(".newElement").filter("rect")
        .transition()
        .duration(1000)
        .attr("x", width - arrElementWidth)
        .attr("y", index * (arrElementHeight + 5))
        .attr("class", index + "element");

    drawingArea.selectAll(".newElement").filter("text")
        .transition()
        .duration(1000)
        .attr("x", width - arrElementWidth/2)
        .attr("y", 2*arrElementHeight/3 + index * (arrElementHeight+5))
        .attr("class", index + "element");

    drawingArea.selectAll(".newElement").classed(".newElement", false);
}

function runCommand() {
    console.log(cmd[currentCmd]);
    unHighlightCode();
    switch(cmd[currentCmd].substring(0, Math.min(cmd[currentCmd].length, 4))) {
        case "high":
            //clearHighlight();
            eval(cmd[currentCmd]);
            break;
        case "code":
            eval(cmd[currentCmd]);
            break;
        case "clea":
            eval(cmd[currentCmd]);
            break;
        default:
            console.log("Unknown command" + cmd[currentCmd].substring(0, Math.min(cmd[currentCmd].length, 4)));
    }
    currentCmd++;
}

function play() {
    setTimeout(function(){
        runCommand();
        //Run next command if there is one
        if(currentCmd < cmd.length) play();
    }, 1000);
}

function initCode() {
    code.selectAll("span")
        .data(codeContent)
        .enter()
        .append("span")
        .attr("id", function(d, i) { return "codeLine" + i})
        .text(function (d) { return d })
        .append("br");

    //Restart code highlightning
    hljs.initHighlighting.called = false;
    hljs.initHighlighting();
}

function codeLineHighlight(lineNr) {
    //console.log(code);
    code.selectAll("span").filter("#codeLine" + lineNr)
        .transition()
        .duration(500)
        .style("background-color", "yellow");
}

function unHighlightCode() {
    code.selectAll("span")
        .transition()
        .duration(500)
        .style("background-color", "transparent");
}

<|endoftext|>