mirror of
https://github.com/lxsang/antos-frontend.git
synced 2024-11-10 14:58:21 +01:00
support dnd and grid sort
This commit is contained in:
parent
079af3b0ce
commit
2cdd8f9a43
147
d.ts/antos.d.ts
vendored
147
d.ts/antos.d.ts
vendored
@ -3089,13 +3089,13 @@ declare namespace OS {
|
|||||||
*/
|
*/
|
||||||
private _onfileopen;
|
private _onfileopen;
|
||||||
/**
|
/**
|
||||||
* Reference to the currently selected file meta-data
|
* Reference to the all selected files meta-datas
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {API.FileInfoType}
|
* @type {API.FileInfoType[]}
|
||||||
* @memberof FileViewTag
|
* @memberof FileViewTag
|
||||||
*/
|
*/
|
||||||
private _selectedFile;
|
private _selectedFiles;
|
||||||
/**
|
/**
|
||||||
* Data placeholder of the current working directory
|
* Data placeholder of the current working directory
|
||||||
*
|
*
|
||||||
@ -3116,7 +3116,7 @@ declare namespace OS {
|
|||||||
* Header definition of the widget grid view
|
* Header definition of the widget grid view
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {(GenericObject<string | number>[])}
|
* @type {(GenericObject<any>[])}
|
||||||
* @memberof FileViewTag
|
* @memberof FileViewTag
|
||||||
*/
|
*/
|
||||||
private _header;
|
private _header;
|
||||||
@ -3227,6 +3227,19 @@ declare namespace OS {
|
|||||||
*/
|
*/
|
||||||
set showhidden(v: boolean);
|
set showhidden(v: boolean);
|
||||||
get showhidden(): boolean;
|
get showhidden(): boolean;
|
||||||
|
/**
|
||||||
|
* Setter:
|
||||||
|
*
|
||||||
|
* Allow multiple selection on file view
|
||||||
|
*
|
||||||
|
* Getter:
|
||||||
|
*
|
||||||
|
* Check whether the multiselection is actived
|
||||||
|
*
|
||||||
|
* @memberof FileViewTag
|
||||||
|
*/
|
||||||
|
set multiselect(v: boolean);
|
||||||
|
get multiselect(): boolean;
|
||||||
/**
|
/**
|
||||||
* Get the current selected file
|
* Get the current selected file
|
||||||
*
|
*
|
||||||
@ -3235,6 +3248,14 @@ declare namespace OS {
|
|||||||
* @memberof FileViewTag
|
* @memberof FileViewTag
|
||||||
*/
|
*/
|
||||||
get selectedFile(): API.FileInfoType;
|
get selectedFile(): API.FileInfoType;
|
||||||
|
/**
|
||||||
|
* Get all selected files
|
||||||
|
*
|
||||||
|
* @readonly
|
||||||
|
* @type {API.FileInfoType[]}
|
||||||
|
* @memberof FileViewTag
|
||||||
|
*/
|
||||||
|
get selectedFiles(): API.FileInfoType[];
|
||||||
/**
|
/**
|
||||||
* Setter:
|
* Setter:
|
||||||
*
|
*
|
||||||
@ -3266,7 +3287,7 @@ declare namespace OS {
|
|||||||
*
|
*
|
||||||
* @memberof FileViewTag
|
* @memberof FileViewTag
|
||||||
*/
|
*/
|
||||||
set ondragndrop(v: TagEventCallback<DnDEventDataType<TreeViewTag | ListViewItemTag>>);
|
set ondragndrop(v: TagEventCallback<DnDEventDataType<TreeViewTag | ListViewItemTag | GridCellPrototype>>);
|
||||||
/**
|
/**
|
||||||
* Sort file by its type
|
* Sort file by its type
|
||||||
*
|
*
|
||||||
@ -3593,7 +3614,7 @@ declare namespace OS {
|
|||||||
* @type {T}
|
* @type {T}
|
||||||
* @memberof DnDEventDataType
|
* @memberof DnDEventDataType
|
||||||
*/
|
*/
|
||||||
from: T;
|
from: T[];
|
||||||
/**
|
/**
|
||||||
* Reference to the target DOM element
|
* Reference to the target DOM element
|
||||||
*
|
*
|
||||||
@ -4148,7 +4169,7 @@ declare namespace OS {
|
|||||||
* drag and drop on the list
|
* drag and drop on the list
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {{ from: ListViewItemTag; to: ListViewItemTag }}
|
* @type {{ from: ListViewItemTag[]; to: ListViewItemTag }}
|
||||||
* @memberof ListViewTag
|
* @memberof ListViewTag
|
||||||
*/
|
*/
|
||||||
private _dnd;
|
private _dnd;
|
||||||
@ -5056,6 +5077,15 @@ declare namespace OS {
|
|||||||
*/
|
*/
|
||||||
set text(v: string | FormattedString);
|
set text(v: string | FormattedString);
|
||||||
get text(): string | FormattedString;
|
get text(): string | FormattedString;
|
||||||
|
/**
|
||||||
|
* Setter: Turn on/off text selection
|
||||||
|
*
|
||||||
|
* Getter: Check whether the label is selectable
|
||||||
|
*
|
||||||
|
* @memberof LabelTag
|
||||||
|
*/
|
||||||
|
set selectable(v: boolean);
|
||||||
|
get swon(): boolean;
|
||||||
/**
|
/**
|
||||||
* Lqbel layout definition
|
* Lqbel layout definition
|
||||||
*
|
*
|
||||||
@ -5275,6 +5305,10 @@ interface Array<T> {
|
|||||||
declare namespace OS {
|
declare namespace OS {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
namespace tag {
|
namespace tag {
|
||||||
|
/**
|
||||||
|
* Row item event data type
|
||||||
|
*/
|
||||||
|
type GridRowEventData = TagEventDataType<GridRowTag>;
|
||||||
/**
|
/**
|
||||||
* A grid Row is a simple element that
|
* A grid Row is a simple element that
|
||||||
* contains a group of grid cell
|
* contains a group of grid cell
|
||||||
@ -5291,11 +5325,34 @@ declare namespace OS {
|
|||||||
* @memberof GridRowTag
|
* @memberof GridRowTag
|
||||||
*/
|
*/
|
||||||
data: GenericObject<any>[];
|
data: GenericObject<any>[];
|
||||||
|
/**
|
||||||
|
* placeholder for the row select event callback
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {TagEventCallback<GridRowEventData>}
|
||||||
|
* @memberof ListViewItemTag
|
||||||
|
*/
|
||||||
|
private _onselect;
|
||||||
/**
|
/**
|
||||||
*Creates an instance of GridRowTag.
|
*Creates an instance of GridRowTag.
|
||||||
* @memberof GridRowTag
|
* @memberof GridRowTag
|
||||||
*/
|
*/
|
||||||
constructor();
|
constructor();
|
||||||
|
/**
|
||||||
|
* Set item select event handle
|
||||||
|
*
|
||||||
|
* @memberof ListViewItemTag
|
||||||
|
*/
|
||||||
|
set onrowselect(v: TagEventCallback<GridRowEventData>);
|
||||||
|
/**
|
||||||
|
* Setter: select/unselect the current item
|
||||||
|
*
|
||||||
|
* Getter: Check whether the current item is selected
|
||||||
|
*
|
||||||
|
* @memberof ListViewItemTag
|
||||||
|
*/
|
||||||
|
set selected(v: boolean);
|
||||||
|
get selected(): boolean;
|
||||||
/**
|
/**
|
||||||
* Mount the tag, do nothing
|
* Mount the tag, do nothing
|
||||||
*
|
*
|
||||||
@ -5576,11 +5633,64 @@ declare namespace OS {
|
|||||||
* @memberof GridViewTag
|
* @memberof GridViewTag
|
||||||
*/
|
*/
|
||||||
private _oncelldbclick;
|
private _oncelldbclick;
|
||||||
|
/**
|
||||||
|
* Event data passing between mouse event when performing
|
||||||
|
* drag and drop on the list
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {{ from: GridRowTag[]; to: GridRowTag }}
|
||||||
|
* @memberof GridViewTag
|
||||||
|
*/
|
||||||
|
private _dnd;
|
||||||
|
/**
|
||||||
|
* placeholder of list drag and drop event handle
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {TagEventCallback<DnDEventDataType<GridRowTag>>}
|
||||||
|
* @memberof GridViewTag
|
||||||
|
*/
|
||||||
|
private _ondragndrop;
|
||||||
/**
|
/**
|
||||||
* Creates an instance of GridViewTag.
|
* Creates an instance of GridViewTag.
|
||||||
* @memberof GridViewTag
|
* @memberof GridViewTag
|
||||||
*/
|
*/
|
||||||
constructor();
|
constructor();
|
||||||
|
/**
|
||||||
|
* Set drag and drop event handle
|
||||||
|
*
|
||||||
|
* @memberof GridViewTag
|
||||||
|
*/
|
||||||
|
set ondragndrop(v: TagEventCallback<DnDEventDataType<GridRowTag>>);
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
get dragndrop(): boolean;
|
||||||
|
/**
|
||||||
|
* placeholder of drag and drop mouse down event handle
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @memberof GridViewTag
|
||||||
|
*/
|
||||||
|
private _onmousedown;
|
||||||
|
/**
|
||||||
|
* placeholder of drag and drop mouse up event handle
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @memberof GridViewTag
|
||||||
|
*/
|
||||||
|
private _onmouseup;
|
||||||
|
/**
|
||||||
|
* placeholder of drag and drop mouse move event handle
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @memberof GridViewTag
|
||||||
|
*/
|
||||||
|
private _onmousemove;
|
||||||
/**
|
/**
|
||||||
* Init the grid view before mounting.
|
* Init the grid view before mounting.
|
||||||
* Reset all the placeholders to default values
|
* Reset all the placeholders to default values
|
||||||
@ -5694,6 +5804,16 @@ declare namespace OS {
|
|||||||
*/
|
*/
|
||||||
set resizable(v: boolean);
|
set resizable(v: boolean);
|
||||||
get resizable(): boolean;
|
get resizable(): boolean;
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
/**
|
/**
|
||||||
* Delete a grid rows
|
* Delete a grid rows
|
||||||
*
|
*
|
||||||
@ -5732,11 +5852,18 @@ declare namespace OS {
|
|||||||
* This function triggers the row select event, a cell select
|
* This function triggers the row select event, a cell select
|
||||||
* event will also trigger this event
|
* event will also trigger this event
|
||||||
*
|
*
|
||||||
* @param {TagEventType<CellEventData>} e
|
* @param {TagEventType<GridRowEventData>} e
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
* @memberof GridViewTag
|
* @memberof GridViewTag
|
||||||
*/
|
*/
|
||||||
private rowselect;
|
private rowselect;
|
||||||
|
/**
|
||||||
|
* Unselect all the selected rows in the grid
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
* @memberof GridViewTag
|
||||||
|
*/
|
||||||
|
unselect(): void;
|
||||||
/**
|
/**
|
||||||
* Check whether the grid has header
|
* Check whether the grid has header
|
||||||
*
|
*
|
||||||
@ -6584,7 +6711,7 @@ declare namespace OS {
|
|||||||
* Private data object passing between dragndrop mouse event
|
* Private data object passing between dragndrop mouse event
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {{ from: TreeViewTag; to: TreeViewTag }}
|
* @type {{ from: TreeViewTag[]; to: TreeViewTag }}
|
||||||
* @memberof TreeViewTag
|
* @memberof TreeViewTag
|
||||||
*/
|
*/
|
||||||
private _dnd;
|
private _dnd;
|
||||||
@ -6631,7 +6758,7 @@ declare namespace OS {
|
|||||||
* current tree. This function should return a promise on
|
* current tree. This function should return a promise on
|
||||||
* a list of [[TreeViewDataType]]
|
* a list of [[TreeViewDataType]]
|
||||||
*
|
*
|
||||||
* @memberof TreeViewItemPrototype
|
* @memberof TreeViewTag
|
||||||
*/
|
*/
|
||||||
fetch: (d: TreeViewItemPrototype) => Promise<TreeViewDataType[]>;
|
fetch: (d: TreeViewItemPrototype) => Promise<TreeViewDataType[]>;
|
||||||
/**
|
/**
|
||||||
|
@ -264,7 +264,6 @@ namespace OS {
|
|||||||
*/
|
*/
|
||||||
main(): void {
|
main(): void {
|
||||||
const win = this.scheme as tag.WindowTag;
|
const win = this.scheme as tag.WindowTag;
|
||||||
$(win).attr("tabindex", 0);
|
|
||||||
$(win).on('keydown', (e) => {
|
$(win).on('keydown', (e) => {
|
||||||
switch (e.which) {
|
switch (e.which) {
|
||||||
case 27:
|
case 27:
|
||||||
@ -672,7 +671,7 @@ namespace OS {
|
|||||||
}
|
}
|
||||||
for (let k in this.data) {
|
for (let k in this.data) {
|
||||||
const v = this.data[k];
|
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;
|
const grid = this.find("grid") as tag.GridViewTag;
|
||||||
grid.header = [
|
grid.header = [
|
||||||
@ -1052,7 +1051,7 @@ namespace OS {
|
|||||||
__("Resource not found: {0}", path)
|
__("Resource not found: {0}", path)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (fileview.path = path);
|
fileview.path = path;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!this.data || !this.data.root) {
|
if (!this.data || !this.data.root) {
|
||||||
@ -1088,11 +1087,14 @@ namespace OS {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
(this.find("btnOk") as tag.ButtonTag).onbtclick = (_e) => {
|
(this.find("btnOk") as tag.ButtonTag).onbtclick = (_e) => {
|
||||||
const f = fileview.selectedFile;
|
let f = fileview.selectedFile;
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
const sel = location.selectedItem;
|
||||||
|
if(!sel)
|
||||||
return this.notify(
|
return this.notify(
|
||||||
__("Please select a file/fofler")
|
__("Please select a file/fofler")
|
||||||
);
|
);
|
||||||
|
f = sel.data as API.FileInfoType;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
this.data &&
|
this.data &&
|
||||||
|
@ -28,13 +28,13 @@ namespace OS {
|
|||||||
private _onfileopen: TagEventCallback<API.FileInfoType>;
|
private _onfileopen: TagEventCallback<API.FileInfoType>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the currently selected file meta-data
|
* Reference to the all selected files meta-datas
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {API.FileInfoType}
|
* @type {API.FileInfoType[]}
|
||||||
* @memberof FileViewTag
|
* @memberof FileViewTag
|
||||||
*/
|
*/
|
||||||
private _selectedFile: API.FileInfoType;
|
private _selectedFiles: API.FileInfoType[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data placeholder of the current working directory
|
* Data placeholder of the current working directory
|
||||||
@ -58,10 +58,10 @@ namespace OS {
|
|||||||
* Header definition of the widget grid view
|
* Header definition of the widget grid view
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {(GenericObject<string | number>[])}
|
* @type {(GenericObject<any>[])}
|
||||||
* @memberof FileViewTag
|
* @memberof FileViewTag
|
||||||
*/
|
*/
|
||||||
private _header: GenericObject<string | number>[];
|
private _header: GenericObject<any>[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* placeholder for the user-specified meta-data fetch function
|
* placeholder for the user-specified meta-data fetch function
|
||||||
@ -92,10 +92,37 @@ namespace OS {
|
|||||||
this.chdir = true;
|
this.chdir = true;
|
||||||
this.view = "list";
|
this.view = "list";
|
||||||
this._onfileopen = this._onfileselect = (e) => { };
|
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 = [
|
this._header = [
|
||||||
{ text: "__(File name)" },
|
{
|
||||||
|
text: "__(File name)",
|
||||||
|
sort: fn
|
||||||
|
},
|
||||||
{ text: "__(Type)" },
|
{ text: "__(Type)" },
|
||||||
{ text: "__(Size)" },
|
{
|
||||||
|
text: "__(Size)",
|
||||||
|
sort: fn
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,6 +254,28 @@ namespace OS {
|
|||||||
return this.hasattr("showhidden");
|
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
|
* Get the current selected file
|
||||||
*
|
*
|
||||||
@ -235,7 +284,21 @@ namespace OS {
|
|||||||
* @memberof FileViewTag
|
* @memberof FileViewTag
|
||||||
*/
|
*/
|
||||||
get selectedFile(): API.FileInfoType {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -305,11 +368,21 @@ namespace OS {
|
|||||||
*/
|
*/
|
||||||
set ondragndrop(
|
set ondragndrop(
|
||||||
v: TagEventCallback<
|
v: TagEventCallback<
|
||||||
DnDEventDataType<TreeViewTag | ListViewItemTag>
|
DnDEventDataType<TreeViewTag | ListViewItemTag | GridCellPrototype>
|
||||||
>
|
>
|
||||||
) {
|
) {
|
||||||
(this.refs.treeview as TreeViewTag).ondragndrop = v;
|
(this.refs.treeview as TreeViewTag).ondragndrop = v;
|
||||||
(this.refs.listview as ListViewTag).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.listview).hide();
|
||||||
$(this.refs.gridview).hide();
|
$(this.refs.gridview).hide();
|
||||||
$(this.refs.treecontainer).hide();
|
$(this.refs.treecontainer).hide();
|
||||||
this._selectedFile = undefined;
|
this._selectedFiles = [];
|
||||||
switch (this.view) {
|
switch (this.view) {
|
||||||
case "icon":
|
case "icon":
|
||||||
$(this.refs.listview).show();
|
$(this.refs.listview).show();
|
||||||
@ -552,7 +625,6 @@ namespace OS {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const evt = { id: this.aid, data: e };
|
const evt = { id: this.aid, data: e };
|
||||||
this._selectedFile = e;
|
|
||||||
this._onfileselect(evt);
|
this._onfileselect(evt);
|
||||||
this.observable.trigger("fileselect", evt);
|
this.observable.trigger("fileselect", evt);
|
||||||
}
|
}
|
||||||
@ -612,18 +684,22 @@ namespace OS {
|
|||||||
grid.header = this._header;
|
grid.header = this._header;
|
||||||
tree.dragndrop = true;
|
tree.dragndrop = true;
|
||||||
list.dragndrop = true;
|
list.dragndrop = true;
|
||||||
|
grid.dragndrop = true;
|
||||||
// even handles
|
// even handles
|
||||||
list.onlistselect = (e) => {
|
list.onlistselect = (e) => {
|
||||||
this.fileselect(e.data.item.data as API.FileInfoType);
|
this.fileselect(e.data.item.data as API.FileInfoType);
|
||||||
|
this._selectedFiles = e.data.items.map( x => x.data as API.FileInfoType);
|
||||||
};
|
};
|
||||||
grid.onrowselect = (e) => {
|
grid.onrowselect = (e) => {
|
||||||
this.fileselect(
|
this.fileselect(
|
||||||
($(e.data.item).children()[0] as GridCellPrototype)
|
($(e.data.item).children()[0] as GridCellPrototype)
|
||||||
.data as API.FileInfoType
|
.data as API.FileInfoType
|
||||||
);
|
);
|
||||||
|
this._selectedFiles = e.data.items.map( x => ($(x).children()[0] as GridCellPrototype).data as API.FileInfoType);
|
||||||
};
|
};
|
||||||
tree.ontreeselect = (e) => {
|
tree.ontreeselect = (e) => {
|
||||||
this.fileselect(e.data.item.data as API.FileInfoType);
|
this.fileselect(e.data.item.data as API.FileInfoType);
|
||||||
|
this._selectedFiles = [e.data.item.data as API.FileInfoType];
|
||||||
};
|
};
|
||||||
// dblclick
|
// dblclick
|
||||||
list.onlistdbclick = (e) => {
|
list.onlistdbclick = (e) => {
|
||||||
|
@ -19,6 +19,10 @@ interface Array<T> {
|
|||||||
namespace OS {
|
namespace OS {
|
||||||
export namespace GUI {
|
export namespace GUI {
|
||||||
export namespace tag {
|
export namespace tag {
|
||||||
|
/**
|
||||||
|
* Row item event data type
|
||||||
|
*/
|
||||||
|
export type GridRowEventData = TagEventDataType<GridRowTag>;
|
||||||
/**
|
/**
|
||||||
* A grid Row is a simple element that
|
* A grid Row is a simple element that
|
||||||
* contains a group of grid cell
|
* contains a group of grid cell
|
||||||
@ -36,6 +40,15 @@ namespace OS {
|
|||||||
*/
|
*/
|
||||||
data: GenericObject<any>[];
|
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.
|
*Creates an instance of GridRowTag.
|
||||||
* @memberof GridRowTag
|
* @memberof GridRowTag
|
||||||
@ -44,6 +57,36 @@ namespace OS {
|
|||||||
super();
|
super();
|
||||||
|
|
||||||
this.refs.yield = this;
|
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>;
|
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.
|
* Creates an instance of GridViewTag.
|
||||||
* @memberof GridViewTag
|
* @memberof GridViewTag
|
||||||
@ -428,6 +492,68 @@ namespace OS {
|
|||||||
super();
|
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.
|
* Init the grid view before mounting.
|
||||||
* Reset all the placeholders to default values
|
* Reset all the placeholders to default values
|
||||||
@ -444,9 +570,13 @@ namespace OS {
|
|||||||
this._selectedRow = undefined;
|
this._selectedRow = undefined;
|
||||||
this._rows = [];
|
this._rows = [];
|
||||||
this.resizable = false;
|
this.resizable = false;
|
||||||
|
this.dragndrop = false;
|
||||||
this._oncellselect = this._onrowselect = this._oncelldbclick = (
|
this._oncellselect = this._onrowselect = this._oncelldbclick = (
|
||||||
e: TagEventType<CellEventData>
|
e: TagEventType<CellEventData>
|
||||||
): void => {};
|
): void => {};
|
||||||
|
this._ondragndrop = (
|
||||||
|
e: TagEventType<DnDEventDataType<GridRowTag>>
|
||||||
|
) => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -507,7 +637,14 @@ namespace OS {
|
|||||||
* @memberof GridViewTag
|
* @memberof GridViewTag
|
||||||
*/
|
*/
|
||||||
set cellitem(v: string) {
|
set cellitem(v: string) {
|
||||||
|
const currci = this.cellitem;
|
||||||
$(this).attr("cellitem", v);
|
$(this).attr("cellitem", v);
|
||||||
|
if(v != currci)
|
||||||
|
{
|
||||||
|
// force render data
|
||||||
|
$(this.refs.grid).empty();
|
||||||
|
this.rows = this.rows;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
get cellitem(): string {
|
get cellitem(): string {
|
||||||
return $(this).attr("cellitem");
|
return $(this).attr("cellitem");
|
||||||
@ -539,6 +676,12 @@ namespace OS {
|
|||||||
element.uify(this.observable);
|
element.uify(this.observable);
|
||||||
element.data = item;
|
element.data = item;
|
||||||
item.domel = element;
|
item.domel = element;
|
||||||
|
element.oncellselect = (e) => {
|
||||||
|
if(element.data.sort)
|
||||||
|
{
|
||||||
|
this.sort(element.data, element.data.sort);
|
||||||
|
}
|
||||||
|
};
|
||||||
i++;
|
i++;
|
||||||
if (this.resizable) {
|
if (this.resizable) {
|
||||||
if (i != v.length) {
|
if (i != v.length) {
|
||||||
@ -604,9 +747,48 @@ namespace OS {
|
|||||||
* @memberof GridViewTag
|
* @memberof GridViewTag
|
||||||
*/
|
*/
|
||||||
set rows(rows: GenericObject<any>[][]) {
|
set rows(rows: GenericObject<any>[][]) {
|
||||||
$(this.refs.grid).empty();
|
|
||||||
this._rows = rows;
|
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>[][] {
|
get rows(): GenericObject<any>[][] {
|
||||||
return this._rows;
|
return this._rows;
|
||||||
@ -639,7 +821,24 @@ namespace OS {
|
|||||||
get resizable(): boolean {
|
get resizable(): boolean {
|
||||||
return this.hasattr("resizable");
|
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
|
* Delete a grid rows
|
||||||
*
|
*
|
||||||
@ -713,6 +912,10 @@ namespace OS {
|
|||||||
element.oncelldbclick = (e) => this.cellselect(e, true);
|
element.oncelldbclick = (e) => this.cellselect(e, true);
|
||||||
element.data = cell;
|
element.data = cell;
|
||||||
}
|
}
|
||||||
|
el.onrowselect = (e) => this.rowselect({
|
||||||
|
id: el.aid,
|
||||||
|
data: {item: el}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -751,7 +954,10 @@ namespace OS {
|
|||||||
} else {
|
} else {
|
||||||
this.observable.trigger("cellselect", e);
|
this.observable.trigger("cellselect", e);
|
||||||
this._oncellselect(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
|
* This function triggers the row select event, a cell select
|
||||||
* event will also trigger this event
|
* event will also trigger this event
|
||||||
*
|
*
|
||||||
* @param {TagEventType<CellEventData>} e
|
* @param {TagEventType<GridRowEventData>} e
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
* @memberof GridViewTag
|
* @memberof GridViewTag
|
||||||
*/
|
*/
|
||||||
private rowselect(e: TagEventType<CellEventData>): void {
|
private rowselect(e: TagEventType<GridRowEventData>): void {
|
||||||
if (!e.data.item) {
|
if (!e.data.item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -774,39 +980,58 @@ namespace OS {
|
|||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const row = ($(
|
const row = e.data.item as GridRowTag;
|
||||||
e.data.item
|
|
||||||
).parent()[0] as any) as GridRowTag;
|
|
||||||
if (this.multiselect) {
|
if (this.multiselect) {
|
||||||
if (this.selectedRows.includes(row)) {
|
if (this.selectedRows.includes(row)) {
|
||||||
this.selectedRows.splice(
|
this.selectedRows.splice(
|
||||||
this.selectedRows.indexOf(row),
|
this.selectedRows.indexOf(row),
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
$(row).removeClass();
|
row.selected = false;
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
this.selectedRows.push(row);
|
this.selectedRows.push(row);
|
||||||
$(row)
|
|
||||||
.removeClass()
|
|
||||||
.addClass("afx-grid-row-selected");
|
|
||||||
}
|
}
|
||||||
evt.data.items = this.selectedRows;
|
evt.data.items = this.selectedRows;
|
||||||
} else {
|
} else {
|
||||||
|
if(this.selectedRows.length > 0)
|
||||||
|
{
|
||||||
|
for(const item of this.selectedRows)
|
||||||
|
{
|
||||||
|
if(item != row)
|
||||||
|
{
|
||||||
|
item.selected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.selectedRow === row) {
|
if (this.selectedRow === row) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$(this.selectedRow).removeClass();
|
if(this.selectedRow)
|
||||||
this._selectedRows = [row];
|
this.selectedRow.selected = false;
|
||||||
evt.data.item = row;
|
|
||||||
evt.data.items = [row];
|
evt.data.items = [row];
|
||||||
$(row).removeClass().addClass("afx-grid-row-selected");
|
|
||||||
this._selectedRows = [row];
|
this._selectedRows = [row];
|
||||||
}
|
}
|
||||||
|
evt.data.item = row;
|
||||||
this._selectedRow = row;
|
this._selectedRow = row;
|
||||||
this._onrowselect(evt);
|
this._onrowselect(evt);
|
||||||
return this.observable.trigger("rowselect", 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
|
* Check whether the grid has header
|
||||||
*
|
*
|
||||||
@ -904,7 +1129,6 @@ namespace OS {
|
|||||||
*/
|
*/
|
||||||
protected mount(): void {
|
protected mount(): void {
|
||||||
$(this).css("overflow", "hidden");
|
$(this).css("overflow", "hidden");
|
||||||
|
|
||||||
$(this.refs.grid).css("display", "grid");
|
$(this.refs.grid).css("display", "grid");
|
||||||
$(this.refs.header).css("display", "grid");
|
$(this.refs.header).css("display", "grid");
|
||||||
this.observable.on("resize", (e) => this.calibrate());
|
this.observable.on("resize", (e) => this.calibrate());
|
||||||
@ -912,6 +1136,73 @@ namespace OS {
|
|||||||
.css("width", "100%")
|
.css("width", "100%")
|
||||||
.css("overflow-x", "hidden")
|
.css("overflow-x", "hidden")
|
||||||
.css("overflow-y", "auto");
|
.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();
|
return this.calibrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ namespace OS {
|
|||||||
this.icon = undefined;
|
this.icon = undefined;
|
||||||
this.iconclass = undefined;
|
this.iconclass = undefined;
|
||||||
this.text = undefined;
|
this.text = undefined;
|
||||||
|
this.selectable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,6 +122,33 @@ namespace OS {
|
|||||||
return this._text;
|
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
|
* Lqbel layout definition
|
||||||
*
|
*
|
||||||
|
@ -444,10 +444,10 @@ namespace OS {
|
|||||||
* drag and drop on the list
|
* drag and drop on the list
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {{ from: ListViewItemTag; to: ListViewItemTag }}
|
* @type {{ from: ListViewItemTag[]; to: ListViewItemTag }}
|
||||||
* @memberof ListViewTag
|
* @memberof ListViewTag
|
||||||
*/
|
*/
|
||||||
private _dnd: { from: ListViewItemTag; to: ListViewItemTag };
|
private _dnd: { from: ListViewItemTag[]; to: ListViewItemTag };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Creates an instance of ListViewTag.
|
*Creates an instance of ListViewTag.
|
||||||
@ -990,6 +990,16 @@ namespace OS {
|
|||||||
this.selectedItems.push(e.data);
|
this.selectedItems.push(e.data);
|
||||||
edata.items = this.selectedItems;
|
edata.items = this.selectedItems;
|
||||||
} else {
|
} else {
|
||||||
|
if(this.selectedItems.length > 0)
|
||||||
|
{
|
||||||
|
for(const item of this.selectedItems)
|
||||||
|
{
|
||||||
|
if(item != e.data)
|
||||||
|
{
|
||||||
|
item.selected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.selectedItem === e.data) {
|
if (this.selectedItem === e.data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1044,14 +1054,22 @@ namespace OS {
|
|||||||
to: undefined,
|
to: undefined,
|
||||||
};
|
};
|
||||||
this._onmousedown = (e) => {
|
this._onmousedown = (e) => {
|
||||||
|
if(this.multiselect || this.selectedItems == undefined || this.selectedItems.length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
let el: any = $(e.target).closest(
|
let el: any = $(e.target).closest(
|
||||||
"li[dataref='afx-list-item']"
|
"li[dataref='afx-list-item']"
|
||||||
);
|
);
|
||||||
if (el.length === 0) {
|
if (el.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
el = el.parent()[0] as ListViewItemTag;
|
el = el.parent()[0];
|
||||||
this._dnd.from = el;
|
if(!this.selectedItems.includes(el))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._dnd.from = this.selectedItems;
|
||||||
this._dnd.to = undefined;
|
this._dnd.to = undefined;
|
||||||
$(window).on("mouseup", this._onmouseup);
|
$(window).on("mouseup", this._onmouseup);
|
||||||
$(window).on("mousemove", this._onmousemove);
|
$(window).on("mousemove", this._onmousemove);
|
||||||
@ -1068,7 +1086,7 @@ namespace OS {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
el = el.parent()[0];
|
el = el.parent()[0];
|
||||||
if (el === this._dnd.from) {
|
if (this._dnd.from.includes(el)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._dnd.to = el;
|
this._dnd.to = el;
|
||||||
@ -1086,7 +1104,18 @@ namespace OS {
|
|||||||
if (!this._dnd.from) {
|
if (!this._dnd.from) {
|
||||||
return;
|
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 $label = $("#systooltip");
|
||||||
const top = e.clientY + 5;
|
const top = e.clientY + 5;
|
||||||
const left = e.clientX + 5;
|
const left = e.clientX + 5;
|
||||||
|
@ -586,10 +586,10 @@ namespace OS {
|
|||||||
* Private data object passing between dragndrop mouse event
|
* Private data object passing between dragndrop mouse event
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {{ from: TreeViewTag; to: TreeViewTag }}
|
* @type {{ from: TreeViewTag[]; to: TreeViewTag }}
|
||||||
* @memberof TreeViewTag
|
* @memberof TreeViewTag
|
||||||
*/
|
*/
|
||||||
private _dnd: { from: TreeViewTag; to: TreeViewTag };
|
private _dnd: { from: TreeViewTag[]; to: TreeViewTag };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to parent tree of the current tree.
|
* Reference to parent tree of the current tree.
|
||||||
@ -638,7 +638,7 @@ namespace OS {
|
|||||||
* current tree. This function should return a promise on
|
* current tree. This function should return a promise on
|
||||||
* a list of [[TreeViewDataType]]
|
* a list of [[TreeViewDataType]]
|
||||||
*
|
*
|
||||||
* @memberof TreeViewItemPrototype
|
* @memberof TreeViewTag
|
||||||
*/
|
*/
|
||||||
fetch: (
|
fetch: (
|
||||||
d: TreeViewItemPrototype
|
d: TreeViewItemPrototype
|
||||||
@ -920,7 +920,7 @@ namespace OS {
|
|||||||
*/
|
*/
|
||||||
protected mount(): void {
|
protected mount(): void {
|
||||||
this._dnd = {
|
this._dnd = {
|
||||||
from: undefined,
|
from: [],
|
||||||
to: undefined,
|
to: undefined,
|
||||||
};
|
};
|
||||||
this._treemousedown = (e) => {
|
this._treemousedown = (e) => {
|
||||||
@ -932,7 +932,7 @@ namespace OS {
|
|||||||
if (el === this) {
|
if (el === this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._dnd.from = el;
|
this._dnd.from = [el];
|
||||||
this._dnd.to = undefined;
|
this._dnd.to = undefined;
|
||||||
$(window).on("mouseup", this._treemouseup);
|
$(window).on("mouseup", this._treemouseup);
|
||||||
return $(window).on("mousemove", this._treemousemove);
|
return $(window).on("mousemove", this._treemousemove);
|
||||||
@ -951,8 +951,8 @@ namespace OS {
|
|||||||
el = el.parent;
|
el = el.parent;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
el === this._dnd.from ||
|
el === this._dnd.from[0] ||
|
||||||
el === this._dnd.from.parent
|
el === this._dnd.from[0].parent
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -962,7 +962,7 @@ namespace OS {
|
|||||||
data: this._dnd,
|
data: this._dnd,
|
||||||
});
|
});
|
||||||
this._dnd = {
|
this._dnd = {
|
||||||
from: undefined,
|
from: [],
|
||||||
to: undefined,
|
to: undefined,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -974,7 +974,7 @@ namespace OS {
|
|||||||
if (!this._dnd.from) {
|
if (!this._dnd.from) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = this._dnd.from.data;
|
const data = this._dnd.from[0].data;
|
||||||
const $label = $("#systooltip");
|
const $label = $("#systooltip");
|
||||||
const top = e.clientY + 5;
|
const top = e.clientY + 5;
|
||||||
const left = e.clientX + 5;
|
const left = e.clientX + 5;
|
||||||
|
@ -306,6 +306,7 @@ namespace OS {
|
|||||||
.removeClass("unactive");
|
.removeClass("unactive");
|
||||||
this._shown = true;
|
this._shown = true;
|
||||||
$(this.refs.win_overlay).hide();
|
$(this.refs.win_overlay).hide();
|
||||||
|
$(this).trigger("focus");
|
||||||
});
|
});
|
||||||
|
|
||||||
this.observable.on("blur", () => {
|
this.observable.on("blur", () => {
|
||||||
@ -336,6 +337,7 @@ namespace OS {
|
|||||||
w: this.width,
|
w: this.width,
|
||||||
h: this.height,
|
h: this.height,
|
||||||
});
|
});
|
||||||
|
$(this).attr("tabindex", 0).css("outline", "none");
|
||||||
return this.observable.trigger("rendered", {
|
return this.observable.trigger("rendered", {
|
||||||
id: this.aid,
|
id: this.aid,
|
||||||
});
|
});
|
||||||
|
@ -233,7 +233,7 @@ namespace OS {
|
|||||||
* @type {T}
|
* @type {T}
|
||||||
* @memberof DnDEventDataType
|
* @memberof DnDEventDataType
|
||||||
*/
|
*/
|
||||||
from: T;
|
from: T[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the target DOM element
|
* Reference to the target DOM element
|
||||||
|
@ -21,7 +21,7 @@ namespace OS {
|
|||||||
|
|
||||||
interface FilesClipboardType {
|
interface FilesClipboardType {
|
||||||
cut: boolean;
|
cut: boolean;
|
||||||
file: API.VFS.BaseFileHandle;
|
files: API.VFS.BaseFileHandle[];
|
||||||
}
|
}
|
||||||
interface FilesViewType {
|
interface FilesViewType {
|
||||||
icon: boolean;
|
icon: boolean;
|
||||||
@ -228,43 +228,54 @@ namespace OS {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.vfs_event_flag = true;
|
this.vfs_event_flag = true;
|
||||||
this.view.ondragndrop = (e) => {
|
this.view.ondragndrop = async (e) => {
|
||||||
if (!e) {
|
if (!e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const src = e.data.from.data;
|
const src = e.data.from;
|
||||||
const des = e.data.to.data;
|
const des = e.data.to.data;
|
||||||
if (des.type === "file") {
|
if (des.type === "file") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const file = src.path.asFileHandle();
|
// ask to confirm
|
||||||
|
const r = await this.ask({
|
||||||
|
title: __("Move files"),
|
||||||
|
text: __("Move selected file to {0}?", des.text)
|
||||||
|
});
|
||||||
|
if(!r)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
// disable the vfs event on
|
// disable the vfs event on
|
||||||
// we update it manually
|
// we update it manually
|
||||||
this.vfs_event_flag = false;
|
this.vfs_event_flag = false;
|
||||||
return file
|
const promises = [];
|
||||||
.move(`${des.path}/${file.basename}`)
|
for(const item of src)
|
||||||
.then(() => {
|
{
|
||||||
if (this.view.view === "icon") {
|
let file = item.data.path.asFileHandle();
|
||||||
this.view.path = this.view.path;
|
promises.push(
|
||||||
} else {
|
file.move(`${des.path}/${file.basename}`));
|
||||||
this.view.update(file.parent().path);
|
|
||||||
this.view.update(des.path);
|
|
||||||
}
|
}
|
||||||
//reenable the vfs event
|
try{
|
||||||
return (this.vfs_event_flag = true);
|
await Promise.all(promises);
|
||||||
})
|
if (this.view.view === "tree") {
|
||||||
.catch((e: Error) => {
|
this.view.update(src[0].data.path.asFileHandle().parent().path);
|
||||||
// reenable the vfs event
|
this.view.update(des.path);
|
||||||
this.vfs_event_flag = true;
|
} else {
|
||||||
return this.error(
|
this.view.path = this.view.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(error)
|
||||||
|
{
|
||||||
|
this.error(
|
||||||
__(
|
__(
|
||||||
"Unable to move: {0} -> {1}",
|
"Unable to move files to: {0}",
|
||||||
src.path,
|
|
||||||
des.path
|
des.path
|
||||||
),
|
),
|
||||||
e
|
error
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
this.vfs_event_flag = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// application setting
|
// application setting
|
||||||
@ -355,6 +366,23 @@ namespace OS {
|
|||||||
this.view.view = "list";
|
this.view.view = "list";
|
||||||
this.viewType.list = true;
|
this.viewType.list = true;
|
||||||
};
|
};
|
||||||
|
// enable or disable multi-select by CTRL key
|
||||||
|
$(this.scheme).on("keydown", (evt)=>{
|
||||||
|
if(evt.ctrlKey && evt.which == 17)
|
||||||
|
{
|
||||||
|
this.view.multiselect = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.view.multiselect = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$(this.scheme).on("keyup", (evt)=>{
|
||||||
|
if(!evt.ctrlKey)
|
||||||
|
{
|
||||||
|
this.view.multiselect = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
this.view.path = this.currdir.path;
|
this.view.path = this.currdir.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,20 +613,22 @@ namespace OS {
|
|||||||
title: "__(Delete)",
|
title: "__(Delete)",
|
||||||
iconclass: "fa fa-question-circle",
|
iconclass: "fa fa-question-circle",
|
||||||
text: __(
|
text: __(
|
||||||
"Do you really want to delete: {0}?",
|
"Do you really want to delete selected files?"
|
||||||
file.filename
|
|
||||||
),
|
),
|
||||||
}).then(async (d) => {
|
}).then(async (d) => {
|
||||||
if (!d) {
|
if (!d) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const promises = [];
|
||||||
|
for(const f of this.view.selectedFiles)
|
||||||
|
{
|
||||||
|
promises.push(f.path.asFileHandle().remove());
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return file.path
|
await Promise.all(promises);
|
||||||
.asFileHandle()
|
|
||||||
.remove();
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return this.error(__("Fail to delete: {0}", file.path), e);
|
return this.error(__("Fail to delete selected files"), e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@ -609,9 +639,9 @@ namespace OS {
|
|||||||
}
|
}
|
||||||
this.clipboard = {
|
this.clipboard = {
|
||||||
cut: true,
|
cut: true,
|
||||||
file: file.path.asFileHandle(),
|
files: this.view.selectedFiles.map(x => x.path.asFileHandle()),
|
||||||
};
|
};
|
||||||
return this.notify(__("File {0} cut", file.filename));
|
return this.notify(__("{0} files cut", this.clipboard.files.length));
|
||||||
|
|
||||||
case `${this.name}-copy`:
|
case `${this.name}-copy`:
|
||||||
if (!file) {
|
if (!file) {
|
||||||
@ -619,10 +649,10 @@ namespace OS {
|
|||||||
}
|
}
|
||||||
this.clipboard = {
|
this.clipboard = {
|
||||||
cut: false,
|
cut: false,
|
||||||
file: file.path.asFileHandle(),
|
files: this.view.selectedFiles.map(x => x.path.asFileHandle()),
|
||||||
};
|
};
|
||||||
return this.notify(
|
return this.notify(
|
||||||
__("File {0} copied", file.filename)
|
__("{0} files copied", this.clipboard.files.length)
|
||||||
);
|
);
|
||||||
|
|
||||||
case `${this.name}-paste`:
|
case `${this.name}-paste`:
|
||||||
@ -630,29 +660,33 @@ namespace OS {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.clipboard.cut) {
|
if (this.clipboard.cut) {
|
||||||
this.clipboard.file
|
const promises = [];
|
||||||
.move(
|
for(const file of this.clipboard.files)
|
||||||
`${this.currdir.path}/${this.clipboard.file.basename}`
|
{
|
||||||
)
|
promises.push(file.move(
|
||||||
|
`${this.currdir.path}/${file.basename}`
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Promise.all(promises)
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
return (this.clipboard = undefined);
|
return (this.clipboard = undefined);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
return this.error(
|
return this.error(
|
||||||
__(
|
__(
|
||||||
"Fail to paste: {0}",
|
"Fail to paste to: {0}",
|
||||||
this.clipboard.file.path
|
this.currdir.path
|
||||||
),
|
),
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
API.VFS.copy([this.clipboard.file.path],this.currdir.path)
|
API.VFS.copy(this.clipboard.files.map(x => x.path),this.currdir.path)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return (this.clipboard = undefined);
|
return (this.clipboard = undefined);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
return this.error(__("Fail to paste: {0}", this.clipboard.file.path), e);
|
return this.error(__("Fail to paste to: {0}", this.currdir.path), e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"author": "Xuan Sang LE",
|
"author": "Xuan Sang LE",
|
||||||
"email": "xsang.le@gmail.com"
|
"email": "xsang.le@gmail.com"
|
||||||
},
|
},
|
||||||
"version":"0.1.4-b",
|
"version":"0.1.5-b",
|
||||||
"category":"System",
|
"category":"System",
|
||||||
"iconclass":"fa fa-hdd-o",
|
"iconclass":"fa fa-hdd-o",
|
||||||
"mimes":["dir"],
|
"mimes":["dir"],
|
||||||
|
@ -5,5 +5,4 @@ afx-label i.label-text{
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
user-select:text;
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user