@tabler/core
Version:
Premium and Open Source dashboard template with responsive and high quality UI.
144 lines (108 loc) • 3.75 kB
text/typescript
/**
* Plugin: "drag_drop" (Tom Select)
* Copyright (c) contributors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at:
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
* ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*
*/
import type TomSelect from '../../tom-select.ts';
import { TomOption, TomItem } from '../../types/index.ts';
import { escape_html, preventDefault, addEvent } from '../../utils.ts';
import { getDom, setAttr } from '../../vanilla.ts';
const insertAfter = (referenceNode:Element, newNode:Element) => {
referenceNode.parentNode?.insertBefore(newNode, referenceNode.nextSibling);
}
const insertBefore = (referenceNode:Element, newNode:Element) => {
referenceNode.parentNode?.insertBefore(newNode, referenceNode);
}
const isBefore = (referenceNode:Element|undefined|null, newNode:Element|undefined|null) =>{
do{
newNode = newNode?.previousElementSibling;
if( referenceNode == newNode ){
return true;
}
}while( newNode && newNode.previousElementSibling );
return false;
}
export default function(this:TomSelect) {
var self = this;
if (self.settings.mode !== 'multi') return;
var orig_lock = self.lock;
var orig_unlock = self.unlock;
let sortable = true;
let drag_item:TomItem|undefined;
/**
* Add draggable attribute to item
*/
self.hook('after','setupTemplates',() => {
var orig_render_item = self.settings.render.item;
self.settings.render.item = (data:TomOption, escape:typeof escape_html) => {
const item = getDom(orig_render_item.call(self, data, escape)) as TomItem;
setAttr(item,{'draggable':'true'});
// prevent doc_mousedown (see tom-select.ts)
const mousedown = (evt:Event) => {
if( !sortable ) preventDefault(evt);
evt.stopPropagation();
}
const dragStart = (evt:Event) => {
drag_item = item;
setTimeout(() => {
item.classList.add('ts-dragging');
}, 0);
}
const dragOver = (evt:Event) =>{
evt.preventDefault();
item.classList.add('ts-drag-over');
moveitem(item,drag_item);
}
const dragLeave = () => {
item.classList.remove('ts-drag-over');
}
const moveitem = (targetitem:TomItem, dragitem:TomItem|undefined) => {
if( dragitem === undefined ) return;
if( isBefore(dragitem,item) ){
insertAfter(targetitem,dragitem);
}else{
insertBefore(targetitem,dragitem);
}
}
const dragend = () => {
document.querySelectorAll('.ts-drag-over').forEach(el=> el.classList.remove('ts-drag-over'));
drag_item?.classList.remove('ts-dragging');
drag_item = undefined;
var values:string[] = [];
self.control.querySelectorAll(`[data-value]`).forEach((el:Element)=> {
if( (<HTMLOptionElement>el).dataset.value ){
let value = (<HTMLOptionElement>el).dataset.value;
if( value ){
values.push(value);
}
}
});
self.setValue(values);
}
addEvent(item,'mousedown', mousedown);
addEvent(item,'dragstart', dragStart);
addEvent(item,'dragenter', dragOver)
addEvent(item,'dragover', dragOver);
addEvent(item,'dragleave', dragLeave);
addEvent(item,'dragend', dragend);
return item;
}
});
self.hook('instead','lock',()=>{
sortable = false;
return orig_lock.call(self);
});
self.hook('instead','unlock',()=>{
sortable = true;
return orig_unlock.call(self);
});
};