Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
cdn
Overview
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
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lambda
cdn
Commits
06ee95f0
Commit
06ee95f0
authored
Jul 06, 2016
by
TingSong-Syu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add jquery-sortable 0.9.13
parent
0252e70f
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
712 additions
and
0 deletions
+712
-0
jquery-sortable-min.js
jquery-sortable/0.9.13/jquery-sortable-min.js
+19
-0
jquery-sortable.js
jquery-sortable/0.9.13/jquery-sortable.js
+693
-0
No files found.
jquery-sortable/0.9.13/jquery-sortable-min.js
0 → 100644
View file @
06ee95f0
!
function
(
d
,
B
,
m
,
f
){
function
v
(
a
,
b
){
var
c
=
Math
.
max
(
0
,
a
[
0
]
-
b
[
0
],
b
[
0
]
-
a
[
1
]),
e
=
Math
.
max
(
0
,
a
[
2
]
-
b
[
1
],
b
[
1
]
-
a
[
3
]);
return
c
+
e
}
function
w
(
a
,
b
,
c
,
e
){
var
k
=
a
.
length
;
e
=
e
?
"offset"
:
"position"
;
for
(
c
=
c
||
0
;
k
--
;){
var
g
=
a
[
k
].
el
?
a
[
k
].
el
:
d
(
a
[
k
]),
l
=
g
[
e
]();
l
.
left
+=
parseInt
(
g
.
css
(
"margin-left"
),
10
);
l
.
top
+=
parseInt
(
g
.
css
(
"margin-top"
),
10
);
b
[
k
]
=
[
l
.
left
-
c
,
l
.
left
+
g
.
outerWidth
()
+
c
,
l
.
top
-
c
,
l
.
top
+
g
.
outerHeight
()
+
c
]}}
function
p
(
a
,
b
){
var
c
=
b
.
offset
();
return
{
left
:
a
.
left
-
c
.
left
,
top
:
a
.
top
-
c
.
top
}}
function
x
(
a
,
b
,
c
){
b
=
[
b
.
left
,
b
.
top
];
c
=
c
&&
[
c
.
left
,
c
.
top
];
for
(
var
e
,
k
=
a
.
length
,
d
=
[];
k
--
;)
e
=
a
[
k
],
d
[
k
]
=
[
k
,
v
(
e
,
b
),
c
&&
v
(
e
,
c
)];
return
d
=
d
.
sort
(
function
(
a
,
b
){
return
b
[
1
]
-
a
[
1
]
||
b
[
2
]
-
a
[
2
]
||
b
[
0
]
-
a
[
0
]})}
function
q
(
a
){
this
.
options
=
d
.
extend
({},
n
,
a
);
this
.
containers
=
[];
this
.
options
.
rootGroup
||
(
this
.
scrollProxy
=
d
.
proxy
(
this
.
scroll
,
this
),
this
.
dragProxy
=
d
.
proxy
(
this
.
drag
,
this
),
this
.
dropProxy
=
d
.
proxy
(
this
.
drop
,
this
),
this
.
placeholder
=
d
(
this
.
options
.
placeholder
),
a
.
isValidTarget
||
(
this
.
options
.
isValidTarget
=
f
))}
function
t
(
a
,
b
){
this
.
el
=
a
;
this
.
options
=
d
.
extend
({},
z
,
b
);
this
.
group
=
q
.
get
(
this
.
options
);
this
.
rootGroup
=
this
.
options
.
rootGroup
||
this
.
group
;
this
.
handle
=
this
.
rootGroup
.
options
.
handle
||
this
.
rootGroup
.
options
.
itemSelector
;
var
c
=
this
.
rootGroup
.
options
.
itemPath
;
this
.
target
=
c
?
this
.
el
.
find
(
c
):
this
.
el
;
this
.
target
.
on
(
r
.
start
,
this
.
handle
,
d
.
proxy
(
this
.
dragInit
,
this
));
this
.
options
.
drop
&&
this
.
group
.
containers
.
push
(
this
)}
var
r
,
z
=
{
drag
:
!
0
,
drop
:
!
0
,
exclude
:
""
,
nested
:
!
0
,
vertical
:
!
0
},
n
=
{
afterMove
:
function
(
a
,
b
,
c
){},
containerPath
:
""
,
containerSelector
:
"ol, ul"
,
distance
:
0
,
delay
:
0
,
handle
:
""
,
itemPath
:
""
,
itemSelector
:
"li"
,
bodyClass
:
"dragging"
,
draggedClass
:
"dragged"
,
isValidTarget
:
function
(
a
,
b
){
return
!
0
},
onCancel
:
function
(
a
,
b
,
c
,
e
){},
onDrag
:
function
(
a
,
b
,
c
,
e
){
a
.
css
(
b
)},
onDragStart
:
function
(
a
,
b
,
c
,
e
){
a
.
css
({
height
:
a
.
outerHeight
(),
width
:
a
.
outerWidth
()});
a
.
addClass
(
b
.
group
.
options
.
draggedClass
);
d
(
"body"
).
addClass
(
b
.
group
.
options
.
bodyClass
)},
onDrop
:
function
(
a
,
b
,
c
,
e
){
a
.
removeClass
(
b
.
group
.
options
.
draggedClass
).
removeAttr
(
"style"
);
d
(
"body"
).
removeClass
(
b
.
group
.
options
.
bodyClass
)},
onMousedown
:
function
(
a
,
b
,
c
){
if
(
!
c
.
target
.
nodeName
.
match
(
/^
(
input|select|textarea
)
$/i
))
return
c
.
preventDefault
(),
!
0
},
placeholderClass
:
"placeholder"
,
placeholder
:
'<li class="placeholder"></li>'
,
pullPlaceholder
:
!
0
,
serialize
:
function
(
a
,
b
,
c
){
a
=
d
.
extend
({},
a
.
data
());
if
(
c
)
return
[
b
];
b
[
0
]
&&
(
a
.
children
=
b
);
delete
a
.
subContainers
;
delete
a
.
sortable
;
return
a
},
tolerance
:
0
},
s
=
{},
y
=
0
,
A
=
{
left
:
0
,
top
:
0
,
bottom
:
0
,
right
:
0
};
r
=
{
start
:
"touchstart.sortable mousedown.sortable"
,
drop
:
"touchend.sortable touchcancel.sortable mouseup.sortable"
,
drag
:
"touchmove.sortable mousemove.sortable"
,
scroll
:
"scroll.sortable"
};
q
.
get
=
function
(
a
){
s
[
a
.
group
]
||
(
a
.
group
===
f
&&
(
a
.
group
=
y
++
),
s
[
a
.
group
]
=
new
q
(
a
));
return
s
[
a
.
group
]};
q
.
prototype
=
{
dragInit
:
function
(
a
,
b
){
this
.
$document
=
d
(
b
.
el
[
0
].
ownerDocument
);
var
c
=
d
(
a
.
target
).
closest
(
this
.
options
.
itemSelector
);
c
.
length
&&
(
this
.
item
=
c
,
this
.
itemContainer
=
b
,
!
this
.
item
.
is
(
this
.
options
.
exclude
)
&&
this
.
options
.
onMousedown
(
this
.
item
,
n
.
onMousedown
,
a
)
&&
(
this
.
setPointer
(
a
),
this
.
toggleListeners
(
"on"
),
this
.
setupDelayTimer
(),
this
.
dragInitDone
=!
0
))},
drag
:
function
(
a
){
if
(
!
this
.
dragging
){
if
(
!
this
.
distanceMet
(
a
)
||!
this
.
delayMet
)
return
;
this
.
options
.
onDragStart
(
this
.
item
,
this
.
itemContainer
,
n
.
onDragStart
,
a
);
this
.
item
.
before
(
this
.
placeholder
);
this
.
dragging
=!
0
}
this
.
setPointer
(
a
);
this
.
options
.
onDrag
(
this
.
item
,
p
(
this
.
pointer
,
this
.
item
.
offsetParent
()),
n
.
onDrag
,
a
);
a
=
this
.
getPointer
(
a
);
var
b
=
this
.
sameResultBox
,
c
=
this
.
options
.
tolerance
;(
!
b
||
b
.
top
-
c
>
a
.
top
||
b
.
bottom
+
c
<
a
.
top
||
b
.
left
-
c
>
a
.
left
||
b
.
right
+
c
<
a
.
left
)
&&!
this
.
searchValidTarget
()
&&
(
this
.
placeholder
.
detach
(),
this
.
lastAppendedItem
=
f
)},
drop
:
function
(
a
){
this
.
toggleListeners
(
"off"
);
this
.
dragInitDone
=!
1
;
if
(
this
.
dragging
){
if
(
this
.
placeholder
.
closest
(
"html"
)[
0
])
this
.
placeholder
.
before
(
this
.
item
).
detach
();
else
this
.
options
.
onCancel
(
this
.
item
,
this
.
itemContainer
,
n
.
onCancel
,
a
);
this
.
options
.
onDrop
(
this
.
item
,
this
.
getContainer
(
this
.
item
),
n
.
onDrop
,
a
);
this
.
clearDimensions
();
this
.
clearOffsetParent
();
this
.
lastAppendedItem
=
this
.
sameResultBox
=
f
;
this
.
dragging
=!
1
}},
searchValidTarget
:
function
(
a
,
b
){
a
||
(
a
=
this
.
relativePointer
||
this
.
pointer
,
b
=
this
.
lastRelativePointer
||
this
.
lastPointer
);
for
(
var
c
=
x
(
this
.
getContainerDimensions
(),
a
,
b
),
e
=
c
.
length
;
e
--
;){
var
d
=
c
[
e
][
0
];
if
(
!
c
[
e
][
1
]
||
this
.
options
.
pullPlaceholder
)
if
(
d
=
this
.
containers
[
d
],
!
d
.
disabled
){
if
(
!
this
.
$getOffsetParent
()){
var
g
=
d
.
getItemOffsetParent
();
a
=
p
(
a
,
g
);
b
=
p
(
b
,
g
)}
if
(
d
.
searchValidTarget
(
a
,
b
))
return
!
0
}}
this
.
sameResultBox
&&
(
this
.
sameResultBox
=
f
)},
movePlaceholder
:
function
(
a
,
b
,
c
,
e
){
var
d
=
this
.
lastAppendedItem
;
if
(
e
||!
d
||
d
[
0
]
!==
b
[
0
])
b
[
c
](
this
.
placeholder
),
this
.
lastAppendedItem
=
b
,
this
.
sameResultBox
=
e
,
this
.
options
.
afterMove
(
this
.
placeholder
,
a
,
b
)},
getContainerDimensions
:
function
(){
this
.
containerDimensions
||
w
(
this
.
containers
,
this
.
containerDimensions
=
[],
this
.
options
.
tolerance
,
!
this
.
$getOffsetParent
());
return
this
.
containerDimensions
},
getContainer
:
function
(
a
){
return
a
.
closest
(
this
.
options
.
containerSelector
).
data
(
m
)},
$getOffsetParent
:
function
(){
if
(
this
.
offsetParent
===
f
){
var
a
=
this
.
containers
.
length
-
1
,
b
=
this
.
containers
[
a
].
getItemOffsetParent
();
if
(
!
this
.
options
.
rootGroup
)
for
(;
a
--
;)
if
(
b
[
0
]
!=
this
.
containers
[
a
].
getItemOffsetParent
()[
0
]){
b
=!
1
;
break
}
this
.
offsetParent
=
b
}
return
this
.
offsetParent
},
setPointer
:
function
(
a
){
a
=
this
.
getPointer
(
a
);
if
(
this
.
$getOffsetParent
()){
var
b
=
p
(
a
,
this
.
$getOffsetParent
());
this
.
lastRelativePointer
=
this
.
relativePointer
;
this
.
relativePointer
=
b
}
this
.
lastPointer
=
this
.
pointer
;
this
.
pointer
=
a
},
distanceMet
:
function
(
a
){
a
=
this
.
getPointer
(
a
);
return
Math
.
max
(
Math
.
abs
(
this
.
pointer
.
left
-
a
.
left
),
Math
.
abs
(
this
.
pointer
.
top
-
a
.
top
))
>=
this
.
options
.
distance
},
getPointer
:
function
(
a
){
var
b
=
a
.
originalEvent
||
a
.
originalEvent
.
touches
&&
a
.
originalEvent
.
touches
[
0
];
return
{
left
:
a
.
pageX
||
b
.
pageX
,
top
:
a
.
pageY
||
b
.
pageY
}},
setupDelayTimer
:
function
(){
var
a
=
this
;
this
.
delayMet
=!
this
.
options
.
delay
;
this
.
delayMet
||
(
clearTimeout
(
this
.
_mouseDelayTimer
),
this
.
_mouseDelayTimer
=
setTimeout
(
function
(){
a
.
delayMet
=!
0
},
this
.
options
.
delay
))},
scroll
:
function
(
a
){
this
.
clearDimensions
();
this
.
clearOffsetParent
()},
toggleListeners
:
function
(
a
){
var
b
=
this
;
d
.
each
([
"drag"
,
"drop"
,
"scroll"
],
function
(
c
,
e
){
b
.
$document
[
a
](
r
[
e
],
b
[
e
+
"Proxy"
])})},
clearOffsetParent
:
function
(){
this
.
offsetParent
=
f
},
clearDimensions
:
function
(){
this
.
traverse
(
function
(
a
){
a
.
_clearDimensions
()})},
traverse
:
function
(
a
){
a
(
this
);
for
(
var
b
=
this
.
containers
.
length
;
b
--
;)
this
.
containers
[
b
].
traverse
(
a
)},
_clearDimensions
:
function
(){
this
.
containerDimensions
=
f
},
_destroy
:
function
(){
s
[
this
.
options
.
group
]
=
f
}};
t
.
prototype
=
{
dragInit
:
function
(
a
){
var
b
=
this
.
rootGroup
;
!
this
.
disabled
&&!
b
.
dragInitDone
&&
this
.
options
.
drag
&&
this
.
isValidDrag
(
a
)
&&
b
.
dragInit
(
a
,
this
)},
isValidDrag
:
function
(
a
){
return
1
==
a
.
which
||
"touchstart"
==
a
.
type
&&
1
==
a
.
originalEvent
.
touches
.
length
},
searchValidTarget
:
function
(
a
,
b
){
var
c
=
x
(
this
.
getItemDimensions
(),
a
,
b
),
e
=
c
.
length
,
d
=
this
.
rootGroup
,
g
=!
d
.
options
.
isValidTarget
||
d
.
options
.
isValidTarget
(
d
.
item
,
this
);
if
(
!
e
&&
g
)
return
d
.
movePlaceholder
(
this
,
this
.
target
,
"append"
),
!
0
;
for
(;
e
--
;)
if
(
d
=
c
[
e
][
0
],
!
c
[
e
][
1
]
&&
this
.
hasChildGroup
(
d
)){
if
(
this
.
getContainerGroup
(
d
).
searchValidTarget
(
a
,
b
))
return
!
0
}
else
if
(
g
)
return
this
.
movePlaceholder
(
d
,
a
),
!
0
},
movePlaceholder
:
function
(
a
,
b
){
var
c
=
d
(
this
.
items
[
a
]),
e
=
this
.
itemDimensions
[
a
],
k
=
"after"
,
g
=
c
.
outerWidth
(),
f
=
c
.
outerHeight
(),
h
=
c
.
offset
(),
h
=
{
left
:
h
.
left
,
right
:
h
.
left
+
g
,
top
:
h
.
top
,
bottom
:
h
.
top
+
f
};
this
.
options
.
vertical
?
b
.
top
<=
(
e
[
2
]
+
e
[
3
])
/
2
?(
k
=
"before"
,
h
.
bottom
-=
f
/
2
):
h
.
top
+=
f
/
2
:
b
.
left
<=
(
e
[
0
]
+
e
[
1
])
/
2
?(
k
=
"before"
,
h
.
right
-=
g
/
2
):
h
.
left
+=
g
/
2
;
this
.
hasChildGroup
(
a
)
&&
(
h
=
A
);
this
.
rootGroup
.
movePlaceholder
(
this
,
c
,
k
,
h
)},
getItemDimensions
:
function
(){
this
.
itemDimensions
||
(
this
.
items
=
this
.
$getChildren
(
this
.
el
,
"item"
).
filter
(
":not(."
+
this
.
group
.
options
.
placeholderClass
+
", ."
+
this
.
group
.
options
.
draggedClass
+
")"
).
get
(),
w
(
this
.
items
,
this
.
itemDimensions
=
[],
this
.
options
.
tolerance
));
return
this
.
itemDimensions
},
getItemOffsetParent
:
function
(){
var
a
=
this
.
el
;
return
"relative"
===
a
.
css
(
"position"
)
||
"absolute"
===
a
.
css
(
"position"
)
||
"fixed"
===
a
.
css
(
"position"
)?
a
:
a
.
offsetParent
()},
hasChildGroup
:
function
(
a
){
return
this
.
options
.
nested
&&
this
.
getContainerGroup
(
a
)},
getContainerGroup
:
function
(
a
){
var
b
=
d
.
data
(
this
.
items
[
a
],
"subContainers"
);
if
(
b
===
f
){
var
c
=
this
.
$getChildren
(
this
.
items
[
a
],
"container"
),
b
=!
1
;
c
[
0
]
&&
(
b
=
d
.
extend
({},
this
.
options
,{
rootGroup
:
this
.
rootGroup
,
group
:
y
++
}),
b
=
c
[
m
](
b
).
data
(
m
).
group
);
d
.
data
(
this
.
items
[
a
],
"subContainers"
,
b
)}
return
b
},
$getChildren
:
function
(
a
,
b
){
var
c
=
this
.
rootGroup
.
options
,
e
=
c
[
b
+
"Path"
],
c
=
c
[
b
+
"Selector"
];
a
=
d
(
a
);
e
&&
(
a
=
a
.
find
(
e
));
return
a
.
children
(
c
)},
_serialize
:
function
(
a
,
b
){
var
c
=
this
,
e
=
this
.
$getChildren
(
a
,
b
?
"item"
:
"container"
).
not
(
this
.
options
.
exclude
).
map
(
function
(){
return
c
.
_serialize
(
d
(
this
),
!
b
)}).
get
();
return
this
.
rootGroup
.
options
.
serialize
(
a
,
e
,
b
)},
traverse
:
function
(
a
){
d
.
each
(
this
.
items
||
[],
function
(
b
){(
b
=
d
.
data
(
this
,
"subContainers"
))
&&
b
.
traverse
(
a
)});
a
(
this
)},
_clearDimensions
:
function
(){
this
.
itemDimensions
=
f
},
_destroy
:
function
(){
var
a
=
this
;
this
.
target
.
off
(
r
.
start
,
this
.
handle
);
this
.
el
.
removeData
(
m
);
this
.
options
.
drop
&&
(
this
.
group
.
containers
=
d
.
grep
(
this
.
group
.
containers
,
function
(
b
){
return
b
!=
a
}));
d
.
each
(
this
.
items
||
[],
function
(){
d
.
removeData
(
this
,
"subContainers"
)})}};
var
u
=
{
enable
:
function
(){
this
.
traverse
(
function
(
a
){
a
.
disabled
=!
1
})},
disable
:
function
(){
this
.
traverse
(
function
(
a
){
a
.
disabled
=
!
0
})},
serialize
:
function
(){
return
this
.
_serialize
(
this
.
el
,
!
0
)},
refresh
:
function
(){
this
.
traverse
(
function
(
a
){
a
.
_clearDimensions
()})},
destroy
:
function
(){
this
.
traverse
(
function
(
a
){
a
.
_destroy
()})}};
d
.
extend
(
t
.
prototype
,
u
);
d
.
fn
[
m
]
=
function
(
a
){
var
b
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
);
return
this
.
map
(
function
(){
var
c
=
d
(
this
),
e
=
c
.
data
(
m
);
if
(
e
&&
u
[
a
])
return
u
[
a
].
apply
(
e
,
b
)
||
this
;
e
||
a
!==
f
&&
"object"
!==
typeof
a
||
c
.
data
(
m
,
new
t
(
c
,
a
));
return
this
})}}(
jQuery
,
window
,
"sortable"
);
jquery-sortable/0.9.13/jquery-sortable.js
0 → 100644
View file @
06ee95f0
/* ===================================================
* jquery-sortable.js v0.9.13
* http://johnny.github.com/jquery-sortable/
* ===================================================
* Copyright (c) 2012 Jonas von Andrian
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ========================================================== */
!
function
(
$
,
window
,
pluginName
,
undefined
){
var
eventNames
,
containerDefaults
=
{
// If true, items can be dragged from this container
drag
:
true
,
// If true, items can be droped onto this container
drop
:
true
,
// Exclude items from being draggable, if the
// selector matches the item
exclude
:
""
,
// If true, search for nested containers within an item.If you nest containers,
// either the original selector with which you call the plugin must only match the top containers,
// or you need to specify a group (see the bootstrap nav example)
nested
:
true
,
// If true, the items are assumed to be arranged vertically
vertical
:
true
},
// end container defaults
groupDefaults
=
{
// This is executed after the placeholder has been moved.
// $closestItemOrContainer contains the closest item, the placeholder
// has been put at or the closest empty Container, the placeholder has
// been appended to.
afterMove
:
function
(
$placeholder
,
container
,
$closestItemOrContainer
)
{
},
// The exact css path between the container and its items, e.g. "> tbody"
containerPath
:
""
,
// The css selector of the containers
containerSelector
:
"ol, ul"
,
// Distance the mouse has to travel to start dragging
distance
:
0
,
// Time in milliseconds after mousedown until dragging should start.
// This option can be used to prevent unwanted drags when clicking on an element.
delay
:
0
,
// The css selector of the drag handle
handle
:
""
,
// The exact css path between the item and its subcontainers.
// It should only match the immediate items of a container.
// No item of a subcontainer should be matched. E.g. for ol>div>li the itemPath is "> div"
itemPath
:
""
,
// The css selector of the items
itemSelector
:
"li"
,
// The class given to "body" while an item is being dragged
bodyClass
:
"dragging"
,
// The class giving to an item while being dragged
draggedClass
:
"dragged"
,
// Check if the dragged item may be inside the container.
// Use with care, since the search for a valid container entails a depth first search
// and may be quite expensive.
isValidTarget
:
function
(
$item
,
container
)
{
return
true
},
// Executed before onDrop if placeholder is detached.
// This happens if pullPlaceholder is set to false and the drop occurs outside a container.
onCancel
:
function
(
$item
,
container
,
_super
,
event
)
{
},
// Executed at the beginning of a mouse move event.
// The Placeholder has not been moved yet.
onDrag
:
function
(
$item
,
position
,
_super
,
event
)
{
$item
.
css
(
position
)
},
// Called after the drag has been started,
// that is the mouse button is being held down and
// the mouse is moving.
// The container is the closest initialized container.
// Therefore it might not be the container, that actually contains the item.
onDragStart
:
function
(
$item
,
container
,
_super
,
event
)
{
$item
.
css
({
height
:
$item
.
outerHeight
(),
width
:
$item
.
outerWidth
()
})
$item
.
addClass
(
container
.
group
.
options
.
draggedClass
)
$
(
"body"
).
addClass
(
container
.
group
.
options
.
bodyClass
)
},
// Called when the mouse button is being released
onDrop
:
function
(
$item
,
container
,
_super
,
event
)
{
$item
.
removeClass
(
container
.
group
.
options
.
draggedClass
).
removeAttr
(
"style"
)
$
(
"body"
).
removeClass
(
container
.
group
.
options
.
bodyClass
)
},
// Called on mousedown. If falsy value is returned, the dragging will not start.
// Ignore if element clicked is input, select or textarea
onMousedown
:
function
(
$item
,
_super
,
event
)
{
if
(
!
event
.
target
.
nodeName
.
match
(
/^
(
input|select|textarea
)
$/i
))
{
event
.
preventDefault
()
return
true
}
},
// The class of the placeholder (must match placeholder option markup)
placeholderClass
:
"placeholder"
,
// Template for the placeholder. Can be any valid jQuery input
// e.g. a string, a DOM element.
// The placeholder must have the class "placeholder"
placeholder
:
'<li class="placeholder"></li>'
,
// If true, the position of the placeholder is calculated on every mousemove.
// If false, it is only calculated when the mouse is above a container.
pullPlaceholder
:
true
,
// Specifies serialization of the container group.
// The pair $parent/$children is either container/items or item/subcontainers.
serialize
:
function
(
$parent
,
$children
,
parentIsContainer
)
{
var
result
=
$
.
extend
({},
$parent
.
data
())
if
(
parentIsContainer
)
return
[
$children
]
else
if
(
$children
[
0
]){
result
.
children
=
$children
}
delete
result
.
subContainers
delete
result
.
sortable
return
result
},
// Set tolerance while dragging. Positive values decrease sensitivity,
// negative values increase it.
tolerance
:
0
},
// end group defaults
containerGroups
=
{},
groupCounter
=
0
,
emptyBox
=
{
left
:
0
,
top
:
0
,
bottom
:
0
,
right
:
0
},
eventNames
=
{
start
:
"touchstart.sortable mousedown.sortable"
,
drop
:
"touchend.sortable touchcancel.sortable mouseup.sortable"
,
drag
:
"touchmove.sortable mousemove.sortable"
,
scroll
:
"scroll.sortable"
},
subContainerKey
=
"subContainers"
/*
* a is Array [left, right, top, bottom]
* b is array [left, top]
*/
function
d
(
a
,
b
)
{
var
x
=
Math
.
max
(
0
,
a
[
0
]
-
b
[
0
],
b
[
0
]
-
a
[
1
]),
y
=
Math
.
max
(
0
,
a
[
2
]
-
b
[
1
],
b
[
1
]
-
a
[
3
])
return
x
+
y
;
}
function
setDimensions
(
array
,
dimensions
,
tolerance
,
useOffset
)
{
var
i
=
array
.
length
,
offsetMethod
=
useOffset
?
"offset"
:
"position"
tolerance
=
tolerance
||
0
while
(
i
--
){
var
el
=
array
[
i
].
el
?
array
[
i
].
el
:
$
(
array
[
i
]),
// use fitting method
pos
=
el
[
offsetMethod
]()
pos
.
left
+=
parseInt
(
el
.
css
(
'margin-left'
),
10
)
pos
.
top
+=
parseInt
(
el
.
css
(
'margin-top'
),
10
)
dimensions
[
i
]
=
[
pos
.
left
-
tolerance
,
pos
.
left
+
el
.
outerWidth
()
+
tolerance
,
pos
.
top
-
tolerance
,
pos
.
top
+
el
.
outerHeight
()
+
tolerance
]
}
}
function
getRelativePosition
(
pointer
,
element
)
{
var
offset
=
element
.
offset
()
return
{
left
:
pointer
.
left
-
offset
.
left
,
top
:
pointer
.
top
-
offset
.
top
}
}
function
sortByDistanceDesc
(
dimensions
,
pointer
,
lastPointer
)
{
pointer
=
[
pointer
.
left
,
pointer
.
top
]
lastPointer
=
lastPointer
&&
[
lastPointer
.
left
,
lastPointer
.
top
]
var
dim
,
i
=
dimensions
.
length
,
distances
=
[]
while
(
i
--
){
dim
=
dimensions
[
i
]
distances
[
i
]
=
[
i
,
d
(
dim
,
pointer
),
lastPointer
&&
d
(
dim
,
lastPointer
)]
}
distances
=
distances
.
sort
(
function
(
a
,
b
)
{
return
b
[
1
]
-
a
[
1
]
||
b
[
2
]
-
a
[
2
]
||
b
[
0
]
-
a
[
0
]
})
// last entry is the closest
return
distances
}
function
ContainerGroup
(
options
)
{
this
.
options
=
$
.
extend
({},
groupDefaults
,
options
)
this
.
containers
=
[]
if
(
!
this
.
options
.
rootGroup
){
this
.
scrollProxy
=
$
.
proxy
(
this
.
scroll
,
this
)
this
.
dragProxy
=
$
.
proxy
(
this
.
drag
,
this
)
this
.
dropProxy
=
$
.
proxy
(
this
.
drop
,
this
)
this
.
placeholder
=
$
(
this
.
options
.
placeholder
)
if
(
!
options
.
isValidTarget
)
this
.
options
.
isValidTarget
=
undefined
}
}
ContainerGroup
.
get
=
function
(
options
)
{
if
(
!
containerGroups
[
options
.
group
])
{
if
(
options
.
group
===
undefined
)
options
.
group
=
groupCounter
++
containerGroups
[
options
.
group
]
=
new
ContainerGroup
(
options
)
}
return
containerGroups
[
options
.
group
]
}
ContainerGroup
.
prototype
=
{
dragInit
:
function
(
e
,
itemContainer
)
{
this
.
$document
=
$
(
itemContainer
.
el
[
0
].
ownerDocument
)
// get item to drag
var
closestItem
=
$
(
e
.
target
).
closest
(
this
.
options
.
itemSelector
);
// using the length of this item, prevents the plugin from being started if there is no handle being clicked on.
// this may also be helpful in instantiating multidrag.
if
(
closestItem
.
length
)
{
this
.
item
=
closestItem
;
this
.
itemContainer
=
itemContainer
;
if
(
this
.
item
.
is
(
this
.
options
.
exclude
)
||
!
this
.
options
.
onMousedown
(
this
.
item
,
groupDefaults
.
onMousedown
,
e
))
{
return
;
}
this
.
setPointer
(
e
);
this
.
toggleListeners
(
'on'
);
this
.
setupDelayTimer
();
this
.
dragInitDone
=
true
;
}
},
drag
:
function
(
e
)
{
if
(
!
this
.
dragging
){
if
(
!
this
.
distanceMet
(
e
)
||
!
this
.
delayMet
)
return
this
.
options
.
onDragStart
(
this
.
item
,
this
.
itemContainer
,
groupDefaults
.
onDragStart
,
e
)
this
.
item
.
before
(
this
.
placeholder
)
this
.
dragging
=
true
}
this
.
setPointer
(
e
)
// place item under the cursor
this
.
options
.
onDrag
(
this
.
item
,
getRelativePosition
(
this
.
pointer
,
this
.
item
.
offsetParent
()),
groupDefaults
.
onDrag
,
e
)
var
p
=
this
.
getPointer
(
e
),
box
=
this
.
sameResultBox
,
t
=
this
.
options
.
tolerance
if
(
!
box
||
box
.
top
-
t
>
p
.
top
||
box
.
bottom
+
t
<
p
.
top
||
box
.
left
-
t
>
p
.
left
||
box
.
right
+
t
<
p
.
left
)
if
(
!
this
.
searchValidTarget
()){
this
.
placeholder
.
detach
()
this
.
lastAppendedItem
=
undefined
}
},
drop
:
function
(
e
)
{
this
.
toggleListeners
(
'off'
)
this
.
dragInitDone
=
false
if
(
this
.
dragging
){
// processing Drop, check if placeholder is detached
if
(
this
.
placeholder
.
closest
(
"html"
)[
0
]){
this
.
placeholder
.
before
(
this
.
item
).
detach
()
}
else
{
this
.
options
.
onCancel
(
this
.
item
,
this
.
itemContainer
,
groupDefaults
.
onCancel
,
e
)
}
this
.
options
.
onDrop
(
this
.
item
,
this
.
getContainer
(
this
.
item
),
groupDefaults
.
onDrop
,
e
)
// cleanup
this
.
clearDimensions
()
this
.
clearOffsetParent
()
this
.
lastAppendedItem
=
this
.
sameResultBox
=
undefined
this
.
dragging
=
false
}
},
searchValidTarget
:
function
(
pointer
,
lastPointer
)
{
if
(
!
pointer
){
pointer
=
this
.
relativePointer
||
this
.
pointer
lastPointer
=
this
.
lastRelativePointer
||
this
.
lastPointer
}
var
distances
=
sortByDistanceDesc
(
this
.
getContainerDimensions
(),
pointer
,
lastPointer
),
i
=
distances
.
length
while
(
i
--
){
var
index
=
distances
[
i
][
0
],
distance
=
distances
[
i
][
1
]
if
(
!
distance
||
this
.
options
.
pullPlaceholder
){
var
container
=
this
.
containers
[
index
]
if
(
!
container
.
disabled
){
if
(
!
this
.
$getOffsetParent
()){
var
offsetParent
=
container
.
getItemOffsetParent
()
pointer
=
getRelativePosition
(
pointer
,
offsetParent
)
lastPointer
=
getRelativePosition
(
lastPointer
,
offsetParent
)
}
if
(
container
.
searchValidTarget
(
pointer
,
lastPointer
))
return
true
}
}
}
if
(
this
.
sameResultBox
)
this
.
sameResultBox
=
undefined
},
movePlaceholder
:
function
(
container
,
item
,
method
,
sameResultBox
)
{
var
lastAppendedItem
=
this
.
lastAppendedItem
if
(
!
sameResultBox
&&
lastAppendedItem
&&
lastAppendedItem
[
0
]
===
item
[
0
])
return
;
item
[
method
](
this
.
placeholder
)
this
.
lastAppendedItem
=
item
this
.
sameResultBox
=
sameResultBox
this
.
options
.
afterMove
(
this
.
placeholder
,
container
,
item
)
},
getContainerDimensions
:
function
()
{
if
(
!
this
.
containerDimensions
)
setDimensions
(
this
.
containers
,
this
.
containerDimensions
=
[],
this
.
options
.
tolerance
,
!
this
.
$getOffsetParent
())
return
this
.
containerDimensions
},
getContainer
:
function
(
element
)
{
return
element
.
closest
(
this
.
options
.
containerSelector
).
data
(
pluginName
)
},
$getOffsetParent
:
function
()
{
if
(
this
.
offsetParent
===
undefined
){
var
i
=
this
.
containers
.
length
-
1
,
offsetParent
=
this
.
containers
[
i
].
getItemOffsetParent
()
if
(
!
this
.
options
.
rootGroup
){
while
(
i
--
){
if
(
offsetParent
[
0
]
!=
this
.
containers
[
i
].
getItemOffsetParent
()[
0
]){
// If every container has the same offset parent,
// use position() which is relative to this parent,
// otherwise use offset()
// compare #setDimensions
offsetParent
=
false
break
;
}
}
}
this
.
offsetParent
=
offsetParent
}
return
this
.
offsetParent
},
setPointer
:
function
(
e
)
{
var
pointer
=
this
.
getPointer
(
e
)
if
(
this
.
$getOffsetParent
()){
var
relativePointer
=
getRelativePosition
(
pointer
,
this
.
$getOffsetParent
())
this
.
lastRelativePointer
=
this
.
relativePointer
this
.
relativePointer
=
relativePointer
}
this
.
lastPointer
=
this
.
pointer
this
.
pointer
=
pointer
},
distanceMet
:
function
(
e
)
{
var
currentPointer
=
this
.
getPointer
(
e
)
return
(
Math
.
max
(
Math
.
abs
(
this
.
pointer
.
left
-
currentPointer
.
left
),
Math
.
abs
(
this
.
pointer
.
top
-
currentPointer
.
top
)
)
>=
this
.
options
.
distance
)
},
getPointer
:
function
(
e
)
{
var
o
=
e
.
originalEvent
||
e
.
originalEvent
.
touches
&&
e
.
originalEvent
.
touches
[
0
]
return
{
left
:
e
.
pageX
||
o
.
pageX
,
top
:
e
.
pageY
||
o
.
pageY
}
},
setupDelayTimer
:
function
()
{
var
that
=
this
this
.
delayMet
=
!
this
.
options
.
delay
// init delay timer if needed
if
(
!
this
.
delayMet
)
{
clearTimeout
(
this
.
_mouseDelayTimer
);
this
.
_mouseDelayTimer
=
setTimeout
(
function
()
{
that
.
delayMet
=
true
},
this
.
options
.
delay
)
}
},
scroll
:
function
(
e
)
{
this
.
clearDimensions
()
this
.
clearOffsetParent
()
// TODO is this needed?
},
toggleListeners
:
function
(
method
)
{
var
that
=
this
,
events
=
[
'drag'
,
'drop'
,
'scroll'
]
$
.
each
(
events
,
function
(
i
,
event
)
{
that
.
$document
[
method
](
eventNames
[
event
],
that
[
event
+
'Proxy'
])
})
},
clearOffsetParent
:
function
()
{
this
.
offsetParent
=
undefined
},
// Recursively clear container and item dimensions
clearDimensions
:
function
()
{
this
.
traverse
(
function
(
object
){
object
.
_clearDimensions
()
})
},
traverse
:
function
(
callback
)
{
callback
(
this
)
var
i
=
this
.
containers
.
length
while
(
i
--
){
this
.
containers
[
i
].
traverse
(
callback
)
}
},
_clearDimensions
:
function
(){
this
.
containerDimensions
=
undefined
},
_destroy
:
function
()
{
containerGroups
[
this
.
options
.
group
]
=
undefined
}
}
function
Container
(
element
,
options
)
{
this
.
el
=
element
this
.
options
=
$
.
extend
(
{},
containerDefaults
,
options
)
this
.
group
=
ContainerGroup
.
get
(
this
.
options
)
this
.
rootGroup
=
this
.
options
.
rootGroup
||
this
.
group
this
.
handle
=
this
.
rootGroup
.
options
.
handle
||
this
.
rootGroup
.
options
.
itemSelector
var
itemPath
=
this
.
rootGroup
.
options
.
itemPath
this
.
target
=
itemPath
?
this
.
el
.
find
(
itemPath
)
:
this
.
el
this
.
target
.
on
(
eventNames
.
start
,
this
.
handle
,
$
.
proxy
(
this
.
dragInit
,
this
))
if
(
this
.
options
.
drop
)
this
.
group
.
containers
.
push
(
this
)
}
Container
.
prototype
=
{
dragInit
:
function
(
e
)
{
var
rootGroup
=
this
.
rootGroup
if
(
!
this
.
disabled
&&
!
rootGroup
.
dragInitDone
&&
this
.
options
.
drag
&&
this
.
isValidDrag
(
e
))
{
rootGroup
.
dragInit
(
e
,
this
)
}
},
isValidDrag
:
function
(
e
)
{
return
e
.
which
==
1
||
e
.
type
==
"touchstart"
&&
e
.
originalEvent
.
touches
.
length
==
1
},
searchValidTarget
:
function
(
pointer
,
lastPointer
)
{
var
distances
=
sortByDistanceDesc
(
this
.
getItemDimensions
(),
pointer
,
lastPointer
),
i
=
distances
.
length
,
rootGroup
=
this
.
rootGroup
,
validTarget
=
!
rootGroup
.
options
.
isValidTarget
||
rootGroup
.
options
.
isValidTarget
(
rootGroup
.
item
,
this
)
if
(
!
i
&&
validTarget
){
rootGroup
.
movePlaceholder
(
this
,
this
.
target
,
"append"
)
return
true
}
else
while
(
i
--
){
var
index
=
distances
[
i
][
0
],
distance
=
distances
[
i
][
1
]
if
(
!
distance
&&
this
.
hasChildGroup
(
index
)){
var
found
=
this
.
getContainerGroup
(
index
).
searchValidTarget
(
pointer
,
lastPointer
)
if
(
found
)
return
true
}
else
if
(
validTarget
){
this
.
movePlaceholder
(
index
,
pointer
)
return
true
}
}
},
movePlaceholder
:
function
(
index
,
pointer
)
{
var
item
=
$
(
this
.
items
[
index
]),
dim
=
this
.
itemDimensions
[
index
],
method
=
"after"
,
width
=
item
.
outerWidth
(),
height
=
item
.
outerHeight
(),
offset
=
item
.
offset
(),
sameResultBox
=
{
left
:
offset
.
left
,
right
:
offset
.
left
+
width
,
top
:
offset
.
top
,
bottom
:
offset
.
top
+
height
}
if
(
this
.
options
.
vertical
){
var
yCenter
=
(
dim
[
2
]
+
dim
[
3
])
/
2
,
inUpperHalf
=
pointer
.
top
<=
yCenter
if
(
inUpperHalf
){
method
=
"before"
sameResultBox
.
bottom
-=
height
/
2
}
else
sameResultBox
.
top
+=
height
/
2
}
else
{
var
xCenter
=
(
dim
[
0
]
+
dim
[
1
])
/
2
,
inLeftHalf
=
pointer
.
left
<=
xCenter
if
(
inLeftHalf
){
method
=
"before"
sameResultBox
.
right
-=
width
/
2
}
else
sameResultBox
.
left
+=
width
/
2
}
if
(
this
.
hasChildGroup
(
index
))
sameResultBox
=
emptyBox
this
.
rootGroup
.
movePlaceholder
(
this
,
item
,
method
,
sameResultBox
)
},
getItemDimensions
:
function
()
{
if
(
!
this
.
itemDimensions
){
this
.
items
=
this
.
$getChildren
(
this
.
el
,
"item"
).
filter
(
":not(."
+
this
.
group
.
options
.
placeholderClass
+
", ."
+
this
.
group
.
options
.
draggedClass
+
")"
).
get
()
setDimensions
(
this
.
items
,
this
.
itemDimensions
=
[],
this
.
options
.
tolerance
)
}
return
this
.
itemDimensions
},
getItemOffsetParent
:
function
()
{
var
offsetParent
,
el
=
this
.
el
// Since el might be empty we have to check el itself and
// can not do something like el.children().first().offsetParent()
if
(
el
.
css
(
"position"
)
===
"relative"
||
el
.
css
(
"position"
)
===
"absolute"
||
el
.
css
(
"position"
)
===
"fixed"
)
offsetParent
=
el
else
offsetParent
=
el
.
offsetParent
()
return
offsetParent
},
hasChildGroup
:
function
(
index
)
{
return
this
.
options
.
nested
&&
this
.
getContainerGroup
(
index
)
},
getContainerGroup
:
function
(
index
)
{
var
childGroup
=
$
.
data
(
this
.
items
[
index
],
subContainerKey
)
if
(
childGroup
===
undefined
){
var
childContainers
=
this
.
$getChildren
(
this
.
items
[
index
],
"container"
)
childGroup
=
false
if
(
childContainers
[
0
]){
var
options
=
$
.
extend
({},
this
.
options
,
{
rootGroup
:
this
.
rootGroup
,
group
:
groupCounter
++
})
childGroup
=
childContainers
[
pluginName
](
options
).
data
(
pluginName
).
group
}
$
.
data
(
this
.
items
[
index
],
subContainerKey
,
childGroup
)
}
return
childGroup
},
$getChildren
:
function
(
parent
,
type
)
{
var
options
=
this
.
rootGroup
.
options
,
path
=
options
[
type
+
"Path"
],
selector
=
options
[
type
+
"Selector"
]
parent
=
$
(
parent
)
if
(
path
)
parent
=
parent
.
find
(
path
)
return
parent
.
children
(
selector
)
},
_serialize
:
function
(
parent
,
isContainer
)
{
var
that
=
this
,
childType
=
isContainer
?
"item"
:
"container"
,
children
=
this
.
$getChildren
(
parent
,
childType
).
not
(
this
.
options
.
exclude
).
map
(
function
()
{
return
that
.
_serialize
(
$
(
this
),
!
isContainer
)
}).
get
()
return
this
.
rootGroup
.
options
.
serialize
(
parent
,
children
,
isContainer
)
},
traverse
:
function
(
callback
)
{
$
.
each
(
this
.
items
||
[],
function
(
item
){
var
group
=
$
.
data
(
this
,
subContainerKey
)
if
(
group
)
group
.
traverse
(
callback
)
});
callback
(
this
)
},
_clearDimensions
:
function
()
{
this
.
itemDimensions
=
undefined
},
_destroy
:
function
()
{
var
that
=
this
;
this
.
target
.
off
(
eventNames
.
start
,
this
.
handle
);
this
.
el
.
removeData
(
pluginName
)
if
(
this
.
options
.
drop
)
this
.
group
.
containers
=
$
.
grep
(
this
.
group
.
containers
,
function
(
val
){
return
val
!=
that
})
$
.
each
(
this
.
items
||
[],
function
(){
$
.
removeData
(
this
,
subContainerKey
)
})
}
}
var
API
=
{
enable
:
function
()
{
this
.
traverse
(
function
(
object
){
object
.
disabled
=
false
})
},
disable
:
function
(){
this
.
traverse
(
function
(
object
){
object
.
disabled
=
true
})
},
serialize
:
function
()
{
return
this
.
_serialize
(
this
.
el
,
true
)
},
refresh
:
function
()
{
this
.
traverse
(
function
(
object
){
object
.
_clearDimensions
()
})
},
destroy
:
function
()
{
this
.
traverse
(
function
(
object
){
object
.
_destroy
();
})
}
}
$
.
extend
(
Container
.
prototype
,
API
)
/**
* jQuery API
*
* Parameters are
* either options on init
* or a method name followed by arguments to pass to the method
*/
$
.
fn
[
pluginName
]
=
function
(
methodOrOptions
)
{
var
args
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
)
return
this
.
map
(
function
(){
var
$t
=
$
(
this
),
object
=
$t
.
data
(
pluginName
)
if
(
object
&&
API
[
methodOrOptions
])
return
API
[
methodOrOptions
].
apply
(
object
,
args
)
||
this
else
if
(
!
object
&&
(
methodOrOptions
===
undefined
||
typeof
methodOrOptions
===
"object"
))
$t
.
data
(
pluginName
,
new
Container
(
$t
,
methodOrOptions
))
return
this
});
};
}(
jQuery
,
window
,
'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