add icons for Character groups

This commit is contained in:
coderkun 2014-04-29 14:18:04 +02:00
commit 2d9a41a5fe
3461 changed files with 594457 additions and 0 deletions

View file

@ -0,0 +1,136 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Overlay;
use Exception;
use Piwik\Access;
use Piwik\Config;
use Piwik\DataTable;
use Piwik\Piwik;
use Piwik\Plugins\SitesManager\API as APISitesManager;
use Piwik\Plugins\SitesManager\SitesManager;
use Piwik\Plugins\Transitions\API as APITransitions;
use Piwik\Tracker\PageUrl;
/**
* Class API
* @method static \Piwik\Plugins\Overlay\API getInstance()
*/
class API extends \Piwik\Plugin\API
{
/**
* Get translation strings
*/
public function getTranslations($idSite)
{
$this->authenticate($idSite);
$translations = array(
'oneClick' => 'Overlay_OneClick',
'clicks' => 'Overlay_Clicks',
'clicksFromXLinks' => 'Overlay_ClicksFromXLinks',
'link' => 'Overlay_Link'
);
return array_map(array('\\Piwik\\Piwik','translate'), $translations);
}
/**
* Get excluded query parameters for a site.
* This information is used for client side url normalization.
*/
public function getExcludedQueryParameters($idSite)
{
$this->authenticate($idSite);
$sitesManager = APISitesManager::getInstance();
$site = $sitesManager->getSiteFromId($idSite);
try {
return SitesManager::getTrackerExcludedQueryParameters($site);
} catch (Exception $e) {
// an exception is thrown when the user has no view access.
// do not throw the exception to the outside.
return array();
}
}
/**
* Get following pages of a url.
* This is done on the logs - not the archives!
*
* Note: if you use this method via the regular API, the number of results will be limited.
* Make sure, you set filter_limit=-1 in the request.
*/
public function getFollowingPages($url, $idSite, $period, $date, $segment = false)
{
$this->authenticate($idSite);
$url = PageUrl::excludeQueryParametersFromUrl($url, $idSite);
// we don't unsanitize $url here. it will be done in the Transitions plugin.
$resultDataTable = new DataTable;
try {
$limitBeforeGrouping = Config::getInstance()->General['overlay_following_pages_limit'];
$transitionsReport = APITransitions::getInstance()->getTransitionsForAction(
$url, $type = 'url', $idSite, $period, $date, $segment, $limitBeforeGrouping,
$part = 'followingActions', $returnNormalizedUrls = true);
} catch (Exception $e) {
return $resultDataTable;
}
$reports = array('followingPages', 'outlinks', 'downloads');
foreach ($reports as $reportName) {
if (!isset($transitionsReport[$reportName])) {
continue;
}
foreach ($transitionsReport[$reportName]->getRows() as $row) {
// don't touch the row at all for performance reasons
$resultDataTable->addRow($row);
}
}
return $resultDataTable;
}
/** Do cookie authentication. This way, the token can remain secret. */
private function authenticate($idSite)
{
/**
* Triggered immediately before the user is authenticated.
*
* This event can be used by plugins that provide their own authentication mechanism
* to make that mechanism available. Subscribers should set the `'auth'` object in
* the {@link Piwik\Registry} to an object that implements the {@link Piwik\Auth} interface.
*
* **Example**
*
* use Piwik\Registry;
*
* public function initAuthenticationObject($activateCookieAuth)
* {
* Registry::set('auth', new LDAPAuth($activateCookieAuth));
* }
*
* @param bool $activateCookieAuth Whether authentication based on `$_COOKIE` values should
* be allowed.
*/
Piwik::postEvent('Request.initAuthenticationObject', array($activateCookieAuth = true));
$auth = \Piwik\Registry::get('auth');
$success = Access::getInstance()->reloadAccess($auth);
if (!$success) {
throw new Exception('Authentication failed');
}
Piwik::checkUserHasViewAccess($idSite);
}
}

View file

