Alien-GvaScript
view release on metacpan or search on metacpan
lib/Alien/GvaScript/lib/GvaScript.js view on Meta::CPAN
new Ajax.Updater(content, url, {onComplete: callback});
return true;
}
},
select: function (node) {
var previousNode = this.selectedNode;
// re-selecting the current node is a no-op
if (node == previousNode) return;
// deselect the previously selected node
if (previousNode) {
var label = this.label(previousNode);
if (label) {
Element.removeClassName(label, this.classes.selected);
}
}
// select the new node
this.selectedNode = node;
if (node) {
this._assertNodeOrLeaf(node, 'select node');
var label = this.label(node);
if (!label) {
throw new Error("selected node has no label");
}
else {
Element.addClassName(label, this.classes.selected);
if (this.isVisible(label)) {
// focus has not yet been given to label
if(! label.hasAttribute('hasFocus'))
label.focus();
}
}
}
// cancel if there was any select execution pending
if (this._selectionTimeoutId) clearTimeout(this._selectionTimeoutId);
// register code to call the selection handlers after some delay
var callback = this._selectionTimeoutHandler.bind(this, previousNode);
this._selectionTimeoutId =
setTimeout(callback, this.options.selectDelay);
},
scrollTo: function(node, with_content) {
if(!node) return;
var container = this.options.scrollingContainer;
if(typeof container == 'string') {
container = $(container);
}
if(!container) return;
// donot invoke scroll if scrolling is disabled
// first test if scrolling is enabled on the scrolling container
if(container.tagName.toLowerCase() == 'html') {
// on document body
if(document.body.style.overflow == 'hidden'
|| document.body.style.overflowY == 'hidden'
|| document.body.scroll == 'no') // IE
return;
}
else {
// on element
if(container.style.overflow == 'hidden'
|| container.style.overflowY == 'hidden')
return;
}
// test if the node in 'in view'
_container_y_start = container.scrollTop;
_container_y_end = _container_y_start + container.clientHeight;
_node_y = Element.cumulativeOffset(node).top + (with_content? node.offsetHeight: 0);
// calculate padding space between the selected node and
// the edge of the scrollable container
_perc = this.options.autoScrollPercentage || 0;
_padding = container.clientHeight * _perc / 100;
// calculate delta scroll to affect on scrollingContainer
_delta = 0;
// node is beneath scrolling area
if(_node_y > _container_y_end - _padding) {
_delta = _node_y - _container_y_end + _padding;
}
// node is above scrolling area
if(_node_y < _container_y_start + _padding) {
_delta = _container_y_start - _node_y - _padding;
}
if(_delta != 0) {
// amount required to scroll to greater than available document height
if(_delta > container.clientHeight - _padding) {
// make label top
var lbl_pos = Element.cumulativeOffset(this.label(node)).top;
container.scrollTop = lbl_pos - _padding;
}
else
container.scrollTop += parseInt(_delta)
}
return;
},
label: function(node) {
this._assertNodeOrLeaf(node, 'label: arg type');
return Element.navigateDom(node.firstChild, 'nextSibling',
this.classes.label);
},
content: function(node) {
if (this.isLeaf(node)) return null;
this._assertNode(node, 'content: arg type');
return Element.navigateDom(node.lastChild, 'previousSibling',
this.classes.content);
},
parentNode: function (node) {
this._assertNodeOrLeaf(node, 'parentNode: arg type');
return Element.navigateDom(
node.parentNode, 'parentNode', this.classes.node,
this.isRootElement.bind(this));
},
nextSibling: function (node) {
lib/Alien/GvaScript/lib/GvaScript.js view on Meta::CPAN
// second param is the HTTP method (post or get)
// DALNOTE 10.01.09 : pas de raison de faire le choix de la méthode HTTP
// dans setAdditionalParams()! TOFIX. Apparemment, utilisé une seule fois
// dans DMWeb (root\src\tab_composition\form.tt2:43)
setAdditionalParams : function(params, method) {
this.additional_params = params;
if (method) this.options.http_method = method;
},
addAdditionalParam : function(param, value) {
if (!this.additional_params)
this.additional_params = {};
this.additional_params[param] = value;
},
setdatasource : function(datasource) {
// remember datasource in private property
this._datasource = datasource;
// register proper "updateChoices" function according to type of datasource
var ds_type = typeof datasource;
this._updateChoicesHandler
= (ds_type == "string") ? this._updateChoicesFromAjax
: (ds_type == "function") ? this._updateChoicesFromCallback
: (ds_type == "object" && datasource instanceof Array)
? this._updateChoicesFromArray
: (ds_type == "object" && datasource instanceof Object)
? this._updateChoicesFromJSONP
: undefined;
if (!this._updateChoicesHandler)
throw new Error("unexpected datasource type");
},
// 'fireEvent' function is copied from GvaScript.fireEvent, so that "this"
// in that code gets properly bound to the current object
fireEvent: GvaScript.fireEvent,
// Set the element for the AC to look at to adapt its position. If elem is
// null, stop observing the scroll.
// DALNOTE 10.01.09 : pas certain de l'utilité de "set_observed_scroll"; si
// l'élément est positionné correctement dans le DOM par rapport à son parent,
// il devrait suivre le scroll automatiquement. N'est utilisé dans DMWeb que
// par "avocat.js".
set_observed_scroll : function(elem) {
if (!elem) {
Event.stopObserving(this.observed_scroll, 'scroll',
correct_dropdown_position);
return;
}
this.observed_scroll = elem;
this.currentScrollTop = elem.scrollTop;
this.currentScrollLeft = elem.scrollLeft;
var correct_dropdown_position = function() {
if (this.dropdownDiv) {
var dim = Element.getDimensions(this.inputElement);
var pos = this.dropdownDiv.positionedOffset();
pos.top -= this.observed_scroll.scrollTop - this.currentScrollTop;
pos.left -= this.observed_scroll.scrollLeft;
this.dropdownDiv.style.top = pos.top + "px";
this.dropdownDiv.style.left = pos.left + "px";
}
this.currentScrollTop = this.observed_scroll.scrollTop;
this.currentScrollLeft = this.observed_scroll.scrollLeft;
}
Event.observe(elem, 'scroll',
correct_dropdown_position.bindAsEventListener(this));
},
//----------------------------------------------------------------------
// PRIVATE METHODS
//----------------------------------------------------------------------
_updateChoicesFromAjax: function (val_to_complete, continuation) {
// copies into local variables, needed for closures below (can't rely on
// 'this' because 'this' may have changed when the ajax call comes back)
var autocompleter = this;
var inputElement = this.inputElement;
inputElement.style.backgroundColor = ""; // remove colorIllegal
// abort prev ajax request on this input element
if (this._runningAjax[inputElement.name])
this._runningAjax[inputElement.name].transport.abort();
Element.addClassName(inputElement, this.classes.loading);
// encode value to complete
val_to_complete = val_to_complete.split("").map(function (c) {
if (c.match(/[@\+\/]/)) {
return encodeURIComponent(c);
}
else {
return escape(c);
}
}).join("");
var complete_url = this._datasource + val_to_complete;
this._runningAjax[inputElement.name] = new Ajax.Request(
complete_url,
{asynchronous: true,
method: this.options.http_method,
parameters: this.additional_params, // for example {C_ETAT_AVOC : 'AC'}
// DALNOTE 10.01.09: forcer du JSON dans le body du POST est spécifique
// DMWeb; pour le cas général il faut pouvoir envoyer du
// x-www-form-urlencoded ordinaire
postBody: this.options.http_method == 'post'
? Object.toJSON(this.additional_params)
: null,
contentType: "text/javascript",
evalJSON: 'force', // will evaluate even if header != 'application/json'
onSuccess: function(xhr) {
// aborted by the onblur handler
if (xhr.transport.status == 0) return;
autocompleter._runningAjax[inputElement.name] = null;
if (xhr.responseJSON) continuation(xhr.responseJSON);
// autocompleter input already blurred without _blurHandler being
// called (autocompleter is strict and needs its choices to
// be able to fire its final status
if (xhr['blurAfterSuccess']) autocompleter._blurHandler();
},
onFailure: function(xhr) {
autocompleter._runningAjax[inputElement.name] = null;
autocompleter.displayMessage("pas de réponse du serveur");
},
onComplete: function(xhr) {
Element.removeClassName(inputElement,
autocompleter.classes.loading);
}
});
},
_updateChoicesFromCallback : function(val_to_complete, continuation) {
continuation(this._datasource(val_to_complete));
lib/Alien/GvaScript/lib/GvaScript.js view on Meta::CPAN
// if (window.console) console.log('updateChoices', value);
this._updateChoicesHandler(value, continuation);
},
// does the reverse of "autocomplete()"
// doesnot fire if input blurred from click on choice list
_blurHandler: function(event) {
// remove choice list
if (this.dropdownDiv) this._removeDropdownDiv();
// xhr is still active: waiting for response from server
if (_xhr = this._runningAjax[this.inputElement.name]) {
// if autocompleter is strict, need to wait for xhr to
// finish before calling the _blurHandler to fire the
// autocompleter's finalState
if (this.options.strict) {
_xhr['blurAfterSuccess'] = true;
return;
}
_xhr.transport.abort();
_xhr = null;
Element.removeClassName(this.inputElement, this.classes.loading);
}
// if strict mode, inform client about the final status
if (this.options.strict) {
var value = this._getValueToComplete();
// if value has changed, invalidate previous list of choices
if (value != this.lastValue) {
this.choices = null;
}
// if blank and blankOK, this is a legal value
if (!value && this.options.blankOK) {
this._updateDependentFields(this.inputElement, "");
this.fireEvent({ type : "LegalValue",
value : "",
choice : null,
controller : null }, this.inputElement);
}
// if choices are known, just inspect status
else if (this.choices) {
this._fireFinalStatus(this.inputElement, this.choices);
}
// if not enough chars to get valid choices, this is illegal
else if (value.length < this.options.minimumChars) {
var return_value = this.fireEvent({
type: "IllegalValue", value: value
}, this.inputElement);
if(! return_value) {
this.inputElement.style.backgroundColor = this.options.colorIllegal;
this._updateDependentFields(this.inputElement, null);
}
}
// otherwise get choices and then inspect status (maybe asynchronously)
else {
this._updateChoices(this._fireFinalStatus.bind(this,
this.inputElement));
}
}
this.fireEvent("Leave", this.inputElement);
this.inputElement = null;
},
_fireFinalStatus: function (inputElement, choices) {
// NOTE: takes inputElement and choices as arguments, because it might be
// called asynchronously, after "this" has been detached from the input
// element and the choices array, so we cannot call the object properties.
var input_val = this._getValueToComplete(inputElement.value);
var index = null;
// inspect the choice list to automatically choose the appropriate candidate
for (var i=0; i < choices.length; i++) {
var val = this._valueFromChoiceItem(choices[i]);
if (val == input_val) {
index = i;
break; // break the loop because this is the best choice
}
else if (val.toUpperCase() == input_val.toUpperCase()) {
index = i; // is a candidate, but we may find a better one
}
}
// if automatic choice did not work, but we have only 1 choice, and this is
// not blank on purpose, then force it into the field
if (index === null && choices.length == 1
&& (input_val || !this.options.blankOK ))
index = 0;
if (index !== null) {
var choice = choices[index];
var val = this._valueFromChoiceItem(choice);
// put canonical value back into input field
this._setValue(val, inputElement);
// for backwards compatibility, we generate a "Complete" event, but
// with a fake controller (because the real controller might be in a
// diffent state).
this.fireEvent({ type : "Complete",
referrer : "blur", // input blur fired this event
index : index,
choice : choice,
controller: {choices: choices} }, inputElement);
// update dependent fields
this._updateDependentFields(inputElement, choice);
// for new code : generate a "LegalValue" event
this.fireEvent({ type : "LegalValue",
value : val,
choice : choice,
controller : null }, inputElement);
}
else {
var return_value = this.fireEvent({
type : "IllegalValue",
value : input_val,
controller : null
}, inputElement);
if(! return_value) {
inputElement.style.backgroundColor = this.options.colorIllegal;
this._updateDependentFields(inputElement, null);
}
}
},
_updateDependentFields: function(inputElement, choice) {
// "choice" might be
// - an object or nonempty string ==> update dependent fields
// - an empty string ==> clear dependent fields
// - null ==> put "ILLEGAL_***"
var attr = inputElement.getAttribute('ac:dependentFields');
var dep_fields = attr ? eval("("+attr+")")
: this.options.dependentFields;
if (!dep_fields) return;
var form = inputElement.form;
var name_parts = inputElement.name.split(/\./);
for (var k in dep_fields) {
name_parts[name_parts.length - 1] = k;
var related_name = name_parts.join('.');
var related_field = form[related_name];
var value_in_choice = dep_fields[k];
if (related_field) {
related_field.value
= (value_in_choice == "") ? ""
: (choice === null) ? "!!ILLEGAL_" + k + "!!"
: (typeof choice == "object") ?
(choice[value_in_choice] ? choice[value_in_choice] : "")
: (typeof choice == "string") ? choice
: "!!UNEXPECTED SOURCE FOR RELATED FIELD!!";
}
}
},
// if clicking in the 20px right border of the input element, will display
// or hide the drowpdown div (like pressing ARROWDOWN or ESC)
_clickHandler: function(event) {
var x = event.offsetX || event.layerX; // MSIE || FIREFOX
if (x > Element.getDimensions(this.inputElement).width - 20) {
if ( this.dropdownDiv ) {
this._removeDropdownDiv();
Event.stop(event);
}
else
this._ArrowDownHandler(event);
}
},
_ArrowDownHandler: function(event) {
var value = this._getValueToComplete();
var valueLength = (value || "").length;
if (valueLength < this.options.minimumChars)
this.displayMessage("liste de choix à partir de "
+ this.options.minimumChars + " caractères");
else
this._displayChoices();
Event.stop(event);
},
lib/Alien/GvaScript/lib/GvaScript.js view on Meta::CPAN
// browser behaviour can update the value; then come back through a
// timeout to update the Autocompleter
},
_checkNewValue: function() {
// abort if the timeout occurs after a blur (no input element)
if (!this.inputElement) {
// if (window.console) console.log('_checkNewValue ... no input elem');
return;
}
// several calls to this function may be queued by setTimeout,
// so we perform some checks to avoid doing the work twice
if (this._timeLastCheck > this._timeLastKeyDown) {
// if (window.console) console.log('_checkNewValue ... done already ',
// this._timeLastCheck, this._timeLastKeyDown);
return; // the work was done already
}
var now = (new Date()).getTime();
var deltaTime = now - this._timeLastKeyDown;
if (deltaTime + this.options.deltaTime_tolerance
< this.options.checkNewValDelay) {
// if (window.console) console.log('_checkNewValue ... too young ',
// now, this._timeLastKeyDown);
return; // too young, let olders do the work
}
this._timeLastCheck = now;
var value = this._getValueToComplete();
// if (window.console)
// console.log('_checkNewValue ... real work [value = %o] - [lastValue = %o] ',
// value, this.lastValue);
this.lastValue = this.lastTypedValue = value;
// create a list of choices if we have enough chars
if (value.length >= this.options.minimumChars) {
// first create a "continuation function"
var continuation = function (choices) {
// if, meanwhile, another keyDown occurred, then abort
if (this._timeLastKeyDown > this._timeLastCheck) {
// if (window.console)
// console.log('after updateChoices .. abort because of keyDown',
// now, this._timeLastKeyDown);
return;
}
this.choices = choices;
if (choices && choices.length > 0) {
this.inputElement.style.backgroundColor = ""; // remove colorIllegal
if (this.options.autoSuggest)
this._displayChoices();
}
else if (this.options.strict && (!this.options.blankOK)) {
this.inputElement.style.backgroundColor = this.options.colorIllegal;
}
};
// now call updateChoices (which then will call the continuation)
this._updateChoices(continuation.bind(this));
}
},
// return the value to be completed
// TODO : for multivalued, should return the value under the cursor,
// instead returning sytematically the last value
_getValueToComplete : function(value) {
// NOTE: the explicit value as argument is only used from
//_fireFinalStatus(), when we can no longer rely on
// this.inputElement.value
value = value || this.inputElement.value;
if (this.options.multivalued) {
var vals = value.split(this.options.multivalue_separator);
value = vals[vals.length-1];
}
return value;
},
_setValue : function(value, inputElement) {
// NOTE: the explicit inputElement as argument is only used from
// _fireFinalStatus(), when we can no longer rely on this.inputElement
// default inputElement is the one bound to this autocompleter
if (!inputElement) inputElement = this.inputElement;
// if multivalued, the completed value replaces the last one in the list
if (this.options.multivalued) {
var _sep = inputElement.value.match(this.options.multivalue_separator);
if (_sep) {
var vals = inputElement.value.split(this.options.multivalue_separator);
vals[vals.length-1] = value;
value = vals.join(_sep[0]); // join all vals with first separator found
}
}
// setting value in input field
inputElement.value = this.lastValue = value;
},
_typeAhead : function () {
var curLen = this.lastTypedValue.length;
var index = this.choiceList.currentHighlightedIndex;
var suggestion = this._valueFromChoice(index);
var newLen = suggestion.length;
this._setValue(suggestion);
if (this.inputElement.createTextRange){ // MSIE
var range = this.inputElement.createTextRange();
range.moveStart("character", curLen); // no need to moveEnd
range.select(); // will call focus();
}
else if (this.inputElement.setSelectionRange){ // Mozilla
this.inputElement.setSelectionRange(curLen, newLen);
}
},
//----------------------------------------------------------------------
// methods for the dropdown list of choices
//----------------------------------------------------------------------
_mkDropdownDiv : function() {
this._removeDropdownDiv();
// the autocompleter has been blurred ->
// do not display the div
if(!this.inputElement) return null;
// if observed element for scroll, reposition
var movedUpBy = 0;
var movedLeftBy = 0;
if (this.observed_scroll) {
movedUpBy = this.observed_scroll.scrollTop;
movedLeftBy = this.observed_scroll.scrollLeft;
}
// create div
var div = new Element('div');
div.className = this.classes.dropdown;
// positioning
var coords = Position.cumulativeOffset(this.inputElement);
var dim = Element.getDimensions(this.inputElement);
div.style.left = coords[0] + this.options.offsetX - movedLeftBy + "px";
div.style.top = coords[1] + dim.height -movedUpBy + "px";
div.style.maxHeight = this.options.maxHeight + "px";
div.style.minWidth = this.options.minWidth + "px";
div.style.zIndex = 32767; //Seems to be the highest valid value
// insert into DOM
document.body.appendChild(div);
// simulate minWidth on old MSIE (must be AFTER appendChild())
// maxHeight cannot be simulated untill displayChoices
if (navigator.userAgent.match(/\bMSIE [456]\b/)) {
div.style.width = this.options.minWidth + "px";
}
// mouseenter and mouseleave events to control
// whether autocompleter has been blurred
var elem = this.inputElement;
div.observe('mouseenter', function(e) {
Element.stopObserving(elem, "blur", this.reuse.onblur);
}.bind(this));
div.observe('mouseleave', function(e) {
Element.observe(elem, "blur", this.reuse.onblur);
}.bind(this));
return this.dropdownDiv = div;
},
_displayChoices: function() {
// if no choices are ready, can't display anything
if (!this.choices) return;
var toCompleteVal = this._getValueToComplete();
if (this.choices.length > 0) {
var ac = this;
// create a choiceList
var cl = this.choiceList = new GvaScript.ChoiceList(this.choices, {
labelField : this.options.labelField,
scrollCount : this.options.scrollCount,
choiceItemTagName : this.options.choiceItemTagName,
htmlWrapper : this.options.htmlWrapper
});
cl.currentHighlightedIndex = ac._idx_to_hilite;
// TODO: explain and publish method "choiceElementHTML", or redesign
// and make it a private method
if ( this.choiceElementHTML ) {
cl.choiceElementHTML = this.choiceElementHTML;
}
cl.onHighlight = function(event) {
if (ac.options.typeAhead)
ac._typeAhead();
ac.fireEvent(event, ac.inputElement);
};
cl.onPing = function(event) {
ac._completeFromChoiceElem(event.target);
};
cl.onCancel = function(event) {
ac._removeDropdownDiv();
};
// append div to DOM
var choices_div = this._mkDropdownDiv();
// fill div now so that the keymap gets initialized
cl.fillContainer(choices_div);
// set height of div for IE6 (no suppport for maxHeight!)
if (navigator.userAgent.match(/\bMSIE [456]\b/)) {
choices_div.style.height =
(choices_div.scrollHeight > this.options.maxHeight)?
this.options.maxHeight + 'px' :
'auto';
}
// determine if there is a space to dislay
// the choices list under the input
// if not, display above.
// onscreen height needed for displaying the choices list
var _h_needed = Element.viewportOffset(this.inputElement)[1]
+ this.inputElement.offsetHeight
+ choices_div.offsetHeight;
var _h_avail = document.viewport.getHeight();
// move choices list on top of the input element
if(_h_needed >= _h_avail) {
var div_top = choices_div.offsetTop
- choices_div.offsetHeight
- this.inputElement.offsetHeight;
if (div_top >= 0)
choices_div.style.top = div_top + 'px';
}
// catch keypress on TAB while choiceList has focus
cl.keymap.rules[0].TAB = cl.keymap.rules[0].S_TAB = function(event) {
var index = cl.currentHighlightedIndex;
if (index != undefined) {
var elem = cl._choiceElem(index);
// generate a "Ping" on the choiceList, like if user had
// pressed RETURN to select the current highlighted item
cl.fireEvent({type : "Ping",
index: index}, elem, cl.container);
// NO Event.stop() here, because the navigator should
// do the tabbing (pass focus to next/previous element)
}
};
// more key handlers when the suggestion list is displayed
this.keymap.rules.push(cl.keymap.rules[0]);
}
else
this.displayMessage("pas de suggestion");
},
_removeDropdownDiv: function() {
// remove the dropdownDiv that was added previously by _mkDropdownDiv();
// that div contained either a menu of choices or a message to the user
if (this.dropdownDiv) {
// remove mouseenter and mouseleave observers
this.dropdownDiv.stopObserving();
Element.remove(this.dropdownDiv);
this.dropdownDiv = null;
}
// if applicable, also remove rules previously pushed by _displayChoices
if (this.keymap.rules.length > 1)
this.keymap.rules.pop();
},
_valueFromChoice: function(index) {
if (!this.choices) return null;
var choice = this.choices[index];
return (choice !== null) ? this._valueFromChoiceItem(choice) : null;
},
_valueFromChoiceItem: function(choice) {
return (typeof choice == "string") ? choice
: choice[this.options.valueField];
},
//triggered by the onPing event on the choicelist, i.e. when the user selects
//one of the choices in the list
_completeFromChoiceElem: function(elem) {
// identify the selected line and handle it
var num = parseInt(elem.id.match(/\.(\d+)$/)[1], 10);
// add the value to the input element
var value = this._valueFromChoice(num);
if (value !== null) {
this._setValue(value)
this._removeDropdownDiv();
// ADDED LEMOINEJ 26.09.13
this._timeLastCheck = this._timeLastKeyDown = 0;
this._checkNewValue();
if (!this.options.multivalued) {
this.inputElement.select();
}
this._updateDependentFields(this.inputElement, this.choices[num]);
// fire events: "Complete" for backwards compatibility, "LegalValue"
// for regular use
var eventNames = ["Complete", "LegalValue"];
// for loop : can't use .each() from prototype.js because it alters "this"
for (var i = 0; i < eventNames.length; i++) {
this.fireEvent({
type : eventNames[i],
referrer : "select", // choice selection fired this event
index : num,
choice : this.choices[num],
controller: {choices: this.choices}
}, elem, this.inputElement);
}
}
}
}
//----------customButtons.js
// depends: keyMap.js
GvaScript.CustomButtons = {};
GvaScript.CustomButtons.Button = Class.create();
// Renders Buttons in the following HTML structure
// <span class="gva-btn-container">
// <span class="left"/>
// <span class="center">
// <button class="btn" style="width: auto;" id="btn_1227001526005">
// Créer
// </button>
// </span>
// <span class="right"/>
// </span>
Object.extend(GvaScript.CustomButtons.Button.prototype, function() {
var bcss = CSSPREFIX();
function _extendCss(button_options) {
// basic class
var button_css = bcss+'-btn-container';
// extended classes
switch (typeof button_options.css) {
case 'object': button_css += (' ' + button_options.css.join(' ')); break;
case 'string': button_css += (' ' + button_options.css); break;
default: break;
}
button_options.button_css = button_css;
}
var _button_template = new Template(
'<span class="#{button_css}" id="#{id}">'
+ '<span class="left"></span>'
+ '<span class="center">'
+ '<button type="#{type}" style="width:#{width}" '
+ ' class="btn">#{label}'
+ '</button>'
+ '</span>'
+ '<span class="right"></span>'
+ '</span>'
);
function _render(button_options) {
_extendCss(button_options);
return _button_template.evaluate(button_options);
}
function _evalCondition(button_condition) {
if(typeof button_condition == 'function') return button_condition();
else
if(eval(button_condition)) return true;
else return false;
}
return {
destroy: function() {
// test that element still in DOM
if(this.btnElt) this.btnElt.stopObserving('click');
},
initialize: function(container, options) {
var defaults = {
id: 'btn_' + (new Date()).getTime(),
callback: Prototype.emptyFunction,
condition: true,
width: 'auto',
type: 'button',
label: 'GVA_SCRIPT_BUTTON'
};
this.options = Object.extend(defaults, options || {});
if(_evalCondition(this.options.condition)) {
try {
this.container = $(container);
this.container.insert(_render(this.options));
this.btnContainer = $(this.options.id); // the outer <span/>
this.btnElt = this.btnContainer.down('.btn'); // the <button/>
// setting inline style on the button container
if(typeof this.options.style != 'undefined') {
this.btnContainer.setStyle(this.options.style);
}
// setting tabindex on button if any
if(typeof this.options.tabindex != 'undefined') {
this.btnElt.writeAttribute('tabindex', this.options.tabindex);
}
this.btnElt.observe('click', this.options.callback.bind(this.btnElt));
} catch (e) {}
}
}
}
}());
GvaScript.CustomButtons.ButtonNavigation = Class.create();
Object.extend(GvaScript.CustomButtons.ButtonNavigation.prototype, function() {
// private members
var bcss = CSSPREFIX();
function _leftHandler(event) {
var selectedBtn = this.selectedBtn;
if (selectedBtn) {
var nextBtn = this.previousBtn(selectedBtn);
if (nextBtn) this.select(nextBtn);
else selectedBtn.flash();
Event.stop(event);
}
}
function _rightHandler(event) {
var selectedBtn = this.selectedBtn;
if (selectedBtn) {
var prevBtn = this.nextBtn(selectedBtn);
if (prevBtn) this.select(prevBtn);
else selectedBtn.flash();
Event.stop(event);
}
}
function _tabHandler(event) {
if (this.options.preventListBlur)
if (this.isLast(this.selectedBtn))
Event.stop(event);
}
function _shiftTabHandler(event) {
if (this.options.preventListBlur)
if (this.isFirst(this.selectedBtn))
Event.stop(event);
}
function _homeHandler(event) {
if (this.selectedBtn) {
this.select(this.firstBtn());
Event.stop(event);
}
}
function _endHandler(event) {
if (this.selectedBtn) {
this.select(this.lastBtn());
Event.stop(event);
}
}
function _addHandlers() {
this.buttons.each(function(btnContainer) {
var btn;
// if the button is a GvaScript.CustomButtons.BUTTON, then the actual <button> element
// will be embedded and selectable via .btn classname:
// <span class="gva-btn-container">
// <span class="left"/>
// <span class="center">
// <button accesskey="r" class="btn" style="width: auto;" id="btn_1226916357164">
// Rechercher dans Calvin
// </button>
// </span>
// <span class="right"/>
// </span>
// this will be cleaner when all application buttons are transformed into
// GvaScript.CustomButtons.Button instances
if(btnContainer.tagName.search(/^(INPUT|BUTTON)$/i) > -1) btn = btnContainer;
else {
btn = btnContainer.down('.btn');
btn.visible = function() {return btnContainer.visible();}
// support focus function on span.buttonContainer
btnContainer.focus = function() {btn.focus();}
}
if(typeof btn == 'undefined') return;
}, this);
this.container.register('button.btn', 'focus', function(e) {
this.select.call(this, e._target.up('.'+bcss+'-btn-container'));
}.bind(this));
this.container.register('button.btn', 'blur', function(e) {
this.select.call(this, null);
}.bind(this));
}
// public members
return {
destroy: function() {
// test that element still in DOM
if(this.container) this.container.unregister();
this.keymap.destroy();
},
initialize: function(container, options) {
var defaults = {
preventListBlur : false,
flashDuration : 100, // milliseconds
flashClassName : 'flash',
keymap : null,
selectFirstBtn : true,
className : bcss+'-button'
};
this.options = Object.extend(defaults, options || {});
this.container = $(container);
// initializing the keymap
var keyHandlers = {
LEFT: _leftHandler .bindAsEventListener(this),
RIGHT: _rightHandler .bindAsEventListener(this),
TAB: _tabHandler .bindAsEventListener(this),
S_TAB: _shiftTabHandler .bindAsEventListener(this),
HOME: _homeHandler .bindAsEventListener(this),
END: _endHandler .bindAsEventListener(this)
};
this.keymap = new GvaScript.KeyMap(keyHandlers);
this.keymap.observe("keydown", container, {
preventDefault:false,
stopPropagation:false
});
lib/Alien/GvaScript/lib/GvaScript.js view on Meta::CPAN
this.back.removeClassName('inactive');
this.first.removeClassName('inactive');
}
else {
this.back.addClassName('inactive');
this.first.addClassName('inactive');
}
if(this.hasNext()) {
this.forward.removeClassName('inactive');
this.last.removeClassName('inactive');
}
else {
this.forward.addClassName('inactive');
this.last.addClassName('inactive');
}
this.links_container.show();
}
/* Create pagination controls and append them to the placeholder 'PG:frame' */
function _addPaginationElts() {
// append the pagination buttons
this.links_container.insert(pagination_buttons);
this.first = this.links_container.down('.first');
this.last = this.links_container.down('.last');
this.forward = this.links_container.down('.forward');
this.back = this.links_container.down('.back');
this.textElem = this.links_container.down('.text');
this.first.observe ('click', this.getFirstPage.bind(this));
this.last.observe ('click', this.getLastPage.bind(this));
this.back.observe ('click', this.getPrevPage.bind(this));
this.forward.observe('click', this.getNextPage.bind(this));
}
return {
destroy: function() {
this.first.stopObserving();
this.last.stopObserving();
this.back.stopObserving();
this.forward.stopObserving();
},
initialize: function(url, options) {
var defaults = {
reset : 'no', // if yes, first call sends RESET=yes,
// subsequent calls don't (useful for
// resetting cache upon first request)
step : 20,
method : 'post', // POST so we get dispatched to *_PROCESS_FORM
parameters : $H({}),
onSuccess : Prototype.emptyFunction,
lazy : false, // false: load first page with Paginator initialization
// true: donot load automatically, loadContent would
// have to be called explicity
timeoutAjax : 15,
errorMsg : "Problème de connexion. Réessayer et si le problème persiste, contacter un administrateur."
};
this.options = Object.extend(defaults, options || {});
this.options.errorMsg = "<h3 style='color: #183E6C'>" + this.options.errorMsg + "</h3>";
this.links_container = $(this.options.links_container);
this.list_container = $(this.options.list_container);
this.url = url;
// initialization of flags
this.index = 1;
this.end_index = 0;
this.total = 0;
this._executing = false; // loadContent one at a time
// set the css for the paginator container
this.links_container.addClassName(paginator_css);
// and hide it
this.links_container.hide();
// add the pagination elements (next/prev links + text)
_addPaginationElts.apply(this);
this.links_container.addClassName(bcss+'-widget');
this.links_container.store('widget', this);
// load content by XHR
if(!this.options.lazy) this.loadContent();
},
hasPrevious: function() {
return this.index != 1;
},
hasNext: function() {
return this.end_index != this.total;
},
/* Get the next set of index to 1records from the current url */
getNextPage: function(btn) {
if(this._executing == false && this.hasNext()) {
this.index += this.options.step;
this.loadContent();
return true;
}
else
return false;
},
/* Get the prev set of records from the current url */
getPrevPage: function() {
if(this._executing == false && this.hasPrevious()) {
this.index -= this.options.step;
this.loadContent();
return true;
}
else
return false;
},
getLastPage: function() {
if(this._executing == false && this.hasNext()) {
this.index = Math.floor(this.total/this.options.step)*this.options.step+1;
this.loadContent();
lib/Alien/GvaScript/lib/GvaScript.js view on Meta::CPAN
new Ajax.Request(url, {
evalJSON: 'force', // force evaluation of response into responseJSON
method: this.options.method,
parameters: this.options.parameters,
requestTimeout: this.options.timeoutAjax * 1000,
onTimeout: function(req) {
this._executing = false;
this.list_container.update(this.options.errorMsg);
}.bind(this),
// on s'attend à avoir du JSON en retour
onFailure: function(req) {
this._executing = false;
var answer = req.responseJSON;
var msg = answer.error.message || this.options.errorMsg;
this.list_container.update(msg);
}.bind(this),
onSuccess: function(req) {
this._executing = false;
var answer = req.responseJSON;
if(answer) {
var nb_displayed_records = this.options.onSuccess(answer);
this.total = answer.total; // total number of records
this.end_index = Math.min(this.total, this.index+nb_displayed_records-1); // end index of records on current page
this.textElem.innerHTML = (this.total > 0)?
this.index + " à " + this.end_index + " de " + this.total: '0';
_toggleNavigatorsVisibility.apply(this);
}
}.bind(this)
});
}
}
}());
//----------grid.js
// depends: custom-buttons.js
// paginator.js
// choiceList.js
GvaScript.Grid = Class.create();
Object.extend(GvaScript.Grid.prototype, function() {
var bcss = CSSPREFIX();
function _compileDTO(dto) {
switch(typeof dto) {
case 'object': return $H(dto).update({VUE: 'JSON'});
case 'string': return $H(dto.toQueryParams()).update({VUE: 'JSON'});
default: return {VUE: 'JSON'};
}
}
function _compileCss(column) {
switch (typeof column.css) {
case 'object': return ' '+column.css.join(' ');
case 'string': return ' '+column.css;
default: return '';
}
}
function _compileWidth(column) {
switch (typeof column.width) {
case 'number': return ' style="width: '+column.width+'px"';
case 'string':
if(isNaN(column.width)) return ' style="width: '+column.width+'"';
else return ' style="width: '+column.width+'px"';
default: return '';
}
}
function _compileTitle(column) {
switch (typeof column.title) {
case 'string': return 'title= '+'"'+column.title+'"';
default: return '';
}
}
function _evalCondition(column, grid) {
if(typeof column.condition == 'undefined') return true;
else
if(typeof column.condition == 'function') return column.condition(grid);
else
if(eval(column.condition)) return true;
else return false;
}
function _getColumnValue(column, elt) {
switch(typeof column.value) {
case 'function' : if(val = column.value(elt)) return val; else return (column.default_value || '');
case 'string' : if(val = elt[column.value]) return val; else return (column.default_value || '');
default: return '';
}
}
return {
destroy: function() {
// do not destroy if not initialized !
if(GvaScript.Grids.unregister(this.id)) {
if(this.choiceList) this.choiceList.destroy();
if(this.actionButtons) this.actionButtons.destroy();
}
},
initialize: function(id, datasource, options) {
var defaults = {
css : '',
dto : {},
columns : [],
actions : [],
grabfocus : true,
pagesize : 'auto', // fill available grid height
gridheight : 'auto', // available space
recordheight : 21, // default record height in pixels
requestTimeout : 15,
method : 'post', // default XHR method
errorMsg : "Problème de connexion. Réessayer et si le problème persiste, contacter un administrateur.",
onShow : Prototype.emptyFunction,
onPing : Prototype.emptyFunction,
onEmpty : Prototype.emptyFunction,
onCancel : Prototype.emptyFunction
}
this.options = Object.extend(defaults, options || {});
this.id = id;
this.grid_container = $(this.options.grid_container);
this.toolbar_container = $(this.options.toolbar_container);
this.columns = this.options.columns;
this.datasource = datasource;
// determine pagesize to send to paginator
( run in 0.375 second using v1.01-cache-2.11-cpan-119454b85a5 )