Alien-GvaScript
view release on metacpan or search on metacpan
src/autoCompleter.js view on Meta::CPAN
// 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));
},
_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);
});
}
},
_updateChoicesFromArray : function(val_to_complete, continuation) {
if (this.options.ignorePrefix) {
// store the index of the initial value
if (val_to_complete) {
this._idx_to_hilite = (val_to_complete == ''? 0 : -1);
$A(this._datasource).each(function(choice, index) {
switch(typeof choice) {
case "object" : value = choice[this.options.valueField]; break;
case "number" : value = choice.toString(10); break;
case "string" : value = choice; break;
default: throw new Error("unexpected type of value");
}
if(value.toLowerCase().startsWith(val_to_complete.toLowerCase())) {
this._idx_to_hilite = index;
throw $break;
}
}, this);
}
continuation(this._datasource);
}
else {
var regex = new RegExp("^" + RegExp.escape(val_to_complete),
this.options.caseSensitive ? "" : "i");
var matchPrefix = function(choice) {
var value;
switch(typeof choice) {
case "object" : value = choice[this.options.valueField]; break;
case "number" : value = choice.toString(10); break;
case "string" : value = choice; break;
default: throw new Error("unexpected type of value");
}
return value.search(regex) > -1;
};
continuation(this._datasource.select(matchPrefix.bind(this)));
}
},
_updateChoices : function (continuation) {
var value = this._getValueToComplete();
// 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, "");
( run in 1.042 second using v1.01-cache-2.11-cpan-f5b5a18a01a )