BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
7c4046e1
Commit
7c4046e1
authored
May 31, 2018
by
Kushal Pandya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove in favor of npm package
parent
1cdaa532
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
0 additions
and
1374 deletions
+0
-1374
Sortable.js
vendor/assets/javascripts/Sortable.js
+0
-1374
No files found.
vendor/assets/javascripts/Sortable.js
deleted
100644 → 0
View file @
1cdaa532
/**!
* Sortable
* @author RubaXa <trash@rubaxa.org>
* @license MIT
*/
(
function
sortableModule
(
factory
)
{
"use strict"
;
if
(
typeof
define
===
"function"
&&
define
.
amd
)
{
define
(
factory
);
}
else
if
(
typeof
module
!=
"undefined"
&&
typeof
module
.
exports
!=
"undefined"
)
{
module
.
exports
=
factory
();
}
else
if
(
typeof
Package
!==
"undefined"
)
{
//noinspection JSUnresolvedVariable
Sortable
=
factory
();
// export for Meteor.js
}
else
{
/* jshint sub:true */
window
[
"Sortable"
]
=
factory
();
}
})(
function
sortableFactory
()
{
"use strict"
;
if
(
typeof
window
==
"undefined"
||
!
window
.
document
)
{
return
function
sortableError
()
{
throw
new
Error
(
"Sortable.js requires a window with a document"
);
};
}
var
dragEl
,
parentEl
,
ghostEl
,
cloneEl
,
rootEl
,
nextEl
,
scrollEl
,
scrollParentEl
,
scrollCustomFn
,
lastEl
,
lastCSS
,
lastParentCSS
,
oldIndex
,
newIndex
,
activeGroup
,
putSortable
,
autoScroll
=
{},
tapEvt
,
touchEvt
,
moved
,
/** @const */
RSPACE
=
/
\s
+/g
,
expando
=
'Sortable'
+
(
new
Date
).
getTime
(),
win
=
window
,
document
=
win
.
document
,
parseInt
=
win
.
parseInt
,
$
=
win
.
jQuery
||
win
.
Zepto
,
Polymer
=
win
.
Polymer
,
supportDraggable
=
!!
(
'draggable'
in
document
.
createElement
(
'div'
)),
supportCssPointerEvents
=
(
function
(
el
)
{
// false when IE11
if
(
!!
navigator
.
userAgent
.
match
(
/Trident.*rv
[
:
]?
11
\.
/
))
{
return
false
;
}
el
=
document
.
createElement
(
'x'
);
el
.
style
.
cssText
=
'pointer-events:auto'
;
return
el
.
style
.
pointerEvents
===
'auto'
;
})(),
_silent
=
false
,
abs
=
Math
.
abs
,
min
=
Math
.
min
,
slice
=
[].
slice
,
touchDragOverListeners
=
[],
_autoScroll
=
_throttle
(
function
(
/**Event*/
evt
,
/**Object*/
options
,
/**HTMLElement*/
rootEl
)
{
// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
if
(
rootEl
&&
options
.
scroll
)
{
var
el
,
rect
,
sens
=
options
.
scrollSensitivity
,
speed
=
options
.
scrollSpeed
,
x
=
evt
.
clientX
,
y
=
evt
.
clientY
,
winWidth
=
window
.
innerWidth
,
winHeight
=
window
.
innerHeight
,
vx
,
vy
,
scrollOffsetX
,
scrollOffsetY
;
// Delect scrollEl
if
(
scrollParentEl
!==
rootEl
)
{
scrollEl
=
options
.
scroll
;
scrollParentEl
=
rootEl
;
scrollCustomFn
=
options
.
scrollFn
;
if
(
scrollEl
===
true
)
{
scrollEl
=
rootEl
;
do
{
if
((
scrollEl
.
offsetWidth
<
scrollEl
.
scrollWidth
)
||
(
scrollEl
.
offsetHeight
<
scrollEl
.
scrollHeight
)
)
{
break
;
}
/* jshint boss:true */
}
while
(
scrollEl
=
scrollEl
.
parentNode
);
}
}
if
(
scrollEl
)
{
el
=
scrollEl
;
rect
=
scrollEl
.
getBoundingClientRect
();
vx
=
(
abs
(
rect
.
right
-
x
)
<=
sens
)
-
(
abs
(
rect
.
left
-
x
)
<=
sens
);
vy
=
(
abs
(
rect
.
bottom
-
y
)
<=
sens
)
-
(
abs
(
rect
.
top
-
y
)
<=
sens
);
}
if
(
!
(
vx
||
vy
))
{
vx
=
(
winWidth
-
x
<=
sens
)
-
(
x
<=
sens
);
vy
=
(
winHeight
-
y
<=
sens
)
-
(
y
<=
sens
);
/* jshint expr:true */
(
vx
||
vy
)
&&
(
el
=
win
);
}
if
(
autoScroll
.
vx
!==
vx
||
autoScroll
.
vy
!==
vy
||
autoScroll
.
el
!==
el
)
{
autoScroll
.
el
=
el
;
autoScroll
.
vx
=
vx
;
autoScroll
.
vy
=
vy
;
clearInterval
(
autoScroll
.
pid
);
if
(
el
)
{
autoScroll
.
pid
=
setInterval
(
function
()
{
scrollOffsetY
=
vy
?
vy
*
speed
:
0
;
scrollOffsetX
=
vx
?
vx
*
speed
:
0
;
if
(
'function'
===
typeof
(
scrollCustomFn
))
{
return
scrollCustomFn
.
call
(
_this
,
scrollOffsetX
,
scrollOffsetY
,
evt
);
}
if
(
el
===
win
)
{
win
.
scrollTo
(
win
.
pageXOffset
+
scrollOffsetX
,
win
.
pageYOffset
+
scrollOffsetY
);
}
else
{
el
.
scrollTop
+=
scrollOffsetY
;
el
.
scrollLeft
+=
scrollOffsetX
;
}
},
24
);
}
}
}
},
30
),
_prepareGroup
=
function
(
options
)
{
function
toFn
(
value
,
pull
)
{
if
(
value
===
void
0
||
value
===
true
)
{
value
=
group
.
name
;
}
if
(
typeof
value
===
'function'
)
{
return
value
;
}
else
{
return
function
(
to
,
from
)
{
var
fromGroup
=
from
.
options
.
group
.
name
;
return
pull
?
value
:
value
&&
(
value
.
join
?
value
.
indexOf
(
fromGroup
)
>
-
1
:
(
fromGroup
==
value
)
);
};
}
}
var
group
=
{};
var
originalGroup
=
options
.
group
;
if
(
!
originalGroup
||
typeof
originalGroup
!=
'object'
)
{
originalGroup
=
{
name
:
originalGroup
};
}
group
.
name
=
originalGroup
.
name
;
group
.
checkPull
=
toFn
(
originalGroup
.
pull
,
true
);
group
.
checkPut
=
toFn
(
originalGroup
.
put
);
options
.
group
=
group
;
}
;
/**
* @class Sortable
* @param {HTMLElement} el
* @param {Object} [options]
*/
function
Sortable
(
el
,
options
)
{
if
(
!
(
el
&&
el
.
nodeType
&&
el
.
nodeType
===
1
))
{
throw
'Sortable: `el` must be HTMLElement, and not '
+
{}.
toString
.
call
(
el
);
}
this
.
el
=
el
;
// root element
this
.
options
=
options
=
_extend
({},
options
);
// Export instance
el
[
expando
]
=
this
;
// Default options
var
defaults
=
{
group
:
Math
.
random
(),
sort
:
true
,
disabled
:
false
,
store
:
null
,
handle
:
null
,
scroll
:
true
,
scrollSensitivity
:
30
,
scrollSpeed
:
10
,
draggable
:
/
[
uo
]
l/i
.
test
(
el
.
nodeName
)
?
'li'
:
'>*'
,
ghostClass
:
'sortable-ghost'
,
chosenClass
:
'sortable-chosen'
,
dragClass
:
'sortable-drag'
,
ignore
:
'a, img'
,
filter
:
null
,
animation
:
0
,
setData
:
function
(
dataTransfer
,
dragEl
)
{
dataTransfer
.
setData
(
'Text'
,
dragEl
.
textContent
);
},
dropBubble
:
false
,
dragoverBubble
:
false
,
dataIdAttr
:
'data-id'
,
delay
:
0
,
forceFallback
:
false
,
fallbackClass
:
'sortable-fallback'
,
fallbackOnBody
:
false
,
fallbackTolerance
:
0
,
fallbackOffset
:
{
x
:
0
,
y
:
0
}
};
// Set default options
for
(
var
name
in
defaults
)
{
!
(
name
in
options
)
&&
(
options
[
name
]
=
defaults
[
name
]);
}
_prepareGroup
(
options
);
// Bind all private methods
for
(
var
fn
in
this
)
{
if
(
fn
.
charAt
(
0
)
===
'_'
&&
typeof
this
[
fn
]
===
'function'
)
{
this
[
fn
]
=
this
[
fn
].
bind
(
this
);
}
}
// Setup drag mode
this
.
nativeDraggable
=
options
.
forceFallback
?
false
:
supportDraggable
;
// Bind events
_on
(
el
,
'mousedown'
,
this
.
_onTapStart
);
_on
(
el
,
'touchstart'
,
this
.
_onTapStart
);
if
(
this
.
nativeDraggable
)
{
_on
(
el
,
'dragover'
,
this
);
_on
(
el
,
'dragenter'
,
this
);
}
touchDragOverListeners
.
push
(
this
.
_onDragOver
);
// Restore sorting
options
.
store
&&
this
.
sort
(
options
.
store
.
get
(
this
));
}
Sortable
.
prototype
=
/** @lends Sortable.prototype */
{
constructor
:
Sortable
,
_onTapStart
:
function
(
/** Event|TouchEvent */
evt
)
{
var
_this
=
this
,
el
=
this
.
el
,
options
=
this
.
options
,
type
=
evt
.
type
,
touch
=
evt
.
touches
&&
evt
.
touches
[
0
],
target
=
(
touch
||
evt
).
target
,
originalTarget
=
evt
.
target
.
shadowRoot
&&
evt
.
path
[
0
]
||
target
,
filter
=
options
.
filter
,
startIndex
;
// Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
if
(
dragEl
)
{
return
;
}
if
(
type
===
'mousedown'
&&
evt
.
button
!==
0
||
options
.
disabled
)
{
return
;
// only left button or enabled
}
if
(
options
.
handle
&&
!
_closest
(
originalTarget
,
options
.
handle
,
el
))
{
return
;
}
target
=
_closest
(
target
,
options
.
draggable
,
el
);
if
(
!
target
)
{
return
;
}
// Get the index of the dragged element within its parent
startIndex
=
_index
(
target
,
options
.
draggable
);
// Check filter
if
(
typeof
filter
===
'function'
)
{
if
(
filter
.
call
(
this
,
evt
,
target
,
this
))
{
_dispatchEvent
(
_this
,
originalTarget
,
'filter'
,
target
,
el
,
startIndex
);
evt
.
preventDefault
();
return
;
// cancel dnd
}
}
else
if
(
filter
)
{
filter
=
filter
.
split
(
','
).
some
(
function
(
criteria
)
{
criteria
=
_closest
(
originalTarget
,
criteria
.
trim
(),
el
);
if
(
criteria
)
{
_dispatchEvent
(
_this
,
criteria
,
'filter'
,
target
,
el
,
startIndex
);
return
true
;
}
});
if
(
filter
)
{
evt
.
preventDefault
();
return
;
// cancel dnd
}
}
// Prepare `dragstart`
this
.
_prepareDragStart
(
evt
,
touch
,
target
,
startIndex
);
},
_prepareDragStart
:
function
(
/** Event */
evt
,
/** Touch */
touch
,
/** HTMLElement */
target
,
/** Number */
startIndex
)
{
var
_this
=
this
,
el
=
_this
.
el
,
options
=
_this
.
options
,
ownerDocument
=
el
.
ownerDocument
,
dragStartFn
;
if
(
target
&&
!
dragEl
&&
(
target
.
parentNode
===
el
))
{
tapEvt
=
evt
;
rootEl
=
el
;
dragEl
=
target
;
parentEl
=
dragEl
.
parentNode
;
nextEl
=
dragEl
.
nextSibling
;
activeGroup
=
options
.
group
;
oldIndex
=
startIndex
;
this
.
_lastX
=
(
touch
||
evt
).
clientX
;
this
.
_lastY
=
(
touch
||
evt
).
clientY
;
dragEl
.
style
[
'will-change'
]
=
'transform'
;
dragStartFn
=
function
()
{
// Delayed drag has been triggered
// we can re-enable the events: touchmove/mousemove
_this
.
_disableDelayedDrag
();
// Make the element draggable
dragEl
.
draggable
=
_this
.
nativeDraggable
;
// Chosen item
_toggleClass
(
dragEl
,
options
.
chosenClass
,
true
);
// Bind the events: dragstart/dragend
_this
.
_triggerDragStart
(
touch
);
// Drag start event
_dispatchEvent
(
_this
,
rootEl
,
'choose'
,
dragEl
,
rootEl
,
oldIndex
);
};
// Disable "draggable"
options
.
ignore
.
split
(
','
).
forEach
(
function
(
criteria
)
{
_find
(
dragEl
,
criteria
.
trim
(),
_disableDraggable
);
});
_on
(
ownerDocument
,
'mouseup'
,
_this
.
_onDrop
);
_on
(
ownerDocument
,
'touchend'
,
_this
.
_onDrop
);
_on
(
ownerDocument
,
'touchcancel'
,
_this
.
_onDrop
);
if
(
options
.
delay
)
{
// If the user moves the pointer or let go the click or touch
// before the delay has been reached:
// disable the delayed drag
_on
(
ownerDocument
,
'mouseup'
,
_this
.
_disableDelayedDrag
);
_on
(
ownerDocument
,
'touchend'
,
_this
.
_disableDelayedDrag
);
_on
(
ownerDocument
,
'touchcancel'
,
_this
.
_disableDelayedDrag
);
_on
(
ownerDocument
,
'mousemove'
,
_this
.
_disableDelayedDrag
);
_on
(
ownerDocument
,
'touchmove'
,
_this
.
_disableDelayedDrag
);
_this
.
_dragStartTimer
=
setTimeout
(
dragStartFn
,
options
.
delay
);
}
else
{
dragStartFn
();
}
}
},
_disableDelayedDrag
:
function
()
{
var
ownerDocument
=
this
.
el
.
ownerDocument
;
clearTimeout
(
this
.
_dragStartTimer
);
_off
(
ownerDocument
,
'mouseup'
,
this
.
_disableDelayedDrag
);
_off
(
ownerDocument
,
'touchend'
,
this
.
_disableDelayedDrag
);
_off
(
ownerDocument
,
'touchcancel'
,
this
.
_disableDelayedDrag
);
_off
(
ownerDocument
,
'mousemove'
,
this
.
_disableDelayedDrag
);
_off
(
ownerDocument
,
'touchmove'
,
this
.
_disableDelayedDrag
);
},
_triggerDragStart
:
function
(
/** Touch */
touch
)
{
if
(
touch
)
{
// Touch device support
tapEvt
=
{
target
:
dragEl
,
clientX
:
touch
.
clientX
,
clientY
:
touch
.
clientY
};
this
.
_onDragStart
(
tapEvt
,
'touch'
);
}
else
if
(
!
this
.
nativeDraggable
)
{
this
.
_onDragStart
(
tapEvt
,
true
);
}
else
{
_on
(
dragEl
,
'dragend'
,
this
);
_on
(
rootEl
,
'dragstart'
,
this
.
_onDragStart
);
}
try
{
if
(
document
.
selection
)
{
// Timeout neccessary for IE9
setTimeout
(
function
()
{
document
.
selection
.
empty
();
});
}
else
{
window
.
getSelection
().
removeAllRanges
();
}
}
catch
(
err
)
{
}
},
_dragStarted
:
function
()
{
if
(
rootEl
&&
dragEl
)
{
var
options
=
this
.
options
;
// Apply effect
_toggleClass
(
dragEl
,
options
.
ghostClass
,
true
);
_toggleClass
(
dragEl
,
options
.
dragClass
,
false
);
Sortable
.
active
=
this
;
// Drag start event
_dispatchEvent
(
this
,
rootEl
,
'start'
,
dragEl
,
rootEl
,
oldIndex
);
}
},
_emulateDragOver
:
function
()
{
if
(
touchEvt
)
{
if
(
this
.
_lastX
===
touchEvt
.
clientX
&&
this
.
_lastY
===
touchEvt
.
clientY
)
{
return
;
}
this
.
_lastX
=
touchEvt
.
clientX
;
this
.
_lastY
=
touchEvt
.
clientY
;
if
(
!
supportCssPointerEvents
)
{
_css
(
ghostEl
,
'display'
,
'none'
);
}
var
target
=
document
.
elementFromPoint
(
touchEvt
.
clientX
,
touchEvt
.
clientY
),
parent
=
target
,
i
=
touchDragOverListeners
.
length
;
if
(
parent
)
{
do
{
if
(
parent
[
expando
])
{
while
(
i
--
)
{
touchDragOverListeners
[
i
]({
clientX
:
touchEvt
.
clientX
,
clientY
:
touchEvt
.
clientY
,
target
:
target
,
rootEl
:
parent
});
}
break
;
}
target
=
parent
;
// store last element
}
/* jshint boss:true */
while
(
parent
=
parent
.
parentNode
);
}
if
(
!
supportCssPointerEvents
)
{
_css
(
ghostEl
,
'display'
,
''
);
}
}
},
_onTouchMove
:
function
(
/**TouchEvent*/
evt
)
{
if
(
tapEvt
)
{
var
options
=
this
.
options
,
fallbackTolerance
=
options
.
fallbackTolerance
,
fallbackOffset
=
options
.
fallbackOffset
,
touch
=
evt
.
touches
?
evt
.
touches
[
0
]
:
evt
,
dx
=
(
touch
.
clientX
-
tapEvt
.
clientX
)
+
fallbackOffset
.
x
,
dy
=
(
touch
.
clientY
-
tapEvt
.
clientY
)
+
fallbackOffset
.
y
,
translate3d
=
evt
.
touches
?
'translate3d('
+
dx
+
'px,'
+
dy
+
'px,0)'
:
'translate('
+
dx
+
'px,'
+
dy
+
'px)'
;
// only set the status to dragging, when we are actually dragging
if
(
!
Sortable
.
active
)
{
if
(
fallbackTolerance
&&
min
(
abs
(
touch
.
clientX
-
this
.
_lastX
),
abs
(
touch
.
clientY
-
this
.
_lastY
))
<
fallbackTolerance
)
{
return
;
}
this
.
_dragStarted
();
}
// as well as creating the ghost element on the document body
this
.
_appendGhost
();
moved
=
true
;
touchEvt
=
touch
;
_css
(
ghostEl
,
'webkitTransform'
,
translate3d
);
_css
(
ghostEl
,
'mozTransform'
,
translate3d
);
_css
(
ghostEl
,
'msTransform'
,
translate3d
);
_css
(
ghostEl
,
'transform'
,
translate3d
);
evt
.
preventDefault
();
}
},
_appendGhost
:
function
()
{
if
(
!
ghostEl
)
{
var
rect
=
dragEl
.
getBoundingClientRect
(),
css
=
_css
(
dragEl
),
options
=
this
.
options
,
ghostRect
;
ghostEl
=
dragEl
.
cloneNode
(
true
);
_toggleClass
(
ghostEl
,
options
.
ghostClass
,
false
);
_toggleClass
(
ghostEl
,
options
.
fallbackClass
,
true
);
_toggleClass
(
ghostEl
,
options
.
dragClass
,
true
);
_css
(
ghostEl
,
'top'
,
rect
.
top
-
parseInt
(
css
.
marginTop
,
10
));
_css
(
ghostEl
,
'left'
,
rect
.
left
-
parseInt
(
css
.
marginLeft
,
10
));
_css
(
ghostEl
,
'width'
,
rect
.
width
);
_css
(
ghostEl
,
'height'
,
rect
.
height
);
_css
(
ghostEl
,
'opacity'
,
'0.8'
);
_css
(
ghostEl
,
'position'
,
'fixed'
);
_css
(
ghostEl
,
'zIndex'
,
'100000'
);
_css
(
ghostEl
,
'pointerEvents'
,
'none'
);
options
.
fallbackOnBody
&&
document
.
body
.
appendChild
(
ghostEl
)
||
rootEl
.
appendChild
(
ghostEl
);
// Fixing dimensions.
ghostRect
=
ghostEl
.
getBoundingClientRect
();
_css
(
ghostEl
,
'width'
,
rect
.
width
*
2
-
ghostRect
.
width
);
_css
(
ghostEl
,
'height'
,
rect
.
height
*
2
-
ghostRect
.
height
);
}
},
_onDragStart
:
function
(
/**Event*/
evt
,
/**boolean*/
useFallback
)
{
var
dataTransfer
=
evt
.
dataTransfer
,
options
=
this
.
options
;
this
.
_offUpEvents
();
if
(
activeGroup
.
checkPull
(
this
,
this
,
dragEl
,
evt
)
==
'clone'
)
{
cloneEl
=
_clone
(
dragEl
);
_css
(
cloneEl
,
'display'
,
'none'
);
rootEl
.
insertBefore
(
cloneEl
,
dragEl
);
_dispatchEvent
(
this
,
rootEl
,
'clone'
,
dragEl
);
}
_toggleClass
(
dragEl
,
options
.
dragClass
,
true
);
if
(
useFallback
)
{
if
(
useFallback
===
'touch'
)
{
// Bind touch events
_on
(
document
,
'touchmove'
,
this
.
_onTouchMove
);
_on
(
document
,
'touchend'
,
this
.
_onDrop
);
_on
(
document
,
'touchcancel'
,
this
.
_onDrop
);
}
else
{
// Old brwoser
_on
(
document
,
'mousemove'
,
this
.
_onTouchMove
);
_on
(
document
,
'mouseup'
,
this
.
_onDrop
);
}
this
.
_loopId
=
setInterval
(
this
.
_emulateDragOver
,
50
);
}
else
{
if
(
dataTransfer
)
{
dataTransfer
.
effectAllowed
=
'move'
;
options
.
setData
&&
options
.
setData
.
call
(
this
,
dataTransfer
,
dragEl
);
}
_on
(
document
,
'drop'
,
this
);
setTimeout
(
this
.
_dragStarted
,
0
);
}
},
_onDragOver
:
function
(
/**Event*/
evt
)
{
var
el
=
this
.
el
,
target
,
dragRect
,
targetRect
,
revert
,
options
=
this
.
options
,
group
=
options
.
group
,
activeSortable
=
Sortable
.
active
,
isOwner
=
(
activeGroup
===
group
),
canSort
=
options
.
sort
;
if
(
evt
.
preventDefault
!==
void
0
)
{
evt
.
preventDefault
();
!
options
.
dragoverBubble
&&
evt
.
stopPropagation
();
}
moved
=
true
;
if
(
activeGroup
&&
!
options
.
disabled
&&
(
isOwner
?
canSort
||
(
revert
=
!
rootEl
.
contains
(
dragEl
))
// Reverting item into the original list
:
(
putSortable
===
this
||
activeGroup
.
checkPull
(
this
,
activeSortable
,
dragEl
,
evt
)
&&
group
.
checkPut
(
this
,
activeSortable
,
dragEl
,
evt
)
)
)
&&
(
evt
.
rootEl
===
void
0
||
evt
.
rootEl
===
this
.
el
)
// touch fallback
)
{
// Smart auto-scrolling
_autoScroll
(
evt
,
options
,
this
.
el
);
if
(
_silent
)
{
return
;
}
target
=
_closest
(
evt
.
target
,
options
.
draggable
,
el
);
dragRect
=
dragEl
.
getBoundingClientRect
();
putSortable
=
this
;
if
(
revert
)
{
_cloneHide
(
true
);
parentEl
=
rootEl
;
// actualization
if
(
cloneEl
||
nextEl
)
{
rootEl
.
insertBefore
(
dragEl
,
cloneEl
||
nextEl
);
}
else
if
(
!
canSort
)
{
rootEl
.
appendChild
(
dragEl
);
}
return
;
}
if
((
el
.
children
.
length
===
0
)
||
(
el
.
children
[
0
]
===
ghostEl
)
||
(
el
===
evt
.
target
)
&&
(
target
=
_ghostIsLast
(
el
,
evt
))
)
{
if
(
target
)
{
if
(
target
.
animated
)
{
return
;
}
targetRect
=
target
.
getBoundingClientRect
();
}
_cloneHide
(
isOwner
);
if
(
_onMove
(
rootEl
,
el
,
dragEl
,
dragRect
,
target
,
targetRect
,
evt
)
!==
false
)
{
if
(
!
dragEl
.
contains
(
el
))
{
el
.
appendChild
(
dragEl
);
parentEl
=
el
;
// actualization
}
this
.
_animate
(
dragRect
,
dragEl
);
target
&&
this
.
_animate
(
targetRect
,
target
);
}
}
else
if
(
target
&&
!
target
.
animated
&&
target
!==
dragEl
&&
(
target
.
parentNode
[
expando
]
!==
void
0
))
{
if
(
lastEl
!==
target
)
{
lastEl
=
target
;
lastCSS
=
_css
(
target
);
lastParentCSS
=
_css
(
target
.
parentNode
);
}
targetRect
=
target
.
getBoundingClientRect
();
var
width
=
targetRect
.
right
-
targetRect
.
left
,
height
=
targetRect
.
bottom
-
targetRect
.
top
,
floating
=
/left|right|inline/
.
test
(
lastCSS
.
cssFloat
+
lastCSS
.
display
)
||
(
lastParentCSS
.
display
==
'flex'
&&
lastParentCSS
[
'flex-direction'
].
indexOf
(
'row'
)
===
0
),
isWide
=
(
target
.
offsetWidth
>
dragEl
.
offsetWidth
),
isLong
=
(
target
.
offsetHeight
>
dragEl
.
offsetHeight
),
halfway
=
(
floating
?
(
evt
.
clientX
-
targetRect
.
left
)
/
width
:
(
evt
.
clientY
-
targetRect
.
top
)
/
height
)
>
0.5
,
nextSibling
=
target
.
nextElementSibling
,
moveVector
=
_onMove
(
rootEl
,
el
,
dragEl
,
dragRect
,
target
,
targetRect
,
evt
),
after
;
if
(
moveVector
!==
false
)
{
_silent
=
true
;
setTimeout
(
_unsilent
,
30
);
_cloneHide
(
isOwner
);
if
(
moveVector
===
1
||
moveVector
===
-
1
)
{
after
=
(
moveVector
===
1
);
}
else
if
(
floating
)
{
var
elTop
=
dragEl
.
offsetTop
,
tgTop
=
target
.
offsetTop
;
if
(
elTop
===
tgTop
)
{
after
=
(
target
.
previousElementSibling
===
dragEl
)
&&
!
isWide
||
halfway
&&
isWide
;
}
else
if
(
target
.
previousElementSibling
===
dragEl
||
dragEl
.
previousElementSibling
===
target
)
{
after
=
(
evt
.
clientY
-
targetRect
.
top
)
/
height
>
0.5
;
}
else
{
after
=
tgTop
>
elTop
;
}
}
else
{
after
=
(
nextSibling
!==
dragEl
)
&&
!
isLong
||
halfway
&&
isLong
;
}
if
(
!
dragEl
.
contains
(
el
))
{
if
(
after
&&
!
nextSibling
)
{
el
.
appendChild
(
dragEl
);
}
else
{
target
.
parentNode
.
insertBefore
(
dragEl
,
after
?
nextSibling
:
target
);
}
}
parentEl
=
dragEl
.
parentNode
;
// actualization
this
.
_animate
(
dragRect
,
dragEl
);
this
.
_animate
(
targetRect
,
target
);
}
}
}
},
_animate
:
function
(
prevRect
,
target
)
{
var
ms
=
this
.
options
.
animation
;
if
(
ms
)
{
var
currentRect
=
target
.
getBoundingClientRect
();
_css
(
target
,
'transition'
,
'none'
);
_css
(
target
,
'transform'
,
'translate3d('
+
(
prevRect
.
left
-
currentRect
.
left
)
+
'px,'
+
(
prevRect
.
top
-
currentRect
.
top
)
+
'px,0)'
);
target
.
offsetWidth
;
// repaint
_css
(
target
,
'transition'
,
'all '
+
ms
+
'ms'
);
_css
(
target
,
'transform'
,
'translate3d(0,0,0)'
);
clearTimeout
(
target
.
animated
);
target
.
animated
=
setTimeout
(
function
()
{
_css
(
target
,
'transition'
,
''
);
_css
(
target
,
'transform'
,
''
);
target
.
animated
=
false
;
},
ms
);
}
},
_offUpEvents
:
function
()
{
var
ownerDocument
=
this
.
el
.
ownerDocument
;
_off
(
document
,
'touchmove'
,
this
.
_onTouchMove
);
_off
(
ownerDocument
,
'mouseup'
,
this
.
_onDrop
);
_off
(
ownerDocument
,
'touchend'
,
this
.
_onDrop
);
_off
(
ownerDocument
,
'touchcancel'
,
this
.
_onDrop
);
},
_onDrop
:
function
(
/**Event*/
evt
)
{
var
el
=
this
.
el
,
options
=
this
.
options
;
clearInterval
(
this
.
_loopId
);
clearInterval
(
autoScroll
.
pid
);
clearTimeout
(
this
.
_dragStartTimer
);
// Unbind events
_off
(
document
,
'mousemove'
,
this
.
_onTouchMove
);
if
(
this
.
nativeDraggable
)
{
_off
(
document
,
'drop'
,
this
);
_off
(
el
,
'dragstart'
,
this
.
_onDragStart
);
}
this
.
_offUpEvents
();
if
(
evt
)
{
if
(
moved
)
{
evt
.
preventDefault
();
!
options
.
dropBubble
&&
evt
.
stopPropagation
();
}
ghostEl
&&
ghostEl
.
parentNode
.
removeChild
(
ghostEl
);
if
(
dragEl
)
{
if
(
this
.
nativeDraggable
)
{
_off
(
dragEl
,
'dragend'
,
this
);
}
_disableDraggable
(
dragEl
);
dragEl
.
style
[
'will-change'
]
=
''
;
// Remove class's
_toggleClass
(
dragEl
,
this
.
options
.
ghostClass
,
false
);
_toggleClass
(
dragEl
,
this
.
options
.
chosenClass
,
false
);
if
(
rootEl
!==
parentEl
)
{
newIndex
=
_index
(
dragEl
,
options
.
draggable
);
if
(
newIndex
>=
0
)
{
// Add event
_dispatchEvent
(
null
,
parentEl
,
'add'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
// Remove event
_dispatchEvent
(
this
,
rootEl
,
'remove'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
// drag from one list and drop into another
_dispatchEvent
(
null
,
parentEl
,
'sort'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
_dispatchEvent
(
this
,
rootEl
,
'sort'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
}
}
else
{
// Remove clone
cloneEl
&&
cloneEl
.
parentNode
.
removeChild
(
cloneEl
);
if
(
dragEl
.
nextSibling
!==
nextEl
)
{
// Get the index of the dragged element within its parent
newIndex
=
_index
(
dragEl
,
options
.
draggable
);
if
(
newIndex
>=
0
)
{
// drag & drop within the same list
_dispatchEvent
(
this
,
rootEl
,
'update'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
_dispatchEvent
(
this
,
rootEl
,
'sort'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
}
}
}
if
(
Sortable
.
active
)
{
/* jshint eqnull:true */
if
(
newIndex
==
null
||
newIndex
===
-
1
)
{
newIndex
=
oldIndex
;
}
_dispatchEvent
(
this
,
rootEl
,
'end'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
// Save sorting
this
.
save
();
}
}
}
this
.
_nulling
();
},
_nulling
:
function
()
{
rootEl
=
dragEl
=
parentEl
=
ghostEl
=
nextEl
=
cloneEl
=
scrollEl
=
scrollParentEl
=
tapEvt
=
touchEvt
=
moved
=
newIndex
=
lastEl
=
lastCSS
=
putSortable
=
activeGroup
=
Sortable
.
active
=
null
;
},
handleEvent
:
function
(
/**Event*/
evt
)
{
var
type
=
evt
.
type
;
if
(
type
===
'dragover'
||
type
===
'dragenter'
)
{
if
(
dragEl
)
{
this
.
_onDragOver
(
evt
);
_globalDragOver
(
evt
);
}
}
else
if
(
type
===
'drop'
||
type
===
'dragend'
)
{
this
.
_onDrop
(
evt
);
}
},
/**
* Serializes the item into an array of string.
* @returns {String[]}
*/
toArray
:
function
()
{
var
order
=
[],
el
,
children
=
this
.
el
.
children
,
i
=
0
,
n
=
children
.
length
,
options
=
this
.
options
;
for
(;
i
<
n
;
i
++
)
{
el
=
children
[
i
];
if
(
_closest
(
el
,
options
.
draggable
,
this
.
el
))
{
order
.
push
(
el
.
getAttribute
(
options
.
dataIdAttr
)
||
_generateId
(
el
));
}
}
return
order
;
},
/**
* Sorts the elements according to the array.
* @param {String[]} order order of the items
*/
sort
:
function
(
order
)
{
var
items
=
{},
rootEl
=
this
.
el
;
this
.
toArray
().
forEach
(
function
(
id
,
i
)
{
var
el
=
rootEl
.
children
[
i
];
if
(
_closest
(
el
,
this
.
options
.
draggable
,
rootEl
))
{
items
[
id
]
=
el
;
}
},
this
);
order
.
forEach
(
function
(
id
)
{
if
(
items
[
id
])
{
rootEl
.
removeChild
(
items
[
id
]);
rootEl
.
appendChild
(
items
[
id
]);
}
});
},
/**
* Save the current sorting
*/
save
:
function
()
{
var
store
=
this
.
options
.
store
;
store
&&
store
.
set
(
this
);
},
/**
* 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.
* @param {HTMLElement} el
* @param {String} [selector] default: `options.draggable`
* @returns {HTMLElement|null}
*/
closest
:
function
(
el
,
selector
)
{
return
_closest
(
el
,
selector
||
this
.
options
.
draggable
,
this
.
el
);
},
/**
* Set/get option
* @param {string} name
* @param {*} [value]
* @returns {*}
*/
option
:
function
(
name
,
value
)
{
var
options
=
this
.
options
;
if
(
value
===
void
0
)
{
return
options
[
name
];
}
else
{
options
[
name
]
=
value
;
if
(
name
===
'group'
)
{
_prepareGroup
(
options
);
}
}
},
/**
* Destroy
*/
destroy
:
function
()
{
var
el
=
this
.
el
;
el
[
expando
]
=
null
;
_off
(
el
,
'mousedown'
,
this
.
_onTapStart
);
_off
(
el
,
'touchstart'
,
this
.
_onTapStart
);
if
(
this
.
nativeDraggable
)
{
_off
(
el
,
'dragover'
,
this
);
_off
(
el
,
'dragenter'
,
this
);
}
// Remove draggable attributes
Array
.
prototype
.
forEach
.
call
(
el
.
querySelectorAll
(
'[draggable]'
),
function
(
el
)
{
el
.
removeAttribute
(
'draggable'
);
});
touchDragOverListeners
.
splice
(
touchDragOverListeners
.
indexOf
(
this
.
_onDragOver
),
1
);
this
.
_onDrop
();
this
.
el
=
el
=
null
;
}
};
function
_cloneHide
(
state
)
{
if
(
cloneEl
&&
(
cloneEl
.
state
!==
state
))
{
_css
(
cloneEl
,
'display'
,
state
?
'none'
:
''
);
!
state
&&
cloneEl
.
state
&&
rootEl
.
insertBefore
(
cloneEl
,
dragEl
);
cloneEl
.
state
=
state
;
}
}
function
_closest
(
/**HTMLElement*/
el
,
/**String*/
selector
,
/**HTMLElement*/
ctx
)
{
if
(
el
)
{
ctx
=
ctx
||
document
;
do
{
if
((
selector
===
'>*'
&&
el
.
parentNode
===
ctx
)
||
_matches
(
el
,
selector
))
{
return
el
;
}
/* jshint boss:true */
}
while
(
el
=
_getParentOrHost
(
el
));
}
return
null
;
}
function
_getParentOrHost
(
el
)
{
var
parent
=
el
.
host
;
return
(
parent
&&
parent
.
nodeType
)
?
parent
:
el
.
parentNode
;
}
function
_globalDragOver
(
/**Event*/
evt
)
{
if
(
evt
.
dataTransfer
)
{
evt
.
dataTransfer
.
dropEffect
=
'move'
;
}
evt
.
preventDefault
();
}
function
_on
(
el
,
event
,
fn
)
{
el
.
addEventListener
(
event
,
fn
,
false
);
}
function
_off
(
el
,
event
,
fn
)
{
el
.
removeEventListener
(
event
,
fn
,
false
);
}
function
_toggleClass
(
el
,
name
,
state
)
{
if
(
el
)
{
if
(
el
.
classList
)
{
el
.
classList
[
state
?
'add'
:
'remove'
](
name
);
}
else
{
var
className
=
(
' '
+
el
.
className
+
' '
).
replace
(
RSPACE
,
' '
).
replace
(
' '
+
name
+
' '
,
' '
);
el
.
className
=
(
className
+
(
state
?
' '
+
name
:
''
)).
replace
(
RSPACE
,
' '
);
}
}
}
function
_css
(
el
,
prop
,
val
)
{
var
style
=
el
&&
el
.
style
;
if
(
style
)
{
if
(
val
===
void
0
)
{
if
(
document
.
defaultView
&&
document
.
defaultView
.
getComputedStyle
)
{
val
=
document
.
defaultView
.
getComputedStyle
(
el
,
''
);
}
else
if
(
el
.
currentStyle
)
{
val
=
el
.
currentStyle
;
}
return
prop
===
void
0
?
val
:
val
[
prop
];
}
else
{
if
(
!
(
prop
in
style
))
{
prop
=
'-webkit-'
+
prop
;
}
style
[
prop
]
=
val
+
(
typeof
val
===
'string'
?
''
:
'px'
);
}
}
}
function
_find
(
ctx
,
tagName
,
iterator
)
{
if
(
ctx
)
{
var
list
=
ctx
.
getElementsByTagName
(
tagName
),
i
=
0
,
n
=
list
.
length
;
if
(
iterator
)
{
for
(;
i
<
n
;
i
++
)
{
iterator
(
list
[
i
],
i
);
}
}
return
list
;
}
return
[];
}
function
_dispatchEvent
(
sortable
,
rootEl
,
name
,
targetEl
,
fromEl
,
startIndex
,
newIndex
)
{
sortable
=
(
sortable
||
rootEl
[
expando
]);
var
evt
=
document
.
createEvent
(
'Event'
),
options
=
sortable
.
options
,
onName
=
'on'
+
name
.
charAt
(
0
).
toUpperCase
()
+
name
.
substr
(
1
);
evt
.
initEvent
(
name
,
true
,
true
);
evt
.
to
=
rootEl
;
evt
.
from
=
fromEl
||
rootEl
;
evt
.
item
=
targetEl
||
rootEl
;
evt
.
clone
=
cloneEl
;
evt
.
oldIndex
=
startIndex
;
evt
.
newIndex
=
newIndex
;
rootEl
.
dispatchEvent
(
evt
);
if
(
options
[
onName
])
{
options
[
onName
].
call
(
sortable
,
evt
);
}
}
function
_onMove
(
fromEl
,
toEl
,
dragEl
,
dragRect
,
targetEl
,
targetRect
,
originalEvt
)
{
var
evt
,
sortable
=
fromEl
[
expando
],
onMoveFn
=
sortable
.
options
.
onMove
,
retVal
;
evt
=
document
.
createEvent
(
'Event'
);
evt
.
initEvent
(
'move'
,
true
,
true
);
evt
.
to
=
toEl
;
evt
.
from
=
fromEl
;
evt
.
dragged
=
dragEl
;
evt
.
draggedRect
=
dragRect
;
evt
.
related
=
targetEl
||
toEl
;
evt
.
relatedRect
=
targetRect
||
toEl
.
getBoundingClientRect
();
fromEl
.
dispatchEvent
(
evt
);
if
(
onMoveFn
)
{
retVal
=
onMoveFn
.
call
(
sortable
,
evt
,
originalEvt
);
}
return
retVal
;
}
function
_disableDraggable
(
el
)
{
el
.
draggable
=
false
;
}
function
_unsilent
()
{
_silent
=
false
;
}
/** @returns {HTMLElement|false} */
function
_ghostIsLast
(
el
,
evt
)
{
var
lastEl
=
el
.
lastElementChild
,
rect
=
lastEl
.
getBoundingClientRect
();
// 5 — min delta
// abs — нельзя добавлять, а то глюки при наведении сверху
return
(
(
evt
.
clientY
-
(
rect
.
top
+
rect
.
height
)
>
5
)
||
(
evt
.
clientX
-
(
rect
.
right
+
rect
.
width
)
>
5
)
)
&&
lastEl
;
}
/**
* Generate id
* @param {HTMLElement} el
* @returns {String}
* @private
*/
function
_generateId
(
el
)
{
var
str
=
el
.
tagName
+
el
.
className
+
el
.
src
+
el
.
href
+
el
.
textContent
,
i
=
str
.
length
,
sum
=
0
;
while
(
i
--
)
{
sum
+=
str
.
charCodeAt
(
i
);
}
return
sum
.
toString
(
36
);
}
/**
* Returns the index of an element within its parent for a selected set of
* elements
* @param {HTMLElement} el
* @param {selector} selector
* @return {number}
*/
function
_index
(
el
,
selector
)
{
var
index
=
0
;
if
(
!
el
||
!
el
.
parentNode
)
{
return
-
1
;
}
while
(
el
&&
(
el
=
el
.
previousElementSibling
))
{
if
((
el
.
nodeName
.
toUpperCase
()
!==
'TEMPLATE'
)
&&
(
selector
===
'>*'
||
_matches
(
el
,
selector
)))
{
index
++
;
}
}
return
index
;
}
function
_matches
(
/**HTMLElement*/
el
,
/**String*/
selector
)
{
if
(
el
)
{
selector
=
selector
.
split
(
'.'
);
var
tag
=
selector
.
shift
().
toUpperCase
(),
re
=
new
RegExp
(
'
\\
s('
+
selector
.
join
(
'|'
)
+
')(?=
\\
s)'
,
'g'
);
return
(
(
tag
===
''
||
el
.
nodeName
.
toUpperCase
()
==
tag
)
&&
(
!
selector
.
length
||
((
' '
+
el
.
className
+
' '
).
match
(
re
)
||
[]).
length
==
selector
.
length
)
);
}
return
false
;
}
function
_throttle
(
callback
,
ms
)
{
var
args
,
_this
;
return
function
()
{
if
(
args
===
void
0
)
{
args
=
arguments
;
_this
=
this
;
setTimeout
(
function
()
{
if
(
args
.
length
===
1
)
{
callback
.
call
(
_this
,
args
[
0
]);
}
else
{
callback
.
apply
(
_this
,
args
);
}
args
=
void
0
;
},
ms
);
}
};
}
function
_extend
(
dst
,
src
)
{
if
(
dst
&&
src
)
{
for
(
var
key
in
src
)
{
if
(
src
.
hasOwnProperty
(
key
))
{
dst
[
key
]
=
src
[
key
];
}
}
}
return
dst
;
}
function
_clone
(
el
)
{
return
$
?
$
(
el
).
clone
(
true
)[
0
]
:
(
Polymer
&&
Polymer
.
dom
?
Polymer
.
dom
(
el
).
cloneNode
(
true
)
:
el
.
cloneNode
(
true
)
);
}
// Export utils
Sortable
.
utils
=
{
on
:
_on
,
off
:
_off
,
css
:
_css
,
find
:
_find
,
is
:
function
(
el
,
selector
)
{
return
!!
_closest
(
el
,
selector
,
el
);
},
extend
:
_extend
,
throttle
:
_throttle
,
closest
:
_closest
,
toggleClass
:
_toggleClass
,
clone
:
_clone
,
index
:
_index
};
/**
* Create sortable instance
* @param {HTMLElement} el
* @param {Object} [options]
*/
Sortable
.
create
=
function
(
el
,
options
)
{
return
new
Sortable
(
el
,
options
);
};
// Export
Sortable
.
version
=
'1.4.2'
;
return
Sortable
;
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment