Files
Facilitor/APPL/Shared/Suggest/suggest.js
Jos Groot Lipman 9b402a03be DLLG#90434 Probleem met werkplekreserveringen en persoonselectie via plattegrond
svn path=/Website/branches/v2025.3/; revision=70657
2025-10-20 08:32:10 +00:00

1369 lines
59 KiB
JavaScript
Raw Blame History

/*
$Revision$
$Id$
File: Suggest.js
Description:
Parameters: params.objectName,
params.queryField,
params.queryUrl,
params.initKey,
params.initExtraParam,
params.keyField,
params.fieldReadonly,
params.urlAdd,
params.extraParamField,
params.isBad,
params.highlightDescript,
params.noJustOne,
params.suppressJustOne
params.JSONP
params.multitoggle (true|false voor alle, of [0-6] voor plaatsselector, t/m alg_level #multitoggle
params.addfixedoption Voegt een vaste optie toe, meegegeven als {key, txt, desc}
params.embedded Kijk nooit naar het parent document (embedded)
Context:
Note: Pas op met gebruiken functies uit andere modules. Dit bestand
wordt ook bij vinder/vanuit API\phonebook_js.asp gebruikt en dan
heb je die andere bestanden niet.
*/
var suggesttimer;
function Suggest(params) {
_Suggest.call(this, params);
}
async function _Suggest(inParams) {
// Genereer een enkel stukje busy-html die voor alle suggests in deze pagina hergebruiken
var params = inParams;
var isMention = params.sgType === "mention9999";
var storeKeyField; // = inStoreKeyField; // use function withKeyField() to assign field
var storeExtraParamField; // = instoreExtraParamField; // use function withExtraParamField() to assign field
var _completeDiv = null;
var _comboDiv = null;
// thisdoc.onclick = function(){debugger;};
// Kopie uit FcltJquery.js. Die hebben we niet vanuit API\phonebook_js.asp
var myEncode = function(s) {
return unescape(encodeURIComponent(escape(s))).replace(/\+/g, "%2B");
}
var suggestionValues = [];
var resultsObj;
var selected = -1;
var latestServerQuery = "";
var THROTTLE_PERIOD = 250;
var timerID = null;
var lastHighlight = null;
var divWidth = 500;
var isMobile = ("mobile" in params) ? params.mobile : (typeof mobile != "undefined");
/* when mobile divWidth is too large for the view */
if (isMobile) {
divWidth = 0;
}
var doAction = true;
var emptyKey = ("emptyKey" in params) ? params.emptyKey : -1;
var emptyText = "";
if (params.extraParamValue)
{
this.extraParamValueEmpty = {}; // De parameter bevat het extraParamValue object voor een lege suggest waarde. Alle parameters zijn daarin op een lege string gezet.
var extraPV = params.extraParamValue.split(",");
for (var i = 0; i < extraPV.length; i++)
{
this.extraParamValueEmpty[extraPV[i].replace(/^\s+|\s+$/g,"")] = ""; // Replace is for trim spaces.
}
}
var currentKey = -1;
var currentText = null;
var currentExtraParam = null;
var $currentField = $(params.queryField); // Either the INPUT or the SELECT field
const createPromise = () => {
let resolver;
return [
new Promise((resolve) => {
resolver = resolve;
}).then(() => {
_sgReady = true;
}),
resolver
];
};
var _sgReady = false;
const [ sgReadyState, sgReadyStateResolver ] = createPromise();
// De this. functies zijn zo extern ook beschikbaar
this.sgReadyState = sgReadyState;
this.makeReadOnly = makeReadOnly;
this.undoReadOnly = undoReadOnly;
this.isReadOnly = isReadOnly;
this.makeHidden = makeHidden;
this.undoHidden = undoHidden;
this.isHidden = isHidden;
this.getKeyField = getKeyField;
this.getValue = getValue;
this.setValue = setValue;
this.sgType = params.sgType;
this.isMulti = isMulti;
this.toggleSelect = toggleSelect;
this.updateMultiSuggest = updateMultiSuggest;
this.CheckJustOne = CheckJustOne;
this.reloadUrlAdd = reloadUrlAdd;
this.editUrlAdd = editUrlAdd;
this.changeQueryUrl = changeQueryUrl;
this.sendQuery = sendQuery;
thisdoc = document; // Hier wordt de AutocompleteDiv aan gehangen
function updateMultiSuggest() {
// Niet mooi, wel effectief
toggleSelect();
toggleSelect();
}
function isMulti() {
return $currentField.prop("tagName") == "SELECT";
}
function getKeyField() {
return params.keyField;
}
function multiToggle($fld, adv) {
$fld.addClass(adv ? "advMultiSuggest" : "multiSuggest");
var $lbl = $("<span fcltfor='" + $fld.attr("id") + "' class='multi_suggest_toggle'></span>")
.on("click", async function(e, resolve) {
await toggleSelect(this);
if (typeof resolve === "function") {
resolve();
}
}).html(I("fa-ellipsis"));
var $div = $("<div></div>").addClass(adv ? "advmultitoggle" : "multitoggle");
$fld.add($fld.next(".suggestklikker")).wrapAll($div);
$fld.before($lbl);
}
// TODO: Controleren of parent wel in hetzelfde domein zit?
if (!params.embedded && self != top && window.name != "fclttop" && document.body.id != "searchbody") {
thisdoc = parent.document; // We gaan de AutocompleteDiv aan de parent hangen, uit het frame breken
// Mogelijke fix voor PNBR#22301
if (FcltMgr._pageManager.name == 'defaultManager' && parent.window.name != "fclttop" && parent.FcltMgr && !parent.FcltMgr.IsTheManager)
thisdoc = parent.parent.document; // Nog eentje hoger
if (!window.name || window.name == "") {
// FcltMgr.alert("Internal error. " + document.referrer + " heeft een IFRAME zonder 'name' en 'id' voor " + window.location.pathname);
thisdoc = document;
//debugger;
}
/* Sommige mobile/3G proxies embedden de CSS 'netjes' zodat het bestand niet te vinden is
var cssfound = false;
for (i = 0; i < thisdoc.styleSheets.length; i++)
{
try
{ // TODO faalt op FF?
if (thisdoc.styleSheets[i].href.match(/suggest.css/i))
cssfound = true;
}
catch(e){};
}
if (!cssfound)
{
FcltMgr.alert("Internal error. " + document.referrer + " moet suggest.css ook includen!");
// debugger;
}
*/
}
var icon = params.icon || "fa-asterisk";
if (params.embedded && params.site) {
suggesticon = params.suggesticon || (params.site + "/appl/shared/suggest/suggest.png");
var $klikker = $("<div class='suggestklikker' style='cursor:pointer'><img alt='" + L("mgt_srtkenmerk_referentie_s") + "' src='" + suggesticon + "'></div>");
} else
var $klikker = $("<div class='suggestklikker'>" + I(icon + " suggestklikker") + "</div>");
$(params.queryField).after($klikker);
params.queryField.setAttribute("sgKey", params.initKey);
if (params.multitoggle)
multiToggle($(params.queryField), params.multitoggle == "advanced");
if (params.keyField) {
storeKeyField = params.keyField;
//storeKeyField.value = params.queryField.getAttribute("sgKey");
storeKeyField.value = params.keyField.value;
} else
this.withKeyField = function(inStoreKeyField) {
storeKeyField = inStoreKeyField;
//storeKeyField.value = params.queryField.getAttribute("sgKey");
storeKeyField.value = params.keyField.value;
return this;
}
if (params.extraParamField) {
storeExtraParamField = params.extraParamField;
if (params.queryField.hasAttribute("sgExtraParam"))
storeExtraParamField.value = params.queryField.getAttribute("sgExtraParam");
} else
this.withExtraParamField = function(instoreExtraParamField) {
storeExtraParamField = instoreExtraParamField;
if (params.queryField.hasAttribute("sgExtraParam"))
storeExtraParamField.value = params.queryField.getAttribute("sgExtraParam");
return this;
}
// Kan verwijderd worden. Kan ook bereikt worden door initi<74>le waarde -1 mee te geven
this.withEmpty = function(eKey, eText) {
emptyText = eText ? eText : "";
emptyKey = eKey;
return this;
}
// Niet extern bedoeld maar noodzakekelijk voor setTimeout
this.requestLoop = requestLoop;
//if (params.objectName == "sgPerson") FcltMgr.alert("initKey = " + params.initKey);
//if (params.initKey == -1) FcltMgr.alert(params.objectName + " " + params.initKey);
// Alleen als verplicht
if ((params.initKey == -1 || params.suppressJustOne) && !params.noJustOne && $(params.queryField).hasClass("required"))
await CheckJustOne();
if (params.fieldReadonly) {
params.queryField.readOnly = true;
setClass("suggestReadOnly");
} else
startup();
if (params.isBad)
{
setValue(emptyKey, null, true, false, emptyText, false, this.extraParamValueEmpty);
setClass("suggestBad");
} else
this.isBad = function()
{
setValue(emptyKey, null, true, false, emptyText, false, this.extraParamValueEmpty);
setClass("suggestBad");
}
// Geavanceerd scherm waarvan een suggest geladen wordt met meerdere waarden automatisch uitklappen,
// indien maar 1 waarde aanwezig, dan met setValue de sgKey en sgCurrentvalue setten.
if (params.multitoggle == "advanced") {
var storedVars = $(params.queryField).val().split(",");
if (storedVars.length == 1 && storedVars[0] != "")
setValue(params.keyField.value, storedVars[0]);
else if (storedVars.length > 1 && params.keyField.value == storedVars)
toggleSelect();
}
/**
*
* It all starts here!
*
*/
function startup() {
createAutocompletDiv();
hideAutocompleteDiv();
params.queryField.autocomplete = "off";
params.queryField.title = L("lcl_shared_suggest_hint");
params.queryField.onkeydown = keypressHandler;
params.queryField.onkeyup = keyupHandler;
params.queryField.onblur = function() {
if (document.activeElement &&
typeof thisdoc.activeElement != "unknown" &&
(document.activeElement == params.queryField ||
thisdoc.activeElement == _completeDiv ||
document.activeElement == _comboDiv ||
document.activeElement == $klikker[0] ||
$("body").hasClass("fclt-modal") || // Zou anders in IE9 sluiten bij klikken op scrollbar
thisdoc.activeElement.parentElement == _completeDiv))
return;
if (isAutocompleteDivVisible())
{
if (params.queryField.getAttribute("sgCurrentValue") == null)
setValues(true);
else // Houden we de huidige waarde
setValue(params.queryField.getAttribute("sgKey"),
params.queryField.getAttribute("sgCurrentValue"), false, false,
params.queryField.getAttribute("sgExtraParam"));
hideAutocompleteDiv();
}
};
// http://stackoverflow.com/questions/3380458/looking-for-a-better-workaround-to-chrome-select-on-focus-bug
$(params.queryField).on("focus", () => {
$(params.queryField).trigger("select").on("mouseup", e => {
e.preventDefault();
$(this).unbind("mouseup");
});
if (!timerID)
timerID = setTimeout(params.objectName + '.requestLoop(-1);', THROTTLE_PERIOD);
});
$klikker.click(function(e) {
if (!isReadOnly()) {
// Als je op vergrootglas hebt gedrukt moet checkExist altijd false zijn want je wilt een lijst.
// Anders krijg je ook het verschijnsel dat je 2 keer moet klikken voordat je de lijst krijgt.
params.queryField.removeAttribute("checkExist");
doAction = false; // Voorkomt focus handler op dit veld
$(params.queryField).focus(); // zodat anderen door onblur verbergen
if (!isAutocompleteDivVisible()) {
autoOpen();
} else {
setValue(params.queryField.getAttribute("sgKey"),
params.queryField.getAttribute("sgCurrentValue"), false, false,
params.queryField.getAttribute("sgExtraParam"));
hideAutocompleteDiv();
}
return;
}
});
params.queryField.onmousemove = function(evt) {
if (!isReadOnly()) {
evt = evt || window.event;
var offX = evt.offsetX || evt.layerX; // layerX is FireFox
if (params.queryField.clientWidth - offX < 20) // op de 'combodiv' geklikt
params.queryField.style.cursor = "pointer";
else
params.queryField.style.cursor = "auto";
}
};
params.queryField.setAttribute("sgCurrentValue", params.queryField.defaultValue);
requestLoop(0);
}
async function toggleSelect(label) {
var $suggestField; // The suggest field, INPUT or SELECT
if (!label) // Interne call van sgXxx.toggleSelect(), use $currentField
{
$suggestField = $currentField;
label = $suggestField.prev("span.multi_suggest_toggle");
} else
$suggestField = $(label).next(".multiSuggest, .advMultiSuggest");
if ($(label).hasClass("disabled"))
return;
var isMultiSuggest = $suggestField.prop("tagName") == "SELECT";
var multiClass = $suggestField.hasClass("multiSuggest") ? "multiSuggest" : "advMultiSuggest";
// toggle label between v and ^
$(label).html(isMultiSuggest ? I("fa-ellipsis") : I("fa-angle-up"));
// toggle suggestklikker Icon
$suggestField.next(".suggestklikker").toggle();
// toggle subsequent plaatsselector levels
var sgType = $suggestField.attr("sgType");
// sgType: type Suggest, dit is het gedeelte tussen 'FCLT' en 'selector' (bijvoorbeeld plaats of stdmelding)
// params.sgRelType: Relevante Suggest types die bij een multitoggle moeten inklappen in een string gescheiden door een komma
// sgRelTypeArray: Deze zelfde relevante Suggests maar dan in een Array
var sgRel = []; // Een array van alle opvolgende Suggest-objecten die moeten inklappen bij een multitoggle (van hetzelfde sgType of met een sgType in sgRelType)
var thisSgObj = null; // Het 'togglende' element, pas als deze gevonden is gaan we (alleen onder dit element dus) relevante Suggests zoeken.
var sgRelTypeArray = [];
if (typeof params.sgRelType != "undefined") // van String naar Array
sgRelTypeArray = params.sgRelType.split(/\s*,\s*/); // Regex: komma met 0 of meerdere spaties eromheen
for (var key in window) {
if (window[key] instanceof Suggest) { // Er kunnen meerdere afhankelijke suggest velden zijn.
if (thisSgObj != null && // De 'togglende' Suggest is al gevonden
window[key].sgType && // De gevonden Suggest heeft een sgType (altijd, maar voor de zekerheid)
(window[key].sgType === sgType || // De gevonden Suggest is: (1) van hetzelfde sgType (bijvoorbeeld; alle Suggests met sgType = 'plaats')
sgRelTypeArray.indexOf(window[key].sgType) != -1)) // of (2) heeft een sgType die te vinden is in de sgRelType (gerelateerde types) van de 'togglende' Suggest
{
sgRel.push(window[key]);
}
// thisSgObj = de 'togglende' Suggest
if (window[key].getKeyField() === params.keyField) // keyField used as unique identifier
thisSgObj = window[key];
}
}
// Itereer door alle Suggest's die moeten toggelen bij deze multitoggle
for (var key in sgRel) {
if (isMultiSuggest)
sgRel[key].undoHidden();
else
sgRel[key].makeHidden();
// Alle afhankelijke multi SELECT boxen weer tonen als SUGGEST input velden als deze zichtbaar worden.
if (isMultiSuggest && sgRel[key].isMulti())
// Toggelen naar SUGGEST.
sgRel[key].toggleSelect();
// SUGGEST veld altijd leeg maken want bovenliggende veld kunnen aangepast zijn waardoor de waarden niet meer geldig kan zijn.
await sgRel[key].setValue(-1, "", false, false, null, false, this.extraParamValueEmpty);
}
if (isMultiSuggest) // Replace multi-suggest back to single-suggest with new or empty value.
{
var sgKey = $suggestField.find(":selected").eq(0).val() || -1;
var sgDesc = $suggestField.find(":selected").eq(0).text() || "";
$suggestField.replaceWith($(params.queryField));
$currentField = $(params.queryField);
var extraParam = $suggestField.find(":selected")[0].getAttribute("extra");
await thisSgObj.setValue(sgKey, sgDesc, false, false, extraParam); //setValue(key, txt, doonChange, checkExist, extraParam, lastTry, extraParamValue)
FcltMgr.resized();
}
else // if (!isMultiSuggest)
{
// Make multi-SELECT
var url = params.queryUrl + _urlAddParams(params.urlAdd) + "&SuggestAll=1&multiselect=1&k=*";
var data = await $.getJSON(url);
if (data) {
var sgKey = $currentField[0].getAttribute("sgKey");
var sgExtraParam = $currentField[0].getAttribute("sgExtraParam");
var $sel = $("<select size=\"5\" multiple=\"1\" class=\"" + multiClass + "\">").attr("id", $currentField.attr("id"))
.attr("name", params.keyField.id)
.attr("sgType", sgType);
if (params.multionchange) {
var sgonChange = $currentField[0].getAttribute("sgonChange");
$sel.attr("onchange", sgonChange + ".call(null, this.val)");
}
if (data.hasMore)
$sel.append($("<option>").attr("disabled", true)
.attr("title", L("lcl_shared_suggest_toomany_multi"))
.text(L("lcl_shared_suggest_toomany_multi")));
var $option;
if (params.addfixedoption && "key" in params.addfixedoption && "desc" in params.addfixedoption && "txt" in params.addfixedoption) { // Add fixed option to the resultset
data.result.unshift(params.addfixedoption);
}
var keys_arr = $suggestField.val().split(",");
for (var i = 0; i < data.result.length; i++) {
$option = $("<option>").attr("value", data.result[i].key)
.attr("title", data.result[i].desc)
.attr("extra", data.result[i].extra)
.text(data.result[i].txt);
if (sgKey == data.result[i].key || (keys_arr.length > 1 && $.inArray(String(data.result[i].key), keys_arr) > -1)) {
$option.attr("selected", true);
}
$sel.append($option);
}
$suggestField.replaceWith($sel);
$currentField = $sel;
if (thisSgObj)
await thisSgObj.setValue(-1, "", false, false, sgExtraParam, false, this.extraParamValueEmpty); //setValue(key, txt, doonChange, checkExist, extraParam, lastTry, extraParamValue)
FcltMgr.resized();
}
}
}
function setClass(oneClass) {
$(params.queryField).removeClass("suggest suggestBad suggestReadOnly");
$(params.queryField).addClass(oneClass);
}
function makeReadOnly() {
params.queryField.readOnly = true;
setClass("suggestReadOnly");
params.queryField.title = "";
}
function undoReadOnly() {
params.queryField.readOnly = false;
setClass("suggest");
params.queryField.title = L("lcl_shared_suggest_hint");
}
function isReadOnly() {
return params.queryField.readOnly;
}
function makeHidden() {
if (!$currentField.isHidden) {
if (!isMobile)
$currentField.parents("tr").eq(0).addClass("hidden");
else {
var $parent = $currentField.closest("div");
$parent = ($parent.parent("nobr").length ? $parent.parent("nobr") : $parent);
$parent.prevUntil("", "label[for=" + $currentField.attr("id") + "]").addBack().hide();
}
}
}
function undoHidden() {
if (!isMobile)
$currentField.parents("tr").eq(0).removeClass("hidden");
else {
var $parent = $currentField.closest("div");
$parent = ($parent.parent("nobr").length ? $parent.parent("nobr") : $parent);
$parent.prevUntil("", "label[for=" + $currentField.attr("id") + "]").addBack().show();
}
}
function isHidden() {
return (
isMobile
? $currentField.parent("div").eq(0).hasClass("hidden")
: $currentField.parents("tr").eq(0).hasClass("hidden")
);
}
function setPending(pending) {
var $icon = $(params.queryField).next().find("i.suggestklikker");
var iconClass = params.icon || "fa-asterisk";
if (pending) {
$icon.removeClass(iconClass);
$icon.addClass(getIconPlaceholder("fa-fclt-spinner"));
} else {
$icon.removeClass(getIconPlaceholder("fa-fclt-spinner"));
$icon.addClass(iconClass);
}
}
async function setValue(key, txt, doonChange, checkExist, extraParam, lastTry, extraParamValue) {
// Onthoudt de huidige waarde als je checkt of de te zetten waarde bestaat.
// Als de nieuwe waarde niet voorkomt in de query en niet kan worden gezet
// dan wordt geprobeerd om de huidige waarde weer opnieuw te zetten.
// In dat laatste geval is dan lastTry == true. Indien ook de huidige waarde niet
// meer aanwezig is in de query, dan wordt de suggestbox leeg gemaakt.
// Als alleen de nieuwe waarde moet worden geprobeerd,
// kan ook direct voor lastTry de waarde true worden meegegeven.
if (this instanceof Suggest && !_sgReady) { // Externe aanroep? Wacht dan eerst tot ik klaar ben
await sgReadyState;
}
if (checkExist && !lastTry) {
currentKey = params.queryField.getAttribute("sgKey");
currentText = params.queryField.value;
currentExtraParam = params.queryField.getAttribute("sgExtraParam");
}
if (params.queryField) {
// De suggest class toont het vergrootglas in beeld.
if (!isReadOnly())
setClass("suggest");
params.queryField.setAttribute("sgKey", key);
if (storeKeyField) storeKeyField.value = key;
if (extraParam != null) // De waarde 0 moet niet als false worden opgevat.
{
params.queryField.setAttribute("sgExtraParam", extraParam);
if (storeExtraParamField) storeExtraParamField.value = extraParam;
} else {
if (storeExtraParamField) storeExtraParamField.value = ""; // Als storeExtraParamField bestaat dan leeg maken (vullen met "")
}
// use extra parameter values, if any
if (!!extraParamValue)
{
var paramValueKey;
for (paramValueKey in extraParamValue)
{
params.queryField.setAttribute(paramValueKey, extraParamValue[paramValueKey]);
}
}
if (!checkExist && txt != null) {
params.queryField.value = txt;
params.queryField.setAttribute("sgCurrentValue", txt);
//latestServerQuery = txt.toLowerCase();
if (txt != "" &&
(document.activeElement && (typeof thisdoc.activeElement != "unknown") &&
(document.activeElement == params.queryField ||
thisdoc.activeElement == _completeDiv ||
thisdoc.activeElement == _comboDiv ||
thisdoc.activeElement.parentElement == _completeDiv
)
)
)
// selectRange zou focus stelen
// Alleen focus stelen als element al focus had (activeElement)
selectRange(0, 0);
}
// bij 'checkExist' hoeven we nu nog geen onChange te doen: die komt later nog wel
if (!checkExist && doonChange && params.queryField.getAttribute("sgonChange")) {
const onChangeStr = params.queryField.getAttribute("sgonChange");
if (onChangeStr in window && typeof window[onChangeStr] === "function") {
window[onChangeStr].call(null, key, txt, { suggestid: params.queryField.id });
}
// Update related multiSuggests (related = zelfde sgType of een sgType uit params.sgRelType)
var sgRelTypeArray = [params.sgType]; // In ieder geval die van hetzelfde sgType
if (typeof params.sgRelType != "undefined") // van String naar Array
sgRelTypeArray = params.sgRelType.split(/\s*,\s*/); // Regex: komma met 0 of meerdere spaties eromheen
for (var i = 0; i < sgRelTypeArray.length; i++) {
$(params.queryField).closest(".suggest-wrapper").nextAll(".suggest-wrapper").each(function() { // Voor elke volgende suggest rij;
// We zoeken op 'select' dus we vinden alleen de 'isMulti'
var $multiSuggestToggle = $(this).find("select.multiSuggest[sgType=\"" + sgRelTypeArray[i] + "\"]").prev("span.multi_suggest_toggle");
$multiSuggestToggle.click();
$multiSuggestToggle.click();
});
}
}
if (checkExist)
params.queryField.setAttribute("checkExist", true);
else
params.queryField.removeAttribute("checkExist");
if (doonChange)
params.queryField.setAttribute("doonChange", doonChange);
else
params.queryField.removeAttribute("doonChange");
if (checkExist) {
await sendQuery(txt, false, checkExist);
}
}
}
function getValue() {
return (params.queryField.getAttribute("sgKey"));
}
function process_one_choice_info(data, textStatus) {
if (textStatus == "success") {
// setValue(key, txt, doonChange, checkExist, extraParam, lastTry, extraParamValue)
if (data && data.result.length == 1) {
var txt = data.result[0].txt;
var key = data.result[0].key;
var extraParam = data.result[0].extra;
setValue(key, txt, true, false, extraParam);
if (params.suppressJustOne)
makeHidden();
}
// initiele waarden worden met initkey gezet
//else
//setValue(emptyKey, emptyText, true, false, emptyText); // Er zijn geen waarden. Suggestbox leeg maken.
} else
FcltMgr.alert("process_one_choice_info: " + textStatus);
}
// Een urlAdd kan zijn meegegeven als val, field of jqfield
function _urlAddParams(urlAdd) {
if (!urlAdd)
return "";
var urlAddParams = "";
for (var i = 0; i < urlAdd.length; i++) { // Url parameter aan link toevoegen
urlAddParams += "&" + urlAdd[i].urlParam + "=";
var theVal = urlAdd[i].val;
if (typeof theVal == "undefined") {
var selector = urlAdd[i].jqfield;
var hasselector = "";
if (!selector || selector == "") // JQuery selector, handig voor radio
{
selector = "#" + urlAdd[i].field;
hasselector = "#has_" + urlAdd[i].field;
}
// Is het misschien een checkbox? Dan is de waarde niet belangrijk maar of deze is aangevinkt.
if (hasselector != "" && $(hasselector).length > 0) { // Het is een checkbox. Controleer of de checkbox is aangevinkt.
theVal = $(selector).prop("checked") ? 1 : 0; // Wel (1) of niet (0) aangevinkt.
} else
theVal = $(selector).val() ? $(selector).val() : -1; // Indien niets geselecteerd dan -1;
}
urlAddParams += theVal;
}
return urlAddParams;
}
async function CheckJustOne() {
var isMultiSuggest = $currentField.prop("tagName") == "SELECT";
if (!isMultiSuggest) {
var url = params.queryUrl + _urlAddParams(params.urlAdd) + "&k=*";
// eerste 10 is m<><6D>r dan genoeg url += "&SuggestAll=1&";
await $.getJSON(url, process_one_choice_info);
}
}
function reloadUrlAdd(newUrlAdd) {
params.urlAdd = newUrlAdd;
}
function editUrlAdd(thisUrlParam, newField, newJqfield, newVal) {
if ("urlAdd" in params)
for (var i = 0; i < params.urlAdd.length; i++) {
if (params.urlAdd[i].urlParam == thisUrlParam) {
if (newField) params.urlAdd[i].field = newField;
if (newJqfield) params.urlAdd[i].jqfield = newJqfield;
if (newVal) params.urlAdd[i].val = newVal;
return;
}
}
}
function changeQueryUrl(new_inQueryUrl) {
params.queryUrl = new_inQueryUrl;
latestServerQuery = null;
// gaat mis bij kostenplaats fe res setValue(-1, ""); // TODO: vriendelijk via checkExist?
}
function calculateOffsetLeft(r) {
return SumAttr(r, "offsetLeft")
}
function calculateOffsetTop(r) {
return SumAttr(r, "offsetTop")
}
function SumAttr(r, attr) {
var kb = 0;
while (r) {
kb += r[attr];
r = r.offsetParent
}
return kb
}
function createAutocompletDiv() {
//_completeDiv=$(thisdoc).find("div#"+params.objectName+"completeDiv")[0];
// if (true||!_completeDiv)
{
_completeDiv = thisdoc.createElement("DIV");
_completeDiv.id = params.objectName + "completeDiv";
_completeDiv.className =
isMobile
? "sgDropdown dropdown-menu"
: "suggestautocompleteContainer" + (params.embedded ? " embedded" : "");
_completeDiv.onblur = function() { params.queryField.onblur(); }
_completeDiv.style.zIndex = "2199"; // JQuery dialog begint bij 1000, daar zitten we ruim boven
thisdoc.body.appendChild(_completeDiv);
//_completeDiv.appendChild(thisdoc.createTextNode("DIVVERtje"));
if (isMobile && params.embedded) {
new MutationObserver(function() {
FcltMgr.resized(); // Dan ook het modal resizen
}).observe(_completeDiv, { attributes: true, attributeFilter : ["style"] }); // Soort van onChange [style]-attribuut
}
}
// pas bij echt openen afmetingen zetten setCompleteDivSize();
}
function setCompleteDivSize() {
var _inputField = isMention ? $("#note")[0] : params.queryField;
if (_inputField && _completeDiv) {
var inputWidth = parseFloat($(_inputField).css("width"));
var newdivWidth = Math.min(Math.max(divWidth, inputWidth), thisdoc.body.offsetWidth); // Voor Mobile
var newLeft = calculateOffsetLeft(_inputField);
// De 'mention' komt onder de textarea-caret te staan ipv onder een input, caret-bottom-y ge-set in autogrow functie
var newTop = calculateOffsetTop(_inputField) + (isMention ? parseInt($(_inputField).data("caret-bottom-y"), 10) : _inputField.offsetHeight) - 1;
if (thisdoc != document) {
newTop += calculateOffsetTop(thisdoc.getElementById(window.name)) + 2;
newLeft += calculateOffsetLeft(thisdoc.getElementById(window.name)) + 2;
if (!isMobile) {
newTop -= $(document).scrollTop();
}
}
if (newLeft + newdivWidth > thisdoc.body.offsetWidth) { // Wel in beeld houden
newLeft = Math.max(0, thisdoc.body.offsetWidth - newdivWidth - 20); // ook speling voor scrollbar
}
_completeDiv.style.left = newLeft + "px";
_completeDiv.style.top = newTop + "px";
_completeDiv.style.width = newdivWidth + "px";
}
}
async function doRequest(keyword, bAll) {
if (typeof params.prerequisite == "function" && !await params.prerequisite())
return;
window.suggesttimer = setTimeout(function () { setPending(true); }, 500);
sendQuery(keyword, bAll);
latestServerQuery = keyword;
}
var ESCAPE = 27;
var KEYUP = 38;
var KEYDOWN = 40;
var KEYENTER = 13;
var KEYTAB = 9;
var KEYPGUP = 33;
var KEYPGDOWN = 34;
// Deze functie is via een timer gescheduled
function requestLoop(toetskey) { // Toetskey
// -1: Geen toets, focus op veld
// 0: Initialisatie
// >0: Toets aangeklikt
if (!doAction) { // komt uit $klikker.on(click), dan hoeft de focus(); niet te worden uitgevoerd
doAction = true;
return;
}
// Als de suggest readonly is hoef ik niet verder te kijken.
if (isReadOnly()) return;
setClass("suggest");
timerID = null;
if (params.queryField.value == "" && params.queryField.getAttribute("sgKey") != emptyKey)
// setValue(key, txt, doonChange, checkExist, extraParam, lastTry, extraParamValue)
setValue(emptyKey, emptyText, true, false, emptyText, false, this.extraParamValueEmpty);
// Bepaal wat de gebruiker heeft ingetikt exclusief het deel wat gehighlight is
var keyword = query().toLowerCase();
// Is het een te snelle tab zonder popup selectie. Dan is er geen waarde gezet. Focus terug.
var isToFastTab = (toetskey == KEYTAB && (params.queryField.value != params.queryField.getAttribute("sgCurrentValue")))
if (isToFastTab)
params.queryField.select();
var isUpDownKey = (toetskey == KEYUP || toetskey == KEYDOWN || toetskey == KEYPGUP || toetskey == KEYPGDOWN);
var isNoSpecialKey = (toetskey > 0 && !isUpDownKey && toetskey != KEYENTER && toetskey != KEYTAB);
// Bij toestsaanslag altijd popup scherm. Ook bij default waarde. Omschrijving tekst kan vaker voorkomen.
if (toetskey != 0 &&
(keyword != latestServerQuery) &&
(keyword != '') &&
((params.queryField.value != params.queryField.defaultValue) || (toetskey > 0 && !isUpDownKey)) &&
(params.queryField.value != params.queryField.getAttribute("sgCurrentValue") || isNoSpecialKey)) {
doRequest(query().toLowerCase(), false);
}
if (params.queryField.value == '' || params.queryField.value == params.queryField.defaultValue || toetskey == -2) {
hideAutocompleteDiv();
suggestionValues = [];
latestServerQuery = null;
selected = 0;
if (params.queryField.value == params.queryField.defaultValue && toetskey == 0)
setValue(params.initKey, null, false, false, params.initExtraParam)
else if (params.queryField.value == "" && params.queryField.getAttribute("sgKey") != emptyKey)
setValue(emptyKey, emptyText, true, false, emptyText, false, this.extraParamValueEmpty);
if (keyword == "" && toetskey > 0) { // Eventuele sgCascade uitvoeren als suggest veld wordt leeg gemaakt.
eval(params.queryField.getAttribute("sgCascade"));
}
}
}
// Bepaal wat de gebruiker heeft ingetikt exclusief het deel wat gehighlight is
function query() {
var textbox = params.queryField;
var N;
if (textbox.createTextRange) // IE
{ // IE6/7 soms bij het opstarten: htmlfile: unspecified error. Daarom de catch
try {
var fa = document.selection.createRange().duplicate();
N = fa.text.length;
} catch (e) {
N = 0;
}
} else
if (textbox.setSelectionRange) // Mozilla
{
try {
N = textbox.selectionEnd - textbox.selectionStart;
} catch (e) // Firefox-->Error
{
N = 0;
}
}
return textbox.value.substring(0, textbox.value.length - N);
}
async function sendQuery(txt, bAll, checkExist) {
var url = params.queryUrl + _urlAddParams(params.urlAdd) + "&k=" + myEncode(txt);
if (bAll) url += "&SuggestAll=1";
if (checkExist) url += "&checkExist=1";
await $.ajax({
type: "GET",
url: url,
dataType: params.JSONP ? "jsonp" : "json",
success: function (data, textStatus) { process(data, textStatus, checkExist); }
});
}
// Callback functie van HTTP Request
function process(data, textStatus, checkExist) {
clearTimeout(window.suggesttimer);
setPending(false);
// var checkExist = params.queryField.hasAttribute("checkExist");
var doonChange = params.queryField.getAttribute("doonChange");
// De suggest class toont het vergrootglas in beeld.
if (!isReadOnly())
setClass("suggest");
if (isMention && (!$("#note").hasClass("mentioning") || timerID))
return false; // Niet meer nodig (want gestopt of nieuw teken ingevoerd)
showAutocompleteDiv();
resultsObj = data;
if (params.addfixedoption)
resultsObj.result.unshift(params.addfixedoption);
selected = 0;
if (resultsObj.isAll && !resultsObj.bForcedAll)
selected = Math.min(resultsObj.result.length - 1, 10 - 1);
// voorheen htmlFormat(checkExist, doonChange), nu ingeplakt
lastHighlight = null;
while (_completeDiv.childNodes.length > 0) {
_completeDiv.removeChild(_completeDiv.childNodes[0]);
}
if (!resultsObj.result.length) // Hmm, geen resultaten gevonden
{
if (params.queryField.value.length > 0 && params.queryField.value != "*") {
// Als de nieuwe waarde niet voorkomt in de query en niet kan worden gezet
// dan wordt geprobeerd om de huidige waarde weer opnieuw te zetten (currentKey > 0).
// Indien ook de huidige waarde niet meer aanwezig is in de query,
// dan wordt de suggestbox leeg gemaakt.
if (checkExist && currentKey > 0) {
var pcurrentKey = currentKey;
var pcurrentText = currentText;
var pcurrentExtraParam = currentExtraParam;
currentKey = emptyKey;
currentText = "";
currentExtraParam = null;
setValue(pcurrentKey, pcurrentText, doonChange, true, pcurrentExtraParam, true);
} else {
setValue(emptyKey, (checkExist ? "" : null), true, false, (checkExist ? "" : null), false, this.extraParamValueEmpty);
}
if (!checkExist) {
setClass("suggestBad");
}
} else { // Geen resultaten gevonden en params.queryField was leeg.
// Zet nu opnieuw de lege waarde.
setValue(emptyKey, "", true, false, null, true, this.extraParamValueEmpty);
}
hideAutocompleteDiv();
return;
}
// Maak suggestbox leeg indien checkExist is true en gevonden key en ingevoerde key komen niet overeen:
if (checkExist && resultsObj.result.length == 1 && resultsObj.result[0].key != params.queryField.getAttribute("sgKey")) { // Maak suggestbox leeg
if (params.queryField.value.length > 0)
{
setValue(emptyKey, "", true, false, "", false, this.extraParamValueEmpty);
setClass("suggestBad");
}
hideAutocompleteDiv();
return;
}
// Indien checkExist is true en er zijn meerdere waarden gevonden (Begin gedeelte van de omschrijving komt overeen) dan:
// 1) Komt maar van 1 van deze de gevonden key en ingevoerde key overeen, dan deze selecteren
// 2) Anders selectbox leeg maken.
else if (checkExist && resultsObj.result.length > 1) {
var nr_of_hits = 0;
for (var i = 0; i < resultsObj.result.length; i++) {
if (resultsObj.result[i].key == params.queryField.getAttribute("sgKey")) {
nr_of_hits++;
var hit_i = i;
}
}
if (nr_of_hits == 1) { // Geselecteerde text selecteren (enige overeenkomende resultaat van de meerdere gevonden waarden)
selected = hit_i; // Kies wel de juiste overeenkomende resultaat met de juiste key
setValues(doonChange);
if (!checkExist) selectRange(0, 0);
hideAutocompleteDiv();
return;
} else { // Gevonden key en ingevoerde key komen vaker overeen. Maak suggestbox leeg
if (params.queryField.value.length > 0)
{
setValue(emptyKey, "", true, false, "", false, this.extraParamValueEmpty);
setClass("suggestBad");
}
hideAutocompleteDiv();
return;
}
}
if (checkExist && resultsObj.result.length == 1 && resultsObj.result[0].key == params.queryField.getAttribute("sgKey")) {
// geselecteerde text selecteren (enige resultaat)
setValues(doonChange);
if (!checkExist) selectRange(0, 0);
hideAutocompleteDiv();
return;
}
suggestionValues = [];
if (params.sgType != "persoon" && params.queryField.getAttribute("sgCurrentValue") && params.queryField.getAttribute("sgKey") > 0) {
var extra = params.queryField.getAttribute("sgExtraParam");
// Plak de current er voor als eerste keuze
resultsObj.result = [{
txt: params.queryField.getAttribute("sgCurrentValue"),
key: params.queryField.getAttribute("sgKey"),
extra: extra ? extra : "",
desc: L("lcl_shared_suggest_huidig"),
iscurrent: true
}].concat(resultsObj.result);
}
if (resultsObj.similar)
$(_completeDiv).addClass("suggestsimilar");
else
$(_completeDiv).removeClass("suggestsimilar");
for (var i = 0; i < resultsObj.result.length; i++) {
if (resultsObj.result[i].txt) {
suggestionValues.push(resultsObj.result[i].txt);
var xDiv = thisdoc.createElement("div");
xDiv.sgIndex = i;
if (i == selected) {
xDiv.className = isMobile ? "dropdown-item selected" : "suggestsrs";
lastHighlight = xDiv;
} else {
xDiv.className = isMobile ? "dropdown-item" : "suggestsr";
}
if (!!resultsObj.result[i].extraParamValue)
{
var attr;
for (attr in resultsObj.result[i].extraParamValue)
{
xDiv.setAttribute(attr.replace(/^\s+|\s+$/g, ""), resultsObj.result[i].extraParamValue[attr.replace(/^\s+|\s+$/g, "")]); // Replace is for trim spaces.
}
}
xDiv.ontouchstart = function() { highlight(this.sgIndex); };
xDiv.onmouseover = function() { highlight(this.sgIndex); };
xDiv.onmousedown = function() {
setValues(true);
hideAutocompleteDiv();
return true;
};
if ("title" in resultsObj.result[i])
xDiv.title = resultsObj.result[i].title;
if (resultsObj.anyfoto) {
var fotourl = resultsObj.result[i].foto;
if (fotourl && fotourl.match(/\.(png|jpg|jpeg)$/i)) // het is een image
{
var xFoto = thisdoc.createElement("img");
xFoto.setAttribute("src", fotourl);
xFoto.setAttribute("height", "40");
xFoto.className = "suggestfoto";
xDiv.appendChild(xFoto);
} else {
var xFoto = thisdoc.createElement("div");
xFoto.innerHTML = "&nbsp;";
xFoto.className = "suggestfoto";
xDiv.appendChild(xFoto);
}
}
var xSpan = thisdoc.createElement("span");
xSpan.className = isMobile ? "sgText" : "suggestsrt";
if (i == 0 &&
!isMobile &&
params.sgType != "persoon" &&
params.queryField.getAttribute("sgCurrentValue") &&
params.queryField.getAttribute("sgKey") > 0) // eerste krijgt aparte opmaak
{
xSpan.style.borderBottom = "1px solid black"; // TODO: Stijl voor verzinnen
xSpan.style.paddingBottom = "10px";
}
var ll = 0;
// first matching part bold
var lsq = latestServerQuery;
if (lsq && lsq.charAt(0) == "*") lsq = lsq.substring(1);
ll = resultsObj.result[i].txt.toLowerCase().indexOf(lsq);
if (resultsObj.result[i].isHTML)
xSpan.innerHTML = resultsObj.result[i].txt;
else if (ll >= 0 && lsq.length) {
if (ll > 0)
xSpan.appendChild(thisdoc.createTextNode(resultsObj.result[i].txt.substring(0, ll)));
var xb = thisdoc.createElement("b");
xb.appendChild(thisdoc.createTextNode(resultsObj.result[i].txt.substring(ll, ll + lsq.length)));
xSpan.appendChild(xb);
xSpan.appendChild(thisdoc.createTextNode(resultsObj.result[i].txt.substring(ll + lsq.length)));
} else
xSpan.appendChild(thisdoc.createTextNode(resultsObj.result[i].txt));
xDiv.appendChild(xSpan);
if ("txtextra" in resultsObj.result[i]) {
var $Text = $("<span>").text(resultsObj.result[i].txtextra)
.addClass("suggestextratext");
$(xDiv).append("<br>");
$(xDiv).append($Text);
}
if ("desc" in resultsObj.result[i]) // Extra description present
{
var x3 = thisdoc.createElement("span");
x3.className = isMobile ? "sgDesc rounded" : "suggestsrc";
var desc = (resultsObj.result[i].desc || "").trim();
ll = desc && desc.toLowerCase().indexOf(lsq);
if (params.highlightDescript && ll >= 0) {
x3.appendChild(thisdoc.createTextNode(desc.substring(0, ll)));
var xb = thisdoc.createElement("b");
xb.appendChild(thisdoc.createTextNode(desc.substring(ll, ll + lsq.length)));
x3.appendChild(xb);
x3.appendChild(thisdoc.createTextNode(desc.substring(ll + lsq.length)));
} else
x3.appendChild(thisdoc.createTextNode(desc));
xDiv.appendChild(x3);
}
_completeDiv.appendChild(xDiv);
}
}
// xDiv is op dit moment de laatste
if (!xDiv || (xDiv.offsetTop + (resultsObj.hasMore ? 2 : 1) * xDiv.clientHeight < 300))
_completeDiv.style.height = ""; // Auto
else { //_completeDiv.style.overflow = "hidden";
_completeDiv.style.height = "300px";
if (/MSIE 7.0/.test(navigator.userAgent))
_completeDiv.style.paddingRight = "16px"; // Anders valt bij IE7 een deel achter de scrollbar
_completeDiv.style.overflowY = "auto";
_completeDiv.style.overflowX = "hidden";
}
if (resultsObj.hasMore) // Is gezet als er 10 of meer records zijn
{
var xDiv = thisdoc.createElement("div");
var xSpan = thisdoc.createElement("span");
if (isMobile) {
xDiv.className += " text-center more";
if (!resultsObj.isAll) {
xDiv.className += " dropdown-item tappable";
}
} else {
xDiv.className = "suggestsr";
xSpan.className = "suggestMore";
}
if (resultsObj.isAll)
xSpan.appendChild(thisdoc.createTextNode(L("lcl_shared_suggest_toomany"))); // Maximum bereikt
else {
$(xDiv).mousedown(function(evt) {
doRequest(latestServerQuery, true);
evt.preventDefault(); // Voorkom blur
});
var hasMoreMsg = isMobile ? $(I("fa-chevron-down")).get(0) : thisdoc.createTextNode(L("lcl_shared_suggest_more"));
xSpan.appendChild(hasMoreMsg); // Er is meer
}
xDiv.appendChild(xSpan);
_completeDiv.appendChild(xDiv);
}
//requestSuggestions();
}
function keyupHandler(evt) {
// make sure we have a valid event variable
if (!evt && window.event) {
evt = window.event;
}
var key = evt.keyCode;
if (key < 32 || (key >= 33 && key <= 46) || (key >= 112 && key <= 123)) {
// Ignore
} else {
// Request suggestions from the suggestion provider
// Backspace key(8), Delete key (48)
if (key != 8 && key != 48) {
requestSuggestions();
}
}
return true;
}
function keypressHandler(evt) {
params.queryField.removeAttribute("checkExist");
params.queryField.setAttribute("doonChange", true);
// make sure we have a valid event variable
if (!evt && window.event) {
evt = window.event;
}
var key = evt.keyCode;
// if this key isn't one of the ones we care about, just return
if (timerID) // reset oude. Is goed voor de performance/response
clearTimeout(timerID);
timerID = setTimeout(params.objectName + ".requestLoop(" + key + ");", THROTTLE_PERIOD);
// don't do anything if the div is hidden
if (!isAutocompleteDivVisible()) {
if (key == KEYDOWN || key == KEYPGDOWN)
autoOpen();
return;
}
if (key == KEYPGDOWN) {
if (resultsObj.hasMore && !resultsObj.isAll) {
doRequest(latestServerQuery, true);
} else if (isAutocompleteDivVisible) {
_completeDiv.scrollTop += _completeDiv.clientHeight;
//selected += 20;
//highlight(selected);
}
return false;
}
if (key == KEYPGUP) {
if (isAutocompleteDivVisible) {
_completeDiv.scrollTop -= _completeDiv.clientHeight;
//selected -= 20;
//highlight(selected);
}
return false;
}
if (key == KEYUP) {
if ((selected - 1) >= 0)
selected = selected - 1;
else if (!resultsObj.hasMore)
selected = resultsObj.result.length - 1;
highlight(selected);
return false;
}
if (key == KEYDOWN) {
if ((selected + 1) < resultsObj.result.length)
selected = selected + 1;
else if (resultsObj.hasMore && !resultsObj.isAll)
doRequest(latestServerQuery, true);
else
selected = 0;
highlight(selected);
return false;
}
if (key == ESCAPE) {
params.queryField.onblur();
}
if (key == KEYENTER) {
setValues(true);
selectRange(0, 0);
hideAutocompleteDiv();
return false;
}
return true;
}
// De gewone scrollIntoView() heeft wel eens de neiging de complete pagina ook te scrollen
function myScrollIntoView(theDiv, toView) {
if (theDiv.scrollTop + theDiv.clientHeight < toView.offsetTop + toView.clientHeight)
theDiv.scrollTop = toView.offsetTop + toView.clientHeight - theDiv.clientHeight;
if (theDiv.scrollTop > toView.offsetTop)
theDiv.scrollTop = toView.offsetTop;
}
function highlight(number) {
selected = number;
// Herstel vorige highlight
if (lastHighlight && lastHighlight.className)
lastHighlight.className = isMobile ? "dropdown-item" : "suggestsr";
// Zet nieuwe highlight
var ieDIVs = $(_completeDiv).find('div').not(".suggestfoto");
lastHighlight = ieDIVs[selected];
if (lastHighlight && lastHighlight.className)
lastHighlight.className = isMobile ? "dropdown-item selected" : "suggestsrs";
myScrollIntoView(_completeDiv, lastHighlight);
}
function setValues(doonChange) {
if (resultsObj) {
var result = resultsObj.result[selected][resultsObj.storeDesc ? "desc" : "txt"];
setValue(resultsObj.result[selected].key, result, doonChange, false, resultsObj.result[selected].extra, null, resultsObj.result[selected].extraParamValue) // doonChange
}
}
function autoOpen() {
params.queryField.value = latestServerQuery || "*"; //"*";
doRequest(params.queryField.value, false);
if (params.queryField.createTextRange) {
// Alleen IE komt hier, FF niet!
// alert(JSON.stringify(params));
// var el = document.getElementById("sgRoom");
// var range = el.createTextRange();
// range.move("character", 1);
// range.select();
var oRange = params.queryField.createTextRange();
// alert(JSON.stringify(params.queryField)); // = {"jQuery{blablabla": 103}
// alert(JSON.stringify(oRange)); // oRange = {}
// oRange.collapse(true);
// oRange.moveEnd('character', 1);
// oRange.moveStart('character', 1);
oRange.move("character", 1);
oRange.select();
// oRange.setSelectionRange(1,1);
}
// TODO: else wat voor FireFox?
//set focus back to the textbox (when field is not disabled)
//if (!textbox.disabled) textbox.focus();
//params.queryField.focus();
//selectRange(0,1);
}
function showAutocompleteDiv() {
$(window).on("resize", setCompleteDivSize) // Also runs after "orientationchange"(tilting) for Mobile
.on("scroll", setCompleteDivSize);
setCompleteDivSize(); // voor de zekerheid
_completeDiv.style.display = "block";
}
function hideAutocompleteDiv() {
$(window).off("resize", setCompleteDivSize)
.off("scroll", setCompleteDivSize);
_completeDiv.style.display = "none";
}
function isAutocompleteDivVisible() {
return (_completeDiv.style.display == "block");
}
function requestSuggestions() {
var sTextboxValue = query().toLowerCase();
var aSuggestions = [];
if (suggestionValues.length > 0) { //search for matching states
for (var i = 0; i < suggestionValues.length; i++) {
if (suggestionValues[i].toLowerCase().indexOf(sTextboxValue) == 0)
aSuggestions.push(suggestionValues[i]);
}
autosuggest(aSuggestions);
}
};
function autosuggest(aSuggestions) { // Make sure there's at least one suggestion
if (aSuggestions.length == 1)
typeAhead(aSuggestions[0]);
}
function typeAhead(sSuggestion) {
var textbox = params.queryField;
// Check for support of typeahead functionality
if (textbox.createTextRange || textbox.setSelectionRange) {
var iLen = query().length;
textbox.value = sSuggestion;
selectRange(iLen, sSuggestion.length);
}
};
function selectRange(iStart, iLength) {
var textbox = params.queryField;
// Use text ranges for Internet Explorer
if (textbox.createTextRange) {
var oRange = textbox.createTextRange();
oRange.moveStart("character", iStart);
oRange.moveEnd("character", iLength - textbox.value.length);
oRange.select();
//use setSelectionRange() for Mozilla
} else if (textbox.setSelectionRange) {
textbox.setSelectionRange(iStart, iLength);
}
//set focus back to the textbox (when field is not disabled)
if (!textbox.disabled) textbox.focus();
};
if (typeof window[params.objectName + "OnLoad"] === "function") {
window[params.objectName + "OnLoad"](this);
}
sgReadyStateResolver();
}