@ -0,0 +1,236 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Overlay;
use Piwik\API\Request;
use Piwik\Common;
use Piwik\Config;
use Piwik\Metrics;
use Piwik\MetricsFormatter;
use Piwik\Piwik;
use Piwik\Plugins\Actions\ArchivingHelper;
use Piwik\Plugins\SitesManager\API as APISitesManager;
use Piwik\ProxyHttp;
use Piwik\Tracker\Action;
use Piwik\Tracker\PageUrl;
use Piwik\View;
class Controller extends \Piwik\Plugin\Controller
{
/** The index of the plugin */
public function index()
{
Piwik::checkUserHasViewAccess($this->idSite);
$template = '@Overlay/index';
if (Config::getInstance()->General['overlay_disable_framed_mode']) {
$template = '@Overlay/index_noframe';
}
$view = new View($template);
$this->setGeneralVariablesView($view);
$view->idSite = $this->idSite;
$view->date = Common::getRequestVar('date', 'today');
$view->period = Common::getRequestVar('period', 'day');
$view->ssl = ProxyHttp::isHttps();
return $view->render();
}
/** Render the area left of the iframe */
public function renderSidebar()
{
$idSite = Common::getRequestVar('idSite');
$period = Common::getRequestVar('period');
$date = Common::getRequestVar('date');
$currentUrl = Common::getRequestVar('currentUrl');
$currentUrl = Common::unsanitizeInputValue($currentUrl);
$normalizedCurrentUrl = PageUrl::excludeQueryParametersFromUrl($currentUrl, $idSite);
$normalizedCurrentUrl = Common::unsanitizeInputValue($normalizedCurrentUrl);
// load the appropriate row of the page urls report using the label filter
ArchivingHelper::reloadConfig();
$path = ArchivingHelper::getActionExplodedNames($normalizedCurrentUrl, Action::TYPE_PAGE_URL);
$path = array_map('urlencode', $path);
$label = implode('>', $path);
$request = new Request(
'method=Actions.getPageUrls'
. '&idSite=' . urlencode($idSite)
. '&date=' . urlencode($date)
. '&period=' . urlencode($period)
. '&label=' . urlencode($label)
. '&format=original'
);
$dataTable = $request->process();
$data = array();
if ($dataTable->getRowsCount() > 0) {
$row = $dataTable->getFirstRow();
$translations = Metrics::getDefaultMetricTranslations();
$showMetrics = array('nb_hits', 'nb_visits', 'nb_uniq_visitors',
'bounce_rate', 'exit_rate', 'avg_time_on_page');
foreach ($showMetrics as $metric) {
$value = $row->getColumn($metric);
if ($value === false) {
// skip unique visitors for period != day
continue;
}
if ($metric == 'avg_time_on_page') {
$value = MetricsFormatter::getPrettyTimeFromSeconds($value);
}
$data[] = array(
'name' => $translations[$metric],
'value' => $value
);
}
}
// generate page url string
foreach ($path as &$part) {
$part = preg_replace(';^/;', '', urldecode($part));
}
$page = '/' . implode('/', $path);
$page = preg_replace(';/index$;', '/', $page);
if ($page == '/') {
$page = '/index';
}
// render template
$view = new View('@Overlay/renderSidebar');
$view->data = $data;
$view->location = $page;
$view->normalizedUrl = $normalizedCurrentUrl;
$view->label = $label;
$view->idSite = $idSite;
$view->period = $period;
$view->date = $date;
return $view->render();
}
/**
* Start an Overlay session: Redirect to the tracked website. The Piwik
* tracker will recognize this referrer and start the session.
*/
public function startOverlaySession()
{
$idSite = Common::getRequestVar('idSite', 0, 'int');
Piwik::checkUserHasViewAccess($idSite);
$sitesManager = APISitesManager::getInstance();
$site = $sitesManager->getSiteFromId($idSite);
$urls = $sitesManager->getSiteUrlsFromId($idSite);
@header('Content-Type: text/html; charset=UTF-8');
return '
<html><head><title></title></head><body>
<script type="text/javascript">
function handleProtocol(url) {
if (' . (ProxyHttp::isHttps() ? 'true' : 'false') . ') {
return url.replace(/http:\/\//i, "https://");
} else {
return url.replace(/https:\/\//i, "http://");
}
}
function removeUrlPrefix(url) {
return url.replace(/http(s)?:\/\/(www\.)?/i, "");
}
if (window.location.hash) {
var match = false;
var urlToRedirect = window.location.hash.substr(1);
var urlToRedirectWithoutPrefix = removeUrlPrefix(urlToRedirect);
var knownUrls = ' . Common::json_encode($urls) . ';
for (var i = 0; i < knownUrls.length; i++) {
var testUrl = removeUrlPrefix(knownUrls[i]);
if (urlToRedirectWithoutPrefix.substr(0, testUrl.length) == testUrl) {
match = true;
if (navigator.appName == "Microsoft Internet Explorer") {
// internet explorer loses the referrer if we use window.location.href=X
var referLink = document.createElement("a");
referLink.href = handleProtocol(urlToRedirect);
document.body.appendChild(referLink);
referLink.click();
} else {
window.location.href = handleProtocol(urlToRedirect);
}
break;
}
}
if (!match) {
var idSite = window.location.href.match(/idSite=([0-9]+)/i)[1];
window.location.href = "index.php?module=Overlay&action=showErrorWrongDomain"
+ "&idSite=" + idSite
+ "&url=" + encodeURIComponent(urlToRedirect);
}
}
else {
window.location.href = handleProtocol("' . $site['main_url'] . '");
};
</script>
</body></html>
';
}
/**
* This method is called when the JS from startOverlaySession() detects that the target domain
* is not configured for the current site.
*/
public function showErrorWrongDomain()
{
$idSite = Common::getRequestVar('idSite', 0, 'int');
Piwik::checkUserHasViewAccess($idSite);
$url = Common::getRequestVar('url', '');
$url = Common::unsanitizeInputValue($url);
$message = Piwik::translate('Overlay_RedirectUrlError', array($url, "\n"));
$message = nl2br(htmlentities($message));
$view = new View('@Overlay/showErrorWrongDomain');
$view->message = $message;
if (Piwik::isUserHasAdminAccess($idSite)) {
// TODO use $idSite to link to the correct row. This is tricky because the #rowX ids don't match
// the site ids when sites have been deleted.
$url = 'index.php?module=SitesManager&action=index';
$troubleshoot = htmlentities(Piwik::translate('Overlay_RedirectUrlErrorAdmin'));
$troubleshoot = sprintf($troubleshoot, '<a href="' . $url . '" target="_top">', '</a>');
$view->troubleshoot = $troubleshoot;
} else {
$view->troubleshoot = htmlentities(Piwik::translate('Overlay_RedirectUrlErrorUser'));
}
return $view->render();
}
/**
* This method is used to pass information from the iframe back to Piwik.
* Due to the same origin policy, we can't do that directly, so we inject
* an additional iframe in the Overlay session that calls this controller
* method.
* The rendered iframe is from the same origin as the Piwik window so we
* can bypass the same origin policy and call the parent.
*/
public function notifyParentIframe()
{
$view = new View('@Overlay/notifyParentIframe');
return $view->render();
}
}

View file

@ -0,0 +1,49 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Overlay;
class Overlay extends \Piwik\Plugin
{
public function getInformation()
{
$suffix = ' Note: Requires the Transitions plugin enabled.';
$info = parent::getInformation();
$info['description'] .= ' ' . $suffix;
return $info;
}
/**
* @see Piwik\Plugin::getListHooksRegistered
*/
function getListHooksRegistered()
{
return array(
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys'
);
}
/**
* Returns required Js Files
* @param $jsFiles
*/
public function getJsFiles(&$jsFiles)
{
$jsFiles[] = 'plugins/Overlay/javascripts/rowaction.js';
$jsFiles[] = 'plugins/Overlay/javascripts/Overlay_Helper.js';
}
public function getClientSideTranslationKeys(&$translationKeys)
{
$translationKeys[] = 'General_OverlayRowActionTooltipTitle';
$translationKeys[] = 'General_OverlayRowActionTooltip';
}
}

View file

@ -0,0 +1,138 @@
/**
* Reset styles
*/
#PIS_StatusBar,
#PIS_StatusBar .PIS_Item,
#PIS_StatusBar .PIS_Loading,
.PIS_LinkTag,
.PIS_LinkHighlightBoxTop,
.PIS_LinkHighlightBoxRight,
.PIS_LinkHighlightBoxLeft,
.PIS_LinkHighlightBoxText {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: normal;
font-style: normal;
font-size: 11px;
font-family: Arial, Helvetica, sans-serif;
vertical-align: baseline;
line-height: 1.4em;
text-indent: 0;
text-decoration: none;
text-transform: none;
cursor: default;
text-align: left;
float: none;
color: #333;
}
/**
* Link Tags
*/
.PIS_LinkTag {
position: absolute;
z-index: 9999;
width: 36px;
height: 21px;
text-align: left;
background: url(./linktags_lessshadow.png) no-repeat 0 -21px;
overflow: hidden;
}
.PIS_LinkTag span {
position: absolute;
width: 31px;
height: 14px;
font-size: 10px;
text-align: center;
font-weight: bold;
line-height: 14px;
margin-left: 1px;
}
.PIS_LinkTag.PIS_Highlighted {
z-index: 10002;
}
.PIS_LinkTag.PIS_Highlighted span {
color: #E87500;
}
.PIS_LinkTag.PIS_Right {
background-position: -36px -21px;
}
.PIS_LinkTag.PIS_Right span,
.PIS_LinkTag.PIS_BottomRight span {
margin-left: 5px;
}
.PIS_LinkTag.PIS_Bottom {
background-position: 0 0;
}
.PIS_LinkTag.PIS_Bottom span,
.PIS_LinkTag.PIS_BottomRight span {
margin-top: 4px;
}
.PIS_LinkTag.PIS_BottomRight {
background-position: -36px 0;
}
/**
* Link Highlights
*/
.PIS_LinkHighlightBoxTop,
.PIS_LinkHighlightBoxRight,
.PIS_LinkHighlightBoxText,
.PIS_LinkHighlightBoxLeft {
position: absolute;
z-index: 10001;
overflow: hidden;
width: 2px;
height: 2px;
background: #E87500;
}
.PIS_LinkHighlightBoxText {
line-height: 20px;
height: 20px;
font-size: 11px;
color: white;
width: auto;
}
/**
* Status bar
*/
#PIS_StatusBar {
padding: 10px 0;
position: fixed;
z-index: 10020;
bottom: 0;
right: 0;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
background: #fbfbfb;
border-radius: 6px 0 0;
}
#PIS_StatusBar .PIS_Item {
text-align: right;
padding: 3px 5px 0 0;
margin: 0 15px 0 20px;
font-weight: bold;
}
#PIS_StatusBar .PIS_Loading {
background: url(./loading.gif) no-repeat right center;
padding-right: 30px;
}

