constructor-core 0.9.1 → 1.0.0beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/.keep +0 -0
  3. data/app/assets/javascripts/constructor_core/application.js.coffee +15 -18
  4. data/app/assets/javascripts/constructor_core/expandable_tree/hashchange.js.coffee +33 -0
  5. data/app/assets/javascripts/constructor_core/expandable_tree/initializer.js.coffee +106 -0
  6. data/app/assets/javascripts/constructor_core/expandable_tree/jquery.cookie.coffee +68 -0
  7. data/app/assets/javascripts/constructor_core/expandable_tree/restorable.js.coffee +122 -0
  8. data/app/assets/javascripts/constructor_core/jquery.ui.nestedSortable.js +429 -0
  9. data/app/assets/javascripts/constructor_core/jquery_bundle.js.coffee +2 -1
  10. data/app/assets/javascripts/constructor_core/render_tree_helper.js.coffee +82 -0
  11. data/app/assets/javascripts/constructor_core/sortable_tree/initializer.js.coffee +54 -0
  12. data/app/assets/stylesheets/constructor_core/application.css.scss +24 -1
  13. data/app/assets/stylesheets/constructor_core/framework/all.scss +4 -0
  14. data/app/assets/stylesheets/constructor_core/framework/classes.scss +4 -0
  15. data/app/assets/stylesheets/constructor_core/framework/globals.scss +49 -0
  16. data/app/assets/stylesheets/constructor_core/framework/grid.scss +33 -0
  17. data/app/assets/stylesheets/constructor_core/framework/mixin.scss +193 -0
  18. data/app/assets/stylesheets/constructor_core/project/blocks/b-button/_color/b-button_color_light.scss +12 -0
  19. data/app/assets/stylesheets/constructor_core/project/blocks/b-button/_size/b-button_size_small.scss +7 -0
  20. data/app/assets/stylesheets/constructor_core/project/blocks/b-button/b-button.scss +29 -0
  21. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/__actions/b-form__actions.scss +3 -0
  22. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/__field/b-form__field.scss +12 -0
  23. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/__file/b-form__file.scss +12 -0
  24. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/__label/b-form__label.scss +7 -0
  25. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/__row/b-form__row.scss +4 -0
  26. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/b-form.scss +1 -0
  27. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/b-full-url/__icon/b-full-url__icon.scss +5 -0
  28. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/b-full-url/__path/b-full-url__path.scss +4 -0
  29. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/b-full-url/__url/b-full-url__url.scss +8 -0
  30. data/app/assets/stylesheets/constructor_core/project/blocks/b-form/b-full-url/b-full-url.scss +11 -0
  31. data/app/assets/stylesheets/constructor_core/project/blocks/b-header/b-header.scss +6 -0
  32. data/app/assets/stylesheets/constructor_core/project/blocks/b-login/__field/b-login__field.scss +13 -0
  33. data/app/assets/stylesheets/constructor_core/project/blocks/b-login/__label/b-login__label.scss +6 -0
  34. data/app/assets/stylesheets/constructor_core/project/blocks/b-login/__remember/b-login__remember.scss +4 -0
  35. data/app/assets/stylesheets/constructor_core/project/blocks/b-login/b-login.scss +8 -0
  36. data/app/assets/stylesheets/constructor_core/project/blocks/b-logo/b-logo.scss +15 -0
  37. data/app/assets/stylesheets/constructor_core/project/blocks/b-menu/__item-icon/b-menu__item-icon.scss +3 -0
  38. data/app/assets/stylesheets/constructor_core/project/blocks/b-menu/__item-link/_active/b-menu__item-link_active.scss +10 -0
  39. data/app/assets/stylesheets/constructor_core/project/blocks/b-menu/__item-link/b-menu__item-link.scss +13 -0
  40. data/app/assets/stylesheets/constructor_core/project/blocks/b-menu/__item/b-menu__item.scss +4 -0
  41. data/app/assets/stylesheets/constructor_core/project/blocks/b-menu/b-menu.scss +5 -0
  42. data/app/assets/stylesheets/constructor_core/project/blocks/b-profile/b-profile.scss +3 -0
  43. data/app/assets/stylesheets/constructor_core/project/blocks/b-tree/__expand/b-tree__expand.scss +10 -0
  44. data/app/assets/stylesheets/constructor_core/project/blocks/b-tree/__handle/b-tree__handle.scss +8 -0
  45. data/app/assets/stylesheets/constructor_core/project/blocks/b-tree/__item/b-tree__item.scss +5 -0
  46. data/app/assets/stylesheets/constructor_core/project/blocks/b-tree/__li/b-tree__li.scss +4 -0
  47. data/app/assets/stylesheets/constructor_core/project/blocks/b-tree/__link/b-tree__link.scss +14 -0
  48. data/app/assets/stylesheets/constructor_core/project/blocks/b-tree/__nested-set/b-tree__nested-set.scss +6 -0
  49. data/app/assets/stylesheets/constructor_core/project/blocks/b-tree/__url/b-tree__url.scss +5 -0
  50. data/app/assets/stylesheets/constructor_core/project/blocks/b-tree/b-tree.scss +5 -0
  51. data/app/assets/stylesheets/constructor_core/project/layouts/l-all/l-all.scss +4 -0
  52. data/app/assets/stylesheets/constructor_core/project/layouts/l-content/l-content.scss +3 -0
  53. data/app/assets/stylesheets/constructor_core/project/layouts/l-header/__avatar/l-header__avatar.scss +5 -0
  54. data/app/assets/stylesheets/constructor_core/project/layouts/l-header/__email/l-header__email.scss +12 -0
  55. data/app/assets/stylesheets/constructor_core/project/layouts/l-header/__link-icon/l-header__link-icon.scss +4 -0
  56. data/app/assets/stylesheets/constructor_core/project/layouts/l-header/__link/l-header__link.scss +12 -0
  57. data/app/assets/stylesheets/constructor_core/project/layouts/l-header/__logout/l-header__logout.scss +11 -0
  58. data/app/assets/stylesheets/constructor_core/project/layouts/l-header/__profile/l-header__profile.scss +4 -0
  59. data/app/assets/stylesheets/constructor_core/project/layouts/l-header/l-header.scss +7 -0
  60. data/app/assets/stylesheets/constructor_core/project/layouts/l-pages/l-pages.scss +3 -0
  61. data/app/assets/stylesheets/constructor_core/project/layouts/l-sidebar/l-sidebar.scss +7 -0
  62. data/app/controllers/constructor_core/sessions_controller.rb +1 -1
  63. data/app/helpers/constructor_core/application_helper.rb +6 -0
  64. data/app/helpers/render_expandable_tree_helper.rb +51 -0
  65. data/app/views/constructor_core/sessions/new.html.slim +11 -20
  66. data/app/views/constructor_core/users/profile.html.slim +11 -17
  67. data/app/views/layouts/constructor_core/application_core.html.slim +44 -70
  68. data/app/views/layouts/constructor_core/login.html.slim +27 -0
  69. data/config/locales/en.yml +3 -2
  70. data/config/locales/fr.yml +3 -2
  71. data/config/locales/ru.yml +2 -1
  72. data/constructor-core.gemspec +4 -3
  73. data/lib/constructor-core.rb +5 -2
  74. data/lib/constructor_core/version.rb +1 -1
  75. data/{app → vendor}/assets/javascripts/constructor_core/jquery.cookie.js +0 -0
  76. data/{app → vendor}/assets/javascripts/constructor_core/keys_snippet.js +0 -0
  77. data/{app → vendor}/assets/javascripts/constructor_core/retina.js +0 -0
  78. data/vendor/assets/stylesheets/constructor_core/framework/all.scss +4 -0
  79. data/vendor/assets/stylesheets/constructor_core/framework/classes.scss +4 -0
  80. data/vendor/assets/stylesheets/constructor_core/framework/globals.scss +49 -0
  81. data/vendor/assets/stylesheets/constructor_core/framework/grid.scss +33 -0
  82. data/vendor/assets/stylesheets/constructor_core/framework/mixin.scss +193 -0
  83. metadata +94 -45
  84. data/app/assets/images/constructor_core/glyphicons-halflings-white.png +0 -0
  85. data/app/assets/images/constructor_core/glyphicons-halflings.png +0 -0
  86. data/app/assets/images/constructor_core/minus.gif +0 -0
  87. data/app/assets/images/constructor_core/plus.gif +0 -0
  88. data/app/assets/images/constructor_core/rss.png +0 -0
  89. data/app/assets/images/constructor_core/treeview-black-line.gif +0 -0
  90. data/app/assets/images/constructor_core/treeview-black.gif +0 -0
  91. data/app/assets/images/constructor_core/treeview-default-line.gif +0 -0
  92. data/app/assets/images/constructor_core/treeview-default.gif +0 -0
  93. data/app/assets/images/constructor_core/treeview-famfamfam-line.gif +0 -0
  94. data/app/assets/images/constructor_core/treeview-famfamfam.gif +0 -0
  95. data/app/assets/images/constructor_core/treeview-gray-line.gif +0 -0
  96. data/app/assets/images/constructor_core/treeview-gray.gif +0 -0
  97. data/app/assets/images/constructor_core/treeview-red-line.gif +0 -0
  98. data/app/assets/images/constructor_core/treeview-red.gif +0 -0
  99. data/app/assets/images/constructor_core/twitter.png +0 -0
  100. data/app/assets/images/constructor_core/widgets.png +0 -0
  101. data/app/assets/javascripts/constructor_core/bootstrap.js +0 -2276
  102. data/app/assets/stylesheets/constructor_core/main.css.scss.erb +0 -233
  103. data/app/views/constructor_core/devise/confirmations/new.html.slim +0 -10
  104. data/app/views/constructor_core/devise/mailer/confirmation_instructions.html.slim +0 -5
  105. data/app/views/constructor_core/devise/mailer/reset_password_instructions.html.slim +0 -7
  106. data/app/views/constructor_core/devise/mailer/unlock_instructions.html.slim +0 -5
  107. data/app/views/constructor_core/devise/passwords/edit.html.slim +0 -21
  108. data/app/views/constructor_core/devise/passwords/new.html.slim +0 -13
  109. data/app/views/constructor_core/devise/registrations/edit.html.slim +0 -28
  110. data/app/views/constructor_core/devise/registrations/new.html.slim +0 -20
  111. data/app/views/constructor_core/devise/shared/_links.html.slim +0 -19
  112. data/app/views/constructor_core/devise/unlocks/new.html.slim +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2877812b30ec4bd56ddfd1498fd1f953cc214d2d
