Modernize menu scripts

Change-Id: I784ea3b3680ecd7f36eb7a1724fd9c7d79a860e6
diff --git a/dev/js/src/menu.js b/dev/js/src/menu.js
index 4d80419..ecce23b 100644
--- a/dev/js/src/menu.js
+++ b/dev/js/src/menu.js
@@ -25,8 +25,10 @@
              defaultLengthFieldClass,
              sliderClass) {
 
+  "use strict";
+
   // Default maximum number of menu items
-  var menuLimit = 8;
+  const menuLimit = 8;
 
   /**
    * List of items for drop down menu (complete).
@@ -53,166 +55,155 @@
 
     // Initialize list
     _init : function (list, params) {
-
+      
       if (params === undefined)
         params = {};
 
-      this._itemClass = params["itemClass"] || defaultItemClass;
+      const t = this;
+
+      t._itemClass = params["itemClass"] || defaultItemClass;
 
       // Add prefix object
       if (params["prefixClass"] !== undefined) {
-        this._prefix = params["prefixClass"].create();
+        t._prefix = params["prefixClass"].create();
       }
       else {
-        this._prefix = defaultPrefixClass.create();
+        t._prefix = defaultPrefixClass.create();
       };
-      this._prefix._menu = this;
+      t._prefix._menu = t;
 
       // Add lengthField object
       if (params["lengthFieldClass"] !== undefined) {
-        this._lengthField = params["lengthFieldClass"].create();
+        t._lengthField = params["lengthFieldClass"].create();
       }
       else {
-        this._lengthField = defaultLengthFieldClass.create();
+        t._lengthField = defaultLengthFieldClass.create();
       };
-      this._lengthField._menu = this;
+      t._lengthField._menu = t;
 
       // Initialize slider
-      this._slider = sliderClass.create(this);
+      t._slider = sliderClass.create(t);
 
       // Create the element
       var el = document.createElement("ul");
-      with (el) {
-        style.outline = 0;
-        setAttribute('tabindex', 0);
-        classList.add('menu', 'roll');
-        appendChild(this._prefix.element());
-        appendChild(this._lengthField.element());
-        appendChild(this._slider.element());
-      };
+      el.style.outline = 0;
+      el.setAttribute('tabindex', 0);
+      el.classList.add('menu', 'roll');
+      el.appendChild(t._prefix.element());
+      el.appendChild(t._lengthField.element());
+      el.appendChild(t._slider.element());
 
       // This has to be cleaned up later on
-      el["menu"] = this;
+      el["menu"] = t;
 
       // Arrow keys
       el.addEventListener(
         'keydown',
-        this._keydown.bind(this),
+        t._keydown.bind(t),
         false
       );
 
       // Strings
       el.addEventListener(
         'keypress',
-        this._keypress.bind(this),
+        t._keypress.bind(t),
         false
       );
 
       // Mousewheel
       el.addEventListener(
         'wheel',
-        this._mousewheel.bind(this),
+        t._mousewheel.bind(t),
         false
       );
 
-      // Touch
-      el.addEventListener(
-        'touchstart',
-        this._touch.bind(this),
-        false
-      );
-      el.addEventListener(
-        'touchend',
-        this._touch.bind(this),
-        false
-      );
-      el.addEventListener(
-        'touchmove',
-        this._touch.bind(this),
-        false
+      // Touch events
+      ['touchstart', 'touchend', 'touchmove'].forEach(
+        e => el.addEventListener(e, t._touch.bind(t), false)
       );
 
       
-      this._element = el;
+      t._element = el;
 
-      this._limit = menuLimit;
+      t._limit = menuLimit;
       
-      this._items = new Array();
+      t._items = new Array();
 
       // TODO:
       // Make this separate from _init
-      this.readItems(list);
+      t.readItems(list);
 
-      this.dontHide = false;
+      t.dontHide = false;
         
-      return this;
+      return t;
     },
 
     // Read items to add to list
     readItems : function (list) {
+      const t = this;
 
-      this._list = undefined;
+      t._list = undefined;
 
       // Remove circular reference to "this" in items
-      for (var i = 0; i < this._items.length; i++) {
-        delete this._items[i]["_menu"];
-        delete this._items[i];
+      for (let i = 0; i < t._items.length; i++) {
+        delete t._items[i]["_menu"];
+        delete t._items[i];
       };
 
-      this._items = new Array();
-      this.removeItems();
+      t._items = new Array();
+      t.removeItems();
 
 
       // Initialize items
-      this._lengthField.reset();
+      t._lengthField.reset();
 
-      var i = 0;
       // Initialize item list based on parameters
       list.forEach(function(i){
-        var obj = this._itemClass.create(i);
+        const obj = this._itemClass.create(i);
 
         // This may become circular
         obj["_menu"] = this;
         this._lengthField.add(i);
         this._items.push(obj);
-      }, this);
+      }, t);
 
-      this._slider.length(this.liveLength())
-        .limit(this._limit)
+      t._slider.length(t.liveLength())
+        .limit(t._limit)
         .reInit();
       
-      this._firstActive = false;
+      t._firstActive = false;
       // Show the first item active always?
-      this.offset = 0;
-      this.position = 0;
+      t.offset = 0;
+      t.position = 0;
     },
     
     // Initialize the item list
     _initList : function () {
+      const t = this;
 
       // Create a new list
-      if (this._list === undefined) {
-        this._list = [];
+      if (t._list === undefined) {
+        t._list = [];
       }
-      else if (this._list.length !== 0) {
-        this._boundary(false);
-        this._list.length = 0;
+      else if (t._list.length !== 0) {
+        t._boundary(false);
+        t._list.length = 0;
       };
 
       // Offset is initially zero
-      this.offset = 0;
+      t.offset = 0;
 
       // There is no prefix set
-      if (this.prefix().length <= 0) {
+      if (t.prefix().length <= 0) {
 
         // add all items to the list and lowlight
         let i = 0;
-        for (; i < this._items.length; i++) {
-          this._list.push(i);
-          this._items[i].lowlight();
+        for (; i < t._items.length; i++) {
+          t._list.push(i);
+          t._items[i].lowlight();
         };
 
-        this._slider.length(i).reInit();
+        t._slider.length(i).reInit();
 
         return true;
       };
@@ -220,15 +211,15 @@
       /*
        * There is a prefix set, so filter the list!
        */
-      var pos;
-      var prefixList = this.prefix().toLowerCase().split(" ");
+      let pos;
+      const prefixList = t.prefix().toLowerCase().split(" ");
 
-      var items = [];
-      var maxPoints = 1; // minimum 1
+      const items = [];
+      let maxPoints = 1; // minimum 1
 
       // Iterate over all items and choose preferred matching items
       // i.e. the matching happens at the word start
-      this._items.forEach(function(it, pos){
+      t._items.forEach(function(it, pos){
 
         let points = 0;
 
@@ -252,25 +243,12 @@
         else if (points == maxPoints) {
           this._list.push(pos);
         }
-      },this);
+      }, t);
 
-      // The list is empty - so lower your expectations
-      // Iterate over all items and choose matching items
-      // i.e. the matching happens anywhere in the word
-      /*
-      prefix = prefix.substring(1);
-      if (this._list.length == 0) {
-        for (pos = 0; pos < this._items.length; pos++) {
-          if ((this.item(pos).lcField().indexOf(prefix)) >= 0)
-            this._list.push(pos);
-        };
-      };
-      */
-
-      this._slider.length(this._list.length).reInit();
+      t._slider.length(t._list.length).reInit();
 
       // Filter was successful - yeah!
-      return this._list.length > 0 ? true : false;
+      return t._list.length > 0 ? true : false;
     },
 
 
