diff options
author | mattpiwik <matthieu.aubry@gmail.com> | 2012-09-16 00:56:01 +0400 |
---|---|---|
committer | mattpiwik <matthieu.aubry@gmail.com> | 2012-09-16 00:56:01 +0400 |
commit | 69370182e44c0919f13ec28945498bd6386fd803 (patch) | |
tree | b1ff02f577f2aba30b63e0b78ddcbe5d2f302256 /plugins/Transitions | |
parent | 043835711220f11a922e64a488d6fd8767ded277 (diff) |
Removing temporarily Transitions plugin from release Refs #3332
on the demo, when enabling the plugin, it was creating a JS error in the merged JS file
git-svn-id: http://dev.piwik.org/svn/trunk@6987 59fd770c-687e-43c8-a1e3-f5a4ff64c105
Diffstat (limited to 'plugins/Transitions')
-rw-r--r-- | plugins/Transitions/API.php | 220 | ||||
-rw-r--r-- | plugins/Transitions/Controller.php | 74 | ||||
-rw-r--r-- | plugins/Transitions/Transitions.php | 239 | ||||
-rw-r--r-- | plugins/Transitions/templates/transitions.js | 1078 |
4 files changed, 0 insertions, 1611 deletions
diff --git a/plugins/Transitions/API.php b/plugins/Transitions/API.php deleted file mode 100644 index 1e11063b19..0000000000 --- a/plugins/Transitions/API.php +++ /dev/null @@ -1,220 +0,0 @@ -<?php -/** - * Piwik - Open source web analytics - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * @version $Id$ - * - * @category Piwik_Plugins - * @package Piwik_Transitions - */ - -/** - * @package Piwik_Transitions - */ -class Piwik_Transitions_API -{ - - static private $instance = null; - - static public function getInstance() - { - if (self::$instance == null) - { - self::$instance = new self; - } - return self::$instance; - } - - /** - * This method combines various reports (both from this and from other plugins) and - * returns a complete report. The report is used in the Transitions API to load all - * data at once. - */ - public function getFullReport($pageUrl, $idSite, $period, $date, $segment = false, $limitBeforeGrouping = false) - { - Piwik::checkUserHasViewAccess($idSite); - - $pageUrl = Piwik_Common::unsanitizeInputValue($pageUrl); - - $report = array(); - $this->addMainPageMetricsToReport($report, $pageUrl, $idSite, $period, $date, $segment); - $this->addLiveTransitionsDataToReport($report, $pageUrl, $idSite, $period, $date, $segment, $limitBeforeGrouping); - - // replace column names in the data tables - $columnNames = array( - 'label' => 'url', - Piwik_Archive::INDEX_NB_ACTIONS => 'referrals' - ); - $reportNames = array('previousPages', 'followingPages', 'outlinks', 'downloads'); - foreach ($reportNames as $reportName) - { - if (isset($report[$reportName])) - { - $report[$reportName]->filter('ReplaceColumnNames', array($columnNames)); - } - } - - return $report; - } - - /** - * Add the main metrics (pageviews, exits, bounces) to the full report. - * Data is loaded from Actions.getPageUrls using the label filter. - */ - private function addMainPageMetricsToReport(&$report, $pageUrl, $idSite, $period, $date, $segment) - { - $label = Piwik_Actions::getActionExplodedNames($pageUrl, Piwik_Tracker_Action::TYPE_ACTION_URL); - if (count($label) == 1) - { - $label = $label[0]; - } - else - { - $label = array_map('urlencode', $label); - $label = implode('>', $label); - } - - $parameters = array( - 'method' => 'Actions.getPageUrls', - 'idSite' => $idSite, - 'period' => $period, - 'date' => $date, - 'label' => $label, - 'format' => 'original', - 'serialize' => '0', - 'expanded' => '0' - ); - if (!empty($segment)) - { - $parameters['segment'] = $segment; - } - - $url = Piwik_Url::getQueryStringFromParameters($parameters); - $request = new Piwik_API_Request($url); - try - { - /** @var $dataTable Piwik_DataTable */ - $dataTable = $request->process(); - } - catch(Exception $e) - { - throw new Exception("Actions.getPageUrls returned an error: ".$e->getMessage()."\n"); - } - - if ($dataTable->getRowsCount() == 0) - { - throw new Exception("The label '$label' could not be found in Actions.getPageUrls\n"); - } - - $row = $dataTable->getFirstRow(); - - if ($row !== false) { - $report['pageMetrics'] = array( - 'pageviews' => intval($row->getColumn('nb_hits')), - 'exits' => intval($row->getColumn('exit_nb_visits')), - 'bounces' => intval($row->getColumn('entry_bounce_count')) - ); - } else { - $report['pageMetrics'] = array( - 'pageviews' => 0, - 'exits' => 0, - 'bounces' => 0 - ); - } - } - - /** - * Add transitions data to the report. - * Fake ArchiveProcessing to do the queries live. - */ - private function addLiveTransitionsDataToReport(&$report, $pageUrl, $idSite, $period, $date, - $segment, $limitBeforeGrouping) - { - // get idaction of page url - $actionsPlugin = new Piwik_Actions; - $idaction = $actionsPlugin->getIdActionFromSegment($pageUrl, 'idaction'); - - // prepare archive processing that can be reused by the archiving code - $archiveProcessing = new Piwik_ArchiveProcessing_Day(); - $archiveProcessing->setSite(new Piwik_Site($idSite)); - $archiveProcessing->setPeriod(Piwik_Period::advancedFactory($period, $date)); - $archiveProcessing->setSegment(new Piwik_Segment($segment, $idSite)); - $archiveProcessing->initForLiveUsage(); - - // launch the archiving code - but live - $transitionsArchiving = new Piwik_Transitions; - - $data = $transitionsArchiving->queryInternalReferrers($idaction, $archiveProcessing, $limitBeforeGrouping); - $report['previousPages'] = &$data['previousPages']; - $report['pageMetrics']['loops'] = intval($data['loops']); - - $data = $transitionsArchiving->queryFollowingActions($idaction, $archiveProcessing, $limitBeforeGrouping); - foreach ($data as $tableName => $table) { - $report[$tableName] = $table; - } - - $data = $transitionsArchiving->queryExternalReferrers($idaction, $archiveProcessing, $limitBeforeGrouping); - - $report['pageMetrics']['entries'] = 0; - $report['referrers'] = array(); - foreach ($data->getRows() as $row) - { - $referrerId = $row->getColumn('label'); - $visits = $row->getColumn(Piwik_Archive::INDEX_NB_VISITS); - if ($visits) - { - // load details (i.e. subtables) - $details = array(); - if ($idSubTable = $row->getIdSubDataTable()) - { - $subTable = Piwik_DataTable_Manager::getInstance()->getTable($idSubTable); - foreach ($subTable->getRows() as $subRow) - { - $details[] = array( - 'label' => $subRow->getColumn('label'), - 'referrals' => $subRow->getColumn(Piwik_Archive::INDEX_NB_VISITS) - ); - } - } - $report['referrers'][] = array( - 'label' => $this->getReferrerLabel($referrerId), - 'shortName' => Piwik_getRefererTypeFromShortName($referrerId), - 'visits' => $visits, - 'details' => $details - ); - $report['pageMetrics']['entries'] += $visits; - } - } - - // if there's no data for referrers, Piwik_API_ResponseBuilder::handleMultiDimensionalArray - // does not detect the multi dimensional array and the data is rendered differently, which - // causes an exception. - if (count($report['referrers']) == 0) - { - $report['referrers'][] = array( - 'label' => $this->getReferrerLabel(Piwik_Common::REFERER_TYPE_DIRECT_ENTRY), - 'shortName' => Piwik_getRefererTypeLabel(Piwik_Common::REFERER_TYPE_DIRECT_ENTRY), - 'visits' => 0 - ); - } - } - - private function getReferrerLabel($referrerId) { - switch ($referrerId) - { - case Piwik_Common::REFERER_TYPE_DIRECT_ENTRY: - return Piwik_Transitions_Controller::getTranslation('directEntries'); - case Piwik_Common::REFERER_TYPE_SEARCH_ENGINE: - return Piwik_Transitions_Controller::getTranslation('fromSearchEngines'); - case Piwik_Common::REFERER_TYPE_WEBSITE: - return Piwik_Transitions_Controller::getTranslation('fromWebsites'); - case Piwik_Common::REFERER_TYPE_CAMPAIGN: - return Piwik_Transitions_Controller::getTranslation('fromCampaigns'); - default: - return Piwik_Translate('General_Others'); - } - } - -}
\ No newline at end of file diff --git a/plugins/Transitions/Controller.php b/plugins/Transitions/Controller.php deleted file mode 100644 index 1a32b9ef9b..0000000000 --- a/plugins/Transitions/Controller.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * Piwik - Open source web analytics - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * @version $Id$ - * - * @category Piwik_Plugins - * @package Piwik_Transitions - */ - -/** - * @package Piwik_Transitions - */ -class Piwik_Transitions_Controller extends Piwik_Controller -{ - - /** - * Since the metric translations are taken from different plugins, - * it makes the rest of the code easier to read and maintain when we - * use this indirection to map between the metrics and the actual - * translation keys. - */ - private static $metricTranslations = array( - 'pageviewsInline' => 'Transitions_PageviewsInline', - 'loopsInline' => 'Transitions_LoopsInline', - 'fromPreviousPages' => 'Transitions_FromPreviousPages', - 'fromPreviousPagesInline' => 'Transitions_FromPreviousPagesInline', - 'fromSearchEngines' => 'Transitions_FromSearchEngines', - 'fromSearchEnginesInline' => 'Transitions_FromSearchEnginesInline', - 'fromWebsites' => 'Transitions_FromWebsites', - 'fromWebsitesInline' => 'Transitions_FromWebsitesInline', - 'fromCampaigns' => 'Transitions_FromCampaigns', - 'fromCampaignsInline' => 'Transitions_FromCampaignsInline', - 'directEntries' => 'Transitions_DirectEntries', - 'directEntriesInline' => 'Referers_TypeDirectEntries', - 'toFollowingPages' => 'Transitions_ToFollowingPages', - 'toFollowingPagesInline' => 'Transitions_ToFollowingPagesInline', - 'downloads' => 'Actions_ColumnDownloads', - 'downloadsInline' => 'VisitsSummary_NbDownloadsDescription', - 'outlinks' => 'Actions_ColumnOutlinks', - 'outlinksInline' => 'VisitsSummary_NbOutlinksDescription', - 'exits' => 'General_ColumnExits', - 'exitsInline' => 'Transitions_ExitsInline', - 'bouncesInline' => 'Transitions_BouncesInline' - ); - - /** - * Translations that are added to JS - * (object Piwik_Transitions_Translations) - */ - private static $jsTranslations = array( - 'XOfY' => 'Transitions_XOfY', - 'XOfAllPageviews' => 'Transitions_XOfAllPageviews' - ); - - public static function getTranslation($key) - { - return Piwik_Translate(self::$metricTranslations[$key]); - } - - /** - * The main method of the plugin. - * It is triggered from the Transitions data table action. - */ - public function renderPopover() - { - $view = Piwik_View::factory('transitions'); - $view->translations = self::$metricTranslations + self::$jsTranslations; - echo $view->render(); - } - -} diff --git a/plugins/Transitions/Transitions.php b/plugins/Transitions/Transitions.php deleted file mode 100644 index 94c02d84b7..0000000000 --- a/plugins/Transitions/Transitions.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php -/** - * Piwik - Open source web analytics - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * @version $Id$ - * - * @category Piwik_Plugins - * @package Piwik_Transitions - */ - -/** - * @package Piwik_Transitions - */ -class Piwik_Transitions extends Piwik_Plugin -{ - - private $limitBeforeGrouping = 5; - - public function getInformation() - { - return array( - 'description' => Piwik_Translate('Transitions_PluginDescription'), - 'author' => 'Piwik', - 'author_homepage' => 'http://piwik.org/', - 'version' => Piwik_Version::VERSION, - ); - } - - function getListHooksRegistered() - { - return array( - 'AssetManager.getCssFiles' => 'getCssFiles', - 'AssetManager.getJsFiles' => 'getJsFiles' - ); - } - - public function getCssFiles($notification) - { - $cssFiles = &$notification->getNotificationObject(); - $cssFiles[] = 'plugins/Transitions/templates/transitions.css'; - } - - public function getJsFiles($notification) - { - $jsFiles = &$notification->getNotificationObject(); - $jsFiles[] = 'plugins/Transitions/templates/transitions.js'; - } - - /** - * Get information about external referrers (i.e. search engines, websites & campaigns) - * - * @param $idaction - * @param Piwik_ArchiveProcessing_Day $archiveProcessing - * @return Piwik_DataTable - */ - public function queryExternalReferrers($idaction, Piwik_ArchiveProcessing_Day $archiveProcessing, - $limitBeforeGrouping = false) - { - $rankingQuery = new Piwik_RankingQuery($limitBeforeGrouping ? $limitBeforeGrouping : $this->limitBeforeGrouping); - - // we generate a single column that contains the interesting data for each referrer. - // the reason we cannot group by referer_* becomes clear when we look at search engine keywords. - // referer_url contains the url from the search engine, referer_keyword the keyword we want to - // group by. when we group by both, we don't get a single column for the keyword but instead - // one column per keyword + search engine url. this way, we could not get the top keywords using - // the ranking query. - $dimension = 'referrer_data'; - $rankingQuery->addLabelColumn('referrer_data'); - $select = ' - CASE referer_type - WHEN '.Piwik_Common::REFERER_TYPE_DIRECT_ENTRY.' THEN "" - WHEN '.Piwik_Common::REFERER_TYPE_SEARCH_ENGINE.' THEN referer_keyword - WHEN '.Piwik_Common::REFERER_TYPE_WEBSITE.' THEN referer_url - WHEN '.Piwik_Common::REFERER_TYPE_CAMPAIGN.' THEN CONCAT(referer_name, " ", referer_keyword) - END AS referrer_data, - referer_type'; - - // get one limited group per referrer type - $rankingQuery->partitionResultIntoMultipleGroups('referer_type', array( - Piwik_Common::REFERER_TYPE_DIRECT_ENTRY, - Piwik_Common::REFERER_TYPE_SEARCH_ENGINE, - Piwik_Common::REFERER_TYPE_WEBSITE, - Piwik_Common::REFERER_TYPE_CAMPAIGN - )); - - $orderBy = '`'.Piwik_Archive::INDEX_NB_VISITS.'` DESC'; - $where = 'visit_entry_idaction_url = '.intval($idaction); - - $metrics = array(Piwik_Archive::INDEX_NB_VISITS); - $data = $archiveProcessing->queryVisitsByDimension($dimension, $where, $metrics, $orderBy, - $rankingQuery, $select, $selectGeneratesLabelColumn = true); - - $referrerData = array(); - $referrerSubData = array(); - - foreach ($data as $referrerType => &$subData) - { - $referrerData[$referrerType] = array(Piwik_Archive::INDEX_NB_VISITS => 0); - if ($referrerType != Piwik_Common::REFERER_TYPE_DIRECT_ENTRY) - { - $referrerSubData[$referrerType] = array(); - } - - foreach ($subData as &$row) - { - if ($referrerType == Piwik_Common::REFERER_TYPE_SEARCH_ENGINE && empty($row['referrer_data'])) - { - $row['referrer_data'] = Piwik_Referers::LABEL_KEYWORD_NOT_DEFINED; - } - - $referrerData[$referrerType][Piwik_Archive::INDEX_NB_VISITS] += $row[Piwik_Archive::INDEX_NB_VISITS]; - - $label = $row['referrer_data']; - if ($label) - { - $referrerSubData[$referrerType][$label] = array( - Piwik_Archive::INDEX_NB_VISITS => $row[Piwik_Archive::INDEX_NB_VISITS] - ); - } - } - } - - return $archiveProcessing->getDataTableWithSubtablesFromArraysIndexedByLabel($referrerSubData, $referrerData); - } - - /** - * Get information about internal referrers (previous pages & loops, i.e. page refreshes) - * - * @param $idaction - * @param Piwik_ArchiveProcessing_Day $archiveProcessing - * @return array(previousPages:Piwik_DataTable, loops:integer) - */ - public function queryInternalReferrers($idaction, Piwik_ArchiveProcessing_Day $archiveProcessing, - $limitBeforeGrouping = false) - { - $dimension = 'idaction_url_ref'; - - $rankingQuery = new Piwik_RankingQuery($limitBeforeGrouping ? $limitBeforeGrouping : $this->limitBeforeGrouping); - $rankingQuery->addLabelColumn(array('name', 'url_prefix')); - $rankingQuery->setColumnToMarkExcludedRows('is_self'); - - $addSelect = ' - log_action.name, log_action.url_prefix, - CASE WHEN log_link_visit_action.idaction_url_ref = '.intval($idaction).' THEN 1 ELSE 0 END AS is_self'; - - $where = ' - log_link_visit_action.idaction_url = '.intval($idaction).' AND - log_action.type = '.Piwik_Tracker_Action::TYPE_ACTION_URL; - - $orderBy = '`'.Piwik_Archive::INDEX_NB_ACTIONS.'` DESC'; - - $metrics = array(Piwik_Archive::INDEX_NB_ACTIONS); - $data = $archiveProcessing->queryActionsByDimension(array($dimension), $where, $metrics, $orderBy, - $rankingQuery, $dimension, $addSelect); - - $previousPagesDataTable = new Piwik_DataTable; - foreach ($data['result'] as &$page) - { - $previousPagesDataTable->addRow(new Piwik_DataTable_Row(array( - Piwik_DataTable_Row::COLUMNS => array( - 'label' => Piwik_Tracker_Action::reconstructNormalizedUrl($page['name'], $page['url_prefix']), - Piwik_Archive::INDEX_NB_ACTIONS => intval($page[Piwik_Archive::INDEX_NB_ACTIONS]) - ) - ))); - } - - $loops = 0; - if (count($data['excludedFromLimit'])) - { - $loops = intval($data['excludedFromLimit'][0][Piwik_Archive::INDEX_NB_ACTIONS]); - } - - return array( - 'previousPages' => $previousPagesDataTable, - 'loops' => $loops - ); - } - - /** - * Get information about the following actions (following pages, outlinks, downloads) - * - * @param $idaction - * @param Piwik_ArchiveProcessing_Day $archiveProcessing - * @return array(followingPages:Piwik_DataTable, outlinks:Piwik_DataTable, downloads:Piwik_DataTable) - */ - public function queryFollowingActions($idaction, Piwik_ArchiveProcessing_Day $archiveProcessing, - $limitBeforeGrouping = false) - { - static $types = array( - Piwik_Tracker_Action::TYPE_ACTION_URL => 'followingPages', - Piwik_Tracker_Action::TYPE_OUTLINK => 'outlinks', - Piwik_Tracker_Action::TYPE_DOWNLOAD => 'downloads' - ); - - $dimension = 'idaction_url'; - - $rankingQuery = new Piwik_RankingQuery($limitBeforeGrouping ? $limitBeforeGrouping : $this->limitBeforeGrouping); - $rankingQuery->addLabelColumn(array('name', 'url_prefix')); - $rankingQuery->partitionResultIntoMultipleGroups('type', array_keys($types)); - - $addSelect = 'log_action.name, log_action.url_prefix, log_action.type'; - - $where = ' - log_link_visit_action.idaction_url_ref = '.intval($idaction).' AND - log_link_visit_action.idaction_url != '.intval($idaction); - - $orderBy = '`'.Piwik_Archive::INDEX_NB_ACTIONS.'` DESC'; - - $metrics = array(Piwik_Archive::INDEX_NB_ACTIONS); - $data = $archiveProcessing->queryActionsByDimension(array($dimension), $where, $metrics, $orderBy, - $rankingQuery, $dimension, $addSelect); - - $dataTables = array(); - foreach ($types as $type => $recordName) - { - $dataTable = new Piwik_DataTable; - if (isset($data[$type])) - { - foreach ($data[$type] as &$record) - { - $dataTable->addRow(new Piwik_DataTable_Row(array( - Piwik_DataTable_Row::COLUMNS => array( - 'label' => $type == Piwik_Tracker_Action::TYPE_ACTION_URL ? - Piwik_Tracker_Action::reconstructNormalizedUrl($record['name'], $record['url_prefix']) : - $record['name'], - Piwik_Archive::INDEX_NB_ACTIONS => intval($record[Piwik_Archive::INDEX_NB_ACTIONS]) - ) - ))); - } - } - $dataTables[$recordName] = $dataTable; - } - - return $dataTables; - } - -}
\ No newline at end of file diff --git a/plugins/Transitions/templates/transitions.js b/plugins/Transitions/templates/transitions.js deleted file mode 100644 index 69156ae1f2..0000000000 --- a/plugins/Transitions/templates/transitions.js +++ /dev/null @@ -1,1078 +0,0 @@ -/*! - * Piwik - Web Analytics - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - - -// -// TRANSITIONS ROW ACTION FOR DATA TABLES -// - -function DataTable_RowActions_Transitions(dataTable) { - this.dataTable = dataTable; - this.transitions = null; -} - -DataTable_RowActions_Transitions.prototype = new DataTable_RowAction; - -// override trigger method directly because we don't need the label -DataTable_RowActions_Transitions.prototype.trigger = function(tr, e, subTableLabel) { - var link = tr.find('> td:first > a').attr('href'); - link = $('<textarea>').html(link).val(); // remove html entities - this.openPopover(link); -}; - -DataTable_RowActions_Transitions.prototype.doOpenPopover = function(link) { - if (this.transitions === null) { - this.transitions = new Piwik_Transitions(link, this); - } else { - this.transitions.reset(link); - } - this.transitions.showPopover(); -}; - - -DataTable_RowActions_Registry.register({ - - name: 'Transitions', - - dataTableIcon: 'plugins/Transitions/templates/transitions_rowaction.png', - - createInstance: function(dataTable) { - return new DataTable_RowActions_Transitions(dataTable); - }, - - isAvailable: function(dataTableParams, tr) { - return dataTableParams.module == 'Actions' - && dataTableParams.action == 'getPageUrls' - && tr.find('> td:first > a').size() > 0; - } - -}); - - -// -// TRANSITIONS IMPLEMENTATION -// - -function Piwik_Transitions(link, rowAction) { - this.reset(link); - this.rowAction = rowAction; - - this.ajax = new Piwik_Transitions_Ajax(); - this.model = new Piwik_Transitions_Model(this.ajax); - - this.leftGroups = ['previousPages', 'searchEngines', 'websites', 'campaigns']; - this.rightGroups = ['followingPages', 'downloads', 'outlinks']; -} - -Piwik_Transitions.prototype.reset = function(link) { - this.link = link; - this.popover = null; - this.canvas = null; - this.centerBox = null; - - this.leftOpenGroup = 'previousPages'; - this.rightOpenGroup = 'followingPages'; -}; - -/** Open the popover */ -Piwik_Transitions.prototype.showPopover = function() { - var self = this; - - // initialize popover (with loading message) - var loading = $('div.loadingPiwik:first').clone(); - var box = $(document.createElement('div')).attr('id', 'Transitions_Popover').html(loading); - box.dialog({ - title: '', - modal: true, - width: '900px', - position: ['center', 'center'], - resizable: false, - autoOpen: true, - open: function(event, ui) { - $('.ui-widget-overlay').on('click.transitions',function(){ - box.dialog('close'); - }); - }, - close: function(event, ui) { - box.dialog('destroy').remove(); - piwikHelper.abortQueueAjax(); - $('.ui-widget-overlay').off('click.rowEvolution'); - } - }); - this.popover = box; - - // load the popover HTML - this.ajax.callTransitionsController('renderPopover', function(html) { - box.html(html); - box.dialog({position: ['center', 'center']}); - - var canvasDom = box.find('#Transitions_Canvas')[0]; - var canvasBgDom = box.find('#Transitions_Canvas_Background')[0]; - self.canvas = new Piwik_Transitions_Canvas(canvasDom, canvasBgDom, 850, 550); - - self.centerBox = box.find('#Transitions_CenterBox'); - - var link = Piwik_Transitions_Util.shortenUrl(self.link, true); - self.centerBox.find('h2').html(Piwik_Transitions_Util.addBreakpoints(link)); - - self.model.loadData(self.link, function() { - self.render(); - }); - }); -}; - -/** Render the popover content */ -Piwik_Transitions.prototype.render = function() { - this.renderCenterBox(); - - this.renderLeftSide(); - this.renderRightSide(); - - this.renderLoops(); -}; - -/** Render left side: referrer groups & direct entries */ -Piwik_Transitions.prototype.renderLeftSide = function() { - this.renderGroups(this.leftGroups, this.leftOpenGroup, 'left'); - this.renderEntries(); - - this.reRenderIfNeededToCenter('left'); -}; - -/** Render right side: following pages & exits */ -Piwik_Transitions.prototype.renderRightSide = function() { - this.renderGroups(this.rightGroups, this.rightOpenGroup, 'right'); - this.renderExits(); - - this.reRenderIfNeededToCenter('right'); -}; - -/** Helper method to render open and closed groups for both sides */ -Piwik_Transitions.prototype.renderGroups = function(groups, openGroup, side) { - for (var i = 0; i < groups.length; i++) { - var groupName = groups[i]; - if (groupName == openGroup) { - if (i != 0) { - this.canvas.addBoxSpacing(13, side); - } - this.renderOpenGroup(groupName, side); - } else { - this.renderClosedGroup(groupName, side); - } - } - - this.canvas.addBoxSpacing(13, side); -}; - -/** - * If one side doesn't have much information, it doesn't look good to start from y=0. - * In this case, add some spacing on top and redraw. - */ -Piwik_Transitions.prototype.reRenderIfNeededToCenter = function(side) { - var height = (side == 'left' ? this.canvas.leftBoxPositionY : this.canvas.rightBoxPositionY) - 20; - if (height < 460 && !this.reRendering) { - var yOffset = (460 - height) / 2; - this.canvas.clearSide(side); - this.canvas.addBoxSpacing(yOffset, side); - this.reRendering = true; - side == 'left' ? this.renderLeftSide() : this.renderRightSide(); - this.reRendering = false; - } -}; - -/** Render the center box with the main metrics */ -Piwik_Transitions.prototype.renderCenterBox = function() { - var box = this.centerBox; - box.removeClass('Transitions_Loading'); - - Piwik_Transitions_Util.replacePlaceholderInHtml( - box.find('.Transitions_Pageviews'), this.model.pageviews); - - var self = this; - var showMetric = function(cssClass, modelProperty) { - var el = box.find('.Transitions_' + cssClass); - Piwik_Transitions_Util.replacePlaceholderInHtml(el, self.model[modelProperty]); - self.addTooltipShowingPercentageOfAllPageviews(el, modelProperty); - }; - - showMetric('DirectEntries', 'directEntries'); - showMetric('PreviousPages', 'previousPagesNbTransitions'); - showMetric('SearchEngines', 'searchEnginesNbTransitions'); - showMetric('Websites', 'websitesNbTransitions'); - - showMetric('FollowingPages', 'followingPagesNbTransitions'); - showMetric('Outlinks', 'outlinksNbTransitions'); - showMetric('Downloads', 'downloadsNbTransitions'); - showMetric('Exits', 'exits'); - showMetric('Bounces', 'bounces'); - - box.find('.Transitions_CenterBoxMetrics').show(); -}; - -Piwik_Transitions.prototype.addTooltipShowingPercentageOfAllPageviews = function(element, metric) { - var self = this; - element.hover(function() { - var tip = Piwik_Transitions_Translations.XOfAllPageviews; - var percentage = self.model.getPercentage(metric, true); - tip = tip.replace(/%s/, '<b>' + percentage + '</b>'); - Piwik_Tooltip.show(tip, 'Transitions_Tooltip_Small'); - }, function() { - Piwik_Tooltip.hide(); - }); -}; - -/** Render the loops (i.e. page refreshes) */ -Piwik_Transitions.prototype.renderLoops = function() { - if (this.model.loops == 0) { - return; - } - - var loops = this.popover.find('#Transitions_Loops').show(); - Piwik_Transitions_Util.replacePlaceholderInHtml(loops, this.model.loops); - - this.addTooltipShowingPercentageOfAllPageviews(loops, 'loops'); - - this.canvas.renderLoops(this.model.getPercentage('loops')); -}; - -Piwik_Transitions.prototype.renderEntries = function() { - if (this.model.directEntries > 0) { - this.canvas.renderBox({ - side: 'left', - share: this.model.getPercentage('directEntries'), - gradient: this.canvas.createHorizontalGradient('#CFEDCA', '#91DE83', 'left'), - boxText: Piwik_Transitions_Translations.directEntries, - boxTextNumLines: 1, - boxTextCssClass: 'SingleLine', - smallBox: true - }); - this.canvas.addBoxSpacing(20, 'left'); - } -}; - -Piwik_Transitions.prototype.renderExits = function() { - if (this.model.exits > 0) { - this.canvas.renderBox({ - side: 'right', - share: this.model.getPercentage('exits'), - gradient: this.canvas.createHorizontalGradient('#CFEDCA', '#91DE83', 'right'), - boxText: Piwik_Transitions_Translations.exits, - boxTextNumLines: 1, - boxTextCssClass: 'SingleLine', - smallBox: true - }); - this.canvas.addBoxSpacing(20, 'right'); - } -}; - -/** Render the open group with the detailed data */ -Piwik_Transitions.prototype.renderOpenGroup = function(groupName, side) { - var self = this; - - // get data from the model - var nbTransitionsVarName = groupName + 'NbTransitions'; - var nbTransitions = self.model[nbTransitionsVarName]; - if (nbTransitions == 0) { - return; - } - - var totalShare = this.model.getPercentage(nbTransitionsVarName); - var details = self.model.getDetailsForGroup(groupName); - - // prepare gradients - var gradientItems = this.canvas.createHorizontalGradient('#E3DFD1', '#E8E4D5', side); - var gradientOthers = this.canvas.createHorizontalGradient('#F5F3EB', '#E8E4D5', side); - var gradientBackground = this.canvas.createHorizontalGradient('#FFFFFF', '#B0CAE8', side); - - // remember current offsets to reset them later for drawing the background - var boxPositionBefore, curvePositionBefore; - if (side == 'left') { - boxPositionBefore = this.canvas.leftBoxPositionY; - curvePositionBefore = this.canvas.leftCurvePositionY; - } else { - boxPositionBefore = this.canvas.rightBoxPositionY; - curvePositionBefore = this.canvas.rightCurvePositionY; - } - - // headline of the open group - var titleX, titleClass; - if (side == 'left') { - titleX = this.canvas.leftBoxBeginX + 10; - titleClass = 'BoxTextLeft'; - } else { - titleX = this.canvas.rightBoxBeginX - 1; - titleClass = 'BoxTextRight'; - } - var groupTitle = self.model.getGroupTitle(groupName); - this.canvas.renderText(groupTitle, titleX , boxPositionBefore + 11, [titleClass, 'TitleOfOpenGroup']); - this.canvas.addBoxSpacing(34, side); - - // draw detail boxes - for (var i = 0; i < details.length; i++) { - var data = details[i]; - var label = (typeof data.url != 'undefined' ? data.url : data.label); - var isOthers = (label == 'Others'); - var onClick = false; - if (!isOthers && (groupName == 'previousPages' || groupName == 'followingPages')) { - onClick = (function(url) { - return function() { self.reloadPopover(url); }; - })(label); - } - - var tooltip = Piwik_Transitions_Translations.XOfY; - tooltip = '<b>' + tooltip.replace(/%s/, data.referrals + '</b>').replace(/%s/, nbTransitions); - tooltip = this.model.getShareInGroupTooltip(tooltip, groupName); - - var fullLabel = label; - var shortened = false; - if ((groupName == 'previousPages' || groupName == 'followingPages' || groupName == 'downloads')) { - // remove http + www + domain for internal URLs - label = Piwik_Transitions_Util.shortenUrl(label, true); - shortened = true; - } else if (groupName == 'outlinks' || groupName == 'websites') { - // remove http + www + domain external URLs - label = Piwik_Transitions_Util.shortenUrl(label); - shortened = true; - } - - this.canvas.renderBox({ - side: side, - share: data.percentage / 100 * totalShare, - gradient: isOthers ? gradientOthers : gradientItems, - boxText: label, - boxTextTooltip: isOthers || !shortened ? false : fullLabel, - truncateBoxText: true, - boxTextNumLines: 3, - curveText: data.percentage + '%', - curveTextTooltip: tooltip, - onClick: onClick - }); - } - - // draw background - var boxPositionAfter, curvePositionAfter; - if (side == 'left') { - boxPositionAfter = this.canvas.leftBoxPositionY; - curvePositionAfter = this.canvas.leftCurvePositionY; - this.canvas.leftBoxPositionY = boxPositionBefore; - this.canvas.leftCurvePositionY = curvePositionBefore; - } else { - boxPositionAfter = this.canvas.rightBoxPositionY; - curvePositionAfter = this.canvas.rightCurvePositionY; - this.canvas.rightBoxPositionY = boxPositionBefore; - this.canvas.rightCurvePositionY = curvePositionBefore; - } - - this.canvas.renderBox({ - side: side, - boxHeight: boxPositionAfter - boxPositionBefore - this.canvas.boxSpacing - 2, - curveHeight: curvePositionAfter - curvePositionBefore - this.canvas.curveSpacing, - gradient: gradientBackground, - bgCanvas: true - }); - - this.canvas.addBoxSpacing(15, side); -}; - -/** Render a closed group without detailed data, only one box for the sum */ -Piwik_Transitions.prototype.renderClosedGroup = function(groupName, side) { - var self = this; - var gradient = this.canvas.createHorizontalGradient('#DDE4ED', '#9BBADE', side); - - var nbTransitionsVarName = groupName + 'NbTransitions'; - - if (self.model[nbTransitionsVarName] == 0) { - return; - } - - self.canvas.renderBox({ - side: side, - share: self.model.getPercentage(nbTransitionsVarName), - gradient: gradient, - boxText: self.model.getGroupTitle(groupName), - boxTextNumLines: 1, - boxTextCssClass: 'SingleLine', - boxIcon: 'themes/default/images/plus_blue.png', - smallBox: true, - onClick: function() { - self.openGroup(side, groupName); - } - }); -}; - -/** Reload the entire popover for a different URL */ -Piwik_Transitions.prototype.reloadPopover = function(url) { - this.popover.dialog('close'); - this.rowAction.openPopover(url); -}; - -/** Redraw the left or right sides with a different group opened */ -Piwik_Transitions.prototype.openGroup = function(side, groupName) { - - this.canvas.clearSide(side); - - if (side == 'left') { - this.leftOpenGroup = groupName; - this.renderLeftSide(); - } else { - this.rightOpenGroup = groupName; - this.renderRightSide(); - } - - this.renderLoops(); -}; - - -// -------------------------------------- -// CANVAS -// -------------------------------------- - -function Piwik_Transitions_Canvas(canvasDom, canvasBgDom, width, height) { - if (!canvasDom.getContext) { - alert('Your browser is not supported.'); - return; - } - - /** DOM element that contains the canvas */ - this.container = $(canvasDom).parent(); - /** Drawing context of the canvas */ - this.context = canvasDom.getContext('2d'); - /** Drawing context of the background canvas */ - this.bgContext = canvasBgDom.getContext('2d'); - - /** Width of the entire canvas */ - this.width = canvasDom.width = canvasBgDom.width = width; - /** Height of the entire canvas */ - this.height = canvasDom.height = canvasBgDom.height = height; - - /** Current Y positions */ - this.leftBoxPositionY = this.originalBoxPositionY = 0; - this.leftCurvePositionY = this.originalCurvePositionY = 110; - this.rightBoxPositionY = this.originalBoxPositionY; - this.rightCurvePositionY = this.originalCurvePositionY; - - /** Width of the rectangular box */ - this.boxWidth = 140; - /** Height of the rectangular box */ - this.boxHeight = 53; - /** Height of a smaller rectangular box */ - this.smallBoxHeight = 30; - /** Width of the curve that connects the boxes to the center */ - this.curveWidth = 180; - /** Line-height of the text */ - this.lineHeight = 14; - /** Spacing between rectangular boxes */ - this.boxSpacing = 7; - /** Spacing between the curves where they connect to the center */ - this.curveSpacing = 1.5; - - /** The total net height (without curve spacing) of the curves as they connect to the center */ - this.totalHeightOfConnections = 205; - - /** X positions of the left box - begin means left, end means right */ - this.leftBoxBeginX = 0; - this.leftCurveBeginX = this.leftBoxBeginX + this.boxWidth; - this.leftCurveEndX = this.leftCurveBeginX + this.curveWidth; - - /** X positions of the right box - begin means left, end means right */ - this.rightBoxEndX = this.width; - this.rightBoxBeginX = this.rightCurveEndX = this.rightBoxEndX - this.boxWidth; - this.rightCurveBeginX = this.rightCurveEndX - this.curveWidth; -} - -/** - * Helper to create horizontal gradients - * @param position left|right - */ -Piwik_Transitions_Canvas.prototype.createHorizontalGradient = function(lightColor, darkColor, position) { - var fromX, toX, fromColor, toColor; - - if (position == 'left') { - // gradient is used to fill a box on the left - fromX = this.leftBoxBeginX + 50; - toX = this.leftCurveEndX - 20; - fromColor = lightColor; - toColor = darkColor; - } else { - // gradient is used to fill a box on the right - fromX = this.rightCurveBeginX + 20; - toX = this.rightBoxEndX - 50; - fromColor = darkColor; - toColor = lightColor; - } - - var gradient = this.context.createLinearGradient(fromX, 0, toX, 0); - gradient.addColorStop(0, fromColor); - gradient.addColorStop(1, toColor); - - return gradient; -}; - -/** Render text using a div inside the container */ -Piwik_Transitions_Canvas.prototype.renderText = function(text, x, y, cssClass, onClick, icon, maxLines) { - var div = this.addDomElement('div', 'Text'); - div.html('<span>' + Piwik_Transitions_Util.addBreakpoints(text) + '</span>'); - div.css({ - left: x + 'px', - top: y + 'px' - }); - if (icon) { - div.addClass('Transitions_HasBackground'); - div.css({backgroundImage: 'url(' + icon + ')'}); - } - if (cssClass) { - if (typeof cssClass == 'object') { - for (var i = 0; i < cssClass.length; i++) { - div.addClass('Transitions_' + cssClass[i]); - } - } else { - div.addClass('Transitions_' + cssClass); - } - } - if (onClick) { - div.css('cursor', 'pointer').hover(function() { - $(this).addClass('Transitions_Hover'); - }, function() { - $(this).removeClass('Transitions_Hover'); - }).click(onClick); - } - if (maxLines) { - // truncate until span fits inside div: substitute middle part with ... - var span = div.find('span'); - var divHeight = div.innerHeight(); - var leftPart = false; - var rightPart = false; - while (divHeight < span.outerHeight()) { - if (leftPart === false) { - var middle = Math.round(text.length / 2); - leftPart = text.substring(0, middle); - rightPart = text.substring(middle, text.length); - } - leftPart = leftPart.substring(0, leftPart.length - 2); - rightPart = rightPart.substring(2, rightPart.length); - text = leftPart + '...' + rightPart; - span.html(Piwik_Transitions_Util.addBreakpoints(text)); - } - } - return div; -}; - -/** Add a DOM element inside the container (as a sibling of the canvas) */ -Piwik_Transitions_Canvas.prototype.addDomElement = function(tagName, cssClass) { - var el = $(document.createElement('div')).addClass('Transitions_' + cssClass); - this.container.append(el); - return el; -}; - -/** - * Render a box. - * This method automatically keeps track of the current position. - * - * PARAMS (pass as object): - * side: left or right - * share: of the box in the total amount of incoming transitions - * gradient: for filling the box - * boxText: to be placed inside the box (optional) - * boxTextNumLines: the number of lines to be placed in the box (optional) - * boxTextCssClass: for divs containing the texts (optional) - * boxTextTooltip: text for a tooltip this is when hovering the box text (optional) - * curveText: to be placed where the curve begins (optional) - * curveTextTooltip: text for a tooltip that is shown when hovering the curve text (optional) - * smallBox: use this.smallBoxHeight instead of this.boxHeight (optional) - * boxIcon: path to an icon that is put in front of the text (optional) - * onClick: click callback for the text in the box (optional) - * - * Only used for background: - * curveHeight: fix height in px instead of share - * boxHeight: fix box height in px - * bgCanvas: true to draw on background canvas - */ -Piwik_Transitions_Canvas.prototype.renderBox = function(params) { - var curveHeight = params.curveHeight ? params.curveHeight : - Math.round(this.totalHeightOfConnections * params.share); - curveHeight = Math.max(curveHeight, 1); - - var boxHeight = this.boxHeight; - if (params.smallBox) boxHeight = this.smallBoxHeight; - if (params.boxHeight) boxHeight = params.boxHeight; - - var context = params.bgCanvas ? this.bgContext : this.context; - - // background - context.fillStyle = params.gradient; - context.beginPath(); - if (params.side == 'left') { - this.renderLeftBoxBg(context, boxHeight, curveHeight); - } else { - this.renderRightBoxBg(context, boxHeight, curveHeight); - } - if (typeof context.endPath == 'function') { - context.endPath(); - } - - // text inside the box - if (params.boxText) { - var onClick = typeof params.onClick == 'function' ? params.onClick : false; - var boxTextLeft, boxTextTop, el; - if (params.side == 'left') { - boxTextLeft = this.leftBoxBeginX + 10; - boxTextTop = this.leftBoxPositionY + boxHeight / 2 - params.boxTextNumLines * this.lineHeight / 2; - el = this.renderText(params.boxText, boxTextLeft, boxTextTop, 'BoxTextLeft', onClick, params.boxIcon, params.boxTextNumLines); - } else { - boxTextLeft = this.rightBoxBeginX; - boxTextTop = this.rightBoxPositionY + boxHeight / 2 - params.boxTextNumLines * this.lineHeight / 2; - el = this.renderText(params.boxText, boxTextLeft, boxTextTop, 'BoxTextRight', onClick, params.boxIcon, params.boxTextNumLines); - } - if (params.boxTextCssClass) { - el.addClass('Transitions_' + params.boxTextCssClass); - } - // tooltip - if (params.boxTextTooltip) { - el.hover(function() { - var tip = Piwik_Transitions_Util.addBreakpoints(params.boxTextTooltip); - Piwik_Tooltip.show(tip, 'Transitions_Tooltip_Small', 300); - }, function() { - Piwik_Tooltip.hide(); - }); - } - } - - // text at the beginning of the curve - if (params.curveText) { - var curveTextLeft, curveTextTop; - if (params.side == 'left') { - curveTextLeft = this.leftBoxBeginX + this.boxWidth + 12; - curveTextTop = this.leftBoxPositionY + boxHeight / 2 - this.lineHeight / 2; - } else { - curveTextLeft = this.rightBoxBeginX - 35; - curveTextTop = this.rightBoxPositionY + boxHeight / 2 - this.lineHeight / 2; - } - var textDiv = this.renderText(params.curveText, curveTextLeft, curveTextTop, - params.side == 'left' ? 'CurveTextLeft' : 'CurveTextRight'); - // tooltip - if (params.curveTextTooltip) { - textDiv.hover(function() { - Piwik_Tooltip.show(params.curveTextTooltip, 'Transitions_Tooltip_Small'); - }, function() { - Piwik_Tooltip.hide(); - }); - } - } - - if (params.side == 'left') { - this.leftBoxPositionY += boxHeight + this.boxSpacing; - this.leftCurvePositionY += curveHeight + this.curveSpacing; - } else { - this.rightBoxPositionY += boxHeight + this.boxSpacing; - this.rightCurvePositionY += curveHeight + this.curveSpacing; - } -}; - -Piwik_Transitions_Canvas.prototype.renderLeftBoxBg = function(context, boxHeight, curveHeight) { - // derive coordinates for ths curve - var leftUpper = {x: this.leftCurveBeginX, y: this.leftBoxPositionY}; - var leftLower = {x: this.leftCurveBeginX, y: this.leftBoxPositionY + boxHeight}; - var rightUpper = {x: this.leftCurveEndX, y: this.leftCurvePositionY}; - var rightLower = {x: this.leftCurveEndX, y: this.leftCurvePositionY + curveHeight}; - - // derive control points for bezier curve - var center = (this.leftCurveBeginX + this.leftCurveEndX) / 2; - var cp1Upper = {x: center, y: leftUpper.y}; - var cp2Upper = {x: center, y: rightUpper.y}; - var cp1Lower = {x: center, y: rightLower.y}; - var cp2Lower = {x: center, y: leftLower.y}; - - // the flow - context.moveTo(leftUpper.x, leftUpper.y); - context.bezierCurveTo(cp1Upper.x, cp1Upper.y, cp2Upper.x, cp2Upper.y, rightUpper.x, rightUpper.y); - context.lineTo(rightLower.x, rightLower.y); - context.bezierCurveTo(cp1Lower.x, cp1Lower.y, cp2Lower.x, cp2Lower.y, leftLower.x, leftLower.y); - - // the box - context.lineTo(leftLower.x - this.boxWidth + 4, leftLower.y); - context.lineTo(leftLower.x - this.boxWidth, leftUpper.y); - context.lineTo(leftUpper.x, leftUpper.y); - context.fill(); -}; - -Piwik_Transitions_Canvas.prototype.renderRightBoxBg = function(context, boxHeight, curveHeight) { - // derive coordinates for curve - var leftUpper = {x: this.rightCurveBeginX, y: this.rightCurvePositionY}; - var leftLower = {x: this.rightCurveBeginX, y: this.rightCurvePositionY + curveHeight}; - var rightUpper = {x: this.rightCurveEndX, y: this.rightBoxPositionY}; - var rightLower = {x: this.rightCurveEndX, y: this.rightBoxPositionY + boxHeight}; - - // derive control points for bezier curve - var center = (this.rightCurveBeginX + this.rightCurveEndX) / 2; - var cp1Upper = {x: center, y: leftUpper.y}; - var cp2Upper = {x: center, y: rightUpper.y}; - var cp1Lower = {x: center, y: rightLower.y}; - var cp2Lower = {x: center, y: leftLower.y}; - - // the flow part 1 - context.moveTo(leftUpper.x, leftUpper.y); - context.bezierCurveTo(cp1Upper.x, cp1Upper.y, cp2Upper.x, cp2Upper.y, rightUpper.x, rightUpper.y); - - // the box - context.lineTo(rightUpper.x + this.boxWidth, rightUpper.y); - context.lineTo(rightLower.x + this.boxWidth - 4, rightLower.y); - context.lineTo(rightLower.x, rightLower.y); - - // the flow part 2 - context.bezierCurveTo(cp1Lower.x, cp1Lower.y, cp2Lower.x, cp2Lower.y, leftLower.x, leftLower.y); - context.lineTo(leftUpper.x, leftUpper.y); - context.fill(); -}; - -/** Add spacing after the current box */ -Piwik_Transitions_Canvas.prototype.addBoxSpacing = function(spacing, side) { - if (side == 'left') { - this.leftBoxPositionY += spacing; - } else { - this.rightBoxPositionY += spacing; - } -}; - -Piwik_Transitions_Canvas.prototype.renderLoops = function(share) { - var curveHeight = Math.round(this.totalHeightOfConnections * share); - curveHeight = Math.max(curveHeight, 1); - - // create gradient - var gradient = this.context.createLinearGradient(this.leftCurveEndX - 50, 0, this.rightCurveBeginX + 50, 0); - var light = '#F5F3EB'; - var dark = '#E8E4D5'; - gradient.addColorStop(0, dark); - gradient.addColorStop(.5, light); - gradient.addColorStop(1, dark); - - this.context.fillStyle = gradient; - - this.context.beginPath(); - - // curve from the upper left connection to the center box to the lower left connection to the text box - var point1 = {x: this.leftCurveEndX, y: this.leftCurvePositionY}; - var point2 = {x: this.leftCurveEndX, y: 460}; - - var cpLeftX = (this.leftCurveBeginX + this.leftCurveEndX) / 2 + 30; - var cp1 = {x: cpLeftX, y: point1.y}; - var cp2 = {x: cpLeftX, y: point2.y}; - - this.context.moveTo(point1.x, point1.y); - this.context.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, point2.x, point2.y); - - // lower line of text box - var point3 = {x: this.rightCurveBeginX, y: point2.y}; - this.context.lineTo(point3.x, point3.y); - - // curve to upper right connection to the center box - var point4 = {x: this.rightCurveBeginX, y: this.rightCurvePositionY}; - var cpRightX = (this.rightCurveBeginX + this.rightCurveEndX) / 2 - 30; - var cp3 = {x: cpRightX, y: point3.y}; - var cp4 = {x: cpRightX, y: point4.y}; - this.context.bezierCurveTo(cp3.x, cp3.y, cp4.x, cp4.y, point4.x, point4.y); - - // line to lower right connection to the center box - var point5 = {x: point4.x, y: point4.y + curveHeight}; - this.context.lineTo(point5.x, point5.y); - - // curve to upper right connection to the text box - var point6 = {x: point5.x, y: point2.y - 25}; - cpRightX -= 30; - var cp5 = {x: cpRightX, y: point5.y}; - var cp6 = {x: cpRightX, y: point6.y}; - this.context.bezierCurveTo(cp5.x, cp5.y, cp6.x, cp6.y, point6.x, point6.y); - - // upper line of the text box - var point7 = {x: point1.x, y: point6.y}; - this.context.lineTo(point7.x, point7.y); - - // line to lower left connection to the center box - var point8 = {x: point1.x, y: point1.y + + curveHeight}; - cpLeftX += 30; - var cp7 = {x: cpLeftX, y: point7.y}; - var cp8 = {x: cpLeftX, y: point8.y}; - this.context.bezierCurveTo(cp7.x, cp7.y, cp8.x, cp8.y, point8.x, point8.y); - - this.context.fill(); - - if (typeof this.context.endPath == 'function') { - this.context.endPath(); - } - -}; - -/** Clear one side for redrawing */ -Piwik_Transitions_Canvas.prototype.clearSide = function(side) { - var x = (side == 'left' ? 0 : this.width / 2); - var y = 0; - var w = this.width / 2; - var h = this.height; - - this.context.clearRect(x, y, w, h); - this.bgContext.clearRect(x, y, w, h); - - if (side == 'left') { - this.container.find('.Transitions_BoxTextLeft').remove(); - this.container.find('.Transitions_CurveTextLeft').remove(); - this.leftBoxPositionY = this.originalBoxPositionY; - this.leftCurvePositionY = this.originalCurvePositionY; - } else { - this.container.find('.Transitions_BoxTextRight').remove(); - this.container.find('.Transitions_CurveTextRight').remove(); - this.rightBoxPositionY = this.originalBoxPositionY; - this.rightCurvePositionY = this.originalCurvePositionY; - } -}; - - -// -------------------------------------- -// MODEL -// -------------------------------------- - -function Piwik_Transitions_Model(ajax) { - this.ajax = ajax; -} - -Piwik_Transitions_Model.prototype.loadData = function(link, callback) { - var self = this; - - this.pageviews = 0; - this.exits = 0; - this.bounces = 0; - this.loops = 0; - - this.directEntries = 0; - - this.searchEnginesNbTransitions = 0; - this.searchEngines = []; - - this.websitesNbTransitions = 0; - this.websites = []; - - this.campaignsNbTransitions = 0; - this.campaigns = []; - - this.previousPagesNbTransitions = 0; - this.previousPages = []; - - this.followingPagesNbTransitions = 0; - this.followingPages = []; - - this.downloadsNbTransitions = 0; - this.downloads = []; - - this.outlinksNbTransitions = 0; - this.outlinks = []; - - this.groupTitles = { - previousPages: Piwik_Transitions_Translations.fromPreviousPages, - followingPages: Piwik_Transitions_Translations.toFollowingPages, - outlinks: Piwik_Transitions_Translations.outlinks, - downloads: Piwik_Transitions_Translations.downloads - }; - - this.shareInGroupTexts = { - previousPages: Piwik_Transitions_Translations.fromPreviousPagesInline, - followingPages: Piwik_Transitions_Translations.toFollowingPagesInline, - searchEngines: Piwik_Transitions_Translations.fromSearchEnginesInline, - websites: Piwik_Transitions_Translations.fromWebsitesInline, - campaigns: Piwik_Transitions_Translations.fromCampaignsInline, - outlinks: Piwik_Transitions_Translations.outlinksInline, - downloads: Piwik_Transitions_Translations.downloadsInline - }; - - this.ajax.callApi('Transitions.getFullReport', { - pageUrl: link, - expanded: 1 - }, - function(report) { - // load page metrics - self.pageviews = report.pageMetrics.pageviews; - self.exits = report.pageMetrics.exits; - self.bounces = report.pageMetrics.bounces; - self.loops = report.pageMetrics.loops; - - // load referrers: split direct entries and others - for (var i = 0; i < report.referrers.length; i++) { - var referrer = report.referrers[i]; - if (referrer.shortName == 'direct') { - self.directEntries = referrer.visits; - } else if (referrer.shortName == 'search') { - self.searchEnginesNbTransitions = referrer.visits; - self.searchEngines = referrer.details; - self.groupTitles.searchEngines = referrer.label; - } else if (referrer.shortName == 'website') { - self.websitesNbTransitions = referrer.visits; - self.websites = referrer.details; - self.groupTitles.websites = referrer.label; - } else if (referrer.shortName == 'campaign') { - self.campaignsNbTransitions = referrer.visits; - self.campaigns = referrer.details; - self.groupTitles.campaigns = referrer.label; - } - } - - self.loadAndSumReport(report, 'previousPages'); - self.loadAndSumReport(report, 'followingPages'); - self.loadAndSumReport(report, 'downloads'); - self.loadAndSumReport(report, 'outlinks'); - - callback(); - }); -}; - -Piwik_Transitions_Model.prototype.loadAndSumReport = function(apiData, reportName) { - var data = this[reportName] = apiData[reportName]; - var sumVarName = reportName + 'NbTransitions'; - - this[sumVarName] = 0; - for (var i = 0; i < data.length; i++) { - this[sumVarName] += data[i].referrals; - } -}; - -Piwik_Transitions_Model.prototype.getGroupTitle = function(groupName) { - if (typeof this.groupTitles[groupName] != 'undefined') { - return this.groupTitles[groupName]; - } - return groupName; -}; - -Piwik_Transitions_Model.prototype.getShareInGroupTooltip = function(share, groupName) { - var tip = this.shareInGroupTexts[groupName]; - return tip.replace(/%s/, share); -}; - -Piwik_Transitions_Model.prototype.getDetailsForGroup = function(groupName) { - return this.addPercentagesToData(this[groupName]); -}; - -Piwik_Transitions_Model.prototype.getPercentage = function(metric, formatted) { - var percentage = (this.pageviews == 0 ? 0 : this[metric] / this.pageviews); - - if (formatted) { - percentage = this.roundPercentage(percentage); - percentage += '%'; - } - - return percentage; -}; - -Piwik_Transitions_Model.prototype.addPercentagesToData = function(data) { - var total = 0; - - for (var i = 0; i < data.length; i++) { - total += parseInt(data[i].referrals, 10); - } - - for (i = 0; i < data.length; i++) { - data[i].percentage = this.roundPercentage(data[i].referrals / total); - } - - return data; -}; - -Piwik_Transitions_Model.prototype.roundPercentage = function(value) { - if (value < .1) { - return Math.round(value * 1000) / 10.0; - } else { - return Math.round(value * 100); - } -}; - - -// -------------------------------------- -// AJAX -// -------------------------------------- - -function Piwik_Transitions_Ajax() { -} - -Piwik_Transitions_Ajax.prototype.callTransitionsController = function(action, callback) { - $.post('index.php', { - module: 'Transitions', - action: action, - date: piwik.currentDateString, - idSite: piwik.idSite, - period: piwik.period - }, callback); -}; - -Piwik_Transitions_Ajax.prototype.callApi = function(method, params, callback) { - params.module = 'API'; - params.method = method; - params.date = piwik.currentDateString; - params.idSite = piwik.idSite; - params.period = piwik.period; - params.token_auth = piwik.token_auth; - params.format = 'JSON'; - if (params.period == 'range') { - params.date = piwik.startDateString + ',' + params.date; - } - - $.post('index.php', params, function(result) { - if (typeof result.result != 'undefined' && result.result == 'error') { - alert(result.message); - } else { - callback(result); - } - }, 'json'); -}; - - - -// -------------------------------------- -// STATIC UTIL FUNCTIONS -// -------------------------------------- - -Piwik_Transitions_Util = { - - /** - * Removes protocol, www and trailing slashes from a URL. - * If removeDomain is set, the domain is removed as well. - */ - shortenUrl: function(url, removeDomain) { - if (url == 'Others') { - return url; - } - url = url.replace(/http(s)?:\/\/(www\.)?/, ''); - if (removeDomain) { - var urlBackup = url; - url = url.replace(/[^\/]*/, ''); - if (url == '/') { - url = urlBackup; - } - } - url = url.replace(/\/$/, ''); - return url; - }, - - /** Add break points to string so that it can be displayed more compactly */ - addBreakpoints: function(text) { - return text.replace(/([\/&=?\.%#:])/g, '$1<wbr>'); - }, - - /** - * Replaces a %s placeholder in the HTML. - * The special feature is that it can be called multiple times, replacing the already - * replaced placeholder again. It creates a span that can be assigned a class using the - * spanClass parameter. The default class is 'Transitions_Metric'. - */ - replacePlaceholderInHtml: function(container, value, spanClass) { - var span = container.find('span'); - if (span.size() == 0) { - var html = container.html().replace(/%s/, '<span></span>'); - span = container.html(html).find('span'); - if (!spanClass) { - spanClass = 'Transitions_Metric'; - } - span.addClass(spanClass); - } - span.html(value); - } - -}; |