/*
 * Autocomplete selector, Dropdown menu
 *
 * Author: Andrew Rogozov
 *
 * Last updated: 2010-01-25
 *
 * AntanubiS - Checkbox and Radiobutton added
 *
 */

if (window.StaticFiles)  _proxy_jslib_handle(StaticFiles, ('ui_controls.js'), '', 0, 0).l = 1;

var _DEBUG = false;
function debug(e) {
  if (!_DEBUG) return;
  debugLog(e);
}

var uiWindowDispatcher = {
  _ui_current_uid: 0,
  _event_listeners: [],
  _initialized: false,
  _initialize: function() {
    if (this._initialized) return;
    this._initialized = true;
    var self = this;
    var handler = function(e) {
      var handlers =  _proxy_jslib_handle(self._event_listeners, (e.type), '', 0, 0);
      if (!handlers) return;

      for (var i in handlers) {
        var el =  _proxy_jslib_handle(handlers, (i), '', 0, 0)[0], callback =  _proxy_jslib_handle(handlers, (i), '', 0, 0)[1];

        if (!el || !el.parentNode || el.id && !ge(el.id)) {
          debug('splice');
          handlers.splice(i, 1);
        }
        if (!isVisible(el)) {
          continue;
        }
        if ((e.type == 'click' || e.type == 'mousedown')) {
          e.outside = true;
          var t = e.target;
          while (t != null) {
            if (t == el) {
              e.outside = false;
              break;
            }
            t = t.parentNode;
          }
        }

        if (callback(e) === false) // run handler
          return false;
      }
    }
    addEvent(document, 'keypress keydown mousedown', handler);
  },

  getUID: function() {
    return this._ui_current_uid++;
  },
  attachListener: function(el, event, handler) {
    el = ge(el);
    if (!el || !isFunction(handler)) return false;

    this._initialize();
    if (!isArray( _proxy_jslib_handle(this._event_listeners, (event), '', 0, 0)))
       _proxy_jslib_assign('', this._event_listeners, (event), '=', ( []));
     _proxy_jslib_handle(this._event_listeners, (event), '', 0, 0).push([el, handler]);
  }
}

function Dropdown(input, data, options) {
  if (!options) options = {};
  return Selector(input, options.autocomplete ? data : [], extend(
    {introText: '', multiselect: false, autocomplete: false, selectedItems: options.selectedItem},
    options,
    {defaultItems: data}
  ));
}
// Alias
function Autocomplete(input, data, options) {
  return Selector(input, data, options);
}


