Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattab <matthieu.aubry@gmail.com>2013-08-11 13:19:59 +0400
committermattab <matthieu.aubry@gmail.com>2013-08-11 13:19:59 +0400
commitf9b15e948fc9639ada0f925a5d450e6e158b5f56 (patch)
tree3d6a25c8a271deee7d1136a11c11926be1d33529 /plugins
parenta96ec40e983a8b64f4c25def541a519ff3670e6a (diff)
parent64ca5d548c0cf0c4eef9f5f104901fbf14800127 (diff)
Merge remote-tracking branch 'origin/master' into plugin_namespaces
Conflicts: core/Tracker/Request.php core/ViewDataTable.php core/ViewDataTable/HtmlTable/Goals.php plugins/Actions/Actions.php plugins/Annotations/API.php plugins/CoreHome/CoreHome.php plugins/DBStats/DBStats.php plugins/DevicesDetection/DevicesDetection.php plugins/Goals/Goals.php plugins/Live/Live.php plugins/Referers/Referers.php plugins/UserSettings/UserSettings.php plugins/UsersManager/API.php plugins/VisitTime/VisitTime.php plugins/VisitorInterest/VisitorInterest.php
Diffstat (limited to 'plugins')
-rw-r--r--plugins/API/ProcessedReport.php2
-rw-r--r--plugins/API/RowEvolution.php30
-rw-r--r--plugins/Actions/API.php20
-rw-r--r--plugins/Actions/Actions.php42
-rw-r--r--plugins/Actions/stylesheets/dataTableActions.less4
-rwxr-xr-xplugins/Annotations/API.php5
-rwxr-xr-xplugins/Annotations/javascripts/annotations.js4
-rw-r--r--plugins/CoreAdminHome/Controller.php3
-rw-r--r--plugins/CoreAdminHome/stylesheets/generalSettings.less5
-rw-r--r--plugins/CoreAdminHome/stylesheets/menu.less7
-rw-r--r--plugins/CoreHome/Controller.php4
-rw-r--r--plugins/CoreHome/CoreHome.php18
-rw-r--r--plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php15
-rw-r--r--plugins/CoreHome/DataTableRowAction/RowEvolution.php22
-rw-r--r--plugins/CoreHome/javascripts/autocomplete.js25
-rw-r--r--plugins/CoreHome/javascripts/calendar.js8
-rw-r--r--plugins/CoreHome/javascripts/dataTable.js (renamed from plugins/CoreHome/javascripts/datatable.js)56
-rw-r--r--plugins/CoreHome/javascripts/dataTable_manager.js (renamed from plugins/CoreHome/javascripts/datatable_manager.js)12
-rw-r--r--plugins/CoreHome/javascripts/dataTable_rowactions.js (renamed from plugins/CoreHome/javascripts/datatable_rowactions.js)0
-rw-r--r--plugins/CoreHome/javascripts/menu.js7
-rw-r--r--plugins/CoreHome/javascripts/popover.js37
-rw-r--r--plugins/CoreHome/javascripts/sparkline.js10
-rw-r--r--plugins/CoreHome/stylesheets/coreHome.less2
-rw-r--r--plugins/CoreHome/stylesheets/dataTable.less791
-rw-r--r--plugins/CoreHome/stylesheets/dataTable/_dataTable.less424
-rw-r--r--plugins/CoreHome/stylesheets/dataTable/_limitSelection.less68
-rw-r--r--plugins/CoreHome/stylesheets/dataTable/_reportDocumentation.less62
-rw-r--r--plugins/CoreHome/stylesheets/dataTable/_rowActions.less35
-rw-r--r--plugins/CoreHome/stylesheets/dataTable/_subDataTable.less46
-rw-r--r--plugins/CoreHome/stylesheets/dataTable/_tableConfiguration.less82
-rw-r--r--plugins/CoreHome/stylesheets/jqplotColors.less (renamed from plugins/Zeitgeist/stylesheets/ui/_jqplot.less)48
-rw-r--r--plugins/CoreHome/stylesheets/menu.less4
-rw-r--r--plugins/CoreHome/stylesheets/sparklineColors.less (renamed from plugins/Zeitgeist/stylesheets/ui/_sparkline.less)10
-rw-r--r--plugins/CoreHome/templates/_dataTable.twig3
-rw-r--r--plugins/CoreHome/templates/_dataTableActions_subDataTable.twig8
-rw-r--r--plugins/CoreHome/templates/_dataTableFooter.twig65
-rw-r--r--plugins/CoreHome/templates/_dataTableViz_jqplotGraph.twig10
-rw-r--r--plugins/CoreHome/templates/_siteSelect.twig5
-rw-r--r--plugins/CoreHome/templates/_siteSelectHeader.twig4
-rw-r--r--plugins/CoreHome/templates/_topBarHelloMenu.twig7
-rw-r--r--plugins/CoreHome/templates/_topBarTopMenu.twig2
-rw-r--r--plugins/CoreHome/templates/getDefaultIndexView.twig5
-rw-r--r--plugins/CoreHome/templates/getMultiRowEvolutionPopover.twig2
-rw-r--r--plugins/CoreHome/templates/getRowEvolutionPopover.twig2
-rw-r--r--plugins/CoreUpdater/Controller.php2
-rw-r--r--plugins/CoreUpdater/templates/layout.twig5
-rw-r--r--plugins/CoreVisualizations/CoreVisualizations.php58
-rw-r--r--plugins/CoreVisualizations/JqplotDataGenerator.php209
-rw-r--r--plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php278
-rw-r--r--plugins/CoreVisualizations/Visualizations/Cloud.php172
-rw-r--r--plugins/CoreVisualizations/Visualizations/HtmlTable.php394
-rw-r--r--plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php34
-rw-r--r--plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php34
-rw-r--r--plugins/CoreVisualizations/Visualizations/JqplotGraph.php212
-rw-r--r--plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php35
-rw-r--r--plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php150
-rw-r--r--plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php36
-rw-r--r--plugins/CoreVisualizations/javascripts/jqplot.js (renamed from plugins/CoreHome/javascripts/jqplot.js)31
-rw-r--r--plugins/CoreVisualizations/stylesheets/dataTableVisualizations.less18
-rw-r--r--plugins/CoreVisualizations/stylesheets/jqplot.css (renamed from plugins/CoreHome/stylesheets/jqplot.css)0
-rw-r--r--plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig (renamed from plugins/CoreHome/templates/_dataTableViz_htmlTable.twig)17
-rw-r--r--plugins/CoreVisualizations/templates/_dataTableViz_jqplotGraph.twig10
-rw-r--r--plugins/CoreVisualizations/templates/_dataTableViz_tagCloud.twig (renamed from plugins/CoreHome/templates/_dataTableViz_tagCloud.twig)0
-rw-r--r--plugins/DBStats/DBStats.php18
-rw-r--r--plugins/Dashboard/javascripts/dashboard.js4
-rw-r--r--plugins/Dashboard/javascripts/dashboardObject.js4
-rw-r--r--plugins/Dashboard/stylesheets/dashboard.less52
-rw-r--r--plugins/Dashboard/templates/index.twig5
-rw-r--r--plugins/DevicesDetection/DevicesDetection.php24
-rw-r--r--plugins/DevicesDetection/lang/en.php8
-rw-r--r--plugins/ExampleRssWidget/Controller.php3
-rw-r--r--plugins/ExampleUI/Controller.php16
-rw-r--r--plugins/Goals/Controller.php2
-rw-r--r--plugins/Goals/Goals.php24
-rw-r--r--plugins/Goals/templates/_listGoalEdit.twig2
-rw-r--r--plugins/Installation/Controller.php6
-rw-r--r--plugins/Installation/FormDatabaseSetup.php4
-rw-r--r--plugins/Installation/stylesheets/installation.css6
-rw-r--r--plugins/Installation/templates/layout.twig2
-rw-r--r--plugins/Live/API.php152
-rw-r--r--plugins/Live/Controller.php35
-rw-r--r--plugins/Live/Live.php19
-rw-r--r--plugins/Live/images/REMOVE_ME_avatar.jpgbin0 -> 13984 bytes
-rw-r--r--plugins/Live/images/REMOVE_ME_chart.pngbin0 -> 15208 bytes
-rw-r--r--plugins/Live/images/REMOVE_ME_map.jpgbin0 -> 64945 bytes
-rw-r--r--plugins/Live/images/avatar_frame.pngbin0 -> 5375 bytes
-rw-r--r--plugins/Live/images/paperclip.pngbin0 -> 10924 bytes
-rw-r--r--plugins/Live/images/visitor_profile_background.jpgbin0 -> 11060 bytes
-rw-r--r--plugins/Live/images/visitor_profile_close.png (renamed from plugins/SegmentEditor/images/up_arrow.png)bin2881 -> 4734 bytes
-rw-r--r--plugins/Live/images/visitor_profile_gradient.png (renamed from plugins/SegmentEditor/images/slide.png)bin2831 -> 2840 bytes
-rw-r--r--plugins/Live/stylesheets/live.less2
-rw-r--r--plugins/Live/stylesheets/visitor_profile.less367
-rw-r--r--plugins/Live/templates/_actionsList.twig106
-rw-r--r--plugins/Live/templates/_totalVisitors.twig12
-rw-r--r--plugins/Live/templates/getVisitorLog.twig115
-rw-r--r--plugins/Live/templates/getVisitorProfilePopup.twig127
-rw-r--r--plugins/Login/stylesheets/login.css3
-rw-r--r--plugins/Login/templates/login.twig5
-rwxr-xr-xplugins/MultiSites/API.php4
-rw-r--r--plugins/MultiSites/javascripts/multiSites.js2
-rw-r--r--plugins/MultiSites/stylesheets/multiSites.less10
-rw-r--r--plugins/MultiSites/templates/_siteRow.twig2
-rw-r--r--plugins/PDFReports/templates/index.twig4
-rw-r--r--plugins/PleineLune/plugin.piwik.json3
-rw-r--r--plugins/PleineLune/stylesheets/_dataTable.less182
-rw-r--r--plugins/PleineLune/stylesheets/_general.less7
-rw-r--r--plugins/PleineLune/stylesheets/_jqplotColors.less86
-rw-r--r--plugins/PleineLune/stylesheets/_layout.less61
-rw-r--r--plugins/PleineLune/stylesheets/_menuDashboard.less60
-rw-r--r--plugins/PleineLune/stylesheets/_sparklineColors.less14
-rw-r--r--plugins/PleineLune/stylesheets/_transitionColors.less46
-rw-r--r--plugins/PleineLune/stylesheets/_ui.less23
-rw-r--r--plugins/PleineLune/stylesheets/_widget.less19
-rw-r--r--plugins/PleineLune/stylesheets/controls/_headerMessage.less20
-rw-r--r--plugins/PleineLune/stylesheets/controls/_periodSelect.less34
-rw-r--r--plugins/PleineLune/stylesheets/controls/_segmentSelect.less139
-rw-r--r--plugins/PleineLune/stylesheets/controls/_siteSelect.less69
-rw-r--r--plugins/PleineLune/stylesheets/controls/_widgetSelect.less44
-rw-r--r--plugins/PleineLune/stylesheets/theme.less33
-rw-r--r--plugins/Referers/Controller.php6
-rw-r--r--plugins/Referers/Referers.php104
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php2
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php2
-rw-r--r--plugins/SegmentEditor/SegmentEditor.php5
-rw-r--r--plugins/SegmentEditor/images/down_arrow.pngbin2898 -> 0 bytes
-rw-r--r--plugins/SegmentEditor/images/scroller.pngbin3329 -> 0 bytes
-rw-r--r--plugins/SegmentEditor/javascripts/Segmentation.js95
-rw-r--r--plugins/SegmentEditor/javascripts/jquery.jscrollpane.js1341
-rw-r--r--plugins/SegmentEditor/javascripts/jquery.mousewheel.js117
-rw-r--r--plugins/SegmentEditor/javascripts/mwheelIntent.js76
-rw-r--r--plugins/SegmentEditor/stylesheets/jquery.jscrollpane.css119
-rw-r--r--plugins/SegmentEditor/stylesheets/scroll.less140
-rw-r--r--plugins/SegmentEditor/stylesheets/segmentation.less75
-rw-r--r--plugins/SegmentEditor/templates/getSelector.twig4
-rw-r--r--plugins/SitesManager/javascripts/SitesManager.js2
-rw-r--r--plugins/SitesManager/stylesheets/SitesManager.less2
-rw-r--r--plugins/Transitions/javascripts/transitions.js8
-rw-r--r--plugins/Transitions/stylesheets/_transitionColors.less (renamed from plugins/Zeitgeist/stylesheets/ui/_transitions.less)0
-rw-r--r--plugins/Transitions/stylesheets/transitions.less2
-rwxr-xr-xplugins/UserCountry/GeoIPAutoUpdater.php3
-rwxr-xr-xplugins/UserCountry/LocationProvider.php2
-rwxr-xr-xplugins/UserCountry/LocationProvider/Default.php4
-rw-r--r--plugins/UserCountry/UserCountry.php2
-rwxr-xr-xplugins/UserCountry/templates/_updaterManage.twig2
-rw-r--r--plugins/UserCountryMap/Controller.php12
-rw-r--r--plugins/UserSettings/UserSettings.php248
-rw-r--r--plugins/UsersManager/API.php2
-rw-r--r--plugins/VisitFrequency/API.php8
-rw-r--r--plugins/VisitTime/VisitTime.php60
-rw-r--r--plugins/VisitorInterest/VisitorInterest.php48
-rw-r--r--plugins/Widgetize/Widgetize.php2
-rw-r--r--plugins/Widgetize/javascripts/widgetize.js6
-rw-r--r--plugins/Zeitgeist/javascripts/ajaxHelper.js2
-rw-r--r--plugins/Zeitgeist/stylesheets/base.css2
-rw-r--r--plugins/Zeitgeist/stylesheets/base.less6
-rw-r--r--plugins/Zeitgeist/stylesheets/general/_jqueryUI.less6
-rw-r--r--plugins/Zeitgeist/stylesheets/general/_misc.less34
-rw-r--r--plugins/Zeitgeist/stylesheets/general/_utils.less34
-rw-r--r--plugins/Zeitgeist/stylesheets/ui/_headerMessage.less6
-rw-r--r--plugins/Zeitgeist/stylesheets/ui/_languageSelect.less10
-rw-r--r--plugins/Zeitgeist/stylesheets/ui/_periodSelect.less4
-rw-r--r--plugins/Zeitgeist/stylesheets/ui/_siteSelect.less15
-rw-r--r--plugins/Zeitgeist/templates/_jsGlobalVariables.twig1
-rw-r--r--plugins/Zeitgeist/templates/_sparklineFooter.twig2
-rw-r--r--plugins/Zeitgeist/templates/admin.twig1
-rw-r--r--plugins/Zeitgeist/templates/genericForm.twig2
166 files changed, 4918 insertions, 3407 deletions
diff --git a/plugins/API/ProcessedReport.php b/plugins/API/ProcessedReport.php
index 8e46cec774..92e82aa275 100644
--- a/plugins/API/ProcessedReport.php
+++ b/plugins/API/ProcessedReport.php
@@ -316,7 +316,7 @@ class ProcessedReport
* - translate metric names to a separate array : $columns
*
* @param int $idSite enables monetary value formatting based on site currency
- * @param \Piwik\DataTable\Set $dataTable
+ * @param \Piwik\DataTable\Map|\Piwik\DataTable\Simple $dataTable
* @param array $reportMetadata
* @param bool $showRawMetrics
* @return array Simple|Set $newReport with human readable format & array $columns list of translated column names & Simple|Set $rowsMetadata
diff --git a/plugins/API/RowEvolution.php b/plugins/API/RowEvolution.php
index ac0b7d5e30..8557043ccc 100644
--- a/plugins/API/RowEvolution.php
+++ b/plugins/API/RowEvolution.php
@@ -93,6 +93,11 @@ class RowEvolution
return $dataTable;
}
+ /**
+ * @param DataTable\Map $dataTable
+ * @param array $labels
+ * @return array
+ */
protected function getLabelsFromDataTable($dataTable, $labels)
{
// if no labels specified, use all possible labels as list
@@ -114,7 +119,7 @@ class RowEvolution
/**
* Get row evolution for a single label
- * @param DataTable $dataTable
+ * @param DataTable\Map $dataTable
* @param array $metadata
* @param string $apiModule
* @param string $apiAction
@@ -175,6 +180,13 @@ class RowEvolution
return $return;
}
+ /**
+ * @param Row $row
+ * @param string $apiModule
+ * @param string $apiAction
+ * @param bool $labelUseAbsoluteUrl
+ * @return bool|string
+ */
private function getRowUrlForEvolutionLabel($row, $apiModule, $apiAction, $labelUseAbsoluteUrl)
{
$url = $row->getMetadata('url');
@@ -191,14 +203,14 @@ class RowEvolution
}
/**
- * @param $idSite
- * @param $period
- * @param $date
- * @param $apiModule
- * @param $apiAction
- * @param $label
- * @param $segment
- * @param $idGoal
+ * @param int $idSite
+ * @param string $period
+ * @param string $date
+ * @param string $apiModule
+ * @param string $apiAction
+ * @param string|bool $label
+ * @param string|bool $segment
+ * @param int|bool $idGoal
* @throws Exception
* @return DataTable\Map|DataTable
*/
diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php
index 1804ca4a07..81402e5f2d 100644
--- a/plugins/Actions/API.php
+++ b/plugins/Actions/API.php
@@ -129,9 +129,11 @@ class API
*
* @return DataTable|DataTable\Map
*/
- public function getPageUrls($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false)
+ public function getPageUrls($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false,
+ $depth = false)
{
- $dataTable = Archive::getDataTableFromArchive('Actions_actions_url', $idSite, $period, $date, $segment, $expanded, $idSubtable);
+ $dataTable = Archive::getDataTableFromArchive(
+ 'Actions_actions_url', $idSite, $period, $date, $segment, $expanded, $idSubtable, $depth);
$this->filterPageDatatable($dataTable);
$this->filterActionsDataTable($dataTable, $expanded);
return $dataTable;
@@ -295,7 +297,12 @@ class API
return $dataTable;
}
- //Visitors can search, and then click "next" to view more results. This is the average number of search results pages viewed for this keyword.
+ /**
+ * Visitors can search, and then click "next" to view more results. This is the average number of search results pages viewed for this keyword.
+ *
+ * @param DataTable|DataTable\Simple|DataTable\Map $dataTable
+ * @param string $columnToRead
+ */
protected function addPagesPerSearchColumn($dataTable, $columnToRead = 'nb_hits')
{
$dataTable->filter('ColumnCallbackAddColumnQuotient', array('nb_pages_per_search', $columnToRead, 'nb_visits', $precision = 1));
@@ -469,6 +476,8 @@ class API
/**
* Common filters for Page URLs and Page Titles
+ *
+ * @param DataTable|DataTable\Simple|DataTable\Map $dataTable
*/
protected function filterPageDatatable($dataTable)
{
@@ -513,7 +522,10 @@ class API
}
/**
- * Common filters for all Actions API getters
+ * Common filters for all Actions API
+ *
+ * @param DataTable|DataTable\Simple|DataTable\Map $dataTable
+ * @param bool $expanded
*/
protected function filterActionsDataTable($dataTable, $expanded = false)
{
diff --git a/plugins/Actions/Actions.php b/plugins/Actions/Actions.php
index 665e0511f1..1fd74b5efe 100644
--- a/plugins/Actions/Actions.php
+++ b/plugins/Actions/Actions.php
@@ -61,10 +61,16 @@ class Actions extends \Piwik\Plugin
'API.getReportMetadata' => 'getReportMetadata',
'API.getSegmentsMetadata' => 'getSegmentsMetadata',
'ViewDataTable.getReportDisplayProperties' => 'getReportDisplayProperties',
+ 'AssetManager.getCssFiles' => 'getCssFiles',
);
return $hooks;
}
+ public function getCssFiles(&$cssFiles)
+ {
+ $cssFiles[] = "plugins/Actions/stylesheets/dataTableActions.less";
+ }
+
public function getSegmentsMetadata(&$segments)
{
$sqlFilter = array($this, 'getIdActionFromSegment');
@@ -648,9 +654,9 @@ class Actions extends \Piwik\Plugin
private function addBaseDisplayProperties(&$result)
{
- $result['datatable_css_class'] = 'dataTableActions';
$result['datatable_js_type'] = 'actionDataTable';
- $result['subtable_template'] = '@CoreHome/_dataTableActions_subDataTable.twig';
+ $result['visualization_properties']['table']['subtable_template'] =
+ '@CoreHome/_dataTableActions_subDataTable.twig';
$result['search_recursive'] = true;
$result['show_all_views_icons'] = false;
$result['show_table_all_columns'] = false;
@@ -661,16 +667,26 @@ class Actions extends \Piwik\Plugin
$result['custom_parameters'] = array('flat' => 0);
if (ViewDataTable::shouldLoadExpanded()) {
- $result['show_expanded'] = true;
-
+ $result['visualization_properties']['table']['show_expanded'] = true;
+
$result['filters'][] = function ($dataTable) {
Actions::setDataTableRowLevels($dataTable);
};
}
+ $result['filters'][] = function ($dataTable, $view) {
+ if ($view->getViewDataTableId() == 'table') {
+ $view->datatable_css_class = 'dataTableActions';
+ }
+ };
+
return $result;
}
+ /**
+ * @param \Piwik\DataTable $dataTable
+ * @param int $level
+ */
public static function setDataTableRowLevels($dataTable, $level = 0)
{
foreach ($dataTable->getRows() as $row) {
@@ -777,7 +793,7 @@ class Actions extends \Piwik\Plugin
'filter_sort_column' => 'entry_nb_visits',
'filter_sort_order' => 'desc',
'title' => Piwik_Translate('Actions_SubmenuPagesEntry'),
- 'relatedReports' => array(
+ 'related_reports' => array(
'Actions.getEntryPageTitles' => Piwik_Translate('Actions_EntryPageTitles')
),
'self_url' => $reportUrl
@@ -805,7 +821,7 @@ class Actions extends \Piwik\Plugin
'filter_sort_column' => 'exit_nb_visits',
'filter_sort_order' => 'desc',
'title' => Piwik_Translate('Actions_SubmenuPagesExit'),
- 'relatedReports' => array(
+ 'related_reports' => array(
'Actions.getExitPageTitles' => Piwik_Translate('Actions_ExitPageTitles')
),
'self_url' => $reportUrl,
@@ -863,7 +879,11 @@ class Actions extends \Piwik\Plugin
'columns_to_display' => array('label', 'nb_visits', 'nb_pages_per_search'),
'show_table_all_columns' => false,
'show_bar_chart' => false,
- 'disable_row_evolution' => false,
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_row_evolution' => false,
+ )
+ )
);
}
@@ -888,7 +908,7 @@ class Actions extends \Piwik\Plugin
'filter_sort_order' => 'desc',
'show_exclude_low_population' => false,
'title' => $title,
- 'relatedReports' => $relatedReports
+ 'related_reports' => $relatedReports
);
$this->addExcludeLowPopDisplayProperties($result);
@@ -911,7 +931,7 @@ class Actions extends \Piwik\Plugin
'columns_to_display' => array('label', 'nb_hits', 'nb_visits', 'bounce_rate',
'avg_time_on_page', 'exit_rate', 'avg_time_generation'),
'title' => Piwik_Translate('Actions_SubmenuPageTitles'),
- 'relatedReports' => array(
+ 'related_reports' => array(
'Actions.getEntryPageTitles' => Piwik_Translate('Actions_EntryPageTitles'),
'Actions.getExitPageTitles' => Piwik_Translate('Actions_ExitPageTitles'),
),
@@ -937,7 +957,7 @@ class Actions extends \Piwik\Plugin
),
'columns_to_display' => array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate'),
'title' => Piwik_Translate('Actions_EntryPageTitles'),
- 'relatedReports' => array(
+ 'related_reports' => array(
'Actions.getPageTitles' => Piwik_Translate('Actions_SubmenuPageTitles'),
"Actions.$entryPageUrlAction" => Piwik_Translate('Actions_SubmenuPagesEntry')
),
@@ -961,7 +981,7 @@ class Actions extends \Piwik\Plugin
),
'columns_to_display' => array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate'),
'title' => Piwik_Translate('Actions_ExitPageTitles'),
- 'relatedReports' => array(
+ 'related_reports' => array(
'Actions.getPageTitles' => Piwik_Translate('Actions_SubmenuPageTitles'),
"Actions.$exitPageUrlAction" => Piwik_Translate('Actions_SubmenuPagesExit'),
),
diff --git a/plugins/Actions/stylesheets/dataTableActions.less b/plugins/Actions/stylesheets/dataTableActions.less
new file mode 100644
index 0000000000..7c059d948b
--- /dev/null
+++ b/plugins/Actions/stylesheets/dataTableActions.less
@@ -0,0 +1,4 @@
+.dataTableActions > .dataTableWrapper {
+ width: 500px;
+ min-height: 1px;
+} \ No newline at end of file
diff --git a/plugins/Annotations/API.php b/plugins/Annotations/API.php
index cf0b9de7bf..0e946b7302 100755
--- a/plugins/Annotations/API.php
+++ b/plugins/Annotations/API.php
@@ -17,6 +17,7 @@ use Piwik\Piwik;
use Piwik\Date;
use Piwik\Plugins\Annotations\AnnotationList;
use Piwik\ViewDataTable;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution as EvolutionViz;
/**
* @see plugins/Annotations/AnnotationList.php
@@ -310,7 +311,7 @@ class API
* @param bool|int $lastN Whether to include the last N periods in the range or not.
* Ignored if period == range.
*
- * @return array
+ * @return Date[] array of Date objects or array(false, false)
* @ignore
*/
public static function getDateRangeForPeriod($date, $period, $lastN = false)
@@ -333,7 +334,7 @@ class API
$endDate = $oPeriod->getDateEnd();
} else // if the range includes the last N periods
{
- list($date, $lastN) = \Piwik\ViewDataTable\GenerateGraphHTML\ChartEvolution::getDateRangeAndLastN($period, $date, $lastN);
+ list($date, $lastN) = EvolutionViz::getDateRangeAndLastN($period, $date, $lastN);
list($startDate, $endDate) = explode(',', $date);
$startDate = Date::factory($startDate);
diff --git a/plugins/Annotations/javascripts/annotations.js b/plugins/Annotations/javascripts/annotations.js
index 56e1572843..628d9f2ea1 100755
--- a/plugins/Annotations/javascripts/annotations.js
+++ b/plugins/Annotations/javascripts/annotations.js
@@ -184,7 +184,7 @@
$('.annotation-period-edit', manager).each(function () {
createDatePicker($(this).parent().parent());
});
- }
+ };
/**
* Replaces the HTML of an annotation manager element, and resets date/period
@@ -223,7 +223,7 @@
var newHtml = $(html);
annotation.html(newHtml.html()).attr('data-date', newHtml.attr('data-date'));
createDatePicker(annotation);
- }
+ };
/**
* Binds events to an annotation manager element.
diff --git a/plugins/CoreAdminHome/Controller.php b/plugins/CoreAdminHome/Controller.php
index c70ad35501..f8a23c8dc2 100644
--- a/plugins/CoreAdminHome/Controller.php
+++ b/plugins/CoreAdminHome/Controller.php
@@ -36,7 +36,8 @@ class Controller extends \Piwik\Controller\Admin
public function index()
{
- return $this->redirectToIndex('UsersManager', 'userSettings');
+ $this->redirectToIndex('UsersManager', 'userSettings');
+ return;
}
public function generalSettings()
diff --git a/plugins/CoreAdminHome/stylesheets/generalSettings.less b/plugins/CoreAdminHome/stylesheets/generalSettings.less
index 71871038b0..c372146971 100644
--- a/plugins/CoreAdminHome/stylesheets/generalSettings.less
+++ b/plugins/CoreAdminHome/stylesheets/generalSettings.less
@@ -7,13 +7,14 @@
}
#content.admin {
- margin: 0 15px 0 270px;
+ margin: 0 0 0 260px;
padding: 0 0 40px;
+ display: table;
font: 13px Arial, Helvetica, sans-serif;
}
.admin #header_message {
- margin-top: -10px;
+ margin-top: 10px;
}
table.admin {
diff --git a/plugins/CoreAdminHome/stylesheets/menu.less b/plugins/CoreAdminHome/stylesheets/menu.less
index 4621613aae..f6686a3cdb 100644
--- a/plugins/CoreAdminHome/stylesheets/menu.less
+++ b/plugins/CoreAdminHome/stylesheets/menu.less
@@ -1,8 +1,11 @@
+#container {
+ clear: left;
+}
+
#menu {
- padding: 0 0 0 0;
+ padding: 0;
float: left;
width: 240px;
- position: absolute;
}
#tablist {
diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php
index 8af95e6449..33c9e61abe 100644
--- a/plugins/CoreHome/Controller.php
+++ b/plugins/CoreHome/Controller.php
@@ -158,8 +158,8 @@ class Controller extends \Piwik\Controller
public function getRowEvolutionGraph($fetch = false, $rowEvolution = null)
{
if (empty($rowEvolution)) {
- $paramName = Piwik_CoreHome_DataTableRowAction_MultiRowEvolution::IS_MULTI_EVOLUTION_PARAM;
- $isMultiRowEvolution = Common::getRequestVar($paramName, false, 'int');
+ $label = Common::getRequestVar('label', '', 'string');
+ $isMultiRowEvolution = strpos($label, ',') !== false;
$rowEvolution = $this->makeRowEvolution($isMultiRowEvolution, $graphType = 'graphEvolution');
$rowEvolution->useAvailableMetrics();
diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php
index afb6744bf3..e2e32b1a6b 100644
--- a/plugins/CoreHome/CoreHome.php
+++ b/plugins/CoreHome/CoreHome.php
@@ -42,15 +42,19 @@ class CoreHome extends \Piwik\Plugin
public function getCssFiles(&$cssFiles)
{
$cssFiles[] = "libs/jquery/themes/base/jquery-ui.css";
+ $cssFiles[] = "libs/jquery/stylesheets/jquery.jscrollpane.css";
+ $cssFiles[] = "libs/jquery/stylesheets/scroll.less";
$cssFiles[] = "plugins/Zeitgeist/stylesheets/base.less";
$cssFiles[] = "plugins/CoreHome/stylesheets/coreHome.less";
$cssFiles[] = "plugins/CoreHome/stylesheets/menu.less";
$cssFiles[] = "plugins/CoreHome/stylesheets/dataTable.less";
$cssFiles[] = "plugins/CoreHome/stylesheets/cloud.less";
$cssFiles[] = "plugins/CoreHome/stylesheets/jquery.ui.autocomplete.css";
- $cssFiles[] = "plugins/CoreHome/stylesheets/jqplot.css";
+ $cssFiles[] = "plugins/CoreHome/stylesheets/jqplotColors.less";
+ $cssFiles[] = "plugins/CoreHome/stylesheets/sparklineColors.less";
$cssFiles[] = "plugins/CoreHome/stylesheets/promo.less";
$cssFiles[] = "plugins/CoreHome/stylesheets/color_manager.css";
+ $cssFiles[] = "plugins/CoreHome/stylesheets/sparklineColors.less";
}
public function getJsFiles(&$jsFiles)
@@ -61,11 +65,14 @@ class CoreHome extends \Piwik\Plugin
$jsFiles[] = "libs/jquery/jquery.truncate.js";
$jsFiles[] = "libs/jquery/jquery.scrollTo.js";
$jsFiles[] = "libs/jquery/jquery.history.js";
+ $jsFiles[] = "libs/jquery/jquery.jscrollpane.js";
+ $jsFiles[] = "libs/jquery/jquery.mousewheel.js";
+ $jsFiles[] = "libs/jquery/mwheelIntent.js";
$jsFiles[] = "libs/javascript/sprintf.js";
$jsFiles[] = "plugins/Zeitgeist/javascripts/piwikHelper.js";
$jsFiles[] = "plugins/Zeitgeist/javascripts/ajaxHelper.js";
- $jsFiles[] = "plugins/CoreHome/javascripts/datatable.js";
- $jsFiles[] = "plugins/CoreHome/javascripts/datatable_rowactions.js";
+ $jsFiles[] = "plugins/CoreHome/javascripts/dataTable.js";
+ $jsFiles[] = "plugins/CoreHome/javascripts/dataTable_rowactions.js";
$jsFiles[] = "plugins/CoreHome/javascripts/popover.js";
$jsFiles[] = "plugins/CoreHome/javascripts/broadcast.js";
$jsFiles[] = "plugins/CoreHome/javascripts/menu.js";
@@ -74,11 +81,10 @@ class CoreHome extends \Piwik\Plugin
$jsFiles[] = "plugins/CoreHome/javascripts/autocomplete.js";
$jsFiles[] = "plugins/CoreHome/javascripts/sparkline.js";
$jsFiles[] = "plugins/CoreHome/javascripts/corehome.js";
- $jsFiles[] = "plugins/CoreHome/javascripts/datatable_manager.js";
+ $jsFiles[] = "plugins/CoreHome/javascripts/dataTable_manager.js";
$jsFiles[] = "plugins/CoreHome/javascripts/donate.js";
- $jsFiles[] = "plugins/CoreHome/javascripts/jqplot.js";
$jsFiles[] = "libs/jqplot/jqplot-custom.min.js";
$jsFiles[] = "plugins/CoreHome/javascripts/promo.js";
$jsFiles[] = "plugins/CoreHome/javascripts/color_manager.js";
}
-}
+} \ No newline at end of file
diff --git a/plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php b/plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php
index c2a7506147..0af3a81115 100644
--- a/plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php
+++ b/plugins/CoreHome/DataTableRowAction/MultiRowEvolution.php
@@ -19,8 +19,6 @@ use Piwik\ViewDataTable;
class Piwik_CoreHome_DataTableRowAction_MultiRowEvolution
extends Piwik_CoreHome_DataTableRowAction_RowEvolution
{
- const IS_MULTI_EVOLUTION_PARAM = 'is_multi_evolution';
-
/** The requested metric */
protected $metric;
@@ -72,17 +70,4 @@ class Piwik_CoreHome_DataTableRowAction_MultiRowEvolution
return parent::renderPopover($controller, $view);
}
-
- /**
- * Generic method to get an evolution graph or a sparkline for the row evolution popover.
- * Do as much as possible from outside the controller.
- *
- * @return ViewDataTable
- */
- public function getRowEvolutionGraph($graphType = false, $metrics = false)
- {
- $view = parent::getRowEvolutionGraph($graphType, $metrics);
- $view->custom_parameters[self::IS_MULTI_EVOLUTION_PARAM] = 1; // set in JS
- return $view;
- }
}
diff --git a/plugins/CoreHome/DataTableRowAction/RowEvolution.php b/plugins/CoreHome/DataTableRowAction/RowEvolution.php
index 37e6e52439..c23235009c 100644
--- a/plugins/CoreHome/DataTableRowAction/RowEvolution.php
+++ b/plugins/CoreHome/DataTableRowAction/RowEvolution.php
@@ -15,8 +15,8 @@ use Piwik\Metrics;
use Piwik\Date;
use Piwik\ViewDataTable;
use Piwik\Url;
-use Piwik\ViewDataTable\GenerateGraphHTML\ChartEvolution;
use Piwik\Visualization\Chart\Evolution;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution as EvolutionViz;
/**
* ROW EVOLUTION
@@ -52,7 +52,7 @@ class Piwik_CoreHome_DataTableRowAction_RowEvolution
/**
* The data
- * @var DataTable
+ * @var Piwik\DataTable
*/
protected $dataTable;
@@ -98,8 +98,7 @@ class Piwik_CoreHome_DataTableRowAction_RowEvolution
if ($this->period != 'range') {
// handle day, week, month and year: display last X periods
$end = $date->toString();
- list($this->date, $lastN) =
- ChartEvolution::getDateRangeAndLastN($this->period, $end);
+ list($this->date, $lastN) = EvolutionViz::getDateRangeAndLastN($this->period, $end);
}
$this->segment = \Piwik\API\Request::getRawSegmentFromRequest();
@@ -180,29 +179,33 @@ class Piwik_CoreHome_DataTableRowAction_RowEvolution
/**
* Generic method to get an evolution graph or a sparkline for the row evolution popover.
* Do as much as possible from outside the controller.
+ * @param string|bool $graphType
+ * @param array|bool $metrics
* @return ViewDataTable
*/
public function getRowEvolutionGraph($graphType = false, $metrics = false)
{
// set up the view data table
- $view = ViewDataTable::factory(
- $graphType ?: $this->graphType, $this->apiMethod, $controllerAction = 'CoreHome.getRowEvolutionGraph');
+ $view = ViewDataTable::factory($graphType ?: $this->graphType, $this->apiMethod,
+ $controllerAction = 'CoreHome.getRowEvolutionGraph', $forceDefault = true);
$view->setDataTable($this->dataTable);
if (!empty($this->graphMetrics)) { // In row Evolution popover, this is empty
$view->columns_to_display = array_keys($metrics ?: $this->graphMetrics);
}
+ $view->show_goals = false;
$view->show_all_views_icons = false;
$view->show_active_view_icon = false;
$view->show_related_reports = false;
+ $view->visualization_properties->show_series_picker = false;
foreach ($this->availableMetrics as $metric => $metadata) {
$view->translations[$metric] = $metadata['name'];
}
- $view->external_series_toggle = 'RowEvolutionSeriesToggle';
- $view->external_series_toggle_show_all = $this->initiallyShowAllMetrics;
+ $view->visualization_properties->external_series_toggle = 'RowEvolutionSeriesToggle';
+ $view->visualization_properties->external_series_toggle_show_all = $this->initiallyShowAllMetrics;
return $view;
}
@@ -269,10 +272,9 @@ class Piwik_CoreHome_DataTableRowAction_RowEvolution
{
// sparkline is always echoed, so we need to buffer the output
$view = $this->getRowEvolutionGraph($graphType = 'sparkline', $metrics = array($metric => $metric));
- $view->main();
ob_start();
- $view->getView()->render();
+ $view->render();
$spark = ob_get_contents();
ob_end_clean();
diff --git a/plugins/CoreHome/javascripts/autocomplete.js b/plugins/CoreHome/javascripts/autocomplete.js
index d30197e8d0..2679865a55 100644
--- a/plugins/CoreHome/javascripts/autocomplete.js
+++ b/plugins/CoreHome/javascripts/autocomplete.js
@@ -147,26 +147,26 @@ $(function () {
// close it
$('body').on('mouseup', function (e) {
var closestSelector = $(e.target).closest('.sites_autocomplete');
- if (closestSelector != selector) {
- reset(selector);
- $('.custom_select_block', selector).removeClass('custom_select_block_show');
+ if (!closestSelector.length || !closestSelector.is(selector)) {
+ if ($('.custom_select_block', selector).hasClass('custom_select_block_show')) {
+ reset(selector);
+ $('.custom_select_block', selector).removeClass('custom_select_block_show');
+ }1
}
});
// set event handling code for non-jquery-autocomplete parts of widget
if ($('li', selector).length > 1) {
// event handler for when site selector is clicked. shows dropdown w/ first X sites
- $(".custom_select_main_link", selector).click(function () {
- $(".custom_select_block", selector).addClass("custom_select_block_show");
- $('.custom_select_ul_list', selector).show();
- $('.websiteSearch', selector).val('').focus();
+ $(".custom_select_main_link", selector).click(function() {
+ $(".custom_select_block", selector).toggleClass("custom_select_block_show");
+ $(".websiteSearch", selector).val("").focus();
return false;
});
- $('.custom_select_block', selector).on('mouseenter', function () {
- $('.custom_select_ul_list li a', selector).each(function () {
+ $('.custom_select_block', selector).on('mouseenter', function() {
+ $('.custom_select_ul_list > li > a', selector).each(function() {
var idSite = $(this).attr('siteid');
-
var linkUrl = getUrlForWebsiteId(idSite);
$(this).attr('href', linkUrl);
});
@@ -174,7 +174,7 @@ $(function () {
// change selection. fire's site selector's on select event and modifies the attributes
// of the selected link
- $('.custom_select_ul_list li a', selector).each(function () {
+ $('.custom_select_ul_list li a', selector).each(function() {
$(this).click(function (e) {
var idsite = $(this).attr('siteid'),
name = $(this).text();
@@ -201,9 +201,6 @@ $(function () {
$(".custom_select_block", selector).css('width', widthSitesSelection);
}
}
- else {
- $('.custom_select_main_link', selector).addClass('noselect');
- }
// handle multi-sites link click (triggers site selected event w/ id=all)
$('.custom_select_all', selector).click(function () {
diff --git a/plugins/CoreHome/javascripts/calendar.js b/plugins/CoreHome/javascripts/calendar.js
index 44bf7b9d17..e0580b1be0 100644
--- a/plugins/CoreHome/javascripts/calendar.js
+++ b/plugins/CoreHome/javascripts/calendar.js
@@ -16,7 +16,7 @@
daysSinceYearStart = (this_utc - onejan_utc) / 86400000; // constant is millisecs in one day
return Math.ceil((daysSinceYearStart + onejan.getDay()) / 7);
- }
+ };
var currentYear, currentMonth, currentDay, currentDate, currentWeek;
@@ -449,7 +449,8 @@
});
$('body').on('click', function(e) {
- if (!$(e.target).parents('#periodString').length && !$(e.target).is('#periodString') && !$(e.target).is('option') && $("#periodMore").is(":visible")) {
+ var target = $(e.target);
+ if (target.closest('html').length && !target.closest('#periodString').length && !target.is('option') && $("#periodMore").is(":visible")) {
$("#periodMore").hide();
}
});
@@ -532,8 +533,7 @@
return !isNaN(d.getTime());
}
- var period = broadcast.getValueFromUrl('period');
- if (period == 'range') {
+ if (piwik.period == 'range') {
$("#period_id_range").click();
}
});
diff --git a/plugins/CoreHome/javascripts/datatable.js b/plugins/CoreHome/javascripts/dataTable.js
index bf85c07d1c..8c229be1f3 100644
--- a/plugins/CoreHome/javascripts/datatable.js
+++ b/plugins/CoreHome/javascripts/dataTable.js
@@ -282,22 +282,20 @@ dataTable.prototype =
$('.limitSelection ul li:last', domElem).addClass('last');
if (!self.isEmpty) {
- var show = function () {
+ var show = function() {
$('.limitSelection ul', domElem).show();
$('.limitSelection', domElem).addClass('visible');
- $(document).on('mouseup.limitSelection', function (e) {
- if ((!$(e.target).parents('.limitSelection').length
- || $(e.target).parents('.limitSelection') != $('.limitSelection', domElem))
- && !$(e.target).is('.limitSelection')) {
+ $(document).on('mouseup.limitSelection', function(e) {
+ if (!$(e.target).closest('.limitSelection').length) {
hide();
}
});
- }
+ };
var hide = function () {
$('.limitSelection ul', domElem).hide();
$('.limitSelection', domElem).removeClass('visible');
$(document).off('mouseup.limitSelection');
- }
+ };
$('.limitSelection div', domElem).on('click', function () {
$('.limitSelection', domElem).is('.visible') ? hide() : show();
});
@@ -363,11 +361,13 @@ dataTable.prototype =
var imageSortSrc = getSortImageSrc();
var imageSortWidth = 16;
var imageSortHeight = 16;
+ var ImageSortClass = self.param.filter_sort_order.charAt(0).toUpperCase() + self.param.filter_sort_order.substr(1);
+
// we change the style of the column currently used as sort column
// adding an image and the class columnSorted to the TD
$(".sortable#" + self.param.filter_sort_column + ' #thDIV', domElem).parent()
.addClass('columnSorted')
- .prepend('<div id="sortIconContainer"><img id="sortIcon" width="' + imageSortWidth + '" height="' + imageSortHeight + '" src="' + imageSortSrc + '" /></div>');
+ .prepend('<div class="sortIconContainer sortIconContainer' + ImageSortClass + '"><img class="sortIcon" width="' + imageSortWidth + '" height="' + imageSortHeight + '" src="' + imageSortSrc + '" /></div>');
}
}
},
@@ -391,10 +391,10 @@ dataTable.prototype =
currentPattern = piwikHelper.htmlDecode(currentPattern);
$('.dataTableSearchPattern', domElem)
- .show()
+ .css({display: 'block'})
.each(function () {
// when enter is pressed in the input field we submit the form
- $('#keyword', this)
+ $('.searchInput', this)
.on("keyup",
function (e) {
if (isEnterKey(e)) {
@@ -407,7 +407,7 @@ dataTable.prototype =
$(':submit', this).submit(
function () {
- var keyword = $(this).siblings('#keyword').val();
+ var keyword = $(this).siblings('.searchInput').val();
self.param.filter_offset = 0;
if (self.param.search_recursive) {
@@ -436,10 +436,10 @@ dataTable.prototype =
<img src="plugins/CoreHome/images/reset_search.png" style="position: absolute; top: 4px; left: -15px; cursor: pointer; display: inline;" title="Clear" />\
</span>')
.click(function () {
- $('#keyword', target).val('');
+ $('.searchInput', target).val('');
$(':submit', target).submit();
});
- $('#keyword', this).after(clearImg);
+ $('.searchInput', this).after(clearImg);
}
}
@@ -457,7 +457,7 @@ dataTable.prototype =
var totalRows = Number(self.param.totalRows);
var offsetEndDisp = offsetEnd;
- if (self.param.keep_summary_row == 1) --totalRows;
+ if (self.props.keep_summary_row == 1) --totalRows;
if (offsetEnd > totalRows) offsetEndDisp = totalRows;
@@ -475,7 +475,7 @@ dataTable.prototype =
var offsetEnd = Number(self.param.filter_offset)
+ Number(self.param.filter_limit);
var totalRows = Number(self.param.totalRows);
- if (self.param.keep_summary_row == 1) --totalRows;
+ if (self.props.keep_summary_row == 1) --totalRows;
if (offsetEnd < totalRows) {
$(this).css('display', 'inline');
}
@@ -726,7 +726,7 @@ dataTable.prototype =
self.reloadAjaxDataTable();
self.notifyWidgetParametersChange($(this), {viewDataTable: self.param.viewDataTable});
}
- )
+ );
//handle Graph View icons
$('.tableGraphViews a', domElem)
@@ -781,7 +781,7 @@ dataTable.prototype =
});
self.exportToFormatHide(domElem);
},
- function () {
+ function() {
//Graph icon onmouseout
if (self.graphViewStartingKeep) return self.graphViewStartingKeep = false; //exit while icons animate
$('a', this).each(function (i) {
@@ -876,16 +876,14 @@ dataTable.prototype =
str += '&filter_limit=' + filter_limit;
}
if (label) {
- if (self.param.is_multi_evolution) {
- label = label.split(',');
- }
+ label = label.split(',');
- if (label instanceof Array) {
+ if (label.length > 1) {
for (var i = 0; i != label.length; ++i) {
str += '&label[]=' + encodeURIComponent(label[i]);
}
} else {
- str += '&label=' + encodeURIComponent(label);
+ str += '&label=' + encodeURIComponent(label[0]);
}
}
return str;
@@ -1151,8 +1149,8 @@ dataTable.prototype =
$("th:first-child", domElem).addClass('label');
$("td:first-child:odd", domElem).addClass('label labeleven');
$("td:first-child:even", domElem).addClass('label labelodd');
- $("tr:odd td", domElem).slice(1).addClass('columnodd');
- $("tr:even td", domElem).slice(1).addClass('columneven');
+ $("tr:odd td", domElem).slice(1).addClass('column columnodd');
+ $("tr:even td", domElem).slice(1).addClass('column columneven');
$('td span.label', domElem).each(function () { self.truncate($(this)); });
@@ -1193,7 +1191,7 @@ dataTable.prototype =
self.param.enable_filter_excludelowpop = filtersToRestore.enable_filter_excludelowpop;
self.param.idSubtable = idSubTable;
- self.param.action = self.param.controllerActionCalledWhenRequestSubTable;
+ self.param.action = self.props.subtable_controller_action;
delete self.param.totalRows;
@@ -1429,8 +1427,8 @@ dataTable.prototype =
doHandleRowActions: function (trs) {
var self = this;
- var availableActionsForReport = DataTable_RowActions_Registry
- .getAvailableActionsForReport(self.param);
+ var merged = $.extend({}, self.param, self.props);
+ var availableActionsForReport = DataTable_RowActions_Registry.getAvailableActionsForReport(merged);
if (availableActionsForReport.length == 0) {
return;
@@ -1712,6 +1710,8 @@ actionDataTable.prototype =
// label (first column of a data row) or not
$("td:first-child:odd", this).addClass('label labeleven');
$("td:first-child:even", this).addClass('label labelodd');
+ $("tr:odd td", domElem).slice(1).addClass('column columnodd');
+ $("tr:even td", domElem).slice(1).addClass('column columneven');
});
},
@@ -1761,7 +1761,7 @@ actionDataTable.prototype =
this.param['enable_filter_excludelowpop'] = filtersToRestore['enable_filter_excludelowpop'];
self.param.idSubtable = idSubTable;
- self.param.action = self.param.controllerActionCalledWhenRequestSubTable;
+ self.param.action = self.props.subtable_controller_action;
self.reloadAjaxDataTable(false, function (resp) {
self.actionsSubDataTableLoaded(resp, idSubTable);
diff --git a/plugins/CoreHome/javascripts/datatable_manager.js b/plugins/CoreHome/javascripts/dataTable_manager.js
index a1ea816484..e2f81250ca 100644
--- a/plugins/CoreHome/javascripts/datatable_manager.js
+++ b/plugins/CoreHome/javascripts/dataTable_manager.js
@@ -51,10 +51,8 @@
$('div.dataTable').each(function () {
if (!$(this).attr('id')) {
var params = JSON.parse($(this).attr('data-params') || '{}');
- var tableType = $(this).attr('data-table-type');
- if (!tableType) {
- tableType = 'dataTable';
- }
+ var props = JSON.parse($(this).attr('data-props') || '{}');
+ var tableType = $(this).attr('data-table-type') || 'dataTable';
// convert values in params that are arrays to comma separated string lists
for (var key in params) {
@@ -63,7 +61,7 @@
}
}
- self.initSingleDataTable(this, window[tableType], params);
+ self.initSingleDataTable(this, window[tableType], params, props);
}
});
},
@@ -74,8 +72,9 @@
* @param {Element} domElem The DataTable div element.
* @param {Function} klass The DataTable's JS class.
* @param {Object} params The request params used.
+ * @param {Object} props The view properties that should be visible to the JS.
*/
- initSingleDataTable: function (domElem, klass, params) {
+ initSingleDataTable: function (domElem, klass, params, props) {
var newId = this.getNextId();
$(domElem).attr('id', newId);
@@ -84,6 +83,7 @@
$(domElem).data('dataTableInstance', table);
table.param = params;
+ table.props = props;
table.init(newId);
// if the datatable has a graph, init the graph
diff --git a/plugins/CoreHome/javascripts/datatable_rowactions.js b/plugins/CoreHome/javascripts/dataTable_rowactions.js
index ab5fb7b7b2..ab5fb7b7b2 100644
--- a/plugins/CoreHome/javascripts/datatable_rowactions.js
+++ b/plugins/CoreHome/javascripts/dataTable_rowactions.js
diff --git a/plugins/CoreHome/javascripts/menu.js b/plugins/CoreHome/javascripts/menu.js
index 4a00c16ff0..d83ddb718f 100644
--- a/plugins/CoreHome/javascripts/menu.js
+++ b/plugins/CoreHome/javascripts/menu.js
@@ -28,9 +28,10 @@ menu.prototype =
outMainLI: function () {
clearTimeout(menu.prototype.resetTimer);
- menu.prototype.resetTimer = setTimeout(function () {
- $('.nav>.sfHover').removeClass('sfHover');
- $('.nav>.sfActive').addClass('sfHover');
+ menu.prototype.resetTimer = setTimeout(function() {
+ $('.nav_tab > .sfHover').removeClass('sfHover');
+ $('.nav_tab > .sfActive').addClass('sfHover');
+ menu.prototype.adaptSubMenuHeight();
}, 2000);
},
diff --git a/plugins/CoreHome/javascripts/popover.js b/plugins/CoreHome/javascripts/popover.js
index 4287782142..27c07dc334 100644
--- a/plugins/CoreHome/javascripts/popover.js
+++ b/plugins/CoreHome/javascripts/popover.js
@@ -17,10 +17,11 @@ var Piwik_Popover = (function () {
}
};
- var openPopover = function (title) {
+ var openPopover = function (title, dialogClass) {
createContainer();
- container.dialog({
+ var options =
+ {
title: title,
modal: true,
width: '950px',
@@ -28,6 +29,10 @@ var Piwik_Popover = (function () {
resizable: false,
autoOpen: true,
open: function (event, ui) {
+ if (dialogClass) {
+ $(this).parent().addClass(dialogClass).attr('style', '');
+ }
+
$('.ui-widget-overlay').on('click.popover', function () {
container.dialog('close');
});
@@ -45,7 +50,9 @@ var Piwik_Popover = (function () {
closeCallback = false;
}
}
- });
+ };
+
+ container.dialog(options);
// override the undocumented _title function to ensure that the title attribute is not escaped (according to jQueryUI bug #6016)
container.data( "uiDialog" )._title = function(title) {
@@ -70,7 +77,7 @@ var Piwik_Popover = (function () {
* @param {string} [popoverSubject] subject of the popover (e.g. url, optional)
* @param {int} [height] height of the popover in px (optional)
*/
- showLoading: function (popoverName, popoverSubject, height) {
+ showLoading: function (popoverName, popoverSubject, height, dialogClass) {
var loading = $(document.createElement('div')).addClass('Piwik_Popover_Loading');
var loadingMessage = popoverSubject ? translations.General_LoadingPopoverFor_js :
@@ -94,7 +101,7 @@ var Piwik_Popover = (function () {
}
if (!isOpen) {
- openPopover();
+ openPopover(null, dialogClass);
}
this.setContent(loading);
@@ -203,9 +210,18 @@ var Piwik_Popover = (function () {
* @param {string} url
* @param {string} loadingName
*/
- createPopupAndLoadUrl: function (url, loadingName) {
+ createPopupAndLoadUrl: function (url, loadingName, dialogClass) {
+ // make sure the minimum top position of the popover is 106px
+ var ensureMinimumTop = function () {
+ var popoverContainer = $('#Piwik_Popover').parent();
+ if (popoverContainer.position().top < 106) {
+ popoverContainer.css('top', '106px');
+ }
+ };
+
// open the popover
- var box = Piwik_Popover.showLoading(loadingName);
+ var box = Piwik_Popover.showLoading(loadingName, null, null, dialogClass);
+ ensureMinimumTop();
var callback = function (html) {
function setPopoverTitleIfOneFoundInContainer() {
@@ -218,7 +234,8 @@ var Piwik_Popover = (function () {
Piwik_Popover.setContent(html);
setPopoverTitleIfOneFoundInContainer();
- }
+ ensureMinimumTop();
+ };
var ajaxRequest = new ajaxHelper();
ajaxRequest.addParams(piwikHelper.getArrayFromQueryString(url), 'get');
ajaxRequest.setCallback(callback);
@@ -226,6 +243,4 @@ var Piwik_Popover = (function () {
ajaxRequest.send(false);
}
};
-
-})();
-
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/javascripts/sparkline.js b/plugins/CoreHome/javascripts/sparkline.js
index 6093955eeb..5b308c9606 100644
--- a/plugins/CoreHome/javascripts/sparkline.js
+++ b/plugins/CoreHome/javascripts/sparkline.js
@@ -7,15 +7,15 @@
(function ($) {
-var sparklineColorNames = ['lineColor', 'red', 'blue', 'green'];
+var sparklineColorNames = ['backgroundColor', 'lineColor', 'minPointColor', 'maxPointColor', 'lastPointColor'];
piwik.getSparklineColors = function () {
return piwik.ColorManager.getColors('sparkline-colors', sparklineColorNames);
};
// initializes each sparkline so they use colors defined in CSS
-piwik.initSparklines = function () {
- $('img.sparkline').each(function () {
+piwik.initSparklines = function() {
+ $('.sparkline > img').each(function () {
var $self = $(this);
if ($self.attr('src')) {
@@ -36,7 +36,7 @@ window.initializeSparklines = function () {
// try to find sparklines and add them clickable behaviour
graph.parent().find('div.sparkline').each(function () {
// find the sparkline and get it's src attribute
- var sparklineUrl = $('img.sparkline', this).attr('data-src');
+ var sparklineUrl = $('img', this).attr('data-src');
if (sparklineUrl != "") {
var params = broadcast.getValuesFromUrl(sparklineUrl);
@@ -62,7 +62,7 @@ window.initializeSparklines = function () {
// if this happens, we can't find the graph using $('#'+idDataTable+"Chart");
// instead, we just use the first evolution graph we can find.
if (dataTable.length == 0) {
- dataTable = $('div.dataTableEvolutionGraph');
+ dataTable = $('div.dataTableVizEvolution');
}
// reload the datatable w/ a new column & scroll to the graph
diff --git a/plugins/CoreHome/stylesheets/coreHome.less b/plugins/CoreHome/stylesheets/coreHome.less
index 041bc1a936..2c82ad95b4 100644
--- a/plugins/CoreHome/stylesheets/coreHome.less
+++ b/plugins/CoreHome/stylesheets/coreHome.less
@@ -159,7 +159,7 @@ div.pk-emptyGraph {
line-height: 20px;
font-weight: normal;
text-align: center;
- background: url(../../Zeitgeist/images/loading-blue.gif) no-repeat center 20px;
+ background: url(plugins/Zeitgeist/images/loading-blue.gif) no-repeat center 20px;
}
.Piwik_Popover_Loading_NameWithSubject {
diff --git a/plugins/CoreHome/stylesheets/dataTable.less b/plugins/CoreHome/stylesheets/dataTable.less
index 239d0c8423..d3760872fd 100644
--- a/plugins/CoreHome/stylesheets/dataTable.less
+++ b/plugins/CoreHome/stylesheets/dataTable.less
@@ -1,781 +1,10 @@
-.widget {
- z-index: 1;
-}
-
-.widget p {
- margin-left: 10px;
-}
-
-/* container of each table */
-.dataTableVizHtmlTable > .dataTableWrapper {
- width: 450px;
- /* not more than 450px to make sure 2 tables can fit horizontally on a 1024 screen */
-}
-
-.dataTableAllColumns > .dataTableWrapper {
- width: 535px;
-}
-
-.dataTableActions > .dataTableWrapper {
- width: 500px;
- min-height: 1px;
-}
-
-.subDataTable > .dataTableWrapper {
- width: 95%;
-}
-
-.dataTableGraph > .dataTableWrapper {
- width: 500px;
- min-height: 1px;
-}
-
-.dataTableEvolutionGraph > .dataTableWrapper {
- width: 100%;
-}
-
-/*Overriding some dataTable css for better dashboard display*/
-.widget .dataTableWrapper {
- width: 100%;
-}
-
-/* main data table */
-table.dataTable {
- border: 0;
- width: 100%;
- padding: 0;
- border-spacing: 0;
- margin: 0;
-}
-
-table.dataTable td.label,
-table.subDataTable td.label {
- width: 100%;
- white-space: nowrap;
-}
-
-table.dataTable img,
-table.subDataTable img {
- vertical-align: middle;
-}
-
-#UserCountrygetCountry table.dataTable img {
- vertical-align: baseline;
-}
-
-table.dataTable img {
- border: 0;
- margin-right: 1em;
- margin-left: 0.5em;
-}
-
-table.dataTable tr.subDataTable {
- cursor: pointer;
-}
-
-table.dataTable th {
- margin: 0;
- color: #255792;
- text-align: left;
- padding: 6px 6px 6px 12px;
- background: #e4e2d7;
- font-size: 12px;
- font-weight: normal;
- border-left: 1px solid #d4d0c4;
- vertical-align: top;
-}
-
-table.dataTable th.sortable {
- cursor: pointer;
-}
-
-table.dataTable th.first {
-}
-
-table.dataTable th.last {
-}
-
-table.dataTable th.columnSorted {
- font-weight: bold;
- padding-right: 20px;
- background: #d5d3c8;
-}
-
-table.dataTable td {
- padding: 5px 5px 5px 12px;
- background: #fff;
- border-left: 1px solid #e7e7e7;
- border-bottom: 1px solid #e7e7e7;
-}
-
-table.dataTable td, table.dataTable td a {
- margin: 0;
- text-decoration: none;
- color: #444;
-}
-
-table.dataTable tr:hover>td,
-table.dataTable tr:hover>td .dataTableRowActions {
- background-color: #FFFFF7;
-}
-
-table.dataTable tr.subDataTable:hover>td,
-table.dataTable tr.subDataTable:hover>td .dataTableRowActions {
- background-color: #ffffcb;
-}
-
-table.dataTable tr:hover>td.cellSubDataTable
-table.dataTable tr:hover>td.cellSubDataTable .dataTableRowActions {
- background-color: #fff;
-}
-
-td.clean {
- background-color: #fff !important;
-}
-
-table.dataTable td.columneven {
- background: #efeeec;
-}
-
-table.dataTable td.columnodd {
- background: #f6f5f3;
-}
-
-table.dataTable td.labeleven {
- background: #F9FAFA url(../images/bullet2.gif) no-repeat;
-}
-
-table.dataTable td.labelodd {
- background: #fff url(../images/bullet1.gif) no-repeat;
-}
-
-.dataTable tr.highlight td {
- background-color: #ECF9DD;
- font-weight: bold;
-}
-
-table.dataTable td.label, table.subActionsDataTable td.label, table.actionsDataTable td.label {
- border-top: 0;
- border-left: 0;
-}
-
-table.dataTable th.label {
- border-left: 0;
-}
-
-.dataTableActions table.dataTable th.label {
- /* Ensures tables have enough space to display subtable on click, and prevent the jumping effect */
- min-width: 250px;
-}
-
-table.dataTable span.label.highlighted {
- font-style: italic;
-}
-
-/* the cell containing the subdatatable */
-table.dataTable .cellSubDataTable {
- margin: 0;
- border-left: 0;
-}
-
-/* A link in a column in the DataTable */
-table.dataTable td #urlLink {
- display: none;
-}
-
-/* SUBDATATABLE */
-/* a datatable inside another datatable */
-table.subDataTable {
- background: #FFFFFF;
- margin: 5px 10px;
-}
-
-table.subDataTable td {
- border: 0;
-}
-
-table.subDataTable thead th {
- font-weight: normal;
- font-size: 12px;
- text-align: left;
- padding: .3em 1em;
- background: #f1f0eb;
- border: 0;
- border-top: 1px solid #e7e7e7;
- border-bottom: 1px solid #e7e7e7;
-}
-
-table.subDataTable th.columnSorted {
- background: #e3e1d9;
-}
-
-table.subDataTable td.labeleven, table.subDataTable td.labelodd {
- background-image: none;
-}
-
-table.subDataTable td {
- border-bottom: 1px solid #e7e7e7;
- border-left: 0;
-}
-
-table.subDataTable td, table.subDataTable td a {
- color: #615B53;
-}
-
-table.subDataTable td.labeleven, table.subDataTable td.columneven {
- color: #2D2A27;
-}
-
-table.subDataTable td.label {
- width: 80%;
-}
-
-table.subDataTable td.labelodd, table.subDataTable td.labelodd a {
- background: #fff;
-}
-
-table.subDataTable td.label {
- padding: 5px;
-}
-
-table.dataTable img {
- margin-left: 0;
-}
-
-/* misc SPAN and DIV */
-table thead div {
-
-}
-
-#sortIconContainer {
- float: right;
- position: relative;
-}
-
-#sortIcon {
- margin: 0;
- position: absolute;
-}
-
-.datatableFooterMessage {
- color: #888;
- text-align: left;
- margin: 10px;
-}
-
-.dataTablePages {
- color: #BFBFBF;
- font-weight: bold;
- margin: 10px;
- font-size: 12px;
-}
-
-.dataTableSearchPattern {
- margin: 8px 0 0 0;
- height: 30px;
- display: block !important;
- white-space: nowrap;
- background: url(../../Zeitgeist/images/search_bg.png) no-repeat center 0;
- text-align: center;
-}
-
-.dataTableSearchPattern input {
- vertical-align: top;
- font-size: 10px !important;
- color: #454545 !important;
- border: 0 !important;
- background: transparent !important;
- width: 21px;
- height: 17px;
- overflow: hidden;
- opacity: 0;
- filter: Alpha(opacity=0);
- cursor: pointer;
-}
-
-.dataTableSearchPattern input:hover {
-
-}
-
-.dataTableSearchPattern #keyword {
- width: 114px;
- height: auto;
- overflow: visible;
- padding: 2px 6px;
- opacity: 1;
- cursor: text;
- filter: Alpha(opacity=100);
-}
-
-.dataTableNext, .dataTablePrevious {
- font-size: 12px;
- color: #184A83;
- cursor: pointer;
-}
-
-.datatableRelatedReports {
- color: #888;
- font-size: 11px;
- padding-bottom: 5px;
-}
-
-.datatableRelatedReports span {
- cursor: pointer;
- font-weight: bold;
-}
-
-/* are the following two supposed to be together? */
-.subDataTable.dataTableFeatures {
- padding-top: 0;
- padding-bottom: 5px;
-}
-
-.dataTableFeatures {
- padding-top: 10px;
- text-align: center;
-}
-
-.dataTableNext, .dataTablePrevious, .dataTableSearchPattern {
- display: none;
-}
-
-.dataTableFeatures .loadingPiwik {
- font-size: 0.9em;
-}
-
-.subDataTable .dataTableFooterIcons {
- height: 0;
-}
-
-.dataTable .loadingPiwikBelow {
- padding-bottom: 5px;
- display: block;
- text-align: center;
-}
-
-.dataTableFooterIcons {
- display: block;
- height: 20px;
- white-space: nowrap;
- font-size: 10px;
- padding: 6px 5px;
- border-top: 1px solid #B6B0A6;
-}
-
-.dataTableFooterWrap {
- position: relative;
- float: left;
-}
-
-.dataTableFooterWrap select {
- float: left;
- margin: 1px 0 1px 10px;
-}
-
-.tableIcon {
- background: #f2f1ed;
- display: inline-block;
- float: left;
- margin: 0 1px 0 0;
- padding: 2px;
- border-radius: 2px;
-}
-
-.tableIcon:hover {
- background: #e9e8e1;
-}
-
-.activeIcon {
- background: #e9e8e1;
-}
-
-.dataTableFooterActiveItem {
- position: absolute;
- top: -6px;
- left: 0;
-}
-
-.exportToFormatItems {
- background: #dcdacf;
- float: left;
- margin: 0 1px 0 0;
- padding: 4px 6px 3px 6px;
- color: #968d7f;
- border-radius: 2px;
-}
-
-.exportToFormatItems img {
- vertical-align: middle;
- margin: -4px -3px -2px 2px;
-}
-
-.tableIconsGroup {
- float: left;
- padding-right: 4px;
-}
-
-.tableIconsGroup .tableIcon span {
- margin-right: 5px;
- margin-left: 5px;
-}
-
-.tableIconsGroup img {
- vertical-align: bottom;
-}
-
-.tableIconsGroupActive {
- display: block;
- float: left;
- background: #dcdacf;
- border-radius: 2px;
-}
-
-.tableIconsGroupActive .tableIcon {
- background: none;
-}
-
-.tableIconsGroupActive .tableIcon:hover {
- background: #e9e8e1;
-}
-
-.exportToFormatIcons {
- float: left;
-}
-
-.dataTableFooterIconsShow {
- float: left;
-}
-
-.dataTableFooterIcons, .dataTableFooterIcons a {
- text-decoration: none;
- color: #255792;
-}
-
-.dataTableSpacer {
- clear: both;
-}
-
-/* Actions table */
-.dataTableActions table.dataTable tr td.labelodd {
- background-image: none;
-}
-
-/* levels higher than 4 have a default padding left */
-.actionsDataTable tr td.label {
- padding-left: 7em;
-}
-
-tr.level0 td.label {
- padding-left: 1.5em;
-}
-
-tr.level1 td.label {
- padding-left: 2.5em;
-}
-
-tr.level2 td.label {
- padding-left: 3.5em;
-}
-
-tr.level3 td.label {
- padding-left: 4.5em;
-}
-
-tr.level4 td.label {
- padding-left: 5em;
-}
-
-/* less right margins for the link image in the Pa*/
-.dataTableActions table.dataTable img.link {
- margin-right: 0.3em;
- margin-left: -0.5em;
-}
-
-tr td.label img.plusMinus {
- margin-left: -1em;
- margin-right: 3px;
-}
-
-.pk-emptyDataTable {
- padding-top: 20px;
- padding-bottom: 10px;
- text-align: center;
- font-style: italic;
-}
-
-/* Documentation */
-
-table.dataTable th .columnDocumentation {
- display: none;
- width: 165px;
- text-align: left;
- background: #f7f7f7;
- color: #444;
- font-size: 11px;
- font-weight: normal;
- border: 1px solid #e4e5e4;
- padding: 5px 10px 6px 10px;
- border-radius: 4px;
- z-index: 125;
- position: absolute;
- box-shadow: 0 0 4px #e4e5e4;
- cursor: default;
-}
-
-table.dataTable th .columnDocumentationTitle {
- background: url(../../Zeitgeist/images/help.png) no-repeat;
- line-height: 14px;
- padding: 2px 0 3px 21px;
- font-weight: bold;
-}
-
-.reportDocumentation {
- display: none;
- background: #f7f7f7;
- font-size: 12px;
- font-weight: normal;
- border: 1px solid #e4e5e4;
- margin: 0 0 10px 0;
- padding: 0;
- border-radius: 4px;
- max-width: 500px;
-}
-
-.reportDocumentation p {
- padding: 5px 10px 6px 10px;
- margin: 0;
- color: #444;
- font-size: 12px;
-}
-
-.reportDocumentationIcon {
- display: block;
- width: 16px;
- height: 16px;
- margin: 10px 0;
- background: url(../../Zeitgeist/images/help.png) no-repeat;
-}
-
-h2 .reportDocumentationIcon {
- position: absolute;
- margin: 4px 0 0 0;
- display: none;
- background: url(../../Zeitgeist/images/help_grey.png) no-repeat;
-}
-
-h2 .reportDocumentationIcon.hidden {
- background: none;
-}
-
-.helpDate {
- color: #777777;
- font-size: 11px;
- font-style: italic;
- padding: 4px;
- text-align: right;
- display: block;
-}
-
-table.dataTable .dataTableRowActions {
- position: absolute;
- display: none;
- overflow: hidden;
- margin-top: -5px;
-}
-
-*+html table.dataTable .dataTableRowActions {
- margin-top: -7px;
-}
-
-table.dataTable .dataTableRowActions a {
- display: block;
- float: left;
- padding: 6px 4px 6px 0;
- margin: 0;
-}
-
-table.dataTable .dataTableRowActions a.leftmost {
- padding-left: 4px;
-}
-
-table.dataTable .dataTableRowActions a.rightmost {
- padding-right: 8px;
-}
-
-table.dataTable .dataTableRowActions a img {
- margin: 0;
- padding: 0;
- border: 0;
- width: 20px;
- height: 17px;
-}
-
-body .ui-tooltip.rowActionTooltip {
- font-size: 11px;
- padding: 3px 5px 3px 6px;
-}
-
-.limitSelection {
- float: right;
- position: relative;
- margin-left: 5px;
- min-height: 20px;
- z-index: 1;
-}
-
-.limitSelection.hidden {
- display: none;
-}
-
-.limitSelection div {
- border: 1px solid #DFDFDF;
- border-radius: 4px;
- background: url(../../Zeitgeist/images/sort_subtable_desc_light.png) no-repeat right 2px;
- padding: 0 14px 0 4px;
- display: block;
- width: 24px;
- height: 20px;
- cursor: pointer;
-}
-
-.limitSelection.disabled div {
- opacity: 0.5;
- cursor: not-allowed;
- filter: Alpha(opacity=50);
-}
-
-.limitSelection.visible div {
- border-radius: 0 0 4px 4px;
- background-image: url(../../Zeitgeist/images/sort_subtable_asc_light.png)
-}
-
-.limitSelection ul {
- margin-top: 1px;
- overflow: visible;
- background-color: #fff;
-}
-
-.limitSelection ul li {
- cursor: pointer;
- width: 28px;
- padding: 0 10px 0 4px;
- font-size: 1.1em;
- font-weight: bold;
- height: 20px;
- margin-top: -40px;
- background-color: #fff;
- border-left: 1px solid #DFDFDF;
- border-right: 1px solid #DFDFDF;
- vertical-align: middle;
- text-align: right;
-}
-
-.limitSelection ul li.last {
- border-top: 1px solid #DFDFDF;
- border-radius: 4px 4px 0 0;
-}
-
-.limitSelection ul li:hover {
- background-color: #EBEAE6;
-}
-
-.limitSelection span {
- padding-top: 3px;
- display: inline-block;
-}
-
-.tableConfiguration {
- float: right;
- position: relative;
- margin-left: 5px;
- min-height: 20px;
- min-width: 25px;
-}
-
-a.tableConfigurationIcon {
- display: block;
- width: 30px;
- height: 22px;
- background: url(../../Zeitgeist/images/configure.png) no-repeat center 2px;
- position: absolute;
- z-index: 9;
- right: 0;
-}
-
-a.tableConfigurationIcon.highlighted {
- display: block;
- width: 30px;
- height: 22px;
- background-image: url(../../Zeitgeist/images/configure-highlight.png);
- position: absolute;
- z-index: 9;
- right: 0;
-}
-
-.tableConfiguration ul {
- overflow: visible;
- background-color: #fff;
- display: none;
- position: relative;
- z-index: 8;
- text-align: left;
-}
-
-.tableConfiguration ul.open {
- display: block;
-}
-
-.tableConfiguration ul li {
- padding: 0;
- font-size: 1.1em;
- height: 40px;
- margin-top: -80px;
- background-color: #fff;
- border-left: 1px solid #DFDFDF;
- border-right: 1px solid #DFDFDF;
- vertical-align: middle;
-}
-
-.tableConfiguration ul li.firstDummy {
- border-bottom: 1px solid #DFDFDF;
- border-radius: 0 0 4px 4px;
- height: 25px;
- cursor: default;
- margin-top: -4px;
-}
-
-.tableConfiguration ul li.first {
- margin-top: -65px;
-}
-
-.tableConfiguration ul li.last {
- border-top: 1px solid #DFDFDF;
- border-radius: 4px 4px 0 0;
-}
-
-.tableConfiguration div.configItem {
- cursor: pointer;
- padding: 5px 10px;
- line-height: 15px;
- color: #444;
-}
-
-.tableConfiguration div.configItem:hover {
- background-color: #EBEAE6;
-}
-
-.tableConfiguration div.configItem span.action {
- color: #255792;
-}
-
-table.dataTable span.cell-tooltip {
- cursor: default;
-}
-
-.dataTable .jqplot-graph {
- padding-left: 6px;
-
- > div {
- position: relative;
- }
-} \ No newline at end of file
+@dataTable-link-color: #255792;
+@dataTable-header-background: #e4e2d7;
+@dataTable-headerActive-background: #D5D3C8;
+
+@import "dataTable/_dataTable.less";
+@import "dataTable/_limitSelection.less";
+@import "dataTable/_reportDocumentation.less";
+@import "dataTable/_rowActions.less";
+@import "dataTable/_subDataTable.less";
+@import "dataTable/_tableConfiguration.less"; \ No newline at end of file
diff --git a/plugins/CoreHome/stylesheets/dataTable/_dataTable.less b/plugins/CoreHome/stylesheets/dataTable/_dataTable.less
new file mode 100644
index 0000000000..6083dd1cca
--- /dev/null
+++ b/plugins/CoreHome/stylesheets/dataTable/_dataTable.less
@@ -0,0 +1,424 @@
+/* main data table */
+.dataTable {
+ border: 0;
+ width: 100%;
+ padding: 0;
+ border-spacing: 0;
+ margin: 0;
+}
+
+table.dataTable td.label,
+table.subDataTable td.label {
+ width: 100%;
+ white-space: nowrap;
+}
+
+table.dataTable img,
+table.subDataTable img {
+ vertical-align: middle;
+}
+
+table.dataTable img {
+ border: 0;
+ margin-right: 1em;
+ margin-left: 0.5em;
+}
+
+table.dataTable tr.subDataTable {
+ cursor: pointer;
+}
+
+table.dataTable th {
+ margin: 0;
+ color: @dataTable-link-color;
+ text-align: left;
+ padding: 6px 6px 6px 12px;
+ background: @dataTable-header-background;
+ font-size: 12px;
+ font-weight: normal;
+ border-left: 1px solid #d4d0c4;
+ vertical-align: top;
+}
+
+table.dataTable th.sortable {
+ cursor: pointer;
+}
+
+table.dataTable th.columnSorted {
+ font-weight: bold;
+ padding-right: 20px;
+ background: @dataTable-headerActive-background;
+}
+
+table.dataTable td {
+ padding: 5px 5px 5px 12px;
+ background: #fff;
+ border-left: 1px solid #e7e7e7;
+ border-bottom: 1px solid #e7e7e7;
+}
+
+table.dataTable td,
+table.dataTable td a {
+ margin: 0;
+ text-decoration: none;
+ color: #444;
+}
+
+table.dataTable tr:hover > td,
+table.dataTable tr:hover > td .dataTableRowActions {
+ background-color: #FFFFF7;
+}
+
+table.dataTable tr.subDataTable:hover > td,
+table.dataTable tr.subDataTable:hover > td .dataTableRowActions {
+ background-color: #ffffcb;
+}
+
+table.dataTable tr:hover > td.cellSubDataTable
+table.dataTable tr:hover > td.cellSubDataTable .dataTableRowActions {
+ background-color: #fff;
+}
+
+td.clean {
+ background-color: #fff;
+}
+
+table.dataTable td.columneven {
+ background: #efeeec;
+}
+
+table.dataTable td.columnodd {
+ background: #f6f5f3;
+}
+
+table.dataTable td.labeleven {
+ background: #F9FAFA url(plugins/CoreHome/images/bullet2.gif) no-repeat;
+}
+
+table.dataTable td.labelodd {
+ background: #fff url(plugins/CoreHome/images/bullet1.gif) no-repeat;
+}
+
+.dataTable tr.highlight td {
+ background-color: #ECF9DD;
+ font-weight: bold;
+}
+
+table.dataTable td.label,
+table.subActionsDataTable td.label,
+table.actionsDataTable td.label {
+ border-top: 0;
+ border-left: 0;
+}
+
+table.dataTable th.label {
+ border-left: 0;
+}
+
+.dataTableActions table.dataTable th.label {
+ /* Ensures tables have enough space to display subtable on click, and prevent the jumping effect */
+ min-width: 250px;
+}
+
+table.dataTable span.label.highlighted {
+ font-style: italic;
+}
+
+/* the cell containing the subdatatable */
+table.dataTable .cellSubDataTable {
+ margin: 0;
+ border-left: 0;
+ padding: 12px 12px 0;
+}
+
+/* A link in a column in the DataTable */
+table.dataTable td #urlLink {
+ display: none;
+}
+
+table.dataTable img {
+ margin-left: 0;
+}
+
+.dataTable > .dataTableWrapper {
+ width: 450px;
+}
+
+.subDataTable > .dataTableWrapper {
+ width: 95%;
+}
+
+.sortIconContainer {
+ float: right;
+ position: relative;
+}
+
+.sortIcon {
+ margin: 0;
+ position: absolute;
+}
+
+.datatableFooterMessage {
+ color: #888;
+ text-align: left;
+ margin: 10px;
+}
+
+.dataTablePages {
+ color: #BFBFBF;
+ font-weight: bold;
+ margin: 10px;
+ font-size: 12px;
+}
+
+.dataTableSearchPattern {
+ margin: 5px 0 2px 0;
+ height: 20px;
+ display: block;
+ white-space: nowrap;
+ background: url(plugins/Zeitgeist/images/search_bg.png) no-repeat center 0;
+ text-align: center;
+}
+
+.dataTableSearchPattern input {
+ vertical-align: top;
+ font-size: 10px;
+ color: #454545;
+ border: 0;
+ background: transparent;
+ width: 21px;
+ height: 17px;
+ overflow: hidden;
+ opacity: 0;
+ filter: Alpha(opacity=0);
+ cursor: pointer;
+}
+
+.dataTableSearchPattern .searchInput {
+ width: 114px;
+ height: auto;
+ overflow: visible;
+ padding: 2px 6px;
+ opacity: 1;
+ cursor: text;
+ filter: Alpha(opacity=100);
+}
+
+.dataTableNext,
+.dataTablePrevious {
+ font-size: 12px;
+ color: #184A83;
+ cursor: pointer;
+}
+
+.datatableRelatedReports {
+ color: #888;
+ font-size: 11px;
+ padding-bottom: 5px;
+}
+
+.datatableRelatedReports span {
+ cursor: pointer;
+ font-weight: bold;
+}
+
+.dataTableFeatures {
+ text-align: center;
+}
+
+.dataTableFooterNavigation {
+ padding: 5px 0;
+}
+
+.dataTableNext,
+.dataTablePrevious,
+.dataTableSearchPattern {
+ display: none;
+}
+
+.dataTableFeatures .loadingPiwik {
+ font-size: 0.9em;
+}
+
+.subDataTable .dataTableFooterIcons {
+ height: 0;
+}
+
+.dataTable .loadingPiwikBelow {
+ padding-bottom: 5px;
+ display: block;
+ text-align: center;
+}
+
+.dataTableFooterIcons {
+ display: block;
+ height: 20px;
+ white-space: nowrap;
+ font-size: 10px;
+ padding: 6px 5px;
+ border-top: 1px solid #B6B0A6;
+}
+
+.dataTableFooterWrap {
+ position: relative;
+ float: left;
+}
+
+.dataTableFooterWrap select {
+ float: left;
+ margin: 1px 0 1px 10px;
+}
+
+.tableIcon {
+ background: #f2f1ed;
+ display: inline-block;
+ float: left;
+ margin: 0 1px 0 0;
+ padding: 2px;
+ border-radius: 2px;
+}
+
+.tableIcon:hover {
+ background: #e9e8e1;
+}
+
+.activeIcon {
+ background: #e9e8e1;
+}
+
+.dataTableFooterActiveItem {
+ position: absolute;
+ top: -6px;
+ left: 0;
+}
+
+.exportToFormatItems {
+ background: #dcdacf;
+ float: left;
+ margin: 0 1px 0 0;
+ padding: 4px 6px 3px 6px;
+ color: #968d7f;
+ border-radius: 2px;
+}
+
+.exportToFormatItems img {
+ vertical-align: middle;
+ margin: -4px -3px -2px 2px;
+}
+
+.tableIconsGroup {
+ float: left;
+ padding-right: 4px;
+}
+
+.tableIconsGroup .tableIcon span {
+ margin-right: 5px;
+ margin-left: 5px;
+}
+
+.tableIconsGroup img {
+ vertical-align: bottom;
+}
+
+.tableIconsGroupActive {
+ display: block;
+ float: left;
+ background: #dcdacf;
+ border-radius: 2px;
+}
+
+.tableIconsGroupActive .tableIcon {
+ background: none;
+}
+
+.tableIconsGroupActive .tableIcon:hover {
+ background: #e9e8e1;
+}
+
+.exportToFormatIcons,
+.dataTableFooterIconsShow {
+ float: left;
+}
+
+.dataTableFooterIcons,
+.dataTableFooterIcons a {
+ text-decoration: none;
+ color: @dataTable-link-color;
+}
+
+.dataTableSpacer {
+ clear: both;
+}
+
+/* Actions table */
+.dataTableActions table.dataTable tr td.labelodd {
+ background-image: none;
+}
+
+/* levels higher than 4 have a default padding left */
+.actionsDataTable tr td.label {
+ padding-left: 7em;
+}
+
+tr.level0 td.label {
+ padding-left: 1.5em;
+}
+
+tr.level1 td.label {
+ padding-left: 2.5em;
+}
+
+tr.level2 td.label {
+ padding-left: 3.5em;
+}
+
+tr.level3 td.label {
+ padding-left: 4.5em;
+}
+
+tr.level4 td.label {
+ padding-left: 5em;
+}
+
+/* less right margins for the link image in the Pa*/
+.dataTableActions table.dataTable img.link {
+ margin-right: 0.3em;
+ margin-left: -0.5em;
+}
+
+tr td.label img.plusMinus {
+ margin-left: -1em;
+ margin-right: 3px;
+}
+
+.pk-emptyDataTable {
+ padding-top: 20px;
+ padding-bottom: 10px;
+ text-align: center;
+ font-style: italic;
+}
+
+.helpDate {
+ color: #777777;
+ font-size: 11px;
+ font-style: italic;
+ padding: 4px;
+ text-align: right;
+ display: block;
+}
+
+body .ui-tooltip.rowActionTooltip {
+ font-size: 11px;
+ padding: 3px 5px 3px 6px;
+}
+
+table.dataTable span.cell-tooltip {
+ cursor: default;
+}
+
+.dataTable .jqplot-graph {
+ padding-left: 6px;
+ > div {
+ position: relative;
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/stylesheets/dataTable/_limitSelection.less b/plugins/CoreHome/stylesheets/dataTable/_limitSelection.less
new file mode 100644
index 0000000000..6d899d89ef
--- /dev/null
+++ b/plugins/CoreHome/stylesheets/dataTable/_limitSelection.less
@@ -0,0 +1,68 @@
+.limitSelection {
+ float: right;
+ position: relative;
+ margin-left: 5px;
+ min-height: 20px;
+ z-index: 1;
+}
+
+.limitSelection.hidden {
+ display: none;
+}
+
+.limitSelection > div {
+ border: 1px solid #DFDFDF;
+ border-radius: 4px;
+ background: url(plugins/Zeitgeist/images/sort_subtable_desc_light.png) no-repeat right 2px;
+ padding: 0 14px 0 4px;
+ display: block;
+ width: 24px;
+ height: 20px;
+ cursor: pointer;
+}
+
+.limitSelection.disabled > div {
+ opacity: 0.5;
+ cursor: not-allowed;
+ filter: Alpha(opacity=50);
+}
+
+.limitSelection.visible > div {
+ border-radius: 0 0 4px 4px;
+ background-image: url(plugins/Zeitgeist/images/sort_subtable_asc_light.png)
+}
+
+.limitSelection > ul {
+ margin-top: 1px;
+ overflow: visible;
+ background-color: #fff;
+}
+
+.limitSelection > ul > li {
+ cursor: pointer;
+ width: 28px;
+ padding: 0 10px 0 4px;
+ font-size: 1.1em;
+ font-weight: bold;
+ height: 20px;
+ margin-top: -40px;
+ background-color: #fff;
+ border-left: 1px solid #DFDFDF;
+ border-right: 1px solid #DFDFDF;
+ vertical-align: middle;
+ text-align: right;
+}
+
+.limitSelection > ul > li.last {
+ border-top: 1px solid #DFDFDF;
+ border-radius: 4px 4px 0 0;
+}
+
+.limitSelection > ul > li:hover {
+ background-color: #EBEAE6;
+}
+
+.limitSelection span {
+ padding-top: 3px;
+ display: inline-block;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/stylesheets/dataTable/_reportDocumentation.less b/plugins/CoreHome/stylesheets/dataTable/_reportDocumentation.less
new file mode 100644
index 0000000000..1661ddb5ec
--- /dev/null
+++ b/plugins/CoreHome/stylesheets/dataTable/_reportDocumentation.less
@@ -0,0 +1,62 @@
+/* Documentation */
+table.dataTable th .columnDocumentation {
+ display: none;
+ width: 165px;
+ text-align: left;
+ background: #f7f7f7;
+ color: #444;
+ font-size: 11px;
+ font-weight: normal;
+ border: 1px solid #e4e5e4;
+ padding: 5px 10px 6px 10px;
+ border-radius: 4px;
+ z-index: 125;
+ position: absolute;
+ box-shadow: 0 0 4px #e4e5e4;
+ cursor: default;
+}
+
+table.dataTable th .columnDocumentationTitle {
+ background: url(plugins/Zeitgeist/images/help.png) no-repeat;
+ line-height: 14px;
+ padding: 2px 0 3px 21px;
+ font-weight: bold;
+}
+
+.reportDocumentation {
+ display: none;
+ background: #f7f7f7;
+ font-size: 12px;
+ font-weight: normal;
+ border: 1px solid #e4e5e4;
+ margin: 0 0 10px 0;
+ padding: 0;
+ border-radius: 4px;
+ max-width: 500px;
+}
+
+.reportDocumentation p {
+ padding: 5px 10px 6px 10px;
+ margin: 0;
+ color: #444;
+ font-size: 12px;
+}
+
+.reportDocumentationIcon {
+ display: block;
+ width: 16px;
+ height: 16px;
+ margin: 10px 0;
+ background: url(plugins/Zeitgeist/images/help.png) no-repeat;
+}
+
+h2 .reportDocumentationIcon {
+ position: absolute;
+ margin: 4px 0 0 0;
+ display: none;
+ background: url(plugins/Zeitgeist/images/help_grey.png) no-repeat;
+}
+
+h2 .reportDocumentationIcon.hidden {
+ background: none;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/stylesheets/dataTable/_rowActions.less b/plugins/CoreHome/stylesheets/dataTable/_rowActions.less
new file mode 100644
index 0000000000..55f9876e4c
--- /dev/null
+++ b/plugins/CoreHome/stylesheets/dataTable/_rowActions.less
@@ -0,0 +1,35 @@
+
+
+table.dataTable .dataTableRowActions {
+ position: absolute;
+ display: none;
+ overflow: hidden;
+ margin-top: -5px;
+}
+
+*+html table.dataTable .dataTableRowActions {
+ margin-top: -7px;
+}
+
+table.dataTable .dataTableRowActions a {
+ display: block;
+ float: left;
+ padding: 6px 4px 6px 0;
+ margin: 0;
+}
+
+table.dataTable .dataTableRowActions a.leftmost {
+ padding-left: 4px;
+}
+
+table.dataTable .dataTableRowActions a.rightmost {
+ padding-right: 8px;
+}
+
+table.dataTable .dataTableRowActions a img {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ width: 20px;
+ height: 17px;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/stylesheets/dataTable/_subDataTable.less b/plugins/CoreHome/stylesheets/dataTable/_subDataTable.less
new file mode 100644
index 0000000000..7e540c2b62
--- /dev/null
+++ b/plugins/CoreHome/stylesheets/dataTable/_subDataTable.less
@@ -0,0 +1,46 @@
+/* SUBDATATABLE */
+/* a datatable inside another datatable */
+table.subDataTable td {
+ border: 0;
+}
+
+table.subDataTable thead th {
+ font-weight: normal;
+ font-size: 12px;
+ text-align: left;
+ padding: .3em 1em;
+ border: 0;
+ border-top: 1px solid #e7e7e7;
+ border-bottom: 1px solid #e7e7e7;
+}
+
+table.subDataTable td.labeleven, table.subDataTable td.labelodd {
+ background-image: none;
+}
+
+table.subDataTable td {
+ border-bottom: 1px solid #e7e7e7;
+ border-left: 0;
+}
+
+table.subDataTable td, table.subDataTable td a {
+ color: #615B53;
+}
+
+table.subDataTable td.labeleven, table.subDataTable td.columneven {
+ color: #2D2A27;
+}
+
+table.subDataTable td.label {
+ width: 80%;
+}
+
+table.subDataTable td.label {
+ padding: 5px;
+}
+
+/* are the following two supposed to be together? */
+.subDataTable.dataTableFeatures {
+ padding-top: 0;
+ padding-bottom: 5px;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/stylesheets/dataTable/_tableConfiguration.less b/plugins/CoreHome/stylesheets/dataTable/_tableConfiguration.less
new file mode 100644
index 0000000000..fff7c3d1bf
--- /dev/null
+++ b/plugins/CoreHome/stylesheets/dataTable/_tableConfiguration.less
@@ -0,0 +1,82 @@
+.tableConfiguration {
+ float: right;
+ position: relative;
+ margin-left: 5px;
+ min-height: 20px;
+ min-width: 25px;
+}
+
+a.tableConfigurationIcon {
+ display: block;
+ width: 30px;
+ height: 22px;
+ background: url(plugins/Zeitgeist/images/configure.png) no-repeat center 2px;
+ position: absolute;
+ z-index: 9;
+ right: 0;
+}
+
+a.tableConfigurationIcon.highlighted {
+ display: block;
+ width: 30px;
+ height: 22px;
+ background-image: url(plugins/Zeitgeist/images/configure-highlight.png);
+ position: absolute;
+ z-index: 9;
+ right: 0;
+}
+
+.tableConfiguration ul {
+ overflow: visible;
+ display: none;
+ position: relative;
+ z-index: 8;
+ text-align: left;
+}
+
+.tableConfiguration ul.open {
+ display: block;
+}
+
+.tableConfiguration ul li {
+ padding: 0;
+ font-size: 1.1em;
+ height: 40px;
+ margin-top: -80px;
+ background-color: #fff;
+ border: 1px solid #DFDFDF;
+ border-width: 0 1px;
+ vertical-align: middle;
+}
+
+.tableConfiguration ul li.firstDummy {
+ border-bottom-width: 1px;
+ border-radius: 0 0 4px 4px;
+ height: 25px;
+ cursor: default;
+ margin-top: -4px;
+}
+
+.tableConfiguration ul li.first {
+ margin-top: -65px;
+}
+
+.tableConfiguration ul li.last {
+ border-top-width: 1px;
+ border-radius: 4px 4px 0 0;
+}
+
+.tableConfiguration div.configItem {
+ cursor: pointer;
+ padding: 5px 10px;
+ line-height: 15px;
+ color: #444;
+}
+
+.tableConfiguration div.configItem:hover {
+ background-color: #EBEAE6;
+}
+
+.tableConfiguration div.configItem span.action {
+ color: @dataTable-link-color;
+} \ No newline at end of file
diff --git a/plugins/Zeitgeist/stylesheets/ui/_jqplot.less b/plugins/CoreHome/stylesheets/jqplotColors.less
index b8f47543d2..01dd9b8444 100644
--- a/plugins/Zeitgeist/stylesheets/ui/_jqplot.less
+++ b/plugins/CoreHome/stylesheets/jqplotColors.less
@@ -1,4 +1,12 @@
// evolution graph colors
+.evolution-graph-colors[data-name=grid-background] {
+ color: #fff;
+}
+
+.evolution-graph-colors[data-name=grid-border] {
+ color: #f00;
+}
+
.evolution-graph-colors[data-name=series1] {
color: #5170AE;
}
@@ -31,14 +39,6 @@
color: #49C100;
}
-.evolution-graph-colors[data-name=grid-background] {
- color: #fff;
-}
-
-.evolution-graph-colors[data-name=grid-border] {
- color: #f00;
-}
-
.evolution-graph-colors[data-name=ticks] {
color: #ccc;
}
@@ -48,6 +48,14 @@
}
// bar graph colors
+.bar-graph-colors[data-name=grid-background] {
+ color: #fff;
+}
+
+.bar-graph-colors[data-name=grid-border] {
+ color: #f00;
+}
+
.bar-graph-colors[data-name=series1] {
color: #5170AE;
}
@@ -80,14 +88,6 @@
color: #49C100;
}
-.bar-graph-colors[data-name=grid-background] {
- color: #fff;
-}
-
-.bar-graph-colors[data-name=grid-border] {
- color: #f00;
-}
-
.bar-graph-colors[data-name=ticks] {
color: #ccc;
}
@@ -97,6 +97,14 @@
}
// pie graph colors
+.pie-graph-colors[data-name=grid-background] {
+ color: #fff;
+}
+
+.pie-graph-colors[data-name=grid-border] {
+ color: #f00;
+}
+
.pie-graph-colors[data-name=series1] {
color: #59727F;
}
@@ -133,14 +141,6 @@
color: #A5A5A5;
}
-.pie-graph-colors[data-name=grid-background] {
- color: #fff;
-}
-
-.pie-graph-colors[data-name=grid-border] {
- color: #f00;
-}
-
.pie-graph-colors[data-name=ticks] {
color: #ccc;
}
diff --git a/plugins/CoreHome/stylesheets/menu.less b/plugins/CoreHome/stylesheets/menu.less
index 2bd0f491c5..87705376a6 100644
--- a/plugins/CoreHome/stylesheets/menu.less
+++ b/plugins/CoreHome/stylesheets/menu.less
@@ -31,7 +31,7 @@
font-size: 18px;
display: block;
float: left;
- padding: 8px 27px 0 27px;
+ padding: 8px 27px 0;
height: 25px;
text-decoration: none;
font-weight: normal;
@@ -91,7 +91,7 @@
/* LEVEL2 HOVER */
.nav_tab > li.sfHover > ul,
.nav_tab > li:hover > ul {
- z-index: 50;
+ z-index: 1;
top: 100%;
opacity: 1;
-webkit-transition: opacity 300ms ease-out 10ms; /* property duration timing-function delay */
diff --git a/plugins/Zeitgeist/stylesheets/ui/_sparkline.less b/plugins/CoreHome/stylesheets/sparklineColors.less
index 7d2b9c7c8b..9eef3ff955 100644
--- a/plugins/Zeitgeist/stylesheets/ui/_sparkline.less
+++ b/plugins/CoreHome/stylesheets/sparklineColors.less
@@ -9,18 +9,22 @@ div.sparkline:hover {
}
// sparkline colors
+.sparkline-colors[data-name=backgroundColor] {
+ color: white;
+}
+
.sparkline-colors[data-name=lineColor] {
color: rgb(22, 44, 74);
}
-.sparkline-colors[data-name=red] {
+.sparkline-colors[data-name=minPointColor] {
color: #ff7f7f;
}
-.sparkline-colors[data-name=blue] {
+.sparkline-colors[data-name=lastPointColor] {
color: #55AAFF;
}
-.sparkline-colors[data-name=green] {
+.sparkline-colors[data-name=maxPointColor] {
color: #75BF7C;
}
diff --git a/plugins/CoreHome/templates/_dataTable.twig b/plugins/CoreHome/templates/_dataTable.twig
index 4e12cac5a4..5b04fdf9f7 100644
--- a/plugins/CoreHome/templates/_dataTable.twig
+++ b/plugins/CoreHome/templates/_dataTable.twig
@@ -1,8 +1,9 @@
{% set summaryRowId = constant('Piwik\\DataTable::ID_SUMMARY_ROW') %}{# ID_SUMMARY_ROW #}
{% set isSubtable = javascriptVariablesToSet.idSubtable is defined and javascriptVariablesToSet.idSubtable != 0 %}
-<div class="dataTable {{ properties.datatable_css_class }} {% if isSubtable %}subDataTable{% endif %}"
+<div class="dataTable {{ visualizationCssClass }} {{ properties.datatable_css_class|default('') }} {% if isSubtable %}subDataTable{% endif %}"
data-table-type="{{ properties.datatable_js_type|default('dataTable') }}"
data-report="{{ properties.report_id }}"
+ data-props="{{ clientSidePropertiesToSet|json_encode }}"
data-params="{{ javascriptVariablesToSet|json_encode }}">
<div class="reportDocumentation">
{% if properties.documentation|default is not empty %}<p>{{ properties.documentation|raw }}</p>{% endif %}
diff --git a/plugins/CoreHome/templates/_dataTableActions_subDataTable.twig b/plugins/CoreHome/templates/_dataTableActions_subDataTable.twig
index 72bf6607c1..696c4a5a72 100644
--- a/plugins/CoreHome/templates/_dataTableActions_subDataTable.twig
+++ b/plugins/CoreHome/templates/_dataTableActions_subDataTable.twig
@@ -1,14 +1,14 @@
{% if error is defined %}
{{ error.message }}
{% else %}
- {% if (dataTable is empty or dataTable.getRowsCount() == 0) and not properties.show_expanded|default(false) %}
+ {% if (dataTable is empty or dataTable.getRowsCount() == 0) and not properties.visualization_properties.show_expanded|default(false) %}
<tr>
<td colspan="{{ properties.columns_to_display|length }}">{{ 'CoreHome_CategoryNoData'|translate }}</td>
</tr>
{% else %}
{% for row in dataTable.getRows() %}
{# display this row if it doesn't have a subtable or if we don't replace the row with the subtable #}
- {% if not row.getIdSubDataTable() or not properties.show_expanded|default(false) or not properties.replace_row_with_subtable|default(false) %}
+ {% if not row.getIdSubDataTable() or not properties.visualization_properties.show_expanded|default(false) or not properties.replace_row_with_subtable|default(false) %}
<tr {% if row.getIdSubDataTable() %}id="{{ row.getIdSubDataTable() }}"{% endif %}
class="{{ row.getMetadata('css_class') }} {% if row.getIdSubDataTable() %}subDataTable{% endif %}">
{% for column in properties.columns_to_display %}
@@ -20,8 +20,8 @@
{% endif %}
{# display subtable if present and showing expanded datatable #}
- {% if properties.show_expanded|default(false) and row.getIdSubDataTable() %}
- {% include properties.subtable_template|default("@CoreHome/_dataTable.twig") with {'dataTable': row.getSubtable()} %}
+ {% if properties.visualization_properties.show_expanded|default(false) and row.getIdSubDataTable() %}
+ {% include properties.visualization_properties.subtable_template|default("@CoreHome/_dataTable.twig") with {'dataTable': row.getSubtable()} %}
{% endif %}
{% endfor %}
{% endif %}
diff --git a/plugins/CoreHome/templates/_dataTableFooter.twig b/plugins/CoreHome/templates/_dataTableFooter.twig
index 5a74cf4a74..44b776b31d 100644
--- a/plugins/CoreHome/templates/_dataTableFooter.twig
+++ b/plugins/CoreHome/templates/_dataTableFooter.twig
@@ -1,24 +1,26 @@
<div class="dataTableFeatures">
- {% if properties.show_offset_information %}
- <span>
- <span class="dataTablePages"></span>
- </span>
- {% endif %}
+ <div class="dataTableFooterNavigation">
+ {% if properties.show_offset_information %}
+ <span>
+ <span class="dataTablePages"></span>
+ </span>
+ {% endif %}
- {% if properties.show_pagination_control %}
- <span>
- <span class="dataTablePrevious">&lsaquo; {% if javascriptVariablesToSet.dataTablePreviousIsFirst is defined %}{{ 'General_First'|translate }}{% else %}{{ 'General_Previous'|translate }}{% endif %} </span>
- <span class="dataTableNext">{{ 'General_Next'|translate }} &rsaquo;</span>
- </span>
- {% endif %}
+ {% if properties.show_pagination_control %}
+ <span>
+ <span class="dataTablePrevious">&lsaquo; {% if javascriptVariablesToSet.dataTablePreviousIsFirst is defined %}{{ 'General_First'|translate }}{% else %}{{ 'General_Previous'|translate }}{% endif %} </span>
+ <span class="dataTableNext">{{ 'General_Next'|translate }} &rsaquo;</span>
+ </span>
+ {% endif %}
- {% if properties.show_search %}
- <span class="dataTableSearchPattern">
- <input id="keyword" type="text" length="15" />
- <input type="submit" value="{{ 'General_Search'|translate }}" />
- </span>
- {% endif %}
+ {% if properties.show_search %}
+ <span class="dataTableSearchPattern">
+ <input type="text" class="searchInput" length="15" />
+ <input type="submit" value="{{ 'General_Search'|translate }}" />
+ </span>
+ {% endif %}
+ </div>
<span class="loadingPiwik" style='display:none'><img src="plugins/Zeitgeist/images/loading-blue.gif"/> {{ 'General_LoadingData'|translate }}</span>
{% if properties.show_footer_icons %}
@@ -75,6 +77,13 @@
<img width="16" height="16" src="plugins/Zeitgeist/images/tagcloud.png" title="{{ 'General_TagCloud'|translate }}"/>
</a>
{% endif %}
+ {% if properties.show_non_core_visualizations %}
+ {% for format, info in nonCoreVisualizations %}
+ <a class="tableIcon" format="{{ format }}" var="{{ format }}">
+ <img width="16" height="16" src="{{ info.table_icon }}" title="{{ info.title|translate }}"/>
+ </a>
+ {% endfor %}
+ {% endif %}
</span>
</div>
{% endif %}
@@ -86,14 +95,14 @@
</span>
<span class="exportToFormatItems" style="display:none">
{{ 'General_Export'|translate }}:
- <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="CSV" filter_limit="{{ properties.exportLimit }}">CSV</a> |
- <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="TSV" filter_limit="{{ properties.exportLimit }}">TSV (Excel)</a> |
- <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="XML" filter_limit="{{ properties.exportLimit }}">XML</a> |
- <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="JSON" filter_limit="{{ properties.exportLimit }}">Json</a> |
- <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="PHP" filter_limit="{{ properties.exportLimit }}">Php</a>
+ <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="CSV" filter_limit="{{ properties.export_limit }}">CSV</a> |
+ <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="TSV" filter_limit="{{ properties.export_limit }}">TSV (Excel)</a> |
+ <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="XML" filter_limit="{{ properties.export_limit }}">XML</a> |
+ <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="JSON" filter_limit="{{ properties.export_limit }}">Json</a> |
+ <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="PHP" filter_limit="{{ properties.export_limit }}">Php</a>
{% if properties.show_export_as_rss_feed %}
|
- <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="RSS" filter_limit="{{ properties.exportLimit }}" date="last10">
+ <a target="_blank" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="RSS" filter_limit="{{ properties.export_limit }}" date="last10">
<img border="0" src="plugins/Zeitgeist/images/feed.png"/>
</a>
{% endif %}
@@ -128,7 +137,7 @@
{% endif %}
</ul>
</div>
- {% if not properties.hide_annotations_view %}
+ {% if isPluginLoaded('Annotations') and not properties.hide_annotations_view %}
<div class="annotationView" title="{{ 'Annotations_IconDesc_js'|translate }}">
<a class="tableIcon">
<img width="16" height="16" src="plugins/Zeitgeist/images/grey_marker.png"/>
@@ -140,16 +149,16 @@
{% endif %}
<div class="datatableRelatedReports">
- {% if (properties.relatedReports is not empty) and properties.show_related_reports %}
- {% if properties.relatedReports|length == 1 %}
+ {% if (properties.related_reports is not empty) and properties.show_related_reports %}
+ {% if properties.related_reports|length == 1 %}
{{ 'General_RelatedReport'|translate }}:
{% else %}
{{ 'General_RelatedReports'|translate }}:
{% endif %}
- <ul style="list-style:none;{% if properties.relatedReports|length == 1 %}display:inline-block;{% endif %}}">
+ <ul style="list-style:none;{% if properties.related_reports|length == 1 %}display:inline-block;{% endif %}}">
<li><span href="{{ properties.self_url }}" style="display:none;">{{ properties.title }}</span></li>
- {% for reportUrl,reportTitle in properties.relatedReports %}
+ {% for reportUrl,reportTitle in properties.related_reports %}
<li><span href="{{ reportUrl }}">{{ reportTitle }}</span></li>
{% endfor %}
</ul>
diff --git a/plugins/CoreHome/templates/_dataTableViz_jqplotGraph.twig b/plugins/CoreHome/templates/_dataTableViz_jqplotGraph.twig
deleted file mode 100644
index 65e9f7a43c..0000000000
--- a/plugins/CoreHome/templates/_dataTableViz_jqplotGraph.twig
+++ /dev/null
@@ -1,10 +0,0 @@
-<div class="jqplot-graph">
- <div class="piwik-graph"
- style="width: {{ properties.graph_width }}; height: {{ properties.graph_height }};"
- data-data="{{ data|e('html') }}"
- {% if properties.external_series_toggle is defined and properties.external_series_toggle %}
- data-external-series-toggle="{{ properties.external_series_toggle }}"
- data-external-series-show-all="{% if properties.external_series_toggle_show_all %}1{% else %}0{% endif %}"
- {% endif %}>
- </div>
-</div> \ No newline at end of file
diff --git a/plugins/CoreHome/templates/_siteSelect.twig b/plugins/CoreHome/templates/_siteSelect.twig
index e78b93b0bd..7d3072cddc 100644
--- a/plugins/CoreHome/templates/_siteSelect.twig
+++ b/plugins/CoreHome/templates/_siteSelect.twig
@@ -24,12 +24,13 @@
</a>
</div>
{% endset %}
-<div class="sites_autocomplete" {% if siteSelectorId is defined %}id="{{ siteSelectorId }}"{% endif %}
+<div class="sites_autocomplete {% if sites|length > 1 %}sites_autocomplete--dropdown{% endif %}"
+ {% if siteSelectorId is defined %}id="{{ siteSelectorId }}"{% endif %}
{% if switchSiteOnSelect is not defined or switchSiteOnSelect %}data-switch-site-on-select="1"{% endif %}>
<div class="custom_select">
<a href="#" onclick="return false" class="custom_select_main_link" siteid="{% if idSite is defined %}{{ idSite }}{% else %}{{ sites[0].idsite }}{% endif %}">
- {% if siteName is defined %}{{ siteName|raw }}{% else %}{{ sites[0].name|raw }}{% endif %}
+ <span>{% if siteName is defined %}{{ siteName|raw }}{% else %}{{ sites[0].name|raw }}{% endif %}</span>
</a>
<div class="custom_select_block">
diff --git a/plugins/CoreHome/templates/_siteSelectHeader.twig b/plugins/CoreHome/templates/_siteSelectHeader.twig
new file mode 100644
index 0000000000..a4ab4cf8a0
--- /dev/null
+++ b/plugins/CoreHome/templates/_siteSelectHeader.twig
@@ -0,0 +1,4 @@
+<div class="top_bar_sites_selector">
+ <label>{{ 'General_Website'|translate }}</label>
+ {% include "@CoreHome/_siteSelect.twig" %}
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/templates/_topBarHelloMenu.twig b/plugins/CoreHome/templates/_topBarHelloMenu.twig
index 34503d12bf..7fb0aadb81 100644
--- a/plugins/CoreHome/templates/_topBarHelloMenu.twig
+++ b/plugins/CoreHome/templates/_topBarHelloMenu.twig
@@ -8,7 +8,12 @@
{% endset %}
<span class="topBarElem">{{ 'General_HelloUser'|translate(helloAlias)|raw }}</span>
{% if userLogin != 'anonymous' %}
- | <span class="topBarElem"><a href='index.php?module=CoreAdminHome'>{{ 'General_Settings'|translate }}</a></span>
+ |
+ {% if isAdminLayout is defined %}
+ <span class="topBarElem topBarElemActive">{{ 'General_Settings'|translate }}</span>
+ {% else %}
+ <span class="topBarElem"><a href='index.php?module=CoreAdminHome'>{{ 'General_Settings'|translate }}</a></span>
+ {% endif %}
{% endif %}
| <span class="topBarElem">
{% if userLogin == 'anonymous' %}
diff --git a/plugins/CoreHome/templates/_topBarTopMenu.twig b/plugins/CoreHome/templates/_topBarTopMenu.twig
index 29330720a0..6e7992e7ac 100644
--- a/plugins/CoreHome/templates/_topBarTopMenu.twig
+++ b/plugins/CoreHome/templates/_topBarTopMenu.twig
@@ -3,7 +3,7 @@
{% if menu._html is defined %}
{{ menu._html|raw }}
{% elseif (menu._url.module == currentModule and (menu._url.action is empty or menu._url.action == currentAction)) %}
- <span class="topBarElem"><b>{{ label|translate }}</b></span> |
+ <span class="topBarElem topBarElemActive"><b>{{ label|translate }}</b></span> |
{% else %}
<span class="topBarElem" {% if menu._tooltip is defined %}title="{{ menu._tooltip }}"{% endif %}>
<a id="topmenu-{{ menu._url.module|lower }}" href="index.php{{ menu._url|urlRewriteWithParameters }}">{{ label|translate }}</a>
diff --git a/plugins/CoreHome/templates/getDefaultIndexView.twig b/plugins/CoreHome/templates/getDefaultIndexView.twig
index 0fe04f26de..b9d26c3a7c 100644
--- a/plugins/CoreHome/templates/getDefaultIndexView.twig
+++ b/plugins/CoreHome/templates/getDefaultIndexView.twig
@@ -2,10 +2,7 @@
{% block content %}
-<div class="top_bar_sites_selector">
- <label>{{ 'General_Website'|translate }}</label>
- {% include "@CoreHome/_siteSelect.twig" %}
-</div>
+{% include "@CoreHome/_siteSelectHeader.twig" %}
{% if (menu is defined and menu) %}
{% include "@CoreHome/_menu.twig" %}
diff --git a/plugins/CoreHome/templates/getMultiRowEvolutionPopover.twig b/plugins/CoreHome/templates/getMultiRowEvolutionPopover.twig
index 16ef990aa6..c0a043aac8 100644
--- a/plugins/CoreHome/templates/getMultiRowEvolutionPopover.twig
+++ b/plugins/CoreHome/templates/getMultiRowEvolutionPopover.twig
@@ -1,4 +1,4 @@
-{% set seriesColorCount = constant("Evolution::SERIES_COLOR_COUNT") %}
+{% set seriesColorCount = constant("Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph\\Evolution::SERIES_COLOR_COUNT") %}
<div class="rowevolution multirowevolution">
<div class="popover-title">{{ 'RowEvolution_MultiRowEvolutionTitle'|translate }}</div>
<div class="graph">
diff --git a/plugins/CoreHome/templates/getRowEvolutionPopover.twig b/plugins/CoreHome/templates/getRowEvolutionPopover.twig
index fab9fb2437..74b6cbbfe4 100644
--- a/plugins/CoreHome/templates/getRowEvolutionPopover.twig
+++ b/plugins/CoreHome/templates/getRowEvolutionPopover.twig
@@ -1,4 +1,4 @@
-{% set seriesColorCount = constant("Evolution::SERIES_COLOR_COUNT") %}
+{% set seriesColorCount = constant("Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph\\Evolution::SERIES_COLOR_COUNT") %}
<div class="rowevolution">
<div class="popover-title">{{ popoverTitle | raw }}</div>
<div class="graph">
diff --git a/plugins/CoreUpdater/Controller.php b/plugins/CoreUpdater/Controller.php
index 7cb89e9e30..d829734ae3 100644
--- a/plugins/CoreUpdater/Controller.php
+++ b/plugins/CoreUpdater/Controller.php
@@ -354,7 +354,7 @@ class Controller extends \Piwik\Controller
foreach ($componentsWithUpdateFile as $name => $filenames) {
try {
$this->warningMessages = array_merge($this->warningMessages, $updater->update($name));
- } catch (Updater_UpdateErrorException $e) {
+ } catch (\Piwik\Updater_UpdateErrorException $e) {
$this->errorMessages[] = $e->getMessage();
if ($name == 'core') {
$this->coreError = true;
diff --git a/plugins/CoreUpdater/templates/layout.twig b/plugins/CoreUpdater/templates/layout.twig
index 23aee27884..cf6dd9ae2b 100644
--- a/plugins/CoreUpdater/templates/layout.twig
+++ b/plugins/CoreUpdater/templates/layout.twig
@@ -3,7 +3,8 @@
<head>
<meta charset="utf-8">
<title>Piwik &rsaquo; {{ 'CoreUpdater_UpdateTitle'|translate }}</title>
- <link rel="shortcut icon" href="plugins/CoreHome/images/favicon.ico"/>
+ <meta http-equiv="X-UA-Compatible" content="IE=EDGE,chrome=1"/>
+ <meta name="viewport" content="initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="libs/jquery/themes/base/jquery-ui.css"/>
<link rel="stylesheet" type="text/css" href="plugins/Zeitgeist/stylesheets/base.css" />
@@ -19,6 +20,8 @@
<link rel="stylesheet" type="text/css" href="plugins/Zeitgeist/stylesheets/rtl.css"/>
{% endif %}
{{ loadJavascriptTranslations(['CoreHome'])|raw }}
+
+ <link rel="shortcut icon" href="plugins/CoreHome/images/favicon.ico"/>
</head>
<body id="simple">
<div id="contentsimple">
diff --git a/plugins/CoreVisualizations/CoreVisualizations.php b/plugins/CoreVisualizations/CoreVisualizations.php
new file mode 100644
index 0000000000..00330377a2
--- /dev/null
+++ b/plugins/CoreVisualizations/CoreVisualizations.php
@@ -0,0 +1,58 @@
+<?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_Plugins
+ * @package Piwik_CoreVisualizations
+ */
+
+use Piwik\Plugin;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/JqplotDataGenerator.php';
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/Cloud.php';
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/HtmlTable.php';
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/JqplotGraph.php';
+
+/**
+ * This plugin contains all core visualizations, such as the normal HTML table and
+ * jqPlot graphs.
+ */
+class Piwik_CoreVisualizations extends Plugin
+{
+ /**
+ * @see Piwik_Plugin::getListHooksRegistered
+ */
+ public function getListHooksRegistered()
+ {
+ return array(
+ 'AssetManager.getCssFiles' => 'getCssFiles',
+ 'AssetManager.getJsFiles' => 'getJsFiles',
+ 'DataTableVisualization.getAvailable' => 'getAvailableDataTableVisualizations',
+ );
+ }
+
+ public function getAvailableDataTableVisualizations(&$visualizations)
+ {
+ $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\HtmlTable';
+ $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\HtmlTable\\AllColumns';
+ $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\HtmlTable\\Goals';
+ $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\Cloud';
+ $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph\\Pie';
+ $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph\\Bar';
+ $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph\\Evolution';
+ }
+
+ public function getCssFiles(&$cssFiles)
+ {
+ $cssFiles[] = "plugins/CoreVisualizations/stylesheets/dataTableVisualizations.less";
+ $cssFiles[] = "plugins/CoreVisualizations/stylesheets/jqplot.css";
+ }
+
+ public function getJsFiles(&$jsFiles)
+ {
+ $jsFiles[] = "plugins/CoreVisualizations/javascripts/jqplot.js";
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreVisualizations/JqplotDataGenerator.php b/plugins/CoreVisualizations/JqplotDataGenerator.php
new file mode 100644
index 0000000000..3cf09c8581
--- /dev/null
+++ b/plugins/CoreVisualizations/JqplotDataGenerator.php
@@ -0,0 +1,209 @@
+<?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\Plugins\CoreVisualizations;
+
+use Exception;
+use Piwik\Common;
+use Piwik\Metrics;
+use Piwik\DataTable;
+use Piwik\Visualization;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php';
+
+/**
+ * Generates JSON data used to configure and populate JQPlot graphs.
+ *
+ * Supports pie graphs, bar graphs and time serieses (aka, evolution graphs).
+ */
+class JqplotDataGenerator
+{
+ /**
+ * View properties. @see Piwik_ViewDataTable for more info.
+ *
+ * @var array
+ */
+ protected $properties;
+
+ /**
+ * This object does most of the work in generating the JQPlot JSON data.
+ *
+ * @var Visualization\
+ */
+ protected $visualization;
+
+ /**
+ * Creates a new JqplotDataGenerator instance for a graph type and view properties.
+ *
+ * @param string $type 'pie', 'bar', or 'evolution'
+ * @param array $properties The view properties.
+ * @throws \Exception
+ * @return JqplotDataGenerator
+ */
+ public static function factory($type, $properties)
+ {
+ switch ($type) {
+ case 'evolution':
+ return new JqplotDataGenerator\Evolution($properties);
+ case 'pie':
+ $visualization = new Visualization\Chart\Pie();
+ return new JqplotDataGenerator($visualization, $properties);
+ case 'bar':
+ $visualization = new Visualization\Chart\VerticalBar();
+ return new JqplotDataGenerator($visualization, $properties);
+ default:
+ throw new Exception("Unknown JqplotDataGenerator type '$type'.");
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param Visualization\ $visualization
+ * @param array $properties
+ */
+ public function __construct($visualization, $properties)
+ {
+ $this->visualization = $visualization;
+ $this->properties = $properties;
+ }
+
+ /**
+ * Generates JSON graph data and returns it.
+ *
+ * @param DataTable|DataTable\Map $dataTable
+ * @return string
+ */
+ public function generate($dataTable)
+ {
+ if (!empty($this->properties['visualization_properties']->max_graph_elements)) {
+ $offsetStartSummary = $this->properties['visualization_properties']->max_graph_elements - 1;
+ $sortColumn = !empty($this->properties['filter_sort_column'])
+ ? $this->properties['filter_sort_column']
+ : Metrics::INDEX_NB_VISITS;
+
+ $dataTable->filter(
+ 'AddSummaryRow', array($offsetStartSummary, Piwik_Translate('General_Others'), $sortColumn));
+ }
+
+ if ($dataTable->getRowsCount() > 0) {
+ // if addTotalRow was called in GenerateGraphHTML, add a row containing totals of
+ // different metrics
+ if (!empty($this->properties['visualization_properties']->add_total_row)) {
+ $dataTable->queueFilter('AddSummaryRow', array(0, Piwik_Translate('General_Total'), null, false));
+ }
+
+ $this->initChartObjectData($dataTable);
+ }
+
+ $this->visualization->customizeChartProperties();
+
+ return $this->visualization->render();
+ }
+
+ /**
+ * @param DataTable|DataTable\Map $dataTable
+ */
+ protected function initChartObjectData($dataTable)
+ {
+ $dataTable->applyQueuedFilters();
+
+ // We apply a filter to the DataTable, decoding the label column (useful for keywords for example)
+ $dataTable->filter('ColumnCallbackReplace', array('label', 'urldecode'));
+
+ $xLabels = $dataTable->getColumn('label');
+
+ $columnNames = $this->properties['columns_to_display'];
+ if (($labelColumnIndex = array_search('label', $columnNames)) !== false) {
+ unset($columnNames[$labelColumnIndex]);
+ }
+
+ $columnNameToTranslation = $columnNameToValue = array();
+ foreach ($columnNames as $columnName) {
+ $columnNameToTranslation[$columnName] = @$this->properties['translations'][$columnName];
+
+ $columnNameToValue[$columnName] = $dataTable->getColumn($columnName);
+ }
+
+ $visualization = $this->visualization;
+ $visualization->setAxisXLabels($xLabels);
+ $visualization->setAxisYValues($columnNameToValue);
+ $visualization->setAxisYLabels($columnNameToTranslation);
+ $visualization->setAxisYUnit($this->properties['y_axis_unit']);
+ $visualization->setDisplayPercentageInTooltip(
+ $this->properties['visualization_properties']->display_percentage_in_tooltip);
+
+ // show_all_ticks is not real query param, it is set by GenerateGraphHTML.
+ if ($this->properties['visualization_properties']->show_all_ticks) {
+ $visualization->showAllTicks();
+ }
+
+ $units = $this->getUnitsForColumnsToDisplay();
+ $visualization->setAxisYUnits($units);
+
+ $this->addSeriesPickerToView();
+ }
+
+ protected function getUnitsForColumnsToDisplay()
+ {
+ // derive units from column names
+ $units = $this->deriveUnitsFromRequestedColumnNames();
+ if (!empty($this->properties['y_axis_unit'])) {
+ // force unit to the value set via $this->setAxisYUnit()
+ foreach ($units as &$unit) {
+ $unit = $this->properties['y_axis_unit'];
+ }
+ }
+
+ // the bar charts contain the labels a first series
+ // this series has to be removed from the units
+ if ($this->visualization instanceof Visualization\Chart\VerticalBar) {
+ array_shift($units);
+ }
+
+ return $units;
+ }
+
+ private function deriveUnitsFromRequestedColumnNames()
+ {
+ $idSite = Common::getRequestVar('idSite', null, 'int');
+
+ $units = array();
+ foreach ($this->properties['columns_to_display'] as $columnName) {
+ $derivedUnit = Metrics::getUnit($columnName, $idSite);
+ $units[$columnName] = empty($derivedUnit) ? false : $derivedUnit;
+ }
+ return $units;
+ }
+
+ /**
+ * Used in initChartObjectData to add the series picker config to the view object
+ */
+ protected function addSeriesPickerToView()
+ {
+ $defaultShowSeriesPicker = $this->properties['visualization_properties']->show_series_picker;
+ if (count($this->properties['visualization_properties']->selectable_columns)
+ && Common::getRequestVar('showSeriesPicker', $defaultShowSeriesPicker) == 1
+ ) {
+ $selectableColumns = array();
+ foreach ($this->properties['visualization_properties']->selectable_columns as $column) {
+ $selectableColumns[] = array(
+ 'column' => $column,
+ 'translation' => @$this->properties['translations'][$column],
+ 'displayed' => in_array($column, $this->properties['columns_to_display'])
+ );
+ }
+
+ $this->visualization->setSelectableColumns(
+ $selectableColumns, $this->properties['visualization_properties']->allow_multi_select_series_picker);
+ }
+ }
+}
diff --git a/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php b/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php
new file mode 100644
index 0000000000..2d4f3e93e1
--- /dev/null
+++ b/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php
@@ -0,0 +1,278 @@
+<?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\Plugins\CoreVisualizations\JqplotDataGenerator;
+
+use Piwik\Piwik;
+use Piwik\Common;
+use Piwik\DataTable;
+use Piwik\DataTable\Row;
+use Piwik\ViewDataTable;
+use Piwik\Url;
+use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator;
+
+/**
+ * Generates JQPlot JSON data/config for evolution graphs.
+ */
+class Evolution extends JqplotDataGenerator
+{
+ protected $rowPickerConfig = array();
+
+ /**
+ * Constructor.
+ *
+ * @param array $properties
+ */
+ public function __construct($properties)
+ {
+ parent::__construct(new \Piwik\Visualization\Chart\Evolution(), $properties);
+ }
+
+ /**
+ * @param DataTable|DataTable\Map $dataTable
+ */
+ protected function initChartObjectData($dataTable)
+ {
+ // if the loaded datatable is a simple DataTable, it is most likely a plugin plotting some custom data
+ // we don't expect plugin developers to return a well defined Set
+ if ($dataTable instanceof DataTable) {
+ parent::initChartObjectData($dataTable);
+ return;
+ }
+
+ $dataTable->applyQueuedFilters();
+
+ // the X label is extracted from the 'period' object in the table's metadata
+ $xLabels = $uniqueIdsDataTable = array();
+ foreach ($dataTable->getArray() as $idDataTable => $metadataDataTable) {
+ //eg. "Aug 2009"
+ $xLabels[] = $metadataDataTable->getMetadata('period')->getLocalizedShortString();
+ // we keep track of all unique data table that we need to set a Y value for
+ $uniqueIdsDataTable[] = $idDataTable;
+ }
+
+ $idSite = Common::getRequestVar('idSite', null, 'int');
+ $requestedColumnNames = $this->properties['columns_to_display'];
+ $units = $this->getUnitsForColumnsToDisplay();
+
+ $yAxisLabelToUnit = array();
+ $yAxisLabelToValue = array();
+ foreach ($dataTable->getArray() as $idDataTable => $childTable) {
+ if ($childTable->getRowsCount() > 0) {
+ $rows = $childTable->getRows();
+ } else {
+ $rows = array(new Row());
+ }
+
+ foreach ($rows as $row) {
+ $rowLabel = $row->getColumn('label');
+
+ // put together configuration for row picker.
+ // do this for every data table in the array because rows do not
+ // have to present for each date.
+ if ($this->properties['row_picker_match_rows_by'] !== false) {
+ $rowVisible = $this->handleRowForRowPicker($rowLabel);
+ if (!$rowVisible) {
+ continue;
+ }
+ }
+
+ // build data for request columns
+ foreach ($requestedColumnNames as $requestedColumnName) {
+ $yAxisLabel = $this->getSeriesLabel($rowLabel, $requestedColumnName);
+
+ $yAxisLabelToValue[$yAxisLabel][$idDataTable] = $row->getColumn($requestedColumnName) ?: 0;
+ $yAxisLabelToUnit[$yAxisLabel] = $units[$requestedColumnName];
+ }
+ }
+ }
+
+ // make sure all column values are set to at least zero (no gap in the graph)
+ $yAxisLabelToValueCleaned = array();
+ foreach ($uniqueIdsDataTable as $uniqueIdDataTable) {
+ foreach ($yAxisLabelToValue as $yAxisLabel => $idDataTableToColumnValue) {
+ if (isset($idDataTableToColumnValue[$uniqueIdDataTable])) {
+ $columnValue = $idDataTableToColumnValue[$uniqueIdDataTable];
+ } else {
+ $columnValue = 0;
+ }
+ $yAxisLabelToValueCleaned[$yAxisLabel][] = $columnValue;
+ }
+ }
+
+ $visualization = $this->visualization;
+ $visualization->setAxisXLabels($xLabels);
+ $visualization->setAxisYValues($yAxisLabelToValueCleaned);
+ $visualization->setAxisYUnits($yAxisLabelToUnit);
+
+ $countGraphElements = $dataTable->getRowsCount();
+ $dataTables = $dataTable->getArray();
+ $firstDatatable = reset($dataTables);
+
+ /** @var \Piwik\Period $period */
+ $period = $firstDatatable->getMetadata('period');
+
+ $stepSize = $this->getXAxisStepSize($period->getLabel(), $countGraphElements);
+ $visualization->setXSteps($stepSize);
+
+ if ($this->isLinkEnabled()) {
+ $axisXOnClick = array();
+ $queryStringAsHash = $this->getQueryStringAsHash();
+ foreach ($dataTable->getArray() as $idDataTable => $metadataDataTable) {
+ $period = $metadataDataTable->getMetadata('period');
+ $dateInUrl = $period->getDateStart();
+ $parameters = array(
+ 'idSite' => $idSite,
+ 'period' => $period->getLabel(),
+ 'date' => $dateInUrl->toString(),
+ 'segment' => \Piwik\API\Request::getRawSegmentFromRequest()
+ );
+ $hash = '';
+ if (!empty($queryStringAsHash)) {
+ $hash = '#' . Url::getQueryStringFromParameters($queryStringAsHash + $parameters);
+ }
+ $link = 'index.php?' .
+ Url::getQueryStringFromParameters(array(
+ 'module' => 'CoreHome',
+ 'action' => 'index',
+ ) + $parameters)
+ . $hash;
+ $axisXOnClick[] = $link;
+ }
+ $visualization->setAxisXOnClick($axisXOnClick);
+ }
+
+ $this->addSeriesPickerToView();
+
+ // configure the row picker
+ if ($this->properties['row_picker_match_rows_by'] !== false) {
+ $visualization->setSelectableRows(array_values($this->rowPickerConfig));
+ }
+ }
+
+ /**
+ * This method is called for every row of every table in the DataTable_Array.
+ * It incrementally builds the row picker configuration and determines whether
+ * the row is initially visible or not.
+ * @param string $rowLabel
+ * @return bool
+ */
+ private function handleRowForRowPicker(&$rowLabel)
+ {
+ // determine whether row is visible
+ $isVisible = true;
+ if ($this->properties['row_picker_match_rows_by'] == 'label') {
+ $isVisible = in_array($rowLabel, $this->properties['row_picker_visible_rows']);
+ }
+
+ // build config
+ if (!isset($this->rowPickerConfig[$rowLabel])) {
+ $this->rowPickerConfig[$rowLabel] = array(
+ 'label' => $rowLabel,
+ 'matcher' => $rowLabel,
+ 'displayed' => $isVisible
+ );
+ }
+
+ return $isVisible;
+ }
+
+ /**
+ * Derive the series label from the row label and the column name.
+ * If the row label is set, both the label and the column name are displayed.
+ * @param string $rowLabel
+ * @param string $columnName
+ * @return string
+ */
+ private function getSeriesLabel($rowLabel, $columnName)
+ {
+ $metricLabel = @$this->properties['translations'][$columnName];
+
+ if ($rowLabel !== false) {
+ // eg. "Yahoo! (Visits)"
+ $label = "$rowLabel ($metricLabel)";
+ } else {
+ // eg. "Visits"
+ $label = $metricLabel;
+ }
+
+ return $label;
+ }
+
+ /**
+ * We link the graph dots to the same report as currently being displayed (only the date would change).
+ *
+ * In some cases the widget is loaded within a report that doesn't exist as such.
+ * For example, the dashboards loads the 'Last visits graph' widget which can't be directly linked to.
+ * Instead, the graph must link back to the dashboard.
+ *
+ * In other cases, like Visitors>Overview or the Goals graphs, we can link the graph clicks to the same report.
+ *
+ * To detect whether or not we can link to a report, we simply check if the current URL from which it was loaded
+ * belongs to the menu or not. If it doesn't belong to the menu, we do not append the hash to the URL,
+ * which results in loading the dashboard.
+ *
+ * @return array Query string array to append to the URL hash or false if the dashboard should be displayed
+ */
+ private function getQueryStringAsHash()
+ {
+ $queryString = Url::getArrayFromCurrentQueryString();
+ $piwikParameters = array('idSite', 'date', 'period', 'XDEBUG_SESSION_START', 'KEY');
+ foreach ($piwikParameters as $parameter) {
+ unset($queryString[$parameter]);
+ }
+ if (\Piwik\Menu\Main::getInstance()->isUrlFound($queryString)) {
+ return $queryString;
+ }
+ return false;
+ }
+
+ private function isLinkEnabled()
+ {
+ static $linkEnabled;
+ if (!isset($linkEnabled)) {
+ // 1) Custom Date Range always have link disabled, otherwise
+ // the graph data set is way too big and fails to display
+ // 2) disableLink parameter is set in the Widgetize "embed" code
+ $linkEnabled = !Common::getRequestVar('disableLink', 0, 'int')
+ && Common::getRequestVar('period', 'day') != 'range';
+ }
+ return $linkEnabled;
+ }
+
+ private function getXAxisStepSize($periodLabel, $countGraphElements)
+ {
+ // when the number of elements plotted can be small, make sure the X legend is useful
+ if ($countGraphElements <= 7) {
+ return 1;
+ }
+
+ switch ($periodLabel) {
+ case 'day':
+ $steps = 5;
+ break;
+ case 'week':
+ $steps = 4;
+ break;
+ case 'month':
+ $steps = 5;
+ break;
+ case 'year':
+ $steps = 5;
+ break;
+ default:
+ $steps = 5;
+ break;
+ }
+
+ $paddedCount = $countGraphElements + 2; // pad count so last label won't be cut off
+ return ceil($paddedCount / $steps);
+ }
+}
diff --git a/plugins/CoreVisualizations/Visualizations/Cloud.php b/plugins/CoreVisualizations/Visualizations/Cloud.php
new file mode 100644
index 0000000000..a9a8eb7364
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/Cloud.php
@@ -0,0 +1,172 @@
+<?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\Plugins\CoreVisualizations\Visualizations;
+
+use Piwik\Common;
+use Piwik\View;
+use Piwik\DataTable;
+use Piwik\DataTableVisualization;
+
+/**
+ * Generates a tag cloud from a given data array.
+ * The generated tag cloud can be in PHP format, or in HTML.
+ *
+ * Inspired from Derek Harvey (www.derekharvey.co.uk)
+ *
+ * @package Piwik
+ * @subpackage Piwik_Visualization
+ */
+class Cloud extends DataTableVisualization
+{
+ const ID = 'cloud';
+
+ /** Used by integration tests to make sure output is consistent. */
+ public static $debugDisableShuffle = false;
+
+ protected $wordsArray = array();
+ public $truncatingLimit = 50;
+
+ public static function getDefaultPropertyValues()
+ {
+ return array(
+ 'show_offset_information' => false,
+ 'show_exclude_low_population' => false,
+ 'display_logo_instead_of_label' => false,
+ );
+ }
+
+ /**
+ * Assign word to array
+ * @param string $word
+ * @param int $value
+ * @return string
+ */
+ public function addWord($word, $value = 1)
+ {
+ if (isset($this->wordsArray[$word])) {
+ $this->wordsArray[$word] += $value;
+ } else {
+ $this->wordsArray[$word] = $value;
+ }
+ }
+
+ /**
+ * Renders this visualization.
+ *
+ * @param DataTable $dataTable
+ * @param array $properties
+ * @return string
+ */
+ public function render($dataTable, $properties)
+ {
+ $view = new View("@CoreVisualizations/_dataTableViz_tagCloud.twig");
+ $view->properties = $properties;
+
+ $columnToDisplay = $properties['columns_to_display'][1];
+
+ $labelMetadata = array();
+ foreach ($dataTable->getRows() as $row) {
+ $logo = false;
+ if ($properties['display_logo_instead_of_label']) {
+ $logo = $row->getMetadata('logo');
+ }
+
+ $label = $row->getColumn('label');
+
+ $labelMetadata[$label] = array(
+ 'logo' => $logo,
+ 'url' => $row->getMetadata('url'),
+ );
+
+ $this->addWord($label, $row->getColumn($columnToDisplay));
+ }
+ $cloudValues = $this->getCloudValues();
+ foreach ($cloudValues as &$value) {
+ $value['logoWidth'] = round(max(16, $value['percent']));
+ }
+ $view->labelMetadata = $labelMetadata;
+ $view->cloudValues = $cloudValues;
+
+ return $view->render();
+ }
+
+ private function getCloudValues()
+ {
+ $this->shuffleCloud();
+ $return = array();
+ if (empty($this->wordsArray)) {
+ return array();
+ }
+ $maxValue = max($this->wordsArray);
+ foreach ($this->wordsArray as $word => $popularity) {
+ $wordTruncated = $word;
+ if (Common::mb_strlen($word) > $this->truncatingLimit) {
+ $wordTruncated = Common::mb_substr($word, 0, $this->truncatingLimit - 3) . '...';
+ }
+
+ // case hideFutureHoursWhenToday=1 shows hours with no visits
+ if ($maxValue == 0) {
+ $percent = 0;
+ } else {
+ $percent = ($popularity / $maxValue) * 100;
+ }
+ // CSS style value
+ $sizeRange = $this->getClassFromPercent($percent);
+
+ $return[$word] = array(
+ 'word' => $word,
+ 'wordTruncated' => $wordTruncated,
+ 'value' => $popularity,
+ 'size' => $sizeRange,
+ 'percent' => $percent,
+ );
+ }
+ return $return;
+ }
+
+ /**
+ * Shuffle associated names in array
+ */
+ protected function shuffleCloud()
+ {
+ if (self::$debugDisableShuffle) {
+ return;
+ }
+
+ $keys = array_keys($this->wordsArray);
+
+ shuffle($keys);
+
+ if (count($keys) && is_array($keys)) {
+ $tmpArray = $this->wordsArray;
+ $this->wordsArray = array();
+ foreach ($keys as $key => $value)
+ $this->wordsArray[$value] = $tmpArray[$value];
+ }
+ }
+
+ /**
+ * Get the class range using a percentage
+ *
+ * @param $percent
+ *
+ * @return int class
+ */
+ protected function getClassFromPercent($percent)
+ {
+ $mapping = array(95, 70, 50, 30, 15, 5, 0);
+ foreach ($mapping as $key => $value) {
+ if ($percent >= $value) {
+ return $key;
+ }
+ }
+ }
+}
diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable.php b/plugins/CoreVisualizations/Visualizations/HtmlTable.php
new file mode 100644
index 0000000000..d3c6a61974
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/HtmlTable.php
@@ -0,0 +1,394 @@
+<?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\Plugins\CoreVisualizations\Visualizations;
+
+use Piwik\Piwik;
+use Piwik\DataTable;
+use Piwik\View;
+use Piwik\Config;
+use Piwik\Common;
+use Piwik\Site;
+use Piwik\DataTableVisualization;
+use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal;
+use \Piwik_Goals_API;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php';
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php';
+
+/**
+ * DataTable visualization that shows DataTable data in an HTML table.
+ */
+class HtmlTable extends DataTableVisualization
+{
+ const ID = 'table';
+
+ /**
+ * Custom template used if displaying a subtable.
+ *
+ * TODO: Should be replaced w/ allowing custom visualization for
+ * subtables. Should not directly touch template.
+ */
+ const SUBTABLE_TEMPLATE = 'subtable_template';
+
+ /**
+ * Controls whether the entire DataTable should be rendered (including subtables) or just one
+ * specific table in the tree.
+ */
+ const SHOW_EXPANDED = 'show_expanded';
+
+ /**
+ * When showing an expanded datatable, this property controls whether rows with subtables are
+ * replaced with their subtables, or if they are shown alongside their subtables.
+ */
+ const REPLACE_ROW_WITH_SUBTABLE = 'replace_row_with_subtable';
+
+ /**
+ * Controls whether any DataTable Row Action icons are shown. If true, no icons are shown.
+ *
+ * @see also self::DISABLE_ROW_EVOLUTION
+ */
+ const DISABLE_ROW_ACTIONS = 'disable_row_actions';
+
+ /**
+ * Controls whether the row evolution DataTable Row Action icon is shown or not.
+ *
+ * @see also self::DISABLE_ROW_ACTIONS
+ */
+ const DISABLE_ROW_EVOLUTION = 'disable_row_evolution';
+
+ /**
+ * If true, the 'label', 'nb_visits', 'nb_uniq_visitors' (if present), 'nb_actions',
+ * 'nb_actions_per_visit', 'avg_time_on_site', 'bounce_rate' and 'conversion_rate' (if
+ * goals view is not allowed) are displayed.
+ */
+ const SHOW_EXTRA_COLUMNS = 'show_extra_columns';
+
+ /**
+ * If true, conversions for each existing goal will be displayed for the visits in
+ * each row.
+ */
+ const SHOW_GOALS_COLUMNS = 'show_goals_columns';
+
+ /**
+ * If true, subtables will not be loaded when rows are clicked, but only if the
+ * 'show_goals_columns' property is also true.
+ *
+ * @see also self::SHOW_GOALS_COLUMNS
+ */
+ const DISABLE_SUBTABLE_IN_GOALS_VIEW = 'disable_subtable_when_show_goals';
+
+ static public $clientSideParameters = array(
+ 'search_recursive',
+ );
+
+ static public $clientSideProperties = array(
+ 'show_extra_columns',
+ 'show_goals_columns',
+ 'disable_row_evolution',
+ 'disable_row_actions'
+ );
+
+ /**
+ * Constructor.
+ */
+ public function __construct($view)
+ {
+ if (Common::getRequestVar('idSubtable', false)
+ && $view->visualization_properties->subtable_template
+ ) {
+ $view->datatable_template = $view->visualization_properties->subtable_template;
+ }
+
+ if ($view->visualization_properties->show_extra_columns) {
+ $this->setShowExtraColumnsProperties($view);
+ }
+
+ if ($view->visualization_properties->show_goals_columns) {
+ $this->setShowGoalsColumnsProperties($view);
+ }
+ }
+
+ /**
+ * Renders this visualization.
+ *
+ * @param DataTable $dataTable
+ * @param array $properties View Properties.
+ * @return string
+ */
+ public function render($dataTable, $properties) // TODO: $properties should be a viewdatatable, I think.
+ {
+ $view = new View("@CoreVisualizations/_dataTableViz_htmlTable.twig");
+ $view->properties = $properties;
+ $view->dataTable = $dataTable;
+ return $view->render();
+ }
+
+ public static function getDefaultPropertyValues()
+ {
+ $defaults = array(
+ 'enable_sort' => true,
+ 'datatable_js_type' => 'dataTable',
+ 'filter_limit' => Config::getInstance()->General['datatable_default_limit'],
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_row_evolution' => false,
+ 'disable_row_actions' => false,
+ 'subtable_template' => "@CoreHome/_dataTable.twig",
+ 'show_extra_columns' => false,
+ 'show_goals_columns' => false,
+ 'disable_subtable_when_show_goals' => false,
+ ),
+ ),
+ );
+
+ if (Common::getRequestVar('enable_filter_excludelowpop', false) == '1') {
+ $defaults['filter_excludelowpop'] = 'nb_visits';
+ $defaults['filter_excludelowpop_value'] = null;
+ }
+
+ return $defaults;
+ }
+
+ private function setShowExtraColumnsProperties($view)
+ {
+ $view->filters[] = array('AddColumnsProcessedMetrics', array(), $priority = true);
+
+ $view->filters[] = function ($dataTable, $view) {
+ $columnsToDisplay = array('label', 'nb_visits');
+
+ if (in_array('nb_uniq_visitors', $dataTable->getColumns())) {
+ $columnsToDisplay[] = 'nb_uniq_visitors';
+ }
+
+ $columnsToDisplay = array_merge(
+ $columnsToDisplay, array('nb_actions', 'nb_actions_per_visit', 'avg_time_on_site', 'bounce_rate')
+ );
+
+ // only display conversion rate for the plugins that do not provide "per goal" metrics
+ // otherwise, conversion rate is meaningless as a whole (since we don't process 'cross goals' conversions)
+ if (!$view->show_goals) {
+ $columnsToDisplay[] = 'conversion_rate';
+ }
+
+ $view->columns_to_display = $columnsToDisplay;
+ };
+
+ $prettifyTime = array('\Piwik\Piwik', 'getPrettyTimeFromSeconds');
+ $view->filters[] = array('ColumnCallbackReplace', array('avg_time_on_site', $prettifyTime));
+
+ $view->show_exclude_low_population = true;
+
+ $view->datatable_css_class = 'dataTableVizAllColumns';
+ }
+
+ private function setShowGoalsColumnsProperties($view)
+ {
+ $view->datatable_css_class = 'dataTableVizGoals';
+ $view->show_exclude_low_population = true;
+ $view->show_goals = true;
+ $view->translations += array(
+ 'nb_conversions' => Piwik_Translate('Goals_ColumnConversions'),
+ 'conversion_rate' => Piwik_Translate('General_ColumnConversionRate'),
+ 'revenue' => Piwik_Translate('Goals_ColumnRevenue'),
+ 'revenue_per_visit' => Piwik_Translate('General_ColumnValuePerVisit'),
+ );
+ $view->metrics_documentation['nb_visits'] = Piwik_Translate('Goals_ColumnVisits');
+
+ if (Common::getRequestVar('documentationForGoalsPage', 0, 'int') == 1) { // TODO: should not use query parameter
+ $view->documentation = Piwik_Translate('Goals_ConversionByTypeReportDocumentation',
+ array('<br />', '<br />', '<a href="http://piwik.org/docs/tracking-goals-web-analytics/" target="_blank">', '</a>'));
+ }
+
+ if (!$view->visualization_properties->disable_subtable_when_show_goals) {
+ $view->subtable_controller_action = null;
+ }
+
+ // set view properties based on goal requested
+ $idSite = Common::getRequestVar('idSite', null, 'int');
+ $idGoal = Common::getRequestVar('idGoal', AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW, 'string');
+ if ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
+ $this->setPropertiesForEcommerceView($view);
+ } else if ($idGoal == AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE) {
+ $this->setPropertiesForGoals($view, $idSite, 'all');
+ } else if ($idGoal == AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW) {
+ $this->setPropertiesForGoalsOverview($view, $idSite);
+ } else {
+ $this->setPropertiesForGoals($view, $idSite, array($idGoal));
+ }
+
+ // add goals columns
+ $view->filters[] = array(
+ 'AddColumnsProcessedMetricsGoal', array($ignore = true, $idGoal), $priority = true);
+
+ // prettify columns
+ $setRatePercent = function ($rate, $thang = false) { return $rate == 0 ? "0%" : $rate; };
+ foreach ($view->columns_to_display as $columnName) {
+ if (strpos($columnName, 'conversion_rate') !== false) {
+ $view->filters[] = array('ColumnCallbackReplace', array($columnName, $setRatePercent));
+ }
+ }
+
+ $formatPercent = function ($value) use($idSite) {
+ return Piwik::getPrettyMoney(sprintf("%.1f", $value), $idSite);
+ };
+
+ foreach ($view->columns_to_display as $columnName) {
+ if ($this->isRevenueColumn($columnName)) {
+ $view->filters[] = array('ColumnCallbackReplace', array($columnName, $formatPercent));
+ }
+ }
+
+ // this ensures that the value is set to zero for all rows where the value was not set (no conversion)
+ $identityFunction = function ($value) { return $value; };
+ foreach ($view->columns_to_display as $columnName) {
+ if (!$this->isRevenueColumn($columnName)) {
+ $view->filters[] = array('ColumnCallbackReplace', array($columnName, $identityFunction));
+ }
+ }
+ }
+
+ private function setPropertiesForEcommerceView($view)
+ {
+ $view->filter_sort_column = 'goal_ecommerceOrder_revenue';
+ $view->filter_sort_order = 'desc';
+
+ $view->columns_to_display = array(
+ 'label', 'nb_visits', 'goal_ecommerceOrder_nb_conversions', 'goal_ecommerceOrder_revenue',
+ 'goal_ecommerceOrder_conversion_rate', 'goal_ecommerceOrder_avg_order_revenue', 'goal_ecommerceOrder_items',
+ 'goal_ecommerceOrder_revenue_per_visit'
+ );
+
+ $view->translations += array(
+ 'goal_ecommerceOrder_conversion_rate' => Piwik_Translate('Goals_ConversionRate', Piwik_Translate('Goals_EcommerceOrder')),
+ 'goal_ecommerceOrder_nb_conversions' => Piwik_Translate('General_EcommerceOrders'),
+ 'goal_ecommerceOrder_revenue' => Piwik_Translate('General_TotalRevenue'),
+ 'goal_ecommerceOrder_revenue_per_visit' => Piwik_Translate('General_ColumnValuePerVisit'),
+ 'goal_ecommerceOrder_avg_order_revenue' => Piwik_Translate('General_AverageOrderValue'),
+ 'goal_ecommerceOrder_items' => Piwik_Translate('General_PurchasedProducts')
+ );
+
+ $goalName = Piwik_Translate('General_EcommerceOrders');
+ $view->metrics_documentation += array(
+ 'goal_ecommerceOrder_conversion_rate' => Piwik_Translate('Goals_ColumnConversionRateDocumentation', $goalName),
+ 'goal_ecommerceOrder_nb_conversions' => Piwik_Translate('Goals_ColumnConversionsDocumentation', $goalName),
+ 'goal_ecommerceOrder_revenue' => Piwik_Translate('Goals_ColumnRevenueDocumentation', $goalName),
+ 'goal_ecommerceOrder_revenue_per_visit' => Piwik_Translate('Goals_ColumnAverageOrderRevenueDocumentation', $goalName),
+ 'goal_ecommerceOrder_avg_order_revenue' => Piwik_Translate('Goals_ColumnAverageOrderRevenueDocumentation', $goalName),
+ 'goal_ecommerceOrder_items' => Piwik_Translate('Goals_ColumnPurchasedProductsDocumentation', $goalName),
+ 'revenue_per_visit' => Piwik_Translate('Goals_ColumnRevenuePerVisitDocumentation', $goalName)
+ );
+ }
+
+ private function setPropertiesForGoalsOverview($view, $idSite)
+ {
+ $allGoals = $this->getGoals($idSite);
+
+ // set view properties
+ $view->columns_to_display = array('label', 'nb_visits');
+
+ foreach ($allGoals as $goal) {
+ $column = "goal_{$goal['idgoal']}_conversion_rate";
+
+ $view->columns_to_display[] = $column;
+ $view->translations[$column] = Piwik_Translate('Goals_ConversionRate', $goal['name']);
+ $view->metrics_documentation[$column]
+ = Piwik_Translate('Goals_ColumnConversionRateDocumentation', $goal['quoted_name'] ?: $goal['name']);
+ }
+
+ $view->columns_to_display[] = 'revenue_per_visit';
+ $view->metrics_documentation['revenue_per_visit'] =
+ Piwik_Translate('Goals_ColumnRevenuePerVisitDocumentation', Piwik_Translate('Goals_EcommerceAndGoalsMenu'));
+ }
+
+ private function setPropertiesForGoals($view, $idSite, $idGoals)
+ {
+ $allGoals = $this->getGoals($idSite);
+
+ if ($idGoals == 'all') {
+ $idGoals = array_keys($allGoals);
+ } else {
+ // only sort by a goal's conversions if not showing all goals (for FULL_REPORT)
+ $view->filter_sort_column = 'goal_' . reset($idGoals) . '_nb_conversions';
+ $view->filter_sort_order = 'desc';
+ }
+
+ $view->columns_to_display = array('label', 'nb_visits');
+
+ $goalColumnTemplates = array(
+ 'goal_%s_nb_conversions',
+ 'goal_%s_conversion_rate',
+ 'goal_%s_revenue',
+ 'goal_%s_revenue_per_visit',
+ );
+
+ // set columns to display (columns of same type but different goals will be next to each other,
+ // ie, goal_0_nb_conversions, goal_1_nb_conversions, etc.)
+ foreach ($goalColumnTemplates as $idx => $columnTemplate) {
+ foreach ($idGoals as $idGoal) {
+ $column = sprintf($columnTemplate, $idGoal);
+ $view->columns_to_display[] = $column;
+ }
+ }
+
+ // set translations & metric docs for goal specific metrics
+ foreach ($idGoals as $idGoal) {
+ $goalName = $allGoals[$idGoal]['name'];
+ $quotedGoalName = $allGoals[$idGoal]['quoted_name'] ?: $goalName;
+
+ $view->translations += array(
+ 'goal_' . $idGoal . '_nb_conversions' => Piwik_Translate('Goals_Conversions', $goalName),
+ 'goal_' . $idGoal . '_conversion_rate' => Piwik_Translate('Goals_ConversionRate', $goalName),
+ 'goal_' . $idGoal . '_revenue' =>
+ Piwik_Translate('%s ' . Piwik_Translate('Goals_ColumnRevenue'), $goalName),
+ 'goal_' . $idGoal . '_revenue_per_visit' =>
+ Piwik_Translate('%s ' . Piwik_Translate('General_ColumnValuePerVisit'), $goalName),
+ );
+
+ $view->metrics_documentation += array(
+ 'goal_' . $idGoal . '_nb_conversions' => Piwik_Translate('Goals_ColumnConversionsDocumentation', $quotedGoalName),
+ 'goal_' . $idGoal . '_conversion_rate' => Piwik_Translate('Goals_ColumnConversionRateDocumentation', $quotedGoalName),
+ 'goal_' . $idGoal . '_revenue' => Piwik_Translate('Goals_ColumnRevenueDocumentation', $quotedGoalName),
+ 'goal_' . $idGoal . '_revenue_per_visit' =>
+ Piwik_Translate('Goals_ColumnRevenuePerVisitDocumentation', Piwik_Translate('Goals_EcommerceAndGoalsMenu')),
+ );
+ }
+
+ $view->columns_to_display[] = 'revenue_per_visit';
+ }
+
+ private function getGoals($idSite)
+ {
+ // get all goals to display info for
+ $allGoals = array();
+
+ if (Site::isEcommerceEnabledFor($idSite)) {
+ $ecommerceGoal = array(
+ 'idgoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER,
+ 'name' => Piwik_Translate('Goals_EcommerceOrder'),
+ 'quoted_name' => false
+ );
+ $allGoals[$ecommerceGoal['idgoal']] = $ecommerceGoal;
+ }
+
+ $siteGoals = Piwik_Goals_API::getInstance()->getGoals($idSite);
+ foreach ($siteGoals as &$goal) {
+ $goal['quoted_name'] = '"' . $goal['name'] . '"';
+ $allGoals[$goal['idgoal']] = $goal;
+ }
+
+ return $allGoals;
+ }
+
+ private function isRevenueColumn($name)
+ {
+ return strpos($name, '_revenue') !== false || $name == 'revenue_per_visit';
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php b/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php
new file mode 100644
index 0000000000..43c7f5c72a
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php
@@ -0,0 +1,34 @@
+<?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\Plugins\CoreVisualizations\Visualizations\HtmlTable;
+
+use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
+
+/**
+ * TODO
+ */
+class AllColumns extends HtmlTable
+{
+ const ID = 'tableAllColumns';
+
+ /**
+ * Constructor.
+ *
+ * @param \Piwik\ViewDataTable $view
+ */
+ public function __construct($view)
+ {
+ $view->visualization_properties->show_extra_columns = true;
+
+ parent::__construct($view);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php b/plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php
new file mode 100644
index 0000000000..382eeeaadd
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php
@@ -0,0 +1,34 @@
+<?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\Plugins\CoreVisualizations\Visualizations\HtmlTable;
+
+use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
+
+/**
+ * TODO
+ */
+class Goals extends HtmlTable
+{
+ const ID = 'tableGoals';
+
+ /**
+ * Constructor.
+ *
+ * @param \Piwik\ViewDataTable $view
+ */
+ public function __construct($view)
+ {
+ $view->visualization_properties->show_goals_columns = true;
+
+ parent::__construct($view);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph.php
new file mode 100644
index 0000000000..a67e8665fd
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph.php
@@ -0,0 +1,212 @@
+<?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\Plugins\CoreVisualizations\Visualizations;
+
+use Piwik\Common;
+use Piwik\View;
+use Piwik\DataTable;
+use Piwik\DataTableVisualization;
+use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php';
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php';
+require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php';
+
+/**
+ * DataTable visualization that displays DataTable data in a JQPlot graph.
+ * TODO: should merge all this logic w/ jqplotdatagenerator & 'Chart' visualizations.
+ */
+class JqplotGraph extends DataTableVisualization
+{
+ const DEFAULT_GRAPH_HEIGHT = 250;
+ const ID = 'jqplot_graph';
+
+ /**
+ * Whether the series picker should allow picking more than one series or not.
+ */
+ const ALLOW_MULTI_SELECT_SERIES_PICKER = 'allow_multi_select_series_picker';
+
+ /**
+ * The maximum number of elements to render when rendering a jqPlot graph. All other elements
+ * will be aggregated in an 'Others' element.
+ */
+ const MAX_GRAPH_ELEMENTS = 'max_graph_elements';
+
+ /**
+ * The name of the JavaScript class to use as this graph's external series toggle. The class
+ * must be a subclass of JQPlotExternalSeriesToggle.
+ *
+ * @see self::EXTERNAL_SERIES_TOGGLE_SHOW_ALL
+ */
+ const EXTERNAL_SERIES_TOGGLE = 'external_series_toggle';
+
+ /**
+ * Whether the graph should show all loaded series upon initial display.
+ *
+ * @see self::EXTERNAL_SERIES_TOGGLE
+ */
+ const EXTERNAL_SERIES_TOGGLE_SHOW_ALL = 'external_series_toggle_show_all';
+
+ /**
+ * Array property that contains the names of columns that can be selected in the Series Picker.
+ */
+ const SELECTABLE_COLUMNS = 'selectable_columns';
+
+ /**
+ * Controls whether all ticks & labels are shown on a graph's x-axis or just some.
+ */
+ const SHOW_ALL_TICKS = 'show_all_ticks';
+
+ /**
+ * If true, a row with totals of each DataTable column is added.
+ */
+ const ADD_TOTAL_ROW = 'add_total_row';
+
+ /**
+ * The CSS width of the graph. (eg, '100px').
+ */
+ const GRAPH_WIDTH = 'graph_width';
+
+ /**
+ * The CSS height of the graph. (eg, '100px').
+ */
+ const GRAPH_HEIGHT = 'graph_height';
+
+ /**
+ * Controls whether the Series Picker is shown or not. The Series Picker allows users to
+ * choose between displaying data of different columns.
+ */
+ const SHOW_SERIES_PICKER = 'show_series_picker';
+
+ /**
+ * 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.
+ */
+ const DISPLAY_PERCENTAGE_IN_TOOLTIP = 'display_percentage_in_tooltip';
+
+ /**
+ * Constructor.
+ *
+ * @param \Piwik\ViewDataTable $view
+ */
+ public function __construct($view)
+ {
+ // Graphs require the full dataset, so no filters
+ $this->request_parameters_to_modify['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->request_parameters_to_modify['disable_queued_filters'] = true;
+
+ if ($view->show_goals) {
+ $goalMetrics = array('nb_conversions', 'revenue');
+ $view->visualization_properties->selectable_columns = array_merge(
+ $view->visualization_properties->selectable_columns, $goalMetrics);
+
+ $view->translations['nb_conversions'] = Piwik_Translate('Goals_ColumnConversions');
+ $view->translations['revenue'] = Piwik_Translate('General_TotalRevenue');
+ }
+
+ // do not sort if sorted column was initially "label" or eg. it would make "Visits by Server time" not pretty
+ if ($view->filter_sort_column != 'label') {
+ $columns = $view->columns_to_display;
+
+ $firstColumn = reset($columns);
+ if ($firstColumn == 'label') {
+ $firstColumn = next($columns);
+ }
+
+ $result['filter_sort_column'] = $firstColumn;
+ $result['filter_sort_order'] = 'desc';
+ }
+ }
+
+ /**
+ * Returns an array mapping property names with default values for this visualization.
+ *
+ * @return array
+ */
+ public static function getDefaultPropertyValues()
+ {
+ // selectable columns
+ $selectableColumns = array('nb_visits', 'nb_actions');
+ if (Common::getRequestVar('period', false) == 'day') { // TODO: should depend on columns datatable has.
+ $selectableColumns[] = 'nb_uniq_visitors';
+ }
+
+ return array(
+ 'show_offset_information' => false,
+ 'show_pagination_control' => false,
+ 'show_exclude_low_population' => false,
+ 'show_search' => false,
+ 'show_export_as_image_icon' => true,
+ 'y_axis_unit' => '',
+ 'row_picker_match_rows_by' => false,
+ 'row_picker_visible_rows' => array(),
+ 'visualization_properties' => array(
+ 'jqplot_graph' => array(
+ 'add_total_row' => 0,
+ 'show_all_ticks' => false,
+ 'allow_multi_select_series_picker' => true,
+ 'max_graph_elements' => false,
+ 'selectable_columns' => $selectableColumns,
+ 'graph_width' => '100%',
+ 'graph_height' => self::DEFAULT_GRAPH_HEIGHT . 'px',
+ 'external_series_toggle' => false,
+ 'external_series_toggle_show_all' => false,
+ 'show_series_picker' => true,
+ 'display_percentage_in_tooltip' => true,
+ )
+ )
+ );
+ }
+
+ /**
+ * Renders this visualization.
+ *
+ * @param DataTable $dataTable
+ * @param array $properties View Properties.
+ * @return string
+ */
+ public function render($dataTable, $properties)
+ {
+ $view = new View("@CoreVisualizations/_dataTableViz_jqplotGraph.twig");
+ $view->properties = $properties;
+ $view->dataTable = $dataTable;
+ $view->data = $this->getGraphData($dataTable, $properties);
+ return $view->render();
+ }
+
+ /**
+ * Generats JQPlot graph data for a DataTable.
+ */
+ private function getGraphData($dataTable, $properties)
+ {
+ $properties = array_merge($properties, $properties['request_parameters_to_modify']);
+ $dataGenerator = $this->makeDataGenerator($properties);
+
+ $jsonData = $dataGenerator->generate($dataTable);
+ return str_replace(array("\r", "\n"), '', $jsonData);
+ }
+
+ /**
+ * Returns a JqplotDataGenerator for the given graph_type in $properties
+ * @param array $properties
+ * @return JqplotDataGenerator
+ */
+ protected function makeDataGenerator($properties)
+ {
+ return JqplotDataGenerator::factory($properties['graph_type'], $properties);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php
new file mode 100644
index 0000000000..4ec94329e2
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php
@@ -0,0 +1,35 @@
+<?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\Plugins\CoreVisualizations\Visualizations\JqplotGraph;
+
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph;
+use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator;
+
+/**
+ * Visualization that renders HTML for a Bar graph using jqPlot.
+ */
+class Bar extends JqplotGraph
+{
+ const ID = 'graphVerticalBar';
+
+ public static function getDefaultPropertyValues()
+ {
+ $result = parent::getDefaultPropertyValues();
+ $result['visualization_properties']['jqplot_graph']['max_graph_elements'] = 6;
+ return $result;
+ }
+
+ protected function makeDataGenerator($properties)
+ {
+ return JqplotDataGenerator::factory('bar', $properties);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php
new file mode 100644
index 0000000000..f403684834
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php
@@ -0,0 +1,150 @@
+<?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\Plugins\CoreVisualizations\Visualizations\JqplotGraph;
+
+use Piwik\Common;
+use Piwik\Site;
+use Piwik\Controller;
+use Piwik\Period\Range;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph;
+use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator;
+
+/**
+ * Visualization that renders HTML for a line graph using jqPlot.
+ */
+class Evolution extends JqplotGraph
+{
+ const ID = 'graphEvolution';
+
+ const GRAPH_HEIGHT = 170;
+ const SERIES_COLOR_COUNT = 8;
+
+ public function __construct($view)
+ {
+ parent::__construct($view);
+
+ // period will be overridden when 'range' is requested in the UI
+ // but the graph will display for each day of the range.
+ // Default 'range' behavior is to return the 'sum' for the range
+ if (Common::getRequestVar('period', false) == 'range') {
+ $view->request_parameters_to_modify['period'] = 'day';
+ }
+
+ $this->calculateEvolutionDateRange($view);
+ }
+
+ public static function getDefaultPropertyValues()
+ {
+ $result = parent::getDefaultPropertyValues();
+ $result['show_all_views_icons'] = false;
+ $result['show_table'] = false;
+ $result['show_table'] = false;
+ $result['show_table_all_columns'] = false;
+ $result['hide_annotations_view'] = false;
+ $result['visualization_properties']['graphEvolution']['graph_height'] = self::GRAPH_HEIGHT . 'px';
+ return $result;
+ }
+
+ protected function makeDataGenerator($properties)
+ {
+ return JqplotDataGenerator::factory('evolution', $properties);
+ }
+
+ /**
+ * Based on the period, date and evolution_{$period}_last_n query parameters,
+ * calculates the date range this evolution chart will display data for.
+ */
+ private function calculateEvolutionDateRange(&$view)
+ {
+ $period = Common::getRequestVar('period');
+
+ $defaultLastN = self::getDefaultLastN($period);
+ $originalDate = Common::getRequestVar('date', 'last' . $defaultLastN, 'string');
+
+ if ($period != 'range') { // show evolution limit if the period is not a range
+ $view->show_limit_control = true;
+
+ // set the evolution_{$period}_last_n query param
+ if (Range::parseDateRange($originalDate)) { // if a multiple period
+ // overwrite last_n param using the date range
+ $oPeriod = new Range($period, $originalDate);
+ $lastN = count($oPeriod->getSubperiods());
+ } else { // if not a multiple period
+ list($newDate, $lastN) = self::getDateRangeAndLastN($period, $originalDate, $defaultLastN);
+ $view->request_parameters_to_modify['date'] = $newDate;
+ $view->custom_parameters['dateUsedInGraph'] = $newDate;
+ }
+ $lastNParamName = self::getLastNParamName($period);
+ $view->custom_parameters[$lastNParamName] = $lastN;
+ }
+ }
+
+ /**
+ * Returns the entire date range and lastN value for the current request, based on
+ * a period type and end date.
+ *
+ * @param string $period The period type, 'day', 'week', 'month' or 'year'
+ * @param string $endDate The end date.
+ * @param int|null $defaultLastN The default lastN to use. If null, the result of
+ * getDefaultLastN is used.
+ * @return array An array w/ two elements. The first is a whole date range and the second
+ * is the lastN number used, ie, array('2010-01-01,2012-01-02', 2).
+ */
+ public static function getDateRangeAndLastN($period, $endDate, $defaultLastN = null)
+ {
+ if ($defaultLastN === null) {
+ $defaultLastN = self::getDefaultLastN($period);
+ }
+
+ $lastNParamName = self::getLastNParamName($period);
+ $lastN = Common::getRequestVar($lastNParamName, $defaultLastN, 'int');
+
+ $site = new Site(Common::getRequestVar('idSite'));
+
+ $dateRange = Controller::getDateRangeRelativeToEndDate($period, 'last' . $lastN, $endDate, $site);
+
+ return array($dateRange, $lastN);
+ }
+
+ /**
+ * Returns the default last N number of dates to display for a given period.
+ *
+ * @param string $period 'day', 'week', 'month' or 'year'
+ * @return int
+ */
+ public static function getDefaultLastN($period)
+ {
+ switch ($period) {
+ case 'week':
+ return 26;
+ case 'month':
+ return 24;
+ case 'year':
+ return 5;
+ case 'day':
+ default:
+ return 30;
+ }
+ }
+
+ /**
+ * Returns the query parameter that stores the lastN number of periods to get for
+ * the evolution graph.
+ *
+ * @param string $period The period type, 'day', 'week', 'month' or 'year'.
+ * @return string
+ */
+ public static function getLastNParamName($period)
+ {
+ return "evolution_{$period}_last_n";
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php
new file mode 100644
index 0000000000..a7f62e7dfd
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php
@@ -0,0 +1,36 @@
+<?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\Plugins\CoreVisualizations\Visualizations\JqplotGraph;
+
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph;
+use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator;
+
+/**
+ * Visualization that renders HTML for a Pie graph using jqPlot.
+ */
+class Pie extends JqplotGraph
+{
+ const ID = 'graphPie';
+
+ public static function getDefaultPropertyValues()
+ {
+ $result = parent::getDefaultPropertyValues();
+ $result['visualization_properties']['jqplot_graph']['max_graph_elements'] = 6;
+ $result['visualization_properties']['jqplot_graph']['allow_multi_select_series_picker'] = false;
+ return $result;
+ }
+
+ protected function makeDataGenerator($properties)
+ {
+ return JqplotDataGenerator::factory('pie', $properties);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/javascripts/jqplot.js b/plugins/CoreVisualizations/javascripts/jqplot.js
index d4287a9bec..4d5f80d046 100644
--- a/plugins/CoreHome/javascripts/jqplot.js
+++ b/plugins/CoreVisualizations/javascripts/jqplot.js
@@ -60,7 +60,7 @@ JQPlot.prototype = {
}
if (typeof this.params.axes.yaxis.tickOptions == 'undefined') {
- this.params.yaxis.tickOptions = {
+ this.params.axes.yaxis.tickOptions = {
formatString: '%d'
};
}
@@ -68,21 +68,17 @@ JQPlot.prototype = {
/** Generic render function */
render: function (targetDivId, lang) {
- var type = $('#' + targetDivId).closest('div.dataTable').data('dataTableInstance').param['viewDataTable'];
+ var dataTableDiv = $('#' + targetDivId).closest('div.dataTable');
// preapare the appropriate chart type
- switch (type) {// TODO: should rely on CSS, not viewDataTable. otherwise ecommerceOrder row evolution will fail
- case 'graphEvolution':
- this.prepareEvolutionChart(targetDivId, lang);
- break;
- case 'graphVerticalBar':
- this.prepareBarChart(targetDivId, lang);
- break;
- case 'graphPie':
- this.preparePieChart(targetDivId, lang);
- break;
- default:
- return;
+ if (dataTableDiv.hasClass('dataTableVizEvolution')) {
+ this.prepareEvolutionChart(targetDivId, lang);
+ } else if (dataTableDiv.hasClass('dataTableVizBar')) {
+ this.prepareBarChart(targetDivId, lang);
+ } else if (dataTableDiv.hasClass('dataTableVizPie')) {
+ this.preparePieChart(targetDivId, lang);
+ } else {
+ return;
}
// handle replot
@@ -169,7 +165,7 @@ JQPlot.prototype = {
var percentage = '';
if (typeof self.tooltip.percentages != 'undefined') {
- var percentage = self.tooltip.percentages[s][i];
+ percentage = self.tooltip.percentages[s][i];
percentage = ' (' + percentage + '%)';
}
@@ -304,7 +300,7 @@ JQPlot.prototype = {
var popover = $(document.createElement('div'));
popover.append('<div style="font-size: 13px; margin-bottom: 10px;">'
- + lang.exportText + '</div>').append($(img))
+ + lang.exportText + '</div>').append($(img));
popover.dialog({
title: lang.exportTitle,
@@ -620,7 +616,8 @@ JQPlot.prototype = {
var namespace = graphType + '-graph-colors';
- this.params.seriesColors = colorManager.getColors(namespace, seriesColorNames, true);
+ this.originalData.params.seriesColors = this.params.seriesColors =
+ colorManager.getColors(namespace, seriesColorNames, true);
this.params.grid.background = colorManager.getColor(namespace, 'grid-background');
this.params.grid.borderColor = colorManager.getColor(namespace, 'grid-border');
this.tickColor = colorManager.getColor(namespace, 'ticks');
diff --git a/plugins/CoreVisualizations/stylesheets/dataTableVisualizations.less b/plugins/CoreVisualizations/stylesheets/dataTableVisualizations.less
new file mode 100644
index 0000000000..5ae202f36f
--- /dev/null
+++ b/plugins/CoreVisualizations/stylesheets/dataTableVisualizations.less
@@ -0,0 +1,18 @@
+/* container of each table */
+.dataTableVizHtmlTable > .dataTableWrapper {
+ width: 450px;
+ /* not more than 450px to make sure 2 tables can fit horizontally on a 1024 screen */
+}
+
+.dataTableVizAllColumns > .dataTableWrapper {
+ width: 535px;
+}
+
+.dataTableVizPie > .dataTableWrapper, .dataTableVizBar > .dataTableWrapper {
+ width: 500px;
+ min-height: 1px;
+}
+
+.dataTableVizEvolution > .dataTableWrapper {
+ width: 100%;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/stylesheets/jqplot.css b/plugins/CoreVisualizations/stylesheets/jqplot.css
index bd5dec8e59..bd5dec8e59 100644
--- a/plugins/CoreHome/stylesheets/jqplot.css
+++ b/plugins/CoreVisualizations/stylesheets/jqplot.css
diff --git a/plugins/CoreHome/templates/_dataTableViz_htmlTable.twig b/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig
index aa3911f628..a5ba98ac72 100644
--- a/plugins/CoreHome/templates/_dataTableViz_htmlTable.twig
+++ b/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig
@@ -1,13 +1,20 @@
+{%- set subtablesAreDisabled = properties.visualization_properties.show_goals_columns|default(false)
+ and properties.visualization_properties.disable_subtable_when_show_goals|default(false) -%}
<table cellspacing="0" class="dataTable">
{% include "@CoreHome/_dataTableHead.twig" %}
<tbody>
{% for rowId, row in dataTable.getRows() %}
- {%- set rowHasSubtable = row.getIdSubDataTable() and properties.subtable_controller_action is not null -%}
+ {%- set rowHasSubtable = not subtablesAreDisabled and row.getIdSubDataTable() and properties.subtable_controller_action is not null -%}
{%- set shouldHighlightRow = rowId == constant('Piwik\\DataTable::ID_SUMMARY_ROW') and properties.highlight_summary_row -%}
-
+
{# display this row if it doesn't have a subtable or if we don't replace the row with the subtable #}
- {% if not rowHasSubtable or not properties.show_expanded|default(false) or not properties.replace_row_with_subtable|default(false) %}
+ {%- set showRow = subtablesAreDisabled
+ or not rowHasSubtable
+ or not properties.visualization_properties.show_expanded|default(false)
+ or not properties.visualization_properties.replace_row_with_subtable|default(false) -%}
+
+ {% if showRow %}
<tr {% if rowHasSubtable %}id="{{ row.getIdSubDataTable() }}"{% endif %}
class="{{ row.getMetadata('css_class') }} {% if rowHasSubtable %}subDataTable{% endif %}{% if shouldHighlightRow %} highlight{% endif %}">
{% for column in properties.columns_to_display %}
@@ -19,8 +26,8 @@
{% endif %}
{# display subtable if present and showing expanded datatable #}
- {% if properties.show_expanded|default(false) and rowHasSubtable %}
- {% include properties.subtable_template with {'dataTable': row.getSubtable()} %}
+ {% if properties.visualization_properties.show_expanded|default(false) and rowHasSubtable %}
+ {% include properties.visualization_properties.subtable_template with {'dataTable': row.getSubtable()} %}
{% endif %}
{% endfor %}
</tbody>
diff --git a/plugins/CoreVisualizations/templates/_dataTableViz_jqplotGraph.twig b/plugins/CoreVisualizations/templates/_dataTableViz_jqplotGraph.twig
new file mode 100644
index 0000000000..e980275ac6
--- /dev/null
+++ b/plugins/CoreVisualizations/templates/_dataTableViz_jqplotGraph.twig
@@ -0,0 +1,10 @@
+<div class="jqplot-graph">
+ <div class="piwik-graph"
+ style="width: {{ properties.visualization_properties.graph_width }}; height: {{ properties.visualization_properties.graph_height }};"
+ data-data="{{ data|e('html') }}"
+ {% if properties.visualization_properties.external_series_toggle %}
+ data-external-series-toggle="{{ properties.visualization_properties.external_series_toggle }}"
+ data-external-series-show-all="{% if properties.visualization_properties.external_series_toggle_show_all %}1{% else %}0{% endif %}"
+ {% endif %}>
+ </div>
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/templates/_dataTableViz_tagCloud.twig b/plugins/CoreVisualizations/templates/_dataTableViz_tagCloud.twig
index 1513daca34..1513daca34 100644
--- a/plugins/CoreHome/templates/_dataTableViz_tagCloud.twig
+++ b/plugins/CoreVisualizations/templates/_dataTableViz_tagCloud.twig
diff --git a/plugins/DBStats/DBStats.php b/plugins/DBStats/DBStats.php
index 433f682c9f..e3821800cc 100644
--- a/plugins/DBStats/DBStats.php
+++ b/plugins/DBStats/DBStats.php
@@ -107,7 +107,7 @@ class DBStats extends \Piwik\Plugin
$result['show_offset_information'] = false;
$result['show_pagination_control'] = false;
- $result['show_all_ticks'] = true;
+ $result['visualization_properties']['jqplot_graph']['show_all_ticks'] = true;
// translate the labels themselves
$valueToTranslationStr = array(
@@ -148,8 +148,8 @@ class DBStats extends \Piwik\Plugin
$this->addPresentationFilters($result);
$result['title'] = Piwik_Translate('DBStats_MetricTables');
- $result['relatedReports'] = array(
- 'DBStats.getMetricDataSummaryByYear' => Piwik_Translate('DBStats_MetricDataByYear')
+ $result['related_reports'] = array(
+ 'DBStats.getMetricDataSummaryByYear' => Piwik_Translate('DBStats_MetricDataByYear')
);
return $result;
@@ -163,8 +163,8 @@ class DBStats extends \Piwik\Plugin
$result['translations']['label'] = Piwik_Translate('CoreHome_PeriodYear');
$result['title'] = Piwik_Translate('DBStats_MetricDataByYear');
- $result['relatedReports'] = array(
- 'DBStats.getMetricDataSummary' => Piwik_Translate('DBStats_MetricTables')
+ $result['related_reports'] = array(
+ 'DBStats.getMetricDataSummary' => Piwik_Translate('DBStats_MetricTables')
);
return $result;
@@ -177,7 +177,7 @@ class DBStats extends \Piwik\Plugin
$this->addPresentationFilters($result);
$result['title'] = Piwik_Translate('DBStats_ReportTables');
- $result['relatedReports'] = array(
+ $result['related_reports'] = array(
'DBStats.getReportDataSummaryByYear' => Piwik_Translate('DBStats_ReportDataByYear')
);
@@ -192,8 +192,8 @@ class DBStats extends \Piwik\Plugin
$result['translations']['label'] = Piwik_Translate('CoreHome_PeriodYear');
$result['title'] = Piwik_Translate('DBStats_ReportDataByYear');
- $result['relatedReports'] = array(
- 'DBStats.getReportDataSummary' => Piwik_Translate('DBStats_ReportTables')
+ $result['related_reports'] = array(
+ 'DBStats.getReportDataSummary' => Piwik_Translate('DBStats_ReportTables')
);
return $result;
@@ -258,7 +258,7 @@ class DBStats extends \Piwik\Plugin
$properties['show_tag_cloud'] = false;
$properties['show_table_all_columns'] = false;
$properties['keep_summary_row'] = true;
- $properties['disable_row_evolution'] = true;
+ $properties['visualization_properties']['table']['disable_row_evolution'] = true;
$properties['translations'] = array(
'label' => Piwik_Translate('DBStats_Table'),
'year' => Piwik_Translate('CoreHome_PeriodYear'),
diff --git a/plugins/Dashboard/javascripts/dashboard.js b/plugins/Dashboard/javascripts/dashboard.js
index e23ff669a4..e2a73be1d3 100644
--- a/plugins/Dashboard/javascripts/dashboard.js
+++ b/plugins/Dashboard/javascripts/dashboard.js
@@ -12,9 +12,9 @@ function initDashboard(dashboardId, dashboardLayout) {
$('#periodString').after($('#dashboardSettings'));
var leftMargin = $('#periodString')[0].offsetWidth;
- var segmentSelector = $('.segmentationContainer:visible');
+ var segmentSelector = $('#segmentEditorPanel:visible');
if(segmentSelector.length) {
- segmentSelector = $($('.segmentationContainer:visible')[0]);
+ segmentSelector = $($('#segmentEditorPanel:visible')[0]);
leftMargin = segmentSelector.position().left + segmentSelector.outerWidth();
}
$('#dashboardSettings').css({left: leftMargin});
diff --git a/plugins/Dashboard/javascripts/dashboardObject.js b/plugins/Dashboard/javascripts/dashboardObject.js
index 67614dd231..a91b9ad46a 100644
--- a/plugins/Dashboard/javascripts/dashboardObject.js
+++ b/plugins/Dashboard/javascripts/dashboardObject.js
@@ -409,9 +409,7 @@
}
//launch 'sortable' property on every dashboard widgets
- if ($( "div.col", dashboardElement ).is( ":data('ui-sortable')" )) {
- $( "div.col", dashboardElement ).sortable('destroy');
- }
+ $( "div.col:data('ui-sortable')", dashboardElement ).sortable('destroy');
$('div.col', dashboardElement)
.sortable({
diff --git a/plugins/Dashboard/stylesheets/dashboard.less b/plugins/Dashboard/stylesheets/dashboard.less
index a287a438fc..f00fe46366 100644
--- a/plugins/Dashboard/stylesheets/dashboard.less
+++ b/plugins/Dashboard/stylesheets/dashboard.less
@@ -8,9 +8,24 @@
}
.top_controls_inner {
- position: relative;
- height: 32px;
- padding-bottom: 20px;
+ clear: left;
+ position: relative;
+ height: 32px;
+ padding-bottom: 20px;
+}
+
+@media all and (max-width: 749px) {
+ .top_controls {
+ height: auto;
+ }
+
+ .top_controls #periodString,
+ .top_controls #dashboardSettings,
+ .top_controls #segmentEditorPanel {
+ position: static;
+ margin: 0 0 10px;
+ float: none;
+ }
}
#dashboardWidgetsArea {
@@ -43,7 +58,7 @@
}
.col.width-33 {
- width: 33%;
+ width: 33.33%;
}
.col.width-30 {
@@ -65,6 +80,7 @@
overflow: hidden;
border-radius: 4px;
font-size: 14px;
+ z-index: 1;
}
.widgetHover {
@@ -86,7 +102,7 @@
.widgetContent.loading {
opacity: 0.5;
- background: url(../../../plugins/Zeitgeist/images/loading-blue.gif) no-repeat top right;
+ background: url(plugins/Zeitgeist/images/loading-blue.gif) no-repeat top right;
}
.widget h2 {
@@ -95,10 +111,12 @@
font-weight: bold;
}
+.widget p {
+ margin-left: 10px;
+}
+
.widgetTop {
- background: #b5b0a7 url(../../../plugins/Zeitgeist/images/dashboard_h_bg.png) repeat-x 0 0;
- border-radius: 4px 4px 0 0;
- width: 100%;
+ background: #b5b0a7 url(plugins/Zeitgeist/images/dashboard_h_bg.png) repeat-x 0 0;
cursor: move;
font-size: 10pt;
font-weight: bold;
@@ -106,7 +124,7 @@
}
.widgetTopHover {
- background: #B0A798 url(../../../plugins/Zeitgeist/images/dashboard_h_bg_hover.png) repeat-x 0 0;
+ background: #B0A798 url(plugins/Zeitgeist/images/dashboard_h_bg_hover.png) repeat-x 0 0;
}
.widgetName {
@@ -117,6 +135,11 @@
text-shadow: 1px 1px 2px #7e7363;
}
+// Overriding some dataTable css for better dashboard display
+.widget .dataTableWrapper {
+ width: 100% !important;
+}
+
.button {
cursor: pointer;
}
@@ -157,7 +180,7 @@
}
.ui-dialog-buttonset input[type=button], .ui-dialog-buttonset button{
- background: #B5B0A7 url(../../../plugins/Zeitgeist/images/dashboard_h_bg_hover.png) repeat-x 0 0 !important;
+ background: #B5B0A7 url(plugins/Zeitgeist/images/dashboard_h_bg_hover.png) repeat-x 0 0 !important;
color: #fff !important;
border: 0 !important;
font-size: 12px !important;
@@ -215,6 +238,7 @@
color: #444;
font-size: 14px;
cursor: pointer;
+ overflow: hidden;
}
#dashboardSettings:hover {
@@ -223,7 +247,7 @@
}
#dashboardSettings > span {
- background: url(../../../plugins/Zeitgeist/images/sort_subtable_desc.png) right center no-repeat;
+ background: url(plugins/Zeitgeist/images/sort_subtable_desc.png) right center no-repeat;
padding-right: 20px;
display: block;
}
@@ -358,7 +382,7 @@ ul.widgetpreview-widgetlist li {
}
.widgetpreview-base li.widgetpreview-choosen {
- background: #e4e2d7 url(../../../plugins/Zeitgeist/images/arr_r.png) no-repeat right 6px;
+ background: #e4e2d7 url(plugins/Zeitgeist/images/arr_r.png) no-repeat right 6px;
color: #255792;
font-weight: bold;
}
@@ -487,5 +511,9 @@ div.widgetpreview-preview {
.col.width-30,
.col.width-25 {
width: 100%;
+ .widget {
+ margin-right: 0;
+ }
}
+
} \ No newline at end of file
diff --git a/plugins/Dashboard/templates/index.twig b/plugins/Dashboard/templates/index.twig
index cc86a56715..e16fb1955e 100644
--- a/plugins/Dashboard/templates/index.twig
+++ b/plugins/Dashboard/templates/index.twig
@@ -4,8 +4,9 @@
<div id="Dashboard">
<ul>
{% for dashboard in dashboards %}
- <li class="dashboardMenuItem" id="Dashboard_embeddedIndex_{{ dashboard.iddashboard }}"><a
- href="javascript:$('#dashboardWidgetsArea').dashboard('loadDashboard', {{ dashboard.iddashboard }});">{{ dashboard.name|escape }}</a></li>
+ <li class="dashboardMenuItem" id="Dashboard_embeddedIndex_{{ dashboard.iddashboard }}">
+ <a href="javascript:$('#dashboardWidgetsArea').dashboard('loadDashboard', {{ dashboard.iddashboard }});">{{ dashboard.name|escape }}</a>
+ </li>
{% endfor %}
</ul>
</div>
diff --git a/plugins/DevicesDetection/DevicesDetection.php b/plugins/DevicesDetection/DevicesDetection.php
index 2e8902d6cf..d207cdc285 100644
--- a/plugins/DevicesDetection/DevicesDetection.php
+++ b/plugins/DevicesDetection/DevicesDetection.php
@@ -317,9 +317,9 @@ class DevicesDetection extends \Piwik\Plugin
return array(
'show_search' => false,
'show_exclude_low_population' => false,
- 'translations' => array('label' => Piwik_Translate("DevicesDetection_dataTableLabelSystemFamily")),
- 'title' => Piwik_Translate('DeviceDetection_OperatingSystemFamilies'),
- 'relatedReports' => $this->getOsRelatedReports()
+ 'translations' => array('label' => Piwik_Translate("DevicesDetection_dataTableLabelSystemFamily")),
+ 'title' => Piwik_Translate('DeviceDetection_OperatingSystemFamilies'),
+ 'related_reports' => $this->getOsRelatedReports()
);
}
@@ -328,9 +328,9 @@ class DevicesDetection extends \Piwik\Plugin
return array(
'show_search' => false,
'show_exclude_low_population' => false,
- 'translations' => array('label' => Piwik_Translate("DevicesDetection_dataTableLabelSystemVersion")),
- 'title' => Piwik_Translate('DeviceDetection_OperatingSystemVersions'),
- 'relatedReports' => $this->getOsRelatedReports()
+ 'translations' => array('label' => Piwik_Translate("DevicesDetection_dataTableLabelSystemVersion")),
+ 'title' => Piwik_Translate('DeviceDetection_OperatingSystemVersions'),
+ 'related_reports' => $this->getOsRelatedReports()
);
}
@@ -339,9 +339,9 @@ class DevicesDetection extends \Piwik\Plugin
return array(
'show_search' => false,
'show_exclude_low_population' => false,
- 'translations' => array('label' => Piwik_Translate("DevicesDetection_dataTableLabelBrowserFamily")),
- 'title' => Piwik_Translate('DevicesDetection_BrowsersFamily'),
- 'relatedReports' => $this->getBrowserRelatedReports()
+ 'translations' => array('label' => Piwik_Translate("DevicesDetection_dataTableLabelBrowserFamily")),
+ 'title' => Piwik_Translate('DevicesDetection_BrowsersFamily'),
+ 'related_reports' => $this->getBrowserRelatedReports()
);
}
@@ -350,8 +350,8 @@ class DevicesDetection extends \Piwik\Plugin
return array(
'show_search' => false,
'show_exclude_low_population' => false,
- 'translations' => array('label' => Piwik_Translate("DevicesDetection_dataTableLabelBrowserVersion")),
- 'relatedReports' => $this->getBrowserRelatedReports()
+ 'translations' => array('label' => Piwik_Translate("DevicesDetection_dataTableLabelBrowserVersion")),
+ 'related_reports' => $this->getBrowserRelatedReports()
);
}
@@ -370,4 +370,4 @@ class DevicesDetection extends \Piwik\Plugin
'DevicesDetection.getBrowserVersions' => Piwik_Translate('DevicesDetection_BrowserVersions')
);
}
-}
+} \ No newline at end of file
diff --git a/plugins/DevicesDetection/lang/en.php b/plugins/DevicesDetection/lang/en.php
index 93d4504957..7d1d82ae50 100644
--- a/plugins/DevicesDetection/lang/en.php
+++ b/plugins/DevicesDetection/lang/en.php
@@ -13,15 +13,15 @@ $translations = array(
"DevicesDetection_dataTableLabelBrowserFamily" => "Browser family",
"DevicesDetection_dataTableLabelBrowserVersion" => "Browser version",
// Title translations for reports
- "DevicesDetection_DeviceType" => "Device types report",
- "DevicesDetection_DeviceBrand" => "Device manufacturers report",
- "DevicesDetection_DeviceModel" => "Device model report",
+// "DevicesDetection_DeviceType" => "Device types report",
+// "DevicesDetection_DeviceBrand" => "Device manufacturers report",
+// "DevicesDetection_DeviceModel" => "Device model report",
'DeviceDetection_OperatingSystemVersions' => "Operating System versions",
'DeviceDetection_OperatingSystemFamilies' => "Operating System families",
'DevicesDetection_BrowsersFamily' => 'Browsers families',
'DevicesDetection_BrowserVersions' => 'Browser versions',
// Evolution graph title translations
- "DevicesDetection_DeviceType" => "Device type",
+ 'DevicesDetection_DeviceType' => "Device type",
'DevicesDetection_DeviceBrand' => 'Device brand',
'DevicesDetection_DeviceModel' => 'Device model',
// 'DevicesDetection_OS' => 'Device operating system',
diff --git a/plugins/ExampleRssWidget/Controller.php b/plugins/ExampleRssWidget/Controller.php
index 45e5a44cdc..a8a5eb7247 100644
--- a/plugins/ExampleRssWidget/Controller.php
+++ b/plugins/ExampleRssWidget/Controller.php
@@ -44,6 +44,9 @@ class Controller extends \Piwik\Controller
}
}
+ /**
+ * @param \Exception $e
+ */
protected function error($e)
{
echo '<div class="pk-emptyDataTable">'
diff --git a/plugins/ExampleUI/Controller.php b/plugins/ExampleUI/Controller.php
index 201610f7e7..dc1415b411 100644
--- a/plugins/ExampleUI/Controller.php
+++ b/plugins/ExampleUI/Controller.php
@@ -26,12 +26,20 @@ class Controller extends \Piwik\Controller
$view->translations['label'] = "Hour of day";
$view->filter_sort_column = 'label';
$view->filter_sort_order = 'asc';
- $view->graph_limit = 24;
$view->filter_limit = 24;
$view->show_exclude_low_population = false;
$view->show_table_all_columns = false;
- $view->disable_row_evolution = true;
$view->y_axis_unit = '°C'; // useful if the user requests the bar graph
+ $view->visualization_properties->setForVisualization(
+ 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\HtmlTable',
+ 'disable_row_evolution',
+ true
+ );
+ $view->visualization_properties->setForVisualization(
+ 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph',
+ 'max_graph_elements',
+ 24
+ );
echo $view->render();
}
@@ -57,7 +65,7 @@ class Controller extends \Piwik\Controller
'graphVerticalBar', 'ExampleUI.getTemperatures', $controllerAction = 'ExampleUI.barGraph');
$view->translations['value'] = "Temperature";
$view->y_axis_unit = '°C';
- $view->graph_limit = 24;
+ $view->visualization_properties->max_graph_elements = 24;
$view->show_footer = false;
echo $view->render();
}
@@ -68,7 +76,7 @@ class Controller extends \Piwik\Controller
'graphPie', 'ExampleUI.getPlanetRatios', $controllerAction = 'ExampleUI.pieGraph');
$view->columns_to_display = array('value');
$view->translations['value'] = "times the diameter of Earth";
- $view->graph_limit = 10;
+ $view->visualization_properties->max_graph_elements = 10;
$view->show_footer_icons = false;
echo $view->render();
}
diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php
index c9e10f4074..7cb2353a0b 100644
--- a/plugins/Goals/Controller.php
+++ b/plugins/Goals/Controller.php
@@ -290,7 +290,7 @@ class Controller extends \Piwik\Controller
$view->translations[$columnName] = $columnTranslation;
}
$view->columns_to_display = $columns;
- $view->selectable_columns = $selectableColumns;
+ $view->visualization_properties->selectable_columns = $selectableColumns;
$langString = $idGoal ? 'Goals_SingleGoalOverviewDocumentation' : 'Goals_GoalsOverviewDocumentation';
$view->documentation = Piwik_Translate($langString, '<br />');
diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php
index 2d3bd0de27..f15569affb 100644
--- a/plugins/Goals/Goals.php
+++ b/plugins/Goals/Goals.php
@@ -88,18 +88,18 @@ class Goals extends \Piwik\Plugin
public function getListHooksRegistered()
{
$hooks = array(
- 'AssetManager.getJsFiles' => 'getJsFiles',
- 'AssetManager.getCssFiles' => 'getCssFiles',
- 'Common.fetchWebsiteAttributes' => 'fetchGoalsFromDb',
- 'ArchiveProcessing_Day.compute' => 'archiveDay',
- 'ArchiveProcessing_Period.compute' => 'archivePeriod',
- 'API.getReportMetadata.end' => 'getReportMetadata',
- 'API.getSegmentsMetadata' => 'getSegmentsMetadata',
- 'WidgetsList.add' => 'addWidgets',
- 'Menu.add' => 'addMenus',
- 'SitesManager.deleteSite' => 'deleteSiteGoals',
- 'Goals.getReportsWithGoalMetrics' => 'getActualReportsWithGoalMetrics',
- 'ViewDataTable.getReportDisplayProperties' => 'getReportDisplayProperties', // TODO: ViewDataTable should get ALL once
+ 'AssetManager.getJsFiles' => 'getJsFiles',
+ 'AssetManager.getCssFiles' => 'getCssFiles',
+ 'Common.fetchWebsiteAttributes' => 'fetchGoalsFromDb',
+ 'ArchiveProcessing_Day.compute' => 'archiveDay',
+ 'ArchiveProcessing_Period.compute' => 'archivePeriod',
+ 'API.getReportMetadata.end' => 'getReportMetadata',
+ 'API.getSegmentsMetadata' => 'getSegmentsMetadata',
+ 'WidgetsList.add' => 'addWidgets',
+ 'Menu.add' => 'addMenus',
+ 'SitesManager.deleteSite' => 'deleteSiteGoals',
+ 'Goals.getReportsWithGoalMetrics' => 'getActualReportsWithGoalMetrics',
+ 'ViewDataTable.getReportDisplayProperties' => 'getReportDisplayProperties',
);
return $hooks;
}
diff --git a/plugins/Goals/templates/_listGoalEdit.twig b/plugins/Goals/templates/_listGoalEdit.twig
index c7acc0c553..b8803ff577 100644
--- a/plugins/Goals/templates/_listGoalEdit.twig
+++ b/plugins/Goals/templates/_listGoalEdit.twig
@@ -51,7 +51,7 @@
"url": "{{ 'Goals_VisitUrl'|translate }}",
"title": "{{ 'Goals_VisitPageTitle'|translate }}",
"external_website": "{{ 'Goals_ClickOutlink'|translate }}"
- }
+ };
$(document).ready(function () {
// translation of the goal "match attribute" to human readable description
diff --git a/plugins/Installation/Controller.php b/plugins/Installation/Controller.php
index 9160ca4c63..23333872be 100644
--- a/plugins/Installation/Controller.php
+++ b/plugins/Installation/Controller.php
@@ -623,8 +623,8 @@ class Controller extends \Piwik\Controller\Admin
/**
* Redirect to next step
*
- * @param string Current step
- * @return none
+ * @param string $currentStep Current step
+ * @return void
*/
protected function redirectToNextStep($currentStep)
{
@@ -637,7 +637,7 @@ class Controller extends \Piwik\Controller\Admin
/**
* Skip this step (typically to mark the current function as completed)
*
- * @param string function name
+ * @param string $step function name
*/
protected function skipThisStep($step)
{
diff --git a/plugins/Installation/FormDatabaseSetup.php b/plugins/Installation/FormDatabaseSetup.php
index a1f58c6c78..c67d8b8470 100644
--- a/plugins/Installation/FormDatabaseSetup.php
+++ b/plugins/Installation/FormDatabaseSetup.php
@@ -52,7 +52,7 @@ class FormDatabaseSetup extends QuickForm2
$user->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('Installation_DatabaseSetupLogin')));
$requiredPrivileges = Rule_checkUserPrivileges::getRequiredPrivilegesPretty();
$user->addRule('checkUserPrivileges',
- Piwik_Translate('Installation_InsufficientPrivileges', $requiredPrivileges . '<br/><br/>') .
+ Piwik_Translate('Installation_InsufficientPrivilegesMain', $requiredPrivileges . '<br/><br/>') .
Piwik_Translate('Installation_InsufficientPrivilegesHelp'));
$this->addElement('password', 'password')
@@ -289,7 +289,7 @@ class Rule_checkUserPrivileges extends HTML_QuickForm2_Rule
/**
* Drops the tables created by the privilege checking queries, if they exist.
*
- * @param $db The database object to use.
+ * @param \Piwik\Db $db The database object to use.
*/
private function dropExtraTables($db)
{
diff --git a/plugins/Installation/stylesheets/installation.css b/plugins/Installation/stylesheets/installation.css
index 2cdd581b1a..354f74b539 100644
--- a/plugins/Installation/stylesheets/installation.css
+++ b/plugins/Installation/stylesheets/installation.css
@@ -29,6 +29,10 @@ p {
padding: 20px 30px 40px;
}
+#installationPage #logo {
+ height: auto;
+}
+
h2 {
font-size: 20px;
color: #666666;
@@ -106,7 +110,7 @@ code {
}
/* Cadre general */
-#main {
+#installationPage {
margin: 30px 5px 5px;
text-align: left;
}
diff --git a/plugins/Installation/templates/layout.twig b/plugins/Installation/templates/layout.twig
index 705b40d492..d7b8fb4ff5 100644
--- a/plugins/Installation/templates/layout.twig
+++ b/plugins/Installation/templates/layout.twig
@@ -16,7 +16,7 @@
{% endif %}
</head>
<body>
-<div id="main">
+<div id="installationPage">
<div id="content">
<div id="logo">
<img id="title" width='160' src="plugins/Zeitgeist/images/logo.png"/> &nbsp;&nbsp;&nbsp;<span
diff --git a/plugins/Live/API.php b/plugins/Live/API.php
index a1d2b9248f..e8fa49ed30 100644
--- a/plugins/Live/API.php
+++ b/plugins/Live/API.php
@@ -58,6 +58,10 @@ require_once PIWIK_INCLUDE_PATH . '/plugins/Live/Visitor.php';
*/
class API
{
+ const VISITOR_PROFILE_MAX_VISITS_TO_AGGREGATE = 100;
+ const VISITOR_PROFILE_MAX_VISITS_TO_SHOW = 10;
+ const VISITOR_PROFILE_DATE_FORMAT = '%day% %shortMonth% %longYear%';
+
static private $instance = null;
/**
@@ -161,6 +165,154 @@ class API
}
/**
+ * TODO
+ * TODO: add abandoned cart info.
+ * TODO: check for most recent vs. first visit
+ * TODO: make sure ecommerce is enabled for site, check for goals plugin, etc.
+ */
+ public function getVisitorProfile($idSite, $period, $date, $idVisitor, $segment = false)
+ {
+ if ($segment !== false) {
+ $segment .= '&';
+ }
+ $segment .= 'visitorId==' . $idVisitor; // TODO what happens when visitorId is in the segment?
+
+ $visits = $this->getLastVisitsDetails($idSite, $period, $date, $segment, $filter_limit = self::VISITOR_PROFILE_MAX_VISITS_TO_AGGREGATE);
+ if ($visits->getRowsCount() == 0) {
+ return array();
+ }
+
+ $result = array();
+
+ // use the most recent visit for IP/browser/OS/etc. info
+ // TODO: could just do all of this in twig/JS... really need to do it here?
+ $mostRecentVisit = $visits->getFirstRow();
+ $result['latestVisitIp'] = $mostRecentVisit->getColumn('visitIp');
+ $result['visitorId'] = $mostRecentVisit->getColumn('visitorId');
+ $result['browserCode'] = $mostRecentVisit->getColumn('browserCode');
+ $result['browserName'] = Piwik_UserSettings_getBrowserFromBrowserVersion($mostRecentVisit->getColumn('browserName'));
+ $result['browserLogo'] = $mostRecentVisit->getColumn('browserIcon');
+ $result['operatingSystemCode'] = $mostRecentVisit->getColumn('operatingSystemCode');
+ $result['operatingSystemShortName'] = $mostRecentVisit->getColumn('operatingSystemShortName');
+ $result['operatingSystemLogo'] = $mostRecentVisit->getColumn('operatingSystemIcon');
+ $result['resolution'] = $mostRecentVisit->getColumn('resolution');
+ $result['customVariables'] = $mostRecentVisit->getColumn('customVariables');
+
+ // aggregate all requested visits info for total_* info
+ $result['totalVisits'] = 0;
+ $result['totalVisitDuration'] = 0;
+ $result['totalActionCount'] = 0;
+ $result['totalGoalConversions'] = 0;
+ $result['totalEcommerceConversions'] = 0;
+ $result['totalEcommerceRevenue'] = 0;
+ $result['totalEcommerceItems'] = 0;
+ $result['totalAbandonedCarts'] = 0;
+ $result['totalAbandonedCartsRevenue'] = 0;
+ $result['totalAbandonedCartsItems'] = 0;
+ foreach ($visits->getRows() as $visit) {
+ ++$result['totalVisits'];
+
+ $result['totalVisitDuration'] += $visit->getColumn('visitDuration');
+ $result['totalActionCount'] += $visit->getColumn('actions');
+ $result['totalGoalConversions'] += $visit->getColumn('goalConversions');
+
+ // individual goal conversions are stored in action details
+ foreach ($visit->getColumn('actionDetails') as $action) {
+ if ($action['type'] == 'goal') { // handle goal conversion
+ $idGoal = $action['goalId'];
+
+ if (!isset($result['totalConversionsByGoal'][$idGoal])) {
+ $result['totalConversionsByGoal'][$idGoal] = 0;
+ }
+ ++$result['totalConversionsByGoal'][$idGoal];
+
+ if (!empty($action['revenue'])) {
+ if (!isset($result['totalRevenueByGoal'][$idGoal])) {
+ $result['totalRevenueByGoal'][$idGoal] = 0;
+ }
+ $result['totalRevenueByGoal'][$idGoal] += $action['revenue'];
+ }
+ } else if ($action['type'] == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) { // handle ecommerce order
+ ++$result['totalEcommerceConversions'];
+ $result['totalEcommerceRevenue'] += $action['revenue'];
+ $result['totalEcommerceItems'] += $action['items'];
+ } else if ($action['type'] == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART) { // handler abandoned cart
+ ++$result['totalAbandonedCarts'];
+ $result['totalAbandonedCartsRevenue'] += $action['revenue'];
+ $result['totalAbandonedCartsItems'] += $action['items'];
+ }
+ }
+ }
+
+ $result['totalVisitDurationPretty'] = Piwik::getPrettyTimeFromSeconds($result['totalVisitDuration']);
+
+ // use requested visits for first/last visit info
+ $result['firstVisit'] = $this->getVisitorProfileVisitSummary(end($visits->getRows()));
+ $result['lastVisit'] = $this->getVisitorProfileVisitSummary(reset($visits->getRows()));
+
+ // use N most recent visits for last_visits
+ $visits->deleteRowsOffset(self::VISITOR_PROFILE_MAX_VISITS_TO_SHOW);
+ $result['lastVisits'] = $visits;
+
+ // use the right date format for the pretty server date
+ $timezone = Site::getTimezoneFor($idSite);
+ foreach ($result['lastVisits']->getRows() as $visit) {
+ $dateTimeVisitFirstAction = Date::factory($visit->getColumn('firstActionTimestamp'), $timezone);
+ $dateTimePretty = $dateTimeVisitFirstAction->getLocalized(self::VISITOR_PROFILE_DATE_FORMAT);
+
+ $visit->setColumn('serverDatePrettyFirstAction', $dateTimePretty);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns a summary for an important visit. Used to describe the first & last visits of a visitor.
+ *
+ * @param Piwik\DataTable\Row $visit
+ */
+ private function getVisitorProfileVisitSummary($visit)
+ {
+ $today = Date::today();
+
+ $serverDate = $visit->getColumn('serverDate');
+ return array(
+ 'date' => $serverDate,
+ 'prettyDate' => Date::factory($serverDate)->getLocalized(self::VISITOR_PROFILE_DATE_FORMAT),
+ 'daysAgo' => (int)Date::secondsToDays($today->getTimestamp() - Date::factory($serverDate)->getTimestamp()),
+ 'referralSummary' => $this->getReferrerSummaryForVisit($visit),
+ );
+ }
+
+ /**
+ * Returns a summary for a visit's referral.
+ *
+ * @param Piwik\DataTable\Row $visit
+ */
+ private function getReferrerSummaryForVisit($visit)
+ {
+ $referrerType = $visit->getColumn('referrerType');
+ if ($referrerType === false
+ || $referrerType == 'direct'
+ ) {
+ $result = Piwik_Translate('Referers_DirectEntry');
+ } else if ($referrerType == 'search') {
+ $result = $visit->getColumn('referrerName');
+
+ $keyword = $visit->getColumn('referrerKeyword');
+ if ($keyword !== false) {
+ $result .= ' (' . $keyword . ')';
+ }
+ } else if ($referrerType == 'campaign') {
+ $result = Piwik_Translate('Referers_ColumnCampaign') . ' (' . $visit->getColumn('referrerName') . ')';
+ } else {
+ $result = $visit->getColumn('referrerName');
+ }
+
+ return $result;
+ }
+
+ /**
* @deprecated
*/
public function getLastVisits($idSite, $filter_limit = 10, $minTimestamp = false)
diff --git a/plugins/Live/Controller.php b/plugins/Live/Controller.php
index fd961c923f..a845c468b0 100644
--- a/plugins/Live/Controller.php
+++ b/plugins/Live/Controller.php
@@ -17,6 +17,7 @@ use Piwik\Config;
use Piwik\Plugins\Live\API;
use Piwik\ViewDataTable;
use Piwik\View;
+use Piwik\FrontController;
/**
* @package Live
@@ -101,6 +102,7 @@ class Controller extends \Piwik\Controller
*/
public function getVisitorLog($fetch = false)
{
+ $test = array(); $str = (string)$test;
return $this->getLastVisitsDetails($fetch);
}
@@ -132,4 +134,37 @@ class Controller extends \Piwik\Controller
$view->pisToday = $today['actions'];
return $view;
}
+
+ /**
+ * TODO
+ */
+ public function getVisitorProfilePopup()
+ {
+ $idSite = Common::getRequestVar('idSite', null, 'int');
+
+ $view = new View('@Live/getVisitorProfilePopup.twig');
+ $view->idSite = $idSite;
+ $view->goals = Piwik_Goals_API::getInstance()->getGoals($idSite);
+ $view->visitorData = Request::processRequest('Live.getVisitorProfile');
+ $view->userCountryMap = $this->getUserCountryMapForVisitorProfile();
+ echo $view->render();
+ }
+
+ private function getUserCountryMapForVisitorProfile()
+ {
+ if (empty($_GET['segment'])) {
+ $_GET['segment'] = '';
+ $originalSegment = '';
+ } else {
+ $_GET['segment'] .= '&';
+ $originalSegment = $_GET['segment'];
+ }
+ $_GET['segment'] .= 'visitorId==' . Common::getRequestVar('idVisitor');
+
+ $result = FrontController::getInstance()->fetchDispatch('UserCountryMap', 'visitorMap', array('fetch' => true)); // TODO: check if plugin is enabled?
+
+ $_GET['segment'] = $originalSegment;
+
+ return $result;
+ }
} \ No newline at end of file
diff --git a/plugins/Live/Live.php b/plugins/Live/Live.php
index 7ef67b56b5..bbdd142b43 100644
--- a/plugins/Live/Live.php
+++ b/plugins/Live/Live.php
@@ -36,6 +36,7 @@ class Live extends \Piwik\Plugin
public function getCssFiles(&$cssFiles)
{
$cssFiles[] = "plugins/Live/stylesheets/live.less";
+ $cssFiles[] = "plugins/Live/stylesheets/visitor_profile.less";
}
public function getJsFiles(&$jsFiles)
@@ -72,18 +73,22 @@ class Live extends \Piwik\Plugin
'filter_limit' => 20,
'show_offset_information' => false,
'show_exclude_low_population' => false,
- 'show_all_views_icons' => false,
- 'show_table_all_columns' => false,
- 'show_export_as_rss_feed' => false,
- 'disable_row_actions' => true,
- 'documentation' => Piwik_Translate('Live_VisitorLogDocumentation', array('<br />', '<br />')),
- 'custom_parameters' => array(
+ 'show_all_views_icons' => false,
+ 'show_table_all_columns' => false,
+ 'show_export_as_rss_feed' => false,
+ 'documentation' => Piwik_Translate('Live_VisitorLogDocumentation', array('<br />', '<br />')),
+ 'custom_parameters' => array(
// set a very high row count so that the next link in the footer of the data table is always shown
'totalRows' => 10000000,
'filterEcommerce' => Common::getRequestVar('filterEcommerce', 0, 'int'),
'pageUrlNotDefined' => Piwik_Translate('General_NotDefined', Piwik_Translate('Actions_ColumnPageURL'))
),
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_row_actions' => true,
+ )
+ )
);
}
-}
+} \ No newline at end of file
diff --git a/plugins/Live/images/REMOVE_ME_avatar.jpg b/plugins/Live/images/REMOVE_ME_avatar.jpg
new file mode 100644
index 0000000000..dfd7ec81de
--- /dev/null
+++ b/plugins/Live/images/REMOVE_ME_avatar.jpg
Binary files differ
diff --git a/plugins/Live/images/REMOVE_ME_chart.png b/plugins/Live/images/REMOVE_ME_chart.png
new file mode 100644
index 0000000000..5f8f03ad6a
--- /dev/null
+++ b/plugins/Live/images/REMOVE_ME_chart.png
Binary files differ
diff --git a/plugins/Live/images/REMOVE_ME_map.jpg b/plugins/Live/images/REMOVE_ME_map.jpg
new file mode 100644
index 0000000000..ffae900c21
--- /dev/null
+++ b/plugins/Live/images/REMOVE_ME_map.jpg
Binary files differ
diff --git a/plugins/Live/images/avatar_frame.png b/plugins/Live/images/avatar_frame.png
new file mode 100644
index 0000000000..23eccfd5fb
--- /dev/null
+++ b/plugins/Live/images/avatar_frame.png
Binary files differ
diff --git a/plugins/Live/images/paperclip.png b/plugins/Live/images/paperclip.png
new file mode 100644
index 0000000000..b38d33caa1
--- /dev/null
+++ b/plugins/Live/images/paperclip.png
Binary files differ
diff --git a/plugins/Live/images/visitor_profile_background.jpg b/plugins/Live/images/visitor_profile_background.jpg
new file mode 100644
index 0000000000..082d637dcf
--- /dev/null
+++ b/plugins/Live/images/visitor_profile_background.jpg
Binary files differ
diff --git a/plugins/SegmentEditor/images/up_arrow.png b/plugins/Live/images/visitor_profile_close.png
index c7cb24c2b4..ae132b7b2c 100644
--- a/plugins/SegmentEditor/images/up_arrow.png
+++ b/plugins/Live/images/visitor_profile_close.png
Binary files differ
diff --git a/plugins/SegmentEditor/images/slide.png b/plugins/Live/images/visitor_profile_gradient.png
index 657b9a6de5..ac5068b54d 100644
--- a/plugins/SegmentEditor/images/slide.png
+++ b/plugins/Live/images/visitor_profile_gradient.png
Binary files differ
diff --git a/plugins/Live/stylesheets/live.less b/plugins/Live/stylesheets/live.less
index 29d4b03e03..4325471bb6 100644
--- a/plugins/Live/stylesheets/live.less
+++ b/plugins/Live/stylesheets/live.less
@@ -18,7 +18,7 @@
}
#visitsLive .country {
- background: #FFF url(../../CoreHome/images/bullet1.gif) no-repeat scroll 0 0;
+ background: #FFF url(plugins/CoreHome/images/bullet1.gif) no-repeat scroll 0 0;
}
#visitsLive .referer {
diff --git a/plugins/Live/stylesheets/visitor_profile.less b/plugins/Live/stylesheets/visitor_profile.less
new file mode 100644
index 0000000000..6b94c5ce8a
--- /dev/null
+++ b/plugins/Live/stylesheets/visitor_profile.less
@@ -0,0 +1,367 @@
+// TODO: use less variables for height & width
+.visitor-profile {
+ position:relative;
+ width:1149px;
+ height:844px;
+ border:1px solid #a19e96;
+ border-radius:5px;
+ background:url(../images/visitor_profile_background.jpg) repeat;
+ box-shadow:5px 5px 5px rgba(0,0,0,0.22);
+
+ h1 {
+ font-size:18px;
+ color:#7e7363;
+ text-shadow:0 1px 0 rgba(255,255,255,1);
+ margin:9px 0 0 0;
+ padding:0;
+
+ a {
+ font-size:12px;
+ margin-left:3px;
+ }
+ }
+
+ span, strong {
+ display:inline-block;
+ font-size:14px;
+ color:#5e5e5c;
+ line-height:19px;
+ padding-left:4px;
+ }
+
+ p {
+ font-size:13px;
+ color:#5e5e5c;
+ line-height:20px;
+ }
+
+ h2 {
+ display:inline-block;
+ font-size:14px;
+ margin:0 0 0 5px;
+ padding:0;
+ font-weight:bold;
+ color:black;
+ }
+
+ // TODO: iOS icon looks better in mockup
+ // TODO: remove temporary images
+}
+
+.visitor-profile-close {
+ position:absolute;
+ right:-17px;
+ top:-16px;
+ height:35px;
+ width:35px;
+ background:url(../images/visitor_profile_close.png) no-repeat;
+}
+
+.visitor-profile a {
+ text-decoration:none;
+ color:#255792;
+}
+
+.visitor-profile > div {
+ width:100%;
+}
+
+.visitor-profile-info {
+ height:791px;
+ border-top:2px solid #f6f6f6;
+ border-bottom:1px solid #d1cec8;
+ border-radius:5px 5px 0 0;
+ box-shadow:inset 0 25px 15px -10px #e0e0e0, inset 0 -25px 15px -10px #e0e0e0;
+
+ > div {
+ width:573px;
+ height:100%;
+ float:left;
+ border-left:1px solid #d1cec8;
+
+ > div {
+ border-bottom:1px solid #d1cec8;
+ }
+ }
+
+ > div:first-child {
+ border-left:none;
+ }
+
+ > div:last-child {
+ border-bottom:none;
+ }
+}
+
+.visitor-profile-avatar > div {
+ position:relative;
+ float:left;
+ height:145px;
+ margin-right:15px;
+ padding:12px 0 13px;
+}
+
+.visitor-profile-avatar > div:first-child {
+ width:166px;
+ margin-right:0;
+ padding-left:16px;
+
+ > .visitor-profile-image-frame {
+ width:149px;
+ height:154px;
+ background:url(../images/avatar_frame.png) no-repeat;
+
+ > img { // avatar image
+ width:122px;
+ height:120px;
+ margin:11px 0 0 12px;
+ }
+ }
+
+ > img { // paperclip image
+ position:absolute;
+ top:-8px;
+ left:3px;
+ z-index:2;
+ }
+}
+
+.visitor-profile-avatar > div:last-child {
+ margin-right:0;
+}
+
+.visitor-profile-more-info {
+ height:18px;
+ border-top:1px solid #fff;
+ border-radius:0 0 5px 5px;
+ text-align:center;
+ padding:20px 0 13px;
+
+ > a {
+ font-size:14px;
+ text-decoration:none;
+ color:#255792;
+ text-shadow:0 1px 0 rgba(255,255,255,1);
+ }
+}
+
+.visitor-profile-latest-visit-column {
+ padding-top:6px;
+ display:inline-block;
+ vertical-align:top;
+}
+
+.visitor-profile-browser {
+ width:75px;
+ display:inline-block;
+}
+
+.visitor-profile-os {
+ width:75px;
+ display:inline-block;
+}
+
+.visitor-profile-latest-visit-column:first-child {
+ margin-right:9px;
+}
+
+.visitor-profile-avatar ul {
+ width:178px;
+}
+
+.visitor-profile-avatar ul li {
+ display:inline-block;
+ height:24px;
+ border-bottom:1px solid #d1cec8;
+ width:100%;
+}
+
+.visitor-profile-avatar ul li:last-child {
+ border-bottom:none;
+}
+
+.visitor-profile-avatar ul li:first-child {
+ border-bottom:1px solid #d1cec8; // make sure there is a border if only one item is shown in the list
+}
+
+.visitor-profile-map {
+ padding:19px 0 18px 19px;
+}
+
+.visitor-profile-map > div {
+ border-radius:2px;
+ background-color:#fff;
+ width:532px;
+ height:334px;
+ padding:2px;
+}
+
+.visitor-profile-summary,.visitor-profile-important-visits {
+ overflow:hidden;
+ height:116px;
+ padding:5px 0 0 22px;
+}
+
+.visitor-profile-summary > div {
+ margin-top:6px;
+}
+
+.visitor-profile-important-visits {
+
+ > div {
+ float:left;
+ width:265px;
+ height:100%;
+
+ > div {
+ margin-top:13px;
+ }
+ }
+
+ span {
+ padding-left:0;
+ }
+}
+
+.visitor-profile-location {
+ padding:10px 0 4px 19px;
+
+ img {
+ margin-top:-12px;
+ }
+}
+
+.visitor-profile-pages-visited {
+ height:42px;
+ overflow-y:auto;
+ position:relative;
+ margin-right:10px;
+ border-bottom:none!important;
+ padding:8px 18px 10px 13px;
+
+ h1 {
+ margin-left:6px;
+ }
+}
+
+.visitor-profile-actions {
+ height:550px;
+ overflow-y:auto;
+ position:relative;
+ margin-right:10px;
+ border-bottom:none!important;
+ padding:0 18px 0 13px;
+
+ ol {
+ counter-reset:item;
+ list-style-type:none;
+
+ > li {
+ display:block;
+ font-size:12px;
+ font-weight:700;
+ line-height:25px;
+ padding:0 0 10px 13px;
+
+ span {
+ font-size:13px;
+ font-weight:700;
+ line-height:25px;
+ padding-left:0;
+ }
+ }
+
+ > li:before {
+ content:counter(item) " ";
+ counter-increment:item;
+ }
+ }
+
+ // TODO: unordered lists no longer used, remove
+ ol li ul,ol li ol {
+ border-top:1px solid #d1cec8;
+ }
+
+ ol li ul {
+ padding-left:15px;
+ }
+
+ ol > li > ol > li {
+ margin-left:-12px;
+ }
+
+ ol li ul li,ol li ol li {
+ display:block;
+ color:#5e5e5c;
+ font-size:13px;
+ line-height:22px;
+ padding-top:1px;
+ padding-bottom:1px;
+ }
+
+ ol li ol li {
+ padding-bottom:4px;
+ }
+
+ ol li ul li a,ol li ol li a {
+ display:inline-block;
+ }
+
+ ol > li ol li span {
+ padding-left:4px;
+ }
+
+ ol > li ol li .action-list-url {
+ margin-left:15px;
+ line-height:14px;
+ display:inline-block;
+ }
+
+ ol > li ol li img {
+ margin-left:7px;
+ }
+
+ // overrides for _actionsDetails styles
+ strong {
+ font-size:13px;
+ line-height:25px;
+ }
+}
+
+.visitor-profile-date {
+ float:right;
+ font-size:13px;
+ line-height:26px;
+}
+
+.visitor-profile-fog {
+ height:25px;
+ width:546px;
+ position:absolute;
+ bottom:51px;
+ right:28px;
+ background:url(../images/visitor_profile_gradient.png) repeat-x;
+}
+
+// popup css
+.visitor-profile-popup {
+ width: 1151px;
+ height: auto;
+ padding: 0;
+
+ > .ui-dialog-titlebar {
+ display: none;
+ }
+
+ > #Piwik_Popover {
+ padding: 0;
+ margin: 0;
+ overflow: visible;
+ }
+}
+
+span.visitor-profile-goal-name {
+ font-weight:bold;
+ font-style:italic;
+ font-size:13px;
+} \ No newline at end of file
diff --git a/plugins/Live/templates/_actionsList.twig b/plugins/Live/templates/_actionsList.twig
new file mode 100644
index 0000000000..9f5bc672e4
--- /dev/null
+++ b/plugins/Live/templates/_actionsList.twig
@@ -0,0 +1,106 @@
+{% set visitorHasSomeEcommerceActivity %}0{% endset %}
+{% for action in actionDetails %}
+ {% set customVariablesTooltip %}
+ {% if action.customVariables is defined %}
+ {{ 'CustomVariables_CustomVariables'|translate }}
+ {% for id,customVariable in action.customVariables %}
+ {% set name = 'customVariablePageName' ~ id %}
+ {% set value = 'customVariablePageValue' ~ id %}
+ - {{ customVariable[name]|raw }} {% if customVariable[value]|length > 0 %} = {{ customVariable[value]|raw }}{% endif %}
+ {% endfor %}
+ {% endif %}
+ {% endset %}
+ {% if not javascriptVariablesToSet.filterEcommerce or action.type == 'ecommerceOrder' or action.type == 'ecommerceAbandonedCart' %}
+ <li class="{% if action.goalName is defined %}goal{% else %}action{% endif %}"
+ title="{{ action.serverTimePretty }}{% if action.url is defined and action.url|trim|length %}
+ {{ action.url }}{% endif %} {% if customVariablesTooltip|trim|length %}
+
+ {{ customVariablesTooltip|trim }}{% endif %}{% if action.timeSpentPretty is defined %}
+
+ {{ 'General_TimeOnPage'|translate }}: {{ action.timeSpentPretty|raw }}{% endif %}{% if action.generationTime is defined %}
+
+ {{ 'General_ColumnGenerationTime'|translate }}: {{ action.generationTime|raw }}{% endif %}">
+ {% if action.type == 'ecommerceOrder' or action.type == 'ecommerceAbandonedCart' %}
+ {# Ecommerce Abandoned Cart / Ecommerce Order #}
+ <img src="{{ action.icon }}"/>
+ {% if action.type == 'ecommerceOrder' %}
+ {% set visitorHasSomeEcommerceActivity %}1{% endset %}
+ <strong>{{ 'Goals_EcommerceOrder'|translate }}</strong>
+ <span style='color:#666666'>({{ action.orderId }})</span>
+ {% else %}
+ <strong>{{'Goals_AbandonedCart'|translate}}</strong>
+
+ {# TODO: would be nice to have the icons Orders / Cart in the ecommerce log footer #}
+ {% if javascriptVariablesToSet.filterEcommerce == 2 %}
+ {% set visitorHasSomeEcommerceActivity %}1{% endset %}
+ {% endif %}
+ {% endif %}
+ <br/>
+ <span {% if not isWidget %}style='margin-left:20px'{% endif %}>
+ {% if action.type == 'ecommerceOrder' %}
+ <abbr title="
+ {{ 'Live_GoalRevenue'|translate }}: {{ action.revenue|money(javascriptVariablesToSet.idSite)|raw }}
+ {% if action.revenueSubTotal is not empty %} - {{ 'General_Subtotal'|translate }}: {{ action.revenueSubTotal|money(javascriptVariablesToSet.idSite)|raw }}{% endif %}
+ {% if action.revenueTax is not empty %} - {{ 'General_Tax'|translate }}: {{ action.revenueTax|money(javascriptVariablesToSet.idSite)|raw }}{% endif %}
+ {% if action.revenueShipping is not empty %} - {{ 'General_Shipping'|translate }}: {{ action.revenueShipping|money(javascriptVariablesToSet.idSite)|raw }}{% endif %}
+ {% if action.revenueDiscount is not empty %} - {{ 'General_Discount'|translate }}: {{ action.revenueDiscount|money(javascriptVariablesToSet.idSite)|raw }}{% endif %}
+ ">{{ 'Live_GoalRevenue'|translate }}:
+ {% else %}
+ {% set revenueLeft %}{{ 'Live_GoalRevenue'|translate }}{% endset %}
+ {{ 'Goals_LeftInCart'|translate(revenueLeft) }}:
+ {% endif %}
+ <strong>{{ action.revenue|money(javascriptVariablesToSet.idSite)|raw }}</strong>
+ {% if action.type == 'ecommerceOrder' %}
+ </abbr>
+ {% endif %}, {{ 'General_Quantity'|translate }}: {{ action.items }}
+
+ {# Ecommerce items in Cart/Order #}
+ {% if action.itemDetails is not empty %}
+ <ul style='list-style:square;margin-left:{% if isWidget %}15{% else %}50{% endif %}px'>
+ {% for product in action.itemDetails %}
+ <li>
+ {{ product.itemSKU }}{% if product.itemName is not empty %}: {{ product.itemName }}{% endif %}
+ {% if product.itemCategory is not empty %} ({{ product.itemCategory }}){% endif %}
+ ,
+ {{ 'General_Quantity'|translate }}: {{ product.quantity }},
+ {{ 'General_Price'|translate }}: {{ product.price|money(javascriptVariablesToSet.idSite)|raw }}
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </span>
+ {% elseif action.goalName is not defined%}
+ {# Page view / Download / Outlink #}
+ {% if action.pageTitle is defined and action.pageTitle is not empty %}
+ <span>{{ action.pageTitle|truncate(80) }}</span>
+ {% endif %}
+ {% if action.siteSearchKeyword is defined %}
+ {% if action.type == 'search' %}
+ <img src='{{ action.icon }}' title='{{ 'Actions_SubmenuSitesearch'|translate }}'>
+ {% endif %}
+ {{ action.siteSearchKeyword|truncate(80) }}
+ {% endif %}
+ {% if action.url is not empty %}
+ {% if action.type == 'action' and action.pageTitle is not empty %}<br/>{% endif %}
+ {% if action.type == 'download' or action.type == 'outlink' %}
+ <img src='{{ action.icon }}'>
+ {% endif %}
+ <a href="{{ action.url }}" target="_blank" class="action-list-url"
+ {% if overrideLinkStyle is not defined or overrideLinkStyle %}style="{% if action.type=='action' and action.pageTitle is not empty %}margin-left: 25px;{% endif %}text-decoration:underline;"{% endif %}>
+ {{ action.url|truncate(80) }}
+ </a>
+ {% elseif action.type != 'search' %}
+ <br/>
+ <span style="margin-left: 25px;">{{ javascriptVariablesToSet.pageUrlNotDefined }}</span>
+ {% endif %}
+ {% else %}
+ {# Goal conversion #}
+ <img src="{{ action.icon }}" />
+ <strong>{{ action.goalName }}</strong>
+ {% if action.revenue > 0 %}, {{ 'Live_GoalRevenue'|translate }}:
+ <strong>{{ action.revenue|money(javascriptVariablesToSet.idSite)|raw }}</strong>
+ {% endif %}
+ {% endif %}
+ </li>
+ {% endif %}
+{% endfor %} \ No newline at end of file
diff --git a/plugins/Live/templates/_totalVisitors.twig b/plugins/Live/templates/_totalVisitors.twig
index 40d2d1eed0..c1d70c7c2d 100644
--- a/plugins/Live/templates/_totalVisitors.twig
+++ b/plugins/Live/templates/_totalVisitors.twig
@@ -15,14 +15,14 @@
</thead>
<tbody>
<tr class="">
- <td class="columnodd">{{ 'Live_LastHours'|translate(24) }}</td>
- <td class="columnodd">{{ visitorsCountToday }}</td>
- <td class="columnodd">{{ pisToday }}</td>
+ <td class="column columnodd">{{ 'Live_LastHours'|translate(24) }}</td>
+ <td class="column columnodd">{{ visitorsCountToday }}</td>
+ <td class="column columnodd">{{ pisToday }}</td>
</tr>
<tr class="">
- <td class="columnodd">{{ 'Live_LastMinutes'|translate(30) }}</td>
- <td class="columnodd">{{ visitorsCountHalfHour }}</td>
- <td class="columnodd">{{ pisHalfhour }}</td>
+ <td class="column columnodd">{{ 'Live_LastMinutes'|translate(30) }}</td>
+ <td class="column columnodd">{{ visitorsCountHalfHour }}</td>
+ <td class="column columnodd">{{ pisHalfhour }}</td>
</tr>
</tbody>
</table>
diff --git a/plugins/Live/templates/getVisitorLog.twig b/plugins/Live/templates/getVisitorLog.twig
index 9c9a520acc..25dabd971a 100644
--- a/plugins/Live/templates/getVisitorLog.twig
+++ b/plugins/Live/templates/getVisitorLog.twig
@@ -187,112 +187,7 @@
</strong>
<br/>
<ol class='visitorLog'>
- {% set visitorHasSomeEcommerceActivity %}0{% endset %}
- {% for action in visitor.getColumn('actionDetails') %}
- {% set customVariablesTooltip %}
- {% if action.customVariables is defined %}
- {{ 'CustomVariables_CustomVariables'|translate }}
- {% for id,customVariable in action.customVariables %}
- {% set name = 'customVariablePageName' ~ id %}
- {% set value = 'customVariablePageValue' ~ id %}
- - {{ customVariable[name]|raw }} {% if customVariable[value]|length > 0 %} = {{ customVariable[value]|raw }}{% endif %}
- {% endfor %}
- {% endif %}
- {% endset %}
- {% if not javascriptVariablesToSet.filterEcommerce or action.type == 'ecommerceOrder' or action.type == 'ecommerceAbandonedCart' %}
- <li class="{% if action.goalName is defined %}goal{% else %}action{% endif %}"
- title="{{ action.serverTimePretty }}{% if action.url is defined and action.url|trim|length %}
- {{ action.url }}{% endif %} {% if customVariablesTooltip|trim|length %}
-
- {{ customVariablesTooltip|trim }}{% endif %}{% if action.timeSpentPretty is defined %}
-
- {{ 'General_TimeOnPage'|translate }}: {{ action.timeSpentPretty|raw }}{% endif %}{% if action.generationTime is defined %}
-
- {{ 'General_ColumnGenerationTime'|translate }}: {{ action.generationTime|raw }}{% endif %}">
- {% if action.type == 'ecommerceOrder' or action.type == 'ecommerceAbandonedCart' %}
- {# Ecommerce Abandoned Cart / Ecommerce Order #}
- <img src="{{ action.icon }}"/>
- {% if action.type == 'ecommerceOrder' %}
- {% set visitorHasSomeEcommerceActivity %}1{% endset %}
- <strong>{{ 'Goals_EcommerceOrder'|translate }}</strong>
- <span style='color:#666666'>({{ action.orderId }})</span>
- {% else %}
- <strong>{{'Goals_AbandonedCart'|translate}}</strong>
-
- {# TODO: would be nice to have the icons Orders / Cart in the ecommerce log footer #}
- {% if javascriptVariablesToSet.filterEcommerce == 2 %}
- {% set visitorHasSomeEcommerceActivity %}1{% endset %}
- {% endif %}
- {% endif %}
- <br/>
- <span {% if not isWidget %}style='margin-left:20px'{% endif %}>
- {% if action.type == 'ecommerceOrder' %}
- <abbr title="
- {{ 'Live_GoalRevenue'|translate }}: {{ action.revenue|money(javascriptVariablesToSet.idSite)|raw }}
- {% if action.revenueSubTotal is not empty %} - {{ 'General_Subtotal'|translate }}: {{ action.revenueSubTotal|money(javascriptVariablesToSet.idSite)|raw }}{% endif %}
- {% if action.revenueTax is not empty %} - {{ 'General_Tax'|translate }}: {{ action.revenueTax|money(javascriptVariablesToSet.idSite)|raw }}{% endif %}
- {% if action.revenueShipping is not empty %} - {{ 'General_Shipping'|translate }}: {{ action.revenueShipping|money(javascriptVariablesToSet.idSite)|raw }}{% endif %}
- {% if action.revenueDiscount is not empty %} - {{ 'General_Discount'|translate }}: {{ action.revenueDiscount|money(javascriptVariablesToSet.idSite)|raw }}{% endif %}
- ">{{ 'Live_GoalRevenue'|translate }}:
- {% else %}
- {% set revenueLeft %}{{ 'Live_GoalRevenue'|translate }}{% endset %}
- {{ 'Goals_LeftInCart'|translate(revenueLeft) }}:
- {% endif %}
- <strong>{{ action.revenue|money(javascriptVariablesToSet.idSite)|raw }}</strong>
- {% if action.type == 'ecommerceOrder' %}
- </abbr>
- {% endif %}, {{ 'General_Quantity'|translate }}: {{ action.items }}
-
- {# Ecommerce items in Cart/Order #}
- {% if action.itemDetails is not empty %}
- <ul style='list-style:square;margin-left:{% if isWidget %}15{% else %}50{% endif %}px'>
- {% for product in action.itemDetails %}
- <li>
- {{ product.itemSKU }}{% if product.itemName is not empty %}: {{ product.itemName }}{% endif %}
- {% if product.itemCategory is not empty %} ({{ product.itemCategory }}){% endif %}
- ,
- {{ 'General_Quantity'|translate }}: {{ product.quantity }},
- {{ 'General_Price'|translate }}: {{ product.price|money(javascriptVariablesToSet.idSite)|raw }}
- </li>
- {% endfor %}
- </ul>
- {% endif %}
- </span>
- {% elseif action.goalName is not defined%}
- {# Page view / Download / Outlink #}
- {% if action.pageTitle is defined %}
- {{ action.pageTitle|truncate(80) }}
- {% endif %}
- {% if action.siteSearchKeyword is defined %}
- {% if action.type == 'search' %}
- <img src='{{ action.icon }}' title='{{ 'Actions_SubmenuSitesearch'|translate }}'>
- {% endif %}
- {{ action.siteSearchKeyword|truncate(80) }}
- {% endif %}
- {% if action.url is not empty %}
- {% if action.type == 'action' and action.pageTitle is not empty %}<br/>{% endif %}
- {% if action.type == 'download' or action.type == 'outlink' %}
- <img src='{{ action.icon }}'>
- {% endif %}
- <a href="{{ action.url }}" target="_blank"
- style="{% if action.type=='action' and action.pageTitle is not empty %}margin-left: 25px;{% endif %}text-decoration:underline;">
- {{ action.url|truncate(80) }}
- </a>
- {% elseif action.type != 'search' %}
- <br/>
- <span style="margin-left: 25px;">{{ javascriptVariablesToSet.pageUrlNotDefined }}</span>
- {% endif %}
- {% else %}
- {# Goal conversion #}
- <img src="{{ action.icon }}" />
- <strong>{{ action.goalName }}</strong>
- {% if action.revenue > 0 %}, {{ 'Live_GoalRevenue'|translate }}:
- <strong>{{ action.revenue|money(javascriptVariablesToSet.idSite)|raw }}</strong>
- {% endif %}
- {% endif %}
- </li>
- {% endif %}
- {% endfor %}
+ {% include "@Live/_actionsList.twig" with {'actionDetails': visitor.getColumn('actionDetails')} %}
</ol>
</td>
</tr>
@@ -314,11 +209,11 @@
{% include "@CoreHome/_dataTableJS.twig" %}
<script type="text/javascript" defer="defer">
- var visitorLogTitle = '{{ 'Live_VisitorLog'|translate|e('js') }}';
+ var visitorLogTitle = '{{ 'Live_VisitorProfile'|translate|e('js') }}';
function Piwik_Live_LoadVisitorPopover(visitorId) {
var startingDate = piwik.minDateYear + '-01-01';
- var url = 'module=Live&action=getVisitorLog&period=range&date=' + startingDate + ',today&show_footer=0&segment=visitorId' + encodeURIComponent('==') + visitorId;
- return Piwik_Popover.createPopupAndLoadUrl(url, visitorLogTitle);
+ var url = 'module=Live&action=getVisitorProfilePopup&period=range&date=' + startingDate + ',today&idVisitor=' + encodeURIComponent(visitorId);
+ return Piwik_Popover.createPopupAndLoadUrl(url, visitorLogTitle, 'visitor-profile-popup');
}
$(document).ready(function () {
@@ -332,7 +227,7 @@
$(this).val(counter);
var current = $(this).html();
if (current == prevhtml) {
- var repeat = prevelement.find(".repeat")
+ var repeat = prevelement.find(".repeat");
if (repeat.length) {
repeat.html((parseInt(repeat.html()) + 1) + "x");
} else {
diff --git a/plugins/Live/templates/getVisitorProfilePopup.twig b/plugins/Live/templates/getVisitorProfilePopup.twig
new file mode 100644
index 0000000000..c351ecf570
--- /dev/null
+++ b/plugins/Live/templates/getVisitorProfilePopup.twig
@@ -0,0 +1,127 @@
+<div class="visitor-profile">
+ <a href class="visitor-profile-close"></a>
+ <div class="visitor-profile-info">
+ <div>
+ <div class="visitor-profile-avatar">
+ <div>
+ <div class="visitor-profile-image-frame"><!-- TODO translate -->
+ <img src="plugins/Live/images/REMOVE_ME_avatar.jpg" alt=""/>
+ </div>
+ <img src="plugins/Live/images/paperclip.png" alt=""/>
+ </div>
+ <div>
+ <h1>Visitor profile</h1>
+ <div>
+ <div class="visitor-profile-latest-visit-column">
+ <ul>
+ <li><span>IP</span><strong>{{ visitorData.latestVisitIp }}</strong></li>
+ <li><span>ID</span><strong>{{ visitorData.visitorId }}</strong></li>
+ <li>
+ <div class="visitor-profile-browser">
+ <img src="{{ visitorData.browserLogo }}"/><span>{{ visitorData.browserName }}</span>
+ </div>
+ <div class="visitor-profile-os">
+ <img src="{{ visitorData.operatingSystemLogo }}"/><span>{{ visitorData.operatingSystemShortName }}</span>
+ </div>
+ </li>
+ <li><span>Resolution</span><strong>{{ visitorData.resolution }}</strong></li>
+ </ul>
+ </div>
+ <div class="visitor-profile-latest-visit-column">
+ <ul>
+ {% for id,customVariable in visitorData.customVariables %}
+ {% if loop.index0 < 4 %}
+ {% set name='customVariableName' ~ id %}
+ {% set value='customVariableValue' ~ id %}
+ <li><span>{{ customVariable[name]|truncate(30) }}</span>{% if customVariable[value]|length > 0 %}<strong>{{ customVariable[value]|truncate(50) }}</strong>{% endif %}</li>
+ {% endif %}
+ {% endfor %}
+ {# TODO: Other custom vars go in expanding div. #}
+ </ul>
+ </div>
+ </div>
+ </div>
+ <p style="clear:both; border:none!important;"></p>
+ </div>
+ <div style="clear:both; border:none!important;"></div>
+ <div class="visitor-profile-map">
+ {{ userCountryMap|raw }}
+ </div>
+ <div class="visitor-profile-important-visits">
+ <div>
+ <h1>First visit</h1>
+ <div>
+ <p><strong>{{ visitorData.firstVisit.prettyDate }}</strong><span>&nbsp;- {{ visitorData.firstVisit.daysAgo }} days ago</span></p>
+ <p><span>from:</span>
+ <strong>{{ visitorData.firstVisit.referralSummary }}</strong></p>
+ </div>
+ </div>
+ <div>
+ <h1>Last visit</h1>
+ <div>
+ <p><strong>{{ visitorData.lastVisit.prettyDate }}</strong><span>&nbsp;- {{ visitorData.lastVisit.daysAgo }} days ago</span></p>
+ <p><span>from:</span>
+ <strong>{{ visitorData.lastVisit.referralSummary }}</strong></p>
+ </div>
+ </div>
+ </div>
+ <div class="visitor-profile-summary">
+ <h1>Summary</h1>
+ <div>
+ <p>Spent a total of <strong>{{ visitorData.totalVisitDurationPretty|raw }} on the website</strong>, and <strong>viewed {{ visitorData.totalActionCount }} pages in {{ visitorData.totalVisits }} visits.</strong></p>
+ <p><strong>Converted {{ visitorData.totalGoalConversions }} Goals</strong> (
+ {%- for idGoal, totalConversions in visitorData.totalConversionsByGoal -%}
+ {%- if not loop.first %}, {% endif -%}{{- totalConversions }} <span class="visitor-profile-goal-name">{{ goals[idGoal]['name'] -}}</span>
+ {%- endfor -%}
+ ).</p>
+ <p>Ecommerce: <strong>{{ visitorData.totalEcommerceConversions }} orders for a total of {{ visitorData.totalEcommerceRevenue|money(idSite)|raw }}</strong>, purchased {{ visitorData.totalEcommerceItems }} items.</p>
+ </div>
+ </div>
+ </div>
+ <div>
+ <div class="visitor-profile-location">
+ <h1>Location</h1>
+ <img src="plugins/Live/images/REMOVE_ME_chart.png" alt=""/> {# TODO: country & bar graph #}
+ </div>
+ <div class="visitor-profile-pages-visited">
+ <h1>Visited pages<a href>see all</a></h1>
+ </div>
+ <div class="visitor-profile-actions">
+ <ol>
+ {% for visitInfo in visitorData.lastVisits.getRows() %}
+ <li><h2>Visit</h2><span class="visitor-profile-date">{{ visitInfo.getColumn('serverDatePrettyFirstAction') }}</span>
+ <ol>
+ {% include "@Live/_actionsList.twig" with {'actionDetails': visitInfo.getColumn('actionDetails'),
+ 'javascriptVariablesToSet': {
+ 'filterEcommerce': false,
+ 'idSite': idSite
+ },
+ 'overrideLinkStyle': false} %}
+ </ol>
+ </li>
+ {% endfor %}
+ </ol>
+ <br/>
+ </div>
+ <div class="visitor-profile-fog"></div>
+ </div>
+ </div>
+ <div class="visitor-profile-more-info">
+ <a href="#">View more visitor information</a>
+ </div>
+</div>
+<script type="text/javascript">
+$(function() {
+ $('.visitor-profile-actions').jScrollPane({
+ showArrows: true,
+ verticalArrowPositions: 'os',
+ horizontalArrowPositions: 'os'
+ });
+
+ $('.visitor-profile-close').click(function (e) {
+ e.preventDefault();
+ Piwik_Popover.close();
+ return false;
+ });
+});
+</script> \ No newline at end of file
diff --git a/plugins/Login/stylesheets/login.css b/plugins/Login/stylesheets/login.css
index 93b594e18a..ab472c11a1 100644
--- a/plugins/Login/stylesheets/login.css
+++ b/plugins/Login/stylesheets/login.css
@@ -35,8 +35,9 @@
#logo img {
border: 0;
vertical-align: bottom;
- width: 260px;
height: auto;
+ width: 240px;
+ margin-right: 20px;
}
#logo .h1 {
diff --git a/plugins/Login/templates/login.twig b/plugins/Login/templates/login.twig
index aad97579fb..7b1e37e7f7 100644
--- a/plugins/Login/templates/login.twig
+++ b/plugins/Login/templates/login.twig
@@ -47,11 +47,10 @@
<a href="http://piwik.org" title="{{ linkTitle }}">
{% endif %}
{% if hasSVGLogo %}
- <img src='{{ logoSVG }}' title="{{ linkTitle }}" alt="Piwik" width="240" style='margin-right: 20px'
- class="ie-hide"/>
+ <img src='{{ logoSVG }}' title="{{ linkTitle }}" alt="Piwik" class="ie-hide"/>
<!--[if lt IE 9]>
{% endif %}
- <img src='{{ logoLarge }}' title="{{ linkTitle }}" alt="Piwik" width="240" style='margin-right:20px'/>
+ <img src='{{ logoLarge }}' title="{{ linkTitle }}" alt="Piwik" />
{% if hasSVGLogo %}<![endif]-->{% endif %}
{% if isCustomLogo %}
diff --git a/plugins/MultiSites/API.php b/plugins/MultiSites/API.php
index dec284cd3c..6b2381c0d5 100755
--- a/plugins/MultiSites/API.php
+++ b/plugins/MultiSites/API.php
@@ -402,8 +402,8 @@ class API
* Sets the total evolution metadata for a datatable returned by $this->buildDataTable
* given data for the last period.
*
- * @param DataTable $dataTable
- * @param DataTable $pastData
+ * @param DataTable|DataTable\Map $dataTable
+ * @param DataTable|DataTable\Map $pastData
* @param array $apiMetrics Metrics info.
*/
private function setPastDataMetadata($dataTable, $pastData, $apiMetrics)
diff --git a/plugins/MultiSites/javascripts/multiSites.js b/plugins/MultiSites/javascripts/multiSites.js
index 15c8aade97..8b004fb769 100644
--- a/plugins/MultiSites/javascripts/multiSites.js
+++ b/plugins/MultiSites/javascripts/multiSites.js
@@ -174,7 +174,7 @@ function getSparklineImg(id, column, params) {
if (token_auth.length) {
append = '&token_auth=' + token_auth;
}
- return '<img class="sparkline" alt="" src="?module=MultiSites&action=getEvolutionGraph&period=' + params['period'] + '&date=' + params['dateSparkline'] + '&evolutionBy=' + params['evolutionBy'] + '&columns=' + column + '&idSite=' + id + '&idsite=' + id + '&viewDataTable=sparkline' + append + '" width="100" height="25" />';
+ return '<img alt="" src="?module=MultiSites&action=getEvolutionGraph&period=' + params['period'] + '&date=' + params['dateSparkline'] + '&evolutionBy=' + params['evolutionBy'] + '&columns=' + column + '&idSite=' + id + '&idsite=' + id + '&viewDataTable=sparkline' + append + '&colors=' + encodeURIComponent(JSON.stringify(piwik.getSparklineColors())) + '" width="100" height="25" />';
}
function showPagination(allSites, params) {
diff --git a/plugins/MultiSites/stylesheets/multiSites.less b/plugins/MultiSites/stylesheets/multiSites.less
index 155af00a5c..ffacd8e3ae 100644
--- a/plugins/MultiSites/stylesheets/multiSites.less
+++ b/plugins/MultiSites/stylesheets/multiSites.less
@@ -13,7 +13,7 @@
}
.indicator {
- background: url(../images/loading-blue.gif) no-repeat center;
+ background: url(plugins/MultiSites/images/loading-blue.gif) no-repeat center;
height: 20px;
width: 60px;
margin: auto;
@@ -58,24 +58,24 @@
width: 16px;
height: 13px;
display: inline-block;
- background-image: url(../../Zeitgeist/images/sortdesc.png);
+ background-image: url(plugins/Zeitgeist/images/sortdesc.png);
}
.multisites_asc {
width: 16px;
height: 13px;
display: inline-block;
- background-image: url(../../Zeitgeist/images/sortasc.png);
+ background-image: url(plugins/Zeitgeist/images/sortasc.png);
}
#mt thead {
line-height: 2.5em;
}
-#mt thead :first-child {
+#mt thead *:first-child {
border-top-left-radius: 7px
}
-#mt thead :last-child {
+#mt thead *:last-child {
border-top-right-radius: 7px;
} \ No newline at end of file
diff --git a/plugins/MultiSites/templates/_siteRow.twig b/plugins/MultiSites/templates/_siteRow.twig
index 437db12226..bd4ea54276 100644
--- a/plugins/MultiSites/templates/_siteRow.twig
+++ b/plugins/MultiSites/templates/_siteRow.twig
@@ -26,7 +26,7 @@
{% endif %}
{% if show_sparklines %}
<td style="width:180px">
- <div id="sparkline_%idsite%" style="width: 100px; margin: auto">
+ <div id="sparkline_%idsite%" class="sparkline" style="width: 100px; margin: auto">
<a target="_blank" href="index.php?module=CoreHome&action=index&date=%date%&period=%period%&idSite=%idsite%"
title="{% set dashboardName %}{{ 'Dashboard_DashboardOf'|translate('%name%') }}{% endset %} {{ 'General_GoTo'|translate(dashboardName) }}">%sparkline%</a>
</div>
diff --git a/plugins/PDFReports/templates/index.twig b/plugins/PDFReports/templates/index.twig
index f48038613b..0ee69e28e6 100644
--- a/plugins/PDFReports/templates/index.twig
+++ b/plugins/PDFReports/templates/index.twig
@@ -2,6 +2,8 @@
{% block content %}
+{% include "@CoreHome/_siteSelectHeader.twig" %}
+
<div class="top_controls_inner">
{% include "@CoreHome/_periodSelect.twig" %}
</div>
@@ -26,7 +28,7 @@
</div>
<script type="text/javascript">
- var ReportPlugin = new Object();
+ var ReportPlugin = {};
ReportPlugin.defaultPeriod = '{{ defaultPeriod }}';
ReportPlugin.defaultHour = '{{ defaultHour }}';
ReportPlugin.defaultReportType = '{{ defaultReportType }}';
diff --git a/plugins/PleineLune/plugin.piwik.json b/plugins/PleineLune/plugin.piwik.json
index 8e3ca2a21b..d0718e1737 100644
--- a/plugins/PleineLune/plugin.piwik.json
+++ b/plugins/PleineLune/plugin.piwik.json
@@ -1,4 +1,5 @@
{
- "description": "A dark theme for Piwik, ideal to view your analytics reports before sunrise!",
+ "name": "PleineLune",
+ "description": "A dark theme for Piwik, ideal to view your analytics reports before sunrise.",
"theme": true
} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/_dataTable.less b/plugins/PleineLune/stylesheets/_dataTable.less
new file mode 100644
index 0000000000..bff57f2ff2
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/_dataTable.less
@@ -0,0 +1,182 @@
+/* Header */
+table.dataTable th,
+table.dataTable th.columnSorted {
+ background: @theme-color-background-smallContrast;
+ color: @theme-color-text-base;
+ border-left: 0;
+ vertical-align: bottom;
+}
+
+.sortIconContainer {
+ float: right;
+ margin-right: -20px;
+}
+
+.sortIconContainer:after {
+ content: " \25BC";
+ display: inline;
+}
+
+.sortIconContainerAsc:after {
+ content: " \25B2";
+}
+
+.sortIconContainer > img {
+ display: none;
+}
+
+/* Cells */
+table.dataTable td,
+table.dataTable td a {
+ color: @theme-color-text-base;
+}
+
+table.dataTable td,
+table.dataTable td.label,
+table.dataTable td.column {
+ background-color: @theme-color-background-base;
+ background-color: @theme-color-background-base;
+ border: 1px solid @theme-color-background-smallContrast;
+}
+
+table.dataTable td.column {
+ border-width: 0 0 1px 1px;
+}
+
+table.dataTable td.label {
+ border-width: 0 0 1px 0;
+ background-image: none;
+}
+
+/* SubTable */
+table.dataTable tr:hover > td.cellSubDataTable {
+ background: transparent;
+}
+
+table.subDataTable thead th {
+ border: 1px solid @theme-color-background-smallContrast;
+}
+
+table.subDataTable thead th {
+ border-width: 0 0 1px 1px;
+}
+
+/* Hover state */
+table.dataTable tr:hover > td,
+table.dataTable tr:hover > td .dataTableRowActions,
+table.dataTable tr.subDataTable:hover > td,
+table.dataTable tr.subDataTable:hover > td .dataTableRowActions {
+ background: transparent;
+}
+
+/* Focus widget */
+.ui-dialog-content,
+.widget:hover,
+.cellSubDataTable:hover {
+
+ table.dataTable td,
+ table.dataTable td a {
+ color: @theme-color-text-lightFocus;
+ }
+
+ table.dataTable th,
+ table.dataTable tr:hover > td,
+ table.dataTable tr:hover > td > a {
+ color: @theme-color-text-focus;
+ }
+
+ table.dataTable td.label,
+ table.dataTable td.column {
+ border-bottom-color: #404040;
+ }
+}
+
+/* Footer */
+.dataTableFooterIcons {
+ border-top: 1px solid @theme-color-background-contrast;
+}
+
+.dataTableNext,
+.dataTablePrevious {
+ color: @theme-color-text-link;
+}
+
+.dataTableNext:hover,
+.dataTablePrevious:hover {
+ text-decoration: underline;
+ color: @theme-color-text-focus;
+}
+
+.loadingPiwik {
+ color: @theme-color-text-base;
+}
+
+/* LimitSelection */
+.limitSelection > div {
+ border-color: @theme-color-background-smallContrast;
+ border-radius: 0;
+}
+
+.limitSelection > div > span {
+ color: @theme-color-text-active;
+}
+
+.limitSelection > ul > li {
+ background: @theme-color-background-base;
+ border-color: @theme-color-background-smallContrast;
+}
+
+.limitSelection > ul > li.last {
+ background: @theme-color-background-base;
+ border-color: @theme-color-background-smallContrast;
+}
+
+.limitSelection > ul > li:hover {
+ background-color: @theme-color-background-smallContrast;
+}
+
+.limitSelection > ul > li > span {
+ color: @theme-color-text-link;
+}
+
+.limitSelection > ul > li:hover > span {
+ color: @theme-color-text-focus;
+}
+
+/* TableConfiguration */
+.tableConfiguration ul {
+ background-color: @theme-color-background-base;
+}
+
+.tableConfiguration ul li {
+ background-color: @theme-color-background-base;
+ border-color: @theme-color-background-smallContrast;
+}
+
+.tableConfiguration ul li.firstDummy,
+.tableConfiguration ul li.last {
+ border-radius: 0;
+}
+
+.tableConfiguration div.configItem {
+ color: @theme-color-text-base;
+}
+
+.tableConfiguration div.configItem:hover {
+ background-color: @theme-color-background-smallContrast;
+}
+
+.tableConfiguration div.configItem span.action {
+ color: @theme-color-text-link;
+}
+
+.tableConfiguration div.configItem:hover span.action {
+ text-decoration: underline;
+ color: @theme-color-text-focus;
+}
+
+/* MultiSites */
+#mt thead *:first-child,
+#mt thead *:last-child {
+ border-radius: 0;
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/_general.less b/plugins/PleineLune/stylesheets/_general.less
index d39b36d4b6..089f49f0dc 100644
--- a/plugins/PleineLune/stylesheets/_general.less
+++ b/plugins/PleineLune/stylesheets/_general.less
@@ -19,4 +19,11 @@ a:hover,
a:focus,
a:active {
color: @theme-color-text-focus;
+}
+
+select,
+[type="text"] {
+ background: @theme-color-background-lighter;
+ border: 0 none;
+ color: @theme-color-background-smallContrast;
} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/_jqplotColors.less b/plugins/PleineLune/stylesheets/_jqplotColors.less
new file mode 100644
index 0000000000..ddb9ad3425
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/_jqplotColors.less
@@ -0,0 +1,86 @@
+// evolution graph colors
+.evolution-graph-colors[data-name=grid-background] {
+ color: @theme-color-background-base;
+}
+
+.evolution-graph-colors[data-name=grid-border] {
+ color: @theme-color-background-smallContrast;
+}
+
+.evolution-graph-colors[data-name=series1] {
+ color: @theme-color-highlight1;
+}
+
+.evolution-graph-colors[data-name=series2] {
+ color: @theme-color-highlight2;
+}
+
+.evolution-graph-colors[data-name=series3] {
+ color: @theme-color-highlight3;
+}
+
+.evolution-graph-colors[data-name=ticks] {
+ color: #ccc;
+}
+
+.evolution-graph-colors[data-name=single-metric-label] {
+ color: #666;
+}
+
+// bar graph colors
+.bar-graph-colors[data-name=grid-background] {
+ color: @theme-color-background-base;
+}
+
+.bar-graph-colors[data-name=grid-border] {
+ color: #f00;
+}
+
+.bar-graph-colors[data-name=series1] {
+ color: @theme-color-highlight1;
+}
+
+.bar-graph-colors[data-name=series2] {
+ color: @theme-color-highlight2;
+}
+
+.bar-graph-colors[data-name=series3] {
+ color: @theme-color-highlight3;
+}
+
+.bar-graph-colors[data-name=ticks] {
+ color: #ccc;
+}
+
+.bar-graph-colors[data-name=single-metric-label] {
+ color: #666;
+}
+
+// pie graph colors
+.pie-graph-colors[data-name=grid-background] {
+ color: @theme-color-background-base;
+}
+
+.pie-graph-colors[data-name=grid-border] {
+ color: @theme-color-background-smallContrast;
+}
+
+.pie-graph-colors[data-name=series1] {
+ color: @theme-color-highlight1;
+}
+
+.pie-graph-colors[data-name=series2] {
+ color: @theme-color-highlight2;
+}
+
+.pie-graph-colors[data-name=series3] {
+ color: @theme-color-highlight3;
+}
+
+.pie-graph-colors[data-name=ticks] {
+ color: #ccc;
+}
+
+.pie-graph-colors[data-name=single-metric-label] {
+ color: #666;
+}
diff --git a/plugins/PleineLune/stylesheets/_layout.less b/plugins/PleineLune/stylesheets/_layout.less
index f43d33d1a7..637fd307f6 100644
--- a/plugins/PleineLune/stylesheets/_layout.less
+++ b/plugins/PleineLune/stylesheets/_layout.less
@@ -26,4 +26,63 @@
#topRightBar .topBarElem {
margin-bottom: 5px;
-} \ No newline at end of file
+}
+
+.topBarElemActive {
+ color: @theme-color-text-active;
+}
+
+.topBarElemActive > b {
+ font-weight: normal;
+}
+
+#languageSelect {
+ background: @theme-color-background-base;
+ border: 1px solid @theme-color-background-contrast !important;
+}
+
+#languageSelect a:hover {
+ background: @theme-color-background-smallContrast !important;
+ border: 0;
+ border-radius: 0;
+ color: @theme-color-text-focus !important;
+}
+
+
+/* Logo */
+#logo {
+ opacity: 0.5;
+}
+
+#header:hover #logo {
+ opacity: 1;
+}
+
+@media all and (max-width: 949px) {
+ #logo {
+ float: none;
+ display: block;
+ text-align: center
+ }
+
+ #topBars {
+ float: none;
+ display: table;
+ width: 100%;
+ }
+
+ #topRightBar,
+ #topLeftBar {
+ text-align: center;
+ }
+}
+
+@media all and (min-width: 1250px) {
+ #logo img {
+ height: 80px;
+ }
+
+ #header:after {
+ clear: right;
+ }
+}
diff --git a/plugins/PleineLune/stylesheets/_menuDashboard.less b/plugins/PleineLune/stylesheets/_menuDashboard.less
index 47b0aeb955..c5cadb1493 100644
--- a/plugins/PleineLune/stylesheets/_menuDashboard.less
+++ b/plugins/PleineLune/stylesheets/_menuDashboard.less
@@ -1,45 +1,69 @@
-
/* FIRST LEVEL */
-.nav_tab> li {
- background: transparent;
+.nav_tab {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.nav_tab > li {
+ background: @theme-color-background-base;
border-color: @theme-color-box-border;
margin-right: 5px;
}
-.nav_tab> li:hover,
-.nav_tab> li.sfHover{
- background-color: @theme-color-box-active;
+.nav_tab a {
+ padding: 8px 15px 0;
}
-.nav_tab> li.sfHover > a,
-.nav_tab> li.sfActive.sfHover > a {
- border-bottom: 1px solid @theme-color-box-active;
+.nav_tab > li:hover,
+.nav_tab > li.sfHover {
+ background-color: @theme-color-box-active;
}
-.nav_tab> li > a,
-.nav_tab> li.sfActive > a {
+.nav_tab > li > a,
+.nav_tab > li.sfActive > a {
color: @theme-color-text-base;
}
-.nav_tab> li.sfHover > a,
-.nav_tab> li.sfActive.sfHover > a {
+.nav_tab > li:hover > a,
+.nav_tab > li.sfHover > a,
+.nav_tab > li.sfActive.sfHover > a {
+ border-bottom: 1px solid @theme-color-box-active;
color: @theme-color-text-active;
}
+.nav_tab > li:hover > a,
+.nav_tab > li.sfHover > a,
+.nav_tab > li.sfActive.sfHover > a {
+}
+
+.nav_tab > li:hover > a {
+ text-decoration: none;
+}
+
+.nav_tab > li > a:hover {
+ text-decoration: underline;
+}
+
/* SECOND LEVEL */
.nav_sep {
border-color: @theme-color-box-border;
+ border-width: 1px 0;
+ border-radius: 0;
background: @theme-color-box-active;
+ padding: 0 10px;
+ margin-left: -10px;
+ width: 100%;
}
-.nav_tab> li li > a {
+.nav_tab > li li > a {
color: @theme-color-text-base;
}
-.nav_tab> li li:hover > a,
-.nav_tab> li li:focus > a,
-.nav_tab> li li:active > a {
- color: @theme-color-text-focus;
+.nav_tab > li li:hover > a,
+.nav_tab > li li.sfHover > a,
+.nav_tab > li li:focus > a,
+.nav_tab > li li:active > a {
+ color: @theme-color-text-active;
}
/* UNDER THE MENU */
diff --git a/plugins/PleineLune/stylesheets/_sparklineColors.less b/plugins/PleineLune/stylesheets/_sparklineColors.less
new file mode 100644
index 0000000000..a8f978c861
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/_sparklineColors.less
@@ -0,0 +1,14 @@
+// sparkline styles
+div.sparkline,
+div.sparkline:hover {
+ border-bottom: 0;
+}
+
+// sparkline colors
+.sparkline-colors[data-name=backgroundColor] {
+ color: @theme-color-background-base;
+}
+
+.sparkline-colors[data-name=lineColor] {
+ color: @theme-color-highlight1;
+}
diff --git a/plugins/PleineLune/stylesheets/_transitionColors.less b/plugins/PleineLune/stylesheets/_transitionColors.less
new file mode 100644
index 0000000000..f8bd954310
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/_transitionColors.less
@@ -0,0 +1,46 @@
+.transition-entries[data-name=light],
+.transition-entries[data-name=light-highlighted],
+.transition-exits[data-name=light],
+.transition-exits[data-name=light-highlighted],
+.transition-entries[data-name=dark],
+.transition-exits[data-name=dark],
+.transition-background[data-name=light],
+.transition-background[data-name=light-highlighted],
+.transition-background[data-name=light],
+.transition-background[data-name=light-highlighted],
+.transition-background[data-name=dark],
+.transition-background[data-name=dark] {
+ color: @theme-color-background-contrast;
+}
+
+.transition-entries[data-name=dark-highlighted],
+.transition-exits[data-name=dark-highlighted],
+.transition-background[data-name=dark-highlighted],
+.transition-background[data-name=dark-highlighted] {
+ color: @theme-color-background-smallContrast;
+}
+
+// closed group gradient colors
+.transition-closed-group[data-name=dark],
+.transition-closed-group[data-name=light],
+.transition-closed-group[data-name=light-highlighted] {
+ color: @theme-color-background-contrast;
+}
+
+.transition-closed-group[data-name=dark-highlighted] {
+ color: @theme-color-text-active;
+}
+
+// items gradient colors
+.transition-items[data-name=light],
+.transition-items[data-name=dark],
+.transition-others[data-name=light],
+.transition-others[data-name=dark] {
+ color: @theme-color-background-lighter;
+}
+
+// loop gradient colors
+.transition-loops[data-name=light],
+.transition-loops[data-name=dark] {
+ color: @theme-color-background-smallContrast;
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/_ui.less b/plugins/PleineLune/stylesheets/_ui.less
new file mode 100644
index 0000000000..50f4db575e
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/_ui.less
@@ -0,0 +1,23 @@
+/* Dialog */
+.ui-widget-overlay {
+ opacity: 1;
+}
+
+.ui-dialog {
+ background: @theme-color-background-base;
+ border: 1px solid @theme-color-background-contrast;
+}
+
+/* Autocomplete */
+.ui-autocomplete {
+ background: @theme-color-background-base;
+ border: 1px solid @theme-color-background-contrast;
+}
+
+.ui-menu .ui-menu-item a {
+ color: @theme-color-text-link;
+}
+
+.ui-menu .ui-menu-item a.ui-state-focus {
+ background: @theme-color-background-smallContrast;
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/_widget.less b/plugins/PleineLune/stylesheets/_widget.less
new file mode 100644
index 0000000000..c7db32550d
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/_widget.less
@@ -0,0 +1,19 @@
+.widget {
+ border: 1px solid @theme-color-background-contrast;
+ border-radius: 0;
+ background: @theme-color-background-base;
+}
+
+.widgetTop {
+ background: @theme-color-background-smallContrast;
+}
+
+.widgetName {
+ text-shadow: none;
+ color: @theme-color-text-base;
+}
+
+.ui-dialog-content .widgetName,
+.widget:hover .widgetName {
+ color: @theme-color-text-lightFocus;
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/controls/_headerMessage.less b/plugins/PleineLune/stylesheets/controls/_headerMessage.less
new file mode 100644
index 0000000000..a23fb8a80d
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/controls/_headerMessage.less
@@ -0,0 +1,20 @@
+#header_message {
+ color: @theme-color-text-base;
+ border-radius: 0;
+ padding-left: 8px;
+ right: 0;
+}
+
+#header_message,
+#header_message:hover {
+ background: @theme-color-background-base;
+ border: 1px solid @theme-color-background-contrast;
+}
+
+.header_info a {
+ color: @theme-color-text-link;
+}
+
+.header_info a:hover {
+ color: @theme-color-text-focus;
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/controls/_periodSelect.less b/plugins/PleineLune/stylesheets/controls/_periodSelect.less
new file mode 100644
index 0000000000..60a89dffe5
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/controls/_periodSelect.less
@@ -0,0 +1,34 @@
+#periodString {
+ color: @theme-color-text-base;
+ border-radius: 0;
+}
+
+#periodString,
+#periodString:hover {
+ background: @theme-color-background-base;
+ border: 1px solid @theme-color-background-contrast;
+}
+
+#periodString #date {
+ color: @theme-color-text-active;
+}
+
+#periodString #date:hover {
+ color: @theme-color-text-focus;
+}
+
+#periodString b {
+ color: inherit;
+}
+
+#periodString .calendar-icon {
+ opacity: 0.7;
+}
+
+#periodString label.selected-period-label {
+ color: @theme-color-text-active;
+}
+
+#periodString label:hover {
+ color: @theme-color-text-focus;
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/controls/_segmentSelect.less b/plugins/PleineLune/stylesheets/controls/_segmentSelect.less
new file mode 100644
index 0000000000..ec4c196271
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/controls/_segmentSelect.less
@@ -0,0 +1,139 @@
+
+#segmentEditorPanel {
+ color: @theme-color-text-base;
+ border-radius: 0;
+}
+
+#segmentEditorPanel,
+#segmentEditorPanel:hover {
+ background: @theme-color-background-base;
+ border: 1px solid @theme-color-background-contrast;
+}
+
+#segmentEditorPanel .segmentationTitle,
+.segmentationContainer > span > b,
+ #available_segments a.dropdown {
+ color: @theme-color-text-active;
+}
+
+#segmentEditorPanel .segmentationTitle:hover {
+ color: @theme-color-text-focus;
+}
+
+#segmentEditorPanel .submenu ul {
+ font-size: 13px;
+}
+
+#segmentEditorPanel .submenu ul > li > span {
+ color: @theme-color-text-link;
+ font-weight: normal;
+}
+
+#segmentEditorPanel .submenu ul > li:hover {
+ background: none;
+ border: 0;
+ margin: 3px 0 0;
+}
+
+#segmentEditorPanel .submenu ul > li:hover > span {
+ color: @theme-color-text-focus;
+ text-decoration: underline;
+}
+
+#segmentEditorPanel .add_new_segment {
+ width: auto;
+ text-align: center;
+}
+
+/* Form to create a segment */
+.segment-element {
+ background: @theme-color-background-base;
+ border: 1px solid @theme-color-background-contrast;
+}
+
+.segment-element .segment-nav div > ul > li a {
+ text-shadow: none;
+ color: @theme-color-text-link;
+}
+
+.segment-element .segment-nav div > ul > li li:hover {
+ border: 0;
+ padding: 1px;
+}
+
+.segment-element .segment-nav div > ul > li li:hover a {
+ background: @theme-color-background-smallContrast;
+ border: 0;
+}
+
+.segment-element .custom_select_search {
+ border-color: @theme-color-background-contrast;
+}
+
+.segment-element .custom_select_search input[type="text"],
+.segment-element .segment-top {
+ color: @theme-color-text-base;
+}
+
+.segment-element .segment-content h3 {
+ text-shadow: none;
+ color: @theme-color-text-base;
+}
+
+.segment-element .segment-content .segment-add-row,
+.segment-element .segment-content .segment-rows {
+ background: @theme-color-background-smallContrast;
+ border-color: @theme-color-background-lighter;
+ box-shadow: none;
+}
+
+.segment-element .segment-content .segment-row,
+.segment-element .segment-content .segment-or,
+.segment-element .segment-content .segment-and,
+.segment-element .segment-content .segment-add-row,
+.segment-element .segment-content .segment-add-or {
+ background-color: @theme-color-background-contrast;
+ color: @theme-color-background-smallContrast;
+ text-shadow: none;
+}
+
+.segment-element .segment-content .segment-and:before,
+.segment-element .segment-content .segment-and:after {
+ border-color: @theme-color-background-lighter;
+ background: @theme-color-background-base;
+}
+.segment-element .segment-content .segment-or:before,
+.segment-element .segment-content .segment-or:after {
+ bottom: 0;
+ top: 0;
+ border: 0;
+ background: @theme-color-background-smallContrast;
+}
+
+.segment-element .segment-content .segment-add-row > div,
+.segment-element .segment-content .segment-add-or > div {
+ border-color: @theme-color-background-smallContrast;
+}
+
+.segment-element .segment-content .segment-row-inputs .segment-input {
+ border: 0;
+}
+
+.segment-element .segment-content .segment-input select,
+.segment-element .segment-content .segment-input input {
+ color: @theme-color-background-smallContrast;
+}
+
+.segment-element .segment-content .segment-add-row > div a span,
+.segment-element .segment-content .segment-add-or > div a span {
+ color: @theme-color-text-link;
+}
+
+.segment-element .segment-footer {
+ background: @theme-color-background-smallContrast;
+ border-color: @theme-color-background-contrast;
+}
+
+.segment-element .segment-footer button {
+ text-shadow: none;
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/controls/_siteSelect.less b/plugins/PleineLune/stylesheets/controls/_siteSelect.less
new file mode 100644
index 0000000000..dd26213b04
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/controls/_siteSelect.less
@@ -0,0 +1,69 @@
+.top_bar_sites_selector > label {
+ display: none;
+}
+
+.top_bar_sites_selector > .sites_autocomplete {
+ padding: 0;
+}
+
+.sites_autocomplete .custom_select_main_link {
+ background: none;
+ padding: 0;
+ font-size: 18px;
+ line-height: 1;
+ color: @theme-color-text-base;
+}
+
+.admin .sites_autocomplete .custom_select_main_link,
+.sites_autocomplete--dropdown:hover .custom_select_main_link {
+ color: @theme-color-text-active;
+}
+
+.sites_autocomplete--dropdown .custom_select_main_link:after {
+ content: " \25BC";
+ float: right;
+ font-size: 0.8em;
+ margin-top: 0.2em;
+}
+
+.sites_autocomplete .custom_select_main_link > span {
+ display: inline-block;
+ max-width: 150px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: bottom;
+ white-space: nowrap;
+}
+
+.sites_autocomplete .custom_select {
+ background: @theme-color-background-base;
+ border-color: @theme-color-background-contrast;
+ border-radius: 4px 4px 0 0;
+ font-size: 14px;
+ min-height: 25px;
+ padding: 8px 15px 0;
+}
+
+.sites_autocomplete .custom_select_ul_list li a,
+.sites_autocomplete .custom_select_all a {
+ color: @theme-color-text-link;
+}
+
+.sites_autocomplete .custom_select_ul_list li a:hover,
+.sites_autocomplete .custom_select_all a:hover {
+ background: @theme-color-background-smallContrast;
+ color: @theme-color-text-focus;
+}
+
+
+@media all and (max-width: 949px) {
+ .top_bar_sites_selector {
+ float: none;
+ text-align: center;
+ }
+ .sites_autocomplete .custom_select {
+ padding-left: 8px;
+ padding-right: 8px;
+ border-radius: 0;
+ }
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/controls/_widgetSelect.less b/plugins/PleineLune/stylesheets/controls/_widgetSelect.less
new file mode 100644
index 0000000000..8d9baad15a
--- /dev/null
+++ b/plugins/PleineLune/stylesheets/controls/_widgetSelect.less
@@ -0,0 +1,44 @@
+#dashboardSettings {
+ color: @theme-color-text-base;
+ border-radius: 0;
+}
+
+#dashboardSettings,
+#dashboardSettings:hover {
+ background: @theme-color-background-base;
+ border: 1px solid @theme-color-background-contrast;
+}
+
+#dashboardSettings > span {
+ color: @theme-color-text-active;
+}
+
+#dashboardSettings > span:hover {
+ color: @theme-color-text-focus;
+}
+
+#dashboardSettings > ul.submenu > li {
+ color: @theme-color-text-link;
+}
+
+#dashboardSettings > ul.submenu > li:hover {
+ color: @theme-color-text-focus;
+}
+
+#dashboardSettings .submenu ul li,
+ul.widgetpreview-widgetlist, ul.widgetpreview-categorylist {
+ color: @theme-color-text-base;
+}
+
+#dashboardSettings .submenu ul li:hover,
+#dashboardSettings .submenu ul li.widgetpreview-choosen,
+#dashboardSettings .widgetpreview-widgetlist li:hover,
+#dashboardSettings .widgetpreview-widgetlist li.widgetpreview-choosen, {
+ color: @theme-color-text-focus;
+ background: @theme-color-background-smallContrast;
+}
+
+.widgetpreview-base li.widgetpreview-unavailable {
+ color: @theme-color-text-base;
+ text-decoration: line-through;
+} \ No newline at end of file
diff --git a/plugins/PleineLune/stylesheets/theme.less b/plugins/PleineLune/stylesheets/theme.less
index 0e754e96e0..655f9c6c57 100644
--- a/plugins/PleineLune/stylesheets/theme.less
+++ b/plugins/PleineLune/stylesheets/theme.less
@@ -1,11 +1,32 @@
-@theme-color-text-link: #6C9C50;
+
+@theme-color-background-base: #141414;
+@theme-color-background-contrast: #5F5A60;
+@theme-color-background-smallContrast: #202020;
+@theme-color-background-lighter: #888;
+@theme-color-highlight1: #766F31;
+@theme-color-highlight2: #6C9C50;
+@theme-color-highlight3: #67E750;
+
+@theme-color-text-link: @theme-color-highlight2;
@theme-color-text-base: #59867D;
-@theme-color-text-focus: #67E750;
-@theme-color-text-active: #766F31;
-@theme-color-box-border: #5F5A60; //#777778;
-@theme-color-box-active: #141414;
+@theme-color-text-lightFocus: #AAA;
+@theme-color-text-focus: @theme-color-highlight3;
+@theme-color-text-active: @theme-color-highlight1;
+@theme-color-box-border: @theme-color-background-contrast;
+@theme-color-box-active: @theme-color-background-smallContrast;
@import "_general.less";
@import "_layout.less";
+@import "controls/_periodSelect.less";
+@import "controls/_segmentSelect.less";
+@import "controls/_widgetSelect.less";
+@import "controls/_headerMessage.less";
+@import "controls/_siteSelect.less";
@import "_menuDashboard.less";
-@import "_menuAdmin.less"; \ No newline at end of file
+@import "_menuAdmin.less";
+@import "_widget.less";
+@import "_dataTable.less";
+@import "_sparklineColors.less";
+@import "_jqplotColors.less";
+@import "_ui.less";
+@import "../../PleineLune/stylesheets/_transitionColors.less"; \ No newline at end of file
diff --git a/plugins/Referers/Controller.php b/plugins/Referers/Controller.php
index 672e6c475f..17da96fe90 100644
--- a/plugins/Referers/Controller.php
+++ b/plugins/Referers/Controller.php
@@ -264,7 +264,7 @@ class Controller extends \Piwik\Controller
{
$view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Referers.getRefererType');
- $view->add_total_row = true;
+ $view->visualization_properties->add_total_row = true;
// configure displayed columns
if (empty($columns)) {
@@ -280,7 +280,7 @@ class Controller extends \Piwik\Controller
} else {
$selectable = array('nb_visits', 'nb_actions');
}
- $view->selectable_columns = $selectable;
+ $view->visualization_properties->selectable_columns = $selectable;
// configure displayed rows
$visibleRows = Common::getRequestVar('rows', false);
@@ -300,7 +300,7 @@ class Controller extends \Piwik\Controller
$visibleRows = array($label, $total);
$view->request_parameters_to_modify['rows'] = $label . ',' . $total;
}
- $view->row_picker_mach_rows_by = 'label';
+ $view->row_picker_match_rows_by = 'label';
$view->row_picker_visible_rows = $visibleRows;
$view->documentation = Piwik_Translate('Referers_EvolutionDocumentation') . '<br />'
diff --git a/plugins/Referers/Referers.php b/plugins/Referers/Referers.php
index 1b1efdc7c4..5f6451548b 100644
--- a/plugins/Referers/Referers.php
+++ b/plugins/Referers/Referers.php
@@ -329,15 +329,19 @@ class Referers extends \Piwik\Plugin
}
return array(
- 'default_view_type' => 'tableAllColumns',
- 'show_search' => false,
- 'show_offset_information' => false,
- 'show_pagination_control' => false,
- 'show_exclude_low_population' => false,
- 'disable_subtable_when_show_goals' => true,
- 'show_goals' => true,
- 'filter_limit' => 10,
- 'translations' => array('label' => $labelColumnTitle)
+ 'default_view_type' => 'tableAllColumns',
+ 'show_search' => false,
+ 'show_offset_information' => false,
+ 'show_pagination_control' => false,
+ 'show_exclude_low_population' => false,
+ 'show_goals' => true,
+ 'filter_limit' => 10,
+ 'translations' => array('label' => $labelColumnTitle),
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_subtable_when_show_goals' => true,
+ )
+ ),
);
}
@@ -346,11 +350,15 @@ class Referers extends \Piwik\Plugin
$setGetAllHtmlPrefix = array($this, 'setGetAllHtmlPrefix');
return array(
'show_exclude_low_population' => false,
- 'translations' => array('label' => Piwik_Translate('Referers_Referrer')),
- 'show_goals' => true,
- 'filter_limit' => 20,
- 'custom_parameters' => array('disable_row_actions' => '1'),
- 'filters' => array(
+ 'translations' => array('label' => Piwik_Translate('Referers_Referrer')),
+ 'show_goals' => true,
+ 'filter_limit' => 20,
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_row_actions' => true
+ )
+ ),
+ 'filters' => array(
array('MetadataCallbackAddMetadata', array('referrer_type', 'html_label_prefix', $setGetAllHtmlPrefix))
)
);
@@ -359,12 +367,16 @@ class Referers extends \Piwik\Plugin
private function getDisplayPropertiesForGetKeywords()
{
return array(
- 'subtable_controller_action' => 'getSearchEnginesFromKeywordId',
- 'show_exclude_low_population' => false,
- 'translations' => array('label' => Piwik_Translate('Referers_ColumnKeyword')),
- 'show_goals' => true,
- 'filter_limit' => 25,
- 'disable_subtable_when_show_goals' => true,
+ 'subtable_controller_action' => 'getSearchEnginesFromKeywordId',
+ 'show_exclude_low_population' => false,
+ 'translations' => array('label' => Piwik_Translate('Referers_ColumnKeyword')),
+ 'show_goals' => true,
+ 'filter_limit' => 25,
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_subtable_when_show_goals' => true,
+ )
+ ),
);
}
@@ -380,13 +392,17 @@ class Referers extends \Piwik\Plugin
private function getDisplayPropertiesForGetSearchEngines()
{
return array(
- 'subtable_controller_action' => 'getKeywordsFromSearchEngineId',
- 'show_search' => false,
- 'show_exclude_low_population' => false,
- 'show_goals' => true,
- 'filter_limit' => 25,
- 'disable_subtable_when_show_goals' => true,
- 'translations' => array('label' => Piwik_Translate('Referers_ColumnSearchEngine'))
+ 'subtable_controller_action' => 'getKeywordsFromSearchEngineId',
+ 'show_search' => false,
+ 'show_exclude_low_population' => false,
+ 'show_goals' => true,
+ 'filter_limit' => 25,
+ 'translations' => array('label' => Piwik_Translate('Referers_ColumnSearchEngine')),
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_subtable_when_show_goals' => true,
+ )
+ ),
);
}
@@ -402,25 +418,33 @@ class Referers extends \Piwik\Plugin
private function getDisplayPropertiesForGetWebsites()
{
return array(
- 'subtable_controller_action' => 'getUrlsFromWebsiteId',
- 'show_exclude_low_population' => false,
- 'show_goals' => true,
- 'filter_limit' => 25,
- 'disable_subtable_when_show_goals' => true,
- 'translations' => array('label' => Piwik_Translate('Referers_ColumnWebsite'))
+ 'subtable_controller_action' => 'getUrlsFromWebsiteId',
+ 'show_exclude_low_population' => false,
+ 'show_goals' => true,
+ 'filter_limit' => 25,
+ 'translations' => array('label' => Piwik_Translate('Referers_ColumnWebsite')),
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_subtable_when_show_goals' => true,
+ )
+ ),
);
}
private function getDisplayPropertiesForGetSocials()
{
$result = array(
- 'default_view_type' => 'graphPie',
- 'subtable_controller_action' => 'getUrlsForSocial',
- 'show_exclude_low_population' => false,
- 'filter_limit' => 10,
- 'show_goals' => true,
- 'disable_subtable_when_show_goals' => true,
- 'translations' => array('label' => Piwik_Translate('Referers_ColumnSocial'))
+ 'default_view_type' => 'graphPie',
+ 'subtable_controller_action' => 'getUrlsForSocial',
+ 'show_exclude_low_population' => false,
+ 'filter_limit' => 10,
+ 'show_goals' => true,
+ 'translations' => array('label' => Piwik_Translate('Referers_ColumnSocial')),
+ 'visualization_properties' => array(
+ 'table' => array(
+ 'disable_subtable_when_show_goals' => true,
+ )
+ ),
);
$widget = Common::getRequestVar('widget', false);
diff --git a/plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php b/plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php
index acdba6b959..bc4667665d 100644
--- a/plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php
+++ b/plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php
@@ -182,6 +182,7 @@ class PhpSecInfo
/**
* Constructor
*
+ * @param null|array $opts
* @return PhpSecInfo
*/
function PhpSecInfo($opts = null)
@@ -332,6 +333,7 @@ class PhpSecInfo
*
* @param string $group_name
* @param array $group_results
+ * @return bool
*/
function _outputRenderTable($group_name, $group_results)
{
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php b/plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php
index f04d087802..fa1eeb2353 100644
--- a/plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php
@@ -50,7 +50,7 @@ class PhpSecInfo_Test_Session_Save_Path extends PhpSecInfo_Test_Session
* We are disabling this function on Windows OSes right now until
* we can be certain of the proper way to check world-readability
*
- * @return unknown
+ * @return bool
*/
function isTestable()
{
diff --git a/plugins/SegmentEditor/SegmentEditor.php b/plugins/SegmentEditor/SegmentEditor.php
index cc0146df90..1c588a483d 100644
--- a/plugins/SegmentEditor/SegmentEditor.php
+++ b/plugins/SegmentEditor/SegmentEditor.php
@@ -102,16 +102,11 @@ class SegmentEditor extends \Piwik\Plugin
public function getJsFiles(&$jsFiles)
{
- $jsFiles[] = "plugins/SegmentEditor/javascripts/jquery.jscrollpane.js";
$jsFiles[] = "plugins/SegmentEditor/javascripts/Segmentation.js";
- $jsFiles[] = "plugins/SegmentEditor/javascripts/jquery.mousewheel.js";
- $jsFiles[] = "plugins/SegmentEditor/javascripts/mwheelIntent.js";
}
public function getCssFiles(&$cssFiles)
{
$cssFiles[] = "plugins/SegmentEditor/stylesheets/segmentation.less";
- $cssFiles[] = "plugins/SegmentEditor/stylesheets/jquery.jscrollpane.css";
- $cssFiles[] = "plugins/SegmentEditor/stylesheets/scroll.less";
}
}
diff --git a/plugins/SegmentEditor/images/down_arrow.png b/plugins/SegmentEditor/images/down_arrow.png
deleted file mode 100644
index a364892c7d..0000000000
--- a/plugins/SegmentEditor/images/down_arrow.png
+++ /dev/null
Binary files differ
diff --git a/plugins/SegmentEditor/images/scroller.png b/plugins/SegmentEditor/images/scroller.png
deleted file mode 100644
index ddcab93426..0000000000
--- a/plugins/SegmentEditor/images/scroller.png
+++ /dev/null
Binary files differ
diff --git a/plugins/SegmentEditor/javascripts/Segmentation.js b/plugins/SegmentEditor/javascripts/Segmentation.js
index 8c3029c674..93ec161bb7 100644
--- a/plugins/SegmentEditor/javascripts/Segmentation.js
+++ b/plugins/SegmentEditor/javascripts/Segmentation.js
@@ -45,14 +45,14 @@ Segmentation = (function($) {
return self.currentSegmentStr;
}
return decodeURIComponent(self.currentSegmentStr);
- }
+ };
var setSegment = function(segmentStr){
if(!$.browser.mozilla) {
segmentStr = encodeURIComponent(segmentStr);
}
self.currentSegmentStr = segmentStr;
- }
+ };
segmentation.prototype.shortenSegmentName = function(name, length){
@@ -74,7 +74,7 @@ Segmentation = (function($) {
return name.slice(0,i)+"...";
}
return name;
- }
+ };
var markCurrentSegment = function(){
var current = self.getSegment();
@@ -96,35 +96,35 @@ Segmentation = (function($) {
else {
$(self.content).find(".segmentationTitle").text(self.translations['SegmentEditor_DefaultAllVisits']);
}
- }
+ };
var getAndDiv = function(){
if(typeof andDiv === "undefined"){
var andDiv = $("#SegmentEditor > div.segment-and").clone();
}
return andDiv.clone();
- }
+ };
var getOrDiv = function(){
if(typeof orDiv === "undefined"){
var orDiv = $("#SegmentEditor > div.segment-or").clone();
}
return orDiv.clone();
- }
+ };
var getMockedInputSet = function(){
if(typeof mockedInputSet === "undefined"){
var mockedInputSet = $("#SegmentEditor div.segment-row-inputs").clone();
}
return mockedInputSet.clone();
- }
+ };
var getMockedInputRowHtml = function(){
if(typeof mockedInputRow === "undefined"){
var mockedInputRow = '<div class="segment-row"><a class="segment-close" href="#"></a><div class="segment-row-inputs">'+getMockedInputSet().html()+'</div></div>';
}
return mockedInputRow;
- }
+ };
var getMockedFormRow = function(){
if(typeof mockedFormRow === "undefined")
@@ -133,7 +133,7 @@ Segmentation = (function($) {
$(mockedFormRow).find(".segment-row").append(getMockedInputSet()).after(getAddOrBlockButtonHtml).after(getOrDiv());
}
return mockedFormRow.clone();
- }
+ };
var getInitialStateRowsHtml = function(){
if(typeof initialStateRows === "undefined"){
@@ -141,12 +141,12 @@ Segmentation = (function($) {
var initialStateRows = $(content).clone();
}
return initialStateRows;
- }
+ };
var revokeInitialStateRows = function(){
$(self.form).find(".segment-add-row").remove();
$(self.form).find(".segment-and").remove();
- }
+ };
var appendSpecifiedRowHtml= function(metric) {
$(self.form).find(".segment-content > h3").after(getMockedFormRow());
@@ -154,7 +154,7 @@ Segmentation = (function($) {
$(self.form).find(".segment-content").append(getAddNewBlockButtonHtml());
doDragDropBindings();
$(self.form).find(".metricList").val(metric).trigger("change");
- }
+ };
var appendComplexRowHtml = function(block){
var key;
@@ -177,13 +177,13 @@ Segmentation = (function($) {
$(newRow).append(getAddOrBlockButtonHtml());
}
$(self.form).find(".segment-content").append(newRow).append(getAndDiv());
- }
+ };
var applyInitialStateModification = function(){
$(self.form).find(".segment-add-row").remove();
$(self.form).find(".segment-content").append(getInitialStateRowsHtml());
doDragDropBindings();
- }
+ };
var getSegmentFromId = function (id) {
if(self.availableSegments.length > 0) {
@@ -196,7 +196,7 @@ Segmentation = (function($) {
}
}
return false;
- }
+ };
var getListHtml = function() {
var html = $("#SegmentEditor > .listHtml").clone();
@@ -236,7 +236,7 @@ Segmentation = (function($) {
$(html).find(".segmentList > ul").append(listHtml);
}
return html;
- }
+ };
var getFormHtml = function() {
var html = $("#SegmentEditor > .segment-element").clone();
@@ -257,7 +257,7 @@ Segmentation = (function($) {
}
$(html).find(".segment-content > h3").after(getInitialStateRowsHtml()).show();
return html;
- }
+ };
var doListBindings = function()
{
@@ -273,14 +273,14 @@ Segmentation = (function($) {
doDragDropBindings();
});
- }
+ };
var closeAllOpenLists = function() {
$(".segmentationContainer").each(function() {
if($(this).hasClass("visible"))
$(this).trigger("click");
});
- }
+ };
var findAndExplodeByMatch = function(metric){
@@ -324,7 +324,7 @@ Segmentation = (function($) {
newMetric.value = decodeURIComponent(newMetric.value);
return newMetric;
- }
+ };
var parseSegmentStr = function(segmentStr)
{
@@ -337,7 +337,7 @@ Segmentation = (function($) {
}
}
return blocks;
- }
+ };
var openEditForm = function(segment){
addForm("edit", segment);
@@ -361,7 +361,7 @@ Segmentation = (function($) {
$(this).trigger("change", true);
});
doDragDropBindings();
- }
+ };
var bindListEvents = function(){
$(self.content).off("click").on("click", function(event){
@@ -420,7 +420,7 @@ Segmentation = (function($) {
autoSuggestValues(this, persist);
} );
- }
+ };
// Request auto-suggest values
var autoSuggestValues = function(select, persist) {
@@ -457,7 +457,7 @@ Segmentation = (function($) {
});
ajaxHandler.send();
}
- }
+ };
var alterMatchesList = function(select, persist){
var oldMatch;
@@ -479,7 +479,7 @@ Segmentation = (function($) {
matchSelector.append(optionsHtml);
matchSelector.val(oldMatch);
- }
+ };
var getAddNewBlockButtonHtml = function()
{
@@ -489,7 +489,7 @@ Segmentation = (function($) {
}
return addNewBlockButton.clone();
- }
+ };
var getAddOrBlockButtonHtml = function(){
if(typeof addOrBlockButton === "undefined")
@@ -497,7 +497,7 @@ Segmentation = (function($) {
var addOrBlockButton = $("#SegmentEditor div.segment-add-or").clone();
}
return addOrBlockButton.clone();
- }
+ };
var placeSegmentationFormControls = function(){
doDragDropBindings();
@@ -507,7 +507,7 @@ Segmentation = (function($) {
verticalArrowPositions: 'os',
horizontalArrowPositions: 'os'
});
- }
+ };
function openEditFormGivenSegment(option) {
var segment = {};
@@ -542,7 +542,7 @@ Segmentation = (function($) {
var oldName = $(e.currentTarget).parents("h3").find("span").text();
$(e.currentTarget).parents("h3").find("span").hide();
$(e.currentTarget).hide();
- $(e.currentTarget).before('<input id="edit_segment_name"/>');
+ $(e.currentTarget).before('<input id="edit_segment_name" type="text"/>');
$(e.currentTarget).siblings("#edit_segment_name").focus().val(oldName);
});
@@ -616,7 +616,7 @@ Segmentation = (function($) {
$(self.form).on("click", ".delete", function(){
var segmentName = $(self.form).find(".segment-content > h3 > span").text();
- var segmentId = $(self.form).find("#available_segments_select option:selected").attr("data-idsegment")
+ var segmentId = $(self.form).find("#available_segments_select option:selected").attr("data-idsegment");
var params = {
"idsegment" : segmentId
};
@@ -645,7 +645,7 @@ Segmentation = (function($) {
bindChangeMetricSelectEvent();
placeSegmentationFormControls();
- }
+ };
var doDragDropBindings = function(){
$(self.form).find(".segment-nav div > ul > li > ul > li").sortable({
@@ -681,9 +681,7 @@ Segmentation = (function($) {
$(this).find("a").trigger("click", [ui.draggable.parent().attr("data-metric")]);
}
});
-
-
- }
+ };
var searchSegments = function(search){
// pre-process search string to normalized form
@@ -700,7 +698,7 @@ Segmentation = (function($) {
// 1 - do most obvious selection -> mark whole categories matching search string
// also expand whole category
$(self.form).find('.segment-nav div > ul > li').each( function(){
- curStr = normalizeSearchString($(this).find("a.metric_category").text())
+ curStr = normalizeSearchString($(this).find("a.metric_category").text());
if(curStr.indexOf(search) > -1) {
$(this).addClass("searchFound");
$(this).find("ul").show();
@@ -736,7 +734,7 @@ Segmentation = (function($) {
self.searchAllowed = true;
}
- }
+ };
var clearSearchMetricHighlight = function(){
$(self.form).find('.no_results').remove();
@@ -744,7 +742,7 @@ Segmentation = (function($) {
$(self.form).find('.segment-nav div > ul > li').removeClass("others").show();
$(self.form).find('.segment-nav div > ul > li > ul > li').show();
$(self.form).find('.segment-nav div > ul > li > ul').hide();
- }
+ };
var normalizeSearchString = function(search){
search = search.replace(/^\s+|\s+$/g, ''); // trim
@@ -760,7 +758,7 @@ Segmentation = (function($) {
.replace(/\s+/g, '_') // collapse whitespace and replace by underscore
.replace(/-+/g, '-'); // collapse dashes
return search;
- }
+ };
var bindSegmentManipulationEvents = function(){
// upon clicking - add new segment block, then bind 'x' action to newly added row
@@ -769,7 +767,7 @@ Segmentation = (function($) {
if(typeof data !== "undefined"){
$(self.form).find(".metricList:last").val(data);
}
- $(self.form).find(".metricList:last").trigger('change')
+ $(self.form).find(".metricList:last").trigger('change');
doDragDropBindings();
});
@@ -807,7 +805,7 @@ Segmentation = (function($) {
}
}
});
- }
+ };
// Mode = 'new' or 'edit'
var addForm = function(mode, segment){
@@ -822,7 +820,6 @@ Segmentation = (function($) {
self.form = getFormHtml();
$("#segmentEditorPanel").prepend(self.form);
- setLeftMargin('#segmentEditorPanel > .segment-element');
bindFormEvents();
bindSegmentManipulationEvents();
@@ -854,7 +851,7 @@ Segmentation = (function($) {
}
$("#segmentList").hide();
- }
+ };
var parseForm = function(){
var segmentStr = "";
@@ -879,7 +876,7 @@ Segmentation = (function($) {
segmentStr += subSegmentStr;
});
return segmentStr
- }
+ };
var parseFormAndSave = function(){
var segmentName = $(self.form).find(".segment-content > h3 >span").text();
@@ -905,7 +902,7 @@ Segmentation = (function($) {
});
self.updateMethod(params);
}
- }
+ };
var makeDropList = function(spanId, selectId){
var select = $(self.form).find(selectId).hide();
@@ -954,11 +951,11 @@ Segmentation = (function($) {
dropList.autocomplete().autocomplete("close");
}
});
- }
+ };
var setLeftMargin = function(selector) {
$(selector).css({left: Math.max($('#periodString')[0].offsetWidth) + 10});
- }
+ };
function toggleLoadingMessage(segmentIsSet) {
if (segmentIsSet) {
@@ -980,7 +977,7 @@ Segmentation = (function($) {
$("#"+self.targetId).append(html);
self.content = $("#"+self.targetId).find(".segmentationContainer");
}
- setLeftMargin('.segmentationContainer');
+ setLeftMargin('#segmentEditorPanel');
// assign content to object attribute to make it easil accesible through all widget methods
bindListEvents();
@@ -989,7 +986,7 @@ Segmentation = (function($) {
// Loading message
var segmentIsSet = self.getSegment().length;
toggleLoadingMessage(segmentIsSet);
- }
+ };
initHtml();
};
@@ -1014,7 +1011,7 @@ $(document).ready( function(){
definition = definition.replace("'", "%29");
definition = definition.replace("&", "%26");
return definition;
- }
+ };
var addSegment = function(params){
var ajaxHandler = new ajaxHelper();
diff --git a/plugins/SegmentEditor/javascripts/jquery.jscrollpane.js b/plugins/SegmentEditor/javascripts/jquery.jscrollpane.js
deleted file mode 100644
index 48d8be8537..0000000000
--- a/plugins/SegmentEditor/javascripts/jquery.jscrollpane.js
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*!
- * jScrollPane - v2.0.0beta12 - 2012-09-27
- * http://jscrollpane.kelvinluck.com/
- *
- * Copyright (c) 2010 Kelvin Luck
- * Dual licensed under the MIT or GPL licenses.
- */
-
-// Script: jScrollPane - cross browser customisable scrollbars
-//
-// *Version: 2.0.0beta12, Last updated: 2012-09-27*
-//
-// Project Home - http://jscrollpane.kelvinluck.com/
-// GitHub - http://github.com/vitch/jScrollPane
-// Source - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.js
-// (Minified) - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.js
-//
-// About: License
-//
-// Copyright (c) 2012 Kelvin Luck
-// Dual licensed under the MIT or GPL Version 2 licenses.
-// http://jscrollpane.kelvinluck.com/MIT-LICENSE.txt
-// http://jscrollpane.kelvinluck.com/GPL-LICENSE.txt
-//
-// About: Examples
-//
-// All examples and demos are available through the jScrollPane example site at:
-// http://jscrollpane.kelvinluck.com/
-//
-// About: Support and Testing
-//
-// This plugin is tested on the browsers below and has been found to work reliably on them. If you run
-// into a problem on one of the supported browsers then please visit the support section on the jScrollPane
-// website (http://jscrollpane.kelvinluck.com/) for more information on getting support. You are also
-// welcome to fork the project on GitHub if you can contribute a fix for a given issue.
-//
-// jQuery Versions - tested in 1.4.2+ - reported to work in 1.3.x
-// Browsers Tested - Firefox 3.6.8, Safari 5, Opera 10.6, Chrome 5.0, IE 6, 7, 8
-//
-// About: Release History
-//
-// 2.0.0beta12 - (2012-09-27) fix for jQuery 1.8+
-// 2.0.0beta11 - (2012-05-14)
-// 2.0.0beta10 - (2011-04-17) cleaner required size calculation, improved keyboard support, stickToBottom/Left, other small fixes
-// 2.0.0beta9 - (2011-01-31) new API methods, bug fixes and correct keyboard support for FF/OSX
-// 2.0.0beta8 - (2011-01-29) touchscreen support, improved keyboard support
-// 2.0.0beta7 - (2011-01-23) scroll speed consistent (thanks Aivo Paas)
-// 2.0.0beta6 - (2010-12-07) scrollToElement horizontal support
-// 2.0.0beta5 - (2010-10-18) jQuery 1.4.3 support, various bug fixes
-// 2.0.0beta4 - (2010-09-17) clickOnTrack support, bug fixes
-// 2.0.0beta3 - (2010-08-27) Horizontal mousewheel, mwheelIntent, keyboard support, bug fixes
-// 2.0.0beta2 - (2010-08-21) Bug fixes
-// 2.0.0beta1 - (2010-08-17) Rewrite to follow modern best practices and enable horizontal scrolling, initially hidden
-// elements and dynamically sized elements.
-// 1.x - (2006-12-31 - 2010-07-31) Initial version, hosted at googlecode, deprecated
-
-(function ($, window, undefined) {
-
- $.fn.jScrollPane = function (settings) {
- // JScrollPane "class" - public methods are available through $('selector').data('jsp')
- function JScrollPane(elem, s) {
- var settings, jsp = this, pane, paneWidth, paneHeight, container, contentWidth, contentHeight,
- percentInViewH, percentInViewV, isScrollableV, isScrollableH, verticalDrag, dragMaxY,
- verticalDragPosition, horizontalDrag, dragMaxX, horizontalDragPosition,
- verticalBar, verticalTrack, scrollbarWidth, verticalTrackHeight, verticalDragHeight, arrowUp, arrowDown,
- horizontalBar, horizontalTrack, horizontalTrackWidth, horizontalDragWidth, arrowLeft, arrowRight,
- reinitialiseInterval, originalPadding, originalPaddingTotalWidth, previousContentWidth,
- wasAtTop = true, wasAtLeft = true, wasAtBottom = false, wasAtRight = false,
- originalElement = elem.clone(false, false).empty(),
- mwEvent = $.fn.mwheelIntent ? 'mwheelIntent.jsp' : 'mousewheel.jsp';
-
- originalPadding = elem.css('paddingTop') + ' ' +
- elem.css('paddingRight') + ' ' +
- elem.css('paddingBottom') + ' ' +
- elem.css('paddingLeft');
- originalPaddingTotalWidth = (parseInt(elem.css('paddingLeft'), 10) || 0) +
- (parseInt(elem.css('paddingRight'), 10) || 0);
-
- function initialise(s) {
-
- var /*firstChild, lastChild, */isMaintainingPositon, lastContentX, lastContentY,
- hasContainingSpaceChanged, originalScrollTop, originalScrollLeft,
- maintainAtBottom = false, maintainAtRight = false;
-
- settings = s;
-
- if (pane === undefined) {
- originalScrollTop = elem.scrollTop();
- originalScrollLeft = elem.scrollLeft();
-
- elem.css(
- {
- overflow: 'hidden',
- padding: 0
- }
- );
- // TODO: Deal with where width/ height is 0 as it probably means the element is hidden and we should
- // come back to it later and check once it is unhidden...
- paneWidth = elem.innerWidth();
- paneHeight = elem.innerHeight();
-
- elem.width(paneWidth);
-
- pane = $('<div class="jspPane" />').css('padding', originalPadding).append(elem.children());
- container = $('<div class="jspContainer" />')
- .css({
- 'width': paneWidth + 'px',
- 'height': paneHeight + 'px'
- }
- ).append(pane).appendTo(elem);
-
- /*
- // Move any margins from the first and last children up to the container so they can still
- // collapse with neighbouring elements as they would before jScrollPane
- firstChild = pane.find(':first-child');
- lastChild = pane.find(':last-child');
- elem.css(
- {
- 'margin-top': firstChild.css('margin-top'),
- 'margin-bottom': lastChild.css('margin-bottom')
- }
- );
- firstChild.css('margin-top', 0);
- lastChild.css('margin-bottom', 0);
- */
- } else {
- elem.css('width', '');
-
- maintainAtBottom = settings.stickToBottom && isCloseToBottom();
- maintainAtRight = settings.stickToRight && isCloseToRight();
-
- hasContainingSpaceChanged = elem.innerWidth() + originalPaddingTotalWidth != paneWidth || elem.outerHeight() != paneHeight;
-
- if (hasContainingSpaceChanged) {
- paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
- paneHeight = elem.innerHeight();
- container.css({
- width: paneWidth + 'px',
- height: paneHeight + 'px'
- });
- }
-
- // If nothing changed since last check...
- if (!hasContainingSpaceChanged && previousContentWidth == contentWidth && pane.outerHeight() == contentHeight) {
- elem.width(paneWidth);
- return;
- }
- previousContentWidth = contentWidth;
-
- pane.css('width', '');
- elem.width(paneWidth);
-
- container.find('>.jspVerticalBar,>.jspHorizontalBar').remove().end();
- }
-
- pane.css('overflow', 'auto');
- if (s.contentWidth) {
- contentWidth = s.contentWidth;
- } else {
- contentWidth = pane[0].scrollWidth;
- }
- contentHeight = pane[0].scrollHeight;
- pane.css('overflow', '');
-
- percentInViewH = contentWidth / paneWidth;
- percentInViewV = contentHeight / paneHeight;
- isScrollableV = percentInViewV > 1;
-
- isScrollableH = percentInViewH > 1;
-
- //console.log(paneWidth, paneHeight, contentWidth, contentHeight, percentInViewH, percentInViewV, isScrollableH, isScrollableV);
-
- if (!(isScrollableH || isScrollableV)) {
- elem.removeClass('jspScrollable');
- pane.css({
- top: 0,
- width: container.width() - originalPaddingTotalWidth
- });
- removeMousewheel();
- removeFocusHandler();
- removeKeyboardNav();
- removeClickOnTrack();
- } else {
- elem.addClass('jspScrollable');
-
- isMaintainingPositon = settings.maintainPosition && (verticalDragPosition || horizontalDragPosition);
- if (isMaintainingPositon) {
- lastContentX = contentPositionX();
- lastContentY = contentPositionY();
- }
-
- initialiseVerticalScroll();
- initialiseHorizontalScroll();
- resizeScrollbars();
-
- if (isMaintainingPositon) {
- scrollToX(maintainAtRight ? (contentWidth - paneWidth ) : lastContentX, false);
- scrollToY(maintainAtBottom ? (contentHeight - paneHeight) : lastContentY, false);
- }
-
- initFocusHandler();
- initMousewheel();
- initTouch();
-
- if (settings.enableKeyboardNavigation) {
- initKeyboardNav();
- }
- if (settings.clickOnTrack) {
- initClickOnTrack();
- }
-
- observeHash();
- if (settings.hijackInternalLinks) {
- hijackInternalLinks();
- }
- }
-
- if (settings.autoReinitialise && !reinitialiseInterval) {
- reinitialiseInterval = setInterval(
- function () {
- initialise(settings);
- },
- settings.autoReinitialiseDelay
- );
- } else if (!settings.autoReinitialise && reinitialiseInterval) {
- clearInterval(reinitialiseInterval);
- }
-
- originalScrollTop && elem.scrollTop(0) && scrollToY(originalScrollTop, false);
- originalScrollLeft && elem.scrollLeft(0) && scrollToX(originalScrollLeft, false);
-
- elem.trigger('jsp-initialised', [isScrollableH || isScrollableV]);
- }
-
- function initialiseVerticalScroll() {
- if (isScrollableV) {
-
- container.append(
- $('<div class="jspVerticalBar" />').append(
- $('<div class="jspCap jspCapTop" />'),
- $('<div class="jspTrack" />').append(
- $('<div class="jspDrag" />').append(
- $('<div class="jspDragTop" />'),
- $('<div class="jspDragBottom" />')
- )
- ),
- $('<div class="jspCap jspCapBottom" />')
- )
- );
-
- verticalBar = container.find('>.jspVerticalBar');
- verticalTrack = verticalBar.find('>.jspTrack');
- verticalDrag = verticalTrack.find('>.jspDrag');
-
- if (settings.showArrows) {
- arrowUp = $('<a class="jspArrow jspArrowUp" />').bind(
- 'mousedown.jsp', getArrowScroll(0, -1)
- ).bind('click.jsp', nil);
- arrowDown = $('<a class="jspArrow jspArrowDown" />').bind(
- 'mousedown.jsp', getArrowScroll(0, 1)
- ).bind('click.jsp', nil);
- if (settings.arrowScrollOnHover) {
- arrowUp.bind('mouseover.jsp', getArrowScroll(0, -1, arrowUp));
- arrowDown.bind('mouseover.jsp', getArrowScroll(0, 1, arrowDown));
- }
-
- appendArrows(verticalTrack, settings.verticalArrowPositions, arrowUp, arrowDown);
- }
-
- verticalTrackHeight = paneHeight;
- container.find('>.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow').each(
- function () {
- verticalTrackHeight -= $(this).outerHeight();
- }
- );
-
-
- verticalDrag.hover(
- function () {
- verticalDrag.addClass('jspHover');
- },
- function () {
- verticalDrag.removeClass('jspHover');
- }
- ).bind(
- 'mousedown.jsp',
- function (e) {
- // Stop IE from allowing text selection
- $('html').bind('dragstart.jsp selectstart.jsp', nil);
-
- verticalDrag.addClass('jspActive');
-
- var startY = e.pageY - verticalDrag.position().top;
-
- $('html').bind(
- 'mousemove.jsp',
- function (e) {
- positionDragY(e.pageY - startY, false);
- }
- ).bind('mouseup.jsp mouseleave.jsp', cancelDrag);
- return false;
- }
- );
- sizeVerticalScrollbar();
- }
- }
-
- function sizeVerticalScrollbar() {
- verticalTrack.height(verticalTrackHeight + 'px');
- verticalDragPosition = 0;
- scrollbarWidth = settings.verticalGutter + verticalTrack.outerWidth();
-
- // Make the pane thinner to allow for the vertical scrollbar
- pane.width(paneWidth - scrollbarWidth - originalPaddingTotalWidth);
-
- // Add margin to the left of the pane if scrollbars are on that side (to position
- // the scrollbar on the left or right set it's left or right property in CSS)
- try {
- if (verticalBar.position().left === 0) {
- pane.css('margin-left', scrollbarWidth + 'px');
- }
- } catch (err) {
- }
- }
-
- function initialiseHorizontalScroll() {
- if (isScrollableH) {
-
- container.append(
- $('<div class="jspHorizontalBar" />').append(
- $('<div class="jspCap jspCapLeft" />'),
- $('<div class="jspTrack" />').append(
- $('<div class="jspDrag" />').append(
- $('<div class="jspDragLeft" />'),
- $('<div class="jspDragRight" />')
- )
- ),
- $('<div class="jspCap jspCapRight" />')
- )
- );
-
- horizontalBar = container.find('>.jspHorizontalBar');
- horizontalTrack = horizontalBar.find('>.jspTrack');
- horizontalDrag = horizontalTrack.find('>.jspDrag');
-
- if (settings.showArrows) {
- arrowLeft = $('<a class="jspArrow jspArrowLeft" />').bind(
- 'mousedown.jsp', getArrowScroll(-1, 0)
- ).bind('click.jsp', nil);
- arrowRight = $('<a class="jspArrow jspArrowRight" />').bind(
- 'mousedown.jsp', getArrowScroll(1, 0)
- ).bind('click.jsp', nil);
- if (settings.arrowScrollOnHover) {
- arrowLeft.bind('mouseover.jsp', getArrowScroll(-1, 0, arrowLeft));
- arrowRight.bind('mouseover.jsp', getArrowScroll(1, 0, arrowRight));
- }
- appendArrows(horizontalTrack, settings.horizontalArrowPositions, arrowLeft, arrowRight);
- }
-
- horizontalDrag.hover(
- function () {
- horizontalDrag.addClass('jspHover');
- },
- function () {
- horizontalDrag.removeClass('jspHover');
- }
- ).bind(
- 'mousedown.jsp',
- function (e) {
- // Stop IE from allowing text selection
- $('html').bind('dragstart.jsp selectstart.jsp', nil);
-
- horizontalDrag.addClass('jspActive');
-
- var startX = e.pageX - horizontalDrag.position().left;
-
- $('html').bind(
- 'mousemove.jsp',
- function (e) {
- positionDragX(e.pageX - startX, false);
- }
- ).bind('mouseup.jsp mouseleave.jsp', cancelDrag);
- return false;
- }
- );
- horizontalTrackWidth = container.innerWidth();
- sizeHorizontalScrollbar();
- }
- }
-
- function sizeHorizontalScrollbar() {
- container.find('>.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow').each(
- function () {
- horizontalTrackWidth -= $(this).outerWidth();
- }
- );
-
- horizontalTrack.width(horizontalTrackWidth + 'px');
- horizontalDragPosition = 0;
- }
-
- function resizeScrollbars() {
- if (isScrollableH && isScrollableV) {
- var horizontalTrackHeight = horizontalTrack.outerHeight(),
- verticalTrackWidth = verticalTrack.outerWidth();
- verticalTrackHeight -= horizontalTrackHeight;
- $(horizontalBar).find('>.jspCap:visible,>.jspArrow').each(
- function () {
- horizontalTrackWidth += $(this).outerWidth();
- }
- );
- horizontalTrackWidth -= verticalTrackWidth;
- paneHeight -= verticalTrackWidth;
- paneWidth -= horizontalTrackHeight;
- horizontalTrack.parent().append(
- $('<div class="jspCorner" />').css('width', horizontalTrackHeight + 'px')
- );
- sizeVerticalScrollbar();
- sizeHorizontalScrollbar();
- }
- // reflow content
- if (isScrollableH) {
- pane.width((container.outerWidth() - originalPaddingTotalWidth) + 'px');
- }
- contentHeight = pane.outerHeight();
- percentInViewV = contentHeight / paneHeight;
-
- if (isScrollableH) {
- horizontalDragWidth = Math.ceil(1 / percentInViewH * horizontalTrackWidth);
- if (horizontalDragWidth > settings.horizontalDragMaxWidth) {
- horizontalDragWidth = settings.horizontalDragMaxWidth;
- } else if (horizontalDragWidth < settings.horizontalDragMinWidth) {
- horizontalDragWidth = settings.horizontalDragMinWidth;
- }
- horizontalDrag.width(horizontalDragWidth + 'px');
- dragMaxX = horizontalTrackWidth - horizontalDragWidth;
- _positionDragX(horizontalDragPosition); // To update the state for the arrow buttons
- }
- if (isScrollableV) {
- verticalDragHeight = Math.ceil(1 / percentInViewV * verticalTrackHeight);
- if (verticalDragHeight > settings.verticalDragMaxHeight) {
- verticalDragHeight = settings.verticalDragMaxHeight;
- } else if (verticalDragHeight < settings.verticalDragMinHeight) {
- verticalDragHeight = settings.verticalDragMinHeight;
- }
- verticalDrag.height(verticalDragHeight + 'px');
- dragMaxY = verticalTrackHeight - verticalDragHeight;
- _positionDragY(verticalDragPosition); // To update the state for the arrow buttons
- }
- }
-
- function appendArrows(ele, p, a1, a2) {
- var p1 = "before", p2 = "after", aTemp;
-
- // Sniff for mac... Is there a better way to determine whether the arrows would naturally appear
- // at the top or the bottom of the bar?
- if (p == "os") {
- p = /Mac/.test(navigator.platform) ? "after" : "split";
- }
- if (p == p1) {
- p2 = p;
- } else if (p == p2) {
- p1 = p;
- aTemp = a1;
- a1 = a2;
- a2 = aTemp;
- }
-
- ele[p1](a1)[p2](a2);
- }
-
- function getArrowScroll(dirX, dirY, ele) {
- return function () {
- arrowScroll(dirX, dirY, this, ele);
- this.blur();
- return false;
- };
- }
-
- function arrowScroll(dirX, dirY, arrow, ele) {
- arrow = $(arrow).addClass('jspActive');
-
- var eve,
- scrollTimeout,
- isFirst = true,
- doScroll = function () {
- if (dirX !== 0) {
- jsp.scrollByX(dirX * settings.arrowButtonSpeed);
- }
- if (dirY !== 0) {
- jsp.scrollByY(dirY * settings.arrowButtonSpeed);
- }
- scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.arrowRepeatFreq);
- isFirst = false;
- };
-
- doScroll();
-
- eve = ele ? 'mouseout.jsp' : 'mouseup.jsp';
- ele = ele || $('html');
- ele.bind(
- eve,
- function () {
- arrow.removeClass('jspActive');
- scrollTimeout && clearTimeout(scrollTimeout);
- scrollTimeout = null;
- ele.unbind(eve);
- }
- );
- }
-
- function initClickOnTrack() {
- removeClickOnTrack();
- if (isScrollableV) {
- verticalTrack.bind(
- 'mousedown.jsp',
- function (e) {
- if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
- var clickedTrack = $(this),
- offset = clickedTrack.offset(),
- direction = e.pageY - offset.top - verticalDragPosition,
- scrollTimeout,
- isFirst = true,
- doScroll = function () {
- var offset = clickedTrack.offset(),
- pos = e.pageY - offset.top - verticalDragHeight / 2,
- contentDragY = paneHeight * settings.scrollPagePercent,
- dragY = dragMaxY * contentDragY / (contentHeight - paneHeight);
- if (direction < 0) {
- if (verticalDragPosition - dragY > pos) {
- jsp.scrollByY(-contentDragY);
- } else {
- positionDragY(pos);
- }
- } else if (direction > 0) {
- if (verticalDragPosition + dragY < pos) {
- jsp.scrollByY(contentDragY);
- } else {
- positionDragY(pos);
- }
- } else {
- cancelClick();
- return;
- }
- scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.trackClickRepeatFreq);
- isFirst = false;
- },
- cancelClick = function () {
- scrollTimeout && clearTimeout(scrollTimeout);
- scrollTimeout = null;
- $(document).unbind('mouseup.jsp', cancelClick);
- };
- doScroll();
- $(document).bind('mouseup.jsp', cancelClick);
- return false;
- }
- }
- );
- }
-
- if (isScrollableH) {
- horizontalTrack.bind(
- 'mousedown.jsp',
- function (e) {
- if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
- var clickedTrack = $(this),
- offset = clickedTrack.offset(),
- direction = e.pageX - offset.left - horizontalDragPosition,
- scrollTimeout,
- isFirst = true,
- doScroll = function () {
- var offset = clickedTrack.offset(),
- pos = e.pageX - offset.left - horizontalDragWidth / 2,
- contentDragX = paneWidth * settings.scrollPagePercent,
- dragX = dragMaxX * contentDragX / (contentWidth - paneWidth);
- if (direction < 0) {
- if (horizontalDragPosition - dragX > pos) {
- jsp.scrollByX(-contentDragX);
- } else {
- positionDragX(pos);
- }
- } else if (direction > 0) {
- if (horizontalDragPosition + dragX < pos) {
- jsp.scrollByX(contentDragX);
- } else {
- positionDragX(pos);
- }
- } else {
- cancelClick();
- return;
- }
- scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.trackClickRepeatFreq);
- isFirst = false;
- },
- cancelClick = function () {
- scrollTimeout && clearTimeout(scrollTimeout);
- scrollTimeout = null;
- $(document).unbind('mouseup.jsp', cancelClick);
- };
- doScroll();
- $(document).bind('mouseup.jsp', cancelClick);
- return false;
- }
- }
- );
- }
- }
-
- function removeClickOnTrack() {
- if (horizontalTrack) {
- horizontalTrack.unbind('mousedown.jsp');
- }
- if (verticalTrack) {
- verticalTrack.unbind('mousedown.jsp');
- }
- }
-
- function cancelDrag() {
- $('html').unbind('dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp');
-
- if (verticalDrag) {
- verticalDrag.removeClass('jspActive');
- }
- if (horizontalDrag) {
- horizontalDrag.removeClass('jspActive');
- }
- }
-
- function positionDragY(destY, animate) {
- if (!isScrollableV) {
- return;
- }
- if (destY < 0) {
- destY = 0;
- } else if (destY > dragMaxY) {
- destY = dragMaxY;
- }
-
- // can't just check if(animate) because false is a valid value that could be passed in...
- if (animate === undefined) {
- animate = settings.animateScroll;
- }
- if (animate) {
- jsp.animate(verticalDrag, 'top', destY, _positionDragY);
- } else {
- verticalDrag.css('top', destY);
- _positionDragY(destY);
- }
-
- }
-
- function _positionDragY(destY) {
- if (destY === undefined) {
- destY = verticalDrag.position().top;
- }
-
- container.scrollTop(0);
- verticalDragPosition = destY;
-
- var isAtTop = verticalDragPosition === 0,
- isAtBottom = verticalDragPosition == dragMaxY,
- percentScrolled = destY / dragMaxY,
- destTop = -percentScrolled * (contentHeight - paneHeight);
-
- if (wasAtTop != isAtTop || wasAtBottom != isAtBottom) {
- wasAtTop = isAtTop;
- wasAtBottom = isAtBottom;
- elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
- }
-
- updateVerticalArrows(isAtTop, isAtBottom);
- pane.css('top', destTop);
- elem.trigger('jsp-scroll-y', [-destTop, isAtTop, isAtBottom]).trigger('scroll');
- }
-
- function positionDragX(destX, animate) {
- if (!isScrollableH) {
- return;
- }
- if (destX < 0) {
- destX = 0;
- } else if (destX > dragMaxX) {
- destX = dragMaxX;
- }
-
- if (animate === undefined) {
- animate = settings.animateScroll;
- }
- if (animate) {
- jsp.animate(horizontalDrag, 'left', destX, _positionDragX);
- } else {
- horizontalDrag.css('left', destX);
- _positionDragX(destX);
- }
- }
-
- function _positionDragX(destX) {
- if (destX === undefined) {
- destX = horizontalDrag.position().left;
- }
-
- container.scrollTop(0);
- horizontalDragPosition = destX;
-
- var isAtLeft = horizontalDragPosition === 0,
- isAtRight = horizontalDragPosition == dragMaxX,
- percentScrolled = destX / dragMaxX,
- destLeft = -percentScrolled * (contentWidth - paneWidth);
-
- if (wasAtLeft != isAtLeft || wasAtRight != isAtRight) {
- wasAtLeft = isAtLeft;
- wasAtRight = isAtRight;
- elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
- }
-
- updateHorizontalArrows(isAtLeft, isAtRight);
- pane.css('left', destLeft);
- elem.trigger('jsp-scroll-x', [-destLeft, isAtLeft, isAtRight]).trigger('scroll');
- }
-
- function updateVerticalArrows(isAtTop, isAtBottom) {
- if (settings.showArrows) {
- arrowUp[isAtTop ? 'addClass' : 'removeClass']('jspDisabled');
- arrowDown[isAtBottom ? 'addClass' : 'removeClass']('jspDisabled');
- }
- }
-
- function updateHorizontalArrows(isAtLeft, isAtRight) {
- if (settings.showArrows) {
- arrowLeft[isAtLeft ? 'addClass' : 'removeClass']('jspDisabled');
- arrowRight[isAtRight ? 'addClass' : 'removeClass']('jspDisabled');
- }
- }
-
- function scrollToY(destY, animate) {
- var percentScrolled = destY / (contentHeight - paneHeight);
- positionDragY(percentScrolled * dragMaxY, animate);
- }
-
- function scrollToX(destX, animate) {
- var percentScrolled = destX / (contentWidth - paneWidth);
- positionDragX(percentScrolled * dragMaxX, animate);
- }
-
- function scrollToElement(ele, stickToTop, animate) {
- var e, eleHeight, eleWidth, eleTop = 0, eleLeft = 0, viewportTop, viewportLeft, maxVisibleEleTop, maxVisibleEleLeft, destY, destX;
-
- // Legal hash values aren't necessarily legal jQuery selectors so we need to catch any
- // errors from the lookup...
- try {
- e = $(ele);
- } catch (err) {
- return;
- }
- eleHeight = e.outerHeight();
- eleWidth = e.outerWidth();
-
- container.scrollTop(0);
- container.scrollLeft(0);
-
- // loop through parents adding the offset top of any elements that are relatively positioned between
- // the focused element and the jspPane so we can get the true distance from the top
- // of the focused element to the top of the scrollpane...
- while (!e.is('.jspPane')) {
- eleTop += e.position().top;
- eleLeft += e.position().left;
- e = e.offsetParent();
- if (/^body|html$/i.test(e[0].nodeName)) {
- // we ended up too high in the document structure. Quit!
- return;
- }
- }
-
- viewportTop = contentPositionY();
- maxVisibleEleTop = viewportTop + paneHeight;
- if (eleTop < viewportTop || stickToTop) { // element is above viewport
- destY = eleTop - settings.verticalGutter;
- } else if (eleTop + eleHeight > maxVisibleEleTop) { // element is below viewport
- destY = eleTop - paneHeight + eleHeight + settings.verticalGutter;
- }
- if (destY) {
- scrollToY(destY, animate);
- }
-
- viewportLeft = contentPositionX();
- maxVisibleEleLeft = viewportLeft + paneWidth;
- if (eleLeft < viewportLeft || stickToTop) { // element is to the left of viewport
- destX = eleLeft - settings.horizontalGutter;
- } else if (eleLeft + eleWidth > maxVisibleEleLeft) { // element is to the right viewport
- destX = eleLeft - paneWidth + eleWidth + settings.horizontalGutter;
- }
- if (destX) {
- scrollToX(destX, animate);
- }
-
- }
-
- function contentPositionX() {
- return -pane.position().left;
- }
-
- function contentPositionY() {
- return -pane.position().top;
- }
-
- function isCloseToBottom() {
- var scrollableHeight = contentHeight - paneHeight;
- return (scrollableHeight > 20) && (scrollableHeight - contentPositionY() < 10);
- }
-
- function isCloseToRight() {
- var scrollableWidth = contentWidth - paneWidth;
- return (scrollableWidth > 20) && (scrollableWidth - contentPositionX() < 10);
- }
-
- function initMousewheel() {
- container.unbind(mwEvent).bind(
- mwEvent,
- function (event, delta, deltaX, deltaY) {
- var dX = horizontalDragPosition, dY = verticalDragPosition;
- jsp.scrollBy(deltaX * settings.mouseWheelSpeed, -deltaY * settings.mouseWheelSpeed, false);
- // return true if there was no movement so rest of screen can scroll
- return dX == horizontalDragPosition && dY == verticalDragPosition;
- }
- );
- }
-
- function removeMousewheel() {
- container.unbind(mwEvent);
- }
-
- function nil() {
- return false;
- }
-
- function initFocusHandler() {
- pane.find(':input,a').unbind('focus.jsp').bind(
- 'focus.jsp',
- function (e) {
- scrollToElement(e.target, false);
- }
- );
- }
-
- function removeFocusHandler() {
- pane.find(':input,a').unbind('focus.jsp');
- }
-
- function initKeyboardNav() {
- var keyDown, elementHasScrolled, validParents = [];
- isScrollableH && validParents.push(horizontalBar[0]);
- isScrollableV && validParents.push(verticalBar[0]);
-
- // IE also focuses elements that don't have tabindex set.
- pane.focus(
- function () {
- elem.focus();
- }
- );
-
- elem.attr('tabindex', 0)
- .unbind('keydown.jsp keypress.jsp')
- .bind(
- 'keydown.jsp',
- function (e) {
- if (e.target !== this && !(validParents.length && $(e.target).closest(validParents).length)) {
- return;
- }
- var dX = horizontalDragPosition, dY = verticalDragPosition;
- switch (e.keyCode) {
- case 40: // down
- case 38: // up
- case 34: // page down
- case 32: // space
- case 33: // page up
- case 39: // right
- case 37: // left
- keyDown = e.keyCode;
- keyDownHandler();
- break;
- case 35: // end
- scrollToY(contentHeight - paneHeight);
- keyDown = null;
- break;
- case 36: // home
- scrollToY(0);
- keyDown = null;
- break;
- }
-
- elementHasScrolled = e.keyCode == keyDown && dX != horizontalDragPosition || dY != verticalDragPosition;
- return !elementHasScrolled;
- }
- ).bind(
- 'keypress.jsp', // For FF/ OSX so that we can cancel the repeat key presses if the JSP scrolls...
- function (e) {
- if (e.keyCode == keyDown) {
- keyDownHandler();
- }
- return !elementHasScrolled;
- }
- );
-
- if (settings.hideFocus) {
- elem.css('outline', 'none');
- if ('hideFocus' in container[0]) {
- elem.attr('hideFocus', true);
- }
- } else {
- elem.css('outline', '');
- if ('hideFocus' in container[0]) {
- elem.attr('hideFocus', false);
- }
- }
-
- function keyDownHandler() {
- var dX = horizontalDragPosition, dY = verticalDragPosition;
- switch (keyDown) {
- case 40: // down
- jsp.scrollByY(settings.keyboardSpeed, false);
- break;
- case 38: // up
- jsp.scrollByY(-settings.keyboardSpeed, false);
- break;
- case 34: // page down
- case 32: // space
- jsp.scrollByY(paneHeight * settings.scrollPagePercent, false);
- break;
- case 33: // page up
- jsp.scrollByY(-paneHeight * settings.scrollPagePercent, false);
- break;
- case 39: // right
- jsp.scrollByX(settings.keyboardSpeed, false);
- break;
- case 37: // left
- jsp.scrollByX(-settings.keyboardSpeed, false);
- break;
- }
-
- elementHasScrolled = dX != horizontalDragPosition || dY != verticalDragPosition;
- return elementHasScrolled;
- }
- }
-
- function removeKeyboardNav() {
- elem.attr('tabindex', '-1')
- .removeAttr('tabindex')
- .unbind('keydown.jsp keypress.jsp');
- }
-
- function observeHash() {
- if (location.hash && location.hash.length > 1) {
- var e,
- retryInt,
- hash = escape(location.hash.substr(1)) // hash must be escaped to prevent XSS
- ;
- try {
- e = $('#' + hash + ', a[name="' + hash + '"]');
- } catch (err) {
- return;
- }
-
- if (e.length && pane.find(hash)) {
- // nasty workaround but it appears to take a little while before the hash has done its thing
- // to the rendered page so we just wait until the container's scrollTop has been messed up.
- if (container.scrollTop() === 0) {
- retryInt = setInterval(
- function () {
- if (container.scrollTop() > 0) {
- scrollToElement(e, true);
- $(document).scrollTop(container.position().top);
- clearInterval(retryInt);
- }
- },
- 50
- );
- } else {
- scrollToElement(e, true);
- $(document).scrollTop(container.position().top);
- }
- }
- }
- }
-
- function hijackInternalLinks() {
- // only register the link handler once
- if ($(document.body).data('jspHijack')) {
- return;
- }
-
- // remember that the handler was bound
- $(document.body).data('jspHijack', true);
-
- // use live handler to also capture newly created links
- $(document.body).delegate('a[href*=#]', 'click', function (event) {
- // does the link point to the same page?
- // this also takes care of cases with a <base>-Tag or Links not starting with the hash #
- // e.g. <a href="index.html#test"> when the current url already is index.html
- var href = this.href.substr(0, this.href.indexOf('#')),
- locationHref = location.href,
- hash,
- element,
- container,
- jsp,
- scrollTop,
- elementTop;
- if (location.href.indexOf('#') !== -1) {
- locationHref = location.href.substr(0, location.href.indexOf('#'));
- }
- if (href !== locationHref) {
- // the link points to another page
- return;
- }
-
- // check if jScrollPane should handle this click event
- hash = escape(this.href.substr(this.href.indexOf('#') + 1));
-
- // find the element on the page
- try {
- element = $('#' + hash + ', a[name="' + hash + '"]');
- } catch (e) {
- // hash is not a valid jQuery identifier
- return;
- }
-
- if (!element.length) {
- // this link does not point to an element on this page
- return;
- }
-
- container = element.closest('.jspScrollable');
- jsp = container.data('jsp');
-
- // jsp might be another jsp instance than the one, that bound this event
- // remember: this event is only bound once for all instances.
- jsp.scrollToElement(element, true);
-
- if (container[0].scrollIntoView) {
- // also scroll to the top of the container (if it is not visible)
- scrollTop = $(window).scrollTop();
- elementTop = element.offset().top;
- if (elementTop < scrollTop || elementTop > scrollTop + $(window).height()) {
- container[0].scrollIntoView();
- }
- }
-
- // jsp handled this event, prevent the browser default (scrolling :P)
- event.preventDefault();
- });
- }
-
- // Init touch on iPad, iPhone, iPod, Android
- function initTouch() {
- var startX,
- startY,
- touchStartX,
- touchStartY,
- moved,
- moving = false;
-
- container.unbind('touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick').bind(
- 'touchstart.jsp',
- function (e) {
- var touch = e.originalEvent.touches[0];
- startX = contentPositionX();
- startY = contentPositionY();
- touchStartX = touch.pageX;
- touchStartY = touch.pageY;
- moved = false;
- moving = true;
- }
- ).bind(
- 'touchmove.jsp',
- function (ev) {
- if (!moving) {
- return;
- }
-
- var touchPos = ev.originalEvent.touches[0],
- dX = horizontalDragPosition, dY = verticalDragPosition;
-
- jsp.scrollTo(startX + touchStartX - touchPos.pageX, startY + touchStartY - touchPos.pageY);
-
- moved = moved || Math.abs(touchStartX - touchPos.pageX) > 5 || Math.abs(touchStartY - touchPos.pageY) > 5;
-
- // return true if there was no movement so rest of screen can scroll
- return dX == horizontalDragPosition && dY == verticalDragPosition;
- }
- ).bind(
- 'touchend.jsp',
- function (e) {
- moving = false;
- /*if(moved) {
- return false;
- }*/
- }
- ).bind(
- 'click.jsp-touchclick',
- function (e) {
- if (moved) {
- moved = false;
- return false;
- }
- }
- );
- }
-
- function destroy() {
- var currentY = contentPositionY(),
- currentX = contentPositionX();
- elem.removeClass('jspScrollable').unbind('.jsp');
- elem.replaceWith(originalElement.append(pane.children()));
- originalElement.scrollTop(currentY);
- originalElement.scrollLeft(currentX);
-
- // clear reinitialize timer if active
- if (reinitialiseInterval) {
- clearInterval(reinitialiseInterval);
- }
- }
-
- // Public API
- $.extend(
- jsp,
- {
- // Reinitialises the scroll pane (if it's internal dimensions have changed since the last time it
- // was initialised). The settings object which is passed in will override any settings from the
- // previous time it was initialised - if you don't pass any settings then the ones from the previous
- // initialisation will be used.
- reinitialise: function (s) {
- s = $.extend({}, settings, s);
- initialise(s);
- },
- // Scrolls the specified element (a jQuery object, DOM node or jQuery selector string) into view so
- // that it can be seen within the viewport. If stickToTop is true then the element will appear at
- // the top of the viewport, if it is false then the viewport will scroll as little as possible to
- // show the element. You can also specify if you want animation to occur. If you don't provide this
- // argument then the animateScroll value from the settings object is used instead.
- scrollToElement: function (ele, stickToTop, animate) {
- scrollToElement(ele, stickToTop, animate);
- },
- // Scrolls the pane so that the specified co-ordinates within the content are at the top left
- // of the viewport. animate is optional and if not passed then the value of animateScroll from
- // the settings object this jScrollPane was initialised with is used.
- scrollTo: function (destX, destY, animate) {
- scrollToX(destX, animate);
- scrollToY(destY, animate);
- },
- // Scrolls the pane so that the specified co-ordinate within the content is at the left of the
- // viewport. animate is optional and if not passed then the value of animateScroll from the settings
- // object this jScrollPane was initialised with is used.
- scrollToX: function (destX, animate) {
- scrollToX(destX, animate);
- },
- // Scrolls the pane so that the specified co-ordinate within the content is at the top of the
- // viewport. animate is optional and if not passed then the value of animateScroll from the settings
- // object this jScrollPane was initialised with is used.
- scrollToY: function (destY, animate) {
- scrollToY(destY, animate);
- },
- // Scrolls the pane to the specified percentage of its maximum horizontal scroll position. animate
- // is optional and if not passed then the value of animateScroll from the settings object this
- // jScrollPane was initialised with is used.
- scrollToPercentX: function (destPercentX, animate) {
- scrollToX(destPercentX * (contentWidth - paneWidth), animate);
- },
- // Scrolls the pane to the specified percentage of its maximum vertical scroll position. animate
- // is optional and if not passed then the value of animateScroll from the settings object this
- // jScrollPane was initialised with is used.
- scrollToPercentY: function (destPercentY, animate) {
- scrollToY(destPercentY * (contentHeight - paneHeight), animate);
- },
- // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
- // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
- scrollBy: function (deltaX, deltaY, animate) {
- jsp.scrollByX(deltaX, animate);
- jsp.scrollByY(deltaY, animate);
- },
- // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
- // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
- scrollByX: function (deltaX, animate) {
- var destX = contentPositionX() + Math[deltaX < 0 ? 'floor' : 'ceil'](deltaX),
- percentScrolled = destX / (contentWidth - paneWidth);
- positionDragX(percentScrolled * dragMaxX, animate);
- },
- // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
- // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
- scrollByY: function (deltaY, animate) {
- var destY = contentPositionY() + Math[deltaY < 0 ? 'floor' : 'ceil'](deltaY),
- percentScrolled = destY / (contentHeight - paneHeight);
- positionDragY(percentScrolled * dragMaxY, animate);
- },
- // Positions the horizontal drag at the specified x position (and updates the viewport to reflect
- // this). animate is optional and if not passed then the value of animateScroll from the settings
- // object this jScrollPane was initialised with is used.
- positionDragX: function (x, animate) {
- positionDragX(x, animate);
- },
- // Positions the vertical drag at the specified y position (and updates the viewport to reflect
- // this). animate is optional and if not passed then the value of animateScroll from the settings
- // object this jScrollPane was initialised with is used.
- positionDragY: function (y, animate) {
- positionDragY(y, animate);
- },
- // This method is called when jScrollPane is trying to animate to a new position. You can override
- // it if you want to provide advanced animation functionality. It is passed the following arguments:
- // * ele - the element whose position is being animated
- // * prop - the property that is being animated
- // * value - the value it's being animated to
- // * stepCallback - a function that you must execute each time you update the value of the property
- // You can use the default implementation (below) as a starting point for your own implementation.
- animate: function (ele, prop, value, stepCallback) {
- var params = {};
- params[prop] = value;
- ele.animate(
- params,
- {
- 'duration': settings.animateDuration,
- 'easing': settings.animateEase,
- 'queue': false,
- 'step': stepCallback
- }
- );
- },
- // Returns the current x position of the viewport with regards to the content pane.
- getContentPositionX: function () {
- return contentPositionX();
- },
- // Returns the current y position of the viewport with regards to the content pane.
- getContentPositionY: function () {
- return contentPositionY();
- },
- // Returns the width of the content within the scroll pane.
- getContentWidth: function () {
- return contentWidth;
- },
- // Returns the height of the content within the scroll pane.
- getContentHeight: function () {
- return contentHeight;
- },
- // Returns the horizontal position of the viewport within the pane content.
- getPercentScrolledX: function () {
- return contentPositionX() / (contentWidth - paneWidth);
- },
- // Returns the vertical position of the viewport within the pane content.
- getPercentScrolledY: function () {
- return contentPositionY() / (contentHeight - paneHeight);
- },
- // Returns whether or not this scrollpane has a horizontal scrollbar.
- getIsScrollableH: function () {
- return isScrollableH;
- },
- // Returns whether or not this scrollpane has a vertical scrollbar.
- getIsScrollableV: function () {
- return isScrollableV;
- },
- // Gets a reference to the content pane. It is important that you use this method if you want to
- // edit the content of your jScrollPane as if you access the element directly then you may have some
- // problems (as your original element has had additional elements for the scrollbars etc added into
- // it).
- getContentPane: function () {
- return pane;
- },
- // Scrolls this jScrollPane down as far as it can currently scroll. If animate isn't passed then the
- // animateScroll value from settings is used instead.
- scrollToBottom: function (animate) {
- positionDragY(dragMaxY, animate);
- },
- // Hijacks the links on the page which link to content inside the scrollpane. If you have changed
- // the content of your page (e.g. via AJAX) and want to make sure any new anchor links to the
- // contents of your scroll pane will work then call this function.
- hijackInternalLinks: $.noop,
- // Removes the jScrollPane and returns the page to the state it was in before jScrollPane was
- // initialised.
- destroy: function () {
- destroy();
- }
- }
- );
-
- initialise(s);
- }
-
- // Pluginifying code...
- settings = $.extend({}, $.fn.jScrollPane.defaults, settings);
-
- // Apply default speed
- $.each(['mouseWheelSpeed', 'arrowButtonSpeed', 'trackClickSpeed', 'keyboardSpeed'], function () {
- settings[this] = settings[this] || settings.speed;
- });
-
- return this.each(
- function () {
- var elem = $(this), jspApi = elem.data('jsp');
- if (jspApi) {
- jspApi.reinitialise(settings);
- } else {
- $("script", elem).filter('[type="text/javascript"],:not([type])').remove();
- jspApi = new JScrollPane(elem, settings);
- elem.data('jsp', jspApi);
- }
- }
- );
- };
-
- $.fn.jScrollPane.defaults = {
- showArrows: false,
- maintainPosition: true,
- stickToBottom: false,
- stickToRight: false,
- clickOnTrack: true,
- autoReinitialise: false,
- autoReinitialiseDelay: 500,
- verticalDragMinHeight: 0,
- verticalDragMaxHeight: 99999,
- horizontalDragMinWidth: 0,
- horizontalDragMaxWidth: 99999,
- contentWidth: undefined,
- animateScroll: false,
- animateDuration: 300,
- animateEase: 'linear',
- hijackInternalLinks: false,
- verticalGutter: 4,
- horizontalGutter: 4,
- mouseWheelSpeed: 0,
- arrowButtonSpeed: 0,
- arrowRepeatFreq: 50,
- arrowScrollOnHover: false,
- trackClickSpeed: 0,
- trackClickRepeatFreq: 70,
- verticalArrowPositions: 'split',
- horizontalArrowPositions: 'split',
- enableKeyboardNavigation: true,
- hideFocus: false,
- keyboardSpeed: 0,
- initialDelay: 300, // Delay before starting repeating
- speed: 30, // Default speed when others falsey
- scrollPagePercent: .8 // Percent of visible area scrolled when pageUp/Down or track area pressed
- };
-
-})(jQuery, this);
diff --git a/plugins/SegmentEditor/javascripts/jquery.mousewheel.js b/plugins/SegmentEditor/javascripts/jquery.mousewheel.js
deleted file mode 100644
index 9d65c7162b..0000000000
--- a/plugins/SegmentEditor/javascripts/jquery.mousewheel.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/*! Copyright (c) 2013 Brandon Aaron (http://brandonaaron.net)
- * Licensed under the MIT License (LICENSE.txt).
- *
- * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
- * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
- * Thanks to: Seamus Leahy for adding deltaX and deltaY
- *
- * Version: 3.1.3
- *
- * Requires: 1.2.2+
- */
-
-(function (factory) {
- if ( typeof define === 'function' && define.amd ) {
- // AMD. Register as an anonymous module.
- define(['jquery'], factory);
- } else if (typeof exports === 'object') {
- // Node/CommonJS style for Browserify
- module.exports = factory;
- } else {
- // Browser globals
- factory(jQuery);
- }
-}(function ($) {
-
- var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
- var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
- var lowestDelta, lowestDeltaXY;
-
- if ( $.event.fixHooks ) {
- for ( var i = toFix.length; i; ) {
- $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
- }
- }
-
- $.event.special.mousewheel = {
- setup: function() {
- if ( this.addEventListener ) {
- for ( var i = toBind.length; i; ) {
- this.addEventListener( toBind[--i], handler, false );
- }
- } else {
- this.onmousewheel = handler;
- }
- },
-
- teardown: function() {
- if ( this.removeEventListener ) {
- for ( var i = toBind.length; i; ) {
- this.removeEventListener( toBind[--i], handler, false );
- }
- } else {
- this.onmousewheel = null;
- }
- }
- };
-
- $.fn.extend({
- mousewheel: function(fn) {
- return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
- },
-
- unmousewheel: function(fn) {
- return this.unbind("mousewheel", fn);
- }
- });
-
-
- function handler(event) {
- var orgEvent = event || window.event,
- args = [].slice.call(arguments, 1),
- delta = 0,
- deltaX = 0,
- deltaY = 0,
- absDelta = 0,
- absDeltaXY = 0,
- fn;
- event = $.event.fix(orgEvent);
- event.type = "mousewheel";
-
- // Old school scrollwheel delta
- if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
- if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
-
- // New school wheel delta (wheel event)
- if ( orgEvent.deltaY ) {
- deltaY = orgEvent.deltaY * -1;
- delta = deltaY;
- }
- if ( orgEvent.deltaX ) {
- deltaX = orgEvent.deltaX;
- delta = deltaX * -1;
- }
-
- // Webkit
- if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
- if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }
-
- // Look for lowest delta to normalize the delta values
- absDelta = Math.abs(delta);
- if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
- absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
- if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
-
- // Get a whole value for the deltas
- fn = delta > 0 ? 'floor' : 'ceil';
- delta = Math[fn](delta / lowestDelta);
- deltaX = Math[fn](deltaX / lowestDeltaXY);
- deltaY = Math[fn](deltaY / lowestDeltaXY);
-
- // Add event and delta to the front of the arguments
- args.unshift(event, delta, deltaX, deltaY);
-
- return ($.event.dispatch || $.event.handle).apply(this, args);
- }
-
-}));
diff --git a/plugins/SegmentEditor/javascripts/mwheelIntent.js b/plugins/SegmentEditor/javascripts/mwheelIntent.js
deleted file mode 100644
index 72b7d135ca..0000000000
--- a/plugins/SegmentEditor/javascripts/mwheelIntent.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * @author trixta
- * @version 1.2
- */
-(function($){
-
- var mwheelI = {
- pos: [-260, -260]
- },
- minDif = 3,
- doc = document,
- root = doc.documentElement,
- body = doc.body,
- longDelay, shortDelay
- ;
-
- function unsetPos(){
- if(this === mwheelI.elem){
- mwheelI.pos = [-260, -260];
- mwheelI.elem = false;
- minDif = 3;
- }
- }
-
- $.event.special.mwheelIntent = {
- setup: function(){
- var jElm = $(this).bind('mousewheel', $.event.special.mwheelIntent.handler);
- if( this !== doc && this !== root && this !== body ){
- jElm.bind('mouseleave', unsetPos);
- }
- jElm = null;
- return true;
- },
- teardown: function(){
- $(this)
- .unbind('mousewheel', $.event.special.mwheelIntent.handler)
- .unbind('mouseleave', unsetPos)
- ;
- return true;
- },
- handler: function(e, d){
- var pos = [e.clientX, e.clientY];
- if( this === mwheelI.elem || Math.abs(mwheelI.pos[0] - pos[0]) > minDif || Math.abs(mwheelI.pos[1] - pos[1]) > minDif ){
- mwheelI.elem = this;
- mwheelI.pos = pos;
- minDif = 250;
-
- clearTimeout(shortDelay);
- shortDelay = setTimeout(function(){
- minDif = 10;
- }, 200);
- clearTimeout(longDelay);
- longDelay = setTimeout(function(){
- minDif = 3;
- }, 1500);
- e = $.extend({}, e, {type: 'mwheelIntent'});
- return $.event.dispatch.apply(this, arguments);
- }
- }
- };
- $.fn.extend({
- mwheelIntent: function(fn) {
- return fn ? this.bind("mwheelIntent", fn) : this.trigger("mwheelIntent");
- },
-
- unmwheelIntent: function(fn) {
- return this.unbind("mwheelIntent", fn);
- }
- });
-
- $(function(){
- body = doc.body;
- //assume that document is always scrollable, doesn't hurt if not
- $(doc).bind('mwheelIntent.mwheelIntentDefault', $.noop);
- });
-})(jQuery);
diff --git a/plugins/SegmentEditor/stylesheets/jquery.jscrollpane.css b/plugins/SegmentEditor/stylesheets/jquery.jscrollpane.css
deleted file mode 100644
index 0364216fe0..0000000000
--- a/plugins/SegmentEditor/stylesheets/jquery.jscrollpane.css
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * CSS Styles that are needed by jScrollPane for it to operate correctly.
- *
- * Include this stylesheet in your site or copy and paste the styles below into your stylesheet - jScrollPane
- * may not operate correctly without them.
- */
-
-.jspContainer
-{
- overflow: hidden;
- position: relative;
-}
-
-.jspPane
-{
- position: absolute;
-}
-
-.jspVerticalBar
-{
- position: absolute;
- top: 0;
- right: 0;
- width: 8px;
- height: 100%;
- background: red;
-}
-
-.jspHorizontalBar
-{
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 16px;
- background: red;
-}
-
-.jspVerticalBar *,
-.jspHorizontalBar *
-{
- margin: 0;
- padding: 0;
-}
-
-.jspCap
-{
- display: none;
-}
-
-.jspHorizontalBar .jspCap
-{
- float: left;
-}
-
-.jspTrack
-{
- background: #dde;
- position: relative;
-}
-
-.jspDrag
-{
- background: #bbd;
- position: relative;
- top: 0;
- left: 0;
- cursor: pointer;
-}
-
-.jspHorizontalBar .jspTrack,
-.jspHorizontalBar .jspDrag
-{
- float: left;
- height: 100%;
-}
-
-.jspArrow
-{
- background: #50506d;
- text-indent: -20000px;
- display: block;
- cursor: pointer;
-}
-
-.jspArrow.jspDisabled
-{
- cursor: default;
-}
-
-.jspVerticalBar .jspArrow
-{
- height: 16px;
-}
-
-.jspHorizontalBar .jspArrow
-{
- width: 16px;
- float: left;
- height: 100%;
-}
-
-.jspVerticalBar .jspArrow:focus
-{
- outline: none;
-}
-
-.jspCorner
-{
- background: #eeeef4;
- float: left;
- height: 100%;
-}
-
-/* Yuk! CSS Hack for IE6 3 pixel bug :( */
-* html .jspCorner
-{
- margin: 0 -3px 0 0;
-} \ No newline at end of file
diff --git a/plugins/SegmentEditor/stylesheets/scroll.less b/plugins/SegmentEditor/stylesheets/scroll.less
deleted file mode 100644
index 508adb4c7a..0000000000
--- a/plugins/SegmentEditor/stylesheets/scroll.less
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * CSS Styles that are needed by jScrollPane for it to operate correctly.
- *
- * Include this stylesheet in your site or copy and paste the styles below into your stylesheet - jScrollPane
- * may not operate correctly without them.
- */
-
-.jspContainer
-{
- /*overflow: hidden;*/
- position: relative;
-}
-
-.jspPane
-{
- position: absolute;
-}
-
-.jspVerticalBar
-{
- position: absolute;
- top: 0;
- right: 0;
- width: 16px;
- height: 100%;
-}
-
-.jspHorizontalBar
-{
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 16px;
- background: red;
-}
-
-.jspVerticalBar *,
-.jspHorizontalBar *
-{
- margin: 0;
- padding: 0;
-}
-
-.jspCap
-{
- display: none;
-}
-
-.jspHorizontalBar .jspCap
-{
- float: left;
-}
-
-.jspTrack
-{
- background: url("../images/slide.png") transparent no-repeat 7px;
- position: relative;
- background-size: 20% 100%;
- /*height: 447px!important;*/
-}
-
-.jspDrag
-{
- background: url("../images/scroller.png") transparent no-repeat;
- background-size: 100% 100%;
- width: 17px;
- position: relative;
- top: 0;
- left: 0;
- cursor: pointer;
-}
-
-.jspHorizontalBar .jspTrack,
-.jspHorizontalBar .jspDrag
-{
- float: left;
- height: 100%;
-}
-
-.jspArrow
-{
-
- text-indent: -20000px;
- display: block;
- cursor: pointer;
-}
-.jspArrowDown{
- background: url("../images/down_arrow.png") transparent no-repeat;
-}
-.jspArrowUp{
- background: url("../images/up_arrow.png") transparent no-repeat;
-}
-
-.jspVerticalBar .jspArrow
-{
- height: 14px;
-
-}
-
-.jspHorizontalBar .jspArrow
-{
- width: 16px;
- float: left;
- height: 100%;
-}
-
-.jspVerticalBar .jspArrow:focus
-{
- outline: none;
-}
-
-.jspCorner
-{
- background: #eeeef4;
- float: left;
- height: 100%;
-}
-
-/* Yuk! CSS Hack for IE6 3 pixel bug :( */
-* html .jspCorner
-{
- margin: 0 -3px 0 0;
-}
-
-/* Styles specific to this particular page */
-.scroll-pane-before,
-.scroll-pane-after,
-.scroll-pane-split,
-.scroll-pane-os
-{
- width: 100%;
- height: 200px;
- overflow: auto;
-}
-.horizontal-only
-{
- height: auto;
- max-height: 200px;
-}
diff --git a/plugins/SegmentEditor/stylesheets/segmentation.less b/plugins/SegmentEditor/stylesheets/segmentation.less
index d2ec307deb..ccd34d25a0 100644
--- a/plugins/SegmentEditor/stylesheets/segmentation.less
+++ b/plugins/SegmentEditor/stylesheets/segmentation.less
@@ -81,13 +81,16 @@ div.scrollable {
border: 1px solid #a9a399;
background-color: #f1f0eb;
padding: 6px 4px;
- border-radius: 3px 3px 3px 3px;
+ border-radius: 3px;
+ position: absolute;
+ left: 0;
+ top: 0;
}
.segment-element .custom_select_search {
width: 146px;
height: 21px;
- background: url(../images/bg-segment-search.png) 0 10px no-repeat;
+ background: url(plugins/SegmentEditor/images/bg-segment-search.png) 0 10px no-repeat;
padding: 10px 0 0 0;
margin: 10px 0 10px 15px;
border-top: 1px solid #dcdacf;
@@ -109,7 +112,7 @@ div.scrollable {
height: 13px;
right: 5px;
top: 14px;
- background: url(../images/reset_search.png);
+ background: url(plugins/SegmentEditor/images/reset_search.png);
}
.segment-element .segment-nav {
@@ -128,8 +131,8 @@ div.scrollable {
}
.segment-element .segment-nav h4.visits {
- padding-left: 28px;
- background: url(../images/icon-users.png) 0 0 no-repeat;
+ padding-left: 15px;
+ background: url(plugins/SegmentEditor/images/icon-users.png) 0 0 no-repeat;
}
.segment-element .segment-nav h4 a {
@@ -141,41 +144,40 @@ div.scrollable {
padding: 0 0 0 15px;
}
-.segment-element .segment-nav div > ul > li {
+.segment-element .segment-nav div > ul > li {
padding: 2px 0;
line-height: 14px;
}
-.segment-element .segment-nav div > ul > li li {
+.segment-element .segment-nav div > ul > li li {
padding: 1px;
border-radius: 3px 3px 3px 3px;
}
-.segment-element .segment-nav div > ul > li li:hover {
+.segment-element .segment-nav div > ul > li li:hover {
padding: 0;
border: 1px solid #cfccbd;
border-bottom: 1px solid #7c7a72;
- background-color: #e9e7e3;
}
-.segment-element .segment-nav div > ul > li li:hover a {
+.segment-element .segment-nav div > ul > li li:hover a {
cursor: move;
padding: 1px 0 2px 8px;
border-top: 1px solid #fff;
- background: #eae8e3 url(../images/segment-move.png) 100% 50% no-repeat;
+ background: #eae8e3 url(plugins/SegmentEditor/images/segment-move.png) 100% 50% no-repeat;
}
-.segment-element .segment-nav div > ul > li li a {
+.segment-element .segment-nav div > ul > li li a {
padding: 2px 0 2px 8px;
font-weight: normal;
display: block;
}
-.segment-element .segment-nav div > ul > li ul {
+.segment-element .segment-nav div > ul > li ul {
margin: 2px 0 -3px 10px;
}
-.segment-element .segment-nav div > ul > li a {
+.segment-element .segment-nav div > ul > li a {
color: #5d5342;
font: bold 11px Arial;
text-decoration: none;
@@ -219,21 +221,21 @@ div.scrollable {
position: relative;
}
-.segment-element .segment-content .segment-add-row > div,
-.segment-element .segment-content .segment-add-or > div {
+.segment-element .segment-content .segment-add-row > div,
+.segment-element .segment-content .segment-add-or > div {
border-radius: 4px;
border: 2px dashed #fff;
padding: 10px 0;
}
-.segment-element .segment-content .segment-add-row > div a,
-.segment-element .segment-content .segment-add-or > div a {
+.segment-element .segment-content .segment-add-row > div a,
+.segment-element .segment-content .segment-add-or > div a {
color: #b9b9b9;
text-decoration: none;
}
-.segment-element .segment-content .segment-add-row > div a span,
-.segment-element .segment-content .segment-add-or > div a span {
+.segment-element .segment-content .segment-add-row > div a span,
+.segment-element .segment-content .segment-add-or > div a span {
color: #255792;
}
@@ -254,7 +256,7 @@ div.scrollable {
border-radius: 3px 3px 3px 3px;
}
-.segment-element .segment-content .segment-add-or > div {
+.segment-element .segment-content .segment-add-or > div {
border: 2px dashed #EFEFEB;
}
@@ -274,7 +276,7 @@ div.scrollable {
position: absolute;
width: 15px;
height: 15px;
- background: url(../images/segment-close.png) 0 0 no-repeat;
+ background: url(plugins/SegmentEditor/images/segment-close.png) 0 0 no-repeat;
}
.segment-element .segment-content .segment-row .segment-loading {
@@ -284,7 +286,7 @@ div.scrollable {
position: absolute;
width: 15px;
height: 15px;
- background: url(../../MultiSites/images/loading-blue.gif) 0 0 no-repeat;
+ background: url(plugins/MultiSites/images/loading-blue.gif) 0 0 no-repeat;
}
.segment-element .segment-content .segment-or {
@@ -337,7 +339,7 @@ div.scrollable {
.segment-element .segment-content .segment-and:after {
content: '';
position: absolute;
- background: url(../images/bg-inverted-corners.png);
+ background: url(plugins/SegmentEditor/images/bg-inverted-corners.png);
border: 1px solid #a9a399;
width: 10px;
top: 0px;
@@ -397,7 +399,7 @@ div.scrollable {
.segment-element .segment-top a.dropdown {
padding: 0 17px 0 0;
- background: url(../../Zeitgeist/images/sort_subtable_desc.png) 100% -2px no-repeat;
+ background: url(plugins/Zeitgeist/images/sort_subtable_desc.png) 100% -2px no-repeat;
}
.segment-element .segment-footer {
@@ -437,9 +439,9 @@ div.scrollable {
margin: 0 0 0 15px;
}
-.segmentationContainer {
+#segmentEditorPanel {
position: absolute;
- z-index: 2;
+ z-index: 120; /* Should be the same as 'Dashboard widget selector' (z-index: 120) */
background: #f7f7f7;
border: 1px solid #e4e5e4;
padding: 5px 10px 6px 10px;
@@ -448,12 +450,12 @@ div.scrollable {
font-size: 14px;
}
-.segmentationContainer:hover {
+#segmentEditorPanel:hover {
background: #f1f0eb;
border-color: #a9a399;
}
-.segmentationContainer > span > b {
+.segmentationContainer > span > b {
color: #255792;
}
@@ -496,7 +498,7 @@ div.scrollable {
float: left;
}
-.segmentationContainer ul.submenu > li span.editSegment {
+.segmentationContainer ul.submenu > li span.editSegment {
display: block;
float: right;
width: 45px;
@@ -515,7 +517,7 @@ div.scrollable {
.segmentationContainer.visible .add_new_segment {
display: block;
- background: url("../images/dashboard_h_bg_hover.png") repeat-x scroll 0 0 #847b6d;
+ background: url("plugins/SegmentEditor/images/dashboard_h_bg_hover.png") repeat-x scroll 0 0 #847b6d;
border: 0 none;
border-radius: 4px 4px 4px 4px;
clear: both;
@@ -527,14 +529,14 @@ div.scrollable {
width: 130px;
}
-.segmentationContainer > ul.submenu > li {
+.segmentationContainer > ul.submenu > li {
padding: 5px 0;
clear: both;
cursor: pointer;
}
span.segmentationTitle {
- background: url(../../Zeitgeist/images/sort_subtable_desc.png) right center no-repeat !important;
+ background: url(plugins/Zeitgeist/images/sort_subtable_desc.png) no-repeat right 0;
padding-right: 20px !important;
width: 160px !important;
display: block !important;
@@ -545,8 +547,9 @@ span.segmentationTitle {
display: none;
}
-.segmentList {
+#segmentList {
max-height: 250px;
+ overflow: hidden; /* Create a BFC */
}
.jspVerticalBar {
@@ -558,7 +561,7 @@ body > a.ddmetric {
display: block;
cursor: move;
padding: 1px 0 2px 18px;
- background: #eae8e3 url(../images/segment-move.png) 100% 50% no-repeat;
+ background: #eae8e3 url(plugins/SegmentEditor/images/segment-move.png) 100% 50% no-repeat;
color: #5d5342;
font: normal 11px Arial;
text-decoration: none;
@@ -616,7 +619,7 @@ a.metric_category {
}
#available_segments a.dropdown {
- background: url("../../Zeitgeist/images/sort_subtable_desc.png") no-repeat scroll 100% -2px transparent !important;
+ background: url("plugins/Zeitgeist/images/sort_subtable_desc.png") no-repeat scroll 100% -2px transparent !important;
padding: 0 17px 0 0 !important;
}
diff --git a/plugins/SegmentEditor/templates/getSelector.twig b/plugins/SegmentEditor/templates/getSelector.twig
index 181c97bd84..2cecd2dd31 100644
--- a/plugins/SegmentEditor/templates/getSelector.twig
+++ b/plugins/SegmentEditor/templates/getSelector.twig
@@ -137,9 +137,9 @@
</div>
</div>
-<span id="segmentEditorPanel">
+<div id="segmentEditorPanel">
<div id="segmentList"></div>
-</span>
+</div>
<div class="ui-confirm" id="segment-delete-confirm">
<h2>{{ 'SegmentEditor_AreYouSureDeleteSegment'|translate }}</h2>
diff --git a/plugins/SitesManager/javascripts/SitesManager.js b/plugins/SitesManager/javascripts/SitesManager.js
index 73000c3969..e3bcd8c516 100644
--- a/plugins/SitesManager/javascripts/SitesManager.js
+++ b/plugins/SitesManager/javascripts/SitesManager.js
@@ -306,7 +306,7 @@ function SitesManager(_timezones, _currencies, _defaultTimezone, _defaultCurrenc
$('#defaultCurrency').html(getCurrencySelector(defaultCurrency));
$('td.editableSite').click(function () { $(this).parent().find('.editSite').click(); });
- }
+ };
function getSitesearchSelector(contentBefore) {
var globalKeywordParameters = $('input#globalSearchKeywordParameters').val().trim();
diff --git a/plugins/SitesManager/stylesheets/SitesManager.less b/plugins/SitesManager/stylesheets/SitesManager.less
index 0196289bee..fca6f5d8bf 100644
--- a/plugins/SitesManager/stylesheets/SitesManager.less
+++ b/plugins/SitesManager/stylesheets/SitesManager.less
@@ -21,7 +21,7 @@
.addRowSite:before {
display: inline-block;
- content: url(../../UsersManager/images/add.png);
+ content: url(plugins/UsersManager/images/add.png);
vertical-align: middle;
}
diff --git a/plugins/Transitions/javascripts/transitions.js b/plugins/Transitions/javascripts/transitions.js
index da6c8a8bc2..d442a0cf4c 100644
--- a/plugins/Transitions/javascripts/transitions.js
+++ b/plugins/Transitions/javascripts/transitions.js
@@ -29,7 +29,7 @@ DataTable_RowActions_Transitions.isPageUrlReport = function (module, action) {
DataTable_RowActions_Transitions.isPageTitleReport = function (module, action) {
return module == 'Actions' && (action == 'getPageTitles' || action == 'getPageTitlesFollowingSiteSearch');
-}
+};
DataTable_RowActions_Transitions.prototype.trigger = function (tr, e, subTableLabel) {
var link = tr.find('> td:first > a').attr('href');
@@ -808,9 +808,9 @@ Piwik_Transitions_Canvas.prototype.isNarrowMode = function () {
/**
* Helper to create horizontal gradients
* TODO
- * @param lightColor
- * @param darkColor
- * @param position left|right
+ * @param {String} colorGroup
+ * @param {String} position left|right
+ * @param {Boolean} isHighlighted
*/
Piwik_Transitions_Canvas.prototype.createHorizontalGradient = function (colorGroup, position, isHighlighted) {
var fromX, toX, fromColor, toColor, lightColor, darkColor;
diff --git a/plugins/Zeitgeist/stylesheets/ui/_transitions.less b/plugins/Transitions/stylesheets/_transitionColors.less
index e74d16b341..e74d16b341 100644
--- a/plugins/Zeitgeist/stylesheets/ui/_transitions.less
+++ b/plugins/Transitions/stylesheets/_transitionColors.less
diff --git a/plugins/Transitions/stylesheets/transitions.less b/plugins/Transitions/stylesheets/transitions.less
index 7fc748602b..978ffdd86a 100644
--- a/plugins/Transitions/stylesheets/transitions.less
+++ b/plugins/Transitions/stylesheets/transitions.less
@@ -1,3 +1,5 @@
+@import "_transitionColors";
+
#Transitions_Container {
position: relative;
z-index: 1500;
diff --git a/plugins/UserCountry/GeoIPAutoUpdater.php b/plugins/UserCountry/GeoIPAutoUpdater.php
index 6d28c192cd..86383ed4d8 100755
--- a/plugins/UserCountry/GeoIPAutoUpdater.php
+++ b/plugins/UserCountry/GeoIPAutoUpdater.php
@@ -456,13 +456,14 @@ class GeoIPAutoUpdater
* if we can't unzip it...
*
* @param string $ext The URL file's extension.
+ * @throws \Exception
*/
private static function checkForSupportedArchiveType($ext)
{
if ($ext != 'tar.gz'
&& $ext != 'gz'
) {
- throw new Exception(Piwik_Translate('UserCountry_UnsupportedArchiveType', "'$ext'"));
+ throw new \Exception(Piwik_Translate('UserCountry_UnsupportedArchiveType', "'$ext'"));
}
}
diff --git a/plugins/UserCountry/LocationProvider.php b/plugins/UserCountry/LocationProvider.php
index e26e72934d..946e131f19 100755
--- a/plugins/UserCountry/LocationProvider.php
+++ b/plugins/UserCountry/LocationProvider.php
@@ -137,7 +137,7 @@ abstract class LocationProvider
/**
* Returns every available provider instance.
*
- * @return array
+ * @return Piwik_UserCountry_LocationProvider[]
*/
public static function getAllProviders()
{
diff --git a/plugins/UserCountry/LocationProvider/Default.php b/plugins/UserCountry/LocationProvider/Default.php
index dd44183f21..a8eeb1688d 100755
--- a/plugins/UserCountry/LocationProvider/Default.php
+++ b/plugins/UserCountry/LocationProvider/Default.php
@@ -51,7 +51,7 @@ class DefaultProvider extends LocationProvider
*
* This implementation is always available.
*
- * @return true
+ * @return bool always true
*/
public function isAvailable()
{
@@ -63,7 +63,7 @@ class DefaultProvider extends LocationProvider
*
* This implementation is always working correctly.
*
- * @return true
+ * @return bool always true
*/
public function isWorking()
{
diff --git a/plugins/UserCountry/UserCountry.php b/plugins/UserCountry/UserCountry.php
index 5c7bde67e0..a2fcc00992 100644
--- a/plugins/UserCountry/UserCountry.php
+++ b/plugins/UserCountry/UserCountry.php
@@ -378,7 +378,7 @@ class UserCountry extends \Piwik\Plugin
if (!$self->isGeoIPWorking()) {
$params = array('module' => 'UserCountry', 'action' => 'adminIndex');
$footerMessage .= ' ' . Piwik_Translate('UserCountry_NoDataForGeoIPReport2',
- array('<a target="_blank" href="' . Piwik_Url::getCurrentQueryStringWithParametersModified($params) . '">',
+ array('<a target="_blank" href="' . \Piwik\Url::getCurrentQueryStringWithParametersModified($params) . '">',
'</a>',
'<a target="_blank" href="http://dev.maxmind.com/geoip/geolite?rId=piwik">',
'</a>'));
diff --git a/plugins/UserCountry/templates/_updaterManage.twig b/plugins/UserCountry/templates/_updaterManage.twig
index 27d61283f1..7ed533051a 100755
--- a/plugins/UserCountry/templates/_updaterManage.twig
+++ b/plugins/UserCountry/templates/_updaterManage.twig
@@ -43,7 +43,7 @@
</td>
<td width="164">
{% set lastTimeRunNote %}
- {% if lastTimeUpdaterRun is not empty %}
+ {% if lastTimeUpdaterRun is defined and lastTimeUpdaterRun is not empty %}
{{ 'UserCountry_UpdaterWasLastRun'|translate(lastTimeUpdaterRun)|raw }}
{% else %}
{{ 'UserCountry_UpdaterHasNotBeenRun'|translate }}
diff --git a/plugins/UserCountryMap/Controller.php b/plugins/UserCountryMap/Controller.php
index 187aeb9302..50ce58e31a 100644
--- a/plugins/UserCountryMap/Controller.php
+++ b/plugins/UserCountryMap/Controller.php
@@ -30,7 +30,7 @@ class Controller extends \Piwik\Controller
// By default plot up to the last 30 days of visitors on the map, for low traffic sites
const REAL_TIME_WINDOW = 'last30';
- public function visitorMap()
+ public function visitorMap($fetch = false)
{
$this->checkUserCountryPluginEnabled();
@@ -39,6 +39,7 @@ class Controller extends \Piwik\Controller
$period = Common::getRequestVar('period');
$date = Common::getRequestVar('date');
+ $segment = Common::getRequestVar('segment', '', 'string');
$token_auth = Piwik::getCurrentUserTokenAuth();
$view = new View('@UserCountryMap/visitorMap');
@@ -81,6 +82,7 @@ class Controller extends \Piwik\Controller
'period' => $period,
'idSite' => $idSite,
'date' => $date,
+ 'segment' => $segment,
'token_auth' => $token_auth,
'enable_filter_excludelowpop' => 1,
'filter_excludelowpop_value' => -1
@@ -92,7 +94,11 @@ class Controller extends \Piwik\Controller
$view->config = Common::json_encode($config);
$view->noData = empty($config['visitsSummary']['nb_visits']);
- echo $view->render();
+ if ($fetch) {
+ return $view->render();
+ } else {
+ echo $view->render();
+ }
}
/**
@@ -209,7 +215,7 @@ class Controller extends \Piwik\Controller
. "&period=" . $period
. "&date=" . $date
. "&token_auth=" . $token_auth
- . "&segment=" . \Piwik\API\Request::getRawSegmentFromRequest()
+ . "&segment=" . Common::getRequestVar('segment', '', 'string')
. "&enable_filter_excludelowpop=1"
. "&showRawMetrics=1";
diff --git a/plugins/UserSettings/UserSettings.php b/plugins/UserSettings/UserSettings.php
index f6dd1d8a7e..ba52b97d0d 100644
--- a/plugins/UserSettings/UserSettings.php
+++ b/plugins/UserSettings/UserSettings.php
@@ -177,107 +177,171 @@ class UserSettings extends \Piwik\Plugin
public function getReportDisplayProperties(&$properties)
{
- $basicUserSettingsProperties = array('show_search' => false,
- 'show_exclude_low_population' => false,
- 'filter_limit' => 5,
- 'graph_limit' => 5);
+ $properties['UserSettings.getResolution'] = $this->getDisplayPropertiesForGetResolution();
+ $properties['UserSettings.getConfiguration'] = $this->getDisplayPropertiesForGetConfiguration();
+ $properties['UserSettings.getOS'] = $this->getDisplayPropertiesForGetOS();
+ $properties['UserSettings.getOSFamily'] = $this->getDisplayPropertiesForGetOSFamily();
+ $properties['UserSettings.getBrowserVersion'] = $this->getDisplayPropertiesForGetBrowserVersion();
+ $properties['UserSettings.getBrowser'] = $this->getDisplayPropertiesForGetBrowser();
+ $properties['UserSettings.getBrowserType'] = $this->getDisplayPropertiesForGetBrowserType();
+ $properties['UserSettings.getWideScreen'] = $this->getDisplayPropertiesForGetWideScreen();
+ $properties['UserSettings.getMobileVsDesktop'] = $this->getDisplayPropertiesForGetMobileVsDesktop();
+ $properties['UserSettings.getPlugin'] = $this->getDisplayPropertiesForGetPlugin();
+ $properties['UserSettings.getLanguage'] = $this->getDisplayPropertiesForGetLanguage();
+ }
- $osRelatedReports = array(
- 'UserSettings.getOSFamily' => Piwik_Translate('UserSettings_OperatingSystemFamily'),
- 'UserSettings.getOS' => Piwik_Translate('UserSettings_OperatingSystems')
+ private function getDisplayPropertiesForGetResolution()
+ {
+ return array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnResolution'))
+ ));
+ }
+
+ private function getDisplayPropertiesForGetConfiguration()
+ {
+ return array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'filter_limit' => 3,
+ 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnConfiguration'))
+ ));
+ }
+
+ private function getDisplayPropertiesForGetOS()
+ {
+ return array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnOperatingSystem')),
+ 'title' => Piwik_Translate('UserSettings_OperatingSystems'),
+ 'related_reports' => $this->getOsRelatedReports()
+ ));
+ }
+
+ private function getDisplayPropertiesForGetOSFamily()
+ {
+ return array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array('label' => Piwik_Translate('UserSettings_OperatingSystemFamily')),
+ 'title' => Piwik_Translate('UserSettings_OperatingSystemFamily'),
+ 'related_reports' => $this->getOsRelatedReports()
+ ));
+ }
+
+ private function getDisplayPropertiesForGetBrowserVersion()
+ {
+ $result = array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowserVersion')),
+ 'title' => Piwik_Translate('UserSettings_ColumnBrowserVersion'),
+ 'related_reports' => $this->getBrowserRelatedReports()
+ ));
+ $result['visualization_properties']['jqplot_graph']['max_graph_elements'] = 7;
+ return $result;
+ }
+
+ private function getDisplayPropertiesForGetBrowser()
+ {
+ $result = array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowser')),
+ 'title' => Piwik_Translate('UserSettings_Browsers'),
+ 'related_reports' => $this->getBrowserRelatedReports()
+ ));
+ $result['visualization_properties']['jqplot_graph']['max_graph_elements'] = 7;
+ return $result;
+ }
+
+ private function getDisplayPropertiesForGetBrowserType()
+ {
+ return array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowserFamily')),
+ 'show_offset_information' => false,
+ 'show_pagination_control' => false,
+ 'default_view_type' => 'graphPie',
+ ));
+ }
+
+ private function getDisplayPropertiesForGetWideScreen()
+ {
+ return array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnTypeOfScreen')),
+ 'show_offset_information' => false,
+ 'show_pagination_control' => false,
+ 'title' => Piwik_Translate('UserSettings_ColumnTypeOfScreen'),
+ 'related_reports' => $this->getWideScreenDeviceTypeRelatedReports()
+ ));
+ }
+
+ private function getDisplayPropertiesForGetMobileVsDesktop()
+ {
+ return array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array('label' => Piwik_Translate('UserSettings_MobileVsDesktop')),
+ 'title' => Piwik_Translate('UserSettings_MobileVsDesktop'),
+ 'related_reports' => $this->getWideScreenDeviceTypeRelatedReports()
+ ));
+ }
+
+ private function getDisplayPropertiesForGetPlugin()
+ {
+ return array_merge($this->getBasicUserSettingsDisplayProperties(), array(
+ 'translations' => array(
+ 'label' => Piwik_Translate('UserSettings_ColumnPlugin'),
+ 'nb_visits_percentage' =>
+ str_replace(' ', '&nbsp;', Piwik_Translate('General_ColumnPercentageVisits'))
+ ),
+ 'show_offset_information' => false,
+ 'show_pagination_control' => false,
+ 'show_all_views_icons' => false,
+ 'show_table_all_columns' => false,
+ 'columns_to_display' => array('label', 'nb_visits_percentage', 'nb_visits'),
+ 'filter_sort_column' => 'nb_visits_percentage',
+ 'filter_sort_order' => 'desc',
+ 'filter_limit' => 10,
+ 'show_footer_message' => Piwik_Translate('UserSettings_PluginDetectionDoesNotWorkInIE'),
+ ));
+ }
+
+ private function getDisplayPropertiesForGetLanguage()
+ {
+ return array(
+ 'translations' => array('label' => Piwik_Translate('General_Language')),
+ 'filter_sort_column' => 'nb_visits',
+ 'filter_sort_order' => 'desc',
+ 'show_search' => false,
+ 'columns_to_display' => array('label', 'nb_visits'),
+ 'show_exclude_low_population' => false,
+ );
+ }
+
+ private function getWideScreenDeviceTypeRelatedReports()
+ {
+ return array(
+ 'UserSettings.getMobileVsDesktop' => Piwik_Translate('UserSettings_MobileVsDesktop'),
+ 'UserSettings.getWideScreen' => Piwik_Translate('UserSettings_ColumnTypeOfScreen')
);
+ }
- $browserRelatedReports = array(
- 'UserSettings.getBrowser' => Piwik_Translate('UserSettings_Browsers'),
+ private function getBrowserRelatedReports()
+ {
+ return array(
+ 'UserSettings.getBrowser' => Piwik_Translate('UserSettings_Browsers'),
'UserSettings.getBrowserVersion' => Piwik_Translate('UserSettings_ColumnBrowserVersion')
);
+ }
- $wideScreenDeviceTypeRelatedReports = array(
- 'UserSettings.getMobileVsDesktop' => Piwik_Translate('UserSettings_MobileVsDesktop'),
- 'UserSettings.getWideScreen' => Piwik_Translate('UserSettings_ColumnTypeOfScreen')
+ private function getOsRelatedReports()
+ {
+ return array(
+ 'UserSettings.getOSFamily' => Piwik_Translate('UserSettings_OperatingSystemFamily'),
+ 'UserSettings.getOS' => Piwik_Translate('UserSettings_OperatingSystems')
);
+ }
- $properties['UserSettings.getResolution'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnResolution'))
- ));
-
- $properties['UserSettings.getConfiguration'] = array_merge($basicUserSettingsProperties, array(
- 'filter_limit' => 3,
- 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnConfiguration'))
- ));
-
- $properties['UserSettings.getOS'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnOperatingSystem')),
- 'title' => Piwik_Translate('UserSettings_OperatingSystems'),
- 'relatedReports' => $osRelatedReports
- ));
-
- $properties['UserSettings.getOSFamily'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array('label' => Piwik_Translate('UserSettings_OperatingSystemFamily')),
- 'title' => Piwik_Translate('UserSettings_OperatingSystemFamily'),
- 'relatedReports' => $osRelatedReports
- ));
-
- $properties['UserSettings.getBrowserVersion'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowserVersion')),
- 'graph_limit' => 7,
- 'title' => Piwik_Translate('UserSettings_ColumnBrowserVersion'),
- 'relatedReports' => $browserRelatedReports
- ));
-
- $properties['UserSettings.getBrowser'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowser')),
- 'graph_limit' => 7,
- 'title' => Piwik_Translate('UserSettings_Browsers'),
- 'relatedReports' => $browserRelatedReports
- ));
-
- $properties['UserSettings.getBrowserType'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowserFamily')),
- 'show_offset_information' => false,
- 'show_pagination_control' => false,
- 'default_view_type' => 'graphPie',
- ));
-
- $properties['UserSettings.getWideScreen'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnTypeOfScreen')),
- 'show_offset_information' => false,
- 'show_pagination_control' => false,
- 'title' => Piwik_Translate('UserSettings_ColumnTypeOfScreen'),
- 'relatedReports' => $wideScreenDeviceTypeRelatedReports
- ));
-
- $properties['UserSettings.getMobileVsDesktop'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array('label' => Piwik_Translate('UserSettings_MobileVsDesktop')),
- 'title' => Piwik_Translate('UserSettings_MobileVsDesktop'),
- 'relatedReports' => $wideScreenDeviceTypeRelatedReports
- ));
-
- $properties['UserSettings.getPlugin'] = array_merge($basicUserSettingsProperties, array(
- 'translations' => array(
- 'label' => Piwik_Translate('UserSettings_ColumnPlugin'),
- 'nb_visits_percentage' =>
- str_replace(' ', '&nbsp;', Piwik_Translate('General_ColumnPercentageVisits'))
- ),
- 'show_offset_information' => false,
- 'show_pagination_control' => false,
- 'show_all_views_icons' => false,
- 'show_table_all_columns' => false,
- 'columns_to_display' => array('label', 'nb_visits_percentage', 'nb_visits'),
- 'filter_sort_column' => 'nb_visits_percentage',
- 'filter_sort_order' => 'desc',
- 'filter_limit' => 10,
- 'show_footer_message' => Piwik_Translate('UserSettings_PluginDetectionDoesNotWorkInIE'),
- ));
-
- $properties['UserSettings.getLanguage'] = array(
- 'translations' => array('label' => Piwik_Translate('General_Language')),
- 'filter_sort_column' => 'nb_visits',
- 'filter_sort_order' => 'desc',
+ private function getBasicUserSettingsDisplayProperties()
+ {
+ return array(
'show_search' => false,
- 'filter_limit' => false,
- 'columns_to_display' => array('label', 'nb_visits'),
'show_exclude_low_population' => false,
+ 'filter_limit' => 5,
+ 'visualization_properties' => array(
+ 'jqplot_graph' => array(
+ 'max_graph_elements' => 5
+ )
+ )
);
}
@@ -387,4 +451,4 @@ class UserSettings extends \Piwik\Plugin
$archiving->archivePeriod();
}
}
-}
+} \ No newline at end of file
diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php
index a960d84762..1649cdaca7 100644
--- a/plugins/UsersManager/API.php
+++ b/plugins/UsersManager/API.php
@@ -204,7 +204,7 @@ class API
* If a user doesn't have any access to the $idSite ('noaccess'),
* the user will not be in the returned array.
*
- * @param int $idSite Website ID
+ * @param int $idSite website ID
*
* @return array The returned array has the format
* array(
diff --git a/plugins/VisitFrequency/API.php b/plugins/VisitFrequency/API.php
index f8f433f581..9d10395ba5 100644
--- a/plugins/VisitFrequency/API.php
+++ b/plugins/VisitFrequency/API.php
@@ -34,6 +34,14 @@ class API
return self::$instance;
}
+ /**
+ * @param int $idSite
+ * @param string $period
+ * @param string $date
+ * @param bool|string $segment
+ * @param bool|array $columns
+ * @return mixed
+ */
public function get($idSite, $period, $date, $segment = false, $columns = false)
{
$segment = $this->appendReturningVisitorSegment($segment);
diff --git a/plugins/VisitTime/VisitTime.php b/plugins/VisitTime/VisitTime.php
index 2cd34adc66..8e047803da 100644
--- a/plugins/VisitTime/VisitTime.php
+++ b/plugins/VisitTime/VisitTime.php
@@ -133,35 +133,45 @@ class VisitTime extends \Piwik\Plugin
);
$properties['VisitTime.getVisitInformationPerServerTime'] = array_merge($commonProperties, array(
- 'filter_limit' => 24,
- 'graph_limit' => null,
- 'show_goals' => true,
- 'translations' => array('label' => Piwik_Translate('VisitTime_ColumnServerTime')),
-
- // custom parameter
- 'hideFutureHoursWhenToday' => 1,
- ));
-
+ 'filter_limit' => 24,
+ 'show_goals' => true,
+ 'translations' => array('label' => Piwik_Translate('VisitTime_ColumnServerTime')),
+ 'request_parameters_to_modify' => array('hideFutureHoursWhenToday' => 1),
+ 'visualization_properties' => array(
+ 'jqplot_graph' => array(
+ 'max_graph_elements' => false,
+ )
+ )
+ ));
+
$properties['VisitTime.getVisitInformationPerLocalTime'] = array_merge($commonProperties, array(
- 'filter_limit' => 24,
- 'graph_limit' => null,
- 'title' => Piwik_Translate('VisitTime_ColumnLocalTime'),
- 'translations' => array('label' => Piwik_Translate('VisitTime_LocalTime')),
- ));
-
+ 'filter_limit' => 24,
+ 'title' => Piwik_Translate('VisitTime_ColumnLocalTime'),
+ 'translations' => array('label' => Piwik_Translate('VisitTime_LocalTime')),
+ 'visualization_properties' => array(
+ 'jqplot_graph' => array(
+ 'max_graph_elements' => false,
+ )
+ )
+ ));
+
$properties['VisitTime.getByDayOfWeek'] = array_merge($commonProperties, array(
- 'filter_limit' => 7,
- 'graph_limit' => null,
- 'enable_sort' => false,
- 'show_all_ticks' => true,
- 'show_footer_message' =>
- Piwik_Translate('General_ReportGeneratedFrom', self::getDateRangeForFooterMessage()),
- 'translations' => array('label' => Piwik_Translate('VisitTime_DayOfWeek')),
- ));
+ 'filter_limit' => 7,
+ 'enable_sort' => false,
+ 'show_footer_message' =>
+ Piwik_Translate('General_ReportGeneratedFrom', self::getDateRangeForFooterMessage()),
+ 'translations' => array('label' => Piwik_Translate('VisitTime_DayOfWeek')),
+ 'visualization_properties' => array(
+ 'jqplot_graph' => array(
+ 'show_all_ticks' => true,
+ 'max_graph_elements' => false,
+ )
+ )
+ ));
// add the visits by day of week as a related report, if the current period is not 'day'
if (Common::getRequestVar('period', 'day') != 'day') {
- $properties['VisitTime.getVisitInformationPerLocalTime']['relatedReports'] = array(
+ $properties['VisitTime.getVisitInformationPerLocalTime']['related_reports'] = array(
'VisitTime.getByDayOfWeek' => Piwik_Translate('VisitTime_VisitsByDayOfWeek')
);
}
@@ -207,4 +217,4 @@ class VisitTime extends \Piwik\Plugin
}
return $dateRange;
}
-}
+} \ No newline at end of file
diff --git a/plugins/VisitorInterest/VisitorInterest.php b/plugins/VisitorInterest/VisitorInterest.php
index a60118961d..0692649e33 100644
--- a/plugins/VisitorInterest/VisitorInterest.php
+++ b/plugins/VisitorInterest/VisitorInterest.php
@@ -164,34 +164,42 @@ class VisitorInterest extends \Piwik\Plugin
private function getDisplayPropertiesForGetNumberOfVisitsPerVisitDuration()
{
return array(
- 'default_view_type' => 'cloud',
- 'filter_sort_column' => 'label',
- 'filter_sort_order' => 'asc',
- 'translations' => array('label' => Piwik_Translate('VisitorInterest_ColumnVisitDuration')),
- 'graph_limit' => 10,
- 'enable_sort' => false,
+ 'default_view_type' => 'cloud',
+ 'filter_sort_column' => 'label',
+ 'filter_sort_order' => 'asc',
+ 'translations' => array('label' => Piwik_Translate('VisitorInterest_ColumnVisitDuration')),
+ 'enable_sort' => false,
'show_exclude_low_population' => false,
- 'show_offset_information' => false,
- 'show_pagination_control' => false,
- 'show_search' => false,
- 'show_table_all_columns' => false,
+ 'show_offset_information' => false,
+ 'show_pagination_control' => false,
+ 'show_search' => false,
+ 'show_table_all_columns' => false,
+ 'visualization_properties' => array(
+ 'jqplot_graph' => array(
+ 'max_graph_elements' => 10
+ )
+ )
);
}
private function getDisplayPropertiesForGetNumberOfVisitsPerPage()
{
return array(
- 'default_view_type' => 'cloud',
- 'filter_sort_column' => 'label',
- 'filter_sort_order' => 'asc',
- 'translations' => array('label' => Piwik_Translate('VisitorInterest_ColumnPagesPerVisit')),
- 'graph_limit' => 10,
- 'enable_sort' => false,
+ 'default_view_type' => 'cloud',
+ 'filter_sort_column' => 'label',
+ 'filter_sort_order' => 'asc',
+ 'translations' => array('label' => Piwik_Translate('VisitorInterest_ColumnPagesPerVisit')),
+ 'enable_sort' => false,
'show_exclude_low_population' => false,
- 'show_offset_information' => false,
- 'show_pagination_control' => false,
- 'show_search' => false,
- 'show_table_all_columns' => false,
+ 'show_offset_information' => false,
+ 'show_pagination_control' => false,
+ 'show_search' => false,
+ 'show_table_all_columns' => false,
+ 'visualization_properties' => array(
+ 'jqplot_graph' => array(
+ 'max_graph_elements' => 10
+ )
+ )
);
}
diff --git a/plugins/Widgetize/Widgetize.php b/plugins/Widgetize/Widgetize.php
index 6464807d8c..b47fdf9e21 100644
--- a/plugins/Widgetize/Widgetize.php
+++ b/plugins/Widgetize/Widgetize.php
@@ -43,7 +43,7 @@ class Widgetize extends \Piwik\Plugin
$jsFiles[] = "libs/jquery/jquery.truncate.js";
$jsFiles[] = "libs/jquery/jquery.scrollTo.js";
$jsFiles[] = "plugins/Zeitgeist/javascripts/piwikHelper.js";
- $jsFiles[] = "plugins/CoreHome/javascripts/datatable.js";
+ $jsFiles[] = "plugins/CoreHome/javascripts/dataTable.js";
$jsFiles[] = "plugins/Dashboard/javascripts/widgetMenu.js";
$jsFiles[] = "plugins/Widgetize/javascripts/widgetize.js";
}
diff --git a/plugins/Widgetize/javascripts/widgetize.js b/plugins/Widgetize/javascripts/widgetize.js
index fb65dc7d02..a50dd34630 100644
--- a/plugins/Widgetize/javascripts/widgetize.js
+++ b/plugins/Widgetize/javascripts/widgetize.js
@@ -10,7 +10,7 @@ function widgetize() {
this.getInputFormWithHtml = function (inputId, htmlEmbed) {
return '<input class="formEmbedCode" id="' + inputId + '" value="' + htmlEmbed.replace(/"/g, '&quot;') + '" onclick="javascript:document.getElementById(\'' + inputId + '\').focus();document.getElementById(\'' + inputId + '\').select();" readonly="true" type="text" />';
- }
+ };
this.getEmbedUrl = function (parameters, exportFormat) {
var copyParameters = {};
@@ -31,11 +31,11 @@ function widgetize() {
"&date=" + broadcast.getValueFromUrl('date') +
"&disableLink=1&widget=1";
return sourceUrl;
- }
+ };
this.htmlentities = function (s) {
return s.replace(/[<>&]/g, function (m) { return "&" + m.charCodeAt(0) + ";"; });
- }
+ };
this.callbackAddExportButtonsUnderWidget = function (widgetUniqueId, loadedWidgetElement) {
var widget = widgetsHelper.getWidgetObjectFromUniqueId(widgetUniqueId);
diff --git a/plugins/Zeitgeist/javascripts/ajaxHelper.js b/plugins/Zeitgeist/javascripts/ajaxHelper.js
index 02711b6945..2a50ec2abc 100644
--- a/plugins/Zeitgeist/javascripts/ajaxHelper.js
+++ b/plugins/Zeitgeist/javascripts/ajaxHelper.js
@@ -10,7 +10,7 @@
*
* @type {Array} array holding XhrRequests with automatic cleanup
*/
-var globalAjaxQueue = new Array();
+var globalAjaxQueue = [];
/**
* Extend Array.push with automatic cleanup for finished requests
diff --git a/plugins/Zeitgeist/stylesheets/base.css b/plugins/Zeitgeist/stylesheets/base.css
index 959c4065eb..3eea5ab03a 100644
--- a/plugins/Zeitgeist/stylesheets/base.css
+++ b/plugins/Zeitgeist/stylesheets/base.css
@@ -1,7 +1,7 @@
/* TO GENERATE: lessc plugins/Zeitgeist/stylesheets/base.less plugins/Zeitgeist/stylesheets/base.css */
/* base.less is a standalone Less file */
/* base.css is automatically generated. DO NOT MODIFY */
-/* Genreral styles */
+/* General styles */
/* reset style */
html,
body,
diff --git a/plugins/Zeitgeist/stylesheets/base.less b/plugins/Zeitgeist/stylesheets/base.less
index cce7c66822..f4afcc6220 100644
--- a/plugins/Zeitgeist/stylesheets/base.less
+++ b/plugins/Zeitgeist/stylesheets/base.less
@@ -27,11 +27,5 @@
@import "ui/_loading.less";
-@import "ui/_sparkline.less";
-
-@import "ui/_jqplot.less";
-
-@import "ui/_transitions.less";
-
/* Remote components */
@import "../../CoreHome/stylesheets/_donate.less";
diff --git a/plugins/Zeitgeist/stylesheets/general/_jqueryUI.less b/plugins/Zeitgeist/stylesheets/general/_jqueryUI.less
index bca00bf69d..ea0820c28b 100644
--- a/plugins/Zeitgeist/stylesheets/general/_jqueryUI.less
+++ b/plugins/Zeitgeist/stylesheets/general/_jqueryUI.less
@@ -72,7 +72,7 @@ div.ui-state-highlight {
}
.ui-datepicker-header {
- background: #847b6d url(../images/dashboard_h_bg_hover.png) repeat-x 0 0 !important;
+ background: #847b6d url(plugins/Zeitgeist/images/dashboard_h_bg_hover.png) repeat-x 0 0 !important;
color: #fff !important;
border-radius: 0 !important;
}
@@ -82,11 +82,11 @@ div.ui-state-highlight {
}
.ui-datepicker-header .ui-icon-circle-triangle-w {
- background: url(../images/datepicker_arr_l.png) no-repeat 5px 4px !important;
+ background: url(plugins/Zeitgeist/images/datepicker_arr_l.png) no-repeat 5px 4px !important;
}
.ui-datepicker-header .ui-icon-circle-triangle-e {
- background: url(../images/datepicker_arr_r.png) no-repeat 6px 4px !important;
+ background: url(plugins/Zeitgeist/images/datepicker_arr_r.png) no-repeat 6px 4px !important;
}
.ui-datepicker .ui-datepicker-next-hover,
diff --git a/plugins/Zeitgeist/stylesheets/general/_misc.less b/plugins/Zeitgeist/stylesheets/general/_misc.less
index 38ef9f463f..de419973f1 100644
--- a/plugins/Zeitgeist/stylesheets/general/_misc.less
+++ b/plugins/Zeitgeist/stylesheets/general/_misc.less
@@ -4,4 +4,38 @@
.exception-backtrace {
color: #888;
+}
+
+.section-toggler-link {
+ font-size: .8em;
+ font-style: italic;
+ text-decoration: none;
+}
+
+.section-toggler-link:hover {
+ text-decoration: underline;
+}
+
+.metricEvolution {
+ display: inline-block;
+ font-size: 9pt;
+ opacity: 0.75;
+}
+
+.metricEvolution > .positive-evolution {
+ color: green;
+}
+
+.metricEvolution > .negative-evolution {
+ color: #e02a3b;
+}
+
+.reportsByDimensionView > .entityList {
+ float: left;
+ width: 220px;
+ min-height: 450px;
+}
+
+.dimensionCategory {
+ margin-top: 10px;
} \ No newline at end of file
diff --git a/plugins/Zeitgeist/stylesheets/general/_utils.less b/plugins/Zeitgeist/stylesheets/general/_utils.less
index 0077685734..cd7faddea2 100644
--- a/plugins/Zeitgeist/stylesheets/general/_utils.less
+++ b/plugins/Zeitgeist/stylesheets/general/_utils.less
@@ -27,38 +27,4 @@ html.old-ie .ie-hide {
margin: auto;
text-align: center;
padding-bottom: 10px;
-}
-
-.section-toggler-link {
- font-size: .8em;
- font-style: italic;
- text-decoration: none;
-}
-
-.section-toggler-link:hover {
- text-decoration: underline;
-}
-
-.metricEvolution {
- display: inline-block;
- font-size: 9pt;
- opacity: 0.75;
-}
-
-.metricEvolution > .positive-evolution {
- color: green;
-}
-
-.metricEvolution > .negative-evolution {
- color: #e02a3b;
-}
-
-.reportsByDimensionView > .entityList {
- float: left;
- width: 220px;
- min-height: 450px;
-}
-
-.dimensionCategory {
- margin-top: 10px;
} \ No newline at end of file
diff --git a/plugins/Zeitgeist/stylesheets/ui/_headerMessage.less b/plugins/Zeitgeist/stylesheets/ui/_headerMessage.less
index 779e391e70..7941861a90 100644
--- a/plugins/Zeitgeist/stylesheets/ui/_headerMessage.less
+++ b/plugins/Zeitgeist/stylesheets/ui/_headerMessage.less
@@ -13,6 +13,12 @@
border-radius: 4px;
}
+@media all and (max-width: 949px) {
+ #header_message {
+ display: none;
+ }
+}
+
#header_message:hover,
#header_message.active {
width: auto;
diff --git a/plugins/Zeitgeist/stylesheets/ui/_languageSelect.less b/plugins/Zeitgeist/stylesheets/ui/_languageSelect.less
index b0eafb2707..cbe890246e 100644
--- a/plugins/Zeitgeist/stylesheets/ui/_languageSelect.less
+++ b/plugins/Zeitgeist/stylesheets/ui/_languageSelect.less
@@ -3,11 +3,8 @@
overflow-y: auto;
overflow-x: hidden;
padding: 0 !important;
- position: absolute;
- z-index: 9999;
background:#FFF;
border: 1px solid #1F447F!important;
- position: relative;
}
#languageSelection > form {
@@ -20,7 +17,8 @@
#languageSelection .ui-autocomplete-input:after {
display: inline;
- content: " \25BC"
+ content: " \25BC";
+ font-size: 0.9em;
}
#languageSelection .ui-autocomplete-input {
text-decoration: underline;
@@ -30,12 +28,12 @@
text-decoration: underline;
}
-#languageSelect a{
+#languageSelect a {
text-decoration:none!important;
padding: 1px 25px 1px 3px!important;
}
-#languageSelect a:hover{
+#languageSelect a:hover {
background:#176999!important;
color:#FFF!important;
} \ No newline at end of file
diff --git a/plugins/Zeitgeist/stylesheets/ui/_periodSelect.less b/plugins/Zeitgeist/stylesheets/ui/_periodSelect.less
index 30ff58d2d0..3a87f4eb60 100644
--- a/plugins/Zeitgeist/stylesheets/ui/_periodSelect.less
+++ b/plugins/Zeitgeist/stylesheets/ui/_periodSelect.less
@@ -51,9 +51,11 @@
#periodMore {
padding: 6px 0 0 0;
display: none;
+ overflow: hidden;
}
-#periodString .period-date, #periodString .period-range {
+#periodString .period-date,
+#periodString .period-range {
float: left;
padding: 0 16px 0 0;
}
diff --git a/plugins/Zeitgeist/stylesheets/ui/_siteSelect.less b/plugins/Zeitgeist/stylesheets/ui/_siteSelect.less
index 474c43788b..e3c3ca4ff4 100644
--- a/plugins/Zeitgeist/stylesheets/ui/_siteSelect.less
+++ b/plugins/Zeitgeist/stylesheets/ui/_siteSelect.less
@@ -5,6 +5,7 @@
position: absolute;
font-size: 12px;
display: inline-block;
+ max-height: 30px; /* Hack to not push the dashboard widget bellow */
}
.top_bar_sites_selector {
@@ -40,17 +41,17 @@
}
.sites_autocomplete .custom_select_main_link {
- padding: 0 20px 0 4px;
- display: block;
- text-decoration: none;
- background: url(plugins/Zeitgeist/images/sort_subtable_desc.png) no-repeat right 0;
-}
-
-.sites_autocomplete .custom_select_main_link.noselect {
padding: 0 8px;
display: block;
text-decoration: none;
background: none;
+ cursor: default;
+}
+
+.sites_autocomplete--dropdown .custom_select_main_link {
+ padding: 0 20px 0 4px;
+ background: url(plugins/Zeitgeist/images/sort_subtable_desc.png) no-repeat right 0;
+ cursor: pointer;
}
.sites_autocomplete .custom_select_loading {
diff --git a/plugins/Zeitgeist/templates/_jsGlobalVariables.twig b/plugins/Zeitgeist/templates/_jsGlobalVariables.twig
index 0ec9e5478d..fc60d946f2 100644
--- a/plugins/Zeitgeist/templates/_jsGlobalVariables.twig
+++ b/plugins/Zeitgeist/templates/_jsGlobalVariables.twig
@@ -34,4 +34,3 @@
piwik.config.action_url_category_delimiter = "{{ config_action_url_category_delimiter }}";
{% endif %}
</script>
-<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=IE8"/>
diff --git a/plugins/Zeitgeist/templates/_sparklineFooter.twig b/plugins/Zeitgeist/templates/_sparklineFooter.twig
index b8b864d75c..60664aa216 100644
--- a/plugins/Zeitgeist/templates/_sparklineFooter.twig
+++ b/plugins/Zeitgeist/templates/_sparklineFooter.twig
@@ -1,5 +1,5 @@
<script type="text/javascript">
- $(document).ready(function () {
+ $(function () {
initializeSparklines();
});
</script>
diff --git a/plugins/Zeitgeist/templates/admin.twig b/plugins/Zeitgeist/templates/admin.twig
index f9daab8a91..ef0fca6029 100644
--- a/plugins/Zeitgeist/templates/admin.twig
+++ b/plugins/Zeitgeist/templates/admin.twig
@@ -20,6 +20,7 @@
{% endblock %}
</head>
<body>
+ {% set isAdminLayout = true %}
{% include "_iframeBuster.twig" %}
{% include "@CoreHome/_javaScriptDisabled.twig" %}
diff --git a/plugins/Zeitgeist/templates/genericForm.twig b/plugins/Zeitgeist/templates/genericForm.twig
index 1c509a9ae5..e506f190aa 100644
--- a/plugins/Zeitgeist/templates/genericForm.twig
+++ b/plugins/Zeitgeist/templates/genericForm.twig
@@ -4,7 +4,7 @@
<strong>{{ 'Installation_PleaseFixTheFollowingErrors'|translate }}:</strong>
<ul>
{% for data in form_data.errors %}
- <li>{{ data }}</li>
+ <li>{{ data|raw }}</li>
{% endfor %}
</ul>
</div>