browse-everything 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9580ccdb2b53c75f59eb7002892d3a65c26438a407d19b383825989b43eca287
4
- data.tar.gz: 8ee75aa2fa5f43768f0019456eb9eb49ab90e3ec6fc1a38008c476e47d9506d1
3
+ metadata.gz: 315a6af2831fb8ad4c8222c17cde9fc5e0a0ee257164291adb89d6074ca39cbc
4
+ data.tar.gz: e63c1cac7fcd694138091e637393558610f2d365f90629a08266a714cfc8f901
5
5
  SHA512:
6
- metadata.gz: c524b3167dd198a71e119b7b30d759f935e72f8fc5e894dca5af6dd5120b93cff436c1671ad589a53b8f3753c7d3b59b6cad2d16a82b3fe305b9a50e6d2f057e
7
- data.tar.gz: 600342a8f49b0ac444a0bd8fc5eea6da81f065d9c5cd7ec41999ba7bb671e95229750278618ed94235759c5e255f8126fe9704864f67f8a22a575dc059edbae7
6
+ metadata.gz: 4c0de73d92cd5e0b2098448d1d3b875321633a20f8b60858f86deabda8f1ea7dee179db574c626c47baf8844906814152fa04fc7273f2a2a2aaf58dd1f3430de
7
+ data.tar.gz: a791a8cdb21c903daa246c33eff6eb92a9980ec2e1701f5a659adbc185939144f9d86ebb4dfdc4b74a7e1e7a9d005701ba769964bc48edf50373a371fb595f32
@@ -12,7 +12,7 @@ jobs:
12
12
  type: string
13
13
  bundler_version:
14
14
  type: string
15
- default: 2.0.1
15
+ default: 2.1.4
16
16
  executor:
17
17
  name: 'samvera/ruby'
18
18
  ruby_version: << parameters.ruby_version >>
@@ -27,7 +27,7 @@ jobs:
27
27
  project: 'browse-everything'
28
28
 
29
29
  - samvera/engine_cart_generate:
30
- cache_key: v1-internal-test-app-{{ checksum "browse-everything.gemspec" }}-{{ checksum "spec/test_app_templates/lib/generators/test_app_generator.rb" }}-{{ checksum "lib/generators/browse_everything/install_generator.rb" }}-{{ checksum "lib/generators/browse_everything/config_generator.rb" }}--<< parameters.rails_version >>-<< parameters.ruby_version >>
30
+ cache_key: v1-internal-test-app-{{ checksum "browse-everything.gemspec" }}-{{ checksum "Gemfile" }}-{{ checksum "spec/test_app_templates/lib/generators/test_app_generator.rb" }}-{{ checksum "lib/generators/browse_everything/install_generator.rb" }}-{{ checksum "lib/generators/browse_everything/config_generator.rb" }}--<< parameters.rails_version >>-<< parameters.ruby_version >>
31
31
 
32
32
  - samvera/bundle_for_gem:
33
33
  ruby_version: << parameters.ruby_version >>
@@ -45,27 +45,49 @@ jobs:
45
45
  workflows:
46
46
  ci:
47
47
  jobs:
48
+ - build:
49
+ name: "ruby2-7_rails6-0"
50
+ ruby_version: 2.7.1
51
+ rails_version: 6.0.3.1
52
+ - build:
53
+ name: "ruby2-6_rails6-0"
54
+ ruby_version: 2.6.6
55
+ rails_version: 6.0.3.1
56
+ - build:
57
+ name: "ruby2-5_rails6-0"
58
+ ruby_version: 2.5.8
59
+ rails_version: 6.0.3.1
60
+
61
+ - build:
62
+ name: "ruby2-7_rails5-2"
63
+ ruby_version: 2.7.1
64
+ rails_version: 5.2.4.3
48
65
  - build:
49
66
  name: "ruby2-6_rails5-2"
50
- ruby_version: 2.6.3
51
- rails_version: 5.2.3
67
+ ruby_version: 2.6.6
68
+ rails_version: 5.2.4.3
52
69
  - build:
