Implementing AJAX loading for drop-down options, in progress.
This commit is contained in:
parent
4b28ee8bcb
commit
f56bfe12d0
|
|
@ -36,9 +36,9 @@
|
|||
<script src="<?= Backend::skinAsset('assets/vendor/flot/jquery.flot.resize.js') ?>"></script>
|
||||
<script src="<?= Backend::skinAsset('assets/vendor/flot/jquery.flot.time.js') ?>"></script>
|
||||
|
||||
<script src="<?= Backend::skinAsset('assets/js/october.controls.js') ?>"></script>
|
||||
<script src="<?= Backend::skinAsset('assets/js/october.controls.js') ?>"></script> -->
|
||||
<script src="<?= Backend::skinAsset('assets/js/october.utils.js') ?>"></script>
|
||||
<script src="<?= Backend::skinAsset('assets/js/october.triggerapi.js') ?>"></script>
|
||||
<!--<script src="<?= Backend::skinAsset('assets/js/october.triggerapi.js') ?>"></script>
|
||||
<script src="<?= Backend::skinAsset('assets/js/october.dragscroll.js') ?>"></script>
|
||||
<script src="<?= Backend::skinAsset('assets/js/october.toolbar.js') ?>"></script>
|
||||
<script src="<?= Backend::skinAsset('assets/js/october.verticalmenu.js') ?>"></script>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php namespace Backend\Widgets;
|
||||
|
||||
use Input;
|
||||
use Backend\Classes\WidgetBase;
|
||||
|
||||
/**
|
||||
|
|
@ -90,4 +91,27 @@ class Table extends WidgetBase
|
|||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event handlers
|
||||
*/
|
||||
|
||||
public function onGetDropdownOptions()
|
||||
{
|
||||
$columnName = Input::get('column');
|
||||
$rowData = Input::get('rowData');
|
||||
|
||||
traceLog($columnName);
|
||||
traceLog($rowData);
|
||||
|
||||
$options = [
|
||||
'string'=>'String',
|
||||
'checkbox'=>'Checkbox',
|
||||
'dropdown'=>'Dropdown'
|
||||
];
|
||||
|
||||
return [
|
||||
'options' => $options
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,6 +217,8 @@
|
|||
border-top: 1px solid #ecf0f1;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
.table-control-dropdown-list li {
|
||||
list-style: none;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
var Table = function(element, options) {
|
||||
this.el = element
|
||||
this.$el = $(element)
|
||||
|
||||
this.options = options
|
||||
|
||||
//
|
||||
|
|
@ -250,12 +252,11 @@
|
|||
|
||||
cellContentContainer.setAttribute('class', 'content-container')
|
||||
|
||||
cellProcessor.renderCell(records[i][columnName], cellContentContainer)
|
||||
|
||||
cell.appendChild(cellContentContainer)
|
||||
|
||||
cell.appendChild(dataContainer)
|
||||
row.appendChild(cell)
|
||||
cell.appendChild(dataContainer)
|
||||
|
||||
cellProcessor.renderCell(records[i][columnName], cellContentContainer)
|
||||
}
|
||||
|
||||
tbody.appendChild(row)
|
||||
|
|
@ -551,6 +552,7 @@
|
|||
// collector can delete the elements if needed.
|
||||
this.el = null
|
||||
this.tableContainer = null
|
||||
this.$el = null
|
||||
|
||||
// Delete references to other DOM elements
|
||||
this.activeCell = null
|
||||
|
|
@ -564,6 +566,10 @@
|
|||
return this.el
|
||||
}
|
||||
|
||||
Table.prototype.getAlias = function() {
|
||||
return this.options.alias
|
||||
}
|
||||
|
||||
Table.prototype.getTableContainer = function() {
|
||||
return this.tableContainer
|
||||
}
|
||||
|
|
@ -628,6 +634,26 @@
|
|||
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]')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/*
|
||||
* Drop-down cell processor for the table control.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: implement the search
|
||||
*/
|
||||
|
||||
+function ($) { "use strict";
|
||||
|
||||
// NAMESPACE CHECK
|
||||
|
|
@ -25,6 +30,10 @@
|
|||
|
||||
this.itemListElement = null
|
||||
|
||||
this.optionsCache = {}
|
||||
|
||||
this.cachedOptionPromises = {}
|
||||
|
||||
// Event handlers
|
||||
this.itemClickHandler = this.onItemClick.bind(this)
|
||||
this.itemKeyDownHandler = this.onItemKeyDown.bind(this)
|
||||
|
|
@ -42,8 +51,9 @@
|
|||
DropdownProcessor.prototype.dispose = function() {
|
||||
this.unregisterListHandlers()
|
||||
this.itemClickHandler = null
|
||||
|
||||
this.itemListElement = null
|
||||
this.optionsCache = null
|
||||
this.cachedOptionPromises = null
|
||||
|
||||
BaseProto.dispose.call(this)
|
||||
}
|
||||
|
|
@ -66,7 +76,7 @@
|
|||
DropdownProcessor.prototype.renderCell = function(value, cellContentContainer) {
|
||||
var self = this
|
||||
|
||||
this.fetchOptions(function renderCellFetchOptions(options) {
|
||||
this.fetchOptions(cellContentContainer.parentNode, function renderCellFetchOptions(options) {
|
||||
if ( options[value] !== undefined )
|
||||
value = options[value]
|
||||
|
||||
|
|
@ -127,7 +137,7 @@
|
|||
this.itemListElement.style.left = containerPosition.left + 'px'
|
||||
this.itemListElement.style.top = containerPosition.top - 1 + cellContentContainer.offsetHeight + 'px'
|
||||
|
||||
this.fetchOptions(function renderCellFetchOptions(options) {
|
||||
this.fetchOptions(cellElement, function renderCellFetchOptions(options) {
|
||||
var listElement = document.createElement('ul')
|
||||
|
||||
for (var value in options) {
|
||||
|
|
@ -173,17 +183,65 @@
|
|||
var activeItemElement = this.itemListElement.querySelector('ul li.selected')
|
||||
|
||||
if (activeItemElement) {
|
||||
activeItemElement.focus()
|
||||
window.setTimeout(function(){
|
||||
activeItemElement.focus()
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropdownProcessor.prototype.fetchOptions = function(onSuccess) {
|
||||
// TODO: implement caching and AJAX support,
|
||||
// loading indicator is required here for AJAX-based options.
|
||||
//
|
||||
if ( this.columnConfiguration.options )
|
||||
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)
|
||||
|
||||
if (this.optionsCache[cachingKey] !== undefined) {
|
||||
onSuccess(this.optionsCache[cachingKey])
|
||||
return
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
// TODO: Loading indicator
|
||||
|
||||
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(data){
|
||||
onSuccess(data.options)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
DropdownProcessor.prototype.createOptionsCachingKey = function(row) {
|
||||
var cachingKey = 'non-dependent',
|
||||
dependsOn = this.columnConfiguration.depends_on
|
||||
|
||||
if (dependsOn) {
|
||||
if (typeof this.columnConfiguration.depends_on == '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) {
|
||||
|
|
@ -259,7 +317,6 @@
|
|||
this.updateCellFromSelectedItem(this.findSelectedItem())
|
||||
|
||||
this.hideDropdown()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -269,6 +326,11 @@
|
|||
this.tableObj.navigation.navigateNext(ev)
|
||||
this.tableObj.stopEvent(ev)
|
||||
}
|
||||
|
||||
if (ev.keyCode == 27) {
|
||||
// Esc - hide the drop-down
|
||||
this.hideDropdown()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -245,6 +245,8 @@
|
|||
border-top: 1px solid #ecf0f1;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
li {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
$data = [
|
||||
[
|
||||
'name' => 'City',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'string',
|
||||
'description' => 'City name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => false,
|
||||
'billable' => 'no',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'no',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => false,
|
||||
'billable' => 'no',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => false,
|
||||
'billable' => 'no',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => false,
|
||||
'billable' => 'no',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -111,7 +111,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => false,
|
||||
'billable' => 'no',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -123,7 +123,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => false,
|
||||
'billable' => 'no',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -159,7 +159,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => false,
|
||||
'billable' => 'no',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -171,7 +171,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => false,
|
||||
'billable' => 'no',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -183,7 +183,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -195,7 +195,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -207,7 +207,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -219,7 +219,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -231,7 +231,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -243,7 +243,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -255,7 +255,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -267,7 +267,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -279,7 +279,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -291,7 +291,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -303,7 +303,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'Country',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Country name',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -315,7 +315,7 @@
|
|||
],
|
||||
[
|
||||
'name' => 'State',
|
||||
'billabe' => true,
|
||||
'billable' => 'yes',
|
||||
'type' => 'dropdown',
|
||||
'description' => 'British columbia',
|
||||
'details' => 'Details string',
|
||||
|
|
@ -331,4 +331,4 @@
|
|||
|
||||
<!-- <div data-control="table" data-row-sorting="1" data-columns="<?= e(json_encode($columns)) ?>" data-data="<?= e(json_encode($data)) ?>"></div> -->
|
||||
|
||||
<div data-control="table" class="table-control" data-columns="<?= e(json_encode($columns)) ?>" data-data="<?= e(json_encode($data)) ?>" data-records-per-page="10"></div>
|
||||
<div data-control="table" class="table-control" data-columns="<?= e(json_encode($columns)) ?>" data-data="<?= e(json_encode($data)) ?>" data-records-per-page="10" data-alias="<?= e($this->alias) ?>"></div>
|
||||
Loading…
Reference in New Issue