diff --git a/modules/backend/widgets/Table.php b/modules/backend/widgets/Table.php index a54a7e78e..4bd0071a6 100644 --- a/modules/backend/widgets/Table.php +++ b/modules/backend/widgets/Table.php @@ -129,11 +129,7 @@ class Table extends WidgetBase { $this->addCss('css/table.css', 'core'); - // Include a combined and minified script. - // TODO: At the moment the files are combined with - // CodeKit 2, but we should have a method to - // combine files without external dependencies. -ab - $this->addJs('js/table-min.js', 'core'); + $this->addJs('js/build-min.js', 'core'); /* $this->addJs('js/table.js', 'core'); diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index 8e7387c4e..f5635686c 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -285,7 +285,7 @@ The client-side validation is configured in the widget configuration file in the validation: required: message: Please select the state - applyIfNotEmpty: country + requiredWith: country If a validator doesn't have any options (or default option values should be used), the declaration could look like this: @@ -295,7 +295,7 @@ If a validator doesn't have any options (or default option values should be used validation: required: {} -The `applyIfNotEmpty` and `message` parameters are common for all validators. +The `requiredWith` and `message` parameters are common for all validators. Currently implemented client-side validation rules: diff --git a/modules/backend/widgets/table/assets/js/build-min.js b/modules/backend/widgets/table/assets/js/build-min.js index 6630d1b26..b45a8e30b 100644 --- a/modules/backend/widgets/table/assets/js/build-min.js +++ b/modules/backend/widgets/table/assets/js/build-min.js @@ -1,925 +1,3060 @@ +/* + * Table control class + * + * Dependences: + * - Scrollbar (october.scrollbar.js) + */ ++function ($) { "use strict"; -+function($){"use strict";if($.oc===undefined) -$.oc={} -if($.oc.table===undefined) -$.oc.table={} -var Table=function(element,options){this.el=element -this.$el=$(element) -this.options=options -this.dataSource=null -this.cellProcessors={} -this.activeCellProcessor=null -this.activeCell=null -this.tableContainer=null -this.dataTableContainer=null -this.editedRowKey=null -this.dataTable=null -this.headerTable=null -this.toolbar=null -this.clickHandler=this.onClick.bind(this) -this.keydownHandler=this.onKeydown.bind(this) -this.documentClickHandler=this.onDocumentClick.bind(this) -this.toolbarClickHandler=this.onToolbarClick.bind(this) -if(this.options.postback&&this.options.clientDataSourceClass=='client') -this.formSubmitHandler=this.onFormSubmit.bind(this) -this.navigation=null -this.recordsAddedOrDeleted=0 -this.init()} -Table.prototype.init=function(){this.createDataSource() -this.initCellProcessors() -this.navigation=new $.oc.table.helper.navigation(this) -this.buildUi() -this.registerHandlers()} -Table.prototype.disposeCellProcessors=function(){for(var i=0,len=this.options.columns.length;i-1?this.options.alias+'[TableData]':this.options.alias+'TableData';data.options.data[fieldName]=this.dataSource.getAllData()}} -Table.prototype.onToolbarClick=function(ev){var target=this.getEventTarget(ev),cmd=target.getAttribute('data-cmd') -switch(cmd){case'record-add-below':this.addRecord('below') -break -case'record-add-above':this.addRecord('above') -break -case'record-delete':this.deleteRecord() -break} -this.stopEvent(ev)} -Table.prototype.onDocumentClick=function(ev){var target=this.getEventTarget(ev) -if(this.parentContainsElement(this.el,target)) -return -if(this.activeCellProcessor&&this.activeCellProcessor.elementBelongsToProcessor(target)) -return -this.unfocusTable()} -Table.prototype.dispose=function(){this.unfocusTable() -this.dataSource.dispose() -this.dataSource=null -this.unregisterHandlers() -this.dataTable=null -this.headerTable=null -this.toolbar=null -this.disposeCellProcessors() -this.navigation.dispose() -this.navigation=null -this.disposeScrollbar() -this.el=null -this.tableContainer=null -this.$el=null -this.dataTableContainer=null -this.activeCell=null} -Table.prototype.getElement=function(){return this.el} -Table.prototype.getAlias=function(){return this.options.alias} -Table.prototype.getTableContainer=function(){return this.tableContainer} -Table.prototype.getDataTableBody=function(){return this.dataTable.children[0]} -Table.prototype.getEventTarget=function(ev,tag){var target=ev.target?ev.target:ev.srcElement -if(tag===undefined) -return target -var tagName=target.tagName -while(tagName!=tag){target=target.parentNode -if(!target) -return null -tagName=target.tagName} -return target} -Table.prototype.stopEvent=function(ev){if(ev.stopPropagation) -ev.stopPropagation() -else -ev.cancelBubble=true -if(ev.preventDefault) -ev.preventDefault() -else -ev.returnValue=false} -Table.prototype.elementHasClass=function(el,className){if(el.classList) -return el.classList.contains(className);return new RegExp('(^| )'+className+'( |$)','gi').test(el.className);} -Table.prototype.elementAddClass=function(el,className){if(this.elementHasClass(el,className)) -return -if(el.classList) -el.classList.add(className);else -el.className+=' '+className;} -Table.prototype.elementRemoveClass=function(el,className){if(el.classList) -el.classList.remove(className);else -el.className=el.className.replace(new RegExp('(^|\\b)'+className.split(' ').join('|')+'(\\b|$)','gi'),' ');} -Table.prototype.parentContainsElement=function(parent,element){while(element&&element!=parent){element=element.parentNode} -return element?true:false} -Table.prototype.getCellValue=function(cellElement){return cellElement.querySelector('[data-container]').value} -Table.prototype.getCellRowKey=function(cellElement){return parseInt(cellElement.parentNode.getAttribute('data-row'))} -Table.prototype.findRowByKey=function(key){return this.dataTable.querySelector('tbody tr[data-row="'+key+'"]')} -Table.prototype.findRowByIndex=function(index){return this.getDataTableBody().children[index]} -Table.prototype.getCellRowIndex=function(cellElement){return parseInt(cellElement.parentNode.rowIndex)} -Table.prototype.getRowCellValueByColumnName=function(row,columnName){var cell=row.querySelector('td[data-column="'+columnName+'"]') -if(!cell) -return cell -return this.getCellValue(cell)} -Table.prototype.getRowData=function(row){var result={} -for(var i=0,len=row.children.length;i0){var self=this -this.gotoPage(this.pageIndex-1,function navUpPageSuccess(){self.focusCell('bottom',cellIndex) -self=null})}}} -Navigation.prototype.navigateLeft=function(ev,isTab){if(!this.tableObj.activeCell) -return -if(!isTab&&this.tableObj.activeCellProcessor&&!this.tableObj.activeCellProcessor.keyNavigationAllowed(ev,'left')) -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) -else{this.navigateUp(ev,row.children.length-1,isTab)}} -Navigation.prototype.navigateRight=function(ev,isTab){if(!this.tableObj.activeCell) -return -if(!isTab&&this.tableObj.activeCellProcessor&&!this.tableObj.activeCellProcessor.keyNavigationAllowed(ev,'right')) -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) -else{this.navigateDown(ev,0)}} -Navigation.prototype.navigateNext=function(ev){if(!this.tableObj.activeCell) -return -if(this.tableObj.activeCellProcessor&&!this.tableObj.activeCellProcessor.keyNavigationAllowed(ev,'tab')) -return -if(!ev.shiftKey) -this.navigateRight(ev,true) -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 -else{if(rowReference=='bottom'){row=tbody.children[tbody.children.length-1]} -else if(rowReference=='top'){row=tbody.children[0]}} -if(!row) -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) -else{var focusRow=this.tableObj.findRowByIndex(rowIndex) -if(!focusRow) -focusRow=this.tableObj.findRowByIndex(rowIndex-1) -if(focusRow) -this.focusCell(focusRow,cellIndex) -else -this.focusCell('top',cellIndex)}} -Navigation.prototype.onKeydown=function(ev){if(ev.keyCode==40) -return this.navigateDown(ev) -else if(ev.keyCode==38) -return this.navigateUp(ev) -else if(ev.keyCode==37) -return this.navigateLeft(ev) -if(ev.keyCode==39) -return this.navigateRight(ev) -if(ev.keyCode==9) -return this.navigateNext(ev)} -Navigation.prototype.onClick=function(ev){var target=this.tableObj.getEventTarget(ev,'A') -if(!target) -return -var pageIndex=parseInt(target.getAttribute('data-page-index')) -if(pageIndex===null) -return -this.gotoPage(pageIndex) -this.tableObj.stopEvent(ev) -return false} -$.oc.table.helper.navigation=Navigation;}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.datasource===undefined) -$.oc.table.datasource={} -var Base=function(tableObj){this.tableObj=tableObj} -Base.prototype.dispose=function(){this.tableObj=null} -Base.prototype.getRecords=function(offset,count,onSuccess){onSuccess([])} -Base.prototype.createRecord=function(recordData,placement,relativeToKey,offset,count,onSuccess){onSuccess([],0)} -Base.prototype.updateRecord=function(key,recordData){} -Base.prototype.deleteRecord=function(key,newRecordData,offset,count,onSuccess){onSuccess([],0)} -$.oc.table.datasource.base=Base;}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.datasource===undefined) -throw new Error("The $.oc.table.datasource namespace is not defined. Make sure that the table.datasource.base.js script is loaded.");var Base=$.oc.table.datasource.base,BaseProto=Base.prototype -var Client=function(tableObj){Base.call(this,tableObj) -var dataString=tableObj.getElement().getAttribute('data-data') -if(dataString===null||dataString===undefined) -throw new Error('The required data-data attribute is not found on the table control element.') -this.data=JSON.parse(dataString)};Client.prototype=Object.create(BaseProto) -Client.prototype.constructor=Client -Client.prototype.dispose=function(){BaseProto.dispose.call(this) -this.data=null} -Client.prototype.getRecords=function(offset,count,onSuccess){if(!count){onSuccess(this.data,this.data.length)}else{onSuccess(this.data.slice(offset,offset+count),this.data.length)}} -Client.prototype.createRecord=function(recordData,placement,relativeToKey,offset,count,onSuccess){if(placement==='bottom'){this.data.push(recordData)} -else if(placement=='above'||placement=='below'){var recordIndex=this.getIndexOfKey(relativeToKey) -if(placement=='below') -recordIndex++ -this.data.splice(recordIndex,0,recordData)} -this.getRecords(offset,count,onSuccess)} -Client.prototype.updateRecord=function(key,recordData){var recordIndex=this.getIndexOfKey(key) -if(recordIndex!==-1){recordData[this.tableObj.options.keyColumn]=key -this.data[recordIndex]=recordData} -else{throw new Error('Record with they key '+key+' is not found in the data set')}} -Base.prototype.deleteRecord=function(key,newRecordData,offset,count,onSuccess){var recordIndex=this.getIndexOfKey(key) -if(recordIndex!==-1){this.data.splice(recordIndex,1) -if(this.data.length==0) -this.data.push(newRecordData) -this.getRecords(offset,count,onSuccess)} -else{throw new Error('Record with they key '+key+' is not found in the data set')}} -Client.prototype.getIndexOfKey=function(key){var keyColumn=this.tableObj.options.keyColumn -return this.data.map(function(record){return record[keyColumn]+""}).indexOf(key+"")} -Client.prototype.getAllData=function(){return this.data} -$.oc.table.datasource.client=Client}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.processor===undefined) -$.oc.table.processor={} -var Base=function(tableObj,columnName,columnConfiguration){this.tableObj=tableObj -this.columnName=columnName -this.columnConfiguration=columnConfiguration -this.activeCell=null -this.validators=[] -this.registerHandlers() -this.initValidators()} -Base.prototype.dispose=function(){this.unregisterHandlers() -this.tableObj=null -this.activeCell=null} -Base.prototype.renderCell=function(value,cellContentContainer){} -Base.prototype.registerHandlers=function(){} -Base.prototype.unregisterHandlers=function(){} -Base.prototype.onFocus=function(cellElement,isClick){} -Base.prototype.onUnfocus=function(){} -Base.prototype.onKeyDown=function(ev){} -Base.prototype.onClick=function(ev){} -Base.prototype.onRowValueChanged=function(columnName,cellElement){} -Base.prototype.keyNavigationAllowed=function(ev,direction){return true} -Base.prototype.isCellFocusable=function(){return true} -Base.prototype.getCellContentContainer=function(cellElement){return cellElement.querySelector('.content-container')} -Base.prototype.createViewContainer=function(cellContentContainer,value){var viewContainer=document.createElement('div') -viewContainer.setAttribute('data-view-container','data-view-container') -viewContainer.textContent=value -cellContentContainer.appendChild(viewContainer) -return viewContainer} -Base.prototype.getViewContainer=function(cellElement){return cellElement.querySelector('[data-view-container]')} -Base.prototype.showViewContainer=function(cellElement){return this.getViewContainer(cellElement).setAttribute('class','')} -Base.prototype.hideViewContainer=function(cellElement){return this.getViewContainer(cellElement).setAttribute('class','hide')} -Base.prototype.setViewContainerValue=function(cellElement,value){return this.getViewContainer(cellElement).textContent=value} -Base.prototype.elementBelongsToProcessor=function(element){return false} -Base.prototype.initValidators=function(){if(this.columnConfiguration.validation===undefined) -return -for(var validatorName in this.columnConfiguration.validation){if($.oc.table.validator===undefined||$.oc.table.validator[validatorName]==undefined) -throw new Error('The table cell validator "'+validatorName+'" for the column "'+this.columnName+'" is not '+'found in the $.oc.table.validator namespace.') -var validator=new $.oc.table.validator[validatorName](this.columnConfiguration.validation[validatorName]) -this.validators.push(validator)}} -Base.prototype.validate=function(value,rowData){for(var i=0,len=this.validators.length;i0} -$.oc.table.validator.base=Base;}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.validator===undefined) -throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded.");var Base=$.oc.table.validator.base,BaseProto=Base.prototype -var Required=function(options){Base.call(this,options)};Required.prototype=Object.create(BaseProto) -Required.prototype.constructor=Required -Required.prototype.validateValue=function(value,rowData){value=this.trim(value) -if(value.length===0) -return this.getMessage("The value should not be empty.") -return} -$.oc.table.validator.required=Required}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.validator===undefined) -throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded.");var Base=$.oc.table.validator.base,BaseProto=Base.prototype -var BaseNumber=function(options){Base.call(this,options)};BaseNumber.prototype=Object.create(BaseProto) -BaseNumber.prototype.constructor=BaseNumber -BaseNumber.prototype.doCommonChecks=function(value){if(this.options.min!==undefined||this.options.max!==undefined){if(this.options.min!==undefined){if(this.options.min.value===undefined) -throw new Error('The min.value parameter is not defined in the table validator configuration') -if(valuethis.options.max.value){return this.options.max.message!==undefined?this.options.max.message:"The value should not be more than "+this.options.max.value}}} -return} -$.oc.table.validator.baseNumber=BaseNumber}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.validator===undefined) -throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded.");if($.oc.table.validator.baseNumber===undefined) -throw new Error("The $.oc.table.validator.baseNumber namespace is not defined. Make sure that the table.validator.baseNumber.js script is loaded.");var Base=$.oc.table.validator.baseNumber,BaseProto=Base.prototype -var Integer=function(options){Base.call(this,options)};Integer.prototype=Object.create(BaseProto) -Integer.prototype.constructor=Integer -Integer.prototype.validateValue=function(value,rowData){value=this.trim(value) -if(value.length==0) -return -var testResult=this.options.allowNegative?/^\-?[0-9]*$/.test(value):/^[0-9]*$/.test(value) -if(!testResult){var defaultMessage=this.options.allowNegative?'The value should be an integer.':'The value should be a positive integer';return this.getMessage(defaultMessage)} -return this.doCommonChecks(parseInt(value))} -$.oc.table.validator.integer=Integer}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.validator===undefined) -throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded.");if($.oc.table.validator.baseNumber===undefined) -throw new Error("The $.oc.table.validator.baseNumber namespace is not defined. Make sure that the table.validator.baseNumber.js script is loaded.");var Base=$.oc.table.validator.baseNumber,BaseProto=Base.prototype -var Float=function(options){Base.call(this,options)};Float.prototype=Object.create(BaseProto) -Float.prototype.constructor=Float -Float.prototype.validateValue=function(value,rowData){value=this.trim(value) -if(value.length==0) -return -var testResult=this.options.allowNegative?/^[-]?([0-9]+\.[0-9]+|[0-9]+)$/.test(value):/^([0-9]+\.[0-9]+|[0-9]+)$/.test(value) -if(!testResult){var defaultMessage=this.options.allowNegative?'The value should be a floating point number.':'The value should be a positive floating point number';return this.getMessage(defaultMessage)} -return this.doCommonChecks(parseFloat(value))} -$.oc.table.validator.float=Float}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.validator===undefined) -throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded.");var Base=$.oc.table.validator.base,BaseProto=Base.prototype -var Length=function(options){Base.call(this,options)};Length.prototype=Object.create(BaseProto) -Length.prototype.constructor=Length -Length.prototype.validateValue=function(value,rowData){value=this.trim(value) -if(value.length==0) -return -if(this.options.min!==undefined||this.options.max!==undefined){if(this.options.min!==undefined){if(this.options.min.value===undefined) -throw new Error('The min.value parameter is not defined in the Length table validator configuration') -if(value.lengththis.options.max.value){return this.options.max.message!==undefined?this.options.max.message:"The string should not be longer than "+this.options.max.value}}} -return} -$.oc.table.validator.length=Length}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) -throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.validator===undefined) -throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded.");var Base=$.oc.table.validator.base,BaseProto=Base.prototype -var Regex=function(options){Base.call(this,options)};Regex.prototype=Object.create(BaseProto) -Regex.prototype.constructor=Regex -Regex.prototype.validateValue=function(value,rowData){value=this.trim(value) -if(value.length==0) -return -if(this.options.pattern===undefined) -throw new Error('The pattern parameter is not defined in the Regex table validator configuration') -var regexObj=new RegExp(this.options.pattern,this.options.modifiers) -if(!regexObj.test(value)) -return this.getMessage("Invalid value format.") -return} -$.oc.table.validator.regex=Regex}(window.jQuery); \ No newline at end of file + // TABLE CONTROL NAMESPACES + // ============================ + + if ($.oc === undefined) + $.oc = {} + + if ($.oc.table === undefined) + $.oc.table = {} + + // TABLE CLASS DEFINITION + // ============================ + + var Table = function(element, options) { + this.el = element + this.$el = $(element) + + this.options = options + + // + // State properties + // + + // The data source object + this.dataSource = null + + // The cell processors list + this.cellProcessors = {} + + // A reference to the currently active cell processor + this.activeCellProcessor = null + + // A reference to the currently active table cell + this.activeCell = null + + // A reference to the tables container + this.tableContainer = null + + // A reference to the data table container + this.dataTableContainer = null + + // The key of the row which is being edited at the moment. + // This key corresponds the data source row key which + // uniquely identifies the row in the data set. When the + // table grid notices that a cell in another row is edited it commits + // the previously edited record to the data source. + this.editedRowKey = null + + // A reference to the data table + this.dataTable = null + + // A reference to the header table + this.headerTable = null + + // A reference to the toolbar + this.toolbar = null + + // Event handlers + this.clickHandler = this.onClick.bind(this) + this.keydownHandler = this.onKeydown.bind(this) + this.documentClickHandler = this.onDocumentClick.bind(this) + this.toolbarClickHandler = this.onToolbarClick.bind(this) + + if (this.options.postback && this.options.clientDataSourceClass == 'client') + this.formSubmitHandler = this.onFormSubmit.bind(this) + + // Navigation helper + this.navigation = null + + // Number of records added or deleted during the session + this.recordsAddedOrDeleted = 0 + + // + // Initialization + // + + this.init() + } + + // INTERNAL METHODS + // ============================ + + Table.prototype.init = function() { + // Create the data source object + this.createDataSource() + + // Create cell processors + this.initCellProcessors() + + // Initialize helpers + this.navigation = new $.oc.table.helper.navigation(this) + + // Create the UI + this.buildUi() + + // Register event handlers + this.registerHandlers() + } + + Table.prototype.disposeCellProcessors = function() { + // For the performance reasons cell processors are stored + // in an object structure with keys matching the column names. + // We can iterate through then with the for cycle if we know + // the column names. We use the for cycle for the performance + // reasons: http://jsperf.com/for-vs-foreach/37, + // http://jonraasch.com/blog/10-javascript-performance-boosting-tips-from-nicholas-zakas + + for (var i = 0, len = this.options.columns.length; i < len; i++) { + var column = this.options.columns[i].key + + this.cellProcessors[column].dispose() + this.cellProcessors[column] = null + } + + this.cellProcessors = null + this.activeCellProcessor = null + } + + Table.prototype.createDataSource = function() { + var dataSourceClass = this.options.clientDataSourceClass + + if ($.oc.table.datasource === undefined || $.oc.table.datasource[dataSourceClass] == undefined) + throw new Error('The table client-side data source class "'+dataSourceClass+'" is not ' + + 'found in the $.oc.table.datasource namespace.') + + this.dataSource = new $.oc.table.datasource[dataSourceClass](this) + } + + Table.prototype.registerHandlers = function() { + this.el.addEventListener('click', this.clickHandler) + this.el.addEventListener('keydown', this.keydownHandler) + document.addEventListener('click', this.documentClickHandler) + + if (this.options.postback && this.options.clientDataSourceClass == 'client') + this.$el.closest('form').bind('oc.beforeRequest', this.formSubmitHandler) + + var toolbar = this.getToolbar() + if (toolbar) + toolbar.addEventListener('click', this.toolbarClickHandler); + } + + Table.prototype.unregisterHandlers = function() { + this.el.removeEventListener('click', this.clickHandler); + document.removeEventListener('click', this.documentClickHandler) + + this.clickHandler = null + + this.el.removeEventListener('keydown', this.keydownHandler); + this.keydownHandler = null + + var toolbar = this.getToolbar() + if (toolbar) + toolbar.removeEventListener('click', this.toolbarClickHandler); + + this.toolbarClickHandler = null + + if (this.formSubmitHandler) { + this.$el.closest('form').unbind('oc.beforeRequest', this.formSubmitHandler) + this.formSubmitHandler = null + } + } + + Table.prototype.initCellProcessors = function() { + for (var i = 0, len = this.options.columns.length; i < len; i++) { + var columnConfiguration = this.options.columns[i], + column = columnConfiguration.key, + columnType = columnConfiguration.type + + // Resolve the default column type to string + if (columnType === undefined) { + columnType = 'string' + this.options.columns[i].type = columnType + } + + if ($.oc.table.processor === undefined || $.oc.table.processor[columnType] == undefined) + throw new Error('The table cell processor for the column type "'+columnType+'" is not ' + + 'found in the $.oc.table.processor namespace.') + + this.cellProcessors[column] = new $.oc.table.processor[columnType](this, column, columnConfiguration) + } + } + + Table.prototype.getCellProcessor = function(columnName) { + return this.cellProcessors[columnName] + } + + Table.prototype.buildUi = function() { + this.tableContainer = document.createElement('div') + this.tableContainer.setAttribute('class', 'table-container') + + // Build the toolbar + if (this.options.toolbar) + this.buildToolbar() + + // Build the headers table + this.tableContainer.appendChild(this.buildHeaderTable()) + + // Append the table container to the element + this.el.insertBefore(this.tableContainer, this.el.children[0]) + + if (!this.options.height) + this.dataTableContainer = this.tableContainer + else + this.dataTableContainer = this.buildScrollbar() + + // Build the data table + this.updateDataTable() + } + + Table.prototype.buildToolbar = function() { + if (!this.options.adding && !this.options.deleting) + return + + this.toolbar = document.createElement('div') + this.toolbar.setAttribute('class', 'toolbar') + + if (this.options.adding) { + var addBelowButton = document.createElement('a') + addBelowButton.setAttribute('class', 'btn add-table-row-below') + addBelowButton.setAttribute('data-cmd', 'record-add-below') + this.toolbar.appendChild(addBelowButton) + + if (this.navigation.paginationEnabled() || !this.options.rowSorting) { + // When the pagination is enabled, or sorting is disabled, + // new records can only be added to the bottom of the + // table. + addBelowButton.textContent = 'Add row' + } else { + addBelowButton.textContent = 'Add row below' + + var addAboveButton = document.createElement('a') + addAboveButton.setAttribute('class', 'btn add-table-row-above') + addAboveButton.textContent = 'Add row above' + addAboveButton.setAttribute('data-cmd', 'record-add-above') + this.toolbar.appendChild(addAboveButton) + } + } + + if (this.options.deleting) { + var deleteButton = document.createElement('a') + deleteButton.setAttribute('class', 'btn delete-table-row') + deleteButton.textContent = 'Delete row' + deleteButton.setAttribute('data-cmd', 'record-delete') + this.toolbar.appendChild(deleteButton) + } + + this.tableContainer.appendChild(this.toolbar) + } + + Table.prototype.buildScrollbar = function() { + var scrollbar = document.createElement('div'), + scrollbarContent = document.createElement('div') + + scrollbar.setAttribute('class', 'control-scrollbar') + + if (this.options.dynamicHeight) + scrollbar.setAttribute('style', 'max-height: ' + this.options.height + 'px') + else + scrollbar.setAttribute('style', 'height: ' + this.options.height + 'px') + + scrollbar.appendChild(scrollbarContent) + this.tableContainer.appendChild(scrollbar) + + $(scrollbar).scrollbar({animation: false}) + + return scrollbarContent + } + + Table.prototype.buildHeaderTable = function() { + var headersTable = document.createElement('table'), + row = document.createElement('tr') + + headersTable.className = 'headers' + headersTable.appendChild(row) + + for (var i = 0, len = this.options.columns.length; i < len; i++) { + var header = document.createElement('th') + + if (this.options.columns[i].width) + header.setAttribute('style', 'width: '+this.options.columns[i].width) + + header.textContent !== undefined + ? header.textContent = this.options.columns[i].title + : header.innerText = this.options.columns[i].title + + row.appendChild(header) + } + + this.headerTable = headersTable + + return headersTable + } + + Table.prototype.updateDataTable = function(onSuccess) { + var self = this + + this.unfocusTable() + + this.fetchRecords(function onUpdateDataTableSuccess(records, totalCount){ + self.buildDataTable(records, totalCount) + + if (onSuccess) + onSuccess() + + if (totalCount == 0) + self.addRecord('above', true) + + 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; i < len; i++) { + if (dataCells[i]) + dataCells[i].setAttribute('style', headerCells[i].getAttribute('style')) + } + } + + Table.prototype.buildDataTable = function(records, totalCount) { + var dataTable = document.createElement('table'), + tbody = document.createElement('tbody'), + keyColumn = this.options.keyColumn + + dataTable.setAttribute('class', 'data') + + for (var i = 0, len = records.length; i < len; i++) { + var row = document.createElement('tr') + + if (records[i][keyColumn] === undefined) + throw new Error('The row attribute '+keyColumn+' is not set for the row #'+i); + + row.setAttribute('data-row', records[i][keyColumn]) + for (var j = 0, colsLen = this.options.columns.length; j < colsLen; j++) { + var cell = document.createElement('td'), + dataContainer = document.createElement('input'), + cellContentContainer = document.createElement('div'), + column = this.options.columns[j], + columnName = column.key, + cellProcessor = this.getCellProcessor(columnName) + + cell.setAttribute('data-column', columnName) + cell.setAttribute('data-column-type', column.type) + + dataContainer.setAttribute('type', 'hidden') + dataContainer.setAttribute('data-container', 'data-container') + dataContainer.value = records[i][columnName] !== undefined ? + records[i][columnName] : + "" + + cellContentContainer.setAttribute('class', 'content-container') + + cell.appendChild(cellContentContainer) + row.appendChild(cell) + cell.appendChild(dataContainer) + + cellProcessor.renderCell(records[i][columnName], cellContentContainer) + } + + tbody.appendChild(row) + } + + dataTable.appendChild(tbody) + + // Inject the data table to the DOM or replace the existing table + if (this.dataTable !== null) + this.dataTableContainer.replaceChild(dataTable, this.dataTable) + else + this.dataTableContainer.appendChild(dataTable) + + this.dataTable = dataTable + + // Update column widths + this.updateColumnWidth() + + // Update the scrollbar + this.updateScrollbar() + + // Update the pagination links + this.navigation.buildPagination(totalCount) + } + + Table.prototype.fetchRecords = function(onSuccess) { + this.dataSource.getRecords( + this.navigation.getPageFirstRowOffset(), + this.options.recordsPerPage, + onSuccess) + } + + Table.prototype.updateScrollbar = function() { + if (!this.options.height) + return + + $(this.dataTableContainer.parentNode).data('oc.scrollbar').update() + } + + Table.prototype.scrollCellIntoView = function() { + if (!this.options.height || !this.activeCell) + return + + $(this.dataTableContainer.parentNode).data('oc.scrollbar').gotoElement(this.activeCell) + } + + Table.prototype.disposeScrollbar = function() { + if (!this.options.height) + return + + $(this.dataTableContainer.parentNode).data('oc.scrollbar').dispose() + $(this.dataTableContainer.parentNode).data('oc.scrollbar', null) + } + + /* + * Makes a cell processor active and hides the previously + * active editor. + */ + Table.prototype.setActiveProcessor = function(processor) { + if (this.activeCellProcessor) + this.activeCellProcessor.onUnfocus() + + this.activeCellProcessor = processor + } + + Table.prototype.commitEditedRow = function() { + if (this.editedRowKey === null) + return + + var editedRow = this.dataTable.querySelector('tr[data-row="'+this.editedRowKey+'"]') + if (!editedRow) + return + + if (editedRow.getAttribute('data-dirty') != 1) + return + + var cells = editedRow.children, + data = {} + + for (var i=0, len = cells.length; i < len; i++) { + var cell = cells[i] + + data[cell.getAttribute('data-column')] = this.getCellValue(cell) + } + + this.dataSource.updateRecord(this.editedRowKey, data) + editedRow.setAttribute('data-dirty', 0) + } + + /* + * Removes editor from the currently edited cell and commits the row if needed. + */ + Table.prototype.unfocusTable = function() { + this.elementRemoveClass(this.el, 'active') + + if (this.activeCellProcessor) + this.activeCellProcessor.onUnfocus() + + this.commitEditedRow() + this.activeCellProcessor = null + + if (this.activeCell) + this.activeCell.setAttribute('class', '') + + this.activeCell = null + } + + /* + * Makes the table focused in the UI + */ + Table.prototype.focusTable = function() { + this.elementAddClass(this.el, 'active') + } + + /* + * Calls the onFocus() method for the cell processor responsible for the + * newly focused cell. Commit the previous edited row to the data source + * if needed. + */ + Table.prototype.focusCell = function(cellElement, isClick) { + var columnName = cellElement.getAttribute('data-column') + if (columnName === null) + return + + this.focusTable() + + var processor = this.getCellProcessor(columnName) + if (!processor) + throw new Error("Cell processor not found for the column "+columnName) + + if (this.activeCell !== cellElement) { + if (this.activeCell) + this.elementRemoveClass(this.activeCell, 'active') + + this.setActiveProcessor(processor) + this.activeCell = cellElement + + if (processor.isCellFocusable()) + this.elementAddClass(this.activeCell, 'active') + } + + // If the cell belongs to other row than the currently edited, + // commit currently edited row to the data source. Update the + // currently edited row key. + var rowKey = this.getCellRowKey(cellElement) + + if (this.editedRowKey !== null && rowKey != this.editedRowKey) + this.commitEditedRow() + + this.editedRowKey = rowKey + + processor.onFocus(cellElement, isClick) + + this.scrollCellIntoView() + } + + Table.prototype.markCellRowDirty = function(cellElement) { + cellElement.parentNode.setAttribute('data-dirty', 1) + } + + Table.prototype.addRecord = function(placement, noFocus) { + // If there is no active cell, or the pagination is enabled or + // row sorting is disabled, add the record to the bottom of + // the table (last page). + + if (!this.activeCell || this.navigation.paginationEnabled() || !this.options.rowSorting) + placement = 'bottom' + + var relativeToKey = null, + currentRowIndex = null + + if (placement == 'above' || placement == 'below') { + relativeToKey = this.getCellRowKey(this.activeCell) + currentRowIndex = this.getCellRowIndex(this.activeCell) + } + + this.unfocusTable() + + if (this.navigation.paginationEnabled()) { + var newPageIndex = this.navigation.getNewRowPage(placement, currentRowIndex) + + if (newPageIndex != this.navigation.pageIndex) { + // Validate data on the current page if adding a new record + // is going to create another page. + if (!this.validate()) + return + } + + this.navigation.pageIndex = newPageIndex + } + + this.recordsAddedOrDeleted++ + + // New records have negative keys + var keyColumn = this.options.keyColumn, + recordData = {}, + self = this + + recordData[keyColumn] = -1*this.recordsAddedOrDeleted + + this.dataSource.createRecord(recordData, placement, relativeToKey, + this.navigation.getPageFirstRowOffset(), + this.options.recordsPerPage, + function onAddRecordDataTableSuccess(records, totalCount) { + self.buildDataTable(records, totalCount) + + var row = self.findRowByKey(recordData[keyColumn]) + if (!row) + throw new Error('New row is not found in the updated table: '+recordData[keyColumn]) + + if (!noFocus) + self.navigation.focusCell(row, 0) + + self = null + } + ) + } + + Table.prototype.deleteRecord = function() { + if (!this.activeCell) + return + + var currentRowIndex = this.getCellRowIndex(this.activeCell), + key = this.getCellRowKey(this.activeCell), + self = this, + paginationEnabled = this.navigation.paginationEnabled(), + currentPageIndex = this.navigation.pageIndex, + currentCellIndex = this.activeCell.cellIndex + + if (paginationEnabled) + this.navigation.pageIndex = this.navigation.getPageAfterDeletion(currentRowIndex) + + this.recordsAddedOrDeleted++ + + // New records have negative keys + var keyColumn = this.options.keyColumn, + newRecordData = {} + + newRecordData[keyColumn] = -1*this.recordsAddedOrDeleted + + this.dataSource.deleteRecord(key, + newRecordData, + this.navigation.getPageFirstRowOffset(), + this.options.recordsPerPage, + function onDeleteRecordDataTableSuccess(records, totalCount) { + self.buildDataTable(records, totalCount) + + if (!paginationEnabled) + self.navigation.focusCellInReplacedRow(currentRowIndex, currentCellIndex) + else { + if (currentPageIndex != self.navigation.pageIndex) + self.navigation.focusCell('bottom', currentCellIndex) + else + self.navigation.focusCellInReplacedRow(currentRowIndex, currentCellIndex) + } + + self = null + } + ) + } + + Table.prototype.notifyRowProcessorsOnChange = function(cellElement) { + var columnName = cellElement.getAttribute('data-column'), + row = cellElement.parentNode + + for (var i = 0, len = row.children.length; i < len; i++) { + var column = this.options.columns[i].key + + this.cellProcessors[column].onRowValueChanged(columnName, row.children[i]) + } + } + + Table.prototype.getToolbar = function() { + return this.tableContainer.querySelector('div.toolbar') + } + + /* + * Validaates data on the current page + */ + Table.prototype.validate = function() { + var rows = this.dataTable.querySelectorAll('tbody tr[data-row]') + + for (var i = 0, len = rows.length; i < len; i++) { + var row = rows[i] + + this.elementRemoveClass(row, 'error') + } + + for (var i = 0, rowsLen = rows.length; i < rowsLen; i++) { + var row = rows[i], + rowData = this.getRowData(row) + + for (var j = 0, colsLen = row.children.length; j < colsLen; j++) + this.elementRemoveClass(row.children[j], 'error') + + for (var columnName in rowData) { + var cellProcessor = this.getCellProcessor(columnName), + message = cellProcessor.validate(rowData[columnName], rowData) + + if (message !== undefined) { + var cell = row.querySelector('td[data-column="'+columnName+'"]'), + self = this + + this.elementAddClass(row, 'error') + this.elementAddClass(cell, 'error') + + $.oc.flashMsg({text: message, 'class': 'error'}) + + window.setTimeout(function(){ + self.focusCell(cell, false) + cell = null + self = null + cellProcessor = null + }, 100) + return false + } + } + } + + return true + } + + // EVENT HANDLERS + // ============================ + + Table.prototype.onClick = function(ev) { + this.focusTable() + + if (this.navigation.onClick(ev) === false) + return + + for (var i = 0, len = this.options.columns.length; i < len; i++) { + var column = this.options.columns[i].key + + this.cellProcessors[column].onClick(ev) + } + + var target = this.getEventTarget(ev, 'TD') + + if (!target) + return + + if (target.tagName != 'TD') + return + + this.focusCell(target, true) + } + + Table.prototype.onKeydown = function(ev) { + if (ev.keyCode == 65 && ev.altKey && this.options.adding) { + if (!ev.shiftKey) { + // alt+a - add record below + this.addRecord('below') + } else { + // alt+shift+a - add record above + this.addRecord('above') + } + + this.stopEvent(ev) + return + } + + if (ev.keyCode == 68 && ev.altKey && this.options.deleting) { + // alt+d - delete record + this.deleteRecord() + + this.stopEvent(ev) + return + } + + for (var i = 0, len = this.options.columns.length; i < len; i++) { + var column = this.options.columns[i].key + + this.cellProcessors[column].onKeyDown(ev) + } + + if (this.navigation.onKeydown(ev) === false) + return + } + + Table.prototype.onFormSubmit = function(ev, data) { + if (data.handler == this.options.postbackHandlerName) { + this.unfocusTable() + + if (!this.validate()) { + ev.preventDefault() + return + } + + var fieldName = this.options.alias.indexOf('[') > -1 ? + this.options.alias + '[TableData]' : + this.options.alias + 'TableData'; + + data.options.data[fieldName] = this.dataSource.getAllData() + } + } + + Table.prototype.onToolbarClick = function(ev) { + var target = this.getEventTarget(ev), + cmd = target.getAttribute('data-cmd') + + switch (cmd) { + case 'record-add-below': + this.addRecord('below') + break + case 'record-add-above': + this.addRecord('above') + break + case 'record-delete': + this.deleteRecord() + break + } + + this.stopEvent(ev) + } + + Table.prototype.onDocumentClick = function(ev) { + var target = this.getEventTarget(ev) + + // Determine if the click was inside the table element + // and just exit if so + if (this.parentContainsElement(this.el, target)) + return + + // Request the active cell processor if the clicked + // element belongs to any extra-table element created + // by the processor + + if (this.activeCellProcessor && this.activeCellProcessor.elementBelongsToProcessor(target)) + return + + this.unfocusTable() + } + + // PUBLIC METHODS + // ============================ + + Table.prototype.dispose = function() { + // Remove an editor and commit the data if needed + this.unfocusTable() + + // Dispose the data source and clean up the reference + this.dataSource.dispose() + this.dataSource = null + + // Unregister event handlers + this.unregisterHandlers() + + // Remove references to DOM elements + this.dataTable = null + this.headerTable = null + this.toolbar = null + + // Dispose cell processors + this.disposeCellProcessors() + + // Dispose helpers and remove references + this.navigation.dispose() + this.navigation = null + + // Delete references to the control HTML elements. + // The script doesn't remove any DOM elements themselves. + // If it's needed it should be done by the outer script, + // we only make sure that the table widget doesn't hold + // references to the detached DOM tree so that the garbage + // collector can delete the elements if needed. + this.disposeScrollbar() + this.el = null + this.tableContainer = null + this.$el = null + this.dataTableContainer = null + + // Delete references to other DOM elements + this.activeCell = null + } + + // HELPER METHODS + // ============================ + + Table.prototype.getElement = function() { + return this.el + } + + Table.prototype.getAlias = function() { + return this.options.alias + } + + Table.prototype.getTableContainer = function() { + return this.tableContainer + } + + Table.prototype.getDataTableBody = function() { + return this.dataTable.children[0] + } + + Table.prototype.getEventTarget = function(ev, tag) { + // TODO: refactor to a core library + + var target = ev.target ? ev.target : ev.srcElement + + if (tag === undefined) + return target + + var tagName = target.tagName + + while (tagName != tag) { + target = target.parentNode + + if (!target) + return null + + tagName = target.tagName + } + + return target + } + + Table.prototype.stopEvent = function(ev) { + // TODO: refactor to a core library + + if (ev.stopPropagation) + ev.stopPropagation() + else + ev.cancelBubble = true + + if(ev.preventDefault) + ev.preventDefault() + else + ev.returnValue = false + } + + Table.prototype.elementHasClass = function(el, className) { + // TODO: refactor to a core library + + if (el.classList) + return el.classList.contains(className); + + return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className); + } + + Table.prototype.elementAddClass = function(el, className) { + // TODO: refactor to a core library + + if (this.elementHasClass(el, className)) + return + + if (el.classList) + el.classList.add(className); + else + el.className += ' ' + className; + } + + Table.prototype.elementRemoveClass = function(el, className) { + // TODO: refactor to a core library + + if (el.classList) + el.classList.remove(className); + else + el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); + } + + Table.prototype.parentContainsElement = function(parent, element) { + while (element && element != parent) { + element = element.parentNode + } + + return element ? true : false + } + + Table.prototype.getCellValue = function(cellElement) { + return cellElement.querySelector('[data-container]').value + } + + Table.prototype.getCellRowKey = function(cellElement) { + return parseInt(cellElement.parentNode.getAttribute('data-row')) + } + + Table.prototype.findRowByKey = function(key) { + return this.dataTable.querySelector('tbody tr[data-row="'+key+'"]') + } + + Table.prototype.findRowByIndex = function(index) { + return this.getDataTableBody().children[index] + } + + Table.prototype.getCellRowIndex = function(cellElement) { + return parseInt(cellElement.parentNode.rowIndex) + } + + Table.prototype.getRowCellValueByColumnName = function(row, columnName) { + var cell = row.querySelector('td[data-column="'+columnName+'"]') + + if (!cell) + return cell + + return this.getCellValue(cell) + } + + Table.prototype.getRowData = function(row) { + var result = {} + + for (var i = 0, len = row.children.length; i < len; i++) { + var cell = row.children[i] + result[cell.getAttribute('data-column')] = this.getCellValue(cell) + } + + return result + } + + Table.prototype.setCellValue = function(cellElement, value) { + var dataContainer = cellElement.querySelector('[data-container]') + + if (dataContainer.value != value) { + dataContainer.value = value + + this.markCellRowDirty(cellElement) + + this.notifyRowProcessorsOnChange(cellElement) + } + } + + Table.DEFAULTS = { + clientDataSourceClass: 'client', + keyColumn: 'id', + recordsPerPage: false, + data: null, + postback: true, + postbackHandlerName: 'onSave', + adding: true, + deleting: true, + toolbar: true, + rowSorting: false, + height: false, + dynamicHeight: false + } + + // TABLE PLUGIN DEFINITION + // ============================ + + var old = $.fn.table + + $.fn.table = function (option) { + var args = Array.prototype.slice.call(arguments, 1), + result = undefined + + this.each(function () { + var $this = $(this) + var data = $this.data('oc.table') + var options = $.extend({}, Table.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.table', (data = new Table(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.table.Constructor = Table + + $.oc.table.table = Table + + // TABLE NO CONFLICT + // ================= + + $.fn.table.noConflict = function () { + $.fn.table = old + return this + } + + // TABLE DATA-API + // =============== + + $(document).on('render', function(){ + $('div[data-control=table]').table() + }) + +}(window.jQuery); + +/* ********************************************** + Begin table.datasource.base.js +********************************************** */ + +/* + * Base class for the table data sources. + */ ++function ($) { "use strict"; + + // DATASOURCE NAMESPACES + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.datasource === undefined) + $.oc.table.datasource = {} + + // CLASS DEFINITION + // ============================ + + var Base = function(tableObj) { + // + // State properties + // + + this.tableObj = tableObj + } + + Base.prototype.dispose = function() { + this.tableObj = null + } + + /* + * Fetches records from the underlying data source and + * passes them to the onSuccess callback function. + * The onSuccess callback parameters: records, totalCount. + * Each record contains the key field which uniquely identifies + * the record. The name of the key field is defined with the table + * widget options. + */ + Base.prototype.getRecords = function(offset, count, onSuccess) { + onSuccess([]) + } + + /* + * Creates a record with the passed data and returns the updated page records + * to the onSuccess callback function. + * + * - recordData - the record fields + * - placement - "bottom" (the end of the data set), "above", "below" + * - relativeToKey - a row key, required if the placement is not "bottom" + * - offset - the current page's first record index (zero-based) + * - count - number of records to return + * - onSuccess - a callback function to execute when the updated data gets available. + * + * The onSuccess callback parameters: records, totalCount. + */ + Base.prototype.createRecord = function(recordData, placement, relativeToKey, offset, count, onSuccess) { + onSuccess([], 0) + } + + /* + * Updates a record with the specified key with the passed data + * + * - key - the record key in the dataset (primary key, etc) + * - recordData - the record fields. + */ + Base.prototype.updateRecord = function(key, recordData) { + } + + /* + * Deletes a record with the specified key. + * + * - key - the record key in the dataset (primary key, etc). + * - newRecordData - replacement record to add to the dataset if the deletion + * empties it. + * - offset - the current page's first record key (zero-based) + * - count - number of records to return + * - onSuccess - a callback function to execute when the updated data gets available. + * + * The onSuccess callback parameters: records, totalCount. + */ + Base.prototype.deleteRecord = function(key, newRecordData, offset, count, onSuccess) { + onSuccess([], 0) + } + + $.oc.table.datasource.base = Base; +}(window.jQuery); + +/* ********************************************** + Begin table.processor.base.js +********************************************** */ + +/* + * Base class for the table cell processors. + */ ++function ($) { "use strict"; + + // PROCESSOR NAMESPACES + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.processor === undefined) + $.oc.table.processor = {} + + // CLASS DEFINITION + // ============================ + + var Base = function(tableObj, columnName, columnConfiguration) { + // + // State properties + // + + this.tableObj = tableObj + + this.columnName = columnName + + this.columnConfiguration = columnConfiguration + + this.activeCell = null + + this.validators = [] + + // Register event handlers + this.registerHandlers() + + // Initialize validators + this.initValidators() + } + + Base.prototype.dispose = function() { + // Register event handlers + this.unregisterHandlers() + + // Remove references to the DOM + this.tableObj = null + + this.activeCell = null + } + + /* + * Renders the cell in the normal (no edit) mode + */ + Base.prototype.renderCell = function(value, cellContentContainer) { + } + + /* + * Registers event handlers required for the cell processor. + * Event handers should be bound to the container control element + * (not to the table element). + */ + Base.prototype.registerHandlers = function() { + } + + /* + * Unregisters event handlers previously registered with + * registerHandlers(). + */ + Base.prototype.unregisterHandlers = function() { + } + + /* + * This method is called when the cell managed by the processor + * is focused (clicked or navigated with the keyboard). + */ + Base.prototype.onFocus = function(cellElement, isClick) { + } + + + /* + * Forces the processor to hide the editor when the user navigates + * away from the cell. Processors can update the sell value in this method. + * Processors must clear the reference to the active cell in this method. + */ + Base.prototype.onUnfocus = function() { + } + + /* + * Event handler for the keydown event. The table class calls this method + * for all processors. + */ + Base.prototype.onKeyDown = function(ev) { + } + + /* + * Event handler for the click event. The table class calls this method + * for all processors. + */ + Base.prototype.onClick = function(ev) { + } + + /* + * This method is called when a cell value in the row changes. + */ + Base.prototype.onRowValueChanged = function(columnName, cellElement) { + } + + /* + * Determines if the keyboard navigation in the specified direction is allowed + * by the cell processor. Some processors could reject the navigation, for example + * the string processor could cancel the left array navigation if the caret + * in the text input is not in the beginning of the text. + */ + Base.prototype.keyNavigationAllowed = function(ev, direction) { + return true + } + + /* + * Determines if the processor's cell is focusable. + */ + Base.prototype.isCellFocusable = function() { + return true + } + + /* + * Returns the content container element of a cell + */ + Base.prototype.getCellContentContainer = function(cellElement) { + return cellElement.querySelector('.content-container') + } + + /* + * Creates a cell view data container (a DIV element that contains + * the current cell value). This functionality is required for most + * of the processors, perhaps except the checkbox cell processor. + */ + Base.prototype.createViewContainer = function(cellContentContainer, value) { + var viewContainer = document.createElement('div') + + viewContainer.setAttribute('data-view-container', 'data-view-container') + viewContainer.textContent = value + + cellContentContainer.appendChild(viewContainer) + + return viewContainer + } + + /* + * Returns the cell's view container element. + */ + Base.prototype.getViewContainer = function(cellElement) { + return cellElement.querySelector('[data-view-container]') + } + + /* + * Displays the view container + */ + Base.prototype.showViewContainer = function(cellElement) { + return this.getViewContainer(cellElement).setAttribute('class', '') + } + + /* + * Hides the view container + */ + Base.prototype.hideViewContainer = function(cellElement) { + return this.getViewContainer(cellElement).setAttribute('class', 'hide') + } + + /* + * Sets visual value for the view container + */ + Base.prototype.setViewContainerValue = function(cellElement, value) { + return this.getViewContainer(cellElement).textContent = value + } + + /* + * Determines whether the specified element is some element created by the + * processor. + */ + Base.prototype.elementBelongsToProcessor = function(element) { + return false + } + + Base.prototype.initValidators = function() { + if (this.columnConfiguration.validation === undefined) + return + + for (var validatorName in this.columnConfiguration.validation) { + if ($.oc.table.validator === undefined || $.oc.table.validator[validatorName] == undefined) + throw new Error('The table cell validator "'+validatorName+'" for the column "'+this.columnName+'" is not ' + + 'found in the $.oc.table.validator namespace.') + + var validator = new $.oc.table.validator[validatorName]( + this.columnConfiguration.validation[validatorName] + ) + + this.validators.push(validator) + } + } + + Base.prototype.validate = function(value, rowData) { + for (var i=0, len=this.validators.length; i 0) { + var self = this + + this.gotoPage(this.pageIndex-1, function navUpPageSuccess(){ + self.focusCell('bottom', cellIndex) + self = null + }) + } + } + } + + Navigation.prototype.navigateLeft = function(ev, isTab) { + if (!this.tableObj.activeCell) + return + + if (!isTab && this.tableObj.activeCellProcessor && !this.tableObj.activeCellProcessor.keyNavigationAllowed(ev, 'left')) + 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) + else { + // Try to navigate up if that's possible + this.navigateUp(ev, row.children.length-1, isTab) + } + } + + Navigation.prototype.navigateRight = function(ev, isTab) { + if (!this.tableObj.activeCell) + return + + if (!isTab && this.tableObj.activeCellProcessor && !this.tableObj.activeCellProcessor.keyNavigationAllowed(ev, 'right')) + 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) + else { + // Try to navigate down if that's possible + this.navigateDown(ev, 0) + } + } + + Navigation.prototype.navigateNext = function(ev) { + if (!this.tableObj.activeCell) + return + + if (this.tableObj.activeCellProcessor && !this.tableObj.activeCellProcessor.keyNavigationAllowed(ev, 'tab')) + return + + if (!ev.shiftKey) + this.navigateRight(ev, true) + 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 + else { + if (rowReference == 'bottom') { + row = tbody.children[tbody.children.length-1] + } + else if (rowReference == 'top') { + row = tbody.children[0] + } + } + + if (!row) + 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) + else { + var focusRow = this.tableObj.findRowByIndex(rowIndex) + + if (!focusRow) + focusRow = this.tableObj.findRowByIndex(rowIndex-1) + + if (focusRow) + this.focusCell(focusRow, cellIndex) + else + this.focusCell('top', cellIndex) + } + } + + // EVENT HANDLERS + // ============================ + + Navigation.prototype.onKeydown = function(ev) { + // The navigation object uses the table's keydown handler + // and doesn't register own handler. + + if (ev.keyCode == 40) + return this.navigateDown(ev) + else if (ev.keyCode == 38) + return this.navigateUp(ev) + else if (ev.keyCode == 37) + return this.navigateLeft(ev) + if (ev.keyCode == 39) + return this.navigateRight(ev) + if (ev.keyCode == 9) + return this.navigateNext(ev) + } + + Navigation.prototype.onClick = function(ev) { + // The navigation object uses the table's click handler + // and doesn't register own click handler. + + var target = this.tableObj.getEventTarget(ev, 'A') + + if (!target) + return + + var pageIndex = parseInt(target.getAttribute('data-page-index')) + + if (pageIndex === null) + return + + this.gotoPage(pageIndex) + this.tableObj.stopEvent(ev) + + return false + } + + $.oc.table.helper.navigation = Navigation; +}(window.jQuery); + +/* ********************************************** + Begin table.datasource.client.js +********************************************** */ + +/* + * Client memory data source for the table control. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.datasource === undefined) + throw new Error("The $.oc.table.datasource namespace is not defined. Make sure that the table.datasource.base.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.datasource.base, + BaseProto = Base.prototype + + var Client = function(tableObj) { + Base.call(this, tableObj) + + var dataString = tableObj.getElement().getAttribute('data-data') + + if (dataString === null || dataString === undefined) + throw new Error('The required data-data attribute is not found on the table control element.') + + this.data = JSON.parse(dataString) + }; + + Client.prototype = Object.create(BaseProto) + Client.prototype.constructor = Client + + Client.prototype.dispose = function() { + BaseProto.dispose.call(this) + this.data = null + } + + /* + * Fetches records from the underlying data source and + * passes them to the onSuccess callback function. + * The onSuccess callback parameters: records, totalCount. + * Each record contains the key field which uniquely identifies + * the record. The name of the key field is defined with the table + * widget options. + */ + Client.prototype.getRecords = function(offset, count, onSuccess) { + if (!count) { + // Return all records + onSuccess(this.data, this.data.length) + } else { + // Return a subset of records + onSuccess(this.data.slice(offset, offset+count), this.data.length) + } + } + + /* + * Creates a record with the passed data and returns the updated page records + * to the onSuccess callback function. + * + * - recordData - the record fields + * - placement - "bottom" (the end of the data set), "above", "below" + * - relativeToKey - a row key, required if the placement is not "bottom" + * - offset - the current page's first record index (zero-based) + * - count - number of records to return + * - onSuccess - a callback function to execute when the updated data gets available. + * + * The onSuccess callback parameters: records, totalCount. + */ + Client.prototype.createRecord = function(recordData, placement, relativeToKey, offset, count, onSuccess) { + if (placement === 'bottom') { + // Add record to the bottom of the dataset + this.data.push(recordData) + } + else if (placement == 'above' || placement == 'below') { + // Add record above or below the passed record key + var recordIndex = this.getIndexOfKey(relativeToKey) + if (placement == 'below') + recordIndex ++ + + this.data.splice(recordIndex, 0, recordData) + } + + this.getRecords(offset, count, onSuccess) + } + + /* + * Updates a record with the specified key with the passed data + * + * - key - the record key in the dataset (primary key, etc) + * - recordData - the record fields. + */ + Client.prototype.updateRecord = function(key, recordData) { + var recordIndex = this.getIndexOfKey(key) + + if (recordIndex !== -1) { + recordData[this.tableObj.options.keyColumn] = key + this.data[recordIndex] = recordData + } + else { + throw new Error('Record with they key '+key+ ' is not found in the data set') + } + } + + /* + * Deletes a record with the specified key. + * + * - key - the record key in the dataset (primary key, etc). + * - newRecordData - replacement record to add to the dataset if the deletion + * empties it. + * - offset - the current page's first record key (zero-based) + * - count - number of records to return + * - onSuccess - a callback function to execute when the updated data gets available. + * + * The onSuccess callback parameters: records, totalCount. + */ + Base.prototype.deleteRecord = function(key, newRecordData, offset, count, onSuccess) { + var recordIndex = this.getIndexOfKey(key) + + if (recordIndex !== -1) { + this.data.splice(recordIndex, 1) + + if (this.data.length == 0) + this.data.push(newRecordData) + + this.getRecords(offset, count, onSuccess) + } + else { + throw new Error('Record with they key '+key+ ' is not found in the data set') + } + } + + Client.prototype.getIndexOfKey = function(key) { + var keyColumn = this.tableObj.options.keyColumn + + return this.data.map(function(record) { + return record[keyColumn] + "" + }).indexOf(key + "") + } + + Client.prototype.getAllData = function() { + return this.data + } + + $.oc.table.datasource.client = Client +}(window.jQuery); + +/* ********************************************** + Begin table.processor.checkbox.js +********************************************** */ + +/* + * Checkbox cell processor for the table control. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.processor === undefined) + throw new Error("The $.oc.table.processor namespace is not defined. Make sure that the table.processor.base.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.processor.base, + BaseProto = Base.prototype + + var CheckboxProcessor = function(tableObj, columnName, columnConfiguration) { + // + // Parent constructor + // + + Base.call(this, tableObj, columnName, columnConfiguration) + } + + CheckboxProcessor.prototype = Object.create(BaseProto) + CheckboxProcessor.prototype.constructor = CheckboxProcessor + + CheckboxProcessor.prototype.dispose = function() { + BaseProto.dispose.call(this) + } + + /* + * Determines if the processor's cell is focusable. + */ + CheckboxProcessor.prototype.isCellFocusable = function() { + return false + } + + /* + * Renders the cell in the normal (no edit) mode + */ + CheckboxProcessor.prototype.renderCell = function(value, cellContentContainer) { + var checkbox = document.createElement('div') + checkbox.setAttribute('data-checkbox-element', 'true') + checkbox.setAttribute('tabindex', '0') + + if (value && value != 0 && value != "false") + checkbox.setAttribute('class', 'checked') + + cellContentContainer.appendChild(checkbox) + } + + /* + * This method is called when the cell managed by the processor + * is focused (clicked or navigated with the keyboard). + */ + CheckboxProcessor.prototype.onFocus = function(cellElement, isClick) { + cellElement.querySelector('div[data-checkbox-element]').focus() + } + + /* + * Event handler for the keydown event. The table class calls this method + * for all processors. + */ + CheckboxProcessor.prototype.onKeyDown = function(ev) { + if (ev.keyCode == 32) + this.onClick(ev) + } + + /* + * Event handler for the click event. The table class calls this method + * for all processors. + */ + CheckboxProcessor.prototype.onClick = function(ev) { + var target = this.tableObj.getEventTarget(ev, 'DIV') + + if (target.getAttribute('data-checkbox-element')) { + this.changeState(target) + } + } + + CheckboxProcessor.prototype.changeState = function(divElement) { + var cell = divElement.parentNode.parentNode + + if (divElement.getAttribute('class') == 'checked') { + divElement.setAttribute('class', '') + this.tableObj.setCellValue(cell, 0) + } else { + divElement.setAttribute('class', 'checked') + this.tableObj.setCellValue(cell, 1) + } + } + + $.oc.table.processor.checkbox = CheckboxProcessor; +}(window.jQuery); + +/* ********************************************** + Begin table.processor.dropdown.js +********************************************** */ + +/* + * Drop-down cell processor for the table control. + */ + +/* + * TODO: implement the search + */ + ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.processor === undefined) + throw new Error("The $.oc.table.processor namespace is not defined. Make sure that the table.processor.base.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.processor.base, + BaseProto = Base.prototype + + var DropdownProcessor = function(tableObj, columnName, columnConfiguration) { + // + // State properties + // + + this.itemListElement = null + + this.cachedOptionPromises = {} + + // Event handlers + this.itemClickHandler = this.onItemClick.bind(this) + this.itemKeyDownHandler = this.onItemKeyDown.bind(this) + + // + // Parent constructor + // + + Base.call(this, tableObj, columnName, columnConfiguration) + } + + DropdownProcessor.prototype = Object.create(BaseProto) + DropdownProcessor.prototype.constructor = DropdownProcessor + + DropdownProcessor.prototype.dispose = function() { + this.unregisterListHandlers() + this.itemClickHandler = null + this.itemKeyDownHandler = null + this.itemListElement = null + this.cachedOptionPromises = null + BaseProto.dispose.call(this) + } + + DropdownProcessor.prototype.unregisterListHandlers = function() { + if (this.itemListElement) + { + // This processor binds custom click handler to the item list, + // the standard registerHandlers/unregisterHandlers functionality + // can't be used here because the element belongs to the document + // body, not to the table. + this.itemListElement.removeEventListener('click', this.itemClickHandler) + this.itemListElement.removeEventListener('keydown', this.itemKeyDownHandler) + } + } + + /* + * Renders the cell in the normal (no edit) mode + */ + DropdownProcessor.prototype.renderCell = function(value, cellContentContainer) { + var viewContainer = this.createViewContainer(cellContentContainer, '...') + + this.fetchOptions(cellContentContainer.parentNode, function renderCellFetchOptions(options) { + if (options[value] !== undefined) + viewContainer.textContent = options[value] + + cellContentContainer.setAttribute('tabindex', 0) + }) + } + + /* + * This method is called when the cell managed by the processor + * is focused (clicked or navigated with the keyboard). + */ + DropdownProcessor.prototype.onFocus = function(cellElement, isClick) { + if (this.activeCell === cellElement) { + this.showDropdown() + return + } + + this.activeCell = cellElement + var cellContentContainer = this.getCellContentContainer(cellElement) + this.buildEditor(cellElement, cellContentContainer, isClick) + + if (!isClick) + cellContentContainer.focus() + } + + /* + * Forces the processor to hide the editor when the user navigates + * away from the cell. Processors can update the sell value in this method. + * Processors must clear the reference to the active cell in this method. + */ + DropdownProcessor.prototype.onUnfocus = function() { + if (!this.activeCell) + return + + this.unregisterListHandlers() + + this.hideDropdown() + this.itemListElement = null + this.activeCell = null + } + + DropdownProcessor.prototype.buildEditor = function(cellElement, cellContentContainer, isClick) { + // Create the select control + var currentValue = this.tableObj.getCellValue(cellElement), + containerPosition = this.getAbsolutePosition(cellContentContainer) + self = this + + this.itemListElement = document.createElement('div') + + this.itemListElement.addEventListener('click', this.itemClickHandler) + this.itemListElement.addEventListener('keydown', this.itemKeyDownHandler) + + this.itemListElement.setAttribute('class', 'table-control-dropdown-list') + this.itemListElement.style.width = cellContentContainer.offsetWidth + 'px' + this.itemListElement.style.left = containerPosition.left + 'px' + this.itemListElement.style.top = containerPosition.top - 2 + cellContentContainer.offsetHeight + 'px' + + this.fetchOptions(cellElement, function renderCellFetchOptions(options) { + var listElement = document.createElement('ul') + + for (var value in options) { + var itemElement = document.createElement('li') + itemElement.setAttribute('data-value', value) + itemElement.textContent = options[value] + itemElement.setAttribute('tabindex', 0) + + if (value == currentValue) + itemElement.setAttribute('class', 'selected') + + listElement.appendChild(itemElement) + } + + self.itemListElement.appendChild(listElement) + + if (isClick) + self.showDropdown() + + self = null + }) + } + + /* + * Hide the drop-down, but don't delete it. + */ + DropdownProcessor.prototype.hideDropdown = function() { + if (this.itemListElement && this.activeCell && this.itemListElement.parentNode) { + var cellContentContainer = this.getCellContentContainer(this.activeCell) + cellContentContainer.setAttribute('data-dropdown-open', 'false') + + this.itemListElement.parentNode.removeChild(this.itemListElement) + + cellContentContainer.focus() + } + } + + DropdownProcessor.prototype.showDropdown = function() { + if (this.itemListElement && this.itemListElement.parentNode !== document.body) { + this.getCellContentContainer(this.activeCell).setAttribute('data-dropdown-open', 'true') + document.body.appendChild(this.itemListElement) + + var activeItemElement = this.itemListElement.querySelector('ul li.selected') + + if (!activeItemElement) { + activeItemElement = this.itemListElement.querySelector('ul li:first-child') + + 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) + else { + // If options are not provided and not found in the cache, + // request them from the server. For dependent drop-downs + // the caching key contains the master column values. + + var row = cellElement.parentNode, + cachingKey = this.createOptionsCachingKey(row), + viewContainer = this.getViewContainer(cellElement) + + // Request options from the server. When the table widget builds, + // multiple cells in the column could require loading the options. + // The AJAX promises are cached here so that we have a single + // request per caching key. + + viewContainer.setAttribute('class', 'loading') + + if (!this.cachedOptionPromises[cachingKey]) { + var requestData = { + column: this.columnName, + rowData: this.tableObj.getRowData(row) + }, + handlerName = this.tableObj.getAlias()+'::onGetDropdownOptions' + + this.cachedOptionPromises[cachingKey] = this.tableObj.$el.request(handlerName, {data: requestData}) + } + + this.cachedOptionPromises[cachingKey].done(function onDropDownLoadOptionsSuccess(data){ + onSuccess(data.options) + }).always(function onDropDownLoadOptionsAlways(){ + viewContainer.setAttribute('class', '') + }) + } + } + + DropdownProcessor.prototype.createOptionsCachingKey = function(row) { + var cachingKey = 'non-dependent', + dependsOn = this.columnConfiguration.dependsOn + + if (dependsOn) { + if (typeof dependsOn == 'object') { + for (var i = 0, len = dependsOn.length; i < len; i++ ) + cachingKey += dependsOn[i] + this.tableObj.getRowCellValueByColumnName(row, dependsOn[i]) + } else + cachingKey = dependsOn + this.tableObj.getRowCellValueByColumnName(row, dependsOn) + } + + return cachingKey + } + + DropdownProcessor.prototype.getAbsolutePosition = function(element) { + // TODO: refactor to a core library + + var top = document.body.scrollTop, + left = 0 + + do { + top += element.offsetTop || 0; + top -= element.scrollTop || 0; + left += element.offsetLeft || 0; + element = element.offsetParent; + } while(element) + + return { + top: top, + left: left + } + } + + DropdownProcessor.prototype.updateCellFromSelectedItem = function(selectedItem) { + this.tableObj.setCellValue(this.activeCell, selectedItem.getAttribute('data-value')) + this.setViewContainerValue(this.activeCell, selectedItem.textContent) + } + + DropdownProcessor.prototype.findSelectedItem = function() { + if (this.itemListElement) + return this.itemListElement.querySelector('ul li.selected') + + return null + } + + DropdownProcessor.prototype.onItemClick = function(ev) { + var target = this.tableObj.getEventTarget(ev) + + if (target.tagName == 'LI') { + this.updateCellFromSelectedItem(target) + + var selected = this.findSelectedItem() + if (selected) + selected.setAttribute('class', '') + + target.setAttribute('class', 'selected') + this.hideDropdown() + } + } + + DropdownProcessor.prototype.onItemKeyDown = function(ev) { + if (!this.itemListElement) + return + + if (ev.keyCode == 40 || ev.keyCode == 38) + { + // Up or down keys - find previous/next list item and select it + var selected = this.findSelectedItem(), + newSelectedItem = selected.nextElementSibling + + if (ev.keyCode == 38) + newSelectedItem = selected.previousElementSibling + + if (newSelectedItem) { + selected.setAttribute('class', '') + newSelectedItem.setAttribute('class', 'selected') + newSelectedItem.focus() + } + + return + } + + if (ev.keyCode == 13 || ev.keyCode == 32) { + // Return or space keys - update the selected value and hide the editor + this.updateCellFromSelectedItem(this.findSelectedItem()) + + this.hideDropdown() + return + } + + if (ev.keyCode == 9) { + // Tab - update the selected value and pass control to the table navigation + this.updateCellFromSelectedItem(this.findSelectedItem()) + this.tableObj.navigation.navigateNext(ev) + this.tableObj.stopEvent(ev) + } + + if (ev.keyCode == 27) { + // Esc - hide the drop-down + this.hideDropdown() + } + } + + /* + * Event handler for the keydown event. The table class calls this method + * for all processors. + */ + DropdownProcessor.prototype.onKeyDown = function(ev) { + if (ev.keyCode == 32) + this.showDropdown() + } + + /* + * This method is called when a cell value in the row changes. + */ + DropdownProcessor.prototype.onRowValueChanged = function(columnName, cellElement) { + // Determine if this drop-down depends on the changed column + // and update the option list if necessary + + if (!this.columnConfiguration.dependsOn) + return + + var dependsOnColumn = false, + dependsOn = this.columnConfiguration.dependsOn + + if (typeof dependsOn == 'object') { + for (var i = 0, len = dependsOn.length; i < len; i++ ) { + if (dependsOn[i] == columnName) { + dependsOnColumn = true + break + } + } + } + else { + dependsOnColumn = dependsOn == columnName + } + + if (!dependsOnColumn) + return + + var currentValue = this.tableObj.getCellValue(cellElement), + viewContainer = this.getViewContainer(cellElement) + + this.fetchOptions(cellElement, function rowValueChangedFetchOptions(options) { + var value = options[currentValue] !== undefined + ? options[currentValue] + : '...' + + viewContainer.textContent = value + viewContainer = null + }) + } + + /* + * Determines whether the specified element is some element created by the + * processor. + */ + DropdownProcessor.prototype.elementBelongsToProcessor = function(element) { + if (!this.itemListElement) + return false + + return this.tableObj.parentContainsElement(this.itemListElement, element) + } + + $.oc.table.processor.dropdown = DropdownProcessor; +}(window.jQuery); + +/* ********************************************** + Begin table.processor.string.js +********************************************** */ + +/* + * String cell processor for the table control. + * The string processor allows to edit cell values with a simple + * input control. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.processor === undefined) + throw new Error("The $.oc.table.processor namespace is not defined. Make sure that the table.processor.base.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.processor.base, + BaseProto = Base.prototype + + var StringProcessor = function(tableObj, columnName, columnConfiguration) { + // + // State properties + // + + this.focusTimeoutHandler = this.onFocusTimeout.bind(this) + + // + // Parent constructor + // + + Base.call(this, tableObj, columnName, columnConfiguration) + } + + StringProcessor.prototype = Object.create(BaseProto) + StringProcessor.prototype.constructor = StringProcessor + + StringProcessor.prototype.dispose = function() { + BaseProto.dispose.call(this) + this.focusTimeoutHandler = null + } + + /* + * Renders the cell in the normal (no edit) mode + */ + StringProcessor.prototype.renderCell = function(value, cellContentContainer) { + this.createViewContainer(cellContentContainer, value) + } + + /* + * This method is called when the cell managed by the processor + * is focused (clicked or navigated with the keyboard). + */ + StringProcessor.prototype.onFocus = function(cellElement, isClick) { + if (this.activeCell === cellElement) + return + + this.activeCell = cellElement + this.buildEditor(cellElement, this.getCellContentContainer(cellElement)) + } + + /* + * Forces the processor to hide the editor when the user navigates + * away from the cell. Processors can update the sell value in this method. + * Processors must clear the reference to the active cell in this method. + */ + StringProcessor.prototype.onUnfocus = function() { + if (!this.activeCell) + return + + var editor = this.activeCell.querySelector('.string-input') + if (editor) { + // Update the cell value and remove the editor + this.tableObj.setCellValue(this.activeCell, editor.value) + this.setViewContainerValue(this.activeCell, editor.value) + editor.parentNode.removeChild(editor) + } + + this.showViewContainer(this.activeCell) + this.activeCell = null + } + + StringProcessor.prototype.buildEditor = function(cellElement, cellContentContainer) { + // Hide the view container + this.hideViewContainer(this.activeCell) + + // Create the input control + var input = document.createElement('input') + input.setAttribute('type', 'text') + input.setAttribute('class', 'string-input') + input.value = this.tableObj.getCellValue(cellElement) + cellContentContainer.appendChild(input) + + this.setCaretPosition(input, 0) + + // Focus the element in the next frame. + // http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful + window.setTimeout(this.focusTimeoutHandler, 0) + } + + /* + * Determines if the keyboard navigation in the specified direction is allowed + * by the cell processor. Some processors could reject the navigation, for example + * the string processor could cancel the left array navigation if the caret + * in the text input is not in the beginning of the text. + */ + StringProcessor.prototype.keyNavigationAllowed = function(ev, direction) { + if (direction != 'left' && direction != 'right') + return true + + if (!this.activeCell) + return true + + var editor = this.activeCell.querySelector('.string-input') + if (!editor) + return true + + var caretPosition = this.getCaretPosition(editor) + + if (direction == 'left') + return caretPosition == 0 + + if (direction == 'right') + return caretPosition == editor.value.length + + return true + } + + StringProcessor.prototype.onFocusTimeout = function() { + if (!this.activeCell) + return + + var editor = this.activeCell.querySelector('.string-input') + if (!editor) + return + + editor.focus() + this.setCaretPosition(editor, 0) + } + + StringProcessor.prototype.getCaretPosition = function(input) { + // TODO: refactor to a core library + + if (document.selection) { + var selection = document.selection.createRange() + + selection.moveStart('character', -input.value.length) + return selection.text.length + } + + if (input.selectionStart !== undefined) + return input.selectionStart + + return 0 + } + + StringProcessor.prototype.setCaretPosition = function(input, position) { + // TODO: refactor to a core library + + if (document.selection) { + var range = input.createTextRange() + + setTimeout(function() { + // Asynchronous layout update, better performance + range.collapse(true) + range.moveStart("character", position) + range.moveEnd("character", 0) + range.select() + }, 0) + } + + if (input.selectionStart !== undefined) { + setTimeout(function() { + // Asynchronous layout update + input.selectionStart = position + input.selectionEnd = position + }, 0) + } + + return 0 + } + + $.oc.table.processor.string = StringProcessor; +}(window.jQuery); + +/* ********************************************** + Begin table.validator.base.js +********************************************** */ + +/* + * Base class for the table validators. + */ ++function ($) { "use strict"; + + // VALIDATOR NAMESPACES + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.validator === undefined) + $.oc.table.validator = {} + + // CLASS DEFINITION + // ============================ + + var Base = function(options) { + // + // State properties + // + + this.options = options + } + + /* + * Validates a value and returns the error message. If there + * are no errors, returns undefined. + * The rowData parameter is an object containing all values in the + * target row. + */ + Base.prototype.validate = function(value, rowData) { + if (this.options.requiredWith !== undefined && !this.rowHasValue(this.options.requiredWith, rowData)) + return + + return this.validateValue(value, rowData) + } + + /* + * Validates a value and returns the error message. If there + * are no errors, returns undefined. This method should be redefined + * in descendant classes. + * The rowData parameter is an object containing all values in the + * target row. + */ + Base.prototype.validateValue = function(value, rowData) { + + } + + Base.prototype.trim = function(value) { + if (String.prototype.trim) + return value.trim() + + return value.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '') + } + + Base.prototype.getMessage = function(defaultValue) { + if (this.options.message !== undefined) + return this.options.message + + return defaultValue + } + + Base.prototype.rowHasValue = function(columnName, rowData) { + if (rowData[columnName] === undefined) + return false + + if (typeof rowData[columnName] == 'boolean') + return rowData[columnName] + + var value = this.trim(String(rowData[columnName])) + + return value.length > 0 + } + + $.oc.table.validator.base = Base; +}(window.jQuery); + +/* ********************************************** + Begin table.validator.required.js +********************************************** */ + +/* + * Required table validator. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.validator === undefined) + throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.validator.base, + BaseProto = Base.prototype + + var Required = function(options) { + Base.call(this, options) + }; + + Required.prototype = Object.create(BaseProto) + Required.prototype.constructor = Required + + /* + * Validates a value and returns the error message. If there + * are no errors, returns undefined. + * The rowData parameter is an object containing all values in the + * target row. + */ + Required.prototype.validateValue = function(value, rowData) { + value = this.trim(value) + + if (value.length === 0) + return this.getMessage("The value should not be empty.") + + return + } + + $.oc.table.validator.required = Required +}(window.jQuery); + +/* ********************************************** + Begin table.validator.basenumber.js +********************************************** */ + +/* + * Base class for number validators. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.validator === undefined) + throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.validator.base, + BaseProto = Base.prototype + + var BaseNumber = function(options) { + Base.call(this, options) + }; + + BaseNumber.prototype = Object.create(BaseProto) + BaseNumber.prototype.constructor = BaseNumber + + BaseNumber.prototype.doCommonChecks = function(value) { + if (this.options.min !== undefined || this.options.max !== undefined) { + if (this.options.min !== undefined) { + if (this.options.min.value === undefined) + throw new Error('The min.value parameter is not defined in the table validator configuration') + + if (value < this.options.min.value) { + return this.options.min.message !== undefined ? + this.options.min.message : + "The value should not be less than " + this.options.min.value + } + } + + if (this.options.max !== undefined) { + if (this.options.max.value === undefined) + throw new Error('The max.value parameter is not defined in the table validator configuration') + + if (value > this.options.max.value) { + return this.options.max.message !== undefined ? + this.options.max.message : + "The value should not be more than " + this.options.max.value + } + } + } + + return + } + + $.oc.table.validator.baseNumber = BaseNumber +}(window.jQuery); + +/* ********************************************** + Begin table.validator.integer.js +********************************************** */ + +/* + * Integer table validator. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.validator === undefined) + throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded."); + + if ($.oc.table.validator.baseNumber === undefined) + throw new Error("The $.oc.table.validator.baseNumber namespace is not defined. Make sure that the table.validator.baseNumber.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.validator.baseNumber, + BaseProto = Base.prototype + + var Integer = function(options) { + Base.call(this, options) + }; + + Integer.prototype = Object.create(BaseProto) + Integer.prototype.constructor = Integer + + /* + * Validates a value and returns the error message. If there + * are no errors, returns undefined. + * The rowData parameter is an object containing all values in the + * target row. + */ + Integer.prototype.validateValue = function(value, rowData) { + value = this.trim(value) + + if (value.length == 0) + return + + var testResult = this.options.allowNegative ? + /^\-?[0-9]*$/.test(value) : + /^[0-9]*$/.test(value) + + if (!testResult) { + var defaultMessage = this.options.allowNegative ? + 'The value should be an integer.' : + 'The value should be a positive integer'; + + return this.getMessage(defaultMessage) + } + + return this.doCommonChecks(parseInt(value)) + } + + $.oc.table.validator.integer = Integer +}(window.jQuery); + +/* ********************************************** + Begin table.validator.float.js +********************************************** */ + +/* + * Float table validator. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.validator === undefined) + throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded."); + + if ($.oc.table.validator.baseNumber === undefined) + throw new Error("The $.oc.table.validator.baseNumber namespace is not defined. Make sure that the table.validator.baseNumber.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.validator.baseNumber, + BaseProto = Base.prototype + + var Float = function(options) { + Base.call(this, options) + }; + + Float.prototype = Object.create(BaseProto) + Float.prototype.constructor = Float + + /* + * Validates a value and returns the error message. If there + * are no errors, returns undefined. + * The rowData parameter is an object containing all values in the + * target row. + */ + Float.prototype.validateValue = function(value, rowData) { + value = this.trim(value) + + if (value.length == 0) + return + + var testResult = this.options.allowNegative ? + /^[-]?([0-9]+\.[0-9]+|[0-9]+)$/.test(value) : + /^([0-9]+\.[0-9]+|[0-9]+)$/.test(value) + + if (!testResult) { + var defaultMessage = this.options.allowNegative ? + 'The value should be a floating point number.' : + 'The value should be a positive floating point number'; + + return this.getMessage(defaultMessage) + } + + return this.doCommonChecks(parseFloat(value)) + } + + $.oc.table.validator.float = Float +}(window.jQuery); + +/* ********************************************** + Begin table.validator.length.js +********************************************** */ + +/* + * String length table validator. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.validator === undefined) + throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.validator.base, + BaseProto = Base.prototype + + var Length = function(options) { + Base.call(this, options) + }; + + Length.prototype = Object.create(BaseProto) + Length.prototype.constructor = Length + + /* + * Validates a value and returns the error message. If there + * are no errors, returns undefined. + * The rowData parameter is an object containing all values in the + * target row. + */ + Length.prototype.validateValue = function(value, rowData) { + value = this.trim(value) + + if (value.length == 0) + return + + if (this.options.min !== undefined || this.options.max !== undefined) { + if (this.options.min !== undefined) { + if (this.options.min.value === undefined) + throw new Error('The min.value parameter is not defined in the Length table validator configuration') + + if (value.length < this.options.min.value) { + return this.options.min.message !== undefined ? + this.options.min.message : + "The string should not be shorter than " + this.options.min.value + } + } + + if (this.options.max !== undefined) { + if (this.options.max.value === undefined) + throw new Error('The max.value parameter is not defined in the Length table validator configuration') + + if (value.length > this.options.max.value) { + return this.options.max.message !== undefined ? + this.options.max.message : + "The string should not be longer than " + this.options.max.value + } + } + } + + return + } + + $.oc.table.validator.length = Length +}(window.jQuery); + +/* ********************************************** + Begin table.validator.regex.js +********************************************** */ + +/* + * Regex length table validator. + */ ++function ($) { "use strict"; + + // NAMESPACE CHECK + // ============================ + + if ($.oc.table === undefined) + throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded."); + + if ($.oc.table.validator === undefined) + throw new Error("The $.oc.table.validator namespace is not defined. Make sure that the table.validator.base.js script is loaded."); + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.table.validator.base, + BaseProto = Base.prototype + + var Regex = function(options) { + Base.call(this, options) + }; + + Regex.prototype = Object.create(BaseProto) + Regex.prototype.constructor = Regex + + /* + * Validates a value and returns the error message. If there + * are no errors, returns undefined. + * The rowData parameter is an object containing all values in the + * target row. + */ + Regex.prototype.validateValue = function(value, rowData) { + value = this.trim(value) + + if (value.length == 0) + return + + if (this.options.pattern === undefined) + throw new Error('The pattern parameter is not defined in the Regex table validator configuration') + + var regexObj = new RegExp(this.options.pattern, this.options.modifiers) + + if (!regexObj.test(value)) + return this.getMessage("Invalid value format.") + + return + } + + $.oc.table.validator.regex = Regex +}(window.jQuery); \ No newline at end of file diff --git a/modules/backend/widgets/table/assets/js/table-min.map b/modules/backend/widgets/table/assets/js/table-min.map deleted file mode 100644 index f16839ac9..000000000 --- a/modules/backend/widgets/table/assets/js/table-min.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"/Users/elf/projects/new-cms/dev/modules/backend/widgets/table/assets/js/table-min.js","sources":["table.js","table.datasource.base.js","table.processor.base.js","table.helper.navigation.js","table.datasource.client.js","table.processor.checkbox.js","table.processor.dropdown.js","table.processor.string.js","table.validator.base.js","table.validator.required.js","table.validator.basenumber.js","table.validator.integer.js","table.validator.float.js","table.validator.length.js","table.validator.regex.js"],"names":["$","undefined","oc","table","Table","element","options","this","el","$el","dataSource","cellProcessors","activeCellProcessor","activeCell","tableContainer","dataTableContainer","editedRowKey","dataTable","headerTable","toolbar","clickHandler","onClick","bind","keydownHandler","onKeydown","documentClickHandler","onDocumentClick","toolbarClickHandler","onToolbarClick","postback","clientDataSourceClass","formSubmitHandler","onFormSubmit","navigation","recordsAddedOrDeleted","init","prototype","createDataSource","initCellProcessors","helper","buildUi","registerHandlers","disposeCellProcessors","i","len","columns","length","column","key","dispose","dataSourceClass","datasource","Error","addEventListener","document","closest","getToolbar","unregisterHandlers","removeEventListener","unbind","columnConfiguration","columnType","type","processor","getCellProcessor","columnName","createElement","setAttribute","buildToolbar","appendChild","buildHeaderTable","insertBefore","children","height","buildScrollbar","updateDataTable","adding","deleting","addBelowButton","paginationEnabled","rowSorting","textContent","addAboveButton","deleteButton","scrollbar","scrollbarContent","dynamicHeight","animation","headersTable","row","className","header","width","title","innerText","onSuccess","self","unfocusTable","fetchRecords","onUpdateDataTableSuccess","records","totalCount","buildDataTable","addRecord","updateColumnWidth","headerCells","querySelectorAll","dataCells","getAttribute","tbody","keyColumn","j","colsLen","cell","dataContainer","cellContentContainer","cellProcessor","value","renderCell","replaceChild","updateScrollbar","buildPagination","getRecords","getPageFirstRowOffset","recordsPerPage","parentNode","data","update","scrollCellIntoView","gotoElement","disposeScrollbar","setActiveProcessor","onUnfocus","commitEditedRow","editedRow","querySelector","cells","getCellValue","updateRecord","elementRemoveClass","focusTable","elementAddClass","focusCell","cellElement","isClick","isCellFocusable","rowKey","getCellRowKey","onFocus","markCellRowDirty","placement","noFocus","relativeToKey","currentRowIndex","getCellRowIndex","newPageIndex","getNewRowPage","pageIndex","validate","recordData","createRecord","onAddRecordDataTableSuccess","findRowByKey","deleteRecord","currentPageIndex","currentCellIndex","cellIndex","getPageAfterDeletion","newRecordData","onDeleteRecordDataTableSuccess","focusCellInReplacedRow","notifyRowProcessorsOnChange","onRowValueChanged","rows","rowsLen","rowData","getRowData","message","flashMsg","text","class","window","setTimeout","ev","target","getEventTarget","tagName","keyCode","altKey","shiftKey","stopEvent","onKeyDown","handler","postbackHandlerName","preventDefault","fieldName","alias","indexOf","getAllData","cmd","parentContainsElement","elementBelongsToProcessor","getElement","getAlias","getTableContainer","getDataTableBody","tag","srcElement","stopPropagation","cancelBubble","returnValue","elementHasClass","classList","contains","RegExp","test","add","remove","replace","split","join","parent","parseInt","findRowByIndex","index","rowIndex","getRowCellValueByColumnName","result","setCellValue","DEFAULTS","old","fn","option","args","Array","slice","call","arguments","each","$this","extend","apply","Constructor","noConflict","on","jQuery","Base","tableObj","offset","count","base","validators","initValidators","keyNavigationAllowed","direction","getCellContentContainer","createViewContainer","viewContainer","getViewContainer","showViewContainer","hideViewContainer","setViewContainerValue","validation","validatorName","validator","push","Navigation","pageCount","recordCount","paginationContainer","newPaginationContainer","curRecordCount","calculatePageCount","getRecordCount","pageList","buildPaginationLinkList","markActiveLinkItem","Math","ceil","container","item","link","activeItem","list","gotoPage","getRowCountOnPage","navigateDown","forceCellIndex","newRow","nextElementSibling","navDownPageSuccess","navigateUp","isTab","previousElementSibling","navUpPageSuccess","navigateLeft","newIndex","navigateRight","navigateNext","rowReference","focusRow","BaseProto","Client","dataString","JSON","parse","Object","create","constructor","recordIndex","getIndexOfKey","splice","map","record","client","CheckboxProcessor","checkbox","focus","changeState","divElement","DropdownProcessor","itemListElement","cachedOptionPromises","itemClickHandler","onItemClick","itemKeyDownHandler","onItemKeyDown","unregisterListHandlers","fetchOptions","renderCellFetchOptions","showDropdown","buildEditor","hideDropdown","currentValue","containerPosition","getAbsolutePosition","style","offsetWidth","left","top","offsetHeight","listElement","itemElement","removeChild","body","activeItemElement","cachingKey","createOptionsCachingKey","requestData","handlerName","request","done","onDropDownLoadOptionsSuccess","always","onDropDownLoadOptionsAlways","dependsOn","scrollTop","offsetTop","offsetLeft","offsetParent","updateCellFromSelectedItem","selectedItem","findSelectedItem","selected","newSelectedItem","dependsOnColumn","rowValueChangedFetchOptions","dropdown","StringProcessor","focusTimeoutHandler","onFocusTimeout","editor","input","setCaretPosition","caretPosition","getCaretPosition","selection","createRange","moveStart","selectionStart","position","range","createTextRange","collapse","moveEnd","select","selectionEnd","string","applyIfNotEmpty","rowHasValue","validateValue","trim","String","getMessage","defaultValue","Required","required","BaseNumber","doCommonChecks","min","max","baseNumber","Integer","testResult","allowNegative","defaultMessage","integer","Float","parseFloat","float","Length","Regex","pattern","regexObj","modifiers","regex"],"mappings":"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","sourceRoot":"./"} \ No newline at end of file diff --git a/modules/backend/widgets/table/assets/js/table.validator.base.js b/modules/backend/widgets/table/assets/js/table.validator.base.js index 5cd900e25..5f92b82b2 100644 --- a/modules/backend/widgets/table/assets/js/table.validator.base.js +++ b/modules/backend/widgets/table/assets/js/table.validator.base.js @@ -30,7 +30,7 @@ * target row. */ Base.prototype.validate = function(value, rowData) { - if (this.options.applyIfNotEmpty !== undefined && !this.rowHasValue(this.options.applyIfNotEmpty, rowData)) + if (this.options.requiredWith !== undefined && !this.rowHasValue(this.options.requiredWith, rowData)) return return this.validateValue(value, rowData)