53
- name: "ruby2-6_rails5-1"
54
- ruby_version: 2.6.3
70
+ name: "ruby2-5_rails5-2"
71
+ ruby_version: 2.5.8
72
+ rails_version: 5.2.4.3
73
+ - build:
74
+ name: "ruby2-4_rails5-2"
75
+ ruby_version: 2.4.10
76
+ rails_version: 5.2.4.3
77
+
78
+ - build:
79
+ name: "ruby2-7_rails5-1"
80
+ ruby_version: 2.7.1
55
81
  rails_version: 5.1.7
56
82
  - build:
57
- name: "ruby2-5_rails5-2"
58
- ruby_version: 2.5.5
59
- rails_version: 5.2.3
83
+ name: "ruby2-6_rails5-1"
84
+ ruby_version: 2.6.6
85
+ rails_version: 5.1.7
60
86
  - build:
61
87
  name: "ruby2-5_rails5-1"
62
- ruby_version: 2.5.5
88
+ ruby_version: 2.5.8
63
89
  rails_version: 5.1.7
64
- - build:
65
- name: "ruby2-4_rails5-2"
66
- ruby_version: 2.4.6
67
- rails_version: 5.2.3
68
90
  - build:
69
91
  name: "ruby2-4_rails5-1"
70
- ruby_version: 2.4.6
92
+ ruby_version: 2.4.10
71
93
  rails_version: 5.1.7
@@ -3,71 +3,79 @@ inherit_gem:
3
3
  bixby: bixby_default.yml
4
4
 
5
5
  AllCops:
6
- TargetRubyVersion: 2.3
6
+ TargetRubyVersion: 2.6
7
7
  DisplayCopNames: true
8
8
  Exclude:
9
9
  - 'vendor/**/*'
10
10
 
11
- Rails:
12
- Enabled: true
13
- Rails/FilePath:
11
+ Bundler/DuplicatedGem:
14
12
  Exclude:
15
- - 'lib/generators/browse_everything/config_generator.rb'
13
+ - 'Gemfile'
16
14
 
17
- Metrics/ClassLength:
18
- Max: 130
19
- Exclude:
20
- - 'lib/browse_everything/driver/google_drive.rb'
21
- Metrics/LineLength:
15
+ Layout/LineLength:
22
16
  Max: 400
23
17
  Exclude:
24
18
  - 'spec/lib/browse_everything/driver/box_spec.rb'
25
19
  - 'spec/lib/browse_everything/driver/dropbox_spec.rb'
20
+
26
21
  Metrics/BlockLength:
27
22
  Exclude:
28
23
  - '*.gemspec'
29
24
  - 'spec/**/*'
30
25
 
31
- RSpec/NestedGroups:
32
- Enabled: false
26
+ Metrics/ClassLength:
27
+ Max: 130
28
+ Exclude:
29
+ - 'lib/browse_everything/driver/google_drive.rb'
30
+
31
+ Metrics/MethodLength:
32
+ Exclude:
33
+ - 'spec/test_app_templates/lib/generators/test_app_generator.rb'
34
+
35
+ Naming/FileName:
36
+ Exclude:
37
+ - 'browse-everything.gemspec'
38
+ - 'Gemfile'
39
+ - 'lib/browse-everything.rb'
40
+
41
+ Rails:
42
+ Enabled: true
43
+
44
+ Rails/FilePath:
45
+ Exclude:
46
+ - 'lib/generators/browse_everything/config_generator.rb'
33
47
 
34
48
  RSpec/DescribeClass:
35
49
  Exclude:
36
50
  - 'spec/javascripts/**/*'
37
-
38
- RSpec/LeadingSubject:
39
- Enabled: false
40
51
 
41
52
  RSpec/ExampleLength:
42
53
  Enabled: false
43
54
 
44
- RSpec/MultipleExpectations:
55
+ RSpec/LeadingSubject:
45
56
  Enabled: false
46
57
 
47
- Style/NumericLiterals:
48
- MinDigits: 7
49
-
50
- Layout/IndentationConsistency:
51
- EnforcedStyle: rails
58
+ RSpec/MultipleExpectations:
59
+ Enabled: false
52
60
 
53
- Naming/FileName:
54
- Exclude:
55
- - 'browse-everything.gemspec'
56
- - 'Gemfile'
57
- - 'lib/browse-everything.rb'
61
+ RSpec/NestedGroups:
62
+ Enabled: false
58
63
 
59
64
  Style/MixinUsage:
