Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
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
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
0 additions
and
1374 deletions
+0
-1374
vendor/assets/javascripts/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