Skip to content

Commit d7bbe7e

Browse files
author
Richard Young
committed
i love angular
1 parent 0d0786d commit d7bbe7e

File tree

7 files changed

+20796
-2
lines changed

7 files changed

+20796
-2
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
'use strict';
2+
3+
angular.module('browsercms.controllers', []);
4+
var browserCmsApp = angular.module('browsercms', ['ui.sortable', 'browsercms.controllers']);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
angular.module('browsercms.controllers').controller('CarouselPortletController', ['$scope', function($scope) {
2+
$scope.slides = [];
3+
$scope.html_blocks = [];
4+
5+
$scope.init = function(slides, html_blocks)
6+
{
7+
$scope.slides = slides;
8+
$scope.html_blocks = html_blocks;
9+
};
10+
11+
$scope.addNewSlide = function()
12+
{
13+
$scope.slides.push({id: $scope.html_blocks[0].id});
14+
};
15+
16+
$scope.removeSlide = function(index)
17+
{
18+
$scope.slides.splice(index, 1);
19+
}
20+
}]);

app/assets/javascripts/cms/application.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,8 @@
1414
//= require cms/form_builder
1515
//= require cms/sitemap
1616
//= require bootstrap
17-
//
17+
//= require vendor/angular
18+
//= require vendor/angular-sortable
19+
//= require ../angular/browsercms
20+
//= require_tree ../angular
1821

app/assets/javascripts/cms/page_editor.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jQuery(function($){
1212
});
1313

