Кастомизация
06
Авг
2

Выбор из списка возможных значений

Как-то тут был пост про Выбор из списка существующих значений, в котором рассказывалось как упростить ввод одних и тех же значений в какое-либо поле. Тот пример брал список значений из ранее введенных записей (того же объекта), но это несколько не рацианально, если Ваш список имеет постоянное количество значений и они никогда не меняются (ну, или редка меняются 🙂 ). Например, список стран. Поэтому сейчас сделаем статический список 🙂

Итак, начнем: просто скопируйте следующую функцию в событие onload любого объекта:

function SuggestionTextBox(textfield, method, preload) {
	// максимальное количество значений в списке предложений
	var maxItems = 6;
    
	this.suggestionList = new Array();
	this.suggestionListDisplayed = new Array();
	var actual_textfield = textfield;
	var actual_value = '';
	var selectedNumber = 0;
	var countMatches = 0;
    
	if (preload) {
		// загружаем данные через внешний метод
		this.suggestionList = method();
	}
    
	// прикрепляем функцию к полю
    
	textfield.attachEvent("onfocus", initTextfield);
 
	// прикрепляем необходимые события
	function initTextfield() {
		// при смене фокуса с поля мы должны очистить наш сайт   
		textfield.attachEvent("onblur", resetTextfield);
		document.attachEvent("onkeydown", keyDown);
	}

	function resetTextfield(e) {
		// при смене фокуса мы должны удалить все прикрепленные события
		document.detachEvent("onkeydown", keyDown);
		textfield.detachEvent("onblur",resetTextfield);
    }

	function keyDown(e) {
		keyCode = e.keyCode;

		switch (keyCode) {
			case 9: case 13:
				// клавиши enter и tab
				if (countMatches > 0) {
					actual_textfield.value = suggestionListDisplayed[selectedNumber];
					if (document.getElementById('suggestion_table') != null) document.body.removeChild(document.getElementById('suggestion_table'));
				}
			break;
			case 38:
				// нажатие клавиши «вверх»
				if(selectedNumber > 0 && countMatches > 0) {
					selectedNumber--;
					createSuggestionTable();
				}
                
				return false;
			break;
			case 40:
				// нажатие клавиши «вниз»
				if(selectedNumber < countMatches-1 && countMatches > 0 && selectedNumber < maxItems) {
					selectedNumber++;
					createSuggestionTable();
				}
                
				return false;
			break;                
			default:
				// не вызывайте функцию слишком часто
				setTimeout(
					function() {
						executeSuggestion(keyCode)
					},  200 /* в миллисекундах */
				);
			break;
		}
	}

	function executeSuggestion(keyCode) {
		selectedNumber = 0;
		countMatches = 0;
        
		actual_value = textfield.value;
		
        // Чтобы добавить keyCode получаем все возможные значения из suggestionList
        
		if (!preload) {
			// загружаем данные через внешний метод, чтобы добавить некую функцию кэширования
			this.suggestionList = method();
		}
        
		// используем регулярные выражения для сопоставления со списком предложений
		var re = new RegExp(actual_value, "i");
        
		// Раскоменьте эту строчку (и закомменьте предыдущую) если хотите осуществлять поиск только с начала строк
		//var re = new RegExp("^" + actual_value, "i");
                
		countMatches = 0;
		this.suggestionListDisplayed = new Array();
        
		// веряем каждый элемент на соответствию шаблону RE
		for (i = 0; i < this.suggestionList.length; i++) {
			// если это условие пройдено, то добавляем элемент к массиву suggestionListDisplayed
			if (re.test(this.suggestionList[i]) && actual_value != '') {
				this.suggestionListDisplayed[countMatches] = this.suggestionList[i];
				countMatches++;
                
				// если значений больше чем в maxItems, то прекращаем просмотр
				if (maxItems == countMatches)
					break;
			}
		}
        
		if (countMatches > 0) {
			createSuggestionTable();
		} else {
			if (document.getElementById('suggestion_table')) 
				document.body.removeChild(document.getElementById('suggestion_table'));
		}
	}
   
	function createSuggestionTable() {
        
		if (document.getElementById('suggestion_table'))
			document.body.removeChild(document.getElementById('suggestion_table'));
        
		// создание объекта таблицы, который содержит список предложений
		table = document.createElement('table');
		table.id = 'suggestion_table';
        
		table.width = actual_textfield.style.width;
		table.style.position= 'absolute';
		table.style.zIndex = '100000';

		table.cellSpacing = '1px';
		table.cellPadding = '2px';

		topValue = 0;
		objTop = actual_textfield;
		while(objTop) {
			topValue += objTop.offsetTop;
			objTop = objTop.offsetParent;
		}
        
		table.style.top = eval(topValue + actual_textfield.offsetHeight) + "px";

		leftValue = 0;
		objLeft = actual_textfield
		while(objLeft) {
			leftValue += objLeft.offsetLeft;
			objLeft = objLeft.offsetParent;
		}

		table.style.left = leftValue + "px";
        
		table.style.backgroundColor = '#FFFFFF';
		table.style.border = "solid 1px #7F9DB9";
		table.style.borderTop = "none";
        
		document.body.appendChild(table);
        
		// просмотр списка для создания строк таблицы        
		for ( i = 0; i < this.suggestionListDisplayed.length; i++) {
			row = table.insertRow(-1);
                
			row.id = 'suggestion_row' + (i);
			column = row.insertCell(-1);
			column.id = 'suggestion_column' + (i);
                
			if (selectedNumber == i) {
				column.style.color = '#ffffff';
				column.style.backgroundColor = '#316AC5';
			} else {
				column.style.color = '#000000';
				column.style.backgroundColor = '#ffffff';
			}
                
			column.style.fontFamily = 'Tahoma';
			column.style.fontSize = '11px';
			column.innerHTML = this.suggestionListDisplayed[i];
        }
    }
    
	// возвращаем объект
	return this;
}

