deep-cover 0.1.16 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +3 -8
  4. data/.travis.yml +4 -4
  5. data/CHANGELOG.md +10 -0
  6. data/Gemfile +3 -1
  7. data/README.md +9 -4
  8. data/Rakefile +6 -3
  9. data/deep_cover.gemspec +2 -2
  10. data/lib/deep_cover.rb +10 -0
  11. data/lib/deep_cover/analyser.rb +1 -2
  12. data/lib/deep_cover/analyser/base.rb +32 -0
  13. data/lib/deep_cover/analyser/branch.rb +19 -4
  14. data/lib/deep_cover/analyser/node.rb +52 -0
  15. data/lib/deep_cover/analyser/per_char.rb +18 -1
  16. data/lib/deep_cover/analyser/stats.rb +54 -0
  17. data/lib/deep_cover/backports.rb +1 -0
  18. data/lib/deep_cover/base.rb +17 -1
  19. data/lib/deep_cover/builtin_takeover.rb +5 -0
  20. data/lib/deep_cover/cli/deep_cover.rb +2 -1
  21. data/lib/deep_cover/cli/instrumented_clone_reporter.rb +12 -10
  22. data/lib/deep_cover/config.rb +22 -8
  23. data/lib/deep_cover/core_ext/coverage_replacement.rb +22 -18
  24. data/lib/deep_cover/coverage.rb +3 -203
  25. data/lib/deep_cover/coverage/analysis.rb +36 -0
  26. data/lib/deep_cover/coverage/base.rb +91 -0
  27. data/lib/deep_cover/coverage/istanbul.rb +34 -0
  28. data/lib/deep_cover/coverage/persistence.rb +93 -0
  29. data/lib/deep_cover/covered_code.rb +12 -22
  30. data/lib/deep_cover/custom_requirer.rb +6 -2
  31. data/lib/deep_cover/node/base.rb +1 -1
  32. data/lib/deep_cover/node/case.rb +13 -2
  33. data/lib/deep_cover/node/exceptions.rb +2 -2
  34. data/lib/deep_cover/node/if.rb +21 -2
  35. data/lib/deep_cover/node/mixin/flow_accounting.rb +1 -0
  36. data/lib/deep_cover/node/send.rb +9 -2
  37. data/lib/deep_cover/node/short_circuit.rb +10 -0
  38. data/lib/deep_cover/parser_ext/range.rb +4 -4
  39. data/lib/deep_cover/reporter/html.rb +15 -0
  40. data/lib/deep_cover/reporter/html/base.rb +14 -0
  41. data/lib/deep_cover/reporter/html/index.rb +78 -0
  42. data/lib/deep_cover/reporter/html/site.rb +78 -0
  43. data/lib/deep_cover/reporter/html/source.rb +136 -0
  44. data/lib/deep_cover/reporter/html/template/assets/32px.png +0 -0
  45. data/lib/deep_cover/reporter/html/template/assets/40px.png +0 -0
  46. data/lib/deep_cover/reporter/html/template/assets/deep_cover.css.sass +338 -0
  47. data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.js +4 -0
  48. data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.map +1 -0
  49. data/lib/deep_cover/reporter/html/template/assets/jstree.css +1108 -0
  50. data/lib/deep_cover/reporter/html/template/assets/jstree.js +8424 -0
  51. data/lib/deep_cover/reporter/html/template/assets/jstreetable.js +1069 -0
  52. data/lib/deep_cover/reporter/html/template/assets/throbber.gif +0 -0
  53. data/lib/deep_cover/reporter/html/template/index.html.erb +75 -0
  54. data/lib/deep_cover/reporter/html/template/source.html.erb +35 -0
  55. data/lib/deep_cover/reporter/html/tree.rb +55 -0
  56. data/lib/deep_cover/tools/content_tag.rb +11 -0
  57. data/lib/deep_cover/tools/covered.rb +9 -0
  58. data/lib/deep_cover/tools/merge.rb +16 -0
  59. data/lib/deep_cover/tools/render_template.rb +13 -0
  60. data/lib/deep_cover/tools/transform_keys.rb +9 -0
  61. data/lib/deep_cover/version.rb +1 -1
  62. metadata +33 -7
  63. data/lib/deep_cover/analyser/ignore_uncovered.rb +0 -21
  64. data/lib/deep_cover/analyser/optionally_covered.rb +0 -19
