Показать сообщение отдельно
  #4 (permalink)  
Старый 08.03.2010, 16:00
Аватар для subzey
Пионэр
Отправить личное сообщение для subzey Посмотреть профиль Найти все сообщения от subzey
 
Регистрация: 16.11.2009
Сообщений: 1,322

Обычно я не пишу готовые скрипты в ответах, но этот случай мне почему-то приглянулся.

Во-первых, нужно немного изменить код, чтобы обычные и контрольный чекбоксы чем-то разделялись, я предлагаю использовать для этого связку fieldset — legend, ибо семантика. А уж стили на все это натянуть можно любые и при необходимости добавить другие элементы оформления. Главное — fieldset с классом "js-tree-box" (вдруг, в форме будут другие филдсеты) и легенда.

Код можно засунуть в head страницы — он будет послушно ждать, пока на странице появятся чекбоксы и пользователь их кликнет.
<fieldset class="js-tree-box">
	<legend>
		<label><input type="checkbox" name="obl[]" value="61" />Ростовская</label>
	</legend>
	<label><input type="checkbox" name="gorod[]" value="346780">Азов</label>
	<label><input type="checkbox" name="gorod[]" value="346400">Новочеркасск</label>
	<label><input type="checkbox" name="gorod[]" value="344000">Ростов-на-Дону</label>
	<label><input type="checkbox" name="gorod[]" value="347900">Таганрог</label>
</fieldset>
<fieldset class="js-tree-box">
	<legend>
		<label><input type="checkbox" name="obl[]" value="61" />Ростовская</label>
	</legend>
	<label><input type="checkbox" name="gorod[]" value="346780">Азов</label>
	<label><input type="checkbox" name="gorod[]" value="346400">Новочеркасск</label>
	<label><input type="checkbox" name="gorod[]" value="344000">Ростов-на-Дону</label>
	<label><input type="checkbox" name="gorod[]" value="347900">Таганрог</label>
</fieldset>
…и так далее.

<script>
(function(){ // этот кусок кода автономен, выносим в отдельную область данных
	function clicker(e){ // выполняется при любом кликие или изменении
		var legendObject;
		var fieldsetObject;
		var controlCheckbox;
		
		var trigger = e.srcElement||e.target; // кто вызвал событие?
		if (!trigger.tagName || trigger.tagName.toLowerCase() != "input" || trigger.type.toLowerCase() != "checkbox") return; // если это не чекбокс — делать нам тут нечего
		
		// пробегаемся по всем родителям
		var testElement = trigger;
		while (testElement){
			if (!testElement.tagName) return; // неявно — корень дерева, и мы ничего не нашли
			var tagName = testElement.tagName.toLowerCase();
			if (tagName == "legend") { // по пути встретили legend
				legendObject = testElement;
			} else if (tagName == "fieldset" && /(^|\s)+js-tree-box(\s|$)+/.test(testElement.className)) { // или fieldset с нужным классом
				fieldsetObject = testElement;
				break;
			}
			testElement = testElement.parentNode; // выбираем родителя и повторяем итерацию для него
		};
		if (!fieldsetObject) return;
		if (legendObject){ // т.е., чекбокс внутри легенды
			var controlCheckboxValue = trigger.checked;
			var inputs = fieldsetObject.getElementsByTagName("input");
			for(var i=0; i<inputs.length; i++){
				var input = inputs[i];
				if (input.type.toLowerCase() == "checkbox" && input != controlCheckbox){
					input.checked = controlCheckboxValue;
				};
			};
		} else {
			// находим «контрольный» чекбокс
			if (legendObject = fieldsetObject.getElementsByTagName("legend")[0]){
				var inputs = legendObject.getElementsByTagName("input");
				for(var i=0; i<inputs.length; i++){
					var input = inputs[i];
					if (input.type.toLowerCase() == "checkbox"){
						controlCheckbox = input;
						break;
					};
				};
			};
			if (!controlCheckbox) return;
			var controlCheckboxValue = true;
			// пробегаемся по всем чекбоксам
			var inputs = fieldsetObject.getElementsByTagName("input");
			for(var i=0; i<inputs.length; i++){
				var input = inputs[i];
				// есть неотмеченные?
				if (input.type.toLowerCase() == "checkbox" && input != controlCheckbox && !input.checked){
					controlCheckboxValue = false;
				};
			};
			// устанавливаем значение в контрольный
			controlCheckbox.checked = controlCheckboxValue;
		}
	};
	
	// щелчков будет намного меньше, чем элементов — отлавливаем события через bubbling
	if (document.addEventListener){
		document.addEventListener('change', clicker, false);
		document.addEventListener('click', clicker, false);
	} else {
		document.attachEvent('onchange', clicker);
		document.attachEvent('onclick', clicker);
	};
})();
</script>


Главное, господа, разделение кода и представления. А прописывать каждому чекбоксу уникальный id — проще застрелиться.
Ответить с цитированием