mirror of
https://github.com/lxsang/antos-frontend.git
synced 2025-07-19 15:29:51 +02:00
support dnd and grid sort
This commit is contained in:
@ -264,7 +264,6 @@ namespace OS {
|
||||
*/
|
||||
main(): void {
|
||||
const win = this.scheme as tag.WindowTag;
|
||||
$(win).attr("tabindex", 0);
|
||||
$(win).on('keydown', (e) => {
|
||||
switch (e.which) {
|
||||
case 27:
|
||||
@ -672,7 +671,7 @@ namespace OS {
|
||||
}
|
||||
for (let k in this.data) {
|
||||
const v = this.data[k];
|
||||
rows.push([{ text: k }, { text: v }]);
|
||||
rows.push([{ text: k }, { text: v, selectable: true }]);
|
||||
}
|
||||
const grid = this.find("grid") as tag.GridViewTag;
|
||||
grid.header = [
|
||||
@ -1052,7 +1051,7 @@ namespace OS {
|
||||
__("Resource not found: {0}", path)
|
||||
);
|
||||
}
|
||||
return (fileview.path = path);
|
||||
fileview.path = path;
|
||||
};
|
||||
|
||||
if (!this.data || !this.data.root) {
|
||||
@ -1088,11 +1087,14 @@ namespace OS {
|
||||
}
|
||||
};
|
||||
(this.find("btnOk") as tag.ButtonTag).onbtclick = (_e) => {
|
||||
const f = fileview.selectedFile;
|
||||
let f = fileview.selectedFile;
|
||||
if (!f) {
|
||||
return this.notify(
|
||||
__("Please select a file/fofler")
|
||||
);
|
||||
const sel = location.selectedItem;
|
||||
if(!sel)
|
||||
return this.notify(
|
||||
__("Please select a file/fofler")
|
||||
);
|
||||
f = sel.data as API.FileInfoType;
|
||||
}
|
||||
if (
|
||||
this.data &&
|
||||
|
@ -28,13 +28,13 @@ namespace OS {
|
||||
private _onfileopen: TagEventCallback<API.FileInfoType>;
|
||||
|
||||
/**
|
||||
* Reference to the currently selected file meta-data
|
||||
* Reference to the all selected files meta-datas
|
||||
*
|
||||
* @private
|
||||
* @type {API.FileInfoType}
|
||||
* @type {API.FileInfoType[]}
|
||||
* @memberof FileViewTag
|
||||
*/
|
||||
private _selectedFile: API.FileInfoType;
|
||||
private _selectedFiles: API.FileInfoType[];
|
||||
|
||||
/**
|
||||
* Data placeholder of the current working directory
|
||||
@ -58,10 +58,10 @@ namespace OS {
|
||||
* Header definition of the widget grid view
|
||||
*
|
||||
* @private
|
||||
* @type {(GenericObject<string | number>[])}
|
||||
* @type {(GenericObject<any>[])}
|
||||
* @memberof FileViewTag
|
||||
*/
|
||||
private _header: GenericObject<string | number>[];
|
||||
private _header: GenericObject<any>[];
|
||||
|
||||
/**
|
||||
* placeholder for the user-specified meta-data fetch function
|
||||
@ -92,10 +92,37 @@ namespace OS {
|
||||
this.chdir = true;
|
||||
this.view = "list";
|
||||
this._onfileopen = this._onfileselect = (e) => { };
|
||||
this._selectedFiles = [];
|
||||
const fn = function(r1, r2, i) {
|
||||
let t1 = r1[i].text;
|
||||
let t2 = r2[i].text;
|
||||
if(!t1 || !t2) return 0;
|
||||
t1 = t1.toString().toLowerCase();
|
||||
t2 = t2.toString().toLowerCase();
|
||||
if(this.__f)
|
||||
{
|
||||
this.desc = ! this.desc;
|
||||
if(t1 < t2) { return -1; }
|
||||
if(t1 > t2) { return 1; }
|
||||
}
|
||||
else
|
||||
{
|
||||
this.desc = ! this.desc;
|
||||
if(t1 > t2) { return -1; }
|
||||
if(t1 < t2) { return 1; }
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
this._header = [
|
||||
{ text: "__(File name)" },
|
||||
{
|
||||
text: "__(File name)",
|
||||
sort: fn
|
||||
},
|
||||
{ text: "__(Type)" },
|
||||
{ text: "__(Size)" },
|
||||
{
|
||||
text: "__(Size)",
|
||||
sort: fn
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -227,6 +254,28 @@ namespace OS {
|
||||
return this.hasattr("showhidden");
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter:
|
||||
*
|
||||
* Allow multiple selection on file view
|
||||
*
|
||||
* Getter:
|
||||
*
|
||||
* Check whether the multiselection is actived
|
||||
*
|
||||
* @memberof FileViewTag
|
||||
*/
|
||||
set multiselect(v: boolean) {
|
||||
this.attsw(v, "multiselect");
|
||||
(this.refs.listview as ListViewTag).multiselect = v;
|
||||
(this.refs.gridview as GridViewTag).multiselect = v;
|
||||
}
|
||||
get multiselect(): boolean {
|
||||
return this.hasattr("multiselect");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the current selected file
|
||||
*
|
||||
@ -235,7 +284,21 @@ namespace OS {
|
||||
* @memberof FileViewTag
|
||||
*/
|
||||
get selectedFile(): API.FileInfoType {
|
||||
return this._selectedFile;
|
||||
if(this._selectedFiles.length == 0)
|
||||
return undefined;
|
||||
return this._selectedFiles[this._selectedFiles.length - 1];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all selected files
|
||||
*
|
||||
* @readonly
|
||||
* @type {API.FileInfoType[]}
|
||||
* @memberof FileViewTag
|
||||
*/
|
||||
get selectedFiles(): API.FileInfoType[] {
|
||||
return this._selectedFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -286,7 +349,7 @@ namespace OS {
|
||||
*
|
||||
* @memberof FileViewTag
|
||||
*/
|
||||
set data(v: API.FileInfoType[]) {
|
||||
set data(v: API.FileInfoType[]) {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
@ -305,11 +368,21 @@ namespace OS {
|
||||
*/
|
||||
set ondragndrop(
|
||||
v: TagEventCallback<
|
||||
DnDEventDataType<TreeViewTag | ListViewItemTag>
|
||||
DnDEventDataType<TreeViewTag | ListViewItemTag | GridCellPrototype>
|
||||
>
|
||||
) {
|
||||
(this.refs.treeview as TreeViewTag).ondragndrop = v;
|
||||
(this.refs.listview as ListViewTag).ondragndrop = v;
|
||||
(this.refs.gridview as GridViewTag).ondragndrop = (e) => {
|
||||
const evt = {
|
||||
id: this.aid,
|
||||
data: {
|
||||
from: e.data.from.map(x => x.data[0].domel),
|
||||
to: e.data.to.data[0].domel
|
||||
}
|
||||
};
|
||||
v(evt);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -514,7 +587,7 @@ namespace OS {
|
||||
$(this.refs.listview).hide();
|
||||
$(this.refs.gridview).hide();
|
||||
$(this.refs.treecontainer).hide();
|
||||
this._selectedFile = undefined;
|
||||
this._selectedFiles = [];
|
||||
switch (this.view) {
|
||||
case "icon":
|
||||
$(this.refs.listview).show();
|
||||
@ -552,7 +625,6 @@ namespace OS {
|
||||
);
|
||||
}
|
||||
const evt = { id: this.aid, data: e };
|
||||
this._selectedFile = e;
|
||||
this._onfileselect(evt);
|
||||
this.observable.trigger("fileselect", evt);
|
||||
}
|
||||
@ -612,18 +684,22 @@ namespace OS {
|
||||
grid.header = this._header;
|
||||
tree.dragndrop = true;
|
||||
list.dragndrop = true;
|
||||
grid.dragndrop = true;
|
||||
// even handles
|
||||
list.onlistselect = (e) => {
|
||||
this.fileselect(e.data.item.data as API.FileInfoType);
|
||||
this._selectedFiles = e.data.items.map( x => x.data as API.FileInfoType);
|
||||
};
|
||||
grid.onrowselect = (e) => {
|
||||
this.fileselect(
|
||||
($(e.data.item).children()[0] as GridCellPrototype)
|
||||
.data as API.FileInfoType
|
||||
);
|
||||
this._selectedFiles = e.data.items.map( x => ($(x).children()[0] as GridCellPrototype).data as API.FileInfoType);
|
||||
};
|
||||
tree.ontreeselect = (e) => {
|
||||
this.fileselect(e.data.item.data as API.FileInfoType);
|
||||
this._selectedFiles = [e.data.item.data as API.FileInfoType];
|
||||
};
|
||||
// dblclick
|
||||
list.onlistdbclick = (e) => {
|
||||
|
@ -19,6 +19,10 @@ interface Array<T> {
|
||||
namespace OS {
|
||||
export namespace GUI {
|
||||
export namespace tag {
|
||||
/**
|
||||
* Row item event data type
|
||||
*/
|
||||
export type GridRowEventData = TagEventDataType<GridRowTag>;
|
||||
/**
|
||||
* A grid Row is a simple element that
|
||||
* contains a group of grid cell
|
||||
@ -36,6 +40,15 @@ namespace OS {
|
||||
*/
|
||||
data: GenericObject<any>[];
|
||||
|
||||
/**
|
||||
* placeholder for the row select event callback
|
||||
*
|
||||
* @private
|
||||
* @type {TagEventCallback<GridRowEventData>}
|
||||
* @memberof ListViewItemTag
|
||||
*/
|
||||
private _onselect: TagEventCallback<GridRowEventData>;
|
||||
|
||||
/**
|
||||
*Creates an instance of GridRowTag.
|
||||
* @memberof GridRowTag
|
||||
@ -44,6 +57,36 @@ namespace OS {
|
||||
super();
|
||||
|
||||
this.refs.yield = this;
|
||||
this._onselect = (e) => {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item select event handle
|
||||
*
|
||||
* @memberof ListViewItemTag
|
||||
*/
|
||||
set onrowselect(v: TagEventCallback<GridRowEventData>) {
|
||||
this._onselect = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter: select/unselect the current item
|
||||
*
|
||||
* Getter: Check whether the current item is selected
|
||||
*
|
||||
* @memberof ListViewItemTag
|
||||
*/
|
||||
set selected(v: boolean) {
|
||||
this.attsw(v, "selected");
|
||||
$(this).removeClass();
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
$(this).addClass("afx-grid-row-selected");
|
||||
this._onselect({ id: this.aid, data: this });
|
||||
}
|
||||
get selected(): boolean {
|
||||
return this.hasattr("selected");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -420,6 +463,27 @@ namespace OS {
|
||||
*/
|
||||
private _oncelldbclick: TagEventCallback<CellEventData>;
|
||||
|
||||
/**
|
||||
* Event data passing between mouse event when performing
|
||||
* drag and drop on the list
|
||||
*
|
||||
* @private
|
||||
* @type {{ from: GridRowTag[]; to: GridRowTag }}
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
private _dnd: { from: GridRowTag[]; to: GridRowTag };
|
||||
|
||||
/**
|
||||
* placeholder of list drag and drop event handle
|
||||
*
|
||||
* @private
|
||||
* @type {TagEventCallback<DnDEventDataType<GridRowTag>>}
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
private _ondragndrop: TagEventCallback<
|
||||
DnDEventDataType<GridRowTag>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Creates an instance of GridViewTag.
|
||||
* @memberof GridViewTag
|
||||
@ -428,6 +492,68 @@ namespace OS {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set drag and drop event handle
|
||||
*
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
set ondragndrop(
|
||||
v: TagEventCallback<DnDEventDataType<GridRowTag>>
|
||||
) {
|
||||
this._ondragndrop = v;
|
||||
this.dragndrop = this.dragndrop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter: Enable/disable drag and drop event in the list
|
||||
*
|
||||
* Getter: Check whether the drag and drop event is enabled
|
||||
*
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
set dragndrop(v: boolean) {
|
||||
this.attsw(v, "dragndrop");
|
||||
if(!v)
|
||||
{
|
||||
$(this.refs.container).off("mousedown", this._onmousedown);
|
||||
}
|
||||
else
|
||||
{
|
||||
$(this.refs.container).on(
|
||||
"mousedown",
|
||||
this._onmousedown
|
||||
);
|
||||
}
|
||||
}
|
||||
get dragndrop(): boolean {
|
||||
return this.hasattr("dragndrop");
|
||||
}
|
||||
|
||||
/**
|
||||
* placeholder of drag and drop mouse down event handle
|
||||
*
|
||||
* @private
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
private _onmousedown: (e: JQuery.MouseEventBase) => void;
|
||||
|
||||
/**
|
||||
* placeholder of drag and drop mouse up event handle
|
||||
*
|
||||
* @private
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
private _onmouseup: (e: JQuery.MouseEventBase) => void;
|
||||
|
||||
/**
|
||||
* placeholder of drag and drop mouse move event handle
|
||||
*
|
||||
* @private
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
private _onmousemove: (e: JQuery.MouseEventBase) => void;
|
||||
|
||||
|
||||
/**
|
||||
* Init the grid view before mounting.
|
||||
* Reset all the placeholders to default values
|
||||
@ -444,9 +570,13 @@ namespace OS {
|
||||
this._selectedRow = undefined;
|
||||
this._rows = [];
|
||||
this.resizable = false;
|
||||
this.dragndrop = false;
|
||||
this._oncellselect = this._onrowselect = this._oncelldbclick = (
|
||||
e: TagEventType<CellEventData>
|
||||
): void => {};
|
||||
this._ondragndrop = (
|
||||
e: TagEventType<DnDEventDataType<GridRowTag>>
|
||||
) => {};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -507,7 +637,14 @@ namespace OS {
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
set cellitem(v: string) {
|
||||
const currci = this.cellitem;
|
||||
$(this).attr("cellitem", v);
|
||||
if(v != currci)
|
||||
{
|
||||
// force render data
|
||||
$(this.refs.grid).empty();
|
||||
this.rows = this.rows;
|
||||
}
|
||||
}
|
||||
get cellitem(): string {
|
||||
return $(this).attr("cellitem");
|
||||
@ -539,6 +676,12 @@ namespace OS {
|
||||
element.uify(this.observable);
|
||||
element.data = item;
|
||||
item.domel = element;
|
||||
element.oncellselect = (e) => {
|
||||
if(element.data.sort)
|
||||
{
|
||||
this.sort(element.data, element.data.sort);
|
||||
}
|
||||
};
|
||||
i++;
|
||||
if (this.resizable) {
|
||||
if (i != v.length) {
|
||||
@ -604,9 +747,48 @@ namespace OS {
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
set rows(rows: GenericObject<any>[][]) {
|
||||
$(this.refs.grid).empty();
|
||||
this._rows = rows;
|
||||
rows.map((row) => this.push(row, false));
|
||||
if(!rows) return;
|
||||
// update existing row with new data
|
||||
const ndrows = rows.length;
|
||||
const ncrows = this.refs.grid.children.length;
|
||||
const nmin = ndrows < ncrows? ndrows: ncrows;
|
||||
if(this.selectedRow)
|
||||
{
|
||||
this.selectedRow.selected = false;
|
||||
this._selectedRow = undefined;
|
||||
this._selectedRows = [];
|
||||
}
|
||||
for(let i = 0; i < nmin; i++)
|
||||
{
|
||||
const rowel = (this.refs.grid.children[i] as GridRowTag);
|
||||
rowel.data = rows[i];
|
||||
rowel.data.domel = rowel;
|
||||
for(let celi = 0; celi < rowel.children.length; celi++)
|
||||
{
|
||||
const cel = (rowel.children[celi] as GridCellPrototype);
|
||||
cel.data = rows[i][celi];
|
||||
cel.data.domel = cel;
|
||||
}
|
||||
}
|
||||
// remove existing remaining rows
|
||||
if(ndrows < ncrows)
|
||||
{
|
||||
const arr = Array.prototype.slice.call(this.refs.grid.children);
|
||||
const blacklist = arr.slice(nmin, ncrows);
|
||||
for(const r of blacklist)
|
||||
{
|
||||
this.delete(r);
|
||||
}
|
||||
}
|
||||
// or add more rows
|
||||
else if(ndrows > ncrows)
|
||||
{
|
||||
for(let i = nmin; i < ndrows; i++)
|
||||
{
|
||||
this.push(rows[i], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
get rows(): GenericObject<any>[][] {
|
||||
return this._rows;
|
||||
@ -639,7 +821,24 @@ namespace OS {
|
||||
get resizable(): boolean {
|
||||
return this.hasattr("resizable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the grid using a sort function
|
||||
*
|
||||
* @param {context: any} context of the executed function
|
||||
* @param {(a:GenericObject<any>[], b:GenericObject<any>[]) => boolean} a sort function that compares two rows data
|
||||
* * @param {index: number} current header index
|
||||
* @returns {void}
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
sort(context: any, fn: (a:GenericObject<any>[], b:GenericObject<any>[], index?: number) => number): void {
|
||||
const index = this._header.indexOf(context);
|
||||
const __fn = (a, b) => {
|
||||
return fn.call(context,a, b, index);
|
||||
}
|
||||
this._rows.sort(__fn);
|
||||
context.__f = ! context.__f;
|
||||
this.rows = this._rows;
|
||||
}
|
||||
/**
|
||||
* Delete a grid rows
|
||||
*
|
||||
@ -713,6 +912,10 @@ namespace OS {
|
||||
element.oncelldbclick = (e) => this.cellselect(e, true);
|
||||
element.data = cell;
|
||||
}
|
||||
el.onrowselect = (e) => this.rowselect({
|
||||
id: el.aid,
|
||||
data: {item: el}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -751,7 +954,10 @@ namespace OS {
|
||||
} else {
|
||||
this.observable.trigger("cellselect", e);
|
||||
this._oncellselect(e);
|
||||
return this.rowselect(e);
|
||||
const row = ($(
|
||||
e.data.item
|
||||
).parent()[0] as any) as GridRowTag;
|
||||
row.selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -759,11 +965,11 @@ namespace OS {
|
||||
* This function triggers the row select event, a cell select
|
||||
* event will also trigger this event
|
||||
*
|
||||
* @param {TagEventType<CellEventData>} e
|
||||
* @param {TagEventType<GridRowEventData>} e
|
||||
* @returns {void}
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
private rowselect(e: TagEventType<CellEventData>): void {
|
||||
private rowselect(e: TagEventType<GridRowEventData>): void {
|
||||
if (!e.data.item) {
|
||||
return;
|
||||
}
|
||||
@ -774,39 +980,58 @@ namespace OS {
|
||||
items: [],
|
||||
},
|
||||
};
|
||||
const row = ($(
|
||||
e.data.item
|
||||
).parent()[0] as any) as GridRowTag;
|
||||
const row = e.data.item as GridRowTag;
|
||||
if (this.multiselect) {
|
||||
if (this.selectedRows.includes(row)) {
|
||||
this.selectedRows.splice(
|
||||
this.selectedRows.indexOf(row),
|
||||
1
|
||||
);
|
||||
$(row).removeClass();
|
||||
row.selected = false;
|
||||
return;
|
||||
} else {
|
||||
this.selectedRows.push(row);
|
||||
$(row)
|
||||
.removeClass()
|
||||
.addClass("afx-grid-row-selected");
|
||||
}
|
||||
evt.data.items = this.selectedRows;
|
||||
} else {
|
||||
if(this.selectedRows.length > 0)
|
||||
{
|
||||
for(const item of this.selectedRows)
|
||||
{
|
||||
if(item != row)
|
||||
{
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.selectedRow === row) {
|
||||
return;
|
||||
}
|
||||
$(this.selectedRow).removeClass();
|
||||
this._selectedRows = [row];
|
||||
evt.data.item = row;
|
||||
if(this.selectedRow)
|
||||
this.selectedRow.selected = false;
|
||||
evt.data.items = [row];
|
||||
$(row).removeClass().addClass("afx-grid-row-selected");
|
||||
this._selectedRows = [row];
|
||||
}
|
||||
evt.data.item = row;
|
||||
this._selectedRow = row;
|
||||
this._onrowselect(evt);
|
||||
return this.observable.trigger("rowselect", evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unselect all the selected rows in the grid
|
||||
*
|
||||
* @returns {void}
|
||||
* @memberof GridViewTag
|
||||
*/
|
||||
unselect(): void {
|
||||
for (let v of this.selectedRows) {
|
||||
v.selected = false;
|
||||
}
|
||||
this._selectedRows = [];
|
||||
this._selectedRow = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the grid has header
|
||||
*
|
||||
@ -904,7 +1129,6 @@ namespace OS {
|
||||
*/
|
||||
protected mount(): void {
|
||||
$(this).css("overflow", "hidden");
|
||||
|
||||
$(this.refs.grid).css("display", "grid");
|
||||
$(this.refs.header).css("display", "grid");
|
||||
this.observable.on("resize", (e) => this.calibrate());
|
||||
@ -912,6 +1136,73 @@ namespace OS {
|
||||
.css("width", "100%")
|
||||
.css("overflow-x", "hidden")
|
||||
.css("overflow-y", "auto");
|
||||
// drag and drop
|
||||
this._dnd = {
|
||||
from: undefined,
|
||||
to: undefined,
|
||||
};
|
||||
this._onmousedown = (e) => {
|
||||
if(this.multiselect || this.selectedRows == undefined || this.selectedRows.length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
let el: any = $(e.target).closest("afx-grid-row");
|
||||
if (el.length === 0) {
|
||||
return;
|
||||
}
|
||||
el = el[0];
|
||||
if(!this.selectedRows.includes(el))
|
||||
{
|
||||
return;
|
||||
}
|
||||
this._dnd.from = this.selectedRows;
|
||||
this._dnd.to = undefined;
|
||||
$(window).on("mouseup", this._onmouseup);
|
||||
$(window).on("mousemove", this._onmousemove);
|
||||
};
|
||||
|
||||
this._onmouseup = (e) => {
|
||||
$(window).off("mouseup", this._onmouseup);
|
||||
$(window).off("mousemove", this._onmousemove);
|
||||
$("#systooltip").hide();
|
||||
let el: any = $(e.target).closest("afx-grid-row");
|
||||
if (el.length === 0) {
|
||||
return;
|
||||
}
|
||||
el = el[0];
|
||||
if (this._dnd.from.includes(el)) {
|
||||
return;
|
||||
}
|
||||
this._dnd.to = el;
|
||||
this._ondragndrop({ id: this.aid, data: this._dnd });
|
||||
this._dnd = {
|
||||
from: undefined,
|
||||
to: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
this._onmousemove = (e) => {
|
||||
if (!e) {
|
||||
return;
|
||||
}
|
||||
if (!this._dnd.from) {
|
||||
return;
|
||||
}
|
||||
const data = {
|
||||
text: __("{0} selected elements", this._dnd.from.length).__(),
|
||||
items: this._dnd.from
|
||||
};
|
||||
const $label = $("#systooltip");
|
||||
const top = e.clientY + 5;
|
||||
const left = e.clientX + 5;
|
||||
$label.show();
|
||||
const label = $label[0] as LabelTag;
|
||||
label.set(data);
|
||||
return $label
|
||||
.css("top", top + "px")
|
||||
.css("left", left + "px");
|
||||
};
|
||||
|
||||
return this.calibrate();
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ namespace OS {
|
||||
this.icon = undefined;
|
||||
this.iconclass = undefined;
|
||||
this.text = undefined;
|
||||
this.selectable = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,6 +122,33 @@ namespace OS {
|
||||
return this._text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setter: Turn on/off text selection
|
||||
*
|
||||
* Getter: Check whether the label is selectable
|
||||
*
|
||||
* @memberof LabelTag
|
||||
*/
|
||||
set selectable(v: boolean) {
|
||||
this.attsw(v, "selectable");
|
||||
if(v)
|
||||
{
|
||||
$(this.refs.text)
|
||||
.css("user-select", "text")
|
||||
.css("cursor", "text");
|
||||
}
|
||||
else
|
||||
{
|
||||
$(this.refs.text)
|
||||
.css("user-select", "none")
|
||||
.css("cursor", "default");
|
||||
}
|
||||
}
|
||||
get swon(): boolean {
|
||||
return this.hasattr("selectable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Lqbel layout definition
|
||||
*
|
||||
|
@ -444,10 +444,10 @@ namespace OS {
|
||||
* drag and drop on the list
|
||||
*
|
||||
* @private
|
||||
* @type {{ from: ListViewItemTag; to: ListViewItemTag }}
|
||||
* @type {{ from: ListViewItemTag[]; to: ListViewItemTag }}
|
||||
* @memberof ListViewTag
|
||||
*/
|
||||
private _dnd: { from: ListViewItemTag; to: ListViewItemTag };
|
||||
private _dnd: { from: ListViewItemTag[]; to: ListViewItemTag };
|
||||
|
||||
/**
|
||||
*Creates an instance of ListViewTag.
|
||||
@ -990,6 +990,16 @@ namespace OS {
|
||||
this.selectedItems.push(e.data);
|
||||
edata.items = this.selectedItems;
|
||||
} else {
|
||||
if(this.selectedItems.length > 0)
|
||||
{
|
||||
for(const item of this.selectedItems)
|
||||
{
|
||||
if(item != e.data)
|
||||
{
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.selectedItem === e.data) {
|
||||
return;
|
||||
}
|
||||
@ -1044,14 +1054,22 @@ namespace OS {
|
||||
to: undefined,
|
||||
};
|
||||
this._onmousedown = (e) => {
|
||||
if(this.multiselect || this.selectedItems == undefined || this.selectedItems.length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
let el: any = $(e.target).closest(
|
||||
"li[dataref='afx-list-item']"
|
||||
);
|
||||
if (el.length === 0) {
|
||||
return;
|
||||
}
|
||||
el = el.parent()[0] as ListViewItemTag;
|
||||
this._dnd.from = el;
|
||||
el = el.parent()[0];
|
||||
if(!this.selectedItems.includes(el))
|
||||
{
|
||||
return;
|
||||
}
|
||||
this._dnd.from = this.selectedItems;
|
||||
this._dnd.to = undefined;
|
||||
$(window).on("mouseup", this._onmouseup);
|
||||
$(window).on("mousemove", this._onmousemove);
|
||||
@ -1068,7 +1086,7 @@ namespace OS {
|
||||
return;
|
||||
}
|
||||
el = el.parent()[0];
|
||||
if (el === this._dnd.from) {
|
||||
if (this._dnd.from.includes(el)) {
|
||||
return;
|
||||
}
|
||||
this._dnd.to = el;
|
||||
@ -1086,7 +1104,18 @@ namespace OS {
|
||||
if (!this._dnd.from) {
|
||||
return;
|
||||
}
|
||||
const data = this._dnd.from.data;
|
||||
const data = {
|
||||
text: '',
|
||||
items: this._dnd.from
|
||||
};
|
||||
if(this._dnd.from.length == 1)
|
||||
{
|
||||
data.text = this._dnd.from[0].data.text;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.text = __("{0} selected elements", this._dnd.from.length).__();
|
||||
}
|
||||
const $label = $("#systooltip");
|
||||
const top = e.clientY + 5;
|
||||
const left = e.clientX + 5;
|
||||
|
@ -586,10 +586,10 @@ namespace OS {
|
||||
* Private data object passing between dragndrop mouse event
|
||||
*
|
||||
* @private
|
||||
* @type {{ from: TreeViewTag; to: TreeViewTag }}
|
||||
* @type {{ from: TreeViewTag[]; to: TreeViewTag }}
|
||||
* @memberof TreeViewTag
|
||||
*/
|
||||
private _dnd: { from: TreeViewTag; to: TreeViewTag };
|
||||
private _dnd: { from: TreeViewTag[]; to: TreeViewTag };
|
||||
|
||||
/**
|
||||
* Reference to parent tree of the current tree.
|
||||
@ -638,7 +638,7 @@ namespace OS {
|
||||
* current tree. This function should return a promise on
|
||||
* a list of [[TreeViewDataType]]
|
||||
*
|
||||
* @memberof TreeViewItemPrototype
|
||||
* @memberof TreeViewTag
|
||||
*/
|
||||
fetch: (
|
||||
d: TreeViewItemPrototype
|
||||
@ -920,7 +920,7 @@ namespace OS {
|
||||
*/
|
||||
protected mount(): void {
|
||||
this._dnd = {
|
||||
from: undefined,
|
||||
from: [],
|
||||
to: undefined,
|
||||
};
|
||||
this._treemousedown = (e) => {
|
||||
@ -932,7 +932,7 @@ namespace OS {
|
||||
if (el === this) {
|
||||
return;
|
||||
}
|
||||
this._dnd.from = el;
|
||||
this._dnd.from = [el];
|
||||
this._dnd.to = undefined;
|
||||
$(window).on("mouseup", this._treemouseup);
|
||||
return $(window).on("mousemove", this._treemousemove);
|
||||
@ -951,8 +951,8 @@ namespace OS {
|
||||
el = el.parent;
|
||||
}
|
||||
if (
|
||||
el === this._dnd.from ||
|
||||
el === this._dnd.from.parent
|
||||
el === this._dnd.from[0] ||
|
||||
el === this._dnd.from[0].parent
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -962,7 +962,7 @@ namespace OS {
|
||||
data: this._dnd,
|
||||
});
|
||||
this._dnd = {
|
||||
from: undefined,
|
||||
from: [],
|
||||
to: undefined,
|
||||
};
|
||||
};
|
||||
@ -974,7 +974,7 @@ namespace OS {
|
||||
if (!this._dnd.from) {
|
||||
return;
|
||||
}
|
||||
const data = this._dnd.from.data;
|
||||
const data = this._dnd.from[0].data;
|
||||
const $label = $("#systooltip");
|
||||
const top = e.clientY + 5;
|
||||
const left = e.clientX + 5;
|
||||
|
@ -306,6 +306,7 @@ namespace OS {
|
||||
.removeClass("unactive");
|
||||
this._shown = true;
|
||||
$(this.refs.win_overlay).hide();
|
||||
$(this).trigger("focus");
|
||||
});
|
||||
|
||||
this.observable.on("blur", () => {
|
||||
@ -336,6 +337,7 @@ namespace OS {
|
||||
w: this.width,
|
||||
h: this.height,
|
||||
});
|
||||
$(this).attr("tabindex", 0).css("outline", "none");
|
||||
return this.observable.trigger("rendered", {
|
||||
id: this.aid,
|
||||
});
|
||||
|
@ -233,7 +233,7 @@ namespace OS {
|
||||
* @type {T}
|
||||
* @memberof DnDEventDataType
|
||||
*/
|
||||
from: T;
|
||||
from: T[];
|
||||
|
||||
/**
|
||||
* Reference to the target DOM element
|
||||
|
Reference in New Issue
Block a user