diff --git a/core/Controller.php b/core/Controller.php
index 1187b084d9c619760a814cadfc8e34a8d4f3f590..9c1fe1519b0f7aac07d82106a76fb2df29847491 100644
--- a/core/Controller.php
+++ b/core/Controller.php
@@ -158,19 +158,7 @@ abstract class Controller
      */
     protected function renderView(ViewDataTable $view, $fetch = false)
     {
-        Piwik_PostEvent('Controller.renderView', array(
-                                                      $this,
-                                                      array('view'                                      => $view,
-                                                            'controllerName'                            => $view->getCurrentControllerName(),
-                                                            'controllerAction'                          => $view->getCurrentControllerAction(),
-                                                            'apiMethodToRequestDataTable'               => $view->getApiMethodToRequestDataTable(),
-                                                            'controllerActionCalledWhenRequestSubTable' => $view->getControllerActionCalledWhenRequestSubTable(),
-                                                      )
-                                                 ));
-
-        $view->main();
-
-        $rendered = $view->getView()->render();
+        $rendered = $view->render();
         if ($fetch) {
             return $rendered;
         }
@@ -597,7 +585,7 @@ abstract class Controller
     protected function setMetricsVariablesView(ViewDataTable $view, $defaultMetricDay = 'nb_uniq_visitors',
                                                $defaultMetric = 'nb_visits', $metricsForDay = array('nb_uniq_visitors'),
                                                $metricsForAllPeriods = array('nb_visits', 'nb_actions'), $labelDisplayed = true)
-    {
+    {// TODO: needed?
         // columns is set in the request if metrics picker has been used
         $columns = Common::getRequestVar('columns', false);
         if ($columns !== false) {
@@ -612,7 +600,7 @@ abstract class Controller
         if ($labelDisplayed) {
             array_unshift($columns, 'label');
         }
-        $view->setColumnsToDisplay($columns);
+        $view->columns_to_display = $columns;
     }
 
     /**
diff --git a/core/ViewDataTable.php b/core/ViewDataTable.php
index 86a29eca336883930ad3b281266a612845efa4fc..edd136abe0dc88523a0320f149aee22dce485014 100644
--- a/core/ViewDataTable.php
+++ b/core/ViewDataTable.php
@@ -21,6 +21,7 @@ use Piwik\DataTable;
 use Piwik\Url;
 use Piwik\Site;
 use Piwik\ViewDataTable\Properties;
+use Piwik\ViewDataTable\VisualizationPropertiesProxy;
 use Piwik_API_API;
 
 /**
@@ -57,6 +58,12 @@ use Piwik_API_API;
  */
 abstract class ViewDataTable
 {
+    /**
+     * TODO
+     * TODO: change to private
+     */
+    protected $visualization;
+
     /**
      * Cache for getAllReportDisplayProperties result.
      * 
@@ -132,6 +139,7 @@ abstract class ViewDataTable
      */
     public function __construct()
     {
+        $this->viewProperties['visualization_properties'] = new VisualizationPropertiesProxy(null);
         $this->viewProperties['datatable_template'] = '@CoreHome/_dataTable';
         $this->viewProperties['show_goals'] = false;
         $this->viewProperties['show_ecommerce'] = false;
@@ -199,7 +207,6 @@ abstract class ViewDataTable
     public function &__get($name)
     {
         Properties::checkValidPropertyName($name);
-
         return $this->viewProperties[$name];
     }
 
@@ -215,17 +222,33 @@ abstract class ViewDataTable
     public function __set($name, $value)
     {
         Properties::checkValidPropertyName($name);
-
         return $this->viewProperties[$name] = $value;
     }
 
     /**
-     * Method to be implemented by the ViewDataTable_*.
-     * This method should create and initialize a $this->view object @see Piwik_View_Interface
-     *
-     * @return mixed either prints the result or returns the output string
+     * TODO
      */
-    abstract public function main();
+    public function main()
+    {
+        if ($this->mainAlreadyExecuted) {
+            return;
+        }
+        $this->mainAlreadyExecuted = true;
+
+        try {
+            $this->loadDataTableFromAPI();
+        } catch (\Piwik\NoAccessException $e) {
+            throw $e;
+        } catch (Exception $e) {
+            Piwik::log("Failed to get data from API: " . $e->getMessage());
+
+            $this->loadingError = array('message' => $e->getMessage());
+        }
+
+        $this->postDataTableLoadedFromAPI();
+
+        $this->view = $this->buildView($this->visualization);
+    }
 
     /**
      * Unique string ID that defines the format of the dataTable, eg. "pieChart", "table", etc.
@@ -411,10 +434,6 @@ abstract class ViewDataTable
         $this->viewProperties['report_id'] = $currentControllerName . '.' . $currentControllerAction;
         $this->viewProperties['self_url'] = $this->getBaseReportUrl($currentControllerName, $currentControllerAction);
 
-        if (!\Piwik\PluginsManager::getInstance()->isPluginActivated('Goals')) {
-            $this->viewProperties['show_goals'] = false;
-        }
-
         // the exclude low population threshold value is sometimes obtained by requesting data.
         // to avoid issuing unecessary requests when display properties are determined by metadata,
         // we allow it to be a closure.
@@ -469,16 +488,6 @@ abstract class ViewDataTable
         return $this->currentControllerName;
     }
 
-    public function getApiMethodToRequestDataTable()
-    {
-        return $this->viewProperties['apiMethodToRequestDataTable'];
-    }
-
-    public function getControllerActionCalledWhenRequestSubTable()
-    {
-        return $this->viewProperties['subtable_controller_action'];
-    }
-
     /**
      * Returns the DataTable loaded from the API
      *
@@ -554,7 +563,7 @@ abstract class ViewDataTable
         if ($name == 'translations') {
             $this->viewProperties[$name] = array_merge($this->viewProperties[$name], $value);
         } else if ($name == 'relatedReports') {
-            $this->addRelatedReports($reportTitle = false, $value);
+            $this->addRelatedReports($value);
         } else if ($name == 'filters') {
             foreach ($value as $filterInfo) {
                 if (!is_array($filterInfo)) {
@@ -795,39 +804,15 @@ abstract class ViewDataTable
             $requestArray['segment'] = $segment;
         }
 
+        if (self::shouldLoadExpanded()) {
+            $requestArray['expanded'] = 1;
+        }
+
         $requestArray = array_merge($requestArray, $this->viewProperties['request_parameters_to_modify']);
 
         return $requestArray;
     }
 
-    /**
-     * For convenience, the client code can call methods that are defined in a specific children class
-     * without testing the children class type, which would trigger an error with a different children class.
-     *
-     * Example:
-     *  ViewDataTable/Html.php defines a setColumnsToDisplay(). The client code calls this methods even if
-     *  the ViewDataTable object is a ViewDataTable_Cloud instance (he doesn't know because of the factory()).
-     *  But ViewDataTable_Cloud doesn't define the setColumnsToDisplay() method.
-     *  Because we don't want to force users to test for the object type we simply catch these
-     *  calls when they are not defined in the child and do nothing.
-     *
-     * @param string $function
-     * @param array $args
-     */
-    public function __call($function, $args)
-    {
-    }
-
-    /**
-     * Returns array of properties, eg. "show_footer", "show_search", etc.
-     *
-     * @return array of boolean
-     */
-    protected function getViewProperties()
-    {
-        return $this->viewProperties;
-    }
-
     /**
      * This functions reads the customization values for the DataTable and returns an array (name,value) to be printed in Javascript.
      * This array defines things such as:
@@ -976,376 +961,6 @@ abstract class ViewDataTable
         return $this->viewProperties[$nameVar];
     }
 
-    /**
-     * Sets a set of extra request query parameters to be used when querying API data.
-     *
-     * @param array $params
-     */
-    public function setRequestParametersToModify($params)
-    {
-        $this->viewProperties['request_parameters_to_modify'] += $params;
-    }
-
-    /**
-     * The generic filters (limit, offset, sort by visit desc) will not be applied to this datatable.
-     */
-    public function disableGenericFilters()
-    {
-        $this->viewProperties['disable_generic_filters'] = true;
-    }
-
-    /**
-     * The queued filters (replace column names, enhance column with percentage signs, add logo metadata information, etc.)
-     * will not be applied to this datatable. They can be manually applied by calling applyQueuedFilters on the datatable.
-     */
-    public function disableQueuedFilters()
-    {
-        $this->viewProperties['disable_queued_filters'] = true;
-    }
-
-    /**
-     * The "X-Y of Z" and the "< Previous / Next >"-Buttons won't be displayed under this table
-     */
-    public function disableOffsetInformationAndPaginationControls()
-    {
-        $this->viewProperties['show_offset_information'] = false;
-        $this->viewProperties['show_pagination_control'] = false;
-    }
-
-    /**
-     * The "< Previous / Next >"-Buttons won't be displayed under this table
-     */
-    public function disableShowPaginationControl()
-    {
-        $this->viewProperties['show_pagination_control'] = false;
-    }
-
-    /**
-     * Ensures the limit dropdown will always be shown, even if pagination is disabled.
-     */
-    public function alwaysShowLimitDropdown()
-    {
-        $this->viewProperties['show_limit_control'] = true;
-    }
-
-    /**
-     * The "X-Y of Z" won't be displayed under this table
-     */
-    public function disableOffsetInformation()
-    {
-        $this->viewProperties['show_offset_information'] = false;
-    }
-
-    /**
-     * The search box won't be displayed under this table
-     */
-    public function disableSearchBox()
-    {
-        $this->viewProperties['show_search'] = false;
-    }
-
-    /**
-     * Do not sort this table, leave it as it comes out of the API
-     */
-    public function disableSort()
-    {
-        $this->viewProperties['enable_sort'] = false;
-    }
-
-    /**
-     * Do not show the footer icons (show all columns icon, "plus" icon)
-     */
-    public function disableFooterIcons()
-    {
-        $this->viewProperties['show_footer_icons'] = false;
-    }
-
-    /**
-     * When this method is called, the output will not include the template datatable_footer
-     */
-    public function disableFooter()
-    {
-        $this->viewProperties['show_footer'] = false;
-    }
-
-    /**
-     * The "Include low population" link won't be displayed under this table
-     */
-    public function disableExcludeLowPopulation()
-    {
-        $this->viewProperties['show_exclude_low_population'] = false;
-    }
-
-    /**
-     * Whether or not to show the "View table" icon
-     */
-    public function disableShowTable()
-    {
-        $this->viewProperties['show_table'] = false;
-    }
-
-    /**
-     * Whether or not to show the "View more data" icon
-     */
-    public function disableShowAllColumns()
-    {
-        $this->viewProperties['show_table_all_columns'] = false;
-    }
-
-    /**
-     * Whether or not to show the tag cloud,  pie charts, bar chart icons
-     */
-    public function disableShowAllViewsIcons()
-    {
-        $this->viewProperties['show_all_views_icons'] = false;
-    }
-
-    /**
-     * Whether or not to hide view icons altogether.
-     * The difference to disableShowAllViewsIcons is that not even the single icon
-     * will be shown. This icon might cause trouble because it reloads the graph on click.
-     */
-    public function hideAllViewsIcons()
-    {
-        $this->viewProperties['show_all_views_icons'] = false;
-        $this->viewProperties['show_active_view_icon'] = false;
-    }
-
-    /**
-     * Whether or not to show the annotations view. This method has no effect if
-     * the Annotations plugin is not loaded.
-     */
-    public function showAnnotationsView()
-    {
-        if (!\Piwik\PluginsManager::getInstance()->isPluginLoaded('Annotations')) {
-            return;
-        }
-
-        $this->viewProperties['hide_annotations_view'] = false;
-    }
-
-    /**
-     * Whether or not to show the bar chart icon.
-     */
-    public function disableShowBarChart()
-    {
-        $this->viewProperties['show_bar_chart'] = false;
-    }
-
-    /**
-     * Whether or not to show the pie chart icon.
-     */
-    public function disableShowPieChart()
-    {
-        $this->viewProperties['show_pie_chart'] = false;
-    }
-
-    /**
-     * Whether or not to show the tag cloud icon.
-     */
-    public function disableTagCloud()
-    {
-        $this->viewProperties['show_tag_cloud'] = false;
-    }
-
-    /**
-     * Whether or not to show related reports in the footer
-     */
-    public function disableShowRelatedReports()
-    {
-        $this->viewProperties['show_related_reports'] = false;
-    }
-
-    /**
-     * Whether or not to show the export to RSS feed icon
-     */
-    public function disableShowExportAsRssFeed()
-    {
-        $this->viewProperties['show_export_as_rss_feed'] = false;
-    }
-
-    /**
-     * Whether or not to show the "goal" icon
-     */
-    public function enableShowGoals()
-    {
-        if (\Piwik\PluginsManager::getInstance()->isPluginActivated('Goals')) {
-            $this->viewProperties['show_goals'] = true;
-        }
-    }
-
-    /**
-     * Whether or not to show the "Ecommerce orders/cart" icons
-     */
-    public function enableShowEcommerce()
-    {
-        $this->viewProperties['show_ecommerce'] = true;
-    }
-
-    /**
-     * Whether or not to show the summary row on every page of results. The default behavior
-     * is to treat the summary row like any other row.
-     */
-    public function alwaysShowSummaryRow()
-    {
-        $this->viewProperties['keep_summary_row'] = true;
-    }
-
-    /**
-     * Sets the value to use for the Exclude low population filter.
-     *
-     * @param int|float $columnName  If a row value is less than this value, it will be removed from the dataTable
-     * @param string    $minValue    The name of the column for which we compare the value to $minValue
-     */
-    public function setExcludeLowPopulation($columnName = null, $minValue = null)
-    {
-        if (is_null($columnName)) {
-            $columnName = 'nb_visits';
-        }
-        $this->viewProperties['filter_excludelowpop'] = $columnName;
-        $this->viewProperties['filter_excludelowpop_value'] = $minValue;
-    }
-
-    /**
-     * Sets the pattern to look for in the table (only rows matching the pattern will be kept)
-     *
-     * @param string $pattern to look for
-     * @param string $column to compare the pattern to
-     */
-    public function setSearchPattern($pattern, $column)
-    {
-        $this->viewProperties['filter_pattern'] = $pattern;
-        $this->viewProperties['filter_column'] = $column;
-    }
-
-    /**
-     * Sets the maximum number of rows of the table
-     *
-     * @param int $limit
-     */
-    public function setLimit($limit)
-    {
-        if ($limit !== 0) {
-            $this->viewProperties['filter_limit'] = $limit;
-        }
-    }
-
-    /**
-     * Will display a message in the DataTable footer.
-     *
-     * @param string $message Message
-     */
-    public function setFooterMessage($message)
-    {
-        $this->viewProperties['show_footer_message'] = $message;
-    }
-
-    /**
-     * Sets the dataTable column to sort by. This sorting will be applied before applying the (offset, limit) filter.
-     *
-     * @param int|string $columnId eg. 'nb_visits' for some tables, or Metrics::INDEX_NB_VISITS for others
-     * @param string $order desc or asc
-     */
-    public function setSortedColumn($columnId, $order = 'desc')
-    {
-        $this->viewProperties['filter_sort_column'] = $columnId;
-        $this->viewProperties['filter_sort_order'] = $order;
-    }
-
-    /**
-     * Returns the column name on which the table will be sorted
-     *
-     * @return string
-     */
-    public function getSortedColumn()
-    {
-        return isset($this->viewProperties['filter_sort_column']) ? $this->viewProperties['filter_sort_column'] : false;
-    }
-
-    /**
-     * Sets translation string for given column
-     *
-     * @param string $columnName column name
-     * @param string $columnTranslation column name translation
-     * @throws \Exception
-     */
-    public function setColumnTranslation($columnName, $columnTranslation)
-    {
-        $this->viewProperties['translations'][$columnName] = $columnTranslation;
-    }
-
-    /**
-     * Returns column translation if available, in other case given column name
-     *
-     * @param string $columnName column name
-     * @return string
-     */
-    public function getColumnTranslation($columnName)
-    {
-        if (isset($this->viewProperties['translations'][$columnName])) {
-            return $this->viewProperties['translations'][$columnName];
-        }
-        return $columnName;
-    }
-
-    /**
-     * Set the documentation of a metric used in the report.
-     * Please note, that the default way of doing this is by using
-     * getReportMetadata. Only use this method, if you have a good
-     * reason to do so.
-     *
-     * @param string $metricIdentifier The idenentifier string of
-     *                    the metric
-     * @param string $documentation The metric documentation as a
-     *                    translated string
-     */
-    public function setMetricDocumentation($metricIdentifier, $documentation)
-    {
-        $this->viewProperties['metrics_documentation'][$metricIdentifier] = $documentation;
-    }
-
-    /**
-     * Returns metric documentation, or false
-     *
-     * @param string $columnName column name
-     * @return bool
-     */
-    public function getMetricDocumentation($columnName)
-    {
-        if (empty($this->viewProperties['metrics_documentation'])) {
-            $this->loadDocumentation();
-        }
-
-        if (!empty($this->viewProperties['metrics_documentation'][$columnName])) {
-            return $this->viewProperties['metrics_documentation'][$columnName];
-        }
-
-        return false;
-    }
-
-    /**
-     * Set the documentation of the report.
-     * Please note, that the default way of doing this is by using
-     * getReportMetadata. Only use this method, if you have a good
-     * reason to do so.
-     *
-     * @param string $documentation The report documentation as a
-     *                    translated string
-     */
-    public function setReportDocumentation($documentation)
-    {
-        $this->viewProperties['documentation'] = $documentation;
-    }
-
-    /**
-     * Returns report documentation, or false
-     * @return array|bool
-     */
-    public function getReportDocumentation()
-    {
-        return $this->viewProperties['documentation'];
-    }
-
     /** Load documentation from the API */
     private function loadDocumentation()
     {
@@ -1363,49 +978,6 @@ abstract class ViewDataTable
         }
     }
 
-    /**
-     * Sets the columns that will be displayed in the HTML output
-     * By default all columns are displayed ($columnsNames = array() will display all columns)
-     *
-     * @param array $columnsNames Array of column names eg. array('nb_visits','nb_hits')
-     */
-    public function setColumnsToDisplay($columnsNames)
-    {
-        if (!is_array($columnsNames)) {
-            if (strpos($columnsNames, ',') !== false) {
-                // array values are comma separated
-                $columnsNames = explode(',', $columnsNames);
-            } else {
-                $columnsNames = array($columnsNames);
-            }
-        }
-        $this->viewProperties['columns_to_display'] = array_filter($columnsNames);
-    }
-
-    /**
-     * Returns columns names to display, in order.
-     * If no columns were specified to be displayed, return all columns found in the first row.
-     * If the data table has empty_columns meta data set, those columns will be removed.
-     * @return array
-     */
-    public function getColumnsToDisplay()
-    {
-        if (empty($this->viewProperties['columns_to_display'])) {
-            $row = $this->dataTable->getFirstRow();
-            if (empty($row)) {
-                return array();
-            }
-
-            return array_keys($row->getColumns());
-        }
-
-        $this->viewProperties['columns_to_display'] = array_filter($this->viewProperties['columns_to_display']);
-
-        $this->removeEmptyColumnsFromDisplay();
-
-        return $this->viewProperties['columns_to_display'];
-    }
-
     private function removeEmptyColumnsFromDisplay()
     {
         if (empty($this->dataTable)) {
@@ -1427,48 +999,6 @@ abstract class ViewDataTable
         }
     }
 
-    /**
-     * Set whether to highlight the summary row or not. If not highlighted, it will
-     * look like every other row.
-     */
-    public function setHighlightSummaryRow($highlightSummaryRow)
-    {
-        $this->viewProperties['highlight_summary_row'] = $highlightSummaryRow;
-    }
-
-    /**
-     * Sets the name of the metadata to use for a custom tooltip.
-     */
-    public function setTooltipMetadataName($metadataName)
-    {
-        $this->viewProperties['tooltip_metadata_name'] = $metadataName;
-    }
-
-    /**
-     * Sets columns translations array.
-     *
-     * @param array $columnsTranslations An associative array indexed by column names, eg. array('nb_visit'=>"Numer of visits")
-     */
-    public function setColumnsTranslations($columnsTranslations)
-    {
-        $this->viewProperties['translations'] += $columnsTranslations;
-    }
-
-    /**
-     * Sets a custom parameter, that will be printed in the javascript array associated with each datatable
-     *
-     * @param string $parameter name
-     * @param mixed $value
-     * @throws \Exception
-     */
-    public function setCustomParameter($parameter, $value)
-    {
-        if (isset($this->viewProperties['custom_parameters'][$parameter])) {
-            throw new \Exception("$parameter is already defined for this DataTable.");
-        }
-        $this->viewProperties['custom_parameters'][$parameter] = $value;
-    }
-
     /**
      * Queues a Datatable filter, that will be applied once the datatable is loaded from the API.
      * Useful when the controller needs to add columns, or decorate existing columns, when these filters don't
@@ -1489,21 +1019,7 @@ abstract class ViewDataTable
         }
     }
 
-    /**
-     * Adds one report to the set of reports that are related to this one. Related reports
-     * are displayed in the footer as links. When they are clicked, the report will change to
-     * the related report.
-     *
-     * Make sure to call setReportTitle so this report will be displayed correctly.
-     *
-     * @param string $module The report's controller name, ie, 'UserSettings'.
-     * @param string $action The report's controller action, ie, 'getBrowser'.
-     * @param string $title The text used to describe the related report.
-     * @param array $queryParams Any specific query params to use when loading the report.
-     *                           This can be used to, for example, make a goal report a related
-     *                           report (by adding an idGoal parameter).
-     */
-    public function addRelatedReport($module, $action, $title, $queryParams = array())
+    private function addRelatedReport($module, $action, $title, $queryParams = array())
     {
         // don't add the related report if it references this report
         if ($this->currentControllerName == $module && $this->currentControllerAction == $action) {
@@ -1514,51 +1030,14 @@ abstract class ViewDataTable
         $this->viewProperties['relatedReports'][$url] = $title;
     }
 
-    /**
-     * Adds a set of reports that are related to this one. Related reports are displayed in
-     * the footer as links. When they are clicked, the report will change to the related report.
-     *
-     * If you need to associate specific query params with a report, use the addRelatedReport
-     * method instead of this one.
-     *
-     * @param string $thisReportTitle The title of this report.
-     * @param array $relatedReports An array mapping report IDs ('Controller.methodName') with
-     *                              display text.
-     */
-    public function addRelatedReports($thisReportTitle, $relatedReports)
+    private function addRelatedReports($relatedReports)
     {
-        if (!empty($thisReportTitle)) {
-            $this->setReportTitle($thisReportTitle);
-        }
-
         foreach ($relatedReports as $report => $title) {
             list($module, $action) = explode('.', $report);
             $this->addRelatedReport($module, $action, $title);
         }
     }
 
-    /**
-     * Sets the title of this report.
-     *
-     * @param string $title
-     */
-    public function setReportTitle($title)
-    {
-        $this->viewProperties['title'] = $title;
-    }
-
-    /**
-     * Sets a custom URL to use to reference this report.
-     *
-     * @param string $module
-     * @param string $action
-     * @param array $queryParams
-     */
-    public function setReportUrl($module, $action, $queryParams = array())
-    {
-        $this->viewProperties['self_url'] = $this->getBaseReportUrl($module, $action, $queryParams);
-    }
-
     /**
      * Returns true if it is likely that the data for this report has been purged and if the
      * user should be told about that.
@@ -1706,12 +1185,30 @@ abstract class ViewDataTable
         return false;
     }
 
-    protected function buildView($visualization, $template = false)
+    protected function overrideViewProperties()
     {
-        if ($template === false) {
-            $template = $this->viewProperties['datatable_template'];
+        if (!\Piwik\PluginsManager::getInstance()->isPluginActivated('Goals')) {
+            $this->viewProperties['show_goals'] = false;
         }
 
+        if (!\Piwik\PluginsManager::getInstance()->isPluginLoaded('Annotations')) {
+            $this->viewProperties['hide_annotations_view'] = true;
+        }
+
+        if ($this->idSubtable) {
+            $this->viewProperties['datatable_template'] = $this->viewProperties['subtable_template'];
+        }
+    }
+
+    protected function buildView($visualization)
+    {
+        if (method_exists($visualization, 'getDefaultPropertyValues')) {
+            $this->setPropertyDefaults($visualization->getDefaultPropertyValues());
+        }
+
+        $this->overrideViewProperties();
+
+        $template = $this->viewProperties['datatable_template'];
         $view = new View($template);
 
         if (!empty($this->loadingError)) {
@@ -1731,7 +1228,7 @@ abstract class ViewDataTable
             $view->deleteReportsOlderThan = Piwik_GetOption('delete_reports_older_than');
         }
         $view->javascriptVariablesToSet = $this->getJavascriptVariablesToSet();
-        $view->properties = $this->getViewProperties();
+        $view->properties = $this->viewProperties;
         return $view;
     }
 
@@ -1739,4 +1236,16 @@ abstract class ViewDataTable
     {
         return false;
     }
-}
+
+    /**
+     * TODO
+     */
+    private function setPropertyDefaults($defaultValues)
+    {
+        foreach ($defaultValues as $name => $value) {
+            if (empty($this->viewProperties[$name])) {
+                $this->viewProperties[$name] = $value;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/ViewDataTable/Cloud.php b/core/ViewDataTable/Cloud.php
index c798a00f3bedebd8d798eb7a0fe8de542458009b..60488ff8df51c52050ac1a1babf2884b43493fec 100644
--- a/core/ViewDataTable/Cloud.php
+++ b/core/ViewDataTable/Cloud.php
@@ -39,8 +39,8 @@ class Cloud extends ViewDataTable
     {
         parent::__construct();
 
-        $this->disableOffsetInformation();
-        $this->disableExcludeLowPopulation();
+        $this->viewProperties['show_offset_information'] = false;
+        $this->viewProperties['show_exclude_low_population'] = false;
         $this->viewProperties['display_logo_instead_of_label'] = false;
     }
 
diff --git a/core/ViewDataTable/GenerateGraphHTML.php b/core/ViewDataTable/GenerateGraphHTML.php
index d4d4a3180046c7fdca0e98641db50b967dd6a57d..078571109db496d448153091f0602cb9a4a3f815 100644
--- a/core/ViewDataTable/GenerateGraphHTML.php
+++ b/core/ViewDataTable/GenerateGraphHTML.php
@@ -33,15 +33,18 @@ abstract class GenerateGraphHTML extends ViewDataTable
 
     protected $graphType;
 
+    /**
+     * Default constructor.
+     */
     public function __construct()
     {
         parent::__construct();
-
-        $this->disableOffsetInformationAndPaginationControls();
-        $this->disableExcludeLowPopulation();
-        $this->disableSearchBox();
-        $this->enableShowExportAsImageIcon();
-
+        
+        $this->viewProperties['show_offset_information'] = false;
+        $this->viewProperties['show_pagination_control'] = false;
+        $this->viewProperties['show_exclude_low_population'] = false;
+        $this->viewProperties['show_search'] = false;
+        $this->viewProperties['show_export_as_image_icon'] = true;
         $this->viewProperties['display_percentage_in_tooltip'] = true;
         $this->viewProperties['y_axis_unit'] = '';
         $this->viewProperties['show_all_ticks'] = 0;
@@ -55,65 +58,6 @@ abstract class GenerateGraphHTML extends ViewDataTable
         $this->viewProperties['graph_height'] = self::DEFAULT_GRAPH_HEIGHT . 'px';
     }
 
-    /**
-     * Default constructor.
-     */
-    public function setAxisYUnit($unit)
-    {
-        $this->viewProperties['y_axis_unit'] = $unit;
-    }
-
-    /**
-     * Sets the number max of elements to display (number of pie slice, vertical bars, etc.)
-     * If the data has more elements than $limit then the last part of the data will be the sum of all the remaining data.
-     *
-     * @param int $limit
-     */
-    public function setGraphLimit($limit)
-    {
-        $this->viewProperties['graph_limit'] = $limit;
-    }
-
-    /**
-     * The percentage in tooltips is computed based on the sum of all values for the plotted column.
-     * If the sum of the column in the data set is not the number of elements in the data set,
-     * for example when plotting visits that have a given plugin enabled:
-     * one visit can have several plugins, hence the sum is much greater than the number of visits.
-     * In this case displaying the percentage doesn't make sense.
-     */
-    public function disallowPercentageInGraphTooltip()
-    {
-        $this->viewProperties['display_percentage_in_tooltip'] = false;
-    }
-
-    /**
-     * Sets the columns that can be added/removed by the user
-     * This is done on data level (not html level) because the columns might change after reloading via sparklines
-     * @param array $columnsNames Array of column names eg. array('nb_visits','nb_hits')
-     */
-    public function setSelectableColumns($columnsNames)
-    {
-        // the array contains values if enableShowGoals() has been used
-        // add $columnsNames to the beginning of the array
-        $this->viewProperties['selectable_columns'] = array_merge($columnsNames, $this->viewProperties['selectable_columns']);
-    }
-
-    /**
-     * The implementation of this method in ViewDataTable passes to the graph whether the
-     * goals icon should be displayed or not. Here, we use it to implicitly add the goal metrics
-     * to the metrics picker.
-     */
-    public function enableShowGoals()
-    {
-        parent::enableShowGoals();
-
-        $goalMetrics = array('nb_conversions', 'revenue');
-        $this->viewProperties['selectable_columns'] = array_merge($this->viewProperties['selectable_columns'], $goalMetrics);
-
-        $this->setColumnTranslation('nb_conversions', Piwik_Translate('Goals_ColumnConversions'));
-        $this->setColumnTranslation('revenue', Piwik_Translate('General_TotalRevenue'));
-    }
-
     public function init($currentControllerName,
                          $currentControllerAction,
                          $apiMethodToRequestDataTable,
@@ -130,7 +74,7 @@ abstract class GenerateGraphHTML extends ViewDataTable
         $this->viewProperties['request_parameters_to_modify']['action'] = $currentControllerAction;
 
         // do not sort if sorted column was initially "label" or eg. it would make "Visits by Server time" not pretty
-        if ($this->getSortedColumn() != 'label') {
+        if ($this->viewProperties['filter_sort_column'] != 'label') {
             $columns = $this->viewProperties['columns_to_display'];
 
             $firstColumn = reset($columns);
@@ -138,7 +82,8 @@ abstract class GenerateGraphHTML extends ViewDataTable
                 $firstColumn = next($columns);
             }
 
-            $this->setSortedColumn($firstColumn);
+            $this->viewProperties['filter_sort_column'] = $firstColumn;
+            $this->viewProperties['filter_sort_order'] = 'desc';
         }
 
         // selectable columns
@@ -149,52 +94,6 @@ abstract class GenerateGraphHTML extends ViewDataTable
             }
             $this->viewProperties['selectable_columns'] = $selectableColumns;
         }
-
-        if ($this->viewProperties['show_goals']) {
-            $this->enableShowGoals();
-        }
-    }
-
-    public function enableShowExportAsImageIcon()
-    {
-        $this->viewProperties['show_export_as_image_icon'] = true;
-    }
-
-    public function addRowEvolutionSeriesToggle($initiallyShowAllMetrics)
-    {
-        $this->viewProperties['external_series_toggle'] = 'RowEvolutionSeriesToggle';
-        $this->viewProperties['external_series_toggle_show_all'] = $initiallyShowAllMetrics;
-    }
-
-    /**
-     * Show every x-axis tick instead of just every other one.
-     */
-    public function showAllTicks()
-    {
-        $this->viewProperties['show_all_ticks'] = 1;
-    }
-
-    /**
-     * Adds a row to the report containing totals for contained metrics. Mainly useful
-     * for evolution graphs where displaying the totals w/ the metrics is useful.
-     */
-    public function addTotalRow()
-    {
-        $this->viewProperties['add_total_row'] = 1;
-    }
-
-    /**
-     * Adds the same series picker as parent::setSelectableColumns but the selectable series are not
-     * columns of a single row but the same column across multiple rows, e.g. the number of visits
-     * for each referrer type.
-     * @param array $visibleRows the rows that are initially visible
-     * @param string $matchBy the way the items in $visibleRows are matched with the data. possible values:
-     *                            - label: matches the label of the row
-     */
-    public function addRowPicker($visibleRows, $matchBy = 'label')
-    {
-        $this->viewProperties['row_picker_mach_rows_by'] = $matchBy;
-        $this->viewProperties['row_picker_visible_rows'] = is_array($visibleRows) ? $visibleRows : array($visibleRows);
     }
 
     /**
@@ -227,11 +126,11 @@ abstract class GenerateGraphHTML extends ViewDataTable
         $this->mainAlreadyExecuted = true;
 
         // Graphs require the full dataset, so no filters
-        $this->disableGenericFilters();
-
+        $this->disable_generic_filters = true;
+        
         // the queued filters will be manually applied later. This is to ensure that filtering using search
         // will be done on the table before the labels are enhanced (see ReplaceColumnNames)
-        $this->disableQueuedFilters();
+        $this->disable_queued_filters = true;
 
         try {
             $this->loadDataTableFromAPI();
@@ -260,4 +159,17 @@ abstract class GenerateGraphHTML extends ViewDataTable
     {
         return 'dataTableGraph';
     }
+
+    protected function overrideViewProperties()
+    {
+        parent::overrideViewProperties();
+
+        if ($this->viewProperties['show_goals']) {
+            $goalMetrics = array('nb_conversions', 'revenue');
+            $this->viewProperties['selectable_columns'] = array_merge($this->viewProperties['selectable_columns'], $goalMetrics);
+
+            $this->translations['nb_conversions'] = Piwik_Translate('Goals_ColumnConversions');
+            $this->translations['revenue'] = Piwik_Translate('General_TotalRevenue');
+        }
+    }
 }
diff --git a/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php b/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php
index 85057c719cce445d93c9d470cd61ea046abd8740..919b002587a7958cb3185de2203aeffc0ece84f6 100644
--- a/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php
+++ b/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php
@@ -66,10 +66,11 @@ class ChartEvolution extends GenerateGraphHTML
             $defaultProperties);
 
         $this->calculateEvolutionDateRange();
-        $this->disableShowAllViewsIcons();
-        $this->disableShowTable();
-        $this->disableShowAllColumns();
-        $this->showAnnotationsView();
+        $this->viewProperties['show_all_views_icons'] = false;
+        $this->viewProperties['show_table'] = false;
+        $this->viewProperties['show_table'] = false;
+        $this->viewProperties['show_table_all_columns'] = false;
+        $this->viewProperties['hide_annotations_view'] = false;
     }
 
     /**
@@ -98,18 +99,15 @@ class ChartEvolution extends GenerateGraphHTML
         $defaultLastN = self::getDefaultLastN($period);
         $this->originalDate = Common::getRequestVar('date', 'last' . $defaultLastN, 'string');
 
-        if ($period != 'range') // show evolution limit if the period is not a range
-        {
-            $this->alwaysShowLimitDropdown();
+        if ($period != 'range') { // show evolution limit if the period is not a range
+            $this->viewProperties['show_limit_control'] = true;
 
             // set the evolution_{$period}_last_n query param
-            if (Range::parseDateRange($this->originalDate)) // if a multiple period
-            {
+            if (Range::parseDateRange($this->originalDate)) { // if a multiple period
                 // overwrite last_n param using the date range
                 $oPeriod = new Range($period, $this->originalDate);
                 $lastN = count($oPeriod->getSubperiods());
-            } else // if not a multiple period
-            {
+            } else { // if not a multiple period
                 list($newDate, $lastN) = self::getDateRangeAndLastN($period, $this->originalDate, $defaultLastN);
                 $this->viewProperties['request_parameters_to_modify']['date'] = $newDate;
             }
diff --git a/core/ViewDataTable/HtmlTable.php b/core/ViewDataTable/HtmlTable.php
index 67f2d39a940da59c889275c127293d8261031f11..74abb973935441332581bbe00e4e3c452f0f15c6 100644
--- a/core/ViewDataTable/HtmlTable.php
+++ b/core/ViewDataTable/HtmlTable.php
@@ -29,144 +29,26 @@ use Piwik\Visualization;
  */
 class HtmlTable extends ViewDataTable
 {
-    /**
-     * PHP array conversion of the DataTable
-     *
-     * @var array
-     */
-    public $arrayDataTable; // phpArray
-
     public function __construct()
     {
         parent::__construct();
 
-        $this->viewProperties['enable_sort'] = '1';
-        $this->viewProperties['disable_row_evolution'] = false;
-        $this->viewProperties['disable_row_actions'] = false;
-
-        $this->setLimit(Config::getInstance()->General['datatable_default_limit']);
-        $this->handleLowPopulation();
-        $this->setSubtableTemplate("@CoreHome/_dataTable.twig");
-        $this->viewProperties['datatable_js_type'] = 'dataTable';
+        $this->visualization = new Visualization\HtmlTable();
     }
 
     public function getJavaScriptProperties()
     {
-        $result = parent::getJavaScriptProperties();
-        $result[] = 'search_recursive';
-        return $result;
+        return array_merge(parent::getJavaScriptProperties(), $this->visualization->getJavaScriptProperties());
     }
 
     protected function getViewDataTableId()
     {
-        return 'table';
-    }
-
-    /**
-     * @see ViewDataTable::main()
-     * @throws Exception|\Piwik\NoAccessException
-     * @return null
-     */
-    public function main()
-    {
-        if ($this->mainAlreadyExecuted) {
-            return;
-        }
-        $this->mainAlreadyExecuted = true;
-
-        try {
-            $this->loadDataTableFromAPI();
-        } catch (\Piwik\NoAccessException $e) {
-            throw $e;
-        } catch (Exception $e) {
-            Piwik::log("Failed to get data from API: " . $e->getMessage());
-
-            $this->loadingError = array('message' => $e->getMessage());
-        }
-
-        $this->postDataTableLoadedFromAPI();
-
-        $template = $this->idSubtable ? $this->viewProperties['subtable_template'] : $this->viewProperties['datatable_template'];
-        $this->view = $this->buildView(new Visualization\HtmlTable(), $template);
+        return $this->visualization->getViewDataTableId();
     }
 
     public function getDefaultDataTableCssClass()
     {
-        return 'dataTableNormal';
-    }
-
-    public function setDataTableCssClass($type)
-    {
-        $this->viewProperties['datatable_css_class'] = $type;
-    }
-
-    public function setJsType($type)
-    {
-        $this->viewProperties['datatable_js_type'] = $type;
-    }
-
-    public function setSubtableTemplate($subtableTemplate)
-    {
-        $this->viewProperties['subtable_template'] = $subtableTemplate;
-    }
-
-    public function showExpanded()
-    {
-        $this->viewProperties['show_expanded'] = true;
-    }
-
-    protected function handleLowPopulation($columnToApplyFilter = null)
-    {
-        if (Common::getRequestVar('enable_filter_excludelowpop', '0', 'string') == '0') {
-            return;
-        }
-        if (is_null($columnToApplyFilter)) {
-            $columnToApplyFilter = 'nb_visits';
-        }
-        $this->setExcludeLowPopulation($columnToApplyFilter);
-    }
-
-    /**
-     * Adds a column to the list of columns to be displayed
-     *
-     * @param string $columnName
-     */
-    public function addColumnToDisplay($columnName)
-    {
-        $this->viewProperties['columns_to_display'][] = $columnName;
-    }
-
-    /**
-     * Sets the search on a table to be recursive (also searches in subtables)
-     * Works only on Actions/Downloads/Outlinks tables.
-     */
-    public function setSearchRecursive()
-    {
-        $this->viewProperties['search_recursive'] = true;
-    }
-
-    protected function getRequestArray()
-    {
-        $requestArray = parent::getRequestArray();
-        if (parent::shouldLoadExpanded()) {
-            $requestArray['expanded'] = 1;
-        }
-        return $requestArray;
-    }
-
-    /**
-     * Disable the row evolution feature which is enabled by default
-     */
-    public function disableRowEvolution()
-    {
-        $this->viewProperties['disable_row_evolution'] = true;
-    }
-
-    /**
-     * Disables row actions.
-     */
-    public function disableRowActions()
-    {
-        $this->viewProperties['disable_row_actions'] = true;
+        $parts = explode('\\', get_class($this));
+        return 'dataTableViz' . end($parts);
     }
-}
+}
\ No newline at end of file
diff --git a/core/ViewDataTable/HtmlTable/AllColumns.php b/core/ViewDataTable/HtmlTable/AllColumns.php
index a23cca3cdeb8dad033650d97825de898a98da513..9b29f72b755762baa9e907ee4d96affea7838d97 100644
--- a/core/ViewDataTable/HtmlTable/AllColumns.php
+++ b/core/ViewDataTable/HtmlTable/AllColumns.php
@@ -53,15 +53,10 @@ class AllColumns extends HtmlTable
         if (empty($this->viewProperties['show_goals'])) {
             $columnConversionRate = 'conversion_rate';
         }
-        $this->setColumnsToDisplay(array('label',
-                                         'nb_visits',
-                                         $columnUniqueVisitors,
-                                         'nb_actions',
-                                         'nb_actions_per_visit',
-                                         'avg_time_on_site',
-                                         'bounce_rate',
-                                         $columnConversionRate
-                                   ));
+        $this->viewProperties['columns_to_display'] = array_filter(array(
+            'label', 'nb_visits', $columnUniqueVisitors, 'nb_actions', 'nb_actions_per_visit', 'avg_time_on_site',
+            'bounce_rate', $columnConversionRate
+        ));
         $this->dataTable->filter('ColumnCallbackReplace', array('avg_time_on_site', create_function('$averageTimeOnSite',
             'return \Piwik\Piwik::getPrettyTimeFromSeconds($averageTimeOnSite);')));
 
diff --git a/core/ViewDataTable/HtmlTable/Goals.php b/core/ViewDataTable/HtmlTable/Goals.php
index a85d0d7ccf739cfd7ffa2c510e16652f6e83a250..414e78d6bac63bd040b7b3926d199869d6ec7bed 100644
--- a/core/ViewDataTable/HtmlTable/Goals.php
+++ b/core/ViewDataTable/HtmlTable/Goals.php
@@ -44,147 +44,62 @@ class Goals extends HtmlTable
         $this->viewProperties['show_goals'] = true;
 
         if (Common::getRequestVar('documentationForGoalsPage', 0, 'int') == 1) {
-            $this->setReportDocumentation(Piwik_Translate('Goals_ConversionByTypeReportDocumentation',
-                array('<br />', '<br />', '<a href="http://piwik.org/docs/tracking-goals-web-analytics/" target="_blank">', '</a>')));
+            $this->viewProperties['documentation'] = Piwik_Translate('Goals_ConversionByTypeReportDocumentation',
+                array('<br />', '<br />', '<a href="http://piwik.org/docs/tracking-goals-web-analytics/" target="_blank">', '</a>'));
         }
 
-        $this->setMetricDocumentation('nb_visits', Piwik_Translate('Goals_ColumnVisits'));
+        $this->viewProperties['metrics_documentation']['nb_visits'] = Piwik_Translate('Goals_ColumnVisits');
         if ($this->isEcommerce) {
-            $this->setMetricDocumentation('revenue_per_visit', Piwik_Translate('Goals_ColumnRevenuePerVisitDocumentation', Piwik_Translate('General_EcommerceOrders')));
-            $this->setColumnsTranslations(array(
-                                               'goal_%s_conversion_rate'   => Piwik_Translate('Goals_ConversionRate'),
-                                               'goal_%s_nb_conversions'    => Piwik_Translate('General_EcommerceOrders'),
-                                               'goal_%s_revenue'           => Piwik_Translate('General_TotalRevenue'),
-                                               'goal_%s_revenue_per_visit' => Piwik_Translate('General_ColumnValuePerVisit'),
-                                               'goal_%s_avg_order_revenue' => Piwik_Translate('General_AverageOrderValue'),
-                                               'goal_%s_items'             => Piwik_Translate('General_PurchasedProducts'),
-                                          ));
-            $this->setColumnsToDisplay(array(
-                                            'label',
-                                            'nb_visits',
-                                            'goal_%s_nb_conversions',
-                                            'goal_%s_revenue',
-                                            'goal_%s_conversion_rate',
-                                            'goal_%s_avg_order_revenue',
-                                            'goal_%s_items',
-                                            'goal_%s_revenue_per_visit',
-                                       ));
+            $this->viewProperties['metrics_documentation']['revenue_per_visit'] =
+                Piwik_Translate('Goals_ColumnRevenuePerVisitDocumentation', Piwik_Translate('General_EcommerceOrders'));
+            $this->viewProperties['translations'] += array(
+                'goal_%s_conversion_rate'   => Piwik_Translate('Goals_ConversionRate'),
+                'goal_%s_nb_conversions'    => Piwik_Translate('General_EcommerceOrders'),
+                'goal_%s_revenue'           => Piwik_Translate('General_TotalRevenue'),
+                'goal_%s_revenue_per_visit' => Piwik_Translate('General_ColumnValuePerVisit'),
+                'goal_%s_avg_order_revenue' => Piwik_Translate('General_AverageOrderValue'),
+                'goal_%s_items'             => Piwik_Translate('General_PurchasedProducts')
+            );
+
+            $this->viewProperties['columns_to_display'] = array(
+                'label', 'nb_visits', 'goal_%s_nb_conversions', 'goal_%s_revenue', 'goal_%s_conversion_rate',
+                'goal_%s_avg_order_revenue', 'goal_%s_items', 'goal_%s_revenue_per_visit');
 
             // Default sort column
-            $this->setSortedColumn('goal_ecommerceOrder_revenue', 'desc');
+            $this->viewProperties['filter_sort_column'] = 'goal_ecommerceOrder_revenue';
+            $this->viewProperties['filter_sort_order'] = 'desc';
         } else {
-            $this->setMetricDocumentation('revenue_per_visit', Piwik_Translate('Goals_ColumnRevenuePerVisitDocumentation', Piwik_Translate('Goals_EcommerceAndGoalsMenu')));
-            $this->setColumnsTranslations(array(
-                                               'goal_%s_conversion_rate'   => Piwik_Translate('Goals_ConversionRate'),
-                                               'goal_%s_nb_conversions'    => Piwik_Translate('Goals_Conversions'),
-                                               'goal_%s_revenue'           => '%s ' . Piwik_Translate('Goals_ColumnRevenue'),
-                                               'goal_%s_revenue_per_visit' => '%s ' . Piwik_Translate('General_ColumnValuePerVisit'),
-
-                                               'nb_conversions'            => Piwik_Translate('Goals_ColumnConversions'),
-                                               'conversion_rate'           => Piwik_Translate('General_ColumnConversionRate'),
-                                               'revenue'                   => Piwik_Translate('Goals_ColumnRevenue'),
-                                               'revenue_per_visit'         => Piwik_Translate('General_ColumnValuePerVisit'),
-                                          ));
-            $this->setColumnsToDisplay(array(
-                                            'label',
-                                            'nb_visits',
-                                            'goal_%s_nb_conversions',
-                                            'goal_%s_conversion_rate',
-                                            'goal_%s_revenue',
-                                            'goal_%s_revenue_per_visit',
-                                            'revenue_per_visit',
-                                       ));
+            $this->viewProperties['metrics_documentation'] =
+                Piwik_Translate('Goals_ColumnRevenuePerVisitDocumentation', Piwik_Translate('Goals_EcommerceAndGoalsMenu'));
+            $this->viewProperties['translations'] += array(
+               'goal_%s_conversion_rate'   => Piwik_Translate('Goals_ConversionRate'),
+               'goal_%s_nb_conversions'    => Piwik_Translate('Goals_Conversions'),
+               'goal_%s_revenue'           => '%s ' . Piwik_Translate('Goals_ColumnRevenue'),
+               'goal_%s_revenue_per_visit' => '%s ' . Piwik_Translate('General_ColumnValuePerVisit'),
+               'nb_conversions'            => Piwik_Translate('Goals_ColumnConversions'),
+               'conversion_rate'           => Piwik_Translate('General_ColumnConversionRate'),
+               'revenue'                   => Piwik_Translate('Goals_ColumnRevenue'),
+               'revenue_per_visit'         => Piwik_Translate('General_ColumnValuePerVisit'),
+            );
+
+            $this->viewProperties['columns_to_display'] = array(
+                'label', 'nb_visits', 'goal_%s_nb_conversions', 'goal_%s_conversion_rate', 'goal_%s_revenue',
+                'goal_%s_revenue_per_visit', 'revenue_per_visit');
 
             // Default sort column
-            $columnsToDisplay = $this->getColumnsToDisplay();
+            $columnsToDisplay = $this->viewProperties['columns_to_display'];
             $columnNbConversionsCurrentGoal = $columnsToDisplay[2];
             if ($this->processOnlyIdGoal > 0
                 && strpos($columnNbConversionsCurrentGoal, '_nb_conversions') !== false
             ) {
-                $this->setSortedColumn($columnNbConversionsCurrentGoal, 'desc');
+                $this->viewProperties['filter_sort_column'] = $columnNbConversionsCurrentGoal;
+                $this->viewProperties['filter_sort_order'] = 'desc';
             }
         }
 
         parent::main();
     }
 
-    public function disableSubTableWhenShowGoals()
-    {
-        $this->viewProperties['subtable_controller_action'] = null;
-    }
-
-    public function setColumnsToDisplay($columnsNames)
-    {
-        $newColumnsNames = array();
-        $goals = array();
-        $idSite = $this->getIdSite();
-        if ($idSite) {
-            $goals = Piwik_Goals_API::getInstance()->getGoals($idSite);
-
-            $ecommerceGoal = array(
-                'idgoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER,
-                'name'   => Piwik_Translate('Goals_EcommerceOrder')
-            );
-
-            $site = new Site($idSite);
-            //Case Ecommerce report table
-            if ($this->isEcommerce) {
-                $goals = array($ecommerceGoal);
-            } // Case tableGoals
-            elseif ($site->isEcommerceEnabled()) {
-                $goals = array_merge(
-                    array($ecommerceGoal),
-                    $goals
-                );
-            }
-        }
-        foreach ($columnsNames as $columnName) {
-            if (in_array($columnName, array(
-                                           'goal_%s_conversion_rate',
-                                           'goal_%s_nb_conversions',
-                                           'goal_%s_revenue_per_visit',
-                                           'goal_%s_revenue',
-                                           'goal_%s_avg_order_revenue',
-                                           'goal_%s_items',
-
-                                      ))
-            ) {
-                foreach ($goals as $goal) {
-                    $idgoal = $goal['idgoal'];
-
-                    $goal['name'] = Common::unsanitizeInputValue($goal['name']);
-
-                    if ($this->processOnlyIdGoal > AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE
-                        && $this->processOnlyIdGoal != $idgoal
-                        && !$this->isEcommerce
-                    ) {
-                        continue;
-                    }
-                    $name = Piwik_Translate($this->getColumnTranslation($columnName), $goal['name']);
-                    $columnNameGoal = str_replace('%s', $idgoal, $columnName);
-                    $this->setColumnTranslation($columnNameGoal, $name);
-                    $this->setDynamicMetricDocumentation($columnName, $columnNameGoal, $goal['name'], $goal['idgoal']);
-                    if (strpos($columnNameGoal, '_rate') === false
-                        // For the goal table (when the flag icon is clicked), we only display the per Goal Conversion rate
-                        && $this->processOnlyIdGoal == AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW
-                    ) {
-                        continue;
-                    }
-
-                    if (strstr($columnNameGoal, '_revenue') !== false) {
-                        $this->columnsToRevenueFilter[] = $columnNameGoal;
-                    } else {
-                        $this->columnsToConversionFilter[] = $columnNameGoal;
-                    }
-                    $newColumnsNames[] = $columnNameGoal;
-                }
-            } else {
-                $newColumnsNames[] = $columnName;
-            }
-        }
-        parent::setColumnsToDisplay($newColumnsNames);
-    }
-
     /**
      * Find the appropriate metric documentation for a goal column
      * @param string $genericMetricName
@@ -224,7 +139,7 @@ class Goals extends HtmlTable
 
         if ($langString) {
             $doc = Piwik_Translate($langString, $goalName);
-            $this->setMetricDocumentation($metricName, $doc);
+            $this->viewProperties['metrics_documentation'][$metricName] = $doc;
         }
     }
 
@@ -254,7 +169,7 @@ class Goals extends HtmlTable
         $valid = parent::postDataTableLoadedFromAPI();
         if ($valid === false) return false;
 
-        foreach ($this->getColumnsToDisplay() as $columnName) {
+        foreach ($this->viewProperties['columns_to_display'] as $columnName) {
             if (strpos($columnName, 'conversion_rate')) {
                 $this->dataTable->filter('ColumnCallbackReplace', array($columnName, create_function('$rate', 'if($rate==0) return "0%"; else return $rate;')));
             }
@@ -272,6 +187,85 @@ class Goals extends HtmlTable
         return true;
     }
 
+    protected function overrideViewProperties()
+    {
+        parent::overrideViewProperties();
+
+        $columnsNames = $this->viewProperties['columns_to_display'];
+
+        $newColumnsNames = array();
+        $goals = array();
+        $idSite = $this->getIdSite();
+        if ($idSite) {
+            $goals = Piwik_Goals_API::getInstance()->getGoals($idSite);
+
+            $ecommerceGoal = array(
+                'idgoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER,
+                'name'   => Piwik_Translate('Goals_EcommerceOrder')
+            );
+
+            $site = new Site($idSite);
+            //Case Ecommerce report table
+            if ($this->isEcommerce) {
+                $goals = array($ecommerceGoal);
+            } // Case tableGoals
+            elseif ($site->isEcommerceEnabled()) {
+                $goals = array_merge(
+                    array($ecommerceGoal),
+                    $goals
+                );
+            }
+        }
+        foreach ($columnsNames as $columnName) {
+            if (in_array($columnName, array(
+                                           'goal_%s_conversion_rate',
+                                           'goal_%s_nb_conversions',
+                                           'goal_%s_revenue_per_visit',
+                                           'goal_%s_revenue',
+                                           'goal_%s_avg_order_revenue',
+                                           'goal_%s_items',
+
+                                      ))
+            ) {
+                foreach ($goals as $goal) {
+                    $idgoal = $goal['idgoal'];
+
+                    $goal['name'] = Common::unsanitizeInputValue($goal['name']);
+
+                    if ($this->processOnlyIdGoal > AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE
+                        && $this->processOnlyIdGoal != $idgoal
+                        && !$this->isEcommerce
+                    ) {
+                        continue;
+                    }
+                    $column = isset($this->viewProperties['translations'][$columnName]) ?
+                        $this->viewProperties['translations'][$columnName] : $columnName;
+                    $name = Piwik_Translate($column, $goal['name']);
+                    $columnNameGoal = str_replace('%s', $idgoal, $columnName);
+                    $this->viewProperties['translations'][$columnNameGoal] = $name;
+                    $this->setDynamicMetricDocumentation($columnName, $columnNameGoal, $goal['name'], $goal['idgoal']);
+                    if (strpos($columnNameGoal, '_rate') === false
+                        // For the goal table (when the flag icon is clicked), we only display the per Goal Conversion rate
+                        && $this->processOnlyIdGoal == AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW
+                    ) {
+                        continue;
+                    }
+
+                    if (strstr($columnNameGoal, '_revenue') !== false) {
+                        $this->columnsToRevenueFilter[] = $columnNameGoal;
+                    } else {
+                        $this->columnsToConversionFilter[] = $columnNameGoal;
+                    }
+                    $newColumnsNames[] = $columnNameGoal;
+                }
+            } else {
+                $newColumnsNames[] = $columnName;
+            }
+        }
+
+        $this->viewProperties['columns_to_display'] = $newColumnsNames;
+    }
+
     public function getDefaultDataTableCssClass()
     {
         return 'dataTableGoals';
diff --git a/core/ViewDataTable/Properties.php b/core/ViewDataTable/Properties.php
index dbca5408d1b7955f7c8833b8eddd31218c5c4ea6..9d0a08d55878174ae8ad6f694ab1fe50f2d83a69 100644
--- a/core/ViewDataTable/Properties.php
+++ b/core/ViewDataTable/Properties.php
@@ -20,6 +20,7 @@ use ReflectionClass;
  * @see ViewDataTable - for more info.
  *
  * TODO: change the names of properties to match the const names where appropriate.
+ * TODO: list default value for each property
  */
 class Properties
 {
@@ -71,21 +72,15 @@ class Properties
     const SHOW_EXCLUDE_LOW_POPULATION = 'show_exclude_low_population';
 
     /**
-     * Controls whether the 'All Columns' footer icon is shown.
+     * Controls whether the footer icon that allows user to switch to the 'normal' DataTable view
+     * is shown.
      */
-    const SHOW_ALL_TABLES_VIEW = 'show_table_all_columns';
-
-    /**
-     * Controls whether the Row Evolution datatable row action icon is shown.
-     */
-    const DISABLE_ROW_EVOLUTION = 'disable_row_evolution';
+    const SHOW_NORMAL_TABLE_VIEW = 'show_table';
 
     /**
-     * The unit to display in jqPlot graphs.
-     *
-     * TODO: Either this should be a visualization property, or should be named something different.
+     * Controls whether the 'All Columns' footer icon is shown.
      */
-    const Y_AXIS_UNIT = 'y_axis_unit';
+    const SHOW_ALL_TABLE_VIEW = 'show_table_all_columns';
 
     /**
      * Controls whether the entire view footer is shown.
@@ -132,6 +127,23 @@ class Properties
      */
     const EXTERNAL_SERIES_TOGGLE_SHOW_ALL = 'external_series_toggle_show_all';
 
+    /**
+     * Related reports are listed below a datatable view. When clicked, the original report will
+     * change to the clicked report and the list will change so the original report can be
+     * navigated back to.
+     * 
+     * @see also self::TITLE. Both must be set if associating related reports.
+     */
+    const RELATED_REPORTS = 'relatedReports';
+
+    /**
+     * The report title. Used with related reports so report headings can be changed when switching
+     * reports.
+     * 
+     * @see also self::RELATED_REPORTS. This must be set if related reports are added.
+     */
+    const TITLE = 'title';
+
     /**
      * Controls whether a report's related reports are listed with the view or not.
      */
@@ -149,6 +161,273 @@ class Properties
      */
     const REPORT_DOCUMENTATION = 'documentation';
 
+    /**
+     * An array property that contains query parameter name/value overrides for API requests made
+     * by ViewDataTable.
+     * 
+     * E.g. array('idSite' => ..., 'period' => 'month')
+     */
+    const REQUEST_PARAMETERS_TO_MODIFY = 'request_parameters_to_modify';
+
+    /**
+     * A regex pattern to use to filter the DataTable before it is shown.
+     * 
+     * @see also self::FILTER_PATTERN_COLUMN
+     */
+    const FILTER_PATTERN = 'filter_pattern';
+
+    /**
+     * The column to apply a filter pattern to.
+     * 
+     * @see also self::FILTER_PATTERN
+     */
+    const FILTER_PATTERN_COLUMN = 'filter_column';
+
+    /**
+     * Array property containing custom data to be saved in JSON in the data-params HTML attribute
+     * of a data table div. This data can be used by JavaScript DataTable classes.
+     * 
+     * e.g. array('typeReferer' => ...)
+     */
+    const CUSTOM_PARAMETERS = 'custom_parameters';
+
+    /**
+     * Contains the column (if any) of the values used in the Row Picker.
+     * 
+     * @see self::ROW_PICKER_VISIBLE_VALUES
+     */
+    const ROW_PICKER_VALUE_COLUMN = 'row_picker_mach_rows_by';
+
+    /**
+     * Contains the list of values available for the Row Picker.
+     * 
+     * @see self::ROW_PICKER_VALUE_COLUMN
+     */
+    const ROW_PICKER_VISIBLE_VALUES = 'row_picker_visible_rows';
+
+    /**
+     * Whether to run generic filters on the DataTable before rendering or not.
+     * 
+     * @see Piwik_API_DataTableGenericFilter
+     */
+    const DISABLE_GENERIC_FILTERS = 'disable_generic_filters';
+
+    /**
+     * Whether to run ViewDataTable's list of queued filters or not.
+     * 
+     * NOTE: Priority queued filters are always run.
+     */
+    const DISABLE_QUEUED_FILTERS = 'disable_queued_filters';
+
+    /**
+     * Controls whether the limit dropdown (which allows users to change the number of data shown)
+     * is always shown or not.
+     * 
+     * Normally shown only if pagination is enabled.
+     */
+    const ALWAYS_SHOW_LIMIT_DROPDOWN = 'show_limit_control';
+
+    /**
+     * Controls whether offset information (ie, '5-10 of 20') is shown under the datatable. 
+     * 
+     * @see TODO
+     */
+    const SHOW_OFFSET_INFORMATION = 'show_offset_information';
+
+    /**
+     * Controls whether the search box under the datatable is shown.
+     */
+    const SHOW_SEARCH_BOX = 'show_search';
+
+    /**
+     * Controls whether the user can sort DataTables by clicking on table column headings.
+     */
+    const ENABLE_SORT = 'enable_sort';
+
+    /**
+     * Controls whether annotations are shown or not.
+     * TODO: This is only appropriate for evolution graphs. Move it.
+     */
+    const HIDE_ANNOTATIONS_VIEW = 'hide_annotations_view';
+
+    /**
+     * Controls whether the footer icon that allows users to view data as a bar chart is shown.
+     */
+    const SHOW_BAR_CHART_ICON = 'show_bar_chart';
+
+    /**
+     * Controls whether the footer icon that allows users to view data as a pie chart is shown.
+     */
+    const SHOW_PIE_CHART_ICON = 'show_pie_chart';
+
+    /**
+     * Controls whether the footer icon that allows users to view data as a tag cloud is shown.
+     */
+    const SHOW_TAG_CLOUD = 'show_tag_cloud';
+
+    /**
+     * Controls whether the user is allowed to export data as an RSS feed or not.
+     */
+    const SHOW_EXPORT_AS_RSS_FEED = 'show_export_as_rss_feed';
+
+    /**
+     * Controls whether the 'Ecoommerce Orders'/'Abandoned Cart' footer icons are shown or not.
+     */
+    const SHOW_ECOMMERCE_FOOTER_ICONS = 'show_ecommerce';
+
+    /**
+     * Controls whether the summary row is displayed on every page of the datatable view or not.
+     * If false, the summary row will be treated as the last row of the dataset and will only visible
+     * when viewing the last rows.
+     */
+    const KEEP_SUMMARY_ROW = 'keep_summary_row';
+
+    /**
+     * Stores the column name to filter when filtering out rows with low values.
+     * 
+     * @see also self::EXCLUDE_LOW_POPULATION_VALUE
+     */
+    const EXCLUDE_LOW_POPULATION_COLUMN = 'filter_excludelowpop';
+
+    /**
+     * Stores the value considered 'low' when filtering out rows w/ low values.
+     * 
+     * @see also self::EXCLUDE_LOW_POPULATION_COLUMN
+     */
+    const EXCLUDE_LOW_POPULATION_VALUE = 'filter_excludelowpop_value';
+
+    /**
+     * Stores an HTML message (if any) to display under the datatable view.
+     */
+    const FOOTER_MESSAGE = 'show_footer_message';
+
+    /**
+     * Array property that stores documentation for individual metrics.
+     * 
+     * E.g. array('nb_visits' => '...', ...)
+     * 
+     * Default: Set to values retrieved from report metadata (via API.getReportMetadata API method).
+     */
+    const METRIC_DOCUMENTATION = 'metrics_documentation';
+
+    /**
+     * If true, the summary row will be colored differently than all other DataTable rows.
+     * 
+     * @see also self::KEEP_SUMMARY_ROW
+     */
+    const HIGHLIGHT_SUMMARY_ROW = 'highlight_summary_row';
+
+    /**
+     * Row metadata name that contains the tooltip for the specific row.
+     */
+    const TOOLTIP_METADATA_NAME = 'tooltip_metadata_name';
+
+    /**
+     * The URL to the report the view is displaying. Modifying this means clicking back to this report
+     * from a Related Report will go to a different URL. Can be used to load an entire page instead
+     * of a single report when going back to the original report.
+     * 
+     * @see also self::RELATED_REPORTS
+     */
+    const THIS_REPORT_URL = 'self_url';
+
+    /**
+     * Special property that holds the properties for DataTable Visualizations.
+     * 
+     * @see Piwik\ViewDataTable\VisualizationProperties
+     */
+    const VISUALIZATION_PROPERTIES = 'visualization_properties';
+
+    /**
+     * Custom template used if displaying a subtable.
+     * 
+     * TODO: This is specific to HtmlTable and should be replaced w/ allowing custom visualization for
+     *       subtables. Should not directly touch template.
+     */
+    const SUBTABLE_TEMPLATE = 'subtable_template';
+
+    /**
+     * CSS class to use in the output HTML div.
+     * 
+     * TODO: This only changes based on the visualization type. Would be good if it didn't need to be
+     * set at all...
+     */
+    const DATATABLE_CSS_CLASS = 'datatable_css_class';
+
+    /**
+     * The JavaScript class to instantiate after the result HTML is obtained. This class handles all
+     * interactive behavior for the DataTable view.
+     */
+    const DATATABLE_JS_TYPE = 'datatable_js_type';
+
+    /**
+     * Controls whether the entire DataTable should be rendered (including subtables) or just one
+     * specific table in the tree.
+     * 
+     * TODO: specific to htmltable. make a visualization property.
+     */
+    const SHOW_EXPANDED = 'show_expanded';
+
+    /**
+     * If true, searching through the DataTable will search through all subtables.
+     * 
+     * @see also self::FILTER_PATTERN
+     */
+    const DO_RECURSIVE_SEARCH = 'search_recursive';
+
+    /**
+     * Controls whether the row evolution DataTable Row Action icon is shown or not.
+     * 
+     * TODO: specific to HtmlTable. move.
+     * 
+     * @see also self::DISABLE_ROW_ACTIONS
+     */
+    const DISABLE_ROW_EVOLUTION = 'disable_row_evolution';
+
+    /**
+     * Controls whether any DataTable Row Action icons are shown. If true, no icons are shown.
+     * 
+     * TODO: specific to HtmlTable. move.
+     * 
+     * @see also self::DISABLE_ROW_EVOLUTION
+     */
+    const DISABLE_ROW_ACTIONS = 'disable_row_actions';
+
+    /**
+     * The unit of the displayed column. Valid if only one non-label column is displayed.
+     */
+    const DISPLAYED_COLUMN_UNIT = 'y_axis_unit';
+
+    /**
+     * Controls whether the percentage of the total is displayed as a tooltip in Jqplot graphs.
+     * 
+     * NOTE: Sometimes this percentage is meaningless (when the total of the column values is
+     * not the total number of elements in the set). In this case the tooltip should not be
+     * displayed.
+     * 
+     * TODO: only valid for graphs... move it.
+     */
+    const DISPLAY_PERCENTAGE_IN_TOOLTIP = 'display_percentage_in_tooltip';
+
+    /**
+     * Controls whether to show the 'Export as Image' footer icon.
+     */
+    const SHOW_EXPORT_AS_IMAGE_ICON = 'show_export_as_image_icon';
+
+    /**
+     * Controls whether all ticks & labels are shown on a graph's x-axis or just some.
+     * 
+     * TODO: only for jqplot graphs.
+     */
+    const SHOW_ALL_TICKS = 'show_all_ticks';
+
+    /**
+     * If true, a row with totals of each DataTable column is added.
+     * 
+     * TODO: only for jqplot graphs. also doesn't seem necessary w/ AddSummaryRow
+     */
+    const ADD_TOTAL_ROW = 'add_total_row';
+
     /**
      * Returns the set of all valid ViewDataTable properties. The result is an array with property
      * name as a key. Values of the array are undefined.
diff --git a/core/ViewDataTable/Sparkline.php b/core/ViewDataTable/Sparkline.php
index 710d5ae6c1d0c7d53b19a99649d965c15e2b4a2b..1c31ddeea1cf6afb16da76548ca4d3846f0625ee 100644
--- a/core/ViewDataTable/Sparkline.php
+++ b/core/ViewDataTable/Sparkline.php
@@ -98,7 +98,7 @@ class Sparkline extends ViewDataTable
 
     protected function getValuesFromDataTable($dataTable)
     {
-        $columns = $this->getColumnsToDisplay();
+        $columns = $this->viewProperties['columns_to_display'];
         $columnToPlot = false;
         if (!empty($columns)) {
             $columnToPlot = $columns[0];
diff --git a/core/ViewDataTable/VisualizationPropertiesProxy.php b/core/ViewDataTable/VisualizationPropertiesProxy.php
new file mode 100644
index 0000000000000000000000000000000000000000..00380aacafaff00dbbaa7c224e0318cc54d3050e
--- /dev/null
+++ b/core/ViewDataTable/VisualizationPropertiesProxy.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+namespace Piwik\ViewDataTable;
+
+use Piwik\ViewDataTable\Properties;
+
+/**
+ * Proxy object used to get/set visualization properties. Used to check that property
+ * names are valid.
+ */
+class VisualizationPropertiesProxy
+{
+    /**
+     * The visualization instance.
+     * 
+     * @var array
+     */
+    private $visualization;
+
+    /**
+     * Stores visualization properties.
+     * 
+     * @var array
+     */
+    private $visualizationProperties = array();
+
+    /**
+     * Constructor.
+     * 
+     * @param Piwik\Visualization $visualization The visualization to get/set properties of.
+     */
+    public function __construct($visualization)
+    {
+        $this->visualization = $visualization;
+    }
+
+    /**
+     * Gets a reference to a visualization property.
+     * 
+     * @param string $name A valid property name for the current visualization.
+     * @return mixed
+     * @throws Exception if the property name is invalid.
+     */
+    public function &__get($name)
+    {
+        Properties::checkValidVisualizationProperty($this->visualization, $name);
+        return $this->visualizationProperties[$name];
+    }
+
+    /**
+     * Sets a visualization property.
+     * 
+     * @param string $name A valid property name for the current visualization.
+     * @param mixed $value
+     * @return mixed Returns $value.
+     * @throws Exception if the property name is invalid.
+     */
+    public function __set($name, $value)
+    {
+        Properties::checkValidVisualizationProperty($this->visualization, $name);
+        return $this->visualizationProperties[$name] = $value;
+    }
+}
\ No newline at end of file
diff --git a/core/Visualization/HtmlTable.php b/core/Visualization/HtmlTable.php
index a32001199342ad7faaf4a0111901541b3c90d3a3..036f7eb9edf88cc98d041a25761cde16a18dac57 100644
--- a/core/Visualization/HtmlTable.php
+++ b/core/Visualization/HtmlTable.php
@@ -13,12 +13,31 @@ namespace Piwik\Visualization;
 
 use Piwik\DataTable;
 use Piwik\View;
+use Piwik\Config;
+use Piwik\Common;
 
 /**
  * DataTable visualization that shows DataTable data in an HTML table.
  */
 class HtmlTable
 {
+    /**
+     * TODO
+     */
+    public function getJavaScriptProperties()
+    {
+        return array('search_recursive');
+    }
+
+    /**
+     * TODO
+     * @deprecated
+     */
+    public function getViewDataTableId()
+    {
+        return 'table';
+    }
+
     /**
      * Renders this visualization.
      *
@@ -33,4 +52,30 @@ class HtmlTable
         $view->dataTable = $dataTable;
         return $view->render();
     }
+
+    /**
+     * TODO
+     */
+    public function getDefaultPropertyValues()
+    {
+        $defaults = array(
+            'enable_sort' => true,
+            'disable_row_evolution' => false,
+            'disable_row_actions' => false,
+            'subtable_template' => "@CoreHome/_dataTable.twig",
+            'datatable_js_type' => 'dataTable'
+        );
+
+        $defaultLimit = Config::getInstance()->General['datatable_default_limit'];
+        if ($defaultLimit !== 0) {
+            $defaults['filter_limit'] = $defaultLimit;
+        }
+
+        if (Common::getRequestVar('enable_filter_excludelowpop', false) == '1') {
+            $defaults['filter_excludelowpop'] = 'nb_visits';
+            $defaults['filter_excludelowpop_value'] = null;
+        }
+
+        return $defaults;
+    }
 }
\ No newline at end of file
diff --git a/plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php b/plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php
index d23a2fff8366fea5b11b5455a3da063ee9d02511..1bdf33debe2023b3565348ae6830913aaf943d1c 100644
--- a/plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php
+++ b/plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php
@@ -82,7 +82,7 @@ class Piwik_CoreHome_DataTableRowAction_MultiRowEvolution
     public function getRowEvolutionGraph($graphType = false, $metrics = false)
     {
         $view = parent::getRowEvolutionGraph($graphType, $metrics);
-        $view->setCustomParameter(self::IS_MULTI_EVOLUTION_PARAM, 1); // set in JS
+        $view->custom_parameters[self::IS_MULTI_EVOLUTION_PARAM] = 1; // set in JS
         return $view;
     }
 }
diff --git a/plugins/CoreHome/javascripts/jqplot.js b/plugins/CoreHome/javascripts/jqplot.js
index 5153b19a26471aada1b908dd4c841ac2deebb10a..d4287a9bec36255638152836bff027516a7bbad7 100644
--- a/plugins/CoreHome/javascripts/jqplot.js
+++ b/plugins/CoreHome/javascripts/jqplot.js
@@ -71,7 +71,7 @@ JQPlot.prototype = {
         var type = $('#' + targetDivId).closest('div.dataTable').data('dataTableInstance').param['viewDataTable'];
 
         // preapare the appropriate chart type
-        switch (type) {
+        switch (type) {// TODO: should rely on CSS, not viewDataTable. otherwise ecommerceOrder row evolution will fail
             case 'graphEvolution':
                 this.prepareEvolutionChart(targetDivId, lang);
                 break;
diff --git a/plugins/CoreHome/stylesheets/dataTable.less b/plugins/CoreHome/stylesheets/dataTable.less
index 04e82f539c5c3c407dbc031bae221d06f577b899..239d0c84231bd47e7b7dffb27f333f67f1933519 100644
--- a/plugins/CoreHome/stylesheets/dataTable.less
+++ b/plugins/CoreHome/stylesheets/dataTable.less
@@ -7,7 +7,7 @@
 }
 
 /* container of each table */
-.dataTableNormal > .dataTableWrapper {
+.dataTableVizHtmlTable > .dataTableWrapper {
     width: 450px;
     /* not more than 450px to make sure 2 tables can fit horizontally on a 1024 screen */
 }
diff --git a/plugins/ExamplePlugin/ExamplePlugin.php b/plugins/ExamplePlugin/ExamplePlugin.php
index b2d74414713a7cf384e03c7d31f8ad4fdc529572..481c324b5d83a9a50b45b32b5ad0916d78261e1c 100644
--- a/plugins/ExamplePlugin/ExamplePlugin.php
+++ b/plugins/ExamplePlugin/ExamplePlugin.php
@@ -44,7 +44,7 @@ class Piwik_ExamplePlugin extends Plugin
         if ($view->getCurrentControllerName() == 'Referers'
             && $view->getCurrentControllerAction() == 'getWebsites'
         ) {
-            $view->addColumnToDisplay('nb_uniq_visitors');
+            $view->columns_to_display[] = 'nb_uniq_visitors';
         }
     }
 
diff --git a/plugins/ExampleUI/Controller.php b/plugins/ExampleUI/Controller.php
index 086e949953d8ad3792cb4e282205e27289c1dc88..5660190aaaf7ef3c8a9b53044358a8b4810b4b2b 100644
--- a/plugins/ExampleUI/Controller.php
+++ b/plugins/ExampleUI/Controller.php
@@ -130,8 +130,9 @@ class Piwik_ExampleUI_Controller extends Controller
     private function echoDataTableSearchEnginesFiltered()
     {
         $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Referers.getSearchEngines');
-        $view->setColumnsToDisplay('nb_visits');
-        $view->setSearchPattern('^(Google|Yahoo!)$', 'label');
+        $view->columns_to_display = array('nb_visits');
+        $view->filter_pattern = '^(Google|Yahoo!)$';
+        $view->filter_column = 'label';
         return $this->renderView($view);
     }
 }
diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php
index 1ac46c9ca0ff4577204041fcc2fc185e9dbfc8ad..17a5e38fae11d7720fe63309cdd2032aaa7484e2 100644
--- a/plugins/Goals/Controller.php
+++ b/plugins/Goals/Controller.php
@@ -251,7 +251,7 @@ class Piwik_Goals_Controller extends Controller
             $idGoal = Common::getRequestVar('idGoal', false, 'string');
         }
         $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.get');
-        $view->setRequestParametersToModify(array('idGoal' => $idGoal));
+        $view->request_parameters_to_modify['idGoal'] = $idGoal;
 
         $nameToLabel = $this->goalColumnNameToLabel;
         if ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
@@ -283,13 +283,13 @@ class Piwik_Goals_Controller extends Controller
                 $goalName = $this->goals[$idGoal]['name'];
                 $columnTranslation = "$columnTranslation (" . Piwik_Translate('Goals_GoalX', "$goalName") . ")";
             }
-            $view->setColumnTranslation($columnName, $columnTranslation);
+            $view->translations[$columnName] = $columnTranslation;
         }
-        $view->setColumnsToDisplay($columns);
-        $view->setSelectableColumns($selectableColumns);
+        $view->columns_to_display = $columns;
+        $view->selectable_columns = $selectableColumns;
 
         $langString = $idGoal ? 'Goals_SingleGoalOverviewDocumentation' : 'Goals_GoalsOverviewDocumentation';
-        $view->setReportDocumentation(Piwik_Translate($langString, '<br />'));
+        $view->documentation = Piwik_Translate($langString, '<br />');
 
         return $this->renderView($view, $fetch);
     }
diff --git a/plugins/MultiSites/Controller.php b/plugins/MultiSites/Controller.php
index fd7ee849c8e059e67558220a65dbad8fa58ee86f..b57f90b02055f3460ae41d7a1b3b938781b2d619 100644
--- a/plugins/MultiSites/Controller.php
+++ b/plugins/MultiSites/Controller.php
@@ -224,7 +224,7 @@ class Piwik_MultiSites_Controller extends Controller
             $api = "Goals.get";
         }
         $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, $api);
