1 | if require? and module?
|
2 | async = require 'async'
|
3 | $ = require 'commonjs-jquery'
|
4 |
|
5 | bs_item_s = '.bs-item'
|
6 | bs_static = '.bs-static'
|
7 |
|
8 | memoize_width = (item) -> $(item).data width: $(item).outerWidth()
|
9 | read_width = (item) -> $(item).data().width
|
10 |
|
11 | animation =
|
12 | hide: (item, cb) ->
|
13 | animate_cb = ->
|
14 | $(item).hide()
|
15 | cb()
|
16 | memoize_width item
|
17 | $(item).animate({width: "0px", opacity: 0}, animate_cb)
|
18 |
|
19 | show: (item, cb) ->
|
20 | $(item).show()
|
21 | $(item).animate({width: read_width(item), opacity: 1}, -> cb())
|
22 |
|
23 |
|
24 | get_outer_width = (items) ->
|
25 | width_count_reduce_func = (a, b) ->
|
26 | a += ($ b).outerWidth()
|
27 |
|
28 | items.reduce width_count_reduce_func, 0
|
29 |
|
30 |
|
31 | init = (breadcumbs_wrapper, expander_class, on_animation_start, on_animation_end) ->
|
32 | collapsable_items = $(breadcumbs_wrapper).find("#{bs_item_s}:not(#{bs_static})").toArray()
|
33 | static_items = ($ bs_static).toArray()
|
34 |
|
35 | expander = $(collapsable_items[0]).clone()
|
36 | expander.text '...'
|
37 | expander.css {cursor: "pointer"}
|
38 | expander.addClass expander_class
|
39 |
|
40 | process
|
41 | result_width: get_outer_width collapsable_items.concat static_items
|
42 | allowed_width: $(breadcumbs_wrapper).width()
|
43 | collapsable_items: collapsable_items
|
44 | static_items: static_items
|
45 | expander: expander
|
46 | on_animation_start: on_animation_start
|
47 | on_animation_end: on_animation_end
|
48 |
|
49 |
|
50 | toggle_items = (collapsable_items, effect, action="show", cb) ->
|
51 | item_action = if effect?
|
52 | if action is "show"
|
53 | effect.show
|
54 | else
|
55 | effect.hide
|
56 | else
|
57 | if action is "show"
|
58 | (item, cb) ->
|
59 | $(item).show()
|
60 | cb()
|
61 | else
|
62 | (item, cb) ->
|
63 | $(item).hide()
|
64 | cb()
|
65 |
|
66 | async.map collapsable_items, item_action, (err, items) ->
|
67 | items.map (i) -> ($ i).hide()
|
68 | cb?()
|
69 |
|
70 |
|
71 | show_expander = (expander, item_after) ->
|
72 | expander.insertAfter item_after
|
73 |
|
74 |
|
75 | get_show_hide_items = (from_head=true, items, static_items, allowed_width) ->
|
76 | items.reverse()
|
77 | reduce_by_allowed_width = (a, b) ->
|
78 | [current_width, _items_to_hide, _items_to_show] = a
|
79 |
|
80 | new_width = ($ b).outerWidth() + current_width
|
81 |
|
82 | a = if new_width < allowed_width
|
83 | [new_width, _items_to_hide, _items_to_show.concat b]
|
84 | else
|
85 | [new_width, (_items_to_hide.concat b), _items_to_show]
|
86 |
|
87 | [width, items_to_hide, items_to_show] = items.reduce reduce_by_allowed_width, [get_outer_width(static_items), [], []]
|
88 | [items_to_hide, items_to_show]
|
89 |
|
90 |
|
91 | process = ({result_width
|
92 | allowed_width
|
93 | static_items
|
94 | expander
|
95 | collapsable_items
|
96 | on_animation_start
|
97 | on_animation_end}) ->
|
98 |
|
99 | if result_width > allowed_width
|
100 |
|
101 | [from_head_hide_items, from_head_show_items] = get_show_hide_items(
|
102 | true, collapsable_items, static_items, allowed_width)
|
103 |
|
104 | [from_tail_hide_items, from_tail_show_items] = get_show_hide_items(
|
105 | false, collapsable_items, static_items, allowed_width)
|
106 |
|
107 | toggle_items(from_head_hide_items, animation
|
108 | "hide"
|
109 | () -> show_expander expander, from_head_hide_items[0])
|
110 |
|
111 | from_head = true
|
112 |
|
113 | $(expander).click (ev) ->
|
114 | on_animation_start?()
|
115 | if from_head is true
|
116 | hide_from_head_visible = (cb) ->
|
117 | toggle_items from_tail_hide_items, animation, "hide", () -> cb()
|
118 |
|
119 | expander_change_position = (cb) ->
|
120 | show_expander expander, from_tail_show_items[-1..]
|
121 | cb()
|
122 |
|
123 | show_from_tail_visible = (cb) ->
|
124 | toggle_items from_tail_show_items, animation, "show", () ->
|
125 | cb()
|
126 |
|
127 | async.parallel(
|
128 | [
|
129 | hide_from_head_visible
|
130 | expander_change_position
|
131 | show_from_tail_visible
|
132 | ]
|
133 | () ->
|
134 | on_animation_end?()
|
135 | from_head = false)
|
136 | else
|
137 | hide_from_tail_head_visible = (cb) ->
|
138 | toggle_items from_head_hide_items, animation, "hide", () -> cb()
|
139 |
|
140 | expander_change_position = (cb) ->
|
141 | show_expander expander, from_head_hide_items[0]
|
142 | cb()
|
143 |
|
144 | show_from_tail_tail_visible = (cb) ->
|
145 | toggle_items from_tail_hide_items, animation, "show", () -> cb()
|
146 |
|
147 | async.parallel(
|
148 | [
|
149 | hide_from_tail_head_visible
|
150 | expander_change_position
|
151 | show_from_tail_tail_visible
|
152 | ]
|
153 | () ->
|
154 | on_animation_end?()
|
155 | from_head = true)
|
156 | if module?
|
157 | module.exports = init
|