PageSourceSearch

https://gkh24.ru/components/sitemap/js/jquery.tree.js

js gkh24.ru collected 2026-10-04 01:40:20 UTC 7,866 bytes, 207 lines download raw bytes

1/**
2 * jQuery Tree Control
3 *
4 * @author Maxim Vasiliev
5 */
6(function($){
7
8	var CLASS_JQUERY_TREE = 'jquery-tree';
9	var CLASS_JQUERY_TREE_CONTROLS = 'jquery-tree-controls';
10	var CLASS_JQUERY_TREE_COLLAPSE_ALL = 'jquery-tree-collapseall';
11	var CLASS_JQUERY_TREE_EXPAND_ALL = 'jquery-tree-expandall';
12	var CLASS_JQUERY_TREE_COLLAPSED = 'jquery-tree-collapsed';
13	var CLASS_JQUERY_TREE_HANDLE = 'jquery-tree-handle';
14	var CLASS_JQUERY_TREE_TITLE = 'jquery-tree-title';
15	var CLASS_JQUERY_TREE_NODE = 'jquery-tree-node';
16	var CLASS_JQUERY_TREE_LEAF = 'jquery-tree-leaf';
17	var CLASS_JQUERY_TREE_CHECKED = 'jquery-tree-checked';
18	var CLASS_JQUERY_TREE_UNCHECKED = 'jquery-tree-unchecked';
19	var CLASS_JQUERY_TREE_CHECKED_PARTIAL = 'jquery-tree-checked-partial';
20
21	var COLLAPSE_ALL_CODE = '<span class="' + CLASS_JQUERY_TREE_COLLAPSE_ALL + '">Свернуть все</span>';
22	var EXPAND_ALL_CODE = '<span class="' + CLASS_JQUERY_TREE_EXPAND_ALL + '">Развернуть все</span>';
23	var TREE_CONTROLS_CODE = '<div class="' + CLASS_JQUERY_TREE_CONTROLS + '">' +
24	COLLAPSE_ALL_CODE +
25	EXPAND_ALL_CODE +
26	'</div>';
27
28	var TREE_NODE_HANDLE_CODE = '<span class="' + CLASS_JQUERY_TREE_HANDLE + '">+</span>';
29	var TREE_NODE_HANDLE_COLLAPSED = "+";
30	var TREE_NODE_HANDLE_EXPANDED = "&minus;";
31
32	$.fn.extend({
33
34		/**
35		 * Делает дерево из структуры вида:
36		 * <ul>
37		 *   <li><label><input type="checkbox" />Item1</label></li>
38		 *   <li>
39		 *     <label><input type="checkbox" />ItemWithSubitems</label>
40		 *     <ul>
41		 *       <li><label><input type="checkbox" />Subitem1</label></li>
42		 *     </ul>
43		 *   </li>
44		 * </ul>
45		 */
46		Tree: function(){
47			// Добавим контролы для всего дерева (все свернуть, развернуть и т.д.), и добавим класс
48			$(this)
49				.addClass(CLASS_JQUERY_TREE)
50				.before(TREE_CONTROLS_CODE)
51				.prev('.' + CLASS_JQUERY_TREE_CONTROLS)
52				.find('.' + CLASS_JQUERY_TREE_COLLAPSE_ALL).click(function(){
53					$(this).parent().next('.' + CLASS_JQUERY_TREE)
54						.find('li:has(ul)')
55						.addClass(CLASS_JQUERY_TREE_COLLAPSED)
56						.find('.' + CLASS_JQUERY_TREE_HANDLE)
57						.html(TREE_NODE_HANDLE_COLLAPSED);
58				})
59
60				.parent('.' + CLASS_JQUERY_TREE_CONTROLS).find('.' + CLASS_JQUERY_TREE_EXPAND_ALL)
61					.click(function(){
62						$(this).parent().next('.' + CLASS_JQUERY_TREE)
63							.find('li:has(ul)')
64								.removeClass(CLASS_JQUERY_TREE_COLLAPSED)
65							.find('.' + CLASS_JQUERY_TREE_HANDLE)
66								.html(TREE_NODE_HANDLE_EXPANDED);
67					});
68
69			$('li', this).find(':first').addClass(CLASS_JQUERY_TREE_TITLE)
70				.closest('li').addClass(CLASS_JQUERY_TREE_LEAF);
71
72			// Для всех элементов, являющихся узлами (имеющих дочерние элементы)...
73			$('li:has(ul:has(li))', this).find(':first')
74				// ... добавим элемент, открывающий/закрывающий узел
75				.before(TREE_NODE_HANDLE_CODE)
76				// ... добавим к контейнеру класс "узел дерева" и "свернем".
77				.closest('li')
78					.addClass(CLASS_JQUERY_TREE_NODE)
79					.addClass(CLASS_JQUERY_TREE_COLLAPSED)
80					.removeClass(CLASS_JQUERY_TREE_LEAF);
81
82			// ... повесим обработчик клика
83			$('.' + CLASS_JQUERY_TREE_HANDLE, this).bind('click', function(){
84				var leafContainer = $(this).parent('li');
85				var leafHandle = leafContainer.find('>.' + CLASS_JQUERY_TREE_HANDLE);
86
87				leafContainer.toggleClass(CLASS_JQUERY_TREE_COLLAPSED);
88
89				if (leafContainer.hasClass(CLASS_JQUERY_TREE_COLLAPSED))
90					leafHandle.html(TREE_NODE_HANDLE_COLLAPSED);
91				else
92					leafHandle.html(TREE_NODE_HANDLE_EXPANDED);
93			});
94
95			// Добавляем обработку клика по чекбоксам
96			$('input:checkbox', this).click(function(){
97				setLabelClass(this);
98				checkCheckbox(this);
99			})
100			// Выставляем чекбоксам изначальные классы
101			.each(function(){
102				setLabelClass(this);
103				if (this.checked)
104					checkParentCheckboxes(this);
105			})
106			// Для IE вешаем обработчики на лейбл
107			.closest('label').click(function(){
108				labelClick(this);
109				checkCheckbox($('input:checkbox', this));
110			});
111		}
112
113	});
114
115	/**
116	 * Рекурсивно проверяет, все ли чекбоксы в поддереве родительского узла выбраны.
117	 * Если ни один чекбокс не выбран - снимает чек с родительского чекбокса
118	 * Если хотя бы один, но не все - выставляет класс CLASS_JQUERY_TREE_CHECKED_PARTIAL родительскому чекбоксу
119	 * Если все - ставит чек на родительский чекбокс
120	 *
121	 * @param {Object} checkboxElement текущий чекбокс
122	 */
123	function checkParentCheckboxes(checkboxElement){
124		if (typeof checkboxElement == 'undefined' || !checkboxElement)
125			return;
126
127		// проверим, все ли чекбоксы выделены/частично выделены на вышележащем уровне
128		var closestNode = $(checkboxElement).closest('ul');
129		var allCheckboxes = closestNode.find('input:checkbox');
130		var checkedCheckboxes = closestNode.find('input:checkbox:checked');
131
132		var allChecked = allCheckboxes.length == checkedCheckboxes.length;
133
134		var parentCheckbox = closestNode.closest('li').find('>.' + CLASS_JQUERY_TREE_TITLE + ' input:checkbox');
135
136		if (parentCheckbox.length > 0) {
137			parentCheckbox.get(0).checked = allChecked;
138
139			if (!allChecked && checkedCheckboxes.length > 0)
140				parentCheckbox.closest('label')
141					.addClass(CLASS_JQUERY_TREE_CHECKED_PARTIAL)
142					.removeClass(CLASS_JQUERY_TREE_CHECKED)
143					.removeClass(CLASS_JQUERY_TREE_UNCHECKED);
144			else
145				if (allChecked)
146					parentCheckbox.closest('label')
147						.removeClass(CLASS_JQUERY_TREE_CHECKED_PARTIAL)
148						.removeClass(CLASS_JQUERY_TREE_UNCHECKED)
149						.addClass(CLASS_JQUERY_TREE_CHECKED);
150				else
151					parentCheckbox.closest('label')
152						.removeClass(CLASS_JQUERY_TREE_CHECKED_PARTIAL)
153						.removeClass(CLASS_JQUERY_TREE_CHECKED)
154						.addClass(CLASS_JQUERY_TREE_UNCHECKED);
155
156			checkParentCheckboxes(parentCheckbox.get(0));
157		}
158	}
159
160	/**
161	 * Если у текущего чекбокса есть дочерние узлы - меняет их состояние
162	 * на состояние текущего чекбокса
163	 *
164	 * @param {Object} checkboxElement текущий чекбокс
165	 */
166	function checkCheckbox(checkboxElement){
167		// чекнем/анчекнем нижележащие чекбоксы
168		$(checkboxElement).closest('li').find('input:checkbox').each(function(){
169			this.checked = $(checkboxElement).attr('checked');
170			setLabelClass(this);
171		});
172		checkParentCheckboxes(checkboxElement);
173	};
174
175	/**
176	 * Выставляет класс лейблу в зависимости от состояния чекбокса
177	 *
178	 * @param {Object} checkboxElement чекбокс
179	 */
180	function setLabelClass(checkboxElement){
181		isChecked = $(checkboxElement).attr('checked');
182
183		if (isChecked) {
184			$(checkboxElement).closest('label')
185				.addClass(CLASS_JQUERY_TREE_CHECKED)
186				.removeClass(CLASS_JQUERY_TREE_UNCHECKED)
187				.removeClass(CLASS_JQUERY_TREE_CHECKED_PARTIAL);
188		}
189		else {
190			$(checkboxElement).closest('label')
191				.addClass(CLASS_JQUERY_TREE_UNCHECKED)
192				.removeClass(CLASS_JQUERY_TREE_CHECKED)
193				.removeClass(CLASS_JQUERY_TREE_CHECKED_PARTIAL);
194		}
195	};
196
197	/**
198	 * Обрабатывает клик по лейблу (для IE6)
199	 */
200	function labelClick(labelElement){
201		var checkbox = $('input:checkbox', labelElement);
202		var checked = checkbox.attr('checked');
203		checkbox.attr('checked', !checked);
204		setLabelClass(checkbox);
205	}
206
207})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.