@@ -280,20 +258,21 @@
      * mark and sweep GC)!
      */
     destroy : function () {
+      const t = this;
 
       // Remove circular reference to "this" in menu
-      if (this._element != undefined)
-        delete this._element["menu"]; 
+      if (t._element != undefined)
+        delete t._element["menu"]; 
 
       // Remove circular reference to "this" in items
-      this._items.forEach(function(i) {
+      t._items.forEach(function(i) {
         delete i["_menu"];
       });
 
       // Remove circular reference to "this" in prefix
-      delete this._prefix['_menu'];
-      delete this._lengthField['_menu'];
-      delete this._slider['_menu'];
+      delete t._prefix['_menu'];
+      delete t._lengthField['_menu'];
+      delete t._slider['_menu'];
     },
 
 
@@ -307,8 +286,7 @@
 
     // mouse wheel treatment
     _mousewheel : function (e) {
-      var delta = 0;
-      delta = e.deltaY / 120;
+      const delta = e.deltaY / 120;
       if (delta > 0)
         this.next();
       else if (delta < 0)
@@ -316,33 +294,32 @@
       e.halt();
     },
 
+
     // touchmove treatment
     _touch : function (e) {
-      var s = this.slider();
+      const s = this.slider();
+
       if (e.type === "touchstart") {
-        // s.active(true);
-        var t = e.touches[0];
-        this._lastTouch = t.clientY;
+        this._lastTouch = e.touches[0].clientY;
       }
       else if (e.type === "touchend") {
-        // s.active(false);
         this._lastTouch = undefined;
       }
       else if (e.type === "touchmove") {
-        var t = e.touches[0];
+        const to = e.touches[0];
 
         // TODO:
         // Instead of using 26px, choose the item height
         // or use the menu height // shownItems
         
         // s.movetoRel(t.clientY - this._initTouch);
-        if ((this._lastTouch + 26) < t.clientY) {
+        if ((this._lastTouch + 26) < to.clientY) {
           this.viewDown();
-          this._lastTouch = t.clientY;
+          this._lastTouch = to.clientY;
         }
-        else if ((this._lastTouch - 26) > t.clientY) {
+        else if ((this._lastTouch - 26) > to.clientY) {
           this.viewUp();
-          this._lastTouch = t.clientY;
+          this._lastTouch = to.clientY;
         }
         e.halt();
       };
@@ -350,35 +327,40 @@
 
     // Arrow key and prefix treatment
     _keydown : function (e) {
-      var code = _codeFromEvent(e);
+      const t = this;
 
-      switch (code) {
+      switch (_codeFromEvent(e)) {
+
       case 27: // 'Esc'
         e.halt();
-        this.hide();
+        t.hide();
         break;
 
       case 38: // 'Up'
         e.halt();
-        this.prev();
+        t.prev();
         break;
+
       case 33: // 'Page up'
         e.halt();
-        this.pageUp();
+        t.pageUp();
         break;
+
       case 40: // 'Down'
         e.halt();
-        this.next();
+        t.next();
         break;
+
       case 34: // 'Page down'
         e.halt();
-        this.pageDown();
+        t.pageDown();
         break;
+
       case 39: // 'Right'
-        if (this._prefix.active())
+        if (t._prefix.active())
           break;
 
-        var item = this.liveItem(this.position);
+        const item = t.liveItem(t.position);
         
         if (item["further"] !== undefined) {
           item["further"].bind(item).apply();
@@ -386,42 +368,48 @@
         
         e.halt();
         break;
-      case 13: // 'Enter'
 
+      case 13: // 'Enter'
         // Click on prefix
-        if (this._prefix.active())
-          this._prefix.onclick(e);
+        if (t._prefix.active())
+          t._prefix.onclick(e);
 
         // Click on item
         else
-          this.liveItem(this.position).onclick(e);
+          t.liveItem(t.position).onclick(e);
         e.halt();
         break;
+
       case 8: // 'Backspace'
-        this._prefix.chop();
-        this.show();
+        t._prefix.chop();
+        t.show();
         e.halt();
         break;
       };
     },
 
+
     // Add characters to prefix
     _keypress : function (e) {
       if (e.charCode !== 0) {
         e.halt();
-        var c = String.fromCharCode(_codeFromEvent(e));
         
         // Add prefix
-        this._prefix.add(c);
+        this._prefix.add(
+          String.fromCharCode(_codeFromEvent(e))
+        );
+
         this.show();
       };
     },
 
+
     /**
      * Show a screen with a given offset
      * in the viewport.
      */
     screen : function (nr) {
+      const t = this;
 
       // Normalize negative values
       if (nr < 0) {
@@ -429,20 +417,20 @@
       }
 
       // The shown list already shows everything
-      else if (this.liveLength() < this.limit()) {
+      else if (t.liveLength() < t.limit()) {
         return false;
       }
 
       // Move relatively to the next screen
-      else if (nr > (this.liveLength() - this.limit())) {
-        nr = (this.liveLength() - this.limit());
+      else if (nr > (t.liveLength() - t.limit())) {
+        nr = (t.liveLength() - t.limit());
       };
 
       // no change
-      if (this.offset === nr)
+      if (t.offset === nr)
         return false;
 
-      this._showItems(nr);
+      t._showItems(nr);
 
       return true;
     },
@@ -455,6 +443,7 @@
       return this._element;
     },
 
+
     /**
      * Get the creator class for items
      */
@@ -462,6 +451,7 @@
       return this._itemClass;
     },
 
+
     /**
      * Get and set the numerical value
      * for the maximum number of items visible.
@@ -499,24 +489,25 @@
      * @param {string} Prefix for filtering the list
      */
     show : function (active) {
+      const t = this;
 
       // show menu based on initial offset
-      this._unmark();     // Unmark everything that was marked before
-      this.removeItems();
+      t._unmark();     // Unmark everything that was marked before
+      t.removeItems();
 
       // Initialize the list
-      if (!this._initList()) {
+      if (!t._initList()) {
 
         // The prefix is not active
-        this._prefix.active(true);
+        t._prefix.active(true);
 
         // finally show the element
-        this._element.classList.add('visible');
+        t._element.classList.add('visible');
         
         return true;
       };
 
-      var offset = 0;
+      let offset = 0;
 
       // Set a chosen value to active and move the viewport
       if (arguments.length === 1) {
@@ -525,47 +516,48 @@
         if (active < 0) {
           active = 0;
         }
-        else if (active >= this.liveLength()) {
-          active = this.liveLength() - 1;
+        else if (active >= t.liveLength()) {
+          active = t.liveLength() - 1;
         };
 
         // Item is outside the first viewport
-        if (active >= this._limit) {
+        if (active >= t._limit) {
           offset = active;
-          if (offset > (this.liveLength() - this._limit)) {
-            offset = this.liveLength() - this._limit;
+          const newOffset = t.liveLength() - t._limit;
+          if (offset > newOffset) {
+            offset = newOffset;
           };
         };
         
-        this.position = active;
+        t.position = active;
       }
 
       // Choose the first item
-      else if (this._firstActive) {
-        this.position = 0;
+      else if (t._firstActive) {
+        t.position = 0;
       }
 
       // Choose no item
       else {
-        this.position = -1;
+        t.position = -1;
       };
 
-      this.offset = offset;
-      this._showItems(offset); // Show new item list
+      t.offset = offset;
+      t._showItems(offset); // Show new item list
 
       // Make chosen value active
-      if (this.position !== -1) {
-        this.liveItem(this.position).active(true);
+      if (t.position !== -1) {
+        t.liveItem(t.position).active(true);
       };
 
       // The prefix is not active
-      this._prefix.active(false);
+      t._prefix.active(false);
 
       // finally show the element
-      this._element.classList.add('visible');
+      t._element.classList.add('visible');
 
       // Add classes for rolling menus
-      this._boundary(true);
+      t._boundary(true);
 
       return true;
     },
@@ -575,21 +567,23 @@
      * Hide the menu and call the onHide callback.
      */
     hide : function () {
-      if(!this.dontHide){
-          this.removeItems();
-          this._prefix.clear();
-          this.onHide();
-          this._element.classList.remove('visible');
-      } 
-       /* this._element.blur(); */
+      if (!this.dontHide) {
+        this.removeItems();
+        this._prefix.clear();
+        this.onHide();
+        this._element.classList.remove('visible');
+      }
+      // this._element.blur();
     },
 
+
     /**
      * Function released when the menu hides.
      * This method is expected to be overridden.
      */
     onHide : function () {},
 
+
     /**
      * Get the prefix for filtering,
      * e.g. &quot;ve&quot; for &quot;verb&quot;
@@ -602,6 +596,7 @@
       return this._prefix.value();
     },
 
+    
     /**
      * Get the lengthField object.
      */
@@ -609,6 +604,7 @@
       return this._lengthField;
     },
 
+
     /**
      * Get the associated slider object.
      */
@@ -621,18 +617,18 @@
      * Delete all visible items from the menu element
      */
     removeItems : function () {
-      var child;
-
       // Remove all children
-      var children = this._element.childNodes;
+      const children = this._element.childNodes;
+
       // Leave the prefix and lengthField
-      for (var i = children.length - 1; i >= 3; i--) {
+      for (let i = children.length - 1; i >= 3; i--) {
         this._element.removeChild(
           children[i]
         );
       };
     },
 
+
     /**
      * Get a specific item from the complete list
      *
@@ -667,6 +663,7 @@
     shownItem : function (index) {
       if (index >= this.limit())
         return;
+
       return this.liveItem(this.offset + index);
     },
 
@@ -693,124 +690,128 @@
      * Make the next item in the filtered menu active
      */
     next : function () {
+      const t = this;
 
       // No list
-      if (this.liveLength() === 0)
+      if (t.liveLength() === 0)
         return;
 
       // Deactivate old item
-      if (this.position !== -1 && !this._prefix.active()) {
-        this.liveItem(this.position).active(false);
+      if (t.position !== -1 && !t._prefix.active()) {
+        t.liveItem(t.position).active(false);
       };
 
       // Get new active item
-      this.position++;
-      var newItem = this.liveItem(this.position);
+      t.position++;
+      let newItem = t.liveItem(t.position);
 
       // The next element is undefined - roll to top or to prefix
       if (newItem === undefined) {
 
         // Activate prefix
-        var prefix = this._prefix;
+        const prefix = this._prefix;
 
         // Prefix is set and not active - choose!
         if (prefix.isSet() && !prefix.active()) {
-          this.position--;
+          t.position--;
           prefix.active(true);
           return;
         }
 
         // Choose first item
         else {
-          newItem = this.liveItem(0);
+          newItem = t.liveItem(0);
           // choose first item
-          this.position = 0;
-          this._showItems(0);
+          t.position = 0;
+          t._showItems(0);
         };
       }
 
       // The next element is after the viewport - roll down
-      else if (this.position >= (this.limit() + this.offset)) {
-        this.screen(this.position - this.limit() + 1);
+      else if (t.position >= (t.limit() + t.offset)) {
+        t.screen(t.position - t.limit() + 1);
       }
 
       // The next element is before the viewport - roll up
-      else if (this.position <= this.offset) {
-        this.screen(this.position);
+      else if (t.position <= t.offset) {
+        t.screen(t.position);
       };
 
-      this._prefix.active(false);
+      t._prefix.active(false);
       newItem.active(true);
     },
 
+
     /*
      * Make the previous item in the menu active
      */
     prev : function () {
+      const t = this;
 
       // No list
-      if (this.liveLength() === 0)
+      if (t.liveLength() === 0)
         return;
 
       // Deactivate old item
-      if (!this._prefix.active()) {
+      if (!t._prefix.active()) {
 
         // No active element set
-        if (this.position === -1) {
-          this.position = this.liveLength();
+        if (t.position === -1) {
+          t.position = t.liveLength();
         }
 
         // No active element set
         else {
-          this.liveItem(this.position--).active(false);
+          t.liveItem(t.position--).active(false);
         };
       };
 
       // Get new active item
-      var newItem = this.liveItem(this.position);
+      let newItem = t.liveItem(t.position);
 
       // The previous element is undefined - roll to bottom
       if (newItem === undefined) {
 
         // Activate prefix
-        var prefix = this._prefix;
-        var offset =  this.liveLength() - this.limit();
+        const prefix = t._prefix;
+        let offset =  t.liveLength() - t.limit();
         
         // Normalize offset
         offset = offset < 0 ? 0 : offset;
 
         // Choose the last item
-        this.position = this.liveLength() - 1;
+        t.position = t.liveLength() - 1;
         
         // Prefix is set and not active - choose!
         if (prefix.isSet() && !prefix.active()) {
-          this.position++;
+          t.position++;
           prefix.active(true);
-          this.offset = offset;
+          t.offset = offset;
           return;
         }
 
         // Choose last item
         else {
-          newItem = this.liveItem(this.position);
-          this._showItems(offset);
+          newItem = t.liveItem(t.position);
+          t._showItems(offset);
         };
       }
 
       // The previous element is before the view - roll up
-      else if (this.position < this.offset) {
-        this.screen(this.position);
+      else if (t.position < t.offset) {
+        t.screen(t.position);
       }
 
       // The previous element is after the view - roll down
-      else if (this.position >= (this.limit() + this.offset)) {
-        this.screen(this.position - this.limit() + 2);
+      else if (t.position >= (t.limit() + t.offset)) {
+        t.screen(t.position - t.limit() + 2);
       };
 
-      this._prefix.active(false);
+      t._prefix.active(false);
       newItem.active(true);
     },
 
+
     /**
      * Move the page up by limit!
      */
@@ -842,19 +843,22 @@
       this.screen(this.offset + 1);
     },
 
+
     // Unmark all items
     _unmark : function () {
       this._list.forEach(function(it){
-        var item = this._items[it];
+        const item = this._items[it];
         item.lowlight();
         item.active(false);
       }, this);
     },
 
+
     // Set boundary for viewport
     _boundary : function (bool) {
       if (this._list.length === 0)
         return;
+
       this.item(this._list[0]).noMore(bool);
       this.item(this._list[this._list.length - 1]).noMore(bool);
     },
@@ -862,68 +866,68 @@
 
     // Append Items that should be shown
     _showItems : function (off) {
+      const t = this;
 
       // optimization: scroll down one step
-      if (this.offset === (off - 1)) {
-        this.offset = off;
+      if (t.offset === (off - 1)) {
+        t.offset = off;
 
         // Remove the HTML node from the first item
         // leave lengthField/prefix/slider
-        this._element.removeChild(this._element.children[3]);
-        var pos = this.offset + this.limit() - 1;
-        this._append(this._list[pos]);
+        t._element.removeChild(t._element.children[3]);
+
+        t._append(
+          t._list[t.offset + t.limit() - 1]
+        );
       }
 
       // optimization: scroll up one step
-      else if (this.offset === (off + 1)) {
-        this.offset = off;
+      else if (t.offset === (off + 1)) {
+        t.offset = off;
 
         // Remove the HTML node from the last item
-        this._element.removeChild(this._element.lastChild);
+        t._element.removeChild(t._element.lastChild);
 
-        this._prepend(this._list[this.offset]);
+        t._prepend(t._list[t.offset]);
       }
+
       else {
-        this.offset = off;
+        t.offset = off;
 
         // Remove all items
-        this.removeItems();
+        t.removeItems();
 
         // Use list
-        var shown = 0;
-        var i;
+        let shown = 0;
 
-        for (let i = 0; i < this._list.length; i++) {
+        for (let i = 0; i < t._list.length; i++) {
 
           // Don't show - it's before offset
           shown++;
           if (shown <= off)
             continue;
 
-          var itemNr = this._list[i];
-          var item = this.item(itemNr);
-          this._append(itemNr);
+          t._append(t._list[i]);
           
-          if (shown >= (this.limit() + off))
+          if (shown >= (t.limit() + off))
             break;
         };
       };
 
       // set the slider to the new offset
-      this._slider.offset(this.offset);
+      t._slider.offset(t.offset);
     },
 
 
     // Append item to the shown list based on index
     _append : function (i) {
-      var item = this.item(i);
+      const item = this.item(i);
 
       // Highlight based on prefix
       if (this.prefix().length > 0) {
         item.highlight(this.prefix().toLowerCase());
       };
 
-
       // Append element
       this.element().appendChild(item.element());
     },
@@ -931,14 +935,14 @@
 
     // Prepend item to the shown list based on index
     _prepend : function (i) {
-      var item = this.item(i);
+      const item = this.item(i);
 
       // Highlight based on prefix
       if (this.prefix().length > 0) {
         item.highlight(this.prefix().toLowerCase());
       };
 
-      var e = this.element();
+      const e = this.element();
 
       // Append element after lengthField/prefix/slider
       e.insertBefore(