Improved slider behaviour and fixed prefix handling
diff --git a/dev/js/src/menu/item.js b/dev/js/src/menu/item.js
index b8e8808..8278d17 100644
--- a/dev/js/src/menu/item.js
+++ b/dev/js/src/menu/item.js
@@ -122,10 +122,50 @@
* @param {string} Prefix string for highlights
*/
highlight : function (prefix) {
+
+ // The prefix already matches
+ if (this._prefix === prefix)
+ return;
+
+ // There is a prefix but it doesn't match
+ if (this._prefix !== null) {
+ this.lowlight();
+ }
+
var children = this.element().childNodes;
for (var i = children.length -1; i >= 0; i--) {
this._highlight(children[i], prefix);
};
+
+ this._prefix = prefix;
+ },
+
+ /**
+ * Remove highlight of the menu item
+ */
+ lowlight : function () {
+ if (this._prefix === null)
+ return;
+
+ var e = this.element();
+
+ var marks = e.getElementsByTagName("mark");
+ for (var i = marks.length - 1; i >= 0; i--) {
+ // Create text node clone
+ var x = document.createTextNode(
+ marks[i].firstChild.nodeValue
+ );
+
+ // Replace with content
+ marks[i].parentNode.replaceChild(
+ x,
+ marks[i]
+ );
+ };
+
+ // Remove consecutive textnodes
+ e.normalize();
+ this._prefix = null;
},
// Highlight a certain substring of the menu item
@@ -176,30 +216,6 @@
};
},
- /**
- * Remove highlight of the menu item
- */
- lowlight : function () {
- var e = this.element();
-
- var marks = e.getElementsByTagName("mark");
- for (var i = marks.length - 1; i >= 0; i--) {
- // Create text node clone
- var x = document.createTextNode(
- marks[i].firstChild.nodeValue
- );
-
- // Replace with content
- marks[i].parentNode.replaceChild(
- x,
- marks[i]
- );
- };
-
- // Remove consecutive textnodes
- e.normalize();
- },
-
// Initialize menu item
_init : function (params) {
@@ -212,6 +228,7 @@
this._action = params[1];
this._lcField = ' ' + this.content().textContent.toLowerCase();
+ this._highlight = null;
return this;
},
diff --git a/dev/js/src/menu/slider.js b/dev/js/src/menu/slider.js
index c35f284..d71bae1 100644
--- a/dev/js/src/menu/slider.js
+++ b/dev/js/src/menu/slider.js
@@ -1,14 +1,33 @@
define({
/**
- * Create new prefix object.
+ * Create new slider object.
+ * The slider will only be used by mouse - touch support
+ * shouldn't be necessary.
*/
create : function (menu) {
return Object.create(this)._init(menu);
},
- _mousemove : function (e) {
- var relativePos = e.clientY - this._event.init;
+ length : function (i) {
+ if (arguments.length === 0)
+ return this._length;
+ if (i == this._length)
+ return;
+ this._length = i;
+ this._initSize();
+ },
+
+ limit : function (i) {
+ if (arguments.length === 0)
+ return this._limit;
+ if (i == this._limit)
+ return;
+ this._limit = i;
+ this._initSize();
+ },
+
+ movetoRel : function (relativePos) {
var diffHeight = (this._rulerHeight - this._sliderHeight);
var relativeOffset = (relativePos / diffHeight);
@@ -16,34 +35,38 @@
if (off !== undefined) {
this._menu.screen(off);
};
-
- e.halt();
-
- // Support touch!
},
- _mouseup : function (e) {
- this._element.classList.remove('active');
- window.removeEventListener('mousemove', this._event.mov);
- window.removeEventListener('mouseup', this._event.up);
+ movetoAbs : function (absPos) {
+ var absOffset = (absPos / this._rulerHeight);
+
+ var off = this.offset(parseInt(absOffset * (this._screens + 1)));
+ if (off !== undefined) {
+ this._menu.screen(off);
+ };
},
- _mousedown : function (e) {
- // Bind drag handler
- var ev = this._event;
- ev.init = e.clientY - (this._step * this._offset);
- ev.mov = this._mousemove.bind(this);
- ev.up = this._mouseup.bind(this);
+ offset : function (off) {
+ if (arguments.length === 0)
+ return this._offset;
- this._rulerHeight = this._element.clientHeight; // offsetHeight?
- this._sliderHeight = this._slider.clientHeight; // offsetHeight?
+ if (off > this._screens) {
+ off = this._screens;
+ }
+ else if (off < 0) {
+ off = 0;
+ };
- this._element.classList.add('active');
+ if (off === this._offset)
+ return undefined;
- window.addEventListener('mousemove', ev.mov);
- window.addEventListener('mouseup', ev.up);
+ this._offset = off;
+ this._slider.style.top = (this._step * off) + '%';
+ return off;
+ },
- e.halt();
+ element : function () {
+ return this._element;
},
// Initialize prefix object
@@ -61,51 +84,78 @@
document.createElement('span')
);
- this._element.appendChild(document.createElement('div'))
- // Do not mark the menu on mousedown
- .addEventListener('mousedown', function (e) {
- e.halt()
- });
+ this._ruler = this._element.appendChild(document.createElement('div'));
- // TODO: Support touch!
+ // Do not mark the menu on mousedown
+ this._ruler.addEventListener('mousedown', function (e) {
+ e.halt()
+ }, false);
+
+ // Move the slider to the click position
+ this._ruler.addEventListener('click', this._mouseclick.bind(this), false);
+
this._slider.addEventListener('mousedown', this._mousedown.bind(this), false);
return this;
},
_initSize : function () {
+ if (this._length <= this._limit) {
+ this._element.style.display = 'none';
+ return;
+ }
+ else {
+ this._element.style.display = 'block';
+ };
+
this._height = ((this._limit / this._length) * 100);
this._screens = this._length - this._limit;
this._step = (100 - this._height) / this._screens;
- },
-
- show : function (i) {
this._slider.style.height = this._height + '%';
},
- length : function (i) {
- this._length = i;
- this._initSize();
+ _initClientHeight : function () {
+ this._rulerHeight = this._element.clientHeight; // offsetHeight?
+ this._sliderHeight = this._slider.clientHeight; // offsetHeight?
},
- limit : function (i) {
- this._limit = i;
- this._initSize();
+ _mousemove : function (e) {
+ this.movetoRel(e.clientY - this._event.init);
+ e.halt();
+ // Support touch!
},
- offset : function (off) {
- if (arguments.length === 0)
- return this._offset;
-
- if (off === this._offset || off > this._screens || off < 0)
- return undefined;
-
- this._offset = off;
- this._slider.style.top = (this._step * off) + '%';
- return off;
+ _mouseup : function (e) {
+ this._element.classList.remove('active');
+ window.removeEventListener('mousemove', this._event.mov);
+ window.removeEventListener('mouseup', this._event.up);
+ this._menu.focus();
},
- element : function () {
- return this._element;
+ _mousedown : function (e) {
+ // Bind drag handler
+ var ev = this._event;
+ ev.init = e.clientY - (this._step * this._offset);
+ ev.mov = this._mousemove.bind(this);
+ ev.up = this._mouseup.bind(this);
+
+ // TODO: This may not be necessary all the time
+ this._initClientHeight();
+
+ this._element.classList.add('active');
+
+ window.addEventListener('mousemove', ev.mov);
+ window.addEventListener('mouseup', ev.up);
+
+ e.halt();
+ },
+
+ _mouseclick : function (e) {
+ this._initClientHeight();
+
+ this.movetoAbs(
+ e.clientY - this._ruler.getClientRects()[0].top
+ );
+ e.halt();
}
});