-        $view->setColumnsToDisplay($columns);
+        $view->columns_to_display = $columns;
         return $this->renderView($view, $fetch);
     }
 }
diff --git a/plugins/Referers/Controller.php b/plugins/Referers/Controller.php
index 15f4de09611258e237cfc84e774ce39f097efd51..c9362f4a0170abd3554cfe44fe9e6d1fe059597c 100644
--- a/plugins/Referers/Controller.php
+++ b/plugins/Referers/Controller.php
@@ -263,7 +263,7 @@ class Piwik_Referers_Controller extends Controller
     {
         $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Referers.getRefererType');
 
-        $view->addTotalRow();
+        $view->add_total_row = true;
 
         // configure displayed columns
         if (empty($columns)) {
@@ -271,7 +271,7 @@ class Piwik_Referers_Controller extends Controller
             $columns = Piwik::getArrayFromApiParameter($columns);
         }
         $columns = !is_array($columns) ? array($columns) : $columns;
-        $view->setColumnsToDisplay($columns);
+        $view->columns_to_display = $columns;
 
         // configure selectable columns
         if (Common::getRequestVar('period', false) == 'day') {
@@ -279,7 +279,7 @@ class Piwik_Referers_Controller extends Controller
         } else {
             $selectable = array('nb_visits', 'nb_actions');
         }
-        $view->setSelectableColumns($selectable);
+        $view->selectable_columns = $selectable;
 
         // configure displayed rows
         $visibleRows = Common::getRequestVar('rows', false);
@@ -288,7 +288,7 @@ class Piwik_Referers_Controller extends Controller
             $visibleRows = Piwik::getArrayFromApiParameter($visibleRows);
 
             // typeReferer is redundant if rows are defined, so make sure it's not used
-            $view->setCustomParameter('typeReferer', false);
+            $view->custom_parameters['typeReferer'] = false;
         } else {
             // use $typeReferer as default
             if ($typeReferer === false) {
@@ -297,46 +297,48 @@ class Piwik_Referers_Controller extends Controller
             $label = self::getTranslatedReferrerTypeLabel($typeReferer);
             $total = Piwik_Translate('General_Total');
             $visibleRows = array($label, $total);
-            $view->setRequestParametersToModify(array('rows' => $label . ',' . $total));
+            $view->request_parameters_to_modify['rows'] = $label . ',' . $total;
         }
-        $view->addRowPicker($visibleRows);
+        $view->row_picker_mach_rows_by = 'label';
+        $view->row_picker_visible_rows = $visibleRows;
 
-        $view->setReportDocumentation(Piwik_Translate('Referers_EvolutionDocumentation') . '<br />'
+        $view->documentation = Piwik_Translate('Referers_EvolutionDocumentation') . '<br />'
             . Piwik_Translate('General_BrokenDownReportDocumentation') . '<br />'
-            . Piwik_Translate('Referers_EvolutionDocumentationMoreInfo', '&quot;' . Piwik_Translate('Referers_DetailsByRefererType') . '&quot;'));
+            . Piwik_Translate('Referers_EvolutionDocumentationMoreInfo', '&quot;'
+            . Piwik_Translate('Referers_DetailsByRefererType') . '&quot;');
 
         return $this->renderView($view, $fetch);
     }
 
