sortable_nested_set 0.1.23

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ ul.menu_links li.category span.mega {
2
+ display: inline;
3
+ color: blue;
4
+ cursor: pointer;
5
+ }
6
+
7
+ ul.menu_links li.category {
8
+ position: relative;
9
+ }
10
+
11
+ ul.menu_links li.category div.links {
12
+ display: none;
13
+ z-index: 1;
14
+ border: 1px solid #eea;
15
+ position: absolute;
16
+ top: 1.6em;
17
+ left: 0em;
18
+ padding: 1.3em;
19
+ background: #ffc;
20
+ }
21
+
22
+ ul.menu_links li.category div.items {
23
+ min-height: 5px;
24
+ padding-left: 20px;
25
+ }
26
+
27
+ ul.menu_links li.category div.link_hover {
28
+ display: block;
29
+ }
30
+
31
+ ul.menu_links li.category div.pop_up_hover {
32
+ display: block;
33
+ border: 1px solid #cca;
34
+ }
@@ -0,0 +1,31 @@
1
+ ul.menu_links, ul.sub_menu_links {
2
+ list-style: none;
3
+ margin-left: 0px;
4
+ padding-left: 0px;
5
+ }
6
+
7
+ li > ul.sub_menu_links {
8
+ padding-left: 1em;
9
+ }
10
+
11
+ span.toggle a:hover {
12
+ background-color: white;
13
+ }
14
+
15
+ li.placeholder {
16
+ height: 3px;
17
+ }
18
+
19
+ li.hovered {
20
+ background: url(/images/drag.png) no-repeat bottom left;
21
+ }
22
+
23
+ li.category span.handle {
24
+ cursor: move;
25
+ font-variant: small-caps;
26
+ }
27
+
28
+ li.category div.item .handle {
29
+ cursor: move;
30
+ font-variant: normal;
31
+ }
@@ -0,0 +1,68 @@
1
+ require "awesome_nested_set"
2
+ include CollectiveIdea::Acts::NestedSet
3
+
4
+ module SortableNestedSet
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def acts_as_sortable_nested_set_of(items_type)
11
+ send(:include, InstanceMethods)
12
+
13
+ @subcategories_type = "sub#{name.tableize}".to_sym
14
+ @items_type = items_type
15
+
16
+ instance_eval do
17
+ def sns_subcategories_type ; @subcategories_type end
18
+ def sns_items_type ; @items_type end
19
+ end
20
+
21
+ class_eval do
22
+ define_method(:sns_subcategories) { send(self.class.sns_subcategories_type) }
23
+ define_method(:sns_items) { send(self.class.sns_items_type) }
24
+ end
25
+
26
+ acts_as_nested_set :parent_column => name.foreign_key
27
+
28
+ belongs_to name.underscore
29
+
30
+ has_many @subcategories_type, :class_name => name, :dependent => :destroy
31
+ has_many @items_type, :order => :position, :dependent => :destroy
32
+
33
+ default_scope :order => :lft
34
+ end
35
+ end
36
+
37
+ module InstanceMethods
38
+ def self_and_descendants_with_items
39
+ nested_set_scope.scoped :include => self.class.sns_items_type, :conditions => [
40
+ "#{self.class.quoted_table_name}.#{quoted_left_column_name} >= ? AND
41
+ #{self.class.quoted_table_name}.#{quoted_right_column_name} <= ?", left, right
42
+ ]
43
+ end
44
+
45
+ def lineage(options=Hash.new)
46
+ conditions = [ 'lft <= ? AND rgt >= ?', lft, rgt ]
47
+ unless options[:include_self] == true
48
+ conditions[0] << ' AND id != ?'
49
+ conditions << id
50
+ end
51
+
52
+ self.class.find(:all, :select => 'id, name', :conditions => conditions, :order => 'lft ASC')
53
+ end
54
+
55
+ # descendents() does "SELECT *" but only id field required
56
+ def descendant_subcategory_ids(options=Hash.new)
57
+ conditions = [ 'lft >= ? AND rgt <= ?', lft, rgt ]
58
+ unless options[:include_self] == true
59
+ conditions[0] << ' AND id != ?'
60
+ conditions << id
61
+ end
62
+
63
+ self.class.find(:all, :select => :id, :conditions => conditions).collect(&:id)
64
+ end
65
+ end
66
+ end
67
+
68
+ ActiveRecord::Base.send(:include, SortableNestedSet)
@@ -0,0 +1,10 @@
1
+ require "sortable_nested_set"
2
+ require "rails"
3
+
4
+ module SortableNestedSet
5
+ class Engine < Rails::Engine
6
+ config.to_prepare do
7
+ ApplicationController.helper(SortableNestedSetHelper)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,155 @@
1
+ require "sortable_element_for_nested_set"
2
+ include SortableElementForNestedSet
3
+
4
+ module SortableNestedSet
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def handles_sortable_nested_set
11
+ handles_sorting_of_nested_set
12
+
13
+ class_eval do
14
+ define_method(:sns_category_controller) { controller_name }
15
+ define_method(:sns_category_id_field) { "#{controller_name.singularize}_id" }
16
+ define_method(:sns_category_class) { controller_name.classify.constantize }
17
+ define_method(:sns_items_type) {sns_category_class.sns_items_type }
18
+ define_method(:sns_item_class) {sns_items_type.to_s.classify.constantize }
19
+ end
20
+
21
+ include(SortableNestedSet::InstanceMethods)
22
+ end
23
+ end
24
+
25
+ module InstanceMethods
26
+ def sns_add_subcategory
27
+ redirect_to(:controller => sns_category_controller, :action => :new, sns_category_id_field => params[:id])
28
+ end
29
+
30
+ def sns_add_item
31
+ redirect_to(:controller => sns_items_type, :action => :new, sns_category_id_field => params[:id])
32
+ end
33
+
34
+ def sns_sort_categories
35
+ category = sns_category_class.find(params[:moved])
36
+ new_pos = position_of(:moved).in_tree(:menu)
37
+
38
+ # Ambiguous moves occur when a category is dropped outside the menu AND
39
+ # a :root parameter is specified. In this case, move the element to the
40
+ # :root category in the database and also put it at the end with javascript.
41
+ ambiguous_move = nil
42
+
43
+ begin
44
+ category.transaction do
45
+ if new_pos[:parent]
46
+ category.move_to_child_of(new_pos[:parent])
47
+ elsif params[:root].nil?
48
+ category.move_to_root
49
+ else
50
+ root_id = params[:root].to_i
51
+ ambiguous_move = params[:menu]['0']['id'] == params[:moved] ? :top : :bottom
52
+
53
+ if ambiguous_move == :bottom
54
+ category.move_to_child_of(params[:root])
55
+ else
56
+ category.move_to_left_of(sns_category_class.find(params[:root]).sns_subcategories.first)
57
+ end
58
+ end unless category.parent_id === new_pos[:parent]
59
+
60
+ begin
61
+ if new_pos[:move_to_right_of]
62
+ category.move_to_right_of(new_pos[:move_to_right_of])
63
+ else
64
+ category.move_to_left_of(new_pos[:move_to_left_of])
65
+ end
66
+ rescue ActiveRecord::RecordNotFound
67
+ # FIXME error raised when making first child
68
+ end unless ambiguous_move
69
+
70
+ raise category.errors.full_messages.to_sentence unless category.valid?
71
+ end
72
+ rescue => err
73
+ render :update do |page|
74
+ page.alert err.message
75
+ page.reload # TODO return to original location with javascript
76
+ end
77
+ else
78
+ render :update do |page|
79
+ page.assign :categoryElement, page.literal("$('category_#{category.id}')")
80
+
81
+ if ambiguous_move
82
+ page.assign :rootElement, page.literal("$('subcategories_#{root_id}')")
83
+ page.remove "category_#{category.id}"
84
+
85
+ # there is a placeholder at index 0
86
+ page << (ambiguous_move == :top ?
87
+ 'rootElement.insertBefore(categoryElement, rootElement.childElements()[1])' :
88
+ 'rootElement.insert(categoryElement)')
89
+
90
+ page.visual_effect 'highlight', "category_#{category.id}"
91
+ else
92
+ page.assign :elderSibling, page.literal('categoryElement.nextElementSibling')
93
+ page.assign :parent, page.literal('categoryElement.parentNode')
94
+
95
+ page << <<EOF
96
+ if (elderSibling && elderSibling.hasClassName('placeholder')) {
97
+ elderSibling.remove();
98
+ parent.insertBefore(elderSibling, categoryElement);
99
+ }
100
+
101
+ /* WORKAROUND DEFECT: after dragdrop, z-index not abided by */
102
+ categoryElement.style.removeProperty('z-index');
103
+ EOF
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ def sns_sort_items
110
+ container = params.find { |key, val| key =~ /items_\d+/ }
111
+
112
+ params[container.first].each_with_index do |id, index|
113
+ category_id = container.first.match(/items_(\d+)/)[1]
114
+ sns_item_class.update(id, sns_category_id_field => category_id, :position => index + 1)
115
+ end if container
116
+
117
+ render :update do |page|
118
+ id = "item_#{params[:moved]}"
119
+ page << "$('#{id}').style.removeProperty('z-index')"
120
+ end
121
+ end
122
+
123
+ def sns_toggle
124
+ render :update do |page|
125
+ page["items_#{params[:id]}"].toggle
126
+ page["subcategories_#{params[:id]}"].toggle
127
+ page.replace_html "toggle_#{params[:id]}",
128
+ :partial => 'sortable_nested_set/toggle',
129
+ :locals => { :category_type => params[:category_type],
130
+ :id => params[:id],
131
+ :state => (params[:state] == 'open' ? 'closed' : 'open') }
132
+ end
133
+ end
134
+
135
+ def sns_destroy_category
136
+ @category = sns_category_class.find(params[:id])
137
+ @category.destroy
138
+
139
+ render :update do |page|
140
+ page["category_#{@category.id}"].remove
141
+ end
142
+ end
143
+
144
+ def sns_destroy_item
145
+ @item = sns_item_class.find(params[:id])
146
+ @item.destroy
147
+
148
+ render :update do |page|
149
+ page["item_#{@item.id}"].remove
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ ActionController::Base.send(:include, SortableNestedSet)
@@ -0,0 +1,18 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+ def sortable_nested_set_for(category_type)
4
+ resources category_type do
5
+ get :sns_toggle, :on => :member
6
+ get :sns_add_subcategory, :on => :member
7
+ get :sns_add_item, :on => :member
8
+ put :sns_sort_categories, :on => :collection
9
+ put :sns_sort_items, :on => :collection
10
+ delete :sns_destroy_category, :on => :member
11
+ end
12
+
13
+ resources category_type.to_s.classify.constantize.sns_items_type do
14
+ delete :sns_destroy_item, :on => :member, :controller => category_type
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ require "sortable_nested_set/engine" if defined?(Rails)
2
+ require "sortable_nested_set/acts_as_sortable_nested_set"
3
+ require "sortable_nested_set/handles_sortable_nested_set"
4
+ require "sortable_nested_set/routes"
@@ -0,0 +1,6 @@
1
+ namespace :sortable_nested_set do
2
+ desc "Sync public files"
3
+ task :sync do
4
+ system "rsync -ruvvh #{File.join File.dirname(__FILE__), "..", "public"} ."
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sortable_nested_set
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 23
9
+ version: 0.1.23
10
+ platform: ruby
11
+ authors: []
12
+
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-29 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: awesome_nested_set
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: sortable_element_for_nested_set
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ description:
47
+ email:
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - README
54
+ files:
55
+ - app/helpers/sortable_nested_set_helper.rb
56
+ - app/views/sortable_nested_set/_category.html.erb
57
+ - app/views/sortable_nested_set/_item.html.erb
58
+ - app/views/sortable_nested_set/_toggle.html.erb
59
+ - app/views/sortable_nested_set/_tree.html.erb
60
+ - lib/public/images/drag.png
61
+ - lib/public/images/folder_closed.png
62
+ - lib/public/images/folder_open.png
63
+ - lib/public/javascripts/controls.js
64
+ - lib/public/javascripts/dragdrop.js
65
+ - lib/public/javascripts/effects.js
66
+ - lib/public/javascripts/jquery.hoverIntent.minified.js
67
+ - lib/public/javascripts/jquery.js
68
+ - lib/public/javascripts/mega_menu.js
69
+ - lib/public/javascripts/prototype.js
70
+ - lib/public/stylesheets/mega_menu.css
71
+ - lib/public/stylesheets/menu_tree.css
72
+ - lib/sortable_nested_set.rb
73
+ - lib/sortable_nested_set/acts_as_sortable_nested_set.rb
74
+ - lib/sortable_nested_set/engine.rb
75
+ - lib/sortable_nested_set/handles_sortable_nested_set.rb
76
+ - lib/sortable_nested_set/routes.rb
77
+ - lib/tasks/sortable_nested_set_tasks.rake
78
+ - README
79
+ has_rdoc: true
80
+ homepage:
81
+ licenses: []
82
+
83
+ post_install_message:
84
+ rdoc_options:
85
+ - --charset=UTF-8
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ segments:
102
+ - 0
103
+ version: "0"
104
+ requirements: []
105
+
106
+ rubyforge_project:
107
+ rubygems_version: 1.3.7
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Sortable Nested Set
111
+ test_files: []
112
+