bone_tree 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ task :build => [:spec] do
7
7
  # Build static assets
8
8
  `middleman build`
9
9
 
10
- `cp build/javascripts/bone_tree.js lib/assets/bone_tree.js`
10
+ `cp build/javascripts/bone_tree.js lib/assets/src/bone_tree.js`
11
11
  `gem build bone_tree.gemspec`
12
12
  end
13
13
 
@@ -0,0 +1 @@
1
+ #= require ./src/bone_tree
data/lib/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module BoneTree
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.3"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bone_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -41,8 +41,7 @@ files:
41
41
  - docs/source/javascripts/bone_tree/views/_file.js.html
42
42
  - docs/source/javascripts/bone_tree/views/_menu.js.html
43
43
  - docs/source/javascripts/bone_tree/views/_tree.js.html
44
- - lib/assets/bone_tree.js
45
- - lib/assets/manifest.coffee
44
+ - lib/assets/bone_tree.js.coffee
46
45
  - lib/version.rb
47
46
  - source/images/bonetree.png
48
47
  - source/images/crushed_bone.png
@@ -86,7 +85,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
85
  version: '0'
87
86
  segments:
88
87
  - 0
89
- hash: 2306725095725393049
88
+ hash: -95181981014547945
90
89
  required_rubygems_version: !ruby/object:Gem::Requirement
91
90
  none: false
92
91
  requirements:
