Skip to content
  • Watch
  • Fork

/angular-bootstrap-nav-tree

HTTPS clone URL

SSH clone URL

Subversion checkout URL

You can clone with HTTPS, SSH, or Subversion.

Clone in Desktop Download ZIP
branch: master
480 lines (372 sloc) 11.835 kb
module = angular.module 'angularBootstrapNavTree',[]
module.directive 'abnTree',['$timeout',($timeout)->
restrict:'E'
#templateUrl: '../dist/abn_tree_template.html' # <--- another way to do this
template: """{html}""" # will be replaced by Grunt, during build, with the actual Template HTML
replace:true
scope:
treeData:'='
onSelect:'&'
initialSelection:'@'
treeControl:'='
link:(scope,element,attrs)->
error = (s) ->
console.log 'ERROR:'+s
debugger
return undefined
# default values ( Font-Awesome 3 or 4 or Glyphicons )
attrs.iconExpand ?= 'icon-plus glyphicon glyphicon-plus fa fa-plus'
attrs.iconCollapse ?= 'icon-minus glyphicon glyphicon-minus fa fa-minus'
attrs.iconLeaf ?= 'icon-file glyphicon glyphicon-file fa fa-file'
attrs.expandLevel ?= '3'
expand_level = parseInt attrs.expandLevel,10
# check args
if !scope.treeData
alert 'no treeData defined for the tree!'
return
if !scope.treeData.length?
if treeData.label?
scope.treeData = [ treeData ]
else
alert 'treeData should be an array of root branches'
return
#
# internal utilities...
#
for_each_branch = (f)->
do_f = (branch,level)->
f(branch,level)
if branch.children?
for child in branch.children
do_f(child,level + 1)
for root_branch in scope.treeData
do_f(root_branch,1)
#
# only one branch can be selected at a time
#
selected_branch = null
select_branch = (branch)->
if not branch
if selected_branch?
selected_branch.selected = false
selected_branch = null
return
if branch isnt selected_branch
if selected_branch?
selected_branch.selected = false
branch.selected = true
selected_branch = branch
expand_all_parents(branch)
#
# check:
# 1) branch.onSelect
# 2) tree.onSelect
#
if branch.onSelect?
#
# use $timeout
# so that the branch becomes fully selected
# ( and highlighted )
# before calling the "onSelect" function.
#
$timeout ->
branch.onSelect(branch)
else
if scope.onSelect?
$timeout ->
scope.onSelect({branch:branch})
scope.user_clicks_branch = (branch)->
if branch isnt selected_branch
select_branch(branch)
get_parent = (child)->
parent = undefined
if child.parent_uid
for_each_branch (b)->
if b.uid == child.parent_uid
parent = b
return parent
for_all_ancestors = ( child, fn )->
parent = get_parent( child )
if parent?
fn( parent )
for_all_ancestors( parent, fn )
expand_all_parents = ( child )->
for_all_ancestors child, (b)->
b.expanded = true
#
# To make the Angular rendering simpler,
# ( and to avoid recursive templates )
# we transform the TREE of data into a LIST of data.
# ( "tree_rows" )
#
# We do this whenever data in the tree changes.
# The tree itself is bound to this list.
#
# Children of un-expanded parents are included,
# but are set to "visible:false"
# ( and then they filtered out during rendering )
#
scope.tree_rows = []
on_treeData_change = ->
#console.log 'tree-data-change!'
#
# if "children" is just a list of strings...
# ...change them into objects:
#
for_each_branch (branch)->
if branch.children
if branch.children.length > 0
# don't use Array.map ( old browsers don't have it )
f = (e)->
if typeof e == 'string'
label:e
children:[]
else
e
branch.children = ( f(child) for child in branch.children )
else
branch.children = []
# give each Branch a UID ( to keep AngularJS happy )
for_each_branch (b,level)->
if not b.uid
b.uid = ""+Math.random()
console.log 'UIDs are set.'
# set all parents:
for_each_branch (b)->
if angular.isArray b.children
for child in b.children
child.parent_uid = b.uid
scope.tree_rows = []
#
# add_branch_to_list: recursively add one branch
# and all of it's children to the list
#
add_branch_to_list = (level,branch,visible)->
if not branch.expanded?
branch.expanded = false
if not branch.classes?
branch.classes = []
#
# icons can be Bootstrap or Font-Awesome icons:
# they will be rendered like:
# <i class="icon-plus"></i>
#
if not branch.noLeaf and (not branch.children or branch.children.length == 0)
tree_icon = attrs.iconLeaf
branch.classes.push "leaf" if "leaf" not in branch.classes
else
if branch.expanded
tree_icon = attrs.iconCollapse
else
tree_icon = attrs.iconExpand
#
# append to the list of "Tree Row" objects:
#
scope.tree_rows.push
level : level
branch : branch
label : branch.label
classes : branch.classes
tree_icon : tree_icon
visible : visible
#
# recursively add all children of this branch...( at Level+1 )
#
if branch.children?
for child in branch.children
#
# all branches are added to the list,
# but some are not visible
# ( if parent is collapsed )
#
child_visible = visible and branch.expanded
add_branch_to_list level+1, child, child_visible
#
# start with root branches,
# and recursively add all children to the list
#
for root_branch in scope.treeData
add_branch_to_list 1, root_branch, true
#
# make sure to do a "deep watch" on the tree data
# ( by passing "true" as the third arg )
#
scope.$watch 'treeData',on_treeData_change,true
#
# initial-selection="Branch Label"
# if specified, find and select the branch:
#
if attrs.initialSelection?
for_each_branch (b)->
if b.label == attrs.initialSelection
$timeout ->
select_branch b
#
# expand to the proper level
#
n = scope.treeData.length
console.log 'num root branches = '+n
for_each_branch (b,level)->
b.level = level
b.expanded = b.level < expand_level
#b.expanded = false
#
# TREE-CONTROL : the API to the Tree
#
# if we have been given an Object for this,
# then we attach all of tree-control functions
# to that given object:
#
if scope.treeControl?
if angular.isObject scope.treeControl
tree = scope.treeControl
tree.expand_all = ->
for_each_branch (b,level)->
b.expanded = true
tree.collapse_all = ->
for_each_branch (b,level)->
b.expanded = false
tree.get_first_branch = ->
n = scope.treeData.length
if n > 0
return scope.treeData[0]
tree.select_first_branch = ->
b = tree.get_first_branch()
tree.select_branch(b)
tree.get_selected_branch = ->
selected_branch
tree.get_parent_branch = (b)->
get_parent(b)
tree.select_branch = (b)->
select_branch(b)
b
tree.get_children = (b)->
b.children
tree.select_parent_branch = (b)->
if not b?
b = tree.get_selected_branch()
if b?
p = tree.get_parent_branch(b)
if p?
tree.select_branch(p)
p
tree.add_branch = (parent,new_branch)->
if parent?
parent.children.push new_branch
parent.expanded = true
else
scope.treeData.push new_branch
#tree.select new_branch
new_branch
tree.add_root_branch = (new_branch)->
tree.add_branch null, new_branch
new_branch
tree.expand_branch = (b)->
if not b?
b = tree.get_selected_branch()
if b?
b.expanded = true
b
tree.collapse_branch = (b)->
b ?= selected_branch
if b?
b.expanded = false
b
tree.get_siblings = (b)->
b ?= selected_branch
if b?
p = tree.get_parent_branch(b)
if p
siblings = p.children
else
siblings = scope.treeData # the root branches
return siblings
tree.get_next_sibling = (b)->
b ?= selected_branch
if b?
siblings = tree.get_siblings(b)
n = siblings.length
i = siblings.indexOf b
if i < n
return siblings[i+1]
tree.get_prev_sibling = (b)->
b ?= selected_branch
siblings = tree.get_siblings(b)
n = siblings.length
i = siblings.indexOf b
if i > 0
return siblings[i-1]
tree.select_next_sibling = (b)->
b ?= selected_branch
if b?
next = tree.get_next_sibling(b)
if next?
tree.select_branch next
tree.select_prev_sibling = (b)->
b ?= selected_branch
if b?
prev = tree.get_prev_sibling(b)
if prev?
tree.select_branch prev
tree.get_first_child = (b)->
b ?= selected_branch
if b?
if b.children?.length > 0
return b.children[0]
tree.get_closest_ancestor_next_sibling = (b)->
next = tree.get_next_sibling(b)
if next?
return next
else
parent = tree.get_parent_branch(b)
return tree.get_closest_ancestor_next_sibling(parent)
tree.get_next_branch = (b)->
#
# "next" in the sense of...vertically, from top to bottom
#
# try:
# 1) next sibling
# 2) first child
# 3) parent.get_next() // recursive
#
b ?= selected_branch
if b?
next = tree.get_first_child(b)
if next?
return next
else
next = tree.get_closest_ancestor_next_sibling(b)
return next
tree.select_next_branch = (b)->
b ?= selected_branch
if b?
next = tree.get_next_branch(b)
if next?
tree.select_branch(next)
next
tree.last_descendant = (b)->
if not b?
debugger
n = b.children.length
if n == 0
return b
else
last_child = b.children[n-1]
return tree.last_descendant(last_child)
tree.get_prev_branch = (b)->
b ?= selected_branch
if b?
prev_sibling = tree.get_prev_sibling(b)
if prev_sibling?
return tree.last_descendant prev_sibling
else
parent = tree.get_parent_branch(b)
return parent
tree.select_prev_branch = (b)->
b ?= selected_branch
if b?
prev = tree.get_prev_branch(b)
if prev?
tree.select_branch(prev)
return prev
]
Jump to Line
Something went wrong with that request. Please try again.