ORIENT/modules/backend/widgets/table/assets/js/table.processor.string.js

199 lines
6.1 KiB
JavaScript
Raw Normal View History

/*
* 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
2014-12-04 06:48:16 +00:00
var StringProcessor = function(tableObj, columnName, columnConfiguration) {
//
// State properties
//
2014-11-17 05:48:40 +00:00
this.focusTimeoutHandler = this.onFocusTimeout.bind(this)
//
// Parent constructor
//
2014-12-04 06:48:16 +00:00
Base.call(this, tableObj, columnName, columnConfiguration)
}
StringProcessor.prototype = Object.create(BaseProto)
StringProcessor.prototype.constructor = StringProcessor
2014-11-17 05:48:40 +00:00
StringProcessor.prototype.dispose = function() {
BaseProto.dispose.call(this)
this.focusTimeoutHandler = null
}
/*
* Renders the cell in the normal (no edit) mode
*/
2014-12-02 06:31:11 +00:00
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
2014-12-02 06:31:11 +00:00
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
}
2014-12-02 06:31:11 +00:00
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)
2014-12-02 06:31:11 +00:00
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)
}
2014-11-17 05:48:40 +00:00
/*
* 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
}
/*
* This method is called when a cell value in the row changes.
*/
StringProcessor.prototype.onRowValueChanged = function(columnName, cellElement) {
if (columnName != this.columnName) {
return
}
var value = this.tableObj.getCellValue(cellElement)
this.setViewContainerValue(cellElement, value)
}
2014-11-17 05:48:40 +00:00
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: use the foundation library
2014-11-17 05:48:40 +00:00
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: use the foundation library
2014-11-17 05:48:40 +00:00
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)
2014-11-17 05:48:40 +00:00
}
if (input.selectionStart !== undefined) {
setTimeout(function() {
// Asynchronous layout update
input.selectionStart = position
input.selectionEnd = position
}, 0)
2014-11-17 05:48:40 +00:00
}
return 0
}
$.oc.table.processor.string = StringProcessor;
}(window.jQuery);