-    function getLastDistinctSearchEnginesGraph($fetch = false)
+    public function getLastDistinctSearchEnginesGraph($fetch = false)
     {
         $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "Referers.getNumberOfDistinctSearchEngines");
-        $view->setColumnTranslation('Referers_distinctSearchEngines', ucfirst(Piwik_Translate('Referers_DistinctSearchEngines')));
-        $view->setColumnsToDisplay(array('Referers_distinctSearchEngines'));
+        $view->translations['Referers_distinctSearchEngines'] = ucfirst(Piwik_Translate('Referers_DistinctSearchEngines'));
+        $view->columns_to_display = array('Referers_distinctSearchEngines');
         return $this->renderView($view, $fetch);
     }
 
-    function getLastDistinctKeywordsGraph($fetch = false)
+    public function getLastDistinctKeywordsGraph($fetch = false)
     {
         $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "Referers.getNumberOfDistinctKeywords");
-        $view->setColumnTranslation('Referers_distinctKeywords', ucfirst(Piwik_Translate('Referers_DistinctKeywords')));
-        $view->setColumnsToDisplay(array('Referers_distinctKeywords'));
+        $view->translations['Referers_distinctKeywords'] = ucfirst(Piwik_Translate('Referers_DistinctKeywords'));
+        $view->columns_to_display = array('Referers_distinctKeywords');
         return $this->renderView($view, $fetch);
     }
 