4
- data.tar.gz: d4684246ac4d6cbfc3efe8452445e05a96537514
3
+ metadata.gz: adbea170d2a6f81a42d4484fff1dcbc4e784bd31
4
+ data.tar.gz: fea77520947a5af5616c90751a35a8610b84919a
5
5
  SHA512:
6
- metadata.gz: 9b34c0adceba550ce67746f01b6f012af6667b8ee58822919469e3c78cbcf3c72d62266f77e57f0715e629afd1c450f77d31f660240df8d38c7c3f0f208e2aa0
7
- data.tar.gz: ea755a1de32131a6961151612a9f4e13eef04851ab844844ea3d814b323b357a73274103346e9b7137d1d8c1675aba0b18d24d123fe33ddc26c503c0d819340e
6
+ metadata.gz: 535db94846b950ba718ba22f09c1e90ec4bd9147fb404f77e759592645b3971af7a2c1ec406a73c3e6160b96152ecc5ed9eff25fd20bebca2e5664613f85a3b1
7
+ data.tar.gz: 357b1052969eeaece2f5669aa67d6c81b0a904d4866630950c7f59d6c3ccbf8c642a0d45e3c76bc1b0a115f8938ce62be1ac1eb08aff4634cbe58b28b24581c0
File without changes
@@ -1,17 +1,14 @@
1
1
  #= require constructor_core/jquery_bundle