View file

@ -0,0 +1,261 @@
var Piwik_Overlay_Client = (function () {
/** jQuery */
var $;
/** Url of the Piwik root */
var piwikRoot;
/** Piwik idsite */
var idSite;
/** The current period and date */
var period, date;
/** Reference to the status bar DOM element */
var statusBar;
/** Load the client CSS */
function loadCss() {
var css = c('link').attr({
rel: 'stylesheet',
type: 'text/css',
href: piwikRoot + 'plugins/Overlay/client/client.css'
});
$('head').append(css);
}
/**
* This method loads jQuery, if it is not there yet.
* The callback is triggered after jQuery is loaded.
*/
function loadJQuery(callback) {
if (typeof jQuery != 'undefined') {
$ = jQuery;
callback();
}
else {
Piwik_Overlay_Client.loadScript('libs/jquery/jquery.js', function () {
$ = jQuery;
jQuery.noConflict();
callback();
});
}
}
/**
* Notify Piwik of the current iframe location.
* This way, we can display additional metrics on the side of the iframe.
*/
function notifyPiwikOfLocation() {
// check whether the session has been opened in a new tab (instead of an iframe)
if (window != window.top) {
var iframe = c('iframe', false, {
src: piwikRoot + 'index.php?module=Overlay&action=notifyParentIframe#' + window.location.href
}).css({width: 0, height: 0, border: 0});
// in some cases, calling append right away doesn't work in IE8
$(document).ready(function () {
$('body').append(iframe);
});
}
}
/** Create a jqueryfied DOM element */
function c(tagName, className, attributes) {
var el = $(document.createElement(tagName));
if (className) {
if (className.substring(0, 1) == '#') {
var id = className.substring(1, className.length);
id = 'PIS_' + id;
el.attr('id', id);
}
else {
className = 'PIS_' + className;
el.addClass(className);
}
}
if (attributes) {
el.attr(attributes);
}
return el;
}
/** Special treatment for some internet explorers */
var ieStatusBarEventsBound = false;
function handleIEStatusBar() {
if (navigator.appVersion.indexOf("MSIE 7.") == -1
&& navigator.appVersion.indexOf("MSIE 8.") == -1) {
// this is not IE8 or lower
return;
}
// IE7/8 can't handle position:fixed so we need to do it by hand
statusBar.css({
position: 'absolute',
right: 'auto',
bottom: 'auto',
left: 0,
top: 0
});
var position = function () {
var scrollY = document.body.parentElement.scrollTop;
var scrollX = document.body.parentElement.scrollLeft;
statusBar.css({
top: (scrollY + $(window).height() - statusBar.outerHeight()) + 'px',
left: (scrollX + $(window).width() - statusBar.outerWidth()) + 'px'
});
};
position();
statusBar.css({width: 'auto'});
if (statusBar.width() < 350) {
statusBar.width(350);
} else {
statusBar.width(statusBar.width());
}
if (!ieStatusBarEventsBound) {
ieStatusBarEventsBound = true;
$(window).resize(position);
$(window).scroll(position);
}
}
return {
/** Initialize in-site analytics */
initialize: function (pPiwikRoot, pIdSite, pPeriod, pDate) {
piwikRoot = pPiwikRoot;
idSite = pIdSite;
period = pPeriod;
date = pDate;
var load = this.loadScript;
var loading = this.loadingNotification;
loadJQuery(function () {
notifyPiwikOfLocation();
loadCss();
// translations
load('plugins/Overlay/client/translations.js', function () {
Piwik_Overlay_Translations.initialize(function () {
// following pages
var finishPages = loading('Loading following pages');
load('plugins/Overlay/client/followingpages.js', function () {
Piwik_Overlay_FollowingPages.initialize(finishPages);
});
});
});
});
},
/** Create a jqueryfied DOM element */
createElement: function (tagName, className, attributes) {
return c(tagName, className, attributes);
},
/** Load a script and wait for it to be loaded */
loadScript: function (relativePath, callback) {
var loaded = false;
var onLoad = function () {
if (!loaded) {
loaded = true;
callback();
}
};
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.onreadystatechange = function () {
if (this.readyState == 'loaded' || this.readyState == 'complete') {
onLoad();
}
};
script.onload = onLoad;
script.src = piwikRoot + relativePath + '?v=1';
head.appendChild(script);
},
/** Piwik Overlay API Request */
api: function (method, callback, additionalParams) {
var url = piwikRoot + 'index.php?module=API&method=Overlay.' + method
+ '&idSite=' + idSite + '&period=' + period + '&date=' + date + '&format=JSON&filter_limit=-1';
if (additionalParams) {
url += '&' + additionalParams;
}
$.getJSON(url + "&jsoncallback=?", function (data) {
if (typeof data.result != 'undefined' && data.result == 'error') {
alert('Error: ' + data.message);
}
else {
callback(data);
}
});
},
/**
* Initialize a notification
* To hide the notification use the returned callback
*/
notification: function (message, addClass) {
if (!statusBar) {
statusBar = c('div', '#StatusBar').css('opacity', .8);
$('body').prepend(statusBar);
}
var item = c('div', 'Item').html(message);
if (addClass) {
item.addClass('PIS_' + addClass);
}
statusBar.show().append(item);
handleIEStatusBar();
window.setTimeout(handleIEStatusBar, 100);
return function () {
item.remove();
if (statusBar.children().size() == 0) {
statusBar.hide();
} else {
handleIEStatusBar();
}
};
},
/** Hide all notifications with a certain class */
hideNotifications: function (className) {
statusBar.find('.PIS_' + className).remove();
if (statusBar.children().size() == 0) {
statusBar.hide();
} else {
handleIEStatusBar();
}
},
/**
* Initialize a loading notification
* To hide the notification use the returned callback
*/
loadingNotification: function (message) {
return Piwik_Overlay_Client.notification(message, 'Loading');
}
};
})();

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

View file