60
65
  Exclude:
61
- - 'spec/lib/browse_everything/driver/s3_spec.rb'
62
- - 'spec/lib/browse_everything/driver/google_drive_spec.rb'
63
- - 'spec/lib/browse_everything/driver/file_system_spec.rb'
64
- - 'spec/lib/browse_everything/driver/dropbox_spec.rb'
65
- - 'spec/lib/browse_everything/driver/box_spec.rb'
66
- - 'spec/lib/browse_everything/driver/base_spec.rb'
66
+ - 'spec/helper/browse_everything_controller_helper_spec.rb'
67
67
  - 'spec/lib/browse_everything/browser_spec.rb'
68
+ - 'spec/lib/browse_everything/driver/base_spec.rb'
69
+ - 'spec/lib/browse_everything/driver/box_spec.rb'
70
+ - 'spec/lib/browse_everything/driver/dropbox_spec.rb'
71
+ - 'spec/lib/browse_everything/driver/file_system_spec.rb'
72
+ - 'spec/lib/browse_everything/driver/google_drive_spec.rb'
73
+ - 'spec/lib/browse_everything/driver/s3_spec.rb'
68
74
  - 'spec/services/browser_factory_spec.rb'
69
- - 'spec/helper/browse_everything_controller_helper_spec.rb'
70
75
 
71
- Bundler/DuplicatedGem:
76
+ Style/NumericLiterals:
77
+ MinDigits: 7
78
+
79
+ Style/RedundantBegin:
72
80
  Exclude:
73
- - 'Gemfile'
81
+ - 'lib/browse_everything/browser.rb'
data/Gemfile CHANGED
@@ -34,14 +34,11 @@ else
34
34
  end
35
35
 
36
36
  case ENV['RAILS_VERSION']
37
+ when /^6\./
38
+ gem 'puma', '~> 4.1'
37
39
  when /^5\./
38
40
  gem 'capybara', '~> 2.18.0'
39
- when /^4\.2/
40
- gem 'coffee-rails', '~> 4.1.0'
41
- gem 'json', '~> 1.8'
42
- gem 'railties', '~> 4.2'
43
- gem 'responders', '~> 2.0'
44
- gem 'sass-rails', '>= 5.0'
41
+ gem 'puma', '~> 3.11'
45
42
  end
46
43
  end
47
44
  # END ENGINE_CART BLOCK
data/README.md CHANGED
@@ -45,6 +45,7 @@ Currently, the following releases of Ruby are supported:
45
45
 
46
46
  ## Supported Rails Releases
