So, I have a contenteditable div -- I\'m making a WYSIWYG editor: bold, italics, formatting, whatever, and most lately: inserting fancy images (in a fanc
Since I wanted to see this in a native JS solution I worked a bit to remove all jQuery dependencies. Hopefully it can help someone.
First the markup
WAITING FOR STUFF
Block 1
Second Blk
Then some helpers
function addClass( elem, className ){
var classNames = elem.className.split( " " )
if( classNames.indexOf( className ) === -1 ){
classNames.push( className )
}
elem.className = classNames.join( " " )
}
function selectElem( selector ){
return document.querySelector( selector )
}
function selectAllElems( selector ){
return document.querySelectorAll( selector )
}
function removeElem( elem ){
return elem ? elem.parentNode.removeChild( elem ) : false
}
Then the actual methods
function nativeBindDraggable( elems = false ){
elems = elems || selectAllElems( '.native_drag' );
if( !elems ){
// No element exists, abort
return false;
}else if( elems.outerHTML ){
// if only a single element, put in array
elems = [ elems ];
}
// else it is html-collection already (as good as array)
for( let i = 0 ; i < elems.length ; i++ ){
// For every elem in list, attach or re-attach event handling
elems[i].dataset.transferreference = `transit_${ new Date().getTime() }`;
elems[i].ondragstart = function(e){
if (!e.target.id){
e.target.id = (new Date()).getTime();
}
window.inTransferMarkup = e.target.outerHTML;
window.transferreference = elems[i].dataset.transferreference;
addClass( e.target, 'dragged');
};
};
}
function nativeBindWriteRegion( elems = false ){
elems = elems || selectAllElems( '.native_receiver' );
if( !elems ){
// No element exists, abort
return false;
}else if( elems.outerHTML ){
// if only a single element, put in array
elems = [ elems ];
}
// else it is html-collection
for( let i = 0 ; i < elems.length ; i++ ){
elems[i].ondragover = function(e){
e.preventDefault();
return false;
};
elems[i].ondrop = function(e){
receiveBlock(e);
};
}
}
function receiveBlock(e){
e.preventDefault();
let content = window.inTransferMarkup;
window.inTransferMarkup = "";
let range = null;
if (document.caretRangeFromPoint) { // Chrome
range = document.caretRangeFromPoint(e.clientX, e.clientY);
}else if (e.rangeParent) { // Firefox
range = document.createRange();
range.setStart(e.rangeParent, e.rangeOffset);
}
let sel = window.getSelection();
sel.removeAllRanges();
sel.addRange( range );
e.target.focus();
document.execCommand('insertHTML',false, content);
sel.removeAllRanges();
// reset draggable on all blocks, esp the recently created
nativeBindDraggable(
document.querySelector(
`[data-transferreference='${window.transferreference}']`
)
);
removeElem( selectElem( '.dragged' ) );
return false;
}
And lastly instantiate
nativeBindDraggable();
nativeBindWriteRegion();
Below is the functioning snippet
function addClass( elem, className ){
var classNames = elem.className.split( " " )
if( classNames.indexOf( className ) === -1 ){
classNames.push( className )
}
elem.className = classNames.join( " " )
}
function selectElem( selector ){
return document.querySelector( selector )
}
function selectAllElems( selector ){
return document.querySelectorAll( selector )
}
function removeElem( elem ){
return elem ? elem.parentNode.removeChild( elem ) : false
}
function nativeBindDraggable( elems = false ){
elems = elems || selectAllElems( '.native_drag' );
if( !elems ){
// No element exists, abort
return false;
}else if( elems.outerHTML ){
// if only a single element, put in array
elems = [ elems ];
}
// else it is html-collection already (as good as array)
for( let i = 0 ; i < elems.length ; i++ ){
// For every elem in list, attach or re-attach event handling
elems[i].dataset.transferreference = `transit_${ new Date().getTime() }`;
elems[i].ondragstart = function(e){
if (!e.target.id){
e.target.id = (new Date()).getTime();
}
window.inTransferMarkup = e.target.outerHTML;
window.transferreference = elems[i].dataset.transferreference;
addClass( e.target, 'dragged');
};
};
}
function nativeBindWriteRegion( elems = false ){
elems = elems || selectAllElems( '.native_receiver' );
if( !elems ){
// No element exists, abort
return false;
}else if( elems.outerHTML ){
// if only a single element, put in array
elems = [ elems ];
}
// else it is html-collection
for( let i = 0 ; i < elems.length ; i++ ){
elems[i].ondragover = function(e){
e.preventDefault();
return false;
};
elems[i].ondrop = function(e){
receiveBlock(e);
};
}
}
function receiveBlock(e){
e.preventDefault();
let content = window.inTransferMarkup;
window.inTransferMarkup = "";
let range = null;
if (document.caretRangeFromPoint) { // Chrome
range = document.caretRangeFromPoint(e.clientX, e.clientY);
}else if (e.rangeParent) { // Firefox
range = document.createRange();
range.setStart(e.rangeParent, e.rangeOffset);
}
let sel = window.getSelection();
sel.removeAllRanges();
sel.addRange( range );
e.target.focus();
document.execCommand('insertHTML',false, content);
sel.removeAllRanges();
// reset draggable on all blocks, esp the recently created
nativeBindDraggable(
document.querySelector(
`[data-transferreference='${window.transferreference}']`
)
);
removeElem( selectElem( '.dragged' ) );
return false;
}
nativeBindDraggable();
nativeBindWriteRegion();
WAITING FOR STUFF
Block 1
Second Blk