promethee 1.3.2 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/app/assets/stylesheets/promethee-edit/_move.sass +6 -4
  4. data/app/views/promethee/_edit.html.erb +14 -6
  5. data/app/views/promethee/components/aside/_edit.define.html.erb +14 -151
  6. data/app/views/promethee/components/aside/_icon.svg +3 -0
  7. data/app/views/promethee/components/column/_edit.define.html.erb +17 -31
  8. data/app/views/promethee/components/column/_icon.svg +3 -0
  9. data/app/views/promethee/components/cover/_edit.define.html.erb +16 -151
  10. data/app/views/promethee/components/cover/_icon.svg +3 -0
  11. data/app/views/promethee/components/image/_edit.define.html.erb +17 -149
  12. data/app/views/promethee/components/image/_icon.svg +3 -0
  13. data/app/views/promethee/components/row/_edit.define.html.erb +14 -150
  14. data/app/views/promethee/components/row/_icon.svg +3 -0
  15. data/app/views/promethee/components/slider/_edit.define.html.erb +14 -150
  16. data/app/views/promethee/components/slider/_edit.inspect.html.erb +43 -1
  17. data/app/views/promethee/components/slider/_edit.move.html.erb +6 -2
  18. data/app/views/promethee/components/slider/_icon.svg +3 -0
  19. data/app/views/promethee/components/text/_edit.define.html.erb +15 -150
  20. data/app/views/promethee/components/text/_icon.svg +3 -0
  21. data/app/views/promethee/components/video/_edit.define.html.erb +14 -29
  22. data/app/views/promethee/components/video/_icon.svg +3 -0
  23. data/app/views/promethee/edit/_move.html.erb +48 -21
  24. data/app/views/promethee/presets/_icon.image-with-text.svg +3 -0
  25. data/app/views/promethee/presets/_image-with-text.html.erb +33 -0
  26. data/app/views/promethee/utils/_summernote-config.html.erb +11 -5
  27. data/lib/promethee/rails/helper.rb +4 -0
  28. data/lib/promethee/rails/version.rb +1 -1
  29. data/vendor/assets/javascripts/ui-sortable.js +683 -0
  30. metadata +14 -3