function Selector(input, data, options) {
  var self = this,
      guid = uiWindowDispatcher.getUID(),
      dataURL = typeof(data) == 'string' ? data : null,
      dataItems = isArray(data) ? data : [],
      undefined;

  var timeout, requestTimeout,
      selectedItems = [],
      selectedTokenId = 0,
      activeItemValue,
      hasFocus = 0,
      cache, select,
      disabled = false,
      defaultList = false,
      receivedData,
      changeAfterBlur = false;

  if (input == null ||  _proxy_jslib_handle(input, ('autocomplete'), '', 0, 0)) {
    return false;
  }

  // default options
  var defaults = {
    selectedItems: [],
    defaultItems: [],
    multiselect: true,
    autocomplete: true,
    dropdown: true,
    cacheLength: 0,
    showMax: 10,
    maxItems: 50,
    maxItemsShown: function(query_length) {
      if (query_length > 6) {
        return 500;
      } else if (query_length > 4) {
        return 200;
      } else if (query_length > 2) {
        return 150;
      } else {
        return 100;
      }
    },
    selectFirst: true,
    dividingLine: 'smart',
    enableCustom: false,
    valueForCustom: -1,
    width: 300,
    height: 250,
    progressBar: false,
    highlight: function(label, term) {
      label = term.indexOf(' ') == -1 ? label.split(' ') : [label];
      var tmp = '';
      var termRus = parseLatin(term);

      if (termRus != null) {
        term = term + '|' + termRus;
      }
      var re = new (RegExp)("(?![^&;]+;)(?!<[^<>]*)((\\(*)(" +  _proxy_jslib_handle(term, 'replace', '', 1, 0)('+', '\\+') + "))(?![^<>]*>)(?![^&;]+;)", "gi");
      for (var i in label) {
        tmp += (i > 0 ? ' ' : '') +  _proxy_jslib_handle( _proxy_jslib_handle(label, (i), '', 0, 0), 'replace', '', 1, 0)(re, "$2<em>$3</em>");
      }
      return tmp;
    },
    resultField:  _proxy_jslib_handle(input, ('name'), '', 0, 0) || 'selectedItems',
    customField:  _proxy_jslib_handle(input, ('name'), '', 0, 0) ? ( _proxy_jslib_handle(input, ('name'), '', 0, 0) + '_custom') : 'selectedItems_custom',
    placeholder: '',
    placeholderColor: '#afb8c2',
    introText: 'Start typing',
    noResult: getLang('search_nothing_found'),
    noImageSrc: 'http://vkontakte.ru/images/question_s.gif',
    formatResult: function(data) {
      return data[1] + (typeof(data[2]) == "string" ? " <span>" + data[2] + "</span>" : "");
    }
  };
  // extend default options with user defined

  function convertText_in_options(options) {
    each(['disabledText', 'placeholder'], function() {
      if (this in options) {
         _proxy_jslib_assign('', options, (this), '=', ( winToUtf(stripHTML( _proxy_jslib_handle(options, (this), '', 0, 0)))));
      }
    });
    return options;
  }
  if (!options) options = {};
  options = convertText_in_options(options);
  options = extend(defaults, options);
  if (dataItems.length) {
    sort(dataItems.length);
  }
  //if (options.defaultItems.length) sort(options.defaultItems);

  // if highlight is set to false, replace it with a do-nothing function
  options.highlight = options.highlight || function(label) { return label; };
  // Get selected value
  if(!isArray(options.selectedItems) && isEmpty(options.selectedItems)) {
    options.selectedItems = [];
  }
  if ( _proxy_jslib_handle(input, ('value'), '', 0, 0) && !options.selectedItems.length) {
    options.selectedItems =  _proxy_jslib_handle(input, ('value'), '', 0, 0);
  }

  cache = new (_Cache)(dataItems, options);

  var container, selector, resultList, resultListShadow, resultField, customField, dropdownButton, selectedItemsContainer, readOnly = '', scrollBarWidth = 0, mouseIsOver = false;
  var dropdown_html = options.dropdown ? '<td id="dropdown' + guid + '" class="selector_dropdown">&nbsp;</td>' : '';

  container = document.createElement("div");
  container.id = "container" + guid;
  container.className = "selector_container";

  if (!options.autocomplete) {
    readOnly = 'readonly="true"';
  }

  var customField_html = '<input type="hidden" name="' + options.customField + '" id="' + options.customField + '" value="" class="customField">';
   _proxy_jslib_assign('', container, 'innerHTML', '=', ( '<table cellspacing="0" cellpadding="0" class="selector_table"><tr><td class="selector"><span class="selected_items"></span><input type="text" class="selector_input" ' + readOnly + ' /><input type="hidden" name="' + options.resultField + '" id="' + options.resultField + '" value="" class="resultField">' + customField_html + '</td>' + dropdown_html + '</tr></table><div class="results_container"><div class="result_list" style="display:none;"></div><div class="result_list_shadow"><div class="shadow1"></div><div class="shadow2"></div></div></div>'));

  input.parentNode.replaceChild(container, input);

  selector = geByClass('selector', container)[0];
  resultList = geByClass('result_list', container)[0];
  if (browser.chrome) {
    resultList.style.opacity = 1;
  }
  resultListShadow = geByClass('result_list_shadow', container)[0];
  input = geByClass('selector_input', container)[0];
  input.style.color = options.placeholderColor;
  selectedItemsContainer = geByClass('selected_items', container)[0];

  if (!options.autocomplete) {
    addClass(container, 'dropdown_container');
  }
   _proxy_jslib_assign('', input, ("autocomplete"), '=', ( "1"));

  if (options.dividingLine) {
    addClass(resultList, 'dividing_line')
 }

  resultField = geByClass('resultField', container)[0];
  customField = geByClass('customField', container)[0];

  options.width = parseInt(options.width) > 0 ? parseInt(options.width) : defaults.width;
  options.height = parseInt(options.height) > 0 ? parseInt(options.height) : defaults.height;
  options.resultListWidth = parseInt(options.resultListWidth) > 0 ? parseInt(options.resultListWidth) : options.width;

  container.style.width = options.width + 'px';
  resultList.style.width = resultListShadow.style.width = options.resultListWidth + 'px';

   _proxy_jslib_assign('', selector, ('_width'), '=', ( options.width));

  function initDropdown() {
    dropdownButton = geByClass('selector_dropdown', container)[0];
    addEvent(dropdownButton, "mouseover", function() {
      addClass(this, "selector_dropdown_hover");
    });
    addClass(dropdownButton, "mouseout", function() {
      removeClass(this, "selector_dropdown_hover");
    });

    var fadeToColor, fadeToWhite;
    fadeToColor = function() {
      var state = window.is_rtl ? {backgroundColor: '#E1E8ED', borderRightColor: '#D2DBE0'} : {backgroundColor: '#E1E8ED', borderLeftColor: '#D2DBE0'};
      animate(dropdownButton, state, 200, function() {
        if (!mouseIsOver) {
          if (!select.isVisible()) {
            fadeToWhite();
          } else {
            dropdownButton.style.backgroundColor =  _proxy_jslib_assign('', dropdownButton.style, (window.is_rtl ? 'borderRightColor' : 'borderLeftColor'), '=', ( ''));
          }
        }
      });
    }
    fadeToWhite = function() {
      animate(dropdownButton, {backgroundColor: '#FFFFFF', borderLeftColor: '#FFFFFF'}, 200, function() {
        dropdownButton.style.backgroundColor =  _proxy_jslib_assign('', dropdownButton.style, (window.is_rtl ? 'borderRightColor' : 'borderLeftColor'), '=', ( ''));
        if (mouseIsOver) {
          fadeToColor();
        }
      });
    }
    addEvent(container, "mouseover", function() {
      mouseIsOver = true;
      if (disabled) return;
      fadeToColor();
    });
    addEvent(container, "mouseout", function() {
      mouseIsOver = false;
      if (disabled) return;
       _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)(function() {
        if (mouseIsOver) return;
        if (!select.isVisible()) {
          fadeToWhite();
        } else {
          dropdownButton.style.backgroundColor =  _proxy_jslib_assign('', dropdownButton.style, (window.is_rtl ? 'borderRightColor' : 'borderLeftColor'), '=', ( ''));
        }
      }, 0);
    });

    addEvent(dropdownButton, "mousedown", function() {
      if (!select.isVisible()) {
        showDefaultList();
      } else {
        select.toggle();
      }
    });

    var test = document.createElement("div");
    {var _proxy_jslib_with_objs= [] ;with (_proxy_jslib_with_objs[_proxy_jslib_with_objs.length]= (test.style)) {
      overflowY = "scroll";
      position = "absolute";
      height = "100px";
      width = "100px";
    }; _proxy_jslib_with_objs.length-- ;}
     _proxy_jslib_assign('', test, 'innerHTML', '=', ( '<div style="height:200px;">1<br/>1<br/>1<br/>1<br/></div>'));
    var body =  _proxy_jslib_handle(document, 'getElementsByTagName', '', 1, 0)('body')[0];
     _proxy_jslib_handle(null, 'body', body, 0, 0).appendChild(test);
    scrollbarWidth = test.offsetWidth -  _proxy_jslib_handle(test, 'getElementsByTagName', '', 1, 0)('div')[0].offsetWidth - 1;

    dropdownButton.style.width = scrollbarWidth + 'px';
     _proxy_jslib_assign('', selector, ('_width'), '-=', ( scrollbarWidth));
     _proxy_jslib_handle(null, 'body', body, 0, 0).removeChild(test);
    (test= _proxy_jslib_assign_rval('delete', 'test', '', '', (typeof test=='undefined' ? void 0 : test)));
  }

  function destroyDropdown() {
    dropdownButton = geByClass('selector_dropdown', container)[0];
    removeEvent(dropdownButton, "mouseover");
    removeEvent(dropdownButton, "mouseout");
    removeEvent(dropdownButton, "mousedown");
    removeEvent(container, "mouseover");
    removeEvent(container, "mouseout");
    scrollbarWidth = 0;
     _proxy_jslib_assign('', selector, ('_width'), '=', ( options.width));
  }

  if (options.dropdown) {
    initDropdown();
  }

  function updateInput() {
    if (!selectedItems.length && !hasFocus) {
       _proxy_jslib_assign('', input, 'value', '=', ( options.placeholder));
      input.style.color = options.placeholderColor;
    }
    if (!options.autocomplete && options.multiselect && selectedItems.length){
      hide(input);
    } else {
      if (!isVisible(input)) show(input);
      input.style.width = "20px";
      var w = window.is_rtl ? (input.offsetLeft + input.offsetWidth - 9) : ( _proxy_jslib_handle(selector, ('_width'), '', 0, 0) - input.offsetLeft - 9);
      input.style.width = Math.max(20, w) + 'px';
    }
  }
  updateInput();

  select = new (_Select)(resultList, resultListShadow, {
    selectFirst: options.selectFirst
 , height: options.height
 , onItemActive: function(value) {
      showImage( _proxy_jslib_handle(null, 'value', value, 0, 0));
      activeItemValue =  _proxy_jslib_handle(null, 'value', value, 0, 0);
    }
    , onItemSelect: selectItem
 , onShow: function() {
      highlightInput(true);
    }
    , onHide: function() {
      highlightInput(false);
    }
  });

  uiWindowDispatcher.attachListener(container, 'mousedown', function(e) {
    if (e.outside) {
      select.hide();
      deselectTokens();
    }
  });

  var keyevent = browser.opera || browser.mozilla ? 'keypress' : 'keydown';
  uiWindowDispatcher.attachListener(container, keyevent, function(e) {
    if (disabled ||  _proxy_jslib_handle(input, 'value', '', 0, 0).length > 0 && hasFocus || !hasFocus && selectedTokenId == 0) {
      return;
    }
    switch(e.keyCode) {
      case KEY.RETURN:
        return false;
      break;
      case KEY.LEFT:
        for (var i = selectedItems.length - 1; i >= 0; i--) {
          if (!selectedTokenId ||  _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0] == selectedTokenId && i > 0) {
            if (selectedTokenId) {
              i--;
            }
            selectToken( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0]);
            input.blur();
            break;
          }
        }
        return false;
        break;

      case KEY.RIGHT:
        for (var i = 0; i < selectedItems.length; i++) {
          if ( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0] == selectedTokenId) {
            if (i < selectedItems.length - 1) {
              selectToken( _proxy_jslib_handle(selectedItems, (i+1), '', 0, 0)[0]);
              input.blur();
            } else if (!readOnly) {
              deselectTokens();
              input.focus();
            }
            break;
          }
        }
        return false;
        break;

      case KEY.DEL:
        if (selectedTokenId) {
          var nextTokenId = 0;
          for (var i = selectedItems.length - 2; i >= 0; i--) {
            if ( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0] == selectedTokenId &&  _proxy_jslib_handle(selectedItems, (i+1), '', 0, 0)) {
              nextTokenId =  _proxy_jslib_handle(selectedItems, (i+1), '', 0, 0)[0];
            }
          }
          removeTagData(selectedTokenId);

          if (nextTokenId) {
            selectToken(nextTokenId);
          } else if (!readOnly && !hasFocus) {
            input.focus();
          }
        } else if (hasFocus && selectedItems.length) {
          selectToken( _proxy_jslib_handle(selectedItems, (selectedItems.length - 1), '', 0, 0)[0]);
        }
        return false;
        break;
    }
  });

  var keyevent = browser.msie || browser.safari || browser.chrome ? 'keydown' : 'keypress';

  addEvent(input, 'keypress', function(e) {
    if (e.which == KEY.RETURN && browser.opera && options.enableCustom && (select.selectedItem() === null)) {
      select.hide();
      input.blur();
      return false;
    } else if (e.which == KEY.SPACE || e.which > 40 && !e.metaKey) {
      clearTimeout(timeout);
      timeout =  _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)(function() { onChange(); }, 0);
    }
  });
  addEvent(input, 'keydown', function(e) {
    switch(e.keyCode) {
      case KEY.DOWN:
        if (!select.isVisible()) {
           _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)(showDefaultList, 0);
          return false;
        }
      break;
      case KEY.DEL:
        if ( _proxy_jslib_handle(input, 'value', '', 0, 0).length > 0) {
          clearTimeout(timeout);
          timeout =  _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)(function() { onChange(); }, 0);
        }
        return;
      break;
      case KEY.RETURN:
        if (!browser.opera && options.enableCustom && (select.selectedItem() === null)) {
          select.hide();
          input.blur();
          return false;
        }
      break;
    }
    //  return select.handleKeyEvent(e);
  });
  addEvent(input, 'focus', function() {
    debug('focus');
    if (!disabled && !select.isVisible()) {
      showDefaultList();
    }
    if (disabled || readOnly) {
      this.blur();
      return;
    }

    if ((selectedItems.length == 0) || options.multiselect) {
       _proxy_jslib_assign('', this, 'value', '=', ( ''));
    }
    addClass(this, 'focused');
    this.style.color = '#000';
    hasFocus++;
  });
  addEvent(input, 'blur', function() {
    if (readOnly) return;
    if (!disabled) {
      if (options.enableCustom &&  _proxy_jslib_handle(this, 'value', '', 0, 0).length) {
        var custom_val =  _proxy_jslib_handle(this, 'value', '', 0, 0);
        if (selectedItems.length == 0) {
           _proxy_jslib_assign('', resultField, 'value', '=', ( parseInt(!options.valueForCustom)));
           _proxy_jslib_assign('', customField, 'value', '=', ( custom_val));
          selectItem([options.valueForCustom, custom_val]);
        }
      } else if (selectedItems.length == 0) {
         _proxy_jslib_assign('', this, 'value', '=', ( options.placeholder));
      } else if (options.multiselect) {
         _proxy_jslib_assign('', this, 'value', '=', ( ''));
      }
      clearTimeout(requestTimeout);
      if (changeAfterBlur && isFunction(options.onChange)) {
        if (!options.enableCustom || !selectedItems.length) {
          options.onChange('');
        }
        changeAfterBlur = false;
      }
    }
    if (!hasClass(this, 'selected')) {
      this.style.color = options.placeholderColor;
    }
    removeClass(this, 'focused');
    hasFocus = 0;
  });

  function onInputClick(e) {
    deselectTokens();
    if (!select.isVisible()) {
      showDefaultList();
    } else {
      select.toggle();
    }
    if (!readOnly) input.focus();
    var event = e.originalEvent || e;
    if (event.preventDefault) {
      event.preventDefault();
    }
  }

  addEvent(selector, 'mousedown', function(e) {
    var click_over_token = false;
    var el = e.target;
    while (el != null) {
      if (hasClass(el, 'token')){
        click_over_token = true;
        break;
      }
      el = el.parentNode;
    }
    if (!click_over_token && !hasFocus) {
      return onInputClick(e);
    }
  });

  if (options.selectedItems !== undefined) {
    if (isArray(options.selectedItems)) {
      for (var i in options.selectedItems) {
        selectItem( _proxy_jslib_handle(options.selectedItems, (i), '', 0, 0), false);
      }
    } else {
      each((options.selectedItems + '').split(','), function(i, x) {
        selectItem(x, false);
      });
    }
  }

  // Select first item if it is dropdown
  if (!selectedItems.length && !options.autocomplete && !options.multiselect && options.defaultItems.length) {
    selectItem(options.defaultItems[0], false);
  }

  function highlightInput(focus) {
    if (focus) {
      addClass(container, "selector_focused");
    } else {
      removeClass(container, "selector_focused");
    }
  }

  function selectToken(id) {
    if (!options.multiselect) return;
    select.hide();
    removeClass(ge('bit_' + guid + '_' + selectedTokenId), 'token_selected');
    addClass(ge('bit_' + guid + '_' +  id), 'token_selected');
    selectedTokenId = id;
    if (options.onTokenSelected) options.onTokenSelected(id);
    showImage(id);
  }
  function deselectTokens() {
    if (!selectedTokenId || !options.multiselect) return;
    removeClass(ge('bit_' + guid + '_' + selectedTokenId), 'token_selected');
    selectedTokenId = 0;
    if (options.onTokenSelected) options.onTokenSelected();
    showImage();
  }
  function showImage(itemValue, itemData) {
    if (!options.imageId) {
      return false;
    }
    var img = ge(options.imageId);
    if (!img) return false;
    if (itemData === undefined) {
      if (!itemValue) { // 0 or undefined
        itemValue =  _proxy_jslib_handle(resultField, 'value', '', 0, 0).split(',')[0];
      }
      var data = selectedItems.concat(dataItems);
      if (data && data.length) {
        for (var i in data) {
          if ( _proxy_jslib_handle(data, (i), '', 0, 0)[0] == itemValue) {
            itemData =  _proxy_jslib_handle(data, (i), '', 0, 0);
            break;
          }
        }
      }
    }
    if (itemData !== undefined && typeof(itemData[3]) == 'string' && itemData[3].length) {
      if(itemData[3] == 'none'){
        img.style.display = 'none';
      } else {
        img.style.display = '';
         _proxy_jslib_handle(img, 'setAttribute', '', 1, 0)("src", itemData[3]);
         _proxy_jslib_assign('', img.parentNode, 'href', '=', ( '/id' + itemData[0])); // hack
        removeEvent(img.parentNode, 'click');
      }
    } else {
      img.style.display = '';
       _proxy_jslib_handle(img, 'setAttribute', '', 1, 0)("src", options.noImageSrc);
       _proxy_jslib_assign('', img.parentNode, 'href', '=', ( '#')); // hack
      addEvent(img.parentNode, 'click', function() { return false; });
    }
  }

  function selectItem(item, fireEvent, setFocus) {
    if (item == null) {
      return false;
    }
    if (fireEvent === undefined) {
      fireEvent = true;
    }
    var data;

    if (typeof(item) == 'object') {
      data = item;
    } else {
      var all_data = new (Array)();
      each([dataItems, options.defaultItems, receivedData], function(i,items) {
        if (items && items.length)
          all_data = all_data.concat(items);
      });
      for (var i in all_data) {
        if ( _proxy_jslib_handle(all_data, (i), '', 0, 0)[0] == item ||  _proxy_jslib_handle(all_data, (i), '', 0, 0) == item) {
          data =  _proxy_jslib_handle(all_data, (i), '', 0, 0);
          break;
        }
      }
    }

    if (typeof data != 'object') {
      data = [item, item]; // value and text
    };

    data[0] =  _proxy_jslib_handle(data[0], 'toString', '', 1, 0)();
    data[1] =  _proxy_jslib_handle(data[1], 'toString', '', 1, 0)();

    changeAfterBlur = false;

    if (data[0] ===  _proxy_jslib_handle(resultField, 'value', '', 0, 0)) {
      if (!options.multiselect) {
         _proxy_jslib_assign('', input, 'value', '=', ( winToUtf(stripHTML(data[1])))); // It could have changed in setData method
        showImage();
        if ( _proxy_jslib_handle(input, 'value', '', 0, 0).length || !options.placeholder) {
          addClass(input, 'selected');
          input.style.color = '#000';
        } else {
           _proxy_jslib_assign('', input, 'value', '=', ( options.placeholder));
          input.style.color = options.placeholderColor;
        }
      }
      return;
    }
    select.hide();
    if (selectedItems.length >= options.maxItems) {
      return;
    }

    deselectTokens();
    addTagData(data);
    showImage();

    if (options.multiselect) {
       _proxy_jslib_assign('', input, 'value', '=', ( ''));
      if (dataURL) {
        select.clear();
      } else {
        select.removeItem(data[0]);
      }
    } else {
       _proxy_jslib_assign('', input, 'value', '=', ( winToUtf(stripHTML(data[1]))));
      addClass(input, 'selected');
      input.style.color = '#000';
    }

    updateInput();

    if (setFocus&& !readOnly) {
      input.focus();
    } else if (!options.multiselect) {
      input.blur();
    }

    if (fireEvent) {
      if (options.multiselect && isFunction(options.onTagAdd)) {
        options.onTagAdd(data,  _proxy_jslib_handle(resultField, 'value', '', 0, 0));
      }
      if (isFunction(options.onChange)) {
        options.onChange( _proxy_jslib_handle(resultField, 'value', '', 0, 0));
      }
    }
  }

  function addTagData(data) {
    if (!data || data.length < 2) return false;
    if (!options.multiselect) {
      selectedItems.splice(0, selectedItems.length, data);
       _proxy_jslib_assign('', resultField, 'value', '=', ( data[0]));
      showImage(data[0], data);
      return;
    }
    for (var i in selectedItems) {
      if ( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0] == data[0]) {
        selectToken( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0]);
        return false;
      }
    }
    selectedItems.push(data);

    var resultArr = [];
    for (i in selectedItems) {
      resultArr.push( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0]);
    }
     _proxy_jslib_assign('', resultField, 'value', '=', ( resultArr.join(',')));

    input.style.width = '1px';

    // make box
    var token = document.createElement("div");
    token.id = "bit_" + guid + '_' + data[0];
    token.className = "token";

    var maxTokenWidth = Math.max(selector.clientWidth, getSize(token)[0]);

     _proxy_jslib_assign('', token, 'innerHTML', '=', ( '<span class="l">' + data[1] + '</span><span class="x" />'));

    addEvent(token, 'click', function() {
      selectToken(data[0]);
      return false;
    });
    addEvent(token, 'dblclick', function() {
      if(data[4]){
        removeTagData(data[0]);
        each(data[4], function(i,v) {
          selectItem(v, false);
        });
      }
      return false;
    });
    addEvent(token, 'mouseover', function(e) {
      addClass(token, 'token_hover');
      showImage(data[0], data);
    });
    addEvent(token, 'mouseout', function(e) {
      removeClass(token, 'token_hover');
      showImage(activeItemValue ? activeItemValue : selectedTokenId);
    });
    var close = geByClass('x', token)[0];
    addEvent( _proxy_jslib_handle(null, 'close', close, 0, 0), 'mousedown', function() {
      select.hide();
      removeTagData(data[0]);
      if (!readOnly && hasFocus) {
        input.focus();
      }
      return false;
    });
    selectedItemsContainer.appendChild(token);

    var label = token.firstChild;
    var labelStr =  _proxy_jslib_handle(label, 'innerHTML', '', 0, 0);
    while (token.offsetWidth > maxTokenWidth && labelStr.length > 3) {
       labelStr = labelStr.substr(0, labelStr.length - 2);
        _proxy_jslib_assign('', label, 'innerHTML', '=', ( labelStr + '...'));
    }
  }
  function removeTagData(id) {
    selectedTokenId = 0;
    var token = ge('bit_' + guid + '_' + id);
    token.parentNode.removeChild(token);

    var index, resultArr = [];
    for (i in selectedItems) {
      if ( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0] == id) {
        index = i;
        continue;
      }
      resultArr.push( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0]);
    }
    if (index == undefined) return false;

     _proxy_jslib_assign('', resultField, 'value', '=', ( resultArr.join(',')));

    if (options.onTagRemove) {
      options.onTagRemove( _proxy_jslib_handle(selectedItems, (i), '', 0, 0),  _proxy_jslib_handle(resultField, 'value', '', 0, 0));
    }
    if (isFunction(options.onChange)) {
      options.onChange( _proxy_jslib_handle(resultField, 'value', '', 0, 0));
    }
    selectedItems.splice(index, 1);
    if (options.multiselect) {
      defaultList = false;
    }
    showImage();
    updateInput();
    return false;
  }

  function onChange() {
    var term = trim( _proxy_jslib_handle(input, 'value', '', 0, 0).toLowerCase());
    if (!options.multiselect) {
      if (selectedItems.length) {
        changeAfterBlur = true;
      }
      clear();
    }
    clearTimeout(requestTimeout);
    if (term.length == 0) {
      showDefaultList();
      return false;
    }

//    var data = cache.load(term, (dataItems.length > 0)); // Sometimes it's still local.
    var data =  _proxy_jslib_handle(cache, 'load', '', 1, 0)(term, !dataURL);
    if (data == null && dataURL) {
        requestTimeout =  _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)(function() {
          request(receiveData, showNoDataList);
        }, 300);
    } else if (data != null){
      // receive the cached data
      if (data && data.length) {
        receiveData(term, data);
      } else {
        showNoDataList();
      }
    }
  };

  function showNoDataList() {
    if (hasFocus || readOnly) {
      _showSelectList(options.noResult);
      defaultList = false;
    }
  }
  function showDefaultList() {
    if (defaultList && select.hasItems()) {
      if (options.multiselect || !selectedItems.length)
        select.show();
      else
        select.show(selectedItems[0][0]);
    } else {
      defaultList = true;
      var text = options.autocomplete ? options.introText : null;
      _showSelectList(text, options.defaultItems);
    }
  }
  function showDataList(items, query) {
    defaultList = false;
    _showSelectList(null, items, query);
  }


  function _showSelectList(text, items, query) {
		// RTL fix
		if(window.is_rtl){
			var res_cont = geByClass('results_container', container)[0];
			var l = getXY(container)[0];
			if(l)res_cont.style.left = l + 'px';
		}

    items = isArray(items) && items.length ? items : [];
    select.clear();
    if (text) {
     select.appendItem({
       text: text,
       disabled: true
 });
    }
    if (items.length) {
      for (var i in items) {
        if (typeof  _proxy_jslib_handle(items, (i), '', 0, 0) != 'object')  _proxy_jslib_assign('', items, (i), '=', ( [ _proxy_jslib_handle(items, (i), '', 0, 0),  _proxy_jslib_handle(items, (i), '', 0, 0)]));
      }
      if (options.multiselect) {
        items = filterData(items);
      }

      if (options.dividingLine == 'smart') {
        removeClass(resultList, 'dividing_line');
        for (var i in items) {
          if (typeof( _proxy_jslib_handle(items, (i), '', 0, 0)[2]) == "string" &&  _proxy_jslib_handle(items, (i), '', 0, 0)[2].length) {
            addClass(resultList, 'dividing_line');
          }
        }
      }
      var itemsToShow = (options.autocomplete && query) ? options.maxItemsShown(query.length) : items.length;
      each(items, function() {
        if (!itemsToShow) {
          return;
        }
        var formatted = options.formatResult(this);
        if (query) {
          if (formatted = options.highlight(formatted, query)) {
            (itemsToShow= _proxy_jslib_assign_rval('--', 'itemsToShow', '', '', (typeof itemsToShow=='undefined' ? void 0 : itemsToShow)));
          }
        }
        if (!formatted) {
          return;
        }
        select.appendItem({
          value: this[0],
          text: formatted
 });
      });
      if (!text && !items.length) {
        return showNoDataList();
      }
    }
    if (options.multiselect || !selectedItems.length) {
      select.show();
    } else {
      select.show(selectedItems[0][0]);
    }
  }

  function receiveData(q, data) {
    if (q != "" && data && data.length && hasFocus) {
      receivedData = data;
      showDataList(data, q);
    } else {
      select.hide();
    }
  };

  function filterData(items) {
    var result = [];
    each(items, function(i) {
      for (var j in selectedItems) {
        if (this[0] ==  _proxy_jslib_handle(selectedItems, (j), '', 0, 0)[0])
          return;
      }
      result.push(this);
    });
    return result;
  }

  function request(success, failure) {
    if(dataURL)  {
      var term = trim( _proxy_jslib_handle(input, 'value', '', 0, 0).toLowerCase());
      if (term.length == 0) return;
      var sep = dataURL.indexOf('?') == -1 ? '?' : '&';
      var url = dataURL + sep + "str=" + encodeURI(term);
      var ajax = new (Ajax)(function(ajaxObj, data) {
        if (options.progressBar) {
          hide(options.progressBar);
        }
        try {
          data = eval(_proxy_jslib_proxify_js(('(' + data + ')'), 0, 0) );
        } catch (e) {}
        if (data.length) {
          cache.add(term, data);
          if (isFunction(success)) success(term, data);
        } else {
          cache.addEmpty(term);
          if (isFunction(failure)) failure(term);
        }
      });
      ajax.post(url);
      if (options.progressBar) {
        show(options.progressBar);
      }
    }
  };

  function sort(data) {
    var i, j, tmp;
    if (!data.length || data.length < 2) return data;
    for (i = 0; i < data.length - 1; i++) {
      for (j = i + 1; j < data.length; j++) {
        if ( _proxy_jslib_handle(data, (i), '', 0, 0)[1] >  _proxy_jslib_handle(data, (j), '', 0, 0)[1]) {
          tmp =  _proxy_jslib_handle(data, (i), '', 0, 0);
           _proxy_jslib_assign('', data, (i), '=', (  _proxy_jslib_handle(data, (j), '', 0, 0)));
           _proxy_jslib_assign('', data, (j), '=', ( tmp));
        }
      }
    }
  }

  function disable(value) {
    if ( _proxy_jslib_handle(null, 'value', value, 0, 0) && !disabled) {
      disabled = true;
      addClass(container, 'disabled');

      var s = getSize(container),
          h = document.createElement('div');
          h.className = "hide_mask";
      each({position: 'absolute', background: '#000', opacity: '0', filter:'alpha(opacity=0)', width: s[0] + 'px', height: s[1] + 'px', marginTop: -s[1] + 'px'}, function(k, v) {
         _proxy_jslib_assign('', h.style, (k), '=', ( v));
      });
      if (options.disabledText)  _proxy_jslib_assign('', input, 'value', '=', ( options.disabledText));
      container.appendChild(h);
      input.blur();
      input.style.color = "";
      select.hide();
    } else if (! _proxy_jslib_handle(null, 'value', value, 0, 0) && disabled) {
      disabled = false;
      if (options.autocomplete)  _proxy_jslib_assign('', input, 'value', '=', ( ''));
      removeClass(container, 'disabled');
      container.removeChild(geByClass('hide_mask', container)[0]);
    }
  }

  function clear() {
    showImage();

    if (options.multiselect) {
      selectedTokenId = 0;
       _proxy_jslib_assign('', selectedItemsContainer, 'innerHTML', '=', ( ''));
    }
    if (!options.multiselect && !options.autocomplete) {
      if (selectedItems[0] != options.defaultItems[0]) {
        selectItem(options.defaultItems[0], false);
      }
    } else {
      removeClass(input, 'selected');
       _proxy_jslib_assign('', resultField, 'value', '=', ( ''));
      selectedItems.splice(0, selectedItems.length);
    }

    return false;
  }


  // return object with public methods
   return {
    setURL: function(url) {
      if (typeof(url) == 'string') {
        dataURL = url;
        cache.flush();
        dataItems = [];
      }
    },
    setData: function(dataArr) {
      if (!isArray(dataArr)) return;
      if (!options.autocomplete){
        select.clear();
        options.defaultItems = dataArr;
        if (!options.multiselect) {
          if (!selectedItems.length && options.defaultItems.length) {
            selectItem(options.defaultItems[0], false);
          } else if (selectedItems.length) {
            var exists = false;
            for (var i in options.defaultItems) {
              var item =  _proxy_jslib_handle(options.defaultItems, (i), '', 0, 0)[0] ||  _proxy_jslib_handle(options.defaultItems, (i), '', 0, 0);
              if (item == selectedItems[0][0] || item == selectedItems[0][0]) {
                exists = true;
                break
              }
            }
            if (!exists) {
              selectItem(options.defaultItems[0], false);
            } else {
              selectItem(selectedItems[0][0], false);
            }
          }
        }
      } else {
        dataItems = dataArr;
        dataURL = null;
        cache.flush();
        cache.populate(dataItems);
      }
    },
    focus: function() {
      if (!readOnly) input.focus();
    },
    selectItem: function(item) {
      selectItem(item, false);
    },
    setOptions: function(new_options) {
      new_options = convertText_in_options(new_options);
      extend(options, new_options);
      if ("maxItems" in new_options && options.maxItems >= 0) {
        for (var i = selectedItems.length - 1; i >= options.maxItems; i--) {
          removeTagData( _proxy_jslib_handle(selectedItems, (i), '', 0, 0)[0]);
        }
      }

      if ("defaultItems" in new_options) {
        select.clear();
        if (select.isVisible(container)) {
          showDefaultList();
        }
      }

      if ("enableCustom" in new_options) {
        if (options.enableCustom && !options.autocomplete) {
          options.autocomplete = new_options.autocomplete = true;
        }
      }
      if ("width" in new_options) {
        container.style.width = options.width + 'px';
        resultList.style.width = resultListShadow.style.width = options.width + 'px';

         _proxy_jslib_assign('', selector, ('_width'), '=', ( options.width - scrollbarWidth));
      }
      if ("dropdown" in new_options) {
        var dd = geByClass('selector_dropdown', container)[0];
        if (!options.dropdown && dd) {
          destroyDropdown();
          dd.parentNode.removeChild(dd);
        } else if (!dd && options.dropdown) {
          dd = container.firstChild.rows[0].insertCell(1);
          dd.id = 'dropdown' + guid;
          dd.className = 'selector_dropdown';
           _proxy_jslib_assign('', dd, 'innerHTML', '=', ( '&nbsp;'));
          initDropdown();
        }
      }
      if (("width" in new_options) || ("autocomplete" in new_options) || ("dropdown" in new_options)) {
        updateInput();
      }
      if ("autocomplete" in new_options) {
        if (options.autocomplete) {
          removeClass(container, 'dropdown_container');
          input.readOnly = false;
          readOnly = '';
        } else {
          addClass(container, 'dropdown_container');
          input.readOnly = true;
          options.enableCustom = false;
          readOnly = 'readonly="true"';
        }
      }
    },
    disable: disable,
    val: function(value, fireEvent) {
      if ( _proxy_jslib_handle(null, 'value', value, 0, 0) !== undefined) selectItem( _proxy_jslib_handle(null, 'value', value, 0, 0), (fireEvent === undefined) ? false : fireEvent);
      return  _proxy_jslib_handle(resultField, 'value', '', 0, 0);
    },
    val_full: function() {
      if (options.multiselect) {
        return selectedItems;
      } else {
        if (selectedItems.length) {
          return selectedItems[0];
        } else {
          return [ _proxy_jslib_handle(resultField, 'value', '', 0, 0),  _proxy_jslib_handle(input, 'value', '', 0, 0)];
        }
      }
    },
    customVal: function(value, fireEvent) {
      if ( _proxy_jslib_handle(null, 'value', value, 0, 0) !== undefined) {
         _proxy_jslib_assign('', customField, 'value', '=', (  _proxy_jslib_handle(null, 'value', value, 0, 0)));
        selectItem([options.valueForCustom,  _proxy_jslib_handle(null, 'value', value, 0, 0)], (fireEvent === undefined) ? false : fireEvent);
      }
      return  _proxy_jslib_handle(customField, 'value', '', 0, 0);
    },
    selectedItems: function() {
      return selectedItems;
    },
    clear: function() {
      clear();
      updateInput();
    }
  };
}

function _Cache(dataItems, options) {

  var data = {};
  var length = 0;

  function matchSubset(s, sub) {
    var i, j;
    if (typeof(s) != 'string') return false;
    s = trim(stripHTML(s.toLowerCase()));
    while (1) {
      if (s.indexOf(sub) == 0) return true;
      if ((i = s.indexOf(' ')) == -1) {
        if ((i = s.indexOf('(')) == -1) return false;
      } else {
        if ((j = s.indexOf('(')) != -1) {
          i = i < j ? i : j;
        }
      }
      s = s.substr(i + 1);
    }
  };

  function add(q, add_data) {
    if (length > options.cacheLength){
      flush();
    }
    if (! _proxy_jslib_handle(data, (q), '', 0, 0)){
      length++;
    }
     _proxy_jslib_assign('', data, (q), '=', ( add_data));
  }

  function populate(dataItems) {
    // AntanubiS - enable void data set.
    if( !dataItems   ) return false;

    // track the matches
    var stMatchSets = {},
      nullData = 0;

    // no url was specified, we need to adjust the cache length to make sure it fits the local data store
    options.cacheLength = 1;

    // track all options for minChars = 0
     _proxy_jslib_assign('', stMatchSets, (""), '=', ( []));

    // loop through the array and create a lookup structure
    for ( var i = 0, ol = dataItems.length; i < ol; i++ ) {
      var rawData =  _proxy_jslib_handle(dataItems, (i), '', 0, 0);
      // if rawData is a string, make an array otherwise just reference the array
      rawData = (typeof rawData == "string") ? rawData.split('|') : rawData;

      var firstChar = rawData[1].charAt(0).toLowerCase();
      // if no lookup array for this character exists, look it up now
      if( ! _proxy_jslib_handle(stMatchSets, (firstChar), '', 0, 0) )
         _proxy_jslib_assign('', stMatchSets, (firstChar), '=', ( []));


      // push the current match into the set list
       _proxy_jslib_handle(stMatchSets, (firstChar), '', 0, 0).push(rawData);

      // keep track of minChars zero items
      if ( nullData++ < options.showMax ) {
         _proxy_jslib_handle(stMatchSets, (""), '', 0, 0).push(rawData);
      }
    };

    // add the data items to the cache
    each(stMatchSets, function(i, data) {
      // increase the cache size
      options.cacheLength++;
      // add to the cache
      add(i, data);
    });
  }

  // populate any existing data
  populate(dataItems);

  function flush() {
    data = {};
    length = 0;
  }

  return {
    flush: flush,
    add: add,
    populate: populate,
    addEmpty: function(q) {
       _proxy_jslib_assign('', data, (q), '=', ( []));
    },
    load: function(q, local) {
      if (!options.cacheLength || !length) {
        return null;
      }

      var csub = [];
      if (local) {
        for( var k in data ){
          // don't search through the stMatchSets[""] (minChars: 0) cache
          // this prevents duplicates
          if( k.length > 0 ){
            var c =  _proxy_jslib_handle(data, (k), '', 0, 0);
            each(c, function(i, x) {
              // if we've got a match, add it to the array
              if (matchSubset(x[1], q)) {
                csub.push(x);
              }
            });
          }
        }
      } else {
        if ( _proxy_jslib_handle(data, (q), '', 0, 0) == null) {return null};
         each( _proxy_jslib_handle(data, (q), '', 0, 0), function(i, x) {
          // if we've got a match, add it to the array
          if (matchSubset(x[1], q)) {
            csub.push(x);
          }
        });
      }

      return csub;
    }
  };
};


function _Select(container, shadow, options) {
  var CLASS = {
    FIRST: "first",
    LAST: "last",
    ACTIVE: "active",
    FIRST_ACTIVE: "first_active",
    LAST_ACTIVE: "last_active",
    SCROLLABLE: "result_list_scrollable"
 };
  var active = -1,
    data = [],
    list,
    maxHeight = options.height ? options.height : 250;

list = document.createElement('ul');
container.appendChild(list);
var keyevent = browser.opera ? 'keypress' : 'keydown';
uiWindowDispatcher.attachListener(list, keyevent, handleKeyEvent);

function handleKeyEvent(e) {
  if (!isVisible(container)) {
    return;
  }
  switch(e.keyCode) {
    case KEY.UP:
      moveSelect(-1)
 return false;
      break;

    case KEY.DOWN:
      moveSelect(1);
      return false;
      break;

    case KEY.PAGEUP:
      //select.pageUp();
      return false;
      break;

    case KEY.PAGEDOWN:
      //pageDown();
      return false;
      break;
    case KEY.TAB:
      if (isFunction(options.onItemSelect) && active > -1){
        options.onItemSelect(getSelectedItem());
        return false;
      }
      hideList();
    break;
    case KEY.RETURN:
      if (isFunction(options.onItemSelect) && active > -1){
        options.onItemSelect(getSelectedItem());
      }
      return false;
      break;
    case KEY.ESC:
      hideList();
      return false;
      break;
    }
  };
/** /
pageUp: function() {
      if (active != 0 && active - 8 < 0) {
        moveSelect( -active );
      } else {
        moveSelect(-8);
      }
    },
    pageDown: function() {
      if (active != list.childNodes.length - 1 && active + 8 > list.childNodes.length) {
        moveSelect(list.childNodes.length - 1 - active);
      } else {
        moveSelect(8);
      }
    },
/**/

  function clear() {
    //hideList();
    active = -1;
     _proxy_jslib_assign('', list, 'innerHTML', '=', ( ''));
    updateContainer();
    debug('clear select');
  };


  function getSelectedItem() {
    if (active >= 0 &&  _proxy_jslib_handle(list.childNodes, (active), '', 0, 0)) {
      var item =  _proxy_jslib_handle(list.childNodes, (active), '', 0, 0);
      var value =  _proxy_jslib_handle(item, ('_value'), '', 0, 0) ||  _proxy_jslib_handle(item, 'innerHTML', '', 0, 0);
      return  _proxy_jslib_handle(null, 'value', value, 0, 0);
    }
    return null;
  }

  function moveSelect(step) {
    if (movePosition(step)) {
      highlight( _proxy_jslib_handle(list.childNodes, (active), '', 0, 0));
    }
  };

  function movePosition(step) {
    var selected = parseInt(active) + parseInt(step);
    if (selected < 0)
      container.scrollTop = 0;
    else if (selected + 1 > list.childNodes.length)
      container.scrollTop = list.offsetTop + list.offsetHeight - container.offsetHeight;
    while (1) {
      if (selected + 1 > list.childNodes.length || selected < 0) {
        return false;
      }
      if (! _proxy_jslib_handle( _proxy_jslib_handle(list.childNodes, (selected), '', 0, 0), ('_disabled'), '', 0, 0)) {
        break;
      }
      selected++;
    }


    active = selected;
    return true;
  };

  function highlight(obj) {
    if (!obj) return;
    each(list.childNodes, function(i, li) {
      removeClass(li, CLASS.ACTIVE);
    });
    addClass(obj, CLASS.ACTIVE);
    removeClass(list.firstChild, CLASS.FIRST_ACTIVE);
    removeClass(list.lastChild, CLASS.LAST_ACTIVE);
    if (obj == list.firstChild) {
      addClass(obj, CLASS.FIRST_ACTIVE);
    } else if (obj == list.lastChild) {
      addClass(obj, CLASS.LAST_ACTIVE);
    }
    if (isFunction(options.onItemActive)) {
      options.onItemActive( _proxy_jslib_handle(obj, ('_value'), '', 0, 0) ||  _proxy_jslib_handle(obj, 'innerHTML', '', 0, 0));
    }
    if (obj.offsetTop + obj.offsetHeight + list.offsetTop > container.offsetHeight + container.scrollTop - 1) {
      container.scrollTop = obj.offsetTop + list.offsetTop + obj.offsetHeight - container.offsetHeight + 1;
    } else if (obj.offsetTop + list.offsetTop < container.scrollTop) {
      container.scrollTop = obj.offsetTop + list.offsetTop;
    }

  };

  function onMouseMove_item(e) {
    if (hasClass(this, 'active')) return false;
    active = indexOf(list.childNodes, this);
    highlight(this);
  }

  function onClick_item(e) {
    var value =  _proxy_jslib_handle(this, ('_value'), '', 0, 0) ||  _proxy_jslib_handle(this, 'innerHTML', '', 0, 0);
    if (isFunction(options.onItemSelect)) {
      options.onItemSelect( _proxy_jslib_handle(null, 'value', value, 0, 0));
    }
    hideList();
  }

  function updateContainer() {
    if (maxHeight < list.offsetHeight) {
      container.style.height = maxHeight + 'px';
      show(shadow);
      shadow.style.marginTop = (maxHeight + 1) + 'px'; // +1 - because of border-bottom
      addClass(container, CLASS.SCROLLABLE);
    } else {
      removeClass(container, CLASS.SCROLLABLE);
      container.style.height = 'auto';
      var shadow_height = intval(list.offsetHeight) + intval(list.offsetTop);
      if (shadow_height) {
        show(shadow);
        shadow.style.marginTop = shadow_height + 'px';
      } else {
        hide(shadow);
      }
    }
  }

  function appendItem(item) {
    if (typeof item != 'object') return false;
    if (list.lastChild) {
      removeClass(list.lastChild, CLASS.LAST_ACTIVE);
      removeClass(list.lastChild, CLASS.LAST);
    }
    var li = document.createElement("li");

    item.text = item.text === undefined ? '' :  _proxy_jslib_handle(item.text, 'toString', '', 1, 0)();
     _proxy_jslib_assign('', item, 'value', '=', (  _proxy_jslib_handle(item, 'value', '', 0, 0) === undefined ? '' :  _proxy_jslib_handle( _proxy_jslib_handle(item, 'value', '', 0, 0), 'toString', '', 1, 0)()));
     _proxy_jslib_assign('', li, 'innerHTML', '=', ( item.text ||  _proxy_jslib_handle(item, 'value', '', 0, 0)));
     _proxy_jslib_assign('', li, ('_value'), '=', (  _proxy_jslib_handle(item, 'value', '', 0, 0) || ''));
    list.appendChild(li);

    if (item.disabled) {
       _proxy_jslib_assign('', li, ('_disabled'), '=', ( true));
      addClass(li, 'disabled');
    } else {
      addEvent(li, 'mousemove', onMouseMove_item);
      addEvent(li, 'mousedown', onClick_item);
    }
    addClass(list.lastChild, CLASS.LAST);
    if (list.childNodes.length == 1) {
      addClass(list.firstChild, CLASS.FIRST);
    }
    updateContainer();
  }

  function removeItem(value) {
    if ( _proxy_jslib_handle(null, 'value', value, 0, 0) === undefined) return;
    for (var i in list.childNodes) {
      var node =  _proxy_jslib_handle(list.childNodes, (i), '', 0, 0);
      if (node && ( _proxy_jslib_handle(node, ('_value'), '', 0, 0) ==  _proxy_jslib_handle(null, 'value', value, 0, 0) ||  _proxy_jslib_handle(node, 'innerHTML', '', 0, 0) ==  _proxy_jslib_handle(null, 'value', value, 0, 0))) {
        node.parentNode.removeChild(node);
        break;
      }
    }
    updateContainer();
  }

// AntanubiS - if list.offsetHeight is greater, than screen without scrollbar - bugs.
  function performShow() {
    list.style.position = 'absolute';
    list.style.visibility = 'hidden';
    show(container);// We see bug in MessageBox with Selector between theese lines.
    show(shadow);
    updateContainer();
    list.style.position = 'relative';
    list.style.visibility = 'visible';
  }

  function showList(selectedItem) {
    var wasVisible = isVisible(container);
    if (!wasVisible) {
      performShow();
      debug('show list' + container.parentNode.parentNode.id);
    }

    var childNode;
    if (selectedItem) {
      for (var i = 0; i < list.childNodes.length; i++) {
        childNode =  _proxy_jslib_handle(list.childNodes, (i), '', 0, 0);
        if ( _proxy_jslib_handle(childNode, ('_value'), '', 0, 0) == selectedItem) {
          active = i;
          highlight(childNode);
          break;
        }
      }
    } else if (options.selectFirst) {
      for (var i = 0; i < list.childNodes.length; i++) {
        childNode =  _proxy_jslib_handle(list.childNodes, (i), '', 0, 0);
        if (! _proxy_jslib_handle(childNode, ('_disabled'), '', 0, 0)) {
          active = i;
          highlight(childNode);
          break;
        }
      }
    }

    if (!wasVisible && isFunction(options.onShow)) options.onShow();
  }
  function hideList() {
    if (!isVisible(container)) return;
    debug('hide list');
    hide(container);
    hide(shadow);
    if (isFunction(options.onHide)) options.onHide();
    active = -1;
    if (isFunction(options.onItemActive)) options.onItemActive();
  }

  return {
    data: data,
    clear: clear,
    isVisible: function() {
      return isVisible(container);
    },
    hasItems: function() {
      return list.childNodes.length > 0;
    },
    toggle: function() {
      if (this.isVisible(container)) hideList();
      else {
        showList();
      }
    },
    handleKeyEvent: function(e) {
      if (isVisible(container))
        handleKeyEvent(e);
    },
    hide: hideList,
    show: showList,
    selectedItem: getSelectedItem,
    appendItem: appendItem,
    removeItem: removeItem
 };
};

