Вход Регистрация
Файл: js/lib/ui_controls.js
Строк: 3443
<?php
// Classes:
//   Dropdown / Autocomplete / Selector
//   Select
//   Checkbox
//   Radiobutton
//   Autosize
//   DropdownMenu
//   Cache
//   Indexer

var UI_CONTROLS_DEBUG false;
function 
debug(e) {
  if (!
UI_CONTROLS_DEBUG) return;
  
debugLog(e);
}
if (!
window.vkvk = {};

//
// OOP functions
//
function inherit(childparent) {
  var 
= function() {};
  
F.prototype parent.prototype;
  
child.prototype = new F();
  
child.prototype.constructor child;
  
child.superclass parent.prototype;
}

function 
createChildClass(classNameparentproto) {
  var 
code 'function ' className ' (a, b, c, d) {
    if (this == window || this.setInterval) return new ' 
className '(a, b, c, d);
    this.__className = "' 
className '";
    return this.__construct__(arguments);
  };'
;

  if (
window.execScript) {
    
window.execScript(code);
  } else {
    
window.eval(code);
  }
  
childClass = eval('(' className ')');
  
inherit(childClassparent);
  if ((
'common' in proto)) {
    
extend(childClassproto['common']);
    
proto['common'] = childClass;
  }
  
extend(childClass.prototypeproto);
}

if (
window._ui === undefined) {
  var 
_ui = {
    
_guid0,
    
_selfalse,
    
_uids: [false],
    
reg: function(obj) {
      
_ui._uids.push(obj);
      return ++
_ui._guid;
    },
    
sel: function(nsel) {
      if (
nsel !== undefined) {
        var 
_ui.selobj();
        if (
&& s._blur) {
          
s._blur();
        }
        
_ui._sel nsel;
      }
      return 
_ui._sel;
    },
    
selobj: function(val) {
      if (
_ui._sel && val !== undefined) {
        
_ui._uids[_ui._sel] = val;
      }
      return 
_ui._uids[_ui._sel];
    }
  }

  
addEvent(document'keypress keydown mousedown', function(e) {
    if (
_ui.sel()) {
      var 
sel _ui.selobj();
      if (!
sel) {
        return 
_ui.sel(false);
      }
      if (
sel.container && sel.container != ge(sel.container.id)) {
        
_ui.selobj(false);
        return 
_ui.sel(false);
      }
      
sel.onEvent(e);
    }
  });
}

//
// UiControl abstract class
//
function UiControl(args) {
  return 
this.__construct__(args);
}

