simple_form_nested_fields 0.1.0

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.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "simple_form_nested_fields"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,32 @@
1
+ #= require simple_form_nested_fields__links
2
+ #= require simple_form_nested_fields__sortable
3
+
4
+ do ($ = jQuery, window, document) ->
5
+ pluginName = 'SimpleFormNestedFields'
6
+ defaults =
7
+ debug: false
8
+
9
+ class Plugin
10
+ constructor: (@element, options) ->
11
+ @options = $.extend {}, defaults, options
12
+ @_defaults = defaults
13
+ @_name = pluginName
14
+ @$element = $(@element)
15
+ @init()
16
+
17
+ init: ->
18
+ @$element.SimpleFormNestedFields__Links()
19
+ @$element.SimpleFormNestedFields__Sortable() if @is_sortable()
20
+
21
+ destroy: ->
22
+ @$element.data('plugin_SimpleFormNestedFields__Links').destroy()
23
+ @$element.data('plugin_SimpleFormNestedFields__Sortable').destroy()
24
+
25
+ is_sortable: -> @element.classList.contains('simple_form_nested_fields__sortable')
26
+
27
+ # A really lightweight plugin wrapper around the constructor,
28
+ # preventing against multiple instantiations
29
+ $.fn[pluginName] = (options) ->
30
+ @each ->
31
+ if !$.data(@, "plugin_#{pluginName}")
32
+ $.data(@, "plugin_#{pluginName}", new Plugin(@, options))
@@ -0,0 +1,49 @@
1
+ do ($ = jQuery, window, document) ->
2
+ pluginName = 'SimpleFormNestedFields__Links'
3
+ defaults =
4
+ debug: false
5
+ new_item_class_name: 'simple_form_nested_fields__item__new'
6
+ regexp: new RegExp("__INDEX_PLACEHOLDER__", 'g')
7
+
8
+ class Plugin
9
+ constructor: (@element, options) ->
10
+ @options = $.extend {}, defaults, options
11
+ @_defaults = defaults
12
+ @_name = pluginName
13
+ @$element = $(@element)
14
+ @init()
15
+
16
+ init: ->
17
+ @$element.on "click.#{@_name}", '.simple_form_nested_fields__link', (e) =>
18
+ e.preventDefault()
19
+ link = e.target
20
+ switch
21
+ when link.classList.contains('simple_form_nested_fields__link__add') then @add_new_item(link)
22
+ when link.classList.contains('simple_form_nested_fields__link__remove') then @remove_item(link)
23
+
24
+ destroy: ->
25
+ @$element.off "click.#{@_name}", '.simple_form_nested_fields__link__add'
26
+
27
+ get_index: -> new Date().getTime()
28
+ get_template: (link) -> $(link).data('template').replace(@options.regexp, @get_index())
29
+ get_items_container: -> @$element.find('.simple_form_nested_fields__items')
30
+
31
+ add_new_item: (link) ->
32
+ $template = $(@get_template(link))
33
+ $template.addClass(@options.new_item_class_name)
34
+ @get_items_container().append($template)
35
+
36
+ remove_item: (link) ->
37
+ $item = $(link).closest('.simple_form_nested_fields__item')
38
+ if $item.hasClass(@options.new_item_class_name)
39
+ $item.remove()
40
+ else
41
+ $item.find('input[type=hidden]').val('1')
42
+ $item.hide()
43
+
44
+ # A really lightweight plugin wrapper around the constructor,
45
+ # preventing against multiple instantiations
46
+ $.fn[pluginName] = (options) ->
47
+ @each ->
48
+ if !$.data(@, "plugin_#{pluginName}")
49
+ $.data(@, "plugin_#{pluginName}", new Plugin(@, options))
@@ -0,0 +1,55 @@
1
+ #= require sortablejs/1.6.1/index.js
2
+
3
+ do ($ = jQuery, window, document) ->
4
+ pluginName = 'SimpleFormNestedFields__Sortable'
5
+ defaults =
6
+ debug: false
7
+
8
+ class Plugin
9
+ constructor: (@element, options) ->
10
+ @$element = $(@element)
11
+ @$simple_form_nested_fields = @$element.data('plugin_SimpleFormNestedFields')
12
+ @options = $.extend {}, defaults, options
13
+ @_defaults = defaults
14
+ @_name = pluginName
15
+ @init()
16
+
17
+ init: ->
18
+ return if @sortable
19
+
20
+ @sortable = new Sortable(
21
+ @get_items_container()[0],
22
+
23
+ animation: 150,
24
+ draggable: '.simple_form_nested_fields__item',
25
+ ghostClass: '.simple_form_nested_fields__ghost',
26
+ handle: '.simple_form_nested_fields__item_handle',
27
+
28
+ # TODO: onAdd is not being triggered?
29
+ onAdd: (e) => @update_item_positions(),
30
+ onUpdate: (e) => @update_item_positions(),
31
+ onRemove: (e) => @update_item_positions(),
32
+ )
33
+
34
+ @$element.on "update_item_positions.#{@_name}", (e) =>
35
+ e.stopPropagation()
36
+ @update_item_positions()
37
+
38
+ @update_item_positions()
39
+
40
+ destroy: ->
41
+ @sortable.destroy() if @sortable
42
+
43
+ update_item_positions: ->
44
+ @get_items().each (i, el) =>
45
+ $(el).find('input[name*="position"]').val(i+1)
46
+
47
+ get_items: -> @get_items_container().find('.simple_form_nested_fields__item')
48
+ get_items_container: -> @$element.find('.simple_form_nested_fields__items')
49
+
50
+ # A really lightweight plugin wrapper around the constructor,
51
+ # preventing against multiple instantiations
52
+ $.fn[pluginName] = (options) ->
53
+ @each ->
54
+ if !$.data(@, "plugin_#{pluginName}")
55
+ $.data(@, "plugin_#{pluginName}", new Plugin(@, options))
@@ -0,0 +1,2 @@
1
+ /*! Sortable 1.6.1 - MIT | git://github.com/rubaxa/Sortable.git */
2
+ !function(a){"use strict";"function"==typeof define&&define.amd?define(a):"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=a():window.Sortable=a()}(function(){"use strict";function a(a,b){if(!a||!a.nodeType||1!==a.nodeType)throw"Sortable: `el` must be HTMLElement, and not "+{}.toString.call(a);this.el=a,this.options=b=t({},b),a[T]=this;var c={group:Math.random(),sort:!0,disabled:!1,store:null,handle:null,scroll:!0,scrollSensitivity:30,scrollSpeed:10,draggable:/[uo]l/i.test(a.nodeName)?"li":">*",ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,setData:function(a,b){a.setData("Text",b.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0}};for(var d in c)!(d in b)&&(b[d]=c[d]);ga(b);for(var e in this)"_"===e.charAt(0)&&"function"==typeof this[e]&&(this[e]=this[e].bind(this));this.nativeDraggable=!b.forceFallback&&$,f(a,"mousedown",this._onTapStart),f(a,"touchstart",this._onTapStart),f(a,"pointerdown",this._onTapStart),this.nativeDraggable&&(f(a,"dragover",this),f(a,"dragenter",this)),ea.push(this._onDragOver),b.store&&this.sort(b.store.get(this))}function b(a,b){"clone"!==a.lastPullMode&&(b=!0),z&&z.state!==b&&(i(z,"display",b?"none":""),b||z.state&&(a.options.group.revertClone?(A.insertBefore(z,B),a._animate(w,z)):A.insertBefore(z,w)),z.state=b)}function c(a,b,c){if(a){c=c||V;do if(">*"===b&&a.parentNode===c||r(a,b))return a;while(a=d(a))}return null}function d(a){var b=a.host;return b&&b.nodeType?b:a.parentNode}function e(a){a.dataTransfer&&(a.dataTransfer.dropEffect="move"),a.preventDefault()}function f(a,b,c){a.addEventListener(b,c,Z)}function g(a,b,c){a.removeEventListener(b,c,Z)}function h(a,b,c){if(a)if(a.classList)a.classList[c?"add":"remove"](b);else{var d=(" "+a.className+" ").replace(R," ").replace(" "+b+" "," ");a.className=(d+(c?" "+b:"")).replace(R," ")}}function i(a,b,c){var d=a&&a.style;if(d){if(void 0===c)return V.defaultView&&V.defaultView.getComputedStyle?c=V.defaultView.getComputedStyle(a,""):a.currentStyle&&(c=a.currentStyle),void 0===b?c:c[b];b in d||(b="-webkit-"+b),d[b]=c+("string"==typeof c?"":"px")}}function j(a,b,c){if(a){var d=a.getElementsByTagName(b),e=0,f=d.length;if(c)for(;e<f;e++)c(d[e],e);return d}return[]}function k(a,b,c,d,e,f,g){a=a||b[T];var h=V.createEvent("Event"),i=a.options,j="on"+c.charAt(0).toUpperCase()+c.substr(1);h.initEvent(c,!0,!0),h.to=b,h.from=e||b,h.item=d||b,h.clone=z,h.oldIndex=f,h.newIndex=g,b.dispatchEvent(h),i[j]&&i[j].call(a,h)}function l(a,b,c,d,e,f,g,h){var i,j,k=a[T],l=k.options.onMove;return i=V.createEvent("Event"),i.initEvent("move",!0,!0),i.to=b,i.from=a,i.dragged=c,i.draggedRect=d,i.related=e||b,i.relatedRect=f||b.getBoundingClientRect(),i.willInsertAfter=h,a.dispatchEvent(i),l&&(j=l.call(k,i,g)),j}function m(a){a.draggable=!1}function n(){aa=!1}function o(a,b){var c=a.lastElementChild,d=c.getBoundingClientRect();return b.clientY-(d.top+d.height)>5||b.clientX-(d.left+d.width)>5}function p(a){for(var b=a.tagName+a.className+a.src+a.href+a.textContent,c=b.length,d=0;c--;)d+=b.charCodeAt(c);return d.toString(36)}function q(a,b){var c=0;if(!a||!a.parentNode)return-1;for(;a&&(a=a.previousElementSibling);)"TEMPLATE"===a.nodeName.toUpperCase()||">*"!==b&&!r(a,b)||c++;return c}function r(a,b){if(a){b=b.split(".");var c=b.shift().toUpperCase(),d=new RegExp("\\s("+b.join("|")+")(?=\\s)","g");return!(""!==c&&a.nodeName.toUpperCase()!=c||b.length&&((" "+a.className+" ").match(d)||[]).length!=b.length)}return!1}function s(a,b){var c,d;return function(){void 0===c&&(c=arguments,d=this,setTimeout(function(){1===c.length?a.call(d,c[0]):a.apply(d,c),c=void 0},b))}}function t(a,b){if(a&&b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function u(a){return X?X(a).clone(!0)[0]:Y&&Y.dom?Y.dom(a).cloneNode(!0):a.cloneNode(!0)}function v(a){for(var b=a.getElementsByTagName("input"),c=b.length;c--;){var d=b[c];d.checked&&da.push(d)}}if("undefined"==typeof window||!window.document)return function(){throw new Error("Sortable.js requires a window with a document")};var w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q={},R=/\s+/g,S=/left|right|inline/,T="Sortable"+(new Date).getTime(),U=window,V=U.document,W=U.parseInt,X=U.jQuery||U.Zepto,Y=U.Polymer,Z=!1,$=!!("draggable"in V.createElement("div")),_=function(a){return!navigator.userAgent.match(/Trident.*rv[ :]?11\./)&&(a=V.createElement("x"),a.style.cssText="pointer-events:auto","auto"===a.style.pointerEvents)}(),aa=!1,ba=Math.abs,ca=Math.min,da=[],ea=[],fa=s(function(a,b,c){if(c&&b.scroll){var d,e,f,g,h,i,j=c[T],k=b.scrollSensitivity,l=b.scrollSpeed,m=a.clientX,n=a.clientY,o=window.innerWidth,p=window.innerHeight;if(E!==c&&(D=b.scroll,E=c,F=b.scrollFn,D===!0)){D=c;do if(D.offsetWidth<D.scrollWidth||D.offsetHeight<D.scrollHeight)break;while(D=D.parentNode)}D&&(d=D,e=D.getBoundingClientRect(),f=(ba(e.right-m)<=k)-(ba(e.left-m)<=k),g=(ba(e.bottom-n)<=k)-(ba(e.top-n)<=k)),f||g||(f=(o-m<=k)-(m<=k),g=(p-n<=k)-(n<=k),(f||g)&&(d=U)),Q.vx===f&&Q.vy===g&&Q.el===d||(Q.el=d,Q.vx=f,Q.vy=g,clearInterval(Q.pid),d&&(Q.pid=setInterval(function(){return i=g?g*l:0,h=f?f*l:0,"function"==typeof F?F.call(j,h,i,a):void(d===U?U.scrollTo(U.pageXOffset+h,U.pageYOffset+i):(d.scrollTop+=i,d.scrollLeft+=h))},24)))}},30),ga=function(a){function b(a,b){return void 0!==a&&a!==!0||(a=c.name),"function"==typeof a?a:function(c,d){var e=d.options.group.name;return b?a:a&&(a.join?a.indexOf(e)>-1:e==a)}}var c={},d=a.group;d&&"object"==typeof d||(d={name:d}),c.name=d.name,c.checkPull=b(d.pull,!0),c.checkPut=b(d.put),c.revertClone=d.revertClone,a.group=c};a.prototype={constructor:a,_onTapStart:function(a){var b,d=this,e=this.el,f=this.options,g=f.preventOnFilter,h=a.type,i=a.touches&&a.touches[0],j=(i||a).target,l=a.target.shadowRoot&&a.path&&a.path[0]||j,m=f.filter;if(v(e),!w&&!(/mousedown|pointerdown/.test(h)&&0!==a.button||f.disabled)&&(j=c(j,f.draggable,e),j&&C!==j)){if(b=q(j,f.draggable),"function"==typeof m){if(m.call(this,a,j,this))return k(d,l,"filter",j,e,b),void(g&&a.preventDefault())}else if(m&&(m=m.split(",").some(function(a){if(a=c(l,a.trim(),e))return k(d,a,"filter",j,e,b),!0})))return void(g&&a.preventDefault());f.handle&&!c(l,f.handle,e)||this._prepareDragStart(a,i,j,b)}},_prepareDragStart:function(a,b,c,d){var e,g=this,i=g.el,l=g.options,n=i.ownerDocument;c&&!w&&c.parentNode===i&&(N=a,A=i,w=c,x=w.parentNode,B=w.nextSibling,C=c,L=l.group,J=d,this._lastX=(b||a).clientX,this._lastY=(b||a).clientY,w.style["will-change"]="transform",e=function(){g._disableDelayedDrag(),w.draggable=g.nativeDraggable,h(w,l.chosenClass,!0),g._triggerDragStart(a,b),k(g,A,"choose",w,A,J)},l.ignore.split(",").forEach(function(a){j(w,a.trim(),m)}),f(n,"mouseup",g._onDrop),f(n,"touchend",g._onDrop),f(n,"touchcancel",g._onDrop),f(n,"pointercancel",g._onDrop),f(n,"selectstart",g),l.delay?(f(n,"mouseup",g._disableDelayedDrag),f(n,"touchend",g._disableDelayedDrag),f(n,"touchcancel",g._disableDelayedDrag),f(n,"mousemove",g._disableDelayedDrag),f(n,"touchmove",g._disableDelayedDrag),f(n,"pointermove",g._disableDelayedDrag),g._dragStartTimer=setTimeout(e,l.delay)):e())},_disableDelayedDrag:function(){var a=this.el.ownerDocument;clearTimeout(this._dragStartTimer),g(a,"mouseup",this._disableDelayedDrag),g(a,"touchend",this._disableDelayedDrag),g(a,"touchcancel",this._disableDelayedDrag),g(a,"mousemove",this._disableDelayedDrag),g(a,"touchmove",this._disableDelayedDrag),g(a,"pointermove",this._disableDelayedDrag)},_triggerDragStart:function(a,b){b=b||("touch"==a.pointerType?a:null),b?(N={target:w,clientX:b.clientX,clientY:b.clientY},this._onDragStart(N,"touch")):this.nativeDraggable?(f(w,"dragend",this),f(A,"dragstart",this._onDragStart)):this._onDragStart(N,!0);try{V.selection?setTimeout(function(){V.selection.empty()}):window.getSelection().removeAllRanges()}catch(a){}},_dragStarted:function(){if(A&&w){var b=this.options;h(w,b.ghostClass,!0),h(w,b.dragClass,!1),a.active=this,k(this,A,"start",w,A,J)}else this._nulling()},_emulateDragOver:function(){if(O){if(this._lastX===O.clientX&&this._lastY===O.clientY)return;this._lastX=O.clientX,this._lastY=O.clientY,_||i(y,"display","none");var a=V.elementFromPoint(O.clientX,O.clientY),b=a,c=ea.length;if(b)do{if(b[T]){for(;c--;)ea[c]({clientX:O.clientX,clientY:O.clientY,target:a,rootEl:b});break}a=b}while(b=b.parentNode);_||i(y,"display","")}},_onTouchMove:function(b){if(N){var c=this.options,d=c.fallbackTolerance,e=c.fallbackOffset,f=b.touches?b.touches[0]:b,g=f.clientX-N.clientX+e.x,h=f.clientY-N.clientY+e.y,j=b.touches?"translate3d("+g+"px,"+h+"px,0)":"translate("+g+"px,"+h+"px)";if(!a.active){if(d&&ca(ba(f.clientX-this._lastX),ba(f.clientY-this._lastY))<d)return;this._dragStarted()}this._appendGhost(),P=!0,O=f,i(y,"webkitTransform",j),i(y,"mozTransform",j),i(y,"msTransform",j),i(y,"transform",j),b.preventDefault()}},_appendGhost:function(){if(!y){var a,b=w.getBoundingClientRect(),c=i(w),d=this.options;y=w.cloneNode(!0),h(y,d.ghostClass,!1),h(y,d.fallbackClass,!0),h(y,d.dragClass,!0),i(y,"top",b.top-W(c.marginTop,10)),i(y,"left",b.left-W(c.marginLeft,10)),i(y,"width",b.width),i(y,"height",b.height),i(y,"opacity","0.8"),i(y,"position","fixed"),i(y,"zIndex","100000"),i(y,"pointerEvents","none"),d.fallbackOnBody&&V.body.appendChild(y)||A.appendChild(y),a=y.getBoundingClientRect(),i(y,"width",2*b.width-a.width),i(y,"height",2*b.height-a.height)}},_onDragStart:function(a,b){var c=a.dataTransfer,d=this.options;this._offUpEvents(),L.checkPull(this,this,w,a)&&(z=u(w),z.draggable=!1,z.style["will-change"]="",i(z,"display","none"),h(z,this.options.chosenClass,!1),A.insertBefore(z,w),k(this,A,"clone",w)),h(w,d.dragClass,!0),b?("touch"===b?(f(V,"touchmove",this._onTouchMove),f(V,"touchend",this._onDrop),f(V,"touchcancel",this._onDrop),f(V,"pointermove",this._onTouchMove),f(V,"pointerup",this._onDrop)):(f(V,"mousemove",this._onTouchMove),f(V,"mouseup",this._onDrop)),this._loopId=setInterval(this._emulateDragOver,50)):(c&&(c.effectAllowed="move",d.setData&&d.setData.call(this,c,w)),f(V,"drop",this),setTimeout(this._dragStarted,0))},_onDragOver:function(d){var e,f,g,h,j=this.el,k=this.options,m=k.group,p=a.active,q=L===m,r=!1,s=k.sort;if(void 0!==d.preventDefault&&(d.preventDefault(),!k.dragoverBubble&&d.stopPropagation()),!w.animated&&(P=!0,p&&!k.disabled&&(q?s||(h=!A.contains(w)):M===this||(p.lastPullMode=L.checkPull(this,p,w,d))&&m.checkPut(this,p,w,d))&&(void 0===d.rootEl||d.rootEl===this.el))){if(fa(d,k,this.el),aa)return;if(e=c(d.target,k.draggable,j),f=w.getBoundingClientRect(),M!==this&&(M=this,r=!0),h)return b(p,!0),x=A,void(z||B?A.insertBefore(w,z||B):s||A.appendChild(w));if(0===j.children.length||j.children[0]===y||j===d.target&&o(j,d)){if(0!==j.children.length&&j.children[0]!==y&&j===d.target&&(e=j.lastElementChild),e){if(e.animated)return;g=e.getBoundingClientRect()}b(p,q),l(A,j,w,f,e,g,d)!==!1&&(w.contains(j)||(j.appendChild(w),x=j),this._animate(f,w),e&&this._animate(g,e))}else if(e&&!e.animated&&e!==w&&void 0!==e.parentNode[T]){G!==e&&(G=e,H=i(e),I=i(e.parentNode)),g=e.getBoundingClientRect();var t=g.right-g.left,u=g.bottom-g.top,v=S.test(H.cssFloat+H.display)||"flex"==I.display&&0===I["flex-direction"].indexOf("row"),C=e.offsetWidth>w.offsetWidth,D=e.offsetHeight>w.offsetHeight,E=(v?(d.clientX-g.left)/t:(d.clientY-g.top)/u)>.5,F=e.nextElementSibling,J=!1;if(v){var K=w.offsetTop,N=e.offsetTop;J=K===N?e.previousElementSibling===w&&!C||E&&C:e.previousElementSibling===w||w.previousElementSibling===e?(d.clientY-g.top)/u>.5:N>K}else r||(J=F!==w&&!D||E&&D);var O=l(A,j,w,f,e,g,d,J);O!==!1&&(1!==O&&O!==-1||(J=1===O),aa=!0,setTimeout(n,30),b(p,q),w.contains(j)||(J&&!F?j.appendChild(w):e.parentNode.insertBefore(w,J?F:e)),x=w.parentNode,this._animate(f,w),this._animate(g,e))}}},_animate:function(a,b){var c=this.options.animation;if(c){var d=b.getBoundingClientRect();1===a.nodeType&&(a=a.getBoundingClientRect()),i(b,"transition","none"),i(b,"transform","translate3d("+(a.left-d.left)+"px,"+(a.top-d.top)+"px,0)"),b.offsetWidth,i(b,"transition","all "+c+"ms"),i(b,"transform","translate3d(0,0,0)"),clearTimeout(b.animated),b.animated=setTimeout(function(){i(b,"transition",""),i(b,"transform",""),b.animated=!1},c)}},_offUpEvents:function(){var a=this.el.ownerDocument;g(V,"touchmove",this._onTouchMove),g(V,"pointermove",this._onTouchMove),g(a,"mouseup",this._onDrop),g(a,"touchend",this._onDrop),g(a,"pointerup",this._onDrop),g(a,"touchcancel",this._onDrop),g(a,"pointercancel",this._onDrop),g(a,"selectstart",this)},_onDrop:function(b){var c=this.el,d=this.options;clearInterval(this._loopId),clearInterval(Q.pid),clearTimeout(this._dragStartTimer),g(V,"mousemove",this._onTouchMove),this.nativeDraggable&&(g(V,"drop",this),g(c,"dragstart",this._onDragStart)),this._offUpEvents(),b&&(P&&(b.preventDefault(),!d.dropBubble&&b.stopPropagation()),y&&y.parentNode&&y.parentNode.removeChild(y),A!==x&&"clone"===a.active.lastPullMode||z&&z.parentNode&&z.parentNode.removeChild(z),w&&(this.nativeDraggable&&g(w,"dragend",this),m(w),w.style["will-change"]="",h(w,this.options.ghostClass,!1),h(w,this.options.chosenClass,!1),k(this,A,"unchoose",w,A,J),A!==x?(K=q(w,d.draggable),K>=0&&(k(null,x,"add",w,A,J,K),k(this,A,"remove",w,A,J,K),k(null,x,"sort",w,A,J,K),k(this,A,"sort",w,A,J,K))):w.nextSibling!==B&&(K=q(w,d.draggable),K>=0&&(k(this,A,"update",w,A,J,K),k(this,A,"sort",w,A,J,K))),a.active&&(null!=K&&K!==-1||(K=J),k(this,A,"end",w,A,J,K),this.save()))),this._nulling()},_nulling:function(){A=w=x=y=B=z=C=D=E=N=O=P=K=G=H=M=L=a.active=null,da.forEach(function(a){a.checked=!0}),da.length=0},handleEvent:function(a){switch(a.type){case"drop":case"dragend":this._onDrop(a);break;case"dragover":case"dragenter":w&&(this._onDragOver(a),e(a));break;case"selectstart":a.preventDefault()}},toArray:function(){for(var a,b=[],d=this.el.children,e=0,f=d.length,g=this.options;e<f;e++)a=d[e],c(a,g.draggable,this.el)&&b.push(a.getAttribute(g.dataIdAttr)||p(a));return b},sort:function(a){var b={},d=this.el;this.toArray().forEach(function(a,e){var f=d.children[e];c(f,this.options.draggable,d)&&(b[a]=f)},this),a.forEach(function(a){b[a]&&(d.removeChild(b[a]),d.appendChild(b[a]))})},save:function(){var a=this.options.store;a&&a.set(this)},closest:function(a,b){return c(a,b||this.options.draggable,this.el)},option:function(a,b){var c=this.options;return void 0===b?c[a]:(c[a]=b,void("group"===a&&ga(c)))},destroy:function(){var a=this.el;a[T]=null,g(a,"mousedown",this._onTapStart),g(a,"touchstart",this._onTapStart),g(a,"pointerdown",this._onTapStart),this.nativeDraggable&&(g(a,"dragover",this),g(a,"dragenter",this)),Array.prototype.forEach.call(a.querySelectorAll("[draggable]"),function(a){a.removeAttribute("draggable")}),ea.splice(ea.indexOf(this._onDragOver),1),this._onDrop(),this.el=a=null}},f(V,"touchmove",function(b){a.active&&b.preventDefault()});try{window.addEventListener("test",null,Object.defineProperty({},"passive",{get:function(){Z={capture:!1,passive:!1}}}))}catch(a){}return a.utils={on:f,off:g,css:i,find:j,is:function(a,b){return!!c(a,b,a)},extend:t,throttle:s,closest:c,toggleClass:h,clone:u,index:q},a.create=function(b,c){return new a(b,c)},a.version="1.6.1",a});
@@ -0,0 +1,5 @@
1
+ en:
2
+ simple_form_nested_fields:
3
+ links:
4
+ add: 'Add %{model_name}'
5
+ remove: 'Remove'
@@ -0,0 +1,17 @@
1
+ require 'simple_form'
2
+
3
+ require 'rails'
4
+
5
+ require 'simple_form_nested_fields/version'
6
+
7
+ require 'simple_form_nested_fields/action_view_extension'
8
+ require 'simple_form_nested_fields/nested_fields_builder'
9
+ require 'simple_form_nested_fields/railtie' if defined?(Rails)
10
+
11
+ I18n.load_path += Dir.glob(File.join(File.dirname(__FILE__), 'config', 'locales', '*.yml'))
12
+
13
+ module SimpleFormNestedFields
14
+ def self.asset_path
15
+ File.expand_path('assets/javascripts', __dir__)
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module SimpleFormNestedFields
2
+ module ActionViewExtension
3
+ module Builder
4
+ def nested_fields_for(record_name, record_object = nil, options = {}, &block)
5
+ SimpleFormNestedFields::NestedFieldsBuilder.new(self, @template, record_name, record_object, options).nested_fields_for(&block)
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ module ActionView::Helpers
12
+ class FormBuilder
13
+ include SimpleFormNestedFields::ActionViewExtension::Builder
14
+ end
15
+ end
@@ -0,0 +1,120 @@
1
+ module SimpleFormNestedFields
2
+ class NestedFieldsBuilder
3
+ extend Forwardable
4
+
5
+ BASE_DOM_CLASS = 'simple_form_nested_fields'.freeze
6
+ CHILD_INDEX_STRING = '__INDEX_PLACEHOLDER__'.freeze
7
+
8
+ attr_accessor :builder, :template, :record_name, :record_object, :options
9
+
10
+ def initialize(builder, template, record_name, record_object, options = {})
11
+ @builder = builder
12
+ @template = template
13
+ @record_name = record_name
14
+ @record_object = record_object
15
+ @options = options
16
+ end
17
+
18
+ def_delegators :builder, :object, :object_name, :simple_fields_for
19
+ def_delegators :template, :concat, :content_tag, :hidden_field_tag, :link_to, :render
20
+
21
+ def nested_fields_for
22
+ dom_class = [bem_class, bem_class(m: record_name)]
23
+ dom_class << bem_class(m: :sortable) if is_sortable?
24
+
25
+ content_tag(:div, class: dom_class) do
26
+ concat nested_fields_title
27
+ concat nested_fields_items
28
+ concat nested_fields_links
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def is_sortable?
35
+ options[:sortable] == true
36
+ end
37
+
38
+ def partial_path
39
+ options.fetch(:partial, File.join(object.model_name.collection, relation.klass.model_name.collection, 'fields'))
40
+ end
41
+
42
+ def relation
43
+ object.reflect_on_association(record_name)
44
+ end
45
+
46
+ def nested_fields_title
47
+ dom_class = bem_class(e: :title)
48
+ title = relation.klass.model_name.human.pluralize
49
+ content_tag(:div, title, class: dom_class).html_safe
50
+ end
51
+
52
+ def nested_fields_items
53
+ content_tag(:div, class: bem_class(e: :items)) do
54
+ simple_fields_for(record_name, record_object, options) do |fields|
55
+ dom_class = bem_class(e: :item, m: relation.klass)
56
+ dom_data = { id: fields.object.id.to_s }
57
+
58
+ content_tag(:div, class: dom_class, data: dom_data) do
59
+ concat nested_fields_item_handle
60
+ concat render(partial_path, fields: fields)
61
+ concat link_to_remove(fields)
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def nested_fields_links
68
+ dom_class = bem_class(e: :links)
69
+ content_tag(:div, link_to_add, class: dom_class).html_safe
70
+ end
71
+
72
+ def link_to_add
73
+ label = options.fetch(:label_add, ::I18n.t(:add, scope: %i[simple_form_nested_fields links], model_name: relation.klass.model_name.human))
74
+ dom_class = [bem_class(e: :link), bem_class(e: :link, m: :add)]
75
+ dom_data = { template: CGI.escapeHTML(nested_fields_template).html_safe, turbolinks: 'false' }
76
+ link_to(label, '#', class: dom_class, data: dom_data).html_safe
77
+ end
78
+
79
+ def nested_fields_item_handle
80
+ return unless is_sortable?
81
+ dom_class = bem_class(e: :item_handle)
82
+ content_tag(:div, nil, class: dom_class).html_safe
83
+ end
84
+
85
+ def nested_fields_template
86
+ dom_class = bem_class(e: :item, m: relation.klass)
87
+ content_tag :div, nested_fields_template_string, class: dom_class
88
+ end
89
+
90
+ def nested_fields_template_string
91
+ simple_fields_for(record_name, relation.klass.new, child_index: CHILD_INDEX_STRING) do |fields|
92
+ nested_fields_item_handle.to_s.html_safe +
93
+ render(partial_path, fields: fields).html_safe +
94
+ link_to_remove(fields)
95
+ end.html_safe
96
+ end
97
+
98
+ def destroy_field_tag(fields)
99
+ return if fields.object.new_record?
100
+ hidden_field_tag("#{fields.object_name}[_destroy]", fields.object._destroy).html_safe
101
+ end
102
+
103
+ def link_to_remove(fields, options = {})
104
+ label = options.fetch(:label, ::I18n.t(:remove, scope: %i[simple_form_nested_fields links]))
105
+ dom_class = [bem_class(e: :link), bem_class(e: :link, m: :remove)]
106
+ dom_data = { turbolinks: 'false' }
107
+ [
108
+ destroy_field_tag(fields),
109
+ link_to(label, '#', class: dom_class, data: dom_data)
110
+ ].reject(&:blank?).join.html_safe
111
+ end
112
+
113
+ def bem_class(e: nil, m: nil)
114
+ res = [BASE_DOM_CLASS]
115
+ res << "__#{e}" if e.present?
116
+ res << "__#{m}" if m.present?
117
+ res.join
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,9 @@
1
+ require 'rails'
2
+
3
+ module SimpleFormNestedFields
4
+ class Railtie < Rails::Railtie
5
+ initializer 'simple_form_dependent_fields.assets' do |app|
6
+ app.config.assets.paths << SimpleFormNestedFields.asset_path
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleFormNestedFields
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "simple_form_nested_fields",
3
+ "version": "0.1.0",
4
+ "description": "…",
5
+ "main": "package/dist/index.js",
6
+ "repository": "https://github.com/tomasc/simple_form_nested_fields.git",
7
+ "author": "Tomáš Celizna <tomas.celizna@gmail.com>",
8
+ "license": "MIT",
9
+ "files": [
10
+ "package"
11
+ ],
12
+ "scripts": {
13
+ "build": "webpack"
14
+ },
15
+ "devDependencies": {
16
+ "babel-core": "^6.26.0",
17
+ "babel-loader": "^7.1.2",
18
+ "babel-preset-env": "^1.6.0",
19
+ "babel-preset-es2015": "^6.24.1",
20
+ "coffee-loader": "^0.9.0",
21
+ "coffeescript": "^2.0.2",
22
+ "css-loader": "^0.28.11",
23
+ "extract-text-webpack-plugin": "^3.0.2",
24
+ "jquery": "^3.2.1",
25
+ "jquery-bridget": "^2.0.1",
26
+ "jquery-ujs": "^1.2.2",
27
+ "node-sass": "^4.8.3",
28
+ "sass-loader": "^6.0.7",
29
+ "style-loader": "^0.20.3",
30
+ "webpack": "^3.8.1",
31
+ "webpack-dev-server": "2.11.2",
32
+ "webpack-merge": "^4.1.0"
33
+ },
34
+ "dependencies": {
35
+ "sortablejs": "^1.7.0"
36
+ },
37
+ "peerDependencies": {
38
+ "jquery": "^3.2.1"
39
+ }
40
+ }
@@ -0,0 +1,1924 @@
1
+ (function webpackUniversalModuleDefinition(root, factory) {
2
+ if(typeof exports === 'object' && typeof module === 'object')
3
+ module.exports = factory(require("jquery"));
4
+ else if(typeof define === 'function' && define.amd)
5
+ define("@tomasc/simple_form_nested_fields", ["jquery"], factory);
6
+ else if(typeof exports === 'object')
7
+ exports["@tomasc/simple_form_nested_fields"] = factory(require("jquery"));
8
+ else
9
+ root["@tomasc/simple_form_nested_fields"] = factory(root["jquery"]);
10
+ })(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__) {
11
+ return /******/ (function(modules) { // webpackBootstrap
12
+ /******/ // The module cache
13
+ /******/ var installedModules = {};
14
+ /******/
15
+ /******/ // The require function
16
+ /******/ function __webpack_require__(moduleId) {
17
+ /******/
18
+ /******/ // Check if module is in cache
19
+ /******/ if(installedModules[moduleId]) {
20
+ /******/ return installedModules[moduleId].exports;
21
+ /******/ }
22
+ /******/ // Create a new module (and put it into the cache)
23
+ /******/ var module = installedModules[moduleId] = {
24
+ /******/ i: moduleId,
25
+ /******/ l: false,
26
+ /******/ exports: {}
27
+ /******/ };
28
+ /******/
29
+ /******/ // Execute the module function
30
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31
+ /******/
32
+ /******/ // Flag the module as loaded
33
+ /******/ module.l = true;
34
+ /******/
35
+ /******/ // Return the exports of the module
36
+ /******/ return module.exports;
37
+ /******/ }
38
+ /******/
39
+ /******/
40
+ /******/ // expose the modules object (__webpack_modules__)
41
+ /******/ __webpack_require__.m = modules;
42
+ /******/
43
+ /******/ // expose the module cache
44
+ /******/ __webpack_require__.c = installedModules;
45
+ /******/
46
+ /******/ // define getter function for harmony exports
47
+ /******/ __webpack_require__.d = function(exports, name, getter) {
48
+ /******/ if(!__webpack_require__.o(exports, name)) {
49
+ /******/ Object.defineProperty(exports, name, {
50
+ /******/ configurable: false,
51
+ /******/ enumerable: true,
52
+ /******/ get: getter
53
+ /******/ });
54
+ /******/ }
55
+ /******/ };
56
+ /******/
57
+ /******/ // getDefaultExport function for compatibility with non-harmony modules
58
+ /******/ __webpack_require__.n = function(module) {
59
+ /******/ var getter = module && module.__esModule ?
60
+ /******/ function getDefault() { return module['default']; } :
61
+ /******/ function getModuleExports() { return module; };
62
+ /******/ __webpack_require__.d(getter, 'a', getter);
63
+ /******/ return getter;
64
+ /******/ };
65
+ /******/
66
+ /******/ // Object.prototype.hasOwnProperty.call
67
+ /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
68
+ /******/
69
+ /******/ // __webpack_public_path__
70
+ /******/ __webpack_require__.p = "";
71
+ /******/
72
+ /******/ // Load entry module and return exports
73
+ /******/ return __webpack_require__(__webpack_require__.s = 1);
74
+ /******/ })
75
+ /************************************************************************/
76
+ /******/ ([
77
+ /* 0 */
78
+ /***/ (function(module, exports) {
79
+
80
+ module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
81
+
82
+ /***/ }),
83
+ /* 1 */
84
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
85
+
86
+ "use strict";
87
+ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
88
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__links__ = __webpack_require__(2);
89
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__links___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__links__);
90
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__sortable__ = __webpack_require__(3);
91
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__sortable___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__sortable__);
92
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__simple_form_nested_fields__ = __webpack_require__(5);
93
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__simple_form_nested_fields___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2__simple_form_nested_fields__);
94
+
95
+
96
+
97
+
98
+
99
+ /***/ }),
100
+ /* 2 */
101
+ /***/ (function(module, exports, __webpack_require__) {
102
+
103
+ "use strict";
104
+ /* WEBPACK VAR INJECTION */(function(jQuery) {
105
+
106
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
107
+
108
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
109
+
110
+ (function ($, window, document) {
111
+ var Plugin, defaults, pluginName;
112
+ pluginName = 'SimpleFormNestedFields__Links';
113
+ defaults = {
114
+ debug: false,
115
+ new_item_class_name: 'simple_form_nested_fields__item__new',
116
+ regexp: new RegExp("__INDEX_PLACEHOLDER__", 'g') // regexp: new RegExp("<%= Modulor::NestedFieldsBuilder::CHILD_INDEX_STRING %>", 'g')
117
+ };
118
+ Plugin = function () {
119
+ function Plugin(element, options) {
120
+ _classCallCheck(this, Plugin);
121
+
122
+ this.element = element;
123
+ this.options = $.extend({}, defaults, options);
124
+ this._defaults = defaults;
125
+ this.$element = $(this.element);
126
+ this.init();
127
+ }
128
+
129
+ _createClass(Plugin, [{
130
+ key: 'init',
131
+ value: function init() {
132
+ var _this = this;
133
+
134
+ return this.$element.on('click.' + this._name, '.simple_form_nested_fields__link', function (e) {
135
+ var link;
136
+ e.preventDefault();
137
+ link = e.target;
138
+ switch (false) {
139
+ case !link.classList.contains('simple_form_nested_fields__link__add'):
140
+ return _this.add_new_item(link);
141
+ case !link.classList.contains('simple_form_nested_fields__link__remove'):
142
+ return _this.remove_item(link);
143
+ }
144
+ });
145
+ }
146
+ }, {
147
+ key: 'destroy',
148
+ value: function destroy() {
149
+ return this.$element.off('click.' + this._name, '.simple_form_nested_fields__link__add');
150
+ }
151
+ }, {
152
+ key: 'get_index',
153
+ value: function get_index() {
154
+ return new Date().getTime();
155
+ }
156
+ }, {
157
+ key: 'get_template',
158
+ value: function get_template(link) {
159
+ return $(link).data('template').replace(this.options.regexp, this.get_index());
160
+ }
161
+ }, {
162
+ key: 'get_items_container',
163
+ value: function get_items_container() {
164
+ return this.$element.find('.simple_form_nested_fields__items');
165
+ }
166
+ }, {
167
+ key: 'add_new_item',
168
+ value: function add_new_item(link) {
169
+ var $template;
170
+ $template = $(this.get_template(link));
171
+ $template.addClass(this.options.new_item_class_name);
172
+ return this.get_items_container().append($template);
173
+ }
174
+ }, {
175
+ key: 'remove_item',
176
+ value: function remove_item(link) {
177
+ var $item;
178
+ $item = $(link).closest('.simple_form_nested_fields__item');
179
+ if ($item.hasClass(this.options.new_item_class_name)) {
180
+ return $item.remove();
181
+ } else {
182
+ $item.find('input[type=hidden]').val('1');
183
+ return $item.hide();
184
+ }
185
+ }
186
+ }]);
187
+
188
+ return Plugin;
189
+ }();
190
+ // A really lightweight plugin wrapper around the constructor,
191
+ // preventing against multiple instantiations
192
+ return $.fn[pluginName] = function (options) {
193
+ return this.each(function () {
194
+ if (!$.data(this, 'plugin_' + pluginName)) {
195
+ return $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
196
+ }
197
+ });
198
+ };
199
+ })(jQuery, window, document);
200
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
201
+
202
+ /***/ }),
203
+ /* 3 */
204
+ /***/ (function(module, exports, __webpack_require__) {
205
+
206
+ "use strict";
207
+ /* WEBPACK VAR INJECTION */(function(jQuery) {
208
+
209
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
210
+
211
+ var _sortablejs = __webpack_require__(4);
212
+
213
+ var _sortablejs2 = _interopRequireDefault(_sortablejs);
214
+
215
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
216
+
217
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
218
+
219
+ (function ($, window, document) {
220
+ var Plugin, defaults, pluginName;
221
+ pluginName = 'SimpleFormNestedFields__Sortable';
222
+ defaults = {
223
+ debug: false
224
+ };
225
+ Plugin = function () {
226
+ function Plugin(element, options) {
227
+ _classCallCheck(this, Plugin);
228
+
229
+ this.element = element;
230
+ this.$element = $(this.element);
231
+ this.$simple_form_nested_fields = this.$element.data('plugin_SimpleFormNestedFields');
232
+ this.options = $.extend({}, defaults, options);
233
+ this._defaults = defaults;
234
+ this._name = pluginName;
235
+ this.init();
236
+ }
237
+
238
+ _createClass(Plugin, [{
239
+ key: 'init',
240
+ value: function init() {
241
+ var _this = this;
242
+
243
+ if (this.sortable) {
244
+ return;
245
+ }
246
+ this.sortable = new _sortablejs2.default(this.get_items_container()[0], {
247
+ animation: 150,
248
+ draggable: '.simple_form_nested_fields__item',
249
+ ghostClass: '.simple_form_nested_fields__ghost',
250
+ handle: '.simple_form_nested_fields__item_handle',
251
+ // TODO: onAdd is not being triggered?
252
+ onAdd: function onAdd(e) {
253
+ return _this.update_item_positions();
254
+ },
255
+ onUpdate: function onUpdate(e) {
256
+ return _this.update_item_positions();
257
+ },
258
+ onRemove: function onRemove(e) {
259
+ return _this.update_item_positions();
260
+ }
261
+ });
262
+ this.$element.on('update_item_positions.' + this._name, function (e) {
263
+ e.stopPropagation();
264
+ return _this.update_item_positions();
265
+ });
266
+ return this.update_item_positions();
267
+ }
268
+ }, {
269
+ key: 'destroy',
270
+ value: function destroy() {
271
+ if (this.sortable) {
272
+ return this.sortable.destroy();
273
+ }
274
+ }
275
+ }, {
276
+ key: 'update_item_positions',
277
+ value: function update_item_positions() {
278
+ return this.get_items().each(function (i, el) {
279
+ return $(el).find('input[name*="position"]').val(i + 1);
280
+ });
281
+ }
282
+ }, {
283
+ key: 'get_items',
284
+ value: function get_items() {
285
+ return this.get_items_container().find('.simple_form_nested_fields__item');
286
+ }
287
+ }, {
288
+ key: 'get_items_container',
289
+ value: function get_items_container() {
290
+ return this.$element.find('.simple_form_nested_fields__items');
291
+ }
292
+ }]);
293
+
294
+ return Plugin;
295
+ }();
296
+ // A really lightweight plugin wrapper around the constructor,
297
+ // preventing against multiple instantiations
298
+ return $.fn[pluginName] = function (options) {
299
+ return this.each(function () {
300
+ if (!$.data(this, 'plugin_' + pluginName)) {
301
+ return $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
302
+ }
303
+ });
304
+ };
305
+ })(jQuery, window, document);
306
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
307
+
308
+ /***/ }),
309
+ /* 4 */
310
+ /***/ (function(module, exports, __webpack_require__) {
311
+
312
+ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/**!
313
+ * Sortable
314
+ * @author RubaXa <trash@rubaxa.org>
315
+ * @license MIT
316
+ */
317
+
318
+ (function sortableModule(factory) {
319
+ "use strict";
320
+
321
+ if (true) {
322
+ !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
323
+ __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
324
+ (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :
325
+ __WEBPACK_AMD_DEFINE_FACTORY__),
326
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
327
+ }
328
+ else if (typeof module != "undefined" && typeof module.exports != "undefined") {
329
+ module.exports = factory();
330
+ }
331
+ else {
332
+ /* jshint sub:true */
333
+ window["Sortable"] = factory();
334
+ }
335
+ })(function sortableFactory() {
336
+ "use strict";
337
+
338
+ if (typeof window === "undefined" || !window.document) {
339
+ return function sortableError() {
340
+ throw new Error("Sortable.js requires a window with a document");
341
+ };
342
+ }
343
+
344
+ var dragEl,
345
+ parentEl,
346
+ ghostEl,
347
+ cloneEl,
348
+ rootEl,
349
+ nextEl,
350
+ lastDownEl,
351
+
352
+ scrollEl,
353
+ scrollParentEl,
354
+ scrollCustomFn,
355
+
356
+ lastEl,
357
+ lastCSS,
358
+ lastParentCSS,
359
+
360
+ oldIndex,
361
+ newIndex,
362
+
363
+ activeGroup,
364
+ putSortable,
365
+
366
+ autoScroll = {},
367
+
368
+ tapEvt,
369
+ touchEvt,
370
+
371
+ moved,
372
+
373
+ /** @const */
374
+ R_SPACE = /\s+/g,
375
+ R_FLOAT = /left|right|inline/,
376
+
377
+ expando = 'Sortable' + (new Date).getTime(),
378
+
379
+ win = window,
380
+ document = win.document,
381
+ parseInt = win.parseInt,
382
+ setTimeout = win.setTimeout,
383
+
384
+ $ = win.jQuery || win.Zepto,
385
+ Polymer = win.Polymer,
386
+
387
+ captureMode = false,
388
+ passiveMode = false,
389
+
390
+ supportDraggable = ('draggable' in document.createElement('div')),
391
+ supportCssPointerEvents = (function (el) {
392
+ // false when IE11
393
+ if (!!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\.|msie)/i)) {
394
+ return false;
395
+ }
396
+ el = document.createElement('x');
397
+ el.style.cssText = 'pointer-events:auto';
398
+ return el.style.pointerEvents === 'auto';
399
+ })(),
400
+
401
+ _silent = false,
402
+
403
+ abs = Math.abs,
404
+ min = Math.min,
405
+
406
+ savedInputChecked = [],
407
+ touchDragOverListeners = [],
408
+
409
+ _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {
410
+ // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
411
+ if (rootEl && options.scroll) {
412
+ var _this = rootEl[expando],
413
+ el,
414
+ rect,
415
+ sens = options.scrollSensitivity,
416
+ speed = options.scrollSpeed,
417
+
418
+ x = evt.clientX,
419
+ y = evt.clientY,
420
+
421
+ winWidth = window.innerWidth,
422
+ winHeight = window.innerHeight,
423
+
424
+ vx,
425
+ vy,
426
+
427
+ scrollOffsetX,
428
+ scrollOffsetY
429
+ ;
430
+
431
+ // Delect scrollEl
432
+ if (scrollParentEl !== rootEl) {
433
+ scrollEl = options.scroll;
434
+ scrollParentEl = rootEl;
435
+ scrollCustomFn = options.scrollFn;
436
+
437
+ if (scrollEl === true) {
438
+ scrollEl = rootEl;
439
+
440
+ do {
441
+ if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
442
+ (scrollEl.offsetHeight < scrollEl.scrollHeight)
443
+ ) {
444
+ break;
445
+ }
446
+ /* jshint boss:true */
447
+ } while (scrollEl = scrollEl.parentNode);
448
+ }
449
+ }
450
+
451
+ if (scrollEl) {
452
+ el = scrollEl;
453
+ rect = scrollEl.getBoundingClientRect();
454
+ vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
455
+ vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
456
+ }
457
+
458
+
459
+ if (!(vx || vy)) {
460
+ vx = (winWidth - x <= sens) - (x <= sens);
461
+ vy = (winHeight - y <= sens) - (y <= sens);
462
+
463
+ /* jshint expr:true */
464
+ (vx || vy) && (el = win);
465
+ }
466
+
467
+
468
+ if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
469
+ autoScroll.el = el;
470
+ autoScroll.vx = vx;
471
+ autoScroll.vy = vy;
472
+
473
+ clearInterval(autoScroll.pid);
474
+
475
+ if (el) {
476
+ autoScroll.pid = setInterval(function () {
477
+ scrollOffsetY = vy ? vy * speed : 0;
478
+ scrollOffsetX = vx ? vx * speed : 0;
479
+
480
+ if ('function' === typeof(scrollCustomFn)) {
481
+ return scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt);
482
+ }
483
+
484
+ if (el === win) {
485
+ win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY);
486
+ } else {
487
+ el.scrollTop += scrollOffsetY;
488
+ el.scrollLeft += scrollOffsetX;
489
+ }
490
+ }, 24);
491
+ }
492
+ }
493
+ }
494
+ }, 30),
495
+
496
+ _prepareGroup = function (options) {
497
+ function toFn(value, pull) {
498
+ if (value === void 0 || value === true) {
499
+ value = group.name;
500
+ }
501
+
502
+ if (typeof value === 'function') {
503
+ return value;
504
+ } else {
505
+ return function (to, from) {
506
+ var fromGroup = from.options.group.name;
507
+
508
+ return pull
509
+ ? value
510
+ : value && (value.join
511
+ ? value.indexOf(fromGroup) > -1
512
+ : (fromGroup == value)
513
+ );
514
+ };
515
+ }
516
+ }
517
+
518
+ var group = {};
519
+ var originalGroup = options.group;
520
+
521
+ if (!originalGroup || typeof originalGroup != 'object') {
522
+ originalGroup = {name: originalGroup};
523
+ }
524
+
525
+ group.name = originalGroup.name;
526
+ group.checkPull = toFn(originalGroup.pull, true);
527
+ group.checkPut = toFn(originalGroup.put);
528
+ group.revertClone = originalGroup.revertClone;
529
+
530
+ options.group = group;
531
+ }
532
+ ;
533
+
534
+ // Detect support a passive mode
535
+ try {
536
+ window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
537
+ get: function () {
538
+ // `false`, because everything starts to work incorrectly and instead of d'n'd,
539
+ // begins the page has scrolled.
540
+ passiveMode = false;
541
+ captureMode = {
542
+ capture: false,
543
+ passive: passiveMode
544
+ };
545
+ }
546
+ }));
547
+ } catch (err) {}
548
+
549
+ /**
550
+ * @class Sortable
551
+ * @param {HTMLElement} el
552
+ * @param {Object} [options]
553
+ */
554
+ function Sortable(el, options) {
555
+ if (!(el && el.nodeType && el.nodeType === 1)) {
556
+ throw 'Sortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);
557
+ }
558
+
559
+ this.el = el; // root element
560
+ this.options = options = _extend({}, options);
561
+
562
+
563
+ // Export instance
564
+ el[expando] = this;
565
+
566
+ // Default options
567
+ var defaults = {
568
+ group: Math.random(),
569
+ sort: true,
570
+ disabled: false,
571
+ store: null,
572
+ handle: null,
573
+ scroll: true,
574
+ scrollSensitivity: 30,
575
+ scrollSpeed: 10,
576
+ draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
577
+ ghostClass: 'sortable-ghost',
578
+ chosenClass: 'sortable-chosen',
579
+ dragClass: 'sortable-drag',
580
+ ignore: 'a, img',
581
+ filter: null,
582
+ preventOnFilter: true,
583
+ animation: 0,
584
+ setData: function (dataTransfer, dragEl) {
585
+ dataTransfer.setData('Text', dragEl.textContent);
586
+ },
587
+ dropBubble: false,
588
+ dragoverBubble: false,
589
+ dataIdAttr: 'data-id',
590
+ delay: 0,
591
+ forceFallback: false,
592
+ fallbackClass: 'sortable-fallback',
593
+ fallbackOnBody: false,
594
+ fallbackTolerance: 0,
595
+ fallbackOffset: {x: 0, y: 0},
596
+ supportPointer: Sortable.supportPointer !== false
597
+ };
598
+
599
+
600
+ // Set default options
601
+ for (var name in defaults) {
602
+ !(name in options) && (options[name] = defaults[name]);
603
+ }
604
+
605
+ _prepareGroup(options);
606
+
607
+ // Bind all private methods
608
+ for (var fn in this) {
609
+ if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
610
+ this[fn] = this[fn].bind(this);
611
+ }
612
+ }
613
+
614
+ // Setup drag mode
615
+ this.nativeDraggable = options.forceFallback ? false : supportDraggable;
616
+
617
+ // Bind events
618
+ _on(el, 'mousedown', this._onTapStart);
619
+ _on(el, 'touchstart', this._onTapStart);
620
+ options.supportPointer && _on(el, 'pointerdown', this._onTapStart);
621
+
622
+ if (this.nativeDraggable) {
623
+ _on(el, 'dragover', this);
624
+ _on(el, 'dragenter', this);
625
+ }
626
+
627
+ touchDragOverListeners.push(this._onDragOver);
628
+
629
+ // Restore sorting
630
+ options.store && this.sort(options.store.get(this));
631
+ }
632
+
633
+
634
+ Sortable.prototype = /** @lends Sortable.prototype */ {
635
+ constructor: Sortable,
636
+
637
+ _onTapStart: function (/** Event|TouchEvent */evt) {
638
+ var _this = this,
639
+ el = this.el,
640
+ options = this.options,
641
+ preventOnFilter = options.preventOnFilter,
642
+ type = evt.type,
643
+ touch = evt.touches && evt.touches[0],
644
+ target = (touch || evt).target,
645
+ originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0]) || target,
646
+ filter = options.filter,
647
+ startIndex;
648
+
649
+ _saveInputCheckedState(el);
650
+
651
+
652
+ // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
653
+ if (dragEl) {
654
+ return;
655
+ }
656
+
657
+ if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
658
+ return; // only left button or enabled
659
+ }
660
+
661
+ // cancel dnd if original target is content editable
662
+ if (originalTarget.isContentEditable) {
663
+ return;
664
+ }
665
+
666
+ target = _closest(target, options.draggable, el);
667
+
668
+ if (!target) {
669
+ return;
670
+ }
671
+
672
+ if (lastDownEl === target) {
673
+ // Ignoring duplicate `down`
674
+ return;
675
+ }
676
+
677
+ // Get the index of the dragged element within its parent
678
+ startIndex = _index(target, options.draggable);
679
+
680
+ // Check filter
681
+ if (typeof filter === 'function') {
682
+ if (filter.call(this, evt, target, this)) {
683
+ _dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex);
684
+ preventOnFilter && evt.preventDefault();
685
+ return; // cancel dnd
686
+ }
687
+ }
688
+ else if (filter) {
689
+ filter = filter.split(',').some(function (criteria) {
690
+ criteria = _closest(originalTarget, criteria.trim(), el);
691
+
692
+ if (criteria) {
693
+ _dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex);
694
+ return true;
695
+ }
696
+ });
697
+
698
+ if (filter) {
699
+ preventOnFilter && evt.preventDefault();
700
+ return; // cancel dnd
701
+ }
702
+ }
703
+
704
+ if (options.handle && !_closest(originalTarget, options.handle, el)) {
705
+ return;
706
+ }
707
+
708
+ // Prepare `dragstart`
709
+ this._prepareDragStart(evt, touch, target, startIndex);
710
+ },
711
+
712
+ _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {
713
+ var _this = this,
714
+ el = _this.el,
715
+ options = _this.options,
716
+ ownerDocument = el.ownerDocument,
717
+ dragStartFn;
718
+
719
+ if (target && !dragEl && (target.parentNode === el)) {
720
+ tapEvt = evt;
721
+
722
+ rootEl = el;
723
+ dragEl = target;
724
+ parentEl = dragEl.parentNode;
725
+ nextEl = dragEl.nextSibling;
726
+ lastDownEl = target;
727
+ activeGroup = options.group;
728
+ oldIndex = startIndex;
729
+
730
+ this._lastX = (touch || evt).clientX;
731
+ this._lastY = (touch || evt).clientY;
732
+
733
+ dragEl.style['will-change'] = 'all';
734
+
735
+ dragStartFn = function () {
736
+ // Delayed drag has been triggered
737
+ // we can re-enable the events: touchmove/mousemove
738
+ _this._disableDelayedDrag();
739
+
740
+ // Make the element draggable
741
+ dragEl.draggable = _this.nativeDraggable;
742
+
743
+ // Chosen item
744
+ _toggleClass(dragEl, options.chosenClass, true);
745
+
746
+ // Bind the events: dragstart/dragend
747
+ _this._triggerDragStart(evt, touch);
748
+
749
+ // Drag start event
750
+ _dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex);
751
+ };
752
+
753
+ // Disable "draggable"
754
+ options.ignore.split(',').forEach(function (criteria) {
755
+ _find(dragEl, criteria.trim(), _disableDraggable);
756
+ });
757
+
758
+ _on(ownerDocument, 'mouseup', _this._onDrop);
759
+ _on(ownerDocument, 'touchend', _this._onDrop);
760
+ _on(ownerDocument, 'touchcancel', _this._onDrop);
761
+ _on(ownerDocument, 'selectstart', _this);
762
+ options.supportPointer && _on(ownerDocument, 'pointercancel', _this._onDrop);
763
+
764
+ if (options.delay) {
765
+ // If the user moves the pointer or let go the click or touch
766
+ // before the delay has been reached:
767
+ // disable the delayed drag
768
+ _on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
769
+ _on(ownerDocument, 'touchend', _this._disableDelayedDrag);
770
+ _on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
771
+ _on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
772
+ _on(ownerDocument, 'touchmove', _this._disableDelayedDrag);
773
+ options.supportPointer && _on(ownerDocument, 'pointermove', _this._disableDelayedDrag);
774
+
775
+ _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
776
+ } else {
777
+ dragStartFn();
778
+ }
779
+
780
+
781
+ }
782
+ },
783
+
784
+ _disableDelayedDrag: function () {
785
+ var ownerDocument = this.el.ownerDocument;
786
+
787
+ clearTimeout(this._dragStartTimer);
788
+ _off(ownerDocument, 'mouseup', this._disableDelayedDrag);
789
+ _off(ownerDocument, 'touchend', this._disableDelayedDrag);
790
+ _off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
791
+ _off(ownerDocument, 'mousemove', this._disableDelayedDrag);
792
+ _off(ownerDocument, 'touchmove', this._disableDelayedDrag);
793
+ _off(ownerDocument, 'pointermove', this._disableDelayedDrag);
794
+ },
795
+
796
+ _triggerDragStart: function (/** Event */evt, /** Touch */touch) {
797
+ touch = touch || (evt.pointerType == 'touch' ? evt : null);
798
+
799
+ if (touch) {
800
+ // Touch device support
801
+ tapEvt = {
802
+ target: dragEl,
803
+ clientX: touch.clientX,
804
+ clientY: touch.clientY
805
+ };
806
+
807
+ this._onDragStart(tapEvt, 'touch');
808
+ }
809
+ else if (!this.nativeDraggable) {
810
+ this._onDragStart(tapEvt, true);
811
+ }
812
+ else {
813
+ _on(dragEl, 'dragend', this);
814
+ _on(rootEl, 'dragstart', this._onDragStart);
815
+ }
816
+
817
+ try {
818
+ if (document.selection) {
819
+ // Timeout neccessary for IE9
820
+ _nextTick(function () {
821
+ document.selection.empty();
822
+ });
823
+ } else {
824
+ window.getSelection().removeAllRanges();
825
+ }
826
+ } catch (err) {
827
+ }
828
+ },
829
+
830
+ _dragStarted: function () {
831
+ if (rootEl && dragEl) {
832
+ var options = this.options;
833
+
834
+ // Apply effect
835
+ _toggleClass(dragEl, options.ghostClass, true);
836
+ _toggleClass(dragEl, options.dragClass, false);
837
+
838
+ Sortable.active = this;
839
+
840
+ // Drag start event
841
+ _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex);
842
+ } else {
843
+ this._nulling();
844
+ }
845
+ },
846
+
847
+ _emulateDragOver: function () {
848
+ if (touchEvt) {
849
+ if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
850
+ return;
851
+ }
852
+
853
+ this._lastX = touchEvt.clientX;
854
+ this._lastY = touchEvt.clientY;
855
+
856
+ if (!supportCssPointerEvents) {
857
+ _css(ghostEl, 'display', 'none');
858
+ }
859
+
860
+ var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
861
+ var parent = target;
862
+ var i = touchDragOverListeners.length;
863
+
864
+ if (target && target.shadowRoot) {
865
+ target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
866
+ parent = target;
867
+ }
868
+
869
+ if (parent) {
870
+ do {
871
+ if (parent[expando]) {
872
+ while (i--) {
873
+ touchDragOverListeners[i]({
874
+ clientX: touchEvt.clientX,
875
+ clientY: touchEvt.clientY,
876
+ target: target,
877
+ rootEl: parent
878
+ });
879
+ }
880
+
881
+ break;
882
+ }
883
+
884
+ target = parent; // store last element
885
+ }
886
+ /* jshint boss:true */
887
+ while (parent = parent.parentNode);
888
+ }
889
+
890
+ if (!supportCssPointerEvents) {
891
+ _css(ghostEl, 'display', '');
892
+ }
893
+ }
894
+ },
895
+
896
+
897
+ _onTouchMove: function (/**TouchEvent*/evt) {
898
+ if (tapEvt) {
899
+ var options = this.options,
900
+ fallbackTolerance = options.fallbackTolerance,
901
+ fallbackOffset = options.fallbackOffset,
902
+ touch = evt.touches ? evt.touches[0] : evt,
903
+ dx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x,
904
+ dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y,
905
+ translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
906
+
907
+ // only set the status to dragging, when we are actually dragging
908
+ if (!Sortable.active) {
909
+ if (fallbackTolerance &&
910
+ min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance
911
+ ) {
912
+ return;
913
+ }
914
+
915
+ this._dragStarted();
916
+ }
917
+
918
+ // as well as creating the ghost element on the document body
919
+ this._appendGhost();
920
+
921
+ moved = true;
922
+ touchEvt = touch;
923
+
924
+ _css(ghostEl, 'webkitTransform', translate3d);
925
+ _css(ghostEl, 'mozTransform', translate3d);
926
+ _css(ghostEl, 'msTransform', translate3d);
927
+ _css(ghostEl, 'transform', translate3d);
928
+
929
+ evt.preventDefault();
930
+ }
931
+ },
932
+
933
+ _appendGhost: function () {
934
+ if (!ghostEl) {
935
+ var rect = dragEl.getBoundingClientRect(),
936
+ css = _css(dragEl),
937
+ options = this.options,
938
+ ghostRect;
939
+
940
+ ghostEl = dragEl.cloneNode(true);
941
+
942
+ _toggleClass(ghostEl, options.ghostClass, false);
943
+ _toggleClass(ghostEl, options.fallbackClass, true);
944
+ _toggleClass(ghostEl, options.dragClass, true);
945
+
946
+ _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
947
+ _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
948
+ _css(ghostEl, 'width', rect.width);
949
+ _css(ghostEl, 'height', rect.height);
950
+ _css(ghostEl, 'opacity', '0.8');
951
+ _css(ghostEl, 'position', 'fixed');
952
+ _css(ghostEl, 'zIndex', '100000');
953
+ _css(ghostEl, 'pointerEvents', 'none');
954
+
955
+ options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);
956
+
957
+ // Fixing dimensions.
958
+ ghostRect = ghostEl.getBoundingClientRect();
959
+ _css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
960
+ _css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
961
+ }
962
+ },
963
+
964
+ _onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
965
+ var _this = this;
966
+ var dataTransfer = evt.dataTransfer;
967
+ var options = _this.options;
968
+
969
+ _this._offUpEvents();
970
+
971
+ if (activeGroup.checkPull(_this, _this, dragEl, evt)) {
972
+ cloneEl = _clone(dragEl);
973
+
974
+ cloneEl.draggable = false;
975
+ cloneEl.style['will-change'] = '';
976
+
977
+ _css(cloneEl, 'display', 'none');
978
+ _toggleClass(cloneEl, _this.options.chosenClass, false);
979
+
980
+ // #1143: IFrame support workaround
981
+ _this._cloneId = _nextTick(function () {
982
+ rootEl.insertBefore(cloneEl, dragEl);
983
+ _dispatchEvent(_this, rootEl, 'clone', dragEl);
984
+ });
985
+ }
986
+
987
+ _toggleClass(dragEl, options.dragClass, true);
988
+
989
+ if (useFallback) {
990
+ if (useFallback === 'touch') {
991
+ // Bind touch events
992
+ _on(document, 'touchmove', _this._onTouchMove);
993
+ _on(document, 'touchend', _this._onDrop);
994
+ _on(document, 'touchcancel', _this._onDrop);
995
+
996
+ if (options.supportPointer) {
997
+ _on(document, 'pointermove', _this._onTouchMove);
998
+ _on(document, 'pointerup', _this._onDrop);
999
+ }
1000
+ } else {
1001
+ // Old brwoser
1002
+ _on(document, 'mousemove', _this._onTouchMove);
1003
+ _on(document, 'mouseup', _this._onDrop);
1004
+ }
1005
+
1006
+ _this._loopId = setInterval(_this._emulateDragOver, 50);
1007
+ }
1008
+ else {
1009
+ if (dataTransfer) {
1010
+ dataTransfer.effectAllowed = 'move';
1011
+ options.setData && options.setData.call(_this, dataTransfer, dragEl);
1012
+ }
1013
+
1014
+ _on(document, 'drop', _this);
1015
+
1016
+ // #1143: Бывает элемент с IFrame внутри блокирует `drop`,
1017
+ // поэтому если вызвался `mouseover`, значит надо отменять весь d'n'd.
1018
+ // Breaking Chrome 62+
1019
+ // _on(document, 'mouseover', _this);
1020
+
1021
+ _this._dragStartId = _nextTick(_this._dragStarted);
1022
+ }
1023
+ },
1024
+
1025
+ _onDragOver: function (/**Event*/evt) {
1026
+ var el = this.el,
1027
+ target,
1028
+ dragRect,
1029
+ targetRect,
1030
+ revert,
1031
+ options = this.options,
1032
+ group = options.group,
1033
+ activeSortable = Sortable.active,
1034
+ isOwner = (activeGroup === group),
1035
+ isMovingBetweenSortable = false,
1036
+ canSort = options.sort;
1037
+
1038
+ if (evt.preventDefault !== void 0) {
1039
+ evt.preventDefault();
1040
+ !options.dragoverBubble && evt.stopPropagation();
1041
+ }
1042
+
1043
+ if (dragEl.animated) {
1044
+ return;
1045
+ }
1046
+
1047
+ moved = true;
1048
+
1049
+ if (activeSortable && !options.disabled &&
1050
+ (isOwner
1051
+ ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
1052
+ : (
1053
+ putSortable === this ||
1054
+ (
1055
+ (activeSortable.lastPullMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) &&
1056
+ group.checkPut(this, activeSortable, dragEl, evt)
1057
+ )
1058
+ )
1059
+ ) &&
1060
+ (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
1061
+ ) {
1062
+ // Smart auto-scrolling
1063
+ _autoScroll(evt, options, this.el);
1064
+
1065
+ if (_silent) {
1066
+ return;
1067
+ }
1068
+
1069
+ target = _closest(evt.target, options.draggable, el);
1070
+ dragRect = dragEl.getBoundingClientRect();
1071
+
1072
+ if (putSortable !== this) {
1073
+ putSortable = this;
1074
+ isMovingBetweenSortable = true;
1075
+ }
1076
+
1077
+ if (revert) {
1078
+ _cloneHide(activeSortable, true);
1079
+ parentEl = rootEl; // actualization
1080
+
1081
+ if (cloneEl || nextEl) {
1082
+ rootEl.insertBefore(dragEl, cloneEl || nextEl);
1083
+ }
1084
+ else if (!canSort) {
1085
+ rootEl.appendChild(dragEl);
1086
+ }
1087
+
1088
+ return;
1089
+ }
1090
+
1091
+
1092
+ if ((el.children.length === 0) || (el.children[0] === ghostEl) ||
1093
+ (el === evt.target) && (_ghostIsLast(el, evt))
1094
+ ) {
1095
+ //assign target only if condition is true
1096
+ if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) {
1097
+ target = el.lastElementChild;
1098
+ }
1099
+
1100
+ if (target) {
1101
+ if (target.animated) {
1102
+ return;
1103
+ }
1104
+
1105
+ targetRect = target.getBoundingClientRect();
1106
+ }
1107
+
1108
+ _cloneHide(activeSortable, isOwner);
1109
+
1110
+ if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
1111
+ if (!dragEl.contains(el)) {
1112
+ el.appendChild(dragEl);
1113
+ parentEl = el; // actualization
1114
+ }
1115
+
1116
+ this._animate(dragRect, dragEl);
1117
+ target && this._animate(targetRect, target);
1118
+ }
1119
+ }
1120
+ else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {
1121
+ if (lastEl !== target) {
1122
+ lastEl = target;
1123
+ lastCSS = _css(target);
1124
+ lastParentCSS = _css(target.parentNode);
1125
+ }
1126
+
1127
+ targetRect = target.getBoundingClientRect();
1128
+
1129
+ var width = targetRect.right - targetRect.left,
1130
+ height = targetRect.bottom - targetRect.top,
1131
+ floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display)
1132
+ || (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),
1133
+ isWide = (target.offsetWidth > dragEl.offsetWidth),
1134
+ isLong = (target.offsetHeight > dragEl.offsetHeight),
1135
+ halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,
1136
+ nextSibling = target.nextElementSibling,
1137
+ after = false
1138
+ ;
1139
+
1140
+ if (floating) {
1141
+ var elTop = dragEl.offsetTop,
1142
+ tgTop = target.offsetTop;
1143
+
1144
+ if (elTop === tgTop) {
1145
+ after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;
1146
+ }
1147
+ else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) {
1148
+ after = (evt.clientY - targetRect.top) / height > 0.5;
1149
+ } else {
1150
+ after = tgTop > elTop;
1151
+ }
1152
+ } else if (!isMovingBetweenSortable) {
1153
+ after = (nextSibling !== dragEl) && !isLong || halfway && isLong;
1154
+ }
1155
+
1156
+ var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
1157
+
1158
+ if (moveVector !== false) {
1159
+ if (moveVector === 1 || moveVector === -1) {
1160
+ after = (moveVector === 1);
1161
+ }
1162
+
1163
+ _silent = true;
1164
+ setTimeout(_unsilent, 30);
1165
+
1166
+ _cloneHide(activeSortable, isOwner);
1167
+
1168
+ if (!dragEl.contains(el)) {
1169
+ if (after && !nextSibling) {
1170
+ el.appendChild(dragEl);
1171
+ } else {
1172
+ target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
1173
+ }
1174
+ }
1175
+
1176
+ parentEl = dragEl.parentNode; // actualization
1177
+
1178
+ this._animate(dragRect, dragEl);
1179
+ this._animate(targetRect, target);
1180
+ }
1181
+ }
1182
+ }
1183
+ },
1184
+
1185
+ _animate: function (prevRect, target) {
1186
+ var ms = this.options.animation;
1187
+
1188
+ if (ms) {
1189
+ var currentRect = target.getBoundingClientRect();
1190
+
1191
+ if (prevRect.nodeType === 1) {
1192
+ prevRect = prevRect.getBoundingClientRect();
1193
+ }
1194
+
1195
+ _css(target, 'transition', 'none');
1196
+ _css(target, 'transform', 'translate3d('
1197
+ + (prevRect.left - currentRect.left) + 'px,'
1198
+ + (prevRect.top - currentRect.top) + 'px,0)'
1199
+ );
1200
+
1201
+ target.offsetWidth; // repaint
1202
+
1203
+ _css(target, 'transition', 'all ' + ms + 'ms');
1204
+ _css(target, 'transform', 'translate3d(0,0,0)');
1205
+
1206
+ clearTimeout(target.animated);
1207
+ target.animated = setTimeout(function () {
1208
+ _css(target, 'transition', '');
1209
+ _css(target, 'transform', '');
1210
+ target.animated = false;
1211
+ }, ms);
1212
+ }
1213
+ },
1214
+
1215
+ _offUpEvents: function () {
1216
+ var ownerDocument = this.el.ownerDocument;
1217
+
1218
+ _off(document, 'touchmove', this._onTouchMove);
1219
+ _off(document, 'pointermove', this._onTouchMove);
1220
+ _off(ownerDocument, 'mouseup', this._onDrop);
1221
+ _off(ownerDocument, 'touchend', this._onDrop);
1222
+ _off(ownerDocument, 'pointerup', this._onDrop);
1223
+ _off(ownerDocument, 'touchcancel', this._onDrop);
1224
+ _off(ownerDocument, 'pointercancel', this._onDrop);
1225
+ _off(ownerDocument, 'selectstart', this);
1226
+ },
1227
+
1228
+ _onDrop: function (/**Event*/evt) {
1229
+ var el = this.el,
1230
+ options = this.options;
1231
+
1232
+ clearInterval(this._loopId);
1233
+ clearInterval(autoScroll.pid);
1234
+ clearTimeout(this._dragStartTimer);
1235
+
1236
+ _cancelNextTick(this._cloneId);
1237
+ _cancelNextTick(this._dragStartId);
1238
+
1239
+ // Unbind events
1240
+ _off(document, 'mouseover', this);
1241
+ _off(document, 'mousemove', this._onTouchMove);
1242
+
1243
+ if (this.nativeDraggable) {
1244
+ _off(document, 'drop', this);
1245
+ _off(el, 'dragstart', this._onDragStart);
1246
+ }
1247
+
1248
+ this._offUpEvents();
1249
+
1250
+ if (evt) {
1251
+ if (moved) {
1252
+ evt.preventDefault();
1253
+ !options.dropBubble && evt.stopPropagation();
1254
+ }
1255
+
1256
+ ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
1257
+
1258
+ if (rootEl === parentEl || Sortable.active.lastPullMode !== 'clone') {
1259
+ // Remove clone
1260
+ cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
1261
+ }
1262
+
1263
+ if (dragEl) {
1264
+ if (this.nativeDraggable) {
1265
+ _off(dragEl, 'dragend', this);
1266
+ }
1267
+
1268
+ _disableDraggable(dragEl);
1269
+ dragEl.style['will-change'] = '';
1270
+
1271
+ // Remove class's
1272
+ _toggleClass(dragEl, this.options.ghostClass, false);
1273
+ _toggleClass(dragEl, this.options.chosenClass, false);
1274
+
1275
+ // Drag stop event
1276
+ _dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex);
1277
+
1278
+ if (rootEl !== parentEl) {
1279
+ newIndex = _index(dragEl, options.draggable);
1280
+
1281
+ if (newIndex >= 0) {
1282
+ // Add event
1283
+ _dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex);
1284
+
1285
+ // Remove event
1286
+ _dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex);
1287
+
1288
+ // drag from one list and drop into another
1289
+ _dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
1290
+ _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
1291
+ }
1292
+ }
1293
+ else {
1294
+ if (dragEl.nextSibling !== nextEl) {
1295
+ // Get the index of the dragged element within its parent
1296
+ newIndex = _index(dragEl, options.draggable);
1297
+
1298
+ if (newIndex >= 0) {
1299
+ // drag & drop within the same list
1300
+ _dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex);
1301
+ _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
1302
+ }
1303
+ }
1304
+ }
1305
+
1306
+ if (Sortable.active) {
1307
+ /* jshint eqnull:true */
1308
+ if (newIndex == null || newIndex === -1) {
1309
+ newIndex = oldIndex;
1310
+ }
1311
+
1312
+ _dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex);
1313
+
1314
+ // Save sorting
1315
+ this.save();
1316
+ }
1317
+ }
1318
+
1319
+ }
1320
+
1321
+ this._nulling();
1322
+ },
1323
+
1324
+ _nulling: function() {
1325
+ rootEl =
1326
+ dragEl =
1327
+ parentEl =
1328
+ ghostEl =
1329
+ nextEl =
1330
+ cloneEl =
1331
+ lastDownEl =
1332
+
1333
+ scrollEl =
1334
+ scrollParentEl =
1335
+
1336
+ tapEvt =
1337
+ touchEvt =
1338
+
1339
+ moved =
1340
+ newIndex =
1341
+
1342
+ lastEl =
1343
+ lastCSS =
1344
+
1345
+ putSortable =
1346
+ activeGroup =
1347
+ Sortable.active = null;
1348
+
1349
+ savedInputChecked.forEach(function (el) {
1350
+ el.checked = true;
1351
+ });
1352
+ savedInputChecked.length = 0;
1353
+ },
1354
+
1355
+ handleEvent: function (/**Event*/evt) {
1356
+ switch (evt.type) {
1357
+ case 'drop':
1358
+ case 'dragend':
1359
+ this._onDrop(evt);
1360
+ break;
1361
+
1362
+ case 'dragover':
1363
+ case 'dragenter':
1364
+ if (dragEl) {
1365
+ this._onDragOver(evt);
1366
+ _globalDragOver(evt);
1367
+ }
1368
+ break;
1369
+
1370
+ case 'mouseover':
1371
+ this._onDrop(evt);
1372
+ break;
1373
+
1374
+ case 'selectstart':
1375
+ evt.preventDefault();
1376
+ break;
1377
+ }
1378
+ },
1379
+
1380
+
1381
+ /**
1382
+ * Serializes the item into an array of string.
1383
+ * @returns {String[]}
1384
+ */
1385
+ toArray: function () {
1386
+ var order = [],
1387
+ el,
1388
+ children = this.el.children,
1389
+ i = 0,
1390
+ n = children.length,
1391
+ options = this.options;
1392
+
1393
+ for (; i < n; i++) {
1394
+ el = children[i];
1395
+ if (_closest(el, options.draggable, this.el)) {
1396
+ order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
1397
+ }
1398
+ }
1399
+
1400
+ return order;
1401
+ },
1402
+
1403
+
1404
+ /**
1405
+ * Sorts the elements according to the array.
1406
+ * @param {String[]} order order of the items
1407
+ */
1408
+ sort: function (order) {
1409
+ var items = {}, rootEl = this.el;
1410
+
1411
+ this.toArray().forEach(function (id, i) {
1412
+ var el = rootEl.children[i];
1413
+
1414
+ if (_closest(el, this.options.draggable, rootEl)) {
1415
+ items[id] = el;
1416
+ }
1417
+ }, this);
1418
+
1419
+ order.forEach(function (id) {
1420
+ if (items[id]) {
1421
+ rootEl.removeChild(items[id]);
1422
+ rootEl.appendChild(items[id]);
1423
+ }
1424
+ });
1425
+ },
1426
+
1427
+
1428
+ /**
1429
+ * Save the current sorting
1430
+ */
1431
+ save: function () {
1432
+ var store = this.options.store;
1433
+ store && store.set(this);
1434
+ },
1435
+
1436
+
1437
+ /**
1438
+ * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
1439
+ * @param {HTMLElement} el
1440
+ * @param {String} [selector] default: `options.draggable`
1441
+ * @returns {HTMLElement|null}
1442
+ */
1443
+ closest: function (el, selector) {
1444
+ return _closest(el, selector || this.options.draggable, this.el);
1445
+ },
1446
+
1447
+
1448
+ /**
1449
+ * Set/get option
1450
+ * @param {string} name
1451
+ * @param {*} [value]
1452
+ * @returns {*}
1453
+ */
1454
+ option: function (name, value) {
1455
+ var options = this.options;
1456
+
1457
+ if (value === void 0) {
1458
+ return options[name];
1459
+ } else {
1460
+ options[name] = value;
1461
+
1462
+ if (name === 'group') {
1463
+ _prepareGroup(options);
1464
+ }
1465
+ }
1466
+ },
1467
+
1468
+
1469
+ /**
1470
+ * Destroy
1471
+ */
1472
+ destroy: function () {
1473
+ var el = this.el;
1474
+
1475
+ el[expando] = null;
1476
+
1477
+ _off(el, 'mousedown', this._onTapStart);
1478
+ _off(el, 'touchstart', this._onTapStart);
1479
+ _off(el, 'pointerdown', this._onTapStart);
1480
+
1481
+ if (this.nativeDraggable) {
1482
+ _off(el, 'dragover', this);
1483
+ _off(el, 'dragenter', this);
1484
+ }
1485
+
1486
+ // Remove draggable attributes
1487
+ Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
1488
+ el.removeAttribute('draggable');
1489
+ });
1490
+
1491
+ touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
1492
+
1493
+ this._onDrop();
1494
+
1495
+ this.el = el = null;
1496
+ }
1497
+ };
1498
+
1499
+
1500
+ function _cloneHide(sortable, state) {
1501
+ if (sortable.lastPullMode !== 'clone') {
1502
+ state = true;
1503
+ }
1504
+
1505
+ if (cloneEl && (cloneEl.state !== state)) {
1506
+ _css(cloneEl, 'display', state ? 'none' : '');
1507
+
1508
+ if (!state) {
1509
+ if (cloneEl.state) {
1510
+ if (sortable.options.group.revertClone) {
1511
+ rootEl.insertBefore(cloneEl, nextEl);
1512
+ sortable._animate(dragEl, cloneEl);
1513
+ } else {
1514
+ rootEl.insertBefore(cloneEl, dragEl);
1515
+ }
1516
+ }
1517
+ }
1518
+
1519
+ cloneEl.state = state;
1520
+ }
1521
+ }
1522
+
1523
+
1524
+ function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
1525
+ if (el) {
1526
+ ctx = ctx || document;
1527
+
1528
+ do {
1529
+ if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) {
1530
+ return el;
1531
+ }
1532
+ /* jshint boss:true */
1533
+ } while (el = _getParentOrHost(el));
1534
+ }
1535
+
1536
+ return null;
1537
+ }
1538
+
1539
+
1540
+ function _getParentOrHost(el) {
1541
+ var parent = el.host;
1542
+
1543
+ return (parent && parent.nodeType) ? parent : el.parentNode;
1544
+ }
1545
+
1546
+
1547
+ function _globalDragOver(/**Event*/evt) {
1548
+ if (evt.dataTransfer) {
1549
+ evt.dataTransfer.dropEffect = 'move';
1550
+ }
1551
+ evt.preventDefault();
1552
+ }
1553
+
1554
+
1555
+ function _on(el, event, fn) {
1556
+ el.addEventListener(event, fn, captureMode);
1557
+ }
1558
+
1559
+
1560
+ function _off(el, event, fn) {
1561
+ el.removeEventListener(event, fn, captureMode);
1562
+ }
1563
+
1564
+
1565
+ function _toggleClass(el, name, state) {
1566
+ if (el) {
1567
+ if (el.classList) {
1568
+ el.classList[state ? 'add' : 'remove'](name);
1569
+ }
1570
+ else {
1571
+ var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
1572
+ el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
1573
+ }
1574
+ }
1575
+ }
1576
+
1577
+
1578
+ function _css(el, prop, val) {
1579
+ var style = el && el.style;
1580
+
1581
+ if (style) {
1582
+ if (val === void 0) {
1583
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1584
+ val = document.defaultView.getComputedStyle(el, '');
1585
+ }
1586
+ else if (el.currentStyle) {
1587
+ val = el.currentStyle;
1588
+ }
1589
+
1590
+ return prop === void 0 ? val : val[prop];
1591
+ }
1592
+ else {
1593
+ if (!(prop in style)) {
1594
+ prop = '-webkit-' + prop;
1595
+ }
1596
+
1597
+ style[prop] = val + (typeof val === 'string' ? '' : 'px');
1598
+ }
1599
+ }
1600
+ }
1601
+
1602
+
1603
+ function _find(ctx, tagName, iterator) {
1604
+ if (ctx) {
1605
+ var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
1606
+
1607
+ if (iterator) {
1608
+ for (; i < n; i++) {
1609
+ iterator(list[i], i);
1610
+ }
1611
+ }
1612
+
1613
+ return list;
1614
+ }
1615
+
1616
+ return [];
1617
+ }
1618
+
1619
+
1620
+
1621
+ function _dispatchEvent(sortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex) {
1622
+ sortable = (sortable || rootEl[expando]);
1623
+
1624
+ var evt = document.createEvent('Event'),
1625
+ options = sortable.options,
1626
+ onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
1627
+
1628
+ evt.initEvent(name, true, true);
1629
+
1630
+ evt.to = toEl || rootEl;
1631
+ evt.from = fromEl || rootEl;
1632
+ evt.item = targetEl || rootEl;
1633
+ evt.clone = cloneEl;
1634
+
1635
+ evt.oldIndex = startIndex;
1636
+ evt.newIndex = newIndex;
1637
+
1638
+ rootEl.dispatchEvent(evt);
1639
+
1640
+ if (options[onName]) {
1641
+ options[onName].call(sortable, evt);
1642
+ }
1643
+ }
1644
+
1645
+
1646
+ function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) {
1647
+ var evt,
1648
+ sortable = fromEl[expando],
1649
+ onMoveFn = sortable.options.onMove,
1650
+ retVal;
1651
+
1652
+ evt = document.createEvent('Event');
1653
+ evt.initEvent('move', true, true);
1654
+
1655
+ evt.to = toEl;
1656
+ evt.from = fromEl;
1657
+ evt.dragged = dragEl;
1658
+ evt.draggedRect = dragRect;
1659
+ evt.related = targetEl || toEl;
1660
+ evt.relatedRect = targetRect || toEl.getBoundingClientRect();
1661
+ evt.willInsertAfter = willInsertAfter;
1662
+
1663
+ fromEl.dispatchEvent(evt);
1664
+
1665
+ if (onMoveFn) {
1666
+ retVal = onMoveFn.call(sortable, evt, originalEvt);
1667
+ }
1668
+
1669
+ return retVal;
1670
+ }
1671
+
1672
+
1673
+ function _disableDraggable(el) {
1674
+ el.draggable = false;
1675
+ }
1676
+
1677
+
1678
+ function _unsilent() {
1679
+ _silent = false;
1680
+ }
1681
+
1682
+
1683
+ /** @returns {HTMLElement|false} */
1684
+ function _ghostIsLast(el, evt) {
1685
+ var lastEl = el.lastElementChild,
1686
+ rect = lastEl.getBoundingClientRect();
1687
+
1688
+ // 5 — min delta
1689
+ // abs — нельзя добавлять, а то глюки при наведении сверху
1690
+ return (evt.clientY - (rect.top + rect.height) > 5) ||
1691
+ (evt.clientX - (rect.left + rect.width) > 5);
1692
+ }
1693
+
1694
+
1695
+ /**
1696
+ * Generate id
1697
+ * @param {HTMLElement} el
1698
+ * @returns {String}
1699
+ * @private
1700
+ */
1701
+ function _generateId(el) {
1702
+ var str = el.tagName + el.className + el.src + el.href + el.textContent,
1703
+ i = str.length,
1704
+ sum = 0;
1705
+
1706
+ while (i--) {
1707
+ sum += str.charCodeAt(i);
1708
+ }
1709
+
1710
+ return sum.toString(36);
1711
+ }
1712
+
1713
+ /**
1714
+ * Returns the index of an element within its parent for a selected set of
1715
+ * elements
1716
+ * @param {HTMLElement} el
1717
+ * @param {selector} selector
1718
+ * @return {number}
1719
+ */
1720
+ function _index(el, selector) {
1721
+ var index = 0;
1722
+
1723
+ if (!el || !el.parentNode) {
1724
+ return -1;
1725
+ }
1726
+
1727
+ while (el && (el = el.previousElementSibling)) {
1728
+ if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) {
1729
+ index++;
1730
+ }
1731
+ }
1732
+
1733
+ return index;
1734
+ }
1735
+
1736
+ function _matches(/**HTMLElement*/el, /**String*/selector) {
1737
+ if (el) {
1738
+ selector = selector.split('.');
1739
+
1740
+ var tag = selector.shift().toUpperCase(),
1741
+ re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');
1742
+
1743
+ return (
1744
+ (tag === '' || el.nodeName.toUpperCase() == tag) &&
1745
+ (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
1746
+ );
1747
+ }
1748
+
1749
+ return false;
1750
+ }
1751
+
1752
+ function _throttle(callback, ms) {
1753
+ var args, _this;
1754
+
1755
+ return function () {
1756
+ if (args === void 0) {
1757
+ args = arguments;
1758
+ _this = this;
1759
+
1760
+ setTimeout(function () {
1761
+ if (args.length === 1) {
1762
+ callback.call(_this, args[0]);
1763
+ } else {
1764
+ callback.apply(_this, args);
1765
+ }
1766
+
1767
+ args = void 0;
1768
+ }, ms);
1769
+ }
1770
+ };
1771
+ }
1772
+
1773
+ function _extend(dst, src) {
1774
+ if (dst && src) {
1775
+ for (var key in src) {
1776
+ if (src.hasOwnProperty(key)) {
1777
+ dst[key] = src[key];
1778
+ }
1779
+ }
1780
+ }
1781
+
1782
+ return dst;
1783
+ }
1784
+
1785
+ function _clone(el) {
1786
+ if (Polymer && Polymer.dom) {
1787
+ return Polymer.dom(el).cloneNode(true);
1788
+ }
1789
+ else if ($) {
1790
+ return $(el).clone(true)[0];
1791
+ }
1792
+ else {
1793
+ return el.cloneNode(true);
1794
+ }
1795
+ }
1796
+
1797
+ function _saveInputCheckedState(root) {
1798
+ var inputs = root.getElementsByTagName('input');
1799
+ var idx = inputs.length;
1800
+
1801
+ while (idx--) {
1802
+ var el = inputs[idx];
1803
+ el.checked && savedInputChecked.push(el);
1804
+ }
1805
+ }
1806
+
1807
+ function _nextTick(fn) {
1808
+ return setTimeout(fn, 0);
1809
+ }
1810
+
1811
+ function _cancelNextTick(id) {
1812
+ return clearTimeout(id);
1813
+ }
1814
+
1815
+ // Fixed #973:
1816
+ _on(document, 'touchmove', function (evt) {
1817
+ if (Sortable.active) {
1818
+ evt.preventDefault();
1819
+ }
1820
+ });
1821
+
1822
+ // Export utils
1823
+ Sortable.utils = {
1824
+ on: _on,
1825
+ off: _off,
1826
+ css: _css,
1827
+ find: _find,
1828
+ is: function (el, selector) {
1829
+ return !!_closest(el, selector, el);
1830
+ },
1831
+ extend: _extend,
1832
+ throttle: _throttle,
1833
+ closest: _closest,
1834
+ toggleClass: _toggleClass,
1835
+ clone: _clone,
1836
+ index: _index,
1837
+ nextTick: _nextTick,
1838
+ cancelNextTick: _cancelNextTick
1839
+ };
1840
+
1841
+
1842
+ /**
1843
+ * Create sortable instance
1844
+ * @param {HTMLElement} el
1845
+ * @param {Object} [options]
1846
+ */
1847
+ Sortable.create = function (el, options) {
1848
+ return new Sortable(el, options);
1849
+ };
1850
+
1851
+
1852
+ // Export
1853
+ Sortable.version = '1.7.0';
1854
+ return Sortable;
1855
+ });
1856
+
1857
+
1858
+ /***/ }),
1859
+ /* 5 */
1860
+ /***/ (function(module, exports, __webpack_require__) {
1861
+
1862
+ "use strict";
1863
+ /* WEBPACK VAR INJECTION */(function(jQuery) {
1864
+
1865
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
1866
+
1867
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
1868
+
1869
+ (function ($, window, document) {
1870
+ var Plugin, defaults, pluginName;
1871
+ pluginName = 'SimpleFormNestedFields';
1872
+ defaults = {
1873
+ debug: false
1874
+ };
1875
+ Plugin = function () {
1876
+ function Plugin(element, options) {
1877
+ _classCallCheck(this, Plugin);
1878
+
1879
+ this.element = element;
1880
+ this.options = $.extend({}, defaults, options);
1881
+ this._defaults = defaults;
1882
+ this._name = pluginName;
1883
+ this.$element = $(this.element);
1884
+ this.init();
1885
+ }
1886
+
1887
+ _createClass(Plugin, [{
1888
+ key: 'init',
1889
+ value: function init() {
1890
+ this.$element.SimpleFormNestedFields__Links();
1891
+ if (this.is_sortable()) {
1892
+ return this.$element.SimpleFormNestedFields__Sortable();
1893
+ }
1894
+ }
1895
+ }, {
1896
+ key: 'destroy',
1897
+ value: function destroy() {
1898
+ this.$element.data('plugin_SimpleFormNestedFields__Links').destroy();
1899
+ return this.$element.data('plugin_SimpleFormNestedFields__Sortable').destroy();
1900
+ }
1901
+ }, {
1902
+ key: 'is_sortable',
1903
+ value: function is_sortable() {
1904
+ return this.element.classList.contains('simple_form_nested_fields__sortable');
1905
+ }
1906
+ }]);
1907
+
1908
+ return Plugin;
1909
+ }();
1910
+ // A really lightweight plugin wrapper around the constructor,
1911
+ // preventing against multiple instantiations
1912
+ return $.fn[pluginName] = function (options) {
1913
+ return this.each(function () {
1914
+ if (!$.data(this, 'plugin_' + pluginName)) {
1915
+ return $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
1916
+ }
1917
+ });
1918
+ };
1919
+ })(jQuery, window, document);
1920
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
1921
+
1922
+ /***/ })
1923
+ /******/ ]);
1924
+ });