Subversion Repositories ALCASAR

Rev

Details | Last modification | View Log

Rev Author Line No. Line
2808 rexy 1
/*
2
 * jQuery treegrid Plugin 0.3.0
3
 * https://github.com/maxazan/jquery-treegrid
4
 *
5
 * Copyright 2013, Pomazan Max
6
 * Licensed under the MIT licenses.
7
 */
8
(function($) {
9
 
10
    var methods = {
11
        /**
12
         * Initialize tree
13
         *
14
         * @param {Object} options
15
         * @returns {Object[]}
16
         */
17
        initTree: function(options) {
18
            var settings = $.extend({}, this.treegrid.defaults, options);
19
            return this.each(function() {
20
                var $this = $(this);
21
                $this.treegrid('setTreeContainer', $(this));
22
                $this.treegrid('setSettings', settings);
23
                settings.getRootNodes.apply(this, [$(this)]).treegrid('initNode', settings);
24
                $this.treegrid('getRootNodes').treegrid('render');
25
            });
26
        },
27
        /**
28
         * Initialize node
29
         *
30
         * @param {Object} settings
31
         * @returns {Object[]}
32
         */
33
        initNode: function(settings) {
34
            return this.each(function() {
35
                var $this = $(this);
36
                $this.treegrid('setTreeContainer', settings.getTreeGridContainer.apply(this));
37
                $this.treegrid('getChildNodes').treegrid('initNode', settings);
38
                $this.treegrid('initExpander').treegrid('initIndent').treegrid('initEvents').treegrid('initState').treegrid('initChangeEvent').treegrid("initSettingsEvents");
39
            });
40
        },
41
        initChangeEvent: function() {
42
            var $this = $(this);
43
            //Save state on change
44
            $this.on("change", function() {
45
                var $this = $(this);
46
                $this.treegrid('render');
47
                if ($this.treegrid('getSetting', 'saveState')) {
48
                    $this.treegrid('saveState');
49
                }
50
            });
51
            return $this;
52
        },
53
        /**
54
         * Initialize node events
55
         *
56
         * @returns {Node}
57
         */
58
        initEvents: function() {
59
            var $this = $(this);
60
            //Default behavior on collapse
61
            $this.on("collapse", function() {
62
                var $this = $(this);
63
                $this.removeClass('treegrid-expanded');
64
                $this.addClass('treegrid-collapsed');
65
            });
66
            //Default behavior on expand
67
            $this.on("expand", function() {
68
                var $this = $(this);
69
                $this.removeClass('treegrid-collapsed');
70
                $this.addClass('treegrid-expanded');
71
            });
72
 
73
            return $this;
74
        },
75
        /**
76
         * Initialize events from settings
77
         *
78
         * @returns {Node}
79
         */
80
        initSettingsEvents: function() {
81
            var $this = $(this);
82
            //Save state on change
83
            $this.on("change", function() {
84
                var $this = $(this);
85
                if (typeof($this.treegrid('getSetting', 'onChange')) === "function") {
86
                    $this.treegrid('getSetting', 'onChange').apply($this);
87
                }
88
            });
89
            //Default behavior on collapse
90
            $this.on("collapse", function() {
91
                var $this = $(this);
92
                if (typeof($this.treegrid('getSetting', 'onCollapse')) === "function") {
93
                    $this.treegrid('getSetting', 'onCollapse').apply($this);
94
                }
95
            });
96
            //Default behavior on expand
97
            $this.on("expand", function() {
98
                var $this = $(this);
99
                if (typeof($this.treegrid('getSetting', 'onExpand')) === "function") {
100
                    $this.treegrid('getSetting', 'onExpand').apply($this);
101
                }
102
 
103
            });
104
 
105
            return $this;
106
        },
107
        /**
108
         * Initialize expander for node
109
         *
110
         * @returns {Node}
111
         */
112
        initExpander: function() {
113
            var $this = $(this);
114
            var cell = $this.find('td').get($this.treegrid('getSetting', 'treeColumn'));
115
            var tpl = $this.treegrid('getSetting', 'expanderTemplate');
116
            var expander = $this.treegrid('getSetting', 'getExpander').apply(this);
117
            if (expander) {
118
                expander.remove();
119
            }
120
            $(tpl).prependTo(cell).click(function() {
121
                $($(this).closest('tr')).treegrid('toggle');
122
            });
123
            return $this;
124
        },
125
        /**
126
         * Initialize indent for node
127
         *
128
         * @returns {Node}
129
         */
130
        initIndent: function() {
131
            var $this = $(this);
132
            $this.find('.treegrid-indent').remove();
133
            var tpl = $this.treegrid('getSetting', 'indentTemplate');
134
            var expander = $this.find('.treegrid-expander');
135
            var depth = $this.treegrid('getDepth');
136
            for (var i = 0; i < depth; i++) {
137
                $(tpl).insertBefore(expander);
138
            }
139
            return $this;
140
        },
141
        /**
142
         * Initialise state of node
143
         *
144
         * @returns {Node}
145
         */
146
        initState: function() {
147
            var $this = $(this);
148
            if ($this.treegrid('getSetting', 'saveState') && !$this.treegrid('isFirstInit')) {
149
                $this.treegrid('restoreState');
150
            } else {
151
                if ($this.treegrid('getSetting', 'initialState') === "expanded") {
152
                    $this.treegrid('expand');
153
                } else {
154
                    $this.treegrid('collapse');
155
                }
156
            }
157
            return $this;
158
        },
159
        /**
160
         * Return true if this tree was never been initialised
161
         *
162
         * @returns {Boolean}
163
         */
164
        isFirstInit: function() {
165
            var tree = $(this).treegrid('getTreeContainer');
166
            if (tree.data('first_init') === undefined) {
167
                tree.data('first_init', $.cookie(tree.treegrid('getSetting', 'saveStateName')) === undefined);
168
            }
169
            return tree.data('first_init');
170
        },
171
        /**
172
         * Save state of current node
173
         *
174
         * @returns {Node}
175
         */
176
        saveState: function() {
177
            var $this = $(this);
178
            if ($this.treegrid('getSetting', 'saveStateMethod') === 'cookie') {
179
 
180
                var stateArrayString = $.cookie($this.treegrid('getSetting', 'saveStateName')) || '';
181
                var stateArray = (stateArrayString === '' ? [] : stateArrayString.split(','));
182
                var nodeId = $this.treegrid('getNodeId');
183
 
184
                if ($this.treegrid('isExpanded')) {
185
                    if ($.inArray(nodeId, stateArray) === -1) {
186
                        stateArray.push(nodeId);
187
                    }
188
                } else if ($this.treegrid('isCollapsed')) {
189
                    if ($.inArray(nodeId, stateArray) !== -1) {
190
                        stateArray.splice($.inArray(nodeId, stateArray), 1);
191
                    }
192
                }
193
                $.cookie($this.treegrid('getSetting', 'saveStateName'), stateArray.join(','));
194
            }
195
            return $this;
196
        },
197
        /**
198
         * Restore state of current node.
199
         *
200
         * @returns {Node}
201
         */
202
        restoreState: function() {
203
            var $this = $(this);
204
            if ($this.treegrid('getSetting', 'saveStateMethod') === 'cookie') {
205
                var stateArray = $.cookie($this.treegrid('getSetting', 'saveStateName')).split(',');
206
                if ($.inArray($this.treegrid('getNodeId'), stateArray) !== -1) {
207
                    $this.treegrid('expand');
208
                } else {
209
                    $this.treegrid('collapse');
210
                }
211
 
212
            }
213
            return $this;
214
        },
215
        /**
216
         * Method return setting by name
217
         *
218
         * @param {type} name
219
         * @returns {unresolved}
220
         */
221
        getSetting: function(name) {
222
            if (!$(this).treegrid('getTreeContainer')) {
223
                return null;
224
            }
225
            return $(this).treegrid('getTreeContainer').data('settings')[name];
226
        },
227
        /**
228
         * Add new settings
229
         *
230
         * @param {Object} settings
231
         */
232
        setSettings: function(settings) {
233
            $(this).treegrid('getTreeContainer').data('settings', settings);
234
        },
235
        /**
236
         * Return tree container
237
         *
238
         * @returns {HtmlElement}
239
         */
240
        getTreeContainer: function() {
241
            return $(this).data('treegrid');
242
        },
243
        /**
244
         * Set tree container
245
         *
246
         * @param {HtmlE;ement} container
247
         */
248
        setTreeContainer: function(container) {
249
            return $(this).data('treegrid', container);
250
        },
251
        /**
252
         * Method return all root nodes of tree.
253
         *
254
         * Start init all child nodes from it.
255
         *
256
         * @returns {Array}
257
         */
258
        getRootNodes: function() {
259
            return $(this).treegrid('getSetting', 'getRootNodes').apply(this, [$(this).treegrid('getTreeContainer')]);
260
        },
261
        /**
262
         * Method return all nodes of tree.
263
         *
264
         * @returns {Array}
265
         */
266
        getAllNodes: function() {
267
            return $(this).treegrid('getSetting', 'getAllNodes').apply(this, [$(this).treegrid('getTreeContainer')]);
268
        },
269
        /**
270
         * Mthod return true if element is Node
271
         *
272
         * @returns {String}
273
         */
274
        isNode: function() {
275
            return $(this).treegrid('getNodeId') !== null;
276
        },
277
        /**
278
         * Mthod return id of node
279
         *
280
         * @returns {String}
281
         */
282
        getNodeId: function() {
283
            if ($(this).treegrid('getSetting', 'getNodeId') === null) {
284
                return null;
285
            } else {
286
                return $(this).treegrid('getSetting', 'getNodeId').apply(this);
287
            }
288
        },
289
        /**
290
         * Method return parent id of node or null if root node
291
         *
292
         * @returns {String}
293
         */
294
        getParentNodeId: function() {
295
            return $(this).treegrid('getSetting', 'getParentNodeId').apply(this);
296
        },
297
        /**
298
         * Method return parent node or null if root node
299
         *
300
         * @returns {Object[]}
301
         */
302
        getParentNode: function() {
303
            if ($(this).treegrid('getParentNodeId') === null) {
304
                return null;
305
            } else {
306
                return $(this).treegrid('getSetting', 'getNodeById').apply(this, [$(this).treegrid('getParentNodeId'), $(this).treegrid('getTreeContainer')]);
307
            }
308
        },
309
        /**
310
         * Method return array of child nodes or null if node is leaf
311
         *
312
         * @returns {Object[]}
313
         */
314
        getChildNodes: function() {
315
            return $(this).treegrid('getSetting', 'getChildNodes').apply(this, [$(this).treegrid('getNodeId'), $(this).treegrid('getTreeContainer')]);
316
        },
317
        /**
318
         * Method return depth of tree.
319
         *
320
         * This method is needs for calculate indent
321
         *
322
         * @returns {Number}
323
         */
324
        getDepth: function() {
325
            if ($(this).treegrid('getParentNode') === null) {
326
                return 0;
327
            }
328
            return $(this).treegrid('getParentNode').treegrid('getDepth') + 1;
329
        },
330
        /**
331
         * Method return true if node is root
332
         *
333
         * @returns {Boolean}
334
         */
335
        isRoot: function() {
336
            return $(this).treegrid('getDepth') === 0;
337
        },
338
        /**
339
         * Method return true if node has no child nodes
340
         *
341
         * @returns {Boolean}
342
         */
343
        isLeaf: function() {
344
            return $(this).treegrid('getChildNodes').length === 0;
345
        },
346
        /**
347
         * Method return true if node last in branch
348
         *
349
         * @returns {Boolean}
350
         */
351
        isLast: function() {
352
            if ($(this).treegrid('isNode')) {
353
                var parentNode = $(this).treegrid('getParentNode');
354
                if (parentNode === null) {
355
                    if ($(this).treegrid('getNodeId') === $(this).treegrid('getRootNodes').last().treegrid('getNodeId')) {
356
                        return true;
357
                    }
358
                } else {
359
                    if ($(this).treegrid('getNodeId') === parentNode.treegrid('getChildNodes').last().treegrid('getNodeId')) {
360
                        return true;
361
                    }
362
                }
363
            }
364
            return false;
365
        },
366
        /**
367
         * Method return true if node first in branch
368
         *
369
         * @returns {Boolean}
370
         */
371
        isFirst: function() {
372
            if ($(this).treegrid('isNode')) {
373
                var parentNode = $(this).treegrid('getParentNode');
374
                if (parentNode === null) {
375
                    if ($(this).treegrid('getNodeId') === $(this).treegrid('getRootNodes').first().treegrid('getNodeId')) {
376
                        return true;
377
                    }
378
                } else {
379
                    if ($(this).treegrid('getNodeId') === parentNode.treegrid('getChildNodes').first().treegrid('getNodeId')) {
380
                        return true;
381
                    }
382
                }
383
            }
384
            return false;
385
        },
386
        /**
387
         * Return true if node expanded
388
         *
389
         * @returns {Boolean}
390
         */
391
        isExpanded: function() {
392
            return $(this).hasClass('treegrid-expanded');
393
        },
394
        /**
395
         * Return true if node collapsed
396
         *
397
         * @returns {Boolean}
398
         */
399
        isCollapsed: function() {
400
            return $(this).hasClass('treegrid-collapsed');
401
        },
402
        /**
403
         * Return true if at least one of parent node is collapsed
404
         *
405
         * @returns {Boolean}
406
         */
407
        isOneOfParentsCollapsed: function() {
408
            var $this = $(this);
409
            if ($this.treegrid('isRoot')) {
410
                return false;
411
            } else {
412
                if ($this.treegrid('getParentNode').treegrid('isCollapsed')) {
413
                    return true;
414
                } else {
415
                    return $this.treegrid('getParentNode').treegrid('isOneOfParentsCollapsed');
416
                }
417
            }
418
        },
419
        /**
420
         * Expand node
421
         *
422
         * @returns {Node}
423
         */
424
        expand: function() {
425
            if (!this.treegrid('isLeaf') && !this.treegrid("isExpanded")) {
426
                this.trigger("expand");
427
                this.trigger("change");
428
                return this;
429
            }
430
            return this;
431
        },
432
        /**
433
         * Expand all nodes
434
         *
435
         * @returns {Node}
436
         */
437
        expandAll: function() {
438
            var $this = $(this);
439
            $this.treegrid('getRootNodes').treegrid('expandRecursive');
440
            return $this;
441
        },
442
        /**
443
         * Expand current node and all child nodes begin from current
444
         *
445
         * @returns {Node}
446
         */
447
        expandRecursive: function() {
448
            return $(this).each(function() {
449
                var $this = $(this);
450
                $this.treegrid('expand');
451
                if (!$this.treegrid('isLeaf')) {
452
                    $this.treegrid('getChildNodes').treegrid('expandRecursive');
453
                }
454
            });
455
        },
456
        /**
457
         * Collapse node
458
         *
459
         * @returns {Node}
460
         */
461
        collapse: function() {
462
            return $(this).each(function() {
463
                var $this = $(this);
464
                if (!$this.treegrid('isLeaf') && !$this.treegrid("isCollapsed")) {
465
                    $this.trigger("collapse");
466
                    $this.trigger("change");
467
                }
468
            });
469
        },
470
        /**
471
         * Collapse all nodes
472
         *
473
         * @returns {Node}
474
         */
475
        collapseAll: function() {
476
            var $this = $(this);
477
            $this.treegrid('getRootNodes').treegrid('collapseRecursive');
478
            return $this;
479
        },
480
        /**
481
         * Collapse current node and all child nodes begin from current
482
         *
483
         * @returns {Node}
484
         */
485
        collapseRecursive: function() {
486
            return $(this).each(function() {
487
                var $this = $(this);
488
                $this.treegrid('collapse');
489
                if (!$this.treegrid('isLeaf')) {
490
                    $this.treegrid('getChildNodes').treegrid('collapseRecursive');
491
                }
492
            });
493
        },
494
        /**
495
         * Expand if collapsed, Collapse if expanded
496
         *
497
         * @returns {Node}
498
         */
499
        toggle: function() {
500
            var $this = $(this);
501
            if ($this.treegrid('isExpanded')) {
502
                $this.treegrid('collapse');
503
            } else {
504
                $this.treegrid('expand');
505
            }
506
            return $this;
507
        },
508
        /**
509
         * Rendering node
510
         *
511
         * @returns {Node}
512
         */
513
        render: function() {
514
            return $(this).each(function() {
515
                var $this = $(this);
516
                //if parent colapsed we hidden
517
                if ($this.treegrid('isOneOfParentsCollapsed')) {
518
                    $this.hide();
519
                } else {
520
                    $this.show();
521
                }
522
                if (!$this.treegrid('isLeaf')) {
523
                    $this.treegrid('renderExpander');
524
                    $this.treegrid('getChildNodes').treegrid('render');
525
                }
526
            });
527
        },
528
        /**
529
         * Rendering expander depends on node state
530
         *
531
         * @returns {Node}
532
         */
533
        renderExpander: function() {
534
            return $(this).each(function() {
535
                var $this = $(this);
536
                var expander = $this.treegrid('getSetting', 'getExpander').apply(this);
537
                if (expander) {
538
 
539
                    if (!$this.treegrid('isCollapsed')) {
540
                        expander.removeClass($this.treegrid('getSetting', 'expanderCollapsedClass'));
541
                        expander.addClass($this.treegrid('getSetting', 'expanderExpandedClass'));
542
                    } else {
543
                        expander.removeClass($this.treegrid('getSetting', 'expanderExpandedClass'));
544
                        expander.addClass($this.treegrid('getSetting', 'expanderCollapsedClass'));
545
                    }
546
                } else {
547
                    $this.treegrid('initExpander');
548
                    $this.treegrid('renderExpander');
549
                }
550
            });
551
        }
552
    };
553
    $.fn.treegrid = function(method) {
554
        if (methods[method]) {
555
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
556
        } else if (typeof method === 'object' || !method) {
557
            return methods.initTree.apply(this, arguments);
558
        } else {
559
            $.error('Method with name ' + method + ' does not exists for jQuery.treegrid');
560
        }
561
    };
562
    /**
563
     *  Plugin's default options
564
     */
565
    $.fn.treegrid.defaults = {
566
        initialState: 'expanded',
567
        saveState: false,
568
        saveStateMethod: 'cookie',
569
        saveStateName: 'tree-grid-state',
570
        expanderTemplate: '<span class="treegrid-expander"></span>',
571
        indentTemplate: '<span class="treegrid-indent"></span>',
572
        expanderExpandedClass: 'treegrid-expander-expanded',
573
        expanderCollapsedClass: 'treegrid-expander-collapsed',
574
        treeColumn: 0,
575
        getExpander: function() {
576
            return $(this).find('.treegrid-expander');
577
        },
578
        getNodeId: function() {
579
            var template = /treegrid-([A-Za-z0-9_-]+)/;
580
            if (template.test($(this).attr('class'))) {
581
                return template.exec($(this).attr('class'))[1];
582
            }
583
            return null;
584
        },
585
        getParentNodeId: function() {
586
            var template = /treegrid-parent-([A-Za-z0-9_-]+)/;
587
            if (template.test($(this).attr('class'))) {
588
                return template.exec($(this).attr('class'))[1];
589
            }
590
            return null;
591
        },
592
        getNodeById: function(id, treegridContainer) {
593
            var templateClass = "treegrid-" + id;
594
            return treegridContainer.find('tr.' + templateClass);
595
        },
596
        getChildNodes: function(id, treegridContainer) {
597
            var templateClass = "treegrid-parent-" + id;
598
            return treegridContainer.find('tr.' + templateClass);
599
        },
600
        getTreeGridContainer: function() {
601
            return $(this).closest('table');
602
        },
603
        getRootNodes: function(treegridContainer) {
604
            var result = $.grep(treegridContainer.find('tr'), function(element) {
605
                var classNames = $(element).attr('class');
606
                var templateClass = /treegrid-([A-Za-z0-9_-]+)/;
607
                var templateParentClass = /treegrid-parent-([A-Za-z0-9_-]+)/;
608
                return templateClass.test(classNames) && !templateParentClass.test(classNames);
609
            });
610
            return $(result);
611
        },
612
        getAllNodes: function(treegridContainer) {
613
            var result = $.grep(treegridContainer.find('tr'), function(element) {
614
                var classNames = $(element).attr('class');
615
                var templateClass = /treegrid-([A-Za-z0-9_-]+)/;
616
                return templateClass.test(classNames);
617
            });
618
            return $(result);
619
        },
620
        //Events
621
        onCollapse: null,
622
        onExpand: null,
623
        onChange: null
624
 
625
    };
626
})(jQuery);