extend(UiControl.prototype, {
  
// Constants
  
CSS: {},
  
defaultOptionsnull,
  
dom: {},

  
// Consructor
  
__construct__: function(args) {
    if (
this.beforeInit) if (this.beforeInit.apply(thisargs) === false) return false;
    if (
this.initOptions) if (this.initOptions.apply(thisargs) === false) return false;
    if (
this.init.apply(thisargs) === false) return false;
    if (
this.initDOM) if (this.initDOM.apply(thisargs) === false) return false;
    if (
this.initEventsthis.initEvents.apply(thisargs);
    if (
this.afterInitthis.afterInit.apply(thisargs);
    return 
this;
  },

  
// Standart abstract methods

  // UI Control initialisation

  // User defined callback
  
beforeInitnull,
  
// Init options field
  
initOptionsnull,
  
// init and initEvents are required
  
initnull,
  
// Construct DOM
  
initDOMnull,

  
// Attach events listeners to elements
  
initEventsnull,

  
// User defined callback
  
afterInitnull,

  
shownull,
  
hidenull
});

function 
Dropdown(inputdataoptions) {
  if (!
optionsoptions = {};
  return new 
Selector(
    
input,
    
options.autocomplete data : [], extend({
      
introText'',
      
multiselectfalse,
      
autocompletefalse,
      
selectedItemsoptions.selectedItem
    
}, options, {
      
defaultItemsdata
    
}
  ));
}

// Alias
function Autocomplete(inputdataoptions) {
  return new 
Selector(inputdataoptions);
}

//
// Dropdown class
//
createChildClass('Selector'UiControl, {
  
// Standart object fields
  
CSS: {
  },
  
defaultOptions: {
    
selectedItems: [],
    
defaultItems: [],
    
multiselecttrue,
    
autocompletetrue,
    
dropdowntrue,
    
cacheLength100,
    
maxItems50,
    
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;
      }
    },
    
selectFirsttrue,
    
dividingLine'smart',
    
enableCustomfalse,
    
valueForCustom: -1,
    
width300,
    
height250,
    
progressBarfalse,
    
highlight: function(labelterm) {
      
label term.indexOf(' ') == -label.split(' ') : [label];
      var 
tmp '';
      var 
termRus parseLatin(term);

      if (
termRus != null) {
        
term term '|' termRus;
      }
      var 
re = new RegExp('(?![^&;]+;)(?!<[^<>]*)((\(*)(' escapeRE(term) + '))(?![^<>]*>)(?![^&;]+;)''gi');
      for (var 
i in label) {
        
tmp += (' ' '') + label[i].replace(re'$2<em>$3</em>');
      }
      return 
tmp;
    },
    
placeholder'',
    
placeholderColor'#afb8c2',
    
introText'Start typing',
    
noResultgetLang('search_nothing_found'),
    
noImageSrc'http://vk.com/images/question_s.gif',
    
formatResult: function(data) {
      return 
data[1] + (typeof(data[2]) == 'string' ' <span>' data[2] + '</span>' '');
    },
    
hrefPrefix'id'
  
},
  
controlName'Selector',

  
// Standart object methods
  
beforeInit: function(input) {
    if (
input == null || input['autocomplete']) {
      try { 
console.error("Can't init "input); } catch (e) {}
      return 
false;
    }
    
this.guid _ui.reg(this);
  },
  
initOptions: function(inputdataoptions) {
    var 
opts this.options extend({}, this.defaultOptions, {
      
resultFieldinput['name'] || 'selectedItems',
      
customFieldinput['name'] ? (input['name'] + '_custom') : 'selectedItems_custom'
    
}, this.prepareOptionsText(options || {}));

    
// if highlight is set to false, replace it with a do-nothing function
    
opts.highlight opts.highlight || function(label) { return label; };

    
// Get selected value
    
if (!isArray(opts.selectedItems) && isEmpty(opts.selectedItems)) {
      
opts.selectedItems = [];
    }
    if (
input['value'] && !opts.selectedItems.length) {
      
opts.selectedItems input['value'];
    }

    
opts.width parseInt(opts.width) > parseInt(opts.width) : this.defaultOptions.width;
    
opts.height parseInt(opts.height) > parseInt(opts.height) : this.defaultOptions.height;
    
opts.resultListWidth parseInt(opts.resultListWidth) > parseInt(opts.resultListWidth) : opts.width;
    if (
opts.imageId) {
      
opts.imageId ge(opts.imageId);
    }
  },
  
init: function(inputdata) {
    
this.dataURL typeof(data) == 'string' data null;
    
this.dataItems isArray(data) ? data : [];
    
this.currentList this.dataItems;

    if (
this.dataURL) {
      
this.cache = new Cache(this.options);
    } else {
      
this.indexer = new Indexer(this.dataItems, {indexkeysthis.options.indexkeys});
    }

    
this._selectedItems = [];
    
this.input input;
    
this.disabled false;
    
this.mouseIsOver false;
    
this.hasFocus 0;
    
this.scrollbarWidth 0;
    
this.timeout null;
    
this.readOnly = (!this.options.autocomplete 'readonly="true"' '');
    
this.requestTimeout null;
    
this.selectedTokenId 0;
    
this.selectorWidth this.options.width;
  },
  
initDOM: function(inputdataoptions) {
    var 
opts this.optionsself this;

    
this.container ce('div', {
      
id'container' this.guid,
      
className'selector_container' + (!opts.autocomplete ' dropdown_container' '') + (browser.mobile ' mobile_selector_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" ' 
this.readOnly ' />
        <input type="hidden" name="' 
opts.resultField '" id="' opts.resultField '" value="" class="resultField"><input type="hidden" name="' opts.customField '" id="' opts.customField '" value="" class="customField">
      </td>' 
+ (opts.dropdown '<td id="dropdown' this.guid '" class="selector_dropdown">&nbsp;</td>' '') + '
    </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>'
    
}, {
      
widthopts.width 'px'
    
});
    
input.parentNode.replaceChild(this.containerinput);
    
each ({
      
selector'selector',
      
resultList'result_list',
      
resultListShadow'result_list_shadow',
      
input'selector_input',
      
selectedItemsContainer'selected_items',
      
resultField'resultField',
      
customField'customField',
      
dropdownButton'selector_dropdown'
    
}, function(kv) {
      
self[k] = geByClass(vself.container)[0];
    });

    if (
browser.chrome) {
      
this.resultList.style.opacity 1;
    }

    
//if (!this.disabled) // always enabled at init
    
input.style.color opts.placeholderColor;
    
input.autocomplete '1';

    if (
opts.dividingLine) {
      
addClass(this.resultList'dividing_line')
    }

    
this.resultList.style.width this.resultListShadow.style.width opts.resultListWidth 'px';

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

    
this.select = new Select(this.resultListthis.resultListShadow, {
      
selectFirstopts.selectFirst,
      
heightopts.height,
      
onItemActive: function(value) {
        
self.showImage(value);
        
self.activeItemValue value;
      },
      
onItemSelectself._selectItem.bind(self),
      
onShow: function() {
        
_ui.sel(self.guid);
        
self.highlightInput(true);
        if (
options.onShow) {
          
options.onShow();
        }
      },
      
onHide: function() {
        
_ui.sel(false);
        
self.highlightInput(false);
        if (
options.onHide) {
          
options.onHide();
        }
      }
    });
  },
  
initEvents: function() {
    var 
self this;
    if (
this.options.dropdown) {
      
this.initDropdownEvents();
    }
    var 
keyev1 browser.opera || browser.mozilla 'keypress' 'keydown';
    var 
keyev2 browser.opera 'keypress' 'keydown';
    
this.onEvent = function(e) {
      if (
e.type == 'mousedown') {
        var 
outside truee.target;
        while (
&& != t.parentNode) {
          if (
== self.container) {
            
outside false;
            break;
          }
          
t.parentNode;
        }
        if (
outside) {
          
self.select.hide();
          
self.deselectTokens();
        }
      }
      if (
e.type == keyev1) {
        
self.handleKeyboardEventOutside(e);
      }
      if (
e.type == keyev2) {
        
self.select.handleKeyEvent(e);
      }
    }

    
addEvent(this.input'paste keypress keydown focus blur'this.handleKeyboardEventfalse, {selfthis});
    
addEvent(this.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) {
        return 
self.onInputClick(e);
      }
      return 
true;
    }, 
false, {selfthis});
  },
  
afterInit: function() {
    
this.updateInput();
    var 
opt this.optionsself this;
    if (
opt.selectedItems !== undefined) {
      if (
isArray(opt.selectedItems)) {
        for (var 
i in opt.selectedItems) {
          
this._selectItem(opt.selectedItems[i], false);
        }
      } else {
        
each((opt.selectedItems '').split(','), function(ix) {
          
self._selectItem(xfalse);
        });
      }
    }

    
// Select first item if it is dropdown
    
if (!this._selectedItems.length && !this.options.autocomplete && !this.options.multiselect && this.options.defaultItems.length) {
      
this._selectItem(this.options.defaultItems[0], false);
    }
  },
  
// Extended methods
  
prepareOptionsText: function(options) {
    
each(['disabledText''placeholder'], function() {
      if (
this in options) {
        
options[this] = winToUtf(stripHTML(options[this]));
      }
    });
    return 
options;
  },
  
fadeButtonToColor: function() {
    if (
this.options.customArrow) return;
    var 
state window.is_rtl ? {backgroundColor'#E1E8ED'borderRightColor'#D2DBE0'} : {backgroundColor'#E1E8ED'borderLeftColor'#D2DBE0'};
    var 
self this;
    
animate(this.dropdownButtonstate200, function() {
      if (!
self.mouseIsOver) {
        if (!
self.select.isVisible()) {
           
self.fadeButtonToWhite();
        } else {
          
self.dropdownButton.style.backgroundColor self.dropdownButton.style[window.is_rtl 'borderRightColor' 'borderLeftColor'] = '';
        }
      }
    });
  },
  
fadeButtonToWhite: function() {
    if (
this.options.customArrow) return;
    var 
self this;
    
animate(this.dropdownButton, {backgroundColor'#FFFFFF'borderLeftColor'#FFFFFF'}, 200, function() {
      
self.dropdownButton.style.backgroundColor self.dropdownButton.style[window.is_rtl 'borderRightColor' 'borderLeftColor'] = '';
      if (
self.mouseIsOver) {
        
self.fadeButtonToColor();
      }
    });
  },
  
initDropdown: function() {
    
this.scrollbarWidth this.options.customArrowWidth || window.sbWidth();
    if (
this.scrollbarWidth <= 3) {
      
this.scrollbarWidth browser.mobile 20 14;
    }
    if (!
this.options.customArrow) {
      
this.dropdownButton.style.width this.scrollbarWidth 'px';
    }
    
this.selectorWidth -= this.scrollbarWidth;
  },
  
initDropdownEvents: function() {
    var 
self this;
    
addEvent(this.dropdownButton'mouseover', function() {
      
addClass(this'selector_dropdown_hover');
    });
    
addEvent(this.dropdownButton'mouseout', function() {
      
removeClass(this'selector_dropdown_hover');
    });
    
addEvent(this.container'mouseover', function(e) {
      
self.mouseIsOver true;
      if (
self.disabled) return;
      
self.fadeButtonToColor();
    });
    
addEvent(this.container'mouseout', function() {
      
self.mouseIsOver false;
      if (
self.disabled) return;
      
setTimeout(function() {
        if (
self.mouseIsOver) return;
        if (!
self.select.isVisible()) {
          
self.fadeButtonToWhite();
        } else {
          
self.dropdownButton.style.backgroundColor self.dropdownButton.style[window.is_rtl 'borderRightColor' 'borderLeftColor'] = '';
        }
      }, 
0);
    });
    
addEvent(this.dropdownButton'mousedown', function() {
      if (!
self.select.isVisible()) {
        
self.showDefaultList();
      } else {
        
self.select.toggle();
      }
    });
  },
  
destroyDropdown: function() {
    if (
vk.alcleanElems(this.dropdownButton);
    
removeEvent(this.container'mouseover');
    
removeEvent(this.container'mouseout');
    
this.scrollbarWidth 0;
    
this.selectorWidth this.options.width;
  },
  
destroy: function() {
    if (!
vk.al || this.destroyed) return;
    
this.destroyDropdown();
    var 
img ge(this.options.imageId);
    if (
imgremoveEvent(img'click');
    
this.select.destroy();
    
cleanElems(this.containerthis.inputthis.selectorthis.resultListthis.resultListShadow);
    for (var 
el this.selectedItemsContainer.firstChildelel el.nextSibling) {
      
cleanElems(elel.firstChild.nextSibling);
    }
    
this.destroyed true;
  },
  
updateInput: function() {
    if (!
this._selectedItems.length && !this.hasFocus) {
      
this.input.value = ((this.disabled && this.options.disabledText) ? this.options.disabledText this.options.placeholder);
      if (!
this.disabledthis.input.style.color this.options.placeholderColor;
    }
    if (!
this.options.autocomplete && this.options.multiselect && this._selectedItems.length){
      
hide(this.input);
    } else {
      if (!
isVisible(this.input)) show(this.input);
      
this.input.style.width '20px';
      var 
offset this._selectedItems.length this.input.offsetLeft : (window.is_rtl this.selectorWidth 0);
      var 
window.is_rtl offset : (this.selectorWidth offset 9);
      
this.input.style.width Math.max(20w) + 'px';
    }
  },
  
handleKeyboardEvent: function(e) {
    var 
self e.data.self;

    switch (
e.type) {

    case 
'paste':
      
clearTimeout(self.timeout);
      
self.timeout setTimeout(function(){ self.onChange(); }, 0);
    break;

    case 
'keypress':
      if (
e.which == KEY.RETURN && browser.opera && self.options.enableCustom && (self.select.selectedItem() === null || self.select.selectedItem() === undefined)) {
        
self.select.hide();
        if (!
self.options.noBlur) { self.input.blur(); }
        else if (
isFunction(self.options.onChange)) {
          
self.updateCustom();
          
self.options.onChange(self.resultField.value);
        }
        return 
false;
      } else if (
e.which == KEY.SPACE || e.which 40 && !e.metaKey) {
        
clearTimeout(self.timeout);
        
self.timeout setTimeout(function(){ self.onChange(); }, 0);
      }
    break;

    case 
'keydown':
      switch (
e.keyCode) {
        case 
KEY.DOWN:
          if (!
self.select.isVisible()) {
            
setTimeout(self.showDefaultList.bind(self), 0);
            return 
false;
          }
        break;
        case 
KEY.DEL:
          if (
self.input.value.length 0) {
            
clearTimeout(self.timeout);
            
self.timeout setTimeout(self.onChange.bind(self), 0);
          } else {
            if (
self.selectedTokenId) {
              var 
nextTokenId 0;
              for (var 
self._selectedItems.length 2>= 0i--) {
                if (
self._selectedItems[i][0] == self.selectedTokenId && self._selectedItems[i+1]) {
                  
nextTokenId self._selectedItems[i+1][0];
                }
              }
              
self.removeTagData(self.selectedTokenId);

              if (
nextTokenId) {
                
self.selectToken(nextTokenId);
              } else if (!
self.readOnly && !self.hasFocus) {
                
self.input.focus();
              }
            } else if (
self.hasFocus && self._selectedItems.length) {
              
self.selectToken(self._selectedItems[self._selectedItems.length 1][0]);
            }
            
cancelEvent(e);
          }
          return 
true;
        break;
        case 
KEY.RETURN:
          if (!
browser.opera && self.options.enableCustom && (self.select.selectedItem() === null || self.select.selectedItem() === undefined)) {
            
self.select.hide();
            if (!
self.options.noBlur) { self.input.blur(); }
            else if (
isFunction(self.options.onChange)) {
              
self.updateCustom();
              
self.options.onChange(self.resultField.value);
            }
            return 
false;
          }
          break;
        case 
KEY.ESC:
          
self.input.blur();
          break;
      }
    break;

    case 
'focus':
      if (!
self.disabled && !self.select.isVisible() && !self.focusSelf) {
        
self.showDefaultList();
      }
      
self.focusSelf false;
      if (
self.disabled || self.readOnly) {
        
self.input.blur();
        return 
true;
      }

      if ((
self._selectedItems.length == 0) || self.options.multiselect) {
        if (
browser.mozilla) {
          
setTimeout(function () {
            
self.input.value '';
          }, 
0);
        } else {
          
self.input.value '';
        }
      }
      
addClass(self.input'focused');
      
self.input.style.color '#000';
      
self.hasFocus++;
    break;

    case 
'blur':
      if (
self.options.chooseFirst && self.options.chooseFirst(self.input.value)) { // email field
        // todo
        
self.select.active 0;
        if (
isFunction(self.select.options.onItemSelect)) {
          
self.select.options.onItemSelect(self.select.selectedItem(), undefinedtrue);
        }
        return 
cancelEvent(e);
      }
      if (
self.readOnly) return true;
      if (!
self.disabled) {
        
self.updateCustom();
        
clearTimeout(self.requestTimeout);
        if (
self.changeAfterBlur && isFunction(self.options.onChange)) {
          if (!
self.options.enableCustom || !self._selectedItems.length) {
            
self.options.onChange('');
          }
          
self.changeAfterBlur false;
        }
        if (
self.options.onBlur) { self.options.onBlur(); }
      }
      if (!
hasClass(self.input'selected')) {
        
self.input.style.color self.options.placeholderColor;
      }
      
removeClass(self.input'focused');
      
self.hasFocus 0;
    break;

    }
    return 
true;
  },
  
updateCustom: function() {
    var 
self this;
    if (
self.options.enableCustom && self.input.value.length) {
      var 
custom_val self.input.value;
      if (
self._selectedItems.length == 0) {
        
self.resultField.value parseInt(!self.options.valueForCustom);
        
self.customField.value custom_val;
        
self._selectItem([self.options.valueForCustomcustom_val]);
      }
    } else if (
self._selectedItems.length == 0) {
      
self.input.value self.options.placeholder;
    } else if (
self.options.multiselect) {
      
self.input.value '';
    }
  },
  
handleKeyboardEventOutside: function(e) {
    if (
this.disabled || this.input.value.length && this.hasFocus || !this.hasFocus && this.selectedTokenId == 0) {
      return 
true;
    }
    switch(
e.keyCode) {
      case 
KEY.RETURN:
        return 
false;
      break;
      case 
KEY.LEFT:
        for (var 
this._selectedItems.length 1>= 0i--) {
          if (!
this.selectedTokenId || this._selectedItems[i][0] == this.selectedTokenId && 0) {
            if (
this.selectedTokenId) {
              
i--;
            }
            
this.selectToken(this._selectedItems[i][0]);
            
this.input.blur();
            break;
          }
        }
        return 
false;
        break;

      case 
KEY.RIGHT:
        for (var 
0this._selectedItems.lengthi++) {
          if (
this._selectedItems[i][0] == this.selectedTokenId) {
            if (
this._selectedItems.length 1) {
              
this.selectToken(this._selectedItems[i+1][0]);
              
this.input.blur();
            } else if (!
this.readOnly) {
              
this.deselectTokens();
              
this.input.focus();
            }
            break;
          }
        }
        return 
false;
        break;
    }
    return 
true;
  },
  
onInputClick: function(e) {
    var 
self e.data.self;
    
self.deselectTokens();
    if (!
self.select.isVisible()) {
      
self.showDefaultList();
    } else {
      if (
self.input.readOnly) {
        
self.focusSelf true;
        
self.select.toggle();
      } else {
        
self.onChange();
      }
    }
    if (!
self.readOnly) {
      
// self.focusSelf = true;
      
self.input.focus();
    } else {
      
self.input.blur();
    }
  },
  
highlightInput: function(focus) {
    if (
focus) {
      
addClass(this.container'selector_focused');
    } else {
      
removeClass(this.container'selector_focused');
    }
  },
  
selectToken: function(id) {
    if (!
this.options.multiselect) return;
    
this.select.hide();
    
removeClass(ge('bit_' this.guid '_' this.selectedTokenId), 'token_selected');
    
addClass(ge('bit_' this.guid '_' +  id), 'token_selected');
    
this.selectedTokenId id;
    if (
this.options.onTokenSelectedthis.options.onTokenSelected(id);
    
this.showImage(id);
  },
  
deselectTokens: function() {
    if (!
this.selectedTokenId || !this.options.multiselect) return;
    
removeClass(ge('bit_' this.guid '_' this.selectedTokenId), 'token_selected');
    
this.selectedTokenId 0;
    if (
this.options.onTokenSelectedthis.options.onTokenSelected();
    
this.showImage();
  },
  
_blur: function() {
    
this.select.hide();
  },
  
showImage: function(itemValueitemData) {
    if (!
this.options.imageId) {
      return 
false;
    }
    var 
img ge(this.options.imageId);
    if (!
img) return false;
    if (
itemData === undefined) {
      if (!
itemValue) { // 0 or undefined
        
itemValue this.resultField.value.split(',')[0];
      }
      var 
data this._selectedItems.concat(this.currenDataItems);

      if (
data && data.length) {
        for (var 
i in data) {
          if (
data[i] && data[i][0] == itemValue) {
            
itemData data[i];
            break;
          }
        }
      }
    }
    if (
itemData !== undefined && typeof(itemData[3]) == 'string' && itemData[3].length) {
      if (
itemData[3] == 'none'){
        
img.style.display 'none';
      } else {
        
img.style.display '';
        
img.setAttribute('src'itemData[3]);
        
img.parentNode.href '/' this.options.hrefPrefix itemData[0]; // hack
        
removeEvent(img.parentNode'click');
      }
    } else {
      
img.style.display '';
      
img.setAttribute('src'this.options.noImageSrc);
      
img.parentNode.href '#'// hack
      
addEvent(img.parentNode'click', function() { return true; });
    }
    return 
true;
  },
  
_selectItem: function(itemfireEventfocusIfMultiselect) {
    if (
item == null) {
      return;
    }
    if (
fireEvent === undefined) {
      
fireEvent true;
    }
    var 
data;

    if (
item == -2e9) {
      
data = [this.curTermthis.curTermcur.lang['mail_enter_email_address'], '/images/pics/contact_info.png'0''];
    } else if (
typeof(item) == 'string' && item.indexOf('@') != -1) {
      
data = [itemitemcur.lang['mail_enter_email_address'], '/images/pics/contact_info.png'0''];
    } else if (
typeof(item) == 'object') {
      
data item;
    } else {
      var 
all_data = [];
      
each([this.dataItemsthis.options.defaultItemsthis.receivedData], function(i,items) {
        if (
items && items.length)
          
all_data all_data.concat(items);
      });
      for (var 
i in all_data) {
        if (
all_data[i][0] == item || all_data[i] == item) {
          
data all_data[i];
          break;
        }
      }
    }

    if (
typeof data != 'object') {
      
data = [itemitem]; // value and text
    
};
    
data[0] = data[0].toString();
    
data[1] = data[1].toString();

    
this.changeAfterBlur false;
    if (
data[0] === this.resultField.value) {
      if (!
this.options.multiselect) {
        
this.input.value winToUtf(stripHTML(data[1])); // It could have changed in setData method
        
this.showImage();
        if (
this.input.value.length || !this.options.placeholder) {
          
addClass(this.input'selected');
          if (!
this.disabled) {
            
this.input.style.color this.resultField.value == '0' && this.options.zeroPlaceholder && this.options.placeholderColor || '#000';
          }
        } else {
          
this.input.value this.options.placeholder;
          if (!
this.disabledthis.input.style.color this.options.placeholderColor;
        }
      }
      return;
    }
    if (
this._selectedItems.length >= this.options.maxItems) {
      
this.select.hide();
      return;
    }

    
this.deselectTokens();
    
this.addTagData(data);
    
this.showImage();

    if (
this.options.multiselect) {
      
this.input.value '';
      if (
this.dataURL) {
        
this.select.clear();
      } else {
        
this.select.removeItem(data[0]);
      }
    } else {
      
this.input.value winToUtf(stripHTML(data[1]));
      
addClass(this.input'selected');
      if (!
this.disabled) {
        
this.input.style.color this.resultField.value == '0' && this.options.zeroPlaceholder && this.options.placeholderColor || '#000';
      }
    }

    
this.select.hide();

    
this.updateInput();
    if (
focusIfMultiselect && this.options.multiselect && !this.readOnly) {
      
setTimeout(function() {
        if (!
this.options.multinostop) {
          
this.focusSelf true;
        }
        
hide(this.input);
        
show(this.input);
        
this.input.focus();
      }.
bind(this), 100);
    } else {
      if (!
this.options.noBlurthis.input.blur();
    }

    if (
fireEvent) {
      if (
this.options.multiselect && isFunction(this.options.onTagAdd)) {
        
this.options.onTagAdd(datathis.resultField.value);
      }
      if (
isFunction(this.options.onChange)) {
        
this.options.onChange(this.resultField.value);
      }
    }
  },
  
addTagData: function(data) {
    if (!
data || data.length 2) return;
    if (!
this.options.multiselect) {
      
this._selectedItems.splice(0this._selectedItems.lengthdata);
      
this.resultField.value data[0];
      return;
    }
    for (var 
i in this._selectedItems) {
      if (
this._selectedItems[i][0] == data[0]) {
        
this.selectToken(this._selectedItems[i][0]);
        return;
      }
    }
    
this._selectedItems.push(data);

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

    
this.input.style.width '1px';

    
// make box
    
var token ce('div', {
      
id'bit_' this.guid '_' data[0],
      
className'token'
    
});
    var 
maxTokenWidth Math.max(this.selector.clientWidthgetSize(token)[0]);
    var 
self this;

    
token.innerHTML '<span class="l">' data[1] + '</span><span class="x" />';

    
addEvent(token'click', function() {
      
self.selectToken(data[0]);
      return 
false;
    });
    
addEvent(token'dblclick', function() {
      if (
data[4]) {
        
self.removeTagData(data[0]);
        
each(data[4], function(iv) {
          
self._selectItem(vfalse);
        });
      }
      return 
false;
    });
    
addEvent(token'mouseover', function(e) {
      
addClass(token'token_hover');
      
self.showImage(data[0], data);
    });
    
addEvent(token'mouseout', function(e) {
      
removeClass(token'token_hover');
      
self.showImage(self.activeItemValue self.activeItemValue self.selectedTokenId);
    });
    var 
close token.firstChild.nextSibling;
    
addEvent(close'mousedown', function() {
      
self.select.hide();
      
self.removeTagData(data[0]);
      if (!
self.readOnly && self.hasFocus) {
        
self.input.focus();
      }
      return 
false;
    });

    
self.selectedItemsContainer.appendChild(token);

    var 
label token.firstChild;
    var 
labelStr label.innerHTML;
    while (
token.offsetWidth maxTokenWidth && labelStr.length 3) {
       
labelStr labelStr.substr(0labelStr.length 2);
       
label.innerHTML labelStr '...';
    }
  },
  
removeTagData: function(id) {
    
this.selectedTokenId 0;
    var 
token ge('bit_' this.guid '_' id);
    if (!
token) {
      return 
false;
    }
    var 
close token.firstChild.nextSibling;
    if (
vk.alcleanElems(tokenclose);
    
token.parentNode.removeChild(token);

    var 
indexresultArr = [];
    for (
i in this._selectedItems) {
      if (
this._selectedItems[i][0] == id) {
        
index i;
        continue;
      }
      
resultArr.push(this._selectedItems[i][0]);
    }
    if (
index == undefined) return false;

    
this.resultField.value resultArr.join(',');

    if (
this.options.onTagRemove) {
      
this.options.onTagRemove(this._selectedItems[i], this.resultField.value);
    }
    if (
isFunction(this.options.onChange)) {
      
this.options.onChange(this.resultField.value);
    }
    
this._selectedItems.splice(index1);
    if (
this.options.multiselect) {
      
this.defaultList false;
    }
    
this.showImage();
    
this.updateInput();
    return 
false;
  },
  
onChange: function() {
    var 
term trim(this.input.value.toLowerCase()),
      
self this;
    if (!
this.options.multiselect) {
      if (
this._selectedItems.length) {
        
this.changeAfterBlur true;
      }
      
this._clear();
    }
    
clearTimeout(this.requestTimeout);
    if (
term.length == 0) {
      
this.showDefaultList();
      return;
    }
    
this.curTerm term;
    var 
custom this.options.customSearchres custom && custom(term);
    if (
res) {
      
this.receiveData(termres);
      return;
    }
    if (
this.dataURL) {
      var 
data this.cache.getData(term);
      if (
data == null) {
          
this.requestTimeout setTimeout(function() {
            
self.request(self.receiveData.bind(self), self.showNoDataList.bind(self));
          }, 
300);
      } else {
        
// receive the cached data
        
if (data && data.length) {
          
this.receiveData(termdata);
        } else {
          
this.showNoDataList();
        }
      }
    } else {
      var 
data this.indexer.search(term);
      if (
data && data.length) {
        
this.receiveData(termdata);
      } else {
        
this.showNoDataList();
      }
    }
  },
  
showNoDataList: function() {
    if (
this.hasFocus || this.readOnly) {
      
this._showSelectList(this.options.noResult);
      
this.defaultList false;
    }
  },
  
showDefaultList: function() {
    var 
reversed hasClass(this.resultList'reverse');
    if (
reversed != this.needsReverse() && this.currenDataItems) {
      
this.setSelectContent(this.currenDataText || ''this.currenDataItems);
    }
    if (
this.defaultList && this.select.hasItems()) {
      if (
this.options.multiselect || !this._selectedItems.length)
        
this.select.show();
      else
        
this.select.show(this._selectedItems[0][0]);
    } else {
      
this.defaultList true;
      var 
text this.options.autocomplete this.options.introText null;
      
this._showSelectList(text, (this.options.defaultItems.length || this.options.zeroDefault) ? this.options.defaultItems this.dataItems);
    }
    
reversed hasClass(this.resultList'reverse');
    if (
reversed) {
      if (!
this._selectedItems.length) {
        
this.resultList.scrollTop getSize(this.resultList.firstChild)[1] - getSize(this.resultList)[1] + 10;
      }
      
setStyle(this.resultList, {bottomgetSize(this.container)[1] - 1});
    } else {
      
setStyle(this.resultList, {bottom'auto'});
    }
  },
  
showDataList: function(itemsquery) {
    
this.defaultList false;
    
this._showSelectList(nullitemsquery);
  },
  
needsReverse: function() {
    var 
scrollY window.scrollGetY scrollGetY() : getScroll()[1],
        
contY getXY(this.container)[1] || 0,
        
contH getSize(this.container)[1] || 22,
        
maxListH this.options.height || 250,
        
minListH this.options.minHeight || 0,
        
wh = (window.pageNode && window.browser.mozilla Math.min(getSize(pageNode)[1], window.lastWindowHeight) : window.lastWindowHeight) || getScroll()[3],
        
list_ul this.resultList && this.resultList.firstChildlistH;
    if (
list_ul && list_ul.firstChild) {
      var 
disp getStyle(this.resultList'display'), vis getStyle(this.resultList'visibility');
      
setStyle(this.resultList, {visibility'hidden'display'block'});
      
listH getSize(this.resultList)[1];
      
setStyle(this.resultList, {visibilityvisdisplaydisp});
    } else {
      
listH minListH minListH : (this.currenDataItems this.currenDataItems.length getSize(this.container)[1] : maxListH);
    }
    if (
listH maxListHlistH maxListH;
    return (
contY contH listH scrollY wh && contY listH scrollY 0);
  },
  
setSelectContent: function(textitemsquery) {
    
items isArray(items) && items.length items : [];
    var 
adding = [];
    
this.select.clear();
    if (
text) {
      
adding.push([''texttrue]);
    }

    if (
items.length) {
      for (var 
i in items) {
        if (
typeof items[i] != 'object'items[i] = [items[i], items[i]];
      }
      if (
this.options.multiselect) {
        
items this.filterData(items);
      }
      if (
this.options.dividingLine == 'smart') {
        
removeClass(this.resultList'dividing_line');
        for (var 
i in items) {
          if (
typeof(items[i][2]) == 'string' && items[i][2].length) {
            
addClass(this.resultList'dividing_line');
          }
        }
      }
      var 
itemsToShow = (this.options.autocomplete && query) ? this.options.maxItemsShown(query.length) : items.lengthself this;
      for (var 
0items.length; ++i) {
        var 
it items[i];
        if (!
itemsToShow) break;
        var 
formatted self.options.formatResult(it);
        if (
query) {
          if ((
formatted self.options.highlight(formattedquery))) {
            --
itemsToShow;
          }
        }
        if (!
formatted) continue;
        
adding.push([it[0], formatted]);
      }
    }
    var 
rev this.needsReverse();
    if (
revadding adding.reverse();
    
toggleClass(this.resultList'reverse'rev);
    
toggleClass(this.resultListShadow'reverse'rev);
    
this.select.content(adding);
  },
  
_showSelectList: function(textitemsquery) {
    
this.currenDataItems items;
    
this.currenDataText text;
    
// RTL fix
    
if (window.is_rtl) {
      var 
getXY(this.container)[0];
      if (
lgeByClass('results_container'this.container)[0].style.left 'px';
    }

    
this.setSelectContent(textitemsquery);
    if (
this.options.multiselect || !this._selectedItems.length) {
      
this.select.show();
    } else {
      
this.select.show(this._selectedItems[0][0]);
    }
    return 
true;
  },
  
receiveData: function(qdata) {
    if (
!= this.curTerm) return;
    if (
!= '' && data && data.length && this.hasFocus) {
      
this.receivedData data;
      
this.showDataList(dataq);
    } else {
      
this.select.hide();
    }
  },
  
filterData: function(items) {
    var 
result = [], self this;
    
each(items, function(i) {
      for (var 
j in self._selectedItems) {
        if (
this[0] == self._selectedItems[j][0])
          return;
      }
      
result.push(this);
    });
    return 
result;
  },
  
request: function(successfailure) {
    if (!
this.dataURL) return;
    var 
term trim(this.input.value.toLowerCase()), self this;
    if (
term.length == 0) return;
    var 
sep this.dataURL.indexOf('?') == -'?' '&';
    var 
url this.dataURL sep 'str=' encodeURIComponent(term);
    var 
done = function(data) {
      if (
self.options.progressBar) {
        
hide(self.options.progressBar);
      }
      try {
        
data = eval('(' data ')');
      } catch (
e) {}
      if (
data.length) {
        
self.cache.setData(termdata);
        if (
isFunction(success)) success(termdata);
      } else {
        
self.cache.setData(term, []);
        if (
isFunction(failure)) failure(term);
      }
    }
    if (
vk.al) {
       
ajax.plainpost(url, {}, done);
    } else {
      var 
aj = new Ajax(function(objdata) {
        
done(data);
      });
      
aj.post(url);
    }
    if (
this.options.progressBar) {
      
show(this.options.progressBar);
    }
  },
  
doSort: function(data) {
    var 
ijtmp;
    if (!
data.length || data.length 2) return;
    for (
0data.length 1i++) {
      for (
1data.lengthj++) {
        if (
data[i][1] > data[j][1]) {
          
tmp data[i];
          
data[i] = data[j];
          
data[j] = tmp;
        }
      }
    }
  },
  
disable: function(value) {
    if (
value && !this.disabled) {
      
this.disabled true;
      
addClass(this.container'disabled');

      var 
getSize(this.container);
      if (
this.options.disabledTextthis.input.value this.options.disabledText;
      
this.container.appendChild(
        
ce('div', {
          
className'hide_mask'
        
}, {
          
position'absolute',
          
background'#000',
          
opacity0,
          
widths[0] + 'px',
          
heights[1] + 'px',
          
marginTop: -s[1] + 'px'
        
})
      );
      
this.input.blur();
      
this.input.style.color '';
      
this.select.hide();
      
//this.updateInput(); // Is it correct?
    
} else if (!value && this.disabled) {
      
this.disabled false;
      if (
this.options.autocompletethis.input.value '';
      
removeClass(this.container'disabled');
      
this.container.removeChild(geByClass('hide_mask'this.container)[0]);
      
//this.updateInput(); // Is it correct?
    
}
  },
  
_clear: function() {
    
this.showImage();

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

    return 
false;
  },
  
setURL: function(url) {
    if (
typeof(url) == 'string') {
      
this.dataURL url;
      if (!
this.cache) {
        
this.cache = new Cache(this.options);
      } else {
        
this.cache.flush();
      }
      if (
this.indexerdelete this.indexer;

      
this.dataItems = [];
    }
  },
  
setData: function(dataArr) {
    if (!
isArray(dataArr)) return;
    if (!
this.options.autocomplete) {
      
this.select.clear();
      
this.options.defaultItems dataArr;
      if (!
this.options.multiselect) {
        if (!
this._selectedItems.length && this.options.defaultItems.length) {
          
this._selectItem(this.options.defaultItems[0], false);
        } else if (
this._selectedItems.length) {
          var 
exists false;
          for (var 
i in this.options.defaultItems) {
            var 
item this.options.defaultItems[i][0] || this.options.defaultItems[i];
            if (
item == this._selectedItems[0][0] || item == this._selectedItems[0][0]) {
              
exists true;
              break
            }
          }
          if (!
exists) {
            
this._selectItem(this.options.defaultItems[0], false);
          } else {
            
this._selectItem(this._selectedItems[0][0], false);
          }
        }
      }
    } else {
      
this.dataItems dataArr;
      
this.dataURL null;
    }
    if (!
this.indexer) {
      
this.indexer = new Indexer(dataArr);
    } else {
      
this.indexer.setData(dataArr);
    }
    if (
this.cachedelete this.cache;
  },
  
focus: function() {
    if (!
this.readOnly) {
      
this.input.focus();
    }
  },
  
selectItem: function(itemfireEvent) {
    
this._selectItem(itemfireEvent);
  },
  
setOptions: function(new_options) {
    
new_options this.prepareOptionsText(new_options);
    
extend(this.optionsnew_options);
    if (
'maxItems' in new_options && this.options.maxItems >= 0) {
      for (var 
this._selectedItems.length 1>= this.options.maxItemsi--) {
        
this.removeTagData(this._selectedItems[i][0]);
      }
    }

    if (
'defaultItems' in new_options) {
      
this.select.clear();
      if (
this.select.isVisible(this.container)) { // todo: check and remove arg
        
this.showDefaultList();
      }
    }

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

      
this.selectorWidth this.options.width this.scrollbarWidth;
    }
    if (
'dropdown' in new_options) {
      var 
dd geByClass('selector_dropdown'this.container)[0];
      if (!
this.options.dropdown && dd) {
        
this.destroyDropdown();
        
dd.parentNode.removeChild(dd);
      } else if (!
dd && this.options.dropdown) {
        
dd this.container.firstChild.rows[0].insertCell(1);
        
dd.id 'dropdown' this.guid;
        
dd.className 'selector_dropdown';
        
dd.innerHTML '&nbsp;';
        
this.dropdownButton dd;
        
this.initDropdown();
        
this.initDropdownEvents();
      }
    }
    if ((
'width' in new_options) || ('autocomplete' in new_options) || ('dropdown' in new_options)) {
      
this.updateInput();
    }
    if (
'autocomplete' in new_options) {
      if (
this.options.autocomplete) {
        
removeClass(this.container'dropdown_container');
        
this.input.readOnly false;
        
this.readOnly '';
      } else {
        
addClass(this.container'dropdown_container');
        
this.input.readOnly true;
        
this.options.enableCustom false;
        
this.readOnly 'readonly="true"';
      }
    }
  },
  
val: function(valuefireEvent) {
    if (
value !== undefinedthis._selectItem(value, (fireEvent === undefined) ? false fireEvent);
    return 
this.resultField.value;
  },
  
val_full: function() {
    if (
this.options.multiselect) {
      return 
this._selectedItems;
    } else {
      if (
this._selectedItems.length) {
        return 
this._selectedItems[0];
      } else {
        return [
this.resultField.valuethis.input.value];
      }
    }
  },
  
customVal: function(valuefireEvent) {
    if (
value !== undefined) {
      
this.customField.value value;
      
this.selectItem([this.options.valueForCustomvalue], (fireEvent === undefined) ? false fireEvent);
    }
    return 
this.customField.value;
  },
  
selectedItems: function() {
    return 
this._selectedItems;
  },
  
clear: function() {
    
this._clear();
    
this.updateInput();
  }
});

//
// Select class
//
createChildClass('Select'UiControl, {
  
// Static class fields
  
common: {
    
_selwindow.Select && Select._sel || [],
    
reg: function(obj) {
      
this._sel.push(obj);
      return 
this._sel.length;
    },
    
destroy: function(uid) {
      
this._sel[uid 1] = false;
    },
    
itemMouseMove: function(uidiel) {
      
this._sel[uid 1].onMouseMove(iel);
    },
    
itemMouseDown: function(uidiel) {
      
this._sel[uid 1].onMouseDown(iel);
    }
  },

  
// Standart fields
  
CSS: {
    
FIRST'first',
    
LAST'last',
    
ACTIVE'active',
    
SCROLLABLE'result_list_scrollable'
  
},
  
controlName'SelectList',

  
// Standart methods
  
initOptions: function(containershadowoptions) {
    
this.options options || {};
  },
  
init: function(containershadowoptions) {
    
this.container container;
    
this.shadow shadow;
    
this.active = -1;
    
this.data = [];
    
this.uid this.common.reg(this);
    
this.maxHeight this.options.height this.options.height 250;
  },
  
initDOM: function() {
    
this.list = ce('ul');
    
this.container.appendChild(this.list);
  },
  
show: function(selectedItem) {
    var 
wasVisible isVisible(this.container);
    if (!
wasVisible) {
      
this.performShow();
    }
    var 
childNode;
    if (
selectedItem) {
      for (var 
0this.list.childNodes.lengthi++) {
        
childNode this.list.childNodes[i];
        if (
childNode.getAttribute('val') == selectedItem) {
          
this.highlight(ichildNode);
          break;
        }
      }
    } else if (
this.options.selectFirst) {
      var 
reversed this.container && hasClass(this.container'reverse'), ind;
      for (var 
0this.list.childNodes.lengthi++) {
        
ind reversed this.list.childNodes.length i;
        
childNode this.list.childNodes[ind];
        if (!
childNode.getAttribute('dis')) {
          
this.highlight(indchildNode);
          break;
        }
      }
    }
    if (!
wasVisible && isFunction(this.options.onShow)) this.options.onShow();
  },
  
hide: function() {
    if (!
isVisible(this.container)) return;
    
hide(this.container);
    
hide(this.shadow);
    if (
isFunction(this.options.onHide)) this.options.onHide();
    
this.highlight(-1);
    if (
isFunction(this.options.onItemActive)) this.options.onItemActive();
  },

  
// Extended methods
  
handleKeyEvent: function(e) {
    if (!
isVisible(this.container)) {
      return 
true;
    }
    switch(
e.keyCode) {
      case 
KEY.UP:
        
this.movePosition(-1)
        return 
cancelEvent(e);
        break;

      case 
KEY.DOWN:
        
this.movePosition(1);
        return 
cancelEvent(e);
        break;

      case 
KEY.TAB:
        
this.hide();
      break;

      case 
KEY.RETURN:
        if (
isFunction(this.options.onItemSelect) && this.active > -1) {
          
this.options.onItemSelect(this.selectedItem(), undefinedtrue);
        }
        
cancelEvent(e);
        return 
false;
        break;

      case 
KEY.ESC:
        
this.hide();
        return 
false;
        break;

      case 
KEY.PAGEUP:
      case 
KEY.PAGEDOWN:
        
// deprecated
        
return false;
        break;
    }
    return 
true;
  },
  
clear: function() {
    
this.highlight(-1);
    
this.list.innerHTML '';
    
this.updateContainer();
  },
  
destroy: function() {
    
this.clear();
    
Select.destroy(this.uid);
  },
  
selectedItem: function() {
    if (
this.active >= 0) {
      var 
el this.list.childNodes[this.active];
      var 
value el.getAttribute('val') || el.innerHTML;
      return 
value;
    }
    return 
undefined;
  },
  
movePosition: function(step) {
    var 
selected intval(this.active) + intval(step);
    if (
selected 0)
      
this.container.scrollTop 0;
    else if (
selected this.list.childNodes.length)
      
this.container.scrollTop this.list.offsetTop this.list.offsetHeight this.container.offsetHeight;
    while (
1) {
      if (
selected this.list.childNodes.length || selected 0) {
        if (
this.options.cycle) break;
        else return 
false;
      }
      var 
this.list.childNodes[selected];
      if (
&& !s.getAttribute('dis')) {
        break;
      }
      
selected++;
    }
    
this.highlight(selectedthis.list.childNodes[selected]);
    return 
true;
  },
  
highlight: function(iel) {
    if (
this.active != -1) {
      
removeClass(this.list.childNodes[this.active], this.CSS.ACTIVE);
    }
    if (!
el) {
      
this.active = -1;
      return;
    }
    
this.active i;
    
addClass(elthis.CSS.ACTIVE);

    if (
isFunction(this.options.onItemActive)) {
      
this.options.onItemActive(el.getAttribute('val') || el.innerHTML);
    }
    if (
el.offsetTop el.offsetHeight this.list.offsetTop this.container.offsetHeight this.container.scrollTop 1) {
      
this.container.scrollTop el.offsetTop this.list.offsetTop el.offsetHeight this.container.offsetHeight 1;
    } else if (
el.offsetTop this.list.offsetTop this.container.scrollTop) {
      
this.container.scrollTop el.offsetTop this.list.offsetTop;
    }
  },
  
onMouseMove: function(iel) {
    if (
hasClass(el'active')) return false;
    
this.highlight(iel);
    return 
true;
  },
  
onMouseDown: function(iel) {
    var 
val el.getAttribute('val') || el.innerHTML;
    if (
isFunction(this.options.onItemSelect)) {
      
this.options.onItemSelect(valundefinedtrue);
    }
    
this.hide();
  },
  
updateContainer: function() {
    if (
this.maxHeight this.list.offsetHeight) {
      
this.container.style.height this.maxHeight 'px';
      
show(this.shadow);
      
this.shadow.style.marginTop = (this.maxHeight 1) + 'px'// +1 - because of border-bottom
      
addClass(this.containerthis.CSS.SCROLLABLE);
    } else {
      
removeClass(this.containerthis.CSS.SCROLLABLE);
      
this.container.style.height 'auto';
      var 
shadow_height intval(this.list.offsetHeight) + intval(this.list.offsetTop);
      if (
shadow_height) {
        
show(this.shadow);
        
this.shadow.style.marginTop shadow_height 'px';
      } else {
        
hide(this.shadow);
      }
    }
  },
  
content: function(items) {
    var 
html = [],
        
iitvtdaind,
        
len items.length;
    for (
0len; ++i) {
      
// value, text, disabled, attributes, index
      
it items[i];
      
it[0];
      
it[1];
      
it[2];
      
ind this.uid ', ' i;

      
= (=== undefined) ? '' v.toString();
      
= ((=== undefined) ? '' t.toString()) || v;

      
html.push(
        
'<li ',
        !
'onmousemove="Select.itemMouseMove(' ind ', this)" onmousedown="Select.itemMouseDown(' ind ', this)"' 'dis="1"',
        
' val="',
        
v.replace(/&/g'&amp;').replace(/"/g, '&quot;'),
        '" 
class="',
        (d ? 'disabled ' : ''),
        ((i == len - 1) ? (this.CSS.LAST + ' ') : ''),
        (i ? '' : this.CSS.FIRST) + '"
>',
        t,
        '
</li>'
      );
    }
    this.list.innerHTML = html.join('');
    this.updateContainer();
    return true;
  },
  removeItem: function(value) {
    var undefined, l = this.list.childNodes, len = l.length;
    if (value === undefined) return;
    for (var i = 0; i < len; ++i) {
      var node = l[i];
      if (node.getAttribute('
val') != value && node.innerHTML != value) continue;
      node.setAttribute('
dis', '1');
      hide(node);
      break;
    }
    for (var i = 0; i < len; ++i) {
      if (isVisible(l[i])) {
        addClass(l[i], this.CSS.FIRST);
        break;
      }
    }
    for (var i = len; i > 0; --i) {
      if (isVisible(l[i - 1])) {
        addClass(l[i - 1], this.CSS.LAST);
        break;
      }
    }
    this.updateContainer();
  },
  // AntanubiS - if list.offsetHeight is greater, than screen without scrollbar - bugs.
  performShow: function() {
    this.list.style.position = '
absolute';
    this.list.style.visibility = '
hidden';
    show(this.container);// We see bug in MessageBox with Selector between theese lines.
    show(this.shadow);
    this.updateContainer();
    this.list.style.position = '
relative';
    this.list.style.visibility = '
visible';
  },
  // Shortcuts
  isVisible: function() {
    return isVisible(this.container);
  },
  hasItems: function() {
    return this.list.childNodes.length > 0;
  },
  toggle: function() {
    if (this.isVisible(this.container)) {
      this.hide();
    } else {
      this.show();
    }
  }
});

//
// Checkbox class
//
createChildClass('
Checkbox', UiControl, {
  // Standart fields
  CSS: {
    STANDART: '
checkbox_'
  },
  defaultOptions: {
    checkedValue: 1,
    notCheckedValue: '',
    width: 300,
    label: '
checkbox'
  },
  beforeInit: function() {
    this.guid = _ui.reg(this);
  },
  controlName: '
CheckBox',

  initOptions: function(input, options) {
    if (!input) return false;
    this.options = extend({}, this.defaultOptions, {
      checked: input['
value'],
      resultField: input.name || input.id || '
checkbox'
    }, options);
    this.options.checked = intval(this.options.checked) ? true : false;
    this.options.width = intval(this.options.width) > 0 ? intval(this.options.width) : this.defaultOptions.width;
  },
  init: function() {
    this.disabled = false;
  },
  initDOM: function(input, options) {
    this.container = ce('
div', {
      id: '
container' + this.guid,
      className: '
checkbox_container',
      innerHTML: '
<table cellpadding=0 cellspacing=0><tr><td class="checkbox"><div class="checkbox_off"></div></td><td class="checkbox_label">' + this.options.label + '<input type="hidden" name="' + this.options.resultField + '" id="' + this.options.resultField + '" value="'+ (this.options.checked ? this.options.checkedValue : this.options.notCheckedValue) + '"></td></tr></table>'
    }, {
      width: this.options.width + '
px'
    });
    input.parentNode.replaceChild(this.container, input);

    this.checkbox = geByClass('
checkbox_off', this.container)[0];

    this.resultField = ge(this.options.resultField);
  },
  initEvents: function() {
    addEvent(this.container, '
click mouseover mouseout', this.handleMouseEvent, false, {'self': this});
  },
  afterInit: function() {
    this.setState(this.options.checked, false, true);
  },
  destroy: function() {
    if (!vk.al || this.destroyed) return;
    removeEvent(this.container, '
click mouseover mouseout', this.handleMouseEvent);
    this.destroyed = true;
  },

  show: function() {show(this.container);},
  hide: function() {hide(this.container);},

  // extended methods
  handleMouseEvent: function(e) {
    if (e.type == '
click') {
      if (!e.data.self.disabled) {
        e.data.self.setState(!e.data.self.options.checked);
      }
    } else {
      e.data.self.is_over = (e.type == '
mouseover');
      e.data.self.updateClass();
    }
  },
  disable: function(value) {
    if (value && !this.disabled) {
      this.disabled = true;
      addClass(this.container, '
disabled');
    } else if (!value && this.disabled) {
      this.disabled = false;
      removeClass(this.container, '
disabled');
    }
  },
  updateClass: function() {
    this.checkbox.className = '
checkbox_' + (this.options.checked ? 'on' : 'off') + (this.is_over ? '_over' : '');
  },
  setState: function(checked, fireEvent, forceUpdate) {
    if (fireEvent === undefined) fireEvent = true;
    if (forceUpdate === undefined) forceUpdate = false;

    checked = checked ? true : false;
    if (this.options.checked == checked && !forceUpdate) {
      return;
    }
    this.options.checked = checked;
    this.updateClass();
    this.resultField.value = this.options.checked ? this.options.checkedValue : this.options.notCheckedValue;
    if (fireEvent && isFunction(this.options.onChange)) {
      this.options.onChange(this.resultField.value);
    }
  },
  // shortcuts
  setOptions: function(new_options) {
    extend(this.options, new_options);
    if (('
checked' in new_options) || ('checkedValue' in new_options) || ('notCheckedValue' in new_options)) {
      this.setState(this.options.checked, false, true);
    }
  },
  checked: function(value) {
    if (value !== undefined) this.setState(value);
    return this.options.checked;
  },
  val: function() {
    return this.resultField.value;
  }
});

//
// Radiobutton class
//
createChildClass('
Radiobutton', UiControl, {
  // Static class fields
  common: {
    _radio_buttons: {},
    _callbacks: {},
    // static methods
    deselect: function(name) {
      for (var i = 0; i < this._radio_buttons[name].length; ++i) {
        this._radio_buttons[name][i].checked(false);
      }
    },
    select: function(name, value) {
      for (var i = 0; i < this._radio_buttons[name].length; ++i) {
        if (this._radio_buttons[name][i].val() == value) {
          this._radio_buttons[name][i].checked(true);
          return;
        }
      }
    },
    setChangeEvent: function(name, callback) {
      if (isFunction(callback)) this._callbacks[name] = callback;
      else delete(this._callbacks[name]);
    }
  },

  // Standart object fields
  CSS: {
    STANDART: '
radiobutton_',
    CONTAINER: '
radiobtn_container'
  },
  defaultOptions: {
    checked: false,
    width: 300,
    label: '
radiobutton'
  },
  controlName: '
Radiobutton',

  beforeInit: function() {
    this.guid = _ui.reg(this);
  },
  initOptions: function(input, options) {
    if (!input) return false;
    this.options = extend({}, this.defaultOptions, {
      value: input.value,
      resultField: input.name || '
radiobutton'
    }, options);
    this.options.checked = intval(this.options.checked) ? true : false;
    this.options.width = intval(this.options.width) > 0 ? intval(this.options.width) : this.defaultOptions.width;
  },
  init: function() {
    this.disabled = false;
    this.is_over = false;
    this.inputName = this.options.resultField;
  },
  initDOM: function(input, options) {
    this.container = ce('
div', {
      id: '
container' + this.guid,
      className: this.CSS.CONTAINER,
      innerHTML: '
<table cellpadding=0 cellspacing=0><tr><td class="radiobtn"><div class="radiobtn_off"><div></div></div></td><td class="radiobtn_label">' + this.options.label + '<input type="radio" id="' + input.id + '" name="' + this.options.resultField + '" value="'+ (this.options.checked ? 'checked="true"' : '') + '"></td></tr></table>'
    }, {
      width: this.options.width + '
px'
    });
    input.parentNode.replaceChild(this.container, input);

    this.radiobutton = geByClass('
radiobtn_off', this.container)[0];
    this.resultField = this.container.getElementsByTagName('
input')[0];
    this.resultField.value = this.options.value;
  },
  initEvents: function() {
    addEvent(this.container, '
click mouseover mouseout', this.handleMouseEvent, false, {'self': this});
  },
  afterInit: function() {
    if (!isArray(this.common._radio_buttons[this.inputName])) {
      this.common._radio_buttons[this.inputName] = [];
    }
    this.common._radio_buttons[this.inputName].push(this);
    this.setState(this.options.checked, false, true);
  },
  destroy: function() {
    if (!vk.al || this.destroyed) return;
    for (var i = 0; i < this.common._radio_buttons[this.inputName].length; ++i) {
      if (this.common._radio_buttons[this.inputName][i] === this) {
        this.common._radio_buttons[this.inputName].splice(i, 1);
        break;
      }
    }
    if (!this.common._radio_buttons[this.inputName].length) {
      delete this.common._radio_buttons[this.inputName];
      this.common.setChangeEvent(this.inputName);
    }
    removeEvent(this.container, '
click mouseover mouseout', this.handleMouseEvent);
    this.destroyed = true;
  },

  handleMouseEvent: function(e) {
    var t = e.data.self;

    if (e.type == '
click') {
      if (!t.disabled && !t.options.checked) {
        t.setState(true);
      }
    } else {
      t.is_over = (e.type == '
mouseover');
      t.updateClass();
    }
  },
  disable: function(value) {
    if (value && !this.disabled) {
      this.disabled = true;
      addClass(this.container, '
disabled');
    } else if (!value && this.disabled) {
      this.disabled = false;
      removeClass(this.container, '
disabled');
    }
  },
  updateClass: function() {
    this.radiobutton.className = '
radiobtn_' + (this.options.checked ? 'on' : 'off') + (this.is_over ? '_over' : '');
  },
  setState: function(checked, fireEvent, forceUpdate) {
    if (fireEvent === undefined) fireEvent = true;
    forceUpdate = forceUpdate || false;
    checked = checked ? true : false;

    if (this.options.checked == checked && !forceUpdate)
      return;
    if (checked)
      this.common.deselect(this.inputName);
    this.options.checked = checked;
    this.updateClass();
    this.resultField.checked = checked;
    if (fireEvent) {
      if (this.options.checked && isFunction(this.options.onSelect))
        this.options.onSelect(this.resultField.value);

      if (isFunction(this.options.onChange))
        this.options.onChange(this.resultField.value, checked);

      if (checked) {
        if (isFunction(this.common._callbacks[this.inputName])) this.common._callbacks[this.inputName](this.resultField.value);
      }
    }
  },
  // shortcuts
  setOptions: function(new_options) {
    extend(this.options, new_options);
    if (('
checked' in new_options)) {
      this.setState(this.options.checked, false);
    }
  },
  checked: function(value) {
    if (value !== undefined) this.setState(value);
    return this.options.checked;
  },
  val: function() {
    return this.resultField.value;
  }
});

// Multiple radiobutton initialization
function Radiobuttons(input, buttons, options) {
  var id = input.id;
  Radiobutton._radio_buttons[id] = [];
  Radiobutton._callbacks[id] = [];
  each(buttons, function(i, v) {
    new Radiobutton(ge(id + v[0]), {label: v[1], width: options.width, resultField:id});
  });
  Radiobutton.select(id, options.selected !== undefined ? options.selected : input.value);
  Radiobutton.setChangeEvent(id, function(value) {
    input.value = value;
    if(isFunction(options.onChange)) {
      options.onChange(value);
    }
  });
}

//
// Autosize class
//
createChildClass('
Autosize', UiControl, {
  // Static class fields
  common: {
    _autosize_helpers: null
  },

  // Standart object fields
  CSS: {
  },
  defaultOptions: {
    height: 0,
    minHeight: 0,
    padding: 0,
    helperTA: false // new type of autosize, untested
  },
  controlName: '
Autosize',

  // Standart object methods
  beforeInit: function() {
    this.guid = _ui.reg(this);
    if (!this.common._autosize_helpers || !ge('
autosize_helpers')) {
      document.body.appendChild(
        (this.common._autosize_helpers = ce('
div', {'id': 'autosize_helpers'}, {
          '
position': 'absolute',
          '
left': '-10000px',
          '
top': '-10000px'
        }))
      );
    }
  },
  initOptions: function(textarea, options) {
    this.options = extend({}, this.defaultOptions, options);
    this.options.checked = intval(this.options.checked) ? true : false;
    this.options.width = intval(this.options.width) > 0 ? intval(this.options.width) : this.defaultOptions.width;
  },
  init: function(input) {
    this.input = input;
    this.oldValue = '';
    this.oldHeight = 0;
    this.overflowAuto = false;
  },
  initDOM: function(input) {
    this.minHeight = intval(this.options.minHeight) || intval(getStyle(input, '
height'));
    this.maxHeight = intval(this.options.height);
    this.fontSize = intval(getStyle(input, '
fontSize'));
    var w = intval(getStyle(input, '
width'));
    // fix for hidden textareas
    if (w < 1) {
      w = intval(getStyle(input, '
width', false));
    }
    if (this.defaultOptions.padding) w -= this.defaultOptions.padding * 2;

    this.common._autosize_helpers.appendChild(
      this.helper = ce(this.options.helperTA ? '
textarea' : 'div', false, {
        wordWrap: '
break-word',
        width: (w < 0 ? 0 : w) + '
px',
        fontFamily: getStyle(input, '
fontFamily'),
        fontSize: this.fontSize + '
px',
        lineHeight: getStyle(input, '
lineHeight')
      })
    );
    this.input.helper = this.helper;
    setStyle(this.input, '
overflow', 'hidden');
  },
  initEvents: function() {
    addEvent(this.input, '
keydown keypress keyup', this.updateSize, false, {'self': this});
  },
  afterInit: function() {
    this.update();
  },

  // Extended methods
  updateSize: function(event) {
    var self = event.data.self, value = self.input.value, newHeight;
    if (event.type != '
keyup') {
      if (event.keyCode == 13 && !event.ctrlKey && !event.altKey) {
        value += '
n';
      }
    }
    if (value == self.oldValue) {
      return;
    }
    self.oldValue = value;
    if (self.options.helperTA) {
      self.helper.value = value;
      newHeight = self.helper.scrollHeight + self.fontSize + 4;
    } else {
      self.helper.innerHTML = trim(replaceChars(value)).replace(/<br>$/, '
<br>&nbsp;');
      newHeight = getSize(self.helper, true)[1] + self.fontSize + 4;
    }
    newHeight = Math.max(newHeight, self.minHeight);

    if (self.maxHeight > 0 && newHeight > self.maxHeight) {
      newHeight = self.maxHeight;
      if (!self.overflowAuto) {
        if (browser.mozilla) var cr = self.input.selectionStart;
        self.overflowAuto = true;
        setStyle(self.input, {
          '
overflow': 'auto',
          '
overflowX': 'hidden'
        });
        if (browser.mozilla) self.input.setSelectionRange(cr, cr);
        self.oldHeight = newHeight;
      }
    } else {
      if (self.overflowAuto) {
        self.overflowAuto = false;
        if (browser.mozilla) var cr = self.input.selectionStart;
        self.input.style.overflow = '
hidden';
        if (browser.mozilla) self.input.setSelectionRange(cr, cr);
      }
    }
    if (self.options.preventEnter && event.keyCode == 13 && !event.shiftKey) {
      return;
    }
    if (self.oldHeight != newHeight) {
      self.input.style.height = (self.oldHeight = newHeight) + '
px';
      if (self.options.onResize) self.options.onResize(newHeight);
    }
  },
  // Shortcuts
  update: function() {
    this.updateSize({data: {self: this}});
  }
});

//
// Dropdown Menu class
//
createChildClass('
DropdownMenu', UiControl, {
  // Static class fields
  common: {
    pageContainer: null
  },
  defaultOptions: {
    title: '
Menu',
    hideOnClick: true,
    showHover: true,
    updateTarget: true,
    alwaysMenuToUp: false,
    columnsCount: false,

    offsetLeft: -7,
    offsetTop: -4,
    onSelect: function(){},
    updateHeader: function(i,t){return t;}
  },
  controlName: '
DropdownMenu',

  // Standart object methods
  beforeInit: function() {
    this.guid = _ui.reg(this);
    if (!this.common.pageContainer) {
      this.common.pageContainer = document.body;
      if (browser.msie6 && ge('
pageContainer')) {
        this.pageContainer = ge('
pageContainer');
      }
    }
  },
  initOptions: function(items, options) {
    if (!options.title && options.target) options.title = options.target.innerHTML;
    this.options = extend({}, this.defaultOptions, options);
  },
  init: function(input, options) {
    this.visible = false;
    this.offsetTop = 0;
    this.mouseTimer = 0;
    this.childMenus = [];
    this.childIsOver = false;
    if (options.parentMenu) {
      this.parentMenu = options.parentMenu;
      this.parentMenu.childMenus.push(this);
    }
    this.isOver = false;
    this.value = options.value || 0;
    this.items = {};
  },
  initDOM: function(input, options) {
    this.container = ce('
div', {
      className: '
dd_menu' + (options.containerClass ? ' '+options.containerClass : ''),
      id: '
dd_menu' + this.guid
    });

    this.header = ce('
div', {
      className: '
dd_menu_header',
      innerHTML: '
<div>' + this.options.title.replace(/s+/g, '&nbsp;') + '</div>'
    });

    this.body = ce('
div', {
      className: '
dd_menu_body',
      innerHTML: '
<table cellspacing="0" cellpadding="0"><tbody><tr><td class="dd_menu_shad_l"><div></div></td><td><div class="dd_menu_shad_t2"></div><div class="dd_menu_shad_t"></div><div id="dd_rows_'+this.guid+'" 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>'
    });

    this.container.appendChild(this.header);
    this.container.appendChild(this.body);
    hide(this.header);
    hide(this.body);

    // Container for menu items
    this.rows = ce('
div', {'id': 'rows' + this.guid, 'className' : 'dd_menu_rows2'});
  },
  initEvents: function() {
    addEvent(this.container, '
mouseover mouseout', this.handleMouseEvent, false, {'self': this});
  },
  afterInit: function(items, options) {
    this.setData(items);
    var self = this;
    onDomReady(function() {
      (self.common.pageContainer || window.pageNode).appendChild(self.container);
      var header = self.header, body = self.body, target = self.options.target;
      ge('
dd_rows_'+ self.guid).appendChild(self.rows);
      self.setOptions(self.options);
      if (target) {
        if (target.innerHTML.indexOf('
<') == -1) {
          target.innerHTML = target.innerHTML.replace(/s+/g, '
&nbsp;');
        }
        target.onclick = function() {self.show();return false;};
        if (target.tagName == '
A') {
          target.className += ' 
dd_menu_target';
        }
      }
      if (self.options.target && self.options.showHover) {
        var timer;
        var outFunc = function() {
          if (self.parentMenu) { self.parentMenu.childIsOver = false; }
          if (!self.visible) hide(header);
          removeClass(header, '
dd_header_hover');
        }
        self.showTargetHover = function() {
          if (self.parentMenu) { self.parentMenu.childIsOver = true; }
          addClass(header, '
dd_header_hover');
          self.moveToTarget();
          show(header);
          timer = setTimeout(outFunc, 100);
        };
        addEvent(self.options.target, '
mouseover', self.showTargetHover);
        addEvent(header, '
mouseover', function() {
          if (self.parentMenu) { self.parentMenu.childIsOver = true; }
          clearTimeout(timer);
        });
        addEvent(header, '
mouseout', outFunc);
      }
    });
  },

  moveTo: function(left, top) {
    left = intval(left);
    top  = intval(top);
    extend(this.container.style, {top: top + '
px', left: left + 'px'});
    setStyle(this.rows, '
width', 'auto');

    if (this.options.columnsCount && !browser.msie) {
      setStyle(this.rows, '
columnCount', 'auto');
      setStyle(this.rows, '
MozColumnCount', 'auto');
      setStyle(this.rows, '
webkitColumnCount', 'auto');
      setStyle(this.rows, '
height', 'auto');
      var itemsCount = geByTag('
a', this.rows).length;
      var bodySize   = getSize(this.body);
      var rowsWidth  = bodySize[0] - 4;
      var rowsHeight = bodySize[1] - 4;
      if (rowsHeight > 500) {
        rowsHeight = Math.round(rowsHeight / itemsCount) * Math.ceil(itemsCount / this.options.columnsCount);
        setStyle(this.rows, '
columnCount', this.options.columnsCount.toString());
        setStyle(this.rows, '
MozColumnCount', this.options.columnsCount.toString());
        setStyle(this.rows, '
webkitColumnCount', this.options.columnsCount.toString());
        setStyle(this.rows, '
width', (rowsWidth * 2) + 'px');
        setStyle(this.rows, '
height', rowsHeight + 'px');
      }
    }

    var headerWidth = getSize(this.header)[0];
    var bodyWidth = getSize(this.body)[0];
    if (headerWidth > bodyWidth){
      setStyle(this.rows, '
width', (headerWidth - 2) + 'px');
    }

    bodyWidth = getSize(this.body)[0];
    var windowWidth = document.documentElement.clientWidth;
    var bodyRight = ((left + bodyWidth > windowWidth && left + headerWidth > bodyWidth) ? (-headerWidth - 1) + '
px' : 'auto');
    setStyle(this.body, '
right', bodyRight);
  },
  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);
  },
  alignBody: function() {
    this.body.style.marginLeft = (getSize(this.header)[0] - getSize(this.body)[0] + 1) + '
px';
  },
  setData: function(items) {
    this.rows.innerHTML = '';
    if (isArray(items) && items.length) {
      for (var i=0; i<items.length; i++) {
        this.addItem(items[i]);
      }
    }
    if (this.visible && this.menuToUp()){
      var bh = getSize(this.body)[1];
      this.body.style.top = -bh+3+'
px';
      addClass(this.container, '
dd_up');
    }
  },
  addItem: function(item) {
    if (!item) return false;
    var link = ce('
a');
    if(isArray(item))item = {i: item[0], l: item[1], onClick: item[2], c: item[3], s: item[4], b: item[5], h: item[6], el: link};
    if(item.onClick && !isFunction(item.onClick)){
      var funcs = item.onClick;
      item.onClick = funcs.onClick;
      item.onMouseOver = funcs.onMouseOver;
      item.onMouseOut = funcs.onMouseOut;
    }
    link.innerHTML = (this.options.checkable ? '
<img src="/images/dropdead_check.gif">' : '') + item.l;
    if (item.i) link['
index'] = item.i;
    if (item.c) link.className = item.c;
    if (item.s) extend(link.style, item.s);
    if (item.b) extend(link.style, {backgroundImage: '
url('' item.'')', paddingLeft: '27px' });
    if (item.h) link.href = item.h;
    var self = this;

    addEvent(link, '
click', function(e) {
      self.value = e.data.item.i;
      var hide = true;
      if (isFunction(item.onClick) && item.onClick(e) === false)
        hide = false;
      if (self.options.onSelect(e) === false)
        hide = false;
      if (item.h) {
        return true; //toUrl(item.h, e);
      }
      if (hide) self.hide();
      else cancelEvent(e);
      if(self.options.updateTarget && hide) {
        var text = self.options.updateHeader(e.target.index, e.target.innerHTML);
        self.header.innerHTML = '
<div>'+text+'</div>';
        if (self.options.target) {
          self.options.target.innerHTML = text.replace(/s+/g, '
&nbsp;');
        }
      }
    }, false, {item: item});
    if (isFunction(item.onMouseOver)) {addEvent(link, '
mouseover', item.onMouseOver);}
    if (isFunction(item.onMouseOut)) {addEvent(link, '
mouseout', item.onMouseOut);}
    if (browser.msie) {
      link.onmouseover = function(){addClass(link, '
dd_a_hover');};
      link.onmouseout = function(){removeClass(link, '
dd_a_hover');};
    }

    this.items[item.i] = link;
    this.rows.appendChild(link);
    if (this.options.align == '
left') this.alignBody();
  },
  getRows: function() {
    return this.rows;
  },
  setOptions: function(options) {
    var self = this;
    extend(this.options, options);
    // apply options

    if (this.options.title)
      this.header.innerHTML = '
<div>'+this.options.title+'</div>';
    if (typeof this.options.hideOnClick != '
undefined')
      this.header.onclick = this.options.hideOnClick ? this.toggle.bind(this) : this.show.bind(this);
    if (this.options.align == '
left') this.alignBody();
  },
  onHide: function(fade) {
    this.visible = false;
    if (fade || !this.options.showHover) hide(this.header);
    else addClass(this.header, '
dd_header_hover');
    hide(this.body);
    if (this.options.onHide) this.options.onHide();
  },

  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(this.body);
    if (this.options.showHover) removeClass(this.header, '
dd_header_hover');

    this.visible = true;

    // Set menu coordinates
    if (this.menuToUp()) {
      var bh = getSize(this.body)[1];
      this.body.style.top = -bh+3+'
px';
      addClass(this.container, '
dd_up');
    } else {
      var hh = getSize(this.header)[1];
      this.body.style.top = hh-1+'
px';
      removeClass(this.container, '
dd_up');
    }

    if (this.options.onShow) {
      this.options.onShow();
    }
    _ui.sel(this.guid);
  },
  menuToUp: function() {
    if (this.options.alwaysMenuToUp) {
      return true;
    }
    var h = window.innerHeight,
    bh = getSize(this.body)[1],
    hh = getSize(this.header)[1],
    ht = getXY(this.header)[1];

    if (!h && document.documentElement) {
      h = document.documentElement.clientHeight;
    }
    var pt = this.common.pageContainer.scrollTop;
    if (!pt && !browser.msie6) pt = document.getElementsByTagName('
html')[0].scrollTop;
    if (ht - pt > bh) {
      return (hh + ht + bh > h + pt);
    }
    return false;
  },
  hide: function(fade) {
    if (!this.visible) return;
    // return;
    var self = this;
    if (self.childIsOver) {
      self.mouseTimer = setTimeout(self.hide.bind(self), 400);
      return;
    }
    each(self.childMenus, function () {
      this.hide();
    });
    var fadeSpeed = (this.options.fadeSpeed !== undefined) ? this.options.fadeSpeed : 100;
    (fade === false) ? this.onHide(false) : fadeOut(this.container, fadeSpeed, function(){
      show(self.container);
      self.onHide.call(self, true);
      _ui.sel(false);
      //if (self.options.onHide) self.options.onHide();
    });
    if (self.parentMenu) {
      self.parentMenu.childIsOver = false;
    }
  },
  val: function () {
    return this.value;
  },
  destroy: function() {
    if (!vk.al || this.destroyed) return;
    removeEvent(this.options.target, '
mouseover', this.showTargetHover);
    cleanElems(this.container, this.header);
    for (var el = this.rows.firstChild; el; el = el.nextSibling) {
      cleanElems(el);
    }
    this.destroyed = true;
  },
  handleMouseEvent: function(e) {
    var self = e.data.self;
    self.isOver = (e.type == '
mouseover');
    if (self.parentMenu) { self.parentMenu.childIsOver = self.isOver; }
    clearTimeout(self.mouseTimer);
    if (e.type == '
mouseout') {
      self.mouseTimer = setTimeout(self.hide.bind(self), 400);
    }
  },
  onEvent: function (e) {
    if (inArray(e.type, ['
keydown', 'keypress', 'keyup']) && inArray(e.keyCode, [16, 17, 18, 91])) {
      return;
    }
    var outside = true, t = e.target;
    while (t && t != t.parentNode) {
      if (t == this.container) {
        outside = false;
        break;
      }
      t = t.parentNode;
    }
    if (outside) {
      this.hide();
    }
  }
});

//
// UiControl abstract class
//
function UiUtil(args) {
  return this.__construct__(args);
}

extend(UiUtil.prototype, {
  // Constants
  defaultOptions: null,

  // List of all storages, to delete on page reload
  __components: {},
  __cid: 0,

  // Main storage for current component
  storage: null,

  // Consructor
  __construct__: function(args) {
    if (this.beforeInit) this.beforeInit.apply(this, args);
    if (this.initOptions) this.initOptions.apply(this, args);
    this.init.apply(this, args);
    if (this.initEvents) this.initEvents.apply(this, args);
    if (this.afterInit) this.afterInit.apply(this, args);
    this.__components[(this.componentName ? this.componentName : this.__className) + (this.__cid++)] = this;
    return this;
  },

  // Standart abstract methods

  // Component initialisation

  // User defined callback
  beforeInit: null,
  // Init options field
  initOptions: null,
  // init and initEvents are required
  init: null,
  // Attach events listeners to elements
  initEvents: null,
  // User defined callback
  afterInit: null
});

//
// Cache Menu class
//
createChildClass('
Cache', UiUtil, {
  defaultOptions: {
    cacheLength: 100
  },
  componentName: '
Cache',

  initOptions: function(options) {
    this.options = extend({}, this.defaultOptions, options);
  },
  init: function() {
    this.storage = {};
    this.length = 0;
  },

  setData: function(key, value) {
    if (this.length > this.options.cacheLength) {
      this.flush();
    }
    if (!(key in this.storage)){
      this.length++;
    }
    this.storage[key] = clone(value);
  },
  getData: function(key) {
    if (!this.options.cacheLength || !this.length || !(key in this.storage)) {
      return null;
    }
    return this.storage[key];
  },
  flush: function() {
    delete this.storage;
    this.storage = {};
    this.length = 0;
  }
});

//
// Indexer class
//
createChildClass('
Indexer', UiUtil, {
  defaultOptions: {
    chars: 2,
    delimeter: /[s().,-]+/
  },

  componentName: '
Indexer',

  initOptions: function(data, options) {
    this.options = extend({}, this.defaultOptions, {indexkeys: [1]}, options);
  },
  init: function(data) {
    this.setData(data);
  },

  setData: function(data) {
    delete this.storage;
    this.storage = {
      data: clone(data),
      index: {}
    };
    clearTimeout(this.indexTimer);
    this.indexTimer = setTimeout(this.createIndex.bind(this), 10);
  },
  createIndex: function() {
    if (!this.storage.data.length) return;
    this.storage.index = {};
    debug('
createIndex start' + this.storage.data.length + ' items');
    each(this.storage.data, this.indexItem.bind(this));
    debug('
createIndex ended');
  },
  indexItem: function(k, v) {
    var i, j, current_words = '', index_key, already_indexed = {};
    for (i = 0; i < this.options.indexkeys.length; i++) {
      if (!v[this.options.indexkeys[i]]) continue;
      current_words += ' ' + v[this.options.indexkeys[i]].replace(this.options.delimeter, ' ').replace(/<[^>]*>/, '');
    }
    current_words = trim(winToUtf(current_words).toLowerCase()).split(/s+/);
    for (i = 0; i < current_words.length; i++) {
      for (j = 1; j <= this.options.chars; j++) {
        index_key = current_words[i].substr(0, j);
        if (already_indexed[index_key]) {
          continue;
        }
        already_indexed[index_key] = 1;
        if (this.storage.index[index_key] === undefined) this.storage.index[index_key] = [];
        this.storage.index[index_key].push(k);
      }
    }
  },
  search: function(pattern) {
    debug('
search startindex width' + this.options.chars + 'data size' + this.storage.data.length);
    pattern = trim(pattern.toLowerCase().replace(this.options.delimeter, ' '));
    debug('
pattern'+pattern+'length' + pattern.length);
    var self = this;
    if (!pattern) {
      debug('
empty pattern, return whole list');
      return self.storage.data;
    }
    if (pattern.length <= this.options.chars && pattern.indexOf(' ') == -1) {
      debug('
found whole pattern indexed');
      var retArr = [];
      each ((this.storage.index[pattern] || []), function() {
        retArr.push(self.storage.data[this]);
      });
      return retArr;
    }

    pattern = pattern.split(' ');
    var min_size = 0, min_pattern = '', self = this;
    each (pattern, function() {
      var items = self.storage.index[this.substr(0, self.options.chars)];
      if (!min_pattern || !items || items.length < min_size) {
        min_size = items ? items.length : 0;
        min_pattern = this.substr(0, self.options.chars);
      }
      return !min_size;
    });
    var ret_arr = [];
    debug('
index returned' + min_size + ' items');
    if (!min_size) return ret_arr;
    debug('
starting manual filter');

    each (self.storage.index[min_pattern.substr(0, self.options.chars)], function(k, v) {
      var item = self.storage.data[v];
      var i, fail = false, current_words = '', index_key;
      for (i = 0; i < self.options.indexkeys.length; i++) {
        current_words += ' ' + item[self.options.indexkeys[i]].replace(self.options.delimeter, ' ').replace('
<b>', '').replace('</b>', '');
      }
      current_words = winToUtf(current_words).toLowerCase();
      for (i = 0; i < pattern.length; i++) {
        if (current_words.indexOf(' ' + pattern[i]) == -1) {
          fail = true;
          break;
        }
      }
      if (fail) return;
      ret_arr.push(item);
    });
    debug('
manual filter endedfound ' + ret_arr.length + ' items');
    return ret_arr;
  },
  flush: function() {
    delete this.storage;
  }
});

var curInlineEdit = false;
if (!window.inlineOnEvent) {
  window.inlineOnEvent = function(e) {
    if (!curInlineEdit) return;
    if (e.type == '
mousedown') {
      var outside = true, t = e.target;
      while (t && t != t.parentNode) {
        if (t == curInlineEdit.container) {
          outside = false;
          break;
        }
        t = t.parentNode;
      }
      if (!outside || !isVisible(curInlineEdit.container)) return;
      curInlineEdit.hide();
    }
    if (e.type == '
keydown') {
      if (!isVisible(curInlineEdit.container)) return;
      if (e.keyCode == KEY.ESC) curInlineEdit.hide();
      if (e.keyCode == KEY.RETURN) {
        if (!curInlineEdit.options.onConfirm || curInlineEdit.options.onConfirm.apply(curInlineEdit) !== false) curInlineEdit.hide();
      }
    }
  }
  addEvent(document, '
mousedown keydown', inlineOnEvent);
}

//
// InlineEdit class
//
createChildClass('
InlineEdit', UiControl, {
  // Static class fields
  common: {
    pageContainer: null
  },
  defaultOptions: {
    offsetLeft: -20 + (browser.msie7 ? 2 : (browser.opera || browser.msie ? 3 : (browser.safari || browser.chrome ? 0 : (browser.mozilla ? 2 : 0)))),
    offsetTop: -20 + (browser.msie7 ? 2 : (browser.opera || browser.msie ? 3 : (browser.safari || browser.chrome ? 1 : (browser.mozilla ? 3 : 0)))),
    top: 0,
    left: 0,
    width: '
auto',
    flex: false,

    mainTableHTML:
  '
<tbody><tr><td class="inlFrame00"></td><td class="inlFrame01"><div></div></td><td class="inlFrame02"></td></tr>
   <
tr><td class="inlFrame10"></td><td class="inlContent">{content_table}</td><td class="inlFrame12"></td></tr>
   <
tr><td class="inlFrame20"></td><td class="inlFrame21"><div></div></td><td class="inlFrame22"></td></tr></tbody>',

    contentTableHTML:
  '
<tbody>{content}
   <
tr>
    <
td class="inlButtonOk"><div class="button_yes"><div>{yeslabel}</div></div></td>
    <
td class="inlButtonCancel"><div class="button_no"><div>{nolabel}</div></div></td>
   </
tr></tbody>',
    contentHTML: '
<tr><td><input class="inlInput text" type="text" /></td></tr>',

    confirmLabel: getLang('
global_save'),
    cancelLabel: getLang('
global_cancel'),

    onBeforeShow: null,
    onShow: null,
    onHide: null,
    onConfirm: null,
    onCancel: null
  },
  controlName: '
InlineEdit',

  // Standart object methods
  beforeInit: function() {
    if (!this.common.pageContainer) {
      this.common.pageContainer = document.body;
      if (browser.msie6 && ge('
pageContainer')) {
        this.pageContainer = ge('
pageContainer');
      }
    }
    this.guid = _ui.reg(this);
  },
  initOptions: function(target, options) {
    if (!target) return false;
    this.options = extend({}, this.defaultOptions, options);
  },
  init: function(target) {
    this.target = target;
  },
  initDOM: function(target, options) {
    this.container =  ce('
div', {
      className: '
inlContainer',
      id: '
container' + this.guid,
      innerHTML: '
<table class="inlMainTable">' + this.options.mainTableHTML.replace('{content_table}', '<table class="inlContentTable">' + this.options.contentTableHTML.replace('{content}', this.options.contentHTML).replace('{nolabel}', this.options.cancelLabel).replace('{yeslabel}', this.options.confirmLabel) + '</table>') + '</table>'
    });

    this.mainTable = geByClass('
inlMainTable', this.container)[0];
    this.mainCell = geByClass('
inlContent', this.mainTable)[0];
    this.contentTable = geByClass('
inlContentTable', this.mainCell)[0];
    setStyle(this.contentTable, '
width', this.options.width);

    this.input = geByClass('
inlInput', this.contentTable)[0];
    this.buttonOkCell = geByClass('
inlButtonOk', this.contentTable)[0];
    this.buttonCancelCell = geByClass('
inlButtonCancel', this.contentTable)[0];
    this.buttonOk = this.buttonOkCell.firstChild.firstChild;
    this.buttonCancel = this.buttonCancelCell.firstChild.firstChild;

    this.container.appendChild(this.mainTable);
    this.mainCell.appendChild(this.contentTable);
  },
  initEvents: function() {
    var self = this;
    createButton(this.buttonOk, function() {
      if (!self.options.onConfirm || self.options.onConfirm.apply(self) !== false) self.hide();
    });
    createButton(this.buttonCancel, function() {
      if (!self.options.onCancel || self.options.onCancel.apply(self) !== false) self.hide();
    });
    addEvent(this.target, '
click', function() {self.show(); return false;});
    this.onEvent = function(e) {
    }
  },
  afterInit: function(target, options) {
    if (this.options.afterInit) {
      this.options.afterInit.apply(this);
    }
    var self = this;
    onDomReady(function() {
      self.common.pageContainer.appendChild(self.container);
    });
  },
  hide: function() {
    if (!isVisible(this.container)) return;
    hide(this.container);
    if (curInlineEdit == this) curInlineEdit = false;
    if (this.options.onHide) this.options.onHide.apply(this);
  },
  moveTo: function(left, top) {
    setStyle(this.container, {top: intval(top)+'
px', left: intval(left) + 'px'});
  },
  moveToTarget: function() {
    var tc = getXY(this.target);
    this.moveTo(tc[0] + this.options.offsetLeft + this.options.left, tc[1] + this.options.offsetTop + this.options.top);
  },
  setOptions: function(options) {
    var self = this;
    extend(this.options, options);
  },

  toggle: function() {
    this.visible ? this.hide(false) : this.show();
  },
  show: function() {
    if (isVisible(this.container)) return;
    this.moveToTarget();

    if (this.options.onBeforeShow) {
      this.options.onBeforeShow.apply(this);
    }
    show(this.container);
    if (curInlineEdit) curInlineEdit.hide();
    curInlineEdit = this;
    if (this.input) elfocus(this.input);

    if (this.options.onShow) {
      this.options.onShow.apply(this);
    }
  }
});

try{jsDispatcher.triggerOnload('
lib/ui_controls');}catch(e){}
try{stManager.done('
ui_controls.js');}catch(e){}
?>
Онлайн: 2
Реклама