rails-angular-ui-sortable 0.13.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: aef18264570147d55a1162437937e853b9bd8366
4
+ data.tar.gz: dfd99f800c660509180e96747d742a887c802675
5
+ SHA512:
6
+ metadata.gz: 201a1ec6cf6dad16000761be597c7e37824d333b3c45db909e466ed74ad360662b7534ff4483531aafc81fc6ec5bb750f284e01dd95dc7ac7ca45f96c7214912
7
+ data.tar.gz: bf82de2417c80a78d34784d5e3c53eb78f0041e7a0184e35774816aef662a0eefad150fbc07bb59da54e5638c37c5d7c92fe164b4893efc7fba194da41deb899
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright 2015 Alexander Bobrov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # rails-angular-ui-sortable <a href="http://badge.fury.io/rb/rails-angular-ui-sortable"><img src="https://badge.fury.io/rb/rails-angular-ui-sortable.svg" alt="Gem Version" height="18"></a>
2
+
3
+ rails-angular-ui-sortable wraps the [UI.Sortable](https://github.com/angular-ui/ui-sortable) directive for use in Rails 3.1 and above.
4
+
5
+ ## Usage
6
+
7
+ Add the following to your Gemfile:
8
+
9
+ gem 'rails-angular-ui-sortable'
10
+
11
+ Add the following to your Rails JavaScript manifest file:
12
+
13
+ //= require angular-ui-sortable
14
+
15
+ ## Versioning
16
+
17
+ Current version of jQuery-UI Sortable - 0.13.3.1
@@ -0,0 +1,9 @@
1
+ require "rails-angular-ui-sortable/version"
2
+
3
+ module RailsAngularUiSortable
4
+ if defined? ::Rails::Engine
5
+ require "rails-angular-ui-sortable/engine"
6
+ else
7
+ puts "You should use Rails 3.1+ and higher with rails-angular-ui-sortable!"
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ module RailsAngularUiSortable
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module RailsAngularUiSortable
2
+ VERSION = "0.13.3.1"
3
+ end
@@ -0,0 +1,354 @@
1
+ (function(window, angular, undefined) {
2
+ 'use strict';
3
+ /*
4
+ jQuery UI Sortable plugin wrapper
5
+
6
+ @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
7
+ */
8
+ angular.module('ui.sortable', [])
9
+ .value('uiSortableConfig',{})
10
+ .directive('uiSortable', [
11
+ 'uiSortableConfig', '$timeout', '$log',
12
+ function(uiSortableConfig, $timeout, $log) {
13
+ return {
14
+ require: '?ngModel',
15
+ scope: {
16
+ ngModel: '=',
17
+ uiSortable: '='
18
+ },
19
+ link: function(scope, element, attrs, ngModel) {
20
+ var savedNodes;
21
+
22
+ function combineCallbacks(first,second){
23
+ if(second && (typeof second === 'function')) {
24
+ return function(e, ui) {
25
+ first(e, ui);
26
+ second(e, ui);
27
+ };
28
+ }
29
+ return first;
30
+ }
31
+
32
+ function getSortableWidgetInstance(element) {
33
+ // this is a fix to support jquery-ui prior to v1.11.x
34
+ // otherwise we should be using `element.sortable('instance')`
35
+ var data = element.data('ui-sortable');
36
+ if (data && typeof data === 'object' && data.widgetFullName === 'ui-sortable') {
37
+ return data;
38
+ }
39
+ return null;
40
+ }
41
+
42
+ function hasSortingHelper (element, ui) {
43
+ var helperOption = element.sortable('option','helper');
44
+ return helperOption === 'clone' || (typeof helperOption === 'function' && ui.item.sortable.isCustomHelperUsed());
45
+ }
46
+
47
+ // thanks jquery-ui
48
+ function isFloating (item) {
49
+ return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display'));
50
+ }
51
+
52
+ function getElementScope(elementScopes, element) {
53
+ var result = null;
54
+ for (var i = 0; i < elementScopes.length; i++) {
55
+ var x = elementScopes[i];
56
+ if (x.element[0] === element[0]) {
57
+ result = x.scope;
58
+ break;
59
+ }
60
+ }
61
+ return result;
62
+ }
63
+
64
+ function afterStop(e, ui) {
65
+ ui.item.sortable._destroy();
66
+ }
67
+
68
+ var opts = {};
69
+
70
+ // directive specific options
71
+ var directiveOpts = {
72
+ 'ui-floating': undefined
73
+ };
74
+
75
+ var callbacks = {
76
+ receive: null,
77
+ remove:null,
78
+ start:null,
79
+ stop:null,
80
+ update:null
81
+ };
82
+
83
+ var wrappers = {
84
+ helper: null
85
+ };
86
+
87
+ angular.extend(opts, directiveOpts, uiSortableConfig, scope.uiSortable);
88
+
89
+ if (!angular.element.fn || !angular.element.fn.jquery) {
90
+ $log.error('ui.sortable: jQuery should be included before AngularJS!');
91
+ return;
92
+ }
93
+
94
+ if (ngModel) {
95
+
96
+ // When we add or remove elements, we need the sortable to 'refresh'
97
+ // so it can find the new/removed elements.
98
+ scope.$watch('ngModel.length', function() {
99
+ // Timeout to let ng-repeat modify the DOM
100
+ $timeout(function() {
101
+ // ensure that the jquery-ui-sortable widget instance
102
+ // is still bound to the directive's element
103
+ if (!!getSortableWidgetInstance(element)) {
104
+ element.sortable('refresh');
105
+ }
106
+ }, 0, false);
107
+ });
108
+
109
+ callbacks.start = function(e, ui) {
110
+ if (opts['ui-floating'] === 'auto') {
111
+ // since the drag has started, the element will be
112
+ // absolutely positioned, so we check its siblings
113
+ var siblings = ui.item.siblings();
114
+ var sortableWidgetInstance = getSortableWidgetInstance(angular.element(e.target));
115
+ sortableWidgetInstance.floating = isFloating(siblings);
116
+ }
117
+
118
+ // Save the starting position of dragged item
119
+ ui.item.sortable = {
120
+ model: ngModel.$modelValue[ui.item.index()],
121
+ index: ui.item.index(),
122
+ source: ui.item.parent(),
123
+ sourceModel: ngModel.$modelValue,
124
+ cancel: function () {
125
+ ui.item.sortable._isCanceled = true;
126
+ },
127
+ isCanceled: function () {
128
+ return ui.item.sortable._isCanceled;
129
+ },
130
+ isCustomHelperUsed: function () {
131
+ return !!ui.item.sortable._isCustomHelperUsed;
132
+ },
133
+ _isCanceled: false,
134
+ _isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed,
135
+ _destroy: function () {
136
+ angular.forEach(ui.item.sortable, function(value, key) {
137
+ ui.item.sortable[key] = undefined;
138
+ });
139
+ }
140
+ };
141
+ };
142
+
143
+ callbacks.activate = function(e, ui) {
144
+ // We need to make a copy of the current element's contents so
145
+ // we can restore it after sortable has messed it up.
146
+ // This is inside activate (instead of start) in order to save
147
+ // both lists when dragging between connected lists.
148
+ savedNodes = element.contents();
149
+
150
+ // If this list has a placeholder (the connected lists won't),
151
+ // don't inlcude it in saved nodes.
152
+ var placeholder = element.sortable('option','placeholder');
153
+
154
+ // placeholder.element will be a function if the placeholder, has
155
+ // been created (placeholder will be an object). If it hasn't
156
+ // been created, either placeholder will be false if no
157
+ // placeholder class was given or placeholder.element will be
158
+ // undefined if a class was given (placeholder will be a string)
159
+ if (placeholder && placeholder.element && typeof placeholder.element === 'function') {
160
+ var phElement = placeholder.element();
161
+ // workaround for jquery ui 1.9.x,
162
+ // not returning jquery collection
163
+ phElement = angular.element(phElement);
164
+
165
+ // exact match with the placeholder's class attribute to handle
166
+ // the case that multiple connected sortables exist and
167
+ // the placehoilder option equals the class of sortable items
168
+ var excludes = element.find('[class="' + phElement.attr('class') + '"]:not([ng-repeat], [data-ng-repeat])');
169
+
170
+ savedNodes = savedNodes.not(excludes);
171
+ }
172
+
173
+ // save the directive's scope so that it is accessible from ui.item.sortable
174
+ var connectedSortables = ui.item.sortable._connectedSortables || [];
175
+
176
+ connectedSortables.push({
177
+ element: element,
178
+ scope: scope
179
+ });
180
+
181
+ ui.item.sortable._connectedSortables = connectedSortables;
182
+ };
183
+
184
+ callbacks.update = function(e, ui) {
185
+ // Save current drop position but only if this is not a second
186
+ // update that happens when moving between lists because then
187
+ // the value will be overwritten with the old value
188
+ if(!ui.item.sortable.received) {
189
+ ui.item.sortable.dropindex = ui.item.index();
190
+ var droptarget = ui.item.parent();
191
+ ui.item.sortable.droptarget = droptarget;
192
+
193
+ var droptargetScope = getElementScope(ui.item.sortable._connectedSortables, droptarget);
194
+ ui.item.sortable.droptargetModel = droptargetScope.ngModel;
195
+
196
+ // Cancel the sort (let ng-repeat do the sort for us)
197
+ // Don't cancel if this is the received list because it has
198
+ // already been canceled in the other list, and trying to cancel
199
+ // here will mess up the DOM.
200
+ element.sortable('cancel');
201
+ }
202
+
203
+ // Put the nodes back exactly the way they started (this is very
204
+ // important because ng-repeat uses comment elements to delineate
205
+ // the start and stop of repeat sections and sortable doesn't
206
+ // respect their order (even if we cancel, the order of the
207
+ // comments are still messed up).
208
+ if (hasSortingHelper(element, ui) && !ui.item.sortable.received &&
209
+ element.sortable( 'option', 'appendTo' ) === 'parent') {
210
+ // restore all the savedNodes except .ui-sortable-helper element
211
+ // (which is placed last). That way it will be garbage collected.
212
+ savedNodes = savedNodes.not(savedNodes.last());
213
+ }
214
+ savedNodes.appendTo(element);
215
+
216
+ // If this is the target connected list then
217
+ // it's safe to clear the restored nodes since:
218
+ // update is currently running and
219
+ // stop is not called for the target list.
220
+ if(ui.item.sortable.received) {
221
+ savedNodes = null;
222
+ }
223
+
224
+ // If received is true (an item was dropped in from another list)
225
+ // then we add the new item to this list otherwise wait until the
226
+ // stop event where we will know if it was a sort or item was
227
+ // moved here from another list
228
+ if(ui.item.sortable.received && !ui.item.sortable.isCanceled()) {
229
+ scope.$apply(function () {
230
+ ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0,
231
+ ui.item.sortable.moved);
232
+ });
233
+ }
234
+ };
235
+
236
+ callbacks.stop = function(e, ui) {
237
+ // If the received flag hasn't be set on the item, this is a
238
+ // normal sort, if dropindex is set, the item was moved, so move
239
+ // the items in the list.
240
+ if(!ui.item.sortable.received &&
241
+ ('dropindex' in ui.item.sortable) &&
242
+ !ui.item.sortable.isCanceled()) {
243
+
244
+ scope.$apply(function () {
245
+ ngModel.$modelValue.splice(
246
+ ui.item.sortable.dropindex, 0,
247
+ ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]);
248
+ });
249
+ } else {
250
+ // if the item was not moved, then restore the elements
251
+ // so that the ngRepeat's comment are correct.
252
+ if ((!('dropindex' in ui.item.sortable) || ui.item.sortable.isCanceled()) &&
253
+ !hasSortingHelper(element, ui)) {
254
+ savedNodes.appendTo(element);
255
+ }
256
+ }
257
+
258
+ // It's now safe to clear the savedNodes
259
+ // since stop is the last callback.
260
+ savedNodes = null;
261
+ };
262
+
263
+ callbacks.receive = function(e, ui) {
264
+ // An item was dropped here from another list, set a flag on the
265
+ // item.
266
+ ui.item.sortable.received = true;
267
+ };
268
+
269
+ callbacks.remove = function(e, ui) {
270
+ // Workaround for a problem observed in nested connected lists.
271
+ // There should be an 'update' event before 'remove' when moving
272
+ // elements. If the event did not fire, cancel sorting.
273
+ if (!('dropindex' in ui.item.sortable)) {
274
+ element.sortable('cancel');
275
+ ui.item.sortable.cancel();
276
+ }
277
+
278
+ // Remove the item from this list's model and copy data into item,
279
+ // so the next list can retrive it
280
+ if (!ui.item.sortable.isCanceled()) {
281
+ scope.$apply(function () {
282
+ ui.item.sortable.moved = ngModel.$modelValue.splice(
283
+ ui.item.sortable.index, 1)[0];
284
+ });
285
+ }
286
+ };
287
+
288
+ wrappers.helper = function (inner) {
289
+ if (inner && typeof inner === 'function') {
290
+ return function (e, item) {
291
+ var innerResult = inner(e, item);
292
+ item.sortable._isCustomHelperUsed = item !== innerResult;
293
+ return innerResult;
294
+ };
295
+ }
296
+ return inner;
297
+ };
298
+
299
+ scope.$watch('uiSortable', function(newVal /*, oldVal*/) {
300
+ // ensure that the jquery-ui-sortable widget instance
301
+ // is still bound to the directive's element
302
+ var sortableWidgetInstance = getSortableWidgetInstance(element);
303
+ if (!!sortableWidgetInstance) {
304
+ angular.forEach(newVal, function(value, key) {
305
+ // if it's a custom option of the directive,
306
+ // handle it approprietly
307
+ if (key in directiveOpts) {
308
+ if (key === 'ui-floating' && (value === false || value === true)) {
309
+ sortableWidgetInstance.floating = value;
310
+ }
311
+
312
+ opts[key] = value;
313
+ return;
314
+ }
315
+
316
+ if (callbacks[key]) {
317
+ if( key === 'stop' ){
318
+ // call apply after stop
319
+ value = combineCallbacks(
320
+ value, function() { scope.$apply(); });
321
+
322
+ value = combineCallbacks(value, afterStop);
323
+ }
324
+ // wrap the callback
325
+ value = combineCallbacks(callbacks[key], value);
326
+ } else if (wrappers[key]) {
327
+ value = wrappers[key](value);
328
+ }
329
+
330
+ opts[key] = value;
331
+ element.sortable('option', key, value);
332
+ });
333
+ }
334
+ }, true);
335
+
336
+ angular.forEach(callbacks, function(value, key) {
337
+ opts[key] = combineCallbacks(value, opts[key]);
338
+ if( key === 'stop' ){
339
+ opts[key] = combineCallbacks(opts[key], afterStop);
340
+ }
341
+ });
342
+
343
+ } else {
344
+ $log.info('ui.sortable: ngModel not provided!', element);
345
+ }
346
+
347
+ // Create sortable
348
+ element.sortable(opts);
349
+ }
350
+ };
351
+ }
352
+ ]);
353
+
354
+ })(window, window.angular);
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-angular-ui-sortable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.13.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Bobrov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails-angularjs
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails-jquery-ui-sortable
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1.9'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1.9'
41
+ description: Injects UI.Sortable directive into your asset pipeline.
42
+ email: alexander@devvela.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - MIT-LICENSE
48
+ - README.md
49
+ - lib/rails-angular-ui-sortable.rb
50
+ - lib/rails-angular-ui-sortable/engine.rb
51
+ - lib/rails-angular-ui-sortable/version.rb
52
+ - vendor/assets/javascripts/angular-ui-sortable.js
53
+ homepage: https://github.com/alexkpek/rails-angular-ui-sortable
54
+ licenses:
55
+ - MIT
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.4.6
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: UI.Sortable directive on Rails
77
+ test_files: []
78
+ has_rdoc: