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
Jérome Perrin
gitlab-ce
Commits
dec43760
Commit
dec43760
authored
Oct 07, 2016
by
Phil Hughes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated Sortable JS plugin
Fixes an issue in Safari that stops issues from being draggable Closes #23048
parent
b328c788
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
149 additions
and
55 deletions
+149
-55
CHANGELOG.md
CHANGELOG.md
+1
-0
app/assets/stylesheets/pages/boards.scss
app/assets/stylesheets/pages/boards.scss
+4
-0
vendor/assets/javascripts/Sortable.js
vendor/assets/javascripts/Sortable.js
+144
-55
No files found.
CHANGELOG.md
View file @
dec43760
...
...
@@ -22,6 +22,7 @@ Please view this file on the master branch, on stable branches it's out of date.
-
Escape ref and path for relative links !6050 (winniehell)
-
Fixed link typo on /help/ui to Alerts section. !6915 (Sam Rose)
-
Fix filtering of milestones with quotes in title (airatshigapov)
-
Fix issue boards dragging bug in Safari
-
Refactor less readable existance checking code from CoffeeScript !6289 (jlogandavison)
-
Update mail_room and enable sentinel support to Reply By Email (!7101)
-
Add task completion status in Issues and Merge Requests tabs: "X of Y tasks completed" (!6527, @gmesalazar)
...
...
app/assets/stylesheets/pages/boards.scss
View file @
dec43760
...
...
@@ -12,6 +12,10 @@
opacity
:
1
!
important
;
*
{
-webkit-user-select
:
none
;
-moz-user-select
:
none
;
-ms-user-select
:
none
;
user-select
:
none
;
// !important to make sure no style can override this when dragging
cursor
:
-
webkit-grabbing
!
important
;
cursor
:
grabbing
!
important
;
...
...
vendor/assets/javascripts/Sortable.js
View file @
dec43760
...
...
@@ -4,8 +4,7 @@
* @license MIT
*/
(
function
(
factory
)
{
(
function
sortableModule
(
factory
)
{
"
use strict
"
;
if
(
typeof
define
===
"
function
"
&&
define
.
amd
)
{
...
...
@@ -15,15 +14,22 @@
module
.
exports
=
factory
();
}
else
if
(
typeof
Package
!==
"
undefined
"
)
{
//noinspection JSUnresolvedVariable
Sortable
=
factory
();
// export for Meteor.js
}
else
{
/* jshint sub:true */
window
[
"
Sortable
"
]
=
factory
();
}
})(
function
()
{
})(
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
,
...
...
@@ -33,6 +39,7 @@
scrollEl
,
scrollParentEl
,
scrollCustomFn
,
lastEl
,
lastCSS
,
...
...
@@ -42,6 +49,8 @@
newIndex
,
activeGroup
,
putSortable
,
autoScroll
=
{},
tapEvt
,
...
...
@@ -58,8 +67,15 @@
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
'
;
...
...
@@ -88,13 +104,17 @@
winHeight
=
window
.
innerHeight
,
vx
,
vy
vy
,
scrollOffsetX
,
scrollOffsetY
;
// Delect scrollEl
if
(
scrollParentEl
!==
rootEl
)
{
scrollEl
=
options
.
scroll
;
scrollParentEl
=
rootEl
;
scrollCustomFn
=
options
.
scrollFn
;
if
(
scrollEl
===
true
)
{
scrollEl
=
rootEl
;
...
...
@@ -136,11 +156,18 @@
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
+
vx
*
speed
,
win
.
pageYOffset
+
vy
*
speed
);
win
.
scrollTo
(
win
.
pageXOffset
+
scrollOffsetX
,
win
.
pageYOffset
+
scrollOffsetY
);
}
else
{
vy
&&
(
el
.
scrollTop
+=
vy
*
speed
)
;
vx
&&
(
el
.
scrollLeft
+=
vx
*
speed
)
;
el
.
scrollTop
+=
scrollOffsetY
;
el
.
scrollLeft
+=
scrollOffsetX
;
}
},
24
);
}
...
...
@@ -149,19 +176,39 @@
},
30
),
_prepareGroup
=
function
(
options
)
{
var
group
=
options
.
group
;
function
toFn
(
value
,
pull
)
{
if
(
value
===
void
0
||
value
===
true
)
{
value
=
group
.
name
;
}
if
(
!
group
||
typeof
group
!=
'
object
'
)
{
group
=
options
.
group
=
{
name
:
group
};
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
)
);
};
}
}
[
'
pull
'
,
'
put
'
].
forEach
(
function
(
key
)
{
if
(
!
(
key
in
group
))
{
group
[
key
]
=
true
;
}
});
var
group
=
{};
var
originalGroup
=
options
.
group
;
if
(
!
originalGroup
||
typeof
originalGroup
!=
'
object
'
)
{
originalGroup
=
{
name
:
originalGroup
};
}
options
.
groups
=
'
'
+
group
.
name
+
(
group
.
put
.
join
?
'
'
+
group
.
put
.
join
(
'
'
)
:
''
)
+
'
'
;
group
.
name
=
originalGroup
.
name
;
group
.
checkPull
=
toFn
(
originalGroup
.
pull
,
true
);
group
.
checkPut
=
toFn
(
originalGroup
.
put
);
options
.
group
=
group
;
}
;
...
...
@@ -198,6 +245,7 @@
draggable
:
/
[
uo
]
l/i
.
test
(
el
.
nodeName
)
?
'
li
'
:
'
>*
'
,
ghostClass
:
'
sortable-ghost
'
,
chosenClass
:
'
sortable-chosen
'
,
dragClass
:
'
sortable-drag
'
,
ignore
:
'
a, img
'
,
filter
:
null
,
animation
:
0
,
...
...
@@ -211,7 +259,8 @@
forceFallback
:
false
,
fallbackClass
:
'
sortable-fallback
'
,
fallbackOnBody
:
false
,
fallbackTolerance
:
0
fallbackTolerance
:
0
,
fallbackOffset
:
{
x
:
0
,
y
:
0
}
};
...
...
@@ -224,7 +273,7 @@
// Bind all private methods
for
(
var
fn
in
this
)
{
if
(
fn
.
charAt
(
0
)
===
'
_
'
)
{
if
(
fn
.
charAt
(
0
)
===
'
_
'
&&
typeof
this
[
fn
]
===
'
function
'
)
{
this
[
fn
]
=
this
[
fn
].
bind
(
this
);
}
}
...
...
@@ -258,7 +307,7 @@
type
=
evt
.
type
,
touch
=
evt
.
touches
&&
evt
.
touches
[
0
],
target
=
(
touch
||
evt
).
target
,
originalTarget
=
target
,
originalTarget
=
evt
.
target
.
shadowRoot
&&
evt
.
path
[
0
]
||
target
,
filter
=
options
.
filter
,
startIndex
;
...
...
@@ -271,13 +320,13 @@
return
;
// only left button or enabled
}
target
=
_closest
(
target
,
options
.
draggable
,
el
);
if
(
!
target
)
{
if
(
options
.
handle
&&
!
_closest
(
originalTarget
,
options
.
handle
,
el
))
{
return
;
}
if
(
options
.
handle
&&
!
_closest
(
originalTarget
,
options
.
handle
,
el
))
{
target
=
_closest
(
target
,
options
.
draggable
,
el
);
if
(
!
target
)
{
return
;
}
...
...
@@ -332,16 +381,18 @@
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
=
tru
e
;
dragEl
.
draggable
=
_this
.
nativeDraggabl
e
;
// Chosen item
_toggleClass
(
dragEl
,
_this
.
options
.
chosenClass
,
true
);
_toggleClass
(
dragEl
,
options
.
chosenClass
,
true
);
// Bind the events: dragstart/dragend
_this
.
_triggerDragStart
(
touch
);
...
...
@@ -408,7 +459,10 @@
try
{
if
(
document
.
selection
)
{
document
.
selection
.
empty
();
// Timeout neccessary for IE9
setTimeout
(
function
()
{
document
.
selection
.
empty
();
});
}
else
{
window
.
getSelection
().
removeAllRanges
();
}
...
...
@@ -418,8 +472,11 @@
_dragStarted
:
function
()
{
if
(
rootEl
&&
dragEl
)
{
var
options
=
this
.
options
;
// Apply effect
_toggleClass
(
dragEl
,
this
.
options
.
ghostClass
,
true
);
_toggleClass
(
dragEl
,
options
.
ghostClass
,
true
);
_toggleClass
(
dragEl
,
options
.
dragClass
,
false
);
Sortable
.
active
=
this
;
...
...
@@ -443,12 +500,11 @@
var
target
=
document
.
elementFromPoint
(
touchEvt
.
clientX
,
touchEvt
.
clientY
),
parent
=
target
,
groupName
=
'
'
+
this
.
options
.
group
.
name
+
''
,
i
=
touchDragOverListeners
.
length
;
if
(
parent
)
{
do
{
if
(
parent
[
expando
]
&&
parent
[
expando
].
options
.
groups
.
indexOf
(
groupName
)
>
-
1
)
{
if
(
parent
[
expando
])
{
while
(
i
--
)
{
touchDragOverListeners
[
i
]({
clientX
:
touchEvt
.
clientX
,
...
...
@@ -478,9 +534,10 @@
if
(
tapEvt
)
{
var
options
=
this
.
options
,
fallbackTolerance
=
options
.
fallbackTolerance
,
fallbackOffset
=
options
.
fallbackOffset
,
touch
=
evt
.
touches
?
evt
.
touches
[
0
]
:
evt
,
dx
=
touch
.
clientX
-
tapEvt
.
clientX
,
dy
=
touch
.
clientY
-
tapEvt
.
clientY
,
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
...
...
@@ -520,6 +577,7 @@
_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
));
...
...
@@ -545,13 +603,15 @@
this
.
_offUpEvents
();
if
(
activeGroup
.
pull
==
'
clone
'
)
{
cloneEl
=
dragEl
.
cloneNode
(
true
);
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
...
...
@@ -581,10 +641,11 @@
var
el
=
this
.
el
,
target
,
dragRect
,
targetRect
,
revert
,
options
=
this
.
options
,
group
=
options
.
group
,
groupPut
=
group
.
put
,
activeSortable
=
Sortable
.
active
,
isOwner
=
(
activeGroup
===
group
),
canSort
=
options
.
sort
;
...
...
@@ -598,9 +659,9 @@
if
(
activeGroup
&&
!
options
.
disabled
&&
(
isOwner
?
canSort
||
(
revert
=
!
rootEl
.
contains
(
dragEl
))
// Reverting item into the original list
:
activeGroup
.
pull
&&
groupPut
&&
(
(
activeGroup
.
name
===
group
.
name
)
||
// by Name
(
groupPut
.
indexOf
&&
~
groupPut
.
indexOf
(
activeGroup
.
name
))
// by Array
:
(
putSortable
===
this
||
activeGroup
.
checkPull
(
this
,
activeSortable
,
dragEl
,
evt
)
&&
group
.
checkPut
(
this
,
activeSortable
,
dragEl
,
evt
)
)
)
&&
(
evt
.
rootEl
===
void
0
||
evt
.
rootEl
===
this
.
el
)
// touch fallback
...
...
@@ -614,6 +675,7 @@
target
=
_closest
(
evt
.
target
,
options
.
draggable
,
el
);
dragRect
=
dragEl
.
getBoundingClientRect
();
putSortable
=
this
;
if
(
revert
)
{
_cloneHide
(
true
);
...
...
@@ -633,7 +695,6 @@
if
((
el
.
children
.
length
===
0
)
||
(
el
.
children
[
0
]
===
ghostEl
)
||
(
el
===
evt
.
target
)
&&
(
target
=
_ghostIsLast
(
el
,
evt
))
)
{
if
(
target
)
{
if
(
target
.
animated
)
{
return
;
...
...
@@ -644,7 +705,7 @@
_cloneHide
(
isOwner
);
if
(
_onMove
(
rootEl
,
el
,
dragEl
,
dragRect
,
target
,
targetRect
)
!==
false
)
{
if
(
_onMove
(
rootEl
,
el
,
dragEl
,
dragRect
,
target
,
targetRect
,
evt
)
!==
false
)
{
if
(
!
dragEl
.
contains
(
el
))
{
el
.
appendChild
(
dragEl
);
parentEl
=
el
;
// actualization
...
...
@@ -661,9 +722,9 @@
lastParentCSS
=
_css
(
target
.
parentNode
);
}
targetRect
=
target
.
getBoundingClientRect
();
var
targetRect
=
target
.
getBoundingClientRect
(),
width
=
targetRect
.
right
-
targetRect
.
left
,
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
),
...
...
@@ -671,7 +732,7 @@
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
),
moveVector
=
_onMove
(
rootEl
,
el
,
dragEl
,
dragRect
,
target
,
targetRect
,
evt
),
after
;
...
...
@@ -784,6 +845,7 @@
}
_disableDraggable
(
dragEl
);
dragEl
.
style
[
'
will-change
'
]
=
''
;
// Remove class's
_toggleClass
(
dragEl
,
this
.
options
.
ghostClass
,
false
);
...
...
@@ -793,15 +855,16 @@
newIndex
=
_index
(
dragEl
,
options
.
draggable
);
if
(
newIndex
>=
0
)
{
// drag from one list and drop into another
_dispatchEvent
(
null
,
parentEl
,
'
sort
'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
_dispatchEvent
(
this
,
rootEl
,
'
sort
'
,
dragEl
,
rootEl
,
oldIndex
,
newIndex
);
// 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
{
...
...
@@ -821,7 +884,8 @@
}
if
(
Sortable
.
active
)
{
if
(
newIndex
===
null
||
newIndex
===
-
1
)
{
/* jshint eqnull:true */
if
(
newIndex
==
null
||
newIndex
===
-
1
)
{
newIndex
=
oldIndex
;
}
...
...
@@ -837,7 +901,7 @@
this
.
_nulling
();
},
_nulling
:
function
()
{
_nulling
:
function
()
{
rootEl
=
dragEl
=
parentEl
=
...
...
@@ -857,6 +921,7 @@
lastEl
=
lastCSS
=
putSortable
=
activeGroup
=
Sortable
.
active
=
null
;
},
...
...
@@ -1011,14 +1076,21 @@
if
((
selector
===
'
>*
'
&&
el
.
parentNode
===
ctx
)
||
_matches
(
el
,
selector
))
{
return
el
;
}
}
while
(
el
!==
ctx
&&
(
el
=
el
.
parentNode
));
/* 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
'
;
...
...
@@ -1094,8 +1166,10 @@
function
_dispatchEvent
(
sortable
,
rootEl
,
name
,
targetEl
,
fromEl
,
startIndex
,
newIndex
)
{
sortable
=
(
sortable
||
rootEl
[
expando
]);
var
evt
=
document
.
createEvent
(
'
Event
'
),
options
=
(
sortable
||
rootEl
[
expando
])
.
options
,
options
=
sortable
.
options
,
onName
=
'
on
'
+
name
.
charAt
(
0
).
toUpperCase
()
+
name
.
substr
(
1
);
evt
.
initEvent
(
name
,
true
,
true
);
...
...
@@ -1116,7 +1190,7 @@
}
function
_onMove
(
fromEl
,
toEl
,
dragEl
,
dragRect
,
targetEl
,
targetRect
)
{
function
_onMove
(
fromEl
,
toEl
,
dragEl
,
dragRect
,
targetEl
,
targetRect
,
originalEvt
)
{
var
evt
,
sortable
=
fromEl
[
expando
],
onMoveFn
=
sortable
.
options
.
onMove
,
...
...
@@ -1135,7 +1209,7 @@
fromEl
.
dispatchEvent
(
evt
);
if
(
onMoveFn
)
{
retVal
=
onMoveFn
.
call
(
sortable
,
evt
);
retVal
=
onMoveFn
.
call
(
sortable
,
evt
,
originalEvt
);
}
return
retVal
;
...
...
@@ -1155,9 +1229,14 @@
/** @returns {HTMLElement|false} */
function
_ghostIsLast
(
el
,
evt
)
{
var
lastEl
=
el
.
lastElementChild
,
rect
=
lastEl
.
getBoundingClientRect
();
return
((
evt
.
clientY
-
(
rect
.
top
+
rect
.
height
)
>
5
)
||
(
evt
.
clientX
-
(
rect
.
right
+
rect
.
width
)
>
5
))
&&
lastEl
;
// min delta
rect
=
lastEl
.
getBoundingClientRect
();
// 5 — min delta
// abs — нельзя добавлять, а то глюки при наведении сверху
return
(
(
evt
.
clientY
-
(
rect
.
top
+
rect
.
height
)
>
5
)
||
(
evt
.
clientX
-
(
rect
.
right
+
rect
.
width
)
>
5
)
)
&&
lastEl
;
}
...
...
@@ -1251,6 +1330,15 @@
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
=
{
...
...
@@ -1265,6 +1353,7 @@
throttle
:
_throttle
,
closest
:
_closest
,
toggleClass
:
_toggleClass
,
clone
:
_clone
,
index
:
_index
};
...
...
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