function Checkbox(input, options) {
  var self = this,
      guid = uiWindowDispatcher.getUID(),
      undefined;

  var disabled = false;

  if (input == null) {
    return false;
  }

  // default options
  var defaults = {
    checked:  _proxy_jslib_handle(input, ('value'), '', 0, 0),
    checkedValue: 1,
    notCheckedValue: '',
    width: 300,
    label: 'checkbox',
    resultField:  _proxy_jslib_handle(input, ('name'), '', 0, 0) || 'checkbox'
 };
  // extend default options with user defined
  options = extend(defaults, options);

  options.checked = intval(options.checked) ? true : false;

  var container, checkbox, resultField, is_over = false;

  container = document.createElement("div");
  container.id = "container" + guid;
  container.className = "checkbox_container";

   _proxy_jslib_assign('', container, 'innerHTML', '=', ( '<table cellpadding=0 cellspacing=0><tr><td class="checkbox"><div class="checkbox_off"></div></td><td class="checkbox_label">' + options.label + '<input type="hidden" name="' + options.resultField + '" id="' + options.resultField + '" value=""></td></tr></table>'));

  input.parentNode.replaceChild(container, input);

  checkbox = geByClass('checkbox_off', container)[0];
  resultField = ge(options.resultField);
   _proxy_jslib_assign('', resultField, 'value', '=', ( options.checked ? options.checkedValue : options.notCheckedValue));

  options.width = intval(options.width) > 0 ? intval(options.width) : defaults.width;

  container.style.width = options.width + 'px';

  addEvent(container, 'click', function(e) {
    if (!disabled) {
      setState(!options.checked);
    }
  });

  addEvent(container, 'mouseover', function(e) {
    is_over = true;
    updateClass();
  });

  addEvent(container, 'mouseout', function(e) {
    is_over = false;
    updateClass();
  });

  function disable(value) {
    if ( _proxy_jslib_handle(null, 'value', value, 0, 0) && !disabled) {
      disabled = true;
      addClass(container, 'disabled');
    } else if (! _proxy_jslib_handle(null, 'value', value, 0, 0) && disabled) {
      disabled = false;
      removeClass(container, 'disabled');
    }
  }

  function updateClass() {
    if (is_over && options.checked) {
      checkbox.className = 'checkbox_on_over';
    } else if (is_over) {
      checkbox.className = 'checkbox_off_over';
    } else if (options.checked) {
      checkbox.className = 'checkbox_on';
    } else {
      checkbox.className = 'checkbox_off';
    }
  }

  function setState(checked, fireEvent, forceUpdate) {
    if (fireEvent === undefined) fireEvent = true;
    if (forceUpdate === undefined) forceUpdate = false;

    checked = checked ? true : false;
    if (options.checked == checked && !forceUpdate) {
      return;
    }
    options.checked = checked;
    updateClass();
     _proxy_jslib_assign('', resultField, 'value', '=', ( options.checked ? options.checkedValue : options.notCheckedValue));
    if (fireEvent && isFunction(options.onChange)) {
      options.onChange( _proxy_jslib_handle(resultField, 'value', '', 0, 0));
    }
  }
  setState(options.checked, false, true);

  // return object with public methods
   return {
    setOptions: function(new_options) {
      extend(options, new_options);
      if (("checked" in new_options) || ("checkedValue" in new_options) || ("notCheckedValue" in new_options)) {
        setState(options.checked, false, true);
      }
    },
    disable: disable,
    checked: function(value) {
      if ( _proxy_jslib_handle(null, 'value', value, 0, 0) !== undefined) setState( _proxy_jslib_handle(null, 'value', value, 0, 0));
      return options.checked;
    },
    val: function() {
      return  _proxy_jslib_handle(resultField, 'value', '', 0, 0);
    }
  };
}

