Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
KSS
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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Packages
Packages
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Thimo Kraemer
KSS
Commits
8642a56c
Commit
8642a56c
authored
Nov 04, 2018
by
Thimo Kraemer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added DND plugin
parent
e35322e8
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
358 additions
and
0 deletions
+358
-0
dnd.js
dnd.js
+358
-0
No files found.
dnd.js
0 → 100644
View file @
8642a56c
/*
dnd.js - KSS HTML5 Drag and Drop plugin
Copyright (c) 2018, joonis new media
Author: Thimo Kraemer <thimo.kraemer@joonis.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
/*******************************************************************************************
* DND Plugin
*
* Based on the original Kukit plugin and modified to work with KSS-RPC.
* Should be reviewed in general.
*
* Brief documentation
* -------------------
*
* This plugin provides HTML5 DND functionality and is not meant to move some
* elements around the screen. The latter can be realized with the core KSS
* functionality.
*
* Main events to use:
*
* - "dragstart" on dragable elements
* - "drop" on target elements
*
* All bindings are done automatically (no need to set *draggable* attributes, etc).
* In *dragstart* events the most important thing is to set the drag data with the
* KSS action *setDragData*:
*
* .my-draggable:dragstart {
* kss-action-client: setDragData;
* type: "text/plain";
* value: outerHTML();
* }
*
* In *drop* events you can access the data with the paramater provider "dragData":
*
* #my-drop-target:drop {
* kss-action-client: appendHTML:
* html: dragData("text/plain");
* }
*
* An element is only dropable if all required drag data types are available.
* That is all requested types in *drop* must have been specified in *dragstart*
* previously. Dropping data from external resources is possible as well with
* the exception of files which isn't implemented yet.
*
******************************************************************************************/
kss
.
dnd
=
{
_dropEffect
:
'
move
'
,
_isValidDropTarget
:
false
,
_dataTransfer
:
null
};
// A wrapper around the original dataTransfer object of a DND event.
// It enables the possibility to use any data type within the document,
// even if not supported by the browser (eg. IE<10).
kss
.
dnd
.
DataTransfer
=
function
()
{
this
.
initialize
=
function
(
dataTransfer
,
external
)
{
this
.
data
=
{};
this
.
dataTransfer
=
dataTransfer
;
this
.
external
=
external
||
false
;
if
(
external
)
{
// IE<10 doesn't provide the "types" attribute,
// so we assume that we have a text and url value.
// Anyway the only two supported types by IE<10.
this
.
types
=
dataTransfer
.
types
||
[
'
text/plain
'
,
'
text/uri-list
'
];
}
else
{
this
.
types
=
[];
}
};
this
.
normalizeType
=
function
(
type
)
{
// Type mapping for backwards compatibility (IE<10)
var
map
=
{
'
text
'
:
'
text/plain
'
,
'
url
'
:
'
text/uri-list
'
};
type
=
type
.
toLowerCase
();
return
map
[
type
]
||
type
;
};
this
.
setData
=
function
(
type
,
value
)
{
type
=
this
.
normalizeType
(
type
);
this
.
types
.
push
(
type
);
this
.
data
[
type
]
=
value
;
// required by IE
if
(
type
==
'
text/plain
'
)
{
this
.
dataTransfer
.
setData
(
'
Text
'
,
value
);
}
else
if
(
type
==
'
text/uri-list
'
)
{
this
.
dataTransfer
.
setData
(
'
url
'
,
value
);
}
try
{
this
.
dataTransfer
.
setData
(
type
,
value
);
}
catch
(
exc
)
{}
};
this
.
getData
=
function
(
type
)
{
type
=
this
.
normalizeType
(
type
);
var
value
=
this
.
data
[
type
];
if
(
!
value
)
{
// required by IE
if
(
type
==
'
text/plain
'
)
{
value
=
this
.
dataTransfer
.
getData
(
'
Text
'
);
}
else
if
(
type
==
'
text/uri-list
'
)
{
value
=
this
.
dataTransfer
.
getData
(
'
url
'
);
}
}
if
(
!
value
)
{
try
{
value
=
this
.
dataTransfer
.
getData
(
type
);
}
catch
(
exc
)
{}
}
return
value
||
''
;
};
this
.
initialize
.
apply
(
this
,
arguments
);
};
kss
.
dnd
.
isValidDropTarget
=
function
(
handler
)
{
var
dnd
=
kss
.
dnd
;
var
dataTransfer
=
dnd
.
_dataTransfer
;
if
(
!
dataTransfer
||
dnd
.
_dropEffect
==
'
none
'
)
{
dnd
.
_isValidDropTarget
=
false
;
}
else
if
(
handler
)
{
// We want to know all required data types of each action that
// is processed when an object is dropped. For that we evaluate
// all parameter providers that contain the provider "dragData".
// The real job is then done by the parameter provider "dragData"
// itself, see below.
handler
.
_requiredDragDataTypes
=
[];
kss
.
each
(
handler
.
rule
.
actions
,
function
(
action
)
{
kss
.
each
(
action
.
props
,
function
(
value
)
{
if
(
/
\b
dragData
\s
*
\(
/
.
test
(
value
))
{
handler
.
_evalParam
(
value
);
}
});
kss
.
each
(
action
.
params
,
function
(
value
)
{
if
(
/
\b
dragData
\s
*
\(
/
.
test
(
value
))
{
handler
.
_evalParam
(
value
);
}
});
});
var
requiredDragData
=
handler
.
_requiredDragDataTypes
;
delete
handler
.
_requiredDragDataTypes
;
// Now check if all requested data types are available.
// Only in this case we declare it as a valid drop target.
var
isValid
=
true
;
for
(
var
i
=
0
;
i
<
requiredDragData
.
length
;
i
++
)
{
isValid
=
false
;
var
type
=
dataTransfer
.
normalizeType
(
requiredDragData
[
i
]);
for
(
var
j
=
0
;
j
<
dataTransfer
.
types
.
length
;
j
++
)
{
if
(
dataTransfer
.
types
[
j
]
==
type
)
{
isValid
=
true
;
break
;
}
}
if
(
!
isValid
)
{
break
;
}
}
dnd
.
_isValidDropTarget
=
isValid
;
}
// Set it also as state variable.
kss
.
_stateVars
[
'
validDropTarget
'
]
=
dnd
.
_isValidDropTarget
;
return
dnd
.
_isValidDropTarget
;
};
// DND DragStart binder class
kss
.
dnd
.
_DragStartEventBinder
=
function
(
handler
)
{
// Make the node draggable if there exists a "dragstart" event.
var
node
=
handler
.
node
;
var
props
=
handler
.
propertyGetter
({
effectallowed
:
'
all
'
});
if
(
node
.
getAttribute
(
'
draggable
'
)
!=
'
true
'
)
{
// HTML5 way
node
.
setAttribute
(
'
draggable
'
,
'
true
'
);
node
.
style
.
cursor
=
'
default
'
;
try
{
// required by Safari
node
.
style
.
webkitUserDrag
=
'
element
'
;
node
.
style
.
khtmlUserDrag
=
'
element
'
;
}
catch
(
exc
)
{}
if
(
node
.
dragDrop
)
{
// required by IE<10
node
.
addEventListener
(
'
selectstart
'
,
function
(
e
)
{
node
.
dragDrop
();
e
.
preventDefault
();
},
false
);
}
// Default behaviour on dragstart event.
// It must be executed before all others.
node
.
addEventListener
(
'
dragstart
'
,
function
(
e
)
{
if
(
node
.
getAttribute
(
'
draggable
'
)
!=
'
true
'
)
{
e
.
preventDefault
();
return
;
}
var
effectallowed
=
props
(
'
effectallowed
'
);
//~ if (effectallowed == 'shift') {
//~ e.preventDefault();
//~ return;
//~ }
// XXX Firefox through version 5 does not fire
// the drop event if effectAllowed is set.
e
.
dataTransfer
.
effectAllowed
=
effectallowed
;
// Create and store our own dataTransfer object
kss
.
dnd
.
_dataTransfer
=
new
kss
.
dnd
.
DataTransfer
(
e
.
dataTransfer
);
try
{
// required at least by Firefox
e
.
dataTransfer
.
setData
(
'
_dummy
'
,
''
);
}
catch
(
exc
)
{}
},
true
);
// Default behaviour on dragend event.
node
.
addEventListener
(
'
dragend
'
,
function
(
e
)
{
// Clear the dataTransfer object
kss
.
dnd
.
_dataTransfer
=
null
;
},
false
);
}
};
kss
.
registerEventBinder
(
'
dragstart
'
,
kss
.
dnd
.
_DragStartEventBinder
);
// DND Drop binder class
kss
.
dnd
.
_DropEventBinder
=
function
(
handler
)
{
var
dnd
=
kss
.
dnd
;
var
node
=
handler
.
node
;
if
(
!
node
.
getAttribute
(
'
droptarget
'
))
{
node
.
setAttribute
(
'
droptarget
'
,
'
true
'
);
// Default behaviour on drop event.
node
.
addEventListener
(
'
drop
'
,
function
(
e
)
{
// We must renew the dataTransfer object on external drag actions
if
(
!
dnd
.
_dataTransfer
||
dnd
.
_dataTransfer
.
external
)
{
dnd
.
_dataTransfer
=
new
dnd
.
DataTransfer
(
e
.
dataTransfer
,
true
);
}
// By default Firefox opens any transfered data as URL
e
.
preventDefault
();
},
false
);
}
// Default behaviour on dragenter event.
// It must be executed before all others.
node
.
addEventListener
(
'
dragenter
'
,
function
(
e
)
{
// We must renew the dataTransfer object on external drag actions
if
(
!
dnd
.
_dataTransfer
||
dnd
.
_dataTransfer
.
external
)
{
dnd
.
_dataTransfer
=
new
dnd
.
DataTransfer
(
e
.
dataTransfer
,
true
);
}
if
(
kss
.
dnd
.
isValidDropTarget
(
handler
))
{
// Init drop effect
dnd
.
_dropEffect
=
e
.
dataTransfer
.
dropEffect
=
'
move
'
;
// Make the node a valid drop target
e
.
preventDefault
();
}
},
true
);
// Default behaviour on dragover event.
node
.
addEventListener
(
'
dragover
'
,
function
(
e
)
{
if
(
kss
.
dnd
.
isValidDropTarget
())
{
// Apply drop effect
e
.
dataTransfer
.
dropEffect
=
dnd
.
_dropEffect
;
// Make the node a valid drop target
e
.
preventDefault
();
}
},
false
);
};
kss
.
registerEventBinder
(
'
drop
'
,
kss
.
dnd
.
_DropEventBinder
);
// action provider setDropEffect
kss
.
registerActionProvider
(
'
setDropEffect
'
,
function
(
node
,
params
)
{
// value must be one of none, move, copy or link
if
(
this
.
eventname
!=
'
dragenter
'
&&
this
.
eventname
!=
'
dragover
'
)
{
this
.
error
(
'
Action provider setDropEffect is only
'
+
'
available during events [dragenter|dragover].
'
);
return
;
}
kss
.
dnd
.
_dropEffect
=
params
.
value
.
toLowerCase
();
// update validDropTarget state variable
kss
.
dnd
.
isValidDropTarget
();
});
// action provider setDragImage, sets the element given by kssSelector
kss
.
registerActionProvider
(
'
setDragImage
'
,
function
(
node
,
params
)
{
if
(
this
.
eventname
!=
'
dragstart
'
)
{
this
.
error
(
'
Action provider setDragImage is only
'
+
'
available during event [dragstart].
'
);
return
;
}
try
{
// Set the drag image. Not supported by IE.
// Offsets are buggy in Opera and Firefox.
this
.
event
.
dataTransfer
.
setDragImage
(
node
,
params
.
offsetX
||
0
,
params
.
offsetY
||
0
);
// dataTransfer.addElement(elem) could be interesting, too.
// But at time not supported by Safari and IE.
}
catch
(
exc
)
{}
});
// action provider setDragData
kss
.
registerActionProvider
(
'
setDragData
'
,
function
(
node
,
params
)
{
if
(
this
.
eventname
!=
'
dragstart
'
)
{
this
.
error
(
'
Action provider setDragData is only
'
+
'
available during event [dragstart].
'
);
return
;
}
if
(
!
kss
.
dnd
.
_dataTransfer
)
{
this
.
error
(
'
No dataTransfer object available
'
);
return
;
}
kss
.
dnd
.
_dataTransfer
.
setData
(
params
.
type
,
params
.
value
);
});
// parameter provider dragData
kss
.
registerParameterProvider
(
'
dragData
'
,
function
(
node
,
datatype
)
{
// Check if we just want to collect all requested data types.
// Used by kss.dnd.isValidDropTarget above.
if
(
typeof
this
.
_requiredDragDataTypes
==
'
object
'
)
{
this
.
_requiredDragDataTypes
.
push
(
datatype
);
return
;
}
if
(
!
kss
.
dnd
.
_dataTransfer
)
{
this
.
error
(
'
No dataTransfer object available
'
);
return
;
}
return
kss
.
dnd
.
_dataTransfer
.
getData
(
datatype
);
});
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