sortable_nested_set 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +30 -18
- data/VERSION +1 -1
- data/app/controllers/sortable_nested_set_controller.rb +35 -0
- data/app/helpers/sortable_nested_set_helper.rb +3 -6
- data/app/views/sortable_nested_set/_category.html.erb +4 -10
- data/app/views/sortable_nested_set/_item.html.erb +2 -6
- data/app/views/sortable_nested_set/_tree.html.erb +6 -8
- data/config/routes.rb +3 -0
- data/lib/{sortable_nested_set/acts_as_sortable_nested_set.rb → acts_as_sortable_nested_set.rb} +17 -8
- data/lib/sortable_nested_set.rb +12 -4
- data/public/javascripts/sortable_nested_set.js +40 -40
- data/public/stylesheets/sortable_nested_set.css +7 -7
- data/sortable_nested_set.gemspec +5 -8
- data/test/helper.rb +0 -1
- metadata +7 -10
- data/app/views/sortable_nested_set/sns_destroy_category.js.erb +0 -1
- data/app/views/sortable_nested_set/sns_destroy_item.js.erb +0 -1
- data/lib/sortable_nested_set/engine.rb +0 -7
- data/lib/sortable_nested_set/handles_sortable_nested_set.rb +0 -74
- data/lib/sortable_nested_set/routes.rb +0 -27
data/README.rdoc
CHANGED
@@ -1,32 +1,44 @@
|
|
1
|
-
|
1
|
+
= Sortable Nested Set
|
2
2
|
|
3
|
-
|
4
|
-
gem 'sortable_nested_set'
|
3
|
+
== Requirements
|
5
4
|
|
6
|
-
|
7
|
-
acts_as_sortable_nested_set_of :items
|
8
|
-
where :items is the pluralized Item model (e.g. "File").
|
5
|
+
jQuery is required.
|
9
6
|
|
10
|
-
|
11
|
-
handles_sortable_nested_set
|
12
|
-
to include menu actions.
|
7
|
+
== Usage
|
13
8
|
|
14
|
-
|
15
|
-
sortable_nested_set_for :categories
|
16
|
-
for each pluralized "Category" model.
|
9
|
+
Add the gem to your Gemfile.
|
17
10
|
|
18
|
-
|
19
|
-
|
11
|
+
gem 'sortable_nested_set'
|
12
|
+
|
13
|
+
In each "Category" (e.g. "Directory") migration:
|
20
14
|
lft:integer
|
21
15
|
rgt:integer
|
16
|
+
depth:integer [optional]
|
22
17
|
|
23
|
-
In
|
24
|
-
|
18
|
+
In the routing configuration file:
|
19
|
+
nest the "Category" and "Item" resources
|
20
|
+
|
21
|
+
In each "Category" model:
|
22
|
+
acts_as_sortable_nested_set_of :items
|
23
|
+
where :items is the pluralized, underscored "Item" model (e.g. "ImageFile"=>:image_files).
|
24
|
+
|
25
|
+
In the "Category" and "Item" controllers:
|
26
|
+
[new] use param[:category_id]
|
27
|
+
[destroy] respond_to format.js (and provide associated view)
|
28
|
+
|
29
|
+
In the "Category" and "Items" models:
|
30
|
+
provide #to_s.
|
25
31
|
|
26
32
|
In the <head> section of the layout(s) where the trees will be displayed:
|
27
33
|
yield(:head)
|
34
|
+
after jQuery is loaded.
|
35
|
+
|
36
|
+
== Support for acts_as_list
|
37
|
+
|
38
|
+
When an "Item" model acts_as_list, SortableNestedSet will use its position for sorting.
|
39
|
+
|
40
|
+
== Helpers
|
28
41
|
|
29
|
-
Helpers:
|
30
42
|
sns_options
|
31
43
|
sns_lineage
|
32
|
-
|
44
|
+
sns_tree
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class SortableNestedSetController < ActionController::Base
|
2
|
+
def sns_sort
|
3
|
+
category_class = params[:category_class].classify.constantize
|
4
|
+
|
5
|
+
matches = params[:moved].match(/(\w+)_(\d+)$/)
|
6
|
+
moved_type = matches[1]
|
7
|
+
moved_id = matches[2].to_i
|
8
|
+
moved_parent = nil
|
9
|
+
tree = {} # category_id => [children of move_type]
|
10
|
+
|
11
|
+
for node in params[:tree].scan(/(\w+)\[(\d+)\]=(\w+)/)
|
12
|
+
type = node[0]
|
13
|
+
next unless type == moved_type
|
14
|
+
|
15
|
+
id = node[1].to_i
|
16
|
+
parent = (node[2] == 'root') ? nil : node[2].to_i
|
17
|
+
|
18
|
+
moved_parent = parent if id == moved_id
|
19
|
+
|
20
|
+
tree[parent] ||= []
|
21
|
+
tree[parent] << id
|
22
|
+
end
|
23
|
+
|
24
|
+
if moved_type == category_class.sns_items_type.to_s.singularize
|
25
|
+
item = category_class.sns_items_type.to_s.classify.constantize.find(moved_id)
|
26
|
+
item.remove_from_list if item.respond_to?(:remove_from_list) # acts_as_list support
|
27
|
+
item.update_attribute(category_class.name.foreign_key, moved_parent)
|
28
|
+
item.insert_at(tree[moved_parent].index(moved_id)) if item.respond_to?(:insert_at) # acts_as_list support
|
29
|
+
else
|
30
|
+
moved_type.classify.constantize.find(moved_id).move(moved_parent, tree[moved_parent])
|
31
|
+
end
|
32
|
+
|
33
|
+
render :nothing => true
|
34
|
+
end
|
35
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module SortableNestedSetHelper
|
2
|
-
def
|
2
|
+
def sns_tree(class_or_category)
|
3
3
|
if class_or_category.is_a?(Class)
|
4
4
|
@category_class = class_or_category
|
5
5
|
@categories = @category_class.includes(@category_class.sns_items_type)
|
@@ -8,8 +8,7 @@ module SortableNestedSetHelper
|
|
8
8
|
@categories = class_or_category.self_and_descendants.includes(@category_class.sns_items_type)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
render 'sortable_nested_set/tree', :categories => @categories.arrange, :sns_sort_path => sns_sort_path
|
11
|
+
render 'sortable_nested_set/tree', :category_class => @category_class, :categories => @categories.arrange
|
13
12
|
end
|
14
13
|
|
15
14
|
def sns_lineage(category, options={})
|
@@ -27,8 +26,6 @@ module SortableNestedSetHelper
|
|
27
26
|
end
|
28
27
|
|
29
28
|
def sns_options(category_class, mover=nil)
|
30
|
-
sorted_nested_set_options(category_class, lambda(&:left_column_name), mover)
|
31
|
-
'.' * level + category.name
|
32
|
-
end
|
29
|
+
sorted_nested_set_options(category_class, lambda(&:left_column_name), mover) { |cat, lvl| "#{'.'*lvl}#{cat}" }
|
33
30
|
end
|
34
31
|
end
|
@@ -1,20 +1,14 @@
|
|
1
|
-
<% cpath = category.class.name.underscore + '_path' %>
|
2
|
-
|
3
1
|
<div>
|
4
2
|
<span class="toggle open"></span>
|
5
3
|
<span class="handle"><%= category %></span>
|
6
4
|
<%= link_to image_tag('mega_menu.png'), category, :class => :mega_menu %>
|
7
5
|
<div class="mega_menu_links">
|
8
6
|
<%= link_to_unless_current 'show', category %> |
|
9
|
-
<%= link_to 'edit',
|
10
|
-
<%= link_to 'remove',
|
11
|
-
send("sns_destroy_category_#{cpath}", category),
|
12
|
-
:confirm => 'Are you sure?',
|
13
|
-
:method => :delete,
|
14
|
-
:remote => !current_page?(send(cpath, category)) %> |
|
7
|
+
<%= link_to 'edit', polymorphic_path(category, :action => :edit) %> |
|
8
|
+
<%= link_to 'remove', category, :confirm => 'Are you sure?', :method => :delete, :remote => !current_page?(category) %> |
|
15
9
|
<%= link_to "add #{category.class.sns_subcategories_type.to_s.singularize}",
|
16
|
-
|
10
|
+
polymorphic_path([category, category.class], :action => :new) %> |
|
17
11
|
<%= link_to "add #{category.class.sns_items_type.to_s.singularize}",
|
18
|
-
|
12
|
+
polymorphic_path([category, category.class.sns_items_class], :action => :new) %>
|
19
13
|
</div>
|
20
14
|
</div>
|
@@ -4,12 +4,8 @@
|
|
4
4
|
<%= link_to image_tag('mega_menu.png'), item, :class => :mega_menu %>
|
5
5
|
<div class="mega_menu_links">
|
6
6
|
<%= link_to 'show', item %> |
|
7
|
-
<%= link_to 'edit',
|
8
|
-
<%= link_to 'remove',
|
9
|
-
send("sns_destroy_item_#{item.class.name.underscore}_path", item),
|
10
|
-
:confirm => 'Are you sure?',
|
11
|
-
:method => :delete,
|
12
|
-
:remote => true %>
|
7
|
+
<%= link_to 'edit', polymorphic_path(item, :action => :edit) %> |
|
8
|
+
<%= link_to 'remove', item, :confirm => 'Are you sure?', :method => :delete, :remote => true %>
|
13
9
|
</div>
|
14
10
|
</div>
|
15
11
|
</li>
|
@@ -5,14 +5,12 @@
|
|
5
5
|
'sortable_nested_set' %>
|
6
6
|
<% end %>
|
7
7
|
|
8
|
-
<%= render_tree categories, :id => :sns_categories,
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
</ul>
|
15
|
-
|
8
|
+
<%= render_tree categories, :id => :sns_categories,
|
9
|
+
:class => :sortable,
|
10
|
+
'data-url' => sns_sort_path(:category_class => @category_class) do |category, child| %>
|
11
|
+
<li id="<%= category.class.name.underscore %>_<%= category.id %>" class="sns_category">
|
12
|
+
<%= render :partial => 'sortable_nested_set/category', :object => category %>
|
13
|
+
<ul><%= render :partial => 'sortable_nested_set/item', :collection => category.sns_items %></ul>
|
16
14
|
<%= child %>
|
17
15
|
</li>
|
18
16
|
<% end %>
|
data/config/routes.rb
ADDED
data/lib/{sortable_nested_set/acts_as_sortable_nested_set.rb → acts_as_sortable_nested_set.rb}
RENAMED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'nested_set'
|
2
|
-
include CollectiveIdea::Acts::NestedSet
|
3
2
|
|
4
3
|
module SortableNestedSet
|
5
4
|
def self.included(base)
|
@@ -11,10 +10,12 @@ module SortableNestedSet
|
|
11
10
|
def acts_as_sortable_nested_set_of(items_type)
|
12
11
|
@subcategories_type = "sub#{name.tableize}".to_sym
|
13
12
|
@items_type = items_type
|
13
|
+
@foreign_key = self.class.method_defined?(:parent) ? :parent_id : name.foreign_key
|
14
14
|
|
15
15
|
instance_eval do
|
16
16
|
def sns_subcategories_type ; @subcategories_type end
|
17
17
|
def sns_items_type ; @items_type end
|
18
|
+
def sns_items_class ; @items_type.to_s.singularize.classify.constantize end
|
18
19
|
end
|
19
20
|
|
20
21
|
class_eval do
|
@@ -22,16 +23,22 @@ module SortableNestedSet
|
|
22
23
|
define_method(:sns_items) { send(self.class.sns_items_type) }
|
23
24
|
end
|
24
25
|
|
25
|
-
acts_as_nested_set :parent_column =>
|
26
|
+
acts_as_nested_set :parent_column => @foreign_key
|
26
27
|
|
27
|
-
|
28
|
+
has_many @subcategories_type, :class_name => name, :foreign_key => @foreign_key, :dependent => :destroy
|
29
|
+
has_many @items_type,
|
30
|
+
:order => (sns_items_class.position_column if sns_items_class.method_defined?(:position_column)),
|
31
|
+
:dependent => :destroy
|
28
32
|
|
29
|
-
|
30
|
-
has_many @items_type, :order => :position, :dependent => :destroy
|
33
|
+
after_initialize :default_depth_to_zero
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
34
37
|
module InstanceMethods
|
38
|
+
def indented_name(indentation_character='.')
|
39
|
+
indentation_character * depth + name
|
40
|
+
end
|
41
|
+
|
35
42
|
def move(parent, children)
|
36
43
|
if children.size == 1
|
37
44
|
move_to_child_of(parent)
|
@@ -39,7 +46,7 @@ module SortableNestedSet
|
|
39
46
|
prev_sibling = nil
|
40
47
|
|
41
48
|
for i in 0...children.size
|
42
|
-
if children[i] == id
|
49
|
+
if children[i] == self.id
|
43
50
|
prev_sibling ? move_to_right_of(prev_sibling) : move_to_left_of(children[i+1])
|
44
51
|
break
|
45
52
|
end
|
@@ -49,8 +56,10 @@ module SortableNestedSet
|
|
49
56
|
end
|
50
57
|
end
|
51
58
|
|
52
|
-
|
53
|
-
|
59
|
+
private
|
60
|
+
|
61
|
+
def default_depth_to_zero
|
62
|
+
self.depth ||= 0 if has_attribute?(:depth)
|
54
63
|
end
|
55
64
|
end
|
56
65
|
end
|
data/lib/sortable_nested_set.rb
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require '
|
1
|
+
module SortableNestedSet
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
initializer 'nested_fields.add_middleware' do |app|
|
4
|
+
require 'acts_as_sortable_nested_set'
|
5
|
+
app.middleware.use ActionDispatch::Static, "#{root}/public"
|
6
|
+
end
|
7
|
+
|
8
|
+
config.to_prepare do
|
9
|
+
ApplicationController.helper(SortableNestedSetHelper)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -1,38 +1,44 @@
|
|
1
|
-
$(
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
$(this).
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
1
|
+
$('#sns_categories span.toggle').live('click', function() {
|
2
|
+
$(this).toggleClass('open');
|
3
|
+
$(this).toggleClass('closed');
|
4
|
+
$(this).closest('li').find('> ul').toggle();
|
5
|
+
});
|
6
|
+
|
7
|
+
function linkHover() {
|
8
|
+
$(this).next().addClass('link_hover');
|
9
|
+
}
|
10
|
+
|
11
|
+
function linkUnhover() {
|
12
|
+
if (!$(this).next().hasClass('pop_up_hover'))
|
13
|
+
$(this).next().removeClass('link_hover');
|
14
|
+
}
|
15
|
+
|
16
|
+
function popUpHover() {
|
17
|
+
$(this).removeClass('link_hover');
|
18
|
+
$(this).addClass('pop_up_hover');
|
19
|
+
}
|
20
|
+
|
21
|
+
function popUpUnhover() {
|
22
|
+
$(this).removeClass('pop_up_hover');
|
23
|
+
}
|
24
|
+
|
25
|
+
var linkConfig = {
|
26
|
+
interval: 200,
|
27
|
+
out: linkUnhover,
|
28
|
+
over: linkHover,
|
29
|
+
sensitivity: 4,
|
30
|
+
timeout: 250
|
31
|
+
};
|
32
|
+
|
33
|
+
var popUpConfig = {
|
34
|
+
interval: 0,
|
35
|
+
out: popUpUnhover,
|
36
|
+
over: popUpHover,
|
37
|
+
sensitivity: 4,
|
38
|
+
timeout: 250
|
39
|
+
};
|
35
40
|
|
41
|
+
$(document).ready(function() {
|
36
42
|
$('.mega_menu').hoverIntent(linkConfig);
|
37
43
|
$('.mega_menu_links').hoverIntent(popUpConfig);
|
38
44
|
|
@@ -54,10 +60,4 @@ $(document).ready(function() {
|
|
54
60
|
});
|
55
61
|
}
|
56
62
|
});
|
57
|
-
|
58
|
-
$('#sns_categories .toggle').click(function() {
|
59
|
-
$(this).toggleClass('open');
|
60
|
-
$(this).toggleClass('closed');
|
61
|
-
$(this).closest('li').find('> ul').toggle();
|
62
|
-
});
|
63
63
|
});
|
@@ -1,3 +1,8 @@
|
|
1
|
+
.toggle {
|
2
|
+
cursor: pointer;
|
3
|
+
padding-right: 1em;
|
4
|
+
}
|
5
|
+
|
1
6
|
.mega_menu_links {
|
2
7
|
background: #ffc;
|
3
8
|
border: 1px solid #eea;
|
@@ -12,8 +17,8 @@
|
|
12
17
|
}
|
13
18
|
|
14
19
|
.pop_up_hover {
|
15
|
-
display: block;
|
16
20
|
border: 1px solid #cca;
|
21
|
+
display: block;
|
17
22
|
}
|
18
23
|
|
19
24
|
#sns_categories, #sns_categories ul {
|
@@ -23,7 +28,7 @@
|
|
23
28
|
}
|
24
29
|
|
25
30
|
#sns_categories {
|
26
|
-
margin: 0;
|
31
|
+
margin: 0 0 10px 0;
|
27
32
|
}
|
28
33
|
|
29
34
|
#sns_categories li {
|
@@ -47,11 +52,6 @@
|
|
47
52
|
color: #8a1f11;
|
48
53
|
}
|
49
54
|
|
50
|
-
.toggle {
|
51
|
-
cursor: pointer;
|
52
|
-
padding-right: 1em;
|
53
|
-
}
|
54
|
-
|
55
55
|
#sns_categories span.open {
|
56
56
|
background: url(/images/folder_open.png) no-repeat center;
|
57
57
|
}
|
data/sortable_nested_set.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sortable_nested_set}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jason Murad"]
|
12
|
-
s.date = %q{2011-01-
|
12
|
+
s.date = %q{2011-01-25}
|
13
13
|
s.description = %q{reusable menu for navigation and modification or hierarchical categories}
|
14
14
|
s.email = %q{jason@thriess.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -22,17 +22,14 @@ Gem::Specification.new do |s|
|
|
22
22
|
"README.rdoc",
|
23
23
|
"Rakefile",
|
24
24
|
"VERSION",
|
25
|
+
"app/controllers/sortable_nested_set_controller.rb",
|
25
26
|
"app/helpers/sortable_nested_set_helper.rb",
|
26
27
|
"app/views/sortable_nested_set/_category.html.erb",
|
27
28
|
"app/views/sortable_nested_set/_item.html.erb",
|
28
29
|
"app/views/sortable_nested_set/_tree.html.erb",
|
29
|
-
"
|
30
|
-
"
|
30
|
+
"config/routes.rb",
|
31
|
+
"lib/acts_as_sortable_nested_set.rb",
|
31
32
|
"lib/sortable_nested_set.rb",
|
32
|
-
"lib/sortable_nested_set/acts_as_sortable_nested_set.rb",
|
33
|
-
"lib/sortable_nested_set/engine.rb",
|
34
|
-
"lib/sortable_nested_set/handles_sortable_nested_set.rb",
|
35
|
-
"lib/sortable_nested_set/routes.rb",
|
36
33
|
"public/images/folder_closed.png",
|
37
34
|
"public/images/folder_open.png",
|
38
35
|
"public/images/mega_menu.png",
|
data/test/helper.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
- 2
|
8
7
|
- 3
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jason Murad
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-25 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -101,17 +101,14 @@ files:
|
|
101
101
|
- README.rdoc
|
102
102
|
- Rakefile
|
103
103
|
- VERSION
|
104
|
+
- app/controllers/sortable_nested_set_controller.rb
|
104
105
|
- app/helpers/sortable_nested_set_helper.rb
|
105
106
|
- app/views/sortable_nested_set/_category.html.erb
|
106
107
|
- app/views/sortable_nested_set/_item.html.erb
|
107
108
|
- app/views/sortable_nested_set/_tree.html.erb
|
108
|
-
-
|
109
|
-
-
|
109
|
+
- config/routes.rb
|
110
|
+
- lib/acts_as_sortable_nested_set.rb
|
110
111
|
- lib/sortable_nested_set.rb
|
111
|
-
- lib/sortable_nested_set/acts_as_sortable_nested_set.rb
|
112
|
-
- lib/sortable_nested_set/engine.rb
|
113
|
-
- lib/sortable_nested_set/handles_sortable_nested_set.rb
|
114
|
-
- lib/sortable_nested_set/routes.rb
|
115
112
|
- public/images/folder_closed.png
|
116
113
|
- public/images/folder_open.png
|
117
114
|
- public/images/mega_menu.png
|
@@ -136,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
133
|
requirements:
|
137
134
|
- - ">="
|
138
135
|
- !ruby/object:Gem::Version
|
139
|
-
hash:
|
136
|
+
hash: 3123587155221195723
|
140
137
|
segments:
|
141
138
|
- 0
|
142
139
|
version: "0"
|
@@ -1 +0,0 @@
|
|
1
|
-
$('#category_<%= @category.id %>').remove();
|
@@ -1 +0,0 @@
|
|
1
|
-
$('#item_<%= @item.id %>').remove();
|
@@ -1,74 +0,0 @@
|
|
1
|
-
module SortableNestedSet
|
2
|
-
def self.included(base)
|
3
|
-
base.extend ClassMethods
|
4
|
-
end
|
5
|
-
|
6
|
-
module ClassMethods
|
7
|
-
def handles_sortable_nested_set
|
8
|
-
class_eval do
|
9
|
-
define_method(:sns_category_id_field) { "#{controller_name.singularize}_id" }
|
10
|
-
define_method(:sns_category_class) { controller_name.classify.constantize }
|
11
|
-
define_method(:sns_items_type) { sns_category_class.sns_items_type }
|
12
|
-
define_method(:sns_item_class) { sns_items_type.to_s.classify.constantize }
|
13
|
-
end
|
14
|
-
|
15
|
-
include InstanceMethods
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
module InstanceMethods
|
20
|
-
def sns_add_subcategory
|
21
|
-
redirect_to :action => :new, sns_category_id_field => params[:id]
|
22
|
-
end
|
23
|
-
|
24
|
-
def sns_add_item
|
25
|
-
redirect_to :controller => sns_items_type, :action => :new, sns_category_id_field => params[:id]
|
26
|
-
end
|
27
|
-
|
28
|
-
def sns_sort
|
29
|
-
matches = params[:moved].match(/(\w+)_(\d+)$/)
|
30
|
-
moved_type = matches[1]
|
31
|
-
moved_id = matches[2].to_i
|
32
|
-
moved_parent = nil
|
33
|
-
tree = {} # category_id => [children of move_type]
|
34
|
-
|
35
|
-
for node in params[:tree].scan(/(\w+)\[(\d+)\]=(\w+)/)
|
36
|
-
type = node[0]
|
37
|
-
next unless type == moved_type
|
38
|
-
|
39
|
-
id = node[1].to_i
|
40
|
-
parent = (node[2] == 'root') ? nil : node[2].to_i
|
41
|
-
|
42
|
-
moved_parent = parent if id == moved_id
|
43
|
-
|
44
|
-
tree[parent] ||= []
|
45
|
-
tree[parent] << id
|
46
|
-
end
|
47
|
-
|
48
|
-
if moved_type == sns_items_type.to_s.singularize
|
49
|
-
item = sns_item_class.find(moved_id)
|
50
|
-
item.remove_from_list
|
51
|
-
item.update_attribute(sns_category_id_field, moved_parent)
|
52
|
-
item.insert_at(tree[moved_parent].index(moved_id))
|
53
|
-
else
|
54
|
-
moved_type.classify.constantize.find(moved_id).move(moved_parent, tree[moved_parent])
|
55
|
-
end
|
56
|
-
|
57
|
-
render :nothing => true
|
58
|
-
end
|
59
|
-
|
60
|
-
def sns_destroy_category
|
61
|
-
@category = sns_category_class.find(params[:id])
|
62
|
-
@category.destroy
|
63
|
-
render 'sortable_nested_set/sns_destroy_category'
|
64
|
-
end
|
65
|
-
|
66
|
-
def sns_destroy_item
|
67
|
-
@item = sns_item_class.find(params[:id])
|
68
|
-
@item.destroy
|
69
|
-
render 'sortable_nested_set/sns_destroy_item'
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
ActionController::Base.send :include, SortableNestedSet
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module ActionDispatch::Routing
|
2
|
-
class Mapper
|
3
|
-
def sortable_nested_set_for(category_type)
|
4
|
-
item_type = category_type.to_s.classify.constantize.sns_items_type
|
5
|
-
|
6
|
-
resources category_type do
|
7
|
-
resources category_type, :as => "sub#{category_type}"
|
8
|
-
resources item_type
|
9
|
-
|
10
|
-
member do
|
11
|
-
get :sns_toggle
|
12
|
-
get :sns_add_subcategory
|
13
|
-
get :sns_add_item
|
14
|
-
delete :sns_destroy_category
|
15
|
-
end
|
16
|
-
|
17
|
-
collection do
|
18
|
-
put :sns_sort
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
resources item_type do
|
23
|
-
delete :sns_destroy_item, :on => :member, :controller => category_type
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|