constructor-core 0.9.1 → 1.0.0beta1

Sign up to get free protection for your applications and to get access to all the features.
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);