@@ -2,15 +2,21 @@
2
2
  promethee.constant('summernoteConfig', {
3
3
  disableDragAndDrop: true,
4
4
  callbacks: {
5
+ // Remove text styles on paste
5
6
  onPaste: function(event) {
6
- // Remove text styles on paste
7
+ event.preventDefault();
8
+
9
+ // Get and trim clipboard content as paragraph
7
10
  var paragraph = document.createElement('p');
8
11
  paragraph.textContent = ((event.originalEvent || event).clipboardData || window.clipboardData).getData('Text').trim();
9
- event.preventDefault();
10
12
 
11
- setTimeout(function() {
12
- document.execCommand('insertNode', false, paragraph);
13
- }, 10);
13
+ // Delete selection if anything is selected (expected behaviour on paste)
14
+ if((window.getSelection !== undefined ? window.getSelection() : document.selection.createRange()).toString().length > 0) {
15
+ document.execCommand('delete', false);
16
+ }
17
+
18
+ // Insert trimmed clipboard content as paragraph
19
+ document.execCommand('insertHTML', false, paragraph.outerHTML);
14
20
  }
15
21
  },
16
22
  toolbar: [
@@ -22,6 +22,10 @@ module Promethee::Rails::Helper
22
22
  promethee_partials_for 'utils/_*.html.erb'
23
23
  end
24
24
 
25
+ def promethee_preset_partials
26
+ promethee_partials_for 'presets/_*.html.erb'
27
+ end
28
+
25
29
  # promethee_bem_classes 'promethee-edit__move__droppable', '--{{type}}', '--first'
26
30
  # -> promethee-edit__move__droppable promethee-edit__move__droppable--{{type}} promethee-edit__move__droppable--{{type}}--first"
27
31
  def promethee_bem_classes(*args)
@@ -1,5 +1,5 @@
1
1
  module Promethee
2
2
  module Rails
3
- VERSION = '1.3.2'
3
+ VERSION = '1.3.3'
4
4
  end
5
5
  end
@@ -0,0 +1,683 @@
1
+ /*
2
+ jQuery UI Sortable plugin wrapper
3
+ @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
4
+ */
5
+ angular
6
+ .module('ui.sortable', [])
7
+ .value('uiSortableConfig', {
8
+ // the default for jquery-ui sortable is "> *", we need to restrict this to
9
+ // ng-repeat items
10
+ // if the user uses
11
+ items: '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'
12
+ })
13
+ .directive('uiSortable', [
14
+ 'uiSortableConfig',
15
+ '$timeout',
16
+ '$log',
17
+ function(uiSortableConfig, $timeout, $log) {
18
+ return {
19
+ require: '?ngModel',
20
+ scope: {
21
+ ngModel: '=',
22
+ uiSortable: '=',
23
+ ////Expression bindings from html.
24
+ create: '&uiSortableCreate',
25
+ // helper:'&uiSortableHelper',
26
+ start: '&uiSortableStart',
27
+ activate: '&uiSortableActivate',
28
+ // sort:'&uiSortableSort',
29
+ // change:'&uiSortableChange',
30
+ // over:'&uiSortableOver',
31
+ // out:'&uiSortableOut',
32
+ beforeStop: '&uiSortableBeforeStop',
33
+ update: '&uiSortableUpdate',
34
+ remove: '&uiSortableRemove',
35
+ receive: '&uiSortableReceive',
36
+ deactivate: '&uiSortableDeactivate',
37
+ stop: '&uiSortableStop'
38
+ },
39
+ link: function(scope, element, attrs, ngModel) {
40
+ var savedNodes;
41
+ var helper;
42
+
43
+ function combineCallbacks(first, second) {
44
+ var firstIsFunc = typeof first === 'function';
45
+ var secondIsFunc = typeof second === 'function';
46
+ if (firstIsFunc && secondIsFunc) {
47
+ return function() {
48
+ first.apply(this, arguments);
49
+ second.apply(this, arguments);
50
+ };
51
+ } else if (secondIsFunc) {
52
+ return second;
53
+ }
54
+ return first;
55
+ }
56
+
57
+ function getSortableWidgetInstance(element) {
58
+ // this is a fix to support jquery-ui prior to v1.11.x
59
+ // otherwise we should be using `element.sortable('instance')`
60
+ var data = element.data('ui-sortable');
61
+ if (
62
+ data &&
63
+ typeof data === 'object' &&
64
+ data.widgetFullName === 'ui-sortable'
65
+ ) {
66
+ return data;
67
+ }
68
+ return null;
69
+ }
70
+
71
+ function setItemChildrenWidth(item) {
72
+ item.children().each(function() {
73
+ var $el = angular.element(this);
74
+
75
+ // Preserve the with of the element
76
+ $el.width($el.width());
77
+ });
78
+ }
79
+
80
+ function dummyHelper(e, item) {
81
+ return item;
82
+ }
83
+
84
+ function patchSortableOption(key, value) {
85
+ if (callbacks[key]) {
86
+ if (key === 'stop') {
87
+ // call apply after stop
88
+ value = combineCallbacks(value, function() {
89
+ scope.$apply();
90
+ });
91
+
92
+ value = combineCallbacks(value, afterStop);
93
+ }
94
+ // wrap the callback
95
+ value = combineCallbacks(callbacks[key], value);
96
+ } else if (wrappers[key]) {
97
+ value = wrappers[key](value);
98
+ }
99
+
100
+ // patch the options that need to have values set
101
+ if (!value && (key === 'items' || key === 'ui-model-items')) {
102
+ value = uiSortableConfig.items;
103
+ }
104
+
105
+ return value;
106
+ }
107
+
108
+ function patchUISortableOptions(
109
+ newOpts,
110
+ oldOpts,
111
+ sortableWidgetInstance
112
+ ) {
113
+ function addDummyOptionKey(value, key) {
114
+ if (!(key in opts)) {
115
+ // add the key in the opts object so that
116
+ // the patch function detects and handles it
117
+ opts[key] = null;
118
+ }
119
+ }
120
+ // for this directive to work we have to attach some callbacks
121
+ angular.forEach(callbacks, addDummyOptionKey);
122
+
123
+ // only initialize it in case we have to
124
+ // update some options of the sortable
125
+ var optsDiff = null;
126
+
127
+ if (oldOpts) {
128
+ // reset deleted options to default
129
+ var defaultOptions;
130
+ angular.forEach(oldOpts, function(oldValue, key) {
131
+ if (!newOpts || !(key in newOpts)) {
132
+ if (key in directiveOpts) {
133
+ if (key === 'ui-floating') {
134
+ opts[key] = 'auto';
135
+ } else {
136
+ opts[key] = patchSortableOption(key, undefined);
137
+ }
138
+ return;
139
+ }
140
+
141
+ if (!defaultOptions) {
142
+ defaultOptions = angular.element.ui.sortable().options;
143
+ }
144
+ var defaultValue = defaultOptions[key];
145
+ defaultValue = patchSortableOption(key, defaultValue);
146
+
147
+ if (!optsDiff) {
148
+ optsDiff = {};
149
+ }
150
+ optsDiff[key] = defaultValue;
151
+ opts[key] = defaultValue;
152
+ }
153
+ });
154
+ }
155
+
156
+ newOpts = angular.extend({}, newOpts);
157
+ // update changed options
158
+ // handle the custom option of the directive first
159
+ angular.forEach(newOpts, function(value, key) {
160
+ if (key in directiveOpts) {
161
+ if (
162
+ key === 'ui-floating' &&
163
+ (value === false || value === true) &&
164
+ sortableWidgetInstance
165
+ ) {
166
+ sortableWidgetInstance.floating = value;
167
+ }
168
+
169
+ if (
170
+ key === 'ui-preserve-size' &&
171
+ (value === false || value === true)
172
+ ) {
173
+ var userProvidedHelper = opts.helper;
174
+ newOpts.helper = function(e, item) {
175
+ if (opts['ui-preserve-size'] === true) {
176
+ setItemChildrenWidth(item);
177
+ }
178
+ return (userProvidedHelper || dummyHelper).apply(
179
+ this,
180
+ arguments
181
+ );
182
+ };
183
+ }
184
+
185
+ opts[key] = patchSortableOption(key, value);
186
+ }
187
+ });
188
+
189
+ // handle the normal option of the directive
190
+ angular.forEach(newOpts, function(value, key) {
191
+ if (key in directiveOpts) {
192
+ // the custom option of the directive are already handled
193
+ return;
194
+ }
195
+
196
+ value = patchSortableOption(key, value);
197
+
198
+ if (!optsDiff) {
199
+ optsDiff = {};
200
+ }
201
+ optsDiff[key] = value;
202
+ opts[key] = value;
203
+ });
204
+
205
+ return optsDiff;
206
+ }
207
+
208
+ function getPlaceholderElement(element) {
209
+ var placeholder = element.sortable('option', 'placeholder');
210
+
211
+ // placeholder.element will be a function if the placeholder, has
212
+ // been created (placeholder will be an object). If it hasn't
213
+ // been created, either placeholder will be false if no
214
+ // placeholder class was given or placeholder.element will be
215
+ // undefined if a class was given (placeholder will be a string)
216
+ if (
217
+ placeholder &&
218
+ placeholder.element &&
219
+ typeof placeholder.element === 'function'
220
+ ) {
221
+ var result = placeholder.element();
222
+ // workaround for jquery ui 1.9.x,
223
+ // not returning jquery collection
224
+ result = angular.element(result);
225
+ return result;
226
+ }
227
+ return null;
228
+ }
229
+
230
+ function getPlaceholderExcludesludes(element, placeholder) {
231
+ // exact match with the placeholder's class attribute to handle
232
+ // the case that multiple connected sortables exist and
233
+ // the placeholder option equals the class of sortable items
234
+ var notCssSelector = opts['ui-model-items'].replace(/[^,]*>/g, '');
235
+ var excludes = element.find(
236
+ '[class="' +
237
+ placeholder.attr('class') +
238
+ '"]:not(' +
239
+ notCssSelector +
240
+ ')'
241
+ );
242
+ return excludes;
243
+ }
244
+
245
+ function hasSortingHelper(element, ui) {
246
+ var helperOption = element.sortable('option', 'helper');
247
+ return (
248
+ helperOption === 'clone' ||
249
+ (typeof helperOption === 'function' &&
250
+ ui.item.sortable.isCustomHelperUsed())
251
+ );
252
+ }
253
+
254
+ function getSortingHelper(element, ui /*, savedNodes*/) {
255
+ var result = null;
256
+ if (
257
+ hasSortingHelper(element, ui) &&
258
+ element.sortable('option', 'appendTo') === 'parent'
259
+ ) {
260
+ // The .ui-sortable-helper element (that's the default class name)
261
+ result = helper;
262
+ }
263
+ return result;
264
+ }
265
+
266
+ // thanks jquery-ui
267
+ function isFloating(item) {
268
+ return (
269
+ /left|right/.test(item.css('float')) ||
270
+ /inline|table-cell/.test(item.css('display'))
271
+ );
272
+ }
273
+
274
+ function getElementContext(elementScopes, element) {
275
+ for (var i = 0; i < elementScopes.length; i++) {
276
+ var c = elementScopes[i];
277
+ if (c.element[0] === element[0]) {
278
+ return c;
279
+ }
280
+ }
281
+ }
282
+
283
+ function afterStop(e, ui) {
284
+ ui.item.sortable._destroy();
285
+ }
286
+
287
+ // return the index of ui.item among the items
288
+ // we can't just do ui.item.index() because there it might have siblings
289
+ // which are not items
290
+ function getItemIndex(item) {
291
+ return item
292
+ .parent()
293
+ .find(opts['ui-model-items'])
294
+ .index(item);
295
+ }
296
+
297
+ var opts = {};
298
+
299
+ // directive specific options
300
+ var directiveOpts = {
301
+ 'ui-floating': undefined,
302
+ 'ui-model-items': uiSortableConfig.items,
303
+ 'ui-preserve-size': undefined
304
+ };
305
+
306
+ var callbacks = {
307
+ create: null,
308
+ start: null,
309
+ activate: null,
310
+ // sort: null,
311
+ // change: null,
312
+ // over: null,
313
+ // out: null,
314
+ beforeStop: null,
315
+ update: null,
316
+ remove: null,
317
+ receive: null,
318
+ deactivate: null,
319
+ stop: null
320
+ };
321
+
322
+ var wrappers = {
323
+ helper: null
324
+ };
325
+
326
+ angular.extend(
327
+ opts,
328
+ directiveOpts,
329
+ uiSortableConfig,
330
+ scope.uiSortable
331
+ );
332
+
333
+ if (!angular.element.fn || !angular.element.fn.jquery) {
334
+ $log.error(
335
+ 'ui.sortable: jQuery should be included before AngularJS!'
336
+ );
337
+ return;
338
+ }
339
+
340
+ function wireUp() {
341
+ // When we add or remove elements, we need the sortable to 'refresh'
342
+ // so it can find the new/removed elements.
343
+ scope.$watchCollection('ngModel', function() {
344
+ // Timeout to let ng-repeat modify the DOM
345
+ $timeout(
346
+ function() {
347
+ // ensure that the jquery-ui-sortable widget instance
348
+ // is still bound to the directive's element
349
+ if (!!getSortableWidgetInstance(element)) {
350
+ element.sortable('refresh');
351
+ }
352
+ },
353
+ 0,
354
+ false
355
+ );
356
+ });
357
+
358
+ callbacks.start = function(e, ui) {
359
+ if (opts['ui-floating'] === 'auto') {
360
+ // since the drag has started, the element will be
361
+ // absolutely positioned, so we check its siblings
362
+ var siblings = ui.item.siblings();
363
+ var sortableWidgetInstance = getSortableWidgetInstance(
364
+ angular.element(e.target)
365
+ );
366
+ sortableWidgetInstance.floating = isFloating(siblings);
367
+ }
368
+
369
+ // Save the starting position of dragged item
370
+ var index = getItemIndex(ui.item);
371
+ ui.item.sortable = {
372
+ model: ngModel.$modelValue[index],
373
+ index: index,
374
+ source: element,
375
+ sourceList: ui.item.parent(),
376
+ sourceModel: ngModel.$modelValue,
377
+ cancel: function() {
378
+ ui.item.sortable._isCanceled = true;
379
+ },
380
+ isCanceled: function() {
381
+ return ui.item.sortable._isCanceled;
382
+ },
383
+ isCustomHelperUsed: function() {
384
+ return !!ui.item.sortable._isCustomHelperUsed;
385
+ },
386
+ _isCanceled: false,
387
+ _isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed,
388
+ _destroy: function() {
389
+ angular.forEach(ui.item.sortable, function(value, key) {
390
+ ui.item.sortable[key] = undefined;
391
+ });
392
+ },
393
+ _connectedSortables: [],
394
+ _getElementContext: function(element) {
395
+ return getElementContext(this._connectedSortables, element);
396
+ }
397
+ };
398
+ };
399
+
400
+ callbacks.activate = function(e, ui) {
401
+ var isSourceContext = ui.item.sortable.source === element;
402
+ var savedNodesOrigin = isSourceContext
403
+ ? ui.item.sortable.sourceList
404
+ : element;
405
+ var elementContext = {
406
+ element: element,
407
+ scope: scope,
408
+ isSourceContext: isSourceContext,
409
+ savedNodesOrigin: savedNodesOrigin
410
+ };
411
+ // save the directive's scope so that it is accessible from ui.item.sortable
412
+ ui.item.sortable._connectedSortables.push(elementContext);
413
+
414
+ // We need to make a copy of the current element's contents so
415
+ // we can restore it after sortable has messed it up.
416
+ // This is inside activate (instead of start) in order to save
417
+ // both lists when dragging between connected lists.
418
+ savedNodes = savedNodesOrigin.contents();
419
+ helper = ui.helper;
420
+
421
+ // If this list has a placeholder (the connected lists won't),
422
+ // don't inlcude it in saved nodes.
423
+ var placeholder = getPlaceholderElement(element);
424
+ if (placeholder && placeholder.length) {
425
+ var excludes = getPlaceholderExcludesludes(
426
+ element,
427
+ placeholder
428
+ );
429
+ savedNodes = savedNodes.not(excludes);
430
+ }
431
+ };
432
+
433
+ callbacks.update = function(e, ui) {
434
+ // Save current drop position but only if this is not a second
435
+ // update that happens when moving between lists because then
436
+ // the value will be overwritten with the old value
437
+ if (!ui.item.sortable.received) {
438
+ ui.item.sortable.dropindex = getItemIndex(ui.item);
439
+ var droptarget = ui.item
440
+ .parent()
441
+ .closest(
442
+ '[ui-sortable], [data-ui-sortable], [x-ui-sortable]'
443
+ );
444
+ ui.item.sortable.droptarget = droptarget;
445
+ ui.item.sortable.droptargetList = ui.item.parent();
446
+
447
+ var droptargetContext = ui.item.sortable._getElementContext(
448
+ droptarget
449
+ );
450
+ ui.item.sortable.droptargetModel =
451
+ droptargetContext.scope.ngModel;
452
+
453
+ // Cancel the sort (let ng-repeat do the sort for us)
454
+ // Don't cancel if this is the received list because it has
455
+ // already been canceled in the other list, and trying to cancel
456
+ // here will mess up the DOM.
457
+ element.sortable('cancel');
458
+ }
459
+
460
+ // Put the nodes back exactly the way they started (this is very
461
+ // important because ng-repeat uses comment elements to delineate
462
+ // the start and stop of repeat sections and sortable doesn't
463
+ // respect their order (even if we cancel, the order of the
464
+ // comments are still messed up).
465
+ var sortingHelper =
466
+ !ui.item.sortable.received &&
467
+ getSortingHelper(element, ui, savedNodes);
468
+ if (sortingHelper && sortingHelper.length) {
469
+ // Restore all the savedNodes except from the sorting helper element.
470
+ // That way it will be garbage collected.
471
+ savedNodes = savedNodes.not(sortingHelper);
472
+ }
473
+ var elementContext = ui.item.sortable._getElementContext(element);
474
+ savedNodes.appendTo(elementContext.savedNodesOrigin);
475
+
476
+ // If this is the target connected list then
477
+ // it's safe to clear the restored nodes since:
478
+ // update is currently running and
479
+ // stop is not called for the target list.
480
+ if (ui.item.sortable.received) {
481
+ savedNodes = null;
482
+ }
483
+
484
+ // If received is true (an item was dropped in from another list)
485
+ // then we add the new item to this list otherwise wait until the
486
+ // stop event where we will know if it was a sort or item was
487
+ // moved here from another list
488
+ if (ui.item.sortable.received && !ui.item.sortable.isCanceled()) {
489
+ scope.$apply(function() {
490
+ ngModel.$modelValue.splice(
491
+ ui.item.sortable.dropindex,
492
+ 0,
493
+ ui.item.sortable.moved
494
+ );
495
+ });
496
+ scope.$emit('ui-sortable:moved', ui);
497
+ }
498
+ };
499
+
500
+ callbacks.stop = function(e, ui) {
501
+ // If the received flag hasn't be set on the item, this is a
502
+ // normal sort, if dropindex is set, the item was moved, so move
503
+ // the items in the list.
504
+ var wasMoved =
505
+ 'dropindex' in ui.item.sortable &&
506
+ !ui.item.sortable.isCanceled();
507
+
508
+ if (wasMoved && !ui.item.sortable.received) {
509
+ scope.$apply(function() {
510
+ ngModel.$modelValue.splice(
511
+ ui.item.sortable.dropindex,
512
+ 0,
513
+ ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]
514
+ );
515
+ });
516
+ scope.$emit('ui-sortable:moved', ui);
517
+ } else if (
518
+ !wasMoved &&
519
+ !angular.equals(
520
+ element.contents().toArray(),
521
+ savedNodes.toArray()
522
+ )
523
+ ) {
524
+ // if the item was not moved
525
+ // and the DOM element order has changed,
526
+ // then restore the elements
527
+ // so that the ngRepeat's comment are correct.
528
+
529
+ var sortingHelper = getSortingHelper(element, ui, savedNodes);
530
+ if (sortingHelper && sortingHelper.length) {
531
+ // Restore all the savedNodes except from the sorting helper element.
532
+ // That way it will be garbage collected.
533
+ savedNodes = savedNodes.not(sortingHelper);
534
+ }
535
+ var elementContext = ui.item.sortable._getElementContext(
536
+ element
537
+ );
538
+ savedNodes.appendTo(elementContext.savedNodesOrigin);
539
+ }
540
+
541
+ // It's now safe to clear the savedNodes and helper
542
+ // since stop is the last callback.
543
+ savedNodes = null;
544
+ helper = null;
545
+ };
546
+
547
+ callbacks.receive = function(e, ui) {
548
+ // An item was dropped here from another list, set a flag on the
549
+ // item.
550
+ ui.item.sortable.received = true;
551
+ };
552
+
553
+ callbacks.remove = function(e, ui) {
554
+ // Workaround for a problem observed in nested connected lists.
555
+ // There should be an 'update' event before 'remove' when moving
556
+ // elements. If the event did not fire, cancel sorting.
557
+ if (!('dropindex' in ui.item.sortable)) {
558
+ element.sortable('cancel');
559
+ ui.item.sortable.cancel();
560
+ }
561
+
562
+ // Remove the item from this list's model and copy data into item,
563
+ // so the next list can retrive it
564
+ if (!ui.item.sortable.isCanceled()) {
565
+ scope.$apply(function() {
566
+ ui.item.sortable.moved = ngModel.$modelValue.splice(
567
+ ui.item.sortable.index,
568
+ 1
569
+ )[0];
570
+ });
571
+ }
572
+ };
573
+
574
+ // setup attribute handlers
575
+ angular.forEach(callbacks, function(value, key) {
576
+ callbacks[key] = combineCallbacks(callbacks[key], function() {
577
+ var attrHandler = scope[key];
578
+ var attrHandlerFn;
579
+ if (
580
+ typeof attrHandler === 'function' &&
581
+ (
582
+ 'uiSortable' +
583
+ key.substring(0, 1).toUpperCase() +
584
+ key.substring(1)
585
+ ).length &&
586
+ typeof (attrHandlerFn = attrHandler()) === 'function'
587
+ ) {
588
+ attrHandlerFn.apply(this, arguments);
589
+ }
590
+ });
591
+ });
592
+
593
+ wrappers.helper = function(inner) {
594
+ if (inner && typeof inner === 'function') {
595
+ return function(e, item) {
596
+ var oldItemSortable = item.sortable;
597
+ var index = getItemIndex(item);
598
+
599
+ item.sortable = {
600
+ model: ngModel.$modelValue[index],
601
+ index: index,
602
+ source: element,
603
+ sourceList: item.parent(),
604
+ sourceModel: ngModel.$modelValue,
605
+ _restore: function() {
606
+ angular.forEach(item.sortable, function(value, key) {
607
+ item.sortable[key] = undefined;
608
+ });
609
+
610
+ item.sortable = oldItemSortable;
611
+ }
612
+ };
613
+
614
+ var innerResult = inner.apply(this, arguments);
615
+ item.sortable._restore();
616
+ item.sortable._isCustomHelperUsed = item !== innerResult;
617
+ return innerResult;
618
+ };
619
+ }
620
+ return inner;
621
+ };
622
+
623
+ scope.$watchCollection(
624
+ 'uiSortable',
625
+ function(newOpts, oldOpts) {
626
+ // ensure that the jquery-ui-sortable widget instance
627
+ // is still bound to the directive's element
628
+ var sortableWidgetInstance = getSortableWidgetInstance(element);
629
+ if (!!sortableWidgetInstance) {
630
+ var optsDiff = patchUISortableOptions(
631
+ newOpts,
632
+ oldOpts,
633
+ sortableWidgetInstance
634
+ );
635
+
636
+ if (optsDiff) {
637
+ element.sortable('option', optsDiff);
638
+ }
639
+ }
640
+ },
641
+ true
642
+ );
643
+
644
+ patchUISortableOptions(opts);
645
+ }
646
+
647
+ function init() {
648
+ if (ngModel) {
649
+ wireUp();
650
+ } else {
651
+ $log.info('ui.sortable: ngModel not provided!', element);
652
+ }
653
+
654
+ // Create sortable
655
+ element.sortable(opts);
656
+ }
657
+
658
+ function initIfEnabled() {
659
+ if (scope.uiSortable && scope.uiSortable.disabled) {
660
+ return false;
661
+ }
662
+
663
+ init();
664
+
665
+ // Stop Watcher
666
+ initIfEnabled.cancelWatcher();
667
+ initIfEnabled.cancelWatcher = angular.noop;
668
+
669
+ return true;
670
+ }
671
+
672
+ initIfEnabled.cancelWatcher = angular.noop;
673
+
674
+ if (!initIfEnabled()) {
675
+ initIfEnabled.cancelWatcher = scope.$watch(
676
+ 'uiSortable.disabled',
677
+ initIfEnabled
678
+ );
679
+ }
680
+ }
681
+ };
682
+ }
683
+ ]);