var uiRadioButtonsData = {
  _radio_buttons: {},
  _callbacks: {},
  register: function(name, button) {
    if (!isArray( _proxy_jslib_handle(this._radio_buttons, (name), '', 0, 0))) {
       _proxy_jslib_assign('', this._radio_buttons, (name), '=', ( []));
    }
     _proxy_jslib_handle(this._radio_buttons, (name), '', 0, 0).push(button);
  },

  deselect: function(name) {
    for (var i = 0; i <  _proxy_jslib_handle(this._radio_buttons, (name), '', 0, 0).length; (i= _proxy_jslib_assign_rval('++', 'i', '', '', (typeof i=='undefined' ? void 0 : i)))) {
       _proxy_jslib_handle( _proxy_jslib_handle(this._radio_buttons, (name), '', 0, 0), (i), '', 0, 0).checked(false);
    }
  },

  select: function(name, value) {
    for (var i = 0; i <  _proxy_jslib_handle(this._radio_buttons, (name), '', 0, 0).length; (i= _proxy_jslib_assign_rval('++', 'i', '', '', (typeof i=='undefined' ? void 0 : i)))) {
      if ( _proxy_jslib_handle( _proxy_jslib_handle(this._radio_buttons, (name), '', 0, 0), (i), '', 0, 0).val() ==  _proxy_jslib_handle(null, 'value', value, 0, 0)) {
         _proxy_jslib_handle( _proxy_jslib_handle(this._radio_buttons, (name), '', 0, 0), (i), '', 0, 0).checked(true);
        return;
      }
    }
  },

  setChangeEvent: function(name, callback) {
    if (isFunction(callback))  _proxy_jslib_assign('', this._callbacks, (name), '=', ( callback));
    else  _proxy_jslib_assign('delete', (this._callbacks), (name), '');
  },

  _onValueChange: function(name, value) {
    if (isFunction( _proxy_jslib_handle(this._callbacks, (name), '', 0, 0)))
       _proxy_jslib_handle(this._callbacks, (name), '', 1, 0)( _proxy_jslib_handle(null, 'value', value, 0, 0));
  }
}