1414
jQuery(function($){
15+
window.editor = CKEDITOR.currentInstance;
1516
$.cms_editor = {
1617
// Returns the widget that a user has currently selected.
1718
// @return [JQuery.Element]
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
jQuery UI Sortable plugin wrapper
3+
4+
@param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
5+
*/
6+
angular.module('ui.sortable', [])
7+
.value('uiSortableConfig',{})
8+
.directive('uiSortable', [
9+
'uiSortableConfig', '$timeout', '$log',
10+
function(uiSortableConfig, $timeout, $log) {
11+
return {
12+
require: '?ngModel',
13+
link: function(scope, element, attrs, ngModel) {
14+
var savedNodes;
15+
16+
function combineCallbacks(first,second){
17+
if(second && (typeof second === 'function')) {
18+
return function(e, ui) {
19+
first(e, ui);
20+
second(e, ui);
21+
};
22+
}
23+
return first;
24+
}
25+
26+
var opts = {};
27+
28+
var callbacks = {
29+
receive: null,
30+
remove:null,
31+
start:null,
32+
stop:null,
33+
update:null
34+
};
35+
36+
angular.extend(opts, uiSortableConfig);
37+
38+
if (ngModel) {
39+
40+
// When we add or remove elements, we need the sortable to 'refresh'
41+
// so it can find the new/removed elements.
42+
scope.$watch(attrs.ngModel+'.length', function() {
43+
// Timeout to let ng-repeat modify the DOM
44+
$timeout(function() {
45+
element.sortable('refresh');
46+
});
47+
});
48+
49+
callbacks.start = function(e, ui) {
50+
// Save the starting position of dragged item
51+
ui.item.sortable = {
52+
index: ui.item.index(),
53+
cancel: function () {
54+
ui.item.sortable._isCanceled = true;
55+
},
56+
isCanceled: function () {
57+
return ui.item.sortable._isCanceled;
58+
},
59+
_isCanceled: false
60+
};
61+
};
62+
63+
callbacks.activate = function(/*e, ui*/) {
64+
// We need to make a copy of the current element's contents so
65+
// we can restore it after sortable has messed it up.
66+
// This is inside activate (instead of start) in order to save
67+
// both lists when dragging between connected lists.
68+
savedNodes = element.contents();
69+
70+
// If this list has a placeholder (the connected lists won't),
71+
// don't inlcude it in saved nodes.
72+
var placeholder = element.sortable('option','placeholder');
73+
74+
// placeholder.element will be a function if the placeholder, has
75+
// been created (placeholder will be an object). If it hasn't
76+
// been created, either placeholder will be false if no
77+
// placeholder class was given or placeholder.element will be
78+
// undefined if a class was given (placeholder will be a string)
79+
if (placeholder && placeholder.element && typeof placeholder.element === 'function') {
80+
var phElement = placeholder.element();
81+
// workaround for jquery ui 1.9.x,
82+
// not returning jquery collection
83+
if (!phElement.jquery) {
84+
phElement = angular.element(phElement);
85+
}
86+
87+
// exact match with the placeholder's class attribute to handle
88+
// the case that multiple connected sortables exist and
89+
// the placehoilder option equals the class of sortable items
90+
var excludes = element.find('[class="' + phElement.attr('class') + '"]');
91+
92+
savedNodes = savedNodes.not(excludes);
93+
}
94+
};
95+
96+
callbacks.update = function(e, ui) {
97+
// Save current drop position but only if this is not a second
98+
// update that happens when moving between lists because then
99+
// the value will be overwritten with the old value
100+
if(!ui.item.sortable.received) {
101+
ui.item.sortable.dropindex = ui.item.index();
102+
ui.item.sortable.droptarget = ui.item.parent();
103+
104+
// Cancel the sort (let ng-repeat do the sort for us)
105+
// Don't cancel if this is the received list because it has
106+
// already been canceled in the other list, and trying to cancel
107+
// here will mess up the DOM.
108+
element.sortable('cancel');
109+
}
110+
111+
// Put the nodes back exactly the way they started (this is very
112+
// important because ng-repeat uses comment elements to delineate
113+
// the start and stop of repeat sections and sortable doesn't
114+
// respect their order (even if we cancel, the order of the
115+
// comments are still messed up).
116+
if (element.sortable('option','helper') === 'clone') {
117+
// restore all the savedNodes except .ui-sortable-helper element
118+
// (which is placed last). That way it will be garbage collected.
119+
savedNodes = savedNodes.not(savedNodes.last());
120+
}
121+
savedNodes.appendTo(element);
122+
123+
// If received is true (an item was dropped in from another list)
124+
// then we add the new item to this list otherwise wait until the
125+
// stop event where we will know if it was a sort or item was
126+
// moved here from another list
127+
if(ui.item.sortable.received && !ui.item.sortable.isCanceled()) {
128+
scope.$apply(function () {
129+
ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0,
130+
ui.item.sortable.moved);
131+
});
132+
}
133+
};
134+
135+
callbacks.stop = function(e, ui) {
136+
// If the received flag hasn't be set on the item, this is a
137+
// normal sort, if dropindex is set, the item was moved, so move
138+
// the items in the list.
139+
if(!ui.item.sortable.received &&
140+
('dropindex' in ui.item.sortable) &&
141+
!ui.item.sortable.isCanceled()) {
142+
143+
scope.$apply(function () {
144+
ngModel.$modelValue.splice(
145+
ui.item.sortable.dropindex, 0,
146+
ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]);
147+
});
148+
} else {
149+
// if the item was not moved, then restore the elements
150+
// so that the ngRepeat's comment are correct.
151+
if((!('dropindex' in ui.item.sortable) || ui.item.sortable.isCanceled()) && element.sortable('option','helper') !== 'clone') {
152+
savedNodes.appendTo(element);
153+
}
154+
}
155+
};
156+
157+
callbacks.receive = function(e, ui) {
158+
// An item was dropped here from another list, set a flag on the
159+
// item.
160+
ui.item.sortable.received = true;
161+
};
162+
163+
callbacks.remove = function(e, ui) {
164+
// Remove the item from this list's model and copy data into item,
165+
// so the next list can retrive it
166+
if (!ui.item.sortable.isCanceled()) {
167+
scope.$apply(function () {
168+
ui.item.sortable.moved = ngModel.$modelValue.splice(
169+
ui.item.sortable.index, 1)[0];
170+
});
171+
}
172+
};
173+
174+
scope.$watch(attrs.uiSortable, function(newVal /*, oldVal*/) {
175+
angular.forEach(newVal, function(value, key) {
176+
if(callbacks[key]) {
177+
if( key === 'stop' ){
178+
// call apply after stop
179+
value = combineCallbacks(
180+
value, function() { scope.$apply(); });
181+
}
182+
// wrap the callback
183+
value = combineCallbacks(callbacks[key], value);
184+
}
185+
element.sortable('option', key, value);
186+
});
187+
}, true);
188+
189+
angular.forEach(callbacks, function(value, key) {
190+
opts[key] = combineCallbacks(value, opts[key]);
191+
});
192+
193+
} else {
194+
$log.info('ui.sortable: ngModel not provided!', element);
195+
}
196+
197+
// Create sortable
198+
element.sortable(opts);
199+
}
200+
};
201+
}
202+
]);

0 commit comments

Comments
 (0)