2
- #= require constructor_core/bootstrap
3
2
  #= require ckeditor/ckeditor
4
3
  #= require constructor_pages/urlify
4
+ #= require ./jquery.ui.nestedSortable
5
+ #= require ./sortable_tree/initializer
6
+ #= require ./expandable_tree/hashchange
7
+ #= require ./expandable_tree/restorable
8
+ #= require ./expandable_tree/initializer
5
9
  #= require_self
6
10
 
7
11
  $(document).ready ->
8
- $(".alert").alert()
9
- $(".collapse").collapse()
10
-
11
- $('#url-if-empty').popover({
12
- offset: 10
13
- })
14
-
15
12
  $('.auto_url').hide()
16
13
  $('#page_url').hide()
17
14
 
@@ -20,33 +17,33 @@ $(document).ready ->
20
17
  unless auto_url
21
18
  auto_url_true()
22
19
 
23
- $('#page_name').keyup -> $('.address').html(parameterize())
20
+ $('#page_name').keyup -> $('.b-full-url__url').html(parameterize())
24
21
  $('#page_parent_id').change ->
25
- parent_full_url = $('#page_parent_id option:selected').data('full_url')
22
+ parent_full_url = $('#page_parent_id option:selected').data('b-full-url')
26
23
  if parent_full_url
27
- $('.path').html(parent_full_url)
24
+ $('.b-full-url__path').html(parent_full_url)
28
25
  else
29
- $('.path').html('')
26
+ $('.b-full-url__path').html('')
30
27
 
31
- $('.address, .address_icon').click ->
28
+ $('.b-full-url__url, .b-full-url__icon').click ->
32
29
  if $('#page_auto_url').is(':checked') == true
33
30
  $('#page_url').prop('value', parameterize())
34
31
  auto_url_true()
35
32
  else
36
- $('.address').html(parameterize())
33
+ $('.b-full-url__url').html(parameterize())
37
34
  auto_url_false()
38
35
 
39
36
  auto_url_true = ->
40
37
  $('#page_url').show()
41
38
  $('#page_auto_url').prop('checked', false)
42
- $('.address_icon').addClass('icon-remove').removeClass('icon-pencil')
43
- $('.address').hide()
39
+ $('.b-full-url__icon').addClass('fa-times-circle-o').removeClass('fa-pencil')
40
+ $('.b-full-url__url').hide()
44
41
 
45
42
  auto_url_false = ->
46
43
  $('#page_url').hide()
47
44
  $('#page_auto_url').prop('checked', true)
48
- $('.address_icon').addClass('icon-pencil').removeClass('icon-remove')
49
- $('.address').show()
45
+ $('.b-full-url__icon').addClass('fa-pencil').removeClass('fa-times-circle-o')
46
+ $('.b-full-url__url').show()
50
47
 
51
48
  parameterize = ->
52
49
  URLify($('#page_name').prop('value'))
