// global constants
var minSearchLength=2, // min. number of characters to activate preview
maxSearchCacheEntries=20; // number of cache entries
// global vars
var searchPreviewTimeout, searchCache, $searchForm, $liefInput, $searchInput;
// clears the timer
var clearTimer = function() {
window.clearTimeout(searchPreviewTimeout);
return true;
};
// returns a list element with events, cloning via $.clone(true) did not work
var getResultNode = function(str) {
return $('
' + str + '').bind('click.search', function(){
// unbind click handler
var $this = $(this).siblings().andSelf().unbind('click.search').end().end();
// fill search field/submit form
var idPrefix = $this.parent().attr('id').replace(/-result-list/,''),
$input = $searchForm.find('#input-' + idPrefix),
isLief = (idPrefix == 'lief');
if (isLief) { // Lieferanten
$input.val($this.html()).next('div.search-preview-container').hide();
$searchInput.focus().select();
}
else { // Artikel/Katalog
$input.val($this.data('qResult'));
$searchForm.submit();
}
return false;
}).hover(
function(){
$(this).addClass('over');
},
function(){
$(this).removeClass('over');
}
);
};
// input field event handler
var addInputEventHandler = function($input, backendUrl, isLief, isKatalog) {
var $preview = $input.siblings('div.search-preview-container'),
$wait = $preview.find('div.wait-container'),
$noResult = $preview.find('div.noresult'),
$result = $noResult.next('div'),
$resultList = $preview.find('ul.search-result-list'),
$resultBtns = isLief
? null
: $result.find('a[id^=btn-search-result-]').bind('click.search',function() {
// button up/down clicked?
var args = $input.data('backendArgs');
getPreviewList($input, backendUrl, isLief, isKatalog,
args.value, $(this).data('limit'), args.Aufruf_art, args.SucheUeber);
});
//console.log('addInputEventHandler() isLief:', isLief, ', isKatalog:', isKatalog, ', input[name]=' + $input.attr('name'));
// store data/jQuery elements, add event handler
$input.data('$el',
{'input':$input, 'preview':$preview, 'wait':$wait, 'noResult':$noResult,
'result':$result, 'btns':$resultBtns, 'resultList':$resultList})
.focus(function() { // hide other preview containers
$searchForm.find('div.search-preview-container:visible').not($preview).hide();
}).keyup(function(e){
var key = TCode(e),
value = $.trim($(this).val()),
lastQuery = $input.data('lastquery') || '';
children = null;
// hide container
$preview.children().andSelf().hide();
if (lastQuery == value // backspace=8, tab=9, delete=46
|| isLief && (value=='' || key==8 || key==9 || key==46)
|| !isLief && value.length < minSearchLength){
$preview.hide();
return false;
}
if (!isLief && key== 13) { // submit form
$searchForm.submit();
return false;
}
$input.data('lastquery', value); // store last query
// Lieferanten
if (isLief) {
$wait.show();
getPreviewList($input, backendUrl, isLief, isKatalog, value);
return false;
}
// Artikel, Katalog
var $withPreview = $searchForm.find('input[name=ShowVorschau]');
if ($withPreview.length == 1 && $withPreview.val() == "1") {
clearTimer();
searchPreviewTimeout = window.setTimeout(function(){
getPreviewList($input, backendUrl, isLief, isKatalog, value,
isKatalog ? 0 : 1,
$searchForm.find('input[name=art]').val().toUpperCase(),
$searchForm.find('input[name=SucheUeber]').val());
}, 500);
}
return false;
});
};
// initializes jquery vars
var initSearch = function()
{
// Erweiterte Suche
$('#ErwSucheToggle').click(function(){
$(this).children('span').toggle(); // toggle +/-
$('#ErwSuche').toggle();
});
$searchForm=$('#search-form');
// Lieferanten
$liefInput = $searchForm.find('input#input-lief');
if ($liefInput.length == 1) {
addInputEventHandler($liefInput, 'backend/LiefRequest.php', true, false);
}
// Artikelsuche/Katalogsuche
$searchInput = $searchForm.find('#input-search');
var isKatalog = ($searchInput.attr('name').search('Kat') == 0);
addInputEventHandler($searchInput, 'backend/Vorschau' + (isKatalog ? 'K' : '') + 'Request.php', false, isKatalog);
// global search cache
searchCache = function() {
var _keys = [], _values = [], // two arrays used as hashmap-like lookup table
_getKey = function(data) { // returns a key for given parameters
var s = '';
if (typeof data == 'object') {
for (i in data) {
s += data[i] + ',';
}
}
else { // string
s = data;
}
//console.log('searchCache._getKey() key=' + s);
return s;
},
_find = function(data) {
var key = _getKey(data);
for (var i=0; i<_keys.length; i++) {
if (_keys[i] === key) { // cache hit
//console.log('searchCache._find() key=' + key + ', value=', _values[i]);
return _values[i];
}
}
return null;
};
return {
// add data and result to "cache"
add: function(data, result) {
if (_keys.length == maxSearchCacheEntries) {
// cache is full, remove first element
_keys.pop();
_values.pop();
}
_keys.push(_getKey(data));
_values.push(result);
},
// get cached result or null for given data
get: function(data) {
if (!data) return null;
return _find(data);
}
};
}();
};
/* ### Lieferanten-/Artikel-/Katalogvorschau ###################################### */
var getPreviewList = function($input, backendUrl, isLief, isKatalog, value, slimit, art, type) {
// inner callback for (cached) json
var _previewListCallback = function(json)
{
$el.wait.hide();
if(!json || json.nohits){ // no result...
$el.noResult.show();
if (isLief) $el.input.focus().select();
return;
}
// show result...
$el.result.show();
if (json.hits) {
$el.result.children('div.search-result-hits').empty()
.append('[' + json.hits + '] Treffer').show();
}
if (json.up !=null || json.down != null) {
if (json.up != null) {
$el.btns.eq(0).data('limit',json.up).css('display','block');
}
else {
$el.btns.eq(0).hide();
}
if (json.down != null) {
$el.btns.eq(1).data('limit',json.down).css('display','block');
}
else {
$el.btns.eq(1).hide();
}
}
if (json.data) { // fill result list
if (isLief) { // Lieferanten
if (json.data.length == 1) { // one result
// fill input field and select search field
$el.input.val(json.data);
$searchInput.focus().select();
return;
}
else { // result list
var $s = $('');
$.each(json.data,function(){
$s.append(getResultNode('' + this));
});
$el.resultList.empty().append($s.children()).show();
}
}
else { // Katalog/Artikel
var $s = $(''); // dummy container
$.each(json.data,function(){
var str = isKatalog
? (this[0] + ' [' + this[1] + '] Treffer')
: this[1];
$s.append( getResultNode(str).data('qResult', this[0]) );
});
$el.resultList.empty().append($s.children()).show();
}
}
};
var $el = $input.data('$el'),
backendArgs = isLief ? {value : value} // Lieferanten
: (isKatalog ? {value : value, // Katalog
SLimit : slimit}
: {value : value, // Artikel
SLimit : slimit,
Aufruf_art : art,
SucheUeber : type,
LiefName : (type == 4) ? $liefInput.val() : ''});
// save args for search cache and up-/down-buttons
$el.input.data('backendArgs', backendArgs);
$el.noResult.hide();
$el.result.children().andSelf().hide(); // hide: hits, up, down, result-list
$el.wait.show();
$el.preview.show();
var cached = searchCache.get(backendArgs);
if (cached) { // return cached data
return _previewListCallback(cached);
}
// return data from backend URL
$.getJSON(backendUrl, backendArgs, function(json){
searchCache.add(backendArgs, json);
_previewListCallback(json);
}
);
};