function Radiobutton(input, options) {
  var self = this,
      guid = uiWindowDispatcher.getUID(),
      undefined;

  var disabled = false;

  if (input == null) {
    return false;
  }

  // default options
  var defaults = {
    checked: false,
    value:  _proxy_jslib_handle(input, ('value'), '', 0, 0),
    width: 300,
    label: 'radiobutton',
    resultField:  _proxy_jslib_handle(input, ('name'), '', 0, 0) || 'radiobutton'
 };
  // extend default options with user defined
  options = extend(defaults, options);

  options.checked = intval(options.checked) ? true : false;

  var container, radiobutton, resultField, is_over = false;

  container = document.createElement("div");
  container.id = "container" + guid;
  container.className = "radiobtn_container";

  var checked_property = options.checked ? 'checked="true"' : '';

   _proxy_jslib_assign('', container, 'innerHTML', '=', ( '<table cellpadding=0 cellspacing=0><tr><td class="radiobtn"><div class="radiobtn_off"><div></div></div></td><td class="radiobtn_label">' + options.label + '<input type="radio" name="' + options.resultField + '" id="' + input.id + '" ' + checked_property + ' /></td></tr></table>'));

  input.parentNode.replaceChild(container, input);

  radiobutton = geByClass('radiobtn_off', container)[0];
  resultField =  _proxy_jslib_handle(container, 'getElementsByTagName', '', 1, 0)('input')[0];
   _proxy_jslib_assign('', resultField, 'value', '=', (  _proxy_jslib_handle(options, 'value', '', 0, 0)));

  options.width = intval(options.width) > 0 ? intval(options.width) : defaults.width;

  container.style.width = options.width + 'px';

  addEvent(container, 'click', function(e) {
    if (!disabled && !options.checked) {
      setState(true);
    }
  });

  addEvent(container, 'mouseover', function(e) {
    is_over = true;
    updateClass();
  });

  addEvent(container, 'mouseout', function(e) {
    is_over = false;
    updateClass();
  });

  function disable(value) {
    if ( _proxy_jslib_handle(null, 'value', value, 0, 0) && !disabled) {
      disabled = true;
      addClass(container, 'disabled');
    } else if (! _proxy_jslib_handle(null, 'value', value, 0, 0) && disabled) {
      disabled = false;
      removeClass(container, 'disabled');
    }
  }

  function updateClass() {
    if (is_over && options.checked) {
      radiobutton.className = 'radiobtn_on_over';
    } else if (is_over) {
      radiobutton.className = 'radiobtn_off_over';
    } else if (options.checked) {
      radiobutton.className = 'radiobtn_on';
    } else {
      radiobutton.className = 'radiobtn_off';
    }
  }

  function setState(checked, fireEvent, forceUpdate) {
    if (fireEvent === undefined) fireEvent = true;
    if (forceUpdate === undefined) forceUpdate = false;

    checked = checked ? true : false;
    if (options.checked == checked && !forceUpdate)
      return;
    if (checked)
      uiRadioButtonsData.deselect(options.resultField);
    options.checked = checked;
    updateClass();
    resultField.checked = checked;
    if (fireEvent) {
      if (options.checked && isFunction(options.onSelect))
        options.onSelect( _proxy_jslib_handle(resultField, 'value', '', 0, 0));

      if (isFunction(options.onChange))
        options.onChange( _proxy_jslib_handle(resultField, 'value', '', 0, 0), checked);

      if (checked)
        uiRadioButtonsData._onValueChange(resultField.name,  _proxy_jslib_handle(resultField, 'value', '', 0, 0));
    }
  }
  setState(options.checked, false, true);

  // return object with public methods
  var result = {
    setOptions: function(new_options) {
      extend(options, new_options);
      if ("checked" in new_options) {
        options.checked = !options.checked;
        setState(!options.checked, false);
      }
    },
    disable: disable,
    checked: function(value) {
      if ( _proxy_jslib_handle(null, 'value', value, 0, 0) !== undefined) setState( _proxy_jslib_handle(null, 'value', value, 0, 0));
      return options.checked;
    },
    val: function() {
      return  _proxy_jslib_handle(resultField, 'value', '', 0, 0);
    }
  };
  uiRadioButtonsData.register(resultField.name, result);
  return result;
}

