bone_tree 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +17 -0
  3. data/Gemfile.lock +190 -0
  4. data/Guardfile +14 -0
  5. data/README +1 -0
  6. data/Rakefile +21 -0
  7. data/app/assets/images/bonetree.png +0 -0
  8. data/app/assets/images/crushed_bone.png +0 -0
  9. data/app/assets/index.html +439 -0
  10. data/app/assets/javascripts/bone_tree.js +1292 -0
  11. data/app/assets/stylesheets/bone_tree.css +186 -0
  12. data/app/assets/stylesheets/bone_tree_repo.css +73 -0
  13. data/bone_tree-0.0.1.gem +0 -0
  14. data/bone_tree.gemspec +20 -0
  15. data/config.rb +26 -0
  16. data/config.ru +4 -0
  17. data/docs/index.html +222 -0
  18. data/docs/resources/base.css +70 -0
  19. data/docs/resources/index.css +20 -0
  20. data/docs/resources/module.css +24 -0
  21. data/docs/source/javascripts/bone_tree/_namespace.js.html +45 -0
  22. data/docs/source/javascripts/bone_tree/models/_directory.js.html +126 -0
  23. data/docs/source/javascripts/bone_tree/models/_file.js.html +112 -0
  24. data/docs/source/javascripts/bone_tree/models/_nodes.js.html +174 -0
  25. data/docs/source/javascripts/bone_tree/models/_settings.js.html +75 -0
  26. data/docs/source/javascripts/bone_tree/views/_directory.js.html +94 -0
  27. data/docs/source/javascripts/bone_tree/views/_file.js.html +82 -0
  28. data/docs/source/javascripts/bone_tree/views/_menu.js.html +110 -0
  29. data/docs/source/javascripts/bone_tree/views/_tree.js.html +432 -0
  30. data/lib/version.rb +4 -0
  31. data/source/images/bonetree.png +0 -0
  32. data/source/images/crushed_bone.png +0 -0
  33. data/source/index.html.haml +438 -0
  34. data/source/javascripts/_backbone.js +1293 -0
  35. data/source/javascripts/_jquery.min.js +5 -0
  36. data/source/javascripts/_underscore.js +999 -0
  37. data/source/javascripts/bone_tree/_namespace.js.coffee +7 -0
  38. data/source/javascripts/bone_tree/models/_directory.js.coffee +63 -0
  39. data/source/javascripts/bone_tree/models/_file.js.coffee +55 -0
  40. data/source/javascripts/bone_tree/models/_nodes.js.coffee +117 -0
  41. data/source/javascripts/bone_tree/models/_settings.js.coffee +25 -0
  42. data/source/javascripts/bone_tree/views/_directory.js.coffee +73 -0
  43. data/source/javascripts/bone_tree/views/_file.js.coffee +49 -0
  44. data/source/javascripts/bone_tree/views/_menu.js.coffee +97 -0
  45. data/source/javascripts/bone_tree/views/_tree.js.coffee +498 -0
  46. data/source/javascripts/bone_tree.js.coffee +1 -0
  47. data/source/layout.haml +13 -0
  48. data/source/stylesheets/bone_tree.css.sass +107 -0
  49. data/source/stylesheets/bone_tree_repo.css.sass +65 -0
  50. data/spec/javascripts/directory_view_spec.coffee +91 -0
  51. data/spec/javascripts/file_view_spec.coffee +70 -0
  52. data/spec/javascripts/helpers/spec_helper.coffee +7 -0
  53. data/spec/javascripts/menu_view_spec.coffee +42 -0
  54. data/spec/javascripts/nodes_spec.coffee +37 -0
  55. data/spec/javascripts/support/jasmine.yml +8 -0
  56. data/spec/javascripts/support/jasmine_config.rb +23 -0
  57. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  58. data/spec/javascripts/tree_view_spec.coffee +39 -0
  59. metadata +123 -0