Затем, мы должны вызвать функцию для каждого текстового поля, для которого хотим задать ниспадающий список:

var f = function ListOfCountries() {
	return new Array('Директор','Заместитель директора по Маркетингу','Заместитель директора по Продажам','Коммерческий директор','Бухгалтер','Менеджер по продажам','Маркетолог');
}
    
var obj = SuggestionTextBox(document.getElementById('jobtitle'), f, true);

Мы вызываем функцию «SuggestionTextBox» и передаем ей три параметра:

  • Имя текстового поля (внутри метода getElementById) для которого добавляем список предложений. Т.е. первый параметр будет выглядеть так:
    document.getElementById('<имя_текстового_поля>')
  • Функция (в данном случи это «f»), которая возвращает массив строк со всеми возможными значениями;
  • Последний параметр определяет, (если true) будет ли список значений составлен только один раз при первом нажатии клавиши или (если false) он будет обновляться при каждом нажатии клавиши (и соответственно отбор данных будет осуществляться уже по нескольким буквам).

В этом примере, есть только функция «f», которая содержит список профессий и один экземпляр функции SuggestionTextBox. Если хотите добавить еще ниспадающие списки с предопределенными значениями просто скопируйте эти две функции и измените их нужным Вам образом (т.е. составьте нужный список значений и передайте нужные параметры в функцию SuggestionTextBox).


Комментарии (2)
  • scint 06.08.2009

    когда я выбираю из списка возможных значений, а затем перехожу на другое поле, то у меня не срабатывает onChange данного поля. Почему?

  • slivka_83 06.08.2009

    Событие onChange поля будет срабатывать только если обращаться к нему через

    crmForm.all.

    А мы работаем напрямую через HTML

    document.getElementById('jobtitle')

    Чтобы исправить это можете передавать в функцию и поле CRM в виде:

    crmForm.all.<поле>

    а затем фнутри функции (где-нить в конце кода) вызывать принудитьлно событие onChange для него

    field.FireOnChange();

    field здесь это алиас который Вы назначите в параметрах функции.

*

code