/**
|
* Created by chamaeleon (chamaeleon-nitr[at]yandex.ru).
|
* Date: 07.09.13
|
* Time: 22:55
|
*/
|
|
var bindReady = function (handler) {
|
var called = false,
|
isFrame,
|
fn;
|
|
function ready() {
|
if (called) {
|
return;
|
}
|
called = true;
|
handler();
|
}
|
|
function tryScroll() {
|
if (called) {
|
return;
|
}
|
try {
|
document.documentElement.doScroll("left");
|
ready();
|
} catch (e) {
|
setTimeout(tryScroll, 10);
|
}
|
}
|
|
if (document.addEventListener) {
|
document.addEventListener("DOMContentLoaded", ready, false);
|
} else if (document.attachEvent) {// IE
|
|
try {
|
isFrame = window.frameElement !== null;
|
} catch (e) {
|
}
|
|
// IE, the document is not inside a frame
|
if (document.documentElement.doScroll && !isFrame) {
|
tryScroll();
|
}
|
|
// IE, the document is inside a frame
|
document.attachEvent("onreadystatechange", function () {
|
if (document.readyState === "complete") {
|
ready();
|
}
|
});
|
}
|
|
// Old browsers
|
if (window.addEventListener) {
|
window.addEventListener('load', ready, false);
|
} else if (window.attachEvent) {
|
window.attachEvent('onload', ready);
|
} else {
|
fn = window.onload;
|
window.onload = function () {
|
if (typeof fn === 'function') {
|
fn();
|
}
|
ready();
|
};
|
}
|
};
|
|
var ComboBox = function (id_or_element) {
|
var select = typeof id_or_element === 'string' ? document.getElementById(id_or_element) : id_or_element,
|
divs = [],
|
options,
|
parent,
|
combobox = document.createElement('div'),
|
input = document.createElement('input'),
|
list = document.createElement('div'),
|
trigger = document.createElement('div'),
|
targetSelect = null,
|
selectElem = null,
|
oldselectElem = null,
|
currentIndex = 0,
|
i,
|
el,
|
value,
|
label,
|
currentTarget,
|
escapeExp = new RegExp("([" + ["[", "]", "{", "}", "(", ")", "+", "*", "\\", "?", ".", "$", "^"].join("\\") + "])", "g");
|
if (!select) {
|
select = new Error('not found element "' + id_or_element + '"');
|
return;
|
}
|
id_or_element = typeof id_or_element === 'string' ? id_or_element : id_or_element.id;
|
|
function setSize() {
|
// size by select element
|
if (select.offsetWidth > 0) {
|
combobox.offsetWidth = select.offsetWidth;
|
input.style.width = (select.offsetWidth - 34) + 'px';
|
}
|
if (select.style.width !== '') {
|
combobox.style.width = select.style.width;
|
}
|
if (select.style.height !== '') {
|
combobox.style.height = select.style.height;
|
}
|
if (select.style.font !== '') {
|
combobox.style.font = select.style.font;
|
}
|
if (combobox.offsetWidth > 0) {
|
input.style.width = (combobox.offsetWidth - 34) + 'px';
|
}
|
if (combobox.offsetHeight > 0) {
|
list.style.top = combobox.offsetHeight + 'px';
|
}
|
}
|
// document DOM ready
|
bindReady(setSize);
|
|
// functions
|
function hide(elem) {
|
elem.style.display = 'none';
|
}
|
|
function show(elem) {
|
elem.style.display = 'block';
|
}
|
|
function toggleList() {
|
if (list.style.display && list.style.display === 'block') {
|
hide(list);
|
} else {
|
show(list);
|
}
|
}
|
|
function clearCls(classname) {
|
var regexp = new RegExp('\\s*' + (classname || 'selected') + '\\s*', 'i'),
|
i;
|
for (i = 0; i < divs.length; i++) {
|
divs[i].el.className = divs[i].el.className.replace(regexp, '');
|
}
|
}
|
|
function removeCls(el, cls) {
|
var regexp = new RegExp('\\s*' + (cls || 'selected') + '\\s*', 'i');
|
el.className = el.className.replace(regexp, '');
|
}
|
|
function addCls(el, cls) {
|
if (el) {
|
el.className = el.className + ' ' + cls;
|
}
|
}
|
|
function selection(elem) {
|
//this.className = !/selection/.test(this.className) ? this.className + ' selection' : this.className.replace(/\s*selection\s*/i, '');
|
if (elem) {
|
//clearCls('selection');
|
if (targetSelect) {
|
removeCls(targetSelect, 'selection');
|
}
|
targetSelect = elem;
|
|
addCls(elem, 'selection');
|
}
|
}
|
|
function optionSelect(elem) {
|
var oldvalue = select.value;
|
hide(list);
|
if (elem) { // && elem !== selectElem
|
input.value = elem.innerText;
|
select.value = elem.value;
|
if (typeof select.onchange === 'function' && (oldvalue !== elem.value)) { // && (elem.value && oldvalue !== elem.value)
|
select.onchange();
|
}
|
//clearCls();
|
if (selectElem) {
|
removeCls(selectElem, 'selected');
|
}
|
selectElem = elem;
|
addCls(elem, 'selected');
|
}
|
oldselectElem = selectElem;
|
}
|
|
function selectItem(el) {
|
addCls(el, 'selected');
|
if (selectElem) {
|
removeCls(selectElem, 'selected');
|
}
|
selectElem = el;
|
input.value = el.innerText;
|
}
|
|
function optionSelectEvent() {
|
optionSelect(this);
|
}
|
|
function optionMouseOverEvent(index) {
|
return function () {
|
currentIndex = index;
|
selection(this);
|
};
|
}
|
|
function filter() {
|
var regexp = new RegExp('(' + input.value.replace(escapeExp, "\\$1") + ')', 'i'),
|
i,
|
elem;
|
targetSelect = selectElem;
|
clearCls('selection');
|
|
for (i = 0; i < divs.length; i++) {
|
elem = divs[i].el;
|
if (!regexp.test(divs[i].label)) {
|
if (selectElem === elem) {
|
removeCls(selectElem, 'selected');
|
selectElem = null;
|
}
|
hide(elem);
|
if (targetSelect === elem) {
|
removeCls(targetSelect, 'selection');
|
targetSelect = null;
|
}
|
} else {
|
elem.innerHTML = elem.innerHTML.replace(/<(b|\/b)>/ig, '');
|
elem.innerHTML = elem.innerHTML.replace(regexp, '<b>$1</b>');
|
show(elem);
|
if (!targetSelect) {
|
currentIndex = i;
|
selection(elem);
|
}
|
}
|
}
|
if (oldselectElem && regexp.test(oldselectElem.innerHTML) && !selectElem) {
|
if (!selectElem) {
|
selectElem = oldselectElem;
|
}
|
addCls(oldselectElem, 'selected');
|
}
|
}
|
|
function selectFirstItem() {
|
var regexp = new RegExp(input.value.replace(escapeExp, "\\$1"), 'i');
|
if (targetSelect && (!selectElem || !selectElem.value)) {
|
optionSelect(targetSelect);
|
} else if (!selectElem && oldselectElem && regexp.test(oldselectElem.innerHTML)) {
|
optionSelect(oldselectElem);
|
} else {
|
selectItem(selectElem);
|
}
|
}
|
|
select.style.display = 'none';
|
combobox.setAttribute('id', 'cb_' + id_or_element);
|
combobox.className = 'combobox';
|
list.className = 'cblist';
|
list.style.display = 'none';
|
input.className = 'cbinput';
|
input.setAttribute('type', 'text');
|
trigger.className = 'cbtrigger';
|
//trigger.innerHTML = '▼';
|
trigger.innerHTML = '<img alt="">▼';
|
|
// parent element of select
|
parent = select.parentElement;
|
|
// insert into DOM
|
parent.insertBefore(combobox, select);
|
combobox.insertBefore(list, null);
|
combobox.insertBefore(trigger, null);
|
combobox.insertBefore(input, list);
|
|
options = select.getElementsByTagName('option');
|
for (i = 0; i < options.length; i++) {
|
el = document.createElement('div');
|
value = options.item(i).value;
|
label = options.item(i).text || value;
|
el.setAttribute('value', value);
|
el.value = value;
|
el.innerText = label;
|
el.onclick = optionSelectEvent;
|
el.onmouseover = optionMouseOverEvent(i);
|
divs.push({
|
label: label,
|
value: value,
|
el: el
|
});
|
if (value === '' || !value) {
|
selectItem(el);
|
}
|
if (options.item(i).selected && el !== selectElem) {
|
selectItem(el);
|
}
|
list.insertBefore(el, null);
|
}
|
|
trigger.onclick = function () {
|
if (selectElem && !selectElem.value) {
|
input.value = '';
|
}
|
input.select();
|
setTimeout(function () {
|
toggleList();
|
}, 200);
|
};
|
input.onclick = function () {
|
if (selectElem && !selectElem.value) {
|
input.value = '';
|
}
|
input.select();
|
setTimeout(function () {
|
toggleList();
|
}, 200);
|
};
|
|
input.onblur = function () {
|
setTimeout(function () {
|
hide(list);
|
selectFirstItem();
|
//optionSelect(selectElem);
|
}, 200);
|
};
|
|
input.onkeyup = function (e) {
|
e = e || window.event;
|
|
// enter
|
if (e.keyCode === 13) {
|
targetSelect = divs[currentIndex].el;
|
optionSelect(targetSelect);
|
e.cancelBubble = true;
|
} else if (e.keyCode === 38 || e.keyCode === 40) {
|
e.cancelBubble = true;
|
} else {
|
show(list);
|
filter();
|
}
|
};
|
|
input.onkeydown = function (e) {
|
e = e || window.event;
|
var elem;
|
|
if (e.keyCode === 38) {
|
// up
|
elem = divs[currentIndex].el;
|
removeCls(elem, 'selection');
|
currentIndex--;
|
if (!divs[currentIndex]) {
|
currentIndex = divs.length - 1;
|
}
|
targetSelect = divs[currentIndex].el;
|
addCls(targetSelect, 'selection');
|
targetSelect.scrollIntoView(false);
|
e.cancelBubble = true;
|
if (navigator.appName !== 'Microsoft Internet Explorer') { //!/msie/i.test(navigator.userAgent.toLowerCase())
|
e.preventDefault();
|
e.stopPropagation();
|
}
|
} else if (e.keyCode === 40) {
|
// down
|
elem = divs[currentIndex].el;
|
removeCls(elem, 'selection');
|
currentIndex++;
|
if (!divs[currentIndex]) {
|
currentIndex = 0;
|
}
|
targetSelect = divs[currentIndex].el;
|
addCls(targetSelect, 'selection');
|
targetSelect.scrollIntoView(false);
|
e.cancelBubble = true;
|
if (navigator.appName !== 'Microsoft Internet Explorer') { //!/msie/i.test(navigator.userAgent.toLowerCase())
|
e.preventDefault();
|
e.stopPropagation();
|
}
|
}
|
};
|
|
setSize();
|
};
|
|
/*function generateCombobox() {
|
var selects = document.querySelectorAll('select[combobox="true"]'),
|
i,
|
el,
|
cb;
|
console.log(selects);
|
for (i = 0; i < selects.length; i++) {
|
el = selects[i];
|
if (el && !document.getElementById('cb_' + el.id)) {
|
cb = new ComboBox(selects[i]);
|
}
|
}
|
}*/
|