@ -0,0 +1,544 @@
var Piwik_Overlay_FollowingPages = (function () {
/** jQuery */
var $ = jQuery;
/** Info about the following pages */
var followingPages = [];
/** List of excluded get parameters */
var excludedParams = [];
/** Index of the links on the page */
var linksOnPage = {};
/** Reference to create element function */
var c;
/** Load the following pages */
function load(callback) {
// normalize current location
var location = window.location.href;
location = Piwik_Overlay_UrlNormalizer.normalize(location);
location = (("https:" == document.location.protocol) ? 'https' : 'http') + '://' + location;
var excludedParamsLoaded = false;
var followingPagesLoaded = false;
// load excluded params
Piwik_Overlay_Client.api('getExcludedQueryParameters', function (data) {
for (var i = 0; i < data.length; i++) {
if (typeof data[i] == 'object') {
data[i] = data[i][0];
}
}
excludedParams = data;
excludedParamsLoaded = true;
if (followingPagesLoaded) {
callback();
}
});
// load following pages
Piwik_Overlay_Client.api('getFollowingPages', function (data) {
followingPages = data;
processFollowingPages();
followingPagesLoaded = true;
if (excludedParamsLoaded) {
callback();
}
}, 'url=' + encodeURIComponent(location));
}
/** Normalize the URLs of following pages and aggregate some stats */
function processFollowingPages() {
var totalClicks = 0;
for (var i = 0; i < followingPages.length; i++) {
var page = followingPages[i];
// though the following pages are returned without the prefix, downloads
// and outlinks still have it.
page.label = Piwik_Overlay_UrlNormalizer.removeUrlPrefix(page.label);
totalClicks += followingPages[i].referrals;
}
for (i = 0; i < followingPages.length; i++) {
followingPages[i].clickRate = followingPages[i].referrals / totalClicks * 100;
}
}
/**
* Build an index of links on the page.
* This function is passed to $('a').each()
*/
var processLinkDelta = false;
function processLink() {
var a = $(this);
a[0].piwikDiscovered = true;
var href = a.attr('href');
href = Piwik_Overlay_UrlNormalizer.normalize(href);
if (href) {
if (typeof linksOnPage[href] == 'undefined') {
linksOnPage[href] = [a];
}
else {
linksOnPage[href].push(a);
}
}
if (href && processLinkDelta !== false) {
if (typeof processLinkDelta[href] == 'undefined') {
processLinkDelta[href] = [a];
}
else {
processLinkDelta[href].push(a);
}
}
}
var repositionTimeout = false;
var resizeTimeout = false;
function build(callback) {
// build an index of all links on the page
$('a').each(processLink);
// add tags to known following pages
createLinkTags(linksOnPage);
// position the tags
positionLinkTags();
callback();
// check on a regular basis whether new links have appeared.
// we use a timeout instead of an interval to make sure one call is done before
// the next one is triggered
var repositionAfterTimeout;
repositionAfterTimeout = function () {
repositionTimeout = window.setTimeout(function () {
findNewLinks();
positionLinkTags(repositionAfterTimeout);
}, 1800);
};
repositionAfterTimeout();
// reposition link tags on window resize
$(window).resize(function () {
if (repositionTimeout) {
window.clearTimeout(repositionTimeout);
}
if (resizeTimeout) {
window.clearTimeout(resizeTimeout);
}
resizeTimeout = window.setTimeout(function () {
positionLinkTags();
repositionAfterTimeout();
}, 70);
});
}
/** Create a batch of link tags */
function createLinkTags(links) {
var body = $('body');
for (var i = 0; i < followingPages.length; i++) {
var url = followingPages[i].label;
if (typeof links[url] != 'undefined') {
for (var j = 0; j < links[url].length; j++) {
createLinkTag(links[url][j], url, followingPages[i], body);
}
}
}
}
/** Create the link tag element */
function createLinkTag(linkTag, linkUrl, data, body) {
if (typeof linkTag[0].piwikTagElement != 'undefined' && linkTag[0].piwikTagElement !== null) {
// this link tag already has a tag element. happens in rare cases.
return;
}
linkTag[0].piwikTagElement = true;
var rate = data.clickRate;
if (rate < 10) {
rate = Math.round(rate * 10) / 10;
} else {
rate = Math.round(rate);
}
var span = c('span').html(rate + '%');
var tagElement = c('div', 'LinkTag').append(span).hide();
body.prepend(tagElement);
linkTag.add(tagElement).hover(function () {
highlightLink(linkTag, linkUrl, data);
}, function () {
unHighlightLink(linkTag, linkUrl);
});
// attach the tag element to the link element. we can't use .data() because jquery
// would remove it when removing the link from the dom. but we still need to find
// the tag element to remove it as well.
linkTag[0].piwikTagElement = tagElement;
}
/** Position the link tags next to the links */
function positionLinkTags(callback) {
var url, linkTag, tagElement, offset, top, left, isRight, hasOneChild, inlineChild;
var tagWidth = 36, tagHeight = 21;
var tagsToRemove = [];
for (var i = 0; i < followingPages.length; i++) {
url = followingPages[i].label;
if (typeof linksOnPage[url] != 'undefined') {
for (var j = 0; j < linksOnPage[url].length; j++) {
linkTag = linksOnPage[url][j];
tagElement = linkTag[0].piwikTagElement;
if (linkTag.closest('html').length == 0 || !tagElement) {
// the link has been removed from the dom
if (tagElement) {
tagElement.hide();
}
// mark for deletion. don't delete it now because we
// are iterating of the array it's in. it will be deleted
// below this for loop.
tagsToRemove.push({
index1: url,
index2: j
});
continue;
}
hasOneChild = checkHasOneChild(linkTag);
inlineChild = false;
if (hasOneChild && linkTag.css('display') != 'block') {
inlineChild = linkTag.children().eq(0);
}
if (getVisibility(linkTag) == 'hidden' || (
// in case of hasOneChild: jquery always returns linkTag.is(':visible')=false
!linkTag.is(':visible') && !(hasOneChild && inlineChild && inlineChild.is(':visible'))
)) {
// link is not visible
tagElement.hide();
continue;
}
tagElement.attr('class', 'PIS_LinkTag'); // reset class
if (tagElement[0].piwikHighlighted) {
tagElement.addClass('PIS_Highlighted');
}
// see comment in highlightLink()
if (hasOneChild && linkTag.find('> img').size() == 1) {
offset = linkTag.find('> img').offset();
if (offset.left == 0 && offset.top == 0) {
offset = linkTag.offset();
}
} else if (inlineChild !== false) {
offset = inlineChild.offset();
} else {
offset = linkTag.offset();
}
top = offset.top - tagHeight + 6;
left = offset.left - tagWidth + 10;
if (isRight = (left < 2)) {
tagElement.addClass('PIS_Right');
left = offset.left + linkTag.outerWidth() - 10;
}
if (top < 2) {
tagElement.addClass(isRight ? 'PIS_BottomRight' : 'PIS_Bottom');
top = offset.top + linkTag.outerHeight() - 6;
}
tagElement.css({
top: top + 'px',
left: left + 'px'
}).show();
}
}
}
// walk tagsToRemove from back to front because it contains the indexes in ascending
// order. removing something from the front will impact the indexes that come after-
// wards. this can be avoided by starting in the back.
for (var k = tagsToRemove.length - 1; k >= 0; k--) {
var tagToRemove = tagsToRemove[k];
linkTag = linksOnPage[tagToRemove.index1][tagToRemove.index2];
// remove the tag element from the dom
if (linkTag && linkTag[0] && linkTag[0].piwikTagElement) {
tagElement = linkTag[0].piwikTagElement;
if (tagElement[0].piwikHighlighted) {
unHighlightLink(linkTag, tagToRemove.index1);
}
tagElement.remove();
linkTag[0].piwikTagElement = null;
}
// remove the link from the index
linksOnPage[tagToRemove.index1].splice(tagToRemove.index2, 1);
if (linksOnPage[tagToRemove.index1].length == 0) {
delete linksOnPage[tagToRemove.index1];
}
}
if (typeof callback == 'function') {
callback();
}
}
/** Get the visibility of an element */
function getVisibility(el) {
var visibility = el.css('visibility');
if (visibility == 'inherit') {
el = el.parent();
if (el.size() > 0) {
return getVisibility(el);
}
}
return visibility;
}
/**
* Find out whether a link has only one child. Using .children().size() == 1 doesn't work
* because it doesn't take additional text nodes into account.
*/
function checkHasOneChild(linkTag) {
var hasOneChild = (linkTag.children().size() == 1);
if (hasOneChild) {
// if the element contains one tag and some text, hasOneChild is set incorrectly
var contents = linkTag.contents();
if (contents.size() > 1) {
// find non-empty text nodes
contents = contents.filter(function () {
return this.nodeType == 3 && // text node
$.trim(this.data).length > 0; // contains more than whitespaces
});
if (contents.size() > 0) {
hasOneChild = false;
}
}
}
return hasOneChild;
}
/** Check whether new links have been added to the dom */
function findNewLinks() {
var newLinks = $('a').filter(function () {
return typeof this.piwikDiscovered == 'undefined' || this.piwikDiscovered === null;
});
if (newLinks.size() == 0) {
return;
}
processLinkDelta = {};
newLinks.each(processLink);
createLinkTags(processLinkDelta);
processLinkDelta = false;
}
/** Dom elements used for drawing a box around the link */
var highlightElements = [];
/** Highlight a link on hover */
function highlightLink(linkTag, linkUrl, data) {
if (highlightElements.length == 0) {
highlightElements.push(c('div', 'LinkHighlightBoxTop'));
highlightElements.push(c('div', 'LinkHighlightBoxRight'));
highlightElements.push(c('div', 'LinkHighlightBoxLeft'));
highlightElements.push(c('div', 'LinkHighlightBoxText'));
var body = $('body');
for (var i = 0; i < highlightElements.length; i++) {
body.prepend(highlightElements[i].css({display: 'none'}));
}
}
var width = linkTag.outerWidth();
var offset, height;
var hasOneChild = checkHasOneChild(linkTag);
if (hasOneChild && linkTag.find('img').size() == 1) {
// if the <a> tag contains only an <img>, the offset and height methods don't work properly.
// as a result, the box around the image link would be wrong. we use the image to derive
// the offset and height instead of the link to get correct values.
var img = linkTag.find('img');
offset = img.offset();
height = img.outerHeight();
}
if (hasOneChild && linkTag.css('display') != 'block') {
// if the <a> tag is not displayed as block and has only one child, using the child to
// derive the offset and dimensions is more robust.
var child = linkTag.children().eq(0);
offset = child.offset();
height = child.outerHeight();
width = child.outerWidth();
} else {
offset = linkTag.offset();
height = linkTag.outerHeight();
}
var numLinks = linksOnPage[linkUrl].length;
putBoxAroundLink(offset, width, height, numLinks, data.referrals);
// highlight tags
for (var j = 0; j < numLinks; j++) {
var tag = linksOnPage[linkUrl][j][0].piwikTagElement;
tag.addClass('PIS_Highlighted');
tag[0].piwikHighlighted = true;
}
// Sometimes it fails to remove the notification when the hovered element is removed.
// To make sure we don't display more than one location at a time, we hide all before showing the new one.
Piwik_Overlay_Client.hideNotifications('LinkLocation');
// we don't use .data() because jquery would remove the callback when the link tag is removed
linkTag[0].piwikHideNotification = Piwik_Overlay_Client.notification(
Piwik_Overlay_Translations.get('link') + ': ' + linkUrl, 'LinkLocation');
}
function putBoxAroundLink(offset, width, height, numLinks, numReferrals) {
var borderWidth = 2;
var padding = 4; // the distance between the link and the border
// top border
highlightElements[0]
.width(width + 2 * padding)
.css({
top: offset.top - borderWidth - padding,
left: offset.left - padding
}).show();
// right border
highlightElements[1]
.height(height + 2 * borderWidth + 2 * padding)
.css({
top: offset.top - borderWidth - padding,
left: offset.left + width + padding
}).show();
// left border
highlightElements[2]
.height(height + 2 * borderWidth + 2 * padding)
.css({
top: offset.top - borderWidth - padding,
left: offset.left - borderWidth - padding
}).show();
// bottom box text
var text;
if (numLinks > 1) {
text = Piwik_Overlay_Translations.get('clicksFromXLinks')
.replace(/%1\$s/, numReferrals)
.replace(/%2\$s/, numLinks);
} else if (numReferrals == 1) {
text = Piwik_Overlay_Translations.get('oneClick');
} else {
text = Piwik_Overlay_Translations.get('clicks')
.replace(/%s/, numReferrals);
}
// bottom box position and dimension
var textPadding = '&nbsp;&nbsp;&nbsp;';
highlightElements[3].html(textPadding + text + textPadding).css({
width: 'auto',
top: offset.top + height + padding,
left: offset.left - borderWidth - padding
}).show();
var minBoxWidth = width + 2 * borderWidth + 2 * padding;
if (highlightElements[3].width() < minBoxWidth) {
// we cannot use minWidth because of IE7
highlightElements[3].width(minBoxWidth);
}
}
/** Remove highlight from link */
function unHighlightLink(linkTag, linkUrl) {
for (var i = 0; i < highlightElements.length; i++) {
highlightElements[i].hide();
}
var numLinks = linksOnPage[linkUrl].length;
for (var j = 0; j < numLinks; j++) {
var tag = linksOnPage[linkUrl][j][0].piwikTagElement;
if (tag) {
tag.removeClass('PIS_Highlighted');
tag[0].piwikHighlighted = false;
}
}
if ((typeof linkTag[0].piwikHideNotification) == 'function') {
linkTag[0].piwikHideNotification();
linkTag[0].piwikHideNotification = null;
}
}
return {
/**
* The main method
*/
initialize: function (finishCallback) {
c = Piwik_Overlay_Client.createElement;
Piwik_Overlay_Client.loadScript('plugins/Overlay/client/urlnormalizer.js', function () {
Piwik_Overlay_UrlNormalizer.initialize();
load(function () {
Piwik_Overlay_UrlNormalizer.setExcludedParameters(excludedParams);
build(function () {
finishCallback();
})
});
});
},
/**
* Remove everything from the dom and terminate timeouts.
* This can be used from the console in order to load a new implementation for debugging afterwards.
* If you add `Piwik_Overlay_FollowingPages.remove();` to the beginning and
* `Piwik_Overlay_FollowingPages.initialize(function(){});` to the end of this file, you can just
* paste it into the console to inject the new implementation.
*/
remove: function () {
for (var i = 0; i < followingPages.length; i++) {
var url = followingPages[i].label;
if (typeof linksOnPage[url] != 'undefined') {
for (var j = 0; j < linksOnPage[url].length; j++) {
var linkTag = linksOnPage[url][j];
var tagElement = linkTag[0].piwikTagElement;
if (tagElement) {
tagElement.remove();
}
linkTag[0].piwikTagElement = null;
$(linkTag).unbind('mouseenter').unbind('mouseleave');
}
}
}
for (i = 0; i < highlightElements.length; i++) {
highlightElements[i].remove();
}
if (repositionTimeout) {
window.clearTimeout(repositionTimeout);
}
if (resizeTimeout) {
window.clearTimeout(resizeTimeout);
}
$(window).unbind('resize');
}
};
})();

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

