radiant-drag_order-extension 0.3.9 → 0.4.0.beta.2
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/VERSION +1 -1
- data/app/views/admin/pages/_handle.html.haml +2 -0
- data/app/views/admin/pages/_node.html.haml +26 -0
- data/app/views/admin/pages/index.html.haml +20 -0
- data/config/routes.rb +2 -2
- data/drag_order_extension.rb +1 -3
- data/lib/drag_order/controllers/admin/pages_controller.rb +17 -128
- data/lib/drag_order/models/page.rb +0 -24
- data/pkg/radiant-drag_order-extension-0.3.9.gem +0 -0
- data/public/javascripts/admin/extensions/drag_order/drag_order.js +51 -180
- data/public/javascripts/admin/sitemap.js +111 -0
- data/public/javascripts/admin/sortable_tree.js +223 -0
- data/public/stylesheets/sass/admin/extensions/drag_order/drag_order.sass +113 -33
- data/radiant-drag_order-extension.gemspec +13 -6
- data/spec/controllers/pages_controller_spec.rb +48 -0
- data/spec/datasets/sort_pages.rb +31 -0
- data/spec/spec_helper.rb +3 -18
- metadata +24 -13
- data/app/views/admin/pages/_drag_order.html.haml +0 -4
- data/app/views/admin/pages/_drag_order_header.html.haml +0 -2
- data/app/views/admin/pages/_top.html.haml +0 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0.beta.2
|
@@ -0,0 +1,26 @@
|
|
1
|
+
%li.node.page{:class =>"level_#{level}#{children_class}#{virtual_class}", :id => "page_#{page.id}", :'data-page_id' => page.id, :'data-level' => level}
|
2
|
+
.attributes
|
3
|
+
- render_region :node, :locals => {:page => page, :level => level, :simple => simple} do |node|
|
4
|
+
- node.title_column do
|
5
|
+
%span.attribute.title
|
6
|
+
%span.w1
|
7
|
+
- if simple
|
8
|
+
= icon
|
9
|
+
= node_title
|
10
|
+
- else
|
11
|
+
= expander(level) + link_to("#{icon} #{node_title}", edit_admin_page_url(page), :title => page.url)
|
12
|
+
= page_type
|
13
|
+
= spinner
|
14
|
+
- node.status_column do
|
15
|
+
- unless simple
|
16
|
+
%span.attribute.status{:class => "#{page.status.name.downcase}_status", :title => "#{timestamp(page.published_at) if page.published_at}"}= t(page.status.name.downcase)
|
17
|
+
- node.add_child_column do
|
18
|
+
- unless simple
|
19
|
+
%span.attribute.add_child= link_to t('add_child'), new_admin_page_child_url(page)
|
20
|
+
- node.remove_column do
|
21
|
+
- unless simple
|
22
|
+
%span.attribute.remove= link_to t('remove'), remove_admin_page_url(page)
|
23
|
+
|
24
|
+
%ol.children{:id => "#{level == 0 ? 'pages' : "page_#{page.id}_pages"}"}
|
25
|
+
- page.children.each do |child|
|
26
|
+
= render_node child, :level => level + 1, :simple => simple
|
@@ -0,0 +1,20 @@
|
|
1
|
+
- @javascripts << 'admin/dragdrop.js'
|
2
|
+
- @javascripts << 'admin/sortable_tree.js'
|
3
|
+
- @javascripts << 'admin/extensions/drag_order/drag_order.js'
|
4
|
+
- @stylesheets << 'admin/extensions/drag_order/drag_order.css'
|
5
|
+
|
6
|
+
- @page_title = t('pages') + ' - ' + default_page_title
|
7
|
+
|
8
|
+
.outset
|
9
|
+
= render_region :top
|
10
|
+
%ol#site_map.index{:summary=>"Page hierarchy of the current site"}
|
11
|
+
- if @homepage
|
12
|
+
= render_node @homepage
|
13
|
+
- else
|
14
|
+
%li.empty= t('no_pages')
|
15
|
+
= render_region :bottom
|
16
|
+
|
17
|
+
- unless @homepage
|
18
|
+
#actions
|
19
|
+
%ul
|
20
|
+
%li= link_to image('plus') + " " + t("new_homepage"), new_admin_page_path
|
data/config/routes.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
ActionController::Routing::Routes.draw do |map|
|
2
2
|
|
3
|
-
map.
|
4
|
-
|
3
|
+
map.namespace :admin do |admin|
|
4
|
+
admin.resources :pages, :collection => { :sort => :put }
|
5
5
|
end
|
6
6
|
|
7
7
|
end
|
data/drag_order_extension.rb
CHANGED
@@ -8,9 +8,7 @@ class DragOrderExtension < Radiant::Extension
|
|
8
8
|
StandardTags.send :include, DragOrder::Tags::Core
|
9
9
|
Admin::PagesController.send :include, DragOrder::Controllers::Admin::PagesController
|
10
10
|
|
11
|
-
admin.pages.index.add :
|
12
|
-
admin.pages.index.add :node, "drag_order", :before => "title_column"
|
13
|
-
admin.pages.index.add :top, "top"
|
11
|
+
admin.pages.index.add :node, "handle", :before => "title_column"
|
14
12
|
end
|
15
13
|
|
16
14
|
end
|
@@ -8,141 +8,30 @@ module DragOrder
|
|
8
8
|
|
9
9
|
helper_method :order_dragger
|
10
10
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@target = Page.find(params[:rel])
|
21
|
-
|
22
|
-
make_room_for_page if @current_position != 2
|
23
|
-
|
24
|
-
if copying?
|
25
|
-
@orig_parts = @page.parts
|
26
|
-
@page = @page.clone
|
27
|
-
end
|
28
|
-
|
29
|
-
@target.reload
|
30
|
-
|
31
|
-
put_page
|
32
|
-
|
33
|
-
solve_slug_conflicts if copying? || new_parent_different?
|
34
|
-
|
35
|
-
@page.save!
|
36
|
-
|
37
|
-
create_copy_of_parts if copying?
|
38
|
-
|
39
|
-
clear_cache
|
40
|
-
redirect_back_or_to_admin_pages_page
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
def order_dragger
|
45
|
-
%{<img src="/images/admin/extensions/drag_order/handle.png" alt ="Drag this icon to move the page" />}
|
46
|
-
end
|
47
|
-
|
48
|
-
def copying?
|
49
|
-
params[:copy].to_i > 0
|
50
|
-
end
|
51
|
-
|
52
|
-
def ensure_no_nil_position_values
|
53
|
-
if @page.newly_created_siblings?
|
54
|
-
i = 1
|
55
|
-
@page.siblings_and_self.each do |p|
|
56
|
-
p.position = i
|
57
|
-
p.save
|
58
|
-
i += 1
|
11
|
+
def sort
|
12
|
+
begin
|
13
|
+
parent = Page.find(params[:parent_id])
|
14
|
+
params[:children].split(',').each_with_index do |child,index|
|
15
|
+
Page.find(child).update_attributes!(
|
16
|
+
:position => index,
|
17
|
+
:parent_id => params[:parent_id]
|
18
|
+
)
|
59
19
|
end
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
def remove_page_from_old_position
|
65
|
-
@page.following_siblings.each do |sibling|
|
66
|
-
sibling.position -= 1
|
67
|
-
sibling.save!
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def put_page
|
72
|
-
if @current_position != 2
|
73
|
-
@page.parent = @target.parent
|
74
|
-
@page.position = @target.position.to_i + (@current_position == 1 ? 1 : -1)
|
75
|
-
else
|
76
|
-
@page.parent = @target
|
77
|
-
@page.position = 1
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def make_room_for_page
|
82
|
-
new_siblings = Page.children_of_after_position(@target.parent_id, @target.position + @current_position)
|
83
|
-
new_siblings.each do |sibling|
|
84
|
-
if sibling != @page || copying?
|
85
|
-
sibling.position += 1
|
86
|
-
sibling.save!
|
20
|
+
|
21
|
+
respond_to do |format|
|
22
|
+
format.js { render :text => 'Pages successfully sorted.' }
|
87
23
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
def new_parent_different?
|
92
|
-
# @page.parent.changed? always gives false...
|
93
|
-
@page.parent != @old_parent
|
94
|
-
end
|
95
|
-
|
96
|
-
def solve_slug_conflicts
|
97
|
-
check_slug = @page.slug.sub(/-copy-?[0-9]*$/, "")
|
98
|
-
count = 0
|
99
|
-
parent_id = @current_position == 2 ? @target.id : @target.parent.id
|
100
|
-
duplicates = Page.children_of_with_slug_like(parent_id, check_slug )
|
101
|
-
duplicates.each do |d|
|
102
|
-
m = d.slug.match("^#{check_slug}(-copy-?([0-9]*))?$")
|
103
|
-
if !m.nil?
|
104
|
-
if !(m[2].nil? || m[2] == "")
|
105
|
-
nc = m[2].to_i + 1
|
106
|
-
elsif m[1]
|
107
|
-
nc = 2
|
108
|
-
else
|
109
|
-
nc = 1
|
110
|
-
end
|
111
|
-
count = nc if nc > count
|
24
|
+
rescue Exception => e # Without this resource controller will exception when it looks for Page.find('sort.js')
|
25
|
+
respond_to do |format|
|
26
|
+
format.js { render :text => 'Could not sort Pages.', :status => :unprocessable_entity }
|
112
27
|
end
|
113
28
|
end
|
114
|
-
if count > 0
|
115
|
-
# Remove old copy counters
|
116
|
-
re = / - COPY ?[0-9]*$/
|
117
|
-
@page.title.sub! re, ""
|
118
|
-
@page.breadcrumb.sub! re, ""
|
119
|
-
# Add new copy counters
|
120
|
-
@page.slug = check_slug + "-copy" + (count > 1 ? "-" + count.to_s : "")
|
121
|
-
@page.title += " - COPY" + (count > 1 ? " " + count.to_s : "")
|
122
|
-
@page.breadcrumb += " - COPY" + (count > 1 ? " " + count.to_s : "")
|
123
|
-
end
|
124
29
|
end
|
125
30
|
|
126
|
-
|
127
|
-
@orig_parts.each do |op|
|
128
|
-
@page.parts.create({
|
129
|
-
:name => op.name,
|
130
|
-
:filter_id => op.filter_id,
|
131
|
-
:content => op.content
|
132
|
-
})
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def redirect_back_or_to_admin_pages_page
|
137
|
-
redirect_to(:back) rescue redirect_to(admin_page_url)
|
138
|
-
end
|
31
|
+
private
|
139
32
|
|
140
|
-
def
|
141
|
-
|
142
|
-
ResponseCache.instance.clear
|
143
|
-
else
|
144
|
-
Radiant::Cache.clear
|
145
|
-
end
|
33
|
+
def order_dragger
|
34
|
+
%{<img src="/images/admin/extensions/drag_order/handle.png" alt ="Drag this icon to move the page" />}
|
146
35
|
end
|
147
36
|
|
148
37
|
end
|
@@ -13,30 +13,6 @@ module DragOrder
|
|
13
13
|
|
14
14
|
self.reflections[:children].options[:order] = "position ASC"
|
15
15
|
|
16
|
-
class << self
|
17
|
-
|
18
|
-
def children_of_after_position(parent, position)
|
19
|
-
find_all_by_parent_id(parent, :conditions => [ 'position >= ?', position ])
|
20
|
-
end
|
21
|
-
|
22
|
-
def children_of_with_slug_like(parent, slug)
|
23
|
-
find_all_by_parent_id(parent, :conditions => [ 'slug LIKE ?', slug ])
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def newly_created_siblings?
|
29
|
-
self.class.find_all_by_parent_id(parent_id, :conditions => ["position is null"] ).size > 0
|
30
|
-
end
|
31
|
-
|
32
|
-
def siblings_and_self
|
33
|
-
self.class.find_all_by_parent_id(parent_id, :order => ["position ASC"] )
|
34
|
-
end
|
35
|
-
|
36
|
-
def following_siblings
|
37
|
-
self.class.find_all_by_parent_id(parent_id, :conditions => [ 'position > ?', position ] )
|
38
|
-
end
|
39
|
-
|
40
16
|
private
|
41
17
|
def set_initial_position
|
42
18
|
self.position ||= begin
|
Binary file
|
@@ -1,192 +1,63 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
CHILD_PAD : 21,
|
8
|
-
NO_COPY : 0,
|
9
|
-
COPY : 1,
|
10
|
-
|
11
|
-
// Defaults
|
12
|
-
origRow : null,
|
13
|
-
expandObj : null,
|
14
|
-
rowHeight : 0,
|
15
|
-
dragLine : null,
|
16
|
-
moveTo : null,
|
17
|
-
|
18
|
-
initialize: function(table) {
|
19
|
-
// Needed in order to use SiteMap function. Already created in sitemap.js,
|
20
|
-
// but cannot be referred to...
|
21
|
-
this.sMap = SiteMapBehavior.attach(new Element('table'));
|
22
|
-
|
23
|
-
// Attach listeners to drag images in table
|
24
|
-
var _this = this;
|
25
|
-
Event.observe( $(table), 'mousedown', function(evt){
|
26
|
-
if ($(evt.target.parentNode).hasClassName('drag_order') && evt.target.tagName.toLowerCase() == 'img')
|
27
|
-
_this.rowDragStart(evt);
|
28
|
-
}.bindAsEventListener(this) );
|
29
|
-
document.dragOrderObj = this;
|
30
|
-
},
|
1
|
+
document.observe("dom:loaded", function() {
|
2
|
+
drag_order_index = new DragOrderIndex();
|
3
|
+
drag_order_index.initialize();
|
4
|
+
})
|
5
|
+
|
6
|
+
var DragOrderIndex = Class.create({
|
31
7
|
|
32
|
-
|
33
|
-
|
34
|
-
this.origRow = evt.findElement('tr');
|
35
|
-
this.origRow.addClassName('dragging');
|
36
|
-
this.rowHeight = this.origRow.getHeight();
|
37
|
-
this.moveTo = new Object();
|
38
|
-
this.expandObj = new Object();
|
39
|
-
this.childEdge = $(evt.target).cumulativeOffset().left + $(evt.target).getWidth();
|
40
|
-
|
41
|
-
// Attach event listeners for the movement
|
42
|
-
this.moveBind = this.rowDragMove.bindAsEventListener(this);
|
43
|
-
Event.observe($(document.body), 'mousemove', this.moveBind);
|
44
|
-
this.stopBind = this.rowDragStop.bindAsEventListener(this);
|
45
|
-
Event.observe($(document.body), 'mouseup', this.stopBind);
|
46
|
-
|
47
|
-
return this.cancelEvent(evt);
|
8
|
+
initialize: function() {
|
9
|
+
this.sortPages();
|
48
10
|
},
|
49
11
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
this.dragLine.innerHTML = "line";
|
62
|
-
dragLineCircle = new Element('div');
|
63
|
-
this.dragLine.appendChild(dragLineCircle);
|
64
|
-
document.body.appendChild(this.dragLine);
|
65
|
-
}
|
66
|
-
else
|
67
|
-
this.dragLine.show();
|
68
|
-
|
69
|
-
// If children are visible, hide them first
|
70
|
-
if (this.sMap.isExpanded(this.origRow))
|
71
|
-
this.sMap.hideBranch(this.origRow, this.origRow.getElementsByClassName('expander')[0] );
|
72
|
-
|
73
|
-
// Loop through all rows
|
74
|
-
var _this = document.dragOrderObj;
|
75
|
-
var top;
|
76
|
-
this.origRow.parentNode.getElementsBySelector('tr').find(function(obj){
|
77
|
-
top = obj.cumulativeOffset().top;
|
78
|
-
|
79
|
-
// Check if cursor is over row
|
80
|
-
if (evt.pageY >= top && evt.pageY <= top + _this.rowHeight) {
|
81
|
-
|
82
|
-
// If row has children and is collapsed, create timer for expansion
|
83
|
-
if (obj.hasClassName('children_hidden') && _this.expandObj != obj) {
|
84
|
-
_this.expandObj.row = obj;
|
85
|
-
if (_this.expandObj.timer)
|
86
|
-
clearTimeout(_this.expandObj.timer);
|
87
|
-
_this.expandObj.timer = setTimeout("document.dragOrderObj.rowDragExpand();", 750);
|
88
|
-
}
|
89
|
-
else if (_this.expandObj != obj) {
|
90
|
-
_this.expandObj.row = null;
|
91
|
-
clearTimeout(_this.expandObj.timer);
|
92
|
-
}
|
93
|
-
|
94
|
-
var targetRow = null;
|
95
|
-
var targetLoc;
|
96
|
-
// If on the upper half of the row, put the dragline at the top of the row (= bottom of previous)
|
97
|
-
if (evt.pageY >= top && evt.pageY <= top + _this.rowHeight / 2 && obj.previous()) {
|
98
|
-
if (obj.previous().hasClassName('children_visible')) {
|
99
|
-
targetRow = obj;
|
100
|
-
targetLoc = _this.BEFORE;
|
101
|
-
}
|
102
|
-
else {
|
103
|
-
targetRow = _this.sMap.extractLevel(obj.previous()) > _this.sMap.extractLevel(obj) ? obj : obj.previous();
|
104
|
-
targetLoc = _this.sMap.extractLevel(obj.previous()) > _this.sMap.extractLevel(obj) ? _this.BEFORE : _this.AFTER;
|
105
|
-
}
|
106
|
-
}
|
107
|
-
// If on the lower half of the row, put the line at the bottom of the row
|
108
|
-
else if (evt.pageY > top + _this.rowHeight / 2 && evt.pageY <= top + _this.rowHeight) {
|
109
|
-
// Check for moving as new child
|
110
|
-
if (obj != _this.origRow && !_this.sMap.hasChildren(obj) && evt.pageX > _this.childEdge) {
|
111
|
-
targetRow = obj;
|
112
|
-
targetLoc = _this.CHILD;
|
113
|
-
}
|
114
|
-
else {
|
115
|
-
targetRow = obj.hasClassName('children_visible') ? obj.next() : obj;
|
116
|
-
targetLoc = obj.hasClassName('children_visible') ? _this.BEFORE : _this.AFTER;
|
117
|
-
}
|
12
|
+
sortPages: function() {
|
13
|
+
var tree = new SortableTree('pages', {
|
14
|
+
draggable: {
|
15
|
+
handle: 'handle',
|
16
|
+
ghosting: false,
|
17
|
+
constraint: false,
|
18
|
+
onDrag: function(drag, event) {
|
19
|
+
drag.element.addClassName('drag_move');
|
20
|
+
},
|
21
|
+
onEnd: function(drag, event) {
|
22
|
+
drag.element.removeClassName('drag_move');
|
118
23
|
}
|
24
|
+
},
|
25
|
+
onDrop: function(drag, drop, event){
|
26
|
+
var parent = drag.element.up('.page')
|
27
|
+
var children = '';
|
28
|
+
|
29
|
+
this.moveHandles(drag.element);
|
119
30
|
|
120
|
-
|
121
|
-
|
122
|
-
if (copy)
|
123
|
-
_this.dragLine.getElementsByTagName('div')[0].addClassName('copy');
|
124
|
-
else
|
125
|
-
_this.dragLine.getElementsByTagName('div')[0].removeClassName('copy');
|
126
|
-
}
|
127
|
-
|
128
|
-
// If a row has been found
|
129
|
-
if (targetRow) {
|
130
|
-
// Set the dragline
|
131
|
-
var padding = parseInt(targetRow.firstDescendant().getStyle('padding-left')) + 30;
|
132
|
-
_this.dragLine.style.width = targetRow.getWidth() - padding - (targetLoc == _this.CHILD ? _this.CHILD_PAD : 0) + 'px';
|
133
|
-
_this.dragLine.setStyle({
|
134
|
-
left: targetRow.cumulativeOffset().left + padding + (targetLoc == _this.CHILD ? _this.CHILD_PAD : 0) + 'px',
|
135
|
-
top: targetRow.cumulativeOffset().top + (targetLoc == _this.AFTER || targetLoc == _this.CHILD ? _this.rowHeight : 0) - 1 + 'px'
|
31
|
+
parent.down('.children').immediateDescendants().each(function(page) {
|
32
|
+
children += page.readAttribute('data-page_id') + ','
|
136
33
|
});
|
34
|
+
children = children.slice(0,-1);
|
137
35
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
36
|
+
new Ajax.Request('/admin/pages/sort.js', {
|
37
|
+
method: 'put',
|
38
|
+
parameters: {
|
39
|
+
'parent_id': parent.readAttribute('data-page_id'),
|
40
|
+
'children' : children
|
41
|
+
}
|
42
|
+
})
|
143
43
|
|
144
|
-
|
145
|
-
}
|
146
|
-
|
44
|
+
}.bind(this)
|
147
45
|
});
|
148
|
-
|
149
|
-
return this.cancelEvent(evt);
|
150
|
-
},
|
151
|
-
|
152
|
-
rowDragExpand: function(row) {
|
153
|
-
row = this.expandObj.row;
|
154
|
-
this.sMap.showBranch(row, row.getElementsByClassName('expander')[0] );
|
155
|
-
},
|
156
|
-
|
157
|
-
rowDragStop: function() {
|
158
|
-
|
159
|
-
if (this.moveTo.relativeTo && (this.moveTo.hovering != this.origRow || this.moveTo.copy))
|
160
|
-
window.location.href = "/admin/pages/" + this.sMap.extractPageId(this.origRow) + "/move_to/" + this.sMap.extractPageId(this.moveTo.relativeTo) + "/" + this.moveTo.side + "/" + (this.moveTo.copy ? this.COPY : this.NO_COPY);
|
161
|
-
else {
|
162
|
-
// Cleanup not necessary when redirected
|
163
|
-
this.origRow.removeClassName('dragging');
|
164
|
-
|
165
|
-
this.origRow = null;
|
166
|
-
if (this.expandObj.timer) clearTimeout(this.expandObj.timer);
|
167
|
-
this.expandObj = null;
|
168
|
-
if (this.dragLine) this.dragLine.hide();
|
169
|
-
}
|
170
|
-
|
171
|
-
Event.stopObserving(document.body, 'mousemove', this.moveBind);
|
172
|
-
Event.stopObserving(document.body, 'mouseup', this.stopBind);
|
46
|
+
tree.setSortable();
|
173
47
|
},
|
174
48
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
49
|
+
moveHandles: function(page) {
|
50
|
+
var level = parseInt(page.up('.page').getAttribute('data-level'))
|
51
|
+
level += 1;
|
52
|
+
page.setAttribute('data-level', level)
|
53
|
+
page.down('.handle').setStyle({ left: (level * -25) + 'px' })
|
54
|
+
|
55
|
+
page.select('.children').each(function(container) {
|
56
|
+
level += 1
|
57
|
+
container.select('.page').each(function(child) {
|
58
|
+
child.setAttribute('data-level', level)
|
59
|
+
child.down('.handle').setStyle({ left: (level * -25) + 'px' })
|
60
|
+
});
|
61
|
+
});
|
181
62
|
}
|
182
|
-
|
183
|
-
});
|
184
|
-
|
185
|
-
// If the DOM is loaded, create the DragOrder object
|
186
|
-
document.observe('dom:loaded', function() {
|
187
|
-
$$('table.index').each(function(table){
|
188
|
-
if(table.identify() == 'pages' || table.identify() == 'site_map') {
|
189
|
-
new DragOrder(table);
|
190
|
-
}
|
191
|
-
});
|
192
|
-
});
|
63
|
+
})
|
@@ -0,0 +1,111 @@
|
|
1
|
+
/*
|
2
|
+
* sitemap.js
|
3
|
+
*
|
4
|
+
* depends on: prototype.js and lowpro.js
|
5
|
+
*
|
6
|
+
* Used by Radiant to create the expandable sitemap.
|
7
|
+
*
|
8
|
+
* To use, simply add the following lines to application.js:
|
9
|
+
*
|
10
|
+
* Event.addBehavior({
|
11
|
+
* 'table#site_map': SiteMapBehavior()
|
12
|
+
* });
|
13
|
+
*
|
14
|
+
*/
|
15
|
+
|
16
|
+
var SiteMapBehavior = Behavior.create({
|
17
|
+
initialize: function() {
|
18
|
+
this.readExpandedCookie();
|
19
|
+
},
|
20
|
+
|
21
|
+
onclick: function(event) {
|
22
|
+
if (this.isExpander(event.target)) {
|
23
|
+
var row = event.findElement('li');
|
24
|
+
if (this.hasChildren(row)) {
|
25
|
+
this.toggleBranch(row, event.target);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
},
|
29
|
+
|
30
|
+
hasChildren: function(row) {
|
31
|
+
return !row.hasClassName('no_children');
|
32
|
+
},
|
33
|
+
|
34
|
+
isExpander: function(element) {
|
35
|
+
return element.match('img.expander');
|
36
|
+
},
|
37
|
+
|
38
|
+
isExpanded: function(row) {
|
39
|
+
return row.hasClassName('children_visible');
|
40
|
+
},
|
41
|
+
|
42
|
+
isRow: function(element) {
|
43
|
+
return element && element.tagName && element.match('li');
|
44
|
+
},
|
45
|
+
|
46
|
+
extractPageId: function(row) {
|
47
|
+
return row.readAttribute('data-page_id').toInteger();
|
48
|
+
},
|
49
|
+
|
50
|
+
getExpanderImageForRow: function(row) {
|
51
|
+
return row.down('img');
|
52
|
+
},
|
53
|
+
|
54
|
+
readExpandedCookie: function() {
|
55
|
+
var matches = document.cookie.match(/expanded_rows=(.+?)(;|$)/);
|
56
|
+
this.expandedRows = matches ? decodeURIComponent(matches[1]).split(',') : [];
|
57
|
+
},
|
58
|
+
|
59
|
+
saveExpandedCookie: function() {
|
60
|
+
document.cookie = "expanded_rows=" + encodeURIComponent(this.expandedRows.uniq().join(",")) + "; path=/admin";
|
61
|
+
},
|
62
|
+
|
63
|
+
persistCollapsed: function(row) {
|
64
|
+
var pageId = this.extractPageId(row);
|
65
|
+
this.expandedRows = this.expandedRows.without(pageId);
|
66
|
+
this.saveExpandedCookie();
|
67
|
+
},
|
68
|
+
|
69
|
+
persistExpanded: function(row) {
|
70
|
+
var pageId = this.extractPageId(row);
|
71
|
+
this.expandedRows.push(pageId);
|
72
|
+
this.saveExpandedCookie();
|
73
|
+
},
|
74
|
+
|
75
|
+
toggleExpanded: function(row, img) {
|
76
|
+
if (!img) img = this.getExpanderImageForRow(row);
|
77
|
+
if (this.isExpanded(row)) {
|
78
|
+
img.src = img.src.replace('collapse', 'expand');
|
79
|
+
row.removeClassName('children_visible');
|
80
|
+
row.addClassName('children_hidden');
|
81
|
+
this.persistCollapsed(row);
|
82
|
+
} else {
|
83
|
+
img.src = img.src.replace('expand', 'collapse');
|
84
|
+
row.removeClassName('children_hidden');
|
85
|
+
row.addClassName('children_visible');
|
86
|
+
this.persistExpanded(row);
|
87
|
+
}
|
88
|
+
},
|
89
|
+
|
90
|
+
hideBranch: function(parent, img) {
|
91
|
+
this.toggleExpanded(parent, img);
|
92
|
+
},
|
93
|
+
|
94
|
+
showBranch: function(parent, img) {
|
95
|
+
this.toggleExpanded(parent, img);
|
96
|
+
},
|
97
|
+
|
98
|
+
toggleBranch: function(row, img) {
|
99
|
+
if (!this.updating) {
|
100
|
+
if (this.isExpanded(row)) {
|
101
|
+
this.hideBranch(row, img);
|
102
|
+
} else {
|
103
|
+
this.showBranch(row, img);
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
});
|
108
|
+
|
109
|
+
Event.addBehavior({
|
110
|
+
'#site_map': SiteMapBehavior()
|
111
|
+
})
|
@@ -0,0 +1,223 @@
|
|
1
|
+
var SortableTree = Class.create({
|
2
|
+
initialize: function(element, options) {
|
3
|
+
this.element = $(element);
|
4
|
+
this.root = new SortableTree.Node(this, null, element, options);
|
5
|
+
this.isSortable = false;
|
6
|
+
},
|
7
|
+
|
8
|
+
toggleSortable: function() {
|
9
|
+
this.isSortable ? this.setUnsortable() : this.setSortable();
|
10
|
+
},
|
11
|
+
|
12
|
+
setSortable: function() {
|
13
|
+
Element.addClassName(this.root.element, 'sortable');
|
14
|
+
this.root.setSortable();
|
15
|
+
this.isSortable = true;
|
16
|
+
},
|
17
|
+
|
18
|
+
setUnsortable: function() {
|
19
|
+
Element.removeClassName(this.root.element, 'sortable');
|
20
|
+
this.root.setUnsortable();
|
21
|
+
this.isSortable = false;
|
22
|
+
},
|
23
|
+
|
24
|
+
find: function(element) {
|
25
|
+
return this.root.find($(element));
|
26
|
+
},
|
27
|
+
|
28
|
+
unmark_all: function() {
|
29
|
+
this.root.unmark();
|
30
|
+
}
|
31
|
+
});
|
32
|
+
|
33
|
+
SortableTree.Node = Class.create({
|
34
|
+
initialize: function(tree, parent, element, options) {
|
35
|
+
this.tree = tree;
|
36
|
+
this.parent = parent;
|
37
|
+
this.element = $(element);
|
38
|
+
|
39
|
+
this.options = Object.extend({
|
40
|
+
tagName: 'LI',
|
41
|
+
containerTagName: 'OL',
|
42
|
+
droppable: {},
|
43
|
+
draggable: {}
|
44
|
+
}, options || {});
|
45
|
+
|
46
|
+
this.droppable_options = Object.extend({
|
47
|
+
onHover: function(drag, drop, overlap){ this.onHover(drag, drop, overlap); }.bind(this),
|
48
|
+
onDrop: function(drag, drop, event){ this.onDrop(drag, drop, event); }.bind(this),
|
49
|
+
overlap: 'vertical',
|
50
|
+
hoverclass: 'drop_hover'
|
51
|
+
}, options.droppable);
|
52
|
+
|
53
|
+
this.draggable_options = Object.extend({
|
54
|
+
ghosting: true,
|
55
|
+
revert: true,
|
56
|
+
constraint: 'vertical',
|
57
|
+
reverteffect: function(element, top_offset, left_offset) {
|
58
|
+
element.setStyle({left: '0px', top: '0px'});
|
59
|
+
// would be so cool to be able to use this. but it leaves a backgroundColor
|
60
|
+
// style property on the element which overwrites the class' value
|
61
|
+
// (i.e. the drop marker) and apperently can't be removed anymore (?)
|
62
|
+
// new Effect.Highlight(element, { startcolor: '#FFFF99' })
|
63
|
+
}
|
64
|
+
}, options.draggable);
|
65
|
+
|
66
|
+
this.initChildren();
|
67
|
+
},
|
68
|
+
|
69
|
+
id: function() {
|
70
|
+
if (!this._id) {
|
71
|
+
var match = this.element.id.match(/^[\w]+_([\d]*)$/);
|
72
|
+
this._id = encodeURIComponent(match ? match[1] : null);
|
73
|
+
}
|
74
|
+
return this._id;
|
75
|
+
},
|
76
|
+
|
77
|
+
previousSibling: function() {
|
78
|
+
var pos = this.parent.children.indexOf(this);
|
79
|
+
return pos > 0 ? this.parent.children[pos - 1] : null;
|
80
|
+
},
|
81
|
+
|
82
|
+
initChildren: function() {
|
83
|
+
this.children = [];
|
84
|
+
var container = this.findContainer(this.element);
|
85
|
+
if(container){
|
86
|
+
$A(container.childNodes).each(function(child) {
|
87
|
+
if(this.acceptTagName(child)) {
|
88
|
+
this.children.push(new SortableTree.Node(this.tree, this, child, this.options));
|
89
|
+
}
|
90
|
+
}.bind(this));
|
91
|
+
}
|
92
|
+
},
|
93
|
+
|
94
|
+
acceptTagName: function(element) {
|
95
|
+
return element.tagName && element.tagName.toUpperCase() == this.options.tagName;
|
96
|
+
},
|
97
|
+
|
98
|
+
setSortable: function() {
|
99
|
+
Droppables.add(this.element, this.droppable_options);
|
100
|
+
this.draggable = new Draggable(this.element, this.draggable_options);
|
101
|
+
this.children.each(function(child) { child.setSortable(); });
|
102
|
+
},
|
103
|
+
|
104
|
+
setUnsortable: function() {
|
105
|
+
Droppables.remove(this.element);
|
106
|
+
this.draggable.destroy();
|
107
|
+
this.children.each(function(child) { child.setUnsortable(); });
|
108
|
+
},
|
109
|
+
|
110
|
+
find: function(element) {
|
111
|
+
if(element == this.element) return this;
|
112
|
+
for(var i = 0; i < this.children.length; i++) {
|
113
|
+
var node = this.children[i].find(element);
|
114
|
+
if(node) return node;
|
115
|
+
}
|
116
|
+
},
|
117
|
+
|
118
|
+
findContainer: function(element) {
|
119
|
+
if(element.tagName != this.options.containerTagName) {
|
120
|
+
element = $A(element.childNodes).detect(function(node) {
|
121
|
+
return node.tagName == this.options.containerTagName;
|
122
|
+
}.bind(this));
|
123
|
+
}
|
124
|
+
return element;
|
125
|
+
},
|
126
|
+
|
127
|
+
findOrCreateContainer: function(element) {
|
128
|
+
var container = this.findContainer(element);
|
129
|
+
if(!container) {
|
130
|
+
container = document.createElement(this.options.containerTagName);
|
131
|
+
element.appendChild(container);
|
132
|
+
}
|
133
|
+
return container;
|
134
|
+
},
|
135
|
+
|
136
|
+
onHover: function(drag, drop, overlap) {
|
137
|
+
if(this.canContainChildren(drop)) {
|
138
|
+
this.dropPosition = overlap < 0.15 ? 'bottom' : overlap > 0.85 ? 'top' : 'insert';
|
139
|
+
} else {
|
140
|
+
this.dropPosition = overlap < 0.5 ? 'bottom' : 'top';
|
141
|
+
}
|
142
|
+
this.mark(drop);
|
143
|
+
// $('log').update('hovering: ' + drop.tagName + ': ' + drop.id + "<br />" +
|
144
|
+
// 'classes: ' + drop.className + "<br />" +
|
145
|
+
// 'dropPosition: ' + this.dropPosition)
|
146
|
+
},
|
147
|
+
|
148
|
+
canContainChildren: function(element) {
|
149
|
+
if(this.options.droppable.container) {
|
150
|
+
return element.match(this.options.droppable.container);
|
151
|
+
}
|
152
|
+
return true;
|
153
|
+
},
|
154
|
+
|
155
|
+
onDrop: function(drag, drop, event) {
|
156
|
+
drag = this.tree.find(drag);
|
157
|
+
drop = this.tree.find(drop);
|
158
|
+
|
159
|
+
// i.e. don't do anything if it's a toplevel node and has been dropped on "itself"
|
160
|
+
// another way around this could be to change scriptaculous to affect() a node
|
161
|
+
// when it has been dropped on itself
|
162
|
+
if(drop.parent || this.dropPosition == 'insert') {
|
163
|
+
switch(this.dropPosition) {
|
164
|
+
case 'top': drop.parent.insertBefore(drag, drop); break;
|
165
|
+
case 'bottom': drop.parent.insertBefore(drag, drop.nextSibling()); break;
|
166
|
+
case 'insert': this.insertBefore(drag, this.firstChild()); break;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
if(this.options.onDrop) this.options.onDrop(drag, drop, event);
|
171
|
+
|
172
|
+
this.tree.unmark_all();
|
173
|
+
},
|
174
|
+
|
175
|
+
mark: function(element, position) {
|
176
|
+
this.tree.unmark_all();
|
177
|
+
Element.addClassName(element, 'drop_' + this.dropPosition);
|
178
|
+
},
|
179
|
+
|
180
|
+
unmark: function() {
|
181
|
+
['drop_top', 'drop_bottom', 'drop_insert'].each(function(classname){
|
182
|
+
Element.removeClassName(this.element, classname);
|
183
|
+
}.bind(this));
|
184
|
+
this.children.each(function(child) { child.unmark(); });
|
185
|
+
},
|
186
|
+
|
187
|
+
to_params: function(name) {
|
188
|
+
name = name || this.tree.element.id;
|
189
|
+
var leftNode = this.previousSibling();
|
190
|
+
return name + '[' + this.id() + '][parent_id]=' + this.parent.id() + '&' +
|
191
|
+
name + '[' + this.id() + '][left_id]=' + (leftNode ? leftNode.id() : ''); // null
|
192
|
+
},
|
193
|
+
|
194
|
+
firstChild: function() {
|
195
|
+
return this.children.length > 0 ? this.children[0] : null;
|
196
|
+
},
|
197
|
+
|
198
|
+
previousSibling: function() {
|
199
|
+
var pos = this.parent.children.indexOf(this);
|
200
|
+
return pos > 0 ? this.parent.children[pos - 1] : null;
|
201
|
+
},
|
202
|
+
|
203
|
+
nextSibling: function() {
|
204
|
+
var pos = this.parent.children.indexOf(this);
|
205
|
+
return pos + 1 < this.parent.children.length ? this.parent.children[pos + 1] : null;
|
206
|
+
},
|
207
|
+
|
208
|
+
removeChild: function(node) {
|
209
|
+
this.children.splice(this.children.indexOf(node), 1);
|
210
|
+
node.element.parentNode.removeChild(node.element);
|
211
|
+
},
|
212
|
+
|
213
|
+
insertBefore: function(node, sibling) {
|
214
|
+
if(node == sibling) return;
|
215
|
+
|
216
|
+
node.parent.removeChild(node);
|
217
|
+
node.parent = this;
|
218
|
+
var pos = sibling ? this.children.indexOf(sibling) : this.children.length;
|
219
|
+
this.children.splice(pos, 0, node);
|
220
|
+
|
221
|
+
this.findOrCreateContainer(this.element).insertBefore(node.element, sibling ? sibling.element : null);
|
222
|
+
}
|
223
|
+
});
|
@@ -1,40 +1,120 @@
|
|
1
|
-
#content
|
2
|
-
|
3
|
-
|
1
|
+
#content
|
2
|
+
|
3
|
+
#pages
|
4
|
+
padding-left: 7px
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
.page
|
7
|
+
position: relative
|
8
|
+
|
9
|
+
&.drop_hover
|
10
|
+
background-color: #F9F9F9
|
7
11
|
|
8
|
-
|
9
|
-
|
12
|
+
&.drop_insert
|
13
|
+
background-color: #DFEBFF
|
14
|
+
|
15
|
+
&.drag_move
|
16
|
+
.children
|
17
|
+
opacity: 0.25
|
18
|
+
|
19
|
+
.attributes
|
20
|
+
width: 100%
|
21
|
+
height: 31px
|
22
|
+
line-height: 31px
|
23
|
+
padding: 4px 0 4px 10px
|
24
|
+
overflow: hidden
|
25
|
+
text-decoration: none
|
26
|
+
padding-left: 5px
|
27
|
+
|
28
|
+
.handle
|
29
|
+
position: absolute
|
30
|
+
cursor: move
|
31
|
+
|
32
|
+
.attribute
|
33
|
+
display: block
|
34
|
+
float: left
|
35
|
+
padding-right: 5px
|
36
|
+
|
37
|
+
&.title
|
38
|
+
padding-left: 20px
|
39
|
+
|
40
|
+
a
|
41
|
+
text-decoration: none !important
|
42
|
+
|
43
|
+
.title
|
44
|
+
color: black
|
45
|
+
font-size: 100%
|
46
|
+
font-weight: bold
|
47
|
+
text-decoration: none
|
48
|
+
|
49
|
+
&:hover
|
50
|
+
color: #0066cc
|
51
|
+
text-decoration: underline
|
52
|
+
|
53
|
+
.info
|
54
|
+
color: #9eb3bf
|
55
|
+
font-style: italic
|
56
|
+
font-weight: normal
|
57
|
+
|
58
|
+
&.virtual .page a .title
|
59
|
+
color: #9eb3bf
|
60
|
+
|
61
|
+
.w1
|
62
|
+
display: block
|
63
|
+
|
64
|
+
.expander
|
65
|
+
position: absolute
|
66
|
+
left: 0
|
67
|
+
top: 13px
|
68
|
+
padding: 0 3px
|
69
|
+
|
70
|
+
.add_child, .remove
|
71
|
+
position: absolute
|
72
|
+
top: 3px
|
73
|
+
font-size: 14px
|
74
|
+
width: 100px
|
75
|
+
|
76
|
+
.add_child
|
77
|
+
right: 100px
|
78
|
+
padding-left: 0
|
79
|
+
a
|
80
|
+
color: black
|
81
|
+
text-decoration: none
|
82
|
+
font-size: 80%
|
83
|
+
padding: 0 0 0 20px
|
84
|
+
background: url(/images/admin/plus.png) 4px 0 no-repeat
|
85
|
+
.remove
|
86
|
+
right: 0
|
87
|
+
padding-left: 0
|
88
|
+
a
|
89
|
+
color: black
|
90
|
+
text-decoration: none
|
91
|
+
font-size: 80%
|
92
|
+
padding: 0 0 0 20px
|
93
|
+
background: url(/images/admin/minus.png) 4px 0 no-repeat
|
94
|
+
.disabled
|
95
|
+
color: #ccc
|
96
|
+
font-size: 80%
|
97
|
+
padding: 0 0 0 20px
|
98
|
+
background: url(/images/admin/minus_disabled.png) 4px 0 no-repeat
|
99
|
+
|
100
|
+
&.children_visible
|
101
|
+
.children
|
102
|
+
li
|
103
|
+
display: block
|
104
|
+
&.children_hidden
|
105
|
+
.children
|
106
|
+
li
|
107
|
+
display: none
|
108
|
+
|
109
|
+
.children
|
110
|
+
border-top: 1px solid #FAFAFA
|
111
|
+
|
112
|
+
li
|
113
|
+
margin-left: 25px
|
114
|
+
|
10
115
|
|
11
|
-
.
|
116
|
+
.handle
|
12
117
|
width: 24px
|
13
118
|
|
14
119
|
img
|
15
|
-
visibility: hidden
|
16
120
|
cursor: move
|
17
|
-
|
18
|
-
&:hover
|
19
|
-
img
|
20
|
-
visibility: visible
|
21
|
-
|
22
|
-
|
23
|
-
#drag_line
|
24
|
-
position: relative
|
25
|
-
height: 3px
|
26
|
-
font-size: 0
|
27
|
-
background-color: #800080
|
28
|
-
|
29
|
-
div
|
30
|
-
position: absolute
|
31
|
-
height: 9px
|
32
|
-
width: 9px
|
33
|
-
margin: -3px 0 0 -9px
|
34
|
-
background-image: url('/images/admin/extensions/drag_order/circle.png')
|
35
|
-
|
36
|
-
&.copy
|
37
|
-
height: 20px
|
38
|
-
width: 20px
|
39
|
-
margin: -9px 0 0 -20px
|
40
|
-
background-image: url('/images/admin/extensions/drag_order/copy.png')
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{radiant-drag_order-extension}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0.beta.2"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Dirk Kelly"]
|
12
|
-
s.date = %q{2010-11-
|
12
|
+
s.date = %q{2010-11-26}
|
13
13
|
s.description = %q{Radiant DragOrder allows you to reorder pages funly}
|
14
14
|
s.email = %q{dk@dirkkelly.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -19,9 +19,9 @@ Gem::Specification.new do |s|
|
|
19
19
|
"README.md",
|
20
20
|
"Rakefile",
|
21
21
|
"VERSION",
|
22
|
-
"app/views/admin/pages/
|
23
|
-
"app/views/admin/pages/
|
24
|
-
"app/views/admin/pages/
|
22
|
+
"app/views/admin/pages/_handle.html.haml",
|
23
|
+
"app/views/admin/pages/_node.html.haml",
|
24
|
+
"app/views/admin/pages/index.html.haml",
|
25
25
|
"config/routes.rb",
|
26
26
|
"db/migrate/01_add_position_to_pages.rb",
|
27
27
|
"db/migrate/02_add_default_position.rb",
|
@@ -31,12 +31,17 @@ Gem::Specification.new do |s|
|
|
31
31
|
"lib/drag_order/tags/core.rb",
|
32
32
|
"lib/radiant-drag_order-extension.rb",
|
33
33
|
"lib/tasks/drag_order_extension_tasks.rake",
|
34
|
+
"pkg/radiant-drag_order-extension-0.3.9.gem",
|
34
35
|
"public/images/admin/extensions/drag_order/circle.png",
|
35
36
|
"public/images/admin/extensions/drag_order/copy.png",
|
36
37
|
"public/images/admin/extensions/drag_order/handle.png",
|
37
38
|
"public/javascripts/admin/extensions/drag_order/drag_order.js",
|
39
|
+
"public/javascripts/admin/sitemap.js",
|
40
|
+
"public/javascripts/admin/sortable_tree.js",
|
38
41
|
"public/stylesheets/sass/admin/extensions/drag_order/drag_order.sass",
|
39
42
|
"radiant-drag_order-extension.gemspec",
|
43
|
+
"spec/controllers/pages_controller_spec.rb",
|
44
|
+
"spec/datasets/sort_pages.rb",
|
40
45
|
"spec/spec.opts",
|
41
46
|
"spec/spec_helper.rb"
|
42
47
|
]
|
@@ -45,6 +50,8 @@ Gem::Specification.new do |s|
|
|
45
50
|
s.rubygems_version = %q{1.3.7}
|
46
51
|
s.summary = %q{Drag Order Extension for Radiant CMS}
|
47
52
|
s.test_files = [
|
53
|
+
"spec/controllers/pages_controller_spec.rb",
|
54
|
+
"spec/datasets/sort_pages.rb",
|
48
55
|
"spec/spec_helper.rb"
|
49
56
|
]
|
50
57
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
describe Admin::PagesController do
|
4
|
+
|
5
|
+
dataset :users, :sort_pages
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
login_as :admin
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#sort' do
|
12
|
+
before :each do
|
13
|
+
@params = {
|
14
|
+
:parent_id => pages(:one).id,
|
15
|
+
:children => "#{pages(:four).id},#{pages(:three).id},#{pages(:two).id}"
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'parent not sent' do
|
20
|
+
it 'should return an error' do
|
21
|
+
put :sort, :children => @params[:children], :format => 'js'
|
22
|
+
|
23
|
+
response.should_not be_success
|
24
|
+
response.body.should === 'Could not sort Pages.'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'children not sent' do
|
29
|
+
it 'should return an error' do
|
30
|
+
put :sort, :parent_id => @params[:parent_id], :format => 'js'
|
31
|
+
|
32
|
+
response.should_not be_success
|
33
|
+
response.body.should === 'Could not sort Pages.'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'parent and children sent' do
|
38
|
+
it 'should return success' do
|
39
|
+
put :sort, :parent_id => @params[:parent_id], :children => @params[:children], :format => 'js'
|
40
|
+
|
41
|
+
response.should be_success
|
42
|
+
response.body.should === 'Pages successfully sorted.'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class SortPagesDataset < Dataset::Base
|
2
|
+
def load
|
3
|
+
# TODO Investigate why inflectors are breaking here
|
4
|
+
create_record :page, :one,
|
5
|
+
:title => 'One',
|
6
|
+
:slug => 'one',
|
7
|
+
:breadcrumb => 'one',
|
8
|
+
:position => 1
|
9
|
+
|
10
|
+
create_record :page, :two,
|
11
|
+
:title => 'Two',
|
12
|
+
:slug => 'two',
|
13
|
+
:breadcrumb => 'two',
|
14
|
+
:position => 2,
|
15
|
+
:parent => pages(:one)
|
16
|
+
|
17
|
+
create_record :page, :three,
|
18
|
+
:title => 'Three',
|
19
|
+
:slug => 'three',
|
20
|
+
:breadcrumb => 'three',
|
21
|
+
:position => 3,
|
22
|
+
:parent => pages(:one)
|
23
|
+
|
24
|
+
create_record :page, :four,
|
25
|
+
:title => 'Four',
|
26
|
+
:slug => 'four',
|
27
|
+
:breadcrumb => 'four',
|
28
|
+
:position => 4,
|
29
|
+
:parent => pages(:one)
|
30
|
+
end
|
31
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -11,27 +11,12 @@ unless defined? RADIANT_ROOT
|
|
11
11
|
end
|
12
12
|
require "#{RADIANT_ROOT}/spec/spec_helper"
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
end
|
14
|
+
Dataset::Resolver.default << (File.dirname(__FILE__) + "/datasets")
|
15
|
+
|
17
16
|
if File.directory?(File.dirname(__FILE__) + "/matchers")
|
18
17
|
Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
|
19
18
|
end
|
20
19
|
|
21
20
|
Spec::Runner.configure do |config|
|
22
|
-
|
23
|
-
# config.use_instantiated_fixtures = false
|
24
|
-
# config.fixture_path = RAILS_ROOT + '/spec/fixtures'
|
25
|
-
|
26
|
-
# You can declare fixtures for each behaviour like this:
|
27
|
-
# describe "...." do
|
28
|
-
# fixtures :table_a, :table_b
|
29
|
-
#
|
30
|
-
# Alternatively, if you prefer to declare them only once, you can
|
31
|
-
# do so here, like so ...
|
32
|
-
#
|
33
|
-
# config.global_fixtures = :table_a, :table_b
|
34
|
-
#
|
35
|
-
# If you declare global fixtures, be aware that they will be declared
|
36
|
-
# for all of your examples, even those that don't use them.
|
21
|
+
config.mock_with :rr
|
37
22
|
end
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: radiant-drag_order-extension
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 62196455
|
5
|
+
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
- beta
|
11
|
+
- 2
|
12
|
+
version: 0.4.0.beta.2
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Dirk Kelly
|
@@ -15,7 +17,7 @@ autorequire:
|
|
15
17
|
bindir: bin
|
16
18
|
cert_chain: []
|
17
19
|
|
18
|
-
date: 2010-11-
|
20
|
+
date: 2010-11-26 00:00:00 +08:00
|
19
21
|
default_executable:
|
20
22
|
dependencies:
|
21
23
|
- !ruby/object:Gem::Dependency
|
@@ -46,9 +48,9 @@ files:
|
|
46
48
|
- README.md
|
47
49
|
- Rakefile
|
48
50
|
- VERSION
|
49
|
-
- app/views/admin/pages/
|
50
|
-
- app/views/admin/pages/
|
51
|
-
- app/views/admin/pages/
|
51
|
+
- app/views/admin/pages/_handle.html.haml
|
52
|
+
- app/views/admin/pages/_node.html.haml
|
53
|
+
- app/views/admin/pages/index.html.haml
|
52
54
|
- config/routes.rb
|
53
55
|
- db/migrate/01_add_position_to_pages.rb
|
54
56
|
- db/migrate/02_add_default_position.rb
|
@@ -58,12 +60,17 @@ files:
|
|
58
60
|
- lib/drag_order/tags/core.rb
|
59
61
|
- lib/radiant-drag_order-extension.rb
|
60
62
|
- lib/tasks/drag_order_extension_tasks.rake
|
63
|
+
- pkg/radiant-drag_order-extension-0.3.9.gem
|
61
64
|
- public/images/admin/extensions/drag_order/circle.png
|
62
65
|
- public/images/admin/extensions/drag_order/copy.png
|
63
66
|
- public/images/admin/extensions/drag_order/handle.png
|
64
67
|
- public/javascripts/admin/extensions/drag_order/drag_order.js
|
68
|
+
- public/javascripts/admin/sitemap.js
|
69
|
+
- public/javascripts/admin/sortable_tree.js
|
65
70
|
- public/stylesheets/sass/admin/extensions/drag_order/drag_order.sass
|
66
71
|
- radiant-drag_order-extension.gemspec
|
72
|
+
- spec/controllers/pages_controller_spec.rb
|
73
|
+
- spec/datasets/sort_pages.rb
|
67
74
|
- spec/spec.opts
|
68
75
|
- spec/spec_helper.rb
|
69
76
|
has_rdoc: true
|
@@ -87,12 +94,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
95
|
none: false
|
89
96
|
requirements:
|
90
|
-
- - "
|
97
|
+
- - ">"
|
91
98
|
- !ruby/object:Gem::Version
|
92
|
-
hash:
|
99
|
+
hash: 25
|
93
100
|
segments:
|
94
|
-
-
|
95
|
-
|
101
|
+
- 1
|
102
|
+
- 3
|
103
|
+
- 1
|
104
|
+
version: 1.3.1
|
96
105
|
requirements: []
|
97
106
|
|
98
107
|
rubyforge_project:
|
@@ -101,4 +110,6 @@ signing_key:
|
|
101
110
|
specification_version: 3
|
102
111
|
summary: Drag Order Extension for Radiant CMS
|
103
112
|
test_files:
|
113
|
+
- spec/controllers/pages_controller_spec.rb
|
114
|
+
- spec/datasets/sort_pages.rb
|
104
115
|
- spec/spec_helper.rb
|