6 return Position.strings[position - 1]
9 for i in [1..Position.strings.length]
10 if Position.strings[i - 1] == name
19 Position.strings = ['before', 'after', 'inside', 'none']
22 constructor: (o, is_root=false, node_class=Node) ->
33 @node_class = node_class
37 Set the data of this node.
39 setData(string): set the name of the node
40 setdata(object): set attributes of the node
45 setData({ name: 'node1', id: 1});
47 setData({ name: 'node2', id: 2, color: 'green'});
49 * This is an internal function; it is not in the docs
50 * Does not remove existing node values
56 if typeof o != 'object'
61 # You can use the 'label' key instead of 'name'; this is a legacy feature
63 else if key != 'children'
64 # You can't update the children using this function
69 # Init Node from data without making it the root of the tree
70 initFromData: (data) ->
71 addNode = (node_data) =>
75 addChildren(node_data.children)
77 addChildren = (children_data) =>
78 for child in children_data
79 node = new @tree.node_class('')
80 node.initFromData(child)
88 Create tree from data.
104 loadFromData: (data) ->
108 node = new @tree.node_class(o)
111 if typeof o == 'object' and o.children
112 node.loadFromData(o.children)
125 node._setParent(this)
128 Add child at position. Index starts at 0.
130 tree.addChildAtPosition(
135 addChildAtPosition: (node, index) ->
136 @children.splice(index, 0, node)
137 node._setParent(this)
139 _setParent: (parent) ->
142 @tree.addNodeToIndex(this)
145 Remove child. This also removes the children of the node.
147 tree.removeChild(tree.children[0]);
149 removeChild: (node) ->
150 # remove children from the index
151 node.removeChildren()
155 _removeChild: (node) ->
157 @getChildIndex(node),
160 @tree.removeNodeFromIndex(node)
165 var index = getChildIndex(node);
167 getChildIndex: (node) ->
168 return $.inArray(node, @children)
171 Does the tree have children?
173 if (tree.hasChildren()) {
178 return @children.length != 0
181 return @hasChildren() or @load_on_demand
184 Iterate over all the nodes in the tree.
186 Calls callback with (node, level).
188 The callback must return true to continue the iteration on current node.
191 function(node, level) {
192 console.log(node.name);
194 // stop iteration after level 2
200 iterate: (callback) ->
201 _iterate = (node, level) ->
203 for child in node.children
204 result = callback(child, level)
206 if result and child.hasChildren()
207 _iterate(child, level + 1)
214 Move node relative to another node.
216 Argument position: Position.BEFORE, Position.AFTER or Position.Inside
218 // move node1 after node2
219 tree.moveNode(node1, node2, Position.AFTER);
221 moveNode: (moved_node, target_node, position) ->
222 if moved_node.isParentOf(target_node)
223 # Node is parent of target node. This is an illegal move
226 moved_node.parent._removeChild(moved_node)
227 if position == Position.AFTER
228 target_node.parent.addChildAtPosition(
230 target_node.parent.getChildIndex(target_node) + 1
232 else if position == Position.BEFORE
233 target_node.parent.addChildAtPosition(
235 target_node.parent.getChildIndex(target_node)
237 else if position == Position.INSIDE
238 # move inside as first child
239 target_node.addChildAtPosition(moved_node, 0)
242 Get the tree as data.
244 getData: (include_parent=false) ->
245 getDataFromNodes = (nodes) ->
253 k not in ['parent', 'children', 'element', 'tree'] and
254 Object.prototype.hasOwnProperty.call(node, k)
258 if node.hasChildren()
259 tmp_node.children = getDataFromNodes(node.children)
266 return getDataFromNodes([this])
268 return getDataFromNodes(@children)
270 getNodeByName: (name) ->
271 return @getNodeByCallback(
272 (node) -> (node.name == name)
275 getNodeByCallback: (callback) ->
290 addAfter: (node_info) ->
294 node = new @tree.node_class(node_info)
296 child_index = @parent.getChildIndex(this)
297 @parent.addChildAtPosition(node, child_index + 1)
299 if typeof node_info == 'object' and node_info.children and node_info.children.length
300 node.loadFromData(node_info.children)
304 addBefore: (node_info) ->
308 node = new @tree.node_class(node_info)
310 child_index = @parent.getChildIndex(this)
311 @parent.addChildAtPosition(node, child_index)
313 if typeof node_info == 'object' and node_info.children and node_info.children.length
314 node.loadFromData(node_info.children)
318 addParent: (node_info) ->
322 new_parent = new @tree.node_class(node_info)
323 new_parent._setParent(@tree)
324 original_parent = @parent
326 for child in original_parent.children
327 new_parent.addChild(child)
329 original_parent.children = []
330 original_parent.addChild(new_parent)
335 @parent.removeChild(this)
338 append: (node_info) ->
339 node = new @tree.node_class(node_info)
342 if typeof node_info == 'object' and node_info.children and node_info.children.length
343 node.loadFromData(node_info.children)
347 prepend: (node_info) ->
348 node = new @tree.node_class(node_info)
349 @addChildAtPosition(node, 0)
351 if typeof node_info == 'object' and node_info.children and node_info.children.length
352 node.loadFromData(node_info.children)
356 isParentOf: (node) ->
363 parent = parent.parent
377 getNodeById: (node_id) ->
378 return @id_mapping[node_id]
380 addNodeToIndex: (node) ->
382 @id_mapping[node.id] = node
384 removeNodeFromIndex: (node) ->
386 delete @id_mapping[node.id]
391 @tree.removeNodeFromIndex(child)
397 getPreviousSibling: ->
401 previous_index = @parent.getChildIndex(this) - 1
402 if previous_index >= 0
403 return @parent.children[previous_index]
411 next_index = @parent.getChildIndex(this) + 1
412 if next_index < @parent.children.length
413 return @parent.children[next_index]
417 getNodesByProperty: (key, value) ->
420 return node[key] == value
436 getNextNode: (include_children=true) ->
437 if include_children and @hasChildren() and @is_open
444 next_sibling = @getNextSibling()
449 # Next node of parent
450 return @parent.getNextNode(false)
456 previous_sibling = @getPreviousSibling()
458 if not previous_sibling.hasChildren() or not previous_sibling.is_open
460 return previous_sibling
462 # Last child of previous sibling
463 return previous_sibling.getLastChild()
468 # Return parent except if it is the root node
471 else if not @parent.parent
478 if not @hasChildren()
481 last_child = @children[@children.length - 1]
482 if not last_child.hasChildren() or not last_child.is_open
485 return last_child.getLastChild()