Тема: JS: Editable ComboBox
С праздником, мужики!
Обычно в поле с комбобоксом можно вводить данные. Всеми это воспринимается как само собой разумеющееся.
Реализация комбобокса для браузеров (с помощью <SELECT> и <OPTION>) не подразумевает ввод текста вручную.
Ну а если оно надо? - Тогда каждый идет своим путем. Вариантов в инете - предостаточно. Вот и я предлагаю свой.
Маленький код на чистом JS без всяких фреймворков, графических элементов и новомодных изысков HTM5.
По сути к обычному объекту SELECT добавлены несколько дополнительных свойств.
Создается комбобокс командой
new ComboBox(idCell, 'idCB', '150px');
idCell - id элемента куда он будет вставляться;
'idCB' - строка, содержащая id будущего комбобокса;
'150px' - строка, содержащая ширину будущего комбобокса (если данный параметр отсутствует, то комбобокс займет 100% ширины родителя);
Помимо привычных свойств и методов, присущих любому элементу SELECT, в наш комбобокс добавлены еще четыре:
setText('mytext') - установка текста в поле ввода (того, что можно ввести вручную);
getText() - получение текста из поля ввода;
addOptions(array) - добавление новых пунктов в комбобокс (Добавляются только если такие пункты отсутствуют);
getOptions() - возвращает массив, содержащий список пунктов комбобокса.
Несколько замечаний:
1. Элемент в который подразумевается вставлять данный комбобокс должен иметь ширину, большую чем ширина комбобокса.
2. Данный комобокс создавался исключительно для IE (точнее - для HTA) и во всех IE6..IE11 смотрится вполне прилично. Попробовал в Chrom и Firefox - код четко работает и там, вот только дизайн - значительно хуже, но полагаю, желающие смогут это поправить.
Теперь, собственно, сам код с наглядным примером его использования:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv=MSThemeCompatible content=yes>
<style type="text/css">
* {font:10pt verdana;}
table {border-collapse:collapse;}
table, td {border:1px solid green;}
td {padding:4px 6px;}
</style>
<script type="text/javascript">
// ComboBox с возможностью ручного ввода
function oComboBox (oContainer, id, width) {
var oSelect = document.createElement('SELECT');
oSelect.id = id;
oSelect.style.width = width || '100%';
oSelect.style.position = 'absolute';
var oInput = document.createElement('INPUT');
oInput.style.position = 'relative';
oContainer.appendChild(oSelect);
oContainer.appendChild(oInput);
oSelect.style.top = oInput.offsetTop + 'px';
oSelect.style.clip = 'rect(auto auto auto ' + (oSelect.offsetWidth - 20) + 'px)';
oInput.style.width = oSelect.offsetWidth - 19 + 'px';
oSelect.onchange = function(){oInput.value=this.options[this.selectedIndex].text; oInput.select();};
// Установка текста в поле ввода
oSelect.setText = function(text) {
oSelect.selectedIndex = -1;
for (var j=0; j<oSelect.options.length; j++) {
if (oSelect.options[j].text.toUpperCase() == text.toUpperCase()) oSelect.selectedIndex = j;
}
oInput.value = text;
};
// Получение текста в поле ввода
oSelect.getText = function() {return oInput.value;};
// Добавление новых пунктов в ComboBox (только если такие отсутствуют)
oSelect.addOptions = function (aOptions) {
function isOptionExist(text) {
for (var j=0; j<oSelect.options.length; j++) {
if (oSelect.options[j].text.toUpperCase() == text.toUpperCase()) return true;
}
}
for (var i=0; i<aOptions.length; i++) {
if (!isOptionExist(aOptions[i])) {
var oOption = document.createElement("option");
oOption.text = aOptions[i];
oSelect.options.add(oOption);
oSelect.selectedIndex = oSelect.options.length-1;
oInput.value = oSelect.options[oSelect.options.length-1].text;
}
}
};
// Возвращает массив, содержащий список пунктов ComboBox
oSelect.getOptions = function () {
var aOptions = [];
for (var j=0; j<oSelect.options.length; j++) {
aOptions.push(oSelect.options[j].text);
}
return aOptions;
};
}
function Sample() {
var o = new oComboBox(idCell, 'idCB', '150px');
idCB.addOptions(['RED', 'GREEN', 'BLUE']);
idCB.addOptions(['yellow', 'red', 'orange']);
idCB.setText('Blue');
}
</script>
<title>Editable ComboBox</title>
</head>
<body onload="Sample();">
<table>
<tr>
<td id="idCell" style="width:200px;"></td>
<td>new methods</td>
<td>
<input type="button" value="setText(text)" onclick="idCB.setText('crimson')">
<input type="button" value="getText()" onclick="alert(idCB.getText())">
<input type="button" value="addOptions(array)" onclick="idCB.addOptions(['Violet','Silver'])">
<input type="button" value="getOptions()" onclick="alert(idCB.getOptions())">
</td>
</tr>
<tr>
<td> </td>
<td>built-in methods</td>
<td>
<input type="button" value="selectedIndex" onclick="alert(idCB.selectedIndex)">
<input type="button" value="outerHTML" onclick="alert(idCB.outerHTML)">
<input type="button" value="change option text" onclick="idCB.options[idCB.selectedIndex].text='New Text';">
</td>
</tr>
</table>
</body>
</html>
Буду рад услышать любые конструктивные замечания и предложения (для того и выкладываю).