@@ -0,0 +1,33 @@
1
+ @_arrays_diff = (a, b) -> b.filter (i) -> return !(a.indexOf(i) > -1)
2
+
3
+ @expandable_tree_hashchange = (hash_event) ->
4
+ if window.skip_expandable_tree_hashchange
5
+ window.skip_expandable_tree_hashchange = false
6
+ return true
7
+
8
+ hash_and_cookie_accordance()
9
+
10
+ oEvent = hash_event.originalEvent
11
+ new_url = oEvent.newURL
12
+ old_url = oEvent.oldURL
13
+
14
+ new_hash = new_url.split('#')[1]
15
+ old_hash = old_url.split('#')[1]
16
+
17
+ return false unless ('#'+new_hash).match(TSTconst.re()) or ('#'+old_hash).match(TSTconst.re())
18
+
19
+ new_arr = _nested_set_hash_arr(new_hash)
20
+ old_arr = _nested_set_hash_arr(old_hash)
21
+
22
+ diff_ids = if new_arr.length >= old_arr.length
23
+ _arrays_diff(old_arr, new_arr)
24
+ else
25
+ _arrays_diff(new_arr, old_arr)
26
+
27
+ for id in diff_ids
28
+ btn = $("[data-node-id=#{id}] > .b-tree__item > .b-tree__expand")
29
+ btn.click()
30
+ setTimeout -> window.skip_expandable_tree_hashchange = false
31
+
32
+ $(window).bind 'hashchange', (hash_event) ->
33
+ expandable_tree_hashchange(hash_event)
@@ -0,0 +1,106 @@
1
+ # ----------------------------------------
2
+ # Restorable Helpers
3
+ # ----------------------------------------
4
+ @add_to_restorable_path = (node) ->
5
+ if window.is_restorable_tree
6
+ id = node.data('node-id')
7
+ nested_tree_path_add(id)
8
+ return true
9
+ false
10
+
11
+ @remove_from_restorable_path = (node) ->
12
+ if window.is_restorable_tree
13
+ id = node.data('node-id')
14
+ nested_tree_path_remove(id)
15
+ return true
16
+ false
17
+
18
+ # ----------------------------------------
19
+ # Main Helpers
20
+ # ----------------------------------------
21
+ @nested_tree_toggle = (button) ->
22
+ if button.hasClass('b-tree__minus')
23
+ button.removeClass('b-tree__minus').addClass('b-tree__plus')
24
+ button.removeClass('fa-minus-square-o').addClass('fa-plus-square-o')
25
+ else
26
+ button.removeClass('b-tree__plus').addClass('b-tree__minus')
27
+ button.removeClass('fa-plus-square-o').addClass('fa-minus-square-o')
28
+
29
+ @append_children_to_node = (node, html) ->
30
+ html = html.trim()
31
+ item = node.children('.b-tree__item')
32
+
33
+ button = node.children('.b-tree__item').children('.b-tree__expand')
34
+
35
+ if html.length is 0
36
+ button.addClass 'empty'
37
+
38
+ if html.length > 0
39
+ item.after html
40
+ nested_tree_toggle(button)
41
+ add_to_restorable_path(node)
42
+
43
+ @upload_nodes_children = (node, expand_node_url) ->
44
+ node_id = node.data('node-id')
45
+ tree = $('.b-tree')
46
+ ctrl_items = $('.b-tree__handler, .b-tree__expand', tree)
47
+
48
+ $.ajax
49
+ type: 'POST'
50
+ dataType: 'html'
51
+ data: { id: node_id }
52
+ url: expand_node_url
53
+
54
+ beforeSend: (xhr) ->
55
+ ctrl_items.hide()
56
+ window.skip_expandable_tree_hashchange = true
57
+
58
+ success: (data, status, xhr) ->
59
+ ctrl_items.show()
60
+ append_children_to_node(node, data)
61
+
62
+ error: (xhr, status, error) ->
63
+ try
64
+ console.log error
65
+
66
+ @init_expandable_tree = ->
67
+ sortable_tree = $('.b-tree')
68
+ return false if sortable_tree.length is 0
69
+
70
+ window.is_restorable_tree ||= false
71
+ window.is_cookie_restoreable_tree = sortable_tree.data('cookie_store') || sortable_tree.data('cookie-store')
72
+
73
+ if window.is_cookie_restoreable_tree
74
+ steps = $.cookie(TSTconst.cookie_name())
75
+ _set_hash(TSTconst.hash_prefix() + steps) if steps
76
+
77
+ expand_node_url = sortable_tree.data('expand_node_url') || sortable_tree.data('expand-node-url')
78
+
79
+ # Now it's designed only for one tree
80
+ restore_nested_tree(sortable_tree, expand_node_url) if window.is_restorable_tree
81
+
82
+ sortable_tree.on 'click', '.b-tree__minus', (e) ->
83
+ button = $ @
84
+ node = button.parent().parent()
85
+ nested_tree_toggle(button)
86
+ remove_from_restorable_path(node)
87
+ node.children('.b-tree__nested-set').hide()
88
+ false
89
+
90
+ sortable_tree.on 'click', '.b-tree__plus', (e) ->
91
+ button = $ @
92
+ node = button.parent().parent()
93
+ nested_set = node.children('.b-tree__nested-set')
94
+
95
+ if nested_set.length is 0
96
+ upload_nodes_children(node, expand_node_url)
97
+ else
98
+ nested_set.show()
99
+ nested_tree_toggle(button)
100
+ add_to_restorable_path(node)
101
+
102
+ false
103
+
104
+ true
105
+
106
+ $ -> init_expandable_tree()
@@ -0,0 +1,68 @@
1
+ #!
2
+ # * jQuery Cookie Plugin v1.3.1
3
+ # * https://github.com/carhartl/jquery-cookie
4
+ # *
5
+ # * Copyright 2013 Klaus Hartl
6
+ # * Released under the MIT license
7
+ #
8
+ ((factory) ->
9
+ if typeof define is "function" and define.amd
10
+ # AMD. Register as anonymous module.
11
+ define ["jquery"], factory
12
+ else
13
+ # Browser globals.
14
+ factory jQuery
15
+ ) ($) ->
16
+ pluses = /\+/g
17
+
18
+ raw = (s) -> s
19
+ decoded = (s) -> decodeURIComponent s.replace(pluses, " ")
20
+ converted = (s) ->
21
+ # This is a quoted cookie as according to RFC2068, unescape
22
+ s = s.slice(1, -1).replace(/\\"/g, "\"").replace(/\\\\/g, "\\") if s.indexOf("\"") is 0
23
+ try
24
+ return (if config.json then JSON.parse(s) else s)
25
+
26
+
27
+ config = $.cookie = (key, value, options) ->
28
+ # write
29
+ if value isnt `undefined`
30
+ options = $.extend({}, config.defaults, options)
31
+
32
+ if typeof options.expires is "number"
33
+ days = options.expires
34
+ t = options.expires = new Date()
35
+ t.setDate t.getDate() + days
36
+
37
+ value = (if config.json then JSON.stringify(value) else String(value))
38
+
39
+ # use expires attribute, max-age is not supported by IE
40
+ return (document.cookie = [(if config.raw then key else encodeURIComponent(key)), "=", (if config.raw then value else encodeURIComponent(value)), (if options.expires then "; expires=" + options.expires.toUTCString() else ""), (if options.path then "; path=" + options.path else ""), (if options.domain then "; domain=" + options.domain else ""), (if options.secure then "; secure" else "")].join(""))
41
+
42
+ # read
43
+ decode = (if config.raw then raw else decoded)
44
+ cookies = document.cookie.split("; ")
45
+ result = (if key then `undefined` else {})
46
+
47
+ i = 0
48
+ l = cookies.length
49
+
50
+ while i < l
51
+ parts = cookies[i].split("=")
52
+ name = decode parts.shift()
53
+ cookie = decode parts.join("=")
54
+ if key and key is name
55
+ result = converted(cookie)
56
+ break
57
+ result[name] = converted(cookie) unless key
58
+ i++
59
+ result
60
+
61
+ config.defaults = {}
62
+
63
+ $.removeCookie = (key, options) ->
64
+ if $.cookie(key) isnt `undefined`
65
+ # Must not alter options, thus extending a fresh object...
66
+ $.cookie key, '', $.extend({}, options, expires: -1)
67
+ return true
68
+ false
@@ -0,0 +1,122 @@
1
+ window.is_restorable_tree = true
2
+
3
+ class @TSTconst
4
+ @_name = 'TST'
5
+ @delimiter = ';'
6
+ @separator = '|'
7
+ @re = -> new RegExp(@cookie_name() + '\\' + @separator)
8
+ @hash_prefix = -> @cookie_name() + @separator
9
+ @cookie_scope = -> $('.b-tree').data('cookie_scope') || $('.b-tree').data('cookie-scope')
10
+ @cookie_name = ->
11
+ return @_name unless @cookie_scope()
12
+ @_name + '_' + @cookie_scope()
13
+
14
+ # ====================================
15
+ # Helpers
16
+ # ====================================
17
+ @_get_hash = -> document.location.hash
18
+ @_set_hash = (str) ->
19
+ window.skip_expandable_tree_hashchange = true
20
+ document.location.hash = str
21
+
22
+ @_uniqueArray = (arr = []) ->
23
+ output = {}
24
+ output[item] = item for item in arr
25
+ val for key, val of output
26
+
27
+ @_compactArray = (array) -> array.filter (e) -> return e
28
+
29
+ @_nested_set_hash_arr = (hash) ->
30
+ return [] unless hash
31
+ [prefix, arr] = hash.split(TSTconst.separator)
32
+ _compactArray _uniqueArray arr.split(TSTconst.delimiter)
33
+
34
+ # ====================================
35
+ # Helpers Fn
36
+ # ====================================
37
+ @nested_tree_get_path = ->
38
+ hash = _get_hash()
39
+ return false unless hash.match(TSTconst.re())
40
+ _nested_set_hash_arr(hash)
41
+
42
+ @hash_and_cookie_accordance = ->
43
+ if window.is_cookie_restoreable_tree
44
+ hash = _get_hash()
45
+ if hash.length is 0
46
+ $.removeCookie( TSTconst.cookie_name() )
47
+ else
48
+ return false unless hash.match(TSTconst.re())
49
+ str = hash.split(TSTconst.separator)[1]
50
+ $.cookie(TSTconst.cookie_name(), str, { expires: 14 })
51
+
52
+ false
53
+
54
+ @nested_tree_path_remove = (id) ->
55
+ hash = _get_hash()
56
+ return false unless hash.match(TSTconst.re())
57
+
58
+ arr = _nested_set_hash_arr(hash)
59
+ index = arr.indexOf(id+'')
60
+ return hash_and_cookie_accordance() if index is -1
61
+
62
+ arr.splice(index, 1)
63
+ str = _uniqueArray(arr).join(TSTconst.delimiter)
64
+
65
+ if str.length is 0
66
+ _set_hash('')
67
+ else
68
+ _set_hash(TSTconst.hash_prefix() + str)
69
+
70
+ hash_and_cookie_accordance()
71
+
72
+ true
73
+
74
+ @nested_tree_path_add = (id) ->
75
+ str = id
76
+ hash = _get_hash()
77
+
78
+ if hash.match(TSTconst.re())
79
+ arr = _nested_set_hash_arr(hash)
80
+ arr.push(id)
81
+ arr = _uniqueArray arr
82
+ str = arr.join(TSTconst.delimiter)
83
+
84
+ _set_hash(TSTconst.hash_prefix() + str)
85
+ hash_and_cookie_accordance()
86
+
87
+ # ====================================
88
+ # Restore Fn
89
+ # ====================================
90
+ @load_nested_nodes = (arr, expand_node_url) ->
91
+ if arr.length is 0
92
+ window.skip_expandable_tree_hashchange = false
93
+ return false
94
+
95
+ id = arr.shift()
96
+ tree = $('.b-tree')
97
+ node = $("[data-node-id=#{id}]")
98
+
99
+ if node.length is 0
100
+ load_nested_nodes(arr, expand_node_url)
101
+ else
102
+ $.ajax
103
+ type: 'POST'
104
+ dataType: 'html'
105
+ data: { id: id }
106
+ url: expand_node_url
107
+
108
+ beforeSend: (xhr) ->
109
+ window.skip_expandable_tree_hashchange = true
110
+
111
+ success: (data, status, xhr) ->
112
+ append_children_to_node(node, data)
113
+ load_nested_nodes(arr, expand_node_url)
114
+
115
+ error: (xhr, status, error) ->
116
+ try
117
+ console.log error
118
+
119
+ @restore_nested_tree = (sortable_tree, expand_node_url) ->
120
+ arr = nested_tree_get_path()
121
+ return false unless arr
122
+ load_nested_nodes(arr, expand_node_url)
@@ -0,0 +1,429 @@
1
+ /*
2
+ * jQuery UI Nested Sortable
3
+ * v 1.3.5 / 21 jun 2012
4
+ * http://mjsarfatti.com/code/nestedSortable
5
+ *
6
+ * Depends on:
7
+ * jquery.ui.sortable.js 1.8+
8
+ *
9
+ * Copyright (c) 2010-2012 Manuele J Sarfatti
10
+ * Licensed under the MIT License
11
+ * http://www.opensource.org/licenses/mit-license.php
12
+ */
13
+
14
+ (function($) {
15
+
16
+ $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
17
+
18
+ options: {
19
+ tabSize: 20,
20
+ disableNesting: 'mjs-nestedSortable-no-nesting',
21
+ errorClass: 'mjs-nestedSortable-error',
22
+ doNotClear: false,
23
+ listType: 'ol',
24
+ maxLevels: 0,
25
+ protectRoot: false,
26
+ rootID: null,
27
+ rtl: false,
28
+ isAllowed: function(item, parent) { return true; }
29
+ },
30
+
31
+ _create: function() {
32
+ this.element.data('sortable', this.element.data('nestedSortable'));
33
+
34
+ if (!this.element.is(this.options.listType))
35
+ throw new Error('nestedSortable: Please check the listType option is set to your actual list type');
36
+
37
+ return $.ui.sortable.prototype._create.apply(this, arguments);
38
+ },
39
+
40
+ destroy: function() {
41
+ this.element
42
+ .removeData("nestedSortable")
43
+ .unbind(".nestedSortable");
44
+ return $.ui.sortable.prototype.destroy.apply(this, arguments);
45
+ },
46
+
47
+ _mouseDrag: function(event) {
48
+
49
+ //Compute the helpers position
50
+ this.position = this._generatePosition(event);
51
+ this.positionAbs = this._convertPositionTo("absolute");
52
+
53
+ if (!this.lastPositionAbs) {
54
+ this.lastPositionAbs = this.positionAbs;
55
+ }
56
+
57
+ var o = this.options;
58
+
59
+ //Do scrolling
60
+ if(this.options.scroll) {
61
+ var scrolled = false;
62
+ if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
63
+
64
+ if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
65
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
66
+ else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
67
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
68
+
69
+ if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
70
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
71
+ else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
72
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
73
+
74
+ } else {
75
+
76
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
77
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
78
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
79
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
80
+
81
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
82
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
83
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
84
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
85
+
86
+ }
87
+
88
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
89
+ $.ui.ddmanager.prepareOffsets(this, event);
90
+ }
91
+
92
+ //Regenerate the absolute position used for position checks
93
+ this.positionAbs = this._convertPositionTo("absolute");
94
+
95
+ // Find the top offset before rearrangement,
96
+ var previousTopOffset = this.placeholder.offset().top;
97
+
98
+ //Set the helper position
99
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
100
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
101
+
102
+ //Rearrange
103
+ for (var i = this.items.length - 1; i >= 0; i--) {
104
+
105
+ //Cache variables and intersection, continue if no intersection
106
+ var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
107
+ if (!intersection) continue;
108
+
109
+ if(itemElement != this.currentItem[0] //cannot intersect with itself
110
+ && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
111
+ && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
112
+ && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
113
+ //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
114
+ ) {
115
+
116
+ $(itemElement).mouseenter();
117
+
118
+ this.direction = intersection == 1 ? "down" : "up";
119
+
120
+ if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
121
+ $(itemElement).mouseleave();
122
+ this._rearrange(event, item);
123
+ } else {
124
+ break;
125
+ }
126
+
127
+ // Clear emtpy ul's/ol's
128
+ this._clearEmpty(itemElement);
129
+
130
+ this._trigger("change", event, this._uiHash());
131
+ break;
132
+ }
133
+ }
134
+
135
+ var parentItem = (this.placeholder[0].parentNode.parentNode &&
136
+ $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
137
+ ? $(this.placeholder[0].parentNode.parentNode)
138
+ : null,
139
+ level = this._getLevel(this.placeholder),
140
+ childLevels = this._getChildLevels(this.helper);
141
+
142
+ // To find the previous sibling in the list, keep backtracking until we hit a valid list item.
143
+ var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
144
+ if (previousItem != null) {
145
+ while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
146
+ if (previousItem[0].previousSibling) {
147
+ previousItem = $(previousItem[0].previousSibling);
148
+ } else {
149
+ previousItem = null;
150
+ break;
151
+ }
152
+ }
153
+ }
154
+
155
+ // To find the next sibling in the list, keep stepping forward until we hit a valid list item.
156
+ var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
157
+ if (nextItem != null) {
158
+ while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
159
+ if (nextItem[0].nextSibling) {
160
+ nextItem = $(nextItem[0].nextSibling);
161
+ } else {
162
+ nextItem = null;
163
+ break;
164
+ }
165
+ }
166
+ }
167
+
168
+ var newList = document.createElement(o.listType);
169
+
170
+ this.beyondMaxLevels = 0;
171
+
172
+ // If the item is moved to the left, send it to its parent's level unless there are siblings below it.
173
+ if (parentItem != null && nextItem == null &&
174
+ (o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
175
+ !o.rtl && (this.positionAbs.left < parentItem.offset().left))) {
176
+ parentItem.after(this.placeholder[0]);
177
+ this._clearEmpty(parentItem[0]);
178
+ this._trigger("change", event, this._uiHash());
179
+ }
180
+ // If the item is below a sibling and is moved to the right, make it a child of that sibling.
181
+ else if (previousItem != null &&
182
+ (o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) ||
183
+ !o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))) {
184
+ this._isAllowed(previousItem, level, level+childLevels+1);
185
+ if (!previousItem.children(o.listType).length) {
186
+ previousItem[0].appendChild(newList);
187
+ }
188
+ // If this item is being moved from the top, add it to the top of the list.
189
+ if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
190
+ previousItem.children(o.listType).prepend(this.placeholder);
191
+ }
192
+ // Otherwise, add it to the bottom of the list.
193
+ else {
194
+ previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
195
+ }
196
+ this._trigger("change", event, this._uiHash());
197
+ }
198
+ else {
199
+ this._isAllowed(parentItem, level, level+childLevels);
200
+ }
201
+
202
+ //Post events to containers
203
+ this._contactContainers(event);
204
+
205
+ //Interconnect with droppables
206
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
207
+
208
+ //Call callbacks
209
+ this._trigger('sort', event, this._uiHash());
210
+
211
+ this.lastPositionAbs = this.positionAbs;
212
+ return false;
213
+
214
+ },
215
+
216
+ _mouseStop: function(event, noPropagation) {
217
+
218
+ // If the item is in a position not allowed, send it back
219
+ if (this.beyondMaxLevels) {
220
+
221
+ this.placeholder.removeClass(this.options.errorClass);
222
+
223
+ if (this.domPosition.prev) {
224
+ $(this.domPosition.prev).after(this.placeholder);
225
+ } else {
226
+ $(this.domPosition.parent).prepend(this.placeholder);
227
+ }
228
+
229
+ this._trigger("revert", event, this._uiHash());
230
+
231
+ }
232
+
233
+ // Clean last empty ul/ol
234
+ for (var i = this.items.length - 1; i >= 0; i--) {
235
+ var item = this.items[i].item[0];
236
+ this._clearEmpty(item);
237
+ }
238
+
239
+ $.ui.sortable.prototype._mouseStop.apply(this, arguments);
240
+
241
+ },
242
+
243
+ serialize: function(options) {
244
+
245
+ var o = $.extend({}, this.options, options),
246
+ items = this._getItemsAsjQuery(o && o.connected),
247
+ str = [];
248
+
249
+ $(items).each(function() {
250
+ var res = ($(o.item || this).attr(o.attribute || 'id') || '')
251
+ .match(o.expression || (/(.+)[-=_](.+)/)),
252
+ pid = ($(o.item || this).parent(o.listType)
253
+ .parent(o.items)
254
+ .attr(o.attribute || 'id') || '')
255
+ .match(o.expression || (/(.+)[-=_](.+)/));
256
+
257
+ if (res) {
258
+ str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
259
+ + '='
260
+ + (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
261
+ }
262
+ });
263
+
264
+ if(!str.length && o.key) {
265
+ str.push(o.key + '=');
266
+ }
267
+
268
+ return str.join('&');
269
+
270
+ },
271
+
272
+ toHierarchy: function(options) {
273
+
274
+ var o = $.extend({}, this.options, options),
275
+ sDepth = o.startDepthCount || 0,
276
+ ret = [];
277
+
278
+ $(this.element).children(o.items).each(function () {
279
+ var level = _recursiveItems(this);
280
+ ret.push(level);
281
+ });
282
+
283
+ return ret;
284
+
285
+ function _recursiveItems(item) {
286
+ var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
287
+ if (id) {
288
+ var currentItem = {"id" : id[2]};
289
+ if ($(item).children(o.listType).children(o.items).length > 0) {
290
+ currentItem.children = [];
291
+ $(item).children(o.listType).children(o.items).each(function() {
292
+ var level = _recursiveItems(this);
293
+ currentItem.children.push(level);
294
+ });
295
+ }
296
+ return currentItem;
297
+ }
298
+ }
299
+ },
300
+
301
+ toArray: function(options) {
302
+
303
+ var o = $.extend({}, this.options, options),
304
+ sDepth = o.startDepthCount || 0,
305
+ ret = [],
306
+ left = 2;
307
+
308
+ ret.push({
309
+ "item_id": o.rootID,
310
+ "parent_id": 'none',
311
+ "depth": sDepth,
312
+ "left": '1',
313
+ "right": ($(o.items, this.element).length + 1) * 2
314
+ });
315
+
316
+ $(this.element).children(o.items).each(function () {
317
+ left = _recursiveArray(this, sDepth + 1, left);
318
+ });
319
+
320
+ ret = ret.sort(function(a,b){ return (a.left - b.left); });
321
+
322
+ return ret;
323
+
324
+ function _recursiveArray(item, depth, left) {
325
+
326
+ var right = left + 1,
327
+ id,
328
+ pid;
329
+
330
+ if ($(item).children(o.listType).children(o.items).length > 0) {
331
+ depth ++;
332
+ $(item).children(o.listType).children(o.items).each(function () {
333
+ right = _recursiveArray($(this), depth, right);
334
+ });
335
+ depth --;
336
+ }
337
+
338
+ id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
339
+
340
+ if (depth === sDepth + 1) {
341
+ pid = o.rootID;
342
+ } else {
343
+ var parentItem = ($(item).parent(o.listType)
344
+ .parent(o.items)
345
+ .attr(o.attribute || 'id'))
346
+ .match(o.expression || (/(.+)[-=_](.+)/));
347
+ pid = parentItem[2];
348
+ }
349
+
350
+ if (id) {
351
+ ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
352
+ }
353
+
354
+ left = right + 1;
355
+ return left;
356
+ }
357
+
358
+ },
359
+
360
+ _clearEmpty: function(item) {
361
+
362
+ var emptyList = $(item).children(this.options.listType);
363
+ if (emptyList.length && !emptyList.children().length && !this.options.doNotClear) {
364
+ emptyList.remove();
365
+ }
366
+
367
+ },
368
+
369
+ _getLevel: function(item) {
370
+
371
+ var level = 1;
372
+
373
+ if (this.options.listType) {
374
+ var list = item.closest(this.options.listType);
375
+ while (list && list.length > 0 &&
376
+ !list.is('.ui-sortable')) {
377
+ level++;
378
+ list = list.parent().closest(this.options.listType);
379
+ }
380
+ }
381
+
382
+ return level;
383
+ },
384
+
385
+ _getChildLevels: function(parent, depth) {
386
+ var self = this,
387
+ o = this.options,
388
+ result = 0;
389
+ depth = depth || 0;
390
+
391
+ $(parent).children(o.listType).children(o.items).each(function (index, child) {
392
+ result = Math.max(self._getChildLevels(child, depth + 1), result);
393
+ });
394
+
395
+ return depth ? result + 1 : result;
396
+ },
397
+
398
+ _isAllowed: function(parentItem, level, levels) {
399
+ var o = this.options,
400
+ isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false,
401
+ maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list
402
+
403
+ // Is the root protected?
404
+ // Are we trying to nest under a no-nest?
405
+ // Are we nesting too deep?
406
+ if (!o.isAllowed(this.currentItem, parentItem) ||
407
+ parentItem && parentItem.hasClass(o.disableNesting) ||
408
+ o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
409
+ this.placeholder.addClass(o.errorClass);
410
+ if (maxLevels < levels && maxLevels != 0) {
411
+ this.beyondMaxLevels = levels - maxLevels;
412
+ } else {
413
+ this.beyondMaxLevels = 1;
414
+ }
415
+ } else {
416
+ if (maxLevels < levels && maxLevels != 0) {
417
+ this.placeholder.addClass(o.errorClass);
418
+ this.beyondMaxLevels = levels - maxLevels;
419
+ } else {
420
+ this.placeholder.removeClass(o.errorClass);
421
+ this.beyondMaxLevels = 0;
422
+ }
423
+ }
424
+ }
425
+
426
+ }));
427
+
428
+ $.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
429
+ })(jQuery);