Alien-GvaScript
view release on metacpan or search on metacpan
src/choiceList.js view on Meta::CPAN
//----------------------------------------------------------------------
// CONSTRUCTOR
//----------------------------------------------------------------------
GvaScript.ChoiceList = function(choices, options) {
if (! (choices instanceof Array) )
throw new Error("invalid choices argument : " + choices);
this.choices = choices;
var defaultOptions = {
labelField : "label",
classes : {}, // see below for default classes
idForChoices : "CL_choice",
keymap : null,
grabfocus : false,
mouseovernavi : true,
scrollCount : 5,
choiceItemTagName: "div",
htmlWrapper : function(html) {return html;},
paginator : null
};
this.options = Class.checkOptions(defaultOptions, options);
var defaultClasses = {
choiceItem : "CL_choiceItem",
choiceHighlight : "CL_highlight"
};
this.classes = Class.checkOptions(defaultClasses, this.options.classes);
// handy vars
this.hasPaginator = this.options.paginator != null;
this.pageSize = (
// the step size of the paginator if any
(this.hasPaginator && this.options.paginator.options.step)
||
// scroll count
this.options.scrollCount
);
// prepare some stuff to be reused when binding to inputElements
this.reuse = {
onmouseover : this._listOverHandler.bindAsEventListener(this),
onclick : this._clickHandler.bindAsEventListener(this),
ondblclick : this._dblclickHandler.bindAsEventListener(this),
navigationRules: {
DOWN: this._highlightDelta.bindAsEventListener(this, 1),
UP: this._highlightDelta.bindAsEventListener(this, -1),
PAGE_DOWN: this._highlightDelta.bindAsEventListener(this, this.pageSize),
PAGE_UP: this._highlightDelta.bindAsEventListener(this, -this.pageSize),
HOME: this._jumpToIndex.bindAsEventListener(this, 0),
END: this._jumpToIndex.bindAsEventListener(this, 99999),
RETURN: this._returnHandler .bindAsEventListener(this),
ESCAPE: this._escapeHandler .bindAsEventListener(this)
}
};
if(this.hasPaginator) {
// next/prev page
this.reuse.navigationRules.RIGHT
= this._highlightDelta.bindAsEventListener(this, this.pageSize)
this.reuse.navigationRules.LEFT
= this._highlightDelta.bindAsEventListener(this, -this.pageSize);
// first/last page
this.reuse.navigationRules.C_HOME
= this._jumpToPage.bindAsEventListener(this, 0);
this.reuse.navigationRules.C_END
= this._jumpToPage.bindAsEventListener(this, 99999);
}
};
GvaScript.ChoiceList.prototype = {
//----------------------------------------------------------------------
// PUBLIC METHODS
//----------------------------------------------------------------------
destroy: function() {
// test that element still in DOM
if(this.container) Event.stopObserving(this.container);
},
fillContainer: function(containerElem) {
this.container = containerElem;
this.container.choiceList = this;
Element.update(this.container, this.htmlForChoices());
// mouse events on choice items will bubble up to the container
if(this.options.mouseovernavi) {
Event.observe(this.container, "mouseover", this.reuse.onmouseover);
}
Event.observe(this.container, "click" , this.reuse.onclick);
Event.observe(this.container, "dblclick" , this.reuse.ondblclick);
if (this.options.keymap) {
this.keymap = this.options.keymap;
this.keymap.rules.push(this.reuse.navigationRules);
}
else {
this.keymap = new GvaScript.KeyMap(this.reuse.navigationRules);
var target = this.container.tabIndex == undefined
? document
: this.container;
this.keymap.observe("keydown", target);
}
// POTENTIAL PROBLEM HERE : the keymap may stay active
// even after the choiceList is deleted (may yield memory leaks and
// inconsistent behaviour). But we have no "destructor", so how
// can we unregister the keymap ?
src/choiceList.js view on Meta::CPAN
//----------------------------------------------------------------------
_findChoiceItem: function(event) { // walk up DOM to find mouse target
var stop_condition = function(elem){return elem === this.container};
return Element.navigateDom(Event.element(event), "parentNode",
this.classes.choiceItem,
stop_condition);
},
_listOverHandler: function(event) {
var elem = this._findChoiceItem(event);
if (elem) {
this._highlightChoiceNum(this._choiceIndex(elem), false);
if (this.options.grabfocus)
this.container.focus();
Event.stop(event);
}
},
// no _listOutHandler needed
_dblclickHandler: function(event) {
var elem = this._findChoiceItem(event);
if (elem) {
var newIndex = this._choiceIndex(elem);
this._highlightChoiceNum(newIndex, false);
this._clickHandler(event);
}
},
_clickHandler: function(event) {
var elem = this._findChoiceItem(event);
if (elem) {
var newIndex = this._choiceIndex(elem);
// check if choice is selected
if (this.currentHighlightedIndex == newIndex) {
// selected -> fire ping event
var toStop = this.fireEvent({type : "Ping",
index: this._choiceIndex(elem)},
elem,
this.container);
Event.detailedStop(event, toStop || Event.stopAll);
}
else {
// not selected -> select
this._highlightChoiceNum(newIndex, false);
}
}
},
_returnHandler: function(event) {
var index = this.currentHighlightedIndex;
if (index != undefined) {
var elem = this._choiceElem(index);
var toStop = this.fireEvent({type : "Ping",
index: index}, elem, this.container);
Event.detailedStop(event, toStop || Event.stopAll);
}
},
_escapeHandler: function(event) {
var toStop = this.fireEvent("Cancel", this.container);
Event.detailedStop(event, toStop || Event.stopAll);
}
};
( run in 1.250 second using v1.01-cache-2.11-cpan-f5b5a18a01a )