2 * jQuery treegrid Plugin 0.2.0
\r
3 * https://github.com/maxazan/jquery-treegrid
\r
5 * Copyright 2013, Pomazan Max
\r
6 * Licensed under the MIT licenses.
\r
14 * @param {Object} options
\r
15 * @returns {Object[]}
\r
17 initTree: function(options) {
\r
18 var settings = $.extend({}, this.treegrid.defaults, options);
\r
19 return this.each(function() {
\r
20 var $this = $(this);
\r
21 $this.treegrid('setTreeContainer', $(this));
\r
22 $this.treegrid('setSettings', settings);
\r
23 settings.getRootNodes.apply(this, [$(this)]).treegrid('initNode', settings);
\r
24 $this.treegrid('getRootNodes').treegrid('render');
\r
30 * @param {Object} settings
\r
31 * @returns {Object[]}
\r
33 initNode: function(settings) {
\r
34 return this.each(function() {
\r
35 var $this = $(this);
\r
36 $this.treegrid('setTreeContainer', settings.getTreeGridContainer.apply(this));
\r
37 $this.treegrid('getChildNodes').treegrid('initNode', settings);
\r
38 $this.treegrid('initExpander').treegrid('initIndent').treegrid('initEvents').treegrid('initState').treegrid('initChangeEvent').treegrid("initSettingsEvents");
\r
41 initChangeEvent: function() {
\r
42 var $this = $(this);
\r
43 //Save state on change
\r
44 $this.on("change", function() {
\r
45 var $this = $(this);
\r
46 $this.treegrid('render');
\r
47 if ($this.treegrid('getSetting', 'saveState')) {
\r
48 $this.treegrid('saveState');
\r
54 * Initialize node events
\r
58 initEvents: function() {
\r
59 var $this = $(this);
\r
60 //Default behavior on collapse
\r
61 $this.on("collapse", function() {
\r
62 var $this = $(this);
\r
63 $this.removeClass('treegrid-expanded');
\r
64 $this.addClass('treegrid-collapsed');
\r
66 //Default behavior on expand
\r
67 $this.on("expand", function() {
\r
68 var $this = $(this);
\r
69 $this.removeClass('treegrid-collapsed');
\r
70 $this.addClass('treegrid-expanded');
\r
76 * Initialize events from settings
\r
80 initSettingsEvents: function() {
\r
81 var $this = $(this);
\r
82 //Save state on change
\r
83 $this.on("change", function() {
\r
84 var $this = $(this);
\r
85 if (typeof($this.treegrid('getSetting', 'onChange')) === "function") {
\r
86 $this.treegrid('getSetting', 'onChange').apply($this);
\r
89 //Default behavior on collapse
\r
90 $this.on("collapse", function() {
\r
91 var $this = $(this);
\r
92 if (typeof($this.treegrid('getSetting', 'onCollapse')) === "function") {
\r
93 $this.treegrid('getSetting', 'onCollapse').apply($this);
\r
96 //Default behavior on expand
\r
97 $this.on("expand", function() {
\r
98 var $this = $(this);
\r
99 if (typeof($this.treegrid('getSetting', 'onExpand')) === "function") {
\r
100 $this.treegrid('getSetting', 'onExpand').apply($this);
\r
108 * Initialize expander for node
\r
112 initExpander: function() {
\r
113 var $this = $(this);
\r
114 var cell = $this.find('td').get($this.treegrid('getSetting', 'treeColumn'));
\r
115 var tpl = $this.treegrid('getSetting', 'expanderTemplate');
\r
116 var expander = $this.treegrid('getSetting', 'getExpander').apply(this);
\r
120 $(tpl).prependTo(cell).click(function() {
\r
121 $($(this).closest('tr')).treegrid('toggle');
\r
126 * Initialize indent for node
\r
130 initIndent: function() {
\r
131 var $this = $(this);
\r
132 $this.find('.treegrid-indent').remove();
\r
133 var tpl = $this.treegrid('getSetting', 'indentTemplate');
\r
134 var expander = $this.find('.treegrid-expander');
\r
135 var depth = $this.treegrid('getDepth');
\r
136 for (var i = 0; i < depth; i++) {
\r
137 $(tpl).insertBefore(expander);
\r
142 * Initialise state of node
\r
146 initState: function() {
\r
147 var $this = $(this);
\r
148 if ($this.treegrid('getSetting', 'saveState') && !$this.treegrid('isFirstInit')) {
\r
149 $this.treegrid('restoreState');
\r
151 if ($this.treegrid('getSetting', 'initialState') === "expanded") {
\r
152 $this.treegrid('expand');
\r
154 $this.treegrid('collapse');
\r
160 * Return true if this tree was never been initialised
\r
162 * @returns {Boolean}
\r
164 isFirstInit: function() {
\r
165 var tree = $(this).treegrid('getTreeContainer');
\r
166 if (tree.data('first_init') === undefined) {
\r
167 tree.data('first_init', $.cookie(tree.treegrid('getSetting', 'saveStateName')) === undefined);
\r
169 return tree.data('first_init');
\r
172 * Save state of current node
\r
176 saveState: function() {
\r
177 var $this = $(this);
\r
178 if ($this.treegrid('getSetting', 'saveStateMethod') === 'cookie') {
\r
180 var stateArrayString = $.cookie($this.treegrid('getSetting', 'saveStateName')) || '';
\r
181 var stateArray = (stateArrayString === '' ? [] : stateArrayString.split(','));
\r
182 var nodeId = $this.treegrid('getNodeId');
\r
184 if ($this.treegrid('isExpanded')) {
\r
185 if ($.inArray(nodeId, stateArray) === -1) {
\r
186 stateArray.push(nodeId);
\r
188 } else if ($this.treegrid('isCollapsed')) {
\r
189 if ($.inArray(nodeId, stateArray) !== -1) {
\r
190 stateArray.splice($.inArray(nodeId, stateArray), 1);
\r
193 $.cookie($this.treegrid('getSetting', 'saveStateName'), stateArray.join(','));
\r
198 * Restore state of current node.
\r
202 restoreState: function() {
\r
203 var $this = $(this);
\r
204 if ($this.treegrid('getSetting', 'saveStateMethod') === 'cookie') {
\r
205 var stateArray = $.cookie($this.treegrid('getSetting', 'saveStateName')).split(',');
\r
206 if ($.inArray($this.treegrid('getNodeId'), stateArray) !== -1) {
\r
207 $this.treegrid('expand');
\r
209 $this.treegrid('collapse');
\r
216 * Method return setting by name
\r
218 * @param {type} name
\r
219 * @returns {unresolved}
\r
221 getSetting: function(name) {
\r
222 if (!$(this).treegrid('getTreeContainer')) {
\r
225 return $(this).treegrid('getTreeContainer').data('settings')[name];
\r
230 * @param {Object} settings
\r
232 setSettings: function(settings) {
\r
233 $(this).treegrid('getTreeContainer').data('settings', settings);
\r
236 * Return tree container
\r
238 * @returns {HtmlElement}
\r
240 getTreeContainer: function() {
\r
241 return $(this).data('treegrid');
\r
244 * Set tree container
\r
246 * @param {HtmlE;ement} container
\r
248 setTreeContainer: function(container) {
\r
249 return $(this).data('treegrid', container);
\r
252 * Method return all root nodes of tree.
\r
254 * Start init all child nodes from it.
\r
258 getRootNodes: function() {
\r
259 return $(this).treegrid('getSetting', 'getRootNodes').apply(this, [$(this).treegrid('getTreeContainer')]);
\r
262 * Method return all nodes of tree.
\r
266 getAllNodes: function() {
\r
267 return $(this).treegrid('getSetting', 'getAllNodes').apply(this, [$(this).treegrid('getTreeContainer')]);
\r
270 * Mthod return true if element is Node
\r
272 * @returns {String}
\r
274 isNode: function() {
\r
275 return $(this).treegrid('getNodeId') !== null;
\r
278 * Mthod return id of node
\r
280 * @returns {String}
\r
282 getNodeId: function() {
\r
283 if ($(this).treegrid('getSetting', 'getNodeId') === null) {
\r
286 return $(this).treegrid('getSetting', 'getNodeId').apply(this);
\r
290 * Method return parent id of node or null if root node
\r
292 * @returns {String}
\r
294 getParentNodeId: function() {
\r
295 return $(this).treegrid('getSetting', 'getParentNodeId').apply(this);
\r
298 * Method return parent node or null if root node
\r
300 * @returns {Object[]}
\r
302 getParentNode: function() {
\r
303 if ($(this).treegrid('getParentNodeId') === null) {
\r
306 return $(this).treegrid('getSetting', 'getNodeById').apply(this, [$(this).treegrid('getParentNodeId'), $(this).treegrid('getTreeContainer')]);
\r
310 * Method return array of child nodes or null if node is leaf
\r
312 * @returns {Object[]}
\r
314 getChildNodes: function() {
\r
315 return $(this).treegrid('getSetting', 'getChildNodes').apply(this, [$(this).treegrid('getNodeId'), $(this).treegrid('getTreeContainer')]);
\r
318 * Method return depth of tree.
\r
320 * This method is needs for calculate indent
\r
322 * @returns {Number}
\r
324 getDepth: function() {
\r
325 if ($(this).treegrid('getParentNode') === null) {
\r
328 return $(this).treegrid('getParentNode').treegrid('getDepth') + 1;
\r
331 * Method return true if node is root
\r
333 * @returns {Boolean}
\r
335 isRoot: function() {
\r
336 return $(this).treegrid('getDepth') === 0;
\r
339 * Method return true if node has no child nodes
\r
341 * @returns {Boolean}
\r
343 isLeaf: function() {
\r
344 return $(this).treegrid('getChildNodes').length === 0;
\r
347 * Method return true if node last in branch
\r
349 * @returns {Boolean}
\r
351 isLast: function() {
\r
352 if ($(this).treegrid('isNode')) {
\r
353 var parentNode = $(this).treegrid('getParentNode');
\r
354 if (parentNode === null) {
\r
355 if ($(this).treegrid('getNodeId') === $(this).treegrid('getRootNodes').last().treegrid('getNodeId')) {
\r
359 if ($(this).treegrid('getNodeId') === parentNode.treegrid('getChildNodes').last().treegrid('getNodeId')) {
\r
367 * Method return true if node first in branch
\r
369 * @returns {Boolean}
\r
371 isFirst: function() {
\r
372 if ($(this).treegrid('isNode')) {
\r
373 var parentNode = $(this).treegrid('getParentNode');
\r
374 if (parentNode === null) {
\r
375 if ($(this).treegrid('getNodeId') === $(this).treegrid('getRootNodes').first().treegrid('getNodeId')) {
\r
379 if ($(this).treegrid('getNodeId') === parentNode.treegrid('getChildNodes').first().treegrid('getNodeId')) {
\r
387 * Return true if node expanded
\r
389 * @returns {Boolean}
\r
391 isExpanded: function() {
\r
392 return $(this).hasClass('treegrid-expanded');
\r
395 * Return true if node collapsed
\r
397 * @returns {Boolean}
\r
399 isCollapsed: function() {
\r
400 return $(this).hasClass('treegrid-collapsed');
\r
403 * Return true if at least one of parent node is collapsed
\r
405 * @returns {Boolean}
\r
407 isOneOfParentsCollapsed: function() {
\r
408 var $this = $(this);
\r
409 if ($this.treegrid('isRoot')) {
\r
412 if ($this.treegrid('getParentNode').treegrid('isCollapsed')) {
\r
415 return $this.treegrid('getParentNode').treegrid('isOneOfParentsCollapsed');
\r
424 expand: function() {
\r
425 if (!this.treegrid('isLeaf') && !this.treegrid("isExpanded")) {
\r
426 this.trigger("expand");
\r
427 this.trigger("change");
\r
437 expandAll: function() {
\r
438 var $this = $(this);
\r
439 $this.treegrid('getRootNodes').treegrid('expandRecursive');
\r
443 * Expand current node and all child nodes begin from current
\r
447 expandRecursive: function() {
\r
448 return $(this).each(function() {
\r
449 var $this = $(this);
\r
450 $this.treegrid('expand');
\r
451 if (!$this.treegrid('isLeaf')) {
\r
452 $this.treegrid('getChildNodes').treegrid('expandRecursive');
\r
461 collapse: function() {
\r
462 return $(this).each(function() {
\r
463 var $this = $(this);
\r
464 if (!$this.treegrid('isLeaf') && !$this.treegrid("isCollapsed")) {
\r
465 $this.trigger("collapse");
\r
466 $this.trigger("change");
\r
471 * Collapse all nodes
\r
475 collapseAll: function() {
\r
476 var $this = $(this);
\r
477 $this.treegrid('getRootNodes').treegrid('collapseRecursive');
\r
481 * Collapse current node and all child nodes begin from current
\r
485 collapseRecursive: function() {
\r
486 return $(this).each(function() {
\r
487 var $this = $(this);
\r
488 $this.treegrid('collapse');
\r
489 if (!$this.treegrid('isLeaf')) {
\r
490 $this.treegrid('getChildNodes').treegrid('collapseRecursive');
\r
495 * Expand if collapsed, Collapse if expanded
\r
499 toggle: function() {
\r
500 var $this = $(this);
\r
501 if ($this.treegrid('isExpanded')) {
\r
502 $this.treegrid('collapse');
\r
504 $this.treegrid('expand');
\r
513 render: function() {
\r
514 return $(this).each(function() {
\r
515 var $this = $(this);
\r
516 //if parent colapsed we hidden
\r
517 if ($this.treegrid('isOneOfParentsCollapsed')) {
\r
522 if (!$this.treegrid('isLeaf')) {
\r
523 $this.treegrid('renderExpander');
\r
524 $this.treegrid('getChildNodes').treegrid('render');
\r
529 * Rendering expander depends on node state
\r
533 renderExpander: function() {
\r
534 return $(this).each(function() {
\r
535 var $this = $(this);
\r
536 var expander = $this.treegrid('getSetting', 'getExpander').apply(this);
\r
539 if (!$this.treegrid('isCollapsed')) {
\r
540 expander.removeClass($this.treegrid('getSetting', 'expanderCollapsedClass'));
\r
541 expander.addClass($this.treegrid('getSetting', 'expanderExpandedClass'));
\r
543 expander.removeClass($this.treegrid('getSetting', 'expanderExpandedClass'));
\r
544 expander.addClass($this.treegrid('getSetting', 'expanderCollapsedClass'));
\r
547 $this.treegrid('initExpander');
\r
548 $this.treegrid('renderExpander');
\r
553 $.fn.treegrid = function(method) {
\r
554 if (methods[method]) {
\r
555 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
\r
556 } else if (typeof method === 'object' || !method) {
\r
557 return methods.initTree.apply(this, arguments);
\r
559 $.error('Method with name ' + method + ' does not exists for jQuery.treegrid');
\r
563 * Plugin's default options
\r
565 $.fn.treegrid.defaults = {
\r
566 initialState: 'expanded',
\r
568 saveStateMethod: 'cookie',
\r
569 saveStateName: 'tree-grid-state',
\r
570 expanderTemplate: '<span class="treegrid-expander"></span>',
\r
571 indentTemplate: '<span class="treegrid-indent"></span>',
\r
572 expanderExpandedClass: 'treegrid-expander-expanded',
\r
573 expanderCollapsedClass: 'treegrid-expander-collapsed',
\r
575 getExpander: function() {
\r
576 return $(this).find('.treegrid-expander');
\r
578 getNodeId: function() {
\r
579 var template = /treegrid-([A-Za-z0-9_-]+)/;
\r
580 if (template.test($(this).attr('class'))) {
\r
581 return template.exec($(this).attr('class'))[1];
\r
585 getParentNodeId: function() {
\r
586 var template = /treegrid-parent-([A-Za-z0-9_-]+)/;
\r
587 if (template.test($(this).attr('class'))) {
\r
588 return template.exec($(this).attr('class'))[1];
\r
592 getNodeById: function(id, treegridContainer) {
\r
593 var templateClass = "treegrid-" + id;
\r
594 return treegridContainer.find('tr.' + templateClass);
\r
596 getChildNodes: function(id, treegridContainer) {
\r
597 var templateClass = "treegrid-parent-" + id;
\r
598 return treegridContainer.find('tr.' + templateClass);
\r
600 getTreeGridContainer: function() {
\r
601 return $(this).closest('table');
\r
603 getRootNodes: function(treegridContainer) {
\r
604 var result = $.grep(treegridContainer.find('tr'), function(element) {
\r
605 var classNames = $(element).attr('class');
\r
606 var templateClass = /treegrid-([A-Za-z0-9_-]+)/;
\r
607 var templateParentClass = /treegrid-parent-([A-Za-z0-9_-]+)/;
\r
608 return templateClass.test(classNames) && !templateParentClass.test(classNames);
\r
612 getAllNodes: function(treegridContainer) {
\r
613 var result = $.grep(treegridContainer.find('tr'), function(element) {
\r
614 var classNames = $(element).attr('class');
\r
615 var templateClass = /treegrid-([A-Za-z0-9_-]+)/;
\r
616 return templateClass.test(classNames);
\r