diff options
author | mattab <matthieu.aubry@gmail.com> | 2013-08-11 13:19:59 +0400 |
---|---|---|
committer | mattab <matthieu.aubry@gmail.com> | 2013-08-11 13:19:59 +0400 |
commit | f9b15e948fc9639ada0f925a5d450e6e158b5f56 (patch) | |
tree | 3d6a25c8a271deee7d1136a11c11926be1d33529 /plugins | |
parent | a96ec40e983a8b64f4c25def541a519ff3670e6a (diff) | |
parent | 64ca5d548c0cf0c4eef9f5f104901fbf14800127 (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')
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">‹ {% if javascriptVariablesToSet.dataTablePreviousIsFirst is defined %}{{ 'General_First'|translate }}{% else %}{{ 'General_Previous'|translate }}{% endif %} </span> - <span class="dataTableNext">{{ 'General_Next'|translate }} ›</span> - </span> - {% endif %} + {% if properties.show_pagination_control %} + <span> + <span class="dataTablePrevious">‹ {% if javascriptVariablesToSet.dataTablePreviousIsFirst is defined %}{{ 'General_First'|translate }}{% else %}{{ 'General_Previous'|translate }}{% endif %} </span> + <span class="dataTableNext">{{ 'General_Next'|translate }} ›</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 › {{ '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"/> <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 Binary files differnew file mode 100644 index 0000000000..dfd7ec81de --- /dev/null +++ b/plugins/Live/images/REMOVE_ME_avatar.jpg diff --git a/plugins/Live/images/REMOVE_ME_chart.png b/plugins/Live/images/REMOVE_ME_chart.png Binary files differnew file mode 100644 index 0000000000..5f8f03ad6a --- /dev/null +++ b/plugins/Live/images/REMOVE_ME_chart.png diff --git a/plugins/Live/images/REMOVE_ME_map.jpg b/plugins/Live/images/REMOVE_ME_map.jpg Binary files differnew file mode 100644 index 0000000000..ffae900c21 --- /dev/null +++ b/plugins/Live/images/REMOVE_ME_map.jpg diff --git a/plugins/Live/images/avatar_frame.png b/plugins/Live/images/avatar_frame.png Binary files differnew file mode 100644 index 0000000000..23eccfd5fb --- /dev/null +++ b/plugins/Live/images/avatar_frame.png diff --git a/plugins/Live/images/paperclip.png b/plugins/Live/images/paperclip.png Binary files differnew file mode 100644 index 0000000000..b38d33caa1 --- /dev/null +++ b/plugins/Live/images/paperclip.png diff --git a/plugins/Live/images/visitor_profile_background.jpg b/plugins/Live/images/visitor_profile_background.jpg Binary files differnew file mode 100644 index 0000000000..082d637dcf --- /dev/null +++ b/plugins/Live/images/visitor_profile_background.jpg diff --git a/plugins/SegmentEditor/images/up_arrow.png b/plugins/Live/images/visitor_profile_close.png Binary files differindex c7cb24c2b4..ae132b7b2c 100644 --- a/plugins/SegmentEditor/images/up_arrow.png +++ b/plugins/Live/images/visitor_profile_close.png diff --git a/plugins/SegmentEditor/images/slide.png b/plugins/Live/images/visitor_profile_gradient.png Binary files differindex 657b9a6de5..ac5068b54d 100644 --- a/plugins/SegmentEditor/images/slide.png +++ b/plugins/Live/images/visitor_profile_gradient.png 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> - {{ 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> - {{ 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 Binary files differdeleted file mode 100644 index a364892c7d..0000000000 --- a/plugins/SegmentEditor/images/down_arrow.png +++ /dev/null diff --git a/plugins/SegmentEditor/images/scroller.png b/plugins/SegmentEditor/images/scroller.png Binary files differdeleted file mode 100644 index ddcab93426..0000000000 --- a/plugins/SegmentEditor/images/scroller.png +++ /dev/null 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(' ', ' ', 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(' ', ' ', 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, '"') + '" 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> |