@@ -0,0 +1,7 @@
1
+ window.BoneTree = {}
2
+
3
+ BoneTree.namespace = (target, name, block) ->
4
+ [target, name, block] = [(if typeof exports isnt 'undefined' then exports else window), arguments...] if arguments.length < 3
5
+ top = target
6
+ target = target[item] or= {} for item in name.split '.'
7
+ block target, top
@@ -0,0 +1,63 @@
1
+ #= require ./_nodes
2
+
3
+ BoneTree.namespace "BoneTree.Models", (Models) ->
4
+ class Models.Directory extends Models.Node
5
+ ###
6
+ Public: Object representing a directory.
7
+
8
+ * defaults
9
+ * name - A String naming the directory (default: "New Directory").
10
+ * sortPriority - A String representing the priority with which the
11
+ node is sorted. Directories have sortPriority "0"
12
+ allowing them to be sorted before Files which have
13
+ sortPriority "1".
14
+ * nodeType - A String denoting what type of node this object is.
15
+ The two types are "file" and "directory".
16
+ * open - The state of the directory. Controls whether or not
17
+ to display files and directories contained within this
18
+ Directory (default: false).
19
+
20
+ ###
21
+ defaults:
22
+ name: "New Directory"
23
+ open: false
24
+ sortPriority: "0"
25
+ nodeType: "directory"
26
+
27
+ toggleOpen: =>
28
+ ###
29
+ Public: Toggle the open state of this Directory.
30
+
31
+ Examples
32
+
33
+ dir = new BoneTree.Models.Directory
34
+
35
+ dir.get('open')
36
+ # => false
37
+
38
+ dir.toggleOpen()
39
+ dir.get('open')
40
+ # => true
41
+
42
+ Returns this Directory.
43
+ ###
44
+ currentState = @get 'open'
45
+
46
+ @set {open: not currentState}
47
+
48
+ Models.Directory.find = (currentDirectory, name) ->
49
+ ###
50
+ Internal: Check to see if there is a directory with the matching name
51
+ contained within currentDirectory.
52
+
53
+ * currentDirectory - A Directory object to search for the matching directory name.
54
+
55
+ * name - A String name used to check for matching directory
56
+ names in currentDirectory.
57
+
58
+ Returns The Directory object with the matching name if it exists and undefined otherwise.
59
+ ###
60
+ currentDirectory.collection.find (dir) ->
61
+ dir.get('name') is name
62
+
63
+
@@ -0,0 +1,55 @@
1
+ #= require ./_nodes
2
+
3
+ BoneTree.namespace "BoneTree.Models", (Models) ->
4
+ class Models.File extends Models.Node
5
+ ###
6
+ Public: Object representing file data in the tree.
7
+
8
+ * defaults
9
+ * name - A String naming the file (default: "New File").
10
+ * sortPriority - A String representing the priority with which the
11
+ node is sorted. Directories have sortPriority "0"
12
+ allowing them to be sorted before Files which have
13
+ sortPriority "1".
14
+ * nodeType - A String denoting what type of node this object is.
15
+ The two types are "file" and "directory".
16
+
17
+ ###
18
+ defaults:
19
+ name: "New File"
20
+ sortPriority: "1"
21
+ nodeType: "file"
22
+
23
+ Models.File.createFromFileName = (fileName, fileData) ->
24
+ ###
25
+ Public: Class method to create a new File object based on the fileName
26
+ and fileData passed in.
27
+
28
+ * fileName - A String representing the name of the file to be created.
29
+ files with '.' in the name will be parsed out and only the
30
+ string after the final '.' will be considered the extension.
31
+
32
+ * fileData - An Object of attributes to associate with the file.
33
+
34
+ Examples
35
+
36
+ data = {
37
+ contents: alert 'this is the code in the file'
38
+ createdAt: 1330846900589
39
+ language: 'CoffeeScript'
40
+ }
41
+
42
+ BoneTree.Models.File.createFromFileName('example.coffee', data)
43
+ # => <File>
44
+
45
+ Returns the File object just created.
46
+ ###
47
+
48
+ # Make sure that files like jquery.min.js work
49
+ [names..., extension] = fileName.split "."
50
+ name = names.join('.')
51
+
52
+ data = _.extend({}, fileData, {name: name, extension: extension})
53
+
54
+ return new Models.File(data)
55
+
@@ -0,0 +1,117 @@
1
+ BoneTree.namespace "BoneTree.Models", (Models) ->
2
+ class Models.Node extends Backbone.Model
3
+ ###
4
+ Internal: An abstract super class for File and Directory objects to inherit from.
5
+
6
+ ###
7
+ initialize: ->
8
+ ###
9
+ Internal: Initialize a new Node object. Set it up to contain a collection of
10
+ children nodes.
11
+
12
+ ###
13
+ @collection = new Models.Nodes
14
+
15
+ constantize: =>
16
+ ###
17
+ Public: Returns a String with the nodeType capitalized so that it may be used
18
+ to instatiate the appropriate view type
19
+
20
+ Examples
21
+
22
+ file = new BoneTree.Models.File
23
+ directory = new BoneTree.Models.Directory
24
+
25
+ file.constantize()
26
+ # => 'File'
27
+
28
+ directory.constantize()
29
+ # => 'Directory'
30
+
31
+ # use it to create a new view of the appropriate type
32
+ view = new BoneTree.Views[file.constantize()]
33
+
34
+ Returns a String of the nodeType with the first letter capitalized.
35
+ ###
36
+ nodeType = @get('nodeType')
37
+
38
+ nodeType[0].toUpperCase() + nodeType.substring(1)
39
+
40
+ nameWithExtension: =>
41
+ ###
42
+ Public: Returns the node name with the extension if it has
43
+ one and just the node name if there is no extension.
44
+
45
+ Examples
46
+
47
+ file = new BoneTree.Models.File
48
+ name: "file"
49
+ extension: "coffee"
50
+
51
+ noExt = new BoneTree.Models.File
52
+ name: "file2"
53
+
54
+ directory = new BoneTree.Model.Directory
55
+ name: "source"
56
+
57
+ file.nameWithExtension()
58
+ # => "file.coffee"
59
+
60
+ noExt.nameWithExtension()
61
+ # => "file2"
62
+
63
+ directory.nameWithExtension()
64
+ # => "source"
65
+
66
+ Returns a String. If the extension exists then the node name plus the extension
67
+ are returned. If there is no extension, then just the node name is returned.
68
+ ###
69
+ {extension, name} = @attributes
70
+
71
+ extension ||= ""
72
+
73
+ if extension isnt ""
74
+ extension = "." + extension
75
+
76
+ return name + extension
77
+
78
+ class Models.Nodes extends Backbone.Collection
79
+ ###
80
+ Internal: A collection of node models. Since Node is an abstract super
81
+ class, in practice this collection will hold File objects
82
+ and Directory objects.
83
+
84
+ ###
85
+ comparator: (node) ->
86
+ ###
87
+ Internal: Function that determines how the file tree is sorted. Directories
88
+ are sorted before files. After node type sort
89
+ priority, nodes are sorted by name.
90
+
91
+ Examples
92
+
93
+ tree.addFile('/source/file1.coffee')
94
+ tree.addFile('/source/file2.coffee')
95
+ tree.addFile('main.coffee')
96
+
97
+ tree.render()
98
+
99
+ # even though 'main' comes before 'source' alphabetically it is placed
100
+ # after the 'source' directory due to the sortPriority of the Directory object.
101
+ tree.toAscii()
102
+ # => "
103
+ -source
104
+ -file1.coffee
105
+ -file2.coffee
106
+ -main.coffee
107
+ "
108
+
109
+ ###
110
+ {name, sortPriority} = node.attributes
111
+
112
+ return sortPriority + name
113
+
114
+ model: Models.Node
115
+
116
+
117
+
@@ -0,0 +1,25 @@
1
+ BoneTree.namespace "BoneTree.Models", (Models) ->
2
+ class Models.Settings extends Backbone.Model
3
+ ###
4
+ Internal: A configuration object. Consumers of the API don't need to
5
+ worry about this. It is used internally to manage the options
6
+ passed into the file tree.
7
+
8
+ * defaults
9
+ * beforeAdd - A Function that is invoked before each file is added to the tree.
10
+ It is passed the raw file attributes and should return true if
11
+ that file should be added to the tree and false if not. The
12
+ default implementation is to return true.
13
+ * confirmDeletes - A Boolean. If true, the tree will prompt the user, making
14
+ sure they want to delete the file (default: false).
15
+ * showExtensions - A Boolean. If true, files display their extensions. Internally,
16
+ extensions are always kept track of but by default they are
17
+ hidden (default: false).
18
+ * viewCache - An Object that stores views when they are created and is used
19
+ to look them up to prevent extra views from being created.
20
+ ###
21
+ defaults:
22
+ confirmDeletes: false
23
+ showExtensions: false
24
+ viewCache: {}
25
+
@@ -0,0 +1,73 @@
1
+ BoneTree.namespace "BoneTree.Views", (Views) ->
2
+ class Views.Directory extends Backbone.View
3
+ ###
4
+ Internal: View that renders a Directory node and controls its behavior (class: 'directory', tag: 'ul').
5
+
6
+ ###
7
+ className: 'directory'
8
+ tagName: 'ul'
9
+
10
+ initialize: (options) ->
11
+ ###
12
+ Internal: Initialize a new directory node. Adds associated model cid to the
13
+ view element. Binds change handler to the `change:open` event that
14
+ toggles the display of directory contents. Binds change handler to
15
+ the `change:name` event that re-renders a sorted file tree.
16
+
17
+ * options - Passes in settings object, which is used for access to the
18
+ tree view root in order to proxy events to it.
19
+
20
+ ###
21
+ @settings = options.settings
22
+
23
+ @$el.attr 'data-cid', @model.cid
24
+
25
+ @model.bind 'change:open', (model, open) =>
26
+ @displayChildren(open)
27
+
28
+ @model.bind 'change:name', (model, name) =>
29
+ treeView = @settings.get 'treeView'
30
+ treeView.render().trigger 'rename', model, name
31
+
32
+ @model.collection.bind 'add', @render
33
+
34
+ @model.collection.bind 'remove', (model, collection) =>
35
+ @settings.get('treeView').trigger 'remove', model
36
+ @render()
37
+
38
+ @displayChildren(@model.get('open'))
39
+
40
+ appendView: (node) =>
41
+ ###
42
+ Internal: Appends a view based on the underlying node model to this view.
43
+
44
+ node - A Node model. Either a File or a Directory. This is the model the
45
+ created view will be associated with.
46
+
47
+ ###
48
+ view = @settings.get('treeView').findOrCreateView(node)
49
+
50
+ @$el.append view.render().$el
51
+
52
+ render: =>
53
+ ###
54
+ Internal: Set the text of the view element based on the underlying model name.
55
+
56
+ Returns `this` view.
57
+ ###
58
+ @$el.text @model.get('name')
59
+
60
+ @model.collection.sort().each @appendView
61
+
62
+ return @
63
+
64
+ displayChildren: (open) =>
65
+ ###
66
+ Internal: Toggles display of the children Files or Diretories of this view.
67
+
68
+ ###
69
+ fileDirChildren = @$el.children('.directory, .file')
70
+
71
+ @$el.toggleClass('open', open)
72
+ fileDirChildren.toggle(open)
73
+
@@ -0,0 +1,49 @@
1
+ BoneTree.namespace "BoneTree.Views", (Views) ->
2
+ class Views.File extends Backbone.View
3
+ ###
4
+ Internal: View that renders a File node and controls its behavior (class: 'file', tag: 'li').
5
+
6
+ ###
7
+ className: 'file'
8
+ tagName: 'li'
9
+
10
+ initialize: (options) ->
11
+ ###
12
+ Internal: Initialize a new file node. Adds associated model cid to the
13
+ view element. Binds change handlers to the `change:name` and
14
+ `change:extension` events. These take care of resorting the file
15
+ nodes.
16
+
17
+ * options - Passes in settings object, which is used to control
18
+ whether or not file extensions are shown.
19
+
20
+ ###
21
+ @settings = options.settings
22
+
23
+ @$el.attr('data-cid', @model.cid).addClass(@model.get('extension'))
24
+
25
+ @model.bind 'change:name', (model, name) =>
26
+ treeView = @settings.get('treeView')
27
+ treeView.render().trigger 'rename', model, model.nameWithExtension()
28
+
29
+ @model.bind 'change:extension', (model, extension) =>
30
+ @$el.attr('class', "file #{extension}")
31
+
32
+ treeView = @settings.get('treeView')
33
+ treeView.render().trigger 'rename', model, model.nameWithExtension()
34
+
35
+ render: =>
36
+ ###
37
+ Internal: Sets the text of the file node according to the underlying model
38
+ name. If the 'showExtensions' setting is set, renders the
39
+ full file name with extension, otherwise renders just the file
40
+ name attribute.
41
+
42
+ ###
43
+ if @settings.get('showExtensions')
44
+ @$el.text @model.nameWithExtension()
45
+ else
46
+ @$el.text @model.get('name')
47
+
48
+ return @
49
+
@@ -0,0 +1,97 @@
1
+ BoneTree.namespace "BoneTree.Views", (Views) ->
2
+ class Views.Menu extends Backbone.View
3
+ ###
4
+ Internal: View that controls the context menu (class: 'filetree\_context\_menu').
5
+
6
+ Events
7
+
8
+ * contextMenu - Prevents the standard browser context menu from appearing
9
+ when right clicking within the file tree context menu.
10
+
11
+ * click .rename - Prompts the user to rename a file.
12
+
13
+ * click .delete - Deletes a node from the file tree.
14
+
15
+ ###
16
+ className: 'filetree_context_menu'
17
+
18
+ events:
19
+ 'contextmenu': 'contextMenu'
20
+ 'click .rename': 'rename'
21
+ 'click .delete': 'delete'
22
+
23
+ initialize: (options) ->
24
+ ###
25
+ Internal: Initialize a new menu widget.
26
+
27
+ * options - An Object. Internally used to pass the settings configuration
28
+ into the menu. This controls whether or not the user is
29
+ prompted to confirm deleting a file.
30
+
31
+ ###
32
+ @settings = options.settings
33
+
34
+ contextMenu: (e) =>
35
+ ###
36
+ Internal: Kill the default browser behavior for the contextmenu event.
37
+
38
+ ###
39
+ e.preventDefault()
40
+ e.stopPropagation()
41
+
42
+ delete: (e) =>
43
+ ###
44
+ Internal: Deletes a node from the file tree. If the confirmDeletes setting
45
+ is set, prompts the user for delete confirmation.
46
+
47
+ ###
48
+ if @settings.get('confirmDeletes')
49
+ if confirm "Are you sure you want to delete '#{@model.nameWithExtension()}'?"
50
+ @model.destroy()
51
+ else
52
+ @model.destroy()
53
+
54
+ @$el.hide()
55
+
56
+ rename: (e) =>
57
+ ###
58
+ Internal: Prompts the user to rename a File or Directory.
59
+
60
+ ###
61
+ if newName = prompt "New Name", @model.nameWithExtension()
62
+ [fileName, extension] = newName.split "."
63
+
64
+ extension ?= ""
65
+
66
+ @model.set
67
+ name: fileName
68
+ extension: extension
69
+
70
+ @$el.hide()
71
+
72
+ render: =>
73
+ ###
74
+ Internal: Renders the <ul> that contains the context menu choices
75
+ 'Rename' and 'Delete'.
76
+
77
+ Returns `this`, the menu view.
78
+ ###
79
+
80
+ @$el.html @template()
81
+
82
+ return @
83
+
84
+ template: ->
85
+ ###
86
+ Internal: html template for the context menu.
87
+
88
+ ###
89
+ """
90
+ <ul>
91
+ <li class='rename'>Rename</li>
92
+ <hr/>
93
+ <li class='delete'>Delete</li>
94
+ </ul>
95
+ """
96
+
97
+