-    function getLastDistinctWebsitesGraph($fetch = false)
+    public function getLastDistinctWebsitesGraph($fetch = false)
     {
         $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "Referers.getNumberOfDistinctWebsites");
-        $view->setColumnTranslation('Referers_distinctWebsites', ucfirst(Piwik_Translate('Referers_DistinctWebsites')));
-        $view->setColumnsToDisplay(array('Referers_distinctWebsites'));
+        $view->translations['Referers_distinctWebsites'] = ucfirst(Piwik_Translate('Referers_DistinctWebsites'));
+        $view->columns_to_display = array('Referers_distinctWebsites');
         return $this->renderView($view, $fetch);
     }
 
-    function getLastDistinctCampaignsGraph($fetch = false)
+    public function getLastDistinctCampaignsGraph($fetch = false)
     {
         $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "Referers.getNumberOfDistinctCampaigns");
-        $view->setColumnTranslation('Referers_distinctCampaigns', ucfirst(Piwik_Translate('Referers_DistinctCampaigns')));
-        $view->setColumnsToDisplay(array('Referers_distinctCampaigns'));
+        $view->translations['Referers_distinctCampaigns'] = ucfirst(Piwik_Translate('Referers_DistinctCampaigns'));
+        $view->columns_to_display = array('Referers_distinctCampaigns');
         return $this->renderView($view, $fetch);
     }
 
diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php
index 12793c856f6b8518559a6fcc085a64f6a1a36e20..16548850014dea585524a86afe3fee016e4e2756 100644
--- a/plugins/UserCountry/Controller.php
+++ b/plugins/UserCountry/Controller.php
@@ -359,7 +359,7 @@ class Piwik_UserCountry_Controller extends Admin
     public function getLastDistinctCountriesGraph($fetch = false)
     {
         $view = $this->getLastUnitGraph('UserCountry', __FUNCTION__, "UserCountry.getNumberOfDistinctCountries");
-        $view->setColumnsToDisplay('UserCountry_distinctCountries');
+        $view->columns_to_display = array('UserCountry_distinctCountries');
         return $this->renderView($view, $fetch);
     }
 
diff --git a/plugins/UserCountry/UserCountry.php b/plugins/UserCountry/UserCountry.php
index 37566f19d6a2a17c589a74d1429b56457e08f032..26706dbfa2b6c7d21fac8add973dc8d387e66d57 100644
--- a/plugins/UserCountry/UserCountry.php
+++ b/plugins/UserCountry/UserCountry.php
@@ -381,7 +381,7 @@ class Piwik_UserCountry extends Plugin
                         array('<a target="_blank" href="http://piwik.org/faq/how-to/#faq_167">', '</a>'));
                 }
 
