Derived TableWidget from FilterWidget, added:

- libraries/TableWidgetLib
- widgets/TableWidget
- controllers/widgets/Tables
- public/js/TableWidget.js
This commit is contained in:
Paolo
2019-09-25 17:15:46 +02:00
parent 0a4dffa704
commit 8210c3fdc7
5 changed files with 1317 additions and 0 deletions
+105
View File
@@ -0,0 +1,105 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the tablewidgetlib (back-end)
* Provides data to the ajax get calls about the filter
* Accepts ajax post calls to change the filter data
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
* NOTE: extends the FHC_Controller instead of the Auth_Controller because the TableWidget has its
* own permissions check
*/
class Tables extends FHC_Controller
{
const TABLE_UNIQUE_ID = 'tableUniqueId';
/**
* Calls the parent's constructor and loads the tablewidgetlib
*/
public function __construct()
{
parent::__construct();
// Loads authentication library and starts authentication
$this->load->library('AuthLib');
// Loads the tablewidgetlib with HTTP GET/POST parameters
$this->_loadTableWidgetLib();
// Checks if the caller is allow to read this data
$this->_isAllowed();
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Retrieves data about the current filter from the session and will be written on the output in JSON format
*/
public function getTable()
{
$this->outputJsonSuccess($this->tablewidgetlib->getSession());
}
/**
* Retrieves the number of records present in the current dataset and will be written on the output in JSON format
*/
public function rowNumber()
{
$rowNumber = 0;
$dataset = $this->tablewidgetlib->getSessionElement(TableWidgetLib::SESSION_DATASET);
if (isset($dataset) && is_array($dataset))
{
$rowNumber = count($dataset);
}
$this->outputJsonSuccess($rowNumber);
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Checks if the user is allowed to use this filter
*/
private function _isAllowed()
{
if (!$this->tablewidgetlib->isAllowed())
{
$this->terminateWithJsonError('You are not allowed to access to this content');
}
}
/**
* Loads the tablewidgetlib with the TABLE_UNIQUE_ID parameter
* If the parameter TABLE_UNIQUE_ID is not given then the execution of the controller is terminated and
* an error message is printed
*/
private function _loadTableWidgetLib()
{
// If the parameter TABLE_UNIQUE_ID is present in the HTTP GET or POST
if (isset($_GET[self::TABLE_UNIQUE_ID]) || isset($_POST[self::TABLE_UNIQUE_ID]))
{
// If it is present in the HTTP GET
if (isset($_GET[self::TABLE_UNIQUE_ID]))
{
$tableUniqueId = $this->input->get(self::TABLE_UNIQUE_ID); // is retrieved from the HTTP GET
}
elseif (isset($_POST[self::TABLE_UNIQUE_ID])) // Else if it is present in the HTTP POST
{
$tableUniqueId = $this->input->post(self::TABLE_UNIQUE_ID); // is retrieved from the HTTP POST
}
// Loads the tablewidgetlib that contains all the used logic
$this->load->library('TableWidgetLib');
$this->tablewidgetlib->setTableUniqueId($tableUniqueId);
}
else // Otherwise an error will be written in the output
{
$this->terminateWithJsonError('Parameter "'.self::TABLE_UNIQUE_ID.'" not provided!');
}
}
}
+204
View File
@@ -0,0 +1,204 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* TableWidget logic
*/
class TableWidgetLib
{
const TABLE_UNIQUE_ID = 'tableUniqueId'; // TableWidget unique id
// Session parameters names
const SESSION_NAME = 'FHC_TABLE_WIDGET'; // Table session name
const SESSION_FIELDS = 'fields';
const SESSION_COLUMNS_ALIASES = 'columnsAliases';
const SESSION_ADDITIONAL_COLUMNS = 'additionalColumns';
const SESSION_CHECKBOXES = 'checkboxes';
const SESSION_METADATA = 'datasetMetadata';
const SESSION_DATASET = 'dataset';
const SESSION_ROW_NUMBER = 'rowNumber';
const SESSION_RELOAD_DATASET = 'reloadDataset';
const SESSION_DATASET_REPRESENTATION = 'datasetRepresentation';
const SESSION_DATASET_REP_OPTIONS = 'datasetRepresentationOptions';
const SESSION_DATASET_REP_FIELDS_DEFS = 'datasetRepresentationFieldsDefinitions';
// Alias for the dynamic table used to retrieve the dataset
const DATASET_TABLE_ALIAS = 'datasetTableWidget';
// Parameters names...
// ...to reload the dataset
const DATASET_RELOAD_PARAMETER = 'reloadDataset';
// ...to specify permissions that are needed to use this TableWidget
const REQUIRED_PERMISSIONS_PARAMETER = 'requiredPermissions';
// ...stament to retrieve the dataset
const QUERY_PARAMETER = 'query';
// ...to specify more columns or aliases for them
const ADDITIONAL_COLUMNS = 'additionalColumns';
const CHECKBOXES = 'checkboxes';
const COLUMNS_ALIASES = 'columnsAliases';
// ...to format/mark records of a dataset
const FORMAT_ROW = 'formatRow';
const MARK_ROW = 'markRow';
// ...to specify how to represent the dataset (ex: tablesorter, pivotUI, ...)
const DATASET_REPRESENTATION = 'datasetRepresentation';
const DATASET_REP_OPTIONS = 'datasetRepOptions';
const DATASET_REP_FIELDS_DEFS = 'datasetRepFieldsDefs';
// Different dataset representations
const DATASET_REP_TABLESORTER = 'tablesorter';
const DATASET_REP_PIVOTUI = 'pivotUI';
const DATASET_REP_TABULATOR = 'tabulator';
const PERMISSION_TABLE_METHOD = 'TableWidget'; // Name for fake method to be checked by the PermissionLib
const PERMISSION_TYPE = 'rw';
private $_ci; // Code igniter instance
private $_tableUniqueId; // unique id for this table widget
/**
* Gets the CI instance and loads message helper
*/
public function __construct($params = null)
{
$this->_ci =& get_instance(); // get code igniter instance
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Checks if at least one of the permissions given as parameter (requiredPermissions) belongs
* to the authenticated user, if confirmed then is allowed to use this FilterWidget.
* If the parameter requiredPermissions is NOT given or is not present in the session,
* then NO one is allow to use this FilterWidget
* Wrapper method to permissionlib->hasAtLeastOne
*/
public function isAllowed($requiredPermissions = null)
{
$this->_ci->load->library('PermissionLib'); // Load permission library
// Gets the required permissions from the session if they are not provided as parameter
$rq = $requiredPermissions;
if ($rq == null) $rq = $this->getSessionElement(self::REQUIRED_PERMISSIONS_PARAMETER);
return $this->_ci->permissionlib->hasAtLeastOne($rq, self::PERMISSION_TABLE_METHOD, self::PERMISSION_TYPE);
}
/**
* Wrapper method to the session helper funtions to retrieve the whole session for this filter
*/
public function getSession()
{
return getSessionElement(self::SESSION_NAME, $this->_tableUniqueId);
}
/**
* Wrapper method to the session helper funtions to retrieve one element from the session of this filter
*/
public function getSessionElement($name)
{
$session = getSessionElement(self::SESSION_NAME, $this->_tableUniqueId);
if (isset($session[$name]))
{
return $session[$name];
}
return null;
}
/**
* Wrapper method to the session helper funtions to set the whole session for this filter
*/
public function setSession($data)
{
$data[TableWidgetLib::TABLE_UNIQUE_ID] = $this->_tableUniqueId; // the unique id of this table widget
setSessionElement(self::SESSION_NAME, $this->_tableUniqueId, $data);
}
/**
* Wrapper method to the session helper funtions to set one element in the session for this filter
*/
public function setSessionElement($name, $value)
{
$session = getSessionElement(self::SESSION_NAME, $this->_tableUniqueId);
$session[$name] = $value;
setSessionElement(self::SESSION_NAME, $this->_tableUniqueId, $session); // stores the single value
}
/**
* Generate the query to retrieve the dataset for a filter
*/
public function generateDatasetQuery($query)
{
return 'SELECT * FROM ('.$query.') '.self::DATASET_TABLE_ALIAS;
}
/**
* Retrieves the dataset from the DB
*/
public function getDataset($datasetQuery)
{
$dataset = null;
if ($datasetQuery != null)
{
$this->_ci->load->model('system/Filters_model', 'FiltersModel');
// Execute the given SQL statement suppressing error messages
$dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery);
}
return $dataset;
}
/**
* Retrieves metadata from the last executed query
*/
public function getExecutedQueryMetaData()
{
return $this->_ci->FiltersModel->getExecutedQueryMetaData();
}
/**
* Retrieves the list of fields from the last executed query
*/
public function getExecutedQueryListFields()
{
return $this->_ci->FiltersModel->getExecutedQueryListFields();
}
/**
* Return an unique string that identify this filter widget
* NOTE: The default value is the URI where the FilterWidget is called
* If the fhc_controller_id is present then is also used
*/
public function setTableUniqueIdByParams($params)
{
if ($params != null
&& is_array($params)
&& isset($params[self::TABLE_UNIQUE_ID])
&& !isEmptyString($params[self::TABLE_UNIQUE_ID]))
{
$this->setTableUniqueId($params[self::TABLE_UNIQUE_ID]);
}
}
/**
* Set the _tableUniqueId property
*/
public function setTableUniqueId($filterUniqueId)
{
$this->_tableUniqueId = $filterUniqueId;
}
}
@@ -30,6 +30,7 @@
$pivotui = isset($pivotui) ? $pivotui : false;
$sbadmintemplate = isset($sbadmintemplate) ? $sbadmintemplate : false;
$tablesorter = isset($tablesorter) ? $tablesorter : false;
$tablewidget = isset($tablewidget) ? $tablewidget : false;
$tabulator = isset($tabulator) ? $tabulator : false;
$tinymce = isset($tinymce) ? $tinymce : false;
?>
@@ -103,6 +104,9 @@
// NavigationWidget CSS
if ($navigationwidget === true) generateCSSsInclude('public/css/NavigationWidget.css');
// TableWidget CSS
if ($tablewidget === true) generateCSSsInclude('public/css/TableWidget.css');
// Eventually required CSS
generateCSSsInclude($customCSSs); // Eventually required CSS
@@ -203,6 +207,9 @@
// PhrasesLib JS
if ($phrases != null) generateJSsInclude('public/js/PhrasesLib.js');
// TableWidget JS
if ($tablewidget === true) generateJSsInclude('public/js/TableWidget.js');
// Load addon hooks JS
// NOTE: keep it as the latest but one
if ($addons === true) generateAddonsJSsInclude($calledPath.'/'.$calledMethod);
+414
View File
@@ -0,0 +1,414 @@
<?php
/**
* To display a table that shows data retriev by a SQL statement
*/
class TableWidget extends Widget
{
// Paths of the views
const WIDGET_URL_TABLE = 'widgets/table/table';
const WIDGET_URL_DATASET_TABLESORTER = 'widgets/table/tableDataset';
const WIDGET_URL_DATASET_PIVOTUI = 'widgets/table/pivotUIDataset';
const WIDGET_URL_DATASET_TABULATOR = 'widgets/table/tabulatorDataset';
// Default formats
const DEFAULT_DATE_FORMAT = 'd.m.Y H:i:s';
const DEFAULT_MARK_ROW_CLASS = 'text-danger';
// Required permissions to use this TableWidget
private $_requiredPermissions;
// SQL statement
private $_query;
// Additional columns to add to the dataset or aliases to be used to rename columns of the dataset
private $_additionalColumns;
private $_columnsAliases;
// To format or mark rows of the dataset
private $_formatRow;
private $_markRow;
// To have a column in the GUI with checkboxes to select rows in the table
private $_checkboxes;
private $_datasetRepresentation; // dataset representation (ex: tablesorter, pivotUI, ...)
private $_datasetRepresentationOptions; // dataset representation options for tablesorter, pivotUI, ...
private $_datasetRepFieldsDefs; // dataset representation attributes for each record field
private $_reloadDataset; // Force Reload of Dataset
private static $_TableWidgetInstance; // static property that contains the instance of itself
/**
* Initialize the TableWidget and starts the execution of the logic
*/
public function __construct($name, $args = array())
{
parent::__construct($name, $args); // calls the parent's constructor
self::$_TableWidgetInstance = $this; // set static property $_TableWidgetInstance with this instance
$this->load->library('TableWidgetLib'); // Loads the TableWidgetLib that contains all the used logic
$this->_initTableWidget($args); // checks parameters and initialize properties
$this->tablewidgetlib->setTableUniqueIdByParams($args);
// Let's start if it's allowed
// NOTE: If it is NOT allowed then no data are loaded
if ($this->tablewidgetlib->isAllowed($this->_requiredPermissions))
{
$this->_startTableWidget();
}
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Called when echoing the table widget call
*/
public function display($widgetData)
{
$this->view(self::WIDGET_URL_TABLE, array(
'tableUniqueId' => $widgetData[TableWidgetLib::TABLE_UNIQUE_ID]
)); // GUI starts here
}
//------------------------------------------------------------------------------------------------------------------
// Public static methods used to load views and to access statically to some properies of the TableWidget
/**
* Loads the view related to the dataset, here is decided how to represent the dataset (ex: tablesorter, pivotUI, ...)
*/
public static function loadViewDataset()
{
if (self::$_TableWidgetInstance->_datasetRepresentation == TableWidgetLib::DATASET_REP_TABLESORTER)
{
self::_loadView(self::WIDGET_URL_DATASET_TABLESORTER);
}
if (self::$_TableWidgetInstance->_datasetRepresentation == TableWidgetLib::DATASET_REP_PIVOTUI)
{
self::_loadView(self::WIDGET_URL_DATASET_PIVOTUI);
}
if (self::$_TableWidgetInstance->_datasetRepresentation == TableWidgetLib::DATASET_REP_TABULATOR)
{
self::_loadView(self::WIDGET_URL_DATASET_TABULATOR);
}
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Checks parameters and initialize all the properties of this TableWidget
*/
private function _initTableWidget($args)
{
$this->_checkParameters($args);
// If here then everything is ok
// Initialize class properties
$this->_requiredPermissions = null;
$this->_reloadDataset = null;
$this->_query = null;
$this->_additionalColumns = null;
$this->_columnsAliases = null;
$this->_formatRow = null;
$this->_markRow = null;
$this->_checkboxes = null;
$this->_datasetRepresentation = null;
$this->_datasetRepresentationOptions = null;
$this->_datasetRepFieldsDefs = null;
// Retrieved the required permissions parameter if present
if (isset($args[TableWidgetLib::REQUIRED_PERMISSIONS_PARAMETER]))
{
$this->_requiredPermissions = $args[TableWidgetLib::REQUIRED_PERMISSIONS_PARAMETER];
}
// How to retrieve data for the table: SQL statement or a result from DB
if (isset($args[TableWidgetLib::QUERY_PARAMETER]))
{
$this->_query = $args[TableWidgetLib::QUERY_PARAMETER];
}
if (isset($args[TableWidgetLib::DATASET_RELOAD_PARAMETER]))
{
$this->_reloadDataset = $args[TableWidgetLib::DATASET_RELOAD_PARAMETER];
}
// Parameter is used to add extra columns to the dataset
if (isset($args[TableWidgetLib::ADDITIONAL_COLUMNS])
&& is_array($args[TableWidgetLib::ADDITIONAL_COLUMNS])
&& count($args[TableWidgetLib::ADDITIONAL_COLUMNS]) > 0)
{
$this->_additionalColumns = $args[TableWidgetLib::ADDITIONAL_COLUMNS];
}
// Parameter is used to add use aliases for the columns fo the dataset
if (isset($args[TableWidgetLib::COLUMNS_ALIASES])
&& is_array($args[TableWidgetLib::COLUMNS_ALIASES])
&& count($args[TableWidgetLib::COLUMNS_ALIASES]) > 0)
{
$this->_columnsAliases = $args[TableWidgetLib::COLUMNS_ALIASES];
}
// Parameter that contains a function to format the rows of the dataset
if (isset($args[TableWidgetLib::FORMAT_ROW]) && is_callable($args[TableWidgetLib::FORMAT_ROW]))
{
$this->_formatRow = $args[TableWidgetLib::FORMAT_ROW];
}
// Parameter that contains a function to mark in the GUI the rows of the dataset
if (isset($args[TableWidgetLib::MARK_ROW]) && is_callable($args[TableWidgetLib::MARK_ROW]))
{
$this->_markRow = $args[TableWidgetLib::MARK_ROW];
}
// Parameter used to specify the column of the dataset that will be used
// as id of the checkboxes column in the GUI
if (isset($args[TableWidgetLib::CHECKBOXES]))
{
$this->_checkboxes = $args[TableWidgetLib::CHECKBOXES];
}
// To specify how to represent the dataset (ex: tablesorter, pivotUI, ...)
if (isset($args[TableWidgetLib::DATASET_REPRESENTATION])
&& ($args[TableWidgetLib::DATASET_REPRESENTATION] == TableWidgetLib::DATASET_REP_TABLESORTER
|| $args[TableWidgetLib::DATASET_REPRESENTATION] == TableWidgetLib::DATASET_REP_PIVOTUI
|| $args[TableWidgetLib::DATASET_REPRESENTATION] == TableWidgetLib::DATASET_REP_TABULATOR))
{
$this->_datasetRepresentation = $args[TableWidgetLib::DATASET_REPRESENTATION];
}
// To specify options for the dataset representation (ex: tablesorter, pivotUI, ...)
if (isset($args[TableWidgetLib::DATASET_REP_OPTIONS]) && !isEmptyString($args[TableWidgetLib::DATASET_REP_OPTIONS]))
{
$this->_datasetRepresentationOptions = $args[TableWidgetLib::DATASET_REP_OPTIONS];
}
// To specify how to represent each record field
if (isset($args[TableWidgetLib::DATASET_REP_FIELDS_DEFS]) && !isEmptyString($args[TableWidgetLib::DATASET_REP_FIELDS_DEFS]))
{
$this->_datasetRepFieldsDefs = $args[TableWidgetLib::DATASET_REP_FIELDS_DEFS];
}
}
/**
* Checks the required parameters used to call this TableWidget
*/
private function _checkParameters($args)
{
if (!is_array($args) || (is_array($args) && count($args) == 0))
{
show_error('Second parameter of the widget call must be a NOT empty associative array');
}
else
{
if (!isset($args[TableWidgetLib::TABLE_UNIQUE_ID]))
{
show_error('The parameter "'.TableWidgetLib::TABLE_UNIQUE_ID.'" must be specified');
}
if (!isset($args[TableWidgetLib::QUERY_PARAMETER]))
{
show_error('The parameters "'.TableWidgetLib::QUERY_PARAMETER.'" must be specified');
}
if (!isset($args[TableWidgetLib::DATASET_REPRESENTATION]))
{
show_error('The parameter "'.TableWidgetLib::DATASET_REPRESENTATION.'" must be specified');
}
if (isset($args[TableWidgetLib::DATASET_REPRESENTATION])
&& $args[TableWidgetLib::DATASET_REPRESENTATION] != TableWidgetLib::DATASET_REP_TABLESORTER
&& $args[TableWidgetLib::DATASET_REPRESENTATION] != TableWidgetLib::DATASET_REP_PIVOTUI
&& $args[TableWidgetLib::DATASET_REPRESENTATION] != TableWidgetLib::DATASET_REP_TABULATOR)
{
show_error(
'The parameter "'.TableWidgetLib::DATASET_REPRESENTATION.
'" must be IN ("'
.TableWidgetLib::DATASET_REP_TABLESORTER.'", "'
.TableWidgetLib::DATASET_REP_PIVOTUI.'", "'
.TableWidgetLib::DATASET_REP_TABULATOR.'")'
);
}
}
}
/**
* Contains all the logic used to load all the data needed to the TableWidget
*/
private function _startTableWidget()
{
// Read the all session for this table widget
$session = $this->tablewidgetlib->getSession();
// If session is NOT empty -> a table was already loaded
if ($session != null)
{
// Get SESSION_RELOAD_DATASET from the session
$sessionReloadDataset = $this->tablewidgetlib->getSessionElement(TableWidgetLib::SESSION_RELOAD_DATASET);
// if Filter changed or reload is forced by parameter then reload the Dataset
if ($this->_reloadDataset === true || $sessionReloadDataset === true)
{
// Set as false to stop changing the dataset
$this->tablewidgetlib->setSessionElement(TableWidgetLib::SESSION_RELOAD_DATASET, false);
// Generate dataset query using tables from the session
$datasetQuery = $this->tablewidgetlib->generateDatasetQuery($this->_query);
// Then retrieve dataset from DB
$dataset = $this->tablewidgetlib->getDataset($datasetQuery);
// Save changes into session if data are valid
if (!isError($dataset))
{
$this->_formatDataset($dataset); // marks rows using markRow and format rowns using formatRow
// Set the new dataset and its attributes in the session
$this->tablewidgetlib->setSessionElement(TableWidgetLib::SESSION_METADATA, $this->tablewidgetlib->getExecutedQueryMetaData());
$this->tablewidgetlib->setSessionElement(TableWidgetLib::SESSION_ROW_NUMBER, count($dataset->retval));
$this->tablewidgetlib->setSessionElement(TableWidgetLib::SESSION_DATASET, $dataset->retval);
}
}
}
// If the session is empty -> first time that this table is loaded
if ($session == null)
{
// Generate dataset query
$datasetQuery = $this->tablewidgetlib->generateDatasetQuery($this->_query);
// Then retrieve dataset from DB
$dataset = $this->tablewidgetlib->getDataset($datasetQuery);
// Save changes into session if data are valid
if (!isError($dataset))
{
$this->_formatDataset($dataset); // marks rows using markRow and format rowns using formatRow
// Stores an array that contains all the data useful for
$this->tablewidgetlib->setSession(
array(
TableWidgetLib::SESSION_FIELDS => $this->tablewidgetlib->getExecutedQueryListFields(), // all the fields of the dataset
TableWidgetLib::SESSION_COLUMNS_ALIASES => $this->_columnsAliases, // all the fields aliases
TableWidgetLib::SESSION_ADDITIONAL_COLUMNS => $this->_additionalColumns, // additional columns
TableWidgetLib::SESSION_CHECKBOXES => $this->_checkboxes, // the name of the field used to build the checkboxes column
TableWidgetLib::SESSION_METADATA => $this->tablewidgetlib->getExecutedQueryMetaData(), // the metadata of the dataset
TableWidgetLib::SESSION_ROW_NUMBER => count($dataset->retval), // the number of loaded rows by this table
TableWidgetLib::SESSION_DATASET => $dataset->retval, // the entire dataset
TableWidgetLib::SESSION_RELOAD_DATASET => false, // if the dataset must be reloaded, not needed the first time
TableWidgetLib::SESSION_DATASET_REPRESENTATION => $this->_datasetRepresentation, // the choosen dataset representation
TableWidgetLib::SESSION_DATASET_REP_OPTIONS => $this->_datasetRepresentationOptions, // the choosen dataset representation options
TableWidgetLib::SESSION_DATASET_REP_FIELDS_DEFS => $this->_datasetRepFieldsDefs // the choosen dataset representation record fields definition
)
);
}
}
// To be always stored in the session, otherwise is not possible to load data from Filters controller
// NOTE: must the latest operation to be performed in the session to be shure that is always present
$this->tablewidgetlib->setSessionElement(TableWidgetLib::REQUIRED_PERMISSIONS_PARAMETER, $this->_requiredPermissions);
}
/**
* Calls the method _markRow and _formatRow to marks rows using markRow and format rowns using formatRow
* NOTE: this method operates directly on the retrieved dataset: parameter passed by reference
*/
private function _formatDataset(&$rawDataset)
{
if (hasData($rawDataset) && is_array($rawDataset->retval))
{
// For each row of the data set
for ($rowCounter = 0; $rowCounter < count($rawDataset->retval); $rowCounter++)
{
// Calls the methods to mark and to format a row
// NOTE: keep this order! the markRow function given as parameter is supposing to work
// on a raw dataset, NOT on a formatted one
$rawDataset->retval[$rowCounter]->MARK_ROW_CLASS = $this->_markRow($rawDataset->retval[$rowCounter]);
$this->_formatRow($rawDataset->retval[$rowCounter]);
}
}
}
/**
* Formats the columns of all the rows of the entire dataset
* - converts booleans into strings "true" and "false"
* - format dates using the format string defined in DEFAULT_DATE_FORMAT
* Calls the parameter formatRow if it was given and if it is a valid funtion
* NOTE: this method operates directly on the retrieved dataset: parameter passed by reference
*/
private function _formatRow(&$rawDatasetRow)
{
// For each column of the row
foreach ($rawDatasetRow as $columnName => $columnValue)
{
// Basic conversions
if (is_bool($columnValue))
{
$rawDatasetRow->{$columnName} = ($columnValue === true ? 'true' : 'false');
}
elseif (DateTime::createFromFormat('Y-m-d H:i:s', $columnValue) !== false)
{
$rawDatasetRow->{$columnName} = date(self::DEFAULT_DATE_FORMAT, strtotime($columnValue));
}
}
// If a valid function call the given formatRow
if ($this->_formatRow != null && is_callable($this->_formatRow))
{
$formatRowFunction = $this->_formatRow;
$rawDatasetRow = $formatRowFunction($rawDatasetRow);
}
}
/**
* Returns a string that contains a class name used to mark rows in the dataset table
* Calls the parameter markRow if it was given and if it is a valid funtion
*/
private function _markRow($rawDatasetRow)
{
// If a valid function call the given markRow
if ($this->_markRow != null && is_callable($this->_markRow))
{
$markRowFunction = $this->_markRow;
$class = $markRowFunction($rawDatasetRow);
}
return !isset($class) ? '' : $class;
}
/**
* Utility method that retrieves the name of the columns present in a table JSON definition
*/
private function _getColumnsNames($columns)
{
$columnsNames = array();
foreach ($columns as $key => $obj)
{
if (isset($obj->name))
{
$columnsNames[] = $obj->name;
}
}
return $columnsNames;
}
/**
* Loads a view using the given viewName and eventually other parameters
*/
private static function _loadView($viewName, $parameters = null)
{
$ci =& get_instance();
$ci->load->view($viewName, $parameters);
}
}
+587
View File
@@ -0,0 +1,587 @@
/**
* TableWidget JS magic
*/
//--------------------------------------------------------------------------------------------------------------------
// Constants
//
const DATASET_REP_TABLESORTER = "tablesorter";
const DATASET_REP_PIVOTUI = "pivotUI";
const DATASET_REP_TABULATOR = "tabulator";
/**
* FHC_TableWidget this object is used to render the GUI of a table widget and to operate with it
*/
var FHC_TableWidget = {
//------------------------------------------------------------------------------------------------------------------
// Properties
_datasetRepresentation: null, // contains the current data representation
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* To display the TableWidget using the loaded data prenset in the session
*/
display: function() {
FHC_TableWidget._getTables(FHC_TableWidget._renderTableWidget);
},
/**
* Alias call to method display only to inprove the readability of the code
*/
refresh: function() {
FHC_TableWidget.display();
},
//------------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Utility method that checks if data contains an error and print that to the console
* otherwise the TableWidget GUI is refreshed
*/
_failOrRefresh: function(data, textStatus, jqXHR) {
if (FHC_AjaxClient.isError(data))
{
console.log(FHC_AjaxClient.getError(data));
}
else
{
FHC_TableWidget.refresh();
}
},
/**
* Utility method that checks if data contains an error and print that to the console
* otherwise the page is reloaded
*/
_failOrReload: function(data, textStatus, jqXHR) {
if (FHC_AjaxClient.isError(data))
{
console.log(FHC_AjaxClient.getError(data));
}
else
{
location.reload();
}
},
/**
* To reset the Table Widget GUI
*/
_resetGUI: function(tableWidgetDiv) {
// If the choosen dataset representation is tablesorter
if (FHC_TableWidget._datasetRepresentation == DATASET_REP_TABLESORTER)
{
tableWidgetDiv.find("#tableWidgetTableDataset > thead > tr").html("");
tableWidgetDiv.find("#tableWidgetTableDataset > tbody").html("");
}
// If the choosen dataset representation is pivotUI
if (FHC_TableWidget._datasetRepresentation == DATASET_REP_PIVOTUI)
{
tableWidgetDiv.find("#tableWidgetPivotUI").html("");
}
// If the choosen dataset representation is tabulator
if (FHC_TableWidget._datasetRepresentation == DATASET_REP_TABULATOR)
{
tableWidgetDiv.find("#tableWidgetTabulator").html("");
}
},
/**
* To get via Ajax all the data related to the TableWidget present in the given page
* If the parameter renderFunction is a valid function, is called on success
*/
_getTables: function(renderFunction) {
var tableWidgetUniqueIdArray = FHC_TableWidget._getTableWidgetUniqueIdArray();
for (var tableWidgetsCounter = 0; tableWidgetsCounter < tableWidgetUniqueIdArray.length; tableWidgetsCounter++)
{
FHC_AjaxClient.ajaxCallGet(
"widgets/Tables/getTable",
{
tableUniqueId: tableWidgetUniqueIdArray[tableWidgetsCounter]
},
{
successCallback: function(data, textStatus, jqXHR) {
if (FHC_AjaxClient.hasData(data))
{
if (typeof renderFunction == "function")
{
renderFunction(FHC_AjaxClient.getData(data));
}
}
else
{
console.log(FHC_AjaxClient.getError(data));
}
}
}
);
}
},
/**
* This method calls all the other methods needed to rendere the GUI for a TableWidget
* The parameter data contains all the data about the TableWidget and it is given as parameter
* to all the methods that here are called
* NOTE: think very carefully before changing the order of the calls
*/
_renderTableWidget: function(data) {
FHC_TableWidget._setDatasetRepresentation(data); // set what type of dataset representation was choosen
var tableWidgetDiv = $('div[tableUniqueId="' + data.tableUniqueId + '"]');
FHC_TableWidget._turnOffEvents(tableWidgetDiv); // turns all the events off
FHC_TableWidget._resetGUI(tableWidgetDiv); // Reset the entire GUI
FHC_TableWidget._renderDataset(tableWidgetDiv, data);
FHC_TableWidget._turnOnEvents(tableWidgetDiv); // turns all the events off
},
/**
* Turns all the events off
* NOTE: must be aligned to _turnOnEvents
*/
_turnOffEvents: function(tableWidgetDiv) {
// If the choosen dataset representation is tablesorter
if (FHC_TableWidget._datasetRepresentation == DATASET_REP_TABLESORTER)
{
FHC_TableWidget._disableTablesorter(tableWidgetDiv); // disable the tablesorter
}
},
/**
* Turns all the events on
* NOTE: must be aligned to _turnOffEvents
*/
_turnOnEvents: function(tableWidgetDiv) {
// If the choosen dataset representation is tablesorter
if (FHC_TableWidget._datasetRepresentation == DATASET_REP_TABLESORTER)
{
FHC_TableWidget._enableTableSorter(tableWidgetDiv); // enable the tablesorter
}
},
_renderDataset: function(tableWidgetDiv, data) {
// If the choosen dataset representation is tablesorter then...
if (FHC_TableWidget._datasetRepresentation == DATASET_REP_TABLESORTER)
{
FHC_TableWidget._renderDatasetTablesorter(tableWidgetDiv, data); // ...render the tablesorter GUI
}
// If the choosen dataset representation is pivotUI then...
if (FHC_TableWidget._datasetRepresentation == DATASET_REP_PIVOTUI)
{
FHC_TableWidget._renderDatasetPivotUI(tableWidgetDiv, data); // ...render the pivotUI GUI
}
// If the choosen dataset representation is tabulator then...
if (FHC_TableWidget._datasetRepresentation == DATASET_REP_TABULATOR)
{
FHC_TableWidget._renderDatasetTabulator(tableWidgetDiv, data); // ...render the tabulator GUI
}
},
/**
* Renders the tablesorter for the TableWidget
* The data to be displayed are retrived from the parameter data
*/
_renderDatasetTablesorter: function(tableWidgetDiv, data) {
if (data.hasOwnProperty("checkboxes") && data.checkboxes != null && data.checkboxes.trim() != "")
{
tableWidgetDiv.find("#tableWidgetTableDataset > thead > tr").append("<th data-filter='false' title='Select'>Select</th>");
}
var arrayFieldsToDisplay = FHC_TableWidget._getFieldsToDisplay(data);
for (var i = 0; i < arrayFieldsToDisplay.length; i++)
{
var columnName = arrayFieldsToDisplay[i];
tableWidgetDiv.find("#tableWidgetTableDataset > thead > tr").append("<th title='" + columnName + "'>" + columnName + "</th>");
}
if (data.hasOwnProperty("additionalColumns") && $.isArray(data.additionalColumns))
{
for (var i = 0; i < data.additionalColumns.length; i++)
{
var columnName = data.additionalColumns[i];
tableWidgetDiv.find("#tableWidgetTableDataset > thead > tr").append("<th title='" + columnName + "'>" + columnName + "</th>");
}
}
if (arrayFieldsToDisplay.length > 0)
{
if (data.hasOwnProperty("dataset") && $.isArray(data.dataset))
{
if (data.checkboxes != null && data.checkboxes != "")
{
// select checkbox range with shift key
if (typeof tableWidgetDiv.find("#tableWidgetTableDataset").checkboxes === 'function')
tableWidgetDiv.find("#tableWidgetTableDataset").checkboxes("range", true);
}
for (var i = 0; i < data.dataset.length; i++)
{
var record = data.dataset[i];
if ($.isEmptyObject(record))
{
continue;
}
var strHtml = "<tr class='" + record.MARK_ROW_CLASS + "'>";
if (data.checkboxes != null && data.checkboxes != "")
{
strHtml += "<td>";
strHtml += "<input type='checkbox' name='" + data.checkboxes + "[]' value='" + record[data.checkboxes] + "'>";
strHtml += "</td>";
}
$.each(arrayFieldsToDisplay, function(i, fieldToDisplay) {
if (record.hasOwnProperty(data.fields[i]))
{
strHtml += "<td>" + record[data.fields[i]] + "</td>";
}
});
if (data.additionalColumns != null && $.isArray(data.additionalColumns))
{
$.each(data.additionalColumns, function(i, additionalColumn) {
if (record.hasOwnProperty(additionalColumn))
{
strHtml += "<td>" + record[additionalColumn] + "</td>";
}
});
}
strHtml += "</tr>";
tableWidgetDiv.find("#tableWidgetTableDataset > tbody").append(strHtml);
}
}
}
},
/**
* Enable the tablesorter libs to render the dataset table with sorting features
*/
_enableTableSorter: function(tableWidgetDiv) {
var tableWidgetTablesorter = tableWidgetDiv.find("#tableWidgetTableDataset");
// Checks if the table contains data (rows)
if (tableWidgetTablesorter.find("tbody:empty").length == 0
&& tableWidgetTablesorter.find("tr:empty").length == 0
&& tableWidgetTablesorter.hasClass("table-condensed"))
{
tableWidgetTablesorter.tablesorter({
dateFormat: "ddmmyyyy",
widgets: ["zebra", "filter"],
widgetOptions: {
filter_saveFilters : true
}
});
$.tablesorter.updateAll(tableWidgetTablesorter[0].config, true, null);
}
},
/**
* Disable the tablesorter
*/
_disableTablesorter: function(tableWidgetDiv) {
tableWidgetDiv.find("#tableWidgetTableDataset").trigger("disable");
},
/**
* Renders the pivotUI for the TableWidget
* The data to be displayed are retrived from the parameter data
*/
_renderDatasetPivotUI: function(tableWidgetDiv, data) {
// Checks if options were given and returns them
var options = FHC_TableWidget._getRepresentationOptions(data);
// Manipulation for the representation!
var arrayFieldsToDisplay = FHC_TableWidget._getFieldsToDisplay(data);
// If there are fields to be displayed...
if (arrayFieldsToDisplay.length > 0)
{
// ...if there are data to be displayed...
if (data.hasOwnProperty("dataset") && $.isArray(data.dataset))
{
// Build the array of objects used by pivotUI and store it in pivotUIData
var pivotUIData = [];
// Loops through data
for (var i = 0; i < data.dataset.length; i++)
{
var record = data.dataset[i]; // Single record
var tmpObj = {}; // New object that represents a record
// Loops through columns of a record
$.each(arrayFieldsToDisplay, function(i, fieldToDisplay) {
if (record.hasOwnProperty(data.fields[i]))
{
tmpObj[fieldToDisplay] = record[data.fields[i]]; // Add data with the column alias
}
});
// If additional columns are present...
if (data.additionalColumns != null && $.isArray(data.additionalColumns))
{
// ...loops through them
$.each(data.additionalColumns, function(i, additionalColumn) {
if (record.hasOwnProperty(additionalColumn))
{
tmpObj[additionalColumn] = record[additionalColumn]; // Add the additional column
}
});
}
pivotUIData.push(tmpObj); // Add tmpObj to pivotUIData
}
// Renders the pivotUI
tableWidgetDiv.find("#tableWidgetPivotUI").pivotUI(
pivotUIData,
options
);
}
}
},
/**
* Retrives the fields to be displayed from the data parameter, if aliases are present then they are used
*/
_getFieldsToDisplay: function(data) {
var arrayFieldsToDisplay = [];
if (data.hasOwnProperty("fields") && $.isArray(data.fields))
{
if (data.hasOwnProperty("columnsAliases") && $.isArray(data.columnsAliases))
{
for (var sfc = 0; sfc < data.fields.length; sfc++)
{
for (var fc = 0; fc < data.fields.length; fc++)
{
if (data.fields[sfc] == data.fields[fc])
{
arrayFieldsToDisplay[sfc] = data.columnsAliases[fc];
}
}
}
}
else
{
arrayFieldsToDisplay = data.fields;
}
}
return arrayFieldsToDisplay;
},
/**
* Renders the tabulator for the TableWidget
* The data to be displayed are retrived from the parameter data
*/
_renderDatasetTabulator: function(tableWidgetDiv, data) {
// Checks if options were given and returns them
var options = FHC_TableWidget._getRepresentationOptions(data);
// Checks if record fields definitions were given and returns them
var recordFieldsDefinitions = FHC_TableWidget._getRepresentationFieldsDefinitions(data);
// Manipulation for the representation!
var arrayTabulatorColumns = FHC_TableWidget._getTabulatorColumns(data, recordFieldsDefinitions);
if (arrayTabulatorColumns.length > 0)
{
// ...if there are data to be displayed...
if (data.hasOwnProperty("dataset") && $.isArray(data.dataset))
{
if (options == null) options = {};
options.columns = arrayTabulatorColumns;
options.data = data.dataset;
// Renders the tabulator
tableWidgetDiv.find("#tableWidgetTabulator").tabulator(options);
}
}
},
/**
* Retrives the fields to be displayed from the data parameter, if aliases are present then they are used
*/
_getTabulatorColumns: function(data, recordFieldsDefinitions) {
var fieldsToDisplayTabulator = [];
if (data.hasOwnProperty("fields") && $.isArray(data.fields))
{
for (var sfc = 0; sfc < data.fields.length; sfc++)
{
for (var fc = 0; fc < data.fields.length; fc++)
{
if (data.fields[sfc] == data.fields[fc])
{
// Build the array of objects (columns) used by tabulator and store it in tabulatorColumns
var tmpColumnObj = {}; // New object that represents a column
// If was given a definition for this field then use it!
if (recordFieldsDefinitions != null && recordFieldsDefinitions.hasOwnProperty(data.fields[sfc]))
{
tmpColumnObj = recordFieldsDefinitions[data.fields[sfc]];
}
tmpColumnObj.field = data.fields[sfc]; // Field name to be linked with dataset field name
// If there is an alias for this field use it to give a title to this field (header)
if (data.hasOwnProperty("columnsAliases") && $.isArray(data.columnsAliases))
{
tmpColumnObj.title = data.columnsAliases[fc];
}
else // otherwise use the field name itself
{
tmpColumnObj.title = data.fields[sfc];
}
fieldsToDisplayTabulator.push(tmpColumnObj); // Add tmpColumnObj to tabulatorColumns
}
}
}
}
// If additional columns are present...
if (data.hasOwnProperty("additionalColumns") && data.additionalColumns != null && $.isArray(data.additionalColumns))
{
// ...loops through them
$.each(data.additionalColumns, function(i, additionalColumn) {
var tmpColumnObj = {}; // New object that represents a column
// If was given a definition for this field then use it!
if (recordFieldsDefinitions != null && recordFieldsDefinitions.hasOwnProperty(additionalColumn))
{
tmpColumnObj = recordFieldsDefinitions[additionalColumn];
}
tmpColumnObj.title = additionalColumn; // Give a title to this field (header)
tmpColumnObj.field = additionalColumn; // Field name to be linked with dataset field name
fieldsToDisplayTabulator.push(tmpColumnObj); // Add tmpColumnObj to tabulatorColumns
});
}
return fieldsToDisplayTabulator;
},
/**
* Gets options for the representation
*/
_getRepresentationOptions: function(data) {
var options = {}; // eventually contains options fot the representation
// Checks if options were given
if (data.hasOwnProperty("datasetRepresentationOptions") && data.datasetRepresentationOptions != "")
{
var tmpOptions = eval("(" + data.datasetRepresentationOptions + ")"); // and converts them from string to javascript code
// If it is an object then can be used
if (typeof tmpOptions == "object")
{
options = tmpOptions;
}
}
return options;
},
/**
* Gets record fields definitions to represent the dataset
*/
_getRepresentationFieldsDefinitions: function(data) {
var fieldsDefinitions = {}; // eventually contains record fields definitions
// Checks if record fields definitions was given as parameter
if (data.hasOwnProperty("datasetRepresentationFieldsDefinitions") && data.datasetRepresentationFieldsDefinitions != "")
{
var tmpFDefs = eval("(" + data.datasetRepresentationFieldsDefinitions + ")"); // and converts them from string to javascript code
// If it is an object then can be used
if (typeof tmpFDefs == "object")
{
fieldsDefinitions = tmpFDefs;
}
}
return fieldsDefinitions;
},
/**
* Set what type of dataset representation was choosen
*/
_setDatasetRepresentation: function(data) {
if (data.hasOwnProperty("datasetRepresentation"))
{
FHC_TableWidget._datasetRepresentation = data.datasetRepresentation;
}
},
_getTableWidgetUniqueIdArray: function() {
var tableWidgetUniqueIdArray = [];
$("div[id*='divTableWidgetDataset']").each(function(i, e) {
tableWidgetUniqueIdArray.push(e.attributes["tableUniqueId"].nodeValue);
});
return tableWidgetUniqueIdArray;
}
};
/**
* When JQuery is up
*/
$(document).ready(function() {
FHC_TableWidget.display();
});