View file

@ -0,0 +1,30 @@
var Piwik_Overlay_Translations = (function () {
/** Translations strings */
var translations = [];
return {
/**
* Initialize translations module.
* Callback is triggered when data is available.
*/
initialize: function (callback) {
// Load translation data
Piwik_Overlay_Client.api('getTranslations', function (data) {
translations = data[0];
callback();
});
},
/** Get translation string */
get: function (identifier) {
if (typeof translations[identifier] == 'undefined') {
return identifier;
}
return translations[identifier];
}
};
})();

View file

@ -0,0 +1,198 @@
/**
* URL NORMALIZER
* This utility preprocesses both the URLs in the document and
* from the Piwik logs in order to make matching possible.
*/
var Piwik_Overlay_UrlNormalizer = (function () {
/** Base href of the current document */
var baseHref = false;
/** Url of current folder */
var currentFolder;
/** The current domain */
var currentDomain;
/** Regular expressions for parameters to be excluded when matching links on the page */
var excludedParamsRegEx = [];
/**
* Basic normalizations for domain names
* - remove protocol and www from absolute urls
* - add a trailing slash to urls without a path
*
* Returns array
* 0: normalized url
* 1: true, if url was absolute (if not, no normalization was performed)
*/
function normalizeDomain(url) {
if (url === null) {
return '';
}
var absolute = false;
// remove protocol
if (url.substring(0, 7) == 'http://') {
absolute = true;
url = url.substring(7, url.length);
} else if (url.substring(0, 8) == 'https://') {
absolute = true;
url = url.substring(8, url.length);
}
if (absolute) {
// remove www.
url = removeWww(url);
// add slash to domain names
if (url.indexOf('/') == -1) {
url += '/';
}
}
return [url, absolute];
}
/** Remove www. from a domain */
function removeWww(domain) {
if (domain.substring(0, 4) == 'www.') {
return domain.substring(4, domain.length);
}
return domain;
}
return {
initialize: function () {
this.setCurrentDomain(document.location.hostname);
this.setCurrentUrl(window.location.href);
var head = document.getElementsByTagName('head');
if (head.length) {
var base = head[0].getElementsByTagName('base');
if (base.length && base[0].href) {
this.setBaseHref(base[0].href);
}
}
},
/**
* Explicitly set domain (for testing)
*/
setCurrentDomain: function (pCurrentDomain) {
currentDomain = removeWww(pCurrentDomain);
},
/**
* Explicitly set current url (for testing)
*/
setCurrentUrl: function (url) {
var index = url.lastIndexOf('/');
if (index != url.length - 1) {
currentFolder = url.substring(0, index + 1);
} else {
currentFolder = url;
}
currentFolder = normalizeDomain(currentFolder)[0];
},
/**
* Explicitly set base href (for testing)
*/
setBaseHref: function (pBaseHref) {
if (!pBaseHref) {
baseHref = false;
} else {
baseHref = normalizeDomain(pBaseHref)[0];
}
},
/**
* Set the parameters to be excluded when matching links on the page
*/
setExcludedParameters: function (pExcludedParams) {
excludedParamsRegEx = [];
for (var i = 0; i < pExcludedParams.length; i++) {
var paramString = pExcludedParams[i];
excludedParamsRegEx.push(new RegExp('&' + paramString + '=([^&#]*)', 'ig'));
}
},
/**
* Remove the protocol and the prefix of a URL
*/
removeUrlPrefix: function (url) {
return normalizeDomain(url)[0];
},
/**
* Normalize URL
* Can be an absolute or a relative URL
*/
normalize: function (url) {
if (!url) {
return '';
}
// ignore urls starting with #
if (url.substring(0, 1) == '#') {
return '';
}
// basic normalizations for absolute urls
var normalized = normalizeDomain(url);
url = normalized[0];
var absolute = normalized[1];
if (!absolute) {
/** relative url */
if (url.substring(0, 1) == '/') {
// relative to domain root
url = currentDomain + url;
} else if (baseHref) {
// relative to base href
url = baseHref + url;
} else {
// relative to current folder
url = currentFolder + url;
}
}
// replace multiple / with a single /
url = url.replace(/\/\/+/g, '/');
// handle ./ and ../
var parts = url.split('/');
var urlArr = [];
for (var i = 0; i < parts.length; i++) {
if (parts[i] == '.') {
// ignore
}
else if (parts[i] == '..') {
urlArr.pop();
}
else {
urlArr.push(parts[i]);
}
}
url = urlArr.join('/');
// remove ignored parameters
url = url.replace(/\?/, '?&');
for (i = 0; i < excludedParamsRegEx.length; i++) {
var regEx = excludedParamsRegEx[i];
url = url.replace(regEx, '');
}
url = url.replace(/\?&/, '?');
url = url.replace(/\?#/, '#');
url = url.replace(/\?$/, '');
return url;
}
};
})();

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

View file

@ -0,0 +1,31 @@
/*!
* Piwik - Web Analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
var Overlay_Helper = {
/** Encode the iframe url to put it behind the hash in sidebar mode */
encodeFrameUrl: function (url) {
// url encode + replace % with $ to make sure that browsers don't break the encoding
return encodeURIComponent(url).replace(/%/g, '$')
},
/** Decode the url after reading it from the hash */
decodeFrameUrl: function (url) {
// reverse encodeFrameUrl()
return decodeURIComponent(url.replace(/\$/g, '%'));
},
/** Get the url to launch overlay */
getOverlayLink: function (idSite, period, date, link) {
var url = 'index.php?module=Overlay&period=' + period + '&date=' + date + '&idSite=' + idSite;
if (link) {
url += '#l=' + Overlay_Helper.encodeFrameUrl(link);
}
return url;
}
};