-                $view->setFooterMessage($footerMessage);
+                $view->show_footer_message = $footerMessage;
             }
         };
     }
diff --git a/tests/PHPUnit/proxy/libs b/tests/PHPUnit/proxy/libs
new file mode 120000
index 0000000000000000000000000000000000000000..d63817ad19ed795c3b3543396defd9dabcbe63a8
--- /dev/null
+++ b/tests/PHPUnit/proxy/libs
@@ -0,0 +1 @@
+../../../libs
\ No newline at end of file
diff --git a/tests/PHPUnit/proxy/plugins b/tests/PHPUnit/proxy/plugins
new file mode 120000
index 0000000000000000000000000000000000000000..842d50c3aea9eaf6575d7e23e360842154dfcab7
--- /dev/null
+++ b/tests/PHPUnit/proxy/plugins
@@ -0,0 +1 @@
+../../../plugins
\ No newline at end of file
diff --git a/tests/PHPUnit/proxy/tests b/tests/PHPUnit/proxy/tests
new file mode 120000
index 0000000000000000000000000000000000000000..c25bddb6dd4666c6eb8cc92e33f1d60f64c3162b
--- /dev/null
+++ b/tests/PHPUnit/proxy/tests
@@ -0,0 +1 @@
+../..
\ No newline at end of file