the_sortable_tree 1.9.4 → 2.0.0

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 (65) hide show
  1. data/MIT-LICENSE +4 -2
  2. data/README.md +237 -438
  3. data/app/assets/images/iconza/{gray → icons}/add.png +0 -0
  4. data/app/assets/images/iconza/{gray → icons}/delete.png +0 -0
  5. data/app/assets/images/iconza/{gray → icons}/edit.png +0 -0
  6. data/app/assets/images/iconza/icons/move.png +0 -0
  7. data/app/assets/images/iconza/{red/add.png → icons/red_add.png} +0 -0
  8. data/app/assets/images/iconza/{red/delete.png → icons/red_delete.png} +0 -0
  9. data/app/assets/images/iconza/{red/edit.png → icons/red_edit.png} +0 -0
  10. data/app/assets/images/iconza/icons/red_move.png +0 -0
  11. data/app/assets/javascripts/render_tree_helper.js.coffee +82 -0
  12. data/app/assets/javascripts/sortable_tree/initializer.js.coffee +54 -0
  13. data/app/assets/stylesheets/sortable_tree.css.scss +106 -0
  14. data/app/assets/stylesheets/tree.css.scss +26 -29
  15. data/app/controllers/the_sortable_tree_controller.rb +3 -2
  16. data/app/helpers/render_sortable_tree_helper.rb +62 -0
  17. data/app/helpers/render_tree_helper.rb +45 -0
  18. data/app/helpers/the_sortable_tree_helper.rb +67 -52
  19. data/app/views/sortable/client/_tree.html.erb +9 -0
  20. data/app/views/tree/client/_tree.html.erb +23 -0
  21. data/lib/fake.example +44 -0
  22. data/lib/generators/the_sortable_tree/views_generator.rb +29 -18
  23. data/lib/the_sortable_tree.rb +4 -8
  24. data/lib/the_sortable_tree/engine.rb +1 -1
  25. data/lib/the_sortable_tree/version.rb +1 -1
  26. metadata +31 -60
  27. data/app/assets/images/iconza/blue/add.png +0 -0
  28. data/app/assets/images/iconza/blue/delete.png +0 -0
  29. data/app/assets/images/iconza/blue/down.png +0 -0
  30. data/app/assets/images/iconza/blue/downloads_folder.png +0 -0
  31. data/app/assets/images/iconza/blue/edit.png +0 -0
  32. data/app/assets/images/iconza/blue/move.png +0 -0
  33. data/app/assets/images/iconza/blue/up.png +0 -0
  34. data/app/assets/images/iconza/gray/down.png +0 -0
  35. data/app/assets/images/iconza/gray/lock.png +0 -0
  36. data/app/assets/images/iconza/gray/mail.png +0 -0
  37. data/app/assets/images/iconza/gray/push_pin.png +0 -0
  38. data/app/assets/images/iconza/gray/up.png +0 -0
  39. data/app/assets/images/iconza/red/down.png +0 -0
  40. data/app/assets/images/iconza/red/newspaper.png +0 -0
  41. data/app/assets/images/iconza/red/trash.png +0 -0
  42. data/app/assets/images/iconza/red/up.png +0 -0
  43. data/app/assets/images/iconza/red/zoom.png +0 -0
  44. data/app/assets/javascripts/comments/base.js.coffee +0 -46
  45. data/app/assets/javascripts/sortable/base.js.coffee +0 -47
  46. data/app/assets/stylesheets/comments_tree.css.scss +0 -84
  47. data/app/assets/stylesheets/sortable.css.scss +0 -106
  48. data/app/views/comments/base/_children.html.haml +0 -1
  49. data/app/views/comments/base/_comment.html.haml +0 -8
  50. data/app/views/comments/base/_new_comment_form.html.haml +0 -18
  51. data/app/views/comments/base/_node.html.haml +0 -3
  52. data/app/views/comments/base/_tree.html.haml +0 -5
  53. data/app/views/sortable/base/_children.html.haml +0 -1
  54. data/app/views/sortable/base/_controls.html.haml +0 -16
  55. data/app/views/sortable/base/_link.html.haml +0 -7
  56. data/app/views/sortable/base/_new.html.haml +0 -3
  57. data/app/views/sortable/base/_node.html.haml +0 -3
  58. data/app/views/sortable/base/_tree.html.haml +0 -12
  59. data/app/views/tree/base/_children.html.haml +0 -1
  60. data/app/views/tree/base/_link.html.haml +0 -1
  61. data/app/views/tree/base/_node.html.haml +0 -3
  62. data/app/views/tree/base/_tree.html.haml +0 -3
  63. data/config/locales/en.yml +0 -31
  64. data/config/locales/ru.yml +0 -31
  65. data/lib/tasks/the_sortable_tree.rake +0 -4
