diff --git a/core/ViewDataTable/HtmlTable.php b/core/ViewDataTable/HtmlTable.php index 1be90bb670e71743698fdbbf87b7891fa00f752c..0301efd5e3deba78f59ab390953a5d665d6175a4 100644 --- a/core/ViewDataTable/HtmlTable.php +++ b/core/ViewDataTable/HtmlTable.php @@ -223,6 +223,6 @@ class Piwik_ViewDataTable_HtmlTable extends Piwik_ViewDataTable */ public function disableRowEvolution() { - $this->viewProperties['disable_row_evolution'] = true; + $this->variablesDefault['disable_row_evolution'] = true; } } diff --git a/plugins/CoreHome/templates/datatable.css b/plugins/CoreHome/templates/datatable.css index 67a44de37bcc47debd2f9a90858e433b278bdd5a..dec1aa899ecdfb9cb6e9401a87a4284794d47f24 100644 --- a/plugins/CoreHome/templates/datatable.css +++ b/plugins/CoreHome/templates/datatable.css @@ -584,7 +584,6 @@ table.dataTable .dataTableRowActions { display: none; overflow: hidden; margin-top: -5px; - width: 40px; } *+html table.dataTable .dataTableRowActions { margin-top: -7px; @@ -601,6 +600,8 @@ table.dataTable .dataTableRowActions a img { margin: 0; padding: 0; border: 0; + width: 20px; + height: 17px; } diff --git a/plugins/CoreHome/templates/datatable.js b/plugins/CoreHome/templates/datatable.js index 4d28d5fb4221d0f56902dad3aa24d465f043aa23..1355d86cee6ec480f0d2ee049a086daf28bb60c4 100644 --- a/plugins/CoreHome/templates/datatable.js +++ b/plugins/CoreHome/templates/datatable.js @@ -1244,61 +1244,83 @@ dataTable.prototype = trs.each(function() { var tr = $(this); - var actions = tr.find('div.dataTableRowActions'); - if (actions.size() == 0) + var td = tr.find('td:first'); + + // load available actions for this row + var availableActions = DataTable_RowActions_Registry.getAvailableActions(self.param, tr); + if (availableActions.length == 0) { - return true; + return; } - // move before image in actions data table - if (actions.prev().size() > 0) + // call initTr on all available actions + for (var i = 0; i < availableActions.length; i++) { - actions.prev().before(actions); + var action = availableActions[i]; + if (typeof actionInstances[action.name] == "undefined") + { + actionInstances[action.name] = action.createInstance(self); + } + var actionInstance = actionInstances[action.name]; + actionInstance.initTr(tr); } // show actions on hover + var actionsDom = null; tr.hover(function() { - self.repositionRowActions($(this)); - actions.show(); + if (actionsDom === null) + { + // create dom nodes on the fly + actionsDom = self.createRowActions(availableActions, tr, actionInstances); + td.prepend(actionsDom); + } + // reposition and show the actions + self.repositionRowActions(tr); + actionsDom.show(); }, function() { - actions.hide(); + if (actionsDom !== null) + { + actionsDom.hide(); + } }); + }); + }, + + createRowActions: function(availableActions, tr, actionInstances) + { + var container = $(document.createElement('div')).addClass('dataTableRowActions'); + + for (var i = 0; i < availableActions.length; i++) + { + var action = availableActions[i]; + + var actionEl = $(document.createElement('a')).attr({href: '#'}).addClass('action' + action.name); + actionEl.append($(document.createElement('img')).attr({src: action.dataTableIcon})); + container.append(actionEl); - // handle the individual actions - actions.find('> a').each(function() + actionEl.click((function(action) { - var a = $(this); - var className = a.attr('class'); - if (className.substring(0, 6) == 'action') + return function(e) { - var actionName = className.substring(6, className.length); - if (typeof actionInstances[actionName] == "undefined") - { - actionInstances[actionName] = DataTable_RowActions_Factory(actionName, self); - } - var action = actionInstances[actionName]; - action.initTr(tr); - - a.click(function(e) - { - $(this).blur(); - actions.hide(); - action.trigger(tr, e); - return false; - }); + $(this).blur(); + container.hide(); + actionInstances[action.name].trigger(tr, e); + return false; } - }); - }); + })(action)); + } + + return container; }, repositionRowActions: function(tr) { var td = tr.find('td:first'); var actions = tr.find('div.dataTableRowActions'); - actions.height(tr.innerHeight() - 2) - .css('marginLeft', (td.width() + 5 - actions.outerWidth())+'px'); + actions.height(tr.innerHeight() - 2); + actions.css('marginLeft', (td.width() + 5 - actions.outerWidth()) + 'px'); }, _findReportHeader: function(domElem) { @@ -1356,6 +1378,7 @@ actionDataTable.prototype = handleColumnDocumentation: dataTable.prototype.handleColumnDocumentation, handleReportDocumentation: dataTable.prototype.handleReportDocumentation, doHandleRowActions: dataTable.prototype.doHandleRowActions, + createRowActions: dataTable.prototype.createRowActions, repositionRowActions: dataTable.prototype.repositionRowActions, onClickSort: dataTable.prototype.onClickSort, truncate: dataTable.prototype.truncate, diff --git a/plugins/CoreHome/templates/datatable_cell.tpl b/plugins/CoreHome/templates/datatable_cell.tpl index a4f335a0a111f983872c96f6701775c6b9b36383..bde9569505b8805b4088196f29cfc6309d25ad89 100644 --- a/plugins/CoreHome/templates/datatable_cell.tpl +++ b/plugins/CoreHome/templates/datatable_cell.tpl @@ -1,12 +1,3 @@ -{if $column=='label'} - <div class="dataTableRowActions"> - {if (!isset($properties.disable_row_evolution) || $properties.disable_row_evolution === false) - && !(isset($javascriptVariablesToSet.flat) && $javascriptVariablesToSet.flat == 1)} - <a href="#" class="actionRowEvolution"><img src="themes/default/images/row_evolution.png" alt="" /></a> - {/if} - </div> -{/if} - {if !$row.idsubdatatable && $column=='label' && !empty($row.metadata.url)} <a target="_blank" href='{if !in_array(substr($row.metadata.url,0,4), array('http','ftp:'))}http://{/if}{$row.metadata.url|escape:'html'}'> {if empty($row.metadata.logo)} diff --git a/plugins/CoreHome/templates/datatable_rowactions.js b/plugins/CoreHome/templates/datatable_rowactions.js index 15c635fe4206157690c86d0ec13efcb7f1905093..57d2b2dc78298aee8728162a7e00501b3e82aacb 100644 --- a/plugins/CoreHome/templates/datatable_rowactions.js +++ b/plugins/CoreHome/templates/datatable_rowactions.js @@ -1,5 +1,63 @@ /** - * DataTable RowActions + * Registry for row actions + * + * Plugins can call DataTable_RowActions_Registry.register() from their JS + * files in order to add new actions to arbitrary data tables. The register() + * method takes an object containing: + * - name: string identifying the action. must be short, no spaces. + * - dataTableIcon: path to the icon for the action + * - createInstance: a factory method to create an instance of the appropriate + * subclass of DataTable_RowAction + * - isAvailable: a method to determine whether the action is available in a + * given row of a data table + */ +var DataTable_RowActions_Registry = { + + registry: [], + + register: function(action) { + this.registry.push(action); + }, + + getAvailableActions: function(dataTableParams, tr) { + var available = []; + for (var i = 0; i < this.registry.length; i++) { + if (this.registry[i].isAvailable(dataTableParams, tr)) { + available.push(this.registry[i]); + } + } + return available; + } + +}; + +// Register Row Evolution (also servers as example) +DataTable_RowActions_Registry.register({ + + name: 'RowEvolution', + + dataTableIcon: 'themes/default/images/row_evolution.png', + + createInstance: function(dataTable) { + return new DataTable_RowActions_RowEvolution(dataTable); + }, + + isAvailable: function(dataTableParams, tr) { + return ( + typeof dataTableParams.disable_row_evolution == 'undefined' + || dataTableParams.disable_row_evolution == "0" + ) && ( + typeof dataTableParams.flat == 'undefined' + || dataTableParams.flat == "0" + ); + } + +}); + + + +/** + * DataTable Row Actions * * The lifecycle of an action is as follows: * - for each data table, a new instance of the action is created using the factory @@ -13,19 +71,6 @@ */ -/** - * Factory function for creating action instances dynamically. - * It's designed to decouple the row actions from the data table code. - * Also, custom actions can be added more easily this way. - */ -function DataTable_RowActions_Factory(actionName, dataTable) { - var className = 'DataTable_RowActions_' + actionName; - eval('if (typeof ' + className + ' == "undefined") alert("Invalid action: ' + className + '");' + - 'var instance = new ' + className + '(dataTable)'); - return instance; -} - - // // BASE CLASS //