the_sortable_tree 1.8.6 → 1.9.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.
- data/README.md +89 -76
- data/app/assets/javascripts/comments_tree.js.coffee +46 -0
- data/app/assets/stylesheets/comments_tree.css.scss +84 -0
- data/app/assets/stylesheets/sortable.css.scss +106 -0
- data/app/assets/stylesheets/tree.css.scss +38 -0
- data/app/controllers/the_sortable_tree_controller.rb +6 -7
- data/app/helpers/the_sortable_tree_helper.rb +35 -14
- data/app/views/{the_sortable_tree → comments/base}/_children.html.haml +0 -0
- data/app/views/comments/base/_comment.html.haml +7 -0
- data/app/views/comments/base/_new_comment_form.html.haml +18 -0
- data/app/views/comments/base/_node.html.haml +3 -0
- data/app/views/comments/base/_tree.html.haml +5 -0
- data/app/views/{the_sortable_tree_min → sortable/base}/_children.html.haml +0 -0
- data/app/views/{the_sortable_tree → sortable/base}/_controls.html.haml +0 -0
- data/app/views/{the_sortable_tree → sortable/base}/_js_init_sortable_tree.html.haml +0 -0
- data/app/views/{the_sortable_tree → sortable/base}/_js_on_update_tree.html.haml +0 -0
- data/app/views/{the_sortable_tree → sortable/base}/_js_rebuild_ajax.html.haml +0 -0
- data/app/views/{the_sortable_tree → sortable/base}/_link.html.haml +0 -0
- data/app/views/{the_sortable_tree → sortable/base}/_new.html.haml +0 -0
- data/app/views/{the_sortable_tree → sortable/base}/_node.html.haml +0 -0
- data/app/views/sortable/base/_tree.html.haml +7 -0
- data/app/views/tree/base/_children.html.haml +1 -0
- data/app/views/{the_sortable_tree_min → tree/base}/_link.html.haml +0 -0
- data/app/views/{the_sortable_tree_min → tree/base}/_node.html.haml +0 -0
- data/app/views/tree/base/_tree.html.haml +3 -0
- data/config/locales/en.yml +30 -9
- data/lib/generators/the_sortable_tree/views_generator.rb +10 -5
- data/lib/the_sortable_tree/version.rb +1 -1
- metadata +36 -27
- data/app/assets/stylesheets/the_sortable_tree.css +0 -120
- data/app/assets/stylesheets/the_sortable_tree_min.css +0 -26
- data/app/views/the_sortable_tree/_tree.html.haml +0 -6
- data/app/views/the_sortable_tree_min/_tree.html.haml +0 -2
data/README.md
CHANGED
@@ -1,40 +1,51 @@
|
|
1
1
|
### TheSortableTree
|
2
2
|
|
3
|
-
|
3
|
+
Awesome Helper for building sortable nested sets
|
4
4
|
|
5
|
-
|
5
|
+
### Keywords
|
6
6
|
|
7
|
-
|
7
|
+
Sortable awesom_nested_set, Drag&Drop GUI for awesom_nested_set, View Helper for nested set, Nested Comments
|
8
8
|
|
9
|
-
|
9
|
+
### Description
|
10
|
+
|
11
|
+
**sortable_tree** - recursive helper-method for rendering sortable awesome_nested_set tree.
|
12
|
+
|
13
|
+
**sortable_tree** uses partials for rendering, that's why it is **so easy to customize**!
|
14
|
+
|
15
|
+
### Capabilities
|
10
16
|
|
11
|
-
**
|
17
|
+
**Just Tree [default or tree option)**
|
12
18
|
|
13
19
|

|
14
20
|
|
15
|
-
**
|
21
|
+
**Drag&Drop Sortable Tree [sortable option]**
|
16
22
|
|
17
|
-
|
23
|
+

|
24
|
+
|
25
|
+
**Comments Tree [__comments__ option]**
|
18
26
|
|
19
|
-
|
27
|
+
With New Comment form and reply functionality
|
20
28
|
|
21
|
-
|
22
|
-
* Simple nested sets (**min** option)
|
23
|
-
* Nested sets with expand/collapse animation (**expand** option) [under development]
|
24
|
-
* Nested comments (**comments** option) [under development]
|
29
|
+

