sortable_tree_rails 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +26 -0
- data/app/controllers/sortable_tree_controller.rb +53 -0
- data/app/helpers/sortable_tree_helper.rb +37 -0
- data/app/views/sortable_tree/_sortable_tree.html.haml +75 -0
- data/config/routes.rb +2 -0
- data/lib/assets/javascripts/jquery.mjs.nestedSortable.js +907 -0
- data/lib/assets/stylesheets/sortable_tree.scss +112 -0
- data/lib/sortable_tree_rails/engine.rb +7 -0
- data/lib/sortable_tree_rails/version.rb +3 -0
- data/lib/sortable_tree_rails.rb +4 -0
- data/lib/tasks/sortable_tree_rails_tasks.rake +4 -0
- data/readme.md +189 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0373aa113f25bc22e733601b2a8f8dd20eeb18e6
|
4
|
+
data.tar.gz: 7bafb1232ef6f952f5711bd25a547ceb56b65445
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3bb39be2172073da11f3a66dfa5f279be979b2572d7e43207b0b8da7dc8897784249330ec28adb8b361befe23655d474ad89b2683162126e560390f6caf56ebc
|
7
|
+
data.tar.gz: 2e2f98fe24e840d9ca97d94db442c127f1562018c75b7c8b93857777911ebb3e03ae3c7af86eefb8f05ddee8b5f8ec2c52982fa5efb55ec1d5f4b900583f9136
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 Max Ivak
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'SortableTreeRails'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('readme.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
Bundler::GemHelper.install_tasks
|
26
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module SortableTreeController
|
4
|
+
module Sort
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper SortableTreeHelper
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def sortable_tree(class_name, options = {})
|
14
|
+
define_method("sort") do
|
15
|
+
resource_class = class_name.to_s.camelize.constantize
|
16
|
+
|
17
|
+
# options
|
18
|
+
options[:tree] = true
|
19
|
+
options[:sorting_attribute] ||= 'pos'
|
20
|
+
options[:parent_method] ||= 'parent'
|
21
|
+
|
22
|
+
records = params[:cat].inject({}) do |res, (resource, parent_resource)|
|
23
|
+
res[resource_class.find(resource)] = resource_class.find(parent_resource) rescue nil
|
24
|
+
res
|
25
|
+
end
|
26
|
+
|
27
|
+
errors = []
|
28
|
+
ActiveRecord::Base.transaction do
|
29
|
+
records.each_with_index do |(record, parent_record), position|
|
30
|
+
record.send "#{options[:sorting_attribute]}=", position
|
31
|
+
if options[:tree]
|
32
|
+
record.send "#{options[:parent_method]}=", parent_record
|
33
|
+
end
|
34
|
+
errors << {record.id => record.errors} if !record.save
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
if errors.empty?
|
40
|
+
head 200
|
41
|
+
else
|
42
|
+
render json: errors, status: 422
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SortableTreeHelper
|
2
|
+
|
3
|
+
def render_sortable_tree(items, opts={})
|
4
|
+
render :partial=>'sortable_tree/sortable_tree', locals: {items: items, options: opts}
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
def sortable_tree_render_nested_groups(groups, opts={})
|
9
|
+
content_tag(:ol) do
|
10
|
+
groups.map do |item, sub_groups|
|
11
|
+
content_tag(:li, {id: "cat_#{item.id}"} ) do
|
12
|
+
#(item.title + sortable_tree_render_nested_groups(sub_groups, opts)).html_safe
|
13
|
+
|
14
|
+
s = content_tag(:div, {class: 'item'}) do
|
15
|
+
(
|
16
|
+
#'<div class="cell left"><i class="handle"></i></div>'\
|
17
|
+
'<h3 class="cell left">'+item.send(opts[:name_method] || :name)+'</h3>'\
|
18
|
+
'<div class="cell right controls">'+sortable_tree_build_actions(item, opts)+'</div>'
|
19
|
+
).html_safe
|
20
|
+
end
|
21
|
+
(s + sortable_tree_render_nested_groups(sub_groups, opts)).html_safe
|
22
|
+
end
|
23
|
+
|
24
|
+
end.join.html_safe
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def sortable_tree_build_actions(item, opts={})
|
29
|
+
partial = opts[:controls_partial] || nil
|
30
|
+
|
31
|
+
if partial
|
32
|
+
render :partial=>partial, locals: {item: item, options: opts}
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
.sortable_tree_wrapper
|
2
|
+
%ol.sortable_tree{data: {'sortable-url' => options[:sort_url]} }
|
3
|
+
- items.each do |root, children|
|
4
|
+
%li{id: "cat_#{root.id}"}
|
5
|
+
.item
|
6
|
+
/.cell.left
|
7
|
+
/ %i.handle
|
8
|
+
%h4.cell.left
|
9
|
+
=root.send(options[:name_method] || :name)
|
10
|
+
.cell.right.controls
|
11
|
+
- if options[:controls_partial]
|
12
|
+
= render options[:controls_partial], item: root
|
13
|
+
|
14
|
+
= sortable_tree_render_nested_groups(children, options.merge({list_tag: :ol, element_class: 'item'}))
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
:javascript
|
19
|
+
$(document).ready(function(){
|
20
|
+
$('.sortable_tree').nestedSortable({
|
21
|
+
forceHelperSizeType: true,
|
22
|
+
errorClass: 'cantdoit',
|
23
|
+
disableNesting: 'cantdoit',
|
24
|
+
handle: '> .item',
|
25
|
+
helper: 'clone',
|
26
|
+
listType: 'ol',
|
27
|
+
items: 'li',
|
28
|
+
opacity: 0.6,
|
29
|
+
placeholder: 'placeholder',
|
30
|
+
revert: 250,
|
31
|
+
maxLevels: #{options[:max_levels] || 5},
|
32
|
+
//tabSize: 20,
|
33
|
+
// protectRoot: $(this).data('protect-root'),
|
34
|
+
|
35
|
+
// prevent drag flickers
|
36
|
+
tolerance: 'pointer',
|
37
|
+
toleranceElement: '> div',
|
38
|
+
isTree: true,
|
39
|
+
startCollapsed: false,
|
40
|
+
//startCollapsed: $(this).data("start-collapsed"),
|
41
|
+
|
42
|
+
relocate: function(){
|
43
|
+
//$(this).nestedSortable("disable");
|
44
|
+
var data = $(this).nestedSortable("serialize");
|
45
|
+
var url = $(this).data("sortable-url");
|
46
|
+
|
47
|
+
// update on server
|
48
|
+
$.ajax({
|
49
|
+
url: url,
|
50
|
+
type: "post",
|
51
|
+
data: data
|
52
|
+
}).always(function(){
|
53
|
+
//$(this).nestedSortable("enable");
|
54
|
+
|
55
|
+
$(this).find('.item').each(function(index){
|
56
|
+
if (index % 2){
|
57
|
+
$(this).removeClass('odd').addClass('even');
|
58
|
+
}else{
|
59
|
+
$(this).removeClass('even').addClass('odd');
|
60
|
+
}
|
61
|
+
});
|
62
|
+
|
63
|
+
}).done(function(data){
|
64
|
+
|
65
|
+
}).fail(function(jqXHR, textStatus){
|
66
|
+
|
67
|
+
});
|
68
|
+
|
69
|
+
|
70
|
+
//$(this).nestedSortable("enable");
|
71
|
+
}
|
72
|
+
}); // nested tree
|
73
|
+
}); // document.ready
|
74
|
+
|
75
|
+
|
data/config/routes.rb
ADDED