@indexea/sdk
Version:
Indexea JavaScript SDK (indexea.com)
234 lines (218 loc) • 6.38 kB
text/typescript
/**
* widget layout manager
* example:
<layout>
<row>
<col width='6'>
<control type='input'/>
</col>
<col width='6'>
<control type='hotwords'/>
</col>
</row>
<row>
<col width='9'>
<control type='results'/>
</col>
<col width='3'>
<control type='aggregation'/>
<control type='aggregation'/>
</col>
</row>
<row>
<col width='9'>
<control type='pagination'/>
</col>
</row>
</layout>
*/
export class WidgetLayout {
private xml: Document;
private constructor(xml: Document) {
this.xml = xml
}
/**
* parse layout xml string
* @param xmlstring
* @returns
*/
static parse(xmlstring: string): WidgetLayout {
const parser = new DOMParser()
const xml = parser.parseFromString(xmlstring, 'text/xml')
return new WidgetLayout(xml);
}
/**
* turn to layout xml string
* @returns
*/
toString(): string {
var oSerializer = new XMLSerializer()
var sXML = oSerializer.serializeToString(this.xml)
return sXML
}
/**
* check if exists a control named `ctrl_name`
* @param ctrl_name
* @returns
*/
control(ctrl_name: string): any {
return this.xml.querySelector(`control[type='${ctrl_name}']`);
}
/**
* get all rows in layout
* @returns
*/
rows(): any {
return this.xml.getElementsByTagName("row");
}
/**
* append node to position
* @param node
* @param row
* @param col
* @returns
*/
append(node: any, row = 0, col = 0): WidgetLayout {
if (this.control(node.type) != null)
return this;
//get position of row and col
let theNode: any;
let rowNodes = this.xml.getElementsByTagName('row')
if (row >= 0 && row < rowNodes.length) {
var rowNode = rowNodes[row]
var colNodes = rowNode.getElementsByTagName('col')
if (col >= 0 && col < colNodes.length) {
theNode = colNodes[col]
}
}
var elem = this.xml.createElement('control')
elem.setAttribute('type', node.type)
if (theNode) {
//拖入设计器的某个元素之上
var cols = theNode.parentNode?.getElementsByTagName('col')
var lastWidth = parseInt(cols[cols.length - 1].getAttribute('width'))
var totalWidth = 0
for (var i = 0; i < cols.length; i++) {
totalWidth += parseInt(cols[i].getAttribute('width'))
}
if (totalWidth + node.width > 12) {
if (node.width == lastWidth) cols[cols.length - 1].appendChild(elem)
else this.appendToNewRow(theNode, elem, node.width)
} else {
this.appendToNewCol(theNode, elem, node.width)
}
} else {
//拖入设计器的空白处
this.appendToNewRow(theNode, elem, node.width)
}
return this
}
/**
* remove node from position
* @param row
* @param col
* @param index
* @returns
*/
remove(row: number, col: number, index: number): WidgetLayout {
let rowNodes = this.xml.getElementsByTagName('row')
if (row < rowNodes.length) {
var rowNode = rowNodes[row]
var colNodes = rowNode.getElementsByTagName('col')
if (col < colNodes.length) {
colNodes[col].removeChild(colNodes[col].childNodes[index])
//如果该列已经没有子节点了,则删除该列
if (!colNodes[col].hasChildNodes()) {
rowNode.removeChild(colNodes[col])
}
//如果该行已经没有子节点了,则删除该行
if (!rowNode.hasChildNodes()) {
rowNode.parentNode?.removeChild(rowNode)
}
}
}
return this;
}
/**
* get control attribute with name `attr_name`
* @param ctrl_name
* @param attr_name
* @returns
*/
getAttribute(ctrl_name: string, attr_name: string): any {
var ctl = this.xml.querySelector(`control[type='${ctrl_name}']`);
return ctl ? ctl.getAttribute(attr_name) : null;
}
/**
* get attributes of control
* @param ctrl_name
*/
getAttributes(ctrl_name: string = ""): any {
let attrs = ctrl_name
? this.xml.querySelector(`control[type='${ctrl_name}']`)?.attributes
: this.xml.querySelector('layout')?.attributes
var props: {[key: string]:any} = {}
if (attrs)
for (var i = 0; i < attrs.length; i++) {
var att = attrs.item(i)
if (att) {
if (att.value === 'true') props[att.name] = true
else if (att.value === 'false') props[att.name] = false
else if (att.value) props[att.name] = att.value
}
}
return props
}
/**
* set control attributes
* @param {row}} ctrl_name
* @param {attrs} attrs
*/
setAttributes(ctrl_name: string, attrs: any) {
let ctrl = this.xml.querySelector(`control[type='${ctrl_name}']`);
if (ctrl) {
for (let key in attrs) {
ctrl.setAttribute(key, attrs[key]);
}
}
}
/**
* set control attributes
* @param {row}} row
* @param {col} col
* @param {index} index
* @param {attrs} attrs
*/
setAttributesByPos(row: number, col: number, index: number, attrs: any) {
let rowNodes = this.xml.getElementsByTagName('row')
if (row < rowNodes.length) {
var rowNode = rowNodes[row]
var colNodes = rowNode.getElementsByTagName('col')
if (col < colNodes.length) {
if (index < colNodes[col].childNodes.length) {
var controls = colNodes[col].getElementsByTagName('control')
if (index < controls.length) {
var control = controls[index]
for (var key in attrs) {
control.setAttribute(key, attrs[key])
}
}
}
}
}
}
private appendToNewRow(node: any, elem: any, width: number) {
var row = this.xml.createElement('row')
var col = this.xml.createElement('col')
col.setAttribute('width', width + "")
col.appendChild(elem)
row.appendChild(col)
this.xml.getElementsByTagName('layout')[0].appendChild(row)
}
private appendToNewCol(node: any, elem: any, width: number) {
var col = this.xml.createElement('col')
col.setAttribute('width', width + "")
col.appendChild(elem)
node.parentNode.appendChild(col)
}
}