@@ -0,0 +1,1069 @@
1
+ /*
2
+ * http://github.com/adamjimenez/jstree-table
3
+ *
4
+ * This plugin handles adding columns to a tree to display additional data
5
+ *
6
+ * Licensed under the MIT license:
7
+ * http://www.opensource.org/licenses/mit-license.php
8
+ *
9
+ * Works only with jstree version >= 3.0.0
10
+ *
11
+ * $Revision: 3.4.2 $
12
+ */
13
+
14
+ /*jslint nomen:true */
15
+ /*jshint unused:vars */
16
+ /*global navigator, document, jQuery, define, localStorage */
17
+
18
+ (function (factory) {
19
+ if (typeof define === 'function' && define.amd) {
20
+ // AMD. Register as an anonymous module.
21
+ define(['jquery', 'jstree'], factory);
22
+ } else {
23
+ // Browser globals
24
+ factory(jQuery);
25
+ }
26
+ }(function ($) {
27
+ var renderAWidth, renderATitle, getIndent, copyData, htmlstripre, findLastClosedNode, BLANKRE = /^\s*$/g,
28
+ IDREGEX = /[\\:&!^|()\[\]<>@*'+~#";,= \/${}%]/g, escapeId = function (id) {
29
+ return (id||"").replace(IDREGEX,'\\$&');
30
+ }, NODE_DATA_ATTR = "data-jstreetable", COL_DATA_ATTR = "data-jstreetable-column",
31
+ SPECIAL_TITLE = "_DATA_", LEVELINDENT = 24, styled = false, TABLECELLID_PREFIX = "jstable_",TABLECELLID_POSTFIX = "_col",
32
+ MINCOLWIDTH = 10,
33
+ findDataCell = function (from,id) {
34
+ return from.find("div["+NODE_DATA_ATTR+'="'+ escapeId(id) +'"]');
35
+ },
36
+ findDataCellFast = function(colNb,id) {
37
+ return $(document.getElementById("jstable_"+id+"_col"+colNb));
38
+ },
39
+ isClickedSep = false, toResize = null, oldMouseX = 0, newMouseX = 0;
40
+
41
+ /*jslint regexp:true */
42
+ htmlstripre = /<\/?[^>]+>/gi;
43
+ /*jslint regexp:false */
44
+
45
+ getIndent = function(node,tree) {
46
+ var div, i, li, width;
47
+
48
+ // did we already save it for this tree?
49
+ tree._tableSettings = tree._tableSettings || {};
50
+ if (tree._tableSettings.indent > 0) {
51
+ width = tree._tableSettings.indent;
52
+ } else {
53
+ // create a new div on the DOM but not visible on the page
54
+ div = $("<div></div>");
55
+ i = node.prev("i");
56
+ li = i.parent();
57
+ // add to that div all of the classes on the tree root
58
+ div.addClass(tree.get_node("#",true).attr("class"));
59
+
60
+ // move the li to the temporary div root
61
+ li.appendTo(div);
62
+
63
+ // attach to the body quickly
64
+ div.appendTo($("body"));
65
+
66
+ // get the width
67
+ width = i.width() || LEVELINDENT;
68
+
69
+ // detach the li from the new div and destroy the new div
70
+ li.detach();
71
+ div.remove();
72
+
73
+ // save it for the future
74
+ tree._tableSettings.indent = width;
75
+ }
76
+
77
+
78
+ return(width);
79
+
80
+ };
81
+
82
+ copyData = function (fromtree,from,totree,to,recurse) {
83
+ var i, j;
84
+ to.data = $.extend(true, {}, from.data);
85
+ if (from && from.children_d && recurse) {
86
+ for(i = 0, j = from.children_d.length; i < j; i++) {
87
+ copyData(fromtree,fromtree.get_node(from.children_d[i]),totree,totree.get_node(to.children_d[i]),recurse);
88
+ }
89
+ }
90
+ };
91
+
92
+ findLastClosedNode = function (tree,id) {
93
+ // first get our node
94
+ var ret, node = tree.get_node(id), children = node.children;
95
+ // is it closed?
96
+ if (!children || children.length <= 0 || !node.state.opened) {
97
+ ret = id;
98
+ } else {
99
+ ret = findLastClosedNode(tree,children[children.length-1]);
100
+ }
101
+ return(ret);
102
+ };
103
+
104
+ renderAWidth = function(node,tree) {
105
+ var depth, width,
106
+ fullWidth = parseInt(tree.settings.table.columns[0].width,10) + parseInt(tree._tableSettings.treeWidthDiff,10);
107
+ // need to use a selector in jquery 1.4.4+
108
+ depth = tree.get_node(node).parents.length;
109
+ width = fullWidth - depth*getIndent(node,tree);
110
+ // the following line is no longer needed, since we are doing this inside a <td>
111
+ //a.css({"vertical-align": "top", "overflow":"hidden"});
112
+ return(fullWidth);
113
+ };
114
+ renderATitle = function(node,t,tree) {
115
+ var a = node.get(0).tagName.toLowerCase() === "a" ? node : node.children("a"), title, col = tree.settings.table.columns[0];
116
+ // get the title
117
+ title = "";
118
+ if (col.title) {
119
+ if (col.title === SPECIAL_TITLE) {
120
+ title = tree.get_text(t);
121
+ } else if (t.attr(col.title)) {
122
+ title = t.attr(col.title);
123
+ }
124
+ }
125
+ // strip out HTML
126
+ title = title.replace(htmlstripre, '');
127
+ if (title) {
128
+ a.attr("title",title);
129
+ }
130
+ };
131
+
132
+ $.jstree.defaults.table = {
133
+ width: 'auto'
134
+ };
135
+
136
+ $.jstree.plugins.table = function(options,parent) {
137
+ var _this = this;
138
+
139
+ this._initialize = function () {
140
+ if (!this._initialized) {
141
+ var s = this.settings.table || {}, styles, container = this.element, i,
142
+ gs = this._tableSettings = {
143
+ columns : s.columns || [],
144
+ treeClass : "jstree-table-col-0",
145
+ context: s.contextmenu || false,
146
+ columnWidth : s.columnWidth,
147
+ defaultConf : {"*display":"inline","*+display":"inline"},
148
+ isThemeroller : !!this._data.themeroller,
149
+ treeWidthDiff : 0,
150
+ resizable : s.resizable,
151
+ draggable : s.draggable,
152
+ stateful: s.stateful,
153
+ indent: 0,
154
+ sortFn: [],
155
+ sortOrder: 'text',
156
+ sortAsc: true,
157
+ fixedHeader: s.fixedHeader !== false,
158
+ headerContextMenu: s.headerContextMenu !== false,
159
+ checkIcon: 'fa fa-check',
160
+ arrowDownIcon: 'fa fa-chevron-down',
161
+ arrowUpIcon: 'fa fa-chevron-up',
162
+ width: s.width,
163
+ height: s.height
164
+ }, cols = gs.columns, treecol = 0;
165
+ // find which column our tree shuld go in
166
+ for (i=0;i<s.columns.length;i++) {
167
+ //Save sort function
168
+ if (i!==0 && s.columns[i].sort) {
169
+ gs.sortFn[s.columns[i].value] = s.columns[i].sort;
170
+ }
171
+ if (s.columns[i].tree) {
172
+ // save which column it was
173
+ treecol = i;
174
+ // do not check any others
175
+ break;
176
+ }
177
+ }
178
+ // set a unique ID for this table
179
+ this.uniq = Math.ceil(Math.random()*1000);
180
+ this.rootid = container.attr("id");
181
+
182
+ var msie = /msie/.test(navigator.userAgent.toLowerCase());
183
+ if (msie) {
184
+ var version = parseFloat(navigator.appVersion.split("MSIE")[1]);
185
+ if (version < 8) {
186
+ gs.defaultConf.display = "inline";
187
+ gs.defaultConf.zoom = "1";
188
+ }
189
+ }
190
+
191
+ // set up the classes we need
192
+ if (!styled) {
193
+ styled = true;
194
+ styles = [
195
+ '.jstree-table-cell {vertical-align: top; overflow:hidden;margin-left:0;width: 100%;padding-left:7px;white-space: nowrap; cursor: default; text-overflow: ellipsis;}',
196
+ '.jstree-table-cell span {margin-right:0px;margin-right:0px;*display:inline;*+display:inline;white-space: nowrap;}',
197
+ '.jstree-table-separator {position:absolute; top:0; right:0; height:24px; margin-left: -2px; border-width: 0 2px 0 0; *display:inline; *+display:inline; margin-right:0px;width:0px;}',
198
+ '.jstree-table-header-cell {overflow: hidden; white-space: nowrap;padding: 4px 3px 2px 5px; cursor: default;}',
199
+ '.jstree-table-header-themeroller {border: 0; padding: 1px 3px;}',
200
+ '.jstree-table-header-regular {position:relative; background-color: #CBF3FD; z-index: 1;}',
201
+ '.jstree-table-resizable-separator {cursor: col-resize; width: 10px;}',
202
+ '.jstree-table-separator-regular {border-color: #d0d0d0; border-style: solid;}',
203
+ '.jstree-table-cell-themeroller {border: none !important; background: transparent !important;}',
204
+ '.jstree-table-wrapper {table-layout: fixed; width: 100%; overflow: auto; position: relative;}',
205
+ '.jstree-table-midwrapper {display: table-row;}',
206
+ '.jstree-table-width-auto {width:auto;display:block;}',
207
+ '.jstree-table-column {display: table-cell; overflow: hidden;}',
208
+ '.jstree-table-col-0 {width: calc(100% - 18px); overflow: hidden; text-overflow: ellipsis;}',
209
+ '.jstree-table-sort-icon {font-size: 8px; position: absolute; top:0; left: calc(50% - 4px);}',
210
+ '.jstree-table-midwrapper a.jstree-clicked, .jstree-table-midwrapper a.jstree-hovered{background: transparent; border-color: transparent;}',
211
+ '.jstree-table-midwrapper a.jstree-clicked:before, .jstree-table-midwrapper a.jstree-hovered:before {position: absolute; left: 0; content:""; height: inherit; z-index: -1;}',
212
+ '.jstree-table-midwrapper a.jstree-hovered:before {background: #e7f4f9;}',
213
+ '.jstree-table-midwrapper a.jstree-clicked:before {background: #beebff;}',
214
+ '.vakata-context {z-index:2;}'
215
+ ];
216
+
217
+ $('<style type="text/css">'+styles.join("\n")+'</style>').appendTo("head");
218
+ }
219
+ this.tableWrapper = $("<div></div>").addClass("jstree-table-wrapper").insertAfter(container);
220
+ this.midWrapper = $("<div></div>").addClass("jstree-table-midwrapper").appendTo(this.tableWrapper);
221
+ // set the wrapper width
222
+ if (s.width) {
223
+ this.tableWrapper.width(s.width);
224
+ }
225
+ if (s.height) {
226
+ this.tableWrapper.height(s.height);
227
+ }
228
+ // create the data columns
229
+ for (i=0;i<cols.length;i++) {
230
+ // create the column
231
+ $("<div></div>").addClass("jstree-default jstree-table-column jstree-table-column-"+i+" jstree-table-column-root-"+this.rootid).appendTo(this.midWrapper);
232
+
233
+ if (typeof(cols[i].value) === "function") {
234
+ console.warn("[jstree-table] using value as a function is no longer supported, use 'format' option instead.");
235
+ }
236
+ }
237
+ this.midWrapper.children("div:eq("+treecol+")").append(container);
238
+ container.addClass("jstree-table-cell");
239
+
240
+ //move header with scroll
241
+ if (gs.fixedHeader) {
242
+ this.tableWrapper.scroll(function() {
243
+ $(this).find('.jstree-table-header').css('top', $(this).scrollTop());
244
+ });
245
+ }
246
+
247
+ // copy original sort function
248
+ var defaultSort = $.proxy(this.settings.sort, this);
249
+
250
+ // override sort function
251
+ this.settings.sort = function (a, b) {
252
+ var bigger;
253
+
254
+ if (gs.sortOrder==='text') {
255
+ bigger = defaultSort(a, b);
256
+ } else {
257
+ var nodeA = this.get_node(a);
258
+ var nodeB = this.get_node(b);
259
+ var valueA = nodeA.data[gs.sortOrder];
260
+ var valueB = nodeB.data[gs.sortOrder];
261
+ if(valueA && valueB){
262
+ if(gs.sortFn[gs.sortOrder]){
263
+ bigger = gs.sortFn[gs.sortOrder](valueA, valueB, nodeA, nodeB);
264
+ }else{
265
+ // Default sorting
266
+ bigger = (valueA > valueB ? 1 : -1);
267
+ }
268
+ }else{
269
+ // undefined is second
270
+ if(valueA){
271
+ bigger = 1;
272
+ }else if(valueB){
273
+ bigger = -1;
274
+ }else{
275
+ // Compare two nodes without values
276
+ bigger = defaultSort(a, b);
277
+ }
278
+ }
279
+ }
280
+
281
+ if (gs.sortAsc===false){
282
+ bigger = -bigger;
283
+
284
+ }
285
+
286
+ return bigger;
287
+ };
288
+
289
+ // sortable columns when jQuery UI is available
290
+ if (gs.draggable) {
291
+ if (!$.ui || !$.ui.sortable) {
292
+ console.warn('[jstree-table] draggable option requires jQuery UI');
293
+ } else {
294
+ var from, to;
295
+
296
+ $(this.midWrapper).sortable({
297
+ axis: "x",
298
+ handle: ".jstree-table-header",
299
+ cancel: ".jstree-table-separator",
300
+ start: function (event, ui) {
301
+ from = ui.item.index();
302
+ },
303
+ stop: function (event, ui) {
304
+ to = ui.item.index();
305
+ gs.columns.splice(to, 0, gs.columns.splice(from, 1)[0]);
306
+ }
307
+ });
308
+ }
309
+ }
310
+
311
+ this._initialized = true;
312
+ }
313
+ };
314
+ this.init = function (el,options) {
315
+ parent.init.call(this,el,options);
316
+ this._initialize();
317
+ };
318
+ this.bind = function () {
319
+ parent.bind.call(this);
320
+ this._initialize();
321
+ this.element
322
+ .on("move_node.jstree create_node.jstree clean_node.jstree change_node.jstree", $.proxy(function (e, data) {
323
+ var target = this.get_node(data || "#",true);
324
+ this._prepare_table(target);
325
+ }, this))
326
+ .on("delete_node.jstree",$.proxy(function (e,data) {
327
+ if (data.node.id !== undefined) {
328
+ var table = this.tableWrapper, removeNodes = [data.node.id], i;
329
+ // add children to remove list
330
+ if (data.node && data.node.children_d) {
331
+ removeNodes = removeNodes.concat(data.node.children_d);
332
+ }
333
+ for (i=0;i<removeNodes.length;i++) {
334
+ findDataCell(table,removeNodes[i]).remove();
335
+ }
336
+ }
337
+ }, this))
338
+ .on("close_node.jstree",$.proxy(function (e,data) {
339
+ this._hide_table(data.node);
340
+ }, this))
341
+ .on("open_node.jstree",$.proxy(function (e,data) {
342
+ }, this))
343
+ .on("load_node.jstree",$.proxy(function (e,data) {
344
+ }, this))
345
+ .on("loaded.jstree", $.proxy(function (e) {
346
+ this._prepare_headers();
347
+ this.element.trigger("loaded_table.jstree");
348
+ }, this))
349
+ .on("ready.jstree",$.proxy(function (e,data) {
350
+ var cls = this.element.attr("class") || "";
351
+
352
+ // add container classes to the wrapper - EXCEPT those that are added by jstree, i.e. "jstree" and "jstree-*"
353
+ q = cls.split(/\s+/).map(function(i) {
354
+ var match = i.match(/^jstree(-|$)/);
355
+ return (match ? "" : i);
356
+ });
357
+ this.tableWrapper.addClass(q.join(" "));
358
+
359
+ var me = this;
360
+ function resize() {
361
+ // find the line-height of the first known node
362
+ var anchorHeight = me.element.find(".jstree-leaf").outerHeight();
363
+
364
+ if(anchorHeight === null) {
365
+ var result = parent.create_node.call(me, '#', { "id" : "tmp", "text" : "tmp" });
366
+ anchorHeight = me.element.find(".jstree-leaf").outerHeight() || 24;
367
+ parent.delete_node.call(me, "tmp");
368
+ }
369
+
370
+ // resize the hover/ focus highlight
371
+ var tableWidth = $('.jstree-table-midwrapper').width();
372
+
373
+ $('#jsTreeTableExtraCss').remove();
374
+ $('<style type="text/css" id="jsTreeTableExtraCss">\
375
+ div.jstree-table-cell-root-'+me.rootid+' {line-height: '+anchorHeight+'px; min-height: '+anchorHeight+'px;}\
376
+ div.jstree-table-midwrapper a.jstree-clicked:before, .jstree-table-midwrapper a.jstree-hovered:before {width: ' + tableWidth + 'px;}\
377
+ </style>').appendTo("head");
378
+ }
379
+
380
+ resize();
381
+
382
+ // resize rows on zoom
383
+ $(window).on('resize', resize);
384
+
385
+ // resize column expand
386
+ this.element.on("resize_column.jstree-table", resize);
387
+ },this))
388
+ .on("move_node.jstree",$.proxy(function(e,data) {
389
+ var node = data.new_instance.element;
390
+ //renderAWidth(node,this);
391
+ // check all the children, because we could drag a tree over
392
+ node.find("li > a").each($.proxy(function(i,elm) {
393
+ //renderAWidth($(elm),this);
394
+ },this));
395
+ },this))
396
+ .on("search.jstree", $.proxy(function (e, data) {
397
+ // search sometimes filters, so we need to hide all of the appropriate table cells as well, and show only the matches
398
+ var table = this.tableWrapper;
399
+ if(this._data.search.som) {
400
+ if(data.nodes.length) {
401
+ // hide all of the table cells
402
+ table.find('div.jstree-table-cell-regular').hide();
403
+ // show only those that match
404
+ data.nodes.add(data.nodes.parentsUntil(".jstree")).filter(".jstree-node").each(function (i,node) {
405
+ var id = node.id;
406
+ if (id) {
407
+ findDataCell(table,id).show();
408
+ }
409
+ });
410
+ }
411
+ }
412
+ return true;
413
+ }, this))
414
+ .on("clear_search.jstree", $.proxy(function (e, data) {
415
+ // search has been cleared, so we need to show all rows
416
+ this.tableWrapper.find('div.jstree-table-cell').show();
417
+ return true;
418
+ }, this))
419
+ .on("copy_node.jstree", function (e, data) {
420
+ var newtree = data.new_instance, oldtree = data.old_instance, obj = newtree.get_node(data.node,true);
421
+ copyData(oldtree,data.original,newtree,data.node,true);
422
+ newtree._prepare_table(obj);
423
+ return true;
424
+ });
425
+ if (this._tableSettings.isThemeroller) {
426
+ this.element
427
+ .on("select_node.jstree",$.proxy(function(e,data) {
428
+ data.rslt.obj.children("a").nextAll("div").addClass("ui-state-active");
429
+ },this))
430
+ .on("deselect_node.jstree deselect_all.jstree",$.proxy(function(e,data) {
431
+ data.rslt.obj.children("a").nextAll("div").removeClass("ui-state-active");
432
+ },this))
433
+ .on("hover_node.jstree",$.proxy(function(e,data) {
434
+ data.rslt.obj.children("a").nextAll("div").addClass("ui-state-hover");
435
+ },this))
436
+ .on("dehover_node.jstree",$.proxy(function(e,data) {
437
+ data.rslt.obj.children("a").nextAll("div").removeClass("ui-state-hover");
438
+ },this));
439
+ }
440
+
441
+ if (this._tableSettings.stateful) {
442
+ this.element
443
+ .on("resize_column.jstree-table",$.proxy(function(e,col,width) {
444
+ localStorage['jstree-root-'+this.rootid+'-column-'+col] = width;
445
+ },this));
446
+ }
447
+ };
448
+ // tear down the tree entirely
449
+ this.teardown = function() {
450
+ var gw = this.tableWrapper, container = this.element, tableparent = gw.parent();
451
+ container.detach();
452
+ gw.remove();
453
+ tableparent.append(container);
454
+ parent.teardown.call(this);
455
+ };
456
+ // clean the table in case of redraw or refresh entire tree
457
+ this._clean_table = function (target,id) {
458
+ var table = this.tableWrapper;
459
+ if (target) {
460
+ findDataCell(table,id).remove();
461
+ } else {
462
+ // get all of the `div` children in all of the `td` in dataRow except for :first (that is the tree itself) and remove
463
+ table.find("div.jstree-table-cell-regular").remove();
464
+ }
465
+ };
466
+ // prepare the headers
467
+ this._prepare_headers = function() {
468
+ var header, i, col, _this = this, gs = this._tableSettings,cols = gs.columns || [], width, defaultWidth = gs.columnWidth, resizable = gs.resizable || false,
469
+ cl, ccl, val, name, margin, last, tr = gs.isThemeroller, classAdd = (tr?"themeroller":"regular"), puller,
470
+ hasHeaders = false, tableparent = this.tableparent, rootid = this.rootid,
471
+ conf = gs.defaultConf,
472
+ borPadWidth = 0, totalWidth = 0;
473
+ // save the original parent so we can reparent on destroy
474
+ this.parent = tableparent;
475
+
476
+
477
+ // create the headers
478
+ for (i=0;i<cols.length;i++) {
479
+ //col = $("<col/>");
480
+ //col.appendTo(colgroup);
481
+ cl = cols[i].headerClass || "";
482
+ ccl = cols[i].columnClass || "";
483
+ val = cols[i].header || "";
484
+ name = cols[i].value || "text";
485
+
486
+ if (val) {hasHeaders = true;}
487
+ if(gs.stateful && localStorage['jstree-root-'+rootid+'-column-'+i])
488
+ width = localStorage['jstree-root-'+rootid+'-column-'+i];
489
+ else
490
+ width = cols[i].width || defaultWidth;
491
+
492
+ col = this.midWrapper.children("div.jstree-table-column-"+i);
493
+ last = $("<div></div>").css(conf).addClass("jstree-table-div-"+this.uniq+"-"+i+" "+(tr?"ui-widget-header ":"")+" jstree-table-header jstree-table-header-cell jstree-table-header-"+classAdd+" "+cl+" "+ccl).html(val);
494
+ last.addClass((tr?"ui-widget-header ":"")+"jstree-table-header jstree-table-header-"+classAdd);
495
+ last.prependTo(col);
496
+
497
+ if (name) {
498
+ last.attr(COL_DATA_ATTR, name);
499
+ }
500
+ last.hover(function () {
501
+ $(this).addClass("jstree-hovered jstree-table-header-hovered");
502
+ }, function () {
503
+ $(this).removeClass("jstree-hovered jstree-table-header-hovered");
504
+ });
505
+ totalWidth += last.outerWidth();
506
+ puller = $("<div class='jstree-table-separator jstree-table-separator-"+classAdd+(tr ? " ui-widget-header" : "")+(resizable? " jstree-table-resizable-separator":"")+"'>&nbsp;</div>").appendTo(last);
507
+ col.width(width);
508
+ col.css("min-width",width);
509
+ col.css("max-width",width);
510
+ }
511
+
512
+ last.addClass((tr?"ui-widget-header ":"")+"jstree-table-header jstree-table-header-last jstree-table-header-"+classAdd);
513
+ // if there is no width given for the last column, do it via automatic
514
+ if (cols[cols.length-1].width === undefined) {
515
+ totalWidth -= width;
516
+ col.css({width:"auto"});
517
+ last.addClass("jstree-table-width-auto").next(".jstree-table-separator").remove();
518
+ }
519
+ if (hasHeaders) {
520
+ // save the offset of the div from the body
521
+ //gs.divOffset = header.parent().offset().left;
522
+ gs.header = header;
523
+ } else {
524
+ $("div.jstree-table-header").hide();
525
+ }
526
+
527
+ if (!this.bound && resizable) {
528
+ this.bound = true;
529
+ $(document).mouseup(function () {
530
+ var ref, cols, width, headers, currentTree, colNum;
531
+ if (isClickedSep) {
532
+ colNum = toResize.prevAll(".jstree-table-column").length;
533
+ currentTree = toResize.closest(".jstree-table-wrapper").find(".jstree");
534
+ ref = $.jstree.reference(currentTree);
535
+ cols = ref.settings.table.columns;
536
+ headers = toResize.parent().children("div.jstree-table-column");
537
+ if (isNaN(colNum) || colNum < 0) { ref._tableSettings.treeWidthDiff = currentTree.find("ins:eq(0)").width() + currentTree.find("a:eq(0)").width() - ref._tableSettings.columns[0].width; }
538
+ width = ref._tableSettings.columns[colNum].width = parseFloat(toResize.css("width"));
539
+ isClickedSep = false;
540
+ toResize = null;
541
+
542
+ currentTree.trigger("resize_column.jstree-table", [colNum,width]);
543
+ }
544
+ }).mousemove(function (e) {
545
+ if (isClickedSep) {
546
+ newMouseX = e.pageX;
547
+ var diff = newMouseX - oldMouseX,
548
+ oldPrevHeaderInner,
549
+ oldPrevColWidth, newPrevColWidth;
550
+
551
+ if (diff !== 0) {
552
+ oldPrevHeaderInner = toResize.width();
553
+ oldPrevColWidth = parseFloat(toResize.css("width"));
554
+
555
+ // handle a Chrome issue with columns set to auto
556
+ // thanks to Brabus https://github.com/side-by-side
557
+ if (!oldPrevColWidth) {
558
+ oldPrevColWidth = toResize.innerWidth();
559
+ }
560
+
561
+ // make sure that diff cannot be beyond the left/right limits
562
+ diff = diff < 0 ? Math.max(diff,-oldPrevHeaderInner) : diff;
563
+ newPrevColWidth = oldPrevColWidth+diff;
564
+
565
+ // only do this if we are not shrinking past 0 on left - and limit it to that amount
566
+ if ((diff > 0 || oldPrevHeaderInner > 0) && newPrevColWidth > MINCOLWIDTH) {
567
+ toResize.width(newPrevColWidth+"px");
568
+ toResize.css("min-width",newPrevColWidth+"px");
569
+ toResize.css("max-width",newPrevColWidth+"px");
570
+ oldMouseX = newMouseX;
571
+ }
572
+ }
573
+ }
574
+ });
575
+ this.tableWrapper.on("selectstart", ".jstree-table-resizable-separator", function () {
576
+ return false;
577
+ })
578
+ .on("mousedown", ".jstree-table-resizable-separator", function (e) {
579
+ isClickedSep = true;
580
+ oldMouseX = e.pageX;
581
+ toResize = $(this).closest("div.jstree-table-column");
582
+ // the max rightmost position we will allow is the right-most of the wrapper minus a buffer (10)
583
+ return false;
584
+ })
585
+ .on("dblclick", ".jstree-table-resizable-separator", function (e) {
586
+ var col = $(this).closest("div.jstree-table-column");
587
+ _this.autosize_column(col);
588
+ })
589
+ .on("click", ".jstree-table-separator", function (e) {
590
+ // don't sort after resize
591
+ e.stopPropagation();
592
+ });
593
+ }
594
+
595
+ this.tableWrapper.on("click", ".jstree-table-header-cell", function (e) {
596
+ if (!_this.sort) { return; }
597
+
598
+ // get column
599
+ var name = $(this).attr(COL_DATA_ATTR);
600
+ if (!name) { return; }
601
+
602
+ // sort order
603
+ var arrowClass;
604
+ if (gs.sortOrder === name && gs.sortAsc === true) {
605
+ gs.sortAsc = false;
606
+ arrowClass = gs.arrowDownIcon;
607
+ } else {
608
+ gs.sortOrder = name;
609
+ gs.sortAsc = true;
610
+ arrowClass = gs.arrowUpIcon;
611
+ }
612
+
613
+ // add sort arrow
614
+ $(this).closest('.jstree-table-wrapper').find(".jstree-table-sort-icon").remove();
615
+ $("<span></span>").addClass("jstree-table-sort-icon").appendTo($(this)).addClass(arrowClass);
616
+
617
+ // sort by column
618
+ var rootNode = _this.get_node('#');
619
+ _this.sort(rootNode, true);
620
+ _this.redraw_node(rootNode, true);
621
+ });
622
+
623
+ // header context menu
624
+ this.midWrapper.on("contextmenu", ".jstree-table-header-cell", function(e) {
625
+ if (!gs.headerContextMenu) { return; }
626
+ e.preventDefault();
627
+
628
+ var options = {
629
+ "fit":{label:"Size column to fit","action": function (data) {
630
+ var col = $(e.target).closest("div.jstree-table-column");
631
+ _this.autosize_column(col);
632
+ }},
633
+ "fitAll":{"separator_after": true,label:"Size all columns to fit","action": function (data) {
634
+ _this.autosize_all_columns();
635
+ }}
636
+ };
637
+
638
+ // create menu item for every header cell
639
+ var cell, icon, value, label;
640
+ _this.midWrapper.find(".jstree-table-header-cell").each(function() {
641
+ cell = $(this);
642
+ icon = cell.is(":visible") ? gs.checkIcon : false;
643
+ value = cell.attr(COL_DATA_ATTR);
644
+ //get label without sorting arrows
645
+ label = cell.clone().children('.jstree-table-sort-icon').remove().end().text().trim();
646
+
647
+ options[value] = {icon:icon, column:value, label:label, _disabled: (value === 'text'), "action": function (data) {
648
+ var col = _this.midWrapper.find(".jstree-table-header-cell["+COL_DATA_ATTR+"='"+data.item.column+"']").parent();
649
+ col.toggle();
650
+ }};
651
+ });
652
+
653
+ $.vakata.context.show(this,{ 'x' : e.pageX, 'y' : e.pageY },options);
654
+ });
655
+ };
656
+ /*
657
+ * Override redraw_node to correctly insert the table
658
+ */
659
+ this.redraw_node = function(obj, deep, is_callback, force_render) {
660
+ // first allow the parent to redraw the node
661
+ obj = parent.redraw_node.call(this, obj, deep, is_callback, force_render);
662
+ // next prepare the table
663
+ if(obj) {
664
+ this._prepare_table(obj);
665
+ }
666
+ return obj;
667
+ };
668
+ this.refresh = function () {
669
+ this._clean_table();
670
+ return parent.refresh.apply(this,arguments);
671
+ };
672
+ /*
673
+ * Override set_id to update cell attributes
674
+ */
675
+ this.set_id = function (obj, id) {
676
+ var old;
677
+ if(obj) {
678
+ old = obj.id;
679
+ }
680
+ var result = parent.set_id.apply(this,arguments);
681
+ if(result) {
682
+ if (old !== undefined) {
683
+ var table = this.tableWrapper, oldNodes = [old], i;
684
+ // get children
685
+ if (obj && obj.children_d) {
686
+ oldNodes = oldNodes.concat(obj.children_d);
687
+ }
688
+ // update id in children
689
+ for (i=0;i<oldNodes.length;i++) {
690
+ findDataCell(table,oldNodes[i])
691
+ .attr(NODE_DATA_ATTR, obj.id)
692
+ .attr('id', TABLECELLID_PREFIX+obj.id+TABLECELLID_POSTFIX+(i+1))
693
+ .removeClass(TABLECELLID_PREFIX+old+TABLECELLID_POSTFIX)
694
+ .addClass(TABLECELLID_PREFIX+obj.id+TABLECELLID_POSTFIX);
695
+ }
696
+ }
697
+ }
698
+ return result;
699
+ };
700
+ this._hide_table = function (node) {
701
+ var children = node && node.children_d ? node.children_d : [], i;
702
+ // go through each column, remove all children with the correct ID name
703
+ for (i=0;i<children.length;i++) {
704
+ findDataCell(this.tableWrapper,children[i]).remove();
705
+ }
706
+ };
707
+ this.holdingCells = {};
708
+ this.getHoldingCells = function (obj,col,hc) {
709
+ var ret = [];
710
+ this._getHoldingCells(obj,col,hc,ret);
711
+ return($(ret));
712
+ };
713
+ this._getHoldingCells = function (obj,col,hc,ret) {
714
+ var children = obj.children||[], child, i;
715
+ // run through each child, render it, and then render its children recursively
716
+ for (i=0;i<children.length;i++) {
717
+ child = TABLECELLID_PREFIX+escapeId(children[i])+TABLECELLID_POSTFIX+col;
718
+ if (hc[child] && obj.state.opened) {
719
+ ret.push(hc[child][0]);
720
+ this._getHoldingCells(this.get_node(children[i]),col,hc,ret);
721
+ //delete hc[child];
722
+ }
723
+ }
724
+ };
725
+ /**
726
+ * put a table cell in edit mode (input field to edit the data)
727
+ * @name edit(obj, col)
728
+ * @param {mixed} obj
729
+ * @param {obj} col definition
730
+ * @param {element} cell element, either span or wrapping div
731
+ */
732
+ this._edit = function (obj, col, element) {
733
+ if(!obj) { return false; }
734
+ if (element) {
735
+ element = $(element);
736
+ if (element.prop("tagName").toLowerCase() === "div") {
737
+ element = element.children("span:first");
738
+ }
739
+ } else {
740
+ // need to find the element - later
741
+ return false;
742
+ }
743
+ var rtl = this._data.core.rtl,
744
+ w = this.element.width(),
745
+ t = obj.data[col.value],
746
+ h1 = $("<"+"div />", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo("body"),
747
+ h2 = $("<"+"input />", {
748
+ "value" : t,
749
+ "class" : "jstree-rename-input",
750
+ "css" : {
751
+ "padding" : "0",
752
+ "border" : "1px solid silver",
753
+ "box-sizing" : "border-box",
754
+ "display" : "inline-block",
755
+ "height" : (this._data.core.li_height) + "px",
756
+ "lineHeight" : (this._data.core.li_height) + "px",
757
+ "width" : "150px" // will be set a bit further down
758
+ },
759
+ "blur" : $.proxy(function () {
760
+ var v = h2.val();
761
+ // save the value if changed
762
+ if(v === "" || v === t) {
763
+ v = t;
764
+ } else {
765
+ obj.data[col.value] = v;
766
+ this.element.trigger('update_cell.jstree-table',{node:obj, col:col.value, value:v, old:t});
767
+ this._prepare_table(this.get_node(obj,true));
768
+ }
769
+ h2.remove();
770
+ element.show();
771
+ }, this),
772
+ "keydown" : function (event) {
773
+ var key = event.which;
774
+ if(key === 27) {
775
+ this.value = t;
776
+ }
777
+ if(key === 27 || key === 13 || key === 37 || key === 38 || key === 39 || key === 40 || key === 32) {
778
+ event.stopImmediatePropagation();
779
+ }
780
+ if(key === 27 || key === 13) {
781
+ event.preventDefault();
782
+ this.blur();
783
+ }
784
+ },
785
+ "click" : function (e) { e.stopImmediatePropagation(); },
786
+ "mousedown" : function (e) { e.stopImmediatePropagation(); },
787
+ "keyup" : function (event) {
788
+ h2.width(Math.min(h1.text("pW" + this.value).width(),w));
789
+ },
790
+ "keypress" : function(event) {
791
+ if(event.which === 13) { return false; }
792
+ }
793
+ }),
794
+ fn = {
795
+ fontFamily : element.css('fontFamily') || '',
796
+ fontSize : element.css('fontSize') || '',
797
+ fontWeight : element.css('fontWeight') || '',
798
+ fontStyle : element.css('fontStyle') || '',
799
+ fontStretch : element.css('fontStretch') || '',
800
+ fontVariant : element.css('fontVariant') || '',
801
+ letterSpacing : element.css('letterSpacing') || '',
802
+ wordSpacing : element.css('wordSpacing') || ''
803
+ };
804
+ element.hide();
805
+ element.parent().append(h2);
806
+ h2.css(fn).width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select();
807
+ };
808
+
809
+ this.autosize_column = function (col) {
810
+ // don't resize hidden columns
811
+ if (col.is(":hidden")) { return; }
812
+
813
+ var oldPrevColWidth = parseFloat(col.css("width")), newWidth = 0, diff,
814
+ colNum = col.prevAll(".jstree-table-column").length,
815
+ oldPrevHeaderInner = col.width(), newPrevColWidth;
816
+
817
+ //find largest width
818
+ col.find(".jstree-table-cell").each(function() {
819
+ var item = $(this), width;
820
+ item.css("position", "absolute");
821
+ item.css("width", "auto");
822
+ width = item.outerWidth();
823
+ item.css("position", "relative");
824
+
825
+ if (width>newWidth) {
826
+ newWidth = width;
827
+ }
828
+ });
829
+
830
+ diff = newWidth-oldPrevColWidth;
831
+
832
+ // make sure that diff cannot be beyond the left limits
833
+ diff = diff < 0 ? Math.max(diff,-oldPrevHeaderInner) : diff;
834
+ newPrevColWidth = (oldPrevColWidth+diff)+"px";
835
+
836
+ col.width(newPrevColWidth);
837
+ col.css("min-width",newPrevColWidth);
838
+ col.css("max-width",newPrevColWidth);
839
+
840
+ $(this).closest(".jstree-table-wrapper").find(".jstree").trigger("resize_column.jstree-table",[colNum,newPrevColWidth]);
841
+ };
842
+
843
+ this.autosize_all_columns = function () {
844
+ this.tableWrapper.find(".jstree-table-column").each(function() {
845
+ _this.autosize_column($(this));
846
+ });
847
+ };
848
+
849
+ this._prepare_table = function (obj) {
850
+ var gs = this._tableSettings, c = gs.treeClass, _this = this, t, cols = gs.columns || [], width, tr = gs.isThemeroller,
851
+ tree = this.element, rootid = this.rootid,
852
+ classAdd = (tr?"themeroller":"regular"), img, objData = this.get_node(obj),
853
+ defaultWidth = gs.columnWidth, conf = gs.defaultConf, cellClickHandler = function (tree,node,val,col,t) {
854
+ return function(e) {
855
+ //node = tree.find("#"+node.attr("id"));
856
+ node.children(".jstree-anchor").trigger("click.jstree",e);
857
+ tree.trigger("select_cell.jstree-table", [{value: val,column: col.header,node: node,table:$(this),sourceName: col.value}]);
858
+ };
859
+ }, cellRightClickHandler = function (tree,node,val,col,t) {
860
+ return function (e) {
861
+ if (gs.context) {
862
+ e.preventDefault();
863
+ $.vakata.context.show(this,{ 'x' : e.pageX, 'y' : e.pageY },{
864
+ "edit":{label:"Edit","action": function (data) {
865
+ var obj = t.get_node(node);
866
+ _this._edit(obj,col,e.target);
867
+ }}
868
+ });
869
+ }
870
+ };
871
+ },
872
+ hoverInHandler = function (node, jsTreeInstance) {
873
+ return function() { jsTreeInstance.hover_node(node); };
874
+ },
875
+ hoverOutHandler = function (node, jsTreeInstance) {
876
+ return function() { jsTreeInstance.dehover_node(node); };
877
+ },
878
+ i, val, cl, wcl, ccl, a, last, valClass, wideValClass, span, paddingleft, title, tableCellName, tableCellParentId, tableCellParent,
879
+ tableCellPrev, tableCellPrevId, tableCellNext, tableCellNextId, tableCellChild, tableCellChildId,
880
+ col, content, tmpWidth, mw = this.midWrapper, dataCell, dataCellNb, lid = objData.id,
881
+ peers = this.get_node(objData.parent).children,
882
+ // find my position in the list of peers. "peers" is the list of everyone at my level under my parent, in order
883
+ pos = $.inArray(lid,peers),
884
+ hc = this.holdingCells, rendered = false, closed;
885
+ // get our column definition
886
+ t = $(obj);
887
+
888
+ // find the a children
889
+ a = t.children("a");
890
+
891
+ if (a.length === 1) {
892
+ closed = !objData.state.opened;
893
+ tableCellName = TABLECELLID_PREFIX+escapeId(lid)+TABLECELLID_POSTFIX;
894
+ tableCellParentId = objData.parent === "#" ? null : objData.parent;
895
+ a.addClass(c);
896
+ //renderAWidth(a,_this);
897
+ renderATitle(a,t,_this);
898
+ last = a;
899
+ // find which column our tree shuld go in
900
+ var s = this.settings.table;
901
+ var treecol = 0;
902
+ for (i=0;i<s.columns.length;i++) {
903
+ if (s.columns[i].tree) {
904
+ // save which column it was
905
+ treecol = i;
906
+ // do not check any others
907
+ break;
908
+ }
909
+ }
910
+ for (i=0;i<cols.length;i++) {
911
+ if (treecol === i) {
912
+ continue;
913
+ }
914
+ col = cols[i];
915
+ dataCell = mw.children("div:eq("+i+")");
916
+ dataCellNb = i;
917
+ // get the cellClass, the wideCellClass, and the columnClass
918
+ cl = col.cellClass || "";
919
+ wcl = col.wideCellClass || "";
920
+ ccl = col.columnClass || "";
921
+
922
+ // add a column class to the dataCell
923
+ dataCell.addClass(ccl);
924
+
925
+ // get the contents of the cell
926
+ val = "";
927
+ if (objData.data && objData.data[col.value] !== undefined) {
928
+ val = objData.data[col.value];
929
+ }
930
+
931
+ if (typeof(col.format) === "function") {
932
+ val = col.format(val);
933
+ }
934
+
935
+ // put images instead of text if needed
936
+ if (col.images) {
937
+ img = col.images[val] || col.images["default"];
938
+ if (img) {content = img[0] === "*" ? '<span class="'+img.substr(1)+'"></span>' : '<img src="'+img+'">';}
939
+ } else { content = val; }
940
+
941
+ // content cannot be blank, or it messes up heights
942
+ if (content === undefined || content === null || BLANKRE.test(content)) {
943
+ content = "&nbsp;";
944
+ }
945
+
946
+ // get the valueClass
947
+ valClass = col.valueClass && objData.data !== null && objData.data !== undefined ? objData.data[col.valueClass] || "" : "";
948
+ if (valClass && col.valueClassPrefix && col.valueClassPrefix !== "") {
949
+ valClass = col.valueClassPrefix + valClass;
950
+ }
951
+ // get the wideValueClass
952
+ wideValClass = col.wideValueClass && objData.data !== null && objData.data !== undefined ? objData.data[col.wideValueClass] || "" : "";
953
+ if (wideValClass && col.wideValueClassPrefix && col.wideValueClassPrefix !== "") {
954
+ wideValClass = col.wideValueClassPrefix + wideValClass;
955
+ }
956
+ // get the title
957
+ title = col.title && objData.data !== null && objData.data !== undefined ? objData.data[col.title] || "" : "";
958
+ // strip out HTML
959
+ if (typeof title === 'string') {
960
+ title = title.replace(htmlstripre, '');
961
+ }
962
+
963
+ // get the width
964
+ paddingleft = 7;
965
+ width = col.width || defaultWidth;
966
+ if (width !== 'auto') {
967
+ width = tmpWidth || (width - paddingleft);
968
+ }
969
+
970
+ last = findDataCellFast(dataCellNb, lid);
971
+ if (!last || last.length < 1) {
972
+ last = $("<div></div>");
973
+ $("<span></span>").appendTo(last);
974
+ last.attr("id",tableCellName+i);
975
+ last.addClass(tableCellName);
976
+ last.attr(NODE_DATA_ATTR,lid);
977
+
978
+ }
979
+ // we need to put it in the dataCell - after the parent, but the position matters
980
+ // if we have no parent, then we are one of the root nodes, but still need to look at peers
981
+
982
+
983
+ // if we are first, i.e. pos === 0, we go right after the parent;
984
+ // if we are not first, and our previous peer (one before us) is closed, we go right after the previous peer cell
985
+ // if we are not first, and our previous peer is opened, then we have to find its youngest & lowest closed child (incl. leaf)
986
+ //
987
+ // probably be much easier to go *before* our next one
988
+ // but that one might not be drawn yet
989
+ // here is the logic for jstree drawing:
990
+ // it draws peers from first to last or from last to first
991
+ // it draws children before a parent
992
+ //
993
+ // so I can rely on my *parent* not being drawn, but I cannot rely on my previous peer or my next peer being drawn
994
+
995
+ // so we do the following:
996
+ // 1- We are the first child: install after the parent
997
+ // 2- Our previous peer is already drawn: install after the previous peer
998
+ // 3- Our previous peer is not drawn, we have a child that is drawn: install right before our first child
999
+ // 4- Our previous peer is not drawn, we have no child that is drawn, our next peer is drawn: install right before our next peer
1000
+ // 5- Our previous peer is not drawn, we have no child that is drawn, our next peer is not drawn: install right after parent
1001
+ tableCellPrevId = pos <=0 ? objData.parent : findLastClosedNode(this,peers[pos-1]);
1002
+ tableCellPrev = findDataCellFast(dataCellNb,tableCellPrevId);
1003
+ tableCellNextId = pos >= peers.length-1 ? "NULL" : peers[pos+1];
1004
+ tableCellNext = findDataCellFast(dataCellNb,tableCellNextId);
1005
+ tableCellChildId = objData.children && objData.children.length > 0 ? objData.children[0] : "NULL";
1006
+ tableCellChild = findDataCellFast(dataCellNb,tableCellChildId);
1007
+ tableCellParent = findDataCellFast(dataCellNb,tableCellParentId);
1008
+
1009
+ // if our parent is already drawn, then we put this in the right order under our parent
1010
+ if (tableCellParentId) {
1011
+ if (tableCellParent && tableCellParent.length > 0) {
1012
+ if (tableCellPrev && tableCellPrev.length > 0) {
1013
+ last.insertAfter(tableCellPrev);
1014
+ } else if (tableCellChild && tableCellChild.length > 0) {
1015
+ last.insertBefore(tableCellChild);
1016
+ } else if (tableCellNext && tableCellNext.length > 0) {
1017
+ last.insertBefore(tableCellNext);
1018
+ } else {
1019
+ last.insertAfter(tableCellParent);
1020
+ }
1021
+ rendered = true;
1022
+ } else {
1023
+ rendered = false;
1024
+ }
1025
+ // always put it in the holding cells, and then sort when the parent comes in, in case parent is (re)drawn later
1026
+ hc[tableCellName+i] = last;
1027
+ } else {
1028
+ if (tableCellPrev && tableCellPrev.length > 0) {
1029
+ last.insertAfter(tableCellPrev);
1030
+ } else if (tableCellChild && tableCellChild.length > 0) {
1031
+ last.insertBefore(tableCellChild);
1032
+ } else if (tableCellNext && tableCellNext.length > 0) {
1033
+ last.insertBefore(tableCellNext);
1034
+ } else {
1035
+ last.appendTo(dataCell);
1036
+ }
1037
+ rendered = true;
1038
+ }
1039
+ // do we have any children waiting for this cell? walk down through the children/grandchildren/etc tree
1040
+ if (rendered) {
1041
+ last.after(this.getHoldingCells(objData,i,hc));
1042
+ }
1043
+ // need to make the height of this match the line height of the tree. How?
1044
+ span = last.children("span");
1045
+
1046
+ // create a span inside the div, so we can control what happens in the whole div versus inside just the text/background
1047
+ span.addClass(cl+" "+valClass).html(content);
1048
+ last = last.css(conf).addClass("jstree-table-cell jstree-table-cell-regular jstree-table-cell-root-"+rootid+" jstree-table-cell-"+classAdd+" "+wcl+ " " + wideValClass + (tr?" ui-state-default":"")).addClass("jstree-table-col-"+i);
1049
+ // add click handler for clicking inside a table cell
1050
+ last.click(cellClickHandler(tree,t,val,col,this));
1051
+ last.on("contextmenu",cellRightClickHandler(tree,t,val,col,this));
1052
+ last.hover(hoverInHandler(t, this), hoverOutHandler(t, this));
1053
+
1054
+ if (title) {
1055
+ span.attr("title",title);
1056
+ }
1057
+ }
1058
+ last.addClass("jstree-table-cell-last"+(tr?" ui-state-default":""));
1059
+ // if there is no width given for the last column, do it via automatic
1060
+ if (cols[cols.length-1].width === undefined) {
1061
+ last.addClass("jstree-table-width-auto").next(".jstree-table-separator").remove();
1062
+ }
1063
+ }
1064
+ this.element.css({'overflow-y':'auto !important'});
1065
+ };
1066
+ // clean up holding cells
1067
+ this.holdingCells = {};
1068
+ };
1069
+ }));