472 lines
12 KiB
JavaScript
Executable File
472 lines
12 KiB
JavaScript
Executable File
var bricks = window.bricks || {};
|
|
bricks.TreeNode = class extends bricks.VBox {
|
|
constructor(tree, pnode, data){
|
|
var opts = {
|
|
width:'100%',
|
|
height:'auto',
|
|
}
|
|
super(opts);
|
|
this.tree = tree;
|
|
this.parent_node = pnode;
|
|
this.children_loaded = false;
|
|
this.user_data = data;
|
|
this.is_leaf = this.user_data.is_leaf;
|
|
this.params = bricks.extend(this.tree.params, {id:this.user_data[this.tree.opts.idField]});
|
|
if (this.tree.multitype_tree){
|
|
this.params['type'] = this.user_data[this.tree.opts.typeField];
|
|
}
|
|
var n = new bricks.HBox({
|
|
height:this.tree.row_height,
|
|
width:'100%'
|
|
})
|
|
n.dom_element.style.margin = bricks.app.charsize * 0.2;
|
|
this.add_widget(n);
|
|
n.bind('click', this.tree.node_click_handle.bind(this.tree, this));
|
|
this.node_widget = n;
|
|
schedule_once(this.create_node_content.bind(this,n), 0.01);
|
|
if (! this.user_data.is_leaf) {
|
|
this.container = new bricks.VBox({height:'auto'});
|
|
this.add_widget(this.container);
|
|
this.container.dom_element.style.marginLeft = bricks.app.charsize + 'px';
|
|
if (this.user_data.children){
|
|
this.tree.create_node_children(this, this.user_data.children);
|
|
}
|
|
this.container.hide();
|
|
}
|
|
}
|
|
getValue(){
|
|
var v = this.user_data;
|
|
if (this.container){
|
|
var children = [];
|
|
for (var i=0; i<this.container.children.length;i++){
|
|
var sv = this.container.children[i].getValue();
|
|
children.push(sv);
|
|
}
|
|
v.children = children;
|
|
}
|
|
return v;
|
|
}
|
|
get_id(){
|
|
return this.user_data[this.tree.idField];
|
|
}
|
|
selected(flg){
|
|
if (flg){
|
|
this.str_w.set_css('selected');
|
|
} else {
|
|
this.str_w.set_css('selected',true);
|
|
}
|
|
}
|
|
async toggleExpandCollapse(event){
|
|
if (event.params == 'open') {
|
|
await this.expand();
|
|
} else {
|
|
this.collapse()
|
|
}
|
|
}
|
|
async expand(){
|
|
if (this.is_leaf){
|
|
return;
|
|
}
|
|
if (this.tree.opts.dataurl && !this.is_leaf && !this.children_loaded){
|
|
await this.tree.get_children_data(this)
|
|
this.children_loaded = true;
|
|
}
|
|
this.container.show();
|
|
}
|
|
collapse(){
|
|
if (this.is_leaf){
|
|
return;
|
|
}
|
|
this.container.hide();
|
|
}
|
|
async create_node_content(widget){
|
|
var img_size = bricks.app.charsize;
|
|
if (this.is_leaf){
|
|
widget.add_widget(new bricks.BlankIcon({}));
|
|
} else {
|
|
var srcs = this.tree.opts.node_state_imgs || {};
|
|
var sources = {};
|
|
sources['open'] = objget(srcs, 'open', bricks_resource('imgs/down_arrow.png'));
|
|
sources['close'] = objget(srcs, 'close', bricks_resource('imgs/right_arrow.png'));
|
|
this.trigle = new bricks.MultipleStateIcon({
|
|
state:'close',
|
|
urls:sources,
|
|
height:img_size,
|
|
width:img_size
|
|
});
|
|
this.trigle.bind('state_changed', this.toggleExpandCollapse.bind(this));
|
|
widget.add_widget(this.trigle);
|
|
}
|
|
if (this.tree.checkField){
|
|
var v = this.user_data[this.tree.checkField];
|
|
this.check_w = new bricks.UiCheck({name:'check', value:v});
|
|
widget.add_widget(this.check_w);
|
|
this.check_w.bind('changed', this.tree.node_checked.bind(this.tree, this))
|
|
}
|
|
var dtype = this.user_data[this.tree.opts.typeField];
|
|
var icon = objget(TypeIcons, dtype);
|
|
if (!icon && this.tree.opts.default_type){
|
|
icon = objget(TypeIcons, his.tree.opts.default_type);
|
|
}
|
|
if (!icon){
|
|
icon = bricks_resource('imgs/folder.png');
|
|
}
|
|
var img = new bricks.Icon({
|
|
url:icon
|
|
});
|
|
widget.add_widget(img);
|
|
if (this.tree.node_view){
|
|
this.view_w = await bricks.widgetBuild(this.tree.node_view, widget, this.user_data);
|
|
if (this.view_w){
|
|
widget.add_widget(this.view_w);
|
|
}
|
|
} else {
|
|
var txt = this.user_data[this.tree.opts.textField];
|
|
this.str_w = new bricks.Text({text:txt});
|
|
widget.add_widget(this.str_w);
|
|
}
|
|
}
|
|
async update_content(){
|
|
if (this.tree.node_view){
|
|
this.node_widget.remove_Widget(this.view_w);
|
|
this.view_w = await bricks.widgetBuild(this.tree.node_view, widget, this.user_data);
|
|
if (this.view_w){
|
|
widget.add_widget(this.view_w);
|
|
}
|
|
} else {
|
|
this.str_w.set_text(this.user_data[this.tree.opts.textField]);
|
|
}
|
|
}
|
|
}
|
|
|
|
bricks.Tree = class extends bricks.VScrollPanel {
|
|
/*
|
|
{
|
|
row_height:
|
|
multitype_tree:false,
|
|
idField:
|
|
textField:
|
|
type_icons:
|
|
typeField:
|
|
default_type:
|
|
data:
|
|
dataurl:
|
|
node_state_imgs:{
|
|
open:url,
|
|
close:url
|
|
},
|
|
admin:{
|
|
{
|
|
addurl:
|
|
deleteurl:
|
|
updateurl:
|
|
othertools:[
|
|
]
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
constructor(options){
|
|
super(options);
|
|
this.row_height = this.opts.row_height || '35px';
|
|
this.multitype_tree = this.opts.multitype_tree||false;
|
|
this.selected_node = null;
|
|
this.create_toolbar();
|
|
this.checked_data = [];
|
|
this.container = new bricks.VBox({
|
|
"width":"100%",
|
|
"height":"auto",
|
|
"overflow":"auto"
|
|
});
|
|
this.add_widget(this.container);
|
|
this.data_id = null;
|
|
if (this.opts.dataurl){
|
|
this.params = options.params || {};
|
|
schedule_once(this.get_children_data.bind(this, this), 0.1);
|
|
} else {
|
|
this.user_data = {
|
|
id:null,
|
|
children:this.opts.data
|
|
}
|
|
this.create_node_children(this, this.opts.data);
|
|
}
|
|
}
|
|
getValue(){
|
|
var v = this.user_data;
|
|
if (this.container){
|
|
var children = [];
|
|
for (var i=0; i<this.container.children.length;i++){
|
|
var sv = this.container.children[i].getValue();
|
|
children.push(sv);
|
|
}
|
|
v.children = children;
|
|
}
|
|
return v;
|
|
}
|
|
get_id(){
|
|
return this.user_data[this.idField];
|
|
}
|
|
create_toolbar(){
|
|
var toolbar = bricks.extend({}, this.toolbar);
|
|
var tools = [];
|
|
if (toolbar.tools){
|
|
toolbar.tools.forEach(f => tools.push(f));
|
|
}
|
|
if (this.editable){
|
|
tools.push({icon:bricks_resource('imgs/add.png'), name:'add'});
|
|
tools.push({icon:bricks_resource('imgs/update.png'), name:'update'});
|
|
tools.push({icon:bricks_resource('imgs/delete.png'), name:'delete'});
|
|
}
|
|
if (tools.length == 0){
|
|
return;
|
|
}
|
|
toolbar.tools = tools;
|
|
this.toolbar_w = new bricks.IconTextBar(toolbar);
|
|
this.add_widget(this.toolbar_w);
|
|
this.toolbar_w.bind('command', this.toolbar_command.bind(this))
|
|
}
|
|
toolbar_command(event){
|
|
var opts = event.params;
|
|
switch (opts.name){
|
|
case 'add':
|
|
this.add_new_node();
|
|
breaks;
|
|
case 'delete':
|
|
this.delete_node();
|
|
break;
|
|
case 'update':
|
|
this.update_node();
|
|
break;
|
|
default:
|
|
console.log('opts=', opts);
|
|
var d = null;
|
|
if (opts.checked_data){
|
|
d = {
|
|
checked_data:JSON.stringify(this.checked_data)
|
|
}
|
|
} else if (opts.selected_node){
|
|
d = {
|
|
selected_data:JSON.stringify(this.selected_node.user_data)
|
|
}
|
|
}
|
|
this.dispatch(opts.name, d);
|
|
break;
|
|
}
|
|
}
|
|
async add_new_node(){
|
|
var w = new bricks.ModalForm({
|
|
target:this,
|
|
"width":"80%",
|
|
"height":"80%",
|
|
title:'add new node',
|
|
fields:this.editable.fields
|
|
});
|
|
w.bind('submit', this.new_node_inputed.bind(this))
|
|
}
|
|
|
|
async new_node_inputed(event){
|
|
var d = event.params;
|
|
var node = this;
|
|
if (this.selected_node){
|
|
node = this.selected_node;
|
|
d[this.parentField] = node.get_id();
|
|
}
|
|
if (this.editable.add_url){
|
|
var jc = new bricks.HttpJson()
|
|
var desc = await jc.post(this.editable.add_url, {params:d});
|
|
if (desc.widgettype == 'Message'){
|
|
var data = desc.options.user_data;
|
|
this.append_new_subnode(node, data);
|
|
}
|
|
var w = await bricks.widgetBuild(desc, this);
|
|
w.open();
|
|
} else {
|
|
d[this.idField] = bricks.uuid();
|
|
this.append_new_subnode(node, d);
|
|
}
|
|
}
|
|
async create_tree_nodes(node, records){
|
|
for (var i=0;i<records.length;i++){
|
|
this.build_subnode(node, records[i]);
|
|
}
|
|
}
|
|
append_new_subnode(node, data){
|
|
data.is_left = true;
|
|
if (!node.user_data){
|
|
node.user_data = {};
|
|
}
|
|
if (!node.user_data.children){
|
|
node.user_data.children = [];
|
|
}
|
|
node.is_leaf = false;
|
|
node.children_loaded = true;
|
|
node.user_data.children.push(data)
|
|
this.build_subnode(node, data);
|
|
}
|
|
|
|
build_subnode(node, data){
|
|
var n = new bricks.TreeNode(this, node, data);
|
|
node.container.add_widget(n);
|
|
}
|
|
|
|
async delete_node(){
|
|
if (! this.selected_node){
|
|
w = new bricks.Error({title:'Delete', message:'No selected node found'});
|
|
w.open();
|
|
return;
|
|
}
|
|
var w = new bricks.Conform({
|
|
title:'Delete node',
|
|
message:'Please conform delete selected node'
|
|
});
|
|
w.bind('conformed', this.delete_node_conformed.bind(this))
|
|
}
|
|
async delete_node_conformed(event){
|
|
var d = {};
|
|
d[this.idField] = this.selected_node.get_id();
|
|
if (this.editable.delete_url){
|
|
var jc = new bricks.HttpJson()
|
|
var desc = await jc.post(this.editable.delete_url, {params:d});
|
|
if (desc.widgettype == 'Message'){
|
|
var pnode = this.selected_node.parent_node;
|
|
console.log('parent node=', pnode);
|
|
if (pnode && pnode.container){
|
|
pnode.container.remove_widget(this.selected_node);
|
|
}
|
|
this.selected_node = null;
|
|
}
|
|
var w = await bricks.widgetBuild(desc, this);
|
|
w.open();
|
|
} else {
|
|
var pnode = this.selected_node.parent_node;
|
|
if (pnode && pnode.container){
|
|
pnode.container.remove_widget(this.selected_node);
|
|
}
|
|
this.selected_node = null;
|
|
}
|
|
}
|
|
delete_subnode(node, subnode){
|
|
var subid = subnode.user_data[this.idField];
|
|
var children = [];
|
|
for (var i=0;i< node.user_data.children.length;i++){
|
|
var c = node.user_data.children[i];
|
|
if (c[this.idField] != subid){
|
|
children.push(c);
|
|
}
|
|
}
|
|
node.user_data.children = children;
|
|
node.container.remove_widget(subnode);
|
|
}
|
|
|
|
async update_node(){
|
|
if (! this.selected_node){
|
|
w = new bricks.Error({title:'Update', message:'No selected node found'});
|
|
w.open();
|
|
return;
|
|
}
|
|
var fields = [];
|
|
for (var i=0;i<this.editable.fields.length;i++){
|
|
var f = bricks.extend({}, this.editable.fields[i]);
|
|
f.value = this.selected_node.user_data[f.name];
|
|
fields.push(f);
|
|
}
|
|
var w = new bricks.ModalForm({
|
|
target:this,
|
|
"width":"80%",
|
|
"height":"80%",
|
|
title:'add new node',
|
|
fields:fields
|
|
});
|
|
w.bind('submit', this.update_node_inputed.bind(this))
|
|
}
|
|
|
|
async update_node_inputed(event){
|
|
var d = event.params;
|
|
var node = this.selected_node;
|
|
d[this.idField] = node.get_id();
|
|
if(this.editable.update_url){
|
|
var jc = new bricks.HttpJson()
|
|
var desc = await jc.post(this.editable.update_url, {params:d});
|
|
if (desc.widgettype == 'Message'){
|
|
await this.update_node_data(node, d);
|
|
}
|
|
var w = await bricks.widgetBuild(desc, this);
|
|
w.open();
|
|
} else {
|
|
await this.update_node_data(node, d);
|
|
}
|
|
}
|
|
|
|
async update_node_data(node, data){
|
|
for (var name in Object.keys(data)){
|
|
node.user_data[name] = data[name];
|
|
}
|
|
await node.update_content();
|
|
}
|
|
|
|
async get_children_data(node){
|
|
var jc = new bricks.HttpJson();
|
|
var p = bricks.extend({}, this.params);
|
|
if (node != this){
|
|
p.id = node.user_data[this.idField];
|
|
}
|
|
console.log('params=', p);
|
|
var d = await jc.httpcall(this.opts.dataurl,{
|
|
method : this.opts.method || 'GET',
|
|
params : p
|
|
})
|
|
if (d.length == 0){
|
|
node.is_leaf = true;
|
|
} else {
|
|
this.user_data = {
|
|
children:d
|
|
}
|
|
this.create_tree_nodes(node, d);
|
|
}
|
|
}
|
|
create_node_children(node, data){
|
|
if(!data) return;
|
|
for (var i=0; i<data.length; i++){
|
|
var n = new bricks.TreeNode(this, node, data[i]);
|
|
node.container.add_widget(n);
|
|
}
|
|
}
|
|
node_click_handle(node, event){
|
|
if (this.selected_node){
|
|
this.node_selected(this.selected_node, false);
|
|
}
|
|
if (this.selected_node == node){
|
|
this.selected_node = null;
|
|
} else {
|
|
this.selected_node = node;
|
|
this.node_selected(node, true);
|
|
}
|
|
}
|
|
node_selected(node, flag){
|
|
console.log('node_selected():node=', node, flag);
|
|
node.selected(flag);
|
|
var d = bricks.extend(node.user_data, {
|
|
selected:flag
|
|
});
|
|
|
|
this.dispatch('node_selected', d);
|
|
}
|
|
async node_checked(node, event){
|
|
var cb = event.target.bricks_widget;
|
|
var stat = cb.getValue().check;
|
|
if (stat){
|
|
this.checked_data.push(node.user_data);
|
|
} else {
|
|
this.checked_data = this.checked_data.filter((d , idnex) => d.id == node.user_data.id);
|
|
}
|
|
node.user_data[this.checkField] = stat;
|
|
if (stat){
|
|
console.log('value=', cb.getValue(), 'node=', node);
|
|
}
|
|
this.dispatch('check_changed', node.user_data);
|
|
}
|
|
}
|
|
|
|
bricks.Factory.register('Tree', bricks.Tree);
|
|
bricks.Factory.register('EditableTree', bricks.EditableTree);
|