mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-08-15 02:42:30 +02:00
Implements DND for et2-select-email tags
This commit is contained in:
@ -10,6 +10,7 @@
|
||||
import {Et2Select} from "./Et2Select";
|
||||
import {css} from "@lion/core";
|
||||
import {IsEmail} from "../Validators/IsEmail";
|
||||
import interact from "@interactjs/interact";
|
||||
|
||||
export class Et2SelectEmail extends Et2Select
|
||||
{
|
||||
@ -39,6 +40,18 @@ export class Et2SelectEmail extends Et2Select
|
||||
];
|
||||
}
|
||||
|
||||
static get properties()
|
||||
{
|
||||
return {
|
||||
...super.properties,
|
||||
|
||||
/**
|
||||
* Allow drag and drop tags
|
||||
*/
|
||||
allowDragAndDrop: {type: Boolean}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(...args : any[])
|
||||
{
|
||||
super(...args);
|
||||
@ -46,6 +59,7 @@ export class Et2SelectEmail extends Et2Select
|
||||
this.searchUrl = "EGroupware\\Api\\Etemplate\\Widget\\Taglist::ajax_email";
|
||||
this.allowFreeEntries = true;
|
||||
this.editModeEnabled = true;
|
||||
this.allowDragAndDrop = false;
|
||||
this.multiple = true;
|
||||
this.defaultValidators.push(new IsEmail());
|
||||
}
|
||||
@ -94,6 +108,44 @@ export class Et2SelectEmail extends Et2Select
|
||||
results.forEach(r => r.value = r.id);
|
||||
super.processRemoteResults(results);
|
||||
}
|
||||
|
||||
/**
|
||||
* override tag creation in order to add DND functionality
|
||||
* @param item
|
||||
* @protected
|
||||
*/
|
||||
protected _createTagNode(item)
|
||||
{
|
||||
let tag = super._createTagNode(item);
|
||||
if (!this.readonly && this.allowFreeEntries && this.allowDragAndDrop)
|
||||
{
|
||||
let dragTranslate = {x:0,y:0};
|
||||
tag.class = item.classList.value + " et2-select-draggable";
|
||||
let draggable = interact(tag).draggable({
|
||||
startAxis: 'xy',
|
||||
listeners: {
|
||||
start: function(e)
|
||||
{
|
||||
let dragPosition = {x:e.page.x, y:e.page.y};
|
||||
e.target.setAttribute('style', `width:${e.target.clientWidth}px !important`);
|
||||
e.target.style.position = 'fixed';
|
||||
e.target.style.transform =
|
||||
`translate(${dragPosition.x}px, ${dragPosition.y}px)`;
|
||||
},
|
||||
move : function(e)
|
||||
{
|
||||
dragTranslate.x += e.delta.x;
|
||||
dragTranslate.y += e.delta.y;
|
||||
e.target.style.transform =
|
||||
`translate(${dragTranslate.x}px, ${dragTranslate.y}px)`;
|
||||
}
|
||||
}
|
||||
});
|
||||
// set parent_node with widget context in order to make it accessible after drop
|
||||
draggable.parent_node = this;
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore TypeScript is not recognizing that this widget is a LitElement
|
||||
|
@ -12,6 +12,7 @@ import {css, html, LitElement, render, repeat, SlotMixin} from "@lion/core";
|
||||
import {cleanSelectOptions, SelectOption} from "./FindSelectOptions";
|
||||
import {Validator} from "@lion/form-core";
|
||||
import {Et2Tag} from "./Tag/Et2Tag";
|
||||
import interact from "@interactjs/interact";
|
||||
|
||||
// Otherwise import gets stripped
|
||||
let keep_import : Et2Tag;
|
||||
@ -441,8 +442,33 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
|
||||
this.addEventListener("sl-blur", this._handleSearchAbort);
|
||||
this.addEventListener("sl-select", this._handleSelect);
|
||||
this.addEventListener("sl-clear", this._handleClear)
|
||||
|
||||
this._searchButtonNode.addEventListener("click", this._handleSearchButtonClick);
|
||||
if (this.nodeName === 'ET2-SELECT-EMAIL')
|
||||
{
|
||||
interact(this).dropzone({
|
||||
accept: `.et2-select-draggable`,
|
||||
ondrop: function(e)
|
||||
{
|
||||
e.target.createFreeEntry(e.draggable.target.value);
|
||||
e.target.classList.remove('et2_toolbarDropArea');
|
||||
|
||||
// remove the dragged value from its origin source
|
||||
e.draggable.parent_node.value = e.draggable.parent_node.value.filter(_item=>{return e.draggable.target.value !== _item;})
|
||||
|
||||
// set value for newly dropped target
|
||||
e.target.value.push(e.draggable.target.value);
|
||||
},
|
||||
ondragenter: function(e)
|
||||
{
|
||||
e.target.classList.add('et2_dropZone');
|
||||
},
|
||||
ondragleave: function(e)
|
||||
{
|
||||
e.target.classList.remove('et2_dropZone');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected _unbindListeners()
|
||||
|
@ -248,10 +248,10 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
|
||||
// Clear existing
|
||||
this.div.empty();
|
||||
this.actionbox
|
||||
.removeClass('et2_toolbarDropArea')
|
||||
.removeClass('et2_dropZone')
|
||||
.empty();
|
||||
this.actionlist
|
||||
.removeClass('et2_toolbarDropArea')
|
||||
.removeClass('et2_dropZone')
|
||||
.empty();
|
||||
let admin_setting = this.options.is_admin ? '<span class="toolbar-admin-pref" title="'+egw.lang('Admin settings')+' ..."></span>': '';
|
||||
const list_header = this.options.list_header == 'more'?true:false;
|
||||
@ -509,11 +509,11 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
|
||||
},
|
||||
ondragenter: function(e)
|
||||
{
|
||||
e.target.classList.add('et2_toolbarDropArea');
|
||||
e.target.classList.add('et2_dropZone');
|
||||
},
|
||||
ondragleave: function(e)
|
||||
{
|
||||
e.target.classList.remove('et2_toolbarDropArea');
|
||||
e.target.classList.remove('et2_dropZone');
|
||||
}
|
||||
});
|
||||
const menulist = [`.et2_toolbar_dropzone_more${this.id}`, `#${this.id}-menulist`];
|
||||
@ -546,11 +546,11 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
|
||||
},
|
||||
ondragenter: function(e)
|
||||
{
|
||||
e.target.classList.add('et2_toolbarDropArea');
|
||||
e.target.classList.add('et2_dropZone');
|
||||
},
|
||||
ondragleave: function(e)
|
||||
{
|
||||
e.target.classList.remove('et2_toolbarDropArea');
|
||||
e.target.classList.remove('et2_dropZone');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user