loleaflet/js/w2ui-1.5.rc1.js |16475 +------------------------------------------ 1 file changed, 598 insertions(+), 15877 deletions(-)
New commits: commit bb6f13d94dc6063df926e918868d144f36729c14 Author: Henry Castro <hcas...@collabora.com> AuthorDate: Fri Feb 14 12:28:36 2020 -0400 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Mon Feb 17 14:57:19 2020 +0100 w2ui: remove unused components w2ui is bundled with: w2grid, w2layout, w2popup, w2tabs, w2sidebar, w2fields, w2form But they are not used in desktop nor mobile and it is preferable to remove the dead code to reduce bundle size, parse with mobile devices. If in a near future, these components are used, still we can restore the components. Change-Id: I522f01a73217635acc9828a54006111fa196636d Reviewed-on: https://gerrit.libreoffice.org/c/online/+/88735 Tested-by: Michael Meeks <michael.me...@collabora.com> Reviewed-by: Michael Meeks <michael.me...@collabora.com> diff --git a/loleaflet/js/w2ui-1.5.rc1.js b/loleaflet/js/w2ui-1.5.rc1.js index 687a00202..82243a0f0 100644 --- a/loleaflet/js/w2ui-1.5.rc1.js +++ b/loleaflet/js/w2ui-1.5.rc1.js @@ -2903,302 +2903,65 @@ w2utils.event = { /************************************************************************ * Library: Web 2.0 UI for jQuery (using prototypical inheritance) * - Following objects defined -* - w2grid - grid widget -* - $().w2grid - jQuery wrapper -* - Dependencies: jQuery, w2utils, w2toolbar, w2fields +* - w2toolbar - toolbar widget +* - $().w2toolbar - jQuery wrapper +* - Dependencies: jQuery, w2utils, w2field * * == NICE TO HAVE == -* - column autosize based on largest content -* - reorder columns/records -* - problem with .set() and arrays, array get extended too, but should be replaced -* - after edit stay on the same record option -* - if supplied array of ids, get should return array of records -* - allow functions in routeData (also add routeData to list/enum) -* - implement global routeData and all elements read from there -* - send parsed URL to the event if there is routeData -* - if you set searchData or sortData and call refresh() it should work -* - add selectType: 'none' so that no selection can be make but with mouse -* - reorder records with frozen columns -* - focus/blur for selectType = cell not display grayed out selection -* - frozen columns - - load more only on the right side - - scrolling on frozen columns is not working only on regular columns -* - copy or large number of records is slow -* - reusable search component (see https://github.com/vitmalina/w2ui/issues/914#issuecomment-107340524) -* - allow enum in inline edit (see https://github.com/vitmalina/w2ui/issues/911#issuecomment-107341193) -* - if record has no recid, then it should be index in the aray (should not be 0) -* -* == KNOWN ISSUES == -* - bug: vs_start = 100 and more then 500 records, when scrolling empty sets -* - row drag and drop has bugs -* - Shift-click/Ctrl-click/Ctrl-Shift-Click selection is not as robust as it should be -* -* == 1.5 changes -* - $('#grid').w2grid() - if called w/o argument then it returns grid object -* - added statusRange : true, -* statusBuffered : false, -* statusRecordID : true, -* statusSelection : true, -* statusResponse : true, -* statusSort : true, -* statusSearch : true, -* - change selectAll() and selectNone() - return time it took -* - added vs_start and vs_extra -* - added update(cells) - updates only data in the grid (or cells) -* - add to docs onColumnDragStart, onColumnDragEnd -* - onSelect and onSelect should fire 1 time for selects with shift or selectAll(), selectNone() -* - record.w2ui.style[field_name] -* - use column field for style: { 1: 'color: red' } -* - added focus(), blur(), onFocus, onBlur -* - search.simple - if false, will not show up in simple search -* - search.operator - default operator to use with search field -* - search.operators - array of operators for the serach -* - search.hidden - could not be clearned by the user -* - search.value - only for hidden searches -* - if .search(val) - search all fields -* - refactor reorderRow (not finished) -* - return JSON can now have summary array -* - frozen columns -* - added selectionSave, selectionRestore - for internal use -* - added additional search filter options for int, float, date, time -* - added getLineHTML -* - added lineNumberWidth -* - add searches.style -* - getColumn without params returns fields of all columns -* - getSearch without params returns fields of all searches -* - added column.tooltip -* - added hasFocus, refactored w2utils.keyboard -* - do not clear selection when clicked and it was not in focus -* - added record.w2ui.colspan -* - editable area extends with typing -* - removed onSubmit and onDeleted - now it uses onSave and onDelete -* - column.seachable - can be an object, which will create search -* - added null, not null filters -* - update(cells) - added argument cells -* - scrollIntoView(..., ..., instant) - added third argument -* - added onResizeDblClick -* - added onColumnDblClick -* - implemented showBubble -* - added show.searchAll -* - added w2grid.operators -* - added w2grid.operatorsMap -* - move events into prototype -* - move rec.summary, rec.style, rec.editable -> into rec.w2ui.summary, rec.w2ui.style, rec.w2ui.editable -* - record: { - recid - field1 - ... - fieldN - w2ui: { - colspan: { field: 5, ...} - editable: true/false - changes: { - field: chagned_value, - .... - }, - children: [ - // similar to records array - // can have sub children - ] - parent_recid: (internally set, id of the parent record, when children are copied to records array) - summary: true/false - style: 'string' - for entire row OR { field: 'string', ...} - per field - class: 'string' - for entire row OR { field: 'string', ...} - per field - } - } -* - added this.show.toolbarInput -* - disableCVS -* - grid.message -* - added noReset option to localSort() -* - onColumnSelect -* - need to update PHP example -* - added scrollToColumn(field) -* - textSearch: 'begins' (default), 'contains', 'is', ... -* - added refreshBody -* - added response.total = -1 (or not present) to indicate that number of records is unknown -* - message(.., callBack) - added callBack -* - grid.msgEmpty -* - field.render(..., data) -- added last argument which is what grid thinks should be there -* - onSearchOpen (onSearch will have mutli and reset flags) -* - added httpHeaders -* - col.editable can be a function which will be called with the same args as col.render() -* - getCellEditable(index, col_ind) -- return an 'editable' descriptor if cell is really editable -* - added stateId -* - rec.w2ui.class (and rec.w2ui.class { fname: '...' }) -* - columnTooltip -* - expendable grids are still working -* - added search.type = 'color' +* - vertical toolbar * ************************************************************************/ (function ($) { - var w2grid = function(options) { - - // public properties - this.name = null; - this.box = null; // HTML element that hold this element - this.header = ''; - this.url = ''; - this.routeData = {}; // data for dynamic routes - this.columns = []; // { field, caption, size, attr, render, hidden, gridMinWidth, editable } - this.columnGroups = []; // { span: int, caption: 'string', master: true/false } - this.records = []; // { recid: int(requied), field1: 'value1', ... fieldN: 'valueN', style: 'string', changes: object } - this.summary = []; // arry of summary records, same structure as records array - this.searches = []; // { type, caption, field, inTag, outTag, hidden } - this.searchData = []; - this.sortData = []; - this.postData = {}; - this.httpHeaders = {}; - this.toolbar = {}; // if not empty object; then it is toolbar object - this.stateId = null; // Custom state name for satateSave, stateRestore and stateReset - - this.show = { - header : false, - toolbar : false, - footer : false, - columnHeaders : true, - lineNumbers : false, - expandColumn : false, - selectColumn : false, - emptyRecords : true, - toolbarReload : true, - toolbarColumns : true, - toolbarSearch : true, - toolbarInput : true, - toolbarAdd : false, - toolbarEdit : false, - toolbarDelete : false, - toolbarSave : false, - searchAll : true, - statusRange : true, - statusBuffered : false, - statusRecordID : true, - statusSelection : true, - statusResponse : true, - statusSort : false, - statusSearch : false, - recordTitles : true, - selectionBorder : true, - skipRecords : true, - saveRestoreState: true - }; - - this.hasFocus = false; - this.autoLoad = true; // for infinite scroll - this.fixedBody = true; // if false; then grid grows with data - this.recordHeight = 24; // should be in prototype - this.lineNumberWidth = null; - this.vs_start = 150; - this.vs_extra = 15; - this.keyboard = true; - this.selectType = 'row'; // can be row|cell - this.multiSearch = true; - this.multiSelect = true; - this.multiSort = true; - this.reorderColumns = false; - this.reorderRows = false; - this.markSearch = true; - this.columnTooltip = 'normal'; // can be normal, top, bottom, left, right - this.disableCVS = false; // disable Column Virtual Scroll - this.textSearch = 'begins'; // default search type for text - - this.total = 0; // server total - this.limit = 100; - this.offset = 0; // how many records to skip (for infinite scroll) when pulling from server - this.style = ''; - this.ranges = []; - this.menu = []; - this.method = null; // if defined, then overwrited ajax method - this.recid = null; - this.parser = null; - - // internal - this.last = { - field : '', - caption : '', - logic : 'OR', - search : '', - searchIds : [], - selection : { - indexes : [], - columns : {} - }, - multi : false, - scrollTop : 0, - scrollLeft : 0, - colStart : 0, // for column virtual scrolling - colEnd : 0, - sortData : null, - sortCount : 0, - xhr : null, - range_start : null, - range_end : null, - sel_ind : null, - sel_col : null, - sel_type : null, - edit_col : null, - isSafari : (/^((?!chrome|android).)*safari/i).test(navigator.userAgent) - }; + var w2toolbar = function (options) { + this.box = null; // DOM Element that holds the element + this.name = null; // unique name for w2ui + this.routeData = {}; // data for dynamic routes + this.items = []; + this.right = ''; // HTML text on the right of toolbar + this.tooltip = 'top|left';// can be top, bottom, left, right - $.extend(true, this, w2obj.grid, options); + $.extend(true, this, w2obj.toolbar, options); }; // ==================================================== // -- Registers as a jQuery plugin - $.fn.w2grid = function(method) { + $.fn.w2toolbar = function(method) { if ($.isPlainObject(method)) { // check name parameter - if (!w2utils.checkName(method, 'w2grid')) return; - // remember items - var columns = method.columns; - var columnGroups = method.columnGroups; - var records = method.records; - var searches = method.searches; - var searchData = method.searchData; - var sortData = method.sortData; - var postData = method.postData; - var httpHeaders = method.httpHeaders; - var toolbar = method.toolbar; + if (!w2utils.checkName(method, 'w2toolbar')) return; // extend items - var object = new w2grid(method); - $.extend(object, { postData: {}, httpHeaders: {}, records: [], columns: [], searches: [], toolbar: {}, sortData: [], searchData: [], handlers: [] }); - if (object.onExpand != null) object.show.expandColumn = true; - $.extend(true, object.toolbar, toolbar); - // reassign variables - var p; - if (columns) for (p = 0; p < columns.length; p++) object.columns[p] = $.extend(true, {}, columns[p]); - if (columnGroups) for (p = 0; p < columnGroups.length; p++) object.columnGroups[p] = $.extend(true, {}, columnGroups[p]); - if (searches) for (p = 0; p < searches.length; p++) object.searches[p] = $.extend(true, {}, searches[p]); - if (searchData) for (p = 0; p < searchData.length; p++) object.searchData[p] = $.extend(true, {}, searchData[p]); - if (sortData) for (p = 0; p < sortData.length; p++) object.sortData[p] = $.extend(true, {}, sortData[p]); - object.postData = $.extend(true, {}, postData); - object.httpHeaders = $.extend(true, {}, httpHeaders); - - // check if there are records without recid - if (records) for (var r = 0; r < records.length; r++) { - if (records[r].recid == null && records[r][object.recid] == null) { - console.log('ERROR: Cannot add records without recid. (obj: '+ object.name +')'); - return; + var items = method.items || []; + var object = new w2toolbar(method); + $.extend(object, { items: [], handlers: [] }); + for (var i = 0; i < items.length; i++) { + object.items[i] = $.extend({}, w2toolbar.prototype.item, items[i]); + // menus + if (object.items[i].type == 'menu-check') { + var item = object.items[i]; + if (!Array.isArray(item.selected)) item.selected = []; + if (Array.isArray(item.items)) { + for (var j = 0; j < item.items.length; j++) { + var it = item.items[j]; + if (it.checked && item.selected.indexOf(it.id) == -1) item.selected.push(it.id); + if (!it.checked && item.selected.indexOf(it.id) != -1) it.checked = true; + if (it.checked == null) it.checked = false; + } + } } - object.records[r] = $.extend(true, {}, records[r]); - } - // add searches - for (var i = 0; i < object.columns.length; i++) { - var col = object.columns[i]; - var search = col.searchable; - if (search == null || search === false || object.getSearch(col.field) != null) continue; - if ($.isPlainObject(search)) { - object.addSearch($.extend({ field: col.field, caption: col.caption, type: 'text' }, search)); - } else { - var stype = col.searchable, attr = ''; - if (col.searchable === true) { stype = 'text'; attr = 'size="20"'; } - object.addSearch({ field: col.field, caption: col.caption, type: stype, attr: attr }); + else if (object.items[i].type == 'menu-radio') { + var item = object.items[i]; + if (Array.isArray(item.items)) { + for (var j = 0; j < item.items.length; j++) { + var it = item.items[j]; + if (it.checked && item.selected == null) item.selected = it.id; else it.checked = false; + if (!it.checked && item.selected == it.id) it.checked = true; + if (it.checked == null) it.checked = false; + } + } } } - // init toolbar - object.initToolbar(); - // render if necessary if ($(this).length !== 0) { object.render($(this)[0]); } @@ -3221,15747 +2984,705 @@ w2utils.event = { // ==================================================== // -- Implementation of core functionality - w2grid.prototype = { - msgDelete : 'Are you sure you want to delete selected records?', - msgNotJSON : 'Returned data is not in valid JSON format.', - msgAJAXerror : 'AJAX error. See console for more details.', - msgRefresh : 'Refreshing...', - msgNeedReload : 'Your remote data source record count has changed, reloading from the first record.', - msgEmpty : '', // if not blank, then it is message when server returns no records - - buttons: { - 'reload' : { type: 'button', id: 'w2ui-reload', icon: 'w2ui-icon-reload', tooltip: 'Reload data in the list' }, - 'columns' : { type: 'drop', id: 'w2ui-column-on-off', icon: 'w2ui-icon-columns', tooltip: 'Show/hide columns', arrow: false, html: '' }, - 'search' : { type: 'html', id: 'w2ui-search', - html: '<div class="w2ui-icon icon-search-down w2ui-search-down" '+ - 'onclick="var obj = w2ui[jQuery(this).parents(\'div.w2ui-grid\').attr(\'name\')]; obj.searchShowFields();"></div>' - }, - 'search-go': { type: 'drop', id: 'w2ui-search-advanced', icon: 'w2ui-icon-search', text: 'Search', tooltip: 'Open Search Fields' }, - 'add' : { type: 'button', id: 'w2ui-add', text: 'Add New', tooltip: 'Add new record', icon: 'w2ui-icon-plus' }, - 'edit' : { type: 'button', id: 'w2ui-edit', text: 'Edit', tooltip: 'Edit selected record', icon: 'w2ui-icon-pencil', disabled: true }, - 'delete' : { type: 'button', id: 'w2ui-delete', text: 'Delete', tooltip: 'Delete selected records', icon: 'w2ui-icon-cross', disabled: true }, - 'save' : { type: 'button', id: 'w2ui-save', text: 'Save', tooltip: 'Save changed records', icon: 'w2ui-icon-check' } - }, + w2toolbar.prototype = { + onClick : null, + onRender : null, + onRefresh : null, + onResize : null, + onDestroy : null, - operators: { // for search fields - "text" : ['is', 'begins', 'contains', 'ends'], - "number" : ['is', 'between', { oper: 'less', text: 'less than'}, { oper: 'more', text: 'more than' }], - "date" : ['is', 'between', { oper: 'less', text: 'before'}, { oper: 'more', text: 'after' }], - "list" : ['is'], - "hex" : ['is', 'between'], - "color" : ['is', 'begins', 'contains', 'ends'], - "enum" : ['in', 'not in'] - // -- all posible - // "text" : ['is', 'begins', 'contains', 'ends'], - // "number" : ['is', 'between', 'less:less than', 'more:more than', 'null:is null', 'not null:is not null'], - // "list" : ['is', 'null:is null', 'not null:is not null'], - // "enum" : ['in', 'not in', 'null:is null', 'not null:is not null'] + item: { + id : null, // command to be sent to all event handlers + type : 'button', // button, check, radio, drop, menu, menu-radio, menu-check, break, html, spacer + text : null, + html : '', + tooltip : null, // w2toolbar.tooltip should be + count : null, + hidden : false, + disabled : false, + checked : false, // used for radio buttons + img : null, + icon : null, + route : null, // if not null, it is route to go + arrow : true, // arrow down for drop/menu types + style : null, // extre css style for caption + color : null, // color value - used in color pickers + transparent : null, // transparent t/f - used in color pickers + group : null, // used for radio buttons + items : null, // for type menu* it is an array of items in the menu + selected : null, // used for menu-check, menu-radio + overlay : {}, + onClick : null, + onRefresh : null }, - operatorsMap: { - "text" : "text", - "int" : "number", - "float" : "number", - "money" : "number", - "currency" : "number", - "percent" : "number", - "hex" : "hex", - "alphanumeric" : "text", - "color" : "color", - "date" : "date", - "time" : "date", - "datetime" : "date", - "list" : "list", - "combo" : "text", - "enum" : "enum", - "file" : "enum", - "select" : "list", - "radio" : "list", - "checkbox" : "list", - "toggle" : "list" + add: function (items) { + this.insert(null, items); }, - // events - onAdd : null, - onEdit : null, - onRequest : null, // called on any server event - onLoad : null, - onDelete : null, - onSave : null, - onSelect : null, - onUnselect : null, - onClick : null, - onDblClick : null, - onContextMenu : null, - onMenuClick : null, // when context menu item selected - onColumnClick : null, - onColumnDblClick : null, - onColumnResize : null, - onSort : null, - onSearch : null, - onSearchOpen : null, - onChange : null, // called when editable record is changed - onRestore : null, // called when editable record is restored - onExpand : null, - onCollapse : null, - onError : null, - onKeydown : null, - onToolbar : null, // all events from toolbar - onColumnOnOff : null, - onCopy : null, - onPaste : null, - onSelectionExtend : null, - onEditField : null, - onRender : null, - onRefresh : null, - onReload : null, - onResize : null, - onDestroy : null, - onStateSave : null, - onStateRestore : null, - onFocus : null, - onBlur : null, - onReorderRow : null, - - add: function (record, first) { - if (!$.isArray(record)) record = [record]; - var added = 0; - for (var i = 0; i < record.length; i++) { - var rec = record[i]; - if (rec.recid == null && rec[this.recid] == null) { - console.log('ERROR: Cannot add record without recid. (obj: '+ this.name +')'); - continue; - } - if (rec.w2ui && rec.w2ui.summary === true) { - if (first) this.summary.unshift(rec); else this.summary.push(rec); - } else { - if (first) this.records.unshift(rec); else this.records.push(rec); + insert: function (id, items) { + if (!$.isArray(items)) items = [items]; + for (var o = 0; o < items.length; o++) { + // checks + if (items[o].type == null) { + console.log('ERROR: The parameter "type" is required but not supplied in w2toolbar.add() method.'); + return; } - added++; - } - var url = (typeof this.url != 'object' ? this.url : this.url.get); - if (!url) { - this.total = this.records.length; - this.localSort(false, true); - this.localSearch(); - // do not call this.refresh(), this is unnecessary, heavy, and messes with the toolbar. - this.refreshBody(); - this.resizeRecords(); - return added; - } - this.refresh(); // ?? should it be reload? - return added; - }, - - find: function (obj, returnIndex) { - if (obj == null) obj = {}; - var recs = []; - var hasDots = false; - // check if property is nested - needed for speed - for (var o in obj) if (String(o).indexOf('.') != -1) hasDots = true; - // look for an item - for (var i = 0; i < this.records.length; i++) { - var match = true; - for (var o in obj) { - var val = this.records[i][o]; - if (hasDots && String(o).indexOf('.') != -1) val = this.parseField(this.records[i], o); - if (obj[o] == 'not-null') { - if (val == null || val === '') match = false; - } else { - if (obj[o] != val) match = false; - } + if ($.inArray(String(items[o].type), ['button', 'check', 'radio', 'drop', 'menu', 'menu-radio', 'menu-check', 'color', 'text-color', 'break', 'html', 'spacer']) == -1) { + console.log('ERROR: The parameter "type" should be one of the following [button, check, radio, drop, menu, break, html, spacer] '+ + 'in w2toolbar.add() method.'); + return; } - if (match && returnIndex !== true) recs.push(this.records[i].recid); - if (match && returnIndex === true) recs.push(i); - } - return recs; - }, - - set: function (recid, record, noRefresh) { // does not delete existing, but overrides on top of it - if (typeof recid == 'object') { - noRefresh = record; - record = recid; - recid = null; - } - // update all records - if (recid == null) { - for (var i = 0; i < this.records.length; i++) { - $.extend(true, this.records[i], record); // recid is the whole record + if (items[o].id == null && items[o].type != 'break' && items[o].type != 'spacer') { + console.log('ERROR: The parameter "id" is required but not supplied in w2toolbar.add() method.'); + return; } - if (noRefresh !== true) this.refresh(); - } else { // find record to update - var ind = this.get(recid, true); - if (ind == null) return false; - var isSummary = (this.records[ind] && this.records[ind].recid == recid ? false : true); - if (isSummary) { - $.extend(true, this.summary[ind], record); + if (!w2utils.checkUniqueId(items[o].id, this.items, 'toolbar items', this.name)) return; + // add item + var it = $.extend({}, w2toolbar.prototype.item, items[o]); + if (id == null) { + this.items.push(it); } else { - $.extend(true, this.records[ind], record); - } - if (noRefresh !== true) this.refreshRow(recid, ind); // refresh only that record - } - return true; - }, - - get: function (recid, returnIndex) { - // search records - if ($.isArray(recid)) { - var recs = []; - for (var i = 0; i < this.records.length; i++) { - if ($.inArray(this.records[i].recid, recid) != -1) { - if (returnIndex === true) { - recs.push(i); - } else { - recs.push(this.records[i]); - } - } - } - for (var i = 0; i < this.summary.length; i++) { - if ($.inArray(this.summary[i].recid, recid) != -1) { - if (returnIndex === true) { - recs.push(i); - } else { - recs.push(this.summary[i]); - } - } - } - return recs; - } else { - for (var i = 0; i < this.records.length; i++) { - if (this.records[i].recid == recid) { - if (returnIndex === true) return i; else return this.records[i]; - } - } - // search summary - for (var i = 0; i < this.summary.length; i++) { - if (this.summary[i].recid == recid) { - if (returnIndex === true) return i; else return this.summary[i]; - } + var middle = this.get(id, true); + this.items = this.items.slice(0, middle).concat([it], this.items.slice(middle)); } - return null; + this.refresh(it.id); + this.resize(); } }, remove: function () { var removed = 0; for (var a = 0; a < arguments.length; a++) { - for (var r = this.records.length-1; r >= 0; r--) { - if (this.records[r].recid == arguments[a]) { this.records.splice(r, 1); removed++; } - } - for (var r = this.summary.length-1; r >= 0; r--) { - if (this.summary[r].recid == arguments[a]) { this.summary.splice(r, 1); removed++; } - } - } - var url = (typeof this.url != 'object' ? this.url : this.url.get); - if (!url) { - this.localSort(false, true); - this.localSearch(); + var it = this.get(arguments[a]); + if (!it || String(arguments[a]).indexOf(':') != -1) continue; + removed++; + // remove from screen + $(this.box).find('#tb_'+ this.name +'_item_'+ w2utils.escapeId(it.id)).remove(); + // remove from array + var ind = this.get(it.id, true); + if (ind != null) this.items.splice(ind, 1); } - this.refresh(); + this.resize(); return removed; }, - addColumn: function (before, columns) { - var added = 0; - if (arguments.length == 1) { - columns = before; - before = this.columns.length; - } else { - if (typeof before == 'string') before = this.getColumn(before, true); - if (before == null) before = this.columns.length; - } - if (!$.isArray(columns)) columns = [columns]; - for (var i = 0; i < columns.length; i++) { - this.columns.splice(before, 0, columns[i]); - // if column is searchable, add search field - if (columns[i].searchable) { - var stype = columns[i].searchable; - var attr = ''; - if (columns[i].searchable === true) { stype = 'text'; attr = 'size="20"'; } - this.addSearch({ field: columns[i].field, caption: columns[i].caption, type: stype, attr: attr }); - } - before++; - added++; - } - this.refresh(); - return added; - }, - - removeColumn: function () { - var removed = 0; - for (var a = 0; a < arguments.length; a++) { - for (var r = this.columns.length-1; r >= 0; r--) { - if (this.columns[r].field == arguments[a]) { - if (this.columns[r].searchable) this.removeSearch(arguments[a]); - this.columns.splice(r, 1); - removed++; - } - } - } - this.refresh(); - return removed; + set: function (id, newOptions) { + var item = this.get(id); + if (item == null) return false; + $.extend(item, newOptions); + this.refresh(String(id).split(':')[0]); + return true; }, - getColumn: function (field, returnIndex) { - // no arguments - return fields of all columns + get: function (id, returnIndex) { if (arguments.length === 0) { - var ret = []; - for (var i = 0; i < this.columns.length; i++) ret.push(this.columns[i].field); - return ret; + var all = []; + for (var i1 = 0; i1 < this.items.length; i1++) if (this.items[i1].id != null) all.push(this.items[i1].id); + return all; } - // find column - for (var i = 0; i < this.columns.length; i++) { - if (this.columns[i].field == field) { - if (returnIndex === true) return i; else return this.columns[i]; + var tmp = String(id).split(':'); + for (var i2 = 0; i2 < this.items.length; i2++) { + var it = this.items[i2]; + // find a menu item + if (['menu', 'menu-radio', 'menu-check'].indexOf(it.type) != -1 && tmp.length == 2 && it.id == tmp[0]) { + for (var i = 0; i < it.items.length; i++) { + var item = it.items[i]; + if (item.id == tmp[1] || (item.id == null && item.text == tmp[1])) { + if (returnIndex == true) return i; else return item; + } + } + } else if (it.id == tmp[0]) { + if (returnIndex == true) return i2; else return it; } } return null; }, - toggleColumn: function () { - var effected = 0; + show: function () { + var obj = this; + var items = 0; + var tmp = []; for (var a = 0; a < arguments.length; a++) { - for (var r = this.columns.length-1; r >= 0; r--) { - var col = this.columns[r]; - if (col.field == arguments[a]) { - col.hidden = !col.hidden; - effected++; - } - } + var it = this.get(arguments[a]); + if (!it) continue; + items++; + it.hidden = false; + tmp.push(String(arguments[a]).split(':')[0]); } - this.refreshBody(); - this.resizeRecords(); - return effected; + setTimeout(function () { for (var t=0; t<tmp.length; t++) obj.refresh(tmp[t]); obj.resize(); }, 15); // needs timeout + return items; }, - showColumn: function () { - var shown = 0; + hide: function () { + var obj = this; + var items = 0; + var tmp = []; for (var a = 0; a < arguments.length; a++) { - for (var r = this.columns.length-1; r >= 0; r--) { - var col = this.columns[r]; - if (col.gridMinWidth) delete col.gridMinWidth; - if (col.field == arguments[a] && col.hidden !== false) { - col.hidden = false; - shown++; - } - } + var it = this.get(arguments[a]); + if (!it) continue; + items++; + it.hidden = true; + tmp.push(String(arguments[a]).split(':')[0]); } - this.refreshBody(); - this.resizeRecords(); - return shown; + setTimeout(function () { for (var t=0; t<tmp.length; t++) { obj.refresh(tmp[t]); obj.tooltipHide(tmp[t]); } obj.resize(); }, 15); // needs timeout + return items; }, - hideColumn: function () { - var hidden = 0; + enable: function () { + var obj = this; + var items = 0; + var tmp = []; for (var a = 0; a < arguments.length; a++) { - for (var r = this.columns.length-1; r >= 0; r--) { - var col = this.columns[r]; - if (col.field == arguments[a] && col.hidden !== true) { - col.hidden = true; - hidden++; - } - } + var it = this.get(arguments[a]); + if (!it) continue; + items++; + it.disabled = false; + tmp.push(String(arguments[a]).split(':')[0]); } - this.refreshBody(); - this.resizeRecords(); - return hidden; + setTimeout(function () { for (var t=0; t<tmp.length; t++) obj.refresh(tmp[t]); }, 15); // needs timeout + return items; }, - addSearch: function (before, search) { - var added = 0; - if (arguments.length == 1) { - search = before; - before = this.searches.length; - } else { - if (typeof before == 'string') before = this.getSearch(before, true); - if (before == null) before = this.searches.length; - } - if (!$.isArray(search)) search = [search]; - for (var i = 0; i < search.length; i++) { - this.searches.splice(before, 0, search[i]); - before++; - added++; + disable: function () { + var obj = this; + var items = 0; + var tmp = []; + for (var a = 0; a < arguments.length; a++) { + var it = this.get(arguments[a]); + if (!it) continue; + items++; + it.disabled = true; + tmp.push(String(arguments[a]).split(':')[0]); } - this.searchClose(); - return added; + setTimeout(function () { for (var t=0; t<tmp.length; t++) { obj.refresh(tmp[t]); obj.tooltipHide(tmp[t]); } }, 15); // needs timeout + return items; }, - removeSearch: function () { - var removed = 0; + check: function () { + var obj = this; + var items = 0; + var tmp = []; for (var a = 0; a < arguments.length; a++) { - for (var r = this.searches.length-1; r >= 0; r--) { - if (this.searches[r].field == arguments[a]) { this.searches.splice(r, 1); removed++; } - } + var it = this.get(arguments[a]); + if (!it || String(arguments[a]).indexOf(':') != -1) continue; + items++; + it.checked = true; + tmp.push(String(arguments[a]).split(':')[0]); } - this.searchClose(); - return removed; - }, - - getSearch: function (field, returnIndex) { - // no arguments - return fields of all searches - if (arguments.length === 0) { - var ret = []; - for (var i = 0; i < this.searches.length; i++) ret.push(this.searches[i].field); - return ret; - } - // find search - for (var i = 0; i < this.searches.length; i++) { - if (this.searches[i].field == field) { - if (returnIndex === true) return i; else return this.searches[i]; - } - } - return null; + setTimeout(function () { for (var t=0; t<tmp.length; t++) obj.refresh(tmp[t]); }, 15); // needs timeout + return items; }, - toggleSearch: function () { - var effected = 0; + uncheck: function () { + var obj = this; + var items = 0; + var tmp = []; for (var a = 0; a < arguments.length; a++) { - for (var r = this.searches.length-1; r >= 0; r--) { - if (this.searches[r].field == arguments[a]) { - this.searches[r].hidden = !this.searches[r].hidden; - effected++; - } + var it = this.get(arguments[a]); + if (!it || String(arguments[a]).indexOf(':') != -1) continue; + // remove overlay + if (['menu', 'menu-radio', 'menu-check', 'drop', 'color', 'text-color'].indexOf(it.type) != -1 && it.checked) { + // hide overlay + setTimeout(function () { + var el = $('#tb_'+ obj.name +'_item_'+ w2utils.escapeId(it.id)); + el.w2overlay({ name: obj.name }); + }, 1); } + items++; + it.checked = false; + tmp.push(String(arguments[a]).split(':')[0]); } - this.searchClose(); - return effected; + setTimeout(function () { for (var t=0; t<tmp.length; t++) obj.refresh(tmp[t]); }, 15); // needs timeout + return items; }, - showSearch: function () { - var shown = 0; - for (var a = 0; a < arguments.length; a++) { - for (var r = this.searches.length-1; r >= 0; r--) { - if (this.searches[r].field == arguments[a] && this.searches[r].hidden !== false) { - this.searches[r].hidden = false; - shown++; - } + click: function (id, event) { + var obj = this; + // click on menu items + var tmp = String(id).split(':'); + var it = this.get(tmp[0]); + if (tmp.length > 1) { + var subItem = this.get(id); + if (subItem && !subItem.disabled) { + obj.menuClick({ name: obj.name, item: it, subItem: subItem, originalEvent: event }); } + return; } - this.searchClose(); - return shown; - }, - - hideSearch: function () { - var hidden = 0; - for (var a = 0; a < arguments.length; a++) { - for (var r = this.searches.length-1; r >= 0; r--) { - if (this.searches[r].field == arguments[a] && this.searches[r].hidden !== true) { - this.searches[r].hidden = true; - hidden++; - } + if (it && !it.disabled) { + // event before + var edata = this.trigger({ phase: 'before', type: 'click', target: (id != null ? id : this.name), + item: it, object: it, originalEvent: event }); + if (tmp[0] === 'zoomin' || tmp[0] === 'zoomout') { + return; } - } - this.searchClose(); - return hidden; - }, + if (edata.isCancelled === true) return; - getSearchData: function (field) { - for (var i = 0; i < this.searchData.length; i++) { - if (this.searchData[i].field == field) return this.searchData[i]; - } - return null; - }, + var btn = '#tb_'+ this.name +'_item_'+ w2utils.escapeId(it.id) +' table.w2ui-button'; + $(btn).removeClass('down'); // need to requery at the moment -- as well as elsewhere in this function - localSort: function (silent, noResetRefresh) { - var url = (typeof this.url != 'object' ? this.url : this.url.get); - if (url) { - console.log('ERROR: grid.localSort can only be used on local data source, grid.url should be empty.'); - return; - } - if ($.isEmptyObject(this.sortData)) return; - var time = (new Date()).getTime(); - var obj = this; - // process date fields - obj.selectionSave(); - obj.prepareData(); - if (!noResetRefresh) { - obj.reset(); - } - // process sortData - for (var i = 0; i < this.sortData.length; i++) { - var column = this.getColumn(this.sortData[i].field); - if (!column) return; - if (typeof column.render == 'string') { - if (['date', 'age'].indexOf(column.render.split(':')[0]) != -1) { - this.sortData[i]['field_'] = column.field + '_'; - } - if (['time'].indexOf(column.render.split(':')[0]) != -1) { - this.sortData[i]['field_'] = column.field + '_'; + if (it.type == 'radio') { + for (var i = 0; i < this.items.length; i++) { + var itt = this.items[i]; + if (itt == null || itt.id == it.id || itt.type !== 'radio') continue; + if (itt.group == it.group && itt.checked) { + itt.checked = false; + this.refresh(itt.id); + } } + it.checked = true; + $(btn).addClass('checked'); } - } - // prepare paths and process sort - preparePaths(); - this.records.sort(function (a, b) { - return compareRecordPaths(a, b); - }); - cleanupPaths(); + if (['menu', 'menu-radio', 'menu-check', 'drop', 'color', 'text-color'].indexOf(it.type) != -1) { + obj.tooltipHide(id); + if (it.checked) { + // if it was already checked, second click will hide it + setTimeout(function () { + // hide overlay + var el = $('#tb_'+ obj.name +'_item_'+ w2utils.escapeId(it.id)); + el.w2overlay({ name: obj.name }); + // uncheck + it.checked = false; + obj.refresh(it.id); + }, 1); - obj.selectionRestore(noResetRefresh); - time = (new Date()).getTime() - time; - if (silent !== true && obj.show.statusSort) { - setTimeout(function () { - obj.status(w2utils.lang('Sorting took') + ' ' + time/1000 + ' ' + w2utils.lang('sec')); - }, 10); - } - return time; + } else { - // grab paths before sorting for efficiency and because calling obj.get() - // while sorting 'obj.records' is unsafe, at least on webkit - function preparePaths() { - for (var i = 0; i < obj.records.length; i++) { - var rec = obj.records[i]; - if (rec.w2ui && rec.w2ui.parent_recid != null) - rec.w2ui._path = getRecordPath(rec); + // show overlay + setTimeout(function () { + var el = $('#tb_'+ obj.name +'_item_'+ w2utils.escapeId(it.id)); + if (!$.isPlainObject(it.overlay)) it.overlay = {}; + var left = (el.width() - 50) / 2; + if (left > 19) left = 19; + if (it.type == 'drop') { + el.w2overlay(it.html, $.extend({ name: obj.name, left: left, top: 3 }, it.overlay, { + onHide: function (event) { + hideDrop(); + } + })); + } + if (['menu', 'menu-radio', 'menu-check'].indexOf(it.type) != -1) { + var menuType = 'normal'; + if (it.type == 'menu-radio') { + menuType = 'radio'; + it.items.forEach(function (item) { + if (it.selected == item.id) item.checked = true; else item.checked = false; + }); + } + if (it.type == 'menu-check') { + menuType = 'check'; + it.items.forEach(function (item) { + if ($.isArray(it.selected) && it.selected.indexOf(item.id) != -1) item.checked = true; else item.checked = false; + }); + } + el.w2menu($.extend({ name: obj.name, items: it.items, left: left, top: 3 }, it.overlay, { + type: menuType, + select: function (event) { + obj.menuClick({ name: obj.name, item: it, subItem: event.item, originalEvent: event.originalEvent, keepOpen: event.keepOpen }); + }, + onHide: function (event) { + hideDrop(); + } + })); + } + if (['color', 'text-color'].indexOf(it.type) != -1) { + if (it.transparent == null) it.transparent = true; + $(el).w2color({ color: it.color, transparent: it.transparent }, function (color, index) { + if (color != null) { + obj.colorClick({ name: obj.name, item: it, color: color, originalEvent: event.originalEvent }); + } + hideDrop(); + }); + } + function hideDrop(event) { + it.checked = false; + $(btn).removeClass('checked'); + } + }, 1); + } } - } - // cleanup and release memory allocated by preparePaths() - function cleanupPaths() { - for (var i = 0; i < obj.records.length; i++) { - var rec = obj.records[i]; - if (rec.w2ui && rec.w2ui.parent_recid != null) - rec.w2ui._path = null; + if (['check', 'menu', 'menu-radio', 'menu-check', 'drop', 'color', 'text-color'].indexOf(it.type) != -1) { + it.checked = !it.checked; + if (it.checked) { + $(btn).addClass('checked'); + } else { + $(btn).removeClass('checked'); + } } - } - - // compare two paths, from root of tree to given records - function compareRecordPaths(a, b) { - if ((!a.w2ui || a.w2ui.parent_recid == null) && (!b.w2ui || b.w2ui.parent_recid == null)) { - return compareRecords(a, b); // no tree, fast path + // route processing + if (it.route) { + var route = String('/'+ it.route).replace(/\/{2,}/g, '/'); + var info = w2utils.parseRoute(route); + if (info.keys.length > 0) { + for (var k = 0; k < info.keys.length; k++) { + route = route.replace((new RegExp(':'+ info.keys[k].name, 'g')), this.routeData[info.keys[k].name]); + } + } + setTimeout(function () { window.location.hash = route; }, 1); } - var pa = getRecordPath(a); - var pb = getRecordPath(b); - for (var i = 0; i < Math.min(pa.length, pb.length); i++) { - var diff = compareRecords(pa[i], pb[i]); - if (diff !== 0) return diff; // different subpath + if (event && ['button', 'check', 'radio'].indexOf(it.type) != -1) { + // need to refresh toolbar as it might be dynamic + this.tooltipShow(id, event, true); } - if (pa.length > pb.length) return 1; - if (pa.length < pb.length) return -1; - console.log('ERROR: two paths should not be equal.'); - return 0; + // event after + this.trigger($.extend(edata, { phase: 'after' })); } + }, - // return an array of all records from root to and including 'rec' - function getRecordPath(rec) { - if (!rec.w2ui || rec.w2ui.parent_recid == null) return [rec]; - if (rec.w2ui._path) - return rec.w2ui._path; - // during actual sort, we should never reach this point - var subrec = obj.get(rec.w2ui.parent_recid); - if (!subrec) { - console.log('ERROR: no parent record: '+rec.w2ui.parent_recid); - return [rec]; - } - return (getRecordPath(subrec).concat(rec)); - } + scroll: function (direction) { + var box = $(this.box); + var obj = this; + var scrollBox = box.find('.w2ui-scroll-wrapper'); + var scrollLeft = scrollBox.scrollLeft(); + var width1, width2, scroll; - // compare two records according to sortData and finally recid - function compareRecords(a, b) { - if (a === b) return 0; // optimize, same object - for (var i = 0; i < obj.sortData.length; i++) { - var fld = obj.sortData[i].field; - if (obj.sortData[i].field_) fld = obj.sortData[i].field_; - var aa = a[fld]; - var bb = b[fld]; - if (String(fld).indexOf('.') != -1) { - aa = obj.parseField(a, fld); - bb = obj.parseField(b, fld); - } - var col = obj.getColumn(fld); - if (col && col.editable != null) { // for drop editable fields and drop downs - if ($.isPlainObject(aa) && aa.text) aa = aa.text; - if ($.isPlainObject(bb) && bb.text) bb = bb.text; - } - var ret = compareCells(aa, bb, i, obj.sortData[i].direction); - if (ret !== 0) return ret; - } - // break tie for similar records, - // required to have consistent ordering for tree paths - var ret = compareCells(a.recid, b.recid, -1, 'asc'); - if (ret !== 0) return ret; - return 0; - } + switch (direction) { + case 'left': + width1 = scrollBox.outerWidth(); + width2 = scrollBox.find(':first').outerWidth(); + scroll = scrollLeft - width1 + 50; // 35 is width of both button + if (scroll <= 0) scroll = 0; + scrollBox.animate({ scrollLeft: scroll }, 300); + break; - // compare two values, aa and bb, producing consistent ordering - function compareCells(aa, bb, i, direction) { - // if both objects are strictly equal, we're done - if (aa === bb) - return 0; - // all nulls, empty and undefined on bottom - if ((aa == null || aa === "") && (bb != null && bb !== "")) - return 1; - if ((aa != null && aa !== "") && (bb == null || bb === "")) - return -1; - var dir = (direction == 'asc') ? 1 : -1; - // for different kind of objects, sort by object type - if (typeof aa != typeof bb) - return (typeof aa > typeof bb) ? dir : -dir; - // for different kind of classes, sort by classes - if (aa.constructor.name != bb.constructor.name) - return (aa.constructor.name > bb.constructor.name) ? dir : -dir; - // if we're dealing with non-null objects, call valueOf(). - // this mean that Date() or custom objects will compare properly. - if (aa && typeof aa == 'object') - aa = aa.valueOf(); - if (bb && typeof bb == 'object') - bb = bb.valueOf(); - // if we're still dealing with non-null objects that have - // a useful Object => String conversion, convert to string. - var defaultToString = {}.toString; - if (aa && typeof aa == 'object' && aa.toString != defaultToString) - aa = String(aa); - if (bb && typeof bb == 'object' && bb.toString != defaultToString) - bb = String(bb); - // do case-insensitive string comparaison - if (typeof aa == 'string') - aa = $.trim(aa.toLowerCase()); - if (typeof bb == 'string') - bb = $.trim(bb.toLowerCase()); - // compare both objects - if (aa > bb) - return dir; - if (aa < bb) - return -dir; - return 0; + case 'right': + width1 = scrollBox.outerWidth(); + width2 = scrollBox.find(':first').outerWidth(); + scroll = scrollLeft + width1 - 50; // 35 is width of both button + if (scroll >= width2 - width1) scroll = width2 - width1; + scrollBox.animate({ scrollLeft: scroll }, 300); + break; } + setTimeout(function () { obj.resize(); }, 350); }, - localSearch: function (silent) { - var url = (typeof this.url != 'object' ? this.url : this.url.get); - if (url) { - console.log('ERROR: grid.localSearch can only be used on local data source, grid.url should be empty.'); - return; - } + render: function (box) { var time = (new Date()).getTime(); - var obj = this; - var defaultToString = {}.toString; - var duplicateMap = {}; - this.total = this.records.length; - // mark all records as shown - this.last.searchIds = []; - // prepare date/time fields - this.prepareData(); - // hide records that did not match - if (this.searchData.length > 0 && !url) { - this.total = 0; - for (var i = 0; i < this.records.length; i++) { - var rec = this.records[i]; - var match = searchRecord(rec); - if (match) { - if (rec && rec.w2ui) - addParent(rec.w2ui.parent_recid); - this.last.searchIds.push(i); - } + // event before + var edata = this.trigger({ phase: 'before', type: 'render', target: this.name, box: box }); + if (edata.isCancelled === true) return; + + if (box != null) { + if ($(this.box).find('> table #tb_'+ this.name + '_right').length > 0) { + $(this.box) + .removeAttr('name') + .removeClass('w2ui-reset w2ui-toolbar') + .html(''); } - this.total = this.last.searchIds.length; + this.box = box; } - time = (new Date()).getTime() - time; - if (silent !== true && obj.show.statusSearch) { - setTimeout(function () { - obj.status(w2utils.lang('Search took') + ' ' + time/1000 + ' ' + w2utils.lang('sec')); - }, 10); + if (!this.box) return; + // render all buttons + var html = '<div class="w2ui-scroll-wrapper" onmousedown="var el=w2ui[\''+ this.name +'\']; if (el) el.resize();" onscroll="var el=w2ui[\'editbar\']; if (el) el.resize();">'+ + '<table cellspacing="0" cellpadding="0" width="100%"><tbody>'+ + '<tr>'; + for (var i = 0; i < this.items.length; i++) { + var it = this.items[i]; + if (it == null) continue; + if (it.id == null) it.id = "item_" + i; + if (it.type == 'spacer') { + html += '<td width="100%" id="tb_'+ this.name +'_item_'+ it.id +'" align="right"></td>'; + } else { + html += '<td id="tb_'+ this.name + '_item_'+ it.id +'" style="'+ (it.hidden ? 'display: none' : '') +'" '+ + ' class="'+ (it.disabled ? 'disabled' : '') +'" valign="middle">'+ + '</td>'; + } } - return time; + html += '<td width="100%" id="tb_'+ this.name +'_right" align="right">'+ this.right +'</td>'; + html += '</tr>'+ + '</tbody></table></div>'+ + '<div class="w2ui-scroll-left" onmousedown="event.preventDefault()" onclick="if($(this).closest(\'#toolbar-up\').length>0 || $(\'#toolbar-down\').width() > 768){var el=w2ui[\''+ this.name +'\']; if (el) el.scroll(\'left\');}"></div>'+ + '<div class="w2ui-scroll-right" onmousedown="event.preventDefault()" onclick="if($(this).closest(\'#toolbar-up\').length>0 || $(\'#toolbar-down\').width() > 768){var el=w2ui[\''+ this.name +'\']; if (el) el.scroll(\'right\');}"></div>'; + $(this.box) + .attr('name', this.name) + .addClass('w2ui-reset w2ui-toolbar') + .html(html); + if ($(this.box).length > 0) $(this.box)[0].style.cssText += this.style; + // refresh all + this.refresh(); + this.resize(); + // event after + this.trigger($.extend(edata, { phase: 'after' })); + return (new Date()).getTime() - time; + }, - // check if a record (or one of its closed children) matches the search data - function searchRecord(rec) { - var fl = 0; - for (var j = 0; j < obj.searchData.length; j++) { - var sdata = obj.searchData[j]; - var search = obj.getSearch(sdata.field); - if (sdata == null) continue; - if (search == null) search = { field: sdata.field, type: sdata.type }; - var val1b = obj.parseField(rec, search.field); - var val1 = (val1b !== null && val1b !== undefined && - (typeof val1b != "object" || val1b.toString != defaultToString)) ? - String(val1b).toLowerCase() : ""; // do not match a bogus string - if (sdata.value != null) { - if (!$.isArray(sdata.value)) { - var val2 = String(sdata.value).toLowerCase(); - } else { - var val2 = sdata.value[0]; - var val3 = sdata.value[1]; - } - } - switch (sdata.operator) { - case 'is': - if (obj.parseField(rec, search.field) == sdata.value) fl++; // do not hide record - else if (search.type == 'date') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatDate(tmp, 'yyyy-mm-dd'); - var val2 = w2utils.formatDate(w2utils.isDate(val2, w2utils.settings.dateFormat, true), 'yyyy-mm-dd'); - if (val1 == val2) fl++; - } - else if (search.type == 'time') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatTime(tmp, 'hh24:mi'); - var val2 = w2utils.formatTime(val2, 'hh24:mi'); - if (val1 == val2) fl++; - } - else if (search.type == 'datetime') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatDateTime(tmp, 'yyyy-mm-dd|hh24:mm:ss'); - var val2 = w2utils.formatDateTime(w2utils.isDateTime(val2, w2utils.settings.datetimeFormat, true), 'yyyy-mm-dd|hh24:mm:ss'); - if (val1 == val2) fl++; - } - break; - case 'between': - if (['int', 'float', 'money', 'currency', 'percent'].indexOf(search.type) != -1) { - if (parseFloat(obj.parseField(rec, search.field)) >= parseFloat(val2) && parseFloat(obj.parseField(rec, search.field)) <= parseFloat(val3)) fl++; - } - else if (search.type == 'date') { - var val1 = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val2 = w2utils.isDate(val2, w2utils.settings.dateFormat, true); - var val3 = w2utils.isDate(val3, w2utils.settings.dateFormat, true); - if (val3 != null) val3 = new Date(val3.getTime() + 86400000); // 1 day - if (val1 >= val2 && val1 < val3) fl++; - } - else if (search.type == 'time') { - var val1 = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val2 = w2utils.isTime(val2, true); - var val3 = w2utils.isTime(val3, true); - val2 = (new Date()).setHours(val2.hours, val2.minutes, val2.seconds ? val2.seconds : 0, 0); - val3 = (new Date()).setHours(val3.hours, val3.minutes, val3.seconds ? val3.seconds : 0, 0); - if (val1 >= val2 && val1 < val3) fl++; - } - else if (search.type == 'datetime') { - var val1 = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val2 = w2utils.isDateTime(val2, w2utils.settings.datetimeFormat, true); - var val3 = w2utils.isDateTime(val3, w2utils.settings.datetimeFormat, true); - if (val3) val3 = new Date(val3.getTime() + 86400000); // 1 day - if (val1 >= val2 && val1 < val3) fl++; - } - break; - case 'less': - if (['int', 'float', 'money', 'currency', 'percent'].indexOf(search.type) != -1) { - if (parseFloat(obj.parseField(rec, search.field)) <= parseFloat(sdata.value)) fl++; - } - else if (search.type == 'date') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatDate(tmp, 'yyyy-mm-dd'); - var val2 = w2utils.formatDate(w2utils.isDate(val2, w2utils.settings.dateFormat, true), 'yyyy-mm-dd'); - if (val1 <= val2) fl++; - } - else if (search.type == 'time') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatTime(tmp, 'hh24:mi'); - var val2 = w2utils.formatTime(val2, 'hh24:mi'); - if (val1 <= val2) fl++; - } - else if (search.type == 'datetime') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatDateTime(tmp, 'yyyy-mm-dd|hh24:mm:ss'); - var val2 = w2utils.formatDateTime(w2utils.isDateTime(val2, w2utils.settings.datetimeFormat, true), 'yyyy-mm-dd|hh24:mm:ss'); - if ( (val1.length == val2.length) && (val1 <= val2) ) fl++; - } - break; - case 'more': - if (['int', 'float', 'money', 'currency', 'percent'].indexOf(search.type) != -1) { - if (parseFloat(obj.parseField(rec, search.field)) >= parseFloat(sdata.value)) fl++; - } - else if (search.type == 'date') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatDate(tmp, 'yyyy-mm-dd'); - var val2 = w2utils.formatDate(w2utils.isDate(val2, w2utils.settings.dateFormat, true), 'yyyy-mm-dd'); - if (val1 >= val2) fl++; - } - else if (search.type == 'time') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatTime(tmp, 'hh24:mi'); - var val2 = w2utils.formatTime(val2, 'hh24:mi'); - if (val1 >= val2) fl++; - } - else if (search.type == 'datetime') { - var tmp = (obj.parseField(rec, search.field + '_') instanceof Date ? obj.parseField(rec, search.field + '_') : obj.parseField(rec, search.field)); - var val1 = w2utils.formatDateTime(tmp, 'yyyy-mm-dd|hh24:mm:ss'); - var val2 = w2utils.formatDateTime(w2utils.isDateTime(val2, w2utils.settings.datetimeFormat, true), 'yyyy-mm-dd|hh24:mm:ss'); - if ( (val1.length == val2.length) && (val1 >= val2) ) fl++; - } - break; - case 'in': - var tmp = sdata.value; - if (sdata.svalue) tmp = sdata.svalue; - if (tmp.indexOf(w2utils.isFloat(val1) ? parseFloat(val1) : val1) !== -1) fl++; - if (tmp.indexOf(w2utils.isFloat(val1b) ? parseFloat(val1b) : val1b) !== -1) fl++; - break; - case 'not in': - var tmp = sdata.value; - if (sdata.svalue) tmp = sdata.svalue; - if (tmp.indexOf(w2utils.isFloat(val1) ? parseFloat(val1) : val1) == -1) fl++; - if (tmp.indexOf(w2utils.isFloat(val1b) ? parseFloat(val1b) : val1b) == -1) fl++; - break; - case 'begins': - case 'begins with': // need for back compatib. - if (val1.indexOf(val2) === 0) fl++; // do not hide record - break; - case 'contains': - if (val1.indexOf(val2) >= 0) fl++; // do not hide record - break; - case 'null': - if (obj.parseField(rec, search.field) == null) fl++; // do not hide record - break; - case 'not null': - if (obj.parseField(rec, search.field) != null) fl++; // do not hide record - break; - case 'ends': - case 'ends with': // need for back compatib. - var lastIndex = val1.lastIndexOf(val2); - if (lastIndex !== -1 && lastIndex == val1.length - val2.length) fl++; // do not hide record - break; - } - } - if ((obj.last.logic == 'OR' && fl !== 0) || - (obj.last.logic == 'AND' && fl == obj.searchData.length)) - return true; - if (rec.w2ui && rec.w2ui.children && rec.w2ui.expanded !== true) { - // there are closed children, search them too. - for (var r = 0; r < rec.w2ui.children.length; r++) { - var subRec = rec.w2ui.children[r]; - if (searchRecord(subRec)) - return true; - } - } - return false; - } - - // add parents nodes recursively - function addParent(recid) { - if (recid === undefined) - return; - if (duplicateMap[recid]) - return; // already visited - duplicateMap[recid] = true; - var i = obj.get(recid, true); - if (i == null) - return; - if ($.inArray(i, obj.last.searchIds) != -1) - return; - var rec = obj.records[i]; - if (rec && rec.w2ui) - addParent(rec.w2ui.parent_recid); - obj.last.searchIds.push(i); - } - }, - - getRangeData: function (range, extra) { - var rec1 = this.get(range[0].recid, true); - var rec2 = this.get(range[1].recid, true); - var col1 = range[0].column; - var col2 = range[1].column; - - var res = []; - if (col1 == col2) { // one row - for (var r = rec1; r <= rec2; r++) { - var record = this.records[r]; - var dt = record[this.columns[col1].field] || null; - if (extra !== true) { - res.push(dt); - } else { - res.push({ data: dt, column: col1, index: r, record: record }); - } - } - } else if (rec1 == rec2) { // one line - var record = this.records[rec1]; - for (var i = col1; i <= col2; i++) { - var dt = record[this.columns[i].field] || null; - if (extra !== true) { - res.push(dt); - } else { - res.push({ data: dt, column: i, index: rec1, record: record }); - } - } - } else { - for (var r = rec1; r <= rec2; r++) { - var record = this.records[r]; - res.push([]); - for (var i = col1; i <= col2; i++) { - var dt = record[this.columns[i].field]; - if (extra !== true) { - res[res.length-1].push(dt); - } else { - res[res.length-1].push({ data: dt, column: i, index: r, record: record }); - } - } - } - } - return res; - }, - - addRange: function (ranges) { - var added = 0; - if (this.selectType == 'row') return added; - if (!$.isArray(ranges)) ranges = [ranges]; - // if it is selection - for (var i = 0; i < ranges.length; i++) { - if (typeof ranges[i] != 'object') ranges[i] = { name: 'selection' }; - if (ranges[i].name == 'selection') { - if (this.show.selectionBorder === false) continue; - var sel = this.getSelection(); - if (sel.length === 0) { - this.removeRange('selection'); - continue; - } else { - var first = sel[0]; - var last = sel[sel.length-1]; - } - } else { // other range - var first = ranges[i].range[0]; - var last = ranges[i].range[1]; - } - if (first) { - var rg = { - name: ranges[i].name, - range: [{ recid: first.recid, column: first.column }, { recid: last.recid, column: last.column }], - style: ranges[i].style || '' - }; - // add range - var ind = false; - for (var j = 0; j < this.ranges.length; j++) if (this.ranges[j].name == ranges[i].name) { ind = j; break; } - if (ind !== false) { - this.ranges[ind] = rg; - } else { - this.ranges.push(rg); - } - added++; - } - } - this.refreshRanges(); - return added; - }, - - removeRange: function () { - var removed = 0; - for (var a = 0; a < arguments.length; a++) { - var name = arguments[a]; - $('#grid_'+ this.name +'_'+ name).remove(); - $('#grid_'+ this.name +'_f'+ name).remove(); - for (var r = this.ranges.length-1; r >= 0; r--) { - if (this.ranges[r].name == name) { - this.ranges.splice(r, 1); - removed++; - } - } - } - return removed; - }, - - refreshRanges: function () { - if (this.ranges.length === 0) return; - var obj = this; + refresh: function (id) { var time = (new Date()).getTime(); - var rec1 = $('#grid_'+ this.name +'_frecords'); - var rec2 = $('#grid_'+ this.name +'_records'); - for (var i = 0; i < this.ranges.length; i++) { - var rg = this.ranges[i]; - var first = rg.range[0]; - var last = rg.range[1]; - if (first.index == null) first.index = this.get(first.recid, true); - if (last.index == null) last.index = this.get(last.recid, true); - var td1 = $('#grid_'+ this.name +'_rec_'+ w2utils.escapeId(first.recid) + ' td[col="'+ first.column +'"]'); - var td2 = $('#grid_'+ this.name +'_rec_'+ w2utils.escapeId(last.recid) + ' td[col="'+ last.column +'"]'); - var td1f = $('#grid_'+ this.name +'_frec_'+ w2utils.escapeId(first.recid) + ' td[col="'+ first.column +'"]'); - var td2f = $('#grid_'+ this.name +'_frec_'+ w2utils.escapeId(last.recid) + ' td[col="'+ last.column +'"]'); - var _lastColumn = last.column; - // adjustment due to column virtual scroll - if (first.column < this.last.colStart && last.column > this.last.colStart) { - td1 = $('#grid_'+ this.name +'_rec_'+ w2utils.escapeId(first.recid) + ' td[col="start"]'); - } - if (first.column < this.last.colEnd && last.column > this.last.colEnd) { - _lastColumn = '"end"'; - td2 = $('#grid_'+ this.name +'_rec_'+ w2utils.escapeId(last.recid) + ' td[col="end"]'); - } - // if virtual scrolling kicked in - var index_top = parseInt($('#grid_'+ this.name +'_rec_top').next().attr('index')); - var index_bottom = parseInt($('#grid_'+ this.name +'_rec_bottom').prev().attr('index')); - var index_ftop = parseInt($('#grid_'+ this.name +'_frec_top').next().attr('index')); - var index_fbottom = parseInt($('#grid_'+ this.name +'_frec_bottom').prev().attr('index')); - if (td1.length === 0 && first.index < index_top && last.index > index_top) { - td1 = $('#grid_'+ this.name +'_rec_top').next().find('td[col='+ first.column +']'); - } - if (td2.length === 0 && last.index > index_bottom && first.index < index_bottom) { - td2 = $('#grid_'+ this.name +'_rec_bottom').prev().find('td[col='+ _lastColumn +']'); - } - if (td1f.length === 0 && first.index < index_ftop && last.index > index_ftop) { // frozen - td1f = $('#grid_'+ this.name +'_frec_top').next().find('td[col='+ first.column +']'); - } - if (td2f.length === 0 && last.index > index_fbottom && first.index < index_fbottom) { // frozen - td2f = $('#grid_'+ this.name +'_frec_bottom').prev().find('td[col='+ last.column +']'); - } - - // do not show selection cell if it is editable - var edit = $(this.box).find('#grid_'+ this.name + '_editable'); - var tmp = edit.find('.w2ui-input'); - var tmp1 = tmp.attr('recid'); - var tmp2 = tmp.attr('column'); - if (rg.name == 'selection' && rg.range[0].recid == tmp1 && rg.range[0].column == tmp2) continue; - - // frozen regular columns range - var $range = $('#grid_'+ this.name +'_f'+ rg.name); - if (td1f.length > 0 || td2f.length > 0) { - if ($range.length === 0) { - rec1.append('<div id="grid_'+ this.name +'_f' + rg.name +'" class="w2ui-selection" style="'+ rg.style +'">'+ - (rg.name == 'selection' ? '<div id="grid_'+ this.name +'_resizer" class="w2ui-selection-resizer"></div>' : '')+ - '</div>'); - $range = $('#grid_'+ this.name +'_f'+ rg.name); - } else { - $range.attr('style', rg.style); - $range.find('.w2ui-selection-resizer').show(); - } - if (td2f.length === 0) { - td2f = $('#grid_'+ this.name +'_frec_'+ w2utils.escapeId(last.recid) +' td:last-child'); - if (td2f.length === 0) td2f = $('#grid_'+ this.name +'_frec_bottom td:first-child'); - $range.css('border-right', '0px'); - $range.find('.w2ui-selection-resizer').hide(); - } - if (first.recid != null && last.recid != null && td1f.length > 0 && td2f.length > 0) { - var _left = (td1f.position().left - 1 + rec1.scrollLeft()); - var _top = (td1f.position().top - 1 + rec1.scrollTop()); - $range.show().css({ - left : (_left > 0 ? _left : 0) + 'px', - top : (_top > 0 ? _top : 0) + 'px', - width : (td2f.position().left - td1f.position().left + td2f.width() + 3) + 'px', - height : (td2f.position().top - td1f.position().top + td2f.height() + 3) + 'px' - }); - } else { - $range.hide(); - } - } else { - $range.hide(); - } - // regular columns range - var $range = $('#grid_'+ this.name +'_'+ rg.name); - if (td1.length > 0 || td2.length > 0) { - if ($range.length === 0) { - rec2.append('<div id="grid_'+ this.name +'_' + rg.name +'" class="w2ui-selection" style="'+ rg.style +'">'+ - (rg.name == 'selection' ? '<div id="grid_'+ this.name +'_resizer" class="w2ui-selection-resizer"></div>' : '')+ - '</div>'); - $range = $('#grid_'+ this.name +'_'+ rg.name); - } else { - $range.attr('style', rg.style); - } - if (td1.length === 0) { - td1 = $('#grid_'+ this.name +'_rec_'+ w2utils.escapeId(first.recid) +' td:first-child'); - if (td1.length === 0) td1 = $('#grid_'+ this.name +'_rec_top td:first-child'); - } - if (td2f.length !== 0) { - $range.css('border-left', '0px'); - } - if (first.recid != null && last.recid != null && td1.length > 0 && td2.length > 0) { - var _left = (td1.position().left - 1 + rec2.scrollLeft()); - var _top = (td1.position().top - 1 + rec2.scrollTop()); - $range.show().css({ - left : (_left > 0 ? _left : 0) + 'px', - top : (_top > 0 ? _top : 0) + 'px', - width : (td2.position().left - td1.position().left + td2.width() + 3) + 'px', - height : (td2.position().top - td1.position().top + td2.height() + 3) + 'px' - }); - } else { - $range.hide(); - } - } else { - $range.hide(); + // event before + var edata = this.trigger({ phase: 'before', type: 'refresh', target: (id != null ? id : this.name), item: this.get(id) }); + if (edata.isCancelled === true) return; + // refresh all + if (id == null) { + for (var i = 0; i < this.items.length; i++) { + var it1 = this.items[i]; + if (it1.id == null) it1.id = "item_" + i; + this.refresh(it1.id); } + return; } - - // add resizer events - $(this.box).find('.w2ui-selection-resizer') - .off('mousedown').on('mousedown', mouseStart) - .off('dblclick').on('dblclick', function (event) { - var edata = obj.trigger({ phase: 'before', type: 'resizerDblClick', target: obj.name, originalEvent: event }); - if (edata.isCancelled === true) return; - obj.trigger($.extend(edata, { phase: 'after' })); - }); - var edata = { phase: 'before', type: 'selectionExtend', target: obj.name, originalRange: null, newRange: null }; - - return (new Date()).getTime() - time; - - function mouseStart (event) { - var sel = obj.getSelection(); - obj.last.move = { - type : 'expand', - x : event.screenX, - y : event.screenY, - divX : 0, - divY : 0, - recid : sel[0].recid, - column : sel[0].column, - originalRange : [{ recid: sel[0].recid, column: sel[0].column }, { recid: sel[sel.length-1].recid, column: sel[sel.length-1].column }], - newRange : [{ recid: sel[0].recid, column: sel[0].column }, { recid: sel[sel.length-1].recid, column: sel[sel.length-1].column }] - }; - $(document).off('mousemove', mouseMove).on('mousemove', mouseMove); - $(document).off('mouseup', mouseStop).on('mouseup', mouseStop); - // do not blur grid - event.preventDefault(); + // create or refresh only one item + var it = this.get(id); + if (it == null) return false; + if (typeof it.onRefresh == 'function') { + var edata2 = this.trigger({ phase: 'before', type: 'refresh', target: id, item: it, object: it }); + if (edata2.isCancelled === true) return; } - - function mouseMove (event) { - var mv = obj.last.move; - if (!mv || mv.type != 'expand') return; - mv.divX = (event.screenX - mv.x); - mv.divY = (event.screenY - mv.y); - // find new cell - var recid, column; - var tmp = event.originalEvent.target; - if (tmp.tagName.toUpperCase() != 'TD') tmp = $(tmp).parents('td')[0]; - if ($(tmp).attr('col') != null) column = parseInt($(tmp).attr('col')); - tmp = $(tmp).parents('tr')[0]; - recid = $(tmp).attr('recid'); - // new range - if (mv.newRange[1].recid == recid && mv.newRange[1].column == column) return; - var prevNewRange = $.extend({}, mv.newRange); - mv.newRange = [{ recid: mv.recid, column: mv.column }, { recid: recid, column: column }]; - // event before - edata = obj.trigger($.extend(edata, { originalRange: mv.originalRange, newRange : mv.newRange })); - if (edata.isCancelled === true) { - mv.newRange = prevNewRange; - edata.newRange = prevNewRange; - return; + var el = $(this.box).find('#tb_'+ this.name +'_item_'+ w2utils.escapeId(it.id)); + var html = this.getItemHTML(it); + if (el.length === 0) { + // does not exist - create it + if (it.type == 'spacer') { + html = '<td width="100%" id="tb_'+ this.name +'_item_'+ it.id +'" align="right"></td>'; } else { - // default behavior - obj.removeRange('grid-selection-expand'); - obj.addRange({ - name : 'grid-selection-expand', - range : edata.newRange, - style : 'background-color: rgba(100,100,100,0.1); border: 2px dotted rgba(100,100,100,0.5);' - }); + html = '<td id="tb_'+ this.name + '_item_'+ it.id +'" style="'+ (it.hidden ? 'display: none' : '') +'" '+ + ' class="'+ (it.disabled ? 'disabled' : '') +'" valign="middle">'+ html + + '</td>'; } - } - - function mouseStop (event) { - // default behavior - obj.removeRange('grid-selection-expand'); - delete obj.last.move; - $(document).off('mousemove', mouseMove); - $(document).off('mouseup', mouseStop); - // event after - obj.trigger($.extend(edata, { phase: 'after' })); - } - }, - - select: function () { - if (arguments.length === 0) return 0; - var time = (new Date).getTime(); - var selected = 0; - var sel = this.last.selection; - if (!this.multiSelect) this.selectNone(); - - // event before - var tmp = { phase: 'before', type: 'select', target: this.name }; - if (arguments.length == 1) { - tmp.multiple = false; - if ($.isPlainObject(arguments[0])) { - tmp.recid = arguments[0].recid; - tmp.column = arguments[0].column; + if (this.get(id, true) == this.items.length-1) { + $(this.box).find('#tb_'+ this.name +'_right').before(html); } else { - tmp.recid = arguments[0]; - } - } else { - tmp.multiple = true; - tmp.recids = Array.prototype.slice.call(arguments, 0); - } - var edata = this.trigger(tmp); - if (edata.isCancelled === true) return 0; - - // default action - if (this.selectType == 'row') { - for (var a = 0; a < arguments.length; a++) { - var recid = typeof arguments[a] == 'object' ? arguments[a].recid : arguments[a]; - var index = this.get(recid, true); - if (index == null) continue; - var recEl1 = null; - var recEl2 = null; - if (this.searchData.length !== 0 || (index + 1 >= this.last.range_start && index + 1 <= this.last.range_end)) { - recEl1 = $('#grid_'+ this.name +'_frec_'+ w2utils.escapeId(recid)); - recEl2 = $('#grid_'+ this.name +'_rec_'+ w2utils.escapeId(recid)); - } - if (this.selectType == 'row') { - if (sel.indexes.indexOf(index) != -1) continue; - sel.indexes.push(index); - if (recEl1 && recEl2) { - recEl1.addClass('w2ui-selected').data('selected', 'yes').find('.w2ui-col-number').addClass('w2ui-row-selected'); - recEl2.addClass('w2ui-selected').data('selected', 'yes').find('.w2ui-col-number').addClass('w2ui-row-selected'); - recEl1.find('.w2ui-grid-select-check').prop("checked", true); - } - selected++; - } + $(this.box).find('#tb_'+ this.name +'_item_'+ w2utils.escapeId(this.items[parseInt(this.get(id, true))+1].id)).before(html); } } else { - // normalize for performance - var new_sel = {}; - for (var a = 0; a < arguments.length; a++) { - var recid = typeof arguments[a] == 'object' ? arguments[a].recid : arguments[a]; - var column = typeof arguments[a] == 'object' ? arguments[a].column : null; - new_sel[recid] = new_sel[recid] || []; - if ($.isArray(column)) { - new_sel[recid] = column; - } else if (w2utils.isInt(column)) { - new_sel[recid].push(column); - } else { - for (var i = 0; i < this.columns.length; i++) { if (this.columns[i].hidden) continue; new_sel[recid].push(parseInt(i)); } - } - } - // add all - var col_sel = []; - for (var recid in new_sel) { - var index = this.get(recid, true); - if (index == null) continue; - var recEl1 = null; - var recEl2 = null; - if (index + 1 >= this.last.range_start && index + 1 <= this.last.range_end) { - recEl1 = $('#grid_'+ this.name +'_rec_'+ w2utils.escapeId(recid)); - recEl2 = $('#grid_'+ this.name +'_frec_'+ w2utils.escapeId(recid)); - } - var s = sel.columns[index] || []; - // default action - if (sel.indexes.indexOf(index) == -1) { - sel.indexes.push(index); - } - // anly only those that are new - for (var t = 0; t < new_sel[recid].length; t++) { - if (s.indexOf(new_sel[recid][t]) == -1) s.push(new_sel[recid][t]); - } - s.sort(function(a, b) { return a-b; }); // sort function must be for numerical sort - for (var t = 0; t < new_sel[recid].length; t++) { - var col = new_sel[recid][t]; - if (col_sel.indexOf(col) == -1) col_sel.push(col); ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits