Skip to content

Commit

Permalink
Improve read-only handling of datatable columns
Browse files Browse the repository at this point in the history
- Style readonly columns with grey background to clearly indicate read-only state
- Prevent editors from being created for all column types if readonly (previously, only string columns would be rendered read-only)
- Allow tab and arrow navigation for readonly columns
  • Loading branch information
bennothommo committed Jan 13, 2025
1 parent 206e738 commit effb570
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 58 deletions.
2 changes: 1 addition & 1 deletion modules/backend/assets/css/winter.css
Original file line number Diff line number Diff line change
Expand Up @@ -1103,4 +1103,4 @@ html.cssanimations .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.f
.flyout-toggle i{margin:7px 0 0 6px;display:inline-block}
.flyout-toggle:hover i{color:#fff}
body.flyout-visible{overflow:hidden}
body.flyout-visible .flyout-overlay{background-color:rgba(0,0,0,0.3)}
body.flyout-visible .flyout-overlay{background-color:rgba(0,0,0,0.3)}
6 changes: 3 additions & 3 deletions modules/backend/formwidgets/codeeditor/assets/js/build-min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -540,4 +540,4 @@ case'undo-resizing':this.undoResizing()
break}}
MediaManagerImageCropPopup.prototype.onSelectionChanged=function(c){this.updateSelectionSizeLabel(c.w,c.h)}
MediaManagerImageCropPopup.DEFAULTS={alias:undefined,onDone:undefined}
$.wn.mediaManager.imageCropPopup=MediaManagerImageCropPopup}(window.jQuery);
$.wn.mediaManager.imageCropPopup=MediaManagerImageCropPopup}(window.jQuery);
20 changes: 10 additions & 10 deletions modules/backend/widgets/table/assets/css/table.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 12 additions & 11 deletions modules/backend/widgets/table/assets/js/build-min.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,7 @@ return}for(var i=0,len=this.options.columns.length;i<len;i++){var column=this.op
if(this.cellProcessors[column].onKeyDown(ev)===false){return}}if(this.navigation.onKeydown(ev)===false){return}if(this.search.onKeydown(ev)===false){return}}
Table.prototype.onFormSubmit=function(ev,data){if(data.handler==this.options.postbackHandlerName){this.unfocusTable()
if(!this.validate()){ev.preventDefault()
return}
data.options.data[this.options.fieldName]=this.dataSource.getAllData()}}
return}data.options.data[this.options.fieldName]=this.dataSource.getAllData()}}
Table.prototype.onToolbarClick=function(ev){var target=this.getEventTarget(ev),cmd=target.getAttribute('data-cmd')
if(!cmd){return}switch(cmd){case'record-add':case'record-add-below':this.addRecord('below')
break
Expand Down Expand Up @@ -513,10 +512,10 @@ StringProcessor.prototype=Object.create(BaseProto)
StringProcessor.prototype.constructor=StringProcessor
StringProcessor.prototype.dispose=function(){BaseProto.dispose.call(this)
this.focusTimeoutHandler=null}
StringProcessor.prototype.renderCell=function(value,cellContentContainer){this.createViewContainer(cellContentContainer,value)}
StringProcessor.prototype.renderCell=function(value,cellContentContainer){this.createViewContainer(cellContentContainer,value);if(this.columnConfiguration.readonly||this.columnConfiguration.readOnly){cellContentContainer.classList.add('readonly');cellContentContainer.setAttribute('tabindex',0);}}
StringProcessor.prototype.onFocus=function(cellElement,isClick){if(this.activeCell===cellElement)return
this.activeCell=cellElement
this.buildEditor(cellElement,this.getCellContentContainer(cellElement))}
if(!this.columnConfiguration.readonly&&!this.columnConfiguration.readOnly){this.buildEditor(cellElement,this.getCellContentContainer(cellElement))}else{this.getCellContentContainer(cellElement).focus()}}
StringProcessor.prototype.onUnfocus=function(){if(!this.activeCell)return
var editor=this.activeCell.querySelector('.string-input')
if(editor){this.tableObj.setCellValue(this.activeCell,editor.value)
Expand All @@ -528,7 +527,7 @@ var input=document.createElement('input')
input.setAttribute('type','text')
input.setAttribute('class','string-input')
input.value=this.tableObj.getCellValue(cellElement)
if(this.columnConfiguration.readOnly){input.setAttribute('readonly',true)}cellContentContainer.appendChild(input)
cellContentContainer.appendChild(input)
this.setCaretPosition(input,0)
window.setTimeout(this.focusTimeoutHandler,0)}
StringProcessor.prototype.keyNavigationAllowed=function(ev,direction){if(direction!='left'&&direction!='right')return true
Expand Down Expand Up @@ -565,10 +564,11 @@ CheckboxProcessor.prototype.isCellFocusable=function(){return false}
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)}
if(value&&value!=0&&value!="false"){checkbox.setAttribute('class','checked')}cellContentContainer.appendChild(checkbox)
if(this.columnConfiguration.readonly||this.columnConfiguration.readOnly){cellContentContainer.classList.add('readonly');}}
CheckboxProcessor.prototype.onFocus=function(cellElement,isClick){cellElement.querySelector('div[data-checkbox-element]').focus()}
CheckboxProcessor.prototype.onKeyDown=function(ev){if(ev.key==='(Space character)'||ev.key==='Spacebar'||ev.key===' ')this.onClick(ev)}
CheckboxProcessor.prototype.onClick=function(ev){var target=this.tableObj.getEventTarget(ev,'DIV')
CheckboxProcessor.prototype.onClick=function(ev){if(this.columnConfiguration.readonly||this.columnConfiguration.readOnly){return}var target=this.tableObj.getEventTarget(ev,'DIV')
if(target.getAttribute('data-checkbox-element')){var container=this.getCheckboxContainerNode(target)
if(container.getAttribute('data-column')!==this.columnName){return}this.changeState(target)
$(ev.target).trigger('change')}}
Expand Down Expand Up @@ -601,14 +601,15 @@ BaseProto.dispose.call(this)}
DropdownProcessor.prototype.unregisterListHandlers=function(){if(this.itemListElement){this.itemListElement.removeEventListener('click',this.itemClickHandler)
this.itemListElement.removeEventListener('keydown',this.itemKeyDownHandler)
this.itemListElement.removeEventListener('mousemove',this.itemMouseMoveHandler)}}
DropdownProcessor.prototype.renderCell=function(value,cellContentContainer){var viewContainer=this.createViewContainer(cellContentContainer,'...')
DropdownProcessor.prototype.renderCell=function(value,cellContentContainer){let viewContainer;if(this.columnConfiguration.readonly||this.columnConfiguration.readOnly){viewContainer=this.createViewContainer(cellContentContainer,value)
cellContentContainer.classList.add('readonly');cellContentContainer.setAttribute('tabindex',0);return;}viewContainer=this.createViewContainer(cellContentContainer,'...')
this.fetchOptions(cellContentContainer.parentNode,function renderCellFetchOptions(options){if(options[value]!==undefined)viewContainer.textContent=options[value]
cellContentContainer.setAttribute('tabindex',0)})}
DropdownProcessor.prototype.onFocus=function(cellElement,isClick){if(this.activeCell===cellElement){this.showDropdown()
return}this.activeCell=cellElement
var cellContentContainer=this.getCellContentContainer(cellElement)
if(!this.columnConfiguration.readonly&&!this.columnConfiguration.readOnly){var cellContentContainer=this.getCellContentContainer(cellElement)
this.buildEditor(cellElement,cellContentContainer,isClick)
if(!isClick)cellContentContainer.focus()}
if(!isClick){cellContentContainer.focus()}}else{this.getCellContentContainer(cellElement).focus()}}
DropdownProcessor.prototype.onUnfocus=function(){if(!this.activeCell)return
this.unregisterListHandlers()
this.hideDropdown()
Expand Down Expand Up @@ -699,7 +700,7 @@ AutocompleteProcessor.prototype.onUnfocus=function(){if(!this.activeCell)return
this.removeAutocomplete()
BaseProto.onUnfocus.call(this)}
AutocompleteProcessor.prototype.renderCell=function(value,cellContentContainer){BaseProto.renderCell.call(this,value,cellContentContainer)}
AutocompleteProcessor.prototype.buildEditor=function(cellElement,cellContentContainer,isClick){BaseProto.buildEditor.call(this,cellElement,cellContentContainer,isClick)
AutocompleteProcessor.prototype.buildEditor=function(cellElement,cellContentContainer,isClick){if(this.columnConfiguration.readonly||this.columnConfiguration.readOnly){return}BaseProto.buildEditor.call(this,cellElement,cellContentContainer,isClick)
var self=this
this.fetchOptions(cellElement,function autocompleteFetchOptions(options){self.buildAutoComplete(options)
self=null})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@
*/
AutocompleteProcessor.prototype.renderCell = function(value, cellContentContainer) {
BaseProto.renderCell.call(this, value, cellContentContainer)

// this.fetchOptions(cellContentContainer.parentNode)
}

AutocompleteProcessor.prototype.buildEditor = function(cellElement, cellContentContainer, isClick) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
}

cellContentContainer.appendChild(checkbox)

if (this.columnConfiguration.readonly || this.columnConfiguration.readOnly) {
cellContentContainer.classList.add('readonly');
}
}

/*
Expand All @@ -77,6 +81,10 @@
* for all processors.
*/
CheckboxProcessor.prototype.onClick = function(ev) {
if (this.columnConfiguration.readonly || this.columnConfiguration.readOnly) {
return
}

var target = this.tableObj.getEventTarget(ev, 'DIV')

if (target.getAttribute('data-checkbox-element')) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,17 @@
* Renders the cell in the normal (no edit) mode
*/
DropdownProcessor.prototype.renderCell = function(value, cellContentContainer) {
var viewContainer = this.createViewContainer(cellContentContainer, '...')
let viewContainer;

if (this.columnConfiguration.readonly || this.columnConfiguration.readOnly) {
viewContainer = this.createViewContainer(cellContentContainer, value)

cellContentContainer.classList.add('readonly');
cellContentContainer.setAttribute('tabindex', 0);
return;
}

viewContainer = this.createViewContainer(cellContentContainer, '...')

this.fetchOptions(cellContentContainer.parentNode, function renderCellFetchOptions(options) {
if (options[value] !== undefined)
Expand All @@ -98,11 +108,16 @@
}

this.activeCell = cellElement
var cellContentContainer = this.getCellContentContainer(cellElement)
this.buildEditor(cellElement, cellContentContainer, isClick)
if (!this.columnConfiguration.readonly && !this.columnConfiguration.readOnly) {
var cellContentContainer = this.getCellContentContainer(cellElement)
this.buildEditor(cellElement, cellContentContainer, isClick)

if (!isClick)
cellContentContainer.focus()
if (!isClick) {
cellContentContainer.focus()
}
} else {
this.getCellContentContainer(cellElement).focus()
}
}

/*
Expand Down
17 changes: 11 additions & 6 deletions modules/backend/widgets/table/assets/js/table.processor.string.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@
* Renders the cell in the normal (no edit) mode
*/
StringProcessor.prototype.renderCell = function(value, cellContentContainer) {
this.createViewContainer(cellContentContainer, value)
this.createViewContainer(cellContentContainer, value);

if (this.columnConfiguration.readonly || this.columnConfiguration.readOnly) {
cellContentContainer.classList.add('readonly');
cellContentContainer.setAttribute('tabindex', 0);
}
}

/*
Expand All @@ -58,7 +63,11 @@
return

this.activeCell = cellElement
this.buildEditor(cellElement, this.getCellContentContainer(cellElement))
if (!this.columnConfiguration.readonly && !this.columnConfiguration.readOnly) {
this.buildEditor(cellElement, this.getCellContentContainer(cellElement))
} else {
this.getCellContentContainer(cellElement).focus()
}
}

/*
Expand Down Expand Up @@ -92,10 +101,6 @@
input.setAttribute('class', 'string-input')
input.value = this.tableObj.getCellValue(cellElement)

if (this.columnConfiguration.readOnly) {
input.setAttribute('readonly', true)
}

cellContentContainer.appendChild(input)

this.setCaretPosition(input, 0)
Expand Down
Loading

0 comments on commit effb570

Please sign in to comment.