Alien-GvaScript
view release on metacpan or search on metacpan
src/autoCompleter.js view on Meta::CPAN
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));
},
_updateChoicesFromJSONP : function(val_to_complete, continuation) {
if(val_to_complete) {
var _url = this._datasource.json_url.replace(/\?1/, val_to_complete).replace(/\?2/, '?');
var that = this;
Element.addClassName(that.inputElement, that.classes.loading);
Prototype.getJSON(_url, function(data) {
var _data_list = data;
if(that._datasource.json_list)
that._datasource.json_list.split('/').each(function(p) {
_data_list = _data_list[p];
});
Element.removeClassName(that.inputElement, that.classes.loading);
continuation(_data_list);
});
}
},
src/autoCompleter.js view on Meta::CPAN
// 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;
( run in 0.358 second using v1.01-cache-2.11-cpan-acebb50784d )