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

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattpiwik <matthieu.aubry@gmail.com>2008-07-28 03:32:54 +0400
committermattpiwik <matthieu.aubry@gmail.com>2008-07-28 03:32:54 +0400
commit995c69fefeb52d289e3613e552ce11d204826d8e (patch)
treeab59bac1803b272272ca9d16ae69b65fd44a25ba
parent9bcf3f24892e3ce52e0ce9cb4c38465b9084059c (diff)
- end of previous commit. For some reasons Tortoise didn't see these files, bad!
git-svn-id: http://dev.piwik.org/svn/trunk@582 59fd770c-687e-43c8-a1e3-f5a4ff64c105
-rw-r--r--plugins/CoreAdminHome/Controller.php66
-rw-r--r--plugins/CoreAdminHome/CoreAdminHome.php27
-rw-r--r--plugins/CoreAdminHome/templates/index.tpl53
-rw-r--r--plugins/CoreAdminHome/templates/menu.css37
-rw-r--r--plugins/CoreAdminHome/templates/menu.tpl5
-rw-r--r--plugins/CoreHome/Controller.php134
-rw-r--r--plugins/CoreHome/CoreHome.php26
-rw-r--r--plugins/CoreHome/templates/calendar.js172
-rw-r--r--plugins/CoreHome/templates/cloud.tpl68
-rw-r--r--plugins/CoreHome/templates/datatable.css339
-rw-r--r--plugins/CoreHome/templates/datatable.js988
-rw-r--r--plugins/CoreHome/templates/datatable.tpl40
-rw-r--r--plugins/CoreHome/templates/datatable_actions.tpl40
-rw-r--r--plugins/CoreHome/templates/datatable_actions_js.tpl12
-rw-r--r--plugins/CoreHome/templates/datatable_actions_recursive.tpl44
-rw-r--r--plugins/CoreHome/templates/datatable_actions_subdatable.tpl19
-rw-r--r--plugins/CoreHome/templates/datatable_footer.tpl36
-rw-r--r--plugins/CoreHome/templates/datatable_js.tpl12
-rw-r--r--plugins/CoreHome/templates/date.js89
-rw-r--r--plugins/CoreHome/templates/graph.tpl16
-rw-r--r--plugins/CoreHome/templates/header.tpl8
-rw-r--r--plugins/CoreHome/templates/images/bg_header.jpgbin0 -> 9097 bytes
-rw-r--r--plugins/CoreHome/templates/images/bullet1.gifbin0 -> 47 bytes
-rw-r--r--plugins/CoreHome/templates/images/bullet2.gifbin0 -> 55 bytes
-rw-r--r--plugins/CoreHome/templates/images/more.pngbin0 -> 1045 bytes
-rw-r--r--plugins/CoreHome/templates/images/more_date.gifbin0 -> 56 bytes
-rw-r--r--plugins/CoreHome/templates/images/more_period.gifbin0 -> 53 bytes
-rw-r--r--plugins/CoreHome/templates/images/reset_search.pngbin0 -> 1021 bytes
-rw-r--r--plugins/CoreHome/templates/images/search.pngbin0 -> 136 bytes
-rw-r--r--plugins/CoreHome/templates/index.tpl77
-rw-r--r--plugins/CoreHome/templates/logo.tpl14
-rw-r--r--plugins/CoreHome/templates/menu.css111
-rw-r--r--plugins/CoreHome/templates/menu.js126
-rw-r--r--plugins/CoreHome/templates/menu.tpl16
-rw-r--r--plugins/CoreHome/templates/period_select.tpl13
-rw-r--r--plugins/CoreHome/templates/piwik_tag.tpl19
-rw-r--r--plugins/CoreHome/templates/sites_select.tpl0
-rw-r--r--plugins/CoreHome/templates/sparkline.js59
-rw-r--r--plugins/CoreHome/templates/style.css258
-rw-r--r--plugins/CoreHome/templates/top_bar.tpl31
-rw-r--r--plugins/CorePluginsAdmin/Controller.php65
-rw-r--r--plugins/CorePluginsAdmin/CorePluginsAdmin.php32
-rw-r--r--plugins/CorePluginsAdmin/templates/manage.tpl135
43 files changed, 3187 insertions, 0 deletions
diff --git a/plugins/CoreAdminHome/Controller.php b/plugins/CoreAdminHome/Controller.php
new file mode 100644
index 0000000000..9867b324ad
--- /dev/null
+++ b/plugins/CoreAdminHome/Controller.php
@@ -0,0 +1,66 @@
+<?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
+ *
+ * @package Piwik_CoreAdminHome
+ *
+ */
+
+require_once "API/Request.php";
+
+
+/**
+ *
+ * @package Piwik_CoreAdminHome
+ */
+class Piwik_CoreAdminHome_Controller extends Piwik_Controller
+{
+ function getDefaultAction()
+ {
+ return 'redirectToIndex';
+ }
+ function redirectToIndex()
+ {
+ header("Location:index.php?module=CoreAdminHome&action=showInContext&moduleToLoad=CorePluginsAdmin");
+ }
+
+ public function showInContext()
+ {
+ $controllerName = Piwik_Common::getRequestVar('moduleToLoad');
+ $actionName = Piwik_Common::getRequestVar('actionToLoad', 'index');
+
+ $view = $this->getDefaultIndexView();
+ $view->basicHtmlView = true;
+ $view->content = Piwik_FrontController::getInstance()->fetchDispatch( $controllerName, $actionName );
+ echo $view->render();
+ }
+
+ public function index()
+ {
+ Piwik::checkUserIsSuperUser();
+
+ $view = $this->getDefaultIndexView();
+ echo $view->render();
+ }
+
+ protected function getDefaultIndexView()
+ {
+ $view = new Piwik_View('CoreAdminHome/templates/index.tpl');
+ $view->menu = Piwik_GetAdminMenu();
+ $view->menuJson = json_encode($view->menu);
+
+ $view->userLogin = Piwik::getCurrentUserLogin();
+ $view->token_auth = Piwik::getCurrentUserTokenAuth();
+ $view->sites = Piwik_SitesManager_API::getSitesWithAtLeastViewAccess();
+ $view->url = Piwik_Url::getCurrentUrl();
+
+ $view->basicHtmlView = false;
+ $view->content = '';
+ return $view;
+ }
+}
+
diff --git a/plugins/CoreAdminHome/CoreAdminHome.php b/plugins/CoreAdminHome/CoreAdminHome.php
new file mode 100644
index 0000000000..04fa9d7796
--- /dev/null
+++ b/plugins/CoreAdminHome/CoreAdminHome.php
@@ -0,0 +1,27 @@
+<?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: ExamplePlugin.php 169 2008-01-14 05:41:15Z matt $
+ *
+ * @package Piwik_CoreAdminHome
+ */
+
+
+class Piwik_CoreAdminHome extends Piwik_Plugin
+{
+ public function getInformation()
+ {
+ return array(
+ // name must be the className prefix!
+ 'name' => 'CoreAdminHome',
+ 'description' => 'Administration area of Piwik.',
+ 'author' => 'Piwik',
+ 'homepage' => 'http://piwik.org/',
+ 'version' => '0.1',
+ );
+ }
+}
+
diff --git a/plugins/CoreAdminHome/templates/index.tpl b/plugins/CoreAdminHome/templates/index.tpl
new file mode 100644
index 0000000000..6a13043af7
--- /dev/null
+++ b/plugins/CoreAdminHome/templates/index.tpl
@@ -0,0 +1,53 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+{literal}
+<style>
+#h1, #h1 a {
+ color: #136F8B;
+ font-size: 45px;
+ font-weight: lighter;
+ text-decoration : none;
+ margin:5px;
+}
+
+#subh1 {
+ color: #879dbd;
+ font-size: 25px;
+ font-weight: lighter;
+}
+</style>
+{/literal}
+
+<script type="text/javascript">
+var piwik_token_auth = "{$token_auth}";
+</script>
+
+<script type="text/javascript" src="libs/jquery/jquery.js"></script>
+<script type="text/javascript" src="themes/default/common.js"></script>
+
+<link rel="stylesheet" type="text/css" href="plugins/CoreAdminHome/templates/menu.css">
+<link rel="stylesheet" href="themes/default/common-admin.css">
+
+</head>
+<body>
+<span id="h1">Piwik admin</span> &nbsp;
+<span><a href='index.php'>Back to Piwik</a></span>
+<br /><br />
+
+<div id="menu">
+{include file="CoreAdminHome/templates/menu.tpl"}
+</div>
+
+<div style="clear:both;">
+</div>
+
+<div id='content'>
+{if $content}{$content}{/if}
+</div>
+
+<div id="footer" style="border-top:1px solid gray; margin-top:20px;padding-top:10px;">
+<a href='?module=CoreHome'>{'General_BackToHomepage'|translate}</a>
+
+</div>
diff --git a/plugins/CoreAdminHome/templates/menu.css b/plugins/CoreAdminHome/templates/menu.css
new file mode 100644
index 0000000000..312ba8a436
--- /dev/null
+++ b/plugins/CoreAdminHome/templates/menu.css
@@ -0,0 +1,37 @@
+#tablist {
+ padding: 3px 0;
+ margin-left: 0;
+ margin-bottom: 0;
+ margin-top: 0.1em;
+ border-bottom: 1px solid gray;
+}
+
+#tablist li {
+ list-style: none;
+ display: inline;
+ margin: 0;
+}
+
+#tablist li a {
+ text-decoration: none;
+ padding: 3px 0.5em;
+ margin-right: 3px;
+ border: 1px solid #778;
+ border-bottom: none;
+ background: white;
+ font: bold 16px Georgia;
+}
+
+#tablist li a:link,#tablist li a:visited {
+ color: black;
+}
+
+#tablist li a:hover {
+ color: black;
+ background: #defdbb;
+ border-color: black;
+}
+
+#tablist li a.current {
+ background: #defdbb;
+} \ No newline at end of file
diff --git a/plugins/CoreAdminHome/templates/menu.tpl b/plugins/CoreAdminHome/templates/menu.tpl
new file mode 100644
index 0000000000..0922c2e05b
--- /dev/null
+++ b/plugins/CoreAdminHome/templates/menu.tpl
@@ -0,0 +1,5 @@
+<ul id="tablist">
+{foreach from=$menu key=name item=url name=menu}
+ <li><a name='{$url|@urlRewriteAdminView}' href='{$url|@urlRewriteAdminView}'>{$name}</a></li>
+{/foreach}
+</ul>
diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php
new file mode 100644
index 0000000000..88c992e9e5
--- /dev/null
+++ b/plugins/CoreHome/Controller.php
@@ -0,0 +1,134 @@
+<?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: Controller.php 561 2008-07-21 00:00:35Z matt $
+ *
+ * @package Piwik_CoreHome
+ *
+ */
+
+
+require_once "API/Request.php";
+require_once "ViewDataTable.php";
+
+/**
+ *
+ * @package Piwik_CoreHome
+ */
+class Piwik_CoreHome_Controller extends Piwik_Controller
+{
+ function getDefaultAction()
+ {
+ return 'redirectToIndex';
+ }
+ function redirectToIndex()
+ {
+ $sitesId = Piwik_SitesManager_API::getSitesIdWithAtLeastViewAccess();
+ if(!empty($sitesId))
+ {
+ $firstSiteId = $sitesId[0];
+ $firstSite = new Piwik_Site($firstSiteId);
+ if ($firstSite->getCreationDate()->isToday())
+ {
+ $defaultDate = 'today';
+ }
+ else
+ {
+ $defaultDate = Zend_Registry::get('config')->General->default_day;
+ }
+ header("Location:index.php?module=CoreHome&action=index&idSite=$firstSiteId&period=day&date=$defaultDate");
+ }
+ else
+ {
+ if(($currentLogin = Piwik::getCurrentUserLogin()) != 'anonymous')
+ {
+ Piwik_ExitWithMessage( sprintf(Piwik_Translate('CoreHome_NoPrivileges'),$currentLogin).
+ "<br /><br />&nbsp;&nbsp;&nbsp;<b><a href='?module=Login&amp;action=logout'>&rsaquo; ".Piwik_Translate('General_Logout')."</a></b><br />");
+ }
+ else
+ {
+ Piwik_FrontController::dispatch('Login');
+ }
+ }
+ exit;
+ }
+
+ protected function setGeneralVariablesView($view)
+ {
+ // date
+ $view->date = $this->strDate;
+ $oDate = Piwik_Date::factory($this->strDate);
+ $localizedDateFormat = Piwik_Translate('CoreHome_LocalizedDateFormat');
+ $view->prettyDate = $oDate->getLocalized($localizedDateFormat);
+
+ // period
+ $currentPeriod = Piwik_Common::getRequestVar('period');
+ $otherPeriodsAvailable = array('day', 'week', 'month', 'year');
+
+ $otherPeriodsNames = array(
+ 'day' => Piwik_Translate('CoreHome_PeriodDay'),
+ 'week' => Piwik_Translate('CoreHome_PeriodWeek'),
+ 'month' => Piwik_Translate('CoreHome_PeriodMonth'),
+ 'year' => Piwik_Translate('CoreHome_PeriodYear')
+ );
+
+ $found = array_search($currentPeriod,$otherPeriodsAvailable);
+ if($found !== false)
+ {
+ unset($otherPeriodsAvailable[$found]);
+ }
+
+ $view->period = $currentPeriod;
+ $view->otherPeriods = $otherPeriodsAvailable;
+ $view->periodsNames = $otherPeriodsNames;
+
+ // other
+ $view->idSite = Piwik_Common::getRequestVar('idSite');
+
+ $view->userLogin = Piwik::getCurrentUserLogin();
+ $view->sites = Piwik_SitesManager_API::getSitesWithAtLeastViewAccess();
+ $view->url = Piwik_Url::getCurrentUrl();
+
+ $view->menu = Piwik_GetMenu();
+ $view->menuJson = json_encode($view->menu);
+ //var_dump($view->menuJson);
+ }
+
+ public function showInContext()
+ {
+ $controllerName = Piwik_Common::getRequestVar('moduleToLoad');
+ $actionName = Piwik_Common::getRequestVar('actionToLoad', 'index');
+
+ $view = $this->getDefaultIndexView();
+ $view->basicHtmlView = true;
+ $view->content = Piwik_FrontController::getInstance()->fetchDispatch( $controllerName, $actionName );
+ echo $view->render();
+ }
+
+ protected function getDefaultIndexView()
+ {
+
+ $view = new Piwik_View('CoreHome/templates/index.tpl');
+ $this->setGeneralVariablesView($view);
+
+ $site = new Piwik_Site($view->idSite);
+ $minDate = $site->getCreationDate();
+
+ $view->minDateYear = $minDate->toString('Y');
+ $view->minDateMonth = $minDate->toString('m');
+ $view->minDateDay = $minDate->toString('d');
+
+ $view->basicHtmlView = false;
+ $view->content = '';
+ return $view;
+ }
+ public function index()
+ {
+ $view = $this->getDefaultIndexView();
+ echo $view->render();
+ }
+}
+
diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php
new file mode 100644
index 0000000000..37891b5e3c
--- /dev/null
+++ b/plugins/CoreHome/CoreHome.php
@@ -0,0 +1,26 @@
+<?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: ExamplePlugin.php 169 2008-01-14 05:41:15Z matt $
+ *
+ * @package Piwik_CorePluginsAdmin
+ */
+
+class Piwik_CoreHome extends Piwik_Plugin
+{
+ public function getInformation()
+ {
+ return array(
+ // name must be the className prefix!
+ 'name' => 'CoreHome',
+ 'description' => 'Web Analytics Reports Structure.',
+ 'author' => 'Piwik',
+ 'homepage' => 'http://piwik.org/',
+ 'version' => '0.1',
+ );
+ }
+}
+
diff --git a/plugins/CoreHome/templates/calendar.js b/plugins/CoreHome/templates/calendar.js
new file mode 100644
index 0000000000..a52f856063
--- /dev/null
+++ b/plugins/CoreHome/templates/calendar.js
@@ -0,0 +1,172 @@
+
+Date.prototype.getWeek = function() {
+var onejan = new Date(this.getFullYear(),0,1);
+return Math.ceil((((this - onejan) / 86400000) + onejan.getDay())/7);
+}
+
+var splitDate = currentDateStr.split("-");
+
+var currentYear = splitDate[0];
+var currentMonth = splitDate[1] - 1;
+var currentDay = splitDate[2];
+
+var currentDate = new Date(currentYear, currentMonth, currentDay);
+var todayDate = new Date;
+var todayMonth = todayDate.getMonth();
+var todayYear = todayDate.getFullYear();
+var todayDay = todayDate.getDate();
+
+function isDateSelected( date )
+{
+ var valid = false;
+
+ var dateMonth = date.getMonth();
+ var dateYear = date.getFullYear();
+ var dateDay = date.getDate();
+ var style = '';
+
+ if( date.toLocaleDateString() == todayDate.toLocaleDateString())
+ {
+ style = style + 'dateToday ';
+ }
+
+ // we dont color dates in the future
+ if( dateMonth == todayMonth
+ && dateYear == todayYear
+ && dateDay >= todayDay
+ )
+ {
+ return [true, style];
+ }
+
+ // we dont color dates before the minimum date
+ if( dateYear < minDateYear
+ || ( dateYear == minDateYear
+ &&
+ (
+ (dateMonth == minDateMonth - 1
+ && dateDay < minDateDay)
+ || (dateMonth < minDateMonth - 1)
+ )
+ )
+ )
+ {
+ return [true, style];
+ }
+
+ // we color all day of the month for the same year for the month period
+ if(period == "month"
+ && dateMonth == currentMonth
+ && dateYear == currentYear
+ )
+ {
+ valid = true;
+ }
+ // we color all day of the year for the year period
+ else if(period == "year"
+ && dateYear == currentYear
+ )
+ {
+ valid = true;
+ }
+ else if(period == "week"
+ && date.getWeek() == currentDate.getWeek()
+ && dateYear == currentYear
+ )
+ {
+ valid = true;
+ }
+ else if( period == "day"
+ && dateDay == currentDay
+ && dateMonth == currentMonth
+ && dateYear == currentYear
+ )
+ {
+ valid = true;
+ }
+
+ if(valid)
+ {
+ return [true, style+'dateUsedStats'];
+ }
+ return [true, style];
+}
+
+
+function updateDate()
+{
+ var date = formatDate(popUpCal.getDateFor($('#calendar')[0]));
+
+ // available in global scope
+ var currentUrl = window.location.href;
+ if((startStrDate = currentUrl.indexOf("date")) >= 0)
+ {
+ // look for the & after the date
+ var endStrDate = currentUrl.indexOf("&", startStrDate);
+ if(endStrDate == -1)
+ {
+ endStrDate = currentUrl.length;
+ }
+
+ var dateToReplace = currentUrl.substring(
+ startStrDate + 4+1,
+ endStrDate
+ );
+ regDateToReplace = new RegExp(dateToReplace, 'ig');
+ currentUrl = currentUrl.replace( regDateToReplace, date );
+ }
+ else
+ {
+ currentUrl = currentUrl + '&date=' + date;
+ }
+
+ window.location.href = currentUrl;
+}
+
+function formatDate(date)
+{
+ var day = date.getDate();
+ var month = date.getMonth() + 1;
+ return date.getFullYear() + '-'
+ + (month < 10 ? '0' : '') + month + '-'
+ + (day < 10 ? '0' : '') + day ;
+}
+
+$(document).ready(function(){
+ $("#calendar").calendar({
+ onSelect: updateDate,
+ showOtherMonths: true,
+ dateFormat: 'DMY-',
+ firstDay: 1,
+ minDate: new Date(minDateYear, minDateMonth - 1, minDateDay),
+ maxDate: new Date(),
+ changeFirstDay: false,
+ prevText: "",
+ nextText: "",
+ currentText: "",
+ customDate: isDateSelected,
+ dayNames: [
+ _pk_translate('CoreHome_DaySu'),
+ _pk_translate('CoreHome_DayMo'),
+ _pk_translate('CoreHome_DayTu'),
+ _pk_translate('CoreHome_DayWe'),
+ _pk_translate('CoreHome_DayTh'),
+ _pk_translate('CoreHome_DayFr'),
+ _pk_translate('CoreHome_DaySa')],
+ monthNames: [
+ _pk_translate('CoreHome_MonthJanuary'),
+ _pk_translate('CoreHome_MonthFebruary'),
+ _pk_translate('CoreHome_MonthMarch'),
+ _pk_translate('CoreHome_MonthApril'),
+ _pk_translate('CoreHome_MonthMay'),
+ _pk_translate('CoreHome_MonthJune'),
+ _pk_translate('CoreHome_MonthJuly'),
+ _pk_translate('CoreHome_MonthAugust'),
+ _pk_translate('CoreHome_MonthSeptember'),
+ _pk_translate('CoreHome_MonthOctober'),
+ _pk_translate('CoreHome_MonthNovember'),
+ _pk_translate('CoreHome_MonthDecemeber')]
+ },
+ currentDate);
+ }
+);
diff --git a/plugins/CoreHome/templates/cloud.tpl b/plugins/CoreHome/templates/cloud.tpl
new file mode 100644
index 0000000000..91b3913819
--- /dev/null
+++ b/plugins/CoreHome/templates/cloud.tpl
@@ -0,0 +1,68 @@
+<div id="{$id}" class="parentDiv">
+{literal}
+<style>
+
+#tagCloud{
+ width:100%;
+}
+img {
+ border:0;
+}
+.word a {
+ text-decoration:none;
+}
+.word {
+ padding: 4px 4px 4px 4px;
+}
+.valueIsZero {
+ text-decoration: line-through;
+}
+span.size0, span.size0 a {
+ color: #344971;
+ font-size: 28px;
+}
+span.size1, span.size1 a {
+ color: #344971;
+ font-size: 24px;
+}
+span.size2, span.size2 a {
+ color: #4B74AD;
+ font-size:20px;
+}
+span.size3, span.size3 a {
+ color: #A3A8B6;
+ font-size: 16px;
+}
+span.size4, span.size4 a {
+ color: #A3A8B6;
+ font-size: 15px;
+}
+span.size5, span.size5 a {
+ color: #A3A8B6;
+ font-size: 14px;
+}
+span.size6, span.size6 a {
+ color: #A3A8B6;
+ font-size: 11px;
+}
+</style>
+{/literal}
+
+<div id="tagCloud">
+{if count($cloudValues) == 0}
+ <div id="emptyDatatable">No data for this tag cloud.</div>
+{else}
+ {foreach from=$cloudValues key=word item=value}
+ <span title="{$value.word} ({$labelMetadata[$value.word].hits} hits)" class="word size{$value.size} {* we strike tags with 0 hits *} {if $labelMetadata[$value.word].hits == 0}valueIsZero{/if}">
+ {if false !== $labelMetadata[$value.word].url}<a href="{$labelMetadata[$value.word].url}" target="_blank">{/if}
+ {if false !== $labelMetadata[$value.word].logo}<img src="{$labelMetadata[$value.word].logo}" width="{$value.logoWidth}">{else}
+
+ {$value.wordTruncated}{/if}{if false !== $labelMetadata[$value.word].url}</a>{/if}</span>
+ {/foreach}
+{/if}
+{if $showFooter}
+ {include file="CoreHome/templates/datatable_footer.tpl"}
+{/if}
+{include file="CoreHome/templates/datatable_js.tpl"}
+</div>
+</div>
diff --git a/plugins/CoreHome/templates/datatable.css b/plugins/CoreHome/templates/datatable.css
new file mode 100644
index 0000000000..bfd266b599
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable.css
@@ -0,0 +1,339 @@
+/* container of each table */
+.parentDiv {
+ width: 450px;
+ /* not more than 450px to make sure 2 of them can fit horizontally on a 1024 screen */
+}
+
+.parentDivActions {
+ width: 500px;
+}
+
+.parentDivGraph {
+ width: 500px;
+}
+
+.parentDivGraphEvolution {
+ width: 100%;
+}
+
+/* main data table */
+table.dataTable {
+ width: 100%;
+ padding: 0;
+ border-spacing: 0;
+ margin: 0;
+ font-size: 0.9em;
+}
+
+table.dataTable td.label,table.subDataTable td.label,table.dataTableActions td.label
+ {
+ width: 100%;
+}
+
+table.dataTable img,table.subDataTable img,table.dataTableActions img {
+ vertical-align: middle;
+}
+
+table.dataTable img {
+ border: 0;
+ margin-right: 1em;
+ margin-left: 0.5em;
+}
+
+table.dataTable tr.subDataTable {
+ cursor: pointer;
+}
+
+table.dataTable th {
+ margin: 0;
+ color: #6D929B;
+ border-right: 1px solid #C1DAD7;
+ border-bottom: 1px solid #C1DAD7;
+ border-top: 1px solid #C1DAD7;
+ text-transform: capitalize;
+ text-align: left;
+ padding: 6px 6px 6px 12px;
+ background: #D4E3ED url(images/bg_header.jpg) no-repeat;
+}
+
+table.dataTable th.columnSorted {
+ font-weight: bold;
+ padding-right: 20px;
+}
+
+table.dataTable td {
+ border-right: 1px solid #C1DAD7;
+ border-bottom: 1px solid #C1DAD7;
+ border-left: 0;
+ padding: 5px 5px 5px 12px;
+ background: #fff;
+}
+
+table.dataTable td,table.dataTable td a {
+ margin: 0;
+ text-decoration: none;
+ color: #4f6b72;
+}
+
+table.dataTable td.labeleven,table.dataTable td.columneven {
+ background: #F9FAFA;
+}
+
+table.dataTable td.columneven {
+ color: #797268;
+}
+
+table.dataTable td.labeleven {
+ background-image: url(images/bullet2.gif);
+ background-repeat: no-repeat;
+ color: #797268;
+}
+
+table.dataTable td.labelodd {
+ background: #fff url(images/bullet1.gif) no-repeat;
+}
+
+table.dataTable td.label,table.subActionsDataTable td.label,table.actionsDataTable td.label
+ {
+ border-top: 0;
+ border-left: 1px solid #C1DAD7;
+}
+
+table.dataTable th.label {
+ border-left: 1px solid #C1DAD7;
+}
+
+/* the cell containing the subdatatable */
+table.dataTable .cellSubDataTable {
+ border-left: 1px solid #C1DAD7;
+ padding: 0;
+ margin: 0;
+}
+
+/* A link in a column in the DataTable */
+table.dataTable td #urlLink {
+ display: none;
+}
+
+/* SUBDATATABLE */ /* a datatable inside another datatable */
+table.subDataTable {
+ background: #FFFFFF;
+ width: 95%;
+ border-top: 1px solid #e5eff8;
+ border-right: 1px solid #e5eff8;
+ margin: 10px;
+}
+
+table.subDataTable td {
+ border: 0;
+}
+
+table.subDataTable thead th {
+ font-weight: normal;
+ font-size: 1.1em;
+ text-align: left;
+ border: 0;
+ border: 1px solid #D1D1D1;
+ padding: .3em 1em;
+ color: #333333;
+ background: #FFE9C6;
+}
+
+table.subDataTable td.labeleven,table.subDataTable td.labelodd {
+ background-image: none;
+}
+
+table.subDataTable td {
+ border-bottom: 1px solid #E5E5E5;
+ border-left: 1px solid #E5E5E5;
+}
+
+table.subDataTable td,table.subDataTable td a {
+ padding: 0.3em 1em;
+ color: #615B53;
+}
+
+table.subDataTable td.labeleven,table.subDataTable td.columneven {
+ color: #2D2A27;
+}
+
+table.subDataTable td.label {
+ width: 80%;
+}
+
+table.subDataTable td.labelodd,table.subDataTable td.labelodd a {
+ background: #ffffff;
+}
+
+/* misc SPAN and DIV */
+table thead div {
+
+}
+
+#sortIconContainer {
+ float: right;
+}
+
+#sortIcon {
+ margin: 0px;
+ position: absolute;
+}
+
+#dataTablePages {
+ color: #E1E1E1;
+ font-weight: bold;
+ margin: 10px;
+ font-size: 0.9em;
+}
+
+#dataTableSearchPattern {
+ display: inline;
+ white-space: nowrap;
+}
+
+#dataTableSearchPattern input {
+ font-size: 0.7em;
+ padding: 2px;
+ border: 1px solid #B3B3B3;
+ color: #0C183A;
+}
+
+#dataTableSearchPattern input:hover {
+ background: #F7F7FF none repeat scroll 0%;
+}
+
+#dataTableSearchPattern #keyword {
+ background: transparent url(images/search.png) no-repeat scroll 4px
+ center;
+ padding: 3px 3px 3px 20px;
+}
+
+#dataTableExcludeLowPopulation,#dataTableNext,#dataTablePrevious {
+ font-size: 0.9em;
+ color: #184A83;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
+.subDataTable#dataTableFeatures {
+ padding-top: 0px;
+ padding-bottom: 5px;
+ width: 100%;
+}
+
+#dataTableFeatures {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ width: 100%;
+ text-align: center;
+}
+
+#dataTableExcludeLowPopulation {
+ float: right;
+ font-size: 0.8em;
+ color: #C3C6D8;
+ text-align: right;
+}
+
+#dataTableNext,#dataTablePrevious,#dataTableSearchPattern,#loadingDataTable
+ {
+ display: none;
+}
+
+.subDataTable #exportDataTable {
+ height: 0px;
+}
+
+#exportDataTable {
+ float: right;
+ height: 18px;
+}
+
+#exportToFormat {
+ float: right;
+}
+
+#exportDataTableShow {
+ float: right;
+}
+
+#exportDataTable,#exportDataTable a {
+ text-decoration: none;
+ color: #8894B1;
+}
+
+.dataTableSpacer {
+ clear: both;
+}
+
+#loadingDataTable {
+ float: left;
+ font-size: 1em;
+ color: #193B6C;
+ padding: 0.5em;
+}
+
+#tooltip {
+ position: absolute;
+ z-index: 3000;
+ border: 1px solid #111;
+ background-color: #eee;
+ padding-left: 5px;
+ padding-right: 5px;
+ opacity: 0.85;
+ font-size: 0.7em;
+}
+
+/* Actions table */
+table.dataTableActions tr td.labelodd {
+ background-image: none;
+}
+
+/* levels higher than 4 have a default padding left */
+tr.subActionsDataTable td.label,tr.actionsDataTable td.label {
+ padding-left: 7em;
+}
+
+tr.level0 td.label {
+ padding-left: +1.5em;
+}
+
+tr.level1 td.label {
+ padding-left: +3.5em;
+}
+
+tr.level2 td.label {
+ padding-left: +5.5em;
+}
+
+tr.level3 td.label {
+ padding-left: +6.5em;
+}
+
+tr.level4 td.label {
+ padding-left: +7em;
+}
+
+tr td.label img.plusMinus {
+ margin-left: -1em;
+ margin-right: 0em;
+}
+
+/* graph form containing embed code */
+.formEmbedCode,.formEmbedCode input,.formEmbedCode a {
+ font-size: 11px;
+ text-decoration: none;
+}
+
+.formEmbedCode input {
+ background-color: #FBFDFF;
+ border: 1px solid #ECECEC;
+}
+
+#emptyDatatable {
+ padding-top: 20px;
+ padding-bottom: 10px;
+ text-align: center;
+ font-size: 0.9em;
+ font-style: italic;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/templates/datatable.js b/plugins/CoreHome/templates/datatable.js
new file mode 100644
index 0000000000..3fd9fe85db
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable.js
@@ -0,0 +1,988 @@
+//-----------------------------------------------------------------------------
+// Data Table
+//-----------------------------------------------------------------------------
+//A list of all our DataTables
+//Test if the object have already been initialized (multiple includes)
+if(typeof dataTables == "undefined")
+ var dataTables = new Object;
+
+//DataTable constructor
+function dataTable()
+{
+ this.param = new Object;
+}
+
+//Prototype of the DataTable object
+dataTable.prototype =
+{
+ //initialisation function
+ init: function(workingDivId, domElem)
+ {
+ if(typeof domElem == "undefined")
+ {
+ domElem = $('#'+workingDivId);
+ }
+
+ this.workingDivId = workingDivId;
+ this.loadedSubDataTable = new Object;
+ this.bindEventsAndApplyStyle(domElem);
+ this.initialized = true;
+ },
+
+ //function triggered when user click on column sort
+ onClickSort: function(domElem)
+ {
+ var self = this;
+
+ var newColumnToSort = $(domElem).attr('id');
+ // we lookup if the column to sort was already this one, if it is the case then we switch from desc <-> asc
+ if(self.param.filter_sort_column == newColumnToSort)
+ {
+ // toggle the sorted order
+ if(this.param.filter_sort_order == 'asc')
+ {
+ self.param.filter_sort_order = 'desc';
+ }
+ else
+ {
+ self.param.filter_sort_order = 'asc';
+ }
+ }
+ self.param.filter_offset = 0;
+ self.param.filter_sort_column = newColumnToSort;
+ self.reloadAjaxDataTable();
+ },
+
+ //Reset DataTable filters (used before a reload or view change)
+ resetAllFilters: function()
+ {
+ var self = this;
+ var FiltersToRestore = new Array();
+ filters = [
+ 'filter_column',
+ 'filter_pattern',
+ 'filter_column_recursive',
+ 'filter_pattern_recursive',
+ 'filter_excludelowpop',
+ 'filter_excludelowpop_value',
+ 'filter_offset',
+ 'filter_limit',
+ 'filter_sort_column',
+ 'filter_sort_order',
+ 'show_search'
+ ];
+
+ for(var key in filters)
+ {
+ var value = filters[key];
+ FiltersToRestore[value] = self.param[value];
+ delete self.param[value];
+ }
+
+
+ return FiltersToRestore;
+ },
+
+ //Restores the filters to the values given in the array in parameters
+ restoreAllFilters: function(FiltersToRestore)
+ {
+ var self = this;
+ for(key in FiltersToRestore)
+ {
+ self.param[key] = FiltersToRestore[key];
+ }
+ },
+
+ //Translate string parameters to javascript builtins
+ //'true' -> true, 'false' -> false
+ //it simplifies condition tests in the code
+ cleanParams: function()
+ {
+ var self = this;
+ for(var key in self.param)
+ {
+ if(self.param[key] == 'true') self.param[key]=true;
+ if(self.param[key] == 'false') self.param[key]=false;
+ }
+ },
+
+ // Returns the standard Ajax request object used by the Jquery .ajax method
+ buildAjaxRequest: function(callbackSuccess)
+ {
+ var self = this;
+
+ //prepare the ajax request
+ var ajaxRequest =
+ {
+ type: 'GET',
+ url: 'index.php',
+ dataType: 'html',
+ async: true,
+ error: ajaxHandleError, // Callback when the request fails
+ success: callbackSuccess, // Callback when the request succeeds
+ data: new Object
+ };
+
+ //Extract the configuration from the datatable and pass it to the API
+ for(var key in self.param)
+ {
+ if(typeof self.param[key] != "undefined")
+ ajaxRequest.data[key] = self.param[key];
+ }
+
+ return ajaxRequest;
+ },
+
+ // Function called to trigger the AJAX request
+ // The ajax request contains the function callback to trigger if the request is successful or failed
+ // displayLoading = false When we don't want to display the Loading... DIV #loadingDataTable
+ // for example when the script add a Loading... it self and doesn't want to display the generic Loading
+ reloadAjaxDataTable: function(displayLoading, callbackSuccess)
+ {
+ var self = this;
+
+ if (typeof displayLoading == "undefined")
+ {
+ displayLoading = true;
+ }
+ if (typeof callbackSuccess == "undefined")
+ {
+ callbackSuccess = self.dataTableLoaded;
+ }
+
+ if(displayLoading)
+ {
+ $('#'+self.workingDivId+' #loadingDataTable').css('display','block');
+ }
+
+ $.ajax(self.buildAjaxRequest(callbackSuccess));
+ },
+
+
+ // Function called when the AJAX request is successful
+ // it looks for the ID of the response and replace the very same ID
+ // in the current page with the AJAX response
+ dataTableLoaded: function(response)
+ {
+ var content = $(response);
+ var idToReplace = $(content).attr('id');
+ var dataTableSel = $('#'+idToReplace);
+
+ // if the current dataTable is situated inside another datatable
+ table = $(content).parents('table.dataTable');
+ if(dataTableSel.parents('.dataTable').is('table'))
+ {
+ // we add class to the table so that we can give a different style to the subtable
+ $(content).children('table.dataTable').addClass('subDataTable');
+ $(content).children('#dataTableFeatures').addClass('subDataTable');
+
+ //we force the initialisation of subdatatables
+ dataTableSel.html( $(content).html() );
+ //dataTables[idToReplace].init( idToReplace, $('#'+idToReplace) );
+ }
+ else
+ {
+ dataTableSel.html( $(content).html() );
+ lazyScrollTo(dataTableSel[0], 400);
+ }
+ },
+
+
+ /* This method is triggered when a new DIV is loaded, which happens
+ - at the first loading of the page
+ - after any AJAX loading of a DataTable
+
+ This method basically add features to the DataTable,
+ - such as column sorting, searching in the rows, displaying Next / Previous links, etc.
+ - add styles to the cells and rows (odd / even styles)
+ - modify some rows to add images if a span img is found, or add a link if a span urlLink is found
+ or truncate the labels when they are too big
+ - bind new events onclick / hover / etc. to trigger AJAX requests,
+ nice hovertip boxes for truncated cells
+ */
+ bindEventsAndApplyStyle: function(domElem)
+ {
+ var self = this;
+
+ self.cleanParams();
+
+ self.handleSort(domElem);
+
+ self.handleSearchBox(domElem);
+ self.handleLowPopulationLink(domElem);
+ self.handleOffsetInformation(domElem);
+ self.handleExportBox(domElem);
+
+ self.applyCosmetics(domElem);
+
+ self.handleSubDataTable(domElem);
+ },
+
+ // if sorting the columns is enabled, when clicking on a column,
+ // - if this column was already the one used for sorting, we revert the order desc<->asc
+ // - we send the ajax request with the new sorting information
+ handleSort: function(domElem)
+ {
+ var self = this;
+
+ if( self.param.enable_sort )
+ {
+ $('.sortable', domElem).click(
+ function()
+ {
+ $(this).unbind('click');
+ self.onClickSort(this);
+ }
+ );
+
+ // are we in a subdatatable?
+ var currentIsSubDataTable = $(domElem).parent().hasClass('cellSubDataTable');
+
+ var prefixSortIcon = '';
+ if(currentIsSubDataTable)
+ {
+ prefixSortIcon = '_subtable_';
+ }
+ var imageSortWidth = 16;
+ var imageSortHeight = 16;
+ // we change the style of the column currently used as sort column
+ // adding an image and the class columnSorted to the TD
+ $(".sortable#"+self.param.filter_sort_column+' #thDIV', domElem).parent()
+ .addClass('columnSorted')
+ .prepend('<div id="sortIconContainer"><img id="sortIcon" width="'+imageSortWidth+'" height="'+imageSortHeight+'" src="themes/default/images/sort'+prefixSortIcon+ self.param.filter_sort_order+'.png" /></div>');
+ }
+ },
+
+ // Add behaviour to the low population link
+ handleLowPopulationLink: function(domElem, callbackSuccess)
+ {
+ var self = this;
+
+ // Showing the link "Exclude low population" for this DIV
+ if(self.param.show_exclude_low_population)
+ {
+ // Set the string for the DIV, either "Exclude low pop" or "Include all"
+ $('#dataTableExcludeLowPopulation', domElem)
+ .each(
+ function()
+ {
+ if(Number(self.param.filter_excludelowpop) != 0)
+ {
+ string = _pk_translate('CoreHome_IncludeAllPopulation');
+ }
+ else
+ {
+ string = _pk_translate('CoreHome_ExcludeLowPopulation');
+ }
+ $(this).html(string);
+ }
+ )
+ // Bind a click event to the DIV that triggers the ajax request
+ .click(
+ function()
+ {
+ if(Number(self.param.filter_excludelowpop) != 0)
+ {
+ self.param.filter_excludelowpop = 0;
+ self.param.filter_excludelowpop_value = 0;
+ }
+ else
+ {
+ self.param.filter_excludelowpop = self.param.filter_excludelowpop_default;
+ self.param.filter_excludelowpop_value = self.param.filter_excludelowpop_value_default;
+ }
+ self.param.filter_offset = 0;
+
+ self.reloadAjaxDataTable(true, callbackSuccess);
+ }
+ );
+ }
+
+ },
+
+ //behaviour for the DataTable 'search box'
+ handleSearchBox: function(domElem, callbackSuccess)
+ {
+ var self = this;
+
+ // Showing the search box for dom element DIV and binding the event
+ // - on the keyword DIV anywhere, if the ENTER key is pressed
+ if(self.param.show_search)
+ {
+ var currentPattern = self.param.filter_pattern;
+ if(typeof self.param.filter_pattern != "undefined"
+ && self.param.filter_pattern.length > 0)
+ {
+ currentPattern = self.param.filter_pattern;
+ }
+ else if(typeof self.param.filter_pattern_recursive != "undefined"
+ && self.param.filter_pattern_recursive.length > 0)
+ {
+ currentPattern = self.param.filter_pattern_recursive;
+ }
+ else
+ {
+ currentPattern = '';
+ }
+
+
+ $('#dataTableSearchPattern', domElem)
+ .show()
+ .each(function(){
+ // when enter is pressed in the input field we submit the form
+ $('#keyword', this)
+ .keypress(
+ function(e)
+ {
+ if(submitOnEnter(e))
+ {
+ $(this).siblings(':submit').submit();
+ }
+ }
+ )
+ .val(currentPattern)
+ ;
+
+ $(':submit', this).submit(
+ function()
+ {
+ var keyword = $(this).siblings('#keyword').val();
+ self.param.filter_offset = 0;
+
+ if(self.param.search_recursive)
+ {
+ self.param.filter_column_recursive = 'label';
+ self.param.filter_pattern_recursive = keyword;
+ }
+ else
+ {
+ self.param.filter_column = 'label';
+ self.param.filter_pattern = keyword;
+ }
+ self.reloadAjaxDataTable(true, callbackSuccess);
+ }
+ );
+
+ $(':submit', this)
+ .click( function(){ $(this).submit(); })
+ ;
+
+ // in the case there is a searched keyword we display the RESET image
+ if(currentPattern)
+ {
+ var target = this;
+ var clearImg = $('<span style="position: relative;">\
+ <img src="plugins/CoreHome/templates/images/reset_search.png" style="position: absolute; top: 4px; left: -15px; cursor: pointer; display: inline;" title="Clear"/>\
+ </span>')
+ .click( function() {
+ $('#keyword', target).val('');
+ $(':submit', target).submit();
+ });
+ $('#keyword',this).after(clearImg);
+
+ }
+ }
+ );
+
+ }
+ },
+
+ //behaviour for '< prev' 'next >' links and page count
+ handleOffsetInformation: function(domElem)
+ {
+ var self = this;
+
+ // Showing the offset information (1 - 10 of 42) for this DIV
+ if( self.param.show_offset_information
+ // fix konqueror that doesnt recognize the show_offset_information false for the tag cloud
+ // and we really dont want to print Next/Previous for tag clouds
+ && self.param.viewDataTable != 'cloud' )
+ {
+ $('#dataTablePages', domElem).each(
+ function(){
+ var offset = 1+Number(self.param.filter_offset);
+ var offsetEnd = Number(self.param.filter_offset) + Number(self.param.filter_limit);
+ var totalRows = Number(self.param.totalRows);
+ offsetEndDisp = offsetEnd;
+
+ if(offsetEnd > totalRows) offsetEndDisp = totalRows;
+
+ // only show this string if there is some rows in the datatable
+ if(totalRows != 0)
+ {
+ var str = sprintf(_pk_translate('CoreHome_PageOf'),offset + '-' + offsetEndDisp,totalRows);
+ $(this).text(str);
+ }
+ }
+ );
+
+
+ // Display the next link if the total Rows is greater than the current end row
+ $('#dataTableNext', domElem)
+ .each(function(){
+ var offsetEnd = Number(self.param.filter_offset)
+ + Number(self.param.filter_limit);
+ var totalRows = Number(self.param.totalRows);
+ if(offsetEnd < totalRows)
+ {
+ $(this).css('display','inline');
+ }
+ })
+ // bind the click event to trigger the ajax request with the new offset
+ .click(function(){
+ $(this).unbind('click');
+ self.param.filter_offset = Number(self.param.filter_offset) + Number(self.param.filter_limit);
+ self.reloadAjaxDataTable();
+ })
+ ;
+
+ // Display the previous link if the current offset is not zero
+ $('#dataTablePrevious', domElem)
+ .each(function(){
+ var offset = 1+Number(self.param.filter_offset);
+ if(offset != 1)
+ {
+ $(this).css('display','inline');
+ }
+ }
+ )
+ // bind the click event to trigger the ajax request with the new offset
+ // take care of the negative offset, we setup 0
+ .click(
+ function(){
+ $(this).unbind('click');
+ var offset = Number(self.param.filter_offset) - Number(self.param.filter_limit);
+ if(offset < 0) { offset = 0; }
+ self.param.filter_offset = offset;
+ self.reloadAjaxDataTable();
+ }
+ )
+ ;
+
+ }
+ },
+
+ //behaviour for DataTable view box (data, table, cloud, graph, ...)
+ handleExportBox: function(domElem)
+ {
+ var self = this;
+ if( !self.param.idSubtable )
+ {
+ // When the (+) image is hovered, the export buttons are displayed
+ $('#exportDataTableShow', domElem)
+ .show()
+ .hover( function() {
+ $(this).fadeOut('slow');
+ $('#exportToFormat', $(this).parent()).show('slow');
+ }, function(){}
+ );
+
+ //timeout object used to hide the datatable export buttons
+ var timeout = null;
+
+ $('#exportDataTable', domElem)
+ .hover( function() {
+ //display 'hand' cursor
+ $(this).css({ cursor: "pointer"});
+
+ //cancel timeout if necessary
+ if(timeout != null)
+ {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ },
+ function() {
+ //display standard cursor
+ $(this).css({ cursor: "auto"});
+
+ //set a timeout that will hide export buttons after a few moments
+ var dom = this;
+ timeout = setTimeout(function(){
+ $('#exportToFormat', dom).fadeOut('fast', function(){ //queue the two actions
+ $('#exportDataTableShow', dom).show('fast');});
+ }, 1000);
+ }
+ );
+
+ $('.viewDataTable', domElem).click(
+ function(){
+ var viewDataTable = $(this).attr('format');
+ self.resetAllFilters();
+ self.param.viewDataTable = viewDataTable;
+
+ self.reloadAjaxDataTable();
+ }
+ );
+
+ $('#exportToFormat img', domElem).click(function(){
+ $(this).siblings('#linksExportToFormat').toggle();
+ });
+
+ $('.exportToFormat', domElem).attr( 'href', function(){
+ var format = $(this).attr('format');
+ var method = $(this).attr('methodToCall');
+ var filter_limit = $(this).attr('filter_limit');
+
+ var str = '?module=API'
+ +'&method='+method
+ +'&format='+format
+ +'&idSite='+self.param.idSite
+ +'&period='+self.param.period
+ +'&date='+self.param.date;
+ if( filter_limit )
+ {
+ str += '&filter_limit=' + filter_limit;
+ }
+ return str;
+ }
+ );
+ }
+ },
+
+ //Apply some miscelleaneous style to the DataTable
+ applyCosmetics: function(domElem)
+ {
+ var self = this;
+
+ // we truncate the labels columns from the second row
+ $("table tr td:first-child", domElem).truncate(30);
+ $('.truncated', domElem).Tooltip();
+
+ var imageLinkWidth = 10;
+ var imageLinkHeight = 9;
+
+ // we add a link based on the <span id="urlLink"> present in the column label (the first column)
+ // if this span is there, we add the link around the HTML in the TD
+ // but we add this link only for the rows that are not clickable already (subDataTable)
+ $("tr:not('.subDataTable') td:first-child:has('#urlLink')", domElem).each( function(){
+
+ var imgToPrepend = '';
+ if( $(this).find('img').length == 0 )
+ {
+ imgToPrepend = '<img width="'+imageLinkWidth+'" height="'+imageLinkHeight+'" src="themes/default/images/link.gif" /> ';
+ }
+ var urlToLink = $('#urlLink',this).text();
+
+ $(this).html(
+ '<a target="_blank" href="' + urlToLink + '">' + imgToPrepend + $(this).html() + '</a>'
+ );
+ });
+
+
+ // Add some styles on the cells even/odd
+ // label (first column of a data row) or not
+ $("th:first-child", domElem).addClass('label');
+ $("td:first-child:odd", domElem).addClass('label labeleven');
+ $("td:first-child:even", domElem).addClass('label labelodd');
+ $("tr:odd td", domElem).slice(1).addClass('columnodd');
+ $("tr:even td", domElem).slice(1).addClass('columneven');
+
+ // Change cursor on mouse hover if sort is enabled
+ if( self.param.enable_sort )
+ {
+ $("th.sortable", domElem).hover(
+ function()
+ {
+ $(this).css({ cursor: "pointer"});
+ },
+ function()
+ {
+ $(this).css({ cursor: "auto"});
+ }
+ );
+ }
+ },
+
+ //behaviour for 'nested DataTable' (DataTable loaded on a click on a row)
+ handleSubDataTable: function(domElem)
+ {
+ var self = this;
+ // When the TR has a subDataTable class it means that this row has a link to a subDataTable
+ $('tr.subDataTable', domElem)
+ .click(
+ function()
+ {
+ // get the idSubTable
+ var idSubTable = $(this).attr('id');
+ var divIdToReplaceWithSubTable = 'subDataTable_'+idSubTable;
+
+ // if the subDataTable is not already loaded
+ if (typeof self.loadedSubDataTable[divIdToReplaceWithSubTable] == "undefined")
+ {
+ var numberOfColumns = $(this).children().length;
+
+ // at the end of the query it will replace the ID matching the new HTML table #ID
+ // we need to create this ID first
+ $(this).after( '\
+ <tr>\
+ <td colspan="'+numberOfColumns+'" class="cellSubDataTable">\
+ <div id="'+divIdToReplaceWithSubTable+'">\
+ <span id="loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" />'+ _pk_translate('CoreHome_Loading') +'</span>\
+ </div>\
+ </td>\
+ </tr>\
+ ');
+
+ var savedActionVariable = self.param.action;
+
+ // reset all the filters from the Parent table
+ var filtersToRestore = self.resetAllFilters();
+
+ self.param.idSubtable = idSubTable;
+ self.param.action = self.param.actionToLoadTheSubTable;
+ self.reloadAjaxDataTable(false);
+
+ self.param.action = savedActionVariable;
+ delete self.param.idSubtable;
+ self.restoreAllFilters(filtersToRestore);
+
+ self.loadedSubDataTable[divIdToReplaceWithSubTable] = true;
+
+ $(this).next().toggle();
+ }
+
+ $(this).next().toggle();
+ }
+ );
+ }
+};
+
+
+// Helper function :
+// returns true if the event keypress passed in parameter is the ENTER key
+function submitOnEnter(e)
+{
+ var key=e.keyCode || e.which;
+ if (key==13)
+ {
+ return true;
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Action Data Table
+//-----------------------------------------------------------------------------
+
+//inheritance declaration
+//actionDataTable is a child of dataTable
+actionDataTable.prototype = new dataTable;
+actionDataTable.prototype.constructor = actionDataTable;
+
+
+//A list of all our actionDataTables
+//Test if the object have already been initialized (multiple includes)
+if(typeof actionDataTables == "undefined")
+ var actionDataTables = new Object;
+
+//actionDataTable constructor
+function actionDataTable()
+{
+ dataTable.call(this);
+ this.parentAttributeParent = '';
+ this.parentId = '';
+ this.disabledRowDom = new Object; //to handle double click on '+' row
+}
+
+//Prototype of the actionDataTable object
+actionDataTable.prototype =
+{
+ //method inheritance
+ cleanParams: dataTable.prototype.cleanParams,
+ reloadAjaxDataTable: dataTable.prototype.reloadAjaxDataTable,
+ buildAjaxRequest: dataTable.prototype.buildAjaxRequest,
+ handleLowPopulationLink: dataTable.prototype.handleLowPopulationLink,
+ handleSearchBox: dataTable.prototype.handleSearchBox,
+
+ //initialisation of the actionDataTable
+ init: function(workingDivId, domElem)
+ {
+ if(typeof domElem == "undefined")
+ {
+ domElem = $('#'+workingDivId);
+ }
+ this.workingDivId = workingDivId;
+ this.bindEventsAndApplyStyle(domElem);
+ this.initialized = true;
+ },
+
+ //see dataTable::bindEventsAndApplyStyle
+ bindEventsAndApplyStyle: function(domElem)
+ {
+ var self = this;
+
+ self.cleanParams();
+
+ // we dont display the link on the row with subDataTable when we are already
+ // printing all the subTables (case of recursive search when the content is
+ // including recursively all the subtables
+ if(!self.param.filter_pattern_recursive)
+ {
+ $('tr.subActionsDataTable.rowToProcess')
+ .click( function()
+ {
+ self.onClickActionSubDataTable(this)
+ })
+ .hover(function() {
+ $(this).css({ cursor: "pointer"});
+ },
+ function() {
+ $(this).css({ cursor: "auto"});
+ }
+ );
+ }
+
+ self.applyCosmetics(domElem);
+
+ if( self.workingDivId != undefined)
+ {
+ self.handleSearchBox(domElem, self.actionsDataTableLoaded );
+ self.handleLowPopulationLink(domElem, self.actionsDataTableLoaded );
+ }
+ },
+
+ //see dataTable::applyCosmetics
+ applyCosmetics: function(domElem)
+ {
+ var self = this;
+
+ $('tr.subActionsDataTable.rowToProcess')
+ .css('font-weight','bold');
+
+ $("th:first-child", domElem).addClass('label');
+
+ var imagePlusMinusWidth = 12;
+ var imagePlusMinusHeight = 12;
+ $('tr.subActionsDataTable.rowToProcess td:first-child')
+ .each( function(){
+ $(this).prepend('<img width="'+imagePlusMinusWidth+'" height="'+imagePlusMinusHeight+'" class="plusMinus" src="" />');
+ if(self.param.filter_pattern_recursive)
+ {
+ setImageMinus(this);
+ }
+ else
+ {
+ setImagePlus(this);
+ }
+ });
+
+ $('tr.rowToProcess')
+ .each( function() {
+ // we add the CSS style depending on the level of the current loading category
+ // we look at the style of the parent row
+ var style = $(this).prev().attr('class');
+ var currentStyle = $(this).attr('class');
+
+ if( (typeof currentStyle != 'undefined')
+ && currentStyle.indexOf('level') >= 0 )
+ {
+ }
+ else
+ {
+ var level = getNextLevelFromClass( style );
+ $(this).addClass('level'+ level);
+ }
+
+ // we add an attribute parent that contains the ID of all the parent categories
+ // this ID is used when collapsing a parent row, it searches for all children rows
+ // which 'parent' attribute's value contains the collapsed row ID
+ $(this).attr('parent', function(){
+ return self.parentAttributeParent + ' ' + self.parentId;
+ }
+ );
+
+ // Add some styles on the cells even/odd
+ // label (first column of a data row) or not
+ $("td:first-child:odd", this).addClass('label labeleven');
+ $("td:first-child:even", this).addClass('label labelodd');
+ // we truncate the labels columns from the second row
+ $("td:first-child", this).truncate(30);
+ $('.truncated', this).Tooltip();
+ })
+ .removeClass('rowToProcess');
+ },
+
+ // Called when the user click on an actionDataTable row
+ onClickActionSubDataTable: function(domElem)
+ {
+ var self = this;
+
+ // get the idSubTable
+ var idSubTable = $(domElem).attr('id');
+
+ var divIdToReplaceWithSubTable = 'subDataTable_'+idSubTable;
+
+ var NextStyle = $(domElem).next().attr('class');
+ var CurrentStyle = $(domElem).attr('class');
+
+ var currentRowLevel = getLevelFromClass(CurrentStyle);
+ var nextRowLevel = getLevelFromClass(NextStyle);
+
+ // if the row has not been clicked
+ // which is the same as saying that the next row level is equal or less than the current row
+ // because when we click a row the level of the next rows is higher (level2 row gives level3 rows)
+ if(currentRowLevel >= nextRowLevel)
+ {
+ //unbind click to avoid double click problem
+ $(domElem).unbind('click');
+ self.disabledRowDom = $(domElem);
+
+ var numberOfColumns = $(domElem).children().length;
+ $(domElem).after( '\
+ <tr id="'+divIdToReplaceWithSubTable+'" class="cellSubDataTable">\
+ <td colspan="'+numberOfColumns+'">\
+ <span id="loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" /> Loading...</span>\
+ </td>\
+ </tr>\
+ ');
+ var savedActionVariable = self.param.action;
+
+ // reset search for subcategories
+ delete self.param.filter_column;
+ delete self.param.filter_pattern;
+
+ self.param.idSubtable = idSubTable;
+ self.param.action = self.param.actionToLoadTheSubTable;
+
+ self.reloadAjaxDataTable(false, function(resp){self.actionsSubDataTableLoaded(resp)});
+ self.param.action = savedActionVariable;
+ delete self.param.idSubtable;
+ }
+ // else we toggle all these rows
+ else
+ {
+ var plusDetected = $('td img', domElem).attr('src').indexOf('plus') >= 0;
+
+ $(domElem).siblings().each( function(){
+ var parents = $(this).attr('parent');
+ if(parents)
+ {
+ if(parents.indexOf(idSubTable) >= 0 || parents.indexOf('subDataTable_'+idSubTable) >= 0)
+ {
+ if(plusDetected)
+ {
+ $(this).css('display','');
+
+ //unroll everything and display '-' sign
+ //if the row is already opened
+ var NextStyle = $(this).next().attr('class');
+ var CurrentStyle = $(this).attr('class');
+
+ var currentRowLevel = getLevelFromClass(CurrentStyle);
+ var nextRowLevel = getLevelFromClass(NextStyle);
+
+ if(currentRowLevel < nextRowLevel)
+ setImageMinus(this);
+ }
+ else
+ {
+ $(this).css('display','none');
+ }
+ }
+ }
+ });
+ }
+
+ // toggle the +/- image
+ var plusDetected = $('td img', domElem).attr('src').indexOf('plus') >= 0;
+ if(plusDetected)
+ {
+ setImageMinus(domElem);
+ }
+ else
+ {
+ setImagePlus(domElem);
+ }
+ },
+
+ //called when the full table actions is loaded
+ actionsDataTableLoaded: function(response)
+ {
+ var content = $(response);
+ var idToReplace = $(content).attr('id');
+
+ //reset parents id
+ self.parentAttributeParent = '';
+ self.parentId = '';
+
+ var dataTableSel = $('#'+idToReplace);
+ dataTableSel.html($(content).html());
+ lazyScrollTo(dataTableSel[0], 400);
+ },
+
+ // Called when a set of rows for a category of actions is loaded
+ actionsSubDataTableLoaded: function(response)
+ {
+ var self = this;
+ var idToReplace = $(response).attr('id');
+
+ // remove the first row of results which is only used to get the Id
+ var response = $(response).filter('tr').slice(1).addClass('rowToProcess');
+ self.parentAttributeParent = $('tr#'+idToReplace).prev().attr('parent');
+ self.parentId = idToReplace;
+
+ $('tr#'+idToReplace).after( response ).remove();
+
+
+ var re = /subDataTable_(\d+)/;
+ ok = re.exec(self.parentId);
+ if(ok)
+ {
+ self.parentId = ok[1];
+ }
+
+ // we execute the bindDataTableEvent function for the new DIV
+ self.init(self.workingDivId, $('#'+idToReplace));
+
+ //bind back the click event (disabled to avoid double-click problem)
+ self.disabledRowDom.click(
+ function()
+ {
+ self.onClickActionSubDataTable(this)
+ });
+ }
+};
+
+//helper function for actionDataTable
+function getLevelFromClass( style)
+{
+ if (typeof style == "undefined") return 0;
+
+ var currentLevelIndex = style.indexOf('level');
+ var currentLevel = 0;
+ if( currentLevelIndex >= 0)
+ {
+ currentLevel = Number(style.substr(currentLevelIndex+5,1));
+ }
+ return currentLevel;
+}
+
+//helper function for actionDataTable
+function getNextLevelFromClass( style )
+{
+ if (typeof style == "undefined") return 0;
+ currentLevel = getLevelFromClass(style);
+ newLevel = currentLevel;
+ // if this is not a row to process so
+ if( style.indexOf('rowToProcess') < 0 )
+ {
+ newLevel = currentLevel + 1;
+ }
+ return newLevel;
+}
+
+//helper function for actionDataTable
+function setImageMinus( domElem )
+{
+ $('img',domElem).attr('src', 'themes/default/images/minus.png');
+}
+
+//helper function for actionDataTable
+function setImagePlus( domElem )
+{
+ $('img',domElem).attr('src', 'themes/default/images/plus.png');
+}
+
diff --git a/plugins/CoreHome/templates/datatable.tpl b/plugins/CoreHome/templates/datatable.tpl
new file mode 100644
index 0000000000..5cde2c9974
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable.tpl
@@ -0,0 +1,40 @@
+<div id="{$id}" class="parentDiv">
+ {if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
+ {$arrayDataTable.message}
+ {else}
+ {if count($arrayDataTable) == 0}
+ <div id="emptyDatatable">{'CoreHome_TableNoData'|translate}</div>
+ {else}
+ <a name="{$id}"></a>
+ <table cellspacing="0" class="dataTable">
+ <thead>
+ <tr>
+ {foreach from=$dataTableColumns item=column}
+ <th class="sortable" id="{$column.id}"><div id="thDIV">{$column.displayName}</div></th>
+ {/foreach}
+ </tr>
+ </thead>
+
+ <tbody>
+ {foreach from=$arrayDataTable item=row}
+ <tr {if $row.idsubdatatable}class="subDataTable" id="{$row.idsubdatatable}"{/if}>
+ {foreach from=$dataTableColumns key=idColumn item=column}
+ <td>
+ {if $idColumn==0 && isset($row.metadata.url)}<span id="urlLink">{$row.metadata.url}</span>{/if}
+ {if $idColumn==0 && isset($row.metadata.logo)}<img {if isset($row.metadata.logoWidth)}width="{$row.metadata.logoWidth}"{/if} {if isset($row.metadata.logoHeight)}height="{$row.metadata.logoHeight}"{/if} src="{$row.metadata.logo}" />{/if}
+ {* sometimes all columns are not set in the datatable, we assume the value 0 *}
+ {if isset($row.columns[$column.name])}{$row.columns[$column.name]}{else}0{/if}
+ </td>
+ {/foreach}
+ </tr>
+ {/foreach}
+ </tbody>
+ </table>
+ {/if}
+
+ {if $showFooter}
+ {include file="CoreHome/templates/datatable_footer.tpl"}
+ {/if}
+ {include file="CoreHome/templates/datatable_js.tpl"}
+ {/if}
+</div>
diff --git a/plugins/CoreHome/templates/datatable_actions.tpl b/plugins/CoreHome/templates/datatable_actions.tpl
new file mode 100644
index 0000000000..275a6a2daa
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable_actions.tpl
@@ -0,0 +1,40 @@
+<div id="{$id}" class="parentDivActions">
+{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
+ {$arrayDataTable.message}
+{else}
+ {if count($arrayDataTable) == 0}
+ <div id="emptyDatatable">{'CoreHome_TableNoData'|translate}</div>
+ {else}
+ <table cellspacing="0" class="dataTable dataTableActions">
+ <thead>
+ <tr>
+ {foreach from=$dataTableColumns item=column}
+ <th class="sortable" id="{$column.id}">{$column.name}</td>
+ {/foreach}
+ </tr>
+ </thead>
+
+ <tbody>
+ {foreach from=$arrayDataTable item=row}
+ <tr {if $row.idsubdatatable}class="rowToProcess subActionsDataTable" id="{$row.idsubdatatable}"{else} class="actionsDataTable rowToProcess"{/if}>
+ {foreach from=$dataTableColumns key=idColumn item=column}
+ <td>
+ {* sometimes all columns are not set in the datatable, we assume the value 0 *}
+ {if isset($row.columns[$column.name])}{$row.columns[$column.name]}{else}0{/if}
+ </td>
+ {/foreach}
+ </tr>
+ {/foreach}
+ </tbody>
+
+ </tfoot>
+ </table>
+ {/if}
+
+ {if $showFooter}
+ {include file="CoreHome/templates/datatable_footer.tpl"}
+ {/if}
+ {include file="CoreHome/templates/datatable_actions_js.tpl"}
+
+ {/if}
+</div>
diff --git a/plugins/CoreHome/templates/datatable_actions_js.tpl b/plugins/CoreHome/templates/datatable_actions_js.tpl
new file mode 100644
index 0000000000..5bf5ed2bca
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable_actions_js.tpl
@@ -0,0 +1,12 @@
+
+<script type="text/javascript" defer="defer">
+$(document).ready(function(){literal}{{/literal}
+ actionDataTables['{$id}'] = new actionDataTable();
+ actionDataTables['{$id}'].param = {literal}{{/literal}
+ {foreach from=$javascriptVariablesToSet key=name item=value name=loop}
+ {$name}: '{$value}'{if !$smarty.foreach.loop.last},{/if}
+ {/foreach}
+ {literal}};{/literal}
+ actionDataTables['{$id}'].init('{$id}');
+{literal}}{/literal});
+</script>
diff --git a/plugins/CoreHome/templates/datatable_actions_recursive.tpl b/plugins/CoreHome/templates/datatable_actions_recursive.tpl
new file mode 100644
index 0000000000..754f909158
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable_actions_recursive.tpl
@@ -0,0 +1,44 @@
+<div id="{$id}" class="parentDivActions">
+{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
+ {$arrayDataTable.message}
+{else}
+ {if count($arrayDataTable) == 0}
+ <div id="emptyDatatable">{'CoreHome_TableNoData'|translate}</div>
+ {else}
+ <table cellspacing="0" class="dataTable dataTableActions">
+ <thead>
+ <tr>
+ {foreach from=$dataTableColumns item=column}
+ <th class="sortable" id="{$column.id}">{$column.displayName}</td>
+ {/foreach}
+ </tr>
+ </thead>
+
+ <tbody>
+ {foreach from=$arrayDataTable item=row}
+ <tr {if $row.idsubdatatable}class="level{$row.level} rowToProcess subActionsDataTable" id="{$row.idsubdatatable}"{else}class="actionsDataTable rowToProcess level{$row.level}"{/if}>
+ {foreach from=$dataTableColumns key=idColumn item=column}
+ <td>
+ {* sometimes all columns are not set in the datatable, we assume the value 0 *}
+ {if isset($row.columns[$column.name])}{$row.columns[$column.name]}{else}0{/if}
+ </td>
+ {/foreach}
+ </tr>
+ {/foreach}
+ </tbody>
+
+
+ </foot>
+ <tr><td colspan="{$dataTableColumns|@count}">
+
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ {/if}
+
+ {include file="CoreHome/templates/datatable_footer.tpl"}
+ {include file="CoreHome/templates/datatable_actions_js.tpl"}
+
+ {/if}
+</div>
diff --git a/plugins/CoreHome/templates/datatable_actions_subdatable.tpl b/plugins/CoreHome/templates/datatable_actions_subdatable.tpl
new file mode 100644
index 0000000000..08f91d2db2
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable_actions_subdatable.tpl
@@ -0,0 +1,19 @@
+<tr id="{$id}"></tr>
+{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
+ {$arrayDataTable.message}
+{else}
+ {if count($arrayDataTable) == 0}
+ <tr><td colspan="{$nbColumns}">{'CoreHome_CategoryNoData'|translate}</td></tr>
+ {else}
+ {foreach from=$arrayDataTable item=row}
+ <tr {if $row.idsubdatatable}class="subActionsDataTable" id="{$row.idsubdatatable}"{else}class="actionsDataTable"{/if}>
+ {foreach from=$dataTableColumns key=idColumn item=column}
+ <td>
+ {* sometimes all columns are not set in the datatable, we assume the value 0 *}
+ {if isset($row.columns[$column.name])}{$row.columns[$column.name]}{else}0{/if}
+ </td>
+ {/foreach}
+ </tr>
+ {/foreach}
+ {/if}
+{/if}
diff --git a/plugins/CoreHome/templates/datatable_footer.tpl b/plugins/CoreHome/templates/datatable_footer.tpl
new file mode 100644
index 0000000000..f1e532eaf2
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable_footer.tpl
@@ -0,0 +1,36 @@
+<div id="dataTableFeatures">
+ <span id="dataTableExcludeLowPopulation"></span>
+
+ <span id="dataTableSearchPattern">
+ <input id="keyword" type="text" length="15" />
+ <input type="submit" value="{'General_Search'|translate}" />
+ </span>
+
+ <span id="dataTablePages"></span>
+ <span id="dataTablePrevious">&lt; {'General_Previous'|translate}</span>
+ <span id="dataTableNext">{'General_Next'|translate} &gt;</span>
+ <div>
+ <span id="exportDataTable">
+ <span id="exportToFormat" style="display:none">
+ <img width="16" height="16" src="themes/default/images/export.png" />
+ <span id="linksExportToFormat" style="display:none">
+ <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="CSV" filter_limit="100">CSV</a> |
+ <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="XML" filter_limit="100">XML</a> |
+ <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="JSON" filter_limit="100">Json</a> |
+ <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="PHP" filter_limit="100">Php</a>
+ </span>
+ <a class="viewDataTable" format="table"><img width="16" height="16" src="themes/default/images/table.png" title="{'General_Table'|translate}" /></a>
+ <a class="viewDataTable" format="cloud"><img width="16" height="16" src="themes/default/images/tagcloud.png" title="{'General_TagCloud'|translate}" /></a>
+ <a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="themes/default/images/chart_bar.png" title="{'General_VBarGraph'|translate}" /></a>
+ <a class="viewDataTable" format="graphPie"><img width="16" height="16" src="themes/default/images/chart_pie.png" title="{'General_Piechart'|translate}" /></a>
+ </span>
+ <span id="exportDataTableShow" style="display:none">
+ <img src="plugins/CoreHome/templates/images/more.png" />
+ </span>
+ </span>
+
+ <span id="loadingDataTable"><img src="themes/default/images/loading-blue.gif" /> {'General_LoadingData'|translate}</span>
+ </div>
+</div>
+
+<div class="dataTableSpacer" />
diff --git a/plugins/CoreHome/templates/datatable_js.tpl b/plugins/CoreHome/templates/datatable_js.tpl
new file mode 100644
index 0000000000..83043606f4
--- /dev/null
+++ b/plugins/CoreHome/templates/datatable_js.tpl
@@ -0,0 +1,12 @@
+
+<script type="text/javascript" defer="defer">
+$(document).ready(function(){literal}{{/literal}
+ dataTables['{$id}'] = new dataTable();
+ dataTables['{$id}'].param = {literal}{{/literal}
+ {foreach from=$javascriptVariablesToSet key=name item=value name=loop}
+ {$name}: '{$value}'{if !$smarty.foreach.loop.last},{/if}
+ {/foreach}
+ {literal}};{/literal}
+ dataTables['{$id}'].init('{$id}');
+{literal}}{/literal});
+</script>
diff --git a/plugins/CoreHome/templates/date.js b/plugins/CoreHome/templates/date.js
new file mode 100644
index 0000000000..2ee73f08bf
--- /dev/null
+++ b/plugins/CoreHome/templates/date.js
@@ -0,0 +1,89 @@
+$(document).ready(function(){
+ $("#periodString").hide();
+ $("#otherPeriods").hide();
+ $("#calendar").hide();
+ $("#periodString").show();
+
+ // we get the content of the div before modifying it (append image, etc.)
+ // so we can restore its value when we want
+ var savedCurrentPeriod = $("#periodString #currentPeriod").html();
+
+ // timeout used to fadeout the menu
+ var timeout = null;
+ var timeoutLength;
+
+ // restore the normal style of the current period type eg "DAY"
+ function restoreCurrentPeriod()
+ {
+ $("#currentPeriod")
+ .removeClass("hoverPeriod")
+ .html(savedCurrentPeriod);
+ }
+ // remove the sub menu created that contains the other periods availble
+ // eg. week | month | year
+ function removePeriodMenu() {
+ $("#otherPeriods").fadeOut('fast');
+ setCurrentPeriodStyle = true;
+ }
+
+ // state machine a bit complex and was hard to come up with
+ // there should be a simpler way to do it with jquery...
+ // if set to true, means that we want to style our current period
+ // for example add bold and append the image
+ var setCurrentPeriodStyle = true;
+
+ $("#periodString #periods")
+ .hover(function(){
+ $(this).css({ cursor: "pointer"});
+
+ // cancel the timeout
+ // indeed if the user goes away of the div and goes back on
+ // we don't hide the submenu!
+ if(timeout != null)
+ {
+ clearTimeout(timeout);
+ timeout = null;
+ timeoutLength = 500;
+ }
+ else
+ {
+ timeoutLength = 0;
+ setCurrentPeriodStyle = true;
+ }
+ if( setCurrentPeriodStyle == true)
+ {
+ $("#currentPeriod:not(.hoverPeriod)")
+ .addClass("hoverPeriod")
+ .append('&nbsp;<img src="plugins/CoreHome/templates/images/more_period.gif" style="vertical-align:middle">');
+ }
+ }, function(){
+ restoreCurrentPeriod();
+ // we callback the function to hide the sub menu
+ // only if it was visible (otherwise it messes the state machine)
+ if($("#otherPeriods").is(":visible"))
+ {
+ timeout = setTimeout( removePeriodMenu , timeoutLength);
+ }
+ setCurrentPeriodStyle = false;
+ })
+ .click( function() {
+ // we restore the initial style on the DAY link
+ restoreCurrentPeriod();
+ // the menu shall fadeout after 500ms
+ timeoutLength = 500;
+ // appearance!
+ $("#otherPeriods").fadeIn();
+
+ }
+ );
+
+ $("#periodString #date")
+ .hover( function(){
+ $(this).css({ cursor: "pointer"});
+ }, function(){
+
+ })
+ .click(function(){
+ $("#calendar").toggle();
+ });
+} ); \ No newline at end of file
diff --git a/plugins/CoreHome/templates/graph.tpl b/plugins/CoreHome/templates/graph.tpl
new file mode 100644
index 0000000000..90a4d8fe63
--- /dev/null
+++ b/plugins/CoreHome/templates/graph.tpl
@@ -0,0 +1,16 @@
+<div id="{$id}" class="{if $graphType=='evolution'}parentDivGraphEvolution{else}parentDivGraph{/if}">
+{$jsInvocationTag}
+
+{if $showFooter}
+ <br/><br/>
+ <form class="formEmbedCode" id="{$formId}">
+ Embed <input name="embed_code" value="{$codeEmbed}" onclick="javascript:document.getElementById('{$formId}').embed_code.focus();document.getElementById('{$formId}').embed_code.select();" readonly="true" type="text">
+
+ | <a target="_blank" href="{$urlData}">{'General_GraphData'|translate}</a>
+ </form>
+
+ {include file="CoreHome/templates/datatable_footer.tpl"}
+ {include file="CoreHome/templates/datatable_js.tpl"}
+{/if}
+
+</div>
diff --git a/plugins/CoreHome/templates/header.tpl b/plugins/CoreHome/templates/header.tpl
new file mode 100644
index 0000000000..0af51cce87
--- /dev/null
+++ b/plugins/CoreHome/templates/header.tpl
@@ -0,0 +1,8 @@
+
+<span id="righttext">
+ <span id="messageToUsers"><a href='http://piwik.org'>Piwik</a> is a collaborative project and still Beta. <br />
+ If you want to help, please <u><a href="mailto:hello@piwik.org?subject=Piwik">contact us</a></u>.</span>
+</span>
+
+{include file="CoreHome/templates/logo.tpl"}
+{include file="CoreHome/templates/period_select.tpl"} \ No newline at end of file
diff --git a/plugins/CoreHome/templates/images/bg_header.jpg b/plugins/CoreHome/templates/images/bg_header.jpg
new file mode 100644
index 0000000000..1733b0e355
--- /dev/null
+++ b/plugins/CoreHome/templates/images/bg_header.jpg
Binary files differ
diff --git a/plugins/CoreHome/templates/images/bullet1.gif b/plugins/CoreHome/templates/images/bullet1.gif
new file mode 100644
index 0000000000..d4ed73eea7
--- /dev/null
+++ b/plugins/CoreHome/templates/images/bullet1.gif
Binary files differ
diff --git a/plugins/CoreHome/templates/images/bullet2.gif b/plugins/CoreHome/templates/images/bullet2.gif
new file mode 100644
index 0000000000..d51d938dd1
--- /dev/null
+++ b/plugins/CoreHome/templates/images/bullet2.gif
Binary files differ
diff --git a/plugins/CoreHome/templates/images/more.png b/plugins/CoreHome/templates/images/more.png
new file mode 100644
index 0000000000..cba03a05f5
--- /dev/null
+++ b/plugins/CoreHome/templates/images/more.png
Binary files differ
diff --git a/plugins/CoreHome/templates/images/more_date.gif b/plugins/CoreHome/templates/images/more_date.gif
new file mode 100644
index 0000000000..87da6b4963
--- /dev/null
+++ b/plugins/CoreHome/templates/images/more_date.gif
Binary files differ
diff --git a/plugins/CoreHome/templates/images/more_period.gif b/plugins/CoreHome/templates/images/more_period.gif
new file mode 100644
index 0000000000..b0c9787851
--- /dev/null
+++ b/plugins/CoreHome/templates/images/more_period.gif
Binary files differ
diff --git a/plugins/CoreHome/templates/images/reset_search.png b/plugins/CoreHome/templates/images/reset_search.png
new file mode 100644
index 0000000000..cb1d9e80a2
--- /dev/null
+++ b/plugins/CoreHome/templates/images/reset_search.png
Binary files differ
diff --git a/plugins/CoreHome/templates/images/search.png b/plugins/CoreHome/templates/images/search.png
new file mode 100644
index 0000000000..6d1f037c69
--- /dev/null
+++ b/plugins/CoreHome/templates/images/search.png
Binary files differ
diff --git a/plugins/CoreHome/templates/index.tpl b/plugins/CoreHome/templates/index.tpl
new file mode 100644
index 0000000000..43fb78a0d8
--- /dev/null
+++ b/plugins/CoreHome/templates/index.tpl
@@ -0,0 +1,77 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<title>Piwik - Your Web Analytics Reports</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+{loadJavascriptTranslations modules='CoreHome'}
+
+<script type="text/javascript">
+var period = "{$period}";
+var currentDateStr = "{$date}";
+var minDateYear = {$minDateYear};
+var minDateMonth = {$minDateMonth};
+var minDateDay = {$minDateDay};
+</script>
+
+<script type="text/javascript" src="libs/jquery/jquery.js"></script>
+
+<script type="text/javascript" src="themes/default/common.js"></script>
+<script type="text/javascript" src="libs/jquery/jquery.dimensions.js"></script>
+<script type="text/javascript" src="libs/jquery/tooltip/jquery.tooltip.js"></script>
+<script type="text/javascript" src="libs/jquery/truncate/jquery.truncate.js"></script>
+<script type="text/javascript" src="libs/jquery/jquery.scrollTo.js"></script>
+<script type="text/javascript" src="libs/jquery/jquery-calendar.js"></script>
+<script type="text/javascript" src="libs/swfobject/swfobject.js"></script>
+
+<script type="text/javascript" src="plugins/CoreHome/templates/datatable.js"></script>
+<script type="text/javascript" src="plugins/CoreHome/templates/calendar.js"></script>
+<script type="text/javascript" src="plugins/CoreHome/templates/date.js"></script>
+
+<script type="text/javascript" src="libs/jquery/jquery.blockUI.js"></script>
+<script type="text/javascript" src="libs/jquery/ui.mouse.js"></script>
+<script type="text/javascript" src="libs/jquery/ui.sortable_modif.js"></script>
+
+<link rel="stylesheet" href="plugins/CoreHome/templates/datatable.css" />
+<link rel="stylesheet" href="plugins/Dashboard/templates/dashboard.css" />
+<style type="text/css">@import url(libs/jquery/jquery-calendar.css);</style>
+
+<script type="text/javascript" src="libs/jquery/superfish_modified.js"></script>
+<script type="text/javascript" src="plugins/CoreHome/templates/menu.js"></script>
+<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/menu.css" media="screen" />
+<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/style.css" media="screen" />
+
+<script type="text/javascript" src="libs/jquery/thickbox.js"></script>
+<link rel="stylesheet" href="libs/jquery/thickbox.css" />
+</head>
+<body>
+
+{include file="CoreHome/templates/top_bar.tpl"}
+
+<br clear="all" />
+
+<div id="header">
+{include file="CoreHome/templates/header.tpl"}
+</div>
+
+<noscript>
+<span id="javascriptDisable">
+{'CoreHome_JavascriptDisabled'|translate:'<a href="">':'</a>'}
+</span>
+</noscript>
+
+<br />
+{include file="CoreHome/templates/menu.tpl"}
+
+<div style='clear:both'></div>
+
+<div id="loadingPiwik" {if $basicHtmlView}style="display:none"{/if}><img src="themes/default/images/loading-blue.gif" alt="" /> {'General_LoadingData'|translate}</div>
+<div id="loadingError">{'General_ErrorRequest'|translate}</div>
+
+<div id='content'>
+{if $content}{$content}{/if}
+</div>
+
+{include file="CoreHome/templates/piwik_tag.tpl"}
+</body>
+</html>
diff --git a/plugins/CoreHome/templates/logo.tpl b/plugins/CoreHome/templates/logo.tpl
new file mode 100644
index 0000000000..ce2656865e
--- /dev/null
+++ b/plugins/CoreHome/templates/logo.tpl
@@ -0,0 +1,14 @@
+<span id="logo">
+<a href="http://piwik.org" target="_blank" title="open source web analytics" style="text-decoration: none;">
+ <span style="color: rgb(245, 223, 114);">P</span><span style="color: rgb(241, 175, 108);">i</span><span style="color: rgb(241, 117, 117);">w</span><span style="color: rgb(155, 106, 58);">i</span><span style="color: rgb(107, 50, 11);">k</span>
+ <!--
+ <span style="font-size: 20pt; letter-spacing: -1pt;">
+ <span style="color: rgb(107, 50, 11);">#</span>
+ <span style="color: rgb(107, 50, 11);"> Open</span>
+ <span style="color: rgb(107, 50, 11);"> source </span>
+ <span style="color: rgb(107, 50, 11);">web </span>
+ <span style="color: rgb(107, 50, 11);">analytics</span>
+ </span>
+ -->
+</a>
+</span> \ No newline at end of file
diff --git a/plugins/CoreHome/templates/menu.css b/plugins/CoreHome/templates/menu.css
new file mode 100644
index 0000000000..00baa61df0
--- /dev/null
+++ b/plugins/CoreHome/templates/menu.css
@@ -0,0 +1,111 @@
+.nav,.nav * {
+ margin: 0;
+ padding: 0;
+}
+
+.nav {
+ padding-bottom: 2.5em;
+ height: 2.5em;
+ float: left;
+ line-height: 1.0;
+ margin-bottom: 1.5em;
+ position: relative;
+}
+
+.nav ul {
+ background: #fff; /*IE6 needs this*/
+ float: left;
+ position: relative;
+}
+
+/* LEVEL1 NORMAL */
+.nav li {
+ background: #DFE6FF;
+ border-left: 1px solid #fff;
+ float: left;
+ list-style: none;
+ z-index: 49;
+}
+
+.nav li.current ul {
+ z-index: 49;
+}
+
+.nav li.sfHover ul,ul.nav li:hover ul {
+ z-index: 50;
+}
+
+/* LEVEL2 NORMAL */
+.nav li li {
+ background: #FBFFFF;
+ border-left-color: #AABDE6;
+}
+
+.nav a {
+ border-bottom: 1px solid #CFDEFF;
+ color: #13a;
+ display: block;
+ float: left;
+ padding: .75em 0 .75em 1em;
+ text-decoration: none;
+ width: 8em;
+}
+
+.nav li ul {
+ left: 0;
+ top: -999em;
+ position: absolute;
+ width: 48em;
+}
+
+/* LEVEL1 HOVER */
+.nav li:hover,.nav li.sfHover,.nav li.current,.nav a:focus,.nav a:hover,.nav a:active
+ {
+ background: #C9D5FF;
+}
+
+.nav li {
+ font-weight: normal;
+}
+
+.nav li.sfHover {
+ font-weight: bold;
+}
+
+/* LEVEL2 HOVER */
+.nav li li:hover,.nav li li.sfHover,.nav li li a:focus,.nav li li a:hover,.nav li li a:active
+ {
+ background: #C9F6FF;
+ font-weight: bold;
+}
+
+.nav li.sfHover a,.nav li.current a,.nav a:focus,.nav a:hover,.nav a:active
+ {
+ border-bottom: none;
+}
+
+.nav li li.current a {
+ font-weight: bold;
+}
+
+.nav li:hover ul, /* pure CSS hover is removed below */ body .nav li.current ul,
+ /* this must be more specific than the .superfish override below */ ul.nav li.sfHover ul
+ {
+ top: 2.5em;
+}
+
+.nav li:hover li ul,.nav li.sfHover li ul {
+ top: -999em;
+}
+
+.nav li li:hover ul, /* pure CSS hover is removed below */ ul.nav li li.sfHover ul
+ {
+ top: 2.5em;
+}
+
+/*following rule negates pure CSS hovers
+so submenu remains hidden and JS controls
+when and how it appears*/
+.superfish li:hover ul,.superfish li li:hover ul {
+ top: -999em;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/templates/menu.js b/plugins/CoreHome/templates/menu.js
new file mode 100644
index 0000000000..c87d894a05
--- /dev/null
+++ b/plugins/CoreHome/templates/menu.js
@@ -0,0 +1,126 @@
+// menu constructor
+function menu()
+{
+ this.param = new Object;
+}
+
+// this should be in the menu prototype but I couldn't figure out
+// how to use it as a callback in the jquery ajax request
+
+
+//Prototype of the DataTable object
+menu.prototype =
+{
+ menuSectionLoaded: function (content, urlLoaded)
+ {
+ if(urlLoaded == menu.prototype.lastUrlRequested)
+ {
+ $('#content').html( content ).show();
+ $('#loadingPiwik').hide();
+ menu.prototype.lastUrlRequested = null;
+ //console.log('display '+urlLoaded);
+ }
+ else
+ {
+ //console.log('loaded '+urlLoaded+' but expecting to display '+menu.prototype.lastUrlRequested);
+ }
+ },
+
+ customAjaxHandleError: function ()
+ {
+ menu.prototype.lastUrlRequested = null;
+ ajaxHandleError();
+ },
+
+ overMainLI: function ()
+ {
+ $(this).siblings().removeClass('sfHover');
+ },
+
+ outMainLI: function ()
+ {
+ },
+
+ onClickLI: function ()
+ {
+ var self = this;
+ var urlAjax = $('a',this).attr('name');
+ function menuSectionLoaded(content)
+ {
+ menu.prototype.menuSectionLoaded(content, urlAjax);
+ }
+
+ // showing loading...
+ $('#loadingPiwik').show();
+ $('#content').hide();
+
+ if(menu.prototype.lastUrlRequested == urlAjax)
+ {
+ return false;
+ }
+ menu.prototype.lastUrlRequested = urlAjax;
+
+ // we are in the SUB UL LI
+ if($(this).find('ul li').size() == 0)
+ {
+ // console.log('clicked SUB LI');
+ $(this).addClass('sfHover');
+ }
+ // we clicked on a MAIN LI
+ else
+ {
+ $(this).find('>ul li:first').addClass('sfHover');
+ }
+
+ //prepare the ajax request
+ ajaxRequest =
+ {
+ type: 'GET',
+ url: urlAjax,
+ dataType: 'html',
+ async: true,
+ error: menu.prototype.customAjaxHandleError, // Callback when the request fails
+ success: menuSectionLoaded, // Callback when the request succeeds
+ data: new Object
+ };
+ $.ajax(ajaxRequest);
+
+ return false;
+
+ },
+
+ init: function()
+ {
+ var self = this;
+ this.param.superfish = $('.nav')
+ .superfish({
+ pathClass : 'current',
+ animation : {opacity:'show'},
+ delay : 1000
+ });
+ this.param.superfish.find("li")
+ .click( self.onClickLI )
+ ;
+
+ this.param.superfish
+ .find("li:has(ul)")
+ .hover(self.overMainLI, self.outMainLI)
+ ;
+ },
+
+ loadFirstSection: function()
+ {
+ var self=this;
+ $('li:first', self.param.superfish)
+ .click()
+ .each(function(){
+ $(this).showSuperfishUl();
+ });
+ }
+}
+
+$(document).ready( function(){
+ piwikMenu = new menu();
+ piwikMenu.init();
+ piwikMenu.loadFirstSection();
+}); \ No newline at end of file
diff --git a/plugins/CoreHome/templates/menu.tpl b/plugins/CoreHome/templates/menu.tpl
new file mode 100644
index 0000000000..d7f036cbc3
--- /dev/null
+++ b/plugins/CoreHome/templates/menu.tpl
@@ -0,0 +1,16 @@
+
+<ul class="nav">
+{foreach from=$menu key=level1 item=level2 name=menu}
+<li>
+ <a name='{$level2._url|@urlRewriteWithParameters}' href='{$level2._url|@urlRewriteBasicView}'>{$level1} &#8595;</a>
+ <ul>
+ {foreach from=$level2 key=name item=urlParameters name=level2}
+ {if $name != '_url'}
+ <li><a name='{$urlParameters|@urlRewriteWithParameters}' href='{$urlParameters|@urlRewriteBasicView}'>{$name}</a></li>
+ {/if}
+ {/foreach}
+ </ul>
+</li>
+{/foreach}
+</ul>
+
diff --git a/plugins/CoreHome/templates/period_select.tpl b/plugins/CoreHome/templates/period_select.tpl
new file mode 100644
index 0000000000..f836dc449b
--- /dev/null
+++ b/plugins/CoreHome/templates/period_select.tpl
@@ -0,0 +1,13 @@
+<span id="periodString">
+ <span id="date"><img src='plugins/CoreHome/templates/images/more_date.gif' style="vertical-align:middle" alt="" /> {$prettyDate}</span> -&nbsp;
+ <span id="periods">
+ <span id="currentPeriod">{$periodsNames.$period}</span>
+ <span id="otherPeriods">
+ {foreach from=$otherPeriods item=thisPeriod} | <a href='{url period=$thisPeriod}'>{$periodsNames.$thisPeriod}</a>{/foreach}
+ </span>
+ </span>
+ <br/>
+ <span id="calendar"></span>
+</span>
+<div style="clear:both"></div>
+
diff --git a/plugins/CoreHome/templates/piwik_tag.tpl b/plugins/CoreHome/templates/piwik_tag.tpl
new file mode 100644
index 0000000000..3f207f6bda
--- /dev/null
+++ b/plugins/CoreHome/templates/piwik_tag.tpl
@@ -0,0 +1,19 @@
+{if ereg('http://127.0.0.1|http://localhost|http://piwik.org', $url)}
+{literal}
+<!-- Piwik -->
+<a href="http://piwik.org" title="Web analytics" onclick="window.open(this.href);return(false);">
+<script language="javascript" src="piwik.js" type="text/javascript"></script>
+<script type="text/javascript">
+<!--
+piwik_action_name = '';
+piwik_idsite = 1;
+piwik_url = 'piwik.php';
+piwik_vars = { 'video_play':1, 'video_finished':0 };
+piwik_log(piwik_action_name, piwik_idsite, piwik_url, piwik_vars);
+//-->
+</script><object>
+<noscript><p>Web analytics <img src="piwik.php" style="border:0" alt="piwik"/></p>
+</noscript></object></a>
+<!-- /Piwik -->
+{/literal}
+{/if} \ No newline at end of file
diff --git a/plugins/CoreHome/templates/sites_select.tpl b/plugins/CoreHome/templates/sites_select.tpl
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/plugins/CoreHome/templates/sites_select.tpl
diff --git a/plugins/CoreHome/templates/sparkline.js b/plugins/CoreHome/templates/sparkline.js
new file mode 100644
index 0000000000..2ab68d18c7
--- /dev/null
+++ b/plugins/CoreHome/templates/sparkline.js
@@ -0,0 +1,59 @@
+
+$(document).ready( function(){
+
+ //for every section
+ $("a[name='evolutionGraph']").each(
+ function()
+ {
+ //try to find the graph
+ var graph = $(this);
+
+ if(graph && graph.size() > 0)
+ {
+ //console.log($(this).parent());
+ //try to find sparklines and add them clickable behaviour
+ $(this).parent().find('p').each(
+ function()
+ {
+ var url = "";
+ //find the sparkline and get it's src attribute
+ $(".sparkline", this).each(
+ function()
+ {
+ //search viewDataTable parameter and replace it with value for chart
+ var reg = new RegExp("(viewDataTable=sparkline)", "g");
+ url = this.src.replace(reg,'viewDataTable=generateDataChartEvolution');
+ }
+ );
+
+ if(url != "")
+ {
+ $("*", this).each(
+ function()
+ {
+ //on click, reload the graph with the new url
+ $(this).click(
+ function()
+ {
+ //get the main page graph and reload with new data
+ findSWFGraph(graph.attr('graphId')+"Chart_swf").reload(url);
+ lazyScrollTo(graph[0], 400);
+ }
+ );
+
+ //on hover, change cursor to indicate clickable item
+ $(this).hover(
+ function()
+ {
+ $(this).css({ cursor: "pointer"});
+ }, function (){}
+ );
+ }
+ );
+ }
+ }
+ );
+ }
+ }
+ );
+});
diff --git a/plugins/CoreHome/templates/style.css b/plugins/CoreHome/templates/style.css
new file mode 100644
index 0000000000..c7ab9408ad
--- /dev/null
+++ b/plugins/CoreHome/templates/style.css
@@ -0,0 +1,258 @@
+/* reset style */
+html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td
+ {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ font-size: 100%;
+ vertical-align: baseline;
+ background: transparent;
+}
+
+body {
+ line-height: 1.33;
+ background-color: white;
+ color: black;
+}
+
+ol,ul {
+ list-style: none;
+}
+
+blockquote,q {
+ quotes: none;
+}
+
+/* remember to define focus styles! */
+:focus {
+ outline: 0;
+}
+
+/* remember to highlight inserts somehow! */
+ins {
+ text-decoration: none;
+}
+
+del {
+ text-decoration: line-through;
+}
+
+/* start piwik styles */
+body {
+ font-family: Georgia, "Trebuchet MS", Verdana, Arial, Helvetica,
+ sans-serif;
+ font-size: 1em;
+}
+
+#title {
+ align: left;
+}
+
+h1 {
+ font-size: 2em;
+ color: #0F1B2E;
+ padding-bottom: 1em;
+}
+
+h2 {
+ font-size: 1.6em;
+ color: #1D3256;
+ padding-bottom: 0.5em;
+}
+
+h3 {
+ font-size: 1.3em;
+ margin-top: 2em;
+ color: #1D3256;
+}
+
+a {
+ color: #0F1B2E;
+}
+
+p {
+ padding-bottom: 1em;
+ margin-right: 1em;
+}
+
+/* Content */
+#content {
+ margin-left: 10px;
+}
+
+/* 2 columns reports */
+#leftcolumn {
+ float: left;
+ width: 45%;
+ padding-left: 10px;
+ padding-right: 20px;
+}
+
+#rightcolumn {
+ float: right;
+ width: 45%;
+ padding-left: 20px;
+}
+
+#header {
+ line-height: 1;
+}
+
+#logo {
+ float: left;
+ display: inline;
+ font-size: 45pt;
+ padding-left: 15px;
+ padding-left: 15px;
+}
+
+#righttext {
+ position: relative;
+ text-align: left;
+ float: right;
+ margin-top: 10px;
+ font-size: 1em;
+ width: 300px;
+ line-height: 1.33;
+}
+
+#calendar {
+ display: block;
+}
+
+#periodString #date,#periodString #periods,#periodString #date a,#periodString #periods a
+ {
+ color: #520202;
+ font-size: 15pt;
+}
+
+#periodString {
+ padding-top: 2em;
+ margin-left: 350px;
+ display: block;
+}
+
+/* Calendar*/
+.calendar td.dateToday,.calendar td.dateToday a {
+ font-weight: bold;
+}
+
+.calendar td.dateUsedStats,.calendar td.dateUsedStats a {
+ color: #2E85FF;
+ border-color: #2E85FF;
+}
+
+.calendar td.calendar_unselectable {
+ color: #F2F7FF;
+}
+
+.calendar {
+ line-height: 1.33;
+}
+
+#otherPeriods a {
+ text-decoration: none;
+}
+
+#otherPeriods a:hover {
+ text-decoration: underline;
+}
+
+#currentPeriod {
+ border-bottom: 1px dotted #520202;
+}
+
+.hoverPeriod {
+ cursor: pointer;
+ font-weight: bold;
+ border-bottom: 1px solid #520202;
+}
+
+/* OTHER */
+#loadingError {
+ font-weight: bold;
+ font-size: 1.1em;
+ color: #F88D22;
+ padding: 0.5em;
+ margin-left: 30%;
+ display: none;
+}
+
+#loadingPiwik {
+ font-weight: bold;
+ font-size: 1.1em;
+ color: #193B6C;
+ padding: 0.5em;
+ margin-left: 30%;
+}
+
+#bar,#user {
+ font-family: arial, sans-serif !important;
+ height: 20px;
+ padding: 4px 10px 0px !important;
+ background-color: #FFFFFF;
+ font-size: 13px;
+ padding-top: 4px !important;
+}
+
+#bar {
+ float: left;
+ height: 22px;
+ padding-left: 10px;
+}
+
+.bar-elem {
+ height: 22px;
+ margin-right: 0.73em;
+ vertical-align: top;
+ color: #000000;
+ margin-bottom: 0px;
+}
+
+.line {
+ left: 0pt;
+ position: absolute;
+ top: 30px;
+ width: 100%;
+ border-top: 1px solid #C9D7F1;
+ font-size: 0pt;
+ height: 0pt;
+}
+
+#periodSelection,#periodSelection a {
+ color: #8D92AA;
+}
+
+#messageToUsers,#messageToUsers a {
+ color: red;
+ font-size: 0.9em;
+ text-decoration: none;
+ width: 100%;
+}
+
+.sparkline {
+ vertical-align: middle;
+ padding-right: 10px;
+}
+
+/* top right bar */
+#loggued {
+ float: right;
+ text-align: right;
+ margin-right: 20px;
+ padding-bottom: 5px;
+ padding-top: 5px;
+ padding-left: 5px;
+ border-bottom: 1px dotted #E2E3FE;
+ border-left: 1px dotted #E2E3FE;
+}
+
+#loggued form {
+ display: inline;
+}
+
+#javascriptDisable,#javascriptDisable a {
+ font-weight: bold;
+ color: #F88D22;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/templates/top_bar.tpl b/plugins/CoreHome/templates/top_bar.tpl
new file mode 100644
index 0000000000..7627d6b745
--- /dev/null
+++ b/plugins/CoreHome/templates/top_bar.tpl
@@ -0,0 +1,31 @@
+<div id="bar">
+<span class="bar-elem"><b>Your Dashboard</b></span>
+<span class="bar-elem"><a href='?module=CoreAdminHome&amp;action=showInContext&amp;moduleToLoad=API&amp;actionToLoad=listAllAPI&amp;module=CoreAdminHome&amp;action=showInContext'>API</a></span>
+<span class="bar-elem"><a href='?module=Widgetize'>Widgets</a></span>
+<span class="bar-elem"><a href='?module=Feedback&amp;action=index&amp;keepThis=true&amp;TB_iframe=true&amp;height=400&amp;width=320' title="Send us feedback" class="thickbox">Send us feedback</a></span>
+</div>
+
+
+<div align="right">
+<div id="user" align="right" width="100%" style="padding: 0pt 0pt 4px; font-size: 84%;">
+<nobr>
+<form action="{url idSite=null}" method="get" id="siteSelection">
+<small>
+ <strong>{$userLogin}</strong>
+ |
+<a href='?module=CoreAdminHome'>Admin</a> |
+<span id="sitesSelection">Site <select name="idSite" onchange='javascript:this.form.submit()'>
+ <optgroup label="Sites">
+ {foreach from=$sites item=info}
+ <option label="{$info.name}" value="{$info.idsite}" {if $idSite==$info.idsite} selected="selected"{/if}>{$info.name}</option>
+ {/foreach}
+ </optgroup>
+</select>
+{hiddenurl idSite=null}
+</span> | {if $userLogin=='anonymous'}<a href='?module=Login'>{'Login_LogIn'|translate}</a>{else}<a href='?module=Login&amp;action=logout'>{'Login_Logout'|translate}</a>{/if}
+</small>
+</form>
+</nobr>
+</div>
+</div>
+
diff --git a/plugins/CorePluginsAdmin/Controller.php b/plugins/CorePluginsAdmin/Controller.php
new file mode 100644
index 0000000000..2e3a673671
--- /dev/null
+++ b/plugins/CorePluginsAdmin/Controller.php
@@ -0,0 +1,65 @@
+<?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: Controller.php 169 2008-01-14 05:41:15Z matt $
+ *
+ * @package Piwik_ExamplePlugin
+ */
+
+
+
+/**
+ *
+ * @package Piwik_ExamplePlugin
+ */
+class Piwik_CorePluginsAdmin_Controller extends Piwik_Controller
+{
+ function index()
+ {
+ Piwik::checkUserIsSuperUser();
+
+ $listPlugins = Piwik_PluginsManager::getInstance()->readPluginsDirectory();
+
+ $loadedPlugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins();
+ $plugins = array();
+
+ foreach($listPlugins as $pluginName)
+ {
+ $oPlugin = Piwik_PluginsManager::getInstance()->loadPlugin($pluginName);
+ $plugins[$pluginName]= array( 'activated' => Piwik_PluginsManager::getInstance()->isPluginEnabled($pluginName),
+ 'alwaysActivated' => Piwik_PluginsManager::getInstance()->isPluginAlwaysActivated($pluginName),
+ 'info' => $oPlugin->getInformation()
+ );
+ }
+
+ $view = new Piwik_View('CorePluginsAdmin/templates/manage.tpl');
+
+ $view->pluginsName = $plugins;
+
+ echo $view->render();
+ }
+
+ function deactivate()
+ {
+ Piwik::checkUserIsSuperUser();
+
+ $pluginName = Piwik_Common::getRequestVar('pluginName', null, 'string');
+ Piwik_PluginsManager::getInstance()->deactivatePlugin($pluginName);
+
+ Piwik_Url::redirectToUrl('index.php?module=CoreAdminHome&action=showInContext&moduleToLoad=CorePluginsAdmin');
+
+ }
+ function activate()
+ {
+ Piwik::checkUserIsSuperUser();
+
+ $pluginName = Piwik_Common::getRequestVar('pluginName', null, 'string');
+ Piwik_PluginsManager::getInstance()->activatePlugin($pluginName);
+
+ Piwik_Url::redirectToUrl('index.php?module=CoreAdminHome&action=showInContext&moduleToLoad=CorePluginsAdmin');
+
+ }
+}
diff --git a/plugins/CorePluginsAdmin/CorePluginsAdmin.php b/plugins/CorePluginsAdmin/CorePluginsAdmin.php
new file mode 100644
index 0000000000..dc301c29fe
--- /dev/null
+++ b/plugins/CorePluginsAdmin/CorePluginsAdmin.php
@@ -0,0 +1,32 @@
+<?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: ExamplePlugin.php 169 2008-01-14 05:41:15Z matt $
+ *
+ * @package Piwik_CorePluginsAdmin
+ */
+
+class Piwik_CorePluginsAdmin extends Piwik_Plugin
+{
+ public function getInformation()
+ {
+ return array(
+ // name must be the className prefix!
+ 'name' => 'CorePluginsAdmin',
+ 'description' => 'Plugins Administration Interface.',
+ 'author' => 'Piwik',
+ 'homepage' => 'http://piwik.org/',
+ 'version' => '0.1',
+ );
+ }
+
+ function postLoad()
+ {
+ Piwik_AddAdminMenu(Piwik_Translate('CorePluginsAdmin_MenuPlugins'), array('module' => 'CorePluginsAdmin'));
+ }
+}
+
+
diff --git a/plugins/CorePluginsAdmin/templates/manage.tpl b/plugins/CorePluginsAdmin/templates/manage.tpl
new file mode 100644
index 0000000000..11c0be2c01
--- /dev/null
+++ b/plugins/CorePluginsAdmin/templates/manage.tpl
@@ -0,0 +1,135 @@
+
+{literal}
+<style>
+.widefat {
+ border-width: 1px;
+ border-style: solid;
+ border-collapse: collapse;
+ width: 100%;
+ clear: both;
+ margin: 0;
+}
+
+.widefat a {
+ text-decoration: none;
+}
+
+.widefat abbr {
+ white-space: nowrap;
+}
+
+.widefat td, .widefat th {
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
+ border-bottom-color: #ccc;
+ font-size: 11px;
+ vertical-align: text-top;
+}
+
+.widefat td {
+ padding: 7px 15px 9px 10px;
+ vertical-align: top;
+}
+
+.widefat th {
+ padding: 9px 15px 6px 10px;
+ text-align: left;
+ line-height: 1.3em;
+}
+
+.widefat th input {
+ margin: 0 0 0 8px;
+ padding: 0;
+}
+
+.widefat .check-column {
+ text-align: right;
+ width: 1.5em;
+ padding: 0;
+
+}
+.widefat {
+ border-color: #ccc;
+}
+
+.widefat tbody th.check-column {
+ padding: 8px 0 22px;
+}
+.widefat .num {
+ text-align: center;
+}
+.widefat td, .widefat th, div#available-widgets-filter, ul#widget-list li.widget-list-item, .commentlist li {
+ border-bottom-color: #ccc;
+}
+
+.widefat thead, .thead {
+ background-color: #464646;
+ color: #d7d7d7;
+}
+
+td.action-links, th.action-links {
+ text-align: right;
+}
+
+#plugins .name {
+ font-weight: bold;
+}
+
+a {
+color:#2583AD;
+}
+#plugins .active {
+ background-color: #ECF9DD;
+}
+
+
+</style>
+{/literal}
+
+<div style="max-width:980px;">
+
+<h2>Plugins Management</h2>
+<p>Plugins extend and expand the functionality of Piwik. Once a plugin is installed, you may activate it or deactivate it here.</p>
+<table class="widefat">
+ <thead>
+ <tr>
+ <th>Plugin</th>
+ <th class="num">Version</th>
+ <th>Description</th>
+ <th class="status">Status</th>
+ <th class="action-links">Action</th>
+ </tr>
+ </thead>
+ <tbody id="plugins">
+ {foreach from=$pluginsName key=name item=plugin}
+ <tr class={if $plugin.activated}"active"{else}class="deactivate"{/if}>
+ <td class="name">
+ {if isset($plugin.info.homepage)}<a title="Plugin Homepage" href="{$plugin.info.homepage}">{/if}
+ {$name}
+ {if isset($plugin.info.homepage)}</a>{/if}
+ </td>
+ <td class="vers">{$plugin.info.version}</td>
+ <td class="desc">
+ {$plugin.info.description}
+ &nbsp;<cite>By
+ {if isset($plugin.info.author_homepage)}<a title="Author Homepage" href="{$plugin.info.author_homepage}">{/if}
+ {$plugin.info.author}{if isset($plugin.info.author_homepage)}</a>{/if}.</cite>
+ </td>
+ <td class="status">
+ {if $plugin.alwaysActivated}<span title="{'CorePluginsAdmin_ActivatedHelp'|translate}" class="active">Active</span>
+ {elseif $plugin.activated}Active
+ {else}Inactive{/if}
+ </td>
+
+ <td class="togl action-links" {if $plugin.alwaysActivated}title="{'CorePluginsAdmin_ActivatedHelp'|translate}"{/if}>
+ {if $plugin.alwaysActivated} <center>-</center>
+ {elseif $plugin.activated}<a href=?module=CorePluginsAdmin&action=deactivate&pluginName={$name}>{'CorePluginsAdmin_Deactivate'|translate}</a>
+ {else}<a href=?module=CorePluginsAdmin&action=activate&pluginName={$name}>{'CorePluginsAdmin_Activate'|translate}</a>{/if}
+ </td>
+ </tr>
+{/foreach}
+
+</tbody>
+</table>
+
+</div> \ No newline at end of file