// // @description : // @author : Adarsh Pastakia // @copyright : 2016 // @license : MIT import {autoinject, bindable, bindingMode, containerless, children, customElement, inlineView, noView, DOM} from "aurelia-framework"; import {UIEvent} from "../../utils/ui-event"; import {UIFormat} from "../../utils/ui-format"; import * as Tether from "tether"; @autoinject() @customElement('ui-datagrid') @inlineView(``) export class UIDatagrid { constructor(public element: Element) { if (element.hasAttribute('auto-height')) this.element.classList.add('ui-auto-size'); if (element.hasAttribute('rowselect')) this.__rowSelect = true; if (element.hasAttribute('virtual')) this.__virtual = true; } bind() { this.__columns = _.sortBy(this.columns, 'locked'); } columnsChanged(newValue) { this.__columns = _.sortBy(this.columns, 'locked'); } @children('ui-dg-column,ui-dg-button,ui-dg-switch,ui-dg-link,ui-dg-input') columns; @bindable() data = []; @bindable() summaryRow = false; @bindable() sortColumn = ''; @bindable() sortOrder = ''; __virtual = false; __rowSelect; __columns = []; __tableWidth = ''; calculateWidth(cols) { let w = 0; _.forEach(cols, c => { c.left = w; w += c.getWidth(); }); return (this.__tableWidth = (w + 20) + 'px'); } dataChanged(newValue) { UIEvent.queueTask(() => this.data = _.orderBy(this.data, [this.sortColumn, 'ID', 'id'], [this.sortOrder, this.sortOrder, this.sortOrder])); } __dgWrapHead; __dgWrapFoot; scrolling(evt) { if (this.__dgWrapHead) this.__dgWrapHead.scrollLeft = evt.target.scrollLeft; if (this.__dgWrapFoot) this.__dgWrapFoot.scrollLeft = evt.target.scrollLeft; } doSort(col) { if (!col.sortable) return; if (this.sortColumn != col.dataId) this.sortOrder = 'asc'; if (this.sortColumn == col.dataId) this.sortOrder = this.sortOrder == 'asc' ? 'desc' : 'asc'; this.sortColumn = col.dataId; UIEvent.queueTask(() => this.data = _.orderBy(this.data, [this.sortColumn, 'ID', 'id'], [this.sortOrder, this.sortOrder, this.sortOrder])); } __move; __stop; __diff; __startX; __column; __colNext; __ghost; __scroller; __resizing = false; resizeColumn(evt, col, next) { if (evt.button != 0) return true; this.__diff = 0; this.__column = col; this.__colNext = next; this.__resizing = true; this.__startX = (evt.x || evt.clientX); this.__ghost.style.left = (col.left + parseInt(col.width) - (col.locked == 0 ? 0 : this.__scroller.scrollLeft)) + 'px'; document.addEventListener('mouseup', this.__stop = evt => this.__resizeEnd(evt)); document.addEventListener('mousemove', this.__move = evt => this.__resize(evt)); } __resize(evt) { var x = (evt.x || evt.clientX) - this.__startX; if (x < 0 && (parseInt(this.__column.width) + this.__diff) <= (this.__column.minWidth || 80)) return; if (x > 0 && (parseInt(this.__column.width) + this.__diff) >= (500)) return; this.__startX = (evt.x || evt.clientX); this.__diff += x; this.__ghost.style.left = (parseInt(this.__ghost.style.left) + x) + 'px'; } __resizeEnd(evt) { this.__resizing = false; if (this.__colNext) this.__colNext.left += this.__diff; this.__column.width = (parseInt(this.__column.width) + this.__diff); this.calculateWidth(this.__columns); document.removeEventListener('mousemove', this.__move); document.removeEventListener('mouseup', this.__stop); } fireSelect(record) { UIEvent.fireEvent('rowselect', this.element, ({ record })); } } @containerless() @customElement('ui-dg-empty') @inlineView(``) export class UIDGEmpty { } export class UIDataColumn { constructor(public element: Element) { this.resize = element.hasAttribute('resizeable'); this.sortable = element.hasAttribute('sortable'); this.locked = element.hasAttribute('locked') ? 0 : 1; //alignment if (element.hasAttribute('center')) this.align = 'ui-text-center'; else if (element.hasAttribute('end')) this.align = 'ui-text-end'; if (element.hasAttribute('age')) this.dataType = 'age'; else if (element.hasAttribute('date')) this.dataType = 'date'; else if (element.hasAttribute('time')) this.dataType = 'time'; else if (element.hasAttribute('datetime')) this.dataType = 'datetime'; else if (element.hasAttribute('fromnow')) this.dataType = 'fromnow'; else if (element.hasAttribute('number')) this.dataType = 'number'; else if (element.hasAttribute('currency')) this.dataType = 'currency'; else if (element.hasAttribute('percent')) this.dataType = 'percent'; else if (element.hasAttribute('exrate')) this.dataType = 'exrate'; } dataId; width; minWidth; value; display; format; symbol; dataType = 'text'; align = 'ui-text-start'; left = 0; locked = 1; resize = false; sortable = false; getWidth(tw) { this.width = convertToPx(this.width || this.minWidth || 250); tw += this.width; return this.width; } getTitle() { return this.element.innerHTML; } getValue(value, record) { return this.processValue(value, record) || ' '; } processValue(value, record) { let retVal = ''; // let value = record[this.dataId]; if (isFunction(this.value)) value = this.value(({ value, record })); if (isFunction(this.display)) retVal = this.display(({ value, record })) || ''; else { switch (this.dataType) { case 'age': retVal = UIFormat.age(value); break; case 'date': retVal = UIFormat.date(value, this.format); break; case 'time': retVal = UIFormat.time(value, this.format); break; case 'datetime': retVal = UIFormat.datetime(value, this.format); break; case 'fromnow': retVal = UIFormat.fromNow(value); break; case 'number': retVal = UIFormat.number(value, this.format); break; case 'currency': retVal = UIFormat.currency(value, record[this.symbol] || this.symbol || '$', this.format); break; case 'percent': retVal = UIFormat.percent(value); break; case 'exrate': retVal = UIFormat.exRate(value); break; default: retVal = value; break; } } return retVal; } } @autoinject() @customElement('ui-dg-column') @inlineView(``) export class UIDGColumn extends UIDataColumn { type = 'normal'; constructor(public element: Element) { super(element); } @bindable() dataId; @bindable() width; @bindable() minWidth; @bindable() class; @bindable() value; @bindable() display; @bindable() symbol; @bindable() format; } @autoinject() @customElement('ui-dg-link') @inlineView(``) export class UIDGLink extends UIDataColumn { type = 'link'; constructor(public element: Element) { super(element); } @bindable() dataId; @bindable() width; @bindable() minWidth; @bindable() icon; @bindable() label; @bindable() class; @bindable() disabled = null; isDisabled(value, record) { if (isFunction(this.disabled)) return this.disabled(({ value, record })); if (this.disabled != null) return record[this.disabled]; return false; } getIcon(value, record) { if (isFunction(this.icon)) return this.icon(({ value, record })); return record[this.icon] || this.icon; } getLabel(value, record) { if (isFunction(this.label)) return this.label(({ value, record })); return this.label || this.processValue(value, record) || ''; } fireClick($event, value, record) { $event.stopPropagation(); $event.preventDefault(); if (this.isDisabled(value, record)) return; UIEvent.fireEvent('click', this.element, ({ value, record })); return false; } } @autoinject() @customElement('ui-dg-button') @inlineView(``) export class UIDGButton extends UIDataColumn { type = 'button'; constructor(public element: Element) { super(element); this.align = 'ui-text-center'; } @bindable() dataId; @bindable() width; @bindable() minWidth; @bindable() icon; @bindable() label; @bindable() dropdown; @bindable() theme: any = 'default'; @bindable() disabled = null; isDisabled(value, record) { if (isFunction(this.disabled)) return this.disabled(({ value, record })); if (this.disabled != null) return record[this.disabled]; return false; } getIcon(value, record) { if (isFunction(this.icon)) return this.icon(({ value, record })); return record[this.icon] || this.icon; } getLabel(value, record) { if (isFunction(this.label)) return this.label(({ value, record })); return this.label || this.processValue(value, record) || ''; } getTheme(value, record) { if (isFunction(this.theme)) return this.theme(({ value, record })); return this.theme; } fireClick($event, value, record) { $event.stopPropagation(); $event.preventDefault(); if (this.isDisabled(value, record)) return; UIEvent.fireEvent('click', this.element, ({ value, record })); return false; } fireMenuOpen($event, record) { $event.stopPropagation(); return UIEvent.fireEvent('menuopen', this.element, ({ record })); } } @autoinject() @customElement('ui-dg-switch') @inlineView(``) export class UIDGSwitch extends UIDataColumn { type = 'switch'; constructor(public element: Element) { super(element); this.align = 'ui-text-center'; } @bindable() dataId; @bindable() width; @bindable() minWidth; @bindable({ defaultBindingMode: bindingMode.twoWay }) checked: boolean = false; @bindable({ defaultBindingMode: bindingMode.twoWay }) value: any = ''; @bindable() size = '4em'; @bindable() class = ''; @bindable() onLabel = 'on'; @bindable() offLabel = 'off'; @bindable() onValue = true; @bindable() offValue = false; @bindable() theme = 'default'; @bindable() disabled = null; isDisabled(value, record) { if (isFunction(this.disabled)) return this.disabled(({ value, record })); if (this.disabled != null) return record[this.disabled]; return false; } fireChange(value, record) { UIEvent.fireEvent('change', this.element, ({ value, record })); } }