47
47
  The supported Rail releases follow those specified by [the security policy of the Rails Community](https://rubyonrails.org/security/). As is the case with the supported Ruby releases, it is recommended that one upgrades from any Rails release no longer receiving security updates.
48
+ - 6.0.3
48
49
  - 5.2.3
49
50
  - 5.1.7
50
51
 
@@ -262,21 +262,29 @@ $(function () {
262
262
 
263
263
  $.fn.browseEverything = function (options) {
264
264
  var ctx = $(this).data('ev-state');
265
+
266
+ // Try and load the options from the HTML data attributes
265
267
  if (ctx == null && options == null) {
266
268
  options = $(this).data();
267
269
  }
270
+
268
271
  if (options != null) {
269
272
  ctx = initialize(this[0], options);
270
- $(this).click(function () {
271
- dialog.data('ev-state', ctx);
272
- return dialog.load(ctx.opts.route, function () {
273
- setTimeout(refreshFiles, 500);
274
- ctx.callbacks.show.fire();
275
- return dialog.modal('show');
276
- });
277
- });
278
273
  }
279
274
 
275
+ $(this).click(function () {
276
+ dialog.data('ev-state', ctx);
277
+ return dialog.load(ctx.opts.route, function () {
278
+ setTimeout(refreshFiles, 50);
279
+ ctx.callbacks.show.fire();
280
+ dialog.removeClass('fade')
281
+ .removeClass('in')
282
+ .addClass('show');
283
+
284
+ return dialog.modal('show');
285
+ });
286
+ });
287
+
280
288
  if (ctx) {
281
289
  return ctx.callback_proxy;
282
290
  } else {
@@ -0,0 +1,687 @@
1
+ /*
2
+ * jQuery treetable Plugin 3.2.0
3
+ * http://ludo.cubicphuse.nl/jquery-treetable
4
+ *
5
+ * Copyright 2013, Ludo van den Boom
6
+ * Dual licensed under the MIT or GPL Version 2 licenses.
7
+ */
8
+
9
+ /**
10
+ * Callback defining the Node Class
11
+ */
12
+ var defineNode = function() {
13
+
14
+ function Node(row, tree, settings) {
15
+ var parentId;
16
+
17
+ this.row = row;
18
+ this.tree = tree;
19
+ this.settings = settings;
20
+
21
+ // TODO Ensure id/parentId is always a string (not int)
22
+ this.id = this.row.data(this.settings.nodeIdAttr);
23
+
24
+ // TODO Move this to a setParentId function?
25
+ parentId = this.row.data(this.settings.parentIdAttr);
26
+ if (parentId != null && parentId !== "") {
27
+ this.parentId = parentId;
28
+ }
29
+
30
+ this.treeCell = jQuery(this.row.children(this.settings.columnElType)[this.settings.column]);
31
+ this.expander = jQuery(this.settings.expanderTemplate);
32
+ this.indenter = jQuery(this.settings.indenterTemplate);
33
+ this.children = [];
34
+ this.initialized = false;
35
+ this.treeCell.prepend(this.indenter);
36
+ }
37
+
38
+ Node.prototype.addChild = function(child) {
39
+ return this.children.push(child);
40
+ };
41
+
42
+ Node.prototype.ancestors = function() {
43
+ var ancestors, node;
44
+ node = this;
45
+ ancestors = [];
46
+ while (node = node.parentNode()) {
47
+ ancestors.push(node);
48
+ }
49
+ return ancestors;
50
+ };
51
+
52
+ Node.prototype.collapse = function() {
53
+ if (this.collapsed()) {
54
+ return this;
55
+ }
56
+
57
+ this.row.removeClass("expanded").addClass("collapsed");
58
+
59
+ this._hideChildren();
60
+ this.expander.attr("title", this.settings.stringExpand);
61
+
62
+ if (this.initialized && this.settings.onNodeCollapse != null) {
63
+ this.settings.onNodeCollapse.apply(this);
64
+ }
65
+
66
+ return this;
67
+ };
68
+
69
+ Node.prototype.collapsed = function() {
70
+ return this.row.hasClass("collapsed");
71
+ };
72
+
73
+ // TODO destroy: remove event handlers, expander, indenter, etc.
74
+
75
+ Node.prototype.expand = function() {
76
+ if (this.expanded()) {
77
+ return this;
78
+ }
79
+
80
+ this.row.removeClass("collapsed").addClass("expanded");
81
+
82
+ if (this.initialized && this.settings.onNodeExpand != null) {
83
+ this.settings.onNodeExpand.apply(this);
84
+ }
85
+
86
+ if (jQuery(this.row).is(":visible")) {
87
+ this._showChildren();
88
+ }
89
+
90
+ this.expander.attr("title", this.settings.stringCollapse);
91
+
92
+ return this;
93
+ };
94
+
95
+ Node.prototype.expanded = function() {
96
+ return this.row.hasClass("expanded");
97
+ };
98
+
99
+ Node.prototype.hide = function() {
100
+ this._hideChildren();
101
+ this.row.hide();
102
+ return this;
103
+ };
104
+
105
+ Node.prototype.isBranchNode = function() {
106
+ if(this.children.length > 0 || this.row.data(this.settings.branchAttr) === true) {
107
+ return true;
108
+ } else {
109
+ return false;
110
+ }
111
+ };
112
+
113
+ Node.prototype.updateBranchLeafClass = function(){
114
+ this.row.removeClass('branch');
115
+ this.row.removeClass('leaf');
116
+ this.row.addClass(this.isBranchNode() ? 'branch' : 'leaf');
117
+ };
118
+
119
+ Node.prototype.level = function() {
120
+ return this.ancestors().length;
121
+ };
122
+
123
+ Node.prototype.parentNode = function() {
124
+ if (this.parentId != null) {
125
+ return this.tree[this.parentId];
126
+ } else {
127
+ return null;
128
+ }
129
+ };
130
+
131
+ Node.prototype.removeChild = function(child) {
132
+ var i = jQuery.inArray(child, this.children);
133
+ return this.children.splice(i, 1)
134
+ };
135
+
136
+ Node.prototype.render = function() {
137
+ var handler,
138
+ settings = this.settings,
139
+ target;
140
+
141
+ if (settings.expandable === true && this.isBranchNode()) {
142
+ handler = function(e) {
143
+ jQuery(this).parents("table").treetable("node", jQuery(this).parents("tr").data(settings.nodeIdAttr)).toggle();
144
+ return e.preventDefault();
145
+ };
146
+
147
+ this.indenter.html(this.expander);
148
+ target = settings.clickableNodeNames === true ? this.treeCell : this.expander;
149
+
150
+ target.off("click.treetable").on("click.treetable", handler);
151
+ target.off("keydown.treetable").on("keydown.treetable", function(e) {
152
+ if (e.keyCode == 13) {
153
+ handler.apply(this, [e]);
154
+ }
155
+ });
156
+ }
157
+
158
+ this.indenter[0].style.paddingLeft = "" + (this.level() * settings.indent) + "px";
159
+
160
+ return this;
161
+ };
162
+
163
+ Node.prototype.reveal = function() {
164
+ if (this.parentId != null) {
165
+ this.parentNode().reveal();
166
+ }
167
+ return this.expand();
168
+ };
169
+
170
+ Node.prototype.setParent = function(node) {
171
+ if (this.parentId != null) {
172
+ this.tree[this.parentId].removeChild(this);
173
+ }
174
+ this.parentId = node.id;
175
+ this.row.data(this.settings.parentIdAttr, node.id);
176
+ return node.addChild(this);
177
+ };
178
+
179
+ Node.prototype.show = function() {
180
+ if (!this.initialized) {
181
+ this._initialize();
182
+ }
183
+ this.row.show();
184
+ if (this.expanded()) {
185
+ this._showChildren();
186
+ }
187
+ return this;
188
+ };
189
+
190
+ Node.prototype.toggle = function() {
191
+ if (this.expanded()) {
192
+ this.collapse();
193
+ } else {
194
+ this.expand();
195
+ }
196
+ return this;
197
+ };
198
+
199
+ Node.prototype._hideChildren = function() {
200
+ var child, _i, _len, _ref, _results;
201
+ _ref = this.children;
202
+ _results = [];
203
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
204
+ child = _ref[_i];
205
+ _results.push(child.hide());
206
+ }
207
+ return _results;
208
+ };
209
+
210
+ Node.prototype._initialize = function() {
211
+ var settings = this.settings;
212
+
213
+ this.render();
214
+
215
+ if (settings.expandable === true && settings.initialState === "collapsed") {
216
+ this.collapse();
217
+ } else {
218
+ this.expand();
219
+ }
220
+
221
+ if (settings.onNodeInitialized != null) {
222
+ settings.onNodeInitialized.apply(this);
223
+ }
224
+
225
+ return this.initialized = true;
226
+ };
227
+
228
+ Node.prototype._showChildren = function() {
229
+ var child, _i, _len, _ref, _results;
230
+ _ref = this.children;
231
+ _results = [];
232
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
233
+ child = _ref[_i];
234
+ _results.push(child.show());
235
+ }
236
+ return _results;
237
+ };
238
+
239
+ return Node;
240
+ }
241
+
242
+ var Node = defineNode()
243
+
244
+ /**
245
+ * Callback defining the Tree Class
246
+ */
247
+ var defineTree = function() {
248
+ /**
249
+ * Class modeling trees of nodes
250
+ */
251
+
252
+ function Tree(table, settings) {
253
+ this.table = table;
254
+ this.settings = settings;
255
+ this.tree = {};
256
+
257
+ // Cache the nodes and roots in simple arrays for quick access/iteration
258
+ this.nodes = [];
259
+ this.roots = [];
260
+ }
261
+
262
+ Tree.prototype.collapseAll = function() {
263
+ var node, _i, _len, _ref, _results;
264
+ _ref = this.nodes;
265
+ _results = [];
266
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
267
+ node = _ref[_i];
268
+ _results.push(node.collapse());
269
+ }
270
+ return _results;
271
+ };
272
+
273
+ Tree.prototype.expandAll = function() {
274
+ var node, _i, _len, _ref, _results;
275
+ _ref = this.nodes;
276
+ _results = [];
277
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
278
+ node = _ref[_i];
279
+ _results.push(node.expand());
280
+ }
281
+ return _results;
282
+ };
283
+
284
+ Tree.prototype.findLastNode = function (node) {
285
+ if (node.children.length > 0) {
286
+ return this.findLastNode(node.children[node.children.length - 1]);
287
+ } else {
288
+ return node;
289
+ }
290
+ };
291
+
292
+ Tree.prototype.loadRows = function(rows) {
293
+ var node, row, i;
294
+
295
+ if (rows != null) {
296
+ for (i = 0; i < rows.length; i++) {
297
+ row = jQuery(rows[i]);
298
+
299
+ if (row.data(this.settings.nodeIdAttr) != null) {
300
+ node = new Node(row, this.tree, this.settings);
301
+ this.nodes.push(node);
302
+ this.tree[node.id] = node;
303
+
304
+ if (node.parentId != null && this.tree[node.parentId]) {
305
+ this.tree[node.parentId].addChild(node);
306
+ } else {
307
+ this.roots.push(node);
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ for (i = 0; i < this.nodes.length; i++) {
314
+ node = this.nodes[i].updateBranchLeafClass();
315
+ }
316
+
317
+ return this;
318
+ };
319
+
320
+ Tree.prototype.move = function(node, destination) {
321
+ // Conditions:
322
+ // 1: +node+ should not be inserted as a child of +node+ itself.
323
+ // 2: +destination+ should not be the same as +node+'s current parent (this
324
+ // prevents +node+ from being moved to the same location where it already
325
+ // is).
326
+ // 3: +node+ should not be inserted in a location in a branch if this would
327
+ // result in +node+ being an ancestor of itself.
328
+ var nodeParent = node.parentNode();
329
+ if (node !== destination && destination.id !== node.parentId && jQuery.inArray(node, destination.ancestors()) === -1) {
330
+ node.setParent(destination);
331
+ this._moveRows(node, destination);
332
+
333
+ // Re-render parentNode if this is its first child node, and therefore
334
+ // doesn't have the expander yet.
335
+ if (node.parentNode().children.length === 1) {
336
+ node.parentNode().render();
337
+ }
338
+ }
339
+
340
+ if(nodeParent){
341
+ nodeParent.updateBranchLeafClass();
342
+ }
343
+ if(node.parentNode()){
344
+ node.parentNode().updateBranchLeafClass();
345
+ }
346
+ node.updateBranchLeafClass();
347
+ return this;
348
+ };
349
+
350
+ Tree.prototype.removeNode = function(node) {
351
+ // Recursively remove all descendants of +node+
352
+ this.unloadBranch(node);
353
+
354
+ // Remove node from DOM (<tr>)
355
+ node.row.remove();
356
+
357
+ // Remove node from parent children list
358
+ if (node.parentId != null) {
359
+ node.parentNode().removeChild(node);
360
+ }
361
+
362
+ // Clean up Tree object (so Node objects are GC-ed)
363
+ delete this.tree[node.id];
364
+ this.nodes.splice(jQuery.inArray(node, this.nodes), 1);
365
+
366
+ return this;
367
+ }
368
+
369
+ Tree.prototype.render = function() {
370
+ var root, _i, _len, _ref;
371
+ _ref = this.roots;
372
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
373
+ root = _ref[_i];
374
+
375
+ // Naming is confusing (show/render). I do not call render on node from
376
+ // here.
377
+ root.show();
378
+ }
379
+ return this;
380
+ };
381
+
382
+ Tree.prototype.sortBranch = function(node, sortFun) {
383
+ // First sort internal array of children
384
+ node.children.sort(sortFun);
385
+
386
+ // Next render rows in correct order on page
387
+ this._sortChildRows(node);
388
+
389
+ return this;
390
+ };
391
+
392
+ Tree.prototype.unloadBranch = function(node) {
393
+ // Use a copy of the children array to not have other functions interfere
394
+ // with this function if they manipulate the children array
395
+ // (eg removeNode).
396
+ var children = node.children.slice(0),
397
+ i;
398
+
399
+ for (i = 0; i < children.length; i++) {
400
+ this.removeNode(children[i]);
401
+ }
402
+
403
+ // Reset node's collection of children
404
+ node.children = [];
405
+
406
+ node.updateBranchLeafClass();
407
+
408
+ return this;
409
+ };
410
+
411
+ Tree.prototype._moveRows = function(node, destination) {
412
+ var children = node.children, i;
413
+
414
+ node.row.insertAfter(destination.row);
415
+ node.render();
416
+
417
+ // Loop backwards through children to have them end up on UI in correct
418
+ // order (see #112)
419
+ for (i = children.length - 1; i >= 0; i--) {
420
+ this._moveRows(children[i], node);
421
+ }
422
+ };
423
+
424
+ // Special _moveRows case, move children to itself to force sorting
425
+ Tree.prototype._sortChildRows = function(parentNode) {
426
+ return this._moveRows(parentNode, parentNode);
427
+ };
428
+
429
+ return Tree;
430
+ };
431
+
432
+ var Tree = defineTree()
433
+
434
+ /**
435
+ * Define the methods for the jQuery Plugin
436
+ */
437
+ var methods = {
438
+ /**
439
+ * Constructor
440
+ */
441
+ init: function(options, force) {
442
+ var settings;
443
+
444
+ settings = jQuery.extend({
445
+ branchAttr: "ttBranch",
446
+ clickableNodeNames: false,
447
+ column: 0,
448
+ columnElType: "td", // i.e. 'td', 'th' or 'td,th'
449
+ expandable: false,
450
+ expanderTemplate: "<a href='#'>&nbsp;</a>",
451
+ indent: 19,
452
+ indenterTemplate: "<span class='indenter'></span>",
453
+ initialState: "collapsed",
454
+ nodeIdAttr: "ttId", // maps to data-tt-id
455
+ parentIdAttr: "ttParentId", // maps to data-tt-parent-id
456
+ stringExpand: "Expand",
457
+ stringCollapse: "Collapse",
458
+
459
+ // Events
460
+ onInitialized: null,
461
+ onNodeCollapse: null,
462
+ onNodeExpand: null,
463
+ onNodeInitialized: null
464
+ }, options);
465
+
466
+ return this.each(function() {
467
+ var el = jQuery(this), tree;
468
+
469
+ if (force || el.data("treetable") === undefined) {
470
+ tree = new Tree(this, settings);
471
+ tree.loadRows(this.rows).render();
472
+
473
+ el.addClass("treetable").data("treetable", tree);
474
+
475
+ if (settings.onInitialized != null) {
476
+ settings.onInitialized.apply(tree);
477
+ }
478
+ }
479
+
480
+ return el;
481
+ });
482
+ },
483
+
484
+ /**
485
+ * Destructor
486
+ */
487
+ destroy: function() {
488
+ return this.each(function() {
489
+ return jQuery(this).removeData("treetable").removeClass("treetable");
490
+ });
491
+ },
492
+
493
+ /**
494
+ * Collapsing all tree branches
495
+ */
496
+ collapseAll: function() {
497
+ this.data("treetable").collapseAll();
498
+ return this;
499
+ },
500
+
501
+ /**
502
+ * Collapsing a single tree branch
503
+ */
504
+ collapseNode: function(id) {
505
+ var node = this.data("treetable").tree[id];
506
+
507
+ if (node) {
508
+ node.collapse();
509
+ } else {
510
+ throw new Error("Unknown node '" + id + "'");
511
+ }
512
+
513
+ return this;
514
+ },
515
+
516
+ /**
517
+ * Expanding all tree branches
518
+ */
519
+ expandAll: function() {
520
+ this.data("treetable").expandAll();
521
+ return this;
522
+ },
523
+
524
+ /**
525
+ * Expanding a single tree branch
526
+ */
527
+ expandNode: function(id) {
528
+ var node = this.data("treetable").tree[id];
529
+
530
+ if (node) {
531
+ if (!node.initialized) {
532
+ node._initialize();
533
+ }
534
+
535
+ node.expand();
536
+ } else {
537
+ throw new Error("Unknown node '" + id + "'");
538
+ }
539
+
540
+ return this;
541
+ },
542
+
543
+ /**
544
+ * Load the markup for a single tree branch
545
+ */
546
+ loadBranch: function(node, rows) {
547
+ var settings = this.data("treetable").settings,
548
+ tree = this.data("treetable").tree;
549
+
550
+ // TODO Switch to $.parseHTML
551
+ rows = jQuery(rows);
552
+
553
+ if (node == null) { // Inserting new root nodes
554
+ this.append(rows);
555
+ } else {
556
+ var lastNode = this.data("treetable").findLastNode(node);
557
+ rows.insertAfter(lastNode.row);
558
+ }
559
+
560
+ this.data("treetable").loadRows(rows);
561
+
562
+ // Make sure nodes are properly initialized
563
+ rows.filter("tr").each(function() {
564
+ tree[jQuery(this).data(settings.nodeIdAttr)].show();
565
+ });
566
+
567
+ if (node != null) {
568
+ // Re-render parent to ensure expander icon is shown (#79)
569
+ node.render().expand();
570
+ }
571
+
572
+ return this;
573
+ },
574
+
575
+ /**
576
+ *
577
+ */
578
+ move: function(nodeId, destinationId) {
579
+ var destination, node;
580
+
581
+ node = this.data("treetable").tree[nodeId];
582
+ destination = this.data("treetable").tree[destinationId];
583
+ this.data("treetable").move(node, destination);
584
+
585
+ return this;
586
+ },
587
+
588
+ /**
589
+ *
590
+ */
591
+ node: function(id) {
592
+ return this.data("treetable").tree[id];
593
+ },
594
+
595
+ /**
596
+ *
597
+ */
598
+ removeNode: function(id) {
599
+ var node = this.data("treetable").tree[id];
600
+
601
+ if (node) {
602
+ this.data("treetable").removeNode(node);
603
+ } else {
604
+ throw new Error("Unknown node '" + id + "'");
605
+ }
606
+
607
+ return this;
608
+ },
609
+
610
+ /**
611
+ *
612
+ */
613
+ reveal: function(id) {
614
+ var node = this.data("treetable").tree[id];
615
+
616
+ if (node) {
617
+ node.reveal();
618
+ } else {
619
+ throw new Error("Unknown node '" + id + "'");
620
+ }
621
+
622
+ return this;
623
+ },
624
+
625
+ /**
626
+ *
627
+ */
628
+ sortBranch: function(node, columnOrFunction) {
629
+ var settings = this.data("treetable").settings,
630
+ prepValue,
631
+ sortFun;
632
+
633
+ columnOrFunction = columnOrFunction || settings.column;
634
+ sortFun = columnOrFunction;
635
+
636
+ if (jQuery.isNumeric(columnOrFunction)) {
637
+ sortFun = function(a, b) {
638
+ var extractValue, valA, valB;
639
+
640
+ extractValue = function(node) {
641
+ var val = node.row.find("td:eq(" + columnOrFunction + ")").text();
642
+ // Ignore trailing/leading whitespace and use uppercase values for
643
+ // case insensitive ordering
644
+ return jQuery.trim(val).toUpperCase();
645
+ }
646
+
647
+ valA = extractValue(a);
648
+ valB = extractValue(b);
649
+
650
+ if (valA < valB) return -1;
651
+ if (valA > valB) return 1;
652
+ return 0;
653
+ };
654
+ }
655
+
656
+ this.data("treetable").sortBranch(node, sortFun);
657
+ return this;
658
+ },
659
+
660
+ /**
661
+ *
662
+ */
663
+ unloadBranch: function(node) {
664
+ this.data("treetable").unloadBranch(node);
665
+ return this;
666
+ }
667
+ };
668
+
669
+ /**
670
+ * Define the jQuery Plugin
671
+ *
672
+ */
673
+ jQuery.fn.treetable = function(method) {
674
+ if (methods[method]) {
675
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
676
+ } else if (typeof method === 'object' || !method) {
677
+ return methods.init.apply(this, arguments);
678
+ } else {
679
+ return jQuery.error("Method " + method + " does not exist on jQuery.treetable");
680
+ }
681
+ };
682
+
683
+ // Expose classes to world
684
+ document.TreeTable || (document.TreeTable = {});
685
+ document.TreeTable.Node = Node;
686
+ document.TreeTable.Tree = Tree;
687
+