View file

@ -0,0 +1,252 @@
/*!
* Piwik - Web Analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
var Piwik_Overlay = (function () {
var $body, $iframe, $sidebar, $main, $location, $loading, $errorNotLoading;
var $rowEvolutionLink, $transitionsLink, $fullScreenLink;
var idSite, period, date;
var iframeSrcBase;
var iframeDomain = '';
var iframeCurrentPage = '';
var iframeCurrentPageNormalized = '';
var iframeCurrentActionLabel = '';
var updateComesFromInsideFrame = false;
/** Load the sidebar for a url */
function loadSidebar(currentUrl) {
showLoading();
$location.html('&nbsp;').unbind('mouseenter').unbind('mouseleave');
iframeCurrentPage = currentUrl;
iframeDomain = currentUrl.match(/http(s)?:\/\/(www\.)?([^\/]*)/i)[3];
globalAjaxQueue.abort();
var ajaxRequest = new ajaxHelper();
ajaxRequest.addParams({
module: 'Overlay',
action: 'renderSidebar',
currentUrl: currentUrl
}, 'get');
ajaxRequest.setCallback(
function (response) {
hideLoading();
var $response = $(response);
var $responseLocation = $response.find('.Overlay_Location');
var $url = $responseLocation.find('span');
iframeCurrentPageNormalized = $url.data('normalizedUrl');
iframeCurrentActionLabel = $url.data('label');
$url.html(piwikHelper.addBreakpointsToUrl($url.text()));
$location.html($responseLocation.html()).show();
$responseLocation.remove();
var $locationSpan = $location.find('span');
$locationSpan.html(piwikHelper.addBreakpointsToUrl($locationSpan.text()));
if (iframeDomain) {
// use addBreakpointsToUrl because it also encoded html entities
$locationSpan.tooltip({
track: true,
items: '*',
tooltipClass: 'Overlay_Tooltip',
content: '<strong>' + Piwik_Overlay_Translations.domain + ':</strong> ' +
piwikHelper.addBreakpointsToUrl(iframeDomain),
show: false,
hide: false
});
}
$sidebar.empty().append($response).show();
if ($sidebar.find('.Overlay_NoData').size() == 0) {
$rowEvolutionLink.show();
$transitionsLink.show()
}
}
);
ajaxRequest.setErrorCallback(function () {
hideLoading();
$errorNotLoading.show();
});
ajaxRequest.setFormat('html');
ajaxRequest.send(false);
}
/** Adjust the dimensions of the iframe */
function adjustDimensions() {
$iframe.height($(window).height());
$iframe.width($body.width() - $iframe.offset().left - 2); // -2 because of 2px border
}
/** Display the loading message and hide other containers */
function showLoading() {
$loading.show();
$sidebar.hide();
$location.hide();
$fullScreenLink.hide();
$rowEvolutionLink.hide();
$transitionsLink.hide();
$errorNotLoading.hide();
}
/** Hide the loading message */
function hideLoading() {
$loading.hide();
$fullScreenLink.show();
}
/** $.history callback for hash change */
function hashChangeCallback(urlHash) {
var location = broadcast.getParamValue('l', urlHash);
location = Overlay_Helper.decodeFrameUrl(location);
if (!updateComesFromInsideFrame) {
var iframeUrl = iframeSrcBase;
if (location) {
iframeUrl += '#' + location;
}
$iframe.attr('src', iframeUrl);
showLoading();
} else {
loadSidebar(location);
}
updateComesFromInsideFrame = false;
}
return {
/** This method is called when Overlay loads */
init: function (iframeSrc, pIdSite, pPeriod, pDate) {
iframeSrcBase = iframeSrc;
idSite = pIdSite;
period = pPeriod;
date = pDate;
$body = $('body');
$iframe = $('#Overlay_Iframe');
$sidebar = $('#Overlay_Sidebar');
$location = $('#Overlay_Location');
$main = $('#Overlay_Main');
$loading = $('#Overlay_Loading');
$errorNotLoading = $('#Overlay_Error_NotLoading');
$rowEvolutionLink = $('#Overlay_RowEvolution');
$transitionsLink = $('#Overlay_Transitions');
$fullScreenLink = $('#Overlay_FullScreen');
adjustDimensions();
showLoading();
// apply initial dimensions
window.setTimeout(function () {
adjustDimensions();
}, 50);
// handle window resize
// we manipulate broadcast.pageload because it unbinds all resize events on window
var originalPageload = broadcast.pageload;
broadcast.pageload = function (hash) {
originalPageload(hash);
$(window).resize(function () {
adjustDimensions();
});
};
$(window).resize(function () {
adjustDimensions();
});
// handle hash change
broadcast.loadAjaxContent = hashChangeCallback;
broadcast.init();
if (window.location.href.split('#').length == 1) {
// if there's no hash, broadcast won't trigger the callback - we have to do it here
hashChangeCallback('');
}
// handle date selection
var $select = $('select#Overlay_DateRangeSelect').change(function () {
var parts = $(this).val().split(';');
if (parts.length == 2) {
period = parts[0];
date = parts[1];
window.location.href = Overlay_Helper.getOverlayLink(idSite, period, date, iframeCurrentPage);
}
});
var optionMatchFound = false;
$select.find('option').each(function () {
if ($(this).val() == period + ';' + date) {
$(this).prop('selected', true);
optionMatchFound = true;
}
});
if (!optionMatchFound) {
$select.prepend('<option selected="selected">');
}
// handle transitions link
$transitionsLink.click(function () {
DataTable_RowActions_Transitions.launchForUrl(iframeCurrentPageNormalized);
return false;
});
// handle row evolution link
$rowEvolutionLink.click(function () {
DataTable_RowActions_RowEvolution.launch('Actions.getPageUrls', iframeCurrentActionLabel);
return false;
});
// handle full screen link
$fullScreenLink.click(function () {
var href = iframeSrcBase;
if (iframeCurrentPage) {
href += '#' + iframeCurrentPage.replace(/#/g, '%23');
}
window.location.href = href;
return false;
});
},
/** This callback is used from within the iframe */
setCurrentUrl: function (currentUrl) {
showLoading();
var locationParts = location.href.split('#');
var currentLocation = '';
if (locationParts.length > 1) {
currentLocation = broadcast.getParamValue('l', locationParts[1]);
}
var newLocation = Overlay_Helper.encodeFrameUrl(currentUrl);
if (newLocation != currentLocation) {
updateComesFromInsideFrame = true;
// put the current iframe url in the main url to enable refresh and deep linking.
// use disableHistory=true to make sure that the back and forward buttons can be
// used on the iframe (which in turn notifies the parent about the location change)
broadcast.propagateAjax('l=' + newLocation, true);
} else {
// happens when the url is changed by hand or when the l parameter is there on page load
loadSidebar(currentUrl);
}
}
};
})();