File without changes
File without changes
File without changes
@@ -0,0 +1,82 @@
1
+ @_escape = (str) ->
2
+ str
3
+ .replace(/&/g, '&')
4
+ .replace(/>/g, '>')
5
+ .replace(/</g, '&lt;')
6
+ .replace(/"/g, '&quot;')
7
+
8
+ @_unescape = (str) ->
9
+ str
10
+ .replace(/&amp;/g, '&')
11
+ .replace(/&gt;/g, '>')
12
+ .replace(/&lt;/g, '<')
13
+ .replace(/&quot;/g, '"')
14
+
15
+ @render_tree = (tree, options = {}) ->
16
+ html = ''
17
+
18
+ opts =
19
+ id: 'id'
20
+ node: null
21
+ root: false
22
+ level: 0
23
+ boost: []
24
+
25
+ # JQuery hash merge
26
+ $.extend opts, options
27
+
28
+ # Define Boost Only Once
29
+ unless opts['boost'].length is 0
30
+ boost = []
31
+ for node in tree
32
+ num = node.parent_id || 0
33
+ item = boost[num]
34
+ boost[num] = [] unless item instanceof Array
35
+ boost[num].push node
36
+
37
+ opts['boost'] = boost
38
+
39
+ unless opts.node
40
+ # render root nodes
41
+ roots = opts['boost'][0]
42
+
43
+ # select roots
44
+ # for node in tree
45
+ # roots.push node if node.parent_id is null
46
+
47
+ # roots is empty, but tree is not empty
48
+ # I should select nodes with minimal parent_id
49
+ # they will be roots
50
+ # order by lft, should be made at server side
51
+ min_elem = tree[0]
52
+ if roots.length is 0 and tree.length isnt 0
53
+ for elem in tree
54
+ min_elem = elem if elem.parent_id < min_elem.parent_id
55
+ # select roots witn min parent_id
56
+ for elem in tree
57
+ if elem.parent_id is min_elem.parent_id
58
+ roots.push elem
59
+
60
+ # render tree
61
+ for node in roots
62
+ $.extend opts, { node: node, root: false, level: opts.level + 1 }
63
+ children_html = render_tree tree, opts
64
+ html += opts.render_node(node, children_html, opts)
65
+ else
66
+ # render children nodes
67
+ children = []
68
+ children_html = ''
69
+ children = boost[opts.node.id]
70
+
71
+ # select children
72
+ # for elem in tree
73
+ # children.push elem if elem.parent_id is opts.node.id
74
+
75
+ # render children nodes
76
+ for node in children
77
+ $.extend opts, { node: node, root: false, level: opts.level + 1 }
78
+ children_html = render_tree tree, opts
79
+ html += opts.render_node(node, children_html, opts)
80
+
81
+ # result html
82
+ html
@@ -0,0 +1,54 @@
1
+ @rebuild_sortable_tree = (rebuild_url, item_id, parent_id, prev_id, next_id) ->
2
+ $.ajax
3
+ type: 'POST'
4
+ dataType: 'script'
5
+ url: rebuild_url
6
+ data:
7
+ id: item_id
8
+ parent_id: parent_id
9
+ prev_id: prev_id
10
+ next_id: next_id
11
+
12
+ beforeSend: (xhr) ->
13
+ $('.sortable_tree i.handle').hide()
14
+
15
+ success: (data, status, xhr) ->
16
+ $('.sortable_tree i.handle').show()
17
+
18
+ error: (xhr, status, error) ->
19
+ console.log error
20
+
21
+ $ ->
22
+ for sortable_tree in $('ol.sortable_tree')
23
+ sortable_tree = $ sortable_tree
24
+ rebuild_url = sortable_tree.data('rebuild_url')
25
+ max_levels = sortable_tree.data('max_levels')
26
+
27
+ ############################################
28
+ # Initialize Sortable Tree
29
+ ############################################
30
+ sortable_tree.nestedSortable
31
+ items: 'li'
32
+ helper: 'clone'
33
+ handle: 'i.handle'
34
+ tolerance: 'pointer'
35
+ maxLevels: max_levels
36
+ revert: 250
37
+ tabSize: 25
38
+ opacity: 0.6
39
+ placeholder: 'placeholder'
40
+ disableNesting: 'no-nest'
41
+ toleranceElement: '> div'
42
+ forcePlaceholderSize: true
43
+
44
+ ############################################
45
+ # Sortable Update Event
46
+ ############################################
47
+ sortable_tree.on "sortupdate", (event, ui) =>
48
+ item = ui.item
49
+ item_id = item.attr('id')
50
+ prev_id = item.prev().attr('id')
51
+ next_id = item.next().attr('id')
52
+ parent_id = item.parent().parent().attr('id')
53
+
54
+ rebuild_sortable_tree(rebuild_url, item_id, parent_id, prev_id, next_id)
@@ -0,0 +1,106 @@
1
+ .sortable_tree{
2
+ margin: 0; padding: 0;
3
+ *{ margin: 0; padding: 0; }
4
+
5
+ ol{
6
+ margin: 0 0 0 13px;
7
+ padding: 0 0 0 15px;
8
+ border-left: 1px dashed gray;
9
+ list-style: none outside none;
10
+ }
11
+
12
+ li{
13
+ margin-bottom:5px;
14
+ position: relative;
15
+ list-style: none outside none;
16
+ }
17
+
18
+ a{
19
+ color:#000;
20
+ font-size:10pt;
21
+ font-weight:normal;
22
+ text-decoration:none;
23
+ line-height: 150%;
24
+ margin-left:30px;
25
+ margin-right:120px;
26
+ display:block;
27
+ &:hover{ text-decoration: underline; }
28
+ }
29
+
30
+ h4{
31
+ margin: 0;
32
+ a{
33
+ color: #333;
34
+ font-size: 14px;
35
+ &:hover{ background: #eee; }
36
+ }
37
+ }
38
+
39
+ p{
40
+ margin-right: 75px;
41
+ padding: 5px;
42
+ }
43
+
44
+ .handle{
45
+ background: transparent url(/assets/iconza/icons/move.png);
46
+ background-position: center center;
47
+
48
+ width: 16px;
49
+ height: 16px;
50
+ margin: 3px 10px 0 0;
51
+ float: left;
52
+ cursor: move;
53
+
54
+ &:hover{ background: transparent url(/assets/iconza/icons/red_move.png); }
55
+ }
56
+
57
+ .item{
58
+ padding: 5px;
59
+ background: #f7f7f7;
60
+ border-radius: 3px;
61
+ margin-bottom: 5px;
62
+ &:hover{ background: #eee; }
63
+ }
64
+
65
+ .placeholder {
66
+ background-color: #EEF;
67
+ border: 1px dashed blue;
68
+ }
69
+
70
+ .ui-nestedSortable-error {
71
+ background: #FAA;
72
+ color: #8a1f11;
73
+ }
74
+
75
+ .controls{
76
+ position: absolute;
77
+ top: 1px; right: 10px;
78
+
79
+ a{
80
+ width: 20px;
81
+ height: 20px;
82
+ display: block;
83
+
84
+ float: left;
85
+ padding: 5px;
86
+ cursor: pointer;
87
+ position: relative;
88
+
89
+ margin: 0 0 5px 5px;
90
+ overflow: hidden; zoom: 1;
91
+
92
+ &.new{
93
+ background: transparent url(/assets/iconza/icons/add.png) no-repeat scroll center center;
94
+ &:hover{ background: transparent url(/assets/iconza/icons/red_add.png) no-repeat scroll center center; }
95
+ }
96
+ &.edit{
97
+ background: transparent url(/assets/iconza/icons/edit.png) no-repeat scroll center center;
98
+ &:hover{ background: transparent url(/assets/iconza/icons/red_edit.png) no-repeat scroll center center; }
99
+ }
100
+ &.delete{
101
+ background: transparent url(/assets/iconza/icons/delete.png) no-repeat scroll center center;
102
+ &:hover{ background: transparent url(/assets/iconza/icons/red_delete.png) no-repeat scroll center center; }
103
+ }
104
+ }
105
+ }
106
+ }
@@ -1,38 +1,35 @@
1
1
  .tree{
2
- * {
3
- margin: 0; padding: 0;
4
- list-style:none;
5
- }
2
+ margin:0; padding:0;
3
+ *{ margin: 0; padding: 0; }
6
4
 
7
5
  ol{
6
+ margin: 0 0 0 13px;
7
+ padding: 0 0 0 15px;
8
+ border-left: 1px dashed gray;
9
+ list-style: none outside none;
10
+ }
8
11
 
9
- margin: 0; padding: 0;
10
- list-style:none;
11
-
12
- &.nested_set {
13
- list-style:none;
14
- font-size: 16px;
15
-
16
- li{
17
- font-size: 0.9em;
18
- line-height: 130%;
19
- margin-bottom: 5px;
20
- font-weight: bold;
21
- list-style:none;
22
- list-style-position: outside;
23
- }
24
-
25
- ol{
26
- border-left: 1px dashed #AAA;
27
- padding-left: 10px;
28
- margin-left: 15px;
29
- margin-top: 5px;
12
+ li{
13
+ margin-bottom:5px;
14
+ position: relative;
15
+ list-style: none outside none;
16
+ }
30
17
 
31
- li{ font-weight: normal; }
32
- }
18
+ a{
19
+ color: black;
20
+ font-size: 14px;
33
21
 
34
- a:hover { color: #003A89 !important; }
35
- a:visited { color: #809dc4; }
22
+ &:hover {
23
+ color: black;
24
+ background: #ddd;
36
25
  }
37
26
  }
27
+
28
+ .item{
29
+ padding: 5px;
30
+ background: #eee;
31
+ margin-bottom: 5px;
32
+ border-radius: 3px;
33
+ &:hover{ background: #ddd; }
34
+ }
38
35
  }
@@ -5,8 +5,9 @@ module TheSortableTreeController
5
5
  module DefineVariablesMethod
6
6
  public
7
7
  def the_define_common_variables
8
- collection = self.class.to_s.split(':').last.sub(/Controller/,'').underscore.downcase # recipes
9
- variable = collection.singularize # recipe
8
+ collection = self.class.to_s.split(':').last.sub(/Controller/,'').underscore.downcase # 'recipes'
9
+ collection = self.respond_to?(:sortable_collection) ? self.sortable_collection : collection # 'recipes'
10
+ variable = collection.singularize # 'recipe'
10
11
  klass = self.respond_to?(:sortable_model) ? self.sortable_model : variable.classify.constantize # Recipe
11
12
  ["@#{variable}", collection, klass]
12
13
  end
@@ -0,0 +1,62 @@
1
+ # DOC:
2
+ # We use Helper Methods for tree building,
3
+ # because it's faster than View Templates and Partials
4
+
5
+ # SECURITY note
6
+ # Prepare your data on server side for rendering
7
+ # or use h.html_escape(node.content)
8
+ # for escape potentially dangerous content
9
+ module RenderSortableTreeHelper
10
+ module Render
11
+ class << self
12
+ attr_accessor :h, :options
13
+
14
+ def render_node(h, options)
15
+ @h, @options = h, options
16
+
17
+ node = options[:node]
18
+
19
+ "
20
+ <li id='#{ node.id }_#{ options[:klass] }'>
21
+ <div class='item'>
22
+ <i class='handle'></i>
23
+ #{ show_link }
24
+ #{ controls }
25
+ </div>
26
+ #{ children }
27
+ </li>
28
+ "
29
+ end
30
+
31
+ def show_link
32
+ node = options[:node]
33
+ ns = options[:namespace]
34
+ url = h.url_for(ns + [node])
35
+ title_field = options[:title]
36
+
37
+ "<h4>#{ h.link_to(node.send(title_field), url) }</h4>"
38
+ end
39
+
40
+ def controls
41
+ node = options[:node]
42
+
43
+ edit_path = h.url_for(:controller => options[:klass].pluralize, :action => :edit, :id => node)
44
+ show_path = h.url_for(:controller => options[:klass].pluralize, :action => :show, :id => node)
45
+
46
+ "
47
+ <div class='controls'>
48
+ #{ h.link_to '', edit_path, :class => :edit }
49
+ #{ h.link_to '', show_path, :class => :delete, :data => { :confirm => 'Are you sure?' } }
50
+ </div>
51
+ "
52
+ end
53
+
54
+ def children
55
+ unless options[:children].blank?
56
+ "<ol class='nested_set'>#{ options[:children] }</ol>"
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,45 @@
1
+ # DOC:
2
+ # We use Helper Methods for tree building,
3
+ # because it's faster than View Templates and Partials
4
+
5
+ # SECURITY note
6
+ # Prepare your data on server side for rendering
7
+ # or use h.html_escape(node.content)
8
+ # for escape potentially dangerous content
9
+ module RenderTreeHelper
10
+ class Render
11
+ class << self
12
+ attr_accessor :h, :options
13
+
14
+ def render_node(h, options)
15
+ @h, @options = h, options
16
+
17
+ node = options[:node]
18
+ "
19
+ <li>
20
+ <div class='item'>
21
+ #{ show_link }
22
+ </div>
23
+ #{ children }
24
+ </li>
25
+ "
26
+ end
27
+
28
+ def show_link
29
+ node = options[:node]
30
+ ns = options[:namespace]
31
+ url = h.url_for(ns + [node])
32
+ title_field = options[:title]
33
+
34
+ "<h4>#{ h.link_to(node.send(title_field), url) }</h4>"
35
+ end
36
+
37
+ def children
38
+ unless options[:children].blank?
39
+ "<ol>#{ options[:children] }</ol>"
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end