SCDNG PELER
Server IP : 144.76.124.212  /  Your IP : 216.73.216.29
Web Server : LiteSpeed
System : Linux l4cp.vnetindia.com 4.18.0-553.40.1.lve.el8.x86_64 #1 SMP Wed Feb 12 18:54:57 UTC 2025 x86_64
User : rakcha ( 1356)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home5/rakcha/www/control/assets/plugins/bootstrap-treeview/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /home5/rakcha/www/control/assets/plugins/bootstrap-treeview/bootstrap-treeview.js
/* =========================================================

 * bootstrap-treeview.js v1.2.0

 * =========================================================

 * Copyright 2013 Jonathan Miles

 * Project URL : http://www.jondmiles.com/bootstrap-treeview

 *

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 * http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 * ========================================================= */



;(function ($, window, document, undefined) {



	/*global jQuery, console*/



	'use strict';



	var pluginName = 'treeview';



	var _default = {};



	_default.settings = {



		injectStyle: true,



		levels: 2,



		expandIcon: 'fa fa-plus',

		collapseIcon: 'fa fa-minus',

		emptyIcon: 'glyphicon',

		nodeIcon: '',

		selectedIcon: '',

		checkedIcon: 'fa fa-check',

		uncheckedIcon: 'fa fa-unchecked',



		color: undefined, // '#000000',

		backColor: undefined, // '#FFFFFF',

		borderColor: undefined, // '#dddddd',

		onhoverColor: '#F5F5F5',

		selectedColor: '#FFFFFF',

		selectedBackColor: '#428bca',

		searchResultColor: '#D9534F',

		searchResultBackColor: undefined, //'#FFFFFF',



		enableLinks: false,

		highlightSelected: true,

		highlightSearchResults: true,

		showBorder: true,

		showIcon: true,

		showCheckbox: false,

		showTags: false,

		multiSelect: false,



		// Event handlers

		onNodeChecked: undefined,

		onNodeCollapsed: undefined,

		onNodeDisabled: undefined,

		onNodeEnabled: undefined,

		onNodeExpanded: undefined,

		onNodeSelected: undefined,

		onNodeUnchecked: undefined,

		onNodeUnselected: undefined,

		onSearchComplete: undefined,

		onSearchCleared: undefined

	};



	_default.options = {

		silent: false,

		ignoreChildren: false

	};



	_default.searchOptions = {

		ignoreCase: true,

		exactMatch: false,

		revealResults: true

	};



	var Tree = function (element, options) {



		this.$element = $(element);

		this.elementId = element.id;

		this.styleId = this.elementId + '-style';



		this.init(options);



		return {



			// Options (public access)

			options: this.options,



			// Initialize / destroy methods

			init: $.proxy(this.init, this),

			remove: $.proxy(this.remove, this),



			// Get methods

			getNode: $.proxy(this.getNode, this),

			getParent: $.proxy(this.getParent, this),

			getSiblings: $.proxy(this.getSiblings, this),

			getSelected: $.proxy(this.getSelected, this),

			getUnselected: $.proxy(this.getUnselected, this),

			getExpanded: $.proxy(this.getExpanded, this),

			getCollapsed: $.proxy(this.getCollapsed, this),

			getChecked: $.proxy(this.getChecked, this),

			getUnchecked: $.proxy(this.getUnchecked, this),

			getDisabled: $.proxy(this.getDisabled, this),

			getEnabled: $.proxy(this.getEnabled, this),



			// Select methods

			selectNode: $.proxy(this.selectNode, this),

			unselectNode: $.proxy(this.unselectNode, this),

			toggleNodeSelected: $.proxy(this.toggleNodeSelected, this),



			// Expand / collapse methods

			collapseAll: $.proxy(this.collapseAll, this),

			collapseNode: $.proxy(this.collapseNode, this),

			expandAll: $.proxy(this.expandAll, this),

			expandNode: $.proxy(this.expandNode, this),

			toggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this),

			revealNode: $.proxy(this.revealNode, this),



			// Expand / collapse methods

			checkAll: $.proxy(this.checkAll, this),

			checkNode: $.proxy(this.checkNode, this),

			uncheckAll: $.proxy(this.uncheckAll, this),

			uncheckNode: $.proxy(this.uncheckNode, this),

			toggleNodeChecked: $.proxy(this.toggleNodeChecked, this),



			// Disable / enable methods

			disableAll: $.proxy(this.disableAll, this),

			disableNode: $.proxy(this.disableNode, this),

			enableAll: $.proxy(this.enableAll, this),

			enableNode: $.proxy(this.enableNode, this),

			toggleNodeDisabled: $.proxy(this.toggleNodeDisabled, this),



			// Search methods

			search: $.proxy(this.search, this),

			clearSearch: $.proxy(this.clearSearch, this)

		};

	};



	Tree.prototype.init = function (options) {



		this.tree = [];

		this.nodes = [];



		if (options.data) {

			if (typeof options.data === 'string') {

				options.data = $.parseJSON(options.data);

			}

			this.tree = $.extend(true, [], options.data);

			delete options.data;

		}

		this.options = $.extend({}, _default.settings, options);



		this.destroy();

		this.subscribeEvents();

		this.setInitialStates({ nodes: this.tree }, 0);

		this.render();

	};



	Tree.prototype.remove = function () {

		this.destroy();

		$.removeData(this, pluginName);

		$('#' + this.styleId).remove();

	};



	Tree.prototype.destroy = function () {



		if (!this.initialized) return;



		this.$wrapper.remove();

		this.$wrapper = null;



		// Switch off events

		this.unsubscribeEvents();



		// Reset this.initialized flag

		this.initialized = false;

	};



	Tree.prototype.unsubscribeEvents = function () {



		this.$element.off('click');

		this.$element.off('nodeChecked');

		this.$element.off('nodeCollapsed');

		this.$element.off('nodeDisabled');

		this.$element.off('nodeEnabled');

		this.$element.off('nodeExpanded');

		this.$element.off('nodeSelected');

		this.$element.off('nodeUnchecked');

		this.$element.off('nodeUnselected');

		this.$element.off('searchComplete');

		this.$element.off('searchCleared');

	};



	Tree.prototype.subscribeEvents = function () {



		this.unsubscribeEvents();



		this.$element.on('click', $.proxy(this.clickHandler, this));



		if (typeof (this.options.onNodeChecked) === 'function') {

			this.$element.on('nodeChecked', this.options.onNodeChecked);

		}



		if (typeof (this.options.onNodeCollapsed) === 'function') {

			this.$element.on('nodeCollapsed', this.options.onNodeCollapsed);

		}



		if (typeof (this.options.onNodeDisabled) === 'function') {

			this.$element.on('nodeDisabled', this.options.onNodeDisabled);

		}



		if (typeof (this.options.onNodeEnabled) === 'function') {

			this.$element.on('nodeEnabled', this.options.onNodeEnabled);

		}



		if (typeof (this.options.onNodeExpanded) === 'function') {

			this.$element.on('nodeExpanded', this.options.onNodeExpanded);

		}



		if (typeof (this.options.onNodeSelected) === 'function') {

			this.$element.on('nodeSelected', this.options.onNodeSelected);

		}



		if (typeof (this.options.onNodeUnchecked) === 'function') {

			this.$element.on('nodeUnchecked', this.options.onNodeUnchecked);

		}



		if (typeof (this.options.onNodeUnselected) === 'function') {

			this.$element.on('nodeUnselected', this.options.onNodeUnselected);

		}



		if (typeof (this.options.onSearchComplete) === 'function') {

			this.$element.on('searchComplete', this.options.onSearchComplete);

		}



		if (typeof (this.options.onSearchCleared) === 'function') {

			this.$element.on('searchCleared', this.options.onSearchCleared);

		}

	};



	/*

		Recurse the tree structure and ensure all nodes have

		valid initial states.  User defined states will be preserved.

		For performance we also take this opportunity to

		index nodes in a flattened structure

	*/

	Tree.prototype.setInitialStates = function (node, level) {



		if (!node.nodes) return;

		level += 1;



		var parent = node;

		var _this = this;

		$.each(node.nodes, function checkStates(index, node) {



			// nodeId : unique, incremental identifier

			node.nodeId = _this.nodes.length;



			// parentId : transversing up the tree

			node.parentId = parent.nodeId;



			// if not provided set selectable default value

			if (!node.hasOwnProperty('selectable')) {

				node.selectable = true;

			}



			// where provided we should preserve states

			node.state = node.state || {};



			// set checked state; unless set always false

			if (!node.state.hasOwnProperty('checked')) {

				node.state.checked = false;

			}



			// set enabled state; unless set always false

			if (!node.state.hasOwnProperty('disabled')) {

				node.state.disabled = false;

			}



			// set expanded state; if not provided based on levels

			if (!node.state.hasOwnProperty('expanded')) {

				if (!node.state.disabled &&

						(level < _this.options.levels) &&

						(node.nodes && node.nodes.length > 0)) {

					node.state.expanded = true;

				}

				else {

					node.state.expanded = false;

				}

			}



			// set selected state; unless set always false

			if (!node.state.hasOwnProperty('selected')) {

				node.state.selected = false;

			}



			// index nodes in a flattened structure for use later

			_this.nodes.push(node);



			// recurse child nodes and transverse the tree

			if (node.nodes) {

				_this.setInitialStates(node, level);

			}

		});

	};



	Tree.prototype.clickHandler = function (event) {



		if (!this.options.enableLinks) event.preventDefault();



		var target = $(event.target);

		var node = this.findNode(target);

		if (!node || node.state.disabled) return;

		

		var classList = target.attr('class') ? target.attr('class').split(' ') : [];

		if ((classList.indexOf('expand-icon') !== -1)) {



			this.toggleExpandedState(node, _default.options);

			this.render();

		}

		else if ((classList.indexOf('check-icon') !== -1)) {

			

			this.toggleCheckedState(node, _default.options);

			this.render();

		}

		else {

			

			if (node.selectable) {

				this.toggleSelectedState(node, _default.options);

			} else {

				this.toggleExpandedState(node, _default.options);

			}



			this.render();

		}

	};



	// Looks up the DOM for the closest parent list item to retrieve the

	// data attribute nodeid, which is used to lookup the node in the flattened structure.

	Tree.prototype.findNode = function (target) {



		var nodeId = target.closest('li.list-group-item').attr('data-nodeid');

		var node = this.nodes[nodeId];



		if (!node) {

			console.log('Error: node does not exist');

		}

		return node;

	};



	Tree.prototype.toggleExpandedState = function (node, options) {

		if (!node) return;

		this.setExpandedState(node, !node.state.expanded, options);

	};



	Tree.prototype.setExpandedState = function (node, state, options) {



		if (state === node.state.expanded) return;



		if (state && node.nodes) {



			// Expand a node

			node.state.expanded = true;

			if (!options.silent) {

				this.$element.trigger('nodeExpanded', $.extend(true, {}, node));

			}

		}

		else if (!state) {



			// Collapse a node

			node.state.expanded = false;

			if (!options.silent) {

				this.$element.trigger('nodeCollapsed', $.extend(true, {}, node));

			}



			// Collapse child nodes

			if (node.nodes && !options.ignoreChildren) {

				$.each(node.nodes, $.proxy(function (index, node) {

					this.setExpandedState(node, false, options);

				}, this));

			}

		}

	};



	Tree.prototype.toggleSelectedState = function (node, options) {

		if (!node) return;

		this.setSelectedState(node, !node.state.selected, options);

	};



	Tree.prototype.setSelectedState = function (node, state, options) {



		if (state === node.state.selected) return;



		if (state) {



			// If multiSelect false, unselect previously selected

			if (!this.options.multiSelect) {

				$.each(this.findNodes('true', 'g', 'state.selected'), $.proxy(function (index, node) {

					this.setSelectedState(node, false, options);

				}, this));

			}



			// Continue selecting node

			node.state.selected = true;

			if (!options.silent) {

				this.$element.trigger('nodeSelected', $.extend(true, {}, node));

			}

		}

		else {



			// Unselect node

			node.state.selected = false;

			if (!options.silent) {

				this.$element.trigger('nodeUnselected', $.extend(true, {}, node));

			}

		}

	};



	Tree.prototype.toggleCheckedState = function (node, options) {

		if (!node) return;

		this.setCheckedState(node, !node.state.checked, options);

	};



	Tree.prototype.setCheckedState = function (node, state, options) {



		if (state === node.state.checked) return;



		if (state) {



			// Check node

			node.state.checked = true;



			if (!options.silent) {

				this.$element.trigger('nodeChecked', $.extend(true, {}, node));

			}

		}

		else {



			// Uncheck node

			node.state.checked = false;

			if (!options.silent) {

				this.$element.trigger('nodeUnchecked', $.extend(true, {}, node));

			}

		}

	};



	Tree.prototype.setDisabledState = function (node, state, options) {



		if (state === node.state.disabled) return;



		if (state) {



			// Disable node

			node.state.disabled = true;



			// Disable all other states

			this.setExpandedState(node, false, options);

			this.setSelectedState(node, false, options);

			this.setCheckedState(node, false, options);



			if (!options.silent) {

				this.$element.trigger('nodeDisabled', $.extend(true, {}, node));

			}

		}

		else {



			// Enabled node

			node.state.disabled = false;

			if (!options.silent) {

				this.$element.trigger('nodeEnabled', $.extend(true, {}, node));

			}

		}

	};



	Tree.prototype.render = function () {



		if (!this.initialized) {



			// Setup first time only components

			this.$element.addClass(pluginName);

			this.$wrapper = $(this.template.list);



			this.injectStyle();



			this.initialized = true;

		}



		this.$element.empty().append(this.$wrapper.empty());



		// Build tree

		this.buildTree(this.tree, 0);

	};



	// Starting from the root node, and recursing down the

	// structure we build the tree one node at a time

	Tree.prototype.buildTree = function (nodes, level) {



		if (!nodes) return;

		level += 1;



		var _this = this;

		$.each(nodes, function addNodes(id, node) {



			var treeItem = $(_this.template.item)

				.addClass('node-' + _this.elementId)

				.addClass(node.state.checked ? 'node-checked' : '')

				.addClass(node.state.disabled ? 'node-disabled': '')

				.addClass(node.state.selected ? 'node-selected' : '')

				.addClass(node.searchResult ? 'search-result' : '') 

				.attr('data-nodeid', node.nodeId)

				.attr('style', _this.buildStyleOverride(node));



			// Add indent/spacer to mimic tree structure

			for (var i = 0; i < (level - 1); i++) {

				treeItem.append(_this.template.indent);

			}



			// Add expand, collapse or empty spacer icons

			var classList = [];

			if (node.nodes) {

				classList.push('expand-icon');

				if (node.state.expanded) {

					classList.push(_this.options.collapseIcon);

				}

				else {

					classList.push(_this.options.expandIcon);

				}

			}

			else {

				classList.push(_this.options.emptyIcon);

			}



			treeItem

				.append($(_this.template.icon)

					.addClass(classList.join(' '))

				);





			// Add node icon

			if (_this.options.showIcon) {

				

				var classList = ['node-icon'];



				classList.push(node.icon || _this.options.nodeIcon);

				if (node.state.selected) {

					classList.pop();

					classList.push(node.selectedIcon || _this.options.selectedIcon || 

									node.icon || _this.options.nodeIcon);

				}



				treeItem

					.append($(_this.template.icon)

						.addClass(classList.join(' '))

					);

			}



			// Add check / unchecked icon

			if (_this.options.showCheckbox) {



				var classList = ['check-icon'];

				if (node.state.checked) {

					classList.push(_this.options.checkedIcon); 

				}

				else {

					classList.push(_this.options.uncheckedIcon);

				}



				treeItem

					.append($(_this.template.icon)

						.addClass(classList.join(' '))

					);

			}



			// Add text

			if (_this.options.enableLinks) {

				// Add hyperlink

				treeItem

					.append($(_this.template.link)

						.attr('href', node.href)

						.append(node.text)

					);

			}

			else {

				// otherwise just text

				treeItem

					.append(node.text);

			}



			// Add tags as badges

			if (_this.options.showTags && node.tags) {

				$.each(node.tags, function addTag(id, tag) {

					treeItem

						.append($(_this.template.badge)

							.append(tag)

						);

				});

			}



			// Add item to the tree

			_this.$wrapper.append(treeItem);



			// Recursively add child ndoes

			if (node.nodes && node.state.expanded && !node.state.disabled) {

				return _this.buildTree(node.nodes, level);

			}

		});

	};



	// Define any node level style override for

	// 1. selectedNode

	// 2. node|data assigned color overrides

	Tree.prototype.buildStyleOverride = function (node) {



		if (node.state.disabled) return '';



		var color = node.color;

		var backColor = node.backColor;



		if (this.options.highlightSelected && node.state.selected) {

			if (this.options.selectedColor) {

				color = this.options.selectedColor;

			}

			if (this.options.selectedBackColor) {

				backColor = this.options.selectedBackColor;

			}

		}



		if (this.options.highlightSearchResults && node.searchResult && !node.state.disabled) {

			if (this.options.searchResultColor) {

				color = this.options.searchResultColor;

			}

			if (this.options.searchResultBackColor) {

				backColor = this.options.searchResultBackColor;

			}

		}



		return 'color:' + color +

			';background-color:' + backColor + ';';

	};



	// Add inline style into head

	Tree.prototype.injectStyle = function () {



		if (this.options.injectStyle && !document.getElementById(this.styleId)) {

			$('<style type="text/css" id="' + this.styleId + '"> ' + this.buildStyle() + ' </style>').appendTo('head');

		}

	};



	// Construct trees style based on user options

	Tree.prototype.buildStyle = function () {



		var style = '.node-' + this.elementId + '{';



		if (this.options.color) {

			style += 'color:' + this.options.color + ';';

		}



		if (this.options.backColor) {

			style += 'background-color:' + this.options.backColor + ';';

		}



		if (!this.options.showBorder) {

			style += 'border:none;';

		}

		else if (this.options.borderColor) {

			style += 'border:1px solid ' + this.options.borderColor + ';';

		}

		style += '}';



		if (this.options.onhoverColor) {

			style += '.node-' + this.elementId + ':not(.node-disabled):hover{' +

				'background-color:' + this.options.onhoverColor + ';' +

			'}';

		}



		return this.css + style;

	};



	Tree.prototype.template = {

		list: '<ul class="list-group"></ul>',

		item: '<li class="list-group-item"></li>',

		indent: '<span class="indent"></span>',

		icon: '<span class="icon"></span>',

		link: '<a href="#" style="color:inherit;"></a>',

		badge: '<span class="badge"></span>'

	};



	Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}'





	/**

		Returns a single node object that matches the given node id.

		@param {Number} nodeId - A node's unique identifier

		@return {Object} node - Matching node

	*/

	Tree.prototype.getNode = function (nodeId) {

		return this.nodes[nodeId];

	};



	/**

		Returns the parent node of a given node, if valid otherwise returns undefined.

		@param {Object|Number} identifier - A valid node or node id

		@returns {Object} node - The parent node

	*/

	Tree.prototype.getParent = function (identifier) {

		var node = this.identifyNode(identifier);

		return this.nodes[node.parentId];

	};



	/**

		Returns an array of sibling nodes for a given node, if valid otherwise returns undefined.

		@param {Object|Number} identifier - A valid node or node id

		@returns {Array} nodes - Sibling nodes

	*/

	Tree.prototype.getSiblings = function (identifier) {

		var node = this.identifyNode(identifier);

		var parent = this.getParent(node);

		var nodes = parent ? parent.nodes : this.tree;

		return nodes.filter(function (obj) {

				return obj.nodeId !== node.nodeId;

			});

	};



	/**

		Returns an array of selected nodes.

		@returns {Array} nodes - Selected nodes

	*/

	Tree.prototype.getSelected = function () {

		return this.findNodes('true', 'g', 'state.selected');

	};



	/**

		Returns an array of unselected nodes.

		@returns {Array} nodes - Unselected nodes

	*/

	Tree.prototype.getUnselected = function () {

		return this.findNodes('false', 'g', 'state.selected');

	};



	/**

		Returns an array of expanded nodes.

		@returns {Array} nodes - Expanded nodes

	*/

	Tree.prototype.getExpanded = function () {

		return this.findNodes('true', 'g', 'state.expanded');

	};



	/**

		Returns an array of collapsed nodes.

		@returns {Array} nodes - Collapsed nodes

	*/

	Tree.prototype.getCollapsed = function () {

		return this.findNodes('false', 'g', 'state.expanded');

	};



	/**

		Returns an array of checked nodes.

		@returns {Array} nodes - Checked nodes

	*/

	Tree.prototype.getChecked = function () {

		return this.findNodes('true', 'g', 'state.checked');

	};



	/**

		Returns an array of unchecked nodes.

		@returns {Array} nodes - Unchecked nodes

	*/

	Tree.prototype.getUnchecked = function () {

		return this.findNodes('false', 'g', 'state.checked');

	};



	/**

		Returns an array of disabled nodes.

		@returns {Array} nodes - Disabled nodes

	*/

	Tree.prototype.getDisabled = function () {

		return this.findNodes('true', 'g', 'state.disabled');

	};



	/**

		Returns an array of enabled nodes.

		@returns {Array} nodes - Enabled nodes

	*/

	Tree.prototype.getEnabled = function () {

		return this.findNodes('false', 'g', 'state.disabled');

	};





	/**

		Set a node state to selected

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.selectNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setSelectedState(node, true, options);

		}, this));



		this.render();

	};



	/**

		Set a node state to unselected

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.unselectNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setSelectedState(node, false, options);

		}, this));



		this.render();

	};



	/**

		Toggles a node selected state; selecting if unselected, unselecting if selected.

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.toggleNodeSelected = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.toggleSelectedState(node, options);

		}, this));



		this.render();

	};





	/**

		Collapse all tree nodes

		@param {optional Object} options

	*/

	Tree.prototype.collapseAll = function (options) {

		var identifiers = this.findNodes('true', 'g', 'state.expanded');

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setExpandedState(node, false, options);

		}, this));



		this.render();

	};



	/**

		Collapse a given tree node

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.collapseNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setExpandedState(node, false, options);

		}, this));



		this.render();

	};



	/**

		Expand all tree nodes

		@param {optional Object} options

	*/

	Tree.prototype.expandAll = function (options) {

		options = $.extend({}, _default.options, options);



		if (options && options.levels) {

			this.expandLevels(this.tree, options.levels, options);

		}

		else {

			var identifiers = this.findNodes('false', 'g', 'state.expanded');

			this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

				this.setExpandedState(node, true, options);

			}, this));

		}



		this.render();

	};



	/**

		Expand a given tree node

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.expandNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setExpandedState(node, true, options);

			if (node.nodes && (options && options.levels)) {

				this.expandLevels(node.nodes, options.levels-1, options);

			}

		}, this));



		this.render();

	};



	Tree.prototype.expandLevels = function (nodes, level, options) {

		options = $.extend({}, _default.options, options);



		$.each(nodes, $.proxy(function (index, node) {

			this.setExpandedState(node, (level > 0) ? true : false, options);

			if (node.nodes) {

				this.expandLevels(node.nodes, level-1, options);

			}

		}, this));

	};



	/**

		Reveals a given tree node, expanding the tree from node to root.

		@param {Object|Number|Array} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.revealNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			var parentNode = this.getParent(node);

			while (parentNode) {

				this.setExpandedState(parentNode, true, options);

				parentNode = this.getParent(parentNode);

			};

		}, this));



		this.render();

	};



	/**

		Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed.

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.toggleNodeExpanded = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.toggleExpandedState(node, options);

		}, this));

		

		this.render();

	};





	/**

		Check all tree nodes

		@param {optional Object} options

	*/

	Tree.prototype.checkAll = function (options) {

		var identifiers = this.findNodes('false', 'g', 'state.checked');

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setCheckedState(node, true, options);

		}, this));



		this.render();

	};



	/**

		Check a given tree node

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.checkNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setCheckedState(node, true, options);

		}, this));



		this.render();

	};



	/**

		Uncheck all tree nodes

		@param {optional Object} options

	*/

	Tree.prototype.uncheckAll = function (options) {

		var identifiers = this.findNodes('true', 'g', 'state.checked');

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setCheckedState(node, false, options);

		}, this));



		this.render();

	};



	/**

		Uncheck a given tree node

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.uncheckNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setCheckedState(node, false, options);

		}, this));



		this.render();

	};



	/**

		Toggles a nodes checked state; checking if unchecked, unchecking if checked.

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.toggleNodeChecked = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.toggleCheckedState(node, options);

		}, this));



		this.render();

	};





	/**

		Disable all tree nodes

		@param {optional Object} options

	*/

	Tree.prototype.disableAll = function (options) {

		var identifiers = this.findNodes('false', 'g', 'state.disabled');

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setDisabledState(node, true, options);

		}, this));



		this.render();

	};



	/**

		Disable a given tree node

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.disableNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setDisabledState(node, true, options);

		}, this));



		this.render();

	};



	/**

		Enable all tree nodes

		@param {optional Object} options

	*/

	Tree.prototype.enableAll = function (options) {

		var identifiers = this.findNodes('true', 'g', 'state.disabled');

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setDisabledState(node, false, options);

		}, this));



		this.render();

	};



	/**

		Enable a given tree node

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.enableNode = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setDisabledState(node, false, options);

		}, this));



		this.render();

	};



	/**

		Toggles a nodes disabled state; disabling is enabled, enabling if disabled.

		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers

		@param {optional Object} options

	*/

	Tree.prototype.toggleNodeDisabled = function (identifiers, options) {

		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {

			this.setDisabledState(node, !node.state.disabled, options);

		}, this));



		this.render();

	};





	/**

		Common code for processing multiple identifiers

	*/

	Tree.prototype.forEachIdentifier = function (identifiers, options, callback) {



		options = $.extend({}, _default.options, options);



		if (!(identifiers instanceof Array)) {

			identifiers = [identifiers];

		}



		$.each(identifiers, $.proxy(function (index, identifier) {

			callback(this.identifyNode(identifier), options);

		}, this));	

	};



	/*

		Identifies a node from either a node id or object

	*/

	Tree.prototype.identifyNode = function (identifier) {

		return ((typeof identifier) === 'number') ?

						this.nodes[identifier] :

						identifier;

	};



	/**

		Searches the tree for nodes (text) that match given criteria

		@param {String} pattern - A given string to match against

		@param {optional Object} options - Search criteria options

		@return {Array} nodes - Matching nodes

	*/

	Tree.prototype.search = function (pattern, options) {

		options = $.extend({}, _default.searchOptions, options);



		this.clearSearch({ render: false });



		var results = [];

		if (pattern && pattern.length > 0) {



			if (options.exactMatch) {

				pattern = '^' + pattern + '$';

			}



			var modifier = 'g';

			if (options.ignoreCase) {

				modifier += 'i';

			}



			results = this.findNodes(pattern, modifier);



			// Add searchResult property to all matching nodes

			// This will be used to apply custom styles

			// and when identifying result to be cleared

			$.each(results, function (index, node) {

				node.searchResult = true;

			})

		}



		// If revealResults, then render is triggered from revealNode

		// otherwise we just call render.

		if (options.revealResults) {

			this.revealNode(results);

		}

		else {

			this.render();

		}



		this.$element.trigger('searchComplete', $.extend(true, {}, results));



		return results;

	};



	/**

		Clears previous search results

	*/

	Tree.prototype.clearSearch = function (options) {



		options = $.extend({}, { render: true }, options);



		var results = $.each(this.findNodes('true', 'g', 'searchResult'), function (index, node) {

			node.searchResult = false;

		});



		if (options.render) {

			this.render();	

		}

		

		this.$element.trigger('searchCleared', $.extend(true, {}, results));

	};



	/**

		Find nodes that match a given criteria

		@param {String} pattern - A given string to match against

		@param {optional String} modifier - Valid RegEx modifiers

		@param {optional String} attribute - Attribute to compare pattern against

		@return {Array} nodes - Nodes that match your criteria

	*/

	Tree.prototype.findNodes = function (pattern, modifier, attribute) {



		modifier = modifier || 'g';

		attribute = attribute || 'text';



		var _this = this;

		return $.grep(this.nodes, function (node) {

			var val = _this.getNodeValue(node, attribute);

			if (typeof val === 'string') {

				return val.match(new RegExp(pattern, modifier));

			}

		});

	};



	/**

		Recursive find for retrieving nested attributes values

		All values are return as strings, unless invalid

		@param {Object} obj - Typically a node, could be any object

		@param {String} attr - Identifies an object property using dot notation

		@return {String} value - Matching attributes string representation

	*/

	Tree.prototype.getNodeValue = function (obj, attr) {

		var index = attr.indexOf('.');

		if (index > 0) {

			var _obj = obj[attr.substring(0, index)];

			var _attr = attr.substring(index + 1, attr.length);

			return this.getNodeValue(_obj, _attr);

		}

		else {

			if (obj.hasOwnProperty(attr)) {

				return obj[attr].toString();

			}

			else {

				return undefined;

			}

		}

	};



	var logError = function (message) {

		if (window.console) {

			window.console.error(message);

		}

	};



	// Prevent against multiple instantiations,

	// handle updates and method calls

	$.fn[pluginName] = function (options, args) {



		var result;



		this.each(function () {

			var _this = $.data(this, pluginName);

			if (typeof options === 'string') {

				if (!_this) {

					logError('Not initialized, can not call method : ' + options);

				}

				else if (!$.isFunction(_this[options]) || options.charAt(0) === '_') {

					logError('No such method : ' + options);

				}

				else {

					if (!(args instanceof Array)) {

						args = [ args ];

					}

					result = _this[options].apply(_this, args);

				}

			}

			else if (typeof options === 'boolean') {

				result = _this;

			}

			else {

				$.data(this, pluginName, new Tree(this, $.extend(true, {}, options)));

			}

		});



		return result || this;

	};



})(jQuery, window, document);


Anon7 - 2022
SCDN GOK