@@ -1,1292 +0,0 @@
1
- (function() {
2
- var __slice = [].slice;
3
-
4
- window.BoneTree = {};
5
-
6
- BoneTree.namespace = function(target, name, block) {
7
- var item, top, _i, _len, _ref, _ref1;
8
- if (arguments.length < 3) {
9
- _ref = [(typeof exports !== 'undefined' ? exports : window)].concat(__slice.call(arguments)), target = _ref[0], name = _ref[1], block = _ref[2];
10
- }
11
- top = target;
12
- _ref1 = name.split('.');
13
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
14
- item = _ref1[_i];
15
- target = target[item] || (target[item] = {});
16
- }
17
- return block(target, top);
18
- };
19
-
20
- }).call(this);
21
- (function() {
22
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
23
- __hasProp = {}.hasOwnProperty,
24
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
25
-
26
- BoneTree.namespace("BoneTree.Models", function(Models) {
27
- Models.Node = (function(_super) {
28
-
29
- __extends(Node, _super);
30
-
31
- Node.name = 'Node';
32
-
33
- function Node() {
34
- this.nameWithExtension = __bind(this.nameWithExtension, this);
35
-
36
- this.constantize = __bind(this.constantize, this);
37
- return Node.__super__.constructor.apply(this, arguments);
38
- }
39
-
40
- /*
41
- Internal: An abstract super class for File and Directory objects to inherit from.
42
- */
43
-
44
-
45
- Node.prototype.initialize = function() {
46
- /*
47
- Internal: Initialize a new Node object. Set it up to contain a collection of
48
- children nodes.
49
- */
50
- return this.collection = new Models.Nodes;
51
- };
52
-
53
- Node.prototype.constantize = function() {
54
- /*
55
- Public: Returns a String with the nodeType capitalized so that it may be used
56
- to instatiate the appropriate view type
57
-
58
- Examples
59
-
60
- file = new BoneTree.Models.File
61
- directory = new BoneTree.Models.Directory
62
-
63
- file.constantize()
64
- # => 'File'
65
-
66
- directory.constantize()
67
- # => 'Directory'
68
-
69
- # use it to create a new view of the appropriate type
70
- view = new BoneTree.Views[file.constantize()]
71
-
72
- Returns a String of the nodeType with the first letter capitalized.
73
- */
74
-
75
- var nodeType;
76
- nodeType = this.get('nodeType');
77
- return nodeType[0].toUpperCase() + nodeType.substring(1);
78
- };
79
-
80
- Node.prototype.nameWithExtension = function() {
81
- /*
82
- Public: Returns the node name with the extension if it has
83
- one and just the node name if there is no extension.
84
-
85
- Examples
86
-
87
- file = new BoneTree.Models.File
88
- name: "file"
89
- extension: "coffee"
90
-
91
- noExt = new BoneTree.Models.File
92
- name: "file2"
93
-
94
- directory = new BoneTree.Model.Directory
95
- name: "source"
96
-
97
- file.nameWithExtension()
98
- # => "file.coffee"
99
-
100
- noExt.nameWithExtension()
101
- # => "file2"
102
-
103
- directory.nameWithExtension()
104
- # => "source"
105
-
106
- Returns a String. If the extension exists then the node name plus the extension
107
- are returned. If there is no extension, then just the node name is returned.
108
- */
109
-
110
- var extension, name, _ref;
111
- _ref = this.attributes, extension = _ref.extension, name = _ref.name;
112
- extension || (extension = "");
113
- if (extension !== "") {
114
- extension = "." + extension;
115
- }
116
- return name + extension;
117
- };
118
-
119
- return Node;
120
-
121
- })(Backbone.Model);
122
- return Models.Nodes = (function(_super) {
123
-
124
- __extends(Nodes, _super);
125
-
126
- Nodes.name = 'Nodes';
127
-
128
- function Nodes() {
129
- return Nodes.__super__.constructor.apply(this, arguments);
130
- }
131
-
132
- /*
133
- Internal: A collection of node models. Since Node is an abstract super
134
- class, in practice this collection will hold File objects
135
- and Directory objects.
136
- */
137
-
138
-
139
- Nodes.prototype.comparator = function(node) {
140
- /*
141
- Internal: Function that determines how the file tree is sorted. Directories
142
- are sorted before files. After node type sort
143
- priority, nodes are sorted by name.
144
-
145
- Examples
146
-
147
- tree.addFile('/source/file1.coffee')
148
- tree.addFile('/source/file2.coffee')
149
- tree.addFile('main.coffee')
150
-
151
- tree.render()
152
-
153
- # even though 'main' comes before 'source' alphabetically it is placed
154
- # after the 'source' directory due to the sortPriority of the Directory object.
155
- tree.toAscii()
156
- # => "
157
- -source
158
- -file1.coffee
159
- -file2.coffee
160
- -main.coffee
161
- "
162
- */
163
-
164
- var name, sortPriority, _ref;
165
- _ref = node.attributes, name = _ref.name, sortPriority = _ref.sortPriority;
166
- return sortPriority + name;
167
- };
168
-
169
- Nodes.prototype.model = Models.Node;
170
-
171
- return Nodes;
172
-
173
- })(Backbone.Collection);
174
- });
175
-
176
- }).call(this);
177
- (function() {
178
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
179
- __hasProp = {}.hasOwnProperty,
180
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
181
-
182
- BoneTree.namespace("BoneTree.Models", function(Models) {
183
- Models.Directory = (function(_super) {
184
-
185
- __extends(Directory, _super);
186
-
187
- Directory.name = 'Directory';
188
-
189
- function Directory() {
190
- this.toggleOpen = __bind(this.toggleOpen, this);
191
- return Directory.__super__.constructor.apply(this, arguments);
192
- }
193
-
194
- /*
195
- Public: Object representing a directory.
196
-
197
- * defaults
198
- * name - A String naming the directory (default: "New Directory").
199
- * sortPriority - A String representing the priority with which the
200
- node is sorted. Directories have sortPriority "0"
201
- allowing them to be sorted before Files which have
202
- sortPriority "1".
203
- * nodeType - A String denoting what type of node this object is.
204
- The two types are "file" and "directory".
205
- * open - The state of the directory. Controls whether or not
206
- to display files and directories contained within this
207
- Directory (default: false).
208
- */
209
-
210
-
211
- Directory.prototype.defaults = {
212
- name: "New Directory",
213
- open: false,
214
- sortPriority: "0",
215
- nodeType: "directory"
216
- };
217
-
218
- Directory.prototype.toggleOpen = function() {
219
- /*
220
- Public: Toggle the open state of this Directory.
221
-
222
- Examples
223
-
224
- dir = new BoneTree.Models.Directory
225
-
226
- dir.get('open')
227
- # => false
228
-
229
- dir.toggleOpen()
230
- dir.get('open')
231
- # => true
232
-
233
- Returns this Directory.
234
- */
235
-
236
- var currentState;
237
- currentState = this.get('open');
238
- return this.set({
239
- open: !currentState
240
- });
241
- };
242
-
243
- return Directory;
244
-
245
- })(Models.Node);
246
- return Models.Directory.find = function(currentDirectory, name) {
247
- /*
248
- Internal: Check to see if there is a directory with the matching name
249
- contained within currentDirectory.
250
-
251
- * currentDirectory - A Directory object to search for the matching directory name.
252
-
253
- * name - A String name used to check for matching directory
254
- names in currentDirectory.
255
-
256
- Returns The Directory object with the matching name if it exists and undefined otherwise.
257
- */
258
- return currentDirectory.collection.find(function(dir) {
259
- return dir.get('name') === name;
260
- });
261
- };
262
- });
263
-
264
- }).call(this);
265
- (function() {
266
- var __hasProp = {}.hasOwnProperty,
267
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },
268
- __slice = [].slice;
269
-
270
- BoneTree.namespace("BoneTree.Models", function(Models) {
271
- Models.File = (function(_super) {
272
-
273
- __extends(File, _super);
274
-
275
- File.name = 'File';
276
-
277
- function File() {
278
- return File.__super__.constructor.apply(this, arguments);
279
- }
280
-
281
- /*
282
- Public: Object representing file data in the tree.
283
-
284
- * defaults
285
- * name - A String naming the file (default: "New File").
286
- * sortPriority - A String representing the priority with which the
287
- node is sorted. Directories have sortPriority "0"
288
- allowing them to be sorted before Files which have
289
- sortPriority "1".
290
- * nodeType - A String denoting what type of node this object is.
291
- The two types are "file" and "directory".
292
- */
293
-
294
-
295
- File.prototype.defaults = {
296
- name: "New File",
297
- sortPriority: "1",
298
- nodeType: "file"
299
- };
300
-
301
- return File;
302
-
303
- })(Models.Node);
304
- return Models.File.createFromFileName = function(fileName, fileData) {
305
- /*
306
- Public: Class method to create a new File object based on the fileName
307
- and fileData passed in.
308
-
309
- * fileName - A String representing the name of the file to be created.
310
- files with '.' in the name will be parsed out and only the
311
- string after the final '.' will be considered the extension.
312
-
313
- * fileData - An Object of attributes to associate with the file.
314
-
315
- Examples
316
-
317
- data = {
318
- contents: alert 'this is the code in the file'
319
- createdAt: 1330846900589
320
- language: 'CoffeeScript'
321
- }
322
-
323
- BoneTree.Models.File.createFromFileName('example.coffee', data)
324
- # => <File>
325
-
326
- Returns the File object just created.
327
- */
328
-
329
- var data, extension, name, names, _i, _ref;
330
- _ref = fileName.split("."), names = 2 <= _ref.length ? __slice.call(_ref, 0, _i = _ref.length - 1) : (_i = 0, []), extension = _ref[_i++];
331
- name = names.join('.');
332
- data = _.extend({}, fileData, {
333
- name: name,
334
- extension: extension
335
- });
336
- return new Models.File(data);
337
- };
338
- });
339
-
340
- }).call(this);
341
- (function() {
342
- var __hasProp = {}.hasOwnProperty,
343
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
344
-
345
- BoneTree.namespace("BoneTree.Models", function(Models) {
346
- return Models.Settings = (function(_super) {
347
-
348
- __extends(Settings, _super);
349
-
350
- Settings.name = 'Settings';
351
-
352
- function Settings() {
353
- return Settings.__super__.constructor.apply(this, arguments);
354
- }
355
-
356
- /*
357
- Internal: A configuration object. Consumers of the API don't need to
358
- worry about this. It is used internally to manage the options
359
- passed into the file tree.
360
-
361
- * defaults
362
- * beforeAdd - A Function that is invoked before each file is added to the tree.
363
- It is passed the raw file attributes and should return true if
364
- that file should be added to the tree and false if not. The
365
- default implementation is to return true.
366
- * confirmDeletes - A Boolean. If true, the tree will prompt the user, making
367
- sure they want to delete the file (default: false).
368
- * showExtensions - A Boolean. If true, files display their extensions. Internally,
369
- extensions are always kept track of but by default they are
370
- hidden (default: false).
371
- * viewCache - An Object that stores views when they are created and is used
372
- to look them up to prevent extra views from being created.
373
- */
374
-
375
-
376
- Settings.prototype.defaults = {
377
- confirmDeletes: false,
378
- showExtensions: false,
379
- viewCache: {}
380
- };
381
-
382
- return Settings;
383
-
384
- })(Backbone.Model);
385
- });
386
-
387
- }).call(this);
388
- (function() {
389
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
390
- __hasProp = {}.hasOwnProperty,
391
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
392
-
393
- BoneTree.namespace("BoneTree.Views", function(Views) {
394
- return Views.Directory = (function(_super) {
395
-
396
- __extends(Directory, _super);
397
-
398
- Directory.name = 'Directory';
399
-
400
- function Directory() {
401
- this.displayChildren = __bind(this.displayChildren, this);
402
-
403
- this.render = __bind(this.render, this);
404
-
405
- this.appendView = __bind(this.appendView, this);
406
- return Directory.__super__.constructor.apply(this, arguments);
407
- }
408
-
409
- /*
410
- Internal: View that renders a Directory node and controls its behavior (class: 'directory', tag: 'ul').
411
- */
412
-
413
-
414
- Directory.prototype.className = 'directory';
415
-
416
- Directory.prototype.tagName = 'ul';
417
-
418
- Directory.prototype.initialize = function(options) {
419
- /*
420
- Internal: Initialize a new directory node. Adds associated model cid to the
421
- view element. Binds change handler to the `change:open` event that
422
- toggles the display of directory contents. Binds change handler to
423
- the `change:name` event that re-renders a sorted file tree.
424
-
425
- * options - Passes in settings object, which is used for access to the
426
- tree view root in order to proxy events to it.
427
- */
428
-
429
- var _this = this;
430
- this.settings = options.settings;
431
- this.$el.attr('data-cid', this.model.cid);
432
- this.model.bind('change:open', function(model, open) {
433
- return _this.displayChildren(open);
434
- });
435
- this.model.bind('change:name', function(model, name) {
436
- var treeView;
437
- treeView = _this.settings.get('treeView');
438
- return treeView.render().trigger('rename', model, name);
439
- });
440
- this.model.collection.bind('add', this.render);
441
- this.model.collection.bind('remove', function(model, collection) {
442
- _this.settings.get('treeView').trigger('remove', model);
443
- return _this.render();
444
- });
445
- return this.displayChildren(this.model.get('open'));
446
- };
447
-
448
- Directory.prototype.appendView = function(node) {
449
- /*
450
- Internal: Appends a view based on the underlying node model to this view.
451
-
452
- node - A Node model. Either a File or a Directory. This is the model the
453
- created view will be associated with.
454
- */
455
-
456
- var view;
457
- view = this.settings.get('treeView').findOrCreateView(node);
458
- return this.$el.append(view.render().$el);
459
- };
460
-
461
- Directory.prototype.render = function() {
462
- /*
463
- Internal: Set the text of the view element based on the underlying model name.
464
-
465
- Returns `this` view.
466
- */
467
- this.$el.text(this.model.get('name'));
468
- this.model.collection.sort().each(this.appendView);
469
- return this;
470
- };
471
-
472
- Directory.prototype.displayChildren = function(open) {
473
- /*
474
- Internal: Toggles display of the children Files or Diretories of this view.
475
- */
476
-
477
- var fileDirChildren;
478
- fileDirChildren = this.$el.children('.directory, .file');
479
- this.$el.toggleClass('open', open);
480
- return fileDirChildren.toggle(open);
481
- };
482
-
483
- return Directory;
484
-
485
- })(Backbone.View);
486
- });
487
-
488
- }).call(this);
489
- (function() {
490
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
491
- __hasProp = {}.hasOwnProperty,
492
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
493
-
494
- BoneTree.namespace("BoneTree.Views", function(Views) {
495
- return Views.File = (function(_super) {
496
-
497
- __extends(File, _super);
498
-
499
- File.name = 'File';
500
-
501
- function File() {
502
- this.render = __bind(this.render, this);
503
- return File.__super__.constructor.apply(this, arguments);
504
- }
505
-
506
- /*
507
- Internal: View that renders a File node and controls its behavior (class: 'file', tag: 'li').
508
- */
509
-
510
-
511
- File.prototype.className = 'file';
512
-
513
- File.prototype.tagName = 'li';
514
-
515
- File.prototype.initialize = function(options) {
516
- /*
517
- Internal: Initialize a new file node. Adds associated model cid to the
518
- view element. Binds change handlers to the `change:name` and
519
- `change:extension` events. These take care of resorting the file
520
- nodes.
521
-
522
- * options - Passes in settings object, which is used to control
523
- whether or not file extensions are shown.
524
- */
525
-
526
- var _this = this;
527
- this.settings = options.settings;
528
- this.$el.attr('data-cid', this.model.cid).addClass(this.model.get('extension'));
529
- this.model.bind('change:name', function(model, name) {
530
- var treeView;
531
- treeView = _this.settings.get('treeView');
532
- return treeView.render().trigger('rename', model, model.nameWithExtension());
533
- });
534
- return this.model.bind('change:extension', function(model, extension) {
535
- var treeView;
536
- _this.$el.attr('class', "file " + extension);
537
- treeView = _this.settings.get('treeView');
538
- return treeView.render().trigger('rename', model, model.nameWithExtension());
539
- });
540
- };
541
-
542
- File.prototype.render = function() {
543
- /*
544
- Internal: Sets the text of the file node according to the underlying model
545
- name. If the 'showExtensions' setting is set, renders the
546
- full file name with extension, otherwise renders just the file
547
- name attribute.
548
- */
549
- if (this.settings.get('showExtensions')) {
550
- this.$el.text(this.model.nameWithExtension());
551
- } else {
552
- this.$el.text(this.model.get('name'));
553
- }
554
- return this;
555
- };
556
-
557
- return File;
558
-
559
- })(Backbone.View);
560
- });
561
-
562
- }).call(this);
563
- (function() {
564
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
565
- __hasProp = {}.hasOwnProperty,
566
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
567
-
568
- BoneTree.namespace("BoneTree.Views", function(Views) {
569
- return Views.Menu = (function(_super) {
570
-
571
- __extends(Menu, _super);
572
-
573
- Menu.name = 'Menu';
574
-
575
- function Menu() {
576
- this.render = __bind(this.render, this);
577
-
578
- this.rename = __bind(this.rename, this);
579
-
580
- this["delete"] = __bind(this["delete"], this);
581
-
582
- this.contextMenu = __bind(this.contextMenu, this);
583
- return Menu.__super__.constructor.apply(this, arguments);
584
- }
585
-
586
- /*
587
- Internal: View that controls the context menu (class: 'filetree\_context\_menu').
588
-
589
- Events
590
-
591
- * contextMenu - Prevents the standard browser context menu from appearing
592
- when right clicking within the file tree context menu.
593
-
594
- * click .rename - Prompts the user to rename a file.
595
-
596
- * click .delete - Deletes a node from the file tree.
597
- */
598
-
599
-
600
- Menu.prototype.className = 'filetree_context_menu';
601
-
602
- Menu.prototype.events = {
603
- 'contextmenu': 'contextMenu',
604
- 'click .rename': 'rename',
605
- 'click .delete': 'delete'
606
- };
607
-
608
- Menu.prototype.initialize = function(options) {
609
- /*
610
- Internal: Initialize a new menu widget.
611
-
612
- * options - An Object. Internally used to pass the settings configuration
613
- into the menu. This controls whether or not the user is
614
- prompted to confirm deleting a file.
615
- */
616
- return this.settings = options.settings;
617
- };
618
-
619
- Menu.prototype.contextMenu = function(e) {
620
- /*
621
- Internal: Kill the default browser behavior for the contextmenu event.
622
- */
623
- e.preventDefault();
624
- return e.stopPropagation();
625
- };
626
-
627
- Menu.prototype["delete"] = function(e) {
628
- /*
629
- Internal: Deletes a node from the file tree. If the confirmDeletes setting
630
- is set, prompts the user for delete confirmation.
631
- */
632
- if (this.settings.get('confirmDeletes')) {
633
- if (confirm("Are you sure you want to delete '" + (this.model.nameWithExtension()) + "'?")) {
634
- this.model.destroy();
635
- }
636
- } else {
637
- this.model.destroy();
638
- }
639
- return this.$el.hide();
640
- };
641
-
642
- Menu.prototype.rename = function(e) {
643
- /*
644
- Internal: Prompts the user to rename a File or Directory.
645
- */
646
-
647
- var extension, fileName, newName, _ref;
648
- if (newName = prompt("New Name", this.model.nameWithExtension())) {
649
- _ref = newName.split("."), fileName = _ref[0], extension = _ref[1];
650
- if (extension == null) {
651
- extension = "";
652
- }
653
- this.model.set({
654
- name: fileName,
655
- extension: extension
656
- });
657
- }
658
- return this.$el.hide();
659
- };
660
-
661
- Menu.prototype.render = function() {
662
- /*
663
- Internal: Renders the <ul> that contains the context menu choices
664
- 'Rename' and 'Delete'.
665
-
666
- Returns `this`, the menu view.
667
- */
668
- this.$el.html(this.template());
669
- return this;
670
- };
671
-
672
- Menu.prototype.template = function() {
673
- /*
674
- Internal: html template for the context menu.
675
- */
676
- return "<ul>\n <li class='rename'>Rename</li>\n <hr/>\n <li class='delete'>Delete</li>\n</ul>";
677
- };
678
-
679
- return Menu;
680
-
681
- })(Backbone.View);
682
- });
683
-
684
- }).call(this);
685
- (function() {
686
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
687
- __hasProp = {}.hasOwnProperty,
688
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },
689
- __slice = [].slice;
690
-
691
- BoneTree.namespace("BoneTree.Views", function(Views) {
692
- var Models;
693
- Models = BoneTree.Models;
694
- return Views.Tree = (function(_super) {
695
-
696
- __extends(Tree, _super);
697
-
698
- Tree.name = 'Tree';
699
-
700
- function Tree() {
701
- this.render = __bind(this.render, this);
702
-
703
- this._openFile = __bind(this._openFile, this);
704
-
705
- this._openDirectory = __bind(this._openDirectory, this);
706
-
707
- this.getModelFromClick = __bind(this.getModelFromClick, this);
708
-
709
- this.toAscii = __bind(this.toAscii, this);
710
-
711
- this.files = __bind(this.files, this);
712
-
713
- this._getFile = __bind(this._getFile, this);
714
-
715
- this.getDirectory = __bind(this.getDirectory, this);
716
-
717
- this.flatten = __bind(this.flatten, this);
718
-
719
- this.filterNodes = __bind(this.filterNodes, this);
720
-
721
- this._contextMenu = __bind(this._contextMenu, this);
722
-
723
- this._closeMenu = __bind(this._closeMenu, this);
724
-
725
- this.closeDirectories = __bind(this.closeDirectories, this);
726
-
727
- this.getModelByCid = __bind(this.getModelByCid, this);
728
-
729
- this.findOrCreateView = __bind(this.findOrCreateView, this);
730
-
731
- this.addToTree = __bind(this.addToTree, this);
732
-
733
- this.addFromJSON = __bind(this.addFromJSON, this);
734
-
735
- this.file = __bind(this.file, this);
736
- return Tree.__super__.constructor.apply(this, arguments);
737
- }
738
-
739
- /*
740
- Public: The base tree object. Events from other objects are proxied to the tree
741
- so API consumers only need to know about this top level object.
742
- */
743
-
744
-
745
- Tree.prototype.className = 'tree';
746
-
747
- Tree.prototype.events = {
748
- 'contextmenu .file': '_contextMenu',
749
- 'contextmenu .directory': '_contextMenu',
750
- 'click .directory': '_openDirectory',
751
- 'click .file': '_openFile'
752
- };
753
-
754
- Tree.prototype.initialize = function() {
755
- /*
756
- Public: Initialize a new filetree widget
757
-
758
- * options - An Object of global configuration options for the file tree.
759
- * confirmDeletes - A Boolean. If true, the tree will prompt the user, making
760
- sure they want to delete the file (default: false).
761
- * showExtensions - A Boolean. If true, files display their extensions. Internally,
762
- extensions are always kept track of but by default they are
763
- hidden (default: false).
764
- */
765
-
766
- var settingsConfig,
767
- _this = this;
768
- $(document).click(this._closeMenu);
769
- this._currentFileData = null;
770
- settingsConfig = _.extend({}, this.options, {
771
- treeView: this
772
- });
773
- this.settings = new Models.Settings(settingsConfig);
774
- this.menuView = new Views.Menu({
775
- settings: this.settings
776
- });
777
- this.menuView.render().$el.appendTo($('body'));
778
- this.root = new Models.Node;
779
- this.root.collection.bind('add', this.render);
780
- return this.root.collection.bind('remove', function(model, collection) {
781
- _this.$("[data-cid='" + model.cid + "']").remove();
782
- _this.render();
783
- return _this.trigger('remove', model);
784
- });
785
- };
786
-
787
- Tree.prototype.file = function(filePath, fileData) {
788
- var dirs, file, fileName, _i, _ref;
789
- if (filePath[0] === '/') {
790
- filePath = filePath.replace('/', '');
791
- }
792
- if (fileData != null) {
793
- this._currentFileData = _.extend(fileData, {
794
- path: filePath
795
- });
796
- if (this._currentFileData.autoOpen == null) {
797
- this._currentFileData.autoOpen = true;
798
- }
799
- if (this._currentFileData.hidden == null) {
800
- this._currentFileData.hidden = false;
801
- }
802
- } else {
803
- return this._getFile(filePath);
804
- }
805
- _ref = filePath.split('/'), dirs = 2 <= _ref.length ? __slice.call(_ref, 0, _i = _ref.length - 1) : (_i = 0, []), fileName = _ref[_i++];
806
- if (file = this._getFile(filePath)) {
807
- return file.set(this._currentFileData);
808
- } else {
809
- return this.addToTree(this.root, dirs, fileName);
810
- }
811
- };
812
-
813
- Tree.prototype.addFromJSON = function(data, currentPath) {
814
- var file, name, _i, _len, _ref;
815
- if (currentPath == null) {
816
- currentPath = "";
817
- }
818
- /*
819
- Public: Creates a file tree from a JSON representation. Expects the
820
- JSON object to have a `name` property at each level, specifying
821
- the name of the file or directory, and a files array if the
822
- current node has child directories or files.
823
-
824
- * data - An Object that represents hierarchical file data.
825
-
826
- * currentPath - A String representing the current location in the tree.
827
- Defaults to the file tree root. (default: "")
828
-
829
- Examples
830
-
831
- data = {
832
- name: "My Project"
833
- files: [
834
- { name: "Empty Folder" }
835
- { name: "SomeFile.coffee" }
836
- { name: "AnotherFile.coffee" }
837
- {
838
- name: "Folder with Files inside"
839
- files: [
840
- { name: "NestedFile.coffee" }
841
- ]
842
- }
843
- ]
844
- }
845
-
846
- tree.addFromJSON(data)
847
- # => <Tree>
848
-
849
- Returns the Tree view object.
850
- */
851
-
852
- name = "";
853
- if (data.name != null) {
854
- name = data.name + '/';
855
- delete data.name;
856
- }
857
- if (data.extension != null) {
858
- name = name.replace('/', '.' + data.extension);
859
- delete data.extension;
860
- }
861
- currentPath += name;
862
- if (data.files != null) {
863
- _ref = data.files;
864
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
865
- file = _ref[_i];
866
- this.addFromJSON(file, currentPath);
867
- }
868
- } else {
869
- this.file(currentPath, data);
870
- }
871
- return this;
872
- };
873
-
874
- Tree.prototype.addToTree = function(currentDirectory, remainingDirectories, fileName) {
875
- /*
876
- Internal: Recursive method that traverses nodes, creating
877
- Files and Directories.
878
-
879
- * currentDirectory - A Node object representing which directory we are
880
- adding the current Directory or File to.
881
- * remainingDirectories - A '/' separated String representing the remaining
882
- directories to add.
883
- * fileName - The String name of the file to be added. This can
884
- include the extension name separated by a '.'.
885
-
886
- Examples
887
-
888
- tree.addToTree(@root, '/source/subdirectory/', 'main.coffee')
889
- # => <File>
890
-
891
- Returns the File object if it was created and null if no file was given.
892
- */
893
-
894
- var file, matchingDirectory, newDirectory, newNode, nextDirectoryName;
895
- if (remainingDirectories.length) {
896
- nextDirectoryName = remainingDirectories.shift();
897
- if (matchingDirectory = Models.Directory.find(currentDirectory, nextDirectoryName)) {
898
- matchingDirectory.set({
899
- open: true
900
- });
901
- return this.addToTree(matchingDirectory, remainingDirectories, fileName);
902
- } else {
903
- newNode = new Models.Directory({
904
- name: nextDirectoryName,
905
- open: true
906
- });
907
- newDirectory = currentDirectory.collection.add(newNode);
908
- return this.addToTree(newNode, remainingDirectories, fileName);
909
- }
910
- } else {
911
- if (fileName === "") {
912
- return null;
913
- }
914
- file = Models.File.createFromFileName(fileName, this._currentFileData);
915
- this._currentFileData = null;
916
- currentDirectory.collection.add(file);
917
- if (file.get('autoOpen')) {
918
- this.trigger('openFile', file);
919
- }
920
- return file;
921
- }
922
- };
923
-
924
- Tree.prototype.findOrCreateView = function(node) {
925
- /*
926
- Internal: Look up existing view in the view cache or Create a new view
927
- of the correct type (either File or Directory).
928
-
929
- * node - A Node object. Either a File object or a Directory object.
930
- This is the model that the view will be associated with.
931
-
932
- Examples
933
-
934
- file = new BoneTree.Models.File
935
-
936
- # This will create a new view since we just created the File
937
- tree.findOrCreateView(file)
938
- # => <FileView>
939
-
940
- Returns the view corresponding to the model passed in.
941
- */
942
-
943
- var type, view, viewCache;
944
- type = node.constantize();
945
- viewCache = this.settings.get('viewCache');
946
- if (!(view = viewCache[node.cid])) {
947
- view = viewCache[node.cid] = new Views[type]({
948
- model: node,
949
- settings: this.settings
950
- });
951
- }
952
- return view;
953
- };
954
-
955
- Tree.prototype.getModelByCid = function(cid) {
956
- var modelCid, view, viewCache;
957
- viewCache = this.settings.get('viewCache');
958
- for (modelCid in viewCache) {
959
- view = viewCache[modelCid];
960
- if (modelCid === cid) {
961
- return view.model;
962
- }
963
- }
964
- };
965
-
966
- Tree.prototype.closeDirectories = function() {
967
- /*
968
- Public: Close all the directories in the file tree.
969
-
970
- Examples
971
-
972
- tree.closeDirectories()
973
- # => <Tree>
974
-
975
- Returns the Tree view object.
976
- */
977
-
978
- var directories;
979
- directories = _.filter(this.flatten(), function(node) {
980
- return node.get('nodeType') === 'directory';
981
- });
982
- _.invoke(directories, 'set', {
983
- open: false
984
- });
985
- return this;
986
- };
987
-
988
- Tree.prototype._closeMenu = function(e) {
989
- /*
990
- Internal: Close the context menu. This is called every click on
991
- the document and closes the menu unless you are clicking
992
- within it. This shouldn't be called directly, it is called
993
- automatically by Backbone from user interactions.
994
-
995
- Returns the Menu view object.
996
- */
997
- if (!$(e.currentTarget).is('.menu')) {
998
- this.menuView.$el.hide();
999
- }
1000
- return this.menuView;
1001
- };
1002
-
1003
- Tree.prototype._contextMenu = function(e) {
1004
- /*
1005
- Internal: Open the context menu. This prevents the default browser
1006
- context menu event. This shouldn't be called directly, it is
1007
- called automatically by Backbone from user interations.
1008
-
1009
- Returns the Menu view object.
1010
- */
1011
-
1012
- var model;
1013
- e.preventDefault();
1014
- model = this.getModelFromClick(e);
1015
- this.menuView.model = model;
1016
- this.menuView.$el.css({
1017
- left: e.pageX,
1018
- top: e.pageY
1019
- }).show();
1020
- return this.menuView;
1021
- };
1022
-
1023
- Tree.prototype.filterNodes = function(nodeType, nodeName) {
1024
- /*
1025
- Internal: Returns file tree nodes that match the nodeType and nodeName.
1026
-
1027
- * nodeType - A String that represents the nodeType to match. Choices are
1028
- 'file' or 'directory'.
1029
- * nodeName - A String that represents the name of the node to match.
1030
-
1031
- Examples
1032
-
1033
- # Add some files to the tree
1034
- tree.file('/source/main.coffee')
1035
- tree.file('/source/player.coffee')
1036
-
1037
- # returns an array containing the File 'main.coffee'
1038
- tree.filterNodes('file', 'main')
1039
- # => [<File>]
1040
-
1041
- Returns an Array of nodes that match the filter criteria.
1042
- */
1043
-
1044
- var results,
1045
- _this = this;
1046
- results = _.filter(this.flatten(), function(node) {
1047
- return node.get('nodeType') === nodeType && node.get('name') === nodeName;
1048
- });
1049
- return results;
1050
- };
1051
-
1052
- Tree.prototype.flatten = function(currentNode, results) {
1053
- var _this = this;
1054
- if (currentNode == null) {
1055
- currentNode = this.root;
1056
- }
1057
- if (results == null) {
1058
- results = [];
1059
- }
1060
- /*
1061
- Internal: Returns a one dimensional ordered array representing the
1062
- Directory and File nodes in the tree.
1063
-
1064
- * currentNode - The node to start at when flattening
1065
- * nodeName - A String that represents the name of the node to match.
1066
-
1067
- Examples
1068
-
1069
- # Add some files to the tree
1070
- tree.file('/source/main.coffee', {aFile: true})
1071
- tree.file('/source/player.coffee', {playerData: {x: 50, y: 30}})
1072
-
1073
- # returns an array containing the File 'main.coffee'
1074
- tree.filterNodes('file', 'main')
1075
- # => [<File>]
1076
-
1077
- Returns an Array of nodes that match the filter criteria.
1078
- */
1079
-
1080
- currentNode.collection.each(function(node) {
1081
- results.push(node);
1082
- if (node.collection.length) {
1083
- return _this.flatten(node, results);
1084
- }
1085
- });
1086
- return results;
1087
- };
1088
-
1089
- Tree.prototype.getDirectory = function(directoryName) {
1090
- /*
1091
- Public: Returns an array of directories matching the given directoryName.
1092
-
1093
- * directoryName - A String naming the directory to match.
1094
-
1095
- Examples
1096
-
1097
- # Add some files to the tree
1098
- tree.file('/source/main.coffee', {size: 4039})
1099
- tree.file('/source/player.coffee', {size: 399})
1100
- tree.file('/directory2/file.coffee', {size: 23})
1101
-
1102
- # returns an array containing the Directory 'source'
1103
- tree.getDirectory('source')
1104
- # => [<Directory>]
1105
-
1106
- Returns an Array of Directory nodes that match directoryName.
1107
- */
1108
- return this.filterNodes('directory', directoryName);
1109
- };
1110
-
1111
- Tree.prototype._getFile = function(filePath) {
1112
- /*
1113
- Internal: Returns a file at the specified location.
1114
-
1115
- * fileName - A String describing the file path.
1116
-
1117
- Examples
1118
-
1119
- # Add some files to the tree
1120
- tree.file('/source/main.coffee', {size: 30459})
1121
- tree.file('/source/player.coffee', {size: 943})
1122
- tree.file('/directory2/main.coffee', {size: 4945})
1123
-
1124
- # returns an array containing both the files named main.
1125
- tree._getFile('source/main.coffee')
1126
- # => <File>
1127
-
1128
- Returns a File at the given location.
1129
- */
1130
-
1131
- var filtered, nodes;
1132
- if (filePath[0] === '/') {
1133
- filePath = filePath.replace('/', '');
1134
- }
1135
- nodes = this.flatten();
1136
- filtered = _.filter(nodes, function(node) {
1137
- return node.get('nodeType') === 'file' && node.get('path') === filePath;
1138
- });
1139
- return filtered[0];
1140
- };
1141
-
1142
- Tree.prototype.files = function(directoryName) {
1143
- /*
1144
- Public: Returns an array of files contained within the directory
1145
- matching directoryName.
1146
-
1147
- * directoryName - A String naming the directory to look inside.
1148
-
1149
- Examples
1150
-
1151
- # Add some files to the tree
1152
- tree.file('/source/main.coffee', {main: true})
1153
- tree.file('/source/player.coffee', {active: true})
1154
- tree.file('/directory2/main.coffee', {active: true})
1155
-
1156
- # returns an array containing the files 'player.coffee' and 'main.coffee'
1157
- tree.files('source')
1158
- # => [<File>, <File>]
1159
-
1160
- Returns an Array of File nodes that are contained in the
1161
- Directory matching directoryName.
1162
- */
1163
-
1164
- var directory, nodesInDirectory;
1165
- if (directoryName == null) {
1166
- return _.filter(this.flatten(), function(node) {
1167
- return node.get('nodeType') === 'file';
1168
- });
1169
- }
1170
- directory = this.getDirectory(directoryName)[0];
1171
- if (!directory) {
1172
- return [];
1173
- }
1174
- nodesInDirectory = this.flatten(directory);
1175
- return _.filter(nodesInDirectory, function(node) {
1176
- return node.get('nodeType') === 'file';
1177
- });
1178
- };
1179
-
1180
- Tree.prototype.toAscii = function(collection, indentation, output) {
1181
- var n, rootCollection, spaces, _i,
1182
- _this = this;
1183
- if (indentation == null) {
1184
- indentation = 0;
1185
- }
1186
- if (output == null) {
1187
- output = "\n";
1188
- }
1189
- /*
1190
- Internal: A String representation of the filetree.
1191
-
1192
- * collection - A NodeCollection object describing which folder to start at.
1193
- * indentation - A Number describing how many spaces to indent the next filetree element (default: 0).
1194
- * output - A String representing the current filetree output (default: "\n").
1195
-
1196
- Examples
1197
-
1198
- # Add some files to the tree
1199
- tree.file('/source/main.coffee', {main: true})
1200
- tree.file('/source/player.coffee', {active: true})
1201
- tree.file('/directory2/main.coffee', {active: false})
1202
-
1203
- tree.toAscii()
1204
- # => "
1205
- -directory2
1206
- -main.coffee
1207
- -source
1208
- -main.coffee
1209
- -player.coffee
1210
- "
1211
-
1212
- Returns a String representation of the sorted nodes of the file tree.
1213
- */
1214
-
1215
- rootCollection = collection || this.root.collection;
1216
- spaces = "";
1217
- for (n = _i = 0; 0 <= indentation ? _i <= indentation : _i >= indentation; n = 0 <= indentation ? ++_i : --_i) {
1218
- spaces += " ";
1219
- }
1220
- rootCollection.each(function(nodes) {
1221
- var typeChar;
1222
- typeChar = nodes.get('type') === 'directory' ? '+' : '-';
1223
- output += spaces + typeChar + nodes.nameWithExtension() + '\n';
1224
- return output = _this.toAscii(nodes.collection, indentation + 1, output);
1225
- });
1226
- return output;
1227
- };
1228
-
1229
- Tree.prototype.getModelFromClick = function(e) {
1230
- /*
1231
- Internal: Look up a model based on the cid of the clicked view element.
1232
-
1233
- Returns the Node corresponding to the view element that the user clicked on.
1234
- */
1235
-
1236
- var cid;
1237
- e.stopPropagation();
1238
- this.menuView.$el.hide();
1239
- cid = $(e.currentTarget).data('cid');
1240
- return this.getModelByCid(cid);
1241
- };
1242
-
1243
- Tree.prototype._openDirectory = function(e) {
1244
- /*
1245
- Internal: Toggle the directory icon and display the contents of the clicked Directory.
1246
- */
1247
-
1248
- var model;
1249
- model = this.getModelFromClick(e);
1250
- return model.toggleOpen();
1251
- };
1252
-
1253
- Tree.prototype._openFile = function(e) {
1254
- /*
1255
- Internal: Trigger the 'openFile' event, passing in the file corresponding
1256
- to the view element that the user clicked.
1257
- */
1258
-
1259
- var model;
1260
- model = this.getModelFromClick(e);
1261
- return this.trigger('openFile', model);
1262
- };
1263
-
1264
- Tree.prototype.render = function() {
1265
- /*
1266
- Internal: Call render on each of the nodes underneath the root node.
1267
- Also calls sort on each of the subcollections.
1268
- */
1269
-
1270
- var _this = this;
1271
- this.root.collection.sort().each(function(node) {
1272
- var view;
1273
- node.collection.sort();
1274
- view = _this.findOrCreateView(node);
1275
- if (!view.model.get('hidden')) {
1276
- return _this.$el.append(view.render().$el);
1277
- }
1278
- });
1279
- return this;
1280
- };
1281
-
1282
- return Tree;
1283
-
1284
- })(Backbone.View);
1285
- });
1286
-
1287
- }).call(this);
1288
- (function() {
1289
-
1290
-
1291
-
1292
- }).call(this);
@@ -1 +0,0 @@
1
- #= require ./bone_tree