diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index 403ead01b..d823aa4ea 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -106,7 +106,7 @@ The client memory data sources keeps the data in the client memory. The data is ### Server memory data source ($.oc.table.datasource.server) -**TODO:** document this +**TODO:** document this ## Cell processors ($.oc.table.processor) @@ -137,7 +137,7 @@ The drop-down column type can load options from the column configuration or with blue: Blue width: 15% -If the `options` element is not presented in the configuration, the options will be loaded with AJAX. +If the `options` element is not presented in the configuration, the options will be loaded with AJAX. **TODO:** Document the AJAX interface @@ -203,7 +203,7 @@ Columns are defined as array with the `columns` property. The array keys corresp - `title` - `type` (string, checkbox, dropdown, autocomplete) - `width` - sets the column width, can be specified in percents (10%) or pixels (50px). There could be a single column without width specified, it will be stretched to take the available space. -- `readOnly` +- `readOnly` - prevents the cell value from being modified. Default: false. - `options` (for drop-down elements and autocomplete types) - `dependsOn` (from drop-down elements) - validation - defines the column client-side validation rules. See the **Client-side validation** section below. @@ -212,7 +212,7 @@ Columns are defined as array with the `columns` property. The array keys corresp ### table.getDropdownOptions -table.getDropdownOptions - triggered when drop-down options are requested by the client. Parameters: +table.getDropdownOptions - triggered when drop-down options are requested by the client. Parameters: - `$columnName` - specifies the drop-down column name. - `$rowData` - an array containing values of all columns in the table row. @@ -220,7 +220,7 @@ table.getDropdownOptions - triggered when drop-down options are requested by the Example event handler: ``` -$table->bindEvent('table.getDropdownOptions', +$table->bindEvent('table.getDropdownOptions', function ($columnName, $rowData) { if ($columnName == 'state') return ['ca'=>'California', 'wa'=>'Washington']; diff --git a/modules/backend/widgets/table/assets/js/build-min.js b/modules/backend/widgets/table/assets/js/build-min.js index a14197e9a..0485ca775 100644 --- a/modules/backend/widgets/table/assets/js/build-min.js +++ b/modules/backend/widgets/table/assets/js/build-min.js @@ -85,7 +85,8 @@ if(this.options.adding){var addBelowButton=document.createElement('a') addBelowButton.setAttribute('class','btn table-icon add-table-row-below') addBelowButton.setAttribute('data-cmd','record-add-below') this.toolbar.appendChild(addBelowButton) -if(this.navigation.paginationEnabled()||!this.options.rowSorting){addBelowButton.textContent=this.options.btnAddRowLabel}else{addBelowButton.textContent=this.options.btnAddRowBelowLabel +if(this.navigation.paginationEnabled()||!this.options.rowSorting){addBelowButton.textContent=this.options.btnAddRowLabel} +else{addBelowButton.textContent=this.options.btnAddRowBelowLabel var addAboveButton=document.createElement('a') addAboveButton.setAttribute('class','btn table-icon add-table-row-above') addAboveButton.textContent='Add row above' @@ -124,6 +125,7 @@ if(onSuccess) onSuccess() if(totalCount==0) self.addRecord('above',true) +self.$el.trigger('oc.tableUpdateData',[records,totalCount]) self=null})} Table.prototype.updateColumnWidth=function(){var headerCells=this.headerTable.querySelectorAll('th'),dataCells=this.dataTable.querySelectorAll('tr:first-child td') for(var i=0,len=headerCells.length;i0){var self=this this.gotoPage(this.pageIndex-1,function navUpPageSuccess(){self.focusCell('bottom',cellIndex) @@ -502,8 +505,7 @@ if(!isTab&&this.tableObj.activeCellProcessor&&!this.tableObj.activeCellProcessor return var row=this.tableObj.activeCell.parentNode,newIndex=(!ev.shiftKey||isTab)?this.tableObj.activeCell.cellIndex-1:0 var cell=row.children[newIndex] -if(cell) -this.tableObj.focusCell(cell) +if(cell){this.tableObj.focusCell(cell)} else{this.navigateUp(ev,row.children.length-1,isTab)}} Navigation.prototype.navigateRight=function(ev,isTab){if(!this.tableObj.activeCell) return @@ -511,8 +513,7 @@ if(!isTab&&this.tableObj.activeCellProcessor&&!this.tableObj.activeCellProcessor return var row=this.tableObj.activeCell.parentNode,newIndex=!ev.shiftKey?this.tableObj.activeCell.cellIndex+1:row.children.length-1 var cell=row.children[newIndex] -if(cell) -this.tableObj.focusCell(cell) +if(cell){this.tableObj.focusCell(cell)} else{this.navigateDown(ev,0)}} Navigation.prototype.navigateNext=function(ev){if(!this.tableObj.activeCell) return @@ -524,8 +525,7 @@ else this.navigateLeft(ev,true) this.tableObj.stopEvent(ev)} Navigation.prototype.focusCell=function(rowReference,cellIndex){var row=null,tbody=this.tableObj.getDataTableBody() -if(typeof rowReference==='object') -row=rowReference +if(typeof rowReference==='object'){row=rowReference} else{if(rowReference=='bottom'){row=tbody.children[tbody.children.length-1]} else if(rowReference=='top'){row=tbody.children[0]}} if(!row) @@ -533,8 +533,7 @@ return var cell=row.children[cellIndex] if(cell) this.tableObj.focusCell(cell)} -Navigation.prototype.focusCellInReplacedRow=function(rowIndex,cellIndex){if(rowIndex==0) -this.focusCell('top',cellIndex) +Navigation.prototype.focusCellInReplacedRow=function(rowIndex,cellIndex){if(rowIndex==0){this.focusCell('top',cellIndex)} else{var focusRow=this.tableObj.findRowByIndex(rowIndex) if(!focusRow) focusRow=this.tableObj.findRowByIndex(rowIndex-1) @@ -691,6 +690,7 @@ var input=document.createElement('input') input.setAttribute('type','text') input.setAttribute('class','string-input') input.value=this.tableObj.getCellValue(cellElement) +if(this.columnConfiguration.readOnly){input.setAttribute('readonly',true)} cellContentContainer.appendChild(input) this.setCaretPosition(input,0) window.setTimeout(this.focusTimeoutHandler,0)} @@ -830,8 +830,7 @@ if(!activeItemElement){activeItemElement=this.itemListElement.querySelector('ul if(activeItemElement) activeItemElement.setAttribute('class','selected')} if(activeItemElement){window.setTimeout(function(){activeItemElement.focus()},0)}}} -DropdownProcessor.prototype.fetchOptions=function(cellElement,onSuccess){if(this.columnConfiguration.options) -onSuccess(this.columnConfiguration.options) +DropdownProcessor.prototype.fetchOptions=function(cellElement,onSuccess){if(this.columnConfiguration.options){onSuccess(this.columnConfiguration.options)} else{var row=cellElement.parentNode,cachingKey=this.createOptionsCachingKey(row),viewContainer=this.getViewContainer(cellElement) viewContainer.setAttribute('class','loading') if(!this.cachedOptionPromises[cachingKey]){var requestData={column:this.columnName,rowData:this.tableObj.getRowData(row)},handlerName=this.tableObj.getAlias()+'::onGetDropdownOptions' diff --git a/modules/backend/widgets/table/assets/js/table.helper.navigation.js b/modules/backend/widgets/table/assets/js/table.helper.navigation.js index 6f0893ff0..0483ba2a8 100644 --- a/modules/backend/widgets/table/assets/js/table.helper.navigation.js +++ b/modules/backend/widgets/table/assets/js/table.helper.navigation.js @@ -174,7 +174,7 @@ var curRecordCount = this.getRecordCount() if (placement === 'bottom') - return this.calculatePageCount(curRecordCount+1, this.tableObj.options.recordsPerPage)-1 + return this.calculatePageCount(curRecordCount + 1, this.tableObj.options.recordsPerPage) - 1 // When a row is added above a current row, the current row just moves down, // so it's safe to return the current page index @@ -182,8 +182,8 @@ return this.pageIndex if (placement == 'below') { - if (currentRowIndex == (this.tableObj.options.recordsPerPage-1)) - return this.pageIndex+1 + if (currentRowIndex == (this.tableObj.options.recordsPerPage - 1)) + return this.pageIndex + 1 return this.pageIndex } @@ -193,7 +193,7 @@ Navigation.prototype.getPageAfterDeletion = function(currentRowIndex) { if (currentRowIndex == 0 && this.getRowCountOnPage() == 1) - return this.pageIndex == 0 ? 0 : this.pageIndex-1 + return this.pageIndex == 0 ? 0 : this.pageIndex - 1 return this.pageIndex } @@ -228,10 +228,10 @@ if (!this.paginationEnabled()) return - if (this.pageIndex < this.pageCount-1) { + if (this.pageIndex < this.pageCount - 1) { var self = this - this.gotoPage(this.pageIndex+1, function navDownPageSuccess(){ + this.gotoPage(this.pageIndex + 1, function navDownPageSuccess(){ self.focusCell('top', cellIndex) self = null }) @@ -247,19 +247,20 @@ return var row = this.tableObj.activeCell.parentNode, - newRow = (!ev.shiftKey || isTab) ? - row.previousElementSibling : - row.parentNode.children[0], - cellIndex = forceCellIndex !== undefined ? - forceCellIndex : - this.tableObj.activeCell.cellIndex + newRow = (!ev.shiftKey || isTab) + ? row.previousElementSibling + : row.parentNode.children[0], + cellIndex = forceCellIndex !== undefined + ? forceCellIndex + : this.tableObj.activeCell.cellIndex if (newRow) { var cell = newRow.children[cellIndex] if (cell) this.tableObj.focusCell(cell) - } else { + } + else { // Try to switch to the previous page if that's possible if (!this.paginationEnabled()) @@ -268,7 +269,7 @@ if (this.pageIndex > 0) { var self = this - this.gotoPage(this.pageIndex-1, function navUpPageSuccess(){ + this.gotoPage(this.pageIndex - 1, function navUpPageSuccess(){ self.focusCell('bottom', cellIndex) self = null }) @@ -284,17 +285,18 @@ return var row = this.tableObj.activeCell.parentNode, - newIndex = (!ev.shiftKey || isTab) ? - this.tableObj.activeCell.cellIndex-1 : - 0 + newIndex = (!ev.shiftKey || isTab) + ? this.tableObj.activeCell.cellIndex - 1 + : 0 var cell = row.children[newIndex] - if (cell) + if (cell) { this.tableObj.focusCell(cell) + } else { // Try to navigate up if that's possible - this.navigateUp(ev, row.children.length-1, isTab) + this.navigateUp(ev, row.children.length - 1, isTab) } } @@ -306,14 +308,15 @@ return var row = this.tableObj.activeCell.parentNode, - newIndex = !ev.shiftKey ? - this.tableObj.activeCell.cellIndex+1 : - row.children.length-1 + newIndex = !ev.shiftKey + ? this.tableObj.activeCell.cellIndex + 1 + : row.children.length - 1 var cell = row.children[newIndex] - if (cell) + if (cell) { this.tableObj.focusCell(cell) + } else { // Try to navigate down if that's possible this.navigateDown(ev, 0) @@ -339,12 +342,13 @@ var row = null, tbody = this.tableObj.getDataTableBody() - if (typeof rowReference === 'object') + if (typeof rowReference === 'object') { row = rowReference + } else { if (rowReference == 'bottom') { row = tbody.children[tbody.children.length-1] - } + } else if (rowReference == 'top') { row = tbody.children[0] } @@ -359,8 +363,9 @@ } Navigation.prototype.focusCellInReplacedRow = function(rowIndex, cellIndex) { - if (rowIndex == 0) + if (rowIndex == 0) { this.focusCell('top', cellIndex) + } else { var focusRow = this.tableObj.findRowByIndex(rowIndex) diff --git a/modules/backend/widgets/table/assets/js/table.js b/modules/backend/widgets/table/assets/js/table.js index b0aef7a96..b826a0512 100644 --- a/modules/backend/widgets/table/assets/js/table.js +++ b/modules/backend/widgets/table/assets/js/table.js @@ -215,7 +215,7 @@ if (!this.options.height) this.dataTableContainer = this.tableContainer - else + else this.dataTableContainer = this.buildScrollbar() // Build the data table @@ -240,7 +240,8 @@ // new records can only be added to the bottom of the // table. addBelowButton.textContent = this.options.btnAddRowLabel - } else { + } + else { addBelowButton.textContent = this.options.btnAddRowBelowLabel var addAboveButton = document.createElement('a') @@ -313,7 +314,8 @@ this.unfocusTable() - this.fetchRecords(function onUpdateDataTableSuccess(records, totalCount){ + + this.fetchRecords(function onUpdateDataTableSuccess(records, totalCount) { self.buildDataTable(records, totalCount) if (onSuccess) @@ -322,6 +324,11 @@ if (totalCount == 0) self.addRecord('above', true) + self.$el.trigger('oc.tableUpdateData', [ + records, + totalCount + ]) + self = null }) } @@ -583,7 +590,7 @@ recordData = {}, self = this - recordData[keyColumn] = -1*this.recordsAddedOrDeleted + recordData[keyColumn] = -1 * this.recordsAddedOrDeleted this.$el.trigger('oc.tableNewRow', [ recordData diff --git a/modules/backend/widgets/table/assets/js/table.processor.base.js b/modules/backend/widgets/table/assets/js/table.processor.base.js index 14d14be01..0d63d66cc 100644 --- a/modules/backend/widgets/table/assets/js/table.processor.base.js +++ b/modules/backend/widgets/table/assets/js/table.processor.base.js @@ -174,7 +174,7 @@ /* * Determines whether the specified element is some element created by the - * processor. + * processor. */ Base.prototype.elementBelongsToProcessor = function(element) { return false diff --git a/modules/backend/widgets/table/assets/js/table.processor.dropdown.js b/modules/backend/widgets/table/assets/js/table.processor.dropdown.js index e0c5fb683..c59146f01 100644 --- a/modules/backend/widgets/table/assets/js/table.processor.dropdown.js +++ b/modules/backend/widgets/table/assets/js/table.processor.dropdown.js @@ -192,8 +192,9 @@ } DropdownProcessor.prototype.fetchOptions = function(cellElement, onSuccess) { - if (this.columnConfiguration.options) + if (this.columnConfiguration.options) { onSuccess(this.columnConfiguration.options) + } else { // If options are not provided and not found in the cache, // request them from the server. For dependent drop-downs diff --git a/modules/backend/widgets/table/assets/js/table.processor.string.js b/modules/backend/widgets/table/assets/js/table.processor.string.js index 57dd75499..7aad59288 100644 --- a/modules/backend/widgets/table/assets/js/table.processor.string.js +++ b/modules/backend/widgets/table/assets/js/table.processor.string.js @@ -91,11 +91,16 @@ input.setAttribute('type', 'text') input.setAttribute('class', 'string-input') input.value = this.tableObj.getCellValue(cellElement) + + if (this.columnConfiguration.readOnly) { + input.setAttribute('readonly', true) + } + cellContentContainer.appendChild(input) this.setCaretPosition(input, 0) - // Focus the element in the next frame. + // Focus the element in the next frame. // http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful window.setTimeout(this.focusTimeoutHandler, 0) }