View file

@ -0,0 +1,65 @@
/*!
* Piwik - Web Analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
/**
* This file registers the Overlay row action on the pages report.
*/
function DataTable_RowActions_Overlay(dataTable) {
this.dataTable = dataTable;
}
DataTable_RowActions_Overlay.prototype = new DataTable_RowAction;
DataTable_RowActions_Overlay.prototype.onClick = function (actionA, tr, e) {
if (!actionA.data('overlay-manipulated')) {
actionA.data('overlay-manipulated', 1);
var link = tr.find('> td:first > a').attr('href');
link = $('<textarea>').html(link).val(); // remove html entities
actionA.attr({
target: '_blank',
href: Overlay_Helper.getOverlayLink(this.dataTable.param.idSite, 'month', 'today', link)
});
}
return true;
};
DataTable_RowActions_Registry.register({
name: 'Overlay',
dataTableIcon: 'plugins/Overlay/images/overlay_icon.png',
dataTableIconHover: 'plugins/Overlay/images/overlay_icon_hover.png',
order: 30,
dataTableIconTooltip: [
_pk_translate('General_OverlayRowActionTooltipTitle'),
_pk_translate('General_OverlayRowActionTooltip')
],
createInstance: function (dataTable) {
return new DataTable_RowActions_Overlay(dataTable);
},
isAvailableOnReport: function (dataTableParams) {
// Overlay plugin only works when Transitions plugin is enabled
if (!window.DataTable_RowActions_Transitions) {
return false;
}
return DataTable_RowActions_Transitions.isPageUrlReport(dataTableParams.module, dataTableParams.action);
},
isAvailableOnRow: function (dataTableParams, tr) {
var transitions = DataTable_RowActions_Registry.getActionByName('Transitions');
return transitions.isAvailableOnRow(dataTableParams, tr);
}
});

View file

