fix moving cursor in menu outside the viewport
diff --git a/dev/js/spec/menuSpec.js b/dev/js/spec/menuSpec.js
index e6d5049..972f385 100644
--- a/dev/js/spec/menuSpec.js
+++ b/dev/js/spec/menuSpec.js
@@ -1404,6 +1404,91 @@
expect(menu.slider().offset()).toEqual(2);
expect(menu.shownItem(0).active()).toBe(false);
expect(menu.shownItem(0).lcField()).toEqual(' morphology');
+
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).active()).toBe(false);
+
+ // When the active cursor moves again - scroll to viewport
+ // cursor is before viewport
+ menu.next();
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(0).lcField()).toEqual(' lemma');
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).active()).toBe(false);
+
+ menu.next();
+ menu.next();
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(0).lcField()).toEqual(' lemma');
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(1).lcField()).toEqual(' morphology');
+ expect(menu.shownItem(2).active()).toBe(true);
+ expect(menu.shownItem(2).lcField()).toEqual(' part-of-speech');
+
+ menu.slider().movetoRel(0);
+ expect(menu.slider().offset()).toEqual(0);
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(0).lcField()).toEqual(' constituency');
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(1).lcField()).toEqual(' lemma');
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.shownItem(2).lcField()).toEqual(' morphology');
+
+ // cursor is after viewport
+ menu.next();
+ expect(menu.slider().offset()).toEqual(2);
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(0).lcField()).toEqual(' morphology');
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(1).lcField()).toEqual(' part-of-speech');
+ expect(menu.shownItem(2).active()).toBe(true);
+ expect(menu.shownItem(2).lcField()).toEqual(' syntax');
+
+ menu.slider().movetoRel(0);
+ expect(menu.slider().offset()).toEqual(0);
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(0).lcField()).toEqual(' constituency');
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(1).lcField()).toEqual(' lemma');
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.shownItem(2).lcField()).toEqual(' morphology');
+
+ menu.prev();
+ expect(menu.slider().offset()).toEqual(2);
+ expect(menu.shownItem(0).lcField()).toEqual(' morphology');
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(1).lcField()).toEqual(' part-of-speech');
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.shownItem(2).lcField()).toEqual(' syntax');
+ expect(menu.shownItem(2).active()).toBe(false);
+
+ menu.prev();
+ menu.prev();
+ expect(menu.slider().offset()).toEqual(1);
+ expect(menu.shownItem(0).lcField()).toEqual(' lemma');
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).lcField()).toEqual(' morphology');
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).lcField()).toEqual(' part-of-speech');
+ expect(menu.shownItem(2).active()).toBe(false);
+
+ menu.slider().movetoRel(100);
+ expect(menu.slider().offset()).toEqual(2);
+ expect(menu.shownItem(0).lcField()).toEqual(' morphology');
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(1).lcField()).toEqual(' part-of-speech');
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).lcField()).toEqual(' syntax');
+ expect(menu.shownItem(2).active()).toBe(false);
+
+ menu.prev();
+ expect(menu.slider().offset()).toEqual(0);
+ expect(menu.shownItem(0).lcField()).toEqual(' constituency');
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).lcField()).toEqual(' lemma');
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).lcField()).toEqual(' morphology');
+ expect(menu.shownItem(2).active()).toBe(false);
});
});
});
diff --git a/dev/js/src/menu.js b/dev/js/src/menu.js
index 484f47c..95b4f8d 100644
--- a/dev/js/src/menu.js
+++ b/dev/js/src/menu.js
@@ -9,9 +9,11 @@
* TODO: What is _pos and what is position?
* TODO: What is the difference between position
* and _active?
- * TODO: if the prefix is not found, it should be visible and active!
- * TODO: Bug: The slider vanishes, if the prefix wasn't found in the demo
- * (example: type "elt")
+ * TODO: next and prev should use an optimized version of _screen
+ * TODO: On next and prev the viewport should move
+ * to the active item.
+ * TODO: pageUp and pageDown should use _screen
+ * TODO: Ignore keys with function key combinations (other than shift)
*/
define([
'menu/item',
@@ -307,15 +309,12 @@
// Add characters to prefix
_keypress : function (e) {
+ e.halt();
var c = String.fromCharCode(_codeFromEvent(e)).toLowerCase();
// Add prefix
this._prefix.add(c);
-
- if (!this.show()) {
- this.prefix('').show();
- e.halt();
- };
+ this.show();
},
/**
@@ -325,6 +324,28 @@
screen : function (nr) {
if (this._offset === nr)
return;
+
+ // OPTIMIZE!!!
+
+ // TODO: This is just an optimization of screen
+ /*
+ if (this.position >= (this.limit() + this._offset) {
+ this._removeFirst();
+ this._offset++;
+ this._append(this._list[this.position]);
+ this._slider.offset(this._offset);
+ }
+ else if (this.position < this._offset) {
+
+ this._removeLast();
+ this._offset--;
+ this._prepend(this._list[this.position]);
+ // set the slider to the new offset
+ this._slider.offset(this._offset);
+ }
+ */
+
+
this.unshow();
this._offset = nr;
this._showItems(nr);
@@ -624,12 +645,15 @@
};
}
- // The next element is outside the view - roll down
+ // The next element is after the viewport - roll down
else if (this.position >= (this.limit() + this._offset)) {
- this._removeFirst();
- this._offset++;
- this._append(this._list[this.position]);
- this._slider.offset(this._offset);
+
+ this.screen(this.position - this.limit() + 1);
+ }
+
+ // The next element is before the viewport - roll up
+ else if (this.position <= this._offset) {
+ this.screen(this.position);
};
this._prefix.active(false);
@@ -682,13 +706,14 @@
};
}
- // The previous element is outside the view - roll up
+ // The previous element is before the view - roll up
else if (this.position < this._offset) {
- this._removeLast();
- this._offset--;
- this._prepend(this._list[this.position]);
- // set the slider to the new offset
- this._slider.offset(this._offset);
+ this.screen(this.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);
};
this._prefix.active(false);