|
25
30
|
|
26
31
|
### Can I use gem with Rails 2 or Rails 3.0?
|
27
32
|
|
28
|
-
|
33
|
+
There is no strong dependencies for Rails 3.
|
29
34
|
|
30
|
-
|
35
|
+
Take files from the gem and put it in your Rails 2 application.
|
31
36
|
|
32
|
-
|
37
|
+
And fix errors :) Ha-Ha-Ha! You can ask me if you will do it.
|
33
38
|
|
34
|
-
|
39
|
+
### LiveDemo and App for testcase creating
|
40
|
+
|
41
|
+
https://github.com/the-teacher/the_sortable_tree_test_app
|
35
42
|
|
36
43
|
### Changelog
|
37
44
|
|
45
|
+
1.9.0 - 1) **Helper API changed!** 2) Comments tree with sand form and reply fu! 3) Way to manual set sortable Model klass into controller.
|
46
|
+
|
47
|
+
1.8.6 - fixed CamelCase names definition (by andisthejackass)
|
48
|
+
|
38
49
|
1.8.5 - helper can rendering a part tree
|
39
50
|
|
40
51
|
1.8.0 - stable release
|
@@ -51,17 +62,15 @@ Rendered by 50 sec.
|
|
51
62
|
|
52
63
|
I think it is good result for rendering by partials.
|
53
64
|
|
54
|
-
|
55
|
-
|
56
|
-
### ERB vs HAML vs SLIM
|
65
|
+
### It's can be faster?
|
57
66
|
|
58
|
-
|
67
|
+
Perhaps. Read next idea to learn more. There is no implementation now, sorry.
|
59
68
|
|
60
|
-
|
69
|
+
https://github.com/the-teacher/the_sortable_tree/issues/milestones?with_issues=no
|
61
70
|
|
62
|
-
|
71
|
+
### ERB vs HAML vs SLIM
|
63
72
|
|
64
|
-
|
73
|
+
HAML by default. You can use any Template Engine, but convert partials by yourself, plz.
|
65
74
|
|
66
75
|
### Install
|
67
76
|
|
@@ -69,13 +78,9 @@ Read project wiki for looking ERB partials
|
|
69
78
|
gem 'awesome_nested_set' # gem 'nested_set'
|
70
79
|
gem 'the_sortable_tree'
|
71
80
|
|
81
|
+
```ruby
|
72
82
|
bundle
|
73
|
-
|
74
|
-
### Require
|
75
|
-
|
76
|
-
1. gem 'nested_set' or gem 'awesome_nested_set'
|
77
|
-
2. gem 'haml'
|
78
|
-
3. JQuery UI
|
83
|
+
```
|
79
84
|
|
80
85
|
### Example of using with Page Model
|
81
86
|
|
@@ -160,82 +165,72 @@ class PagesController < ApplicationController
|
|
160
165
|
end
|
161
166
|
```
|
162
167
|
|
163
|
-
###
|
168
|
+
### Extend your Layout (erb)
|
164
169
|
|
165
170
|
``` ruby
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
171
|
+
<%= stylesheet_link_tag "application" %>
|
172
|
+
<%= javascript_include_tag "application" %>
|
173
|
+
<%= csrf_meta_tags %>
|
174
|
+
|
175
|
+
<%= javascript_include_tag 'jquery.ui.nestedSortable' %>
|
176
|
+
<%= javascript_include_tag 'comments_tree' %>
|
170
177
|
|
171
|
-
|
178
|
+
<%= stylesheet_link_tag 'tree', :media => :all %>
|
179
|
+
<%= stylesheet_link_tag 'sortable', :media => :all %>
|
180
|
+
<%= stylesheet_link_tag 'comments_tree', :media => :all %>
|
172
181
|
```
|
173
182
|
|
174
|
-
or (without administrator controls and drag&drop)
|
175
183
|
|
176
|
-
|
177
|
-
- content_for :css do
|
178
|
-
= stylesheet_link_tag 'the_sortable_tree_min', :media => :screen
|
184
|
+
### Render your tree
|
179
185
|
|
180
|
-
|
186
|
+
``` ruby
|
187
|
+
= sortable_tree @pages, :new_url => new_page_path
|
181
188
|
```
|
182
189
|
|
183
|
-
###
|
184
|
-
|
185
|
-
**Use sortable_tree as view helper for simple rendering of nested_set tree**
|
190
|
+
### Render your sortable tree
|
186
191
|
|
187
192
|
``` ruby
|
188
|
-
|
193
|
+
= sortable_tree @pages, :new_url => new_page_path, :type => :sortable, :max_levels => 4
|
189
194
|
```
|
190
195
|
|
191
|
-
|
196
|
+
### Render your comments tree (with New Form and Reply)
|
197
|
+
|
198
|
+
Plz, read **Comments Doc** before using this
|
192
199
|
|
193
200
|
``` ruby
|
194
|
-
|
195
|
-
create app/views/pages/the_sortable_tree_min/_children.html.haml
|
196
|
-
create app/views/pages/the_sortable_tree_min/_node.html.haml
|
197
|
-
create app/views/pages/the_sortable_tree_min/_link.html.haml
|
198
|
-
create app/views/pages/the_sortable_tree_min/_tree.html.haml
|
201
|
+
= sortable_tree @comments, :title => :name, :type => :comments
|
199
202
|
```
|
200
203
|
|
201
|
-
|
204
|
+
### Comments Doc
|
205
|
+
|
206
|
+
Coming soon...
|
207
|
+
|
208
|
+
### Customization
|
209
|
+
|
210
|
+
TheSortableTree view generator will copy a set of partials from gem to your View directory.
|
202
211
|
|
203
212
|
``` ruby
|
204
|
-
|
205
|
-
= stylesheet_link_tag 'the_sortable_tree_min', :media => :screen
|
206
|
-
= sortable_tree @pages, :new_url => new_page_path, :path => 'pages/the_sortable_tree_min'
|
213
|
+
rails g the_sortable_tree:views Model [option]
|
207
214
|
```
|
208
215
|
|
209
|
-
|
216
|
+
## Examples
|
217
|
+
|
218
|
+
### Customize your tree
|
210
219
|
|
211
220
|
``` ruby
|
212
|
-
rails g the_sortable_tree:views
|
221
|
+
rails g the_sortable_tree:views Page
|
213
222
|
```
|
214
223
|
|
215
|
-
|
224
|
+
### Customize your sortable tree
|
216
225
|
|
217
226
|
``` ruby
|
218
|
-
|
219
|
-
create app/views/pages/the_sortable_tree/_controls.html.haml
|
220
|
-
create app/views/pages/the_sortable_tree/_node.html.haml
|
221
|
-
create app/views/pages/the_sortable_tree/_js_init_sortable_tree.html.haml
|
222
|
-
create app/views/pages/the_sortable_tree/_js_on_update_tree.html.haml
|
223
|
-
create app/views/pages/the_sortable_tree/_js_rebuild_ajax.html.haml
|
224
|
-
create app/views/pages/the_sortable_tree/_link.html.haml
|
225
|
-
create app/views/pages/the_sortable_tree/_children.html.haml
|
226
|
-
create app/views/pages/the_sortable_tree/_new.html.haml
|
227
|
-
create app/views/pages/the_sortable_tree/_tree.html.haml
|
227
|
+
rails g the_sortable_tree:views Page sortable
|
228
228
|
```
|
229
229
|
|
230
|
-
Customize
|
230
|
+
### Customize your comments tree
|
231
231
|
|
232
232
|
``` ruby
|
233
|
-
|
234
|
-
= stylesheet_link_tag 'the_sortable_tree', :media => :screen
|
235
|
-
- content_for :js do
|
236
|
-
= javascript_include_tag 'jquery.ui.nestedSortable'
|
237
|
-
|
238
|
-
= sortable_tree @pages, :new_url => new_page_path, :path => 'pages/the_sortable_tree', :max_levels => 2
|
233
|
+
rails g the_sortable_tree:views Comment comments
|
239
234
|
```
|
240
235
|
|
241
236
|
### Rendering a part of tree
|
@@ -250,9 +245,27 @@ Customize and use it!
|
|
250
245
|
= sortable_tree @pages, :new_url => new_page_path
|
251
246
|
```
|
252
247
|
|
253
|
-
###
|
248
|
+
### Troubleshooting
|
254
249
|
|
255
|
-
|
250
|
+
If **TheSortableTree** can't correctly define a Name of your Model, just add **sortable_model** into your Controller:
|
251
|
+
|
252
|
+
``` ruby
|
253
|
+
class Inventory::CategoriesController < ApplicationController
|
254
|
+
include TheSortableTreeController::Rebuild
|
255
|
+
|
256
|
+
def sortable_model
|
257
|
+
Inventory::Category
|
258
|
+
end
|
259
|
+
|
260
|
+
def index
|
261
|
+
@inventory_categories = Inventory::Category.nested_set.all
|
262
|
+
end
|
263
|
+
|
264
|
+
def manage
|
265
|
+
@inventory_categories = Inventory::Category.nested_set.all
|
266
|
+
end
|
267
|
+
end
|
268
|
+
```
|
256
269
|
|
257
270
|
### Options
|
258
271
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
$ ->
|
2
|
+
class @CommentsTreeInit
|
3
|
+
# SELECTORS
|
4
|
+
reply_links: $('.comments_tree .comment .reply')
|
5
|
+
skip_link: $('.comments_tree .new_comment .skip')
|
6
|
+
new_comment_form: $('.comments_tree form.new_comment')
|
7
|
+
parent_input: $(".comments_tree form.new_comment input[name='comment[parent_id]']")
|
8
|
+
|
9
|
+
constructor: ->
|
10
|
+
|
11
|
+
@reply_links.click (event) =>
|
12
|
+
# GET DATA
|
13
|
+
link = $ event.target
|
14
|
+
comment = link.parents('.comment')
|
15
|
+
title = comment.find('.title .main')
|
16
|
+
hidden_field = comment.find('input:hidden')
|
17
|
+
parent_id = hidden_field.val()
|
18
|
+
|
19
|
+
form = @new_comment_form
|
20
|
+
for_block = form.find('.for')
|
21
|
+
name_field = for_block.find('i')
|
22
|
+
|
23
|
+
# SET DATA
|
24
|
+
name_field.html title.html()
|
25
|
+
@parent_input.val parent_id
|
26
|
+
|
27
|
+
# SHOW and JUMP
|
28
|
+
for_block.show()
|
29
|
+
window.location.hash = '#new_comment'
|
30
|
+
|
31
|
+
false
|
32
|
+
|
33
|
+
@skip_link.click (event) =>
|
34
|
+
link = $ event.target
|
35
|
+
form = @new_comment_form
|
36
|
+
for_block = form.find('.for')
|
37
|
+
name_field = for_block.find('i')
|
38
|
+
|
39
|
+
name_field.html ''
|
40
|
+
@parent_input.val ''
|
41
|
+
|
42
|
+
for_block.hide()
|
43
|
+
|
44
|
+
false
|
45
|
+
|
46
|
+
new @CommentsTreeInit
|
@@ -0,0 +1,84 @@
|
|
1
|
+
.comments_tree{
|
2
|
+
* {
|
3
|
+
margin: 0; padding: 0;
|
4
|
+
list-style:none;
|
5
|
+
}
|
6
|
+
|
7
|
+
.new_comment{
|
8
|
+
padding: 10px;
|
9
|
+
margin-bottom: 10px;
|
10
|
+
border: 1px solid Blue;
|
11
|
+
border-radius: 5px;
|
12
|
+
p{
|
13
|
+
margin-bottom: 10px;
|
14
|
+
}
|
15
|
+
input[type=text], textarea{
|
16
|
+
border: 1px solid Grey;
|
17
|
+
border-left: 2px solid Grey;
|
18
|
+
width: 90%;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
.nested_set{
|
23
|
+
margin-bottom: 25px;
|
24
|
+
}
|
25
|
+
|
26
|
+
ol{
|
27
|
+
|
28
|
+
margin: 0;
|
29
|
+
padding: 0;
|
30
|
+
list-style:none;
|
31
|
+
|
32
|
+
&.nested_set {
|
33
|
+
list-style:none;
|
34
|
+
font-size: 16px;
|
35
|
+
|
36
|
+
li{
|
37
|
+
font-size: 0.95em;
|
38
|
+
line-height: 130%;
|
39
|
+
margin-bottom: 5px;
|
40
|
+
list-style:none;
|
41
|
+
list-style-position: outside;
|
42
|
+
|
43
|
+
.comment{
|
44
|
+
border: 1px solid LightGray;
|
45
|
+
border-radius: 4px;
|
46
|
+
padding: 10px;
|
47
|
+
|
48
|
+
.title, .contacts{
|
49
|
+
margin-bottom: 5px;
|
50
|
+
}
|
51
|
+
|
52
|
+
.title{
|
53
|
+
color: blue;
|
54
|
+
.reply a{
|
55
|
+
font-size: 0.9em;
|
56
|
+
font-family: Arial;
|
57
|
+
color: green;
|
58
|
+
text-decoration: none;
|
59
|
+
&:hover{ text-decoration: underline; }
|
60
|
+
}
|
61
|
+
}
|
62
|
+
.contacts{
|
63
|
+
font-style: italic;
|
64
|
+
}
|
65
|
+
.content{
|
66
|
+
background: LightGray;
|
67
|
+
border-radius: 2px;
|
68
|
+
font-family: Arial;
|
69
|
+
padding: 5px;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
ol{
|
75
|
+
border-left: 1px dashed LightGreen;
|
76
|
+
padding-left: 10px;
|
77
|
+
margin-left: 15px;
|
78
|
+
margin-top: 5px;
|
79
|
+
|
80
|
+
li{ font-weight: normal; }
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
.sortable{
|
2
|
+
* {
|
3
|
+
margin: 0; padding: 0;
|
4
|
+
list-style: none;
|
5
|
+
}
|
6
|
+
|
7
|
+
.nested_set_new_image{
|
8
|
+
vertical-align: middle;
|
9
|
+
border: none;
|
10
|
+
}
|
11
|
+
|
12
|
+
.nested_set_new{
|
13
|
+
margin: 25px 0;
|
14
|
+
a{ font-size: 14pt }
|
15
|
+
}
|
16
|
+
|
17
|
+
.nested_set{
|
18
|
+
margin: 0; padding: 0;
|
19
|
+
list-style: none;
|
20
|
+
font-size: 16px;
|
21
|
+
|
22
|
+
a{
|
23
|
+
color: #000;
|
24
|
+
font-size: 10pt;
|
25
|
+
font-weight: normal;
|
26
|
+
text-decoration: none;
|
27
|
+
line-height: 150%;
|
28
|
+
margin-left: 30px;
|
29
|
+
margin-right: 120px;
|
30
|
+
display: block;
|
31
|
+
|
32
|
+
&:hover{
|
33
|
+
color: #2476FF;
|
34
|
+
text-decoration: none;
|
35
|
+
}
|
36
|
+
|
37
|
+
img{
|
38
|
+
float: left
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
ol{
|
43
|
+
margin: 0 0 0 25px;
|
44
|
+
border-left: 1px dashed gray;
|
45
|
+
li{ margin-bottom: 5px; }
|
46
|
+
}
|
47
|
+
|
48
|
+
.root{
|
49
|
+
a{ font-weight: bold; }
|
50
|
+
}
|
51
|
+
.handle{
|
52
|
+
width: 16px;
|
53
|
+
height: 16px;
|
54
|
+
float: left;
|
55
|
+
cursor: move;
|
56
|
+
background: transparent url(/assets/iconza/blue/move.png) no-repeat scroll center center;
|
57
|
+
}
|
58
|
+
.link{
|
59
|
+
position: relative;
|
60
|
+
overflow: hidden;
|
61
|
+
zoom: 1;
|
62
|
+
padding: 5px;
|
63
|
+
margin: 0 0 5px 5px;
|
64
|
+
background: #EFEFEF;
|
65
|
+
border-radius: 5px;
|
66
|
+
&:hover{
|
67
|
+
background: #FEE;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
.controls{
|
71
|
+
position: absolute;
|
72
|
+
top: 5px; right: 10px;
|
73
|
+
}
|
74
|
+
.button{
|
75
|
+
width: 20px;
|
76
|
+
height: 20px;
|
77
|
+
display: block;
|
78
|
+
float: left;
|
79
|
+
margin: 0 0 0 3px;
|
80
|
+
cursor: pointer;
|
81
|
+
|
82
|
+
.new{
|
83
|
+
background: transparent url(/assets/iconza/blue/add.png) no-repeat scroll center center;
|
84
|
+
&:hover{ background: transparent url(/assets/iconza/red/add.png) no-repeat scroll center center }
|
85
|
+
}
|
86
|
+
.edit{
|
87
|
+
background: transparent url(/assets/iconza/blue/edit.png) no-repeat scroll center center;
|
88
|
+
&:hover{ background: transparent url(/assets/iconza/red/edit.png) no-repeat scroll center center }
|
89
|
+
}
|
90
|
+
.delete{
|
91
|
+
background: transparent url(/assets/iconza/blue/delete.png) no-repeat scroll center center;
|
92
|
+
&:hover{ background: transparent url(/assets/iconza/red/delete.png) no-repeat scroll center center }
|
93
|
+
}
|
94
|
+
.undeleted{ background: transparent url(/assets/iconza/gray/delete.png) no-repeat scroll center center }
|
95
|
+
}
|
96
|
+
|
97
|
+
.placeholder {
|
98
|
+
background-color: #EEF;
|
99
|
+
border: 1px dashed blue;
|
100
|
+
}
|
101
|
+
.ui-nestedSortable-error {
|
102
|
+
background: #FAA;
|
103
|
+
color: #8a1f11;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
.tree{
|
2
|
+
* {
|
3
|
+
margin: 0; padding: 0;
|
4
|
+
list-style:none;
|
5
|
+
}
|
6
|
+
|
7
|
+
ol{
|
8
|
+
|
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;
|
30
|
+
|
31
|
+
li{ font-weight: normal; }
|
32
|
+
}
|
33
|
+
|
34
|
+
a:hover { color: #003A89 !important; }
|
35
|
+
a:visited { color: #809dc4; }
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
@@ -5,12 +5,12 @@ module TheSortableTreeController
|
|
5
5
|
module DefineVariablesMethod
|
6
6
|
public
|
7
7
|
def the_define_common_variables
|
8
|
-
collection =
|
9
|
-
variable
|
10
|
-
klass
|
8
|
+
collection = self.class.to_s.split(':').last.sub(/Controller/,'').underscore.downcase # recipes
|
9
|
+
variable = collection.singularize # recipe
|
10
|
+
klass = self.respond_to?(:sortable_model) ? self.sortable_model : variable.classify.constantize # Recipe
|
11
11
|
["@#{variable}", collection, klass]
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
14
14
|
|
15
15
|
module Rebuild
|
16
16
|
include DefineVariablesMethod
|
@@ -36,7 +36,7 @@ module TheSortableTreeController
|
|
36
36
|
|
37
37
|
render(:nothing => true)
|
38
38
|
end
|
39
|
-
end
|
39
|
+
end
|
40
40
|
|
41
41
|
module ReversedRebuild
|
42
42
|
include DefineVariablesMethod
|
@@ -62,6 +62,5 @@ module TheSortableTreeController
|
|
62
62
|
|
63
63
|
render(:nothing => true)
|
64
64
|
end
|
65
|
-
end
|
66
|
-
|
65
|
+
end
|
67
66
|
end
|
@@ -12,28 +12,49 @@ module TheSortableTreeHelper
|
|
12
12
|
def define_class_of_elements_of tree
|
13
13
|
case
|
14
14
|
when tree.is_a?(ActiveRecord::Relation) then tree.name.to_s.underscore.downcase
|
15
|
-
when tree.empty?
|
15
|
+
when tree.empty? then nil
|
16
16
|
else tree.first.class.to_s.underscore.downcase
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
:
|
27
|
-
|
20
|
+
# types:
|
21
|
+
# tree
|
22
|
+
# sortable
|
23
|
+
# comments
|
24
|
+
def sortable_tree(tree, options= {})
|
25
|
+
opts = {
|
26
|
+
:max_levels => 3,
|
27
|
+
:type => :tree,
|
28
|
+
:js => false,
|
29
|
+
:path => false,
|
30
|
+
:title => :title,
|
31
|
+
:klass => define_class_of_elements_of(tree),
|
32
|
+
# comments options
|
33
|
+
:node_id => :id,
|
34
|
+
:contacts_field => :email,
|
35
|
+
:content_field => :content,
|
36
|
+
:raw_content_field => :raw_content
|
37
|
+
}.merge! options
|
38
|
+
|
39
|
+
# RAILS require
|
40
|
+
opts[:namespace] = Array.wrap opts[:namespace]
|
41
|
+
|
42
|
+
# PATH building
|
43
|
+
unless opts[:path]
|
44
|
+
variant = 'base'
|
45
|
+
variant = 'js' if opts[:js]
|
46
|
+
opts[:path] = "#{opts[:type]}/#{variant}"
|
47
|
+
end
|
48
|
+
|
28
49
|
render :partial => "#{opts[:path]}/tree", :locals => { :tree => sortable_tree_builder(tree, opts), :opts => opts }
|
29
50
|
end
|
30
51
|
|
31
52
|
def sortable_tree_builder(tree, options= {})
|
32
53
|
result = ''
|
33
|
-
opts
|
34
|
-
:id
|
35
|
-
:node
|
36
|
-
:root
|
54
|
+
opts = {
|
55
|
+
:id => :id, # node id field
|
56
|
+
:node => nil, # node
|
57
|
+
:root => false, # is it root node?
|
37
58
|
:level => 0 # recursion level
|
38
59
|
}.merge!(options)
|
39
60
|
|
@@ -66,4 +87,4 @@ module TheSortableTreeHelper
|
|
66
87
|
end
|
67
88
|
raw result
|
68
89
|
end
|
69
|
-
end
|
90
|
+
end
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
= form_for Comment.new, :class => :new_comment do |f|
|
2
|
+
= f.hidden_field :parent_id
|
3
|
+
|
4
|
+
%label= t('.title')
|
5
|
+
%p= f.text_field opts[:title]
|
6
|
+
|
7
|
+
%label= t('.contacts')
|
8
|
+
%p= f.text_field opts[:contacts_field]
|
9
|
+
|
10
|
+
%label
|
11
|
+
= t('.content')
|
12
|
+
%span.for{ :style => 'display:none' }
|
13
|
+
= t('.for')
|
14
|
+
%i Undefined
|
15
|
+
= link_to t('.skip'), '#', :class => :skip
|
16
|
+
%p= f.text_area opts[:raw_content_field]
|
17
|
+
|
18
|
+
%div= f.submit t('.submit')
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,7 @@
|
|
1
|
+
.sortable
|
2
|
+
= render :partial => "#{opts[:path]}/new", :locals => { :opts => opts }
|
3
|
+
- unless tree.empty?
|
4
|
+
= render :partial => "#{opts[:path]}/js_init_sortable_tree", :locals => { :opts => opts }
|
5
|
+
= render :partial => "#{opts[:path]}/js_on_update_tree"
|
6
|
+
= render :partial => "#{opts[:path]}/js_rebuild_ajax", :locals => { :opts => opts }
|
7
|
+
%ol.ui-sortable.sortable.nested_set{ :id => "#{opts[:klass]}_nested_set" }= raw tree
|
@@ -0,0 +1 @@
|
|
1
|
+
= content_tag :ol, raw(children)
|
File without changes
|
File without changes
|
data/config/locales/en.yml
CHANGED
@@ -1,10 +1,31 @@
|
|
1
1
|
en:
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
sortable:
|
3
|
+
base:
|
4
|
+
new:
|
5
|
+
create: Add element
|
6
|
+
controls:
|
7
|
+
edit_this: Edit element
|
8
|
+
delete: Delete element
|
9
|
+
delete_confirm: Do you want to delete element?
|
10
|
+
cant_be_deleted: Cant be deleted. Has nested elements
|
11
|
+
delete_nested_elements: Delete all nested elements
|
12
|
+
|
13
|
+
comments:
|
14
|
+
base:
|
15
|
+
new_comment_form:
|
16
|
+
title: Name
|
17
|
+
conatacts: Email
|
18
|
+
content: Your comment
|
19
|
+
for: for
|
20
|
+
skip: '[skip]'
|
21
|
+
submit: Send Comment
|
22
|
+
comment:
|
23
|
+
reply: '[reply]'
|
24
|
+
new:
|
25
|
+
create: Add element
|
26
|
+
controls:
|
27
|
+
edit_this: Edit element
|
28
|
+
delete: Delete element
|
29
|
+
delete_confirm: Do you want to delete element?
|
30
|
+
cant_be_deleted: Cant be deleted. Has nested elements
|
31
|
+
delete_nested_elements: Delete all nested elements
|
@@ -5,16 +5,21 @@ module TheSortableTree
|
|
5
5
|
|
6
6
|
def self.banner
|
7
7
|
<<-BANNER.chomp
|
8
|
-
rails g the_sortable_tree:views MODEL [
|
8
|
+
rails g the_sortable_tree:views MODEL [tree|sortable|comments]
|
9
9
|
Copies files for rendering sortable nested set
|
10
10
|
BANNER
|
11
11
|
end
|
12
12
|
|
13
13
|
def copy_sortable_tree_files
|
14
|
-
|
15
|
-
|
14
|
+
# sortable
|
15
|
+
# comments
|
16
|
+
# tree
|
17
|
+
if ARGV[1] == 'sortable'
|
18
|
+
directory "sortable/base", "app/views/#{folder}/sortable/base"
|
19
|
+
elsif ARGV[1] == 'comments'
|
20
|
+
directory "comments/base", "app/views/#{folder}/comments/base"
|
16
21
|
else
|
17
|
-
directory "
|
22
|
+
directory "tree/base", "app/views/#{folder}/tree/base"
|
18
23
|
end
|
19
24
|
end
|
20
25
|
|
@@ -24,6 +29,6 @@ rails g the_sortable_tree:views MODEL [min]
|
|
24
29
|
name.pluralize.downcase
|
25
30
|
end
|
26
31
|
|
27
|
-
end
|
32
|
+
end
|
28
33
|
end
|
29
34
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: the_sortable_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-08 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &76895850 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '3.1'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *76895850
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: sqlite3
|
27
|
-
requirement: &
|
27
|
+
requirement: &76895640 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *76895640
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &76895410 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *76895410
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec-rails
|
49
|
-
requirement: &
|
49
|
+
requirement: &76895200 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,8 +54,9 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
58
|
-
description: Drag&Drop GUI
|
57
|
+
version_requirements: *76895200
|
58
|
+
description: Sortable awesom_nested_set, Drag&Drop GUI for awesom_nested_set, View
|
59
|
+
Helper for nested set, Nested Comments
|
59
60
|
email:
|
60
61
|
- zykin-ilya@ya.ru
|
61
62
|
executables: []
|
@@ -87,22 +88,29 @@ files:
|
|
87
88
|
- app/assets/images/iconza/blue/delete.png
|
88
89
|
- app/assets/images/iconza/blue/up.png
|
89
90
|
- app/assets/images/iconza/blue/add.png
|
90
|
-
- app/assets/stylesheets/
|
91
|
-
- app/assets/stylesheets/
|
91
|
+
- app/assets/stylesheets/tree.css.scss
|
92
|
+
- app/assets/stylesheets/comments_tree.css.scss
|
93
|
+
- app/assets/stylesheets/sortable.css.scss
|
92
94
|
- app/assets/javascripts/jquery.ui.nestedSortable.js
|
93
|
-
- app/
|
94
|
-
- app/views/
|
95
|
-
- app/views/
|
96
|
-
- app/views/
|
97
|
-
- app/views/
|
98
|
-
- app/views/
|
99
|
-
- app/views/
|
100
|
-
- app/views/
|
101
|
-
- app/views/
|
102
|
-
- app/views/
|
103
|
-
- app/views/
|
104
|
-
- app/views/
|
105
|
-
- app/views/
|
95
|
+
- app/assets/javascripts/comments_tree.js.coffee
|
96
|
+
- app/views/comments/base/_children.html.haml
|
97
|
+
- app/views/comments/base/_node.html.haml
|
98
|
+
- app/views/comments/base/_tree.html.haml
|
99
|
+
- app/views/comments/base/_comment.html.haml
|
100
|
+
- app/views/comments/base/_new_comment_form.html.haml
|
101
|
+
- app/views/sortable/base/_children.html.haml
|
102
|
+
- app/views/sortable/base/_node.html.haml
|
103
|
+
- app/views/sortable/base/_link.html.haml
|
104
|
+
- app/views/sortable/base/_tree.html.haml
|
105
|
+
- app/views/sortable/base/_new.html.haml
|
106
|
+
- app/views/sortable/base/_controls.html.haml
|
107
|
+
- app/views/sortable/base/_js_rebuild_ajax.html.haml
|
108
|
+
- app/views/sortable/base/_js_init_sortable_tree.html.haml
|
109
|
+
- app/views/sortable/base/_js_on_update_tree.html.haml
|
110
|
+
- app/views/tree/base/_children.html.haml
|
111
|
+
- app/views/tree/base/_node.html.haml
|
112
|
+
- app/views/tree/base/_link.html.haml
|
113
|
+
- app/views/tree/base/_tree.html.haml
|
106
114
|
- app/helpers/the_sortable_tree_helper.rb
|
107
115
|
- config/locales/ru.yml
|
108
116
|
- config/locales/en.yml
|
@@ -169,7 +177,8 @@ rubyforge_project: the_sortable_tree
|
|
169
177
|
rubygems_version: 1.8.15
|
170
178
|
signing_key:
|
171
179
|
specification_version: 3
|
172
|
-
summary: Drag&Drop GUI
|
180
|
+
summary: Sortable awesom_nested_set, Drag&Drop GUI for awesom_nested_set, View Helper
|
181
|
+
for nested set, Nested Comments
|
173
182
|
test_files:
|
174
183
|
- spec/controlllers/controller_mixin_spec.rb
|
175
184
|
- spec/spec_helper.rb
|
@@ -1,120 +0,0 @@
|
|
1
|
-
ol.nested_set * {
|
2
|
-
margin: 0; padding: 0;
|
3
|
-
list-style:none;
|
4
|
-
}
|
5
|
-
.nested_set{
|
6
|
-
padding: 0;
|
7
|
-
list-style:none;
|
8
|
-
font-size: 16px;
|
9
|
-
}
|
10
|
-
.nested_set ol{
|
11
|
-
margin:0 0 0 25px;
|
12
|
-
border-left:1px dashed gray;
|
13
|
-
}
|
14
|
-
.nested_set li{
|
15
|
-
margin-bottom:5px;
|
16
|
-
}
|
17
|
-
.nested_set a{
|
18
|
-
color:#000;
|
19
|
-
font-size:10pt;
|
20
|
-
font-weight:normal;
|
21
|
-
text-decoration:none;
|
22
|
-
line-height: 150%;
|
23
|
-
margin-left:30px;
|
24
|
-
margin-right:120px;
|
25
|
-
display:block;
|
26
|
-
}
|
27
|
-
.nested_set a img{float:left;}
|
28
|
-
|
29
|
-
.nested_set .root a{
|
30
|
-
font-weight:bold;
|
31
|
-
}
|
32
|
-
.nested_set a:hover{
|
33
|
-
color:#2476FF;
|
34
|
-
text-decoration:none;
|
35
|
-
}
|
36
|
-
.nested_set .handle{
|
37
|
-
cursor: move;
|
38
|
-
}
|
39
|
-
.nested_set .link{
|
40
|
-
position: relative;
|
41
|
-
overflow: hidden;
|
42
|
-
zoom:1;
|
43
|
-
padding:5px;
|
44
|
-
margin:0 0 5px 5px;
|
45
|
-
background:#EFEFEF;
|
46
|
-
-moz-border-radius:5px;
|
47
|
-
}
|
48
|
-
.nested_set .link:hover{
|
49
|
-
background:#FEE;
|
50
|
-
}
|
51
|
-
.nested_set .controls{
|
52
|
-
position: absolute;
|
53
|
-
top: 5px; right: 10px;
|
54
|
-
}
|
55
|
-
.nested_set .button{
|
56
|
-
width:20px;
|
57
|
-
height:20px;
|
58
|
-
display:block;
|
59
|
-
float:left;
|
60
|
-
margin:0 0 0 3px;
|
61
|
-
cursor:pointer;
|
62
|
-
}
|
63
|
-
.nested_set_new_image{
|
64
|
-
vertical-align:middle;
|
65
|
-
border:none;
|
66
|
-
}
|
67
|
-
.nested_set_new{
|
68
|
-
margin:25px 0;
|
69
|
-
}
|
70
|
-
.nested_set_new a{
|
71
|
-
font-size:14pt;
|
72
|
-
}
|
73
|
-
.nested_set .handle{
|
74
|
-
width:16px;
|
75
|
-
height:16px;
|
76
|
-
float:left;
|
77
|
-
background:transparent url(/assets/iconza/blue/move.png) no-repeat scroll center center;
|
78
|
-
}
|
79
|
-
.nested_set .placeholder {
|
80
|
-
background-color:#EEF;
|
81
|
-
border:1px dashed blue;
|
82
|
-
}
|
83
|
-
.nested_set .ui-nestedSortable-error {
|
84
|
-
background:#FAA;
|
85
|
-
color:#8a1f11;
|
86
|
-
}
|
87
|
-
.nested_set .button.new{ background:transparent url(/assets/iconza/blue/add.png) no-repeat scroll center center; }
|
88
|
-
.nested_set .button.new:hover{ background:transparent url(/assets/iconza/red/add.png) no-repeat scroll center center;}
|
89
|
-
|
90
|
-
.nested_set .button.edit{ background:transparent url(/assets/iconza/blue/edit.png) no-repeat scroll center center; }
|
91
|
-
.nested_set .button.edit:hover{ background:transparent url(/assets/iconza/red/edit.png) no-repeat scroll center center;}
|
92
|
-
|
93
|
-
.nested_set .button.up{ background:transparent url(/assets/iconza/blue/up.png) no-repeat scroll center center; }
|
94
|
-
.nested_set .button.up:hover{ background:transparent url(/assets/iconza/red/up.png) no-repeat scroll center center;}
|
95
|
-
|
96
|
-
.nested_set .button.down{ background:transparent url(/assets/iconza/blue/down.png) no-repeat scroll center center; }
|
97
|
-
.nested_set .button.down:hover{ background:transparent url(/assets/iconza/red/down.png) no-repeat scroll center center;}
|
98
|
-
|
99
|
-
.nested_set .button.delete{ background:transparent url(/assets/iconza/blue/delete.png) no-repeat scroll center center; }
|
100
|
-
.nested_set .button.delete:hover{ background:transparent url(/assets/iconza/red/delete.png) no-repeat scroll center center;}
|
101
|
-
|
102
|
-
.nested_set .button.hard_delete{ background:transparent url(/assets/iconza/gray/delete.png) no-repeat scroll center center; }
|
103
|
-
.nested_set .button.hard_delete:hover{ background:transparent url(/assets/iconza/red/delete.png) no-repeat scroll center center;}
|
104
|
-
|
105
|
-
.nested_set .undeleted{ background:transparent url(/assets/iconza/gray/delete.png) no-repeat scroll center center; }
|
106
|
-
.nested_set .cantup{ background:transparent url(/assets/iconza/gray/up.png) no-repeat scroll center center; }
|
107
|
-
.nested_set .cantdown{ background:transparent url(/assets/iconza/gray/down.png) no-repeat scroll center center; }
|
108
|
-
|
109
|
-
/*STATES*/
|
110
|
-
.nested_set .unsafe{ background:transparent url(/assets/modern/mini-icons/unsafe.png) no-repeat scroll center center; cursor: help; }
|
111
|
-
.nested_set .draft{ background:transparent url(/assets/modern/mini-icons/draft.png) no-repeat scroll center center; cursor: help;}
|
112
|
-
.nested_set .published{ background:transparent url(/assets/modern/mini-icons/publiched.png) no-repeat scroll center center; cursor: help;}
|
113
|
-
.nested_set .restricted{ background:transparent url(/assets/modern/mini-icons/restricted.png) no-repeat scroll center center; cursor: help;}
|
114
|
-
.nested_set .archived{ background:transparent url(/assets/modern/mini-icons/archived.png) no-repeat scroll center center; cursor: help;}
|
115
|
-
.nested_set .deleted{ background:transparent url(/assets/modern/mini-icons/bin.png) no-repeat scroll center center; cursor: help;}
|
116
|
-
|
117
|
-
/* Moderation states*/
|
118
|
-
.nested_set .moderation_unsafe{ background:transparent url(/assets/modern/mini-icons/moderation_unsafe.png) no-repeat scroll center center; cursor: help;}
|
119
|
-
.nested_set .moderation_safe{ background:transparent url(/assets/modern/mini-icons/shield.png) no-repeat scroll center center; cursor: help;}
|
120
|
-
.nested_set .moderation_blocked{ background:transparent url(/assets/modern/mini-icons/moderation_blocked.png) no-repeat scroll center center; cursor: help;}
|
@@ -1,26 +0,0 @@
|
|
1
|
-
ol.nested_set_min * {
|
2
|
-
margin: 0; padding: 0;
|
3
|
-
list-style:none;
|
4
|
-
}
|
5
|
-
ol.nested_set_min {
|
6
|
-
list-style:none;
|
7
|
-
font-size: 16px;
|
8
|
-
}
|
9
|
-
ol.nested_set_min li{
|
10
|
-
font-size: 0.9em;
|
11
|
-
line-height: 130%;
|
12
|
-
margin-bottom: 5px;
|
13
|
-
font-weight: bold;
|
14
|
-
list-style:none;
|
15
|
-
list-style-position: outside;
|
16
|
-
}
|
17
|
-
ol.nested_set_min ol{
|
18
|
-
border-left: 1px dashed #AAA;
|
19
|
-
padding-left: 10px;
|
20
|
-
margin-left: 15px;
|
21
|
-
margin-top: 5px;
|
22
|
-
}
|
23
|
-
ol.nested_set_min ol li{ font-weight: normal; }
|
24
|
-
|
25
|
-
.nested_set_min a:hover { color: #003A89 !important; }
|
26
|
-
.nested_set_min a:visited { color: #809dc4; }
|
@@ -1,6 +0,0 @@
|
|
1
|
-
= render :partial => "#{opts[:path]}/new", :locals => { :opts => opts }
|
2
|
-
- unless tree.empty?
|
3
|
-
= render :partial => "#{opts[:path]}/js_init_sortable_tree", :locals => { :opts => opts }
|
4
|
-
= render :partial => "#{opts[:path]}/js_on_update_tree"
|
5
|
-
= render :partial => "#{opts[:path]}/js_rebuild_ajax", :locals => { :opts => opts }
|
6
|
-
%ol.ui-sortable.sortable.nested_set{ :id => "#{opts[:klass]}_nested_set" }= raw tree
|