@ -0,0 +1,159 @@
html {
width: 100%;
height: 100%;
/** hide scroll bar in ie7 */
*overflow: auto;
}
body {
width: 100%;
height: 100%;
overflow: hidden;
}
body #header {
margin-left: -6px;
}
body #logo {
margin-top: 5px;
}
a#Overlay_Title {
font-size: 15px;
font-weight: normal;
color: #7e7363;
text-decoration: none;
margin: -3px 0 0 0;
padding: 0 0 0 5px;
vertical-align: text-bottom;
}
#Overlay_Title img {
vertical-align: text-bottom;
margin-left: 4px;
}
#Overlay_DateRangeSelection {
padding: 30px 0 20px 23px;
background: url(../../Zeitgeist/images/icon-calendar.gif) 2px 33px no-repeat;
margin-left: 5px;
}
#Overlay_Location {
width: 200px;
padding: 0 0 30px 0;
margin-left: 5px;
font-size: 12px;
}
#Overlay_Loading {
background: url(../../Zeitgeist/images/loading-blue.gif) no-repeat center 10px;
width: 190px;
padding-top: 30px;
margin-top: 30px;
text-align: center;
display: none;
}
#Overlay_Sidebar {
width: 200px;
margin-left: 5px;
}
#Overlay_Sidebar h2 {
font-size: 15px;
margin: 0;
padding: 0 0 8px 23px;
color: #255792;
}
a#Overlay_FullScreen,
a#Overlay_RowEvolution,
a#Overlay_Transitions {
display: block;
color: #255792;
font-size: 13px;
line-height: 15px;
margin: 0 0 0 5px;
padding: 8px 0 3px 25px;
text-decoration: none;
}
a#Overlay_RowEvolution {
margin-top: 20px;
background: url(../../Zeitgeist/images/row_evolution_hover.png) no-repeat 0 7px;
}
a#Overlay_Transitions {
background: url(../../Transitions/images/transitions_icon_hover.png) no-repeat 0 6px;
}
a#Overlay_FullScreen {
margin-top: 20px;
background: url(../../Zeitgeist/images/fullscreen.png) no-repeat 3px 8px;
}
a#Overlay_FullScreen:hover,
a#Overlay_RowEvolution:hover,
a#Overlay_Transitions:hover {
color: #E87500;
}
#Overlay_Main {
margin-left: 220px;
position: absolute;
top: 0;
}
#Overlay_Iframe {
border-left: 2px solid #ddd;
}
.Overlay_Metric {
font-size: 12px;
padding-bottom: 4px;
}
.Overlay_MetricValue {
font-size: 14px;
font-weight: bold;
}
.Overlay_NoData {
font-size: 12px;
color: #7E7363;
}
h2.Overlay_MainMetrics {
background: url(../images/info.png) 0 1px no-repeat;
}
body .ui-tooltip.Overlay_Tooltip {
font-size: 11px;
padding: 3px 5px 3px 6px;
}
#Overlay_NoFrame {
padding: 20px 0 40px 2px;
}
#Overlay_Error_NotLoading {
width: 190px;
display: none;
margin: 20px 0 0 5px;
font-size: 14px;
}
#Overlay_Error_NotLoading span {
color: #E87500;
font-weight: bold;
}
#topBars {
display: none;
}
.overlay-sidebar-container {
width: 220px;
}

View file

@ -0,0 +1,17 @@
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: black;
background: white;
margin: 15px;
padding: 0;
}
p {
margin: 0 0 10px 0;
padding: 0;
}
a {
color: #255792;
}

View file

@ -0,0 +1,74 @@
{% extends 'dashboard.twig' %}
{% block head %}
{{ parent() }}
<script type="text/javascript" src="plugins/Overlay/javascripts/Piwik_Overlay.js"></script>
<link rel="stylesheet" type="text/css" href="plugins/Overlay/stylesheets/overlay.css" />
{% endblock %}
{% block content %}
<div class="overlay-sidebar-container">
<a id="Overlay_Title" href="http://piwik.org/docs/page-overlay/" target="_blank">
{{ 'Overlay_Overlay'|translate }}
<img src="plugins/Zeitgeist/images/help.png" alt="Documentation"/>
</a>
<div id="Overlay_DateRangeSelection">
<select id="Overlay_DateRangeSelect" name="Overlay_DateRangeSelect">
<option value="day;today">{{ 'General_Today'|translate }}</option>
<option value="day;yesterday">{{ 'General_Yesterday'|translate }}</option>
<option value="week;today">{{ 'General_CurrentWeek'|translate }}</option>
<option value="month;today">{{ 'General_CurrentMonth'|translate }}</option>
<option value="year;today">{{ 'General_CurrentYear'|translate }}</option>
</select>
</div>
<div id="Overlay_Error_NotLoading">
<p>
<span>{{ 'Overlay_ErrorNotLoading'|translate }}</span>
</p>
<p>
{% if ssl %}
{{ 'Overlay_ErrorNotLoadingDetailsSSL'|translate }}
{% else %}
{{ 'Overlay_ErrorNotLoadingDetails'|translate }}
{% endif %}
</p>
<p>
<a href="http://piwik.org/docs/page-overlay/#toc-page-overlay-troubleshooting" target="_blank">
{{ 'Overlay_ErrorNotLoadingLink'|translate }}
</a>
</p>
</div>
<div id="Overlay_Location">&nbsp;</div>
<div id="Overlay_Loading">{{ 'General_Loading'|translate }}</div>
<div id="Overlay_Sidebar"></div>
<a id="Overlay_RowEvolution">{{ 'General_RowEvolutionRowActionTooltipTitle'|translate }}</a>
<a id="Overlay_Transitions">{{ 'General_TransitionsRowActionTooltipTitle'|translate }}</a>
</div>
<!-- TODO: rethink the way the sidebar works -->
<!-- <a id="Overlay_FullScreen" href="#">
{'Overlay_OpenFullScreen'|translate|escape:'html'}
</a> -->
<div id="Overlay_Main">
<iframe id="Overlay_Iframe" src="" frameborder="0"></iframe>
</div>
<script type="text/javascript">
var iframeSrc = 'index.php?module=Overlay&action=startOverlaySession&idSite={{ idSite }}&period={{ period }}&date={{ date }}';
Piwik_Overlay.init(iframeSrc, '{{ idSite }}', '{{ period }}', '{{ date }}');
Piwik_Overlay_Translations = {
domain: "{{ 'Overlay_Domain'|translate }}"
};
</script>
{% endblock %}

View file

@ -0,0 +1,21 @@
{% extends 'dashboard.twig' %}
{% block content %}
<h1>{{ 'Overlay_Overlay'|translate }}</h1>
<div id="Overlay_NoFrame">
<script type="text/javascript">
var newLocation = 'index.php?module=Overlay&action=startOverlaySession&idSite={{ idSite }}&period={{ period }}&date={{ date }}';
var locationParts = window.location.href.split('#');
if (locationParts.length > 1) {
var url = broadcast.getParamValue('l', locationParts[1]);
url = Overlay_Helper.decodeFrameUrl(url);
newLocation += '#' + url;
}
window.location.href = newLocation;
</script>
</div>
{% endblock %}

View file

@ -0,0 +1,14 @@
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
// go up two iframes to find the piwik window
var piwikWindow = window.parent.parent;
// notify piwik of location change
// the location has been passed as the hash part of the url from the overlay session
piwikWindow.Piwik_Overlay.setCurrentUrl(window.location.hash.substring(1));
</script>
</body>
</html>

View file

@ -0,0 +1,22 @@
<div> <!-- Wrapper is needed that the html can be jqueryfied -->
<!-- This div is removed by JS and the content is put in the location div -->
<div class="Overlay_Location">
<strong>{{ 'Overlay_Location'|translate }}:</strong>
<span data-normalized-url="{{ normalizedUrl }}" data-label="{{ label }}">
{{ location }}
</span>
</div>
{% if data|length > 0 %}
<h2 class="Overlay_MainMetrics">{{ 'General_MainMetrics'|translate }}</h2>
{% for metric in data %}
<div class="Overlay_Metric">
<span class="Overlay_MetricValue">{{ metric.value|raw }}</span> {{ metric.name }}
</div>
{% endfor %}
{% else %}
<!-- note: the class Overlay_NoData is used in Piwik_Overlay.js -->
<div class="Overlay_NoData">{{ 'Overlay_NoData'|translate }}</div>
{% endif %}
</div>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="generator" content="Piwik - Open Source Web Analytics"/>
<link rel="shortcut icon" href="plugins/CoreHome/images/favicon.ico"/>
<link rel="stylesheet" type="text/css" href="plugins/Overlay/stylesheets/showErrorWrongDomain.css" />
</head>
<body>
<p><strong>{{ message|raw }}</strong></p>
<p>{{ troubleshoot|raw }}</p>
</body>
</html>