function Autosize(textarea, options) {
  var self = this,
      guid = uiWindowDispatcher.getUID(),
      undefined;

  if (textarea == null) {
    return false;
  }

  // default options
  var defaults = {
    height: 0,
    minHeight: 0
 };
  // extend default options with user defined
  options = extend(defaults, options);

  var input = textarea, autosizeHelpers, helper;
  var oldValue, oldHeight, minHeight, maxHeight, fontSize;
  autosizeHelpers = ge('autosize_helpers');
  if (!autosizeHelpers) {
    autosizeHelpers = document.createElement('div');
    autosizeHelpers.id = 'autosize_helpers';
    autosizeHelpers.style.position = 'absolute';
    autosizeHelpers.style.left = '-10000px';
     _proxy_jslib_assign('', autosizeHelpers.style, 'top', '=', ( '-10000px'));
     _proxy_jslib_handle(document, 'body', '', 0, 0).appendChild(autosizeHelpers);
  }
  helper = document.createElement('div');
  autosizeHelpers.appendChild(helper);

  minHeight = intval(options.minHeight);
  maxHeight = intval(options.height);
  if (!minHeight) {
    minHeight = intval(getStyle(input, 'height'));
  }
  fontSize = intval(getStyle(input, 'fontSize'));
  input.style.overflow = 'hidden';
  var w = intval(getStyle(input, 'width'));
  // fix for hidden textareas
  if (w < 1) {
    w = intval(getStyle(input, 'width', false));
  }
  helper.style.width = (w < 0 ? 0 : w) + 'px';
  helper.style.fontFamily = getStyle(input, 'fontFamily');
  helper.style.fontSize = fontSize + 'px';
  helper.style.lineHeight = getStyle(input, 'lineHeight');

  function updateSize(handleEvent) {
    return function(event) {
      var value =  _proxy_jslib_handle(input, 'value', '', 0, 0);
      if (handleEvent) {
        if (event.keyCode == 13 && !event.ctrlKey && !event.altKey) {
           value= _proxy_jslib_assign_rval('', 'value', '+=', ( '\n'), (typeof value=='undefined' ? void 0 : value));
        }
      }
      if ( _proxy_jslib_handle(null, 'value', value, 0, 0) == oldValue) {
        return;
      }
      oldValue =  _proxy_jslib_handle(null, 'value', value, 0, 0);
       _proxy_jslib_assign('', helper, 'innerHTML', '=', (  _proxy_jslib_handle(trim(replaceChars( _proxy_jslib_handle(null, 'value', value, 0, 0))), 'replace', '', 1, 0)(/<br>$/, '<br>&nbsp;')));

      var newHeight = getSize(helper, true)[1] + fontSize;
      if (newHeight < minHeight) {
        newHeight = minHeight;
      }
      if (maxHeight > 0 && newHeight > maxHeight) {
        newHeight = maxHeight;
        input.style.overflow = 'auto';
      } else {
        input.style.overflow = 'hidden';
      }
      if (oldHeight != newHeight) {
        input.style.height = (oldHeight = newHeight) + 'px';
        if (options.onResize) options.onResize(newHeight);
      }
    }
  }
  addEvent(input, 'keydown', updateSize(true));
  addEvent(input, 'keypress', updateSize(true));
  addEvent(input, 'keyup', updateSize(false));

  updateSize(false)();

  return {
    update: updateSize(false)
 }
}

/* Dropdown Menu */

function DropdownMenu(items, options) {
  if (this == window) throw "Use new DropdownMenu";
  if (!options) options = {};
  var self = this;
  var id = this.guid = uiWindowDispatcher.getUID();
  this.options = {};
  if (!options.title && options.target) options.title =  _proxy_jslib_handle(options.target, 'innerHTML', '', 0, 0);

  options = extend({}, this.defaults, options);

  this.container = document.createElement('div');
  this.visible = false;
  var c = this.container;
  c.className = 'dd_menu';
  this.header = document.createElement('div');
  extend(this.header, {className: 'dd_menu_header', innerHTML: '<div>'+this.options.title+'</div>'});
   _proxy_jslib_assign('', this, 'body', '=', ( document.createElement('div')));
  extend( _proxy_jslib_handle(this, 'body', '', 0, 0), {className: 'dd_menu_body', innerHTML: '<table cellspacing="0" cellpadding="0"><tbody><tr><td class="dd_menu_shad_l"><div></div></td><td><div id="dd_rows_'+id+'" class="dd_menu_rows"></div><div class="dd_menu_shad_b"></div><div class="dd_menu_shad_b2"></div></td><td class="dd_menu_shad_r"><div> </div></td></tr></tbody></table>'});
  c.appendChild(this.header);
  c.appendChild( _proxy_jslib_handle(this, 'body', '', 0, 0));
  hide(this.header);
  hide( _proxy_jslib_handle(this, 'body', '', 0, 0));

  // Container for menu items
  this.rows = document.createElement('div');
  this.rows.id = 'rows' + id;

  if (isArray(items) && items.length)
    for (var i=0; i<items.length; i++)
      this.addItem( _proxy_jslib_handle(items, (i), '', 0, 0));

  this.mouseTimer = 0;
  addEvent(c, 'mouseover mouseout', this.__onMouseEvent.bind(this));

  this.onHide = function(fade) {
    this.visible = false;
    if (fade || !this.options.showHover) hide(this.header);
    else addClass(this.header, 'dd_header_hover');
    hide( _proxy_jslib_handle(this, 'body', '', 0, 0));
    if (this.options.onHide) this.options.onHide();
  }

  onDomReady(function() {
     _proxy_jslib_handle(document, 'body', '', 0, 0).appendChild(c);
    var header = self.header, body =  _proxy_jslib_handle(self, 'body', '', 0, 0);
     _proxy_jslib_assign('',  _proxy_jslib_handle(null, 'body', body, 0, 0).style, 'top', '=', ( getSize(header)[1] - 1 + 'px'));
    ge('dd_rows_'+id).appendChild(self.rows);
    self.setOptions(options);
    if (options.target) {
      options.target.onclick = function() {self.show();return false;};
    }
    if (options.target && options.showHover) {
      var timer;
      var outFunc = function() {
        if (!self.visible) hide(header);
        removeClass(header, 'dd_header_hover');
      }
      addEvent(options.target, 'mouseover', function() {
        addClass(header, 'dd_header_hover');
        self.moveToTarget();
        show(header);
        timer =  _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)(outFunc, 100);
      });
      addEvent(header, 'mouseover', function() {
        clearTimeout(timer);
      });
      addEvent(header, 'mouseout', outFunc);
    }
  });
}
DropdownMenu.prototype = {
  moveTo: function(left, top) {
    extend(this.container.style, {top: intval( _proxy_jslib_handle(null, 'top', top, 0, 0))+'px', left: intval(left) + 'px'});
  },
  moveToTarget: function() {
    var tc = getXY(this.options.target);
    if (/mac/.test(_ua) && browser.mozilla) {
      tc[1] += 1; // offset fix
    }
    this.moveTo(tc[0] + this.options.offsetLeft, tc[1] + this.options.offsetTop);
  },
  addItem: function(item) {
    var link = document.createElement('a');
     _proxy_jslib_assign('', link, 'innerHTML', '=', ( item.l));
    if (item.i)  _proxy_jslib_assign('', link, ('index'), '=', ( item.i));
    if (item.c) link.className = c;
    if (item.s) extend(link.style, item.s);
    if (item.b) extend(link.style, {backgroundImage: "url('"+item.b+"')", paddingLeft: '27px' });
    var self = this;
    addEvent(link, 'click', function(e) {
      var hide = true;
      if (isFunction(item.onClick) && item.onClick(e) === false)
        hide = false;
      if (self.options.onSelect(e) === false)
        hide = false;
      if (hide) self.hide();
    });
    if (browser.msie) {
      link.onmouseover = function() {addClass(link, 'dd_a_hover');};
      link.onmouseout = function() {removeClass(link, 'dd_a_hover');};
    }
    this.rows.appendChild(link);
  },
  getRows: function() {
    return this.rows;
  },
  setOptions: function(options) {
    var self = this;
    extend(this.options, options);
    // apply options

    if (options.title)
       _proxy_jslib_assign('', this.header, 'innerHTML', '=', ( '<div>'+this.options.title+'</div>'));
    if (typeof options.hideOnClick != 'undefined')
      this.header.onclick = options.hideOnClick ? this.toggle.bind(this) : this.show.bind(this);
  },

  toggle: function() {
    this.visible ? this.hide(false) : this.show();
  },
  show: function() {
    if (this.visible) return;
    if (this.options.target && !this.options.showHover) this.moveToTarget();
    clearTimeout(this.mouseTimer);
    show(this.header);
    show( _proxy_jslib_handle(this, 'body', '', 0, 0));
    if (this.options.showHover) removeClass(this.header, 'dd_header_hover');
    this.visible = true;
  },
  hide: function(fade) {
    if (!this.visible) return;
    var self = this;
    (fade === false) ? this.onHide(false) : fadeOut(this.container, 100, function() {
      show(self.container);
      self.onHide.call(self, true);
    });
  },

  // Private fields and methods
  __onMouseEvent: function(e) {
    clearTimeout(this.mouseTimer);
    if (e.type == 'mouseout') {
      this.mouseTimer =  _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)(this.hide.bind(this), 400);
    }
  }
};
DropdownMenu.prototype.defaults = {
  title: 'Menu',
  hideOnClick: true,
  showHover: true,
  offsetLeft: -7,
  offsetTop: -4,
  onSelect: function() {}
}; ;
_proxy_jslib_flush_write_buffers() ;