Index: branches/5.2.x/core/admin_templates/js/ajax_dropdown.js =================================================================== diff -u -N --- branches/5.2.x/core/admin_templates/js/ajax_dropdown.js (revision 16339) +++ branches/5.2.x/core/admin_templates/js/ajax_dropdown.js (revision 0) @@ -1,549 +0,0 @@ -/* -(c) Intechnic Europe 2007 http://www.intechnic.lv -Author: Konstantin Tjuterev - -The class adds a dynamic drop-down to the edit-box -Usage: - -
-
- - -The AJAXDropDown constructor takes the following arguments: - input_id - id of textbox to attach to - suggest_url_callback - function which should return URL which returns XML of suggested values, - function takes one argument - it is current value of the text_box - [get_value_callback] - optional argument - function which returns the value to be set in the textbox, - based on currently selected item (out of suggested). If the argument is skipped - the node value of - element will be used as the value - element in the suggestions XML may have unlimited number of attribuets, all the attributes will be set - to the corresponding DIV element and this DIV element will be passed as argument to the get_value_callback, - so one may use the argument to alter the value set into textbox as in the example above - -Response XML structure: - The script will look for ALL elements with tagname = 'item', so basically the structure should look like this: - - - Suggestion 1 - Suggestion 2 - Suggestion 3 - - -Design & CSS - The script will automatically display a div which width will match the width of the text-box - You may control the div look by changing .suggest-box CSS selector - The items inside the box will have .suggest-item and .suggest-item-over - - The default styles which may be used is: - - - -*/ - - -function AJAXDropDown(input_id, suggest_url_callback, get_value_callback, $custom_params) { - this.useTags = false; - this.maxWidth = false; - - if ($custom_params !== undefined) { - $.extend(this, $custom_params); - } - - this.Input = document.getElementById(input_id); - - if (!$( jq('#div_' + input_id) ).length) { - $('
').appendTo('body'); // .insertAfter(this.Input); - } - - this.Box = document.getElementById("div_"+input_id); - this.KeyUpWaiting = false; - this.KeyUpTimer = false; - this.SuggestURLCallback = suggest_url_callback; - this.GetValueCallback = $.isFunction(get_value_callback) ? get_value_callback : this.GetValue; - this.BoxOpen = false; - this.SelectedItem = false; - - var obj = this; - - $(document).ready( - function() { - obj.Init() - } - ); - - if (this.useTags) { - this.tagValue = ''; - this.prevTagValue = ''; - this.tags = {}; - this.saveTagPos = 0; - this.newCaretPos = 0; - this.originalCaretPos = 0; - } -} - -AJAXDropDown.prototype.Init = function() { - // draw box - // this.Box = document.createElement('DIV'); - // document.body.appendChild(this.Box); - // this.Box = addElement(this.Input.parentNode, 'div'); - - this.Box.style.display = 'none'; - this.Box.style.zIndex = 99; - this.Box.style.position = 'absolute'; - this.Box.style.overflow = 'auto'; - this.Box.className = 'suggest-box'; - - // add onkeyup - var obj = this; - - $(this.Input) - .attr('autocomplete', 'off') - .keyup ( function(ev) { obj.KeyUp(ev) } ) - .blur ( function(ev) { obj.Blur(ev) } ); - - $(this.Box) - .scroll( - function(ev) { - if (obj.BlurWaiting) { - window.clearTimeout(obj.BlurTimer); - } - } - ) - .mouseup( function(ev) { obj.BlurWaiting = false } ); -} - -AJAXDropDown.prototype.Blur = function(ev) { - if (this.BlurWaiting) { - return; - } - - var obj = this; - this.BlurWaiting = true; - - this.BlurTimer = window.setTimeout( - function() { - obj.CloseBox(); - this.BlurWaiting = false; - }, 300 - ); -} - -AJAXDropDown.prototype.KeyUp = function(e) { - switch (e.keyCode) { - case 38: //arrow up - if (!this.BoxOpen) { - break; - } - this.SelectPrev(); - break; - - case 40: //arrow down - if (!this.BoxOpen) { - break; - } - this.SelectNext(); - break; - - case 27: //Escape - if (this.BoxOpen) { - this.Input.value = this.OriginalValue; - - if (this.useTags) { - this.setCaretPosition(this.originalCaretPos); - } - - this.CloseBox(); - } - break; - case 13: //Enter - this.CloseBox(); - break; - - default: -// if (this.Input.value == '') return; - if (this.useTags) { - this.setTagValue(); - } - - var obj = this; - if (this.KeyUpWaiting && this.KeyUpTimer) { - window.clearTimeout(this.KeyUpTimer); - this.KeyUpTimer = false; - } - - this.KeyUpWaiting = true; - this.KeyUpTimer = window.setTimeout( - function() { - obj.RequestSuggestions(); - }, 300 - ); - } -} - -AJAXDropDown.prototype.parseTagString = function(tag_string) { - var value_end = tag_string.match(/[ ]*$/)[0]; - tag_string += ','; - - var rex = new RegExp("(^[ ]*\|[ ]*,[ ]*)", "g"); - var separators = tag_string.match(rex); - - var start = 0; - var end = 0; - - for (var i = 0; i < separators.length - 1; i++) { - the_tag = tag_string.substring(0, tag_string.search(/[ ]*,[ ]*/)).replace(rex.compile('^' + separators[i]), ''); - - this.tags[i] = { - 'separator' : separators[i], - 'tag' : the_tag, - 'start' : start, - 'end' : end + the_tag.length - } - - start += the_tag.length + separators[i + 1].length; - end += the_tag.length + separators[i + 1].length; - tag_string = tag_string.substring(tag_string.search(/[ ]*,[ ]*/) + separators[i+1].length); - } - - this.tags['count'] = i; - this.tags['value_end'] = value_end; -} - - -AJAXDropDown.prototype.getCaretPosition = function() { - var element = this.Input; - - if (document.selection) { - // The current selection - var range = document.selection.createRange(); - // We'll use this as a 'dummy' - var stored_range = range.duplicate(); - // Select all text - stored_range.moveToElementText(element); - // Now move 'dummy' end point to end point of original range - stored_range.setEndPoint('EndToEnd', range); - // Now we can calculate start and end points - element.selectionStart = stored_range.text.length - range.text.length; - element.selectionEnd = element.selectionStart + range.text.length; - } - - return element.selectionEnd; -} - -AJAXDropDown.prototype.setCaretPosition = function(caretPos) { - if (this.Input.createTextRange) { - var range = this.Input.createTextRange(); - range.move('character', caretPos); - range.select(); - } - else { - if (this.Input.selectionStart) { - this.Input.focus(); - this.Input.setSelectionRange(caretPos, caretPos); - } - else { - this.Input.focus(); - } - } -} - -AJAXDropDown.prototype.setTagValue = function() { - var endPos = this.getCaretPosition(); - - this.parseTagString(this.Input.value); - - for (pos = 0; pos < this.tags.count; pos++) { - if (endPos >= this.tags[pos].start && endPos <= this.tags[pos].end) { - this.tagValue = this.tags[pos].tag; - this.saveTagPos = pos; - break; - } - } - - this.originalCaretPos = endPos; -} - - -AJAXDropDown.prototype.RequestSuggestions = function() { - var $me = this; - - if (this.useTags) { - if (this.tagValue == '') { - this.CloseBox(); - return; - } - - if (this.prevTagValue != this.tagValue) { - this.prevTagValue = this.tagValue; - - var $me = this; - var $url = this.SuggestURLCallback(this.tagValue); - - if ($url === false) { - // do nothing - return ; - } - - $.get( - $url, - function ($data) { - $me.successCallback($data, 'reload', $me); - }, - 'xml' - ); - } - } - else { - var $url = this.SuggestURLCallback(this.Input.value); - - if ($url === false) { - // do nothing - return ; - } - - $.get( - $url, - function ($data) { - $me.successCallback($data, 'reload', $me); - }, - 'xml' - ); - } -} - -AJAXDropDown.prototype.successCallback = function ($xml, params, object) { - object.OriginalValue = object.Input.value; - object.KeyUpWaiting = false; - object.ClearItems(); - - var items = $xml.getElementsByTagName('item'); - - if (items.length > 0) { - for (var i = 0; i < items.length; i++) { - object.AddItem(items[i].firstChild.nodeValue, items[i].attributes); - } - - object.OpenBox(); - } else { - object.CloseBox(); - } -} - -AJAXDropDown.prototype.errorCallback = function (request, params, object) { - this.KeyUpWaiting = false; -} - -AJAXDropDown.prototype.ClearItems = function() { - this.Box.scrollTop = 0; - this.UnselectItem(); - - for (var i = this.Box.childNodes.length - 1; i >= 0; i--) { - this.Box.removeChild(this.Box.childNodes[i]); - } -} - -AJAXDropDown.prototype.OpenBox = function() { - var $box = $(this.Box); - var $input = $(this.Input); - var $input_position = $(this.Input).offset(); - - $box.css('height', 'auto'); - - // try to place suggest-box below input - var $input_width = $input.outerWidth(); - var $input_height = $input.outerHeight(); - - if (this.maxWidth === false) { - $new_box_width = $input.width(); - - if (document.all) { - $new_box_width += ($input_width - $input.innerWidth()); // add borders for IE - } - } - else { - var $new_box_width = this.maxWidth; - } - - if ($box.width() < $new_box_width) { - // suggest-box width at lease same as input's width - $box.css('width', $new_box_width); - } - - var $box_left = $input_position.left; - var $box_top = $input_position.top + $input_height; - var $box_height = $box.outerHeight(); - - if ($box_top + $box_height > document.body.offsetHeight) { - // move above the box - $box_top -= ($input_height + $box_height); - } - - /*var $scroll_container = $($input).parents('#scroll_container_container'); - var $scroll_container_offset_top = $scroll_container.length > 0 ? $scroll_container.scrollTop() - $scroll_container.offset().top : 0; - - $box_top += $scroll_container_offset_top;*/ - - $(this.Box) - .css( - { - left: $box_left, - top: $box_top - } - ) - .show(); - - this.BoxOpen = true; -} - -AJAXDropDown.prototype.CloseBox = function() { - if (!this.BoxOpen) { - return; - } - - this.Box.style.display = 'none'; - this.BoxOpen = false; -} - -AJAXDropDown.prototype.AddItem = function(value, attributes) { - var item = addElement(this.Box, 'div'); - for (var i = 0; i < attributes.length; i++) { - item.setAttribute(attributes[i].nodeName, attributes[i].nodeValue); - } - - item.className = 'suggest-item'; - item.innerHTML = value; - var obj = this; - - $(item) - .mousemove( function() { obj.SelectItem(item) } ) - .mousedown( function() { obj.ClickItem(item) } ); -} - -AJAXDropDown.prototype.ClickItem = function(item) { - this.Input.value = this.GetValueCallback(item); - - if (this.useTags) { - this.setCaretPosition(this.newCaretPos); - } - - this.CloseBox(); -} - -AJAXDropDown.prototype.SelectNext = function() { - if (!this.SelectedItem) { - this.SelectItem(this.Box.firstChild, true); - return; - } - - if (isset(this.SelectedItem.nextSibling)) { - this.SelectItem(this.SelectedItem.nextSibling, true); - } - else { // down from last - this.UnselectItem(); - this.Input.value = this.OriginalValue; - - if (this.useTags) { - this.setCaretPosition(this.originalCaretPos); - } - } -} - -AJAXDropDown.prototype.SelectPrev = function() { - if (!this.SelectedItem) { - this.SelectItem(this.Box.lastChild, true); - return; - } - - if (isset(this.SelectedItem.previousSibling)) { - this.SelectItem(this.SelectedItem.previousSibling, true) - } - else { // up from first - this.UnselectItem(); - this.Input.value = this.OriginalValue; - - if (this.useTags) { - this.setCaretPosition(this.originalCaretPos); - } - } -} - -AJAXDropDown.prototype.UnselectItem = function(item) { - if (!item) { - item = this.SelectedItem; - } - - if (!item) { - return; - } - - item.className = 'suggest-item'; - this.SelectedItem = false; -} - -AJAXDropDown.prototype.SelectItem = function(item, setvalue) { - if (this.SelectedItem) { - this.UnselectItem(this.SelectedItem); - } - - item.className = 'suggest-item-over'; - this.SelectedItem = item; -// item.scrollIntoView(false); - - if (setvalue) { - this.Input.value = this.GetValueCallback(item); - - if (this.useTags) { - this.setCaretPosition(this.newCaretPos); - } - } -} - -AJAXDropDown.prototype.GetValue = function(item) { - if (!this.useTags) { - return item.innerHTML; - } - - var res = ''; - - for (pos = 0; pos < this.tags.count; pos++) { - res += this.tags[pos].separator; - - if (pos == this.saveTagPos) { - res += item.innerHTML; - this.prevTagValue = item.innerHTML; - this.newCaretPos = res.length; - } else { - res += this.tags[pos].tag; - } - } - - return res; -}