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

215 lines
6.7 KiB
JavaScript

/*
* Autocomplete 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.string,
BaseProto = Base.prototype
var AutocompleteProcessor = function(tableObj, columnName, columnConfiguration) {
//
// State properties
//
this.cachedOptionPromises = {}
//
// Parent constructor
//
Base.call(this, tableObj, columnName, columnConfiguration)
}
AutocompleteProcessor.prototype = Object.create(BaseProto)
AutocompleteProcessor.prototype.constructor = AutocompleteProcessor
AutocompleteProcessor.prototype.dispose = function() {
this.cachedOptionPromises = null
BaseProto.dispose.call(this)
}
/*
* 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.
*/
AutocompleteProcessor.prototype.onUnfocus = function() {
if (!this.activeCell)
return
this.removeAutocomplete()
BaseProto.onUnfocus.call(this)
}
/*
* Renders the cell in the normal (no edit) mode
*/
AutocompleteProcessor.prototype.renderCell = function(value, cellContentContainer) {
BaseProto.renderCell.call(this, value, cellContentContainer)
// this.fetchOptions(cellContentContainer.parentNode)
}
AutocompleteProcessor.prototype.buildEditor = function(cellElement, cellContentContainer, isClick) {
BaseProto.buildEditor.call(this, cellElement, cellContentContainer, isClick)
var self = this
this.fetchOptions(cellElement, function autocompleteFetchOptions(options) {
self.buildAutoComplete(options)
self = null
})
}
AutocompleteProcessor.prototype.fetchOptions = function(cellElement, onSuccess) {
if (this.columnConfiguration.options) {
if (onSuccess !== undefined) {
onSuccess(this.columnConfiguration.options)
}
} else {
// If options are not provided and not found in the cache,
// request them from the server. For dependent autocomplete editors
// the caching key contains the master column values.
if (this.triggerGetOptions(onSuccess) === false) {
return
}
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.
$.oc.foundation.element.addClass(viewContainer, 'loading')
if (!this.cachedOptionPromises[cachingKey]) {
var requestData = {
column: this.columnName,
rowData: this.tableObj.getRowData(row)
},
handlerName = this.tableObj.getAlias()+'::onGetAutocompleteOptions'
this.cachedOptionPromises[cachingKey] = this.tableObj.$el.request(handlerName, {data: requestData})
}
this.cachedOptionPromises[cachingKey].done(function onAutocompleteLoadOptionsSuccess(data){
if (onSuccess !== undefined) {
onSuccess(data.options)
}
}).always(function onAutocompleteLoadOptionsAlways(){
$.oc.foundation.element.removeClass(viewContainer, 'loading')
})
}
}
AutocompleteProcessor.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
}
AutocompleteProcessor.prototype.triggerGetOptions = function(callback) {
var tableElement = this.tableObj.getElement()
if (!tableElement) {
return
}
var optionsEvent = $.Event('autocompleteitems.oc.table'),
values = {} // TODO - implement loading values from the current row.
$(tableElement).trigger(optionsEvent, [{
values: values,
callback: callback,
column: this.columnName,
columnConfiguration: this.columnConfiguration
}])
if (optionsEvent.isDefaultPrevented()) {
return false
}
return true
}
AutocompleteProcessor.prototype.getInput = function() {
if (!this.activeCell) {
return null
}
return this.activeCell.querySelector('.string-input')
}
AutocompleteProcessor.prototype.buildAutoComplete = function(items) {
if (!this.activeCell) {
return
}
var input = this.getInput()
if (!input) {
return
}
if (items === undefined) {
items = []
}
$(input).autocomplete({
source: this.prepareItems(items),
matchWidth: true,
menu: '<ul class="autocomplete dropdown-menu table-widget-autocomplete"></ul>',
bodyContainer: true
})
}
AutocompleteProcessor.prototype.prepareItems = function(items) {
var result = {}
if ($.isArray(items)) {
for (var i = 0, len = items.length; i < len; i++) {
result[items[i]] = items[i]
}
}
else {
result = items
}
return result
}
AutocompleteProcessor.prototype.removeAutocomplete = function() {
var input = this.getInput()
$(input).autocomplete('destroy')
}
$.oc.table.processor.autocomplete = AutocompleteProcessor;
}(window.jQuery);