[Fusionforge-commits] FusionForge branch master updated. 2971c5eadd6851b1441902c9dccf3894f86b1c22

Franck VILLAUME nerville at fusionforge.org
Fri Jul 26 14:30:06 CEST 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "FusionForge".

The branch, master has been updated
       via  2971c5eadd6851b1441902c9dccf3894f86b1c22 (commit)
       via  5c97cdfc0f8ff6bc5e3043f744904af15ed4bd47 (commit)
       via  1317114d850d5954fd0abd6a4fe26ca1866d0052 (commit)
       via  024664e88174a326b5cbe51dd325cc4fa6c24cbd (commit)
       via  1842b4087a5b911d498ca1c83c7e394bcaa0226a (commit)
       via  39577e35f784a7981d382253811d97eb0100c204 (commit)
       via  841592d378b60f11c2cecbf134d6ab674f0c3aa5 (commit)
       via  2ecf0d4e72750ea9c255dee4e8f7c73ef00039a2 (commit)
       via  a342601a8c4f2a91684cb7e012f8411ce417434a (commit)
       via  d021dce5da87313ee3ca251fb7abde8a1c0f530f (commit)
       via  31c907b752c0bd83376535c8185947a00aabd20f (commit)
       via  768dc711285b862f229f84f513b1c935be1219f2 (commit)
       via  edd13b7c1ab61cf39454f5e87f3e4d0aa371c075 (commit)
       via  de8333953d9657372d63552c55f4dc28db7d163f (commit)
       via  d025ef41db220441ad6f52b1718efc69630dc672 (commit)
       via  1530ea3da8fb72ca16c174889c442147d86dcb47 (commit)
       via  fb3c4b0962dcabc8b2abcf254e3e2d92cd3d7f3c (commit)
       via  19fadcfcc299eefb6469da253cb27beab5f45c91 (commit)
       via  fc21f7406c94eae0000c1dd4ff7ee9d9dfb840d5 (commit)
       via  f51ecfec852ab36ef8608515b2bcef0b5d707ebb (commit)
       via  513794c52889d407676df3dd5536e3eec300b082 (commit)
       via  001a3f5a442d4acf5b1bb7385906fa95568d93b5 (commit)
       via  00d70bdcf746e995c04a3ba7890a573e05282d8f (commit)
       via  66c818698b777685adcb8c91d595671f2768aafe (commit)
       via  b921895f4b8276776ba1ced08943ec7e9bb80ac2 (commit)
       via  3f6109b8b2fc08c7ebd02809f44a3da20d7e06fd (commit)
       via  96a4b875c0e1852bed04445a887c5b959d4e446d (commit)
       via  b09d0bfc0df81d1909e5bb78ee4c14591b147164 (commit)
       via  27ff0144e8322f5190d62da70184bc6170443a8d (commit)
       via  d1377a369d4821f061f1d55aa5d29faf03903086 (commit)
       via  2e4e74bbb4a06f14955d8a3e7d18b974aa439f32 (commit)
       via  948aa59b5096eef132ceb909de4a0d6a9e55472b (commit)
       via  8211a9b38d8157179e9b1668db9d752326375286 (commit)
       via  56c1e6fec238466523b119721a1a42e707589365 (commit)
       via  04349af545f045b474a48307dc724a18ec667c6e (commit)
       via  ebfd63e4880878c9f18a2e816233f7cd8ad983be (commit)
       via  734c08356d8a020bd25cb68a156b53fe3bad417e (commit)
       via  528128d402c46e3977b0ecdad81089f93ea0fbdf (commit)
       via  af1dd4ca91a999a2368c4aeb1d69572795cb66d2 (commit)
       via  e39d6b3aa88d3f7519c6391addd562f8a5cb32a0 (commit)
       via  44d5d37cffba4f4d79c0ae341473883fddff2c34 (commit)
       via  486bdf382926cb00275fe24851d24321634094fc (commit)
       via  46af446c40b197f640baaba4e7d9db0ae2cff541 (commit)
       via  13287103254e334532c5c85b9bdd9340e7bc5a14 (commit)
       via  046e007c1d2fb9902ade8a0fa06865286bfc3977 (commit)
       via  5e0ec9dfea7b49a3f6ede40db23bcc7c199aac80 (commit)
       via  f78927fcc564107261595de6b5cda0ed88ccb05d (commit)
       via  473fc58811178fd54e1fdaa9da096f831de3831b (commit)
       via  7ca249869e53d45d59662ce65d57d3145d3dfe10 (commit)
       via  5bdd518d0eecc689587bc4397fa395bf74908134 (commit)
       via  9fe97dbe37d305c3cfc78963600a89cfe67b9014 (commit)
       via  6751bc261c6162a61a3dab874a9fe4e954eae184 (commit)
       via  250e8bef175b62dfff44cfb605f8d4a3127c1f71 (commit)
       via  dfc238b49a84498b6aa372d2b85ce8f595637a4e (commit)
       via  cd41873a8a437246f84242d4bca4afdd331d0438 (commit)
       via  411455f403a404eed0dfe84f89dfd4c3d730eb48 (commit)
       via  5ed9a1b7d32e8a3b8de53e1b3fdf386e899c6560 (commit)
       via  0deca794e8ff3b584f4e7c4d70fee75251ea9169 (commit)
       via  3946310ee35d6b60d75a1b22b5210babeb61f5bd (commit)
       via  7e9d99587154f0e585ca4c594762273084029bac (commit)
       via  0f71be117facb4c4a63c4d14793dbdb9979c0198 (commit)
       via  3eeb1824e364559e7299b1b13dae0eda81869852 (commit)
       via  06b0a17ce20af6b1f45f3ee14912726c59646c96 (commit)
       via  040b44a71f36c76ceb02e4d0912fe03e82d68fa9 (commit)
       via  8c4f50bf598319ea0b7e31d0838a1a297e5f8309 (commit)
       via  256b9c50708fa9460fd51f9d06d2d807a5de6e6c (commit)
       via  03ee3a2a8eaf883021f2f18a33f302ed25e9ad47 (commit)
       via  91666e96c66a54d32b962ea24c6d0024b6c9fd9f (commit)
       via  8b20750e417986388a17b6193f1db71bd25e4cb9 (commit)
       via  17875240c62ea91cb9490363bc290dca2f6de7ea (commit)
       via  3d93e7a79b55174436f768f32ac32dc4adf09b5f (commit)
       via  63f9a40464ebaa0694b3f73eafd852455250fd55 (commit)
       via  471e4d9d918542e54fe95d292d5e1f1272ab8aad (commit)
       via  0aff02f150c6c0df841e7234d9f445abbc445762 (commit)
       via  801e5d60ff032787fd6ac8156061429ca4a8e536 (commit)
       via  d058c513025bf1e558273a5e4f62bff0b3fc7941 (commit)
       via  6cee093606b1e385fba5878bd82f67b8c5451693 (commit)
      from  d70c22e393b9085be068d955f095a3aae4d1d145 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 2971c5eadd6851b1441902c9dccf3894f86b1c22
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 26 14:22:37 2013 +0200

    jqplot: fix display and use gettext when possible

diff --git a/src/vendor/jquery-teamwork-gantt/ganttMaster.js b/src/vendor/jquery-teamwork-gantt/ganttMaster.js
index ac8c9ac..764fe6e 100644
--- a/src/vendor/jquery-teamwork-gantt/ganttMaster.js
+++ b/src/vendor/jquery-teamwork-gantt/ganttMaster.js
@@ -51,8 +51,11 @@ function GanttMaster() {
   var self = this;
 }
 
-GanttMaster.prototype.init = function(place) {
+GanttMaster.prototype.init = function(place, editorratio, calendarratio, splitterposition) {
   this.element = place;
+  this.editorratio = editorratio;
+  this.calendarratio = calendarratio;
+  this.splitterposition = splitterposition;
 
   var self=this;
 
@@ -61,14 +64,14 @@ GanttMaster.prototype.init = function(place) {
 
   //create editor
   this.editor = new GridEditor(this);
-  this.editor.element.width(place.width() * .9 - 10);
+  this.editor.element.width(place.width() * editorratio - 10);
   place.append(this.editor.element);
 
   //create gantt
-  this.gantt = new Ganttalendar("m", new Date().getTime() - 3600000 * 24 * 2, new Date().getTime() + 3600000 * 24 * 15, this, place.width() * .6);
+  this.gantt = new Ganttalendar("m", new Date().getTime() - 3600000 * 24 * 2, new Date().getTime() + 3600000 * 24 * 15, this, place.width() * calendarratio);
 
   //setup splitter
-  var splitter = $.splittify.init(place, this.editor.element, this.gantt.element, 70);
+  var splitter = $.splittify.init(place, this.editor.element, this.gantt.element, splitterposition);
   splitter.secondBox.css("overflow-y", "auto").scroll(function() {
     splitter.firstBox.scrollTop(splitter.secondBox.scrollTop());
   });
diff --git a/src/www/pm/ganttpage.php b/src/www/pm/ganttpage.php
index c221de0..667317b 100644
--- a/src/www/pm/ganttpage.php
+++ b/src/www/pm/ganttpage.php
@@ -205,8 +205,8 @@ echo '<div id="workSpace" style="padding:0px; overflow-y:auto; overflow-x:hidden
 	jQuery(function() {
 		ge = new GanttMaster();
 		var workSpace = jQuery("#workSpace");
-		workSpace.css({width:jQuery(window).width() - 20, height:jQuery(window).height() - 100});
-		ge.init(workSpace);
+		workSpace.css({width:jQuery(window).width() - 40, height:jQuery(window).height() - 100});
+		ge.init(workSpace, 0.5, 0.5, 50);
 		loadI18n();
 		ge.loadProject({
 			"tasks":
@@ -240,14 +240,13 @@ echo '<div id="workSpace" style="padding:0px; overflow-y:auto; overflow-x:hidden
     <tr style="height:40px">
       <th class="gdfColHeader" style="width:15px;"></th>
       <th class="gdfColHeader" style="width:25px;"></th>
-      <th class="gdfColHeader gdfResizable">category</th>
-      <th class="gdfColHeader gdfResizable"></th>
-      <th class="gdfColHeader gdfResizable">task summary</th>
-      <th class="gdfColHeader gdfResizable" style="width:80px;">start</th>
-      <th class="gdfColHeader gdfResizable" style="width:80px;">end</th>
-      <th class="gdfColHeader gdfResizable" style="width:25px;">dur.</th>
-      <th class="gdfColHeader gdfResizable" style="width:25px;">dep.</th>
-      <th class="gdfColHeader gdfResizable">assignees</th>
+      <th class="gdfColHeader gdfResizable"><?php echo _('category'); ?></th>
+      <th class="gdfColHeader gdfResizable"><?php echo _('task summary'); ?></th>
+      <th class="gdfColHeader gdfResizable" style="width:80px;"><?php echo _('start'); ?></th>
+      <th class="gdfColHeader gdfResizable" style="width:80px;"><?php echo _('end'); ?></th>
+      <th class="gdfColHeader gdfResizable" style="width:25px;"><?php echo _('dur.'); ?></th>
+      <th class="gdfColHeader gdfResizable" style="width:25px;"><?php echo _('dep.'); ?></th>
+      <th class="gdfColHeader gdfResizable"><?php echo _('assignees'); ?></th>
     </tr>
     </thead>
   </table>
@@ -255,13 +254,10 @@ echo '<div id="workSpace" style="padding:0px; overflow-y:auto; overflow-x:hidden
 
   <div class="__template__" type="TASKROW"><!--
   <tr taskId="(#=obj.id#)" class="taskEditRow" level="(#=level#)">
-    <th class="gdfCell edit" align="right" style="cursor:pointer;"><span class="taskRowIndex">(#=obj.getRow()+1#)</span></th>
+    <td class="gdfCell edit" align="right" style="cursor:pointer;"><span class="taskRowIndex">(#=obj.getRow()+1#)</span></td>
     <td class="gdfCell" align="center"><div class="taskStatus cvcColorSquare" status="(#=obj.status#)"></div></td>
     <td class="gdfCell"><input type="text" name="code" value="(#=obj.code?obj.code:''#)"></td>
-    <td class="gdfCell"><span>-</span></td>
-
     <td class="gdfCell indentCell" style="padding-left:(#=obj.level*10#)px;"><input type="text" name="name" value="(#=obj.name#)" style="(#=obj.level>0?'border-left:2px dotted orange':''#)"></td>
-
     <td class="gdfCell"><input type="text" name="start"  value="" class="date"></td>
     <td class="gdfCell"><input type="text" name="end" value="" class="date"></td>
     <td class="gdfCell"><input type="text" name="duration" value="(#=obj.duration#)"></td>

commit 5c97cdfc0f8ff6bc5e3043f744904af15ed4bd47
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 26 11:54:14 2013 +0200

    jqplot: gantt, use theme

diff --git a/src/vendor/jquery-teamwork-gantt/platform.css b/src/vendor/jquery-teamwork-gantt/platform.css
index 2d00856..0adfd52 100644
--- a/src/vendor/jquery-teamwork-gantt/platform.css
+++ b/src/vendor/jquery-teamwork-gantt/platform.css
@@ -24,7 +24,8 @@
   body styles
   -------------------------------------------------------
   */
-BODY, TBODY {
+/* Fusionforge : do not override theme */
+/*BODY, TBODY {
   font-family: arial;
   font-size: 14px;
   margin: 0;
@@ -34,7 +35,7 @@ BODY, TBODY {
 
 BODY {
   background-color: #91B4B7; 
-}
+}*/
 
 a {
   text-decoration: none;
diff --git a/src/www/pm/ganttpage.php b/src/www/pm/ganttpage.php
index 1d624b1..c221de0 100644
--- a/src/www/pm/ganttpage.php
+++ b/src/www/pm/ganttpage.php
@@ -29,11 +29,12 @@ require_once $gfcommon.'pm/ProjectTaskFactory.class.php';
 require_once $gfwww.'include/unicode.php';
 require_once $gfwww.'include/html.php';
 
+echo $HTML->Theme();
 html_use_jqueryteamworkgantt();
 html_generic_fileheader(_('Gantt Chart'));
 echo $HTML->getJavascripts();
 echo $HTML->getStylesheets();
-echo '</head><body style="background-color: #fff" >';
+echo '</head><body>';
 
 /* define global vars */
 global $pg, $g;

commit 1317114d850d5954fd0abd6a4fe26ca1866d0052
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 26 11:44:09 2013 +0200

    jqplot: gantt, use generic function for header and footer

diff --git a/src/www/include/html.php b/src/www/include/html.php
index caf2651..c24599a 100644
--- a/src/www/include/html.php
+++ b/src/www/include/html.php
@@ -6,7 +6,7 @@
  * Copyright 2010 (c) FusionForge Team
  * Copyright (C) 2010-2012 Alain Peyrat - Alcatel-Lucent
  * Copyright 2011, Franck Villaume - Capgemini
- * Copyright 2011-2012, Franck Villaume - TrivialDev
+ * Copyright 2011-2013, Franck Villaume - TrivialDev
  * Copyright © 2011, 2012
  *	Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
@@ -477,6 +477,26 @@ function html_use_jqueryjqplotplugindateAxisRenderer() {
 	use_javascript('/scripts/jquery-jqplot/plugins/jqplot.dateAxisRenderer.js');
 }
 
+function html_use_jqueryteamworkgantt() {
+	html_use_jqueryui();
+	use_javascript('/scripts/jquery-teamwork-gantt/libs/jquery.livequery.min.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/libs/jquery.timers.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/libs/platform.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/libs/date.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/libs/date.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/libs/i18nJs.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/libs/dateField/jquery.dateField.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/libs/JST/jquery.JST.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/ganttUtilities.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/ganttTask.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/ganttDrawer.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/ganttGridEditor.js');
+	use_javascript('/scripts/jquery-teamwork-gantt/ganttMaster.js');
+	use_stylesheet('/scripts/jquery-teamwork-gantt/platform.css');
+	use_stylesheet('/scripts/jquery-teamwork-gantt/libs/dateField/jquery.dateField.css');
+	use_stylesheet('/scripts/jquery-teamwork-gantt/gantt.css');
+}
+
 /**
  * html_build_select_box_from_arrays() - Takes two arrays, with the first array being the "id" or value and the other
  * array being the text you want displayed.
diff --git a/src/www/pm/ganttpage.php b/src/www/pm/ganttpage.php
index c64a005..1d624b1 100644
--- a/src/www/pm/ganttpage.php
+++ b/src/www/pm/ganttpage.php
@@ -25,38 +25,15 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-echo '<' . '?xml version="1.0" encoding="utf-8" ?' . ">\n" .
-    $sysDTDs['transitional']['doctype']; ?>
-<html <?php echo $sysXMLNSs; ?> xml:lang="en">
-
-  <head>
-	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-	<title><?php echo _('Gantt Chart');?></title>
-	<link rel=stylesheet href="/scripts/jquery-teamwork-gantt/platform.css" type="text/css">
-	<link rel=stylesheet href="/scripts/jquery-teamwork-gantt/libs/dateField/jquery.dateField.css" type="text/css">
-	<link rel=stylesheet href="/scripts/jquery-teamwork-gantt/gantt.css" type="text/css">
-	
-	<script src="/scripts/jquery/jquery-1.8.3.js"></script>
-	<script src="/scripts/jquery-ui/js/jquery-ui-1.9.2.custom.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/libs/jquery.livequery.min.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/libs/jquery.timers.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/libs/platform.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/libs/date.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/libs/i18nJs.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/libs/dateField/jquery.dateField.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/libs/JST/jquery.JST.js"></script>
-
-	<script src="/scripts/jquery-teamwork-gantt/ganttUtilities.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/ganttTask.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/ganttDrawer.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/ganttGridEditor.js"></script>
-	<script src="/scripts/jquery-teamwork-gantt/ganttMaster.js"></script>
-  </head>
-  <body style="background-color: #fff" >
-<?php
-
 require_once $gfcommon.'pm/ProjectTaskFactory.class.php';
 require_once $gfwww.'include/unicode.php';
+require_once $gfwww.'include/html.php';
+
+html_use_jqueryteamworkgantt();
+html_generic_fileheader(_('Gantt Chart'));
+echo $HTML->getJavascripts();
+echo $HTML->getStylesheets();
+echo '</head><body style="background-color: #fff" >';
 
 /* define global vars */
 global $pg, $g;
@@ -68,7 +45,7 @@ $_order = getIntFromRequest('_order');
 $_resolution = getStringFromRequest('_resolution');
 $_status = getIntFromRequest('_status', 100);
 $_order = getStringFromRequest('_order');
-$max_rows = getIntFromRequest('max_rows',50);
+$max_rows = getIntFromRequest('max_rows', 50);
 
 $engine = RBACEngine::getInstance();
 $techs = $engine->getUsersByAllowedAction('pm', $pg->getID(), 'tech');
@@ -361,7 +338,6 @@ echo '<div id="workSpace" style="padding:0px; overflow-y:auto; overflow-x:hidden
 
   <div class="__template__" type="ASSIGNMENT_ROW"><!--
   --></div>
-
-</div>
-</body>
-</html>
+<?php
+echo $HTML->footer(false);
+?>
\ No newline at end of file

commit 024664e88174a326b5cbe51dd325cc4fa6c24cbd
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 26 10:54:45 2013 +0200

    jqplot: remove unused case in pm

diff --git a/src/www/pm/task.php b/src/www/pm/task.php
index 630ec8e..a60916d 100644
--- a/src/www/pm/task.php
+++ b/src/www/pm/task.php
@@ -7,6 +7,7 @@
  * Copyright 2009, Roland Mas
  * Copyright 2010, Franck Villaume - Capgemini
  * Copyright (C) 2012 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -370,14 +371,6 @@ switch (getStringFromRequest('func')) {
 	}
 
 	//
-	//	Show a gantt chart
-	//
-	case 'ganttchart' : {
-		include $gfwww.'pm/gantt.php';
-		break;
-	}
-
-	//
 	//	View a specific existing task
 	//
 	case 'detailtask' : {

commit 1842b4087a5b911d498ca1c83c7e394bcaa0226a
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 26 10:49:01 2013 +0200

    jqplot: remove old jpgraph gantt

diff --git a/src/www/pm/gantt.php b/src/www/pm/gantt.php
deleted file mode 100644
index 86e45ae..0000000
--- a/src/www/pm/gantt.php
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-/**
- * Project Management Facility
- *
- * Copyright 2010, FusionForge Team
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-if (!file_exists(forge_get_config('jpgraph_path').'/jpgraph.php')) {
-	exit_error(_('Package JPGraph not installed'),'pm');
-}
-
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_gantt.php');
-require_once $gfcommon.'pm/ProjectTaskFactory.class.php';
-require_once $gfwww.'include/unicode.php';
-
-$ptf = new ProjectTaskFactory($pg);
-if (!$ptf || !is_object($ptf)) {
-	exit_error(_('Could Not Get ProjectTaskFactory'),'pm');
-} elseif ($ptf->isError()) {
-	exit_error(_('Error getting PTF: ').$ptf->getErrorMessage(),'pm');
-}
-
-$offset = getIntFromRequest('offset');
-$_assigned_to = getIntFromRequest('_assigned_to');
-$_status = getIntFromRequest('_status');
-$_order = getStringFromRequest('_order');
-$_resolution = getStringFromRequest('_resolution');
-$_category_id = getIntFromRequest('_category_id');
-$_size = getIntFromRequest('_size');
-$max_rows = getIntFromRequest('max_rows',50);
-
-$ptf->setup($offset,$_order,$max_rows,'custom',$_assigned_to,$_status,$_category_id);
-if ($ptf->isError()) {
-	exit_error(_('Error in PTF: ').$ptf->getErrorMessage(),'pm');
-}
-
-$pt_arr =& $ptf->getTasks();
-if ($ptf->isError()) {
-	exit_error($ptf->getErrorMessage(),'pm');
-}
-
-if ($_size==640) {
-	$graph  = new GanttGraph (640,480, "auto");
-} elseif ($_size==1024) {
-	$graph  = new GanttGraph (1024,768, "auto");
-} elseif ($_size==1600) {
-	$graph  = new GanttGraph (1600,1200, "auto");
-} else {
-	$graph  = new GanttGraph (800,600, "auto");
-}
-
-//$graph->SetShadow();
-$graph->SetMargin(10,10,25,10);
-
-// Add title and subtitle
-$graph->title->Set($pg->getName());
-
-if (isset($gantt_title_font_family)) {
-	$graph->title->SetFont( constant($gantt_title_font_family),
-		constant($gantt_title_font_style), $gantt_title_font_size);
-}
-
-//$graph->subtitle-> Set("(Draft version)");
-
-// Show day, week and month scale
-if ($_resolution == 'Days') {
-	$graph->ShowHeaders( GANTT_HDAY |  GANTT_HWEEK |  GANTT_HMONTH);
-} elseif ($_resolution == 'Weeks') {
-	$graph->ShowHeaders( GANTT_HWEEK |  GANTT_HMONTH);
-} elseif ($_resolution == 'Months') {
-	$graph->ShowHeaders( GANTT_HMONTH | GANTT_HYEAR);
-} else {
-	$graph->ShowHeaders( GANTT_HYEAR);
-}
-
-// Instead of week number show the date for the first day in the week
-// on the week scale
-$graph->scale->week->SetStyle(WEEKSTYLE_FIRSTDAY);
-
-// Make the week scale font smaller than the default
-if (isset($gantt_title_font_family)) {
-	$graph->scale->week->SetFont( constant($gantt_title_font_family), FS_NORMAL, 9);
-	$graph->scale->month->SetFont( constant($gantt_title_font_family), FS_NORMAL, 9);
-}
-
-// Use the short name of the month together with a 2 digit year
-// on the month scale
-$graph->scale->month->SetStyle( MONTHSTYLE_SHORTNAME);
-
-$rows=count($pt_arr);
-
-for ($i=0; $i<$rows; $i++) {
-	// Format the bar for the first activity
-	// ($row,$title,$startdate,$enddate)
-	$activity[$i] = new GanttBar ($i, convert_unicode($pt_arr[$i]->getSummary()), date('Y-m-d',$pt_arr[$i]->getStartDate()), date('Y-m-d',$pt_arr[$i]->getEndDate()-86400));
-
-	// Yellow diagonal line pattern on a red background
-	$activity[$i]->SetPattern(BAND_RDIAG, "yellow");
-	$activity[$i]->SetFillColor ("red");
-	$activity[$i]->progress->Set( (( $pt_arr[$i]->getPercentComplete() ) ? ($pt_arr[$i]->getPercentComplete()/100) : 0));
-	$activity[$i]->progress->SetPattern(BAND_RDIAG, "blue");
-
-	if (isset($gantt_task_font_family)) {
-		$activity[$i]->title->SetFont( constant($gantt_task_font_family),
-			constant($gantt_task_font_style), $gantt_task_font_size);
-	}
-
-	// Finally add the bar to the graph
-	$graph->Add( $activity[$i] );
-}
-
-//echo $rows;
-$todayline = new GanttVLine(date('Y-m-d',time()),"Today");
-$todayline ->SetDayOffset (0.5);
-$graph->Add( $todayline);
-
-// Display the Gantt chart
-$graph->Stroke();
diff --git a/src/www/pm/ganttofuser.php b/src/www/pm/ganttofuser.php
deleted file mode 100644
index d32ddcd..0000000
--- a/src/www/pm/ganttofuser.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-/**
- * FusionForge : Project Management Facility
- *
- * Copyright 2010, FusionForge Team
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_gantt.php');
-require_once $gfcommon.'pm/ProjectTasksForUser.class.php';
-
-
-if (!file_exists(forge_get_config('jpgraph_path').'/jpgraph.php')) {
-	exit_error(_('Package JPGraph not installed'),'pm');
-}
-
-if (!session_loggedin()) {
-    exit_not_logged_in();
-}
-
-//
-// The data for the graphs
-//
-$data = array();
-$progress = array();
-
-$User =& session_get_user();
-$projectTasksForUser = new ProjectTasksForUser($User);
-$userTasks =& $projectTasksForUser->getTasksByGroupProjectName();
-
-$last_group="0";
-$g_index = -1;
-$pos = 0;
-if (count($userTasks) > 0) {
-	foreach ($userTasks as $task) {
-		$projectGroup =& $task->getProjectGroup();
-		$group =& $projectGroup->getGroup();
-
-		if($projectGroup->getID() != $last_group) {
-			$last_group = $projectGroup->getID();
-
-			if ($g_index >= 0) {
-				$data[$g_index][3]=date("Y-m-d",$group_begin);
-				$data[$g_index][4]=date("Y-m-d",$group_end-86400);
-			}
-
-			$g_index = $pos;
-
-			$group_begin = $task->getStartDate();
-			$group_end = $task->getEndDate();;
-
-			$data[$pos] = array($pos,ACTYPE_GROUP,
-				"[".$group->getPublicName()."-".$projectGroup->getName()."]",
-				date("Y-m-d",$group_begin),
-				date("Y-m-d",$group_end-86400),
-				'');
-			$progress[$pos] = array($pos,$task->getPercentComplete()/100);
-			$pos = $pos + 1;
-		}
-
-		$data[$pos] = array($pos,ACTYPE_NORMAL,
-			"  - ".$task->getSummary(),
-			date("Y-m-d",$task->getStartDate()),
-			date("Y-m-d",$task->getEndDate()-86400),
-			$task->getPercentComplete()."%");
-		$progress[$pos] = array($pos,$task->getPercentComplete()/100);
-
-		if($group_begin > $task->getStartDate())
-			$group_begin = $task->getStartDate();
-		if($group_end < $task->getEndDate())
-			$group_end = $task->getEndDate();
-
-		$pos = $pos + 1;
-	}
-	if ($g_index > 0) {
-		$data[$g_index][3]=date("Y-m-d",$group_begin);
-		$data[$g_index][4]=date("Y-m-d",$group_end-86400);
-	}
-}
-
-
-//$data = array(
-//    array(0,ACTYPE_GROUP,    "Phase 1",        "2001-10-26","2001-11-23",''),
-//    array(1,ACTYPE_NORMAL,   "  Label 2",      "2001-11-01","2001-11-20",''),
-//    array(2,ACTYPE_NORMAL,   "  Label 3",      "2001-10-26","2001-11-03",''),
-//    array(3,ACTYPE_MILESTONE,"  Phase 1 Done", "2001-11-23",'M2') );
-// The constrains between the activities
-//$constrains = array(array(2,1,CONSTRAIN_ENDSTART),
-//		    array(1,3,CONSTRAIN_STARTSTART));
-
-// progress
-//$progress = array(array(1,0.4));
-
-// Create the basic graph
-$graph = new GanttGraph();
-//$graph->title->SetFont(FF_BIG5,FS_NORMAL,10);
-$graph->title->Set('Projects for '.$User->getRealName());
-
-
-// Setup scale
-$graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH | GANTT_HDAY | GANTT_HWEEK);
-$graph->scale->week->SetStyle(WEEKSTYLE_FIRSTDAY);
-
-// Add the specified activities
-//$graph->SetSimpleFont(FF_BIG5,10);
-$graph->CreateSimple($data,$constrains,$progress);
-
-$todayline = new GanttVLine(date('Y-m-d',time()),"Today");
-$todayline ->SetDayOffset (0.5);
-$graph->Add( $todayline);
-
-// .. and stroke the graph
-$graph->Stroke();
diff --git a/src/www/pm/ganttpage.php b/src/www/pm/ganttpage.php
index 19b3d2c..c64a005 100644
--- a/src/www/pm/ganttpage.php
+++ b/src/www/pm/ganttpage.php
@@ -363,19 +363,5 @@ echo '<div id="workSpace" style="padding:0px; overflow-y:auto; overflow-x:hidden
   --></div>
 
 </div>
-<?php
-echo '<noscript>';
-echo '<img src="'. getStringFromServer('PHP_SELF') .
-		'?func=ganttchart&group_id='.$group_id.
-		'&group_project_id='.$group_project_id.
-		'&_assigned_to='.$_assigned_to.
-		'&_status='.$_status.
-		'&_order='.$_order.
-		'&_resolution='.$_resolution.
-		'&_category_id='.$_category_id.
-		'&rand='.util_randnum().'" alt="'. _('Gantt Chart').'" />';
-echo '</noscript>';
-
-?>
 </body>
 </html>

commit 39577e35f784a7981d382253811d97eb0100c204
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Wed Jul 17 20:48:41 2013 +0200

    jqplot: fix gantt redraw trim, semester

diff --git a/src/www/pm/ganttpage.php b/src/www/pm/ganttpage.php
index 64abc8e..19b3d2c 100644
--- a/src/www/pm/ganttpage.php
+++ b/src/www/pm/ganttpage.php
@@ -204,11 +204,32 @@ echo '<div id="workSpace" style="padding:0px; overflow-y:auto; overflow-x:hidden
 ?>
 <script type="text/javascript">
 	var ge;
+	function loadI18n() {
+		GanttMaster.messages = {
+			"CHANGE_OUT_OF_SCOPE":"NO_RIGHTS_FOR_UPDATE_PARENTS_OUT_OF_EDITOR_SCOPE",
+			"START_IS_MILESTONE":"START_IS_MILESTONE",
+			"END_IS_MILESTONE":"END_IS_MILESTONE",
+			"TASK_HAS_CONSTRAINTS":"TASK_HAS_CONSTRAINTS",
+			"GANTT_ERROR_DEPENDS_ON_OPEN_TASK":"GANTT_ERROR_DEPENDS_ON_OPEN_TASK",
+			"GANTT_ERROR_DESCENDANT_OF_CLOSED_TASK":"GANTT_ERROR_DESCENDANT_OF_CLOSED_TASK",
+			"TASK_HAS_EXTERNAL_DEPS":"TASK_HAS_EXTERNAL_DEPS",
+			"GANTT_ERROR_LOADING_DATA_TASK_REMOVED":"GANTT_ERROR_LOADING_DATA_TASK_REMOVED",
+			"ERROR_SETTING_DATES":"ERROR_SETTING_DATES",
+			"CIRCULAR_REFERENCE":"CIRCULAR_REFERENCE",
+			"CANNOT_DEPENDS_ON_ANCESTORS":"CANNOT_DEPENDS_ON_ANCESTORS",
+			"CANNOT_DEPENDS_ON_DESCENDANTS":"CANNOT_DEPENDS_ON_DESCENDANTS",
+			"INVALID_DATE_FORMAT":"INVALID_DATE_FORMAT",
+			"TASK_MOVE_INCONSISTENT_LEVEL":"TASK_MOVE_INCONSISTENT_LEVEL",
+			"GANT_QUARTER_SHORT":"trim.",
+			"GANT_SEMESTER_SHORT":"sem."
+		};
+	}
 	jQuery(function() {
 		ge = new GanttMaster();
 		var workSpace = jQuery("#workSpace");
 		workSpace.css({width:jQuery(window).width() - 20, height:jQuery(window).height() - 100});
 		ge.init(workSpace);
+		loadI18n();
 		ge.loadProject({
 			"tasks":
 				<?php echo json_encode($transformedTasksArr); ?>,

commit 841592d378b60f11c2cecbf134d6ab674f0c3aa5
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 14 15:51:55 2013 +0200

    jqplot: implement gantt graph using jquery-taemwork-gantt library

diff --git a/src/etc/httpd.conf.d/vhost-main.inc b/src/etc/httpd.conf.d/vhost-main.inc
index 2e88d57..326b2bd 100644
--- a/src/etc/httpd.conf.d/vhost-main.inc
+++ b/src/etc/httpd.conf.d/vhost-main.inc
@@ -40,6 +40,7 @@ Alias /scripts/jquery-tipsy/ {core/source_path}/vendor/jquery-tipsy/
 Alias /scripts/jquery-storage/ {core/source_path}/vendor/jquery-storage/
 Alias /scripts/jquery-simpletreemenu/ {core/source_path}/vendor/jquery-simpletreemenu/
 Alias /scripts/jquery-jqplot/ {core/source_path}/vendor/jquery-jqplot/
+Alias /scripts/jquery-teamwork-gantt/ {core/source_path}/vendor/jquery-teamwork-gantt/
 Alias /scripts/prototype/ {core/source_path}/vendor/prototype/
 Alias /scripts/scriptaculous/ {core/source_path}/vendor/scriptaculous/
 Alias /scripts/yui/ {core/source_path}/vendor/yui/build/
diff --git a/src/vendor/jquery-teamwork-gantt/add.gif b/src/vendor/jquery-teamwork-gantt/add.gif
new file mode 100644
index 0000000..f394cae
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/add.gif differ
diff --git a/src/vendor/jquery-teamwork-gantt/alert.gif b/src/vendor/jquery-teamwork-gantt/alert.gif
new file mode 100644
index 0000000..bb8b049
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/alert.gif differ
diff --git a/src/vendor/jquery-teamwork-gantt/closeBig.png b/src/vendor/jquery-teamwork-gantt/closeBig.png
new file mode 100644
index 0000000..f0fe8a7
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/closeBig.png differ
diff --git a/src/vendor/jquery-teamwork-gantt/del.gif b/src/vendor/jquery-teamwork-gantt/del.gif
new file mode 100644
index 0000000..f2c6859
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/del.gif differ
diff --git a/src/vendor/jquery-teamwork-gantt/edit.gif b/src/vendor/jquery-teamwork-gantt/edit.gif
new file mode 100644
index 0000000..998b08c
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/edit.gif differ
diff --git a/src/vendor/jquery-teamwork-gantt/gantt.css b/src/vendor/jquery-teamwork-gantt/gantt.css
new file mode 100644
index 0000000..bf935ef
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/gantt.css
@@ -0,0 +1,323 @@
+.gdfTable {
+  table-layout: fixed;
+  border-collapse: separate;
+  border-spacing: 0;
+}
+
+.gdfTable td, .gdfTable th {
+  vertical-align: middle;
+  overflow: hidden;
+  text-overflow: clip;
+  white-space: nowrap;
+  font-size: 14px
+}
+
+.gdfCell {
+  overflow: hidden;
+  padding:4px 2px
+}
+
+.gdfColHeader {
+  min-width: 5px;
+  height: 30px;
+}
+
+.gdfCell, .gdfColHeader {
+  border-bottom: 1px solid #eee;
+  border-right: 1px solid #eee;
+}
+
+
+.ganttLines{
+  position:absolute;
+  width:100%;
+  height:1px;
+  border-top:1px solid #eee;
+  z-index:1;
+}
+
+.gdfCellInput {
+  border: 0 none;
+  font-size: 12px;
+  height: 20px;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+  background-color: #d4fbe8;
+}
+
+.gdfCellWrap {
+  border: 0 none;
+  font-size: 12px;
+  height: 17px;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+  overflow: hidden;
+
+  background-color: #ffcccc;
+}
+
+.gdfColHeaderOver {
+  opacity: .7;
+}
+
+.gdfHResizing {
+  cursor: w-resize;
+}
+
+.splitterContainer {
+  width: 100%;
+  height: 100%;
+}
+
+.splitBox1, .splitBox2 {
+  overflow-x: scroll;
+  overflow-y: hidden;
+
+  /*background-color: yellow;*/
+}
+
+.splitBox2 {
+  /*background-color: orange;*/
+}
+
+.unselectable {
+  -webkit-user-select: none;
+  -khtml-user-select: none;
+  -moz-user-select: none;
+  -o-user-select: none;
+  user-select: none;
+}
+
+.splitElement {
+  outline-style: none;
+  position: absolute;
+  height: 100%;
+}
+
+.vSplitBar {
+  width: 5px;
+  background-color: #aaa;
+  cursor: w-resize;
+  text-align: center;
+  color: white;
+}
+
+.end{
+  border-right:1px dotted #666
+}
+
+.holyH{
+    background-color: #9CB7AA;
+}
+.holy{
+  background-color: #FFF5E6;
+}
+
+
+.expcoll{
+  width:6px;
+  height:6px;
+  margin:1px;
+  padding:1px;
+  background-color:yellow;
+  display:inline-block;
+  border:1px solid gray;
+}
+.expcoll.exp{
+  display:none;
+}
+
+
+.ganttTable{
+  table-layout:fixed;
+}
+
+.ganttTable td,.ganttTable th{
+  overflow: hidden;
+  text-overflow: clip;
+  white-space: nowrap;
+}
+
+.ganttHead1,.ganttHead2{
+  height:20px;
+}
+
+.ganttHead1 th,.ganttHead2 th{
+  border-left:1px solid white;
+}
+
+.ganttToday{
+  position:absolute;
+  top:0;
+  width:1px;
+  height:100%;
+  border-left:2px dotted #13AFA5;
+}
+
+.ganttHighLight{
+  position:absolute;
+  width:100%;
+  height:28px;
+  background-color:yellow;
+  opacity:.4;
+}
+
+.ganttButtonBar{
+  position:relative;
+  padding:5px;
+}
+
+.ganttButtonBar .buttons {
+    float:left; margin:45px 0 0 40px
+}
+
+
+.ganttButtonBar .button span.teamworkIcon{
+  font-size: 150%
+}
+
+.ganttButtonSeparator{
+  border-left:1px solid gray;
+  padding-right:10px;
+  margin-left:10px;
+  font-size: 130%
+}
+
+.ganttLinks{
+  z-index:10;
+}
+
+.taskBox{
+  position:absolute;
+  height:25px;
+  margin-top:3px;
+  z-index:100;
+}
+
+.taskBox .layout {
+  height:100%;
+  color:red;
+  border-radius:2px;
+  background: #eee; /* Old browsers */
+  border:1px solid #bbb;
+}
+
+.taskBox .taskStatus {
+    left:5px;
+    top:10px;
+    position:absolute;
+    width:10px;
+    height:10px;
+}
+
+.taskBox .layout .milestone{
+  top:0px;
+  position:absolute;
+  width:18px;
+  background: url(milestone.png) no-repeat;
+  height:18px;
+  display:none;
+}
+.taskBox .layout .milestone.end{
+  right:0;
+}
+.taskBox .layout .milestone.active{
+  display:block;
+}
+
+.taskBox.hasChild .layout{
+  border-top:2px solid black;
+}
+
+.taskBox .taskProgress{
+  height:5px;
+  position:absolute;
+}
+
+.taskBox .layout.extDep{
+  background-image:url(hasExternalDeps.png);
+}
+
+
+.taskLabel{
+  position:absolute;
+  height:28px;
+  color:black;
+  text-align:right;
+  padding-right:5px;
+  overflow:hidden;
+  left:-200px;
+  width:195px;
+  white-space:nowrap;
+}
+
+
+.taskDepLine {
+  border: 1px solid #9999ff;
+  overflow: hidden;
+  position: absolute;
+}
+
+
+.taskEditRow,.emptyRow {
+  height:30px;
+}
+
+.taskEditRow input{
+  border: 0 none;
+  font-size: 14px;
+  height: 20px;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+  font-family: Arial, sans-serif
+}
+
+.taskEditRow.rowSelected td,.taskEditRow.rowSelected input{
+  background-color:#FFFF99;  
+}
+
+.taskStatusBox{
+  position:absolute;
+  width:100px;
+  height:24px;
+  border:1px solid #a0a0a0;
+  background-color:#fff;
+  margin-top:2px;
+  margin-left:-1px;
+  padding: 2px
+}
+.taskStatus{
+  width:15px;
+  height:15px;
+  display:inline-block;
+}
+.taskStatus[status=STATUS_ACTIVE]{
+ background-color: #66FF99;
+}
+.taskStatus[status=STATUS_DONE]{
+ background-color: #0099FF;
+}
+.taskStatus[status=STATUS_FAILED]{
+ background-color: #660066;
+}
+.taskStatus[status=STATUS_SUSPENDED]{
+ background-color: #fbb11e;
+}
+.taskStatus[status=STATUS_UNDEFINED]{
+ background-color: #ffffff;
+}
+.taskStatus.selected{
+  border:#666 2px solid;
+}
+
+
+.ui-resizable-helper { border: 1px dotted #00F;  }
+.ui-resizable-e, .ui-resizable-w {width: 5px;}
+.ui-draggable{
+  cursor:move;
+}
+
+
diff --git a/src/vendor/jquery-teamwork-gantt/ganttDrawer.js b/src/vendor/jquery-teamwork-gantt/ganttDrawer.js
new file mode 100644
index 0000000..1d993bc
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/ganttDrawer.js
@@ -0,0 +1,752 @@
+/*
+  Copyright (c) 2012-2013 Open Lab
+  Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+function Ganttalendar(zoom, startmillis, endMillis, master, minGanttSize) {
+  this.master = master; // is the a GantEditor instance
+  this.element; // is the jquery element containing gantt
+  this.highlightBar;
+  this.zoom = zoom;
+  this.minGanttSize = minGanttSize;
+  this.includeToday=true; //when true today is always visible. If false boundaries comes from tasks periods
+
+  //this.zoomLevels = ["d","w","m","q","s","y"];
+  this.zoomLevels = ["w","m","q","s","y"];
+
+  this.element = this.create(zoom, startmillis, endMillis);
+
+}
+
+Ganttalendar.prototype.zoomGantt = function(isPlus) {
+  var curLevel = this.zoom;
+  var pos = this.zoomLevels.indexOf(curLevel + "");
+
+  var newPos = pos;
+  if (isPlus) {
+    newPos = pos <= 0 ? 0 : pos - 1;
+  } else {
+    newPos = pos >= this.zoomLevels.length - 1 ? this.zoomLevels.length - 1 : pos + 1;
+  }
+  if (newPos != pos) {
+    curLevel = this.zoomLevels[newPos];
+    this.zoom = curLevel;
+    this.refreshGantt();
+  }
+};
+
+
+Ganttalendar.prototype.create = function(zoom, originalStartmillis, originalEndMillis) {
+  //console.debug("Gantt.create " + new Date(originalStartmillis) + " - " + new Date(originalEndMillis));
+
+  var self = this;
+
+  function getPeriod(zoomLevel, stMil, endMillis) {
+    var start = new Date(stMil);
+    var end = new Date(endMillis);
+
+
+    //reset hours
+    if (zoomLevel == "d") {
+      start.setHours(0, 0, 0, 0);
+      end.setHours(23, 59, 59, 999);
+
+      //reset day of week
+    } else if (zoomLevel == "w") {
+      start.setHours(0, 0, 0, 0);
+      end.setHours(23, 59, 59, 999);
+
+      start.setFirstDayOfThisWeek();
+      end.setFirstDayOfThisWeek();
+      end.setDate(end.getDate() + 6);
+
+      //reset day of month
+    } else if (zoomLevel == "m") {
+      start.setHours(0, 0, 0, 0);
+      end.setHours(23, 59, 59, 999);
+
+      start.setDate(1);
+      end.setDate(1);
+      end.setMonth(end.getMonth() + 1);
+      end.setDate(end.getDate() - 1);
+
+      //reset to quarter
+    } else if (zoomLevel == "q") {
+      start.setHours(0, 0, 0, 0);
+      end.setHours(23, 59, 59, 999);
+      start.setDate(1);
+      start.setMonth(Math.floor(start.getMonth() / 3) * 3);
+      end.setDate(1);
+      end.setMonth(Math.floor(end.getMonth() / 3) * 3 + 3);
+      end.setDate(end.getDate() - 1);
+
+      //reset to semester
+    } else if (zoomLevel == "s") {
+      start.setHours(0, 0, 0, 0);
+      end.setHours(23, 59, 59, 999);
+      start.setDate(1);
+
+      start.setMonth(Math.floor(start.getMonth() / 6) * 6);
+      end.setDate(1);
+      end.setMonth(Math.floor(end.getMonth() / 6) * 6 + 6);
+      end.setDate(end.getDate() - 1);
+
+      //reset to year - > gen
+    } else if (zoomLevel == "y") {
+      start.setHours(0, 0, 0, 0);
+      end.setHours(23, 59, 59, 999);
+
+      start.setDate(1);
+      start.setMonth(0);
+
+      end.setDate(1);
+      end.setMonth(12);
+      end.setDate(end.getDate() - 1);
+    }
+    return {start:start.getTime(),end:end.getTime()};
+  }
+
+  function createHeadCell(lbl, span, additionalClass) {
+    var th = $("<th>").html(lbl).attr("colSpan", span);
+    if (additionalClass)
+      th.addClass(additionalClass);
+    return th;
+  }
+
+  function createBodyCell(span, isEnd, additionalClass) {
+    var ret = $("<td>").html(" ").attr("colSpan", span).addClass("ganttBodyCell");
+    if (isEnd)
+      ret.addClass("end");
+    if (additionalClass)
+      ret.addClass(additionalClass);
+    return ret;
+  }
+
+  function createGantt(zoom, startPeriod, endPeriod) {
+    var tr1 = $("<tr>").addClass("ganttHead1");
+    var tr2 = $("<tr>").addClass("ganttHead2");
+    var trBody = $("<tr>").addClass("ganttBody");
+
+    function iterate(renderFunction1, renderFunction2) {
+      var start = new Date(startPeriod);
+      //loop for header1
+      while (start.getTime() <= endPeriod) {
+        renderFunction1(start);
+      }
+
+      //loop for header2
+      start = new Date(startPeriod);
+      while (start.getTime() <= endPeriod) {
+        renderFunction2(start);
+      }
+    }
+
+    //this is computed by hand in order to optimize cell size
+    var computedTableWidth;
+
+    // year
+    if (zoom == "y") {
+      computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24 * 180)) * 100); //180gg = 1 sem = 100px
+      iterate(function(date) {
+        tr1.append(createHeadCell(date.format("yyyy"), 2));
+        date.setFullYear(date.getFullYear() + 1);
+      }, function(date) {
+        var sem = (Math.floor(date.getMonth() / 6) + 1);
+        tr2.append(createHeadCell(GanttMaster.messages["GANT_SEMESTER_SHORT"] + sem, 1));
+        trBody.append(createBodyCell(1, sem == 2));
+        date.setMonth(date.getMonth() + 6);
+      });
+
+      //semester
+    } else if (zoom == "s") {
+      computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24 * 90)) * 100); //90gg = 1 quarter = 100px
+      iterate(function(date) {
+        var end = new Date(date.getTime());
+        end.setMonth(end.getMonth() + 6);
+        end.setDate(end.getDate() - 1);
+        tr1.append(createHeadCell(date.format("MMM") + " - " + end.format("MMM yyyy"), 2));
+        date.setMonth(date.getMonth() + 6);
+      }, function(date) {
+        var quarter = ( Math.floor(date.getMonth() / 3) + 1);
+        tr2.append(createHeadCell(GanttMaster.messages["GANT_QUARTER_SHORT"] + quarter, 1));
+        trBody.append(createBodyCell(1, quarter % 2 == 0));
+        date.setMonth(date.getMonth() + 3);
+      });
+
+      //quarter
+    } else if (zoom == "q") {
+      computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24 * 30)) * 300); //1 month= 300px
+      iterate(function(date) {
+        var end = new Date(date.getTime());
+        end.setMonth(end.getMonth() + 3);
+        end.setDate(end.getDate() - 1);
+        tr1.append(createHeadCell(date.format("MMM") + " - " + end.format("MMM yyyy"), 3));
+        date.setMonth(date.getMonth() + 3);
+      }, function(date) {
+        var lbl = date.format("MMM");
+        tr2.append(createHeadCell(lbl, 1));
+        trBody.append(createBodyCell(1, date.getMonth() % 3 == 2));
+        date.setMonth(date.getMonth() + 1);
+      });
+
+      //month
+    } else if (zoom == "m") {
+      computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24 * 1)) * 20); //1 day= 20px
+      iterate(function(date) {
+        var sm = date.getTime();
+        date.setMonth(date.getMonth() + 1);
+        var daysInMonth = parseInt((date.getTime() - sm) / (3600000 * 24));
+        tr1.append(createHeadCell(new Date(sm).format("MMMM yyyy"), daysInMonth)); //spans mumber of dayn in the month
+      }, function(date) {
+        tr2.append(createHeadCell(date.format("d"), 1, isHoliday(date) ? "holyH" : null));
+        var nd = new Date(date.getTime());
+        nd.setDate(date.getDate() + 1);
+        trBody.append(createBodyCell(1, nd.getDate() == 1, isHoliday(date) ? "holy" : null));
+        date.setDate(date.getDate() + 1);
+      });
+
+      //week
+    } else if (zoom == "w") {
+      computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24)) * 30); //1 day= 30px
+      iterate(function(date) {
+        var end = new Date(date.getTime());
+        end.setDate(end.getDate() + 6);
+        tr1.append(createHeadCell(date.format("MMM d") + " - " + end.format("MMM d'yy"), 7));
+        date.setDate(date.getDate() + 7);
+      }, function(date) {
+        tr2.append(createHeadCell(date.format("EEEE").substr(0, 1), 1, isHoliday(date) ? "holyH" : null));
+        trBody.append(createBodyCell(1, date.getDay() % 7 == (self.master.firstDayOfWeek + 6) % 7, isHoliday(date) ? "holy" : null));
+        date.setDate(date.getDate() + 1);
+      });
+
+      //days
+    } else if (zoom == "d") {
+      computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24)) * 200); //1 day= 200px
+      iterate(function(date) {
+        tr1.append(createHeadCell(date.format("EEEE d MMMM yyyy"), 4, isHoliday(date) ? "holyH" : null));
+        date.setDate(date.getDate() + 1);
+      }, function(date) {
+        tr2.append(createHeadCell(date.format("HH"), 1, isHoliday(date) ? "holyH" : null));
+        trBody.append(createBodyCell(1, date.getHours() > 17, isHoliday(date) ? "holy" : null));
+        date.setHours(date.getHours() + 6);
+      });
+
+    } else {
+      console.error("Wrong level " + zoom);
+    }
+
+    //set a minimal width
+    computedTableWidth = Math.max(computedTableWidth, self.minGanttSize);
+
+    var table = $("<table cellspacing=0 cellpadding=0>");
+    table.append(tr1).append(tr2).append(trBody).addClass("ganttTable").css({width:computedTableWidth});
+    table.height(self.master.editor.element.height());
+
+    var box = $("<div>");
+    box.addClass("gantt unselectable").attr("unselectable","true").css({position:"relative",width:computedTableWidth});
+    box.append(table);
+
+    //highlightBar
+    var hlb = $("<div>").addClass("ganttHighLight");
+    box.append(hlb);
+    self.highlightBar = hlb;
+
+    //create link container
+    var links = $("<div>");
+    links.addClass("ganttLinks").css({position:"absolute",top:0,width:computedTableWidth,height:"100%"});
+    box.append(links);
+
+
+    //compute scalefactor fx
+    self.fx = computedTableWidth / (endPeriod - startPeriod);
+
+    // drawTodayLine
+    if (new Date().getTime() > self.startMillis && new Date().getTime() < self.endMillis) {
+      var x = Math.round(((new Date().getTime()) - self.startMillis) * self.fx);
+      var today = $("<div>").addClass("ganttToday").css("left", x);
+      box.append(today);
+    }
+
+    return box;
+  }
+
+  //if include today synch extremes
+  if (this.includeToday){
+    var today=new Date().getTime();
+    originalStartmillis=originalStartmillis>today ? today:originalStartmillis;
+    originalEndMillis=originalEndMillis<today ? today:originalEndMillis;
+  }
+
+
+  //get best dimension fo gantt
+  var period = getPeriod(zoom, originalStartmillis, originalEndMillis); //this is enlarged to match complete periods basing on zoom level
+
+  //console.debug(new Date(period.start) + "   " + new Date(period.end));
+  self.startMillis = period.start; //real dimension of gantt
+  self.endMillis = period.end;
+  self.originalStartMillis = originalStartmillis; //minimal dimension required by user or by task duration
+  self.originalEndMillis = originalEndMillis;
+
+  var table = createGantt(zoom, period.start, period.end);
+
+  return table;
+};
+
+
+//<%-------------------------------------- GANT TASK GRAPHIC ELEMENT --------------------------------------%>
+Ganttalendar.prototype.drawTask = function (task) {
+  //console.debug("drawTask", task.name,new Date(task.start));
+  var self = this;
+  //var prof = new Profiler("ganttDrawTask");
+  //var editorRow = self.master.editor.element.find("tr[taskId=" + task.id + "]");
+  editorRow = task.rowElement;
+  var top = editorRow.position().top+self.master.editor.element.parent().scrollTop();
+  var x = Math.round((task.start - self.startMillis) * self.fx);
+  var taskBox = $.JST.createFromTemplate(task, "TASKBAR");
+
+
+
+  //save row element on task
+  task.ganttElement = taskBox;
+
+  //if I'm parent
+  if (task.isParent())
+    taskBox.addClass("hasChild");
+
+
+  taskBox.css({top:top,left:x,width:Math.round((task.end - task.start) * self.fx)});
+
+  if (this.master.canWrite) {
+    taskBox.resizable({
+      handles: 'e' + ( task.depends ? "" : ",w"), //if depends cannot move start
+      //helper: "ui-resizable-helper",
+      //grid:[oneDaySize,oneDaySize],
+
+      resize:function(event, ui) {
+        //console.debug(ui)
+        $(".taskLabel[taskId=" + ui.helper.attr("taskId") + "]").css("width", ui.position.left);
+        event.stopImmediatePropagation();
+        event.stopPropagation();
+      },
+      stop:function(event, ui) {
+        //console.debug(ui)
+        var task = self.master.getTask(ui.element.attr("taskId"));
+        var s = Math.round((ui.position.left / self.fx) + self.startMillis);
+        var e = Math.round(((ui.position.left + ui.size.width) / self.fx) + self.startMillis);
+
+        self.master.beginTransaction();
+        self.master.changeTaskDates(task, new Date(s), new Date(e));
+        self.master.endTransaction();
+      }
+
+    });
+
+  }
+
+  taskBox.dblclick(function() {
+    self.master.showTaskEditor($(this).closest("[taskId]").attr("taskId"));
+
+  }).mousedown(function() {
+    var task = self.master.getTask($(this).attr("taskId"));
+    task.rowElement.click();
+  });
+
+  //panning only in no depends
+  if (!task.depends && this.master.canWrite) {
+
+    taskBox.css("position", "absolute").draggable({
+      axis:'x',
+      drag:function (event, ui) {
+        $(".taskLabel[taskId=" + $(this).attr("taskId") + "]").css("width", ui.position.left);
+      },
+      stop:function(event, ui) {
+        //console.debug(ui,$(this))
+        var task = self.master.getTask($(this).attr("taskId"));
+        var s = Math.round((ui.position.left / self.fx) + self.startMillis);
+
+        self.master.beginTransaction();
+        self.master.moveTask(task, new Date(s));
+        self.master.endTransaction();
+      }/*,
+      start:function(event, ui) {
+        var task = self.master.getTask($(this).attr("taskId"));
+        var s = Math.round((ui.position.left / self.fx) + self.startMillis);
+        console.debug("start",new Date(s));
+      }*/
+    });
+  }
+
+
+  var taskBoxSeparator=$("<div class='ganttLines'></div>");
+  taskBoxSeparator.css({top:top+taskBoxSeparator.height()});
+//  taskBoxSeparator.css({top:top+18});
+
+
+  self.element.append(taskBox);
+  self.element.append(taskBoxSeparator);
+
+  //ask for redraw link
+  self.redrawLinks();
+
+  //prof.stop();
+};
+
+
+Ganttalendar.prototype.addTask = function (task) {
+  //set new boundaries for gantt
+  this.originalEndMillis = this.originalEndMillis > task.end ? this.originalEndMillis : task.end;
+  this.originalStartMillis = this.originalStartMillis < task.start ? this.originalStartMillis : task.start;
+};
+
+
+//<%-------------------------------------- GANT DRAW LINK ELEMENT --------------------------------------%>
+//'from' and 'to' are tasks already drawn
+Ganttalendar.prototype.drawLink = function (from, to, type) {
+  var peduncolusSize = 10;
+  var lineSize = 2;
+
+  /**
+   * A representation of a Horizontal line
+   */
+  HLine = function(width, top, left) {
+    var hl = $("<div>").addClass("taskDepLine");
+    hl.css({
+      height: lineSize,
+      left: left,
+      width: width,
+      top: top - lineSize / 2
+    });
+    return hl;
+  };
+
+  /**
+   * A representation of a Vertical line
+   */
+  VLine = function(height, top, left) {
+    var vl = $("<div>").addClass("taskDepLine");
+    vl.css({
+      height: height,
+      left:left - lineSize / 2,
+      width: lineSize,
+      top: top
+    });
+    return vl;
+  };
+
+  /**
+   * Given an item, extract its rendered position
+   * width and height into a structure.
+   */
+  function buildRect(item) {
+    var rect = item.ganttElement.position();
+    rect.width = item.ganttElement.width();
+    rect.height = item.ganttElement.height();
+
+    return rect;
+  }
+
+  /**
+   * The default rendering method, which paints a start to end dependency.
+   *
+   * @see buildRect
+   */
+  function drawStartToEnd(rectFrom, rectTo, peduncolusSize) {
+    var left, top;
+
+    var ndo = $("<div>").attr({
+      from: from.id,
+      to: to.id
+    });
+
+    var currentX = rectFrom.left + rectFrom.width;
+    var currentY = rectFrom.height / 2 + rectFrom.top;
+
+    var useThreeLine = (currentX + 2 * peduncolusSize) < rectTo.left;
+
+    if (!useThreeLine) {
+      // L1
+      if (peduncolusSize > 0) {
+        var l1 = new HLine(peduncolusSize, currentY, currentX);
+        currentX = currentX + peduncolusSize;
+        ndo.append(l1);
+      }
+
+      // L2
+      var l2_4size = ((rectTo.top + rectTo.height / 2) - (rectFrom.top + rectFrom.height / 2)) / 2;
+      var l2;
+      if (l2_4size < 0) {
+        l2 = new VLine(-l2_4size, currentY + l2_4size, currentX);
+      } else {
+        l2 = new VLine(l2_4size, currentY, currentX);
+      }
+      currentY = currentY + l2_4size;
+
+      ndo.append(l2);
+
+      // L3
+      var l3size = rectFrom.left + rectFrom.width + peduncolusSize - (rectTo.left - peduncolusSize);
+      currentX = currentX - l3size;
+      var l3 = new HLine(l3size, currentY, currentX);
+      ndo.append(l3);
+
+      // L4
+      var l4;
+      if (l2_4size < 0) {
+        l4 = new VLine(-l2_4size, currentY + l2_4size, currentX);
+      } else {
+        l4 = new VLine(l2_4size, currentY, currentX);
+      }
+      ndo.append(l4);
+
+      currentY = currentY + l2_4size;
+
+      // L5
+      if (peduncolusSize > 0) {
+        var l5 = new HLine(peduncolusSize, currentY, currentX);
+        currentX = currentX + peduncolusSize;
+        ndo.append(l5);
+
+      }
+    } else {
+      //L1
+      var l1_3Size = (rectTo.left - currentX) / 2;
+      var l1 = new HLine(l1_3Size, currentY, currentX);
+      currentX = currentX + l1_3Size;
+      ndo.append(l1);
+
+      //L2
+      var l2Size = ((rectTo.top + rectTo.height / 2) - (rectFrom.top + rectFrom.height / 2));
+      var l2;
+      if (l2Size < 0) {
+        l2 = new VLine(-l2Size, currentY + l2Size, currentX);
+      } else {
+        l2 = new VLine(l2Size, currentY, currentX);
+      }
+      ndo.append(l2);
+
+      currentY = currentY + l2Size;
+
+      //L3
+      var l3 = new HLine(l1_3Size, currentY, currentX);
+      currentX = currentX + l1_3Size;
+      ndo.append(l3);
+    }
+
+    //arrow
+    var arr = $("<img src='/images/linkArrow.png'>").css({
+      position: 'absolute',
+      top: rectTo.top + rectTo.height / 2 - 5,
+      left: rectTo.left - 5
+    });
+
+    ndo.append(arr);
+
+    return ndo;
+  }
+
+  /**
+   * A rendering method which paints a start to start dependency.
+   *
+   * @see buildRect
+   */
+  function drawStartToStart(rectFrom, rectTo, peduncolusSize) {
+    var left, top;
+
+    var ndo = $("<div>").attr({
+      from: from.id,
+      to: to.id
+    });
+
+    var currentX = rectFrom.left;
+    var currentY = rectFrom.height / 2 + rectFrom.top;
+
+    var useThreeLine = (currentX + 2 * peduncolusSize) < rectTo.left;
+
+    if (!useThreeLine) {
+      // L1
+      if (peduncolusSize > 0) {
+        var l1 = new HLine(peduncolusSize, currentY, currentX - peduncolusSize);
+        currentX = currentX - peduncolusSize;
+        ndo.append(l1);
+      }
+
+      // L2
+      var l2_4size = ((rectTo.top + rectTo.height / 2) - (rectFrom.top + rectFrom.height / 2)) / 2;
+      var l2;
+      if (l2_4size < 0) {
+        l2 = new VLine(-l2_4size, currentY + l2_4size, currentX);
+      } else {
+        l2 = new VLine(l2_4size, currentY, currentX);
+      }
+      currentY = currentY + l2_4size;
+
+      ndo.append(l2);
+
+      // L3
+      var l3size = (rectFrom.left - peduncolusSize) - (rectTo.left - peduncolusSize);
+      currentX = currentX - l3size;
+      var l3 = new HLine(l3size, currentY, currentX);
+      ndo.append(l3);
+
+      // L4
+      var l4;
+      if (l2_4size < 0) {
+        l4 = new VLine(-l2_4size, currentY + l2_4size, currentX);
+      } else {
+        l4 = new VLine(l2_4size, currentY, currentX);
+      }
+      ndo.append(l4);
+
+      currentY = currentY + l2_4size;
+
+      // L5
+      if (peduncolusSize > 0) {
+        var l5 = new HLine(peduncolusSize, currentY, currentX);
+        currentX = currentX + peduncolusSize;
+        ndo.append(l5);
+      }
+    } else {
+      //L1
+      
+      var l1 = new HLine(peduncolusSize, currentY, currentX - peduncolusSize);
+      currentX = currentX - peduncolusSize;
+      ndo.append(l1);
+
+      //L2
+      var l2Size = ((rectTo.top + rectTo.height / 2) - (rectFrom.top + rectFrom.height / 2));
+      var l2;
+      if (l2Size < 0) {
+        l2 = new VLine(-l2Size, currentY + l2Size, currentX);
+      } else {
+        l2 = new VLine(l2Size, currentY, currentX);
+      }
+      ndo.append(l2);
+
+      currentY = currentY + l2Size;
+
+      //L3
+
+      var l3 = new HLine(peduncolusSize + (rectTo.left - rectFrom.left), currentY, currentX);
+      currentX = currentX + peduncolusSize + (rectTo.left - rectFrom.left);
+      ndo.append(l3);
+    }
+
+    //arrow
+    var arr = $("<img src='/images/linkArrow.png'>").css({
+      position: 'absolute',
+      top: rectTo.top + rectTo.height / 2 - 5,
+      left: rectTo.left - 5
+    });
+
+    ndo.append(arr);
+
+    return ndo;
+  }
+
+  var rectFrom = buildRect(from);
+  var rectTo = buildRect(to);
+
+  // Dispatch to the correct renderer
+  if (type == 'start-to-start') {
+    this.element.find(".ganttLinks").append(
+      drawStartToStart(rectFrom, rectTo, peduncolusSize)
+    );
+  } else {
+    this.element.find(".ganttLinks").append(
+      drawStartToEnd(rectFrom, rectTo, peduncolusSize)
+    );
+  }
+};
+
+
+Ganttalendar.prototype.redrawLinks = function() {
+  //console.debug("redrawLinks ");
+  var self = this;
+  this.element.stopTime("ganttlnksredr");
+  this.element.oneTime(60, "ganttlnksredr", function() {
+    //var prof=new Profiler("gd_drawLink_real");
+    self.element.find(".ganttLinks").empty();
+    for (var i=0;i<self.master.links.length;i++) {
+      var link = self.master.links[i];
+      self.drawLink(link.from, link.to);
+    }
+    //prof.stop();
+  });
+};
+
+
+Ganttalendar.prototype.reset = function() {
+  this.element.find(".ganttLinks").empty();
+  this.element.find("[taskId]").remove();
+};
+
+
+Ganttalendar.prototype.redrawTasks = function() {
+  for (var i=0;i<this.master.tasks.length;i++) {
+    var task = this.master.tasks[i];
+    this.drawTask(task);
+  }
+};
+
+
+Ganttalendar.prototype.refreshGantt = function() {
+  //console.debug("refreshGantt")
+  var par = this.element.parent();
+
+  //try to maintain last scroll
+  var scrollY=par.scrollTop();
+  var scrollX=par.scrollLeft();
+
+  this.element.remove();
+  //guess the zoom level in base of period
+  if (!this.zoom ){
+    var days = (this.originalEndMillis - this.originalStartMillis) / (3600000 * 24);
+    this.zoom = this.zoomLevels[days < 2 ? 0 : (days < 15 ? 1 : (days < 60 ? 2 : (days < 150 ? 3 : (days < 400 ? 4 : 5 ) ) ) )];
+  }
+  var domEl = this.create(this.zoom, this.originalStartMillis, this.originalEndMillis);
+  this.element = domEl;
+  par.append(domEl);
+  this.redrawTasks();
+
+  //set old scroll  
+  //console.debug("old scroll:",scrollX,scrollY)
+  par.scrollTop(scrollY);
+  par.scrollLeft(scrollX);
+
+  //set current task
+  if (this.master.currentTask) {
+    this.highlightBar.css("top", this.master.currentTask.ganttElement.position().top);
+  }
+};
+
+
+Ganttalendar.prototype.fitGantt = function() {
+  delete this.zoom;
+  this.refreshGantt();
+};
+
+Ganttalendar.prototype.centerOnToday = function() {
+  //console.debug("centerOnToday");
+  var x = Math.round(((new Date().getTime()) - this.startMillis) * this.fx);
+  this.element.parent().scrollLeft(x);
+};
+
+
+
diff --git a/src/vendor/jquery-teamwork-gantt/ganttGridEditor.js b/src/vendor/jquery-teamwork-gantt/ganttGridEditor.js
new file mode 100644
index 0000000..7896694
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/ganttGridEditor.js
@@ -0,0 +1,518 @@
+/*
+  Copyright (c) 2012-2013 Open Lab
+  Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+function GridEditor(master) {
+  this.master = master; // is the a GantEditor instance
+  var gridEditor = $.JST.createFromTemplate({}, "TASKSEDITHEAD");
+  gridEditor.gridify();
+  this.element = gridEditor;
+}
+
+
+GridEditor.prototype.fillEmptyLines = function() {
+  var factory = new TaskFactory();
+
+  //console.debug("GridEditor.fillEmptyLines");
+  var rowsToAdd = 30 - this.element.find(".taskEditRow").size();
+
+  //fill with empty lines
+  for (var i = 0; i < rowsToAdd; i++) {
+    var emptyRow = $.JST.createFromTemplate({}, "TASKEMPTYROW");
+    //click on empty row create a task and fill above
+    var master = this.master;
+    emptyRow.click(function(ev) {
+      master.beginTransaction();
+      var emptyRow = $(this);
+      var lastTask;
+      var start = new Date().getTime();
+      var level = 0;
+      if (master.tasks[0]) {
+        start = master.tasks[0].start;
+        level = master.tasks[0].level + 1;
+      }
+
+      //fill all empty previouses
+      emptyRow.prevAll(".emptyRow").andSelf().each(function() {
+        var ch = factory.build("tmp_fk" + new Date().getTime(), "", "", level, start, 1);
+        var task = master.addTask(ch);
+        lastTask = ch;
+      });
+      master.endTransaction();
+      lastTask.rowElement.click();
+      lastTask.rowElement.find("[name=name]").focus()//focus to "name" input
+              .blur(function() { //if name not inserted -> undo -> remove just added lines
+        var imp = $(this);
+        if (!imp.isValueChanged())
+          master.undo();
+      });
+    });
+    this.element.append(emptyRow);
+  }
+};
+
+
+GridEditor.prototype.addTask = function(task, row) {
+  //console.debug("GridEditor.addTask",task,row);
+  //var prof = new Profiler("editorAddTaskHtml");
+
+  //remove extisting row
+  this.element.find("[taskId=" + task.id + "]").remove();
+
+  var taskRow = $.JST.createFromTemplate(task, "TASKROW");
+  //save row element on task
+  task.rowElement = taskRow;
+
+  this.bindRowEvents(task, taskRow);
+
+  if (typeof(row) != "number") {
+    var emptyRow = this.element.find(".emptyRow:first"); //tries to fill an empty row
+    if (emptyRow.size() > 0)
+      emptyRow.replaceWith(taskRow);
+    else
+      this.element.append(taskRow);
+  } else {
+    var tr = this.element.find("tr.taskEditRow").eq(row);
+    if (tr.size() > 0) {
+      tr.before(taskRow);
+    } else {
+      this.element.append(taskRow);
+    }
+
+  }
+  this.element.find(".taskRowIndex").each(function(i, el) {
+    $(el).html(i + 1);
+  });
+  //prof.stop();
+
+  return taskRow;
+};
+
+
+GridEditor.prototype.refreshTaskRow = function(task) {
+  //console.debug("refreshTaskRow")
+  //var profiler = new Profiler("editorRefreshTaskRow");
+  var row = task.rowElement;
+
+  row.find(".taskRowIndex").html(task.getRow() + 1);
+  row.find(".indentCell").css("padding-left", task.level * 10);
+  row.find("[name=name]").val(task.name);
+  row.find("[name=code]").val(task.code);
+  row.find("[status]").attr("status", task.status);
+
+  row.find("[name=duration]").val(task.duration);
+  row.find("[name=start]").val(new Date(task.start).format()).updateOldValue(); // called on dates only because for other field is called on focus event
+  row.find("[name=end]").val(new Date(task.end).format()).updateOldValue();
+  row.find("[name=depends]").val(task.depends);
+  row.find(".taskAssigs").html(task.getAssigsString());
+
+  //profiler.stop();
+};
+
+GridEditor.prototype.redraw = function() {
+  for (var i = 0; i < this.master.tasks.length; i++) {
+    this.refreshTaskRow(this.master.tasks[i]);
+  }
+};
+
+GridEditor.prototype.reset = function() {
+  this.element.find("[taskId]").remove();
+};
+
+
+GridEditor.prototype.bindRowEvents = function (task, taskRow) {
+  var self = this;
+  //console.debug("bindRowEvents",this,this.master,this.master.canWrite);
+  if (this.master.canWrite) {
+    self.bindRowInputEvents(task,taskRow);
+
+  } else { //cannot write: disable input
+    taskRow.find("input").attr("readonly", true);
+  }
+
+  taskRow.find(".edit").click(function() {self.openFullEditor(task,taskRow)});
+
+};
+
+
+GridEditor.prototype.bindRowInputEvents = function (task, taskRow) {
+  var self = this;
+
+  //bind dateField on dates
+  taskRow.find(".date").each(function () {
+    var el = $(this);
+
+    el.click(function () {
+      var inp = $(this);
+      inp.dateField({
+        inputField:el
+      });
+    });
+
+    el.blur(function (date) {
+      var inp = $(this);
+      if (inp.isValueChanged()) {
+        if (!Date.isValid(inp.val())) {
+          alert(GanttMaster.messages["INVALID_DATE_FORMAT"]);
+          inp.val(inp.getOldValue());
+
+        } else {
+          var date = Date.parseString(inp.val());
+          var row = inp.closest("tr");
+          var taskId = row.attr("taskId");
+          var task = self.master.getTask(taskId);
+          var lstart = task.start;
+          var lend = task.end;
+
+          if (inp.attr("name") == "start") {
+            lstart = date.getTime();
+            if (lstart >= lend) {
+              var end_as_date = new Date(lstart);
+              lend = end_as_date.add('d', task.duration).getTime();
+            }
+
+            //update task from editor
+            self.master.beginTransaction();
+            self.master.moveTask(task, lstart);
+            self.master.endTransaction();
+
+          } else {
+            var end_as_date = new Date(date.getTime());
+            lend = end_as_date.getTime();
+            if (lstart >= lend) {
+              end_as_date.add('d', -1 * task.duration);
+              lstart = end_as_date.getTime();
+            }
+
+            //update task from editor
+            self.master.beginTransaction();
+            self.master.changeTaskDates(task, lstart, lend);
+            self.master.endTransaction();
+          }
+
+
+          inp.updateOldValue(); //in order to avoid multiple call if nothing changed
+        }
+      }
+    });
+  });
+
+
+  //binding on blur for task update (date exluded as click on calendar blur and then focus, so will always return false, its called refreshing the task row)
+  taskRow.find("input:not(.date)").focus(function () {
+    $(this).updateOldValue();
+
+  }).blur(function () {
+    var el = $(this);
+    if (el.isValueChanged()) {
+      var row = el.closest("tr");
+      var taskId = row.attr("taskId");
+
+      var task = self.master.getTask(taskId);
+
+      //update task from editor
+      var field = el.attr("name");
+
+      self.master.beginTransaction();
+
+      if (field == "depends") {
+
+        var oldDeps = task.depends;
+        task.depends = el.val();
+        // update links
+        var linkOK = self.master.updateLinks(task);
+        if (linkOK) {
+          //synchronize status fro superiors states
+          var sups = task.getSuperiors();
+          for (var i = 0; i < sups.length; i++) {
+            if (!sups[i].from.synchronizeStatus())
+              break;
+          }
+
+          self.master.changeTaskDates(task, task.start, task.end);
+        }
+
+      } else if (field == "duration") {
+        var dur = task.duration;
+        dur = parseInt(el.val()) || 1;
+        el.val(dur);
+        var newEnd = computeEndByDuration(task.start, dur);
+        self.master.changeTaskDates(task, task.start, newEnd);
+
+      } else {
+        task[field] = el.val();
+      }
+      self.master.endTransaction();
+    }
+  });
+
+
+  //change status
+  taskRow.find(".taskStatus").click(function () {
+    var el = $(this);
+    var tr = el.closest("[taskId]");
+    var taskId = tr.attr("taskId");
+    var task = self.master.getTask(taskId);
+
+    var changer = $.JST.createFromTemplate({}, "CHANGE_STATUS");
+    changer.css("top", tr.position().top + self.element.parent().scrollTop());
+    changer.find("[status=" + task.status + "]").addClass("selected");
+    changer.find(".taskStatus").click(function () {
+      self.master.beginTransaction();
+      task.changeStatus($(this).attr("status"));
+      self.master.endTransaction();
+      el.attr("status", task.status);
+      changer.remove();
+      el.show();
+
+    });
+    el.hide().oneTime(3000, "hideChanger", function () {
+      changer.remove();
+      $(this).show();
+    });
+    el.after(changer);
+  });
+
+
+  /*//expand collapse todo to be completed
+   taskRow.find(".expcoll").click(function(){
+   //expand?
+   var el=$(this);
+   var taskId=el.closest("[taskId]").attr("taskId");
+   var task=self.master.getTask(taskId);
+   var descs=task.getDescendant();
+   if (el.is(".exp")){
+   for (var i=0;i<descs.length;i++)
+   descs[i].rowElement.show();
+   } else {
+   for (var i=0;i<descs.length;i++)
+   descs[i].rowElement.hide();
+   }
+
+   });*/
+
+  //bind row selection
+  taskRow.click(function () {
+    var row = $(this);
+    //var isSel = row.hasClass("rowSelected");
+    row.closest("table").find(".rowSelected").removeClass("rowSelected");
+    row.addClass("rowSelected");
+
+    //set current task
+    self.master.currentTask = self.master.getTask(row.attr("taskId"));
+
+    //move highlighter
+    if (self.master.currentTask.ganttElement)
+      self.master.gantt.highlightBar.css("top", self.master.currentTask.ganttElement.position().top);
+
+    //if offscreen scroll to element
+    var top = row.position().top;
+    if (row.position().top > self.element.parent().height()) {
+      self.master.gantt.element.parent().scrollTop(row.position().top - self.element.parent().height() + 100);
+    }
+  });
+
+};
+
+
+
+GridEditor.prototype.openFullEditor = function (task, taskRow) {
+
+  var self=this;
+
+  //task editor in popup
+  var taskId = taskRow.attr("taskId");
+  //console.debug(task);
+
+  //make task editor
+  var taskEditor = $.JST.createFromTemplate({}, "TASK_EDITOR");
+
+  taskEditor.find("#name").val(task.name);
+  taskEditor.find("#description").val(task.description);
+  taskEditor.find("#code").val(task.code);
+  taskEditor.find("#progress").val(task.progress ? parseFloat(task.progress) : 0);
+  taskEditor.find("#status").attr("status", task.status);
+
+  if (task.startIsMilestone)
+    taskEditor.find("#startIsMilestone").attr("checked", true);
+  if (task.endIsMilestone)
+    taskEditor.find("#endIsMilestone").attr("checked", true);
+
+  taskEditor.find("#duration").val(task.duration);
+  taskEditor.find("#start").val(new Date(task.start).format());
+  taskEditor.find("#end").val(new Date(task.end).format());
+
+  //taskEditor.find("[name=depends]").val(task.depends);
+
+  //make assignments table
+  var assigsTable = taskEditor.find("#assigsTable");
+  assigsTable.find("[assigId]").remove();
+  // loop on already assigned resources
+  for (var i = 0; i < task.assigs.length; i++) {
+    var assig = task.assigs[i];
+    var assigRow = $.JST.createFromTemplate({task:task, assig:assig}, "ASSIGNMENT_ROW");
+    assigsTable.append(assigRow);
+  }
+
+  if (!self.master.canWrite) {
+    taskEditor.find("input,textarea").attr("readOnly", true);
+    taskEditor.find("input:checkbox,select").attr("disabled", true);
+  } else {
+
+    //bind dateField on dates
+    taskEditor.find("#start").click(function () {
+      $(this).dateField({
+        inputField:$(this),
+        callback:  function (date) {
+          var dur = parseInt(taskEditor.find("#duration").val());
+          date.clearTime();
+          taskEditor.find("#end").val(new Date(computeEndByDuration(date.getTime(), dur)).format());
+        }
+      });
+    });
+
+    //bind dateField on dates
+    taskEditor.find("#end").click(function () {
+      $(this).dateField({
+        inputField:$(this),
+        callback:  function (end) {
+          var start = Date.parseString(taskEditor.find("#start").val());
+          end.setHours(23, 59, 59, 999);
+
+          if (end.getTime() < start.getTime()) {
+            var dur = parseInt(taskEditor.find("#duration").val());
+            start = incrementDateByWorkingDays(end.getTime(), -dur);
+            taskEditor.find("#start").val(new Date(computeStart(start)).format());
+          } else {
+            taskEditor.find("#duration").val(recomputeDuration(start.getTime(), end.getTime()));
+          }
+        }
+      });
+    });
+
+    //bind blur on duration
+    taskEditor.find("#duration").change(function () {
+      var start = Date.parseString(taskEditor.find("#start").val());
+      var el = $(this);
+      var dur = parseInt(el.val());
+      dur = dur <= 0 ? 1 : dur;
+      el.val(dur);
+      taskEditor.find("#end").val(new Date(computeEndByDuration(start.getTime(), dur)).format());
+    });
+
+    //bind add assignment
+    taskEditor.find("#addAssig").click(function () {
+      var assigsTable = taskEditor.find("#assigsTable");
+      var assigRow = $.JST.createFromTemplate({task:task, assig:{id:"tmp_" + new Date().getTime()}}, "ASSIGNMENT_ROW");
+      assigsTable.append(assigRow);
+    });
+
+    taskEditor.find("#status").click(function () {
+      var tskStatusChooser = $(this);
+      var changer = $.JST.createFromTemplate({}, "CHANGE_STATUS");
+      changer.css("top", tskStatusChooser.position().top);
+      changer.find("[status=" + task.status + "]").addClass("selected");
+      changer.find(".taskStatus").click(function () {
+        tskStatusChooser.attr("status", $(this).attr("status"));
+        changer.remove();
+        tskStatusChooser.show();
+      });
+      tskStatusChooser.hide().oneTime(3000, "hideChanger", function () {
+        changer.remove();
+        $(this).show();
+      });
+      tskStatusChooser.after(changer);
+    });
+
+    //save task
+    taskEditor.find("#saveButton").click(function () {
+      var task = self.master.getTask(taskId); // get task again because in case of rollback old task is lost
+
+      self.master.beginTransaction();
+      task.name = taskEditor.find("#name").val();
+      task.description = taskEditor.find("#description").val();
+      task.code = taskEditor.find("#code").val();
+      task.progress = parseFloat(taskEditor.find("#progress").val());
+      task.duration = parseInt(taskEditor.find("#duration").val());
+      task.startIsMilestone = taskEditor.find("#startIsMilestone").is(":checked");
+      task.endIsMilestone = taskEditor.find("#endIsMilestone").is(":checked");
+
+      //set assignments
+      taskEditor.find("tr[assigId]").each(function () {
+        var trAss = $(this);
+        var assId = trAss.attr("assigId");
+        var resId = trAss.find("[name=resourceId]").val();
+        var roleId = trAss.find("[name=roleId]").val();
+        var effort = millisFromString(trAss.find("[name=effort]").val());
+
+
+        //check if an existing assig has been deleted and re-created with the same values
+        var found = false;
+        for (var i = 0; i < task.assigs.length; i++) {
+          var ass = task.assigs[i];
+
+          if (assId == ass.id) {
+            ass.effort = effort;
+            ass.roleId = roleId;
+            ass.resourceId = resId;
+            ass.touched = true;
+            found = true;
+            break;
+
+          } else if (roleId == ass.roleId && resId == ass.resourceId) {
+            ass.effort = effort;
+            ass.touched = true;
+            found = true;
+            break;
+
+          }
+        }
+
+        if (!found) { //insert
+          var ass = task.createAssignment("tmp_" + new Date().getTime(), resId, roleId, effort);
+          ass.touched = true;
+        }
+
+      });
+
+      //remove untouched assigs
+      task.assigs = task.assigs.filter(function (ass) {
+        var ret = ass.touched;
+        delete ass.touched;
+        return ret;
+      });
+
+      //change dates
+      task.setPeriod(Date.parseString(taskEditor.find("#start").val()).getTime(), Date.parseString(taskEditor.find("#end").val()).getTime() + (3600000 * 24));
+
+      //change status
+      task.changeStatus(taskEditor.find("#status").attr("status"));
+
+      if (self.master.endTransaction()) {
+        $("#__blackpopup__").trigger("close");
+      }
+
+    });
+  }
+
+  var ndo = createBlackPage(800, 500).append(taskEditor);
+
+};
diff --git a/src/vendor/jquery-teamwork-gantt/ganttMaster.js b/src/vendor/jquery-teamwork-gantt/ganttMaster.js
new file mode 100644
index 0000000..ac8c9ac
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/ganttMaster.js
@@ -0,0 +1,702 @@
+/*
+  Copyright (c) 2012-2013 Open Lab
+  Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+function GanttMaster() {
+  this.tasks = [];
+  this.deletedTaskIds=[];
+  this.links = [];
+
+  this.editor; //element for editor
+  this.gantt; //element for gantt
+
+  this.element;
+
+
+  this.resources; //list of resources
+  this.roles;  //list of roles
+
+  this.minEditableDate = 0;
+  this.maxEditableDate = Infinity;
+
+  this.canWriteOnParent=true;
+  this.canWrite=true;
+
+  this.firstDayOfWeek = Date.firstDayOfWeek;
+
+  this.currentTask; // task currently selected;
+
+  this.__currentTransaction;  // a transaction object holds previous state during changes
+  this.__undoStack = [];
+  this.__redoStack = [];
+
+  var self = this;
+}
+
+GanttMaster.prototype.init = function(place) {
+  this.element = place;
+
+  var self=this;
+
+  //load templates
+  $("#gantEditorTemplates").loadTemplates().remove();  // TODO: Remove inline jquery, this should be injected
+
+  //create editor
+  this.editor = new GridEditor(this);
+  this.editor.element.width(place.width() * .9 - 10);
+  place.append(this.editor.element);
+
+  //create gantt
+  this.gantt = new Ganttalendar("m", new Date().getTime() - 3600000 * 24 * 2, new Date().getTime() + 3600000 * 24 * 15, this, place.width() * .6);
+
+  //setup splitter
+  var splitter = $.splittify.init(place, this.editor.element, this.gantt.element, 70);
+  splitter.secondBox.css("overflow-y", "auto").scroll(function() {
+    splitter.firstBox.scrollTop(splitter.secondBox.scrollTop());
+  });
+
+
+  //prepend buttons
+  place.before($.JST.createFromTemplate({}, "GANTBUTTONS"));
+
+
+  //bindings
+  place.bind("refreshTasks.gantt", function() {
+    self.redrawTasks();
+  }).bind("refreshTask.gantt", function(e, task) {
+    self.drawTask(task);
+
+  }).bind("deleteCurrentTask.gantt", function(e) {
+    var row = self.currentTask.getRow();
+    if (self.currentTask && (row>0 || self.currentTask.isNew())) {
+      self.beginTransaction();
+
+      self.currentTask.deleteTask();
+
+      self.currentTask = undefined;
+      //recompute depends string
+      self.updateDependsStrings();
+
+      //redraw
+      self.redraw();
+
+      //focus next row
+      row = row > self.tasks.length - 1 ? self.tasks.length - 1 : row;
+      if (row >= 0) {
+        self.currentTask = self.tasks[row];
+        self.currentTask.rowElement.click();
+        self.currentTask.rowElement.find("[name=name]").focus();
+      }
+      self.endTransaction();
+    }
+
+
+  }).bind("addAboveCurrentTask.gantt", function() {
+    var factory = new TaskFactory();
+
+    var ch;
+    var row = 0;
+    if (self.currentTask) {
+      //cannot add brothers to root
+      if (self.currentTask.level<=0)
+        return;
+
+      ch = factory.build("tmp_" + new Date().getTime(), "", "", self.currentTask.level, self.currentTask.start, 1);
+      row = self.currentTask.getRow();
+    } else {
+      ch = factory.build("tmp_" + new Date().getTime(), "", "", 0, new Date().getTime(), 1);
+    }
+    self.beginTransaction();
+    var task = self.addTask(ch, row);
+    if (task) {
+      task.rowElement.click();
+      task.rowElement.find("[name=name]").focus();
+    }
+    self.endTransaction();
+
+  }).bind("addBelowCurrentTask.gantt", function() {
+    var factory = new TaskFactory();
+    self.beginTransaction();
+    var ch;
+    var row = 0;
+    if (self.currentTask) {
+      ch = factory.build("tmp_" + new Date().getTime(), "", "", self.currentTask.level + 1, self.currentTask.start, 1);
+      row = self.currentTask.getRow() + 1;
+    } else {
+      ch = factory.build("tmp_" + new Date().getTime(), "", "", 0, new Date().getTime(), 1);
+    }
+    var task = self.addTask(ch, row);
+    if (task) {
+      task.rowElement.click();
+      task.rowElement.find("[name=name]").focus();
+    }
+    self.endTransaction();
+
+
+  }).bind("indentCurrentTask.gantt", function() {
+    if (self.currentTask) {
+      self.beginTransaction();
+      self.currentTask.indent();
+      self.endTransaction();
+    }
+
+  }).bind("outdentCurrentTask.gantt", function() {
+    if (self.currentTask) {
+      self.beginTransaction();
+      self.currentTask.outdent();
+      self.endTransaction();
+    }
+
+  }).bind("moveUpCurrentTask.gantt", function() {
+    if (self.currentTask) {
+      self.beginTransaction();
+      self.currentTask.moveUp();
+      self.endTransaction();
+    }
+  }).bind("moveDownCurrentTask.gantt", function() {
+    if (self.currentTask) {
+      self.beginTransaction();
+      self.currentTask.moveDown();
+      self.endTransaction();
+    }
+
+  }).bind("zoomPlus.gantt", function() {
+    self.gantt.zoomGantt(true);
+  }).bind("zoomMinus.gantt", function() {
+    self.gantt.zoomGantt(false);
+
+  }).bind("undo.gantt", function() {
+    self.undo();
+  }).bind("redo.gantt", function() {
+    self.redo();
+  });
+};
+
+GanttMaster.messages = {
+  "CHANGE_OUT_OF_SCOPE":                  "NO_RIGHTS_FOR_UPDATE_PARENTS_OUT_OF_EDITOR_SCOPE",
+  "START_IS_MILESTONE":                   "START_IS_MILESTONE",
+  "END_IS_MILESTONE":                     "END_IS_MILESTONE",
+  "TASK_HAS_CONSTRAINTS":                 "TASK_HAS_CONSTRAINTS",
+  "GANTT_ERROR_DEPENDS_ON_OPEN_TASK":     "GANTT_ERROR_DEPENDS_ON_OPEN_TASK",
+  "GANTT_ERROR_DESCENDANT_OF_CLOSED_TASK":"GANTT_ERROR_DESCENDANT_OF_CLOSED_TASK",
+  "TASK_HAS_EXTERNAL_DEPS":               "TASK_HAS_EXTERNAL_DEPS",
+  "GANTT_ERROR_LOADING_DATA_TASK_REMOVED":"GANTT_ERROR_LOADING_DATA_TASK_REMOVED",
+  "CIRCULAR_REFERENCE":                   "CIRCULAR_REFERENCE",
+  "ERROR_SETTING_DATES":                  "ERROR_SETTING_DATES",
+  "CANNOT_DEPENDS_ON_ANCESTORS":          "CANNOT_DEPENDS_ON_ANCESTORS",
+  "CANNOT_DEPENDS_ON_DESCENDANTS":        "CANNOT_DEPENDS_ON_DESCENDANTS",
+  "INVALID_DATE_FORMAT":                  "INVALID_DATE_FORMAT",
+  "GANTT_QUARTER_SHORT": "GANTT_QUARTER_SHORT",
+  "GANTT_SEMESTER_SHORT":"GANTT_SEMESTER_SHORT"
+};
+
+
+GanttMaster.prototype.createTask = function (id, name, code, level, start, duration) {
+  var factory = new TaskFactory();
+
+  return factory.build(id, name, code, level, start, duration);
+};
+
+
+GanttMaster.prototype.createResource = function (id, name) {
+  var res = new Resource(id, name);
+  return res;
+};
+
+
+//update depends strings
+GanttMaster.prototype.updateDependsStrings = function() {
+  //remove all deps
+  for (var i=0;i<this.tasks.length;i++) {
+    this.tasks[i].depends = "";
+  }
+
+  for (var i=0;i<this.links.length;i++) {
+    var link = this.links[i];
+    var dep = link.to.depends;
+    link.to.depends = link.to.depends + (link.to.depends == "" ? "" : ",") + (link.from.getRow() + 1) + (link.lag ? ":" + link.lag : "");
+  }
+
+};
+
+//------------------------------------  ADD TASK --------------------------------------------
+GanttMaster.prototype.addTask = function(task, row) {
+  //console.debug("master.addTask",task,row,this);
+  task.master = this; // in order to access controller from task
+
+  //replace if already exists
+  var pos = -1;
+  for (var i=0;i<this.tasks.length;i++) {
+    if (task.id == this.tasks[i].id) {
+      pos = i;
+      break;
+    }
+  }
+
+  if (pos >= 0) {
+    this.tasks.splice(pos, 1);
+    row = parseInt(pos);
+  }
+
+  //add task in collection
+  if (typeof(row) != "number") {
+    this.tasks.push(task);
+  } else {
+    this.tasks.splice(row, 0, task);
+
+    //recompute depends string
+    this.updateDependsStrings();
+  }
+
+  //add Link collection in memory
+  var linkLoops = !this.updateLinks(task);
+
+  //set the status according to parent
+  if (task.getParent())
+    task.status=task.getParent().status;
+  else
+    task.status="STATUS_ACTIVE";
+
+
+  var ret = task;
+  if (linkLoops || !task.setPeriod(task.start, task.end)) {
+    //remove task from in-memory collection
+    //console.debug("removing task from memory",task);
+    this.tasks.splice(task.getRow(), 1);
+    ret = undefined;
+  } else {
+    //append task to editor
+    this.editor.addTask(task, row);
+    //append task to gantt
+    this.gantt.addTask(task);
+  }
+  return ret;
+};
+
+
+/**
+ * a project contais tasks, resources, roles, and info about permisions
+ * @param project
+ */
+GanttMaster.prototype.loadProject = function(project) {
+  this.beginTransaction();
+  this.resources = project.resources;
+  this.roles = project.roles;
+  this.canWrite = project.canWrite;
+  this.canWriteOnParent = project.canWriteOnParent;
+
+  if (project.minEditableDate)
+    this.minEditableDate = computeStart(project.minEditableDate);
+  else
+    this.minEditableDate =-Infinity;
+
+  if (project.maxEditableDate)
+    this.maxEditableDate =computeEnd(project.maxEditableDate);
+  else
+    this.maxEditableDate =Infinity;
+
+  this.loadTasks(project.tasks, project.selectedRow);
+  this.deletedTaskIds=[];
+  this.endTransaction();
+  var self=this;
+  this.gantt.element.oneTime(200,function(){self.gantt.centerOnToday()});
+};
+
+
+GanttMaster.prototype.loadTasks = function(tasks, selectedRow) {
+  var factory = new TaskFactory();
+  //reset
+  this.reset();
+
+  for (var i=0;i<tasks.length;i++){
+    var task = tasks[i];
+    if (!(task instanceof Task)) {
+      var t = factory.build(task.id, task.name, task.code, task.level, task.start, task.duration);
+      for (var key in task) {
+        if (key!="end" && key!="start")
+          t[key] = task[key]; //copy all properties
+      }
+      task = t;
+    }
+    task.master = this; // in order to access controller from task
+
+    /*//replace if already exists
+    var pos = -1;
+    for (var i=0;i<this.tasks.length;i++) {
+      if (task.id == this.tasks[i].id) {
+        pos = i;
+        break;
+      }
+    }*/
+
+    this.tasks.push(task);  //append task at the end
+  }
+
+  //var prof=new Profiler("gm_loadTasks_addTaskLoop");
+  for (var i=0;i<this.tasks.length;i++) {
+    var task = this.tasks[i];
+
+    //add Link collection in memory
+    var linkLoops = !this.updateLinks(task);
+
+    if (linkLoops || !task.setPeriod(task.start, task.end)) {
+      alert(GanttMaster.messages.GANNT_ERROR_LOADING_DATA_TASK_REMOVED+"\n" + task.name+"\n"+
+            (linkLoops?GanttMaster.messages.CIRCULAR_REFERENCE:GanttMaster.messages.ERROR_SETTING_DATES));
+
+      //remove task from in-memory collection
+      this.tasks.splice(task.getRow(), 1);
+    } else {
+      //append task to editor
+      this.editor.addTask(task);
+      //append task to gantt
+      this.gantt.addTask(task);
+    }
+  }
+
+  this.editor.fillEmptyLines();
+  //prof.stop();
+
+  // re-select old row if tasks is not empty
+  if (this.tasks && this.tasks.length>0){
+  selectedRow = selectedRow ? selectedRow : 0;
+  this.tasks[selectedRow].rowElement.click();
+  }
+
+};
+
+
+GanttMaster.prototype.getTask = function(taskId) {
+  var ret;
+  for (var i=0;i<this.tasks.length;i++) {
+    var tsk = this.tasks[i];
+    if (tsk.id == taskId) {
+      ret = tsk;
+      break;
+    }
+  }
+  return ret;
+};
+
+
+GanttMaster.prototype.getResource = function(resId) {
+  var ret;
+  for (var i=0;i<this.resources.length;i++) {
+    var res = this.resources[i];
+    if (res.id == resId) {
+      ret = res;
+      break;
+    }
+  }
+  return ret;
+};
+
+
+GanttMaster.prototype.changeTaskDates = function(task, start, end) {
+  return task.setPeriod(start, end);
+};
+
+
+GanttMaster.prototype.moveTask = function(task, newStart) {
+  return task.moveTo(newStart, true);
+};
+
+
+GanttMaster.prototype.taskIsChanged = function() {
+  //console.debug("taskIsChanged");
+  var master=this;
+
+  //refresh is executed only once every 50ms
+  this.element.stopTime("gnnttaskIsChanged");
+  //var profilerext = new Profiler("gm_taskIsChangedRequest");
+  this.element.oneTime(50, "gnnttaskIsChanged", function() {
+    //console.debug("task Is Changed real call to redraw");
+    //var profiler = new Profiler("gm_taskIsChangedReal");
+    master.editor.redraw();
+    master.gantt.refreshGantt();
+    //profiler.stop();
+  });
+  //profilerext.stop();
+};
+
+
+GanttMaster.prototype.redraw = function() {
+  this.editor.redraw();
+  this.gantt.refreshGantt();
+};
+
+GanttMaster.prototype.reset = function() {
+  this.tasks = [];
+  this.links = [];
+  this.deletedTaskIds=[];
+  this.__undoStack = [];
+  this.__redoStack = [];
+  delete this.currentTask;
+
+  this.editor.reset();
+  this.gantt.reset();
+};
+
+
+GanttMaster.prototype.showTaskEditor = function(taskId) {
+  var task = this.getTask(taskId);
+  task.rowElement.find(".edit").click();
+};
+
+GanttMaster.prototype.saveProject = function() {
+  return this.saveGantt(false);
+};
+
+GanttMaster.prototype.saveGantt = function(forTransaction) {
+  //var prof = new Profiler("gm_saveGantt");
+  var saved = [];
+  for (var i=0;i<this.tasks.length;i++) {
+    var task = this.tasks[i];
+    var cloned = task.clone();
+    delete cloned.master;
+    delete cloned.rowElement;
+    delete cloned.ganttElement;
+
+    saved.push(cloned);
+  }
+
+  var ret = {tasks:saved};
+  if (this.currentTask) {
+    ret.selectedRow = this.currentTask.getRow();
+  }
+
+  ret.deletedTaskIds=this.deletedTaskIds;  //this must be consistent with transactions and undo
+
+  if (!forTransaction) {
+    ret.resources = this.resources;
+    ret.roles = this.roles;
+    ret.canWrite = this.canWrite;
+    ret.canWriteOnParent = this.canWriteOnParent;
+  }
+
+  //prof.stop();
+  return ret;
+};
+
+
+GanttMaster.prototype.updateLinks = function(task) {
+  //console.debug("updateLinks");
+  //var prof= new Profiler("gm_updateLinks");
+
+  // defines isLoop function
+  function isLoop(task, target, visited) {
+    if (target == task) {
+      return true;
+    }
+    
+    var sups = task.getSuperiors();
+    var loop = false;
+    for (var i=0;i<sups.length;i++) {
+      var supLink = sups[i];
+      if (supLink.from == target) {
+        loop = true;
+        break;
+      } else {
+        if (visited.indexOf(supLink.from) <= 0) {
+          visited.push(supLink.from);
+          if (isLoop(supLink.from, target, visited)) {
+            loop = true;
+            break;
+          }
+        }
+      }
+    }
+    return loop;
+  }
+
+  //remove my depends
+  this.links = this.links.filter(function(link) {
+    return link.to != task;
+  });
+
+  var todoOk = true;
+  if (task.depends) {
+
+    //cannot depend from an ancestor
+    var parents = task.getParents();
+    //cannot depend from descendants
+    var descendants=task.getDescendant();
+
+    var deps = task.depends.split(",");
+    var newDepsString = "";
+
+    var visited = [];
+    for (var j=0;j<deps.length;j++) {
+      var dep = deps[j]; // in the form of row(lag) e.g. 2:3,3:4,5
+      var par = dep.split(":");
+      var lag = 0;
+
+      if (par.length > 1) {
+        lag = parseInt(par[1]);
+      }
+
+      var sup = this.tasks[parseInt(par[0] - 1)];
+
+      if (sup) {
+        if (parents && parents.indexOf(sup) >= 0) {
+          this.setErrorOnTransaction(task.name + "\n"+GanttMaster.messages.CANNOT_DEPENDS_ON_ANCESTORS+"\n" + sup.name);
+          todoOk = false;
+
+        } else if (descendants && descendants.indexOf(sup) >= 0) {
+          this.setErrorOnTransaction(task.name + "\n"+GanttMaster.messages.CANNOT_DEPENDS_ON_DESCENDANTS+"\n" + sup.name);
+          todoOk = false;
+
+        } else if (isLoop(sup, task, visited)) {
+          todoOk = false;
+          this.setErrorOnTransaction(GanttMaster.messages.CIRCULAR_REFERENCE+"\n" + task.name + " -> " + sup.name);
+        } else {
+          this.links.push(new Link(sup, task, lag));
+          newDepsString = newDepsString + (newDepsString.length > 0 ? "," : "") + dep;
+        }
+      }
+    }
+
+    if (todoOk) {
+      task.depends = newDepsString;
+    }
+
+  }
+
+  //prof.stop();
+
+  return todoOk;
+};
+
+
+//<%----------------------------- TRANSACTION MANAGEMENT ---------------------------------%>
+GanttMaster.prototype.beginTransaction = function() {
+  if (!this.__currentTransaction) {
+    this.__currentTransaction = {
+      snapshot:JSON.stringify(this.saveGantt(true)),
+      errors:[]
+    };
+  } else {
+    console.error("Cannot open twice a transaction");
+  }
+  return this.__currentTransaction;
+};
+
+
+GanttMaster.prototype.endTransaction = function() {
+  if (!this.__currentTransaction) {
+    console.error("Transaction never started.");
+    return true;
+  }
+
+  var ret = true;
+
+  //no error -> commit
+  if (this.__currentTransaction.errors.length <= 0) {
+    //console.debug("committing transaction");
+
+    //put snapshot in undo
+    this.__undoStack.push(this.__currentTransaction.snapshot);
+    //clear redo stack
+    this.__redoStack = [];
+
+    //shrink gantt bundaries
+    this.gantt.originalStartMillis = Infinity;
+    this.gantt.originalEndMillis = -Infinity;
+    for (var i=0;i<this.tasks.length;i++) {
+      var task = this.tasks[i];
+      if (this.gantt.originalStartMillis > task.start)
+        this.gantt.originalStartMillis = task.start;
+      if (this.gantt.originalEndMillis < task.end)
+        this.gantt.originalEndMillis = task.end;
+
+    }
+    this.taskIsChanged(); //enqueue for gantt refresh
+
+
+    //error -> rollback
+  } else {
+    ret = false;
+    //console.debug("rolling-back transaction");
+    //try to restore changed tasks
+    var oldTasks = JSON.parse(this.__currentTransaction.snapshot);
+    this.deletedTaskIds=oldTasks.deletedTaskIds;
+    this.loadTasks(oldTasks.tasks, oldTasks.selectedRow);
+    this.redraw();
+
+    //compose error message
+    var msg = "";
+    for (var i=0;i<this.__currentTransaction.errors.length;i++) {
+      var err = this.__currentTransaction.errors[i];
+      msg = msg + err.msg + "\n\n";
+    }
+    alert(msg);
+  }
+  //reset transaction
+  this.__currentTransaction = undefined;
+
+  return ret;
+};
+
+//this function notify an error to a transaction -> transaction will rollback
+GanttMaster.prototype.setErrorOnTransaction = function(errorMessage, task) {
+  if (this.__currentTransaction) {
+    this.__currentTransaction.errors.push({msg:errorMessage,task:task});
+  } else {
+    console.error(errorMessage);
+  }
+};
+
+// inhibit undo-redo
+GanttMaster.prototype.checkpoint= function() {
+  this.__undoStack = [];
+  this.__redoStack = [];
+};
+
+//----------------------------- UNDO/REDO MANAGEMENT ---------------------------------%>
+
+GanttMaster.prototype.undo = function() {
+  //console.debug("undo before:",undoStack,redoStack);
+  if (this.__undoStack.length > 0) {
+    var his = this.__undoStack.pop();
+    this.__redoStack.push(JSON.stringify(this.saveGantt()));
+
+    var oldTasks = JSON.parse(his);
+    this.deletedTaskIds=oldTasks.deletedTaskIds;
+    this.loadTasks(oldTasks.tasks, oldTasks.selectedRow);
+    //console.debug(oldTasks,oldTasks.deletedTaskIds)
+    this.redraw();
+    //console.debug("undo after:",undoStack,redoStack);
+  }
+};
+
+GanttMaster.prototype.redo = function() {
+  //console.debug("redo before:",undoStack,redoStack);
+  if (this.__redoStack.length > 0) {
+    var his = this.__redoStack.pop();
+    this.__undoStack.push(JSON.stringify(this.saveGantt()));
+
+    var oldTasks = JSON.parse(his);
+    this.deletedTaskIds=oldTasks.deletedTaskIds;
+    this.loadTasks(oldTasks.tasks, oldTasks.selectedRow);
+    this.redraw();
+    //console.debug("redo after:",undoStack,redoStack);
+  }
+};
+
diff --git a/src/vendor/jquery-teamwork-gantt/ganttTask.js b/src/vendor/jquery-teamwork-gantt/ganttTask.js
new file mode 100644
index 0000000..ba80b2c
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/ganttTask.js
@@ -0,0 +1,947 @@
+/*
+  Copyright (c) 2012-2013 Open Lab
+  Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+ * A method to instantiate valid task models from
+ * raw data.
+ */
+function TaskFactory() {
+
+  /**
+   * Build a new Task
+   */
+  this.build = function(id, name, code, level, start, duration) {
+    // Set at beginning of day
+    var adjusted_start = computeStart(start);
+    var calculated_end = computeEndByDuration(adjusted_start, duration);
+
+    return new Task(id, name, code, level, adjusted_start, calculated_end, duration);
+  };
+
+}
+
+function Task(id, name, code, level, start, end, duration) {
+  this.id = id;
+  this.name = name;
+  this.code = code;
+  this.level = level;
+  this.status = "STATUS_UNDEFINED";
+
+  this.start = start
+  this.duration = duration;
+  this.end = end;
+
+  this.startIsMilestone = false;
+  this.endIsMilestone = false;
+
+  this.collapsed = false;
+
+  this.rowElement; //row editor html element
+  this.ganttElement; //gantt html element
+  this.master;
+
+  this.assigs = [];
+}
+
+Task.prototype.clone = function () {
+  var ret = {};
+  for (var key in this) {
+    if (typeof(this[key]) != "function") {
+      ret[key] = this[key];
+    }
+  }
+  return ret;
+};
+
+Task.prototype.getAssigsString = function () {
+  var ret = "";
+  for (var i=0;i<this.assigs.length;i++) {
+    var ass = this.assigs[i];
+    var res = this.master.getResource(ass.resourceId);
+    if (res) {
+      ret = ret + (ret == "" ? "" : ", ") + res.name;
+    }
+  }
+  return ret;
+};
+
+Task.prototype.createAssignment = function (id, resourceId, roleId, effort) {
+  var assig = new Assignment(id, resourceId, roleId, effort);
+  this.assigs.push(assig);
+  return assig;
+};
+
+
+//<%---------- SET PERIOD ---------------------- --%>
+Task.prototype.setPeriod = function (start, end) {
+  //console.debug("setPeriod ",this.name,new Date(start),new Date(end));
+  //var profilerSetPer = new Profiler("gt_setPeriodJS");
+
+  if (start instanceof Date) {
+    start = start.getTime();
+  }
+
+  if (end instanceof Date) {
+    end = end.getTime();
+  }
+
+  var originalPeriod = {
+    start: this.start,
+    end:  this.end,
+    duration: this.duration
+  };
+
+  //console.debug("setStart",date,date instanceof Date);
+  var wantedStartMillis = start;
+
+  //cannot start after end
+  if (start > end) {
+    start = end;
+  }
+
+  //set a legal start
+  start = computeStart(start);
+
+  //if depends -> start is set to max end + lag of superior
+  var sups = this.getSuperiors();
+  if (sups && sups.length > 0) {
+
+    var supEnd = 0;
+    for (var i=0;i<sups.length;i++) {
+      var link = sups[i];
+      supEnd = Math.max(supEnd, incrementDateByWorkingDays(link.from.end, link.lag));
+    }
+    //if changed by depends move it
+    if (computeStart(supEnd) != start) {
+      return this.moveTo(supEnd + 1, false);
+    }
+  }
+
+  var somethingChanged = false;
+
+  //move date to closest day
+  var date = new Date(start);
+
+  if (this.start != start || this.start != wantedStartMillis) {
+    this.start = start;
+    somethingChanged = true;
+  }
+
+  //set end
+  var wantedEndMillis = end;
+
+  end = computeEnd(end);
+
+  if (this.end != end || this.end != wantedEndMillis) {
+    this.end = end;
+    somethingChanged = true;
+  }
+
+  this.duration = recomputeDuration(this.start, this.end);
+
+  //profilerSetPer.stop();
+
+  //nothing changed exit
+  if (!somethingChanged)
+    return true;
+
+  //external dependencies: exit with error
+  if (this.hasExternalDep) {
+    this.master.setErrorOnTransaction(GanttMaster.messages["TASK_HAS_EXTERNAL_DEPS"] + "\n" + this.name, this);
+    return false;
+  }
+
+  var todoOk = true;
+
+  //I'm restricting
+  var deltaPeriod = originalPeriod.duration - this.duration;
+  var restricting = deltaPeriod > 0;
+  var restrictingStart = restricting && (originalPeriod.start < this.start);
+  var restrictingEnd = restricting && (originalPeriod.end > this.end);
+
+  //console.debug( " originalPeriod.duration "+ originalPeriod.duration +" deltaPeriod "+deltaPeriod+" "+"restricting "+restricting);
+
+  if (restricting) {
+    //loops children to get boundaries
+    var children = this.getChildren();
+    var bs = Infinity;
+    var be = 0;
+    for (var i=0;i<children.length;i++) {
+
+      ch = children[i];
+      //console.debug("restricting: test child "+ch.name+" "+ch.end)
+      if (restrictingEnd) {
+        be = Math.max(be, ch.end);
+      } else {
+        bs = Math.min(bs, ch.start);
+      }
+    }
+
+    if (restrictingEnd) {
+      //console.debug("restricting end ",be, this.end);
+      this.end = Math.max(be, this.end);
+    } else {
+      //console.debug("restricting start");
+      this.start = Math.min(bs, this.start);
+    }
+
+     this.duration = recomputeDuration(this.start, this.end);
+  } else {
+
+    //check global boundaries
+    if (this.start < this.master.minEditableDate || this.end > this.master.maxEditableDate) {
+      this.master.setErrorOnTransaction(GanttMaster.messages["CHANGE_OUT_OF_SCOPE"], this);
+      todoOk = false;
+    }
+
+    //console.debug("set period: somethingChanged",this);
+    if (todoOk && !updateTree(this)) {
+      todoOk = false;
+    }
+  }
+
+  if (todoOk) {
+    //and now propagate to inferiors
+    var infs = this.getInferiors();
+    if (infs && infs.length > 0) {
+      for (var i=0;i<infs.length;i++) {
+        var link = infs[i];
+        todoOk = link.to.moveTo(end, false); //this is not the right date but moveTo checks start
+        if (!todoOk)
+          break;
+      }
+    }
+  }
+
+  return todoOk;
+};
+
+
+//<%---------- MOVE TO ---------------------- --%>
+Task.prototype.moveTo = function (start, ignoreMilestones) {
+  //console.debug("moveTo ",this,start,ignoreMilestones);
+  //var profiler = new Profiler("gt_task_moveTo");
+
+  if (start instanceof Date) {
+    start = start.getTime();
+  }
+
+  var originalPeriod = {
+    start:this.start,
+    end:this.end
+  };
+
+  var wantedStartMillis = start;
+
+  //set a legal start
+  start = computeStart(start);
+
+  //if start is milestone cannot be move
+  if (!ignoreMilestones && this.startIsMilestone && start != this.start) {
+    //notify error
+    this.master.setErrorOnTransaction(GanttMaster.messages["START_IS_MILESTONE"], this);
+    return false;
+  } else if (this.hasExternalDep) {
+    //notify error
+    this.master.setErrorOnTransaction(GanttMaster.messages["TASK_HAS_EXTERNAL_DEPS"], this);
+    return false;
+  }
+
+  //if depends start is set to max end + lag of superior
+  var sups = this.getSuperiors();
+  if (sups && sups.length > 0) {
+    var supEnd = 0;
+    for (var i=0;i<sups.length;i++) {
+      var link = sups[i];
+      supEnd = Math.max(supEnd, incrementDateByWorkingDays(link.from.end, link.lag));
+    }
+    start = supEnd + 1;
+  }
+  //set a legal start
+  start = computeStart(start);
+
+  var end = computeEndByDuration(start, this.duration);
+
+  if (this.start != start || this.start != wantedStartMillis) {
+    //in case of end is milestone it never changes, but recompute duration
+    if (!ignoreMilestones && this.endIsMilestone) {
+      end = this.end;
+      this.duration = recomputeDuration(start, end);
+    }
+    this.start = start;
+    this.end = end;
+    //profiler.stop();
+
+    //check global boundaries
+    if (this.start < this.master.minEditableDate || this.end > this.master.maxEditableDate) {
+      this.master.setErrorOnTransaction(GanttMaster.messages["CHANGE_OUT_OF_SCOPE"], this);
+      return false;
+    }
+
+
+    var panDelta = originalPeriod.start - this.start;
+    //console.debug("panDelta",panDelta);
+    //loops children to shift them
+    var children = this.getChildren();
+    for (var i=0;i<children.length;i++) {
+      ch = children[i];
+      if (!ch.moveTo(ch.start - panDelta, false)) {
+        return false;
+      }
+    }
+
+
+    //console.debug("set period: somethingChanged",this);
+    if (!updateTree(this)) {
+      return false;
+    }
+
+
+    //and now propagate to inferiors
+    var infs = this.getInferiors();
+    if (infs && infs.length > 0) {
+      for (var i=0;i<infs.length;i++) {
+        var link = infs[i];
+
+        //this is not the right date but moveTo checks start
+        if (!link.to.moveTo(end, false)) {
+          return false;
+        }
+      }
+    }
+
+  }
+
+  return true;
+};
+
+
+function updateTree(task) {
+  //console.debug("updateTree ",task);
+  var error;
+
+  //try to enlarge parent
+  var p = task.getParent();
+
+  //no parent:exit
+  if (!p)
+    return true;
+
+
+  var newStart = p.start;
+  var newEnd = p.end;
+
+  if (p.start > task.start) {
+    if (p.startIsMilestone) {
+      task.master.setErrorOnTransaction(GanttMaster.messages["START_IS_MILESTONE"] + "\n" + p.name, task);
+      return false;
+    } else if (p.depends) {
+      task.master.setErrorOnTransaction(GanttMaster.messages["TASK_HAS_CONSTRAINTS"] + "\n" + p.name, task);
+      return false;
+    }
+
+    newStart = task.start;
+  }
+
+  if (p.end < task.end) {
+    if (p.endIsMilestone) {
+      task.master.setErrorOnTransaction(GanttMaster.messages["END_IS_MILESTONE"] + "\n" + p.name, task);
+      return false;
+    }
+
+    newEnd = task.end;
+  }
+
+  //propagate updates if needed
+  if (newStart != p.start || newEnd != p.end) {
+    //has external deps ?
+    if (p.hasExternalDep) {
+      task.master.setErrorOnTransaction(GanttMaster.messages["TASK_HAS_EXTERNAL_DEPS"] + "\n" + p.name, task);
+      return false;
+    }
+
+    return p.setPeriod(newStart, newEnd);
+  }
+
+
+  return true;
+}
+
+//<%---------- CHANGE STATUS ---------------------- --%>
+Task.prototype.changeStatus = function(newStatus) {
+  //console.debug("changeStatus: "+this.name+" from "+this.status+" -> "+newStatus);
+  //compute descendant for identify a cone where status changes propagate
+  var cone = this.getDescendant();
+
+  function propagateStatus(task, newStatus, manuallyChanged, propagateFromParent, propagateFromChildren) {
+    var oldStatus = task.status;
+
+    //no changes exit
+    if(newStatus == oldStatus){
+      return true;
+    }
+    //console.debug("propagateStatus: "+task.name + " from " + task.status + " to " + newStatus + " " + (manuallyChanged?" a manella":"")+(propagateFromParent?" da parent":"")+(propagateFromChildren?" da children":""));
+
+    var todoOk = true;
+    task.status = newStatus;
+
+    //xxxx -> STATUS_DONE            may activate dependent tasks, both suspended and undefined. Will set to done all descendants.
+    //STATUS_FAILED -> STATUS_DONE          do nothing if not forced by hand
+    if (newStatus == "STATUS_DONE") {
+
+      if ((manuallyChanged || oldStatus != "STATUS_FAILED")) { //cannot change for cascade when failed
+
+        //can be closed only if superiors are already done
+        var sups = task.getSuperiors();
+        for (var i=0;i<sups.length;i++) {
+          if (cone.indexOf(sups[i].from) < 0) {
+            if (sups[i].from.status != "STATUS_DONE") {
+              if (manuallyChanged || propagateFromParent)
+                task.master.setErrorOnTransaction(GanttMaster.messages["GANTT_ERROR_DEPENDS_ON_OPEN_TASK"] + "\n" + sups[i].from.name + " -> " + task.name);
+              todoOk = false;
+              break;
+            }
+          }
+        }
+
+        if (todoOk) {
+          //todo set progress to 100% if set on config
+
+          var chds = task.getChildren();
+          //set children as done
+          for (var i=0;i<chds.length;i++)
+            propagateStatus(chds[i], "STATUS_DONE", false,true,false);
+
+          //set inferiors as active if outside the cone
+          propagateToInferiors(cone, task.getInferiors(), "STATUS_ACTIVE");
+        }
+      } else {
+        todoOk = false;
+      }
+
+
+      //  STATUS_UNDEFINED -> STATUS_ACTIVE       all children become active, if they have no dependencies.
+      //  STATUS_SUSPENDED -> STATUS_ACTIVE       sets to active all children and their descendants that have no inhibiting dependencies.
+      //  STATUS_DONE -> STATUS_ACTIVE            all those that have dependencies must be set to suspended.
+      //  STATUS_FAILED -> STATUS_ACTIVE          nothing happens: child statuses must be reset by hand.
+    } else if (newStatus == "STATUS_ACTIVE") {
+
+      if ((manuallyChanged || oldStatus != "STATUS_FAILED")) { //cannot change for cascade when failed
+
+        //activate parent if closed
+        var par=task.getParent();
+        if (par && par.status != "STATUS_ACTIVE") {
+          todoOk=propagateStatus(par,"STATUS_ACTIVE",false,false,true);
+        }
+
+        if(todoOk){
+          //can be active only if superiors are already done
+          var sups = task.getSuperiors();
+          for (var i=0;i<sups.length;i++) {
+            if (sups[i].from.status != "STATUS_DONE") {
+              if (manuallyChanged || propagateFromChildren)
+              task.master.setErrorOnTransaction(GanttMaster.messages["GANTT_ERROR_DEPENDS_ON_OPEN_TASK"] + "\n" + sups[i].from.name + " -> " + task.name);
+              todoOk = false;
+              break;
+            }
+          }
+        }
+
+        if (todoOk) {
+          var chds = task.getChildren();
+          if (oldStatus == "STATUS_UNDEFINED" || oldStatus == "STATUS_SUSPENDED") {
+            //set children as active
+            for (var i=0;i<chds.length;i++)
+              if (chds[i].status != "STATUS_DONE" )
+                propagateStatus(chds[i], "STATUS_ACTIVE", false,true,false);
+          }
+
+          //set inferiors as suspended
+          var infs = task.getInferiors();
+          for (var i=0;i<infs.length;i++)
+            propagateStatus(infs[i].to, "STATUS_SUSPENDED", false,false,false);
+        }
+      } else {
+        todoOk = false;
+      }
+
+      // xxxx -> STATUS_SUSPENDED       all active children and their active descendants become suspended. when not failed or forced
+      // xxxx -> STATUS_UNDEFINED       all active children and their active descendants become suspended. when not failed or forced
+    } else if (newStatus == "STATUS_SUSPENDED" || newStatus == "STATUS_UNDEFINED") {
+      if (manuallyChanged || oldStatus != "STATUS_FAILED") { //cannot change for cascade when failed
+
+        //suspend parent if not active
+        var par=task.getParent();
+        if (par && par.status != "STATUS_ACTIVE") {
+          todoOk=propagateStatus(par,newStatus,false,false,true);
+        }
+
+
+        var chds = task.getChildren();
+        //set children as active
+        for (var i=0;i<chds.length;i++){
+          if (chds[i].status != "STATUS_DONE")
+            propagateStatus(chds[i], newStatus, false,true,false);
+        }
+
+        //set inferiors as STATUS_SUSPENDED or STATUS_UNDEFINED
+        propagateToInferiors(cone, task.getInferiors(), newStatus);
+      } else {
+        todoOk = false;
+      }
+
+      // xxxx -> STATUS_FAILED children and dependent failed
+    } else if (newStatus == "STATUS_FAILED") {
+      var chds = task.getChildren();
+      //set children as failed
+      for (var i=0;i<chds.length;i++)
+        propagateStatus(chds[i], "STATUS_FAILED", false,true,false);
+
+      //set inferiors as active
+      //set children as done
+      propagateToInferiors(cone, task.getInferiors(), "STATUS_FAILED");
+    }
+    if (!todoOk){
+      task.status = oldStatus;
+      //console.debug("status rolled back: "+task.name + " to " + oldStatus);
+    }
+
+    return todoOk;
+  }
+
+  /**
+   * A helper method to traverse an array of 'inferior' tasks
+   * and signal a status change.
+   */
+  function propagateToInferiors(cone, infs, status) {
+    for (var i=0;i<infs.length;i++) {
+      if (cone.indexOf(infs[i].to) < 0) {
+        propagateStatus(infs[i].to, status, false, false, false);
+      }
+    }
+  }
+
+  var todoOk = true;
+  var oldStatus = this.status;
+
+  todoOk = propagateStatus(this, newStatus, true,false,false);
+
+  if (!todoOk)
+    this.status = oldStatus;
+
+  return todoOk;
+};
+
+Task.prototype.synchronizeStatus=function(){
+  var oldS=this.status;
+  this.status="";
+  return this.changeStatus(oldS);
+};
+
+Task.prototype.isLocallyBlockedByDependencies=function(){
+  var sups = this.getSuperiors();
+  var blocked=false;
+  for (var i=0;i<sups.length;i++) {
+    if (sups[i].from.status != "STATUS_DONE") {
+      blocked=true;
+      break;
+    }
+  }
+  return blocked;
+};
+
+//<%---------- TASK STRUCTURE ---------------------- --%>
+Task.prototype.getRow = function() {
+  ret = -1;
+  if (this.master)
+    ret = this.master.tasks.indexOf(this);
+  return ret;
+};
+
+
+Task.prototype.getParents = function() {
+  var ret;
+  if (this.master) {
+    var topLevel = this.level;
+    var pos = this.getRow();
+    ret = [];
+    for (var i = pos; i >= 0; i--) {
+      var par = this.master.tasks[i];
+      if (topLevel > par.level) {
+        topLevel = par.level;
+        ret.push(par);
+      }
+    }
+  }
+  return ret;
+};
+
+
+Task.prototype.getParent = function() {
+  var ret;
+  if (this.master) {
+    for (var i = this.getRow(); i >= 0; i--) {
+      var par = this.master.tasks[i];
+      if (this.level > par.level) {
+        ret = par;
+        break;
+      }
+    }
+  }
+  return ret;
+};
+
+
+Task.prototype.isParent = function() {
+  var ret = false;
+  if (this.master) {
+    var pos = this.getRow();
+    if (pos < this.master.tasks.length - 1)
+      ret = this.master.tasks[pos + 1].level > this.level;
+  }
+  return ret;
+};
+
+
+Task.prototype.getChildren = function() {
+  var ret = [];
+  if (this.master) {
+    var pos = this.getRow();
+    for (var i = pos + 1; i < this.master.tasks.length; i++) {
+      var ch = this.master.tasks[i];
+      if (ch.level == this.level + 1)
+        ret.push(ch);
+      else if (ch.level <= this.level) // exit loop if parent or brother
+        break;
+    }
+  }
+  return ret;
+};
+
+
+Task.prototype.getDescendant = function() {
+  var ret = [];
+  if (this.master) {
+    var pos = this.getRow();
+    for (var i = pos + 1; i < this.master.tasks.length; i++) {
+      var ch = this.master.tasks[i];
+      if (ch.level > this.level)
+        ret.push(ch);
+      else
+        break;
+    }
+  }
+  return ret;
+};
+
+
+Task.prototype.getSuperiors = function() {
+  var ret = [];
+  var task = this;
+  if (this.master) {
+    ret = this.master.links.filter(function(link) {
+      return link.to == task;
+    });
+  }
+  return ret;
+};
+
+
+Task.prototype.getInferiors = function() {
+  var ret = [];
+  var task = this;
+  if (this.master) {
+    ret = this.master.links.filter(function(link) {
+      return link.from == task;
+    });
+  }
+  return ret;
+};
+
+
+Task.prototype.deleteTask = function() {
+  //delete both dom elements
+  this.rowElement.remove();
+  this.ganttElement.remove();
+
+  //remove children
+  var chd = this.getChildren();
+  for (var i=0;i<chd.length;i++) {
+    //add removed child in list
+    if(!chd[i].isNew())
+      this.master.deletedTaskIds.push(chd[i].id);
+    chd[i].deleteTask();
+  }
+
+  if(!this.isNew())
+    this.master.deletedTaskIds.push(this.id);
+
+
+  //remove from in-memory collection
+  this.master.tasks.splice(this.getRow(), 1);
+
+  //remove from links
+  var task = this;
+  this.master.links = this.master.links.filter(function(link) {
+    return link.from != task && link.to != task;
+  });
+};
+
+
+Task.prototype.isNew=function(){
+  return (this.id+"").indexOf("tmp_")==0;
+};
+
+//<%------------------------------------------  INDENT/OUTDENT --------------------------------%>
+Task.prototype.indent = function() {
+  //console.debug("indent", this);
+  //a row above must exist
+  var row = this.getRow();
+
+  //no row no party
+  if (row <=0)
+    return false;
+
+  var ret = false;
+  var taskAbove = this.master.tasks[row - 1];
+  var newLev = this.level + 1;
+  if (newLev <= taskAbove.level + 1) {
+    ret = true;
+    //trick to get parents after indent
+    this.level++;
+    var futureParents = this.getParents();
+    this.level--;
+    var oldLevel = this.level;
+    for (var i = row; i < this.master.tasks.length; i++) {
+      var desc = this.master.tasks[i];
+      if (desc.level > oldLevel || desc == this) {
+        desc.level++;
+        //remove links from descendant to my parents
+        this.master.links = this.master.links.filter(function(link) {
+          var linkToParent = false;
+          if (link.to == desc)
+            linkToParent = futureParents.indexOf(link.from) >= 0;
+          else if (link.from == desc)
+            linkToParent = futureParents.indexOf(link.to) >= 0;
+          return !linkToParent;
+        });
+      } else
+        break;
+    }
+    //recompute depends string
+    this.master.updateDependsStrings();
+    //enlarge parent using a fake set period
+    this.setPeriod(this.start + 1, this.end + 1);
+
+    //force status check
+    this.synchronizeStatus();
+  }
+  return ret;
+};
+
+
+Task.prototype.outdent = function() {
+  //console.debug("outdent", this);
+
+  //a level must be >1 -> cannot escape from root
+  if (this.level <= 1)
+    return false;
+
+  var ret = false;
+  var oldLevel = this.level;
+
+  ret = true;
+  var row = this.getRow();
+  for (var i = row; i < this.master.tasks.length; i++) {
+    var desc = this.master.tasks[i];
+    if (desc.level > oldLevel || desc == this) {
+      desc.level--;
+    } else
+      break;
+  }
+
+  var task = this;
+  var chds = this.getChildren();
+  //remove links from me to my new children
+  this.master.links = this.master.links.filter(function(link) {
+    var linkExist = (link.to == task && chds.indexOf(link.from) >= 0 || link.from == task && chds.indexOf(link.to) >= 0);
+    return !linkExist;
+  });
+
+
+  //enlarge me if inherited children are larger
+  for (var i=0;i<chds.length;i++) {
+    //remove links from me to my new children
+    chds[i].setPeriod(chds[i].start + 1, chds[i].end + 1);
+  }
+
+  //enlarge parent using a fake set period
+  this.setPeriod(this.start + 1, this.end + 1);
+
+  //force status check
+  this.synchronizeStatus();
+  return ret;
+};
+
+
+//<%------------------------------------------  MOVE UP / MOVE DOWN --------------------------------%>
+Task.prototype.moveUp = function() {
+  //console.debug("moveUp", this);
+  var ret = false;
+
+  //a row above must exist
+  var row = this.getRow();
+
+  //no row no party
+  if (row <=0)
+    return false;
+
+  //find new row
+  var newRow;
+  for (newRow = row - 1; newRow >= 0; newRow--) {
+    if (this.master.tasks[newRow].level <= this.level)
+      break;
+  }
+
+  //is a parent or a brother
+  if (this.master.tasks[newRow].level == this.level) {
+    ret = true;
+    //compute descendant
+    var descNumber = 0;
+    for (var i = row + 1; i < this.master.tasks.length; i++) {
+      var desc = this.master.tasks[i];
+      if (desc.level > this.level) {
+        descNumber++;
+      } else {
+        break;
+      }
+    }
+    //move in memory
+    var blockToMove = this.master.tasks.splice(row, descNumber + 1);
+    var top = this.master.tasks.splice(0, newRow);
+    this.master.tasks = [].concat(top, blockToMove, this.master.tasks);
+    //move on dom
+    var rows = this.master.editor.element.find("tr[taskId]");
+    var domBlockToMove = rows.slice(row, row + descNumber + 1);
+    rows.eq(newRow).before(domBlockToMove);
+
+    //recompute depends string
+    this.master.updateDependsStrings();
+  } else {
+    this.master.setErrorOnTransaction(GanttMaster.messages["TASK_MOVE_INCONSISTENT_LEVEL"], this);
+    ret = false;
+  }
+  return ret;
+};
+
+
+Task.prototype.moveDown = function() {
+  //console.debug("moveDown", this);
+
+  //a row below must exist, and cannot move root task
+  var row = this.getRow();
+  if (row >= this.master.tasks.length - 1 || row==0)
+    return false;
+
+  var ret = false;
+
+  //find nearest brother
+  var newRow;
+  for (newRow = row + 1; newRow < this.master.tasks.length; newRow++) {
+    if (this.master.tasks[newRow].level <= this.level)
+      break;
+  }
+
+  //is brother
+  if (this.master.tasks[newRow].level == this.level) {
+    ret = true;
+    //find last desc
+    for (newRow = newRow + 1; newRow < this.master.tasks.length; newRow++) {
+      if (this.master.tasks[newRow].level <= this.level)
+        break;
+    }
+
+    //compute descendant
+    var descNumber = 0;
+    for (var i = row + 1; i < this.master.tasks.length; i++) {
+      var desc = this.master.tasks[i];
+      if (desc.level > this.level) {
+        descNumber++;
+      } else {
+        break;
+      }
+    }
+
+    //move in memory
+    var blockToMove = this.master.tasks.splice(row, descNumber + 1);
+    var top = this.master.tasks.splice(0, newRow - descNumber - 1);
+    this.master.tasks = [].concat(top, blockToMove, this.master.tasks);
+
+
+    //move on dom
+    var rows = this.master.editor.element.find("tr[taskId]");
+    var aft = rows.eq(newRow - 1);
+    var domBlockToMove = rows.slice(row, row + descNumber + 1);
+    aft.after(domBlockToMove);
+
+    //recompute depends string
+    this.master.updateDependsStrings();
+  }
+
+  return ret;
+};
+
+
+//<%------------------------------------------------------------------------  LINKS OBJECT ---------------------------------------------------------------%>
+function Link(taskFrom, taskTo, lagInWorkingDays) {
+  this.from = taskFrom;
+  this.to = taskTo;
+  this.lag = lagInWorkingDays;
+}
+
+
+//<%------------------------------------------------------------------------  ASSIGNMENT ---------------------------------------------------------------%>
+function Assignment(id, resourceId, roleId, effort) {
+  this.id = id;
+  this.resourceId = resourceId;
+  this.roleId = roleId;
+  this.effort = effort;
+}
+
+
+//<%------------------------------------------------------------------------  RESOURCE ---------------------------------------------------------------%>
+function Resource(id, name) {
+  this.id = id;
+  this.name = name;
+}
+
+
+//<%------------------------------------------------------------------------  ROLE ---------------------------------------------------------------%>
+function Role(id, name) {
+  this.id = id;
+  this.name = name;
+}
+
+
+
+
diff --git a/src/vendor/jquery-teamwork-gantt/ganttUtilities.js b/src/vendor/jquery-teamwork-gantt/ganttUtilities.js
new file mode 100644
index 0000000..d34c89c
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/ganttUtilities.js
@@ -0,0 +1,240 @@
+/*
+  Copyright (c) 2012-2013 Open Lab
+  Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+$.fn.gridify = function(options) {
+  this.options = {
+    colResizeZoneWidth:10
+  };
+
+  $.extend(this.options, options);
+  $.gridify.init($(this), this.options);
+  return this;
+};
+
+$.gridify = {
+  init: function(elems, opt) {
+    elems.each(function() {
+      var table = $(this);
+
+      //----------------------  header management start
+      table.find("th.gdfColHeader.gdfResizable:not(.gdfied)").mouseover(function() {
+        $(this).addClass("gdfColHeaderOver");
+
+      }).bind("mouseout.gdf", function() {
+        $(this).removeClass("gdfColHeaderOver");
+        if (!$.gridify.columInResize) {
+          $("body").removeClass("gdfHResizing");
+        }
+
+      }).bind("mousemove.gdf", function(e) {
+        if (!$.gridify.columInResize) {
+          var colHeader = $(this);
+          var mousePos = e.pageX - colHeader.offset().left;
+
+          if (colHeader.width() - mousePos < opt.colResizeZoneWidth) {
+            $("body").addClass("gdfHResizing");
+          } else {
+            $("body").removeClass("gdfHResizing");
+          }
+        }
+
+      }).bind("mousedown.gdf", function(e) {
+        var colHeader = $(this);
+        var mousePos = e.pageX - colHeader.offset().left;
+        if (colHeader.width() - mousePos < opt.colResizeZoneWidth) {
+          $.gridify.columInResize = $(this);
+          //bind event for start resizing
+          //console.debug("start resizing");
+          $(document).bind("mousemove.gdf", function(e) {
+            //manage resizing
+            //console.debug(e.pageX - $.gridify.columInResize.offset().left)
+            $.gridify.columInResize.width(e.pageX - $.gridify.columInResize.offset().left);
+
+
+            //bind mouse up on body to stop resizing
+          }).bind("mouseup.gdf", function() {
+            //console.debug("stop resizing");
+            $(this).unbind("mousemove.gdf").unbind("mouseup.gdf");
+            $("body").removeClass("gdfHResizing");
+            delete $.gridify.columInResize;
+          });
+        }
+      }).addClass("gdfied unselectable").attr("unselectable","true");
+
+
+      //----------------------  cell management start wrapping
+      table.find("td.gdfCell:not(.gdfied)").each(function() {
+        var cell = $(this);
+        if (cell.is(".gdfEditable")) {
+          var inp = $("<input type='text'>").addClass("gdfCellInput");
+          inp.val(cell.text());
+          cell.empty().append(inp);
+        } else {
+          var wrp = $("<div>").addClass("gdfCellWrap");
+          wrp.html(cell.html());
+          cell.empty().append(wrp);
+        }
+      }).addClass("gdfied");
+      ;
+
+    });
+  }
+};
+
+$.splittify = {
+  init: function(where, first, second,perc) {
+
+    perc=perc || 50;
+
+    var splitter = $("<div>").addClass("splitterContainer");
+
+    var firstBox = $("<div>").addClass("splitElement splitBox1");
+    var splitterBar = $("<div>").addClass("splitElement vSplitBar").attr("unselectable", "on").html("|").css("padding-top",where.height()/2+"px");
+    var secondBox = $("<div>").addClass("splitElement splitBox2");
+
+    firstBox.append(first);
+    secondBox.append(second);
+
+    splitter.append(firstBox);
+    splitter.append(secondBox);
+    splitter.append(splitterBar);
+
+
+    where.append(splitter);
+
+    var w = where.innerWidth();
+    firstBox.width(w *perc/ 100 - splitterBar.width()).css({left:0});
+    splitterBar.css({left:firstBox.width()});
+    secondBox.width(w -firstBox.width()-splitterBar.width() ).css({left:firstBox.width() + splitterBar.width()});
+
+
+
+    splitterBar.bind("mousedown.gdf", function(e) {
+      $.splittify.splitterBar = $(this);
+      //bind event for start resizing
+      //console.debug("start splitting");
+      $("body").unselectable().bind("mousemove.gdf", function(e) {
+        //manage resizing
+        //console.debug(e.pageX - $.gridify.columInResize.offset().left)
+        var sb = $.splittify.splitterBar;
+        var pos = e.pageX - sb.parent().offset().left;
+        var w = sb.parent().width();
+        if (pos > 10 && pos < w - 20) {
+          sb.css({left:pos});
+          firstBox.width(pos);
+          secondBox.css({left:pos + sb.width(),width:w - pos - sb.width()});
+        }
+
+        //bind mouse up on body to stop resizing
+      }).bind("mouseup.gdf", function() {
+        //console.debug("stop splitting");
+        $(this).unbind("mousemove.gdf").unbind("mouseup.gdf").clearUnselectable();
+        delete $.splittify.splitterBar;
+
+      });
+    });
+
+    return {firstBox:firstBox,secondBox:secondBox,splitterBar:splitterBar};
+  }
+};
+
+
+
+
+//<%------------------------------------------------------------------------  UTILITIES ---------------------------------------------------------------%>
+  function computeStart(start) {
+    var d = new Date(start+3600000*12);
+    d.setHours(0, 0, 0, 0);
+    //move to next working day
+// Currently Fusionforge does not support isHoliday... sadly
+//     while (isHoliday(d)) {
+//       d.setDate(d.getDate() + 1);
+//     } 
+    d.setHours(0, 0, 0, 0);
+    return d.getTime();
+  }
+
+  function computeEnd(end) {
+    var d = new Date(end-3600000*12);
+    d.setHours(23, 59, 59, 999);
+    //move to next working day
+// Currently Fusionforge does not support isHoliday... sadly
+//     while (isHoliday(d)) {
+//       d.setDate(d.getDate() + 1);
+//     }
+    d.setHours(23, 59, 59, 999);
+    return d.getTime();
+  }
+
+  function computeEndByDuration(start, duration) {
+    var d = new Date(start);
+    //console.debug("computeEndByDuration start ",d,duration)
+    var q = duration - 1;
+    while (q > 0) {
+      d.setDate(d.getDate() + 1);
+// Currently Fusionforge does not support isHoliday... sadly
+//       if (!isHoliday(d))
+         q--;
+    }
+    d.setHours(23, 59, 59, 999);
+    return d.getTime();
+  }
+
+  function incrementDateByWorkingDays(date, days) {
+    var d = new Date(date);
+    d.incrementDateByWorkingDays(days);
+    return d.getTime();
+  }
+
+function recomputeDuration(start, end) {
+   //console.debug("recomputeDuration");
+   return new Date(start).distanceInWorkingDays(new Date(end));
+ }
+
+
+
+//This prototype is provided by the Mozilla foundation and
+//is distributed under the MIT license.
+//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
+
+if (!Array.prototype.filter){
+  Array.prototype.filter = function(fun )
+  {
+    var len = this.length;
+    if (typeof fun != "function")
+      throw new TypeError();
+
+    var res = new Array();
+    var thisp = arguments[1];
+    for (var i = 0; i < len; i++)
+    {
+      if (i in this)
+      {
+        var val = this[i]; // in case fun mutates this
+        if (fun.call(thisp, val, i, this))
+          res.push(val);
+      }
+    }
+    return res;
+  };
+}
\ No newline at end of file
diff --git a/src/vendor/jquery-teamwork-gantt/gantt_compact.css b/src/vendor/jquery-teamwork-gantt/gantt_compact.css
new file mode 100644
index 0000000..aadd49b
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/gantt_compact.css
@@ -0,0 +1,323 @@
+.gdfTable {
+  table-layout: fixed;
+  border-collapse: separate;
+  border-spacing: 0;
+}
+
+.gdfTable td, .gdfTable th {
+  vertical-align: middle;
+  overflow: hidden;
+  text-overflow: clip;
+  white-space: nowrap;
+  font-size: 10px
+}
+
+.gdfCell {
+  overflow: hidden;
+  padding:1px
+}
+
+.gdfColHeader {
+  min-width: 5px;
+  height: 30px;
+}
+
+.gdfCell, .gdfColHeader {
+  border-bottom: 1px solid #eee;
+  border-right: 1px solid #eee;
+}
+
+
+.ganttLines{
+  position:absolute;
+  width:100%;
+  height:1px;
+  border-top:1px solid #eee;
+  z-index:1;
+}
+
+.gdfCellInput {
+  border: 0 none;
+  font-size: 12px;
+  height: 14px;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+  background-color: #d4fbe8;
+}
+
+.gdfCellWrap {
+  border: 0 none;
+  font-size: 12px;
+  height: 14px;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+  overflow: hidden;
+
+  background-color: #ffcccc;
+}
+
+.gdfColHeaderOver {
+  opacity: .7;
+}
+
+.gdfHResizing {
+  cursor: w-resize;
+}
+
+.splitterContainer {
+  width: 100%;
+  height: 100%;
+}
+
+.splitBox1, .splitBox2 {
+  overflow-x: scroll;
+  overflow-y: hidden;
+
+  /*background-color: yellow;*/
+}
+
+.splitBox2 {
+  /*background-color: orange;*/
+}
+
+.unselectable {
+  -webkit-user-select: none;
+  -khtml-user-select: none;
+  -moz-user-select: none;
+  -o-user-select: none;
+  user-select: none;
+}
+
+.splitElement {
+  outline-style: none;
+  position: absolute;
+  height: 100%;
+}
+
+.vSplitBar {
+  width: 5px;
+  background-color: #aaa;
+  cursor: w-resize;
+  text-align: center;
+  color: white;
+}
+
+.end{
+  border-right:1px dotted #666
+}
+
+.holyH{
+    background-color: #9CB7AA;
+}
+.holy{
+  background-color: #FFF5E6;
+}
+
+
+.expcoll{
+  width:6px;
+  height:6px;
+  margin:1px;
+  padding:1px;
+  background-color:yellow;
+  display:inline-block;
+  border:1px solid gray;
+}
+.expcoll.exp{
+  display:none;
+}
+
+
+.ganttTable{
+  table-layout:fixed;
+}
+
+.ganttTable td,.ganttTable th{
+  overflow: hidden;
+  text-overflow: clip;
+  white-space: nowrap;
+}
+
+.ganttHead1,.ganttHead2{
+  height:20px;
+}
+
+.ganttHead1 th,.ganttHead2 th{
+  border-left:1px solid white;
+}
+
+.ganttToday{
+  position:absolute;
+  top:0;
+  width:1px;
+  height:100%;
+  border-left:2px dotted #13AFA5;
+}
+
+.ganttHighLight{
+  position:absolute;
+  width:100%;
+  height:18px;
+  background-color:yellow;
+  opacity:.4;
+}
+
+.ganttButtonBar{
+  position:relative;
+  padding:5px;
+}
+
+.ganttButtonBar .buttons {
+    float:left; margin:45px 0 0 40px
+}
+
+
+.ganttButtonBar .button span.teamworkIcon{
+  font-size: 150%
+}
+
+.ganttButtonSeparator{
+  border-left:1px solid gray;
+  padding-right:10px;
+  margin-left:10px;
+  font-size: 130%
+}
+
+.ganttLinks{
+  z-index:10;
+}
+
+.taskBox{
+  position:absolute;
+  height:18px;
+  margin-top:1px;
+  z-index:100;
+}
+
+.taskBox .layout {
+  height:100%;
+  color:red;
+  border-radius:2px;
+  background: #eee; /* Old browsers */
+  border:1px solid #bbb;
+}
+
+.taskBox .taskStatus {
+    left:5px;
+    top:4px;
+    position:absolute;
+    width:10px;
+    height:10px;
+}
+
+.taskBox .layout .milestone{
+  top:0px;
+  position:absolute;
+  width:16px;
+  background: url(milestone.png) no-repeat;
+  height:16px;
+  display:none;
+}
+.taskBox .layout .milestone.end{
+  right:0;
+}
+.taskBox .layout .milestone.active{
+  display:block;
+}
+
+.taskBox.hasChild .layout{
+  border-top:2px solid black;
+}
+
+.taskBox .taskProgress{
+  height:5px;
+  position:absolute;
+}
+
+.taskBox .layout.extDep{
+  background-image:url(hasExternalDeps.png);
+}
+
+
+.taskLabel{
+  position:absolute;
+  height:18px;
+  color:black;
+  text-align:right;
+  padding-right:5px;
+  overflow:hidden;
+  left:-200px;
+  width:195px;
+  white-space:nowrap;
+}
+
+
+.taskDepLine {
+  border: 1px solid #9999ff;
+  overflow: hidden;
+  position: absolute;
+}
+
+
+.taskEditRow,.emptyRow {
+  height:18px;
+}
+
+.taskEditRow input{
+  border: 0 none;
+  font-size: 10px;
+  height: 14px;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+  font-family: Arial, sans-serif
+}
+
+.taskEditRow.rowSelected td,.taskEditRow.rowSelected input{
+  background-color:#FFFF99;  
+}
+
+.taskStatusBox{
+  position:absolute;
+  width:100px;
+  height:18px;
+  border:1px solid #a0a0a0;
+  background-color:#fff;
+  margin-top:2px;
+  margin-left:-1px;
+  padding: 2px
+}
+.taskStatus{
+  width:12px;
+  height:12px;
+  display:inline-block;
+}
+.taskStatus[status=STATUS_ACTIVE]{
+ background-color: #66FF99;
+}
+.taskStatus[status=STATUS_DONE]{
+ background-color: #0099FF;
+}
+.taskStatus[status=STATUS_FAILED]{
+ background-color: #660066;
+}
+.taskStatus[status=STATUS_SUSPENDED]{
+ background-color: #fbb11e;
+}
+.taskStatus[status=STATUS_UNDEFINED]{
+ background-color: #ffffff;
+}
+.taskStatus.selected{
+  border:#666 2px solid;
+}
+
+
+.ui-resizable-helper { border: 1px dotted #00F;  }
+.ui-resizable-e, .ui-resizable-w {width: 5px;}
+.ui-draggable{
+  cursor:move;
+}
+
+
diff --git a/src/vendor/jquery-teamwork-gantt/hasExternalDeps.png b/src/vendor/jquery-teamwork-gantt/hasExternalDeps.png
new file mode 100644
index 0000000..f566d54
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/hasExternalDeps.png differ
diff --git a/src/vendor/jquery-teamwork-gantt/libs/JST/jquery.JST.js b/src/vendor/jquery-teamwork-gantt/libs/JST/jquery.JST.js
new file mode 100644
index 0000000..4376fd4
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/libs/JST/jquery.JST.js
@@ -0,0 +1,167 @@
+$.fn.loadTemplates = function() {
+  $.JST.loadTemplates($(this));
+  return this;
+};
+
+$.JST = {
+  _templates: new Object(),
+  _decorators:new Object(),
+
+  loadTemplates: function(elems) {
+    elems.each(function() {
+      $(this).find(".__template__").each(function() {
+          var tmpl = $(this);
+          var type = tmpl.attr("type");
+
+          //template may be inside <!-- ... --> or not in case of ajax loaded templates
+          if (tmpl.get(0).firstChild.nodeType == 8) // 8==comment
+            var templateBody = tmpl.get(0).firstChild.nodeValue; // this is inside the comment
+          else
+            var templateBody = tmpl.html(); // this is the whole template
+
+          if (!templateBody.match(/##\w+##/)) { // is Resig' style? e.g. (#=id#) or (# ...some javascript code 'obj' is the alias for the object #)
+            var strFunc =
+                    "var p=[],print=function(){p.push.apply(p,arguments);};" +
+                    "with(obj){p.push('" +
+                    templateBody.replace(/[\r\t\n]/g, " ")
+                            .replace(/'(?=[^#]*#\))/g, "\t")
+                            .split("'").join("\\'")
+                            .split("\t").join("'")
+                            .replace(/\(#=(.+?)#\)/g, "',$1,'")
+                            .split("(#").join("');")
+                            .split("#)").join("p.push('")
+                            + "');}return p.join('');";
+
+          try {
+            $.JST._templates[type] = new Function("obj", strFunc);
+          } catch (e) {
+            console.error("JST error: "+type, e,strFunc);
+          }
+
+          } else { //plain template   e.g. ##id##
+          try {
+            $.JST._templates[type] = templateBody;
+          } catch (e) {
+            console.error("JST error: "+type, e,templateBody);
+          }
+          }
+
+          tmpl.remove();
+
+      });
+    });
+  },
+
+  createFromTemplate: function(jsonData, template, transformToPrintable) {
+    var templates = $.JST._templates;
+
+    var jsData=new Object();
+    if (transformToPrintable){
+      for (var prop in jsonData){
+        var value = jsonData[prop];
+        if (typeof(value) == "string")
+          value = (value + "").replace(/\n/g, "<br>");
+        jsData[prop]=value;
+      }
+    } else {
+      jsData=jsonData;
+    }
+
+
+    function fillStripData(strip, data) {
+      for (var prop in data) {
+        var value = data[prop];
+
+        strip = strip.replace(new RegExp("##" + prop + "##", "gi"), value);
+      }
+      // then clean the remaining ##xxx##
+      strip = strip.replace(new RegExp("##\\w+##", "gi"), "");
+      return strip;
+    }
+
+    var stripString = "";
+    if (typeof(template) == "undefined") {
+      alert("Template is required");
+      stripString = "<div>Template is required</div>";
+
+    } else if (typeof(templates[template]) == "function") { // resig template
+      try {
+        stripString = templates[template](jsData);// create a jquery object in memory
+      } catch (e) {
+        console.error("JST error: "+template,e.message);
+        stripString = "<div> ERROR: "+template+"<br>" + e.message + "</div>";
+      }
+
+    } else {
+      stripString = templates[template]; // recover strip template
+      if (!stripString || stripString.trim() == "") {
+        console.error("No template found for type '" + template + "'");
+        return $("<div>");
+
+      } else {
+        stripString = fillStripData(stripString, jsData); //replace placeholders with data
+      }
+    }
+
+    var ret = $(stripString);// create a jquery object in memory
+    ret.attr("__template", template); // set __template attribute
+
+    //decorate the strip
+    var dec = $.JST._decorators[template];
+    if (typeof (dec) == "function")
+      dec(ret, jsData);
+
+    return ret;
+  },
+
+
+  existsTemplate: function(template) {
+    return $.JST._templates[template];
+  },
+
+  //decorate function is like function(domElement,jsonData){...}
+  loadDecorator:function(template, decorator) {
+    $.JST._decorators[template] = decorator;
+  },
+
+  getDecorator:function(template) {
+    return $.JST._decorators[template];
+  },
+
+  decorateTemplate:function(element) {
+    var dec = $.JST._decorators[element.attr("__template")];
+    if (typeof (dec) == "function")
+      dec(editor);
+  },
+
+  // asynchronous
+  ajaxLoadAsynchTemplates: function(templateUrl, callback) {
+
+    $.get(templateUrl, function(data) {
+
+      var div = $("<div>");
+      div.html(data);
+
+      $.JST.loadTemplates(div);
+
+      if (typeof(callback == "function"))
+        callback();
+    },"html");
+  },
+
+  ajaxLoadTemplates: function(templateUrl) {
+    $.ajax({
+      async:false,
+      url: templateUrl,
+      dataType: "html",
+      success: function(data) {
+        var div = $("<div>");
+        div.html(data);
+        $.JST.loadTemplates(div);
+      }
+    });
+
+  }
+
+
+};
diff --git a/src/vendor/jquery-teamwork-gantt/libs/date.js b/src/vendor/jquery-teamwork-gantt/libs/date.js
new file mode 100644
index 0000000..837bc5d
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/libs/date.js
@@ -0,0 +1,584 @@
+/**
+ * Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com)
+ * 
+ * Dual licensed under the MIT and GPL licenses. 
+ * This basically means you can use this code however you want for
+ * free, but don't claim to have written it yourself!
+ * Donations always accepted: http://www.JavascriptToolbox.com/donate/
+ * 
+ * Please do not link to the .js files on javascripttoolbox.com from
+ * your site. Copy the files locally to your server instead.
+ * 
+ */
+/*
+Date functions
+
+These functions are used to parse, format, and manipulate Date objects.
+See documentation and examples at http://www.JavascriptToolbox.com/lib/date/
+
+*/
+Date.$VERSION = 1.02;
+
+// Utility function to append a 0 to single-digit numbers
+Date.LZ = function(x) {return(x<0||x>9?"":"0")+x};
+// Full month names. Change this for local month names
+Date.monthNames = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
+// Month abbreviations. Change this for local month names
+Date.monthAbbreviations = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
+// Full day names. Change this for local month names
+Date.dayNames = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
+// Day abbreviations. Change this for local month names
+Date.dayAbbreviations = new Array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
+// Used for parsing ambiguous dates like 1/2/2000 - default to preferring 'American' format meaning Jan 2.
+// Set to false to prefer 'European' format meaning Feb 1
+Date.preferAmericanFormat = true;
+
+// Set to 0=SUn for American 1=Mon for european
+Date.firstDayOfWeek = 0;
+
+//default 
+Date.defaultFormat="dd/MM/yyyy";
+
+// If the getFullYear() method is not defined, create it
+if (!Date.prototype.getFullYear) { 
+	Date.prototype.getFullYear = function() { var yy=this.getYear(); return (yy<1900?yy+1900:yy); } ;
+} 
+
+// Parse a string and convert it to a Date object.
+// If no format is passed, try a list of common formats.
+// If string cannot be parsed, return null.
+// Avoids regular expressions to be more portable.
+Date.parseString = function(val, format) {
+	// If no format is specified, try a few common formats
+	if (typeof(format)=="undefined" || format==null || format=="") {
+		var generalFormats=new Array(Date.defaultFormat,'y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d','MMM-d','d-MMM');
+		var monthFirst=new Array('M/d/y','M-d-y','M.d.y','M/d','M-d');
+		var dateFirst =new Array('d/M/y','d-M-y','d.M.y','d/M','d-M');
+		var checkList=new Array(generalFormats,Date.preferAmericanFormat?monthFirst:dateFirst,Date.preferAmericanFormat?dateFirst:monthFirst);
+		for (var i=0; i<checkList.length; i++) {
+			var l=checkList[i];
+			for (var j=0; j<l.length; j++) {
+				var d=Date.parseString(val,l[j]);
+				if (d!=null) { 
+					return d; 
+				}
+			}
+		}
+		return null;
+	};
+
+	this.isInteger = function(val) {
+		for (var i=0; i < val.length; i++) {
+			if ("1234567890".indexOf(val.charAt(i))==-1) { 
+				return false; 
+			}
+		}
+		return true;
+	};
+	this.getInt = function(str,i,minlength,maxlength) {
+		for (var x=maxlength; x>=minlength; x--) {
+			var token=str.substring(i,i+x);
+			if (token.length < minlength) { 
+				return null; 
+			}
+			if (this.isInteger(token)) { 
+				return token; 
+			}
+		}
+	return null;
+	};
+
+
+  this.decodeShortcut=function(str){
+    var dateUpper = str.trim().toUpperCase();
+    var ret=new Date();
+    ret.clearTime();
+
+    if (["NOW","N"].indexOf(dateUpper)>=0) {
+      ret= new Date();
+
+    } else if (["TODAY","T"].indexOf(dateUpper)>=0) {
+      //do nothing
+
+    } else if (["YESTERDAY","Y"].indexOf(dateUpper)>=0) {
+      ret.setDate(ret.getDate()-1);
+
+    } else if (["TOMORROW","TO"].indexOf(dateUpper)>=0) {
+      ret.setDate(ret.getDate()+1);
+
+    } else if (["W", "TW", "WEEK", "THISWEEK", "WEEKSTART", "THISWEEKSTART"].indexOf(dateUpper)>=0) {
+      ret.setFirstDayOfThisWeek();
+
+    } else if (["LW", "LASTWEEK", "LASTWEEKSTART"].indexOf(dateUpper)>=0) {
+      ret.setFirstDayOfThisWeek();
+      ret.setDate(ret.getDate()-7);
+
+    } else if (["NW", "NEXTWEEK", "NEXTWEEKSTART"].indexOf(dateUpper)>=0) {
+      ret.setFirstDayOfThisWeek();
+      ret.setDate(ret.getDate()+7);
+
+    } else if (["M", "TM", "MONTH", "THISMONTH", "MONTHSTART", "THISMONTHSTART"].indexOf(dateUpper)>=0) {
+      ret.setDate(1);
+
+    } else if (["LM", "LASTMONTH", "LASTMONTHSTART"].indexOf(dateUpper)>=0) {
+      ret.setDate(1);
+      ret.setMonth(ret.getMonth()-1);
+
+    } else if (["NM", "NEXTMONTH", "NEXTMONTHSTART"].indexOf(dateUpper)>=0) {
+      ret.setDate(1);
+      ret.setMonth(ret.getMonth()+1);
+
+    } else if (["Q", "TQ", "QUARTER", "THISQUARTER", "QUARTERSTART", "THISQUARTERSTART"].indexOf(dateUpper)>=0) {
+      ret.setDate(1);
+      ret.setMonth(Math.floor((ret.getMonth()) / 3) * 3);
+
+    } else if (["LQ", "LASTQUARTER", "LASTQUARTERSTART"].indexOf(dateUpper)>=0) {
+      ret.setDate(1);
+      ret.setMonth(Math.floor((ret.getMonth()) / 3) * 3-3);
+
+    } else if (["NQ", "NEXTQUARTER", "NEXTQUARTERSTART"].indexOf(dateUpper)>=0) {
+      ret.setDate(1);
+      ret.setMonth(Math.floor((ret.getMonth()) / 3) * 3+3);
+
+
+    } else if (/^-?[0-9]+[DWMY]$/.test(dateUpper)) {
+      var lastOne = dateUpper.substr(dateUpper.length - 1);
+      var val = parseInt(dateUpper.substr(0, dateUpper.length - 1));
+      if (lastOne=="W")
+        ret.setDate(ret.getDate()+val*7 );
+      else if (lastOne=="M")
+        ret.setMonth(ret.getMonth()+val );
+      else if (lastOne=="Y")
+        ret.setYear(ret.getYear()+val );
+    } else {
+      ret=undefined;
+    }
+
+    return ret;
+  };
+
+  var ret=this.decodeShortcut(val);
+  if (ret)
+    return ret;
+
+	val=val+"";
+	format=format+"";
+	var i_val=0;
+	var i_format=0;
+	var c="";
+	var token="";
+	var token2="";
+	var x,y;
+	var year=new Date().getFullYear();
+	var month=1;
+	var date=1;
+	var hh=0;
+	var mm=0;
+	var ss=0;
+	var ampm="";
+	while (i_format < format.length) {
+		// Get next token from format string
+		c=format.charAt(i_format);
+		token="";
+		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
+			token += format.charAt(i_format++);
+		}
+		// Extract contents of value based on format token
+		if (token=="yyyy" || token=="yy" || token=="y") {
+			if (token=="yyyy") { 
+				x=4;y=4; 
+			}
+			if (token=="yy") { 
+				x=2;y=2; 
+			}
+			if (token=="y") { 
+				x=2;y=4; 
+			}
+			year=this.getInt(val,i_val,x,y);
+			if (year==null) { 
+				return null; 
+			}
+			i_val += year.length;
+			if (year.length==2) {
+				if (year > 70) { 
+					year=1900+(year-0); 
+				}
+				else { 
+					year=2000+(year-0); 
+				}
+			}
+
+//		} else if (token=="MMM" || token=="NNN"){
+		} else if (token=="MMM" || token=="MMMM"){
+			month=0;
+			var names = (token=="MMMM"?(Date.monthNames.concat(Date.monthAbbreviations)):Date.monthAbbreviations);
+			for (var i=0; i<names.length; i++) {
+				var month_name=names[i];
+				if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) {
+					month=(i%12)+1;
+					i_val += month_name.length;
+					break;
+				}
+			}
+			if ((month < 1)||(month>12)){
+				return null;
+			}
+		}
+		else if (token=="E"||token=="EE"||token=="EEE"||token=="EEEE"){
+			var names = (token=="EEEE"?Date.dayNames:Date.dayAbbreviations);
+			for (var i=0; i<names.length; i++) {
+				var day_name=names[i];
+				if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) {
+					i_val += day_name.length;
+					break;
+				}
+			}
+		}
+		else if (token=="MM"||token=="M") {
+			month=this.getInt(val,i_val,token.length,2);
+			if(month==null||(month<1)||(month>12)){
+				return null;
+			}
+			i_val+=month.length;
+		}
+		else if (token=="dd"||token=="d") {
+			date=this.getInt(val,i_val,token.length,2);
+			if(date==null||(date<1)||(date>31)){
+				return null;
+			}
+			i_val+=date.length;
+		}
+		else if (token=="hh"||token=="h") {
+			hh=this.getInt(val,i_val,token.length,2);
+			if(hh==null||(hh<1)||(hh>12)){
+				return null;
+			}
+			i_val+=hh.length;
+		}
+		else if (token=="HH"||token=="H") {
+			hh=this.getInt(val,i_val,token.length,2);
+			if(hh==null||(hh<0)||(hh>23)){
+				return null;
+			}
+			i_val+=hh.length;
+		}
+		else if (token=="KK"||token=="K") {
+			hh=this.getInt(val,i_val,token.length,2);
+			if(hh==null||(hh<0)||(hh>11)){
+				return null;
+			}
+			i_val+=hh.length;
+			hh++;
+		}
+		else if (token=="kk"||token=="k") {
+			hh=this.getInt(val,i_val,token.length,2);
+			if(hh==null||(hh<1)||(hh>24)){
+				return null;
+			}
+			i_val+=hh.length;
+			hh--;
+		}
+		else if (token=="mm"||token=="m") {
+			mm=this.getInt(val,i_val,token.length,2);
+			if(mm==null||(mm<0)||(mm>59)){
+				return null;
+			}
+			i_val+=mm.length;
+		}
+		else if (token=="ss"||token=="s") {
+			ss=this.getInt(val,i_val,token.length,2);
+			if(ss==null||(ss<0)||(ss>59)){
+				return null;
+			}
+			i_val+=ss.length;
+		}
+		else if (token=="a") {
+			if (val.substring(i_val,i_val+2).toLowerCase()=="am") {
+				ampm="AM";
+			}
+			else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {
+				ampm="PM";
+			}
+			else {
+				return null;
+			}
+			i_val+=2;
+		}
+		else {
+			if (val.substring(i_val,i_val+token.length)!=token) {
+				return null;
+			}
+			else {
+				i_val+=token.length;
+			}
+		}
+	}
+	// If there are any trailing characters left in the value, it doesn't match
+	if (i_val != val.length) { 
+		return null; 
+	}
+	// Is date valid for month?
+	if (month==2) {
+		// Check for leap year
+		if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
+			if (date > 29){ 
+				return null; 
+			}
+		}
+		else { 
+			if (date > 28) { 
+				return null; 
+			} 
+		}
+	}
+	if ((month==4)||(month==6)||(month==9)||(month==11)) {
+		if (date > 30) { 
+			return null; 
+		}
+	}
+	// Correct hours value
+	if (hh<12 && ampm=="PM") {
+		hh=hh-0+12; 
+	}
+	else if (hh>11 && ampm=="AM") { 
+		hh-=12; 
+	}
+	return new Date(year,month-1,date,hh,mm,ss);
+};
+
+// Check if a date string is valid
+Date.isValid = function(val,format) {
+	return (Date.parseString(val,format) != null);
+};
+
+// Check if a date object is before another date object
+Date.prototype.isBefore = function(date2) {
+	if (date2==null) { 
+		return false; 
+	}
+	return (this.getTime()<date2.getTime());
+};
+
+// Check if a date object is after another date object
+Date.prototype.isAfter = function(date2) {
+	if (date2==null) { 
+		return false; 
+	}
+	return (this.getTime()>date2.getTime());
+};
+
+// Check if two date objects have equal dates and times
+Date.prototype.equals = function(date2) {
+	if (date2==null) { 
+		return false; 
+	}
+	return (this.getTime()==date2.getTime());
+};
+
+// Check if two date objects have equal dates, disregarding times
+Date.prototype.equalsIgnoreTime = function(date2) {
+	if (date2==null) { 
+		return false; 
+	}
+	var d1 = new Date(this.getTime()).clearTime();
+	var d2 = new Date(date2.getTime()).clearTime();
+	return (d1.getTime()==d2.getTime());
+};
+
+// Format a date into a string using a given format string
+Date.prototype.format = function(format) {
+  if (!format)
+    format=Date.defaultFormat;
+	format=format+"";
+	var result="";
+	var i_format=0;
+	var c="";
+	var token="";
+	var y=this.getFullYear()+"";
+	var M=this.getMonth()+1;
+	var d=this.getDate();
+	var E=this.getDay();
+	var H=this.getHours();
+	var m=this.getMinutes();
+	var s=this.getSeconds();
+	// Convert real date parts into formatted versions
+	var value=new Object();
+	if (y.length < 4) {
+		y=""+(+y+1900);
+	}
+	value["y"]=""+y;
+	value["yyyy"]=y;
+	value["yy"]=y.substring(2,4);
+	value["M"]=M;
+	value["MM"]=Date.LZ(M);
+  value["MMM"]=Date.monthAbbreviations[M-1];
+  value["MMMM"]=Date.monthNames[M-1];
+	value["d"]=d;
+	value["dd"]=Date.LZ(d);
+	value["E"]=Date.dayAbbreviations[E];
+	value["EE"]=Date.dayAbbreviations[E];
+	value["EEE"]=Date.dayAbbreviations[E];
+	value["EEEE"]=Date.dayNames[E];
+	value["H"]=H;
+	value["HH"]=Date.LZ(H);
+	if (H==0){
+		value["h"]=12;
+	}
+	else if (H>12){
+		value["h"]=H-12;
+	}
+	else {
+		value["h"]=H;
+	}
+	value["hh"]=Date.LZ(value["h"]);
+	value["K"]=value["h"]-1;
+	value["k"]=value["H"]+1;
+	value["KK"]=Date.LZ(value["K"]);
+	value["kk"]=Date.LZ(value["k"]);
+	if (H > 11) { 
+		value["a"]="PM"; 
+	}
+	else { 
+		value["a"]="AM"; 
+	}
+	value["m"]=m;
+	value["mm"]=Date.LZ(m);
+	value["s"]=s;
+	value["ss"]=Date.LZ(s);
+	while (i_format < format.length) {
+		c=format.charAt(i_format);
+		token="";
+		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
+			token += format.charAt(i_format++);
+		}
+		if (typeof(value[token])!="undefined") { 
+			result=result + value[token]; 
+		}
+		else { 
+			result=result + token; 
+		}
+	}
+	return result;
+};
+
+// Get the full name of the day for a date
+Date.prototype.getDayName = function() { 
+	return Date.dayNames[this.getDay()];
+};
+
+// Get the abbreviation of the day for a date
+Date.prototype.getDayAbbreviation = function() { 
+	return Date.dayAbbreviations[this.getDay()];
+};
+
+// Get the full name of the month for a date
+Date.prototype.getMonthName = function() {
+	return Date.monthNames[this.getMonth()];
+};
+
+// Get the abbreviation of the month for a date
+Date.prototype.getMonthAbbreviation = function() { 
+	return Date.monthAbbreviations[this.getMonth()];
+};
+
+// Clear all time information in a date object
+Date.prototype.clearTime = function() {
+  this.setHours(0); 
+  this.setMinutes(0);
+  this.setSeconds(0); 
+  this.setMilliseconds(0);
+  return this;
+};
+
+// Add an amount of time to a date. Negative numbers can be passed to subtract time.
+Date.prototype.add = function(interval, number) {
+	if (typeof(interval)=="undefined" || interval==null || typeof(number)=="undefined" || number==null) { 
+		return this; 
+	}
+	number = +number;
+	if (interval=='y') { // year
+		this.setFullYear(this.getFullYear()+number);
+	}
+	else if (interval=='M') { // Month
+		this.setMonth(this.getMonth()+number);
+	}
+	else if (interval=='d') { // Day
+		this.setDate(this.getDate()+number);
+	}
+	else if (interval=='w') { // Weekday
+		var step = (number>0)?1:-1;
+		while (number!=0) {
+			this.add('d',step);
+			while(this.getDay()==0 || this.getDay()==6) { 
+				this.add('d',step);
+			}
+			number -= step;
+		}
+	}
+	else if (interval=='h') { // Hour
+		this.setHours(this.getHours() + number);
+	}
+	else if (interval=='m') { // Minute
+		this.setMinutes(this.getMinutes() + number);
+	}
+	else if (interval=='s') { // Second
+		this.setSeconds(this.getSeconds() + number);
+	}
+	return this;
+  
+};
+
+Date.prototype.toInt = function () {
+	return this.getFullYear()*10000+(this.getMonth()+1)*100+this.getDate();
+};
+
+Date.fromInt=function (dateInt){
+  var year = parseInt(dateInt/10000);
+  var month = parseInt((dateInt-year*10000)/100);
+  var day = parseInt(dateInt-year*10000-month*100);
+  return new Date(year,month-1,day,12,00,00);
+};
+
+
+Date.prototype.isHoliday=function(){
+  return isHoliday(this);
+};
+
+Date.prototype.isToday=function(){
+  return this.toInt()==new Date().toInt();  
+};
+
+
+Date.prototype.incrementDateByWorkingDays=function (days) {
+  //console.debug("incrementDateByWorkingDays start ",d,days)
+  var q = Math.abs(days);
+  while (q > 0) {
+    this.setDate(this.getDate() + (days > 0 ? 1 : -1));
+    if (!this.isHoliday())
+      q--;
+  }
+  return this;
+};
+
+
+//todo questo può essere poco performante in caso di distanze grandi
+Date.prototype.distanceInWorkingDays= function (toDate){
+  var pos = new Date(this.getTime());
+  pos.setHours(23, 59, 59, 999);
+  var days = 0;
+  var nd=new Date(toDate.getTime());
+  nd.setHours(23, 59, 59, 999);
+  var end=nd.getTime();
+  while (pos.getTime() <= end) {
+    days = days + (isHoliday(pos) ? 0 : 1);
+    pos.setDate(pos.getDate() + 1);
+  }
+  return days;
+};
+
+
+Date.prototype.setFirstDayOfThisWeek= function (firstDayOfWeek){
+  if (!firstDayOfWeek)
+    firstDayOfWeek=Date.firstDayOfWeek;
+  this.setDate(this.getDate() - this.getDay() +firstDayOfWeek - (this.getDay()==0 && firstDayOfWeek!=0 ?7:0));
+}
diff --git a/src/vendor/jquery-teamwork-gantt/libs/dateField/images/next.png b/src/vendor/jquery-teamwork-gantt/libs/dateField/images/next.png
new file mode 100644
index 0000000..c9a9cc9
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/libs/dateField/images/next.png differ
diff --git a/src/vendor/jquery-teamwork-gantt/libs/dateField/images/prev.png b/src/vendor/jquery-teamwork-gantt/libs/dateField/images/prev.png
new file mode 100644
index 0000000..9de575e
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/libs/dateField/images/prev.png differ
diff --git a/src/vendor/jquery-teamwork-gantt/libs/dateField/jquery.dateField.css b/src/vendor/jquery-teamwork-gantt/libs/dateField/jquery.dateField.css
new file mode 100644
index 0000000..8721732
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/libs/dateField/jquery.dateField.css
@@ -0,0 +1,88 @@
+.calBox {
+  background-color: #91B4B7;
+  padding: 2px;
+  -moz-border-radius: 4px;
+  text-align: center;
+  color: white;
+  width:200px;
+  position:absolute;
+}
+
+.calElement,.calDayHeader  {
+  margin: 1px;
+  display: inline-block;
+  overflow:hidden;
+}
+
+.calDayHeader  {
+    background-color: #617777
+}
+
+.calNavBar {
+  padding: 5px 5px 2px 5px;
+  margin-bottom: 5px;
+}
+
+.calDay {
+}
+
+.calDay .calElement, .calDay .calDayHeader {
+  font-size: 11px;
+  border: 1px dotted #617777;
+}
+
+.calElement.prev,
+.calElement.next {
+  width: 16px;
+  height: 16px;
+  border: none;
+}
+.calElement.prev {
+  background: transparent url(images/prev.png) no-repeat 10px 0;
+  float:left;
+}
+
+.calElement.next {
+  background: transparent url(images/next.png) no-repeat;
+  float:right;
+}
+
+.calElement.next:hover, .calElement.prev:hover {
+  background-color: transparent;
+  border:none;
+  cursor: pointer;
+  opacity: 0.6
+}
+
+.calDay .calElement .dayNumber {
+  font-size: 20px;
+}
+
+.calDay.calFullMonth .dayNumber {
+  font-size: 14px;
+}
+.calDay .calOutOfScope{
+  color: #B8D4D6;
+}
+
+.calElement.selected {
+  background-color: #404040;
+  border: 1px solid #404040;
+}
+
+.calElement:hover {
+  background-color: #404040;
+  border: 1px solid #404040;
+  cursor: pointer;
+}
+
+.calElement.today {
+  background-color: #009E94;
+}
+
+.shortCuts span{
+  border: 1px solid #999999;
+  height:14px;
+  padding-left:2px;
+  padding-right:2px;
+}
\ No newline at end of file
diff --git a/src/vendor/jquery-teamwork-gantt/libs/dateField/jquery.dateField.js b/src/vendor/jquery-teamwork-gantt/libs/dateField/jquery.dateField.js
new file mode 100644
index 0000000..0be2639
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/libs/dateField/jquery.dateField.js
@@ -0,0 +1,212 @@
+/*
+  Copyright (c) 2009 Open Lab
+  Written by Roberto Bicchierai http://roberto.open-lab.com
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+jQuery.fn.dateField = function(options) {
+
+  //check if the input field is passed correctly
+  if (!options.inputField){
+    console.error("You must supply an input field");
+    return false;
+  }
+
+  // --------------------------  start default option values --------------------------
+
+  if (typeof(options.firstDayOfWeek) == "undefined")
+    options.firstDayOfWeek=Date.firstDayOfWeek;
+
+  if (typeof(options.useWheel) == "undefined")
+    options.useWheel=true;
+
+  if (typeof(options.dateFormat) == "undefined")
+    options.dateFormat=Date.defaultFormat;
+  // --------------------------  end default option values --------------------------
+
+
+  // ------------------ start
+  if(options.inputField.is("[readonly]") || options.inputField.is("[disabled]"))
+    return;
+  
+  var calendar = {currentDate: new Date()};
+  calendar.options = options;
+
+  //build the calendar on the first element in the set of matched elements.
+  var theOpener = this.eq(0);
+  var theDiv=$("<div>").addClass("calBox");
+
+
+  //create calendar elements elements
+  var divNavBar = $("<div>").addClass("calNavBar");
+  var divDays = $("<div>").addClass("calDay");
+
+  divDays.addClass("calFullMonth");
+  theDiv.append(divNavBar).append(divDays);
+
+  if (options.isSearchField){
+    var divShortcuts=$("<div>").addClass("shortCuts").html("<span title='last quarter'>LQ</span> <span title='last month'>LM</span> <span title='this month'>M</span> <span title='last week'>LW</span> <span title='this week'>W</span> <span title='yesterday'>Y</span> <span title='today'>T</span><span title='tomorrow'>TM</span> <span title='next week'>NW</span> <span title='next month'>NM</span> <span title='this quarter'>Q</span> <span title='next quarter'>NQ</span>");
+    divShortcuts.click(function(ev){
+      var el=$(ev.target);
+      if(el.is("span")){
+        if (!options.isSearchField)
+          options.inputField.val(Date.parseString(el.text().trim(),options.dateFormat).format(options.dateFormat));
+        else
+          options.inputField.val(el.text().trim());
+        theDiv.remove();
+      }
+    });
+    theDiv.append(divShortcuts);
+  }
+
+
+  $("body").append(theDiv);
+  nearBestPosition(theOpener,theDiv);
+  theDiv.bringToFront();
+
+
+  //register for click outside. Delayed to avoid it run immediately
+  $("body").oneTime(100, "regclibodcal", function() {
+    $("body").bind("click.dateField", function() {
+      $(this).unbind("click.dateField");
+      theDiv.remove();
+    });
+  });
+
+
+  calendar.drawCalendar = function(date) {
+    calendar.currentDate = date;
+
+    var fillNavBar = function(date) {
+      var t = new Date(date.getTime());
+      divNavBar.empty();
+
+      t.setMonth(t.getMonth()-1);
+      var spanPrev = $("<span>").addClass("calElement noCallback prev").attr("millis", t.getTime());
+      t.setMonth(t.getMonth()+1);
+      var spanMonth = $("<span>").html(t.format("MMMM yyyy"));
+      t.setMonth(t.getMonth()+1);
+      var spanNext = $("<span>").addClass("calElement noCallback next").attr("millis", t.getTime());
+
+      divNavBar.append(spanPrev).append(spanMonth).append(spanNext);
+    };
+
+    var fillDaysFullMonth = function(date) {
+      divDays.empty();
+      var t = new Date();//today
+      var w = parseInt((theDiv.width()-4-(4*7))/7)+"px";
+      // draw day headers
+      var d = new Date(date);
+      d.setFirstDayOfThisWeek(options.firstDayOfWeek);
+      for (var i = 0; i < 7; i++) {
+        var span = $("<span>").addClass("calDayHeader").attr("day", d.getDay());
+        span.css("width",w);
+        span.html(Date.dayAbbreviations[d.getDay()]);
+
+        //call the dayHeaderRenderer
+        if (typeof(options.dayHeaderRenderer) == "function")
+          options.dayHeaderRenderer(span,d.getDay());
+
+        divDays.append(span);
+        d.setDate(d.getDate()+1);
+      }
+
+      //draw cells
+      d = new Date(date);
+      d.setDate(1); // set day to start of month
+      d.setFirstDayOfThisWeek(options.firstDayOfWeek);//go to first day of week
+
+      var i=0;
+
+      while ((d.getMonth()<=date.getMonth() && d.getFullYear()<=date.getFullYear()) || d.getFullYear()<date.getFullYear() || (i%7!=0)) {
+        var span = $("<span>").addClass("calElement day").attr("millis", d.getTime());
+
+        span.html("<span class=dayNumber>" + d.getDate() + "</span>").css("width",w);
+        if (d.getYear() == t.getYear() && d.getMonth() == t.getMonth() && d.getDate() == t.getDate())
+          span.addClass("today");
+        if (d.getYear() == date.getYear() && d.getMonth() == date.getMonth() && d.getDate() == date.getDate())
+          span.addClass("selected");
+
+        if(d.getMonth()!=date.getMonth())
+          span.addClass("calOutOfScope");
+
+        //call the dayRenderer
+        if (typeof(options.dayRenderer) == "function")
+          options.dayRenderer(span,d);
+
+        divDays.append(span);
+        d.setDate(d.getDate()+1);
+        i++;
+      }
+
+    };
+
+    fillNavBar(date);
+    fillDaysFullMonth(date);
+  };
+
+
+  theDiv.click(function(ev) {
+    var el = $(ev.target).closest(".calElement");
+    if (el.size() > 0) {
+      var date = new Date(parseInt(el.attr("millis")));
+      if (el.hasClass("day")) {
+        theDiv.remove();
+        if (!el.is(".noCallback")) {
+          options.inputField.val(date.format(options.dateFormat)).attr("millis", date.getTime()).focus();
+          if (typeof(options.callback) == "function")
+            options.callback(date);
+        }
+      } else {
+        calendar.drawCalendar(date);
+      }
+    }
+    ev.stopPropagation();
+  });
+
+
+  //if mousewheel
+  if ($.event.special.mousewheel && options.useWheel) {
+    divDays.mousewheel(function(event, delta) {
+      var d = new Date(calendar.currentDate.getTime());
+      d.setMonth(d.getMonth() + delta);
+      calendar.drawCalendar(d);
+      return false;
+    });
+  }
+
+
+  // start calendar to the date in the input
+  var dateStr=options.inputField.val();
+
+
+  if (!dateStr || !Date.isValid(dateStr,options.dateFormat)){
+    calendar.drawCalendar(new Date());
+  } else {
+    var date = Date.parseString(dateStr,options.dateFormat);
+    //set date string formatted
+    if (!options.isSearchField)
+      options.inputField.val(date.format(options.dateFormat)).attr("millis",date.getTime());
+    
+    calendar.drawCalendar(date);
+  }
+
+  return calendar;
+};
\ No newline at end of file
diff --git a/src/vendor/jquery-teamwork-gantt/libs/i18nJs.js b/src/vendor/jquery-teamwork-gantt/libs/i18nJs.js
new file mode 100644
index 0000000..bce8f4b
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/libs/i18nJs.js
@@ -0,0 +1,140 @@
+
+
+
+  function dateToRelative(localTime){
+    var diff=new Date().getTime()-localTime;
+    var ret="";
+
+    var min=60000;
+    var hour=3600000;
+    var day=86400000;
+    var wee=604800000;
+    var mon=2629800000;
+    var yea=31557600000;
+
+    if (diff<-yea*2)
+      ret ="in ## years".replace("##",(-diff/yea).toFixed(0));
+
+    else if (diff<-mon*9)
+      ret ="in ## months".replace("##",(-diff/mon).toFixed(0));
+
+    else if (diff<-wee*5)
+      ret ="in ## weeks".replace("##",(-diff/wee).toFixed(0));
+
+    else if (diff<-day*2)
+      ret ="in ## days".replace("##",(-diff/day).toFixed(0));
+
+    else if (diff<-hour)
+      ret ="in ## hours".replace("##",(-diff/hour).toFixed(0));
+
+    else if (diff<-min*35)
+      ret ="in about one hour";
+
+    else if (diff<-min*25)
+      ret ="in about half hour";
+
+    else if (diff<-min*10)
+      ret ="in some minutes";
+
+    else if (diff<-min*2)
+      ret ="in few minutes";
+
+    else if (diff<=min)
+      ret ="just now";
+
+    else if (diff<=min*5)
+      ret ="few minutes ago";
+
+    else if (diff<=min*15)
+      ret ="some minutes ago";
+
+    else if (diff<=min*35)
+      ret ="about half hour ago";
+
+    else if (diff<=min*75)
+      ret ="about an hour ago";
+
+    else if (diff<=hour*5)
+      ret ="few hours ago";
+
+    else if (diff<=hour*24)
+      ret ="## hours ago".replace("##",(diff/hour).toFixed(0));
+
+    else if (diff<=day*7)
+      ret ="## days ago".replace("##",(diff/day).toFixed(0));
+
+    else if (diff<=wee*5)
+      ret ="## weeks ago".replace("##",(diff/wee).toFixed(0));
+
+    else if (diff<=mon*12)
+      ret ="## months ago".replace("##",(diff/mon).toFixed(0));
+
+    else
+      ret ="## years ago".replace("##",(diff/yea).toFixed(0));
+
+    return ret;
+  }
+
+  //override date format i18n
+  
+  Date.monthNames = ["January","February","March","April","May","June","July","August","September","October","November","December"];
+  // Month abbreviations. Change this for local month names
+  Date.monthAbbreviations = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
+  // Full day names. Change this for local month names
+  Date.dayNames =["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
+  // Day abbreviations. Change this for local month names
+  Date.dayAbbreviations = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
+  // Used for parsing ambiguous dates like 1/2/2000 - default to preferring 'American' format meaning Jan 2.
+  // Set to false to prefer 'European' format meaning Feb 1
+  Date.preferAmericanFormat = false;
+
+  Date.firstDayOfWeek =1;
+  Date.defaultFormat = "dd/MM/yyyy";
+
+
+  Number.decimalSeparator = ".";
+  Number.groupingSeparator = ",";
+  Number.minusSign = "-";
+  Number.currencyFormat = "##0.00";
+
+
+
+  var millisInWorkingDay =36000000;
+  var workingDaysPerWeek =5;
+
+  function isHoliday(date) {
+    var friIsHoly =false;
+    var satIsHoly =true;
+    var sunIsHoly =true;
+
+    pad = function (val) {
+      val = "0" + val;
+      return val.substr(val.length - 2);
+    };
+
+    var holidays = "#01_01#04_25#08_15#11_01#12_25#12_26#06_02#12_08#05_01#2010_04_05#2010_10_19#2010_05_15#2011_04_04#";
+
+    var ymd = "#" + date.getFullYear() + "_" + pad(date.getMonth() + 1) + "_" + pad(date.getDate()) + "#";
+    var md = "#" + pad(date.getMonth() + 1) + "_" + pad(date.getDate()) + "#";
+    var day = date.getDay();
+
+    return  (day == 5 && friIsHoly) || (day == 6 && satIsHoly) || (day == 0 && sunIsHoly) || holidays.indexOf(ymd) > -1 || holidays.indexOf(md) > -1;
+  }
+
+
+  
+  var i18n = {
+    FORM_IS_CHANGED:"You have some unsaved data on the page!",
+    YES:"yes",
+    NO:"no",
+    FLD_CONFIRM_DELETE:"confirm the deletion?",
+    INVALID_DATA:"The data inserted are invalid for the field format.",
+    ERROR_ON_FIELD:"Error on field",
+    CLOSE_ALL_CONTAINERS:"close all?",
+
+
+
+    DO_YOU_CONFIRM:"Do you confirm?"
+  };
+
+  
\ No newline at end of file
diff --git a/src/vendor/jquery-teamwork-gantt/libs/jquery.livequery.min.js b/src/vendor/jquery-teamwork-gantt/libs/jquery.livequery.min.js
new file mode 100644
index 0000000..993b4d3
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/libs/jquery.livequery.min.js
@@ -0,0 +1,11 @@
+/* Copyright (c) 2007 Brandon Aaron (brandon.aaron at gmail.com || http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * Version: 1.0.2
+ * Requires jQuery 1.1.3+
+ * Docs: http://docs.jquery.com/Plugins/livequery
+ */
+(function($){$.extend($.fn,{livequery:function(type,fn,fn2){var self=this,q;if($.isFunction(type))fn2=fn,fn=type,type=undefined;$.each($.livequery.queries,function(i,query){if(self.selector==query.selector&&self.context==query.context&&type==query.type&&(!fn||fn.$lqguid==query.fn.$lqguid)&&(!fn2||fn2.$lqguid==query.fn2.$lqguid))return(q=query)&&false;});q=q||new $.livequery(this.selector,this.context,type,fn,fn2);q.stopped=false;$.livequery.run(q.id);return this;},expire:function(type,fn,fn2){var self=this;if($.isFunction(type))fn2=fn,fn=type,type=undefined;$.each($.livequery.queries,function(i,query){if(self.selector==query.selector&&self.context==query.context&&(!type||type==query.type)&&(!fn||fn.$lqguid==query.fn.$lqguid)&&(!fn2||fn2.$lqguid==query.fn2.$lqguid)&&!this.stopped)$.livequery.stop(query.id);});return this;}});$.livequery=function(selector,context,type,fn,fn2){this.selector=selector;this.context=context||document;this.type=type;this.fn=fn;this.fn2=fn2;this.elements=[];this.stopped=false;this.id=$.livequery.queries.push(this)-1;fn.$lqguid=fn.$lqguid||$.livequery.guid++;if(fn2)fn2.$lqguid=fn2.$lqguid||$.livequery.guid++;return this;};$.livequery.prototype={stop:function(){var query=this;if(this.type)this.elements.unbind(this.type,this.fn);else if(this.fn2)this.elements.each(function(i,el){query.fn2.apply(el);});this.elements=[];this.stopped=true;},run:function(){if(this.stopped)return;var query=this;var oEls=this.elements,els=$(this.selector,this.context),nEls=els.not(oEls);this.elements=els;if(this.type){nEls.bind(this.type,this.fn);if(oEls.length>0)$.each(oEls,function(i,el){if($.inArray(el,els)<0)$.event.remove(el,query.type,query.fn);});}else{nEls.each(function(){query.fn.apply(this);});if(this.fn2&&oEls.length>0)$.each(oEls,function(i,el){if($.inArray(el,els)<0)query.fn2.apply(el);});}}};$.extend($.livequery,{guid:0,queries:[],queue:[],running:false,timeout:null,checkQueue:function(){if($.livequery.running&&$.livequery.queue.length){var length=$.livequery.queue.length;while(length--)$.livequery.queries[$.livequery.queue.shift()].run();}},pause:function(){$.livequery.running=false;},play:function(){$.livequery.running=true;$.livequery.run();},registerPlugin:function(){$.each(arguments,function(i,n){if(!$.fn[n])return;var old=$.fn[n];$.fn[n]=function(){var r=old.apply(this,arguments);$.livequery.run();return r;}});},run:function(id){if(id!=undefined){if($.inArray(id,$.livequery.queue)<0)$.livequery.queue.push(id);}else
+$.each($.livequery.queries,function(id){if($.inArray(id,$.livequery.queue)<0)$.livequery.queue.push(id);});if($.livequery.timeout)clearTimeout($.livequery.timeout);$.livequery.timeout=setTimeout($.livequery.checkQueue,20);},stop:function(id){if(id!=undefined)$.livequery.queries[id].stop();else
+$.each($.livequery.queries,function(id){$.livequery.queries[id].stop();});}});$.livequery.registerPlugin('append','prepend','after','before','wrap','attr','removeAttr','addClass','removeClass','toggleClass','empty','remove');$(function(){$.livequery.play();});var init=$.prototype.init;$.prototype.init=function(a,c){var r=init.apply(this,arguments);if(a&&a.selector)r.context=a.context,r.selector=a.selector;if(typeof a=='string')r.context=c||document,r.selector=a;return r;};$.prototype.init.prototype=$.prototype;})(jQuery);
\ No newline at end of file
diff --git a/src/vendor/jquery-teamwork-gantt/libs/jquery.timers.js b/src/vendor/jquery-teamwork-gantt/libs/jquery.timers.js
new file mode 100644
index 0000000..406de7e
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/libs/jquery.timers.js
@@ -0,0 +1,142 @@
+jQuery.fn.extend({
+	everyTime: function(interval, label, fn, times, belay) {
+		return this.each(function() {
+			jQuery.timer.add(this, interval, label, fn, times, belay);
+		});
+	},
+	oneTime: function(interval, label, fn) {
+		return this.each(function() {
+			jQuery.timer.add(this, interval, label, fn, 1);
+		});
+	},
+	stopTime: function(label, fn) {
+		return this.each(function() {
+			jQuery.timer.remove(this, label, fn);
+		});
+	}
+});
+
+jQuery.extend({
+	timer: {
+		guid: 1,
+		global: {},
+		regex: /^([0-9]+)\s*(.*s)?$/,
+		powers: {
+			// Yeah this is major overkill...
+			'ms': 1,
+			'cs': 10,
+			'ds': 100,
+			's': 1000,
+			'das': 10000,
+			'hs': 100000,
+			'ks': 1000000
+		},
+		timeParse: function(value) {
+			if (value == undefined || value == null)
+				return null;
+			var result = this.regex.exec(jQuery.trim(value.toString()));
+			if (result[2]) {
+				var num = parseInt(result[1], 10);
+				var mult = this.powers[result[2]] || 1;
+				return num * mult;
+			} else {
+				return value;
+			}
+		},
+		add: function(element, interval, label, fn, times, belay) {
+			var counter = 0;
+			
+			if (jQuery.isFunction(label)) {
+				if (!times) 
+					times = fn;
+				fn = label;
+				label = interval;
+			}
+			
+			interval = jQuery.timer.timeParse(interval);
+
+			if (typeof interval != 'number' || isNaN(interval) || interval <= 0)
+				return;
+
+			if (times && times.constructor != Number) {
+				belay = !!times;
+				times = 0;
+			}
+			
+			times = times || 0;
+			belay = belay || false;
+			
+			if (!element.$timers) 
+				element.$timers = {};
+			
+			if (!element.$timers[label])
+				element.$timers[label] = {};
+			
+			fn.$timerID = fn.$timerID || this.guid++;
+			
+			var handler = function() {
+				if (belay && this.inProgress) 
+					return;
+				this.inProgress = true;
+				if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
+					jQuery.timer.remove(element, label, fn);
+				this.inProgress = false;
+			};
+			
+			handler.$timerID = fn.$timerID;
+			
+			if (!element.$timers[label][fn.$timerID]) 
+				element.$timers[label][fn.$timerID] = window.setInterval(handler,interval);
+			
+			if ( !this.global[label] )
+				this.global[label] = [];
+			this.global[label].push( element );
+			
+		},
+		remove: function(element, label, fn) {
+			var timers = element.$timers, ret;
+			
+			if ( timers ) {
+				
+				if (!label) {
+					for ( label in timers )
+						this.remove(element, label, fn);
+				} else if ( timers[label] ) {
+					if ( fn ) {
+						if ( fn.$timerID ) {
+							window.clearInterval(timers[label][fn.$timerID]);
+							delete timers[label][fn.$timerID];
+						}
+					} else {
+						for ( var fn in timers[label] ) {
+							window.clearInterval(timers[label][fn]);
+							delete timers[label][fn];
+						}
+					}
+					
+					for ( ret in timers[label] ) break;
+					if ( !ret ) {
+						ret = null;
+						delete timers[label];
+					}
+				}
+				
+				for ( ret in timers ) break;
+				if ( !ret ) 
+					element.$timers = null;
+			}
+		}
+	}
+});
+
+if (jQuery.browser.msie)
+	jQuery(window).one("unload", function() {
+		var global = jQuery.timer.global;
+		for ( var label in global ) {
+			var els = global[label], i = els.length;
+			while ( --i )
+				jQuery.timer.remove(els[i], label);
+		}
+	});
+
+
diff --git a/src/vendor/jquery-teamwork-gantt/libs/platform.js b/src/vendor/jquery-teamwork-gantt/libs/platform.js
new file mode 100644
index 0000000..d223c43
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/libs/platform.js
@@ -0,0 +1,954 @@
+
+if(!window.console) {
+  window.console = new function() {
+    this.log = function(str) {/*alert(str)*/};
+    this.debug = function(str) {/*alert(str)*/};
+    this.error = function(str) {/*alert(str)*/};
+  };
+}
+if(!window.console.debug || !window.console.error|| !window.console.log ) {
+  window.console = new function() {
+    this.log = function(str) {/*alert(str)*/};
+    this.debug = function(str) {/*alert(str)*/};
+    this.error = function(str) {/*alert(str)*/};
+  };
+}
+
+
+//----------------------------------positioning-----------------------------------------------
+$.fn.bringToFront=function(selector){
+  var zi=10;
+  var elements = selector ? $(selector) : $("*");
+  elements.each(function() {
+    if($(this).css("position")!="static"){
+      var cur = parseInt($(this).css('zIndex'));
+      zi = cur > zi ? parseInt($(this).css('zIndex')) : zi;
+    }
+  });
+
+  return $(this).css('zIndex',zi+=10);
+};
+
+function nearBestPosition(whereId, theObjId, centerOnEl) {
+  var el=whereId;
+  var target=theObjId;
+
+  if (typeof whereId != "object"){ el = $("#"+whereId); }
+  if (typeof theObjId != "object"){target = $("#"+theObjId);}
+
+  if (el) {
+    target.css("visibility","hidden");
+    var hasContainment = false;
+
+    target.parents().each(function(){
+      if($(this).css("position")=="static")
+        return;
+      hasContainment = true;
+
+    });
+
+    var trueX = hasContainment ? el.position().left : el.offset().left;
+    var trueY = hasContainment ? el.position().top : el.offset().top;
+    var h = el.outerHeight();
+    var elHeight = parseFloat(h);
+
+    if (centerOnEl){
+      var elWidth = parseFloat(el.outerWidth());
+      var targetWidth = parseFloat(target.outerWidth());
+      trueX+=(elWidth-targetWidth)/2;
+    }
+
+    trueY += parseFloat(elHeight);
+
+    var left = trueX;
+    var top = trueY;
+    var barHeight = ($.browser.msie) ? 45 : 35;
+    var barWidth = ($.browser.msie) ? 20 : 0;
+
+    if (trueX && trueY) {
+      target.css("left", left);
+      target.css("top", top);
+    }
+
+    if (target.offset().left >= ($(window).width() - target.outerWidth())) {
+      left = ($(window).width() - target.outerWidth() - barWidth )+ "px";
+      target.css("left", left);
+    }
+
+    if (target.offset().left < 0) {
+      left = 0+ "px";
+      target.css("left", left);
+    }
+
+    if ((target.offset().top  + target.outerHeight() >= (($(window).height() - barHeight))) && (target.outerHeight() < $(window).height())) {
+      target.css("margin-top",(-(el.outerHeight() + target.outerHeight())) + "px");
+    }
+
+    target.css("visibility","visible");
+  }
+}
+
+
+String.prototype.trim = function () {
+  return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
+};
+
+String.prototype.startsWith = function(t, i) {
+  if (!i) {
+    return (t == this.substring(0, t.length));
+  } else {
+    return (t.toLowerCase()== this.substring(0, t.length).toLowerCase());
+  }
+};
+
+String.prototype.endsWith = function(t, i) {
+  if (!i) {
+    return (t== this.substring(this.length - t.length));
+  } else {
+    return (t.toLowerCase() == this.substring(this.length -t.length).toLowerCase());
+  }
+};
+
+// leaves only char from A to Z, numbers, _ -> valid ID
+String.prototype.asId = function () {
+  return this.replace(/[^a-zA-Z0-9_]+/g, '');
+};
+
+String.prototype.replaceAll= function(from, to){
+  return this.replace(new RegExp(RegExp.quote(from), 'g'),to);
+};
+
+
+if (!Array.prototype.indexOf) {
+  Array.prototype.indexOf = function (searchElement, fromIndex) {
+    if (this == null) {
+      throw new TypeError();
+    }
+    var t = Object(this);
+    var len = t.length >>> 0;
+    if (len === 0) {
+      return -1;
+    }
+    var n = 0;
+    if (arguments.length > 0) {
+      n = Number(arguments[1]);
+      if (n != n) { // shortcut for verifying if it's NaN
+        n = 0;
+      } else if (n != 0 && n != Infinity && n != -Infinity) {
+        n = (n > 0 || -1) * Math.floor(Math.abs(n));
+      }
+    }
+    if (n >= len) {
+      return -1;
+    }
+    var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+    for (; k < len; k++) {
+      if (k in t && t[k] === searchElement) {
+        return k;
+      }
+    }
+    return -1;
+  };
+}
+
+
+Object.size = function(obj) {
+  var size = 0, key;
+  for (key in obj) {
+    if (obj.hasOwnProperty(key)) size++;
+  }
+  return size;
+};
+
+
+// transform string values to printable: \n in <br>
+function transformToPrintable(data){
+  for (var prop in data) {
+    var value = data[prop];
+    if (typeof(value)=="string")
+      data[prop]=(value + "").replace(/\n/g, "<br>");
+  }
+  return data;
+}
+
+
+/* Types Function */
+
+function isValidURL(url){
+  var RegExp = /^(([\w]+:)?\/\/)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$/;
+  return RegExp.test(url);
+}
+
+function isValidEmail(email){
+  var RegExp = /^((([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+(\.([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+)*)@((((([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.))*([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.)[\w]{2,4}|(((([0-9]){1,3}\.){3}([0-9]){1,3}))|(\[((([0-9]){1,3}\.){3}([0-9]){1,3})\])))$/;
+  return RegExp.test(email);
+}
+
+function isValidInteger(n) {
+  reg = new RegExp("^[-+]{0,1}[0-9]*$");
+  return reg.test(n);
+}
+
+function isValidDouble(n) {
+  var sep = Number.decimalSeparator;
+  reg = new RegExp("^[-+]{0,1}[0-9]*[" + sep + "]{0,1}[0-9]*$");
+  return reg.test(n);
+}
+
+function isValidTime(n) {
+  return !isNaN(millisFromHourMinute(n));
+}
+
+function isValidDurationDays(n) {
+  return !isNaN(daysFromString(n));
+}
+
+function isValidDurationMillis(n) {
+  return !isNaN(millisFromString(n));
+}
+
+function isValidDurationMillis(n) {
+  return !isNaN(millisFromString(n));
+}
+
+
+/*
+ supports almost all Java currency format e.g.: ###,##0.00EUR   €#,###.00  #,###.00€  -$#,###.00  $-#,###.00
+ */
+function isValidCurrency(numStr){
+  //first try to convert format in a regex
+  var regex="";
+  var format=Number.currencyFormat+"";
+
+  var minusFound=false;
+  var numFound=false;
+  var currencyString="";
+  var numberRegex="[0-9\\"+Number.groupingSeparator+"]+[\\"+Number.decimalSeparator+"]?[0-9]*";
+
+  for (var i=0; i<format.length; i++){
+    var ch= format.charAt(i);
+
+    if (ch=="." || ch=="," || ch=="0"){
+      //skip it
+      if(currencyString!=""){
+        regex=regex+"(?:"+RegExp.quote(currencyString)+")?";
+        currencyString="";
+      }
+
+    } else if (ch=="#") {
+      if(currencyString!=""){
+        regex=regex+"(?:"+RegExp.quote(currencyString)+")?";
+        currencyString="";
+      }
+
+      if (!numFound){
+        numFound=true;
+        regex=regex+numberRegex;
+      }
+
+    } else if (ch=="-"){
+      if(currencyString!=""){
+        regex=regex+"(?:"+RegExp.quote(currencyString)+")?";
+        currencyString="";
+      }
+      if (!minusFound){
+        minusFound=true;
+        regex=regex+ "[-]?";
+      }
+
+    } else {
+      currencyString=currencyString+ch;
+    }
+  }
+  if (!minusFound)
+    regex="[-]?"+regex;
+
+  if(currencyString!="")
+    regex=regex+"(?:"+RegExp.quote(currencyString)+")?";
+
+  regex="^"+regex+"$";
+
+  var rg=new RegExp(regex);
+  return rg.test(numStr);
+}
+
+function getCurrencyValue(numStr){
+  if (!isValidCurrency(numStr))
+    return NaN;
+
+  return parseFloat(numStr.replaceAll(Number.groupingSeparator,"").replaceAll(Number.decimalSeparator,".").replace(/[^0123456789.]/,""));
+}
+
+
+function formatCurrency(numberString) {
+  return formatNumber(numberString, Number.currencyFormat);
+}
+
+
+function formatNumber(numberString, format) {
+  if (!format)
+    format="##0.00";
+
+  var dec = Number.decimalSeparator;
+  var group = Number.groupingSeparator;
+  var neg = Number.minusSign;
+
+  var round = true;
+
+  var validFormat = "0#-,.";
+
+  // strip all the invalid characters at the beginning and the end
+  // of the format, and we'll stick them back on at the end
+  // make a special case for the negative sign "-" though, so
+  // we can have formats like -$23.32
+  var prefix = "";
+  var negativeInFront = false;
+  for (var i = 0; i < format.length; i++) {
+    if (validFormat.indexOf(format.charAt(i)) == -1) {
+      prefix = prefix + format.charAt(i);
+    } else {
+      if (i == 0 && format.charAt(i) == '-') {
+        negativeInFront = true;
+      } else {
+        break;
+      }
+    }
+  }
+  var suffix = "";
+  for (var i = format.length - 1; i >= 0; i--) {
+    if (validFormat.indexOf(format.charAt(i)) == -1)
+      suffix = format.charAt(i) + suffix;
+    else
+      break;
+  }
+
+  format = format.substring(prefix.length);
+  format = format.substring(0, format.length - suffix.length);
+
+  // now we need to convert it into a number
+  //while (numberString.indexOf(group) > -1)
+  //	numberString = numberString.replace(group, '');
+  //var number = new Number(numberString.replace(dec, ".").replace(neg, "-"));
+  var number = new Number(numberString);
+
+
+  var forcedToZero = false;
+  if (isNaN(number)) {
+    number = 0;
+    forcedToZero = true;
+  }
+
+  // special case for percentages
+  if (suffix == "%")
+    number = number * 100;
+
+  var returnString = "";
+  if (format.indexOf(".") > -1) {
+    var decimalPortion = dec;
+    var decimalFormat = format.substring(format.lastIndexOf(".") + 1);
+
+    // round or truncate number as needed
+    if (round)
+      number = new Number(number.toFixed(decimalFormat.length));
+    else {
+      var numStr = number.toString();
+      numStr = numStr.substring(0, numStr.lastIndexOf('.') + decimalFormat.length + 1);
+      number = new Number(numStr);
+    }
+
+    var decimalValue = number % 1;
+    var decimalString = new String(decimalValue.toFixed(decimalFormat.length));
+    decimalString = decimalString.substring(decimalString.lastIndexOf(".") + 1);
+
+    for (var i = 0; i < decimalFormat.length; i++) {
+      if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) != '0') {
+        decimalPortion += decimalString.charAt(i);
+      } else if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) == '0') {
+        var notParsed = decimalString.substring(i);
+        if (notParsed.match('[1-9]')) {
+          decimalPortion += decimalString.charAt(i);
+        } else{
+          break;
+        }
+      } else if (decimalFormat.charAt(i) == "0"){
+        decimalPortion += decimalString.charAt(i);
+      }
+    }
+    returnString += decimalPortion;
+  } else{
+    number = Math.round(number);
+  }
+  var ones = Math.floor(number);
+  if (number < 0)
+    ones = Math.ceil(number);
+
+  var onesFormat = "";
+  if (format.indexOf(".") == -1)
+    onesFormat = format;
+  else
+    onesFormat = format.substring(0, format.indexOf("."));
+
+  var onePortion = "";
+  if (!(ones == 0 && onesFormat.substr(onesFormat.length - 1) == '#') || forcedToZero) {
+    // find how many digits are in the group
+    var oneText = new String(Math.abs(ones));
+    var groupLength = 9999;
+    if (onesFormat.lastIndexOf(",") != -1)
+      groupLength = onesFormat.length - onesFormat.lastIndexOf(",") - 1;
+    var groupCount = 0;
+    for (var i = oneText.length - 1; i > -1; i--) {
+      onePortion = oneText.charAt(i) + onePortion;
+      groupCount++;
+      if (groupCount == groupLength && i != 0) {
+        onePortion = group + onePortion;
+        groupCount = 0;
+      }
+    }
+
+    // account for any pre-data padding
+    if (onesFormat.length > onePortion.length) {
+      var padStart = onesFormat.indexOf('0');
+      if (padStart != -1) {
+        var padLen = onesFormat.length - padStart;
+
+        // pad to left with 0's or group char
+        var pos = onesFormat.length - onePortion.length - 1;
+        while (onePortion.length < padLen) {
+          var padChar = onesFormat.charAt(pos);
+          // replace with real group char if needed
+          if (padChar == ',')
+            padChar = group;
+          onePortion = padChar + onePortion;
+          pos--;
+        }
+      }
+    }
+  }
+
+  if (!onePortion && onesFormat.indexOf('0', onesFormat.length - 1) !== -1)
+    onePortion = '0';
+
+  returnString = onePortion + returnString;
+
+  // handle special case where negative is in front of the invalid characters
+  if (number < 0 && negativeInFront && prefix.length > 0)
+    prefix = neg + prefix;
+  else if (number < 0)
+    returnString = neg + returnString;
+
+  if (returnString.lastIndexOf(dec) == returnString.length - 1) {
+    returnString = returnString.substring(0, returnString.length - 1);
+  }
+  returnString = prefix + returnString + suffix;
+  return returnString;
+}
+
+
+
+
+RegExp.quote = function(str) {
+  return str.replace(/([.?*+^$[\]\\(){}-])/g, "\\$1");
+};
+
+/* ----- millis format --------- */
+/**
+ * @param         str         - Striga da riempire
+ * @param         len         - Numero totale di caratteri, comprensivo degli "zeri"
+ * @param         ch          - Carattere usato per riempire
+ */
+function pad(str, len, ch){
+  if ((str+"").length<len){
+    return new Array(len-(''+str).length+1).join(ch) + str;
+  } else{
+    return str
+  }
+}
+
+function getMillisInHours(millis) {
+  if (!millis)
+    return "";
+  var sgn=millis>=0?1:-1;
+  var hour = Math.floor(millis / 3600000);
+  return  (sgn>0?"":"-")+pad(hour,2,"0");
+}
+function getMillisInHoursMinutes(millis) {
+  if (typeof(millis)!="number" )
+    return "";
+
+  var sgn=millis>=0?1:-1;
+  millis=Math.abs(millis);
+  var hour = Math.floor(millis / 3600000);
+  var min = Math.floor((millis % 3600000) / 60000);
+  return  (sgn>0?"":"-")+pad(hour,1,"0") + ":" + pad(min,2,"0");
+}
+
+function getMillisInDaysHoursMinutes(millis) {
+  if (!millis)
+    return "";
+  // millisInWorkingDay is set on partHeaderFooter
+  var sgn=millis>=0?1:-1;
+  millis=Math.abs(millis);
+  var days = Math.floor(millis / millisInWorkingDay);
+  var hour = Math.floor((millis % millisInWorkingDay) / 3600000);
+  var min = Math.floor((millis-days*millisInWorkingDay-hour*3600000) / 60000);
+  return (sgn>=0?"":"-")+(days > 0 ? days + "  " : "") + pad(hour,1,"0") + ":" + pad(min,2,"0");
+}
+
+function millisFromHourMinute(stringHourMinutes) { //All this format are valid: "12:58" "13.75"  "63635676000" (this is already in milliseconds)
+  var result = 0;
+  stringHourMinutes.replace(",",".");
+  var semiColSeparator = stringHourMinutes.indexOf(":");
+  var dotSeparator = stringHourMinutes.indexOf(".");
+
+  if (semiColSeparator < 0 && dotSeparator < 0 && stringHourMinutes.length > 5) {
+    return parseInt(stringHourMinutes, 10); //already in millis
+  } else {
+
+    if (dotSeparator > -1) {
+      var d = parseFloat(stringHourMinutes);
+      result = d * 3600000;
+    } else {
+      var hour = 0;
+      var minute = 0;
+      if (semiColSeparator == -1)
+        hour = parseInt(stringHourMinutes, 10);
+      else {
+        hour = parseInt(stringHourMinutes.substring(0, semiColSeparator), 10);
+        minute = parseInt(stringHourMinutes.substring(semiColSeparator + 1), 10);
+      }
+      result = hour * 3600000 + minute * 60000;
+    }
+    if (typeof(result)!="number")
+      result=NaN;
+    return result;
+  }
+}
+
+
+/**
+ * @param string              "3y 4d", "4D:08:10", "12M/3d", "2H4D", "3M4d,2h", "12:30", "11", "3", "1.5", "2m/3D", "12/3d", "1234"
+ *                            by default 2 means 2 hours 1.5 means 1:30
+ * @param considerWorkingdays if true day lenght is from global.properties CompanyCalendar.MILLIS_IN_WORKING_DAY  otherwise in 24
+ * @return milliseconds. 0 if invalid string
+ */
+function millisFromString(string,considerWorkingdays) {
+  if (!string)
+    return 0;
+
+  var regex = new RegExp("(\\d+[Yy])|(\\d+[M])|(\\d+[Ww])|(\\d+[Dd])|(\\d+[Hh])|(\\d+[m])|(\\d+[Ss])|(\\d+:\\d+)|(:\\d+)|(\\d*[\\.,]\\d+)|(\\d+)","g");
+
+  var matcher = regex.exec(string);
+  var totMillis=0;
+
+  if (!matcher)
+    return NaN;
+
+  while (matcher!=null) {
+    for (var i = 1; i < matcher.length; i++) {
+      var match = matcher[i];
+      if (match) {
+        var number = 0;
+        try {
+          number = parseInt(match);
+        } catch (e) {
+        }
+        if (i == 1) { // years
+          totMillis = totMillis + number * (considerWorkingdays ? millisInWorkingDay * workingDaysPerWeek * 52 : 3600000 * 24 * 365);
+        } else if (i == 2) { // months
+          totMillis = totMillis + number * (considerWorkingdays ? millisInWorkingDay * workingDaysPerWeek * 4 : 3600000 * 24 * 30);
+        } else if (i == 3) { // weeks
+          totMillis = totMillis + number * (considerWorkingdays ? millisInWorkingDay * workingDaysPerWeek : 3600000 * 24 * 7);
+        } else if (i == 4) { // days
+          totMillis = totMillis + number * (considerWorkingdays ? millisInWorkingDay : 3600000 * 24);
+        } else if (i == 5) { // hours
+          totMillis = totMillis + number * 3600000;
+        } else if (i == 6) { // minutes
+          totMillis = totMillis + number * 60000;
+        } else if (i == 7) { // seconds
+          totMillis = totMillis + number * 1000;
+        } else if (i == 8) { // hour:minutes
+          totMillis = totMillis + millisFromHourMinute(match);
+        } else if (i == 9) { // :minutes
+          totMillis = totMillis + millisFromHourMinute(match);
+        } else if (i == 10) { // hour.minutes
+          totMillis = totMillis + millisFromHourMinute(match);
+        } else if (i == 11) { // hours
+          totMillis = totMillis + number * 3600000;
+        }
+      }
+    }
+    matcher=regex.exec(string);
+  }
+
+  return totMillis;
+}
+
+/**
+ * @param string              "3y 4d", "4D:08:10", "12M/3d", "2H4D", "3M4d,2h", "12:30", "11", "3", "1.5", "2m/3D", "12/3d", "1234"
+ *                            by default 2 means 2 hours 1.5 means 1:30
+ * @param considerWorkingdays if true day lenght is from global.properties CompanyCalendar.MILLIS_IN_WORKING_DAY  otherwise in 24
+ * @return milliseconds. 0 if invalid string
+ */
+function daysFromString(string,considerWorkingdays) {
+  if (!string)
+    return undefined;
+
+  var regex = new RegExp("(\\d+[Yy])|(\\d+[Mm])|(\\d+[Ww])|(\\d+[Dd])|(\\d*[\\.,]\\d+)|(\\d+)","g");
+
+  var matcher = regex.exec(string);
+  var totDays=0;
+
+  if (!matcher)
+    return NaN;
+
+  while (matcher != null) {
+    for (var i = 1; i < matcher.length; i++) {
+      var match = matcher[i];
+      if (match) {
+        var number = 0;
+        try {
+          number = parseInt(match);
+        } catch (e) {
+        }
+        if (i == 1) { // years
+          totDays = totDays + number * (considerWorkingdays ? workingDaysPerWeek * 52 : 365);
+        } else if (i == 2) { // months
+          totDays = totDays + number * (considerWorkingdays ? workingDaysPerWeek * 4 : 30);
+        } else if (i == 3) { // weeks
+          totDays = totDays + number * (considerWorkingdays ? workingDaysPerWeek : 7);
+        } else if (i == 4) { // days
+          totDays = totDays + number;
+        } else if (i == 5) { // days.minutes
+          totDays = totDays + number;
+        } else if (i == 6) { // days
+          totDays = totDays + number;
+        }
+      }
+    }
+    matcher=regex.exec(string);
+  }
+
+  return totDays;
+}
+
+
+
+/* Object Functions */
+
+function stopBubble(e) {
+  if ($.browser.msie && event){
+    event.cancelBubble = true;
+    event.returnValue = false;
+
+  }else if (e){
+    e.stopPropagation();
+    e.preventDefault();
+  }
+  return false;
+}
+
+//validation functions - used by textfield and datefield
+function validateField(ev) {
+  var  el = $(this);
+  var rett=true;
+  el.clearErrorAlert();
+  // check serverside only if not empty
+  var value = el.val();
+  if (value) {
+
+    var type = el.attr('entryType').toUpperCase();
+
+    if (type == "INTEGER") {
+      rett = isValidInteger(value);
+    } else if (type == "DOUBLE") {
+      rett = isValidDouble(value);
+    } else if (type == "PERCENTILE") {
+      rett = isValidDouble(value);
+    } else if (type == "URL") {
+      rett = isValidURL(value);
+    } else if (type == "EMAIL") {
+      rett = isValidEmail(value);
+    } else if (type == "DURATIONMILLIS") {
+      rett = isValidDurationMillis(value);
+    } else if (type == "DURATIONDAYS") {
+      rett = isValidDurationDays(value);
+    } else if (type == "DATE") {
+      rett = Date.isValid(value,el.attr("format"));
+    } else if (type == "TIME") {
+      rett = isValidTime(value);
+    } else if (type == "CURRENCY") {
+      rett = isValidCurrency(value);
+    }
+
+    if (!rett) {
+      el.createErrorAlert(i18n.ERROR_ON_FIELD,i18n.INVALID_DATA);
+    }
+  }
+  return rett;
+}
+
+jQuery.fn.clearErrorAlert= function(){
+  this.each(function(){
+    var el = $(this);
+    el.removeAttr("invalid").removeClass("formElementsError");
+    $("#"+el.attr("id")+"error").remove();
+  });
+  return this;
+};
+
+jQuery.fn.createErrorAlert = function(errorCode, message) {
+  this.each(function() {
+    var el = $(this);
+    el.attr("invalid", "true").addClass("formElementsError");
+    if ($("#" + el.attr("id") + "error").size() <= 0) {
+      var errMess = (errorCode?errorCode:"") + ": " + (message?message:"");
+      var err = "<img width='17' heigh='17' id=\"" + el.attr("id") + "error\" error='1'";
+      err += " onclick=\"alert($(this).attr('title'))\" border='0' align='absmiddle'>";
+      err=$(err);
+      err.attr("title",errMess).attr("src",skinImgPath+"alert.gif");
+      el.after(err);
+    }
+  });
+  return this;
+};
+
+
+//errors =[{ceName:ceErrorCode},...]
+function jsonErrorHandling(response){
+  if (!response.ok){
+    if (response.message)
+      alert("ERROR:\n"+ response.message);
+    for (var i in response.clientEntryErrors){
+      var err=response.clientEntryErrors[i];
+      $(":input[name="+err.name+"]").createErrorAlert(err.error);
+    }
+  }
+}
+
+
+
+// ---------------------------------- oldvalues management
+// update all values selected
+jQuery.fn.updateOldValue= function(){
+  this.each(function(){
+    var el = $(this);
+    el.data("_oldvalue",el.val());
+  });
+  return this;
+};
+
+// return true if at least one element has changed
+jQuery.fn.isValueChanged=function (){
+  var ret=false;
+  this.each(function(){
+    var el = $(this);
+    if (el.val()+"" != el.data("_oldvalue") + ""){
+      //console.debug("io sono diverso "+el.attr("id")+ " :"+el.val()+" != "+el.data("_oldvalue"));
+      ret=true;
+      return false;
+    }
+  });
+  return ret;
+};
+
+jQuery.fn.getOldValue=function(){
+  return $(this).data("_oldvalue");
+};
+
+
+
+
+$.fn.unselectable=function(){
+  this.each(function(){
+    $(this).addClass("unselectable").attr("unselectable","on");
+  });
+  return $(this);
+};
+
+$.fn.clearUnselectable=function(){
+  this.each(function(){
+    $(this).removeClass("unselectable").removeAttr("unselectable");
+  });
+  return $(this);
+};
+
+
+// ----------------------------------  PROFILING ------------------------------------------
+var __profiler = {};
+/**
+ * usage: instantiate a new Profiler("a name") at the beginning of the code you want to profile  var p= new Profiler("testLoop")
+ *        call p.stop() at the end of the code you want test.
+ *        call Profiler.displayAll() or p.display() to see how many times the code has been executed and millisecond spent.
+ *        call Profiler.resetAll() or p.reset() to restart profiler.
+ * @param name
+ */
+function Profiler(name) {
+  this.startTime = new Date().getTime();
+  this.name = name;
+
+  this.stop = function() {
+    if (!__profiler[this.name])
+      __profiler[this.name] = {millis:0,count:0};
+    __profiler[this.name].millis += new Date().getTime() - this.startTime;
+    __profiler[this.name].count++;
+  };
+  this.display = function() {
+    console.debug(__profiler[this.name]);
+  };
+
+  this.reset = function() {
+    delete __profiler[this.name];
+  };
+}
+
+Profiler.reset = function() {
+    __profiler = {};
+};
+
+Profiler.displayAll = function() {
+  var ret = "";
+  var totMillis = 0;
+  for (var key in  __profiler) {
+    var p = __profiler[key];
+    var extraspace="                          ".substr(0,30-key.length);
+    ret += key + extraspace+ "\t millis:" + p.millis+"\t count:" + p.count  + "\n";
+    totMillis += p.millis;
+  }
+  console.debug(ret);
+};
+
+
+$(document).ready(function() {
+  $(":input[oldValue]").livequery(function(){$(this).updateOldValue();});
+  $('.validated').livequery('blur', validateField);
+});
+
+function openBlackPopup(url,width,height,onCloseCallBack,iframeId){
+  if(!iframeId)
+    iframeId="bwinPopup";
+
+  if (!width)
+    width='900px';
+  if (!height)
+    height='730px';
+
+  $("#__blackpopup__").remove();
+
+  var bg=$("<div>").attr("id","__blackpopup__");
+  //bg.css({position:'fixed',top:0, left:0,width:'100%',height:'100%', backgroundImage:"url('"+contextPath+"/applications/teamwork/images/black_70.png')",textAlign:'center'});
+  bg.css({position:'fixed',top:0, left:0,width:'100%',height:'100%',textAlign:'center'});
+
+  //add black only if not already in blackpupup
+  if(window.name!=iframeId)
+    bg.css({backgroundImage:"url('"+contextPath+"/applications/teamwork/images/black_70.png')"});
+
+  bg.append("<iframe id='"+iframeId+"' name='"+iframeId+"' frameborder='0'></iframe>");
+  bg.bringToFront();
+
+
+  //close call callback
+  bg.bind("close",function(){
+    bg.slideUp(300,function(){
+      bg.remove();
+      if (typeof(onCloseCallBack)=="function")
+        onCloseCallBack();
+    });
+  });
+
+  //destroy do not call callback
+  bg.bind("destroy",function(){
+    bg.remove();
+  });
+
+  bg.find("iframe:first").attr("src",url).css({width:width, height:height,top:100,border:'8px solid #909090', backgroundColor:'#ffffff'});
+
+  var bdiv= $("<div>").css({width:width,position:"relative",height:"5px", textAlign:"right", margin:"auto" });
+  bdiv.append("<img src='/images/closeBig.png' style='cursor:pointer;position:absolute;right:-40px;top:30px;'>");
+  bdiv.find("img:first").click( function(){
+    bg.trigger("close");
+
+  });
+
+  bg.prepend(bdiv);
+  $("body").append(bg);
+}
+
+
+//returns a jquery object where to write content
+function createBlackPage(width,height,onCloseCallBack){
+  if (!width)
+    width='900px';
+  if (!height)
+    height='730px';
+
+  $("#__blackpopup__").remove();
+
+  var bg=$("<div>").attr("id","__blackpopup__");
+  bg.css({position:'fixed',top:"0px",paddingTop:"50px", left:0,width:'100%',height:'100%',  backgroundImage:"url('res/img/black_70.png')"});
+  bg.append("<div id='bwinPopupd' name='bwinPopupd'></div>");
+  bg.bringToFront();
+
+  var ret=bg.find("#bwinPopupd");
+  ret.css({width:width, height:height,top:10, "-moz-box-shadow":'1px 1px 6px #333333',overflow:'auto',"-webkit-box-shadow":'1px 1px 6px #333333', border:'8px solid #777', backgroundColor:"#fff", margin:"auto" });
+
+  var bdiv= $("<div>").css({width:width,position:"relative",height:"0px", textAlign:"right", margin:"auto" });
+  var img=$("<img src='/images/closeBig.png' style='cursor:pointer;position:absolute;right:-40px;top:5px;' title='close'>");
+  bdiv.append(img);
+  img.click( function(){
+    bg.trigger("close");
+  });
+
+  bg.prepend(bdiv);
+  $("body").append(bg);
+
+  //close call callback
+  bg.bind("close",function(){
+    bg.slideUp(300,function(){
+      bg.remove();
+      if (typeof(onCloseCallBack)=="function")
+        onCloseCallBack();
+    });
+  });
+
+  //destroy do not call callback
+  bg.bind("destroy",function(){
+    bg.remove();
+  });
+  return ret;
+}
+
+
+function getBlackPopup(){
+  var ret=$("#__blackpopup__");
+  if (typeof(top)!="undefined"){
+    ret= window.parent.$("#__blackpopup__");
+  }
+  return ret;
+}
+
+
+function closeBlackPopup(){
+  getBlackPopup().trigger("close");
+}
+
+
+
+//------------------------------------------------ TEAMWORK SPECIFIC FUNCTIONS   --------------------------------------------------------
+function openIssueEditorInBlack(issueId,command,params){
+  if (!command)
+    command="ED";
+  var editUrl=contextPath+"/applications/teamwork/issue/issueEditor.jsp?CM="+command+"&OBJID="+issueId;
+  if (params)
+    editUrl=editUrl+params;
+  openBlackPopup(editUrl,1020,$(window).height()-50, function(){$("#"+issueId).effect("highlight", { color: "yellow" }, 1500);});
+}
+
+function openBoardInBlack(boardId,command,params,callback){
+  if (!command)
+    command="ED";
+  var editUrl=contextPath+"/applications/teamwork/board/boardEditor.jsp?CM="+command+"&OBJID="+boardId;
+  if (params)
+    editUrl=editUrl+params;
+  openBlackPopup(editUrl,$(window).width()-100,$(window).height()-50,callback );
+}
+
diff --git a/src/vendor/jquery-teamwork-gantt/linkArrow.png b/src/vendor/jquery-teamwork-gantt/linkArrow.png
new file mode 100644
index 0000000..e23ec14
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/linkArrow.png differ
diff --git a/src/vendor/jquery-teamwork-gantt/milestone.png b/src/vendor/jquery-teamwork-gantt/milestone.png
new file mode 100644
index 0000000..a2fdadf
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/milestone.png differ
diff --git a/src/vendor/jquery-teamwork-gantt/platform.css b/src/vendor/jquery-teamwork-gantt/platform.css
new file mode 100644
index 0000000..2d00856
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/platform.css
@@ -0,0 +1,346 @@
+ at font-face {
+    font-family: 'TeamworkRegular';
+    src: url('teamwork-regular-webfont.eot');
+    src: url('teamwork-regular-webfont.eot?#iefix') format('embedded-opentype'),
+         url('teamwork-regular-webfont.woff') format('woff'),
+         url('teamwork-regular-webfont.ttf') format('truetype'),
+         url('teamwork-regular-webfont.otf') format('opentype'),
+         url('teamwork-regular-webfont.svg#TeamworkRegular') format('svg');
+    font-weight: normal;
+    font-style: normal;
+}
+
+
+
+*{
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  -o-box-sizing:border-box;
+  box-sizing: border-box;
+}
+
+  /*
+  -------------------------------------------------------
+  body styles
+  -------------------------------------------------------
+  */
+BODY, TBODY {
+  font-family: arial;
+  font-size: 14px;
+  margin: 0;
+  color: #000000;
+  text-decoration: none;
+}
+
+BODY {
+  background-color: #91B4B7; 
+}
+
+a {
+  text-decoration: none;
+  font-weight: bold;
+  color: #16ABDD;
+}
+
+a:hover, a.aHover {
+  color: #0C85AD;
+  text-decoration: underline;
+}
+
+h1 {
+  font-size:32px;
+  line-height: 34px;
+  color:#91B4B7;
+  font-weight:normal;
+  margin:0 0 10px 0
+}
+
+h2 {
+  font-size:22px;
+  color:#373737;
+  font-weight:normal;
+  margin:0 0 10px 0
+}
+
+h3 {
+  text-decoration: none;
+  color: #000000;
+  font-size: 16px;
+  margin: 0;
+}
+
+h4 {
+  font-size:16px;
+  padding:5px 0;
+  color:#617777;
+  margin:0
+}
+
+#savingMessage{
+  background-color:#E3EDED;
+  display:none;
+  color:#617777;
+  font-weight:bolder;
+  position:fixed;
+  top:0;
+  left:50%;
+  width:200px;
+  text-align:center;
+  margin-left:-100px;
+  padding:5px 0;
+  z-index:1000000;
+  box-shadow:0 3px 2px rgba(0,0,0,0.4);
+  -moz-box-shadow:0 3px 2px rgba(0,0,0,0.4);
+  -webkit-box-shadow:0 3px 2px rgba(0,0,0,0.4);
+  -o-box-shadow:0 3px 2px rgba(0,0,0,0.4);
+}
+
+.waiting{
+  cursor:progress;
+}
+
+/*
+  -------------------------------------------------------
+  teamwork icon
+  -------------------------------------------------------
+  */
+
+
+.teamworkIcon {
+  font-family: 'TeamworkRegular', arial, sans-serif;
+  color:#617777;
+  font-weight:normal;
+  font-size:120%
+}
+
+.teamworkIcon.withLabel {
+  padding-right:5px;
+}
+
+
+.button:hover .teamworkIcon {
+  opacity: 0.8
+}
+
+.teamworkIcon.alert {
+  color:#B61E2D;
+}
+
+.cvcColorSquare{
+  display:inline-block;
+  text-align:left;
+  border:#fff 0px solid;
+  box-shadow:0px 0px 5px #999;
+  -moz-box-shadow:2px 2px 2px #999;
+  -webkit-box-shadow:0px 0px 5px #999;
+  -o-box-shadow:0px 0px 5px #999;
+  text-indent:10px;
+  border-radius:5px
+}
+
+.cvcColorSquare:hover{
+  opacity:0.8
+}
+
+
+
+.unselectable {
+  -webkit-user-select: none;
+  -khtml-user-select: none;
+  -moz-user-select: none;
+  -o-user-select: none;
+  user-select: none;
+}
+
+
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
+
+
+  /*
+  -------------------------------------------------------
+  table styles
+  -------------------------------------------------------
+  */
+
+.table {
+  width: 100%;
+}
+
+TH, .tableHeader {
+  font-weight: normal;
+  color: #FFFFFF;
+  border: none;
+  background-color: #91B4B7;
+  padding:2px
+}
+
+TH a {
+  color: #FFFFFF;
+}
+
+
+
+  /*
+  -------------------------------------------------------
+  Buttons
+  -------------------------------------------------------
+  */
+
+.button {
+  display:inline-block;
+  font-size:110%;
+  font-family:Arial, sans-serif;
+  color:#fff;
+  cursor:pointer;
+  background-color:#373737;
+   -moz-box-shadow:2px 2px 2px #999;
+   -webkit-box-shadow:2px 2px 2px #999;
+   -o-box-shadow:2px 2px 2px #999;
+   box-shadow:2px 2px 2px #999;
+   -moz-border-radius:5px;
+   -webkit-border-radius:5px;
+   -o-border-radius:5px;
+   border-radius:5px;
+   border:none;
+   padding:7px 10px;
+   margin-bottom:10px;
+   margin-right:10px;
+  text-align: center
+}
+
+
+.button.first {
+    background-color:#FEA730;
+    font-weight: bold;
+}
+.button.first:hover {
+    background-color:#D98E2A;
+}
+
+
+
+.button[disabled] {
+  cursor: default;
+  opacity:0.4
+}
+
+
+.button:hover[disabled] {
+  background-color:#BABABA
+}
+
+.button.textual, .button.buttonImg {
+  border: none;
+  background-color: transparent;
+  color:#68979B;
+  -moz-box-shadow:0 0 0 #999;
+   -webkit-box-shadow:0 0 0 #999;
+   -o-box-shadow:0 0 0 #999;
+   box-shadow:0 0 0 #999;
+  -moz-border-radius:0;
+   -webkit-border-radius:0;
+   -o-border-radius:0;
+   border-radius:0;
+  padding:0;
+  margin:0;
+  text-align: left
+}
+
+
+
+.button.edit {
+  color:#009E94;
+  padding:0;
+  margin:0
+}
+
+.button.delete {
+  color:#B61E2D;
+  padding:0;
+  margin:0
+}
+
+.button:hover {
+  background-color: #4C4C4C;
+}
+.button.textual:hover, .button.buttonImg:hover {
+  background-color: transparent;
+}
+
+span.separator {
+  display: inline-block;
+}
+
+.button.add {
+  color:#009E94;
+}
+
+.button.add .teamworkIcon {
+  color:#009E94;
+}
+
+
+form {
+  margin: 0;
+  padding: 0;
+}
+
+select {
+  border:1px solid #91B4B7;
+  padding: 4px;
+  font-size: 16px;
+  font-family: Arial, Helvetica, sans-serif;
+}
+
+.formElements {
+  background-color: white;
+  padding: 4px;
+  font-size: 16px;
+  border:1px solid #91B4B7;
+  -moz-border-radius:3px;
+  -webkit-border-radius:3px;
+  -o-border-radius:3px;
+  border-radius:3px;
+  font-family: Arial, Helvetica, sans-serif;
+}
+
+.formElementsError {
+  border: 1px solid #ff0000;
+}
+
+.formElementExclamation {
+  width: 15px;
+  height: 25px;
+  mmmargin-left: -20px;
+  mmmposition: absolute;
+  background: url("alert.gif") no-repeat;
+}
+
+
+span#FLD_LOGIN_NAMEerror, span#FLD_PWDerror {
+  margin-left: -23px;
+  margin-top: 2px;
+}
+
+
+input {
+    background-color: white;
+    padding: 4px;
+    font-size: 16px;
+    border:1px solid #91B4B7;
+    -moz-border-radius:3px;
+    -webkit-border-radius:3px;
+    -o-border-radius:3px;
+    border-radius:3px;
+    font-family: Arial, Helvetica, sans-serif;
+}
diff --git a/src/vendor/jquery-teamwork-gantt/res/img/black_70.png b/src/vendor/jquery-teamwork-gantt/res/img/black_70.png
new file mode 100644
index 0000000..fd42841
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/res/img/black_70.png differ
diff --git a/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.eot b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.eot
new file mode 100644
index 0000000..8c98f3a
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.eot differ
diff --git a/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.otf b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.otf
new file mode 100644
index 0000000..3ba78b1
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.otf differ
diff --git a/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.svg b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.svg
new file mode 100644
index 0000000..8747c71
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.svg
@@ -0,0 +1,152 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="teamworkRegular" horiz-adv-x="2367" >
+<font-face units-per-em="2048" ascent="1638" descent="-410" />
+<missing-glyph horiz-adv-x="500" />
+<glyph horiz-adv-x="0" />
+<glyph horiz-adv-x="2048" />
+<glyph unicode="!" d="M44 572.5q0 174.5 69 346.5t202 304q133 133 305 202t346.5 69t346.5 -69t305 -202q133 -132 202 -304t69 -346.5t-69 -346.5t-202 -304q-133 -133 -305 -202t-346.5 -69t-346.5 69t-305 202q-133 132 -202 304t-69 346.5zM805 1190l35 -905h254l34 905h-323zM840 -96 h254v254h-254v-254z" />
+<glyph unicode="&#x22;" d="M57 120.5q-1 52.5 4.5 151t20.5 121.5q6 9 16.5 28t17.5 28.5t21.5 24.5t38 27.5t57.5 26.5l150 68v113q-5 4 -13 12.5t-24 46t-22 86.5q-20 -7 -38 17t-18 42q-6 32 3 65t34 28q-17 87 -10 120q5 79 69.5 137t167.5 58q98 0 164 -58t72 -137q0 -49 -8 -120 q14 4 23.5 -13.5t12.5 -38.5t3 -41q-5 -14 -13 -27t-22.5 -25t-28.5 -7q-5 -49 -19 -85.5t-25 -48.5l-11 -11l98 -74q-9 -5 -156 -55.5t-167 -79.5q-1 -4 -12.5 -15.5t-23.5 -35.5t-24 -68t-18 -134t-2 -214h-316q-1 35 -2 87.5zM536.5 -45q-0.5 26 0 94.5t2.5 123t8 106.5 t16 67q24 43 84 74t180 76l162 77l4 164q-6 4 -15.5 13.5t-27.5 49.5t-22 93q-23 -6 -43 21t-23 57q0 14 1.5 28t5.5 31.5t13 26.5t23 6q-17 112 -12 143q10 82 82.5 144.5t185.5 62.5q107 0 178.5 -63t79.5 -144q6 -37 -10 -143q14 3 23 -6t12.5 -27t4.5 -31t1 -28 q0 -28 -20.5 -56t-43.5 -22q-6 -53 -22 -92t-28 -51l-13 -13v-164q33 -18 160 -77q118 -43 180 -75t90 -75q15 -24 20.5 -132t4.5 -204l-2 -96h-1239q0 15 -0.5 41zM1477 727q30 6 44 75t18 157.5t7 101.5q18 85 41 133q26 55 84.5 91t134.5 36q96 0 162 -53q15 -6 27.5 -15 t22.5 -21t18.5 -23.5t15 -27.5t11 -27t9 -28t6.5 -24.5t5.5 -23t3.5 -17.5q3 -12 7.5 -101t19 -158t45.5 -75q-8 -22 -26 -26t-32 8q0 -27 -28.5 -31.5t-36.5 20.5q1 -10 -5.5 -15t-16.5 -4.5t-21 3.5t-21 8q0 -34 -4 -100q7 -2 23 -10t47 -22.5t65 -29.5q34 -14 57.5 -26.5 t38.5 -27.5t22 -24.5t17.5 -28.5t16.5 -28q16 -23 22 -113t4 -168l-2 -79h-317q5 107 0 185.5t-11.5 125.5t-19 77.5t-21.5 43t-18.5 22t-11.5 13.5q-15 22 -81 48.5t-143.5 51.5t-96.5 35l59 43q-21 0 -21 20q-5 -16 -21 -20.5t-30 4.5t-14 27q-15 -12 -31.5 -8t-23.5 26z " />
+<glyph unicode="#" d="M41 -76v1694h1522v-258h-174v86h-1199v-1096h84v-426h-233zM362 -399v1671h1522v-1671h-1522zM530 6h1180v1116h-1180v-1116zM694 553v117h813v-117h-813zM694 799v125h813v-125h-813z" />
+<glyph unicode="$" d="M70.5 439.5q-62.5 236.5 0 473t238.5 412.5q132 133 304 202t346.5 69t346.5 -69t304 -202q176 -176 238.5 -412.5t0 -473t-238.5 -412.5t-413 -238.5t-474.5 0t-413.5 238.5t-238.5 412.5zM600 240q48 -25 121.5 -44t148.5 -22v-151h158v165q134 23 208.5 103.5 t74.5 191.5q0 109 -62.5 178.5t-204.5 118.5q-106 40 -151 69.5t-45 65.5q0 38 33 66t104 29q24 0 47 -2t44 -6t36.5 -8t34 -10.5t27 -9.5t25 -10t18.5 -8l49 181q-106 47 -238 49v141h-158l4 -153q-127 -24 -198.5 -101t-71.5 -184q1 -110 76 -178t215 -113 q93 -32 132.5 -62.5t39.5 -74.5q0 -47 -42.5 -74t-113.5 -29q-130 0 -266 70z" />
+<glyph unicode="%" d="M41 -12l1370 1372l301 -297l-1370 -1372zM719 1466l100 103l199 -201l-98 -100zM1112 858l100 -96l301 301l-102 96zM1264 1481v282h143v-282h-143zM1622 567l98 99l199 -199l-98 -98zM1720 1466l199 203l98 -100l-196 -201zM1843 967v141h283v-141h-283z" />
+<glyph unicode="&#x26;" d="M41 1120.5q-3 65.5 6.5 121t24.5 87.5t32 51l437 -436q-25 -21 -30.5 -48t8 -58.5t32.5 -59t49 -61.5q151 -180 307 -307q45 -36 70 -55t57.5 -41.5t51 -30.5t40.5 -13t37.5 0.5t30.5 20.5l426 -416q-19 -19 -53 -35.5t-92 -26.5t-128 -6t-164 33.5t-195.5 83.5 t-228.5 153.5t-257 233.5q-124 126 -215.5 248t-140.5 219t-75.5 187t-29.5 155.5zM164 1440l436 -436l119 118q21 25 19 54.5t-19 46.5l-346 336q-15 23 -45 23t-45 -23zM1253 350l426 -416l119 119q21 17 19 45t-19 45l-336 336q-15 15 -45 15t-45 -15z" />
+<glyph unicode="'" d="M365 96l745 533v-402h139q171 0 292.5 121.5t121.5 292.5t-122 293t-292 121l-796 -8v262l796 8q134 1 257 -50.5t220 -148.5q96 -96 147.5 -219t51.5 -258t-52 -259t-147 -218q-97 -97 -219.5 -148t-257.5 -51h-139v-401z" />
+<glyph unicode="(" d="M451 729q0 133 52 254t140 209t209 140t254 52t254.5 -52t209 -140t139.5 -209t52 -254q0 -172 -84 -321l287 -287q44 -44 44 -107.5t-44 -107.5q-43 -43 -106 -43q-64 0 -107 43l-278 278q-163 -110 -367 -110q-133 0 -254 52t-209 139.5t-140 209t-52 254.5zM653 729 q0 -188 133 -321.5t320 -133.5q92 0 176.5 36t145.5 97t97 145.5t36 176.5q0 187 -133.5 320t-321.5 133t-320.5 -133t-132.5 -320zM803 627v200h201v201h200v-201h203v-200h-203v-203h-200v203h-201z" />
+<glyph unicode=")" d="M451 729q0 133 52 254t140 209t209 140t254 52t254.5 -52t209 -140t139.5 -209t52 -254q0 -172 -84 -321l287 -287q44 -44 44 -107.5t-44 -107.5q-43 -43 -106 -43q-64 0 -107 43l-278 278q-163 -110 -367 -110q-133 0 -254 52t-209 139.5t-140 209t-52 254.5zM653 729 q0 -188 133 -321.5t320 -133.5q92 0 176.5 36t145.5 97t97 145.5t36 176.5q0 187 -133.5 320t-321.5 133t-320.5 -133t-132.5 -320zM803 627v200h604v-200h-604z" />
+<glyph unicode="*" d="M41 881l612 -453l-229 -727l608 446l610 -446l-231 727l614 453h-749l-244 714l-244 -714h-747z" />
+<glyph unicode="+" d="M70.5 368q-62.5 236 0 471.5t238.5 411.5q133 133 304.5 202.5t345.5 69.5t345.5 -69.5t303.5 -202.5q133 -132 202.5 -303t69.5 -344.5t-69.5 -344.5t-202.5 -304q-132 -133 -303.5 -202t-345.5 -69t-345.5 69t-304.5 202q-176 177 -238.5 413zM383 496h459v-459h235 v459h459v235h-459v459h-235v-459h-459v-235z" />
+<glyph unicode="," d="M41 778v639h639l1106 -1083l-658 -658zM252 1032q0 -65 57 -117.5t133 -52.5q65 0 117.5 53t52.5 117q0 78 -51.5 135.5t-118.5 57.5q-78 0 -134 -57t-56 -136z" />
+<glyph unicode="-" d="M70.5 368q-62.5 236 0 471.5t238.5 411.5q133 133 304.5 202.5t345.5 69.5t345.5 -69.5t303.5 -202.5q133 -132 202 -303t69 -344.5t-69 -344.5t-202 -304q-132 -133 -303.5 -202t-345.5 -69t-345.5 69t-304.5 202q-176 177 -238.5 413zM383 496h1153v235h-1153v-235z " />
+<glyph unicode="." d="M371 381v446h864v381l762 -608l-762 -600v381h-864z" />
+<glyph unicode="/" d="M41 -211v1643h2140v-1643h-2140zM182 -86h1862v1395h-1862v-1395zM281 387l284 414l269 -357l200 398l199 401l391 -416l141 285l177 -90l-279 -561l-395 420l-78 -170l-334 -666l-291 408l-141 -209z" />
+<glyph unicode="0" d="M139 674q0 193 73.5 367t199 299t300 198.5t369.5 73.5q194 0 368 -73.5t299 -198.5t198 -299t73 -367q0 -194 -73 -368t-198 -299.5t-299 -199t-368 -73.5q-195 0 -369.5 73.5t-300 199t-199 299.5t-73.5 368zM346 674q0 -203 97 -377.5t266.5 -277.5t371.5 -103 q151 0 290.5 61t241 163t162 242t60.5 292q0 203 -102.5 377t-276 275t-375.5 101t-371.5 -101.5t-266.5 -274.5t-97 -377zM512 420q0 47 20 72q23 0 43.5 -5t30.5 -10t32 -18.5t32 -18.5q87 128 110 197t23 219q-17 -9 -26 -32.5t-21 -40.5t-41 -17q-33 0 -52 16.5 t-24 50.5t-4.5 65t4.5 83t4 82q48 0 73.5 -0.5t70 -5.5t72.5 -14t59 -28t51 -46q22 -23 38 -74t27 -61q38 -22 86 -18t105.5 11t108 12.5t94 -11.5t63.5 -62q0 -19 -17.5 -25.5t-35 -8.5t-17.5 -9q-18 -58 4.5 -124.5t90.5 -131.5q15 0 56 19t77 6q17 -38 5 -55t-46 -17h20 q-302 -113 -547 -113q-306 0 -569 113zM803 395q125 -32 287 -32t266 32q-11 61 -53.5 103.5t-99 60.5t-122.5 16.5t-123 -22t-100 -62t-55 -96.5z" />
+<glyph unicode="1" d="M39 683q0 176 71 349.5t207 306.5q134 134 305.5 204.5t352.5 70.5t351.5 -70.5t303.5 -204.5q133 -133 202.5 -306.5t69.5 -349.5t-69.5 -349t-202.5 -305q-132 -135 -302.5 -205t-352.5 -70t-353 70t-305 205q-136 132 -207 305t-71 349zM121 682q0 -171 63 -320 q65 -157 189 -278q122 -122 282 -190q154 -62 320 -62q168 0 319 62q160 69 281 190q119 116 186 278q64 159 64 320q0 170 -64 322q-63 160 -186 280q-122 122 -281 191q-149 61 -319 61q-171 0 -320 -63q-156 -63 -282 -189q-126 -123 -191 -280q-61 -152 -61 -322z M289 891l422 -309l-156 -498l420 303l416 -303l-156 498l422 309h-516l-166 493l-172 -493h-514z" />
+<glyph unicode="2" d="M41 698q0 186 72.5 356t195 293t292 196t355.5 73t356 -73t292.5 -196t195 -293t72.5 -356t-72.5 -355.5t-195 -292t-292.5 -195t-356 -72.5t-355.5 72.5t-292 195t-195 292t-72.5 355.5zM137 698q0 -166 65 -317.5t175 -261t261.5 -174t317.5 -64.5q134 0 259 41.5 t226 117t176.5 176t117 225t41.5 257.5q0 167 -65 319t-174.5 261.5t-261.5 174.5t-319 65q-166 0 -317.5 -65t-261.5 -174.5t-175 -261.5t-65 -319zM575 551v502q0 53 37 90t90 37q52 0 89 -37q36 -36 36 -90v-125h373q51 0 88 -37t37 -88q0 -53 -37 -90t-88 -37h-373v-123 q0 -53 37 -90q38 -35 88 -35h248q51 0 88 -37t37 -90q0 -51 -37 -88t-88 -37h-248q-155 0 -266 111t-111 264z" />
+<glyph unicode="3" d="M41 1098q0 138 67.5 255t184 185t254.5 68q143 0 270 -78q70 12 150 12q177 0 338.5 -69t278.5 -186t186 -278.5t69 -338.5q0 -91 -20 -189q53 -109 53 -225q0 -209 -148.5 -357.5t-357.5 -148.5q-128 0 -240 59q-93 -14 -159 -14q-178 0 -340 69.5t-279 186.5 t-186.5 279t-69.5 340q0 87 19 174q-70 118 -70 256zM451 418q0 -79 55 -158q56 -80 145 -127q118 -65 312 -65q163 0 274 47q115 50 176 135q62 86 62 194q0 92 -35 154q-36 60 -99 104q-61 40 -149 68q-82 26 -195 51q-24 5 -47.5 11t-44.5 11t-28 7q-20 5 -70 27 q-33 17 -51 41q-19 22 -19 51q0 47 56 82q53 39 149 39q101 0 148 -35q41 -32 77 -97q25 -45 52 -69q26 -23 75 -23q53 0 90 37q35 38 35 84q0 49 -26 100q-28 51 -84 95q-58 46 -146 71q-85 27 -202 27q-152 0 -256 -39q-110 -40 -170 -119q-60 -78 -60 -176 q0 -107 55 -174q58 -70 152 -110q93 -41 227 -68q74 -15 162 -41q61 -20 92 -51q35 -30 35 -82q0 -64 -65 -111q-70 -45 -177 -45q-73 0 -127 23q-44 20 -73 57q-26 37 -49 88q-20 47 -52 76q-34 27 -77 27q-53 0 -91 -35q-36 -33 -36 -82z" />
+<glyph unicode="4" d="M41 664q0 186 72.5 355.5t195 292t292 195t355.5 72.5t356 -72.5t292.5 -195t195 -292t72.5 -355.5t-72.5 -356t-195 -292.5t-292.5 -195t-356 -72.5t-355.5 72.5t-292 195t-195 292.5t-72.5 356zM139 664q0 -166 64.5 -317.5t174 -261t261 -174.5t317.5 -65t317.5 65 t261 174.5t174.5 261t65 317.5t-65 317.5t-174.5 261t-261 174t-317.5 64.5q-111 0 -217 -29.5t-195.5 -82t-165 -128t-128 -165t-82 -195.5t-29.5 -217zM709 639v186h112v111q0 120 56 181t186 61h147v-187h-92q-49 0 -61.5 -15.5t-12.5 -57.5v-93h168l-20 -186h-148v-541 h-223v541h-112z" />
+<glyph unicode="5" d="M41 -147q16 14 38 34t62 57.5t76 76t76.5 84t67.5 87.5t44.5 80t12.5 68.5t-33 46.5q-98 55 -163.5 131.5t-88.5 153.5q-13 37 -10 75t16.5 69.5t46.5 53t80 25.5q83 6 142 -16t88 -59t46 -75t30 -72t26 -42q44 -27 113 24.5t96 102.5q35 64 74 198q24 74 45 127.5 t58 126t91 139.5t123 126q94 83 201.5 118t175.5 0q48 -25 57.5 -68t-9.5 -85t-55.5 -89.5t-66.5 -77.5t-57 -52q-142 -127 -195 -186q-129 -147 -45 -193q21 -10 99.5 85t169 216t118.5 147q100 93 210 84q88 -7 131 -73q51 -79 -3 -186q-52 -102 -192 -197 q-10 -8 -41 -27.5t-55.5 -37t-51 -40t-39.5 -46.5t-8 -46q2 -13 8.5 -21.5t16 -11.5t19 -4t23 2t22.5 5.5t23 7.5t19 6q17 4 50 14t49 14q162 39 273 -36q80 -53 92 -134q14 -85 -58 -141q-112 -87 -362 -40q-59 11 -124 30q-37 9 -52.5 8.5t-24.5 -10.5q-9 -18 2.5 -37.5 t35.5 -20.5q158 -9 241 -99q61 -66 46 -136q-15 -69 -95 -95q-134 -43 -370 58q-71 30 -127 39t-99 1.5t-83 -37t-71 -66.5t-72 -97q-46 -65 -158 -248l-90 58q20 31 53 86.5t53 88.5t53.5 82t58 78t62 64.5t71 53t78.5 32.5t91 14.5t102.5 -12.5t118.5 -39q224 -96 297 -69 q36 14 13 51q-27 45 -101 70q-38 13 -78 16q-76 5 -117 75q-37 64 -17 127q23 71 108 77q45 4 102 -13q219 -64 343 -16q64 24 72 67q7 41 -44 65q-71 33 -199 3q-17 -4 -53 -15.5t-62 -18.5t-61.5 -13.5t-61.5 -3t-51.5 14t-43 37.5t-25.5 68q-10 52 11.5 99.5t66 86.5 t91.5 71.5t100.5 69t80.5 63.5q34 35 49.5 68.5t12 57t-20 38t-42 16.5t-59 -13t-65.5 -45q-39 -36 -127 -153t-170 -212.5t-131 -109.5q-42 -12 -80 7.5t-57 55.5t-27 79t10 79q17 45 72 110.5t118.5 127.5t124 121t97.5 107.5t31 72.5q-26 15 -101.5 -8.5t-156.5 -93.5 q-91 -79 -150 -170t-82 -163t-58 -175t-75 -178q-21 -40 -60 -80t-87.5 -67.5t-97 -39t-94 7.5t-73.5 70q-14 26 -29 63.5t-25 56.5t-28.5 39.5t-50.5 27.5t-82 4q-64 -7 -41 -91q12 -42 42 -80t63.5 -65t70.5 -56.5t63.5 -59t43.5 -66.5t8.5 -85t-41 -109t-104 -144 t-180.5 -185l-90 -79z" />
+<glyph unicode="6" d="M0 639q0 194 75.5 370.5t202.5 304.5t303 203.5t369 75.5q194 0 370.5 -75.5t304.5 -203.5t204 -304.5t76 -370.5q0 -193 -76 -369t-204 -303t-304.5 -202.5t-370.5 -75.5q-193 0 -369 75.5t-303 202.5t-202.5 303t-75.5 369zM100 639q0 -172 67.5 -329.5t181.5 -272 t271.5 -182.5t329.5 -68q69 0 158 14l63 133l37 123l-98 66l-10 72l-13 73l46 68l-15 22l-76 66l-18 47l-80 8l-141 80l-152 264v164l-59 129l-107 70l-129 -111l-18 88l29 49l-27 21q-113 -118 -176.5 -271.5t-63.5 -322.5zM516 1370l94 -51l90 55l142 -47l307 -14l6 -74 l-102 -20l-43 -54l145 -141l43 27l-4 133l47 8l84 -96h51l78 -209l-76 -27l-123 -72l-63 -65q-6 -90 2 -98q8 -7 -4.5 -19t-20.5 -12q-4 0 -15.5 8.5t-20.5 17.5l-9 9q-11 7 -27.5 17t-54.5 24.5t-59 9.5q-24 -6 -38 -35t-12.5 -54t11.5 -36q11 -7 34 1t40 20l18 12l51 -51 l-22 -39l68 -4l26 -70l70 43l28 -23l115 -14l70 -53l22 -96h62l14 -33l-47 -146l-76 -53l-20 -90l-117 -102l-2 -4q235 100 380.5 313.5t145.5 472.5q0 173 -67.5 331t-182 272t-272.5 181.5t-332 67.5q-237 0 -434 -121z" />
+<glyph unicode="7" d="M0 664q0 186 72.5 356t195 293t292 195.5t355.5 72.5q149 0 289 -46.5t252.5 -131t197.5 -197.5t131 -253t46 -289q0 -186 -72.5 -356t-195 -293t-292.5 -196t-356 -73t-355.5 73t-292 196t-195 293t-72.5 356zM96 664q0 -166 65 -318t175 -262t261.5 -175t317.5 -65 q134 0 259 41.5t226 117.5t176.5 177t117 226t41.5 258q0 167 -65 318.5t-174.5 261t-261.5 174.5t-319 65q-166 0 -317.5 -65t-261.5 -174.5t-175 -261t-65 -318.5zM332 502v35h84v-31q0 -92 63 -92q30 0 47 24q17 20 17 49q0 27 -11 56q-11 25 -26 43q-13 16 -49 47 l-62 53q-63 54 -63 121q0 76 35 108q38 35 102 35h25q12 0 45 -8q24 -6 45 -24q13 -11 28 -48q9 -36 9 -55h-89v10q0 24 -18 39q-16 19 -39 19q-26 0 -43 -17q-20 -17 -20 -45q0 -43 51 -82l88 -71q12 -10 33 -31q15 -19 20 -31l14 -28q5 -15 7 -23q2 -14 2 -23v-20 q0 -41 -4 -59q-3 -23 -15 -47q-7 -21 -22 -33q-13 -13 -39 -23q-21 -8 -60 -8q-86 0 -120 37q-35 35 -35 123zM741 944h88l50 -405h34l52 405h86l-82 -594h-146zM1188 350v594h96l96 -289l23 -86v375h82v-594h-90l-101 303l-22 86v-389h-84z" />
+<glyph unicode="8" d="M41 469l186 987q11 41 43 55l117 78q27 12 43.5 -1.5t32.5 -47.5q23 -48 -47 -88l-13 -7l-41 -30q-1 -2 -11 -9t-17.5 -19t-11.5 -31q-37 -137 -109 -740h98q66 85 164 135t209 50q112 0 210.5 -50t164.5 -135h352q66 85 164 135t211 50q111 0 209 -50t164 -135h96 q-2 20 -11.5 97t-14.5 118t-14 116t-16 124.5t-16 108.5t-17 102.5t-16 73.5q-5 19 -13.5 31t-18 19t-11.5 9q-54 43 -53 37q-71 38 -47 88q16 33 33.5 47t42.5 2l117 -78q32 -14 43 -55l184 -987q6 -38 -21 -68l-75 -75q-21 -21 -54 -21h-18q-9 -189 -146.5 -319.5 t-326.5 -130.5q-196 0 -334.5 138t-138.5 333h-156q0 -128 -63.5 -236.5t-172.5 -171.5t-237 -63q-190 0 -327 130.5t-146 319.5h-18q-29 0 -56 21l-76 75q-23 29 -20 68zM369 326q0 -132 92 -224q95 -92 223 -92q127 0 225 92q92 92 92 224q0 130 -92 225q-97 94 -225 94 q-129 0 -223 -94q-92 -95 -92 -225zM1468 326q0 -131 93 -224q95 -92 225 -92q128 0 223 92q92 92 92 224q0 130 -92 225q-94 94 -223 94q-131 0 -225 -94q-93 -96 -93 -225z" />
+<glyph unicode="9" d="M41 555v221q0 14 20.5 24.5t49.5 10.5q63 76 159 76h670q28 0 61 -22t51 -41.5t46 -53.5h248q20 26 32 39.5t34.5 35t45 32t45.5 10.5h670q95 0 158 -76q29 0 49 -10.5t20 -24.5v-221q0 -22 -41 -35l-45 -317q-3 -84 -64 -142.5t-145 -58.5h-536q-84 0 -144 58.5 t-63 142.5l-35 241q0 31 -31 52.5t-75 21.5q-43 0 -75 -22t-32 -52l-35 -241q-2 -83 -62 -142t-145 -59h-536q-84 0 -144 58.5t-63 142.5l-47 317q-41 14 -41 35zM250 657l57 -411q2 -4 2 -10q0 -22 15.5 -38t37.5 -16h484q22 0 37.5 16t15.5 38q0 6 2 10l27 200l30 211 q-2 22 -17 37t-36 15h-600q-23 0 -38 -15t-17 -37zM1487 657l31 -211l28 -200q2 -4 2 -8q0 -23 15.5 -38.5t38.5 -15.5h479q23 0 38 15.5t15 38.5q0 4 2 8l59 411q-2 22 -17.5 38t-35.5 16h-600q-22 0 -37.5 -16t-17.5 -38z" />
+<glyph unicode=":" d="M350 608l762 600v-381h864v-446h-864v-381z" />
+<glyph unicode=";" d="M70 -68v1387q0 95 69 164t166 69h1337q43 0 76 -16l-180 -180h-1233q-15 0 -26 -11t-11 -26v-1387q0 -12 11 -22t26 -10h1378q19 0 30 9.5t11 22.5v652l197 196v-848q0 -94 -69.5 -162.5t-168.5 -68.5h-1378q-96 0 -165.5 68.5t-69.5 162.5zM420 563l246 244l272 -279 l1004 1004l245 -244l-1249 -1241z" />
+<glyph unicode="&#x3c;" horiz-adv-x="1228" />
+<glyph unicode="=" d="M41 0v246h1655v-246h-1655zM41 410v245h1655v-245h-1655zM41 819v246h1655v-246h-1655zM41 1229v246h1655v-246h-1655z" />
+<glyph unicode="?" d="M40 572.5q0 175.5 69 348.5t202 306q177 176 415.5 238.5t477 0t414.5 -238.5q133 -133 202 -306t69 -348.5t-69 -348.5t-202 -306q-132 -133 -304.5 -202t-348 -69t-348.5 69t-306 202t-202 306t-69 348.5zM514 862h229q-2 10 7 37q25 91 77 137q66 60 156 60 q101 0 156 -58q57 -51 57 -131q0 -58 -33 -102q-29 -37 -127 -123q-108 -91 -145 -170q-35 -75 -35 -190v-3h225q3 58 17 93q18 40 94 110q153 135 199 211q45 82 45 166q0 161 -125 277q-126 120 -338 120q-200 0 -324 -118q-124 -120 -135 -279v-37zM856 -43h229v217h-229 v-217z" />
+<glyph unicode="@" d="M41 621q0 189 73.5 361t198.5 297t297.5 199t362.5 74q189 0 361 -74t296.5 -199t198.5 -297t74 -361t-74 -361.5t-198.5 -297t-296.5 -198t-361 -73.5q-190 0 -362.5 73.5t-297.5 198t-198.5 297t-73.5 361.5zM205 621q0 -209 102.5 -385t279 -278.5t386.5 -102.5 q208 0 384 102.5t279 279t103 384.5q0 156 -61 298.5t-163.5 245t-244.5 163.5t-297 61q-209 0 -386 -103t-279.5 -279.5t-102.5 -385.5zM571 854v33q9 139 117 241q106 103 283 103q189 0 291 -105q108 -99 108 -239q0 -85 -39 -146q-40 -72 -170 -182q-69 -66 -84 -100 q-11 -19 -14 -78h-195v2q0 106 29 168q37 69 127 145q98 86 111 109q28 42 28 88q0 67 -49 113q-48 51 -135 51q-84 0 -135 -51q-50 -47 -70 -119q-6 -28 -4 -33h-199zM868 66v188h199v-188h-199z" />
+<glyph unicode="A" d="M41 606q0 202 78 385t210 316t315.5 211.5t385.5 78.5t385.5 -78.5t316.5 -211t212 -316.5t79 -385q0 -202 -79 -386t-212 -316t-316.5 -210.5t-385.5 -78.5t-385.5 78t-315.5 211t-210 316.5t-78 385.5zM279 606q0 -153 59 -292t159 -240t239.5 -161t293.5 -60 q153 0 292.5 60t240 161t160 240t59.5 292t-59.5 292.5t-160 240t-240 160t-292.5 59.5q-154 0 -293 -59.5t-239.5 -160t-159.5 -240t-59 -292.5zM928 578v460q0 38 27 65t65 27h18q41 0 66.5 -26.5t25.5 -65.5v-393l283 -135q36 -12 49 -50q6 -17 6 -35q0 -19 -8 -38 l-10 -18q-11 -24 -34.5 -40t-49.5 -16q-21 0 -39 11l-348 168q-25 10 -39 34q-12 21 -12 45v7z" />
+<glyph unicode="B" d="M41 45v105h1677v-105h-313q12 -30 19 -48.5t22 -60t23 -71t18.5 -69t11.5 -67t-1.5 -53t-15.5 -38.5t-36 -13q-84 0 -250 420h-631q-166 -420 -252 -420q-37 1 -49 33q-8 20 -7 47q0 17 3 39q8 54 21 106.5t31 112t22 82.5h-293zM41 276v945h1677v-945h-1677zM586 1325 l41 229q0 24 3 38t10.5 20t13 7t16.5 1h20q11 0 16.5 -1t13 -7t10.5 -20t3 -38v-229h-147zM1004 1325v229q0 29 11 45.5t21 18.5l11 2h45h1q1 0 3.5 -0.5t5 -1.5t6 -3.5t6.5 -5.5t6 -8.5t5 -11.5t3.5 -15t1.5 -20l41 -229h-167z" />
+<glyph unicode="C" d="M41 -215v1315h1837v-1315q0 -44 -24 -65t-60 -21h-1669q-36 0 -60 21t-24 65zM41 1202v168q0 31 26 58.5t58 27.5h311v230h170v-230h707v230h170v-230h311q32 0 58 -27.5t26 -58.5v-168h-1837zM207 -154h315v320h-315v-320zM207 229h315v338h-315v-338zM207 631h315v301 h-315v-301zM606 -154h312v320h-312v-320zM606 229h312v338h-312v-338zM606 631h312v301h-312v-301zM1001 -154h312v320h-312v-320zM1001 229h312v338h-312v-338zM1001 631h312v301h-312v-301zM1399 -154h315v320h-315v-320zM1399 229h315v338h-315v-338zM1399 631h315v301 h-315v-301z" />
+<glyph unicode="D" d="M41 600q0 207 79.5 395.5t214 325.5t320 218t389.5 81q213 0 404 -81t328 -218t217 -325.5t80 -395.5t-80 -394t-217 -322.5t-328 -215.5t-404 -80q-204 0 -389.5 80t-320 215t-214 322.5t-79.5 394.5zM262 600q0 -251 154 -477l1108 1112q-244 180 -480 180 q-156 0 -300.5 -67t-250 -177.5t-168.5 -260.5t-63 -310zM594 -35q224 -176 450 -176q166 0 316 67t256 178t168.5 259.5t62.5 306.5q0 255 -149 481z" />
+<glyph unicode="E" d="M385 -119h1638v1641h-1638v-1641zM500 -2v1407h1407v-1407h-1407zM735 584v235h350v350h236v-350h350v-235h-350v-351h-236v351h-350z" />
+<glyph unicode="F" d="M23 -131v530v432v392l1536 379l-13 -392l582 140q-160 -1061 -162 -1088q-8 -50 -29.5 -86t-58.5 -59.5t-74 -37.5t-94 -28l-1472 -375q-4 -1 -12 -2.5t-30 -3.5h-15q-14 0 -28 2q-20 3 -45 15.5t-43 33t-30 59t-12 89.5zM141 -115q0 -29 21 -49t51 -20h10q29 0 48 19.5 t22 49.5l162 1047l962 242l6 272l-1280 -313q0 -33 -1 -133.5t-1 -141.5v-973z" />
+<glyph unicode="G" d="M41 -203v426h1704v-426h-1704zM41 471v424h1802v-424h-1802zM43 1141v424h776v-424h-776z" />
+<glyph unicode="H" d="M41 -29h117q12 257 105.5 421t258.5 218v195q-167 56 -260.5 222.5t-103.5 428.5h-117v182h1337v-182h-96q-10 -262 -104 -428.5t-260 -222.5v-195q164 -54 257 -218t105 -421h98v-182h-1337v182zM250 -29h106l164 191l207 244l207 -244l164 -191h92q-4 76 -15 144 t-35.5 138t-60 124t-92 95.5t-127.5 59.5l-35 9v333l35 9q72 18 129 61t92.5 98t59.5 126.5t35 140.5t14 147h-940q3 -78 14 -147t35 -140.5t59.5 -126.5t91.5 -98t128 -61l34 -9v-333l-34 -9q-88 -22 -152 -78.5t-99.5 -137t-53.5 -164.5t-23 -181zM535 1135h380l-96 -113 l-94 -111l-96 111z" />
+<glyph unicode="I" d="M41 -317v1878h1057l233 -236l234 -233v-496h-234v377h-352v352h-703v-1411h555l256 -231h-1046zM1038 33h195v348h405v-348h222l-412 -389z" />
+<glyph unicode="J" d="M16 1162v22q0 31 16 38t38 -16l137 -131q23 -23 54 -23t54 23l138 137q22 23 22 54.5t-22 54.5l-131 131q-24 22 -19 40.5t35 18.5h23.5t57 -4.5t80 -13.5t82 -29t74.5 -49q75 -78 99 -184q9 -45 9 -88q0 -59 -18 -115l574 -573q54 18 111 18q45 0 92 -11 q106 -26 186 -104q47 -45 70.5 -123t23.5 -133v-55q0 -31 -15 -38t-38 16l-137 137q-23 22 -54.5 22t-54.5 -22l-137 -144q-22 -23 -22 -54t22 -54l131 -131q23 -23 19 -38t-35 -15q-3 2 -23 0q-5 -1 -12 -1q-18 0 -46 4q-38 5 -78 12.5t-84 28t-75 50.5q-75 75 -99 182 q-9 45 -9 89q0 60 18 118l-573 573q-56 -18 -115 -18q-43 0 -88 10q-106 23 -184 98q-31 30 -52 73t-29.5 83t-12.5 76q-3 29 -3 49v9zM70 -131l174 268l84 -12l321 330l84 -84l-327 -324l10 -84l-269 -172zM997 993l406 406q46 45 111 45t110 -45l35 -43q49 -45 49 -105 q0 -61 -49 -110l-404 -406l-55 56l393 393q23 24 0 47q-9 9 -23.5 9t-23.5 -9l-393 -393l-53 53l393 393q23 24 4 43q-8 8 -23 8.5t-24 -8.5l-393 -393z" />
+<glyph unicode="K" d="M4 764l326 -447l325 447h-211q5 135 75 249t187.5 180.5t254.5 66.5q140 0 259 -69.5t188 -188.5t69 -259t-69 -259t-188 -188t-259 -69h-953v-229h953q152 0 290 59t237.5 158.5t158.5 237.5t59 290t-59 290t-158.5 238t-237.5 159t-290 59q-198 0 -368 -97t-271.5 -264 t-106.5 -364h-211zM1405 -2q147 89 254 229h256v209l446 -323l-446 -324v209h-510z" />
+<glyph unicode="L" d="M66 562q-26 100 -26 200t26 200q52 200 200 351q112 107 254.5 164t292.5 57t293 -57t256 -164q129 -131 185 -303q39 -121 39 -245q0 -51 -6 -103q-24 -176 -122 -330l502 -502l-219 -219l-504 506q-191 -129 -424 -129q-152 0 -294 57t-253 168q-148 149 -200 349z M332 762q0 -201 139 -342q68 -68 157.5 -106t184.5 -38q195 0 342 144q68 69 105.5 159t37.5 183q0 95 -37.5 184.5t-105.5 157.5q-148 145 -342 145q-94 0 -184 -38.5t-158 -106.5q-139 -141 -139 -342z" />
+<glyph unicode="M" d="M42 -53v35q0 76 6 172q8 118 28 145q9 15 23.5 28.5t38.5 27.5t43.5 24.5t56 25t57 22.5t64.5 24.5t63 23.5q68 30 114 52t58 29l12 7l6 146q-7 5 -17.5 16t-31 57t-26.5 107q-24 -7 -47.5 24t-28.5 64q0 22 3 44.5t14.5 44.5t31.5 17q-12 116 -12 151v11 q10 93 93.5 165.5t211.5 72.5q123 0 206 -73t91 -165q2 -12 2 -30q0 -47 -12 -132q15 3 25.5 -7.5t14.5 -31t5.5 -36t1.5 -31.5q0 -32 -24 -63.5t-50 -24.5q-8 -61 -26 -106t-32 -59l-14 -15v-146q38 -20 183 -88q16 -6 50.5 -18.5t51.5 -19t47 -18t46.5 -18.5t40.5 -18 t39 -20t31.5 -20t28 -22t19.5 -22q18 -27 24 -141q5 -88 4 -168v-48l-2 -100h-1511v19q0 27 -1 86zM1397 854q0 16 1.5 32.5t6 35t13.5 28.5t22 6q-10 105 -10 142q8 89 82.5 154t187.5 65q118 0 192 -64.5t80 -154.5q2 -12 2 -27q0 -42 -14 -115q20 5 31.5 -14t12.5 -44 t-1 -44q0 -23 -21 -51t-45 -21q-6 -55 -22.5 -96.5t-29.5 -55.5l-13 -14v-127q35 -18 170 -77q48 -19 80 -40.5t42 -33t28.5 -43t23.5 -39.5q16 -24 23 -128q5 -80 5 -154v-41l-1 -91h-504q3 104 3 192t-1 144.5t-6.5 106.5t-8 72.5t-10 48.5t-8.5 29t-8 18 q-17 23 -72.5 35.5t-120 21.5t-88.5 22l113 84q-6 5 -14.5 15.5t-26 53t-23.5 97.5q-23 -7 -44 20t-27 52z" />
+<glyph unicode="N" d="M188 928l854 649v-354q76 -9 146 -20.5t161 -34.5t167 -52t152.5 -75t129.5 -102t86 -134.5t33 -169.5q0 -76 -17.5 -151t-45.5 -137t-70.5 -124.5t-84 -110.5t-96 -97t-97 -82.5t-95 -69.5t-82.5 -54t-67.5 -40t-42.5 -25q5 4 13 10.5t33 30t48.5 49t54.5 65.5 t55.5 81.5t47 96.5t34 110t11.5 122t-15 133q-5 26 -17.5 48.5t-28.5 39.5t-41.5 31.5t-47 24t-55 18.5t-56 13.5t-59 9.5t-55.5 7t-53.5 5t-45.5 4v-364z" />
+<glyph unicode="O" d="M42 1168q14 146 118 247q102 105 248 119q22 2 43 2q120 0 221 -68l-566 -563q-66 99 -66 218q0 22 2 45zM209 516q0 145 56.5 277t152.5 228t228.5 153t277.5 57q193 0 357 -96t259.5 -261t95.5 -358q0 -144 -53 -272.5t-149 -227.5l180 -182q15 -13 15 -32.5t-15 -34.5 l-17 -17q-13 -12 -33 -12t-34 12l-187 187l-2 2q-188 -138 -417 -138q-214 0 -396 119l-170 -170q-14 -12 -34 -12t-33 12l-17 17q-14 15 -14 34t14 33l158 162q-105 99 -164 233.5t-59 286.5zM446 516q0 -129 64 -239t174 -174t240 -64q96 0 184 38t152 102t101.5 152 t37.5 185q0 196 -139.5 335.5t-335.5 139.5q-130 0 -240 -63.5t-174 -173t-64 -238.5zM852 541v297q0 24 16.5 40.5t40.5 16.5q25 0 42.5 -17t17.5 -40v-269l172 -137q19 -15 21 -40t-13 -44q-16 -22 -47 -22q-21 0 -35 14l-195 154q-20 18 -20 41v6zM1217 1468 q100 68 221 68q20 0 42 -2q146 -14 249 -119q103 -101 117 -247q2 -22 2 -44q0 -120 -66 -219z" />
+<glyph unicode="P" d="M41 471v408h600v600h410v-600h596v-408h-596v-600h-410v600h-600z" />
+<glyph unicode="Q" d="M385 -119h1638v1641h-1638v-1641zM500 -2v1407h1407v-1407h-1407zM735 584v235h936v-235h-936z" />
+<glyph unicode="R" d="M496 -102v1314q0 57 37.5 98.5t91.5 41.5h26v260h123v-260h123v260h121v-260h123v260h123v-260h122v260h123v-260h123v260h121v-260h29q54 0 91.5 -41.5t37.5 -98.5v-1314q0 -60 -38 -107t-91 -47h-1157q-53 0 -91 47t-38 107zM668 90q0 -49 30 -49h498q11 0 21 15t10 34 q0 17 -10.5 35t-20.5 18h-498q-14 0 -22 -16.5t-8 -36.5zM668 397q0 -49 30 -49h1010q11 0 21 15t10 34q0 17 -10.5 35.5t-20.5 18.5h-1010q-14 0 -22 -17t-8 -37zM668 715q0 -49 30 -49h805q11 0 21 15t10 34t-10.5 38t-20.5 19h-805q-14 0 -22 -18t-8 -39zM668 1016 q0 -49 30 -49h1010q11 0 21 15t10 34t-10 36t-21 17h-1010q-14 0 -22 -16t-8 -37z" />
+<glyph unicode="S" d="M41 37v1204l639 -545zM125 -49l647 667l236 -204q17 -17 34 -17q18 0 39 17l238 204l643 -667h-1837zM139 1317h1813l-910 -778zM1409 696l639 545v-1204z" />
+<glyph unicode="T" d="M41 -170v678h338v338h565v112h-338v680h789v-680h-338v-112h452v-338h336v-678h-788v678h338v225h-903v-225h337v-678h-788zM152 281h565v114h-565v-114zM717 1409h563v115h-563v-115zM1165 281h566v114h-566v-114z" />
+<glyph unicode="U" d="M41 -168v1456q0 35 26.5 60.5t61.5 25.5h958v221q0 36 25.5 61t63.5 25h4q36 0 61 -25t25 -61v-1763q0 -34 -25 -60t-61 -26h-1051q-35 0 -61.5 26t-26.5 60zM184 784q0 -46 33 -78t78 -32h704q46 0 79.5 31.5t33.5 78.5v295q0 47 -33.5 79t-79.5 32h-704q-45 0 -78 -32 t-33 -79v-295zM221 14q0 -46 33.5 -82t77.5 -36q45 0 78.5 36t33.5 82t-33 79.5t-79 33.5q-44 0 -77.5 -33.5t-33.5 -79.5zM221 358q0 -44 33 -76t78 -32q46 0 79 32t33 76q0 46 -33 79.5t-79 33.5q-44 0 -77.5 -33.5t-33.5 -79.5zM543 14q0 -46 33 -82t77 -36q45 0 78 36 t33 82t-32.5 79.5t-78.5 33.5q-44 0 -77 -33.5t-33 -79.5zM543 358q0 -44 33 -76t77 -32q46 0 78.5 32t32.5 76q0 46 -32.5 79.5t-78.5 33.5q-44 0 -77 -33.5t-33 -79.5zM866 14q0 -46 32.5 -82t76.5 -36q46 0 79 35.5t33 82.5q0 46 -32.5 79.5t-79.5 33.5 q-44 0 -76.5 -33.5t-32.5 -79.5zM866 358q0 -44 32.5 -76t76.5 -32q47 0 79.5 31.5t32.5 76.5q0 46 -32.5 79.5t-79.5 33.5q-44 0 -76.5 -33.5t-32.5 -79.5z" />
+<glyph unicode="V" d="M41 1020q0 114 44.5 217.5t119.5 178.5t178.5 119t216.5 44q114 0 217.5 -44t178.5 -119t119 -178.5t44 -217.5q0 -150 -74 -279l-485 -979l-483 979q-76 133 -76 279zM322 1020q0 -116 81.5 -197.5t198.5 -81.5q116 0 197.5 81.5t81.5 197.5q0 117 -81.5 198.5 t-197.5 81.5q-117 0 -198.5 -81.5t-81.5 -198.5z" />
+<glyph unicode="W" d="M41 651q0 171 63.5 328.5t173 275t261.5 193.5t323 92v166h-88v166h334v-166h-80v-166q240 -23 451 -170l180 170l182 -170l-182 -178q182 -247 182 -541q0 -184 -70.5 -350.5t-191 -287t-287.5 -191t-352 -70.5q-180 0 -346 71t-287.5 190.5t-193.5 286.5t-72 351z M270 651q0 -138 52.5 -261t141.5 -211.5t213.5 -140.5t262.5 -52q183 0 336.5 88t242.5 241t89 336q0 137 -52.5 260.5t-142 213t-213 142t-260.5 52.5q-138 0 -262.5 -52.5t-213.5 -142t-141.5 -213t-52.5 -260.5zM774 651q0 91 88 144v342h166v-342q80 -60 80 -144 q0 -46 -23 -83t-57 -58v-104h-166v104q-40 20 -64 56.5t-24 84.5z" />
+<glyph unicode="X" d="M131 856v422h2095v-422h-2095zM1534 184l346 533l346 -533h-692z" />
+<glyph unicode="Y" d="M41 293v1153h752v115h229v-115h750v-1153h-750v-217l455 -359h-113l-342 236v-4h-229v4l-344 -236h-113l457 359v217h-752zM156 408h1501v780h-1501v-780zM223 573l111 322l182 -279l170 269l156 -254l121 373q3 12 13 16.5t21 1.5t17.5 -15t3.5 -22l-160 -491l-172 280 l-170 -262l-166 254l-74 -211q-3 -12 -14 -17.5t-22 -2.5q-18 10 -18 28q0 5 1 10zM1174 532v115h114v-115h-114zM1176 901q0 62 44 107t105 45q63 0 107.5 -45t44.5 -107q0 -63 -44.5 -108t-107.5 -45q-61 0 -105 45t-44 108zM1403 532v115h115v-115h-115z" />
+<glyph unicode="Z" d="M41 -209v840l401 698h199v-149h-98l-344 -566h409l150 -227h370l148 227h410l-343 566h-100v149h199l401 -698v-840h-1802zM569 993h224v580h299v-580h225l-377 -454z" />
+<glyph unicode="[" d="M475 1190h1409l-704 -1086z" />
+<glyph unicode="\" d="M41 -158v776h424v-776h-424zM711 -158v1800h424v-1800h-424zM1382 -158v1235h424v-1235h-424z" />
+<glyph unicode="]" d="M475 104l705 1086l704 -1086h-1409z" />
+<glyph unicode="_" d="M41 61q0 86 60.5 146.5t146.5 60.5q85 0 146 -60.5t61 -146.5q0 -84 -61 -144t-146 -60q-86 0 -146.5 59.5t-60.5 144.5zM41 594v311q214 0 408 -83t334.5 -223.5t223.5 -334.5t83 -407h-312q0 200 -98.5 369.5t-268 268.5t-370.5 99zM41 1184v311q223 0 435.5 -59 t392 -164.5t330.5 -257t256.5 -331t164.5 -392t59 -434.5h-311q0 180 -48 352t-133.5 317.5t-208 268t-268 208t-317.5 133.5t-352 48z" />
+<glyph unicode="a" d="M0 1229v135q0 15 21.5 28t50.5 13h1857q27 0 48.5 -13t21.5 -28v-135q0 -19 -21 -32t-49 -13h-1857q-29 0 -50.5 13t-21.5 32zM39 -102v1036q0 31 21.5 53.5t52.5 22.5h1775q31 0 52.5 -22.5t21.5 -53.5v-1036q0 -29 -21.5 -50.5t-52.5 -21.5h-1775q-31 0 -52.5 21.5 t-21.5 50.5zM557 676q0 -46 32.5 -78.5t78.5 -32.5h665q46 0 79.5 32.5t33.5 78.5q0 45 -33.5 77.5t-79.5 32.5h-665q-46 0 -78.5 -32t-32.5 -78z" />
+<glyph unicode="b" d="M40 -60q0 32 8 97q8 69 32 104q12 18 36 37t47.5 33.5t67.5 35.5t70.5 33t84.5 36.5t83 35.5l219 92v164q-3 2 -7 7t-16 22.5t-22.5 39.5t-21 60t-15.5 82q-4 -1 -8 -1q-24 0 -49 34q-29 38 -29 68q-3 14 -1 37.5t7 46t17.5 36.5t29.5 9q-13 129 -13 174q0 9 1 14 q6 104 103 189t241 85q74 0 138.5 -24.5t107.5 -64t70 -88t32 -97.5q0 -45 -14 -188q18 5 30.5 -9t17.5 -36.5t7.5 -46t-0.5 -37.5q0 -30 -30 -68q-26 -33 -50 -34q-4 0 -8 1q-5 -44 -15.5 -81.5t-22.5 -60.5t-23 -39.5t-18 -23.5l-7 -6l4 -164q41 -18 215 -92 q36 -16 122 -51t125 -52.5t85 -46.5t64 -57q37 -66 37 -145v-115h-1729q-3 25 -3 55z" />
+<glyph unicode="c" d="M41 -184v1767h1397v-153h-1217v-1614h-180zM369 -338v1604h1273v-1233l-380 -371h-893zM512 -201h657v318h324v981h-981v-1299zM694 465v108h621v-108h-621zM694 731v117h621v-117h-621z" />
+<glyph unicode="d" d="M31 616q0 173 70.5 344t205.5 297q127 136 298 207t344 71t343.5 -71t296.5 -207q136 -126 207 -297t71 -344t-71 -344t-207 -297q-126 -136 -296.5 -207t-343.5 -71t-344 71t-298 207q-135 126 -205.5 297t-70.5 344zM469 270l164 -161l315 325l342 -325l162 161 l-319 344l319 320l-162 162l-342 -318l-315 318l-164 -162l317 -320z" />
+<glyph unicode="e" d="M166 -346l196 545l353 -346zM489 309l979 967l336 -334l-985 -985zM1573 1380l215 226l358 -336l-233 -226z" />
+<glyph unicode="f" d="M41 1266q0 23 14.5 44t32.5 39t47 34.5t57 29.5t63 25t65.5 21t63.5 16.5t57.5 12.5t47.5 9q72 21 172 31.5t167 12t186 1.5q117 0 181 -1.5t162.5 -12t180.5 -31.5q39 -8 77 -17.5t97.5 -27t106.5 -40t90 -51t62 -65.5q12 -25 12 -51q0 -14 -3 -28q1 -1 1 -3 q0 -29 -177 -244q-186 -226 -377.5 -448.5t-191.5 -230.5v-242v-287q0 -29 -78.5 -47t-142.5 -18q-75 0 -147 17.5t-72 47.5v287v242q0 8 -191.5 230.5t-377.5 448.5q-178 215 -178 244q0 2 1 3q-8 26 -8 49zM244 1235q0 -50 59 -95t161 -77.5t245.5 -52t304.5 -19.5 q205 0 382.5 32.5t282.5 89t105 122.5q0 52 -105 98t-283 73.5t-382 27.5q-214 0 -392 -27.5t-278 -73t-100 -98.5z" />
+<glyph unicode="g" d="M41 541v135q0 38 30 68t70 30h70q35 0 82.5 54.5t75.5 101.5q11 20 11 45q0 14 -4 29q-9 44 -40 73l-49 47q-29 29 -29 70.5t29 69.5l96 96q28 29 69 29t70 -29l49 -49q17 -19 63 -21q12 -1 24 -1q34 0 66 5q42 8 67 17q32 11 55.5 47.5t23.5 77.5v67q0 41 30.5 72 t70.5 31h133q40 0 70 -31t30 -72v-67q0 -36 55 -85t101 -75q18 -8 40 -8q16 0 33 4q43 9 70 39l49 49q29 29 70.5 29t69.5 -29l96 -96q29 -28 29 -69.5t-29 -70.5l-49 -47q-19 -18 -21 -65q-1 -12 -1 -23q0 -35 5 -67q8 -42 17 -66q10 -34 48 -58t79 -24h65q41 0 72 -30 t31 -70v-133q0 -39 -31 -69t-72 -30h-65q-37 0 -88.5 -56.5t-71.5 -98.5q-11 -20 -11 -45q0 -14 3 -30q10 -43 41 -71l49 -49q29 -29 29 -70t-29 -69l-96 -96q-28 -29 -69.5 -29t-70.5 29l-49 49q-17 19 -64 21h-21q-35 0 -66 -5q-41 -7 -68 -16q-33 -10 -56.5 -46.5 t-23.5 -76.5v-70q0 -41 -30 -71.5t-70 -30.5h-133q-40 0 -70.5 30.5t-30.5 71.5v70q0 24 -32 59t-63.5 58.5t-59.5 40.5q-18 9 -41 9q-16 0 -34 -4q-44 -10 -71 -40l-49 -49q-29 -29 -70 -29t-69 29l-96 96q-29 28 -29 69t29 70l49 49q19 17 22 63q1 14 1 28q0 32 -5 62 q-7 42 -16 66q-10 34 -47.5 58t-77.5 24h-70q-39 0 -69.5 30t-30.5 69zM604 608q0 -180 126.5 -306t305.5 -126q180 0 307 126t127 306t-127 306t-307 126q-179 0 -305.5 -126t-126.5 -306z" />
+<glyph unicode="h" d="M40 341v20q0 117 48 233q12 29 34 71t40 73t51 87.5t45 77.5q38 65 122.5 224.5t100.5 191.5q28 55 62 84t63 30.5t50.5 -5.5t33.5 -21q20 -24 24 -53.5t-7.5 -61t-26 -59t-34 -62t-28.5 -55.5q-35 -62 -66 -118q-27 -46 -84 -162l-24 -48q-14 -15 -24 -50q-4 -13 -4 -25 q0 -21 10 -39q12 -15 27.5 -15.5t33.5 12.5t34 27.5t39.5 37.5t39.5 36q210 174 470 390t470 390q44 36 78 54q32 17 59 17h3q30 -1 51 -26q24 -29 29.5 -57.5t-1 -51.5t-32 -53t-49.5 -51t-68 -57q-134 -111 -224 -186.5t-210 -175.5q-29 -23 -44 -37t-25.5 -31.5t-7 -34.5 t18.5 -39q11 -16 22 -21t26 3t25.5 17t33 30t35.5 33q30 25 473 391q14 12 36 31t38.5 33.5t40 34.5t41 33t41.5 29.5t40 24t38 16t35.5 6t31.5 -6.5q54 -58 54 -101q0 -13 -5 -26q-2 -18 -21.5 -43t-52 -53.5t-62.5 -52.5t-67.5 -52t-50.5 -39q-363 -299 -488 -403 q-62 -50 -85.5 -80t-2.5 -54q22 -15 41.5 -18t40 7t34 20t39 33t38.5 34q186 154 352 293q16 13 41 34.5t39.5 33.5t34.5 26.5t34 19t31 5.5t32 -8t30 -27q16 -13 24.5 -27.5t8 -30t-4.5 -29t-18 -31t-25.5 -31t-34 -32.5t-37.5 -31.5t-41 -33.5t-40 -32 q-102 -85 -173.5 -145t-195.5 -163q-11 -9 -17.5 -15t-17.5 -16t-16 -17.5t-9.5 -17t-3 -17.5t8.5 -15q16 -21 35.5 -25t43.5 9.5t41.5 26t47 39.5t41.5 36q4 4 9 8l5 4l2 2q139 115 182 142q52 34 92 34q26 0 46 -15q11 -8 22 -21q26 -32 26 -58q0 -23 -20 -56 q-22 -36 -83 -89t-160 -132.5t-250 -198.5q-232 -182 -381 -300q-94 -78 -228 -106q-95 -20 -188 -21q-39 0 -78 4q-134 22 -259 87t-212 173q-85 103 -132 216t-51 240z" />
+<glyph unicode="i" d="M41 676q7 17 28 35.5t48 25.5q101 19 207 19q88 0 180 -13q44 98 131 213q-195 117 -346 154q-31 34 -31 57.5t23 40.5q20 20 38.5 24t55.5 3q222 -70 366 -160q20 29 64 68q106 92 199 155q-116 249 -127 428q0 50 41 82q28 14 46 14q24 0 31 -24q35 -210 163.5 -451.5 t334.5 -467.5q208 -226 440 -376t437 -198q18 -7 18 -26.5t-18 -51.5q-8 -16 -33.5 -27t-55.5 -10q-187 27 -411 170q-58 -78 -172 -192q-11 -9 -34.5 -28.5t-35.5 -28.5q102 -215 121 -383q0 -54 -27 -86q-16 -12 -28.5 -16t-32 3.5t-41.5 30.5q-29 180 -125 356 q-107 -66 -221 -114q3 -42 2 -83q0 -157 -39 -298q-10 -31 -29.5 -49t-42.5 -21q-3 -1 -7 -1q-12 0 -30 10q-22 12 -30 30q12 78 12 167.5t-12 190.5q-47 -12 -100 -12h-15q-61 2 -114 11t-107 26.5t-93.5 34.5t-72.5 35l723 661q49 53 49 95q0 24 -16 44q-26 26 -57 26 q-40 0 -89 -42l-723 -668q-20 45 -36.5 102t-28.5 126q-9 57 -9 118q1 13 1 27q2 76 22 139q-124 35 -263 35q-45 0 -91 -4q-19 7 -29 32q-8 21 -8 36v6zM1282 1432q80 29 201 47v10q0 24 14 59.5t43.5 78.5t69.5 81.5t99.5 68.5t125.5 38q17 -2 7.5 -17.5t-34.5 -43.5 t-49 -68q-25 -40 -37 -92q-5 -23 -5 -48q0 -32 9 -67v-11q153 -30 259 -145q97 -103 116 -260q2 0 10 -6q38 -13 79 -13q92 0 192 69q53 37 56 39q14 6 13 -11q-12 -65 -46.5 -121.5t-76.5 -93t-88.5 -63t-84 -38t-60.5 -10.5q-2 0 -6 6q-10 -64 -57 -198q-231 153 -420 362 q-184 198 -330 447zM1665 1311q-9 -8 -9 -19q0 -12 12 -27q22 -29 69 -67.5t55 -46.5q10 -11 40 -57q32 -46 56 -66q13 -11 25 -12q10 0 18 8q11 12 11 35q0 26 -15 67q-28 75 -63 111q-38 35 -105 65q-40 18 -65 18q-18 0 -29 -9z" />
+<glyph unicode="j" d="M580 553h381v864h448v-864h379l-608 -762z" />
+<glyph unicode="k" d="M580 655l608 762l600 -762h-381v-864h-446v864h-381z" />
+<glyph unicode="l" d="M127 164v422h2095v-422h-2095zM127 1257h692l-346 -532z" />
+<glyph unicode="m" d="M41 -217v1337h1837v-1337q0 -44 -24.5 -64t-59.5 -20h-1673q-33 0 -56.5 20t-23.5 64zM41 1202v166q0 33 25 59.5t55 26.5h317v229h164v-229h711v229h168v-229h313q31 0 57.5 -26.5t26.5 -59.5v-166h-1837zM207 -154h1501v1127h-1501v-1127zM326 735l237 74h166v-827 h-221v606l-137 -27zM922 606v193h634v-174l-366 -643h-250l367 624h-385z" />
+<glyph unicode="n" d="M39 218.5q0 85.5 28 169.5t68 143.5t88 107.5l842 842q78 67 184 106q57 20 115 20q48 0 98 -14q108 -30 191 -114q43 -43 73 -88.5t48 -96.5q16 -44 17 -91q0 -7 -1 -15q-3 -56 -29 -109q-14 -49 -41 -95.5t-47 -68.5l-20 -22l-768 -766q-32 -31 -70 -52t-86 -31 q-16 -3 -32 -3q-33 -1 -71 13q-56 20 -108 72.5t-73 108.5q-14 39 -14 74q1 17 3 31q10 48 31 87t53 69l510 512q31 30 67 36q7 1 13 1q28 0 51 -21q21 -25 21 -53q0 -7 -1 -13q-6 -34 -36 -65l-512 -510q-29 -30 -31 -74q0 -3 1 -7q0 -39 26 -66q28 -28 73 -27l2 -1 q46 0 72 30l770 766q18 18 36 54t32 88q7 24 7 50q0 30 -9 63q-16 61 -66 111q-36 36 -84 55q-46 19 -87 19h-3q-42 0 -84 -10q-33 -8 -61 -23.5t-39 -26.5l-12 -12l-842 -842q-15 -15 -27.5 -29t-39 -51.5t-42 -73.5t-25.5 -90q-5 -28 -5 -55q1 -25 5 -49q8 -52 42 -115.5 t94 -123.5t124 -92t120 -36q17 -1 34 -1q38 0 76 6q54 9 94.5 30.5t72 41.5t48.5 36l17 15l919 917q6 4 16.5 8.5t37.5 2t49 -26.5q16 -18 18 -41v-8q0 -18 -6 -29l-6 -14l-920 -918q-48 -49 -106.5 -88.5t-142.5 -68.5t-169 -29t-187.5 45.5t-197.5 140.5 q-94 94 -140 196.5t-46 188z" />
+<glyph unicode="o" d="M621 -254v1704h1183v-1704h-424v338h-338v-338h-421zM788 338h170v254h-170v-254zM788 676h170v254h-170v-254zM788 1016h170v252h-170v-252zM1126 338h170v254h-170v-254zM1126 676h170v254h-170v-254zM1126 1016h170v252h-170v-252zM1466 338h168v254h-168v-254z M1466 676h168v254h-168v-254zM1466 1016h168v252h-168v-252z" />
+<glyph unicode="p" d="M41 20v1016h2216v-1016h-272v-188h-1659v188h-285zM399 1202v350h1506v-350h-1506zM426 -68h1462v480h-1462v-480zM1804 745h176v144h-176v-144z" />
+<glyph unicode="q" d="M273 1310q0 7 4 20q5 16 12.5 34t26.5 42t46 46q114 70 242 70q51 0 103 -11q18 -4 34.5 -9t23.5 -8l7 -3l735 -209q27 -14 27 -41v-1393q0 -13 -11.5 -24.5t-23.5 -11.5q-15 0 -26 11t-11 25v1369l-741 215q-72 22 -133 22h-3q-62 -1 -99.5 -15t-75.5 -40 q-21 -18 -31.5 -37.5t-7.5 -43t36.5 -47t96.5 -42.5l708 -205v-1397l-761 221q-50 14 -77.5 26.5t-53 36.5t-36 63t-10.5 98v1226z" />
+<glyph unicode="r" d="M41 606h242q0 -149 56.5 -287t164.5 -243q255 -223 530 -223q253 0 512 223q21 17 49 47l-245 217h635v-606l-222 217q-10 -9 -17.5 -22t-14 -20t-17.5 -7q-143 -143 -318 -217t-362 -74q-404 0 -704 291q-289 297 -289 704zM66 852v629l217 -217l47 47q298 295 704 295 q187 0 362 -74.5t318 -220.5q143 -140 218 -327t75 -378h-244q0 284 -217 512q-215 215 -512 215q-318 0 -530 -215q-14 0 -26 -12t-23 -12l241 -242h-630z" />
+<glyph unicode="s" d="M45 1090q-5 39 -5 75q0 133 71 211q78 75 190 102q64 16 116 16q38 0 70 -9v117h1194v-117q34 9 73 9q54 0 118 -16q112 -27 190 -102q72 -76 73 -204q0 -38 -7 -82q-16 -75 -54 -140t-89 -111t-107 -82t-114.5 -58.5t-104.5 -35.5t-84 -18q-71 -181 -194 -289t-296 -108 t-294 108t-191 289q-38 5 -84.5 18t-105 35.5t-115 58.5t-107.5 82t-89 111t-54 140zM238 1188q0 -5 -1 -10q0 -26 11 -64q5 -39 27 -73.5t48.5 -58.5t67.5 -48t70.5 -37t70.5 -29q-3 23 -12 87.5t-13 96t-9.5 81.5t-8 87.5t-2.5 69.5q-25 8 -56 8q-28 0 -60 -6 q-69 -14 -105 -47q-10 0 -18 -14t-10 -43zM666 -219q12 1 31.5 3t69 12t87.5 23.5t69 39t31 57.5v195h267v-195q0 -32 29.5 -57.5t71.5 -39t84 -23t72 -12.5l29 -3v-158h-841v158zM1640 868q41 16 70.5 29.5t70 37t67.5 47.5t49.5 58.5t29.5 73.5q11 38 11 64v10 q-2 29 -11 43t-22 14q-32 33 -103 47q-33 7 -62 7q-33 0 -59 -9q0 -155 -41 -422z" />
+<glyph unicode="t" d="M41 78v1024q0 85 61 151t144 66h147v-1450h-147q-85 0 -145 61t-60 148zM569 -131v1450h273v166q0 39 26 67.5t66 28.5h442q38 0 58 -27.5t20 -68.5v-166h279v-1450h-1164zM950 1319h389v151h-389v-151zM1919 -131v1450h156q85 0 143.5 -65.5t58.5 -151.5v-1024 q0 -88 -57.5 -148.5t-144.5 -60.5h-156z" />
+<glyph unicode="u" d="M651 264l467 719l469 -719h-936z" />
+<glyph unicode="v" d="M147 645q0 220 15 375.5t37 155.5q4 0 4 -5q58 -30 133 -83t131.5 -96.5t127.5 -84t130 -55.5q137 -32 295.5 -58.5t333.5 -46t300.5 -31.5t309.5 -27t248 -21v-45q-34 -3 -244 -20t-317.5 -27.5t-294 -31t-342 -47t-293.5 -59.5q-59 -15 -128.5 -55.5t-126 -84 t-131 -96.5t-132.5 -83q0 -4 -4 -4q-22 0 -37 155t-15 375z" />
+<glyph unicode="w" d="M41 582q0 159 58.5 302.5t157.5 248t237 166t290 61.5q160 0 301 -61.5t241 -166t158 -248t58 -302.5q0 -147 -58 -279.5t-158 -229t-241 -153.5t-301 -57q-152 0 -290 57t-237 153.5t-157.5 229.5t-58.5 279zM283 -123q99 -88 233 -131t283 -43q305 0 499 174 q0 -8 -1 -21t-5 -50.5t-9.5 -71.5t-16.5 -76t-24.5 -72t-34.5 -50.5t-46 -20.5h-362h-379q-27 0 -51.5 37.5t-39.5 90.5t-26 106t-15 91zM283 1325q1 8 2.5 21t7.5 50.5t13 72t19 76t25 72t31.5 51t38.5 20.5h379h362q34 0 60.5 -37.5t40 -91t22.5 -106.5t12 -91l2 -37 q-192 170 -499 170q-149 0 -283.5 -41.5t-232.5 -128.5zM680 582q0 -2 0.5 -6.5t3.5 -16.5t8 -22t15 -21.5t24 -17.5l258 -123q31 -12 57 -12q6 1 12 1q32 4 44 23l24 45q11 21 11 40q0 14 -6 26q-15 29 -48 43l-213 92v293q0 52 -16.5 69t-60.5 17h-29q-42 0 -63 -18 t-21 -68v-344zM1612 498v207h100q28 0 49 -24.5t21 -59.5v-54q0 -18 -22.5 -43.5t-47.5 -25.5h-100z" />
+<glyph unicode="x" d="M313 1245l222 228l546 -545l547 545l225 -228l-540 -547l538 -540l-225 -228l-545 543l-544 -541l-222 228l541 538z" />
+<glyph unicode="y" d="M41 457l428 426v-293h961v-268h-961v-293zM700 842v266h963v293l426 -426l-426 -426v293h-963z" />
+<glyph unicode="z" d="M41 610l299 445l297 -445h-186q0 -248 159 -444q0 -2 2 -2q28 -32 43 -47l-157 -162q-9 12 -28.5 34t-29.5 34q0 2 -4 6q-6 8 -20.5 25.5t-20.5 25.5q0 1 -1 4t-1 4q-164 237 -164 522h-188zM504 1276q10 11 61 57q1 1 3 2t3 2q48 38 54 41q1 1 3 2t3 2q236 164 522 164 v189l444 -301l-444 -295v186q-243 0 -444 -160v-2q-8 -6 -50 -43zM719 -207l444 299v-188q253 0 447 164q0 2 2 2q5 4 21 19.5t26 23.5l156 -162q-51 -46 -64 -55q-5 -5 -6 -5q-15 -17 -51 -41q-1 -1 -3.5 -2.5t-4.5 -3.5q-235 -163 -523 -163v-187zM1663 1114l156 158 q12 -12 57 -62q0 -2 4 -6q40 -51 41 -53q0 -4 4 -8q162 -238 162 -522h186l-295 -443l-299 443h187q0 246 -160 444q0 2 -2 2q-7 11 -23.5 28.5t-17.5 18.5z" />
+<glyph unicode="{" d="M563 647l1086 705v-1409z" />
+<glyph unicode="|" d="M774 -27q0 -151 107.5 -256.5t261.5 -105.5q150 0 257 106t107 256q0 100 -49.5 182.5t-132.5 129.5v1095q0 75 -53.5 128t-128.5 53q-78 0 -131.5 -53t-53.5 -128v-241h138v-111h-138v-160h138v-112h-138v-160h138v-115h-138v-196q-84 -47 -134 -130t-50 -182z" />
+<glyph unicode="}" d="M698 -57v1409l1086 -705z" />
+<glyph unicode="~" d="M805 68q0 89 36.5 170t102.5 141v938q0 115 81.5 196.5t197.5 81.5q114 0 195 -81.5t81 -196.5v-938q65 -61 102 -142t37 -169q0 -172 -121.5 -294t-293.5 -122t-295 122t-123 294zM944 68q0 -114 82 -195.5t197 -81.5q114 0 195 81.5t81 195.5q0 76 -37.5 139.5 t-101.5 99.5v1010q0 57 -40 98t-97 41q-58 0 -100 -41t-42 -98v-64h86v-79h-86v-130h129v-79h-129v-127h86v-80h-86v-129h129v-80h-129v-242q-62 -36 -99.5 -100t-37.5 -139z" />
+<glyph unicode="&#xa1;" d="M70 -68v1387q0 92 60 156t153 73q4 4 20 4h1378q17 0 21 -4q91 -9 152 -73.5t61 -155.5v-1387q0 -94 -69.5 -162.5t-164.5 -68.5h-1378q-97 0 -165 68t-68 163zM262 -68q0 -12 13 -22t28 -10h1378q15 0 28 10t13 22v1387q0 15 -13 26t-28 11h-1378q-15 0 -28 -11t-13 -26 v-1387z" />
+<glyph unicode="&#xa2;" d="M510 1006q0 24 12 41t25 23.5t35.5 15t29.5 12.5q25 12 52 38.5t41 51.5q7 17 32 32t58 23v8q0 101 71 171.5t172 70.5h244q103 0 175.5 -70.5t72.5 -171.5v-8q69 -17 92 -55q10 -25 37 -51.5t53 -38.5q5 -3 38 -12.5t49 -27t16 -52.5q0 -18 -93 -48v-993 q0 -100 -71 -172t-170 -72h-635q-102 0 -175 72t-73 172v993q-88 30 -88 48zM721 -35q0 -50 36.5 -85.5t88.5 -35.5h635q48 0 84.5 36t36.5 85v979h-320h-244h-317v-979zM856 -35v858h121v-858h-121zM918 1251h120h244h123q0 50 -35.5 85.5t-87.5 35.5h-244 q-49 0 -84.5 -35.5t-35.5 -85.5zM1100 -35v858h123v-858h-123zM1346 -35v858h120v-858h-120z" />
+<glyph unicode="&#xa3;" d="M121 520q0 104 73.5 178t176.5 74q77 0 139 -42t92 -109h160l534 417q30 37 78 37h389l-51 170l406 -270l-406 -270l51 169h-340l-446 -354l446 -354h340l-51 168l406 -268l-406 -271l51 168h-389q-46 0 -78 37l-534 420h-160q-30 -69 -92 -110.5t-139 -41.5 q-103 0 -176.5 74t-73.5 178z" />
+<glyph unicode="&#xa4;" d="M274 827q0 114 45 211t125.5 167.5t191 120.5t242.5 74.5t279 24.5q111 0 205 -20q73 -4 163.5 -33t144.5 -56l54 -28q52 -31 92.5 -60.5t85 -73.5t74 -89.5t49 -107.5t19.5 -130q0 -137 -76 -249.5t-203 -183.5t-288 -109.5t-336 -38.5l-396 -473v528q-151 62 -227 112 q-244 158 -244 414z" />
+<glyph unicode="&#xa5;" d="M100 -14v1284q3 13 15.5 21.5t27.5 8.5h1964q19 0 33 -13t14 -30v-1259q0 -17 -14 -29t-33 -12h-1964q-15 0 -27.5 8.5t-15.5 20.5zM225 1171l903 -616l902 616h-1805zM256 106h1741v902l-869 -559l-872 559v-902z" />
+<glyph unicode="&#xa7;" d="M73 -264.5q-2 40.5 7 107.5t29 102q11 18 28.5 35t46 34.5t51.5 30.5t66.5 32t68 29t78.5 31.5t76 30.5l230 96v185q-7 6 -18.5 19t-35.5 68t-34 126q-31 -7 -64 33t-33 73q0 20 2.5 42.5t8.5 48.5t20 41t33 11q-23 121 -23 181q8 112 111 200t254 88q148 0 247 -87.5 t107 -200.5q11 -49 -10 -181q19 3 30.5 -11t16 -42.5t5.5 -46t1 -43.5q0 -33 -27.5 -73t-56.5 -33q-6 -45 -16.5 -83.5t-22.5 -61t-22.5 -39t-17.5 -22.5l-7 -7v-185q43 -18 225 -96q30 -12 88.5 -35t88.5 -35t74.5 -32t69.5 -35t49.5 -36t37.5 -42q31 -53 31 -150v-118 h-1792q1 10 -1 50.5zM1534 799v153h264v256h154v-256h260v-153h-260v-258h-154v258h-264z" />
+<glyph unicode="&#xa9;" d="M224 640q0 176 70.5 349.5t205.5 306.5q134 135 308 205.5t350 70.5t348.5 -70.5t305.5 -205.5q133 -133 202.5 -306.5t69.5 -349.5t-69.5 -349t-202.5 -305q-133 -135 -305.5 -205.5t-348.5 -70.5t-350 70.5t-308 205.5q-135 132 -205.5 305t-70.5 349z" />
+<glyph unicode="&#xab;" d="M41 567l575 580l-4 -346h858v-420h-858l4 -395zM973 104h796v1010h-796v217h1052v-1448h-1052v221z" />
+<glyph unicode="&#xad;" d="M70.5 368q-62.5 236 0 471.5t238.5 411.5q133 133 304.5 202.5t345.5 69.5t345.5 -69.5t303.5 -202.5q133 -132 202 -303t69 -344.5t-69 -344.5t-202 -304q-132 -133 -303.5 -202t-345.5 -69t-345.5 69t-304.5 202q-176 177 -238.5 413zM383 496h1153v235h-1153v-235z " />
+<glyph unicode="&#xae;" d="M40 -285q-1 32 6.5 100.5t27.5 98.5q11 20 35 40t50 36t69 35.5t75.5 33t87 35t86.5 35.5q76 30 128 52t67 29l14 7v170q-6 6 -16.5 19t-31.5 65.5t-30 120.5q-32 -7 -62 30t-30 72q0 19 2.5 39.5t8 44.5t18 37.5t30.5 9.5q-20 120 -20 181q6 107 102 189.5t244 82.5 q144 0 239 -83t103 -189q10 -38 -10 -181q17 3 28 -9.5t15 -38.5t5 -42.5t1 -40.5q0 -35 -25.5 -72t-54.5 -30q-9 -68 -29.5 -119t-36.5 -69l-16 -17v-170q43 -20 215 -88q43 -19 123 -50.5t122 -49.5t87 -46.5t64 -58.5q28 -72 28 -141v-121h-1716q-2 21 -3 53zM160 825 v127h264v-127h-264zM336 1378l88 92l192 -192l-92 -90zM848 1370v272h131v-272h-131zM1202 1278l193 184l90 -92l-180 -192zM1395 813v139h264v-139h-264z" />
+<glyph unicode="&#xb1;" d="M303 -55q0 43 20.5 72.5t51.5 29.5h375q12 0 16 -4.5t2.5 -14.5t-5.5 -21.5t-7.5 -28.5t-3.5 -33t3.5 -33.5t7.5 -28.5t5.5 -21t-2.5 -15t-16 -5h-375q-30 0 -51 30.5t-21 72.5zM604.5 671.5q-0.5 24.5 7.5 59.5q37 -59 196 -97t368 -38q210 0 368 38t195 97q9 -35 9 -59 t-9 -70q-3 -37 -53.5 -86.5t-120.5 -71.5q-166 -57 -389 -57q-225 0 -388 57q-73 22 -123.5 71.5t-50.5 86.5q-9 45 -9.5 69.5zM604.5 962.5q-0.5 24.5 7.5 59.5q37 -59 196 -97t368 -38q210 0 368 38t195 97q9 -35 9 -59t-9 -70q-3 -36 -53.5 -86t-120.5 -72 q-176 -57 -389 -57q-215 0 -388 57q-73 22 -123.5 72t-50.5 86q-9 45 -9.5 69.5zM604.5 1255.5q0.5 -24.5 9.5 -71.5q0 -36 50.5 -85t123.5 -71q163 -57 388 -57q223 0 389 57q70 22 120.5 71t53.5 85q9 47 9 71t-9 58q-37 -57 -195.5 -95t-367.5 -38q-208 0 -367.5 38 t-196.5 95q-8 -33 -7.5 -57.5zM614 1448q0 36 75 70.5t206.5 56.5t280.5 22q150 0 282 -22t206.5 -56.5t74.5 -70.5q0 -13 -10 -23q-37 -49 -195 -87t-358 -38q-199 0 -356.5 37.5t-196.5 87.5q-9 13 -9 23zM823 -55q0 46 11.5 86.5t22.5 57.5l11 17h193v213q18 0 56.5 -1 t58.5 -1q21 0 59.5 1t56.5 1v-213h191q5 -6 12 -18.5t19 -54.5t12 -88q0 -45 -11 -85.5t-21 -58.5l-11 -18h-615q-5 7 -12.5 19.5t-20 55t-12.5 87.5zM1585 28q2 -10 5.5 -21.5t7.5 -28.5t4 -33t-4 -33.5t-7.5 -28.5t-5.5 -21t2 -15t15 -5h376q29 0 49.5 30.5t20.5 72.5 q0 43 -20.5 72.5t-49.5 29.5h-376q-11 0 -15 -4.5t-2 -14.5z" />
+<glyph unicode="&#xb6;" d="M811 522h752l-375 -577zM811 680l375 577l377 -577h-752z" />
+<glyph unicode="&#xb7;" d="M365 582q0 135 51.5 259t146.5 218q97 97 219.5 147.5t257.5 50.5h140v402l745 -533l-745 -532v401h-140q-171 0 -292 -121t-121 -292t121.5 -293t291.5 -121l797 8v-262l-797 -8q-134 -1 -257 50t-220 148q-95 95 -146.5 219t-51.5 259z" />
+<glyph unicode="&#xbb;" d="M41 -117v1448h1053v-221h-797v-1010h797v-217h-1053zM594 414v420h860l-4 395l573 -582l-573 -579l4 346h-860z" />
+<glyph unicode="&#xbf;" d="M31 1014q0 167 87.5 310.5t235 227.5t316.5 84q170 0 319 -84t237.5 -227.5t88.5 -310.5q0 -136 -65.5 -259.5t-172.5 -215.5q-62 -69 -102 -162t-53 -178h-506q-20 87 -78.5 200.5t-114.5 175.5q-192 205 -192 439zM246 973l309 -500q3 -6 11 -7.5t14 1.5q29 18 14 43 l-227 405l116 -69q20 -8 35 4l146 84q7 -4 30.5 -19.5t51.5 -32t59 -32.5q14 -11 35 -4l114 69l-243 -405q-15 -26 2 -43q8 -8 16 -8q11 0 21 14l327 500q14 23 -10 51q-25 20 -43 8l-197 -94q-18 7 -54 32.5t-64 47.5t-29 22q-18 11 -37 0l-145 -102l-197 94q-20 10 -47 -8 q-22 -26 -8 -51zM416 68q0 25 18 43t45 18h381q25 0 45.5 -19.5t20.5 -46.5q0 -24 -21 -41.5t-49 -17.5h-377q-28 0 -45.5 18t-17.5 46zM416 -127q0 26 17.5 43.5t45.5 17.5h377q28 0 49 -17.5t21 -43.5q0 -27 -21 -45t-49 -18h-377q-28 0 -45.5 17.5t-17.5 45.5zM483 -266 h357q-9 -53 -51.5 -89t-100.5 -36h-55q-55 0 -99 36.5t-51 88.5z" />
+<glyph unicode="&#xe0;" d="M41 -322h156v928q6 -6 18.5 -16.5t56 -37t93 -46.5t130 -36.5t167.5 -16.5q137 0 331 -19.5t319 -39.5l126 -19l-236 387l236 389q-52 9 -138 21.5t-293.5 33.5t-344.5 21q-87 0 -166.5 16t-131.5 38.5t-91.5 45.5t-57.5 39l-18 16v156h-156v-1860z" />
+<glyph unicode="&#xe8;" d="M385 -119h1638v1641h-1638v-1641zM500 -2v1407h1407v-1407h-1407zM793 180v1045h317v-1045h-317z" />
+<glyph unicode="&#xe9;" d="M41 -330v1911h1071l158 -158l-176 -182l-101 100h-714v-1429h1075v635l237 239v-1116h-1550zM475 131l178 436l260 -256zM764 698l747 740l277 -275l-748 -747zM1608 1542l159 158l281 -277l-162 -139z" />
+<glyph unicode="&#xec;" d="M27 866v125h694v-125h-694zM197 641v125h524v-125h-524zM414 416v125h307v-125h-307zM856 117v1059h1487v-1059h-1487zM987 248h1223v741l-611 -430l-612 430v-741zM989 1042l610 -311l611 311h-1221z" />
+<glyph unicode="&#xf2;" d="M205 80v1458q0 82 82 82h1710q80 0 80 -82v-1731q0 -79 -80 -79h-1438zM426 1165h223v221h-223v-221zM686 -80q0 -19 14 -33t35 -14h1151q20 0 34.5 14t14.5 33v551q0 20 -14.5 33.5t-34.5 13.5h-1151q-22 0 -35.5 -13.5t-13.5 -33.5v-551zM840 -16v370q0 11 8.5 19 t21.5 8h140q9 0 18.5 -8.5t9.5 -18.5v-370q0 -8 -9.5 -16.5t-18.5 -8.5h-140q-13 0 -21.5 8.5t-8.5 16.5z" />
+<glyph unicode="&#xf9;" d="M721 958h936l-467 -718z" />
+<glyph unicode="&#x2000;" horiz-adv-x="936" />
+<glyph unicode="&#x2001;" horiz-adv-x="1872" />
+<glyph unicode="&#x2002;" horiz-adv-x="936" />
+<glyph unicode="&#x2003;" horiz-adv-x="1872" />
+<glyph unicode="&#x2004;" horiz-adv-x="624" />
+<glyph unicode="&#x2005;" horiz-adv-x="468" />
+<glyph unicode="&#x2006;" horiz-adv-x="312" />
+<glyph unicode="&#x2007;" horiz-adv-x="312" />
+<glyph unicode="&#x2008;" horiz-adv-x="234" />
+<glyph unicode="&#x2009;" horiz-adv-x="374" />
+<glyph unicode="&#x200a;" horiz-adv-x="104" />
+<glyph unicode="&#x2010;" d="M70.5 368q-62.5 236 0 471.5t238.5 411.5q133 133 304.5 202.5t345.5 69.5t345.5 -69.5t303.5 -202.5q133 -132 202 -303t69 -344.5t-69 -344.5t-202 -304q-132 -133 -303.5 -202t-345.5 -69t-345.5 69t-304.5 202q-176 177 -238.5 413zM383 496h1153v235h-1153v-235z " />
+<glyph unicode="&#x2011;" d="M70.5 368q-62.5 236 0 471.5t238.5 411.5q133 133 304.5 202.5t345.5 69.5t345.5 -69.5t303.5 -202.5q133 -132 202 -303t69 -344.5t-69 -344.5t-202 -304q-132 -133 -303.5 -202t-345.5 -69t-345.5 69t-304.5 202q-176 177 -238.5 413zM383 496h1153v235h-1153v-235z " />
+<glyph unicode="&#x2012;" d="M70.5 368q-62.5 236 0 471.5t238.5 411.5q133 133 304.5 202.5t345.5 69.5t345.5 -69.5t303.5 -202.5q133 -132 202 -303t69 -344.5t-69 -344.5t-202 -304q-132 -133 -303.5 -202t-345.5 -69t-345.5 69t-304.5 202q-176 177 -238.5 413zM383 496h1153v235h-1153v-235z " />
+<glyph unicode="&#x2013;" horiz-adv-x="2492" d="M596 39v1434h272v-1434h-272zM995 756v2l684 684l201 -197l-489 -487l489 -490l-197 -200z" />
+<glyph unicode="&#x2014;" d="M0 135q0 108 42 209t118 176l358 361q76 76 177 117.5t210 41.5q199 0 350 -129l-235 -235q-53 35 -115 35q-89 0 -153 -64l-359 -360q-63 -60 -63 -152q0 -89 63 -152t152 -63q51 0 101.5 25t66.5 69h487l-270 -264q-77 -76 -177 -118t-208 -42q-148 0 -273.5 73 t-198.5 198.5t-73 273.5zM793 317l235 236q53 -35 115 -35q89 0 153 64l359 360q63 60 63 152q0 89 -63 152t-152 63q-51 0 -101.5 -25.5t-66.5 -69.5h-487l270 265q77 76 177 117.5t208 41.5q148 0 273.5 -72.5t198.5 -198t73 -273.5q0 -108 -42 -209t-118 -176l-358 -361 q-77 -77 -177.5 -118.5t-209.5 -41.5q-199 0 -350 129z" />
+<glyph unicode="&#x2018;" d="M41 -240v1508h528l316 315q-2 10 -2 21q0 34 23.5 60t56.5 26t57 -26t24 -60q0 -11 -2 -21l314 -315h530v-1508h-1845zM250 -8h1417v1044h-1417v-1044zM319 131q6 9 16.5 23.5t43 52t65 66t77.5 52t85 23.5q48 0 85.5 -11.5t58.5 -25.5t59 -25.5t86 -11.5q38 0 76.5 22 t73.5 53t73 62.5t91 53.5t112 22q44 0 83.5 -19.5t67 -51t51 -69.5t38 -76t25 -69.5t14.5 -51.5l4 -19h-1285zM463 717q0 89 62 152t151 63q88 0 153.5 -63t65.5 -152q0 -88 -65 -150.5t-154 -62.5t-151 62t-62 151zM686 1268h551l-254 256q-8 -2 -20 -2q-13 0 -21 2z" />
+<glyph unicode="&#x2019;" d="M573 66v729q0 20 8.5 34t19 21t31 10t33 3.5t37 -0.5t31.5 -1v260q0 116 63.5 208t162 140.5t210.5 49.5q112 -1 211 -49.5t163 -140.5t65 -208v-260q7 0 30.5 1t36 0.5t32.5 -3.5t30.5 -10t19 -21t8.5 -34v-729q0 -66 -65 -66h-1061q-66 0 -66 66zM920 862h499v254 q0 102 -74 154.5t-176 54.5q-102 -2 -175.5 -54.5t-73.5 -154.5v-254z" />
+<glyph unicode="&#x201a;" d="M573 66v729q0 60 74 67h772v254q0 102 -74 154.5t-176 54.5q-102 -2 -175.5 -54.5t-73.5 -154.5v-55h-187v61q0 116 63.5 208t162 140.5t210.5 49.5q112 -1 211 -49.5t163 -140.5t65 -208v-260q7 0 30.5 1t36 0.5t32.5 -3.5t30.5 -10t19 -21t8.5 -34v-729q0 -66 -65 -66 h-1061q-66 0 -66 66z" />
+<glyph unicode="&#x2022;" d="M453 264l489 488l-489 489l196 201l688 -688v-2l-684 -684zM1464 37v1433h273v-1433h-273z" />
+<glyph unicode="&#x2026;" d="M4 98q0 97 70.5 167.5t167.5 70.5q99 0 168 -70t69 -168q0 -100 -68.5 -168.5t-168.5 -68.5q-98 0 -168 69t-70 168zM717 98q0 97 70 167.5t169 70.5q97 0 167.5 -70.5t70.5 -167.5q0 -99 -70 -168t-168 -69q-100 0 -169.5 68.5t-69.5 168.5zM1430 98q0 97 69.5 167.5 t167.5 70.5q97 0 167.5 -70.5t70.5 -167.5q0 -99 -70 -168t-168 -69q-99 0 -168 69t-69 168z" />
+<glyph unicode="&#x202f;" horiz-adv-x="374" />
+<glyph unicode="&#x2039;" d="M135 537l361 362l411 -412l893 891l361 -362l-1252 -1252l-2 3l-4 -3z" />
+<glyph unicode="&#x203a;" d="M127 588q0 172 66 326.5t177.5 265.5t266 176t324.5 65v293l530 -397l-530 -402v297q-164 0 -306 -84t-225.5 -228t-83.5 -312q0 -164 83.5 -306t225.5 -225.5t306 -83.5q168 0 311.5 83.5t227 225.5t83.5 306h211q0 -169 -66.5 -323.5t-178 -266t-266 -178t-322.5 -66.5 q-170 0 -324.5 66.5t-266 178t-177.5 266t-66 323.5z" />
+<glyph unicode="&#x205f;" horiz-adv-x="468" />
+<glyph unicode="&#x20ac;" d="M41 434q0 190 93 351t254 255.5t351 94.5q191 0 352.5 -94.5t255 -255.5t93.5 -351q0 -189 -93.5 -349.5t-255 -254.5t-352.5 -94q-142 0 -271.5 55.5t-223 149.5t-148.5 223t-55 270zM649 424q0 -25 12.5 -47.5t34.5 -32.5l246 -113q29 -17 62 -6t47 41l2 13 q17 32 7 64.5t-42 49.5l-191 88v264q0 36 -22 60t-57 24h-15q-35 0 -59.5 -24.5t-24.5 -59.5v-319v-2zM1012 1257v43q0 26 16.5 43t40.5 17h240v172h110v-172h531v172h114v-172h234q25 0 43 -17t18 -43v-116h-1185q-79 47 -162 73zM1262 1124h1097v-995q0 -23 -18 -40 t-43 -17h-770q42 112 43 114h84v238h-51v10v47h51v234h-94q-2 5 -11 26.5t-14 34.5h119v234h-236v-41q-65 90 -157 155zM1716 186h234v238h-234v-238zM1716 481h234v234h-234v-234zM1716 776h234v234h-234v-234zM2009 186h232v238h-232v-238zM2009 481h232v234h-232v-234z M2009 776h232v234h-232v-234z" />
+<glyph unicode="&#x2122;" d="M40 -97q-2 32 5 85.5t23 79.5q9 15 23 28.5t36 27.5t41 24.5t52 25t54 23t61 25t60 24.5l183 76v145q-6 5 -15 15t-28 53.5t-27 99.5q-25 -6 -50.5 26t-25.5 58q0 24 3 47.5t15 46t33 18.5q-18 92 -18 144q6 88 87.5 157.5t201.5 69.5q116 0 194 -69t84 -158 q9 -38 -8 -144q14 3 23.5 -8t12.5 -33t4 -36t1 -35q0 -26 -21.5 -58t-44.5 -26q-7 -56 -24 -98t-30 -56l-13 -14v-145q35 -17 178 -76q22 -9 82.5 -32.5t84.5 -34t63 -30t59.5 -36.5t32.5 -37q24 -47 24 -119v-94h-1415q1 8 -1 40zM1270 784l186 365h-176l238 489l309 -10 l-185 -332h205l-270 -385h184l-446 -546l153 419h-198z" />
+<glyph unicode="&#xe000;" horiz-adv-x="1474" d="M0 0v1475h1475v-1475h-1475z" />
+</font>
+</defs></svg> 
\ No newline at end of file
diff --git a/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.ttf b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.ttf
new file mode 100644
index 0000000..3f5b69b
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.ttf differ
diff --git a/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.woff b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.woff
new file mode 100644
index 0000000..84ee95b
Binary files /dev/null and b/src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.woff differ
diff --git a/src/vendor/jquery-teamwork-gantt/teamworkFont.css b/src/vendor/jquery-teamwork-gantt/teamworkFont.css
new file mode 100644
index 0000000..1ee92fd
--- /dev/null
+++ b/src/vendor/jquery-teamwork-gantt/teamworkFont.css
@@ -0,0 +1,16 @@
+
+ at font-face {
+    font-family: 'TeamworkRegular';
+    src: url('teamwork-regular-webfont.eot');
+    src: url('teamwork-regular-webfont.eot?#iefix') format('embedded-opentype'),
+    url('teamwork-regular-webfont.woff') format('woff'),
+    url('teamwork-regular-webfont.ttf') format('truetype'),
+    url('teamwork-regular-webfont.otf') format('opentype'),
+    url('teamwork-regular-webfont.svg#TeamworkRegular') format('svg');
+    font-weight: normal;
+    font-style: normal;
+
+}
+
+
+
diff --git a/src/www/images/closeBig.png b/src/www/images/closeBig.png
new file mode 100644
index 0000000..f0fe8a7
Binary files /dev/null and b/src/www/images/closeBig.png differ
diff --git a/src/www/images/linkArrow.png b/src/www/images/linkArrow.png
new file mode 100644
index 0000000..e23ec14
Binary files /dev/null and b/src/www/images/linkArrow.png differ
diff --git a/src/www/pm/detail_task.php b/src/www/pm/detail_task.php
index 26056a2..5a62b91 100644
--- a/src/www/pm/detail_task.php
+++ b/src/www/pm/detail_task.php
@@ -5,6 +5,7 @@
  * Copyright 1999/2000, Sourceforge.net Tim Perdue
  * Copyright 2002 GForge, LLC, Tim Perdue
  * Copyright 2010, FusionForge Team
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -29,6 +30,8 @@ if (getStringFromRequest('commentsort') == 'anti') {
 	$sort_comments_chronologically = true;
 }
 
+global $pt;
+
 pm_header(array('title'=>_('Task Detail'),'group_project_id'=>$group_project_id));
 
 ?>
diff --git a/src/www/pm/ganttpage.php b/src/www/pm/ganttpage.php
index fae3528..64abc8e 100644
--- a/src/www/pm/ganttpage.php
+++ b/src/www/pm/ganttpage.php
@@ -6,6 +6,7 @@
  * Copyright 2002 GForge, LLC, Tim Perdue
  * Copyright 2010, FusionForge Team
  * Copyright (C) 2012 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -31,124 +32,164 @@ echo '<' . '?xml version="1.0" encoding="utf-8" ?' . ">\n" .
   <head>
 	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 	<title><?php echo _('Gantt Chart');?></title>
+	<link rel=stylesheet href="/scripts/jquery-teamwork-gantt/platform.css" type="text/css">
+	<link rel=stylesheet href="/scripts/jquery-teamwork-gantt/libs/dateField/jquery.dateField.css" type="text/css">
+	<link rel=stylesheet href="/scripts/jquery-teamwork-gantt/gantt.css" type="text/css">
+	
+	<script src="/scripts/jquery/jquery-1.8.3.js"></script>
+	<script src="/scripts/jquery-ui/js/jquery-ui-1.9.2.custom.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/libs/jquery.livequery.min.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/libs/jquery.timers.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/libs/platform.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/libs/date.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/libs/i18nJs.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/libs/dateField/jquery.dateField.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/libs/JST/jquery.JST.js"></script>
+
+	<script src="/scripts/jquery-teamwork-gantt/ganttUtilities.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/ganttTask.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/ganttDrawer.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/ganttGridEditor.js"></script>
+	<script src="/scripts/jquery-teamwork-gantt/ganttMaster.js"></script>
   </head>
-  <body>
+  <body style="background-color: #fff" >
 <?php
 
+require_once $gfcommon.'pm/ProjectTaskFactory.class.php';
+require_once $gfwww.'include/unicode.php';
+
+/* define global vars */
+global $pg, $g;
+
+$offset = getIntFromRequest('offset');
 $_assigned_to = getIntFromRequest('_assigned_to', 0);
 $_category_id = getIntFromRequest('_category_id');
 $_order = getIntFromRequest('_order');
 $_resolution = getStringFromRequest('_resolution');
-$_size = getIntFromRequest('_size', 800);
 $_status = getIntFromRequest('_status', 100);
 $_order = getStringFromRequest('_order');
+$max_rows = getIntFromRequest('max_rows',50);
 
-$engine = RBACEngine::getInstance () ;
-$techs = $engine->getUsersByAllowedAction ('pm', $pg->getID(), 'tech') ;
+$engine = RBACEngine::getInstance();
+$techs = $engine->getUsersByAllowedAction('pm', $pg->getID(), 'tech');
 
-$tech_id_arr = array () ;
-$tech_name_arr = array () ;
+$tech_id_arr = array();
+$tech_name_arr = array();
 
-foreach ($techs as $tech) {
-	$tech_id_arr[] = $tech->getID() ;
-	$tech_name_arr[] = $tech->getRealName() ;
+$ptf = new ProjectTaskFactory($pg);
+if (!$ptf || !is_object($ptf)) {
+	exit_error(_('Could not get ProjectTaskFactory'), 'pm');
+} elseif ($ptf->isError()) {
+	exit_error(_('Error getting PTF: ').$ptf->getErrorMessage(), 'pm');
 }
-$tech_id_arr[]='0';
-$tech_name_arr[]=_('Any');
-
-$tech_box=html_build_select_box_from_arrays ($tech_id_arr,$tech_name_arr,'_assigned_to',$_assigned_to,true,_('Unassigned'), true, _('Any'));
 
-$status_box=html_build_select_box($pg->getStatuses(),'_status',$_status, false, '', true, _('Any'));
+$ptf->setup($offset, $_order, $max_rows, 'custom', $_assigned_to, $_status, $_category_id);
+if ($ptf->isError()) {
+	exit_error(_('Error in PTF: ').$ptf->getErrorMessage(),'pm');
+}
 
-$cat_box=html_build_select_box($pg->getCategories(), '_category_id', $_category_id, true, _('None'), true, _('Any'));
+$pt_arr =& $ptf->getTasks();
+if ($ptf->isError()) {
+	exit_error($ptf->getErrorMessage(), 'pm');
+}
+$transformedTechsArr = array();
+$transformedRolesArr = array();
+foreach ($techs as $tech) {
+	$tech_id_arr[] = $tech->getID();
+	$tech_name_arr[] = $tech->getRealName();
+	$transformedTechsArr[] = array('id' => $tech->getID(), 'name' => $tech->getRealName());
+	$role = $tech->getRole($g);
+	$transformedRolesArr[] = array('id' => $role->getID(), 'name' => $role->getName());
+}
+$transformedTasksArr = array();
+$transformedTasksArr2 = array();
+$minstartdate = 99999999999999999999;
+//$maxstartdate = 0;
+foreach ($pt_arr as $task) {
+	$duration = ($task->getEndDate() - $task->getStartDate())/(24*60*60);
+	if ($minstartdate > $task->getStartDate()) {
+		$minstartdate = $task->getStartDate();
+	}
+// 	if ($maxstartdate < $task->getEndDate()) {
+// 		$maxstartdate = $task->getEndDate();
+// 	}
 
-/*
-	Creating a custom sort box
-*/
-$title_arr=array();
-$title_arr[]=_('Task Id');
-$title_arr[]=_('Task Summary');
-$title_arr[]=_('Start Date');
-$title_arr[]=_('End Date');
-$title_arr[]=_('Percent Complete');
-
-$order_col_arr=array();
-$order_col_arr[]='project_task_id';
-$order_col_arr[]='summary';
-$order_col_arr[]='start_date';
-$order_col_arr[]='end_date';
-$order_col_arr[]='percent_complete';
-$order_box=html_build_select_box_from_arrays ($order_col_arr,$title_arr,'_order',$_order,false);
-
-$dispres_col_arr=array();
-$dispres_col_arr[]='Years';
-$dispres_col_arr[]='Months';
-$dispres_col_arr[]='Weeks';
-$dispres_col_arr[]='Days';
-
-$dispres_title_arr=array();
-$dispres_title_arr[]=_('Years');
-$dispres_title_arr[]=_('Months');
-$dispres_title_arr[]=_('Weeks');
-$dispres_title_arr[]=_('Days');
-if (!$_resolution) {
-	$_resolution=_('Months');
+	$assignees = array();
+	$assigneesIdArr = $task->getAssignedTo();
+	foreach ($assigneesIdArr as $assigneeId) {
+		$assigneeOjbject = user_get_object($assigneeId);
+		$assigneeRole = $assigneeOjbject->getRole($g);
+		$assignees[] = array(
+					'resourceId' => $assigneeOjbject->getID(),
+					'id' => $assigneeOjbject->getID(),
+					'roleId' => $assigneeRole->getID(),
+					'effort' => 0
+				);
+	}
+	$transformedTasksArr[] = array(
+					'id' => $task->getID(),
+					'name' => $task->getSummary(),
+					'code' => $task->getCategoryName(),
+					'level' => 0,
+					'status' => 'STATUS_ACTIVE',
+					'start' => (int)$task->getStartDate()*1000,
+					'duration' => (int)$duration,
+					'end' => (int)$task->getEndDate()*1000,
+					'startIsMilestone' => false,
+					'endIsMilestone' => false,
+					'assigs' => $assignees,
+					'description' => $task->getDetails(),
+					'progress' => (int)$task->getPercentComplete()
+				);
+}
+for($j =0; $j <count($pt_arr); $j++) {
+	$dependentTasksArr = $pt_arr[$j]->getDependentOn();
+	$depends = '';
+	$level = 0;
+	foreach ($dependentTasksArr as $key => $dependentTask) {
+		if ($key != 100) {
+			for ($i =0; $i <count($transformedTasksArr); $i++) {
+				if ($transformedTasksArr[$i]['id'] == $key) {
+					// depends is based on the row number in the gantt editor ... which starts at 1 not 0... (0 is the th...)
+					$newkey = $i+1;
+					$level = $transformedTasksArr[$i]['level'] + 1;
+					break;
+				}
+			}
+			// bug here.... $key should be the array key of the task not the task id...
+			$depends .= $newkey.',';
+		}
+	}
+	$transformedTasksArr[$j]['depends'] = $depends;
+	$transformedTasksArr[$j]['level'] = $level;
 }
-$dispres_box=html_build_select_box_from_arrays ($dispres_col_arr,$dispres_title_arr,'_resolution',$_resolution,false);
 
-/*
-	Graph Size Box
-*/
-$size_col_arr=array();
-$size_col_arr[]=640;
-$size_col_arr[]=800;
-$size_col_arr[]=1024;
-$size_col_arr[]=1600;
+$tech_id_arr[] = '0';
+$tech_name_arr[] = _('Any');
+
+$tech_box = html_build_select_box_from_arrays($tech_id_arr, $tech_name_arr, '_assigned_to', $_assigned_to, true, _('Unassigned'), true, _('Any'));
 
-$size_title_arr=array();
-$size_title_arr[]='640 x 480';
-$size_title_arr[]='800 x 600';
-$size_title_arr[]='1024 x 768';
-$size_title_arr[]='1600 x 1200';
+$status_box = html_build_select_box($pg->getStatuses(), '_status', $_status, false, '', true, _('Any'));
 
-$size_box=html_build_select_box_from_arrays ($size_col_arr,$size_title_arr,'_size',$_size,false);
+$cat_box = html_build_select_box($pg->getCategories(), '_category_id', $_category_id, true, _('None'), true, _('Any'));
 
 /*
-	Show the new pop-up boxes to select assigned to and/or status
+	Creating a custom sort box
 */
-	global $_size;
-		if ($_size==640) {
-			$gantt_width=740;
-			$gantt_height=620;
-		} elseif ($_size==1024) {
-			$gantt_width=1084;
-			$gantt_height=920;
-		} elseif ($_size==1600) {
-			$gantt_width=1660;
-			$gantt_height=1340;
-		} else {
-			$gantt_width=860;
-			$gantt_height=740;
-		}
-		//echo "XX $_size $gantt_width $gantt_height XX";
-		?>
-		<script type="text/javascript">/* <![CDATA[ */
-		function setSize(width,height) {
-			if (window.outerWidth) {
-				window.outerWidth = width;
-				window.outerHeight = height;
-				window.resize();
-			}
-			else if (window.resizeTo) {
-				window.resizeTo(width,height);
-			}
-			else {
-				alert("Not supported.");
-			}
-		}
-		window.setSize(<?php echo $gantt_width; ?>,<?php echo $gantt_height; ?>);
-		/* ]]> */</script>
-		<?php
+$title_arr = array();
+$title_arr[] = _('Task Id');
+$title_arr[] = _('Task Summary');
+$title_arr[] = _('Start Date');
+$title_arr[] = _('End Date');
+$title_arr[] = _('Percent Complete');
+
+$order_col_arr = array();
+$order_col_arr[] = 'project_task_id';
+$order_col_arr[] = 'summary';
+$order_col_arr[] = 'start_date';
+$order_col_arr[] = 'end_date';
+$order_col_arr[] = 'percent_complete';
+$order_box = html_build_select_box_from_arrays($order_col_arr, $title_arr, '_order', $_order, false);
 
 echo '	<form action="'. getStringFromServer('PHP_SELF') .'?group_id='.$group_id.'&group_project_id='.$group_project_id.'&func=ganttpage" method="post">
 	<table width="10%" class="tableheading">
@@ -157,11 +198,152 @@ echo '	<form action="'. getStringFromServer('PHP_SELF') .'?group_id='.$group_id.
 		<td>'._('Status').'<br />'. $status_box .'</td>
 		<td>'._('Category').'<br />'. $cat_box .'</td>
 		<td>'._('Sort On').'<br />'. $order_box .'</td>
-		<td>'._('Resolution').'<br />'. $dispres_box .'</td>
-		<td>'._('Size').'<br />'. $size_box .'</td>
 		<td><input type="submit" name="submit" value="'._('Browse').'" /></td>
 	</tr></table></form>';
+echo '<div id="workSpace" style="padding:0px; overflow-y:auto; overflow-x:hidden; border:1px solid #e5e5e5; position:relative; margin:0 5px;"></div>';
+?>
+<script type="text/javascript">
+	var ge;
+	jQuery(function() {
+		ge = new GanttMaster();
+		var workSpace = jQuery("#workSpace");
+		workSpace.css({width:jQuery(window).width() - 20, height:jQuery(window).height() - 100});
+		ge.init(workSpace);
+		ge.loadProject({
+			"tasks":
+				<?php echo json_encode($transformedTasksArr); ?>,
+			"resources":
+				<?php echo json_encode($transformedTechsArr); ?>,
+			"roles":
+				<?php echo json_encode($transformedRolesArr); ?>,
+			"canWrite":false,
+			"canWriteOnParent":false,
+			"selectedRow":0,
+			"deletedTaskIds":[],
+			"minEditableDate":<?php echo $minstartdate*1000 ?>,
+		})
+	});
+</script>
+
+<div id="gantEditorTemplates" style="display:none;">
+	<div class="__template__" type="GANTBUTTONS"><!--
+		<div class="ganttButtonBar">
+			<div class="buttons" style="margin:0 0 0 0">
+				<button onclick="$('#workSpace').trigger('zoomMinus.gantt');" class="button textual" title="zoom out"><span class="teamworkIcon">)</span></button>
+				<button onclick="$('#workSpace').trigger('zoomPlus.gantt');" class="button textual" title="zoom in"><span class="teamworkIcon">(</span></button>
+			</div>
+		</div>
+	--></div>
+
+  <div class="__template__" type="TASKSEDITHEAD"><!--
+  <table class="gdfTable" cellspacing="0" cellpadding="0">
+    <thead>
+    <tr style="height:40px">
+      <th class="gdfColHeader" style="width:15px;"></th>
+      <th class="gdfColHeader" style="width:25px;"></th>
+      <th class="gdfColHeader gdfResizable">category</th>
+      <th class="gdfColHeader gdfResizable"></th>
+      <th class="gdfColHeader gdfResizable">task summary</th>
+      <th class="gdfColHeader gdfResizable" style="width:80px;">start</th>
+      <th class="gdfColHeader gdfResizable" style="width:80px;">end</th>
+      <th class="gdfColHeader gdfResizable" style="width:25px;">dur.</th>
+      <th class="gdfColHeader gdfResizable" style="width:25px;">dep.</th>
+      <th class="gdfColHeader gdfResizable">assignees</th>
+    </tr>
+    </thead>
+  </table>
+  --></div>
+
+  <div class="__template__" type="TASKROW"><!--
+  <tr taskId="(#=obj.id#)" class="taskEditRow" level="(#=level#)">
+    <th class="gdfCell edit" align="right" style="cursor:pointer;"><span class="taskRowIndex">(#=obj.getRow()+1#)</span></th>
+    <td class="gdfCell" align="center"><div class="taskStatus cvcColorSquare" status="(#=obj.status#)"></div></td>
+    <td class="gdfCell"><input type="text" name="code" value="(#=obj.code?obj.code:''#)"></td>
+    <td class="gdfCell"><span>-</span></td>
+
+    <td class="gdfCell indentCell" style="padding-left:(#=obj.level*10#)px;"><input type="text" name="name" value="(#=obj.name#)" style="(#=obj.level>0?'border-left:2px dotted orange':''#)"></td>
+
+    <td class="gdfCell"><input type="text" name="start"  value="" class="date"></td>
+    <td class="gdfCell"><input type="text" name="end" value="" class="date"></td>
+    <td class="gdfCell"><input type="text" name="duration" value="(#=obj.duration#)"></td>
+    <td class="gdfCell"><input type="text" name="depends" value="(#=obj.depends#)" (#=obj.hasExternalDep?"readonly":""#)></td>
+    <td class="gdfCell taskAssigs">(#=obj.getAssigsString()#)</td>
+  </tr>
+  --></div>
 
+  <div class="__template__" type="TASKEMPTYROW"><!--
+  --></div>
+
+  <div class="__template__" type="TASKBAR"><!--
+  <div class="taskBox" taskId="(#=obj.id#)" >
+    <div class="layout (#=obj.hasExternalDep?'extDep':''#)">
+      <div class="taskStatus" status="(#=obj.status#)"></div>
+      <div class="taskProgress" style="width:(#=obj.progress>100?100:obj.progress#)%; background-color:(#=obj.progress>100?'red':'rgb(153,255,51);'#);"></div>
+      <div class="milestone (#=obj.startIsMilestone?'active':''#)" ></div>
+
+      <div class="taskLabel"></div>
+      <div class="milestone end (#=obj.endIsMilestone?'active':''#)" ></div>
+    </div>
+  </div>
+  --></div>
+
+
+  <div class="__template__" type="CHANGE_STATUS"><!--
+    <div class="taskStatusBox">
+      <div class="taskStatus cvcColorSquare" status="STATUS_ACTIVE" title="active"></div>
+      <div class="taskStatus cvcColorSquare" status="STATUS_DONE" title="completed"></div>
+      <div class="taskStatus cvcColorSquare" status="STATUS_FAILED" title="failed"></div>
+      <div class="taskStatus cvcColorSquare" status="STATUS_SUSPENDED" title="suspended"></div>
+      <div class="taskStatus cvcColorSquare" status="STATUS_UNDEFINED" title="undefined"></div>
+    </div>
+  --></div>
+
+
+  <div class="__template__" type="TASK_EDITOR"><!--
+  <div class="ganttTaskEditor">
+  <table width="100%">
+    <tr>
+      <td>
+        <table cellpadding="5">
+          <tr>
+            <td><label for="code">category</label><br><input type="text" name="code" id="code" value="" class="formElements"></td>
+           </tr><tr>
+            <td><label for="name">task summary</label><br><input type="text" name="name" id="name" value=""  size="35" class="formElements"></td>
+          </tr>
+          <tr></tr>
+            <td>
+              <label for="description">description</label><br>
+              <textarea rows="5" cols="30" id="description" name="description" class="formElements"></textarea>
+            </td>
+          </tr>
+        </table>
+      </td>
+      <td valign="top">
+        <table cellpadding="5">
+          <tr>
+          <td colspan="2"><label for="status">status</label><br><div id="status" class="taskStatus" status=""></div></td>
+          <tr>
+          <td colspan="2"><label for="progress">progress</label><br><input type="text" name="progress" id="progress" value="" size="3" class="formElements"></td>
+          </tr>
+          <tr>
+          <td><label for="start">start</label><br><input type="text" name="start" id="start"  value="" class="date" size="10" class="formElements"><input type="checkbox" id="startIsMilestone"> </td>
+          <td rowspan="2" class="graph" style="padding-left:50px"><label for="duration">dur.</label><br><input type="text" name="duration" id="duration" value=""  size="5" class="formElements"></td>
+        </tr><tr>
+          <td><label for="end">end</label><br><input type="text" name="end" id="end" value="" class="date"  size="10" class="formElements"><input type="checkbox" id="endIsMilestone"></td>
+        </table>
+      </td>
+    </tr>
+    </table>
+  </div>
+  --></div>
+
+
+  <div class="__template__" type="ASSIGNMENT_ROW"><!--
+  --></div>
+
+</div>
+<?php
+echo '<noscript>';
 echo '<img src="'. getStringFromServer('PHP_SELF') .
 		'?func=ganttchart&group_id='.$group_id.
 		'&group_project_id='.$group_project_id.
@@ -170,10 +352,9 @@ echo '<img src="'. getStringFromServer('PHP_SELF') .
 		'&_order='.$_order.
 		'&_resolution='.$_resolution.
 		'&_category_id='.$_category_id.
-		'&_size='.$_size.
 		'&rand='.util_randnum().'" alt="'. _('Gantt Chart').'" />';
+echo '</noscript>';
 
-//pm_footer(array());
 ?>
 </body>
 </html>

commit 2ecf0d4e72750ea9c255dee4e8f7c73ef00039a2
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 7 18:44:42 2013 +0200

    jqplot: delete jpgraph tracker implementation

diff --git a/src/www/tracker/reporting/index.php b/src/www/tracker/reporting/index.php
index 125ff99..d4463b1 100644
--- a/src/www/tracker/reporting/index.php
+++ b/src/www/tracker/reporting/index.php
@@ -144,25 +144,13 @@ if ($start == $end) {
 	if ($atid) {
 		if (!$area || $area == 'activity') {
 			if (!trackeract_graph($group_id, 'activity', $SPAN, $start, $end, $atid)) {
-				echo '<p class="error">'._('Error during graphic computation.');
+				echo '<p class="error">'._('Error during graphic computation.').'</p>';
 			}
-	?>
-	<noscript>
-	<img src="trackeract_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&group_id=$group_id&atid=$atid"; ?>" width="640" height="480" alt="" />
-	</noscript>
-	<?php
 		} else {
 			if (!trackerpie_graph($group_id, $area, $SPAN, $start, $end, $atid)) {
-				echo '<p class="error">'._('Error during graphic computation.');
+				echo '<p class="error">'._('Error during graphic computation.').'</p>';
 			}
-	?>
-	<noscript>
-	<img src="trackerpie_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&group_id=$group_id&atid=$atid&area=$area"; ?>" width="640" height="480" alt="" />
-	</noscript>
-	<?php
 		}
 	}
 }
-?>
-</p>
-<?php $h->footer(array());
+$h->footer(array());
diff --git a/src/www/tracker/reporting/trackeract_graph.php b/src/www/tracker/reporting/trackeract_graph.php
deleted file mode 100644
index be51a7f..0000000
--- a/src/www/tracker/reporting/trackeract_graph.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2004 (c) GForge LLC
- *
- * @author Tim Perdue tim at gforge.org
- * @date 2003-03-16
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportTrackerAct.class.php';
-
-$group_id = getIntFromRequest('group_id');
-$atid = getIntFromRequest('atid');
-$SPAN = getIntFromRequest('SPAN', REPORT_TYPE_MONTHLY);
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-//
-// Get Project Object
-//
-$group = group_get_object($group_id);
-if (!$group || !is_object($group)) {
-	exit_no_group();
-}
-if ($group->isError()) {
-	if($group->isPermissionDeniedError()) {
-		exit_permission_denied($group->getErrorMessage());
-	} else {
-		exit_error(_('Error'), $group->getErrorMessage());
-	}
-}
-
-//
-//	Create Report
-//
-$report=new ReportTrackerAct($SPAN,$group_id,$atid,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	echo $report->getErrorMessage();
-	exit;
-}
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-$graph->SetScale( "textlin");
-//$graph->SetScale( "linlog");
-//$graph ->SetYScale("log");
-
-// Create the average time plot
-$ydata  =& $report->getAverageTimeData();
-$lineplot =new LinePlot($ydata);
-$lineplot ->SetColor("black");
-$graph->Add( $lineplot);
-
-// Create the open count plot
-$ydata2  =& $report->getOpenCountData();
-$lineplot2 =new LinePlot($ydata2);
-$lineplot2 ->SetColor("blue");
-$graph->Add( $lineplot2 );
-
-// Create the still open count plot
-$ydata3  =& $report->getStillOpenCountData();
-$lineplot3 =new LinePlot($ydata3);
-$lineplot3 ->SetColor("red");
-$graph->Add( $lineplot3 );
-
-//	Legends
-$lineplot->SetLegend ("Avg Time Open (in days)");
-$lineplot2 ->SetLegend("Total Opened");
-$lineplot3 ->SetLegend("Total Still Open");
-
-//echo "<pre>".print_r($report->getDates()).'<br />'.print_r($ydata).'<br />'.print_r($ydata2).'<br />'.print_r($ydata3);
-//echo "<pre>".print_r($ydata2);
-//exit;
-
-//
-//	Titles
-//
-$graph->title->Set("Tracker Activity For: ".$group->getPublicName().
-	" (".date('Y-m-d',$report->getStartDate()) ." to ". date('Y-m-d',$report->getEndDate()) .")");
-$graph->subtitle->Set(forge_get_config('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval($report->getGraphInterval());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/tracker/reporting/trackerpie_graph.php b/src/www/tracker/reporting/trackerpie_graph.php
deleted file mode 100644
index 7b24101..0000000
--- a/src/www/tracker/reporting/trackerpie_graph.php
+++ /dev/null
@@ -1,154 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2004 (c) GForge LLC
- *
- * @author Tim Perdue tim at gforge.org
- * @date 2003-03-16
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie3d.php');
-require_once $gfcommon.'reporting/Report.class.php';
-require_once $gfcommon.'reporting/report_utils.php';
-require_once $gfcommon.'tracker/include/ArtifactTypeHtml.class.php';
-
-
-$group_id = getIntFromRequest('group_id');
-$atid = getIntFromRequest('atid');
-$area = getFilteredStringFromRequest('area', '/^[a-z]+$/', 'category');
-$SPAN = getIntFromRequest('SPAN', REPORT_TYPE_MONTHLY);
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-//
-//	Create Report
-//
-$report=new Report();
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	echo $report->getErrorMessage();
-	exit;
-}
-
-$group = group_get_object($group_id);
-if (!$group || !is_object($group)) {
-	exit_no_group();
-}
-if ($group->isError()) {
-	if($group->isPermissionDeniedError()) {
-		exit_permission_denied($group->getErrorMessage());
-	} else {
-		exit_error(_('Error'), $group->getErrorMessage());
-	}
-}
-
-$at = new ArtifactType($group, $atid);
-if ($at->isError()) {
-	if ($at->isPermissionDeniedError()) {
-		exit_permission_denied();
-	} else {
-		exit_error('Error',$at->getErrorMessage());
-	}
-}
-
-if (!$start) {
-	$start=mktime(0,0,0,date('m'),1,date('Y'));;
-}
-if (!$end) {
-	$end=time();
-} else {
-	$end--;
-}
-
-
-if ($area == 'category') {
-	$res = db_query_params ('SELECT ac.category_name,count(*)
-	FROM artifact a, artifact_category ac
-	WHERE a.group_artifact_id=$1
-	AND a.category_id=ac.id
-	AND a.open_date BETWEEN $2 AND $3
-	GROUP BY category_name',
-				array($atid,
-				      $start,
-				      $end));
-} elseif ($area == 'group') {
-	$res = db_query_params ('SELECT ag.group_name,count(*)
-	FROM artifact a, artifact_group ag
-	WHERE a.group_artifact_id=$1
-	AND a.artifact_group_id=ag.id
-	AND a.open_date BETWEEN $2 AND $3
-	GROUP BY group_name',
-				array($atid,
-				      $start,
-				      $end));
-} elseif ($area == 'resolution') {
-	$res = db_query_params ('SELECT ar.resolution_name,count(*)
-	FROM artifact a, artifact_resolution ar
-	WHERE a.group_artifact_id=$1
-	AND a.resolution_id=ar.id
-	AND a.open_date BETWEEN $2 AND $3
-	GROUP BY resolution_name',
-				array($atid,
-				      $start,
-				      $end));
-} else {
-	$area = 'assignee';
-	$res = db_query_params ('SELECT u.realname,count(*)
-	FROM artifact a, users u
-	WHERE a.group_artifact_id=$1
-	AND a.assigned_to=u.user_id
-	AND a.open_date BETWEEN $2 AND $3
-	GROUP BY realname',
-				array($atid,
-				      $start,
-				      $end));
-}
-
-if (db_error()) {
-	exit_error('Error',db_error());
-}
-
-// Create the graph. These two calls are always required
-$graph  = new PieGraph(640, 480,"auto");
-//$graph->SetMargin(50,10,35,50);
-
-$arr=array();
-$arr['category']='By Category';
-$arr['group']='By Project';
-$arr['resolution']='By Resolution';
-$arr['assignee']='By Assignee';
-$graph->title->Set($arr[$area]." (".date('m/d/Y',$start) ."-". date('m/d/Y',$end) .")");
-$graph->subtitle->Set(forge_get_config('forge_name'));
-
-// Create the tracker open plot
-report_pie_arr(util_result_column_to_array($res,0), util_result_column_to_array($res,1));
-
-$p1  = new PiePlot3D($pie_vals);
-$p1->ExplodeSlice (0);
-$p1->SetLegends($pie_labels);
-$graph->Add( $p1);
-
-// Display the graph
-$graph->Stroke();

commit a342601a8c4f2a91684cb7e012f8411ce417434a
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 7 18:01:30 2013 +0200

    jqplot: fix report by assignee/subproject

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index eb7a0d7..6ff6b4c 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -1166,7 +1166,9 @@ function report_pm_hbar($id, $values, $ticks, $labels, $stackSeries = false) {
 	}
 	for ($j = 0; $j < count($ticks); $j++) {
 		for ($z = 0; $z < count($values); $z++) {
-			if ($values[$z][$j] > $yMax) {
+			if ($stackSeries !== false && $stackSeries[$j] > $yMax) {
+				$yMax = $stackSeries[$j];
+			} elseif ($values[$z][$j] > $yMax) {
 				$yMax = $values[$z][$j];
 			}
 			echo 'values'.$id.'['.$z.'].push('.$values[$z][$j].');';
@@ -1182,7 +1184,7 @@ function report_pm_hbar($id, $values, $ticks, $labels, $stackSeries = false) {
 			plot'.$id.' = jQuery.jqplot (\'chart'.$id.'\', series'.$id.', {
 				height: '.$height.',';
 	if ($stackSeries) {
-		echo '		stackSeries: '.$stackSeries.',';
+		echo '		stackSeries: true,';
 	}
 	echo '			axesDefaults: {
 					tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
@@ -1215,11 +1217,9 @@ function report_pm_hbar($id, $values, $ticks, $labels, $stackSeries = false) {
 					labels'.$id.'
 				,
 				axes: {
-					xaxis: {';
-	if (!$stackSeries) {
-		echo '				max: '.++$yMax.',';
-	}
-	echo '					min: 0,
+					xaxis: {
+						max: '.++$yMax.',
+						min: 0,
 						tickOptions: {
 							angle: 0,
 							showMark: true,
diff --git a/src/www/include/tool_reports.php b/src/www/include/tool_reports.php
index ef749c3..dfc099d 100644
--- a/src/www/include/tool_reports.php
+++ b/src/www/include/tool_reports.php
@@ -39,7 +39,8 @@ function reports_quick_graph($title,$qpa1,$qpa2,$bar_colors) {
 		$assoc_open = util_result_columns_to_assoc($result1);
 		$assoc_all = util_result_columns_to_assoc($result2);
 		while (list($key, $val) = each($assoc_all)) {
-			$titles[]=$key;
+			$titles[] = $key;
+			$all[] = $val;
 			if (isset($assoc_open[$key])) {
 				$open[] = $assoc_open[$key];
 				$diff[] = $val - $assoc_open[$key];
@@ -53,7 +54,7 @@ function reports_quick_graph($title,$qpa1,$qpa2,$bar_colors) {
 		$labels[] = _('All');
 		$values[] = $open;
 		$values[] = $diff;
-		report_pm_hbar(1, $values, $titles, $labels, true);
+		report_pm_hbar(1, $values, $titles, $labels, $all);
 	} else {
 		echo "<p class='information'>"._('No data found to report')."</p>";
 	}

commit d021dce5da87313ee3ca251fb7abde8a1c0f530f
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 7 17:44:26 2013 +0200

    pm: fix php warning

diff --git a/src/www/include/tool_reports.php b/src/www/include/tool_reports.php
index df2259d..ef749c3 100644
--- a/src/www/include/tool_reports.php
+++ b/src/www/include/tool_reports.php
@@ -40,7 +40,7 @@ function reports_quick_graph($title,$qpa1,$qpa2,$bar_colors) {
 		$assoc_all = util_result_columns_to_assoc($result2);
 		while (list($key, $val) = each($assoc_all)) {
 			$titles[]=$key;
-			if ($assoc_open[$key]) {
+			if (isset($assoc_open[$key])) {
 				$open[] = $assoc_open[$key];
 				$diff[] = $val - $assoc_open[$key];
 			} else {

commit 31c907b752c0bd83376535c8185947a00aabd20f
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 7 17:43:59 2013 +0200

    jqplot: delete unused old php3 graphic library

diff --git a/src/www/include/HTML_Graphs.php b/src/www/include/HTML_Graphs.php
deleted file mode 100644
index 23eb490..0000000
--- a/src/www/include/HTML_Graphs.php
+++ /dev/null
@@ -1,845 +0,0 @@
-<?php
-/**
- * SourceForge: Breaking Down the Barriers to Open Source Development
- * Copyright 1999-2001 (c) VA Linux Systems
- * Copyright (C) 2012 Alain Peyrat - Alcatel-Lucent
- * http://sourceforge.net
- *
- * @author		Tim Perdue <tperdue at valnux.com>
- *
- * Ryan T. Sammartino made several changes to make the output XHTML 1.0
- * Transitional.
- */
-
-/*
-#######################################################################
-#
-#      Revision 1.5  1998/11/05 06:15:52  pdavis
-#      Added error_reporting setting per Jean-Pierre Arneodo's request.
-#      (Though redundant) Added html_graph_init() to initialize vars array.
-#
-#      Revision 1.4  1998/07/08 05:24:25  pdavis
-#      Add double_vertical_graph from Jan Diepens.
-#      Added "max" function to find $largest in examples page.
-#      Added code to increase values of zero to one.
-#      Added double_vertical_graph example
-#      Combined all source into one zip.
-#
-#      Revision 1.3  1998/06/17 23:37:19  pdavis
-#      Added mixed color codes and images to double graph.
-#
-#      Revision 1.2  1998/06/17 21:20:20  pdavis
-#      Fixed Background problem, added mixed color codes and graphics.
-#
-#      Revision 1.1  1998/06/17 15:52:41  pdavis
-#      Initial revision
-#
-#
-#######################################################################
-#
-#     *
-#     *  Phil Davis
-#     *
-#     *  Smyrna, Tennessee  37167  USA
-#     *
-#     *  pdavis at pobox.com
-#     *  http://www.pobox.com/~pdavis/
-#     *
-#
-#     (C) Copyright 1998
-#         Phil Davis
-#         Printed in the United States of America
-#
-#     This program is free software; you can redistribute it
-#     and/or modify it under the terms of the GNU General
-#     Public License version 2 as published by the Free
-#     Software Foundation.
-#
-#     This program is distributed in the hope that it will
-#     be useful, but WITHOUT ANY WARRANTY; without even the
-#     implied warranty of MERCHANTABILITY or FITNESS FOR A
-#     PARTICULAR PURPOSE.  See the GNU General Public License
-#     for more details.
-#
-#     Released under GNU Public License v2.0, available
-#     at www.fsf.org.  The author hereby disclaims all
-#     warranties relating to this software, express or implied,
-#     including with no limitation any implied warranties of
-#     merchantability, quality performance, or fitness for a
-#     particular purpose. The author and their distributors
-#     shall not be liable for any special, incidental,
-#     consequential, indirect or similar damages due to loss
-#     of data, even if an agent of the author has been found
-#     to be the source of loss or damage. In no event shall the
-#     author's liability for any damages ever exceed the price
-#     paid for the license to use software, regardless of the
-#     form of the claim. The person using the software bears all
-#     risk as to the quality and performance of the software.
-#
-#     Swim at your own risk!
-#
-#     This software program, documentation, accompanying
-#     written and disk-based notes and specifications, and all
-#     referenced and related program files, screen display
-#     renditions, and text files, are the property of the
-#     author.
-#
-#     The authors have done their best to insure that the
-#     material found in this document is both useful and
-#     accurate. However, please be aware that errors may exist,
-#     the author does not make any guarantee concerning the
-#     accuracy of the information found here or in the uses
-#     to which it may be put.
-#
-#######################################################################
-#
-#  About:
-#
-#  The following PHP3 code provides a nice class interface for
-#  html graphs.  It provides a single, reasonably consistent
-#  interface for creating HTML based graphs.  The idea behind
-#  this code is that the user of the class sets up four or five
-#  arrays and pass these to html_graph() which then takes
-#  care of all the messy HTML layout.  I am reasonably happy
-#  with the outcome of this interface.  The HTML that must be
-#  generated for HTML graphs *is* messy, and the interface is
-#  very clean and flexible.  I think that once you generate
-#  one graph with it, you'll never look at creating HTML graphs
-#  the same.  The arrays that must be set up consist of:
-#
-#       * A names array containing column/row identifiers ($names)
-#       * One or two values arrays containg corresponding
-#         values to the column/row names ($values & $dvalues)
-#       * One or two bars array which also corresponds to the names
-#         array.  The values in these arrays are URLS to graphics
-#         or color codes starting with a # which will be used to
-#         generate the graph bar.  Color codes and graphics may
-#         be mixed in the same chart, although color codes can't
-#         be used on Vertical charts. ($bars & $dbars)
-#       * The heart of customization... a vals array.  If this
-#         array isn't created then html_graphs will use all
-#         default values for the chart.  Items that are customizable
-#         include font styles & colors, backgrounds, graphics,
-#         labels, cellspacing, cellpadding, borders, anotations
-#         and scaling factor. ($vals)
-#
-#######################################################################
-#
-#  Known Bugs:
-#
-#  * Currently the $vals["background"] tag element doesn't
-#    work in Netscape.
-#
-#######################################################################
-#
-#  To Do:
-#
-#  * Would like to make the $vals array to html_graph() completely
-#    optional.  Currently it has to at least be an empty array.
-#
-#######################################################################
-#
-# Contributors:
-#
-#  Jan Diepens - Eindhoven University of Technologie
-#  Jean-Pierre Arneodo
-#
-#######################################################################
-#
-# Contact:
-#
-# If you have questions, suggestions, bugs, bug fixes, or enhancements
-# please send them to pdavis at pobox.com so that they may be wrapped into
-# future versions of HTML_Graph.
-#
-#######################################################################
-#
-#  Examples:
-#
-#  See http://www.pobox.com/~pdavis/programs/
-#
-#######################################################################
-*/
-
-/*
-#######################################################################
-#
-#  Function:  html_graph($names, $values, $bars, $vals[, $dvalues, $dbars])
-#
-#   Purpose:  Calls routines to initialize defaults, set up table
-#             print data, and close table.
-#
-# Arguments:
-#                   $names - Array of element names.
-#                  $values - Array of corresponding values for elements.
-#                    $bars - Array of corresponding graphic image names
-#                            or color codes (begining with a #) for elements.
-#                            Color codes can't be used on vertical charts.
-#                 $dvalues - Array of corresponding values for elements.
-#                            This set is required only in the double graph.
-#                   $dbars - Array of corresponding graphic image names
-#                            or color codes (begining with a #) for elements.
-#                            This set is required only in the double graph.
-#
-#                    $vals -  array("vlabel"=>"",
-#                                   "hlabel"=>"",
-#                                   "type"=>"",
-#                                   "cellpadding"=>"",
-#                                   "cellspacing"=>"",
-#                                   "border"=>"",
-#                                   "width"=>"",
-#                                   "background"=>"",
-#                                   "vfcolor"=>"",
-#                                   "hfcolor"=>"",
-#                                   "vbgcolor"=>"",
-#                                   "hbgcolor"=>"",
-#                                   "vfstyle"=>"",
-#                                   "hfstyle"=>"",
-#                                   "noshowvals"=>"",
-#                                   "scale"=>"",
-#                                   "namebgcolor"=>"",
-#                                   "valuebgcolor"=>"",
-#                                   "namefcolor"=>"",
-#                                   "valuefcolor"=>"",
-#                                   "namefstyle"=>"",
-#                                   "valuefstyle"=>"",
-#                                   "doublefcolor"=>"")
-#
-#             Where:
-#
-#                   vlabel - Vertical Label to apply
-#                            default is NUL
-#                   hlabel - Horizontal Label to apply
-#                            default is NUL
-#                     type - Type of graph
-#                            0 = horizontal
-#                            1 = vertical
-#                            2 = double horizontal
-#                            3 = double vertical
-#                            default is 0
-#              cellpadding - Padding for the overall table
-#                            default is 0
-#              cellspacing - Space for the overall table
-#                            default is 0
-#                   border - Border size for the overall table
-#                            default is 0
-#                    width - Width of the overall table
-#                            default is NUL
-#               background - Background image for the overall table
-#                            If this value exists then no BGCOLOR
-#                            codes will be added to table elements.
-#                            default is NUL
-#                  vfcolor - Vertical label font color
-#                            default is #000000
-#                  hfcolor - Horizontal label font color
-#                            default is #000000
-#                 vbgcolor - Vertical label background color
-#                            Not used if background is set
-#                            default is #FFFFFF
-#                 hbgcolor - Horizontal label background color
-#                            Not used if background is set
-#                            default is #FFFFFF
-#                  vfstyle - Vertical label font style
-#                            default is NUL
-#                  hfstyle - Horizontal label font style
-#                            default is NUL
-#               noshowvals - Don't show numeric value at end of graphic
-#                            Boolean value, default is FALSE
-#                    scale - Scale values by some number.
-#                            default is 1.
-#              namebgcolor - Color code for element name cells
-#                            Not used if background is set
-#                            default is "#000000"
-#             valuebgcolor - Color code for value cells
-#                            Not used if background is set
-#                            default is "#000000"
-#               namefcolor - Color code for font of name element
-#                            default is "#FFFFFF"
-#              valuefcolor - Color code for font of value element
-#                            default is "#000000"
-#               namefstyle - Style code for font of name element
-#                            default is NUL
-#              valuefstyle - Style code for font of value element
-#                            default is NUL
-#             doublefcolor - Color code for font of second element value
-#                            default is "#886666"
-#
-#######################################################################
-*/
-function html_graph($names, $values, $bars, $vals, $dvalues=0, $dbars=0)
-   {
-    // Set the error level on entry and exit so as not to interfear
-    // with anyone elses error checking.
-    $er = error_reporting(1);
-
-    // Set the values that the user didn't
-    $vals = hv_graph_defaults($vals);
-    start_graph($vals, $names);
-
-    if ($vals["type"] == 0)
-       {
-        horizontal_graph($names, $values, $bars, $vals);
-       }
-    elseif ($vals["type"] == 1)
-       {
-        vertical_graph($names, $values, $bars, $vals);
-       }
-    elseif ($vals["type"] == 2)
-       {
-        double_horizontal_graph($names, $values, $bars, $vals, $dvalues, $dbars);
-       }
-    elseif ($vals["type"] == 3)
-       {
-        double_vertical_graph($names, $values, $bars, $vals, $dvalues, $dbars);
-       }
-
-    end_graph();
-
-    // Set the error level back to where it was.
-    error_reporting($er);
-   }
-
-/*
-#######################################################################
-#
-#  Function:  html_graph_init()
-#
-#   Purpose:  Sets up the $vals array by initializing all values to
-#             null.  Used to avoid warnings from error_reporting being
-#             set high.  This routine only needs to be called if you
-#             are woried about using uninitialized variables.
-#
-#   Returns:  The initialized $vals array
-#
-#######################################################################
-*/
-function html_graph_init()
-   {
-    $vals = array("vlabel"=>"",
-                  "hlabel"=>"",
-                  "type"=>"",
-                  "cellpadding"=>"",
-                  "cellspacing"=>"",
-                  "border"=>"",
-                  "width"=>"",
-                  "background"=>"",
-                  "vfcolor"=>"",
-                  "hfcolor"=>"",
-                  "vbgcolor"=>"",
-                  "hbgcolor"=>"",
-                  "vfstyle"=>"",
-                  "hfstyle"=>"",
-                  "noshowvals"=>"",
-                  "scale"=>"",
-                  "namebgcolor"=>"",
-                  "valuebgcolor"=>"",
-                  "namefcolor"=>"",
-                  "valuefcolor"=>"",
-                  "namefstyle"=>"",
-                  "valuefstyle"=>"",
-                  "doublefcolor"=>"");
-
-    return($vals);
-   }
-/*
-#######################################################################
-#
-#  Function:  start_graph($vals, $names)
-#
-#   Purpose:  Prints out the table header and graph labels.
-#
-#######################################################################
-*/
-function start_graph($vals, $names)
-   {
-    print "<!-- Start Inner Graph Table -->\n\n<table";
-    print ' cellpadding="' . $vals["cellpadding"] . '"';
-    print ' cellspacing="' . $vals["cellspacing"] . '"';
-    print ' border="' . $vals["border"] . '"';
-
-    if (isset($vals["width"]) && ($vals["width"] != 0)) { print ' width="' . $vals["width"] . '"'; }
-
-    print '>';
-
-    if ((isset($vals["vlabel"]) && $vals["vlabel"]) || (isset($vals["hlabel"]) && $vals["hlabel"]))
-       {
-        if (($vals["type"] == 0) || ($vals["type"] == 2 ))// horizontal chart
-           {
-            $rowspan = SizeOf($names) + 1;
-            $colspan = 3;
-           }
-        elseif ($vals["type"] == 1 || ($vals["type"] == 3 )) // vertical chart
-           {
-            $rowspan = 3;
-            $colspan = SizeOf($names) + 1;
-           }
-
-        print '<tr><td class="align-center" valign="center" ';
-
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print 'style="background-color:' . $vals["hbgcolor"] . '"'; }
-
-        print ' colspan="' . $colspan . '">';
-		print '<span style="color:' . $vals["hfcolor"] . '; ' . $vals["hfstyle"] . '">';
-        print "<strong>" . $vals["hlabel"] . "</strong>";
-        print '</span></td></tr>';
-
-        print '<tr><td class="align-center" valign="center" ';
-
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print 'style="background-color:' . $vals["vbgcolor"] . '"'; }
-
-        print ' rowspan="' . $rowspan . '">';
-        print '<span style="color:' . $vals["vfcolor"] . '; ' . $vals["vfstyle"] . '">';
-        print "<strong>" . $vals["vlabel"] . "</strong>";
-        print '</span></td>';
-       }
-   }
-
-/*
-#######################################################################
-#
-#  Function:  end_graph()
-#
-#   Purpose:  Prints out the table footer.
-#
-#######################################################################
-*/
-function end_graph()
-   {
-    print "\n</table>\n\n<!-- end inner graph table -->\n\n";
-   }
-
-/*
-#######################################################################
-#
-#  Function:  hv_graph_defaults($vals)
-#
-#   Purpose:  Sets the default values for the $vals array
-#
-#######################################################################
-*/
-function hv_graph_defaults($vals)
-   {
-    if (!isset($vals["vfcolor"]))      { $vals["vfcolor"]="#000000"; }
-    if (!isset($vals["hfcolor"]))      { $vals["hfcolor"]="#000000"; }
-    if (!isset($vals["vbgcolor"]))     { $vals["vbgcolor"]="#ffffff"; }
-    if (!isset($vals["hbgcolor"]))     { $vals["hbgcolor"]="#ffffff"; }
-    if (!isset($vals["cellpadding"]))  { $vals["cellpadding"]=0; }
-    if (!isset($vals["cellspacing"]))  { $vals["cellspacing"]=0; }
-    if (!isset($vals["border"]))       { $vals["border"]=0; }
-    if (!isset($vals["scale"]))        { $vals["scale"]=1; }
-    if (!isset($vals["namebgcolor"]))  { $vals["namebgcolor"]="#ffffff"; }
-    if (!isset($vals["valuebgcolor"])) { $vals["valuebgcolor"]="#ffffff"; }
-    if (!isset($vals["namefcolor"]))   { $vals["namefcolor"]="#000000"; }
-    if (!isset($vals["valuefcolor"]))  { $vals["valuefcolor"]="#000000"; }
-    if (!isset($vals["doublefcolor"])) { $vals["doublefcolor"]="#886666"; }
-
-    return ($vals);
-   }
-
-/*
-#######################################################################
-#
-#  Function:  horizontal_graph($names, $values, $bars, $vals)
-#
-#   Purpose:  Prints out the actual data for the horizontal chart.
-#
-#######################################################################
-*/
-function horizontal_graph($names, $values, $bars, $vals)
-   {
-    for( $i=0;$i<SizeOf($values);$i++ )
-       {
-?>
-
-	<tr>
-	<td class="align-right" <?php
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["namebgcolor"] . '"'; }
-?>>
-		<span style="font-size: -1;color:<?php
-			echo $vals["namefcolor"];
-		?>;<?php
-			echo $vals["namefstyle"];
-	echo "\">";
-        echo "\n".$names[$i]; ?>
-		</span>
-	</td>
-
-	<td  align="left" <?php
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["valuebgcolor"] . '"'; }
-
-	echo ">";
-
-        // Decide if the value in bar is a color code or image.
-		if (preg_match("/^#/", $bars[$i]))
-           {
-?>
-
-		<table align="left" style="background-color:<?php echo $bars[$i] ?>" width="<?php echo $values[$i] * $vals["scale"] ?>">
-			<tr><td> </td></tr>
-		</table>
-
-<?php
-            }
-         else
-            {
-             print '<img src="' . $bars[$i] . '"';
-             print ' height="10" width="' . $values[$i] * $vals["scale"] . '" alt= "" />';
-            }
-        if (! $vals["noshowvals"])
-           {
-            print '		<em><span style="font-size: -2;color:' . $vals["valuefcolor"] . ';'
-            . $vals["valuefstyle"] . '">(';
-            print $values[$i] . ")</span></em>";
-           }
-?>
-
-	</td>
-	</tr>
-<?php
-       } // endfor
-
-   } // end horizontal_graph
-
-/*
-#######################################################################
-#
-#  Function:  vertical_graph($names, $values, $bars, $vals)
-#
-#   Purpose:  Prints out the actual data for the vertical chart.
-#
-#######################################################################
-*/
-function vertical_graph($names, $values, $bars, $vals)
-   {
-    print "<tr>";
-
-    for( $i=0;$i<SizeOf($values);$i++ )
-       {
-
-        print '<td  align="center" valign="bottom" ';
-
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["valuebgcolor"] . '"'; }
-        print ">";
-
-        if (! $vals["noshowvals"])
-           {
-            print '<em><span style="font-size: -2;color:' . $vals["valuefcolor"] . ';'
-            . $vals["valuefstyle"] . '">(';
-            print $values[$i] . ")</span></em><br />";
-           }
-?>
-
-         <img src="<?php echo $bars[$i] ?>" width="5" height="<?php
-
-        // Values of zero are displayed wrong because a image height of zero
-        // gives a strange behavior in Netscape. For this reason the height
-        // is set at 1 pixel if the value is zero. - Jan Diepens
-        if ($values[$i] != 0)
-           {
-            echo $values[$i] * $vals["scale"];
-           }
-        else
-           {
-            echo "1";
-           }
-?>" alt="" />
-
-         </td>
-<?php
-       } // endfor
-
-    print "</tr><tr>";
-
-    for( $i=0;$i<SizeOf($values);$i++ )
-       {
-?>
-        <td class="align-center" valign="top"
-
-<?php
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["namebgcolor"] . '"'; }
-?>
-         >
-		 <span style="font-size: -1;color:<?php echo $vals["namefcolor"] ?>;<?php echo $vals["namefstyle"] ?>">
-         <?php echo $names[$i] ?>
-         </span>
-        </td>
-<?php
-       } // endfor
-
-   } // end vertical_graph
-
-/*
-#######################################################################
-#
-#  Function:  double_horizontal_graph($names, $values, $bars,
-#                                     $vals, $dvalues, $dbars)
-#
-#   Purpose:  Prints out the actual data for the double horizontal chart.
-#
-#######################################################################
-*/
-function double_horizontal_graph($names, $values, $bars, $vals, $dvalues, $dbars)
-   {
-    for( $i=0;$i<SizeOf($values);$i++ )
-       {
-?>
-       <tr>
-        <td class="align-right"
-<?php
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["namebgcolor"] . '"'; }
-?>
-         >
-		 <span style="font-size: -1;color:<?php echo $vals["namefcolor"] ?>;<?php echo $vals["namefstyle"] ?>">
-         <?php echo $names[$i] ?>
-         </span>
-        </td>
-        <td  align="left"
-<?php
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["valuebgcolor"] . '"'; }
-?>
-         >
-         <table align="left" width="<?php echo $dvalues[$i] * $vals["scale"] ?>">
-          <tr><td
-<?php
-        // Set background to a color if it starts with # or
-        // an image otherwise.
-		if (preg_match("/^#/", $dbars[$i])) { print 'style="background-color:' . $dbars[$i] . '">'; }
-        else { print 'background="' . $dbars[$i] . '">'; }
-?>
-           <nowrap>
-<?php
-        // Decide if the value in bar is a color code or image.
-		if (preg_match("/^#/", $bars[$i]))
-           {
-?>
-            <table align="left" 
-             style="background-color:"<?php echo $bars[$i] ?>"
-             width="<?php echo $values[$i] * $vals["scale"] ?>">
-             <tr><td>&nbsp</td></tr>
-            </table>
-<?php
-            }
-         else
-            {
-             print '<img src="' . $bars[$i] . '"';
-             print ' height="10" width="' . $values[$i] * $vals["scale"] . '" alt="" />';
-            }
-
-        if (! $vals["noshowvals"])
-           {
-            print '<em><span style="font-size: -3:color:' . $vals["valuefcolor"] . ';'
-            . $vals["valuefstyle"] . '">(';
-            print $values[$i] . ")</span></em>";
-           }
-?>
-           </nowrap>
-          </td></tr>
-         </table>
-<?php
-        if (! $vals["noshowvals"])
-           {
-            print '<em><span style="font-size:-3;color:' . $vals["doublefcolor"] . ';'
-            . $vals["valuefstyle"] . '">(';
-            print $dvalues[$i] . ")</span></em>";
-           }
-?>
-        </td>
-       </tr>
-<?php
-       } // endfor
-
-   } // end double_horizontal_graph
-
-/*
-#######################################################################
-#
-#  Function:  double_vertical_graph($names, $values, $bars, $vals, $dvalues, $dbars)
-#
-#   Purpose:  Prints out the actual data for the double vertical chart.
-#
-#    Author: Jan Diepens
-#
-#######################################################################
-*/
-function double_vertical_graph($names, $values, $bars, $vals, $dvalues, $dbars)
-   {
-   // print "<tr>";
-
-    for( $i=0;$i<SizeOf($values);$i++ )
-       {
-
-        print '<td class="align-center" valign="bottom" ';
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["valuebgcolor"] . '"'; }
-        print ">";
-
-	print '<table><tr><td class="align-center" valign="bottom" ';
-
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["valuebgcolor"] . '"'; }
-        print ">";
-
-        if (! $vals["noshowvals"])
-           {
-            print '<em><span style="font-size:-2;color:' . $vals["valuefcolor"] . ';'
-            . $vals["valuefstyle"] . '">(';
-            print $values[$i] . ")</span></em><br />";
-           }
-?>
-
-         <img src="<?php echo $bars[$i] ?>" width="10" height="<?php if ($values[$i]!=0){
-		echo $values[$i] * $vals["scale"];
-		} else { echo "1";} ?>" alt="" />
-         </td><td class="align-center" valign="bottom"
-<?php
-         // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["valuebgcolor"] . '"'; }
-        print ">";
-
-        if (! $vals["noshowvals"])
-           {
-            print '<em><span style="font-size:-2;color:' . $vals["doublefcolor"] . ';'
-            . $vals["valuefstyle"] . '">(';
-            print $dvalues[$i] . ")</span></em><br />";
-           }
-?>
-
-         <img src="<?php echo $dbars[$i] ?>" width="10" height="<?php if ($dvalues[$i]!=0){
-		echo $dvalues[$i] * $vals["scale"];
-		} else { echo "1";} ?>" alt="" />
-         </td></tr></table>
-	 </td>
-<?php
-       } // endfor
-
-    print "</tr><tr>";
-
-    for( $i=0;$i<SizeOf($values);$i++ )
-       {
-?>
-        <td class="align-center" valign="top"
-
-<?php
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) { print ' style="background-color:' . $vals["namebgcolor"] . '"'; }
-?>
-         >
-		 <span style="font-size:-1;color:<?php echo $vals["namefcolor"] ?>;<?php echo $vals["namefstyle"] ?>">
-         <?php echo $names[$i] ?>
-         </span>
-        </td>
-<?php
-       } // endfor
-
-   } // end double_vertical_graph
-
-
-
-/*
-#######################################################################
-#
-#  Function:  horizontal_absolute_multi_graph($names, $multi_rows,
-#                                             $colors, $vals,
-#                                             $additive)
-#     $multi_rows - array of arrays of values (may be seen as
-#             array of columns - column for first color, for second, etc.)
-#             $colors - array of color names or codes
-#	  $additive - treat data as absolute values (will be
-#             differentiated for drawing, and hence should be non-decreasing
-#             sequence) or additive (just stick one on another).
-#
-#   Purpose:  Prints out the actual data for the horizontal chart of
-#             bars with multiple sections
-#
-#######################################################################
-*/
-function horizontal_multisection_graph($names, $multi_rows, $colors, $vals, $additive=false)
-   {
-    $subbars_num=SizeOf($multi_rows);
-    for( $i=0;$i<SizeOf($names);$i++ )
-       {
-?>
-
-	<tr>
-	<td class="align-right" <?php
-        // If a background was choosen don't print cell BGCOLOR
-        if (! $vals["background"]) {
-			print ' style="background-color:' . $vals["namebgcolor"] . '"';
-		}
-?>>
-		<span style="font-size:-1;color:<?php echo $vals["namefcolor"]; ?>;<?php echo $vals["namefstyle"]; ?>">
-<?php
-        echo "\n".$names[$i]; ?>
-		</span>
-	</td>
-
-	<td  align="left" <?php
-        // If a background was choosen don't print cell BGCOLOR
-		if (! $vals["background"]) {
-			print ' style="background-color:' . $vals["valuebgcolor"] . '"';
-		}
-		echo ">";
-
-        echo '<table align="left"><tr>'."\n";
-        $prev_val=0;
-        $shown=0;
-		for( $j=0;$j<$subbars_num;$j++ ) {
-        	$width=$multi_rows[$j][$i];
-            if (!$additive) $width-=$prev_val;
-            if ($width<=0 && ($j!=$subbars_num-1 || $shown)) continue;
-            // make sure that we show at least stump, but only one
-            $shown=1;
-            $prev_val=$multi_rows[$j][$i];
-            $pix_width=$width * $vals["scale"];
-            echo "<td style=\"background-color:".$colors[$j]."\" width=\"".$pix_width."\"> </td>";
-        }
-        echo '</tr></table>';
-
-        if (! $vals["noshowvals"]) {
-            print '		<em><span style="font-size:-2;color:' . $vals["valuefcolor"] . ';'
-                . $vals["valuefstyle"] . '"> (';
-        	for( $j=0;$j<SizeOf($multi_rows);$j++ ) {
-                        if ($j) print "/";
-                        print $multi_rows[$j][$i];
-                }
-                print ")</span></em>";
-           }
-?>
-
-	</td>
-	</tr>
-<?php
-       } // endfor
-
-   } // end horizontal_graph
-
-function graph_calculate_scale($multi_rows,$width) {
-	$max_value=0;
-        $rows_num=count($multi_rows);
-
-        for ($row_i = 0; $row_i < $rows_num; $row_i++) {
-                $row=$multi_rows[$row_i];
-               	$counter=count($row);
-
-		for ($i = 0; $i < $counter; $i++) {
-			if ($row[$i] > $max_value) {
-				$max_value=$row[$i];
-			}
-		}
-        }
-
-	if ($max_value < 1) {
-		$max_value=1;
-	}
-
-	$scale=($width/$max_value);
-        return $scale;
-}

commit 768dc711285b862f229f84f513b1c935be1219f2
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 7 17:38:56 2013 +0200

    jqplot: remove unused require

diff --git a/src/www/pm/reporting/index.php b/src/www/pm/reporting/index.php
index 84d7bc2..1d67b48 100644
--- a/src/www/pm/reporting/index.php
+++ b/src/www/pm/reporting/index.php
@@ -31,7 +31,6 @@ require_once $gfcommon.'pm/ProjectGroupFactory.class.php';
 require_once $gfcommon.'pm/ProjectCategory.class.php';
 require_once $gfwww.'project/stats/project_stats_utils.php';
 require_once $gfwww.'include/tool_reports.php';
-require_once $gfwww.'include/HTML_Graphs.php';
 require_once $gfcommon.'reporting/report_utils.php';
 
 
diff --git a/src/www/survey/admin/show_results_comments.php b/src/www/survey/admin/show_results_comments.php
deleted file mode 100644
index fffbb36..0000000
--- a/src/www/survey/admin/show_results_comments.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * Survey Facility
- *
- * Copyright 1999-2001 (c) VA Linux Systems
- * Copyright 2002-2004 (c) GForge Team
- * http://fusionforge.org/
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once $gfwww.'include/HTML_Graphs.php';
-
-$is_admin_page='y';
-$group_id = getIntFromRequest('group_id');
-$survey_id = getIntFromRequest('survey_id');
-$question_id = getIntFromRequest('question_id');
-survey_header(array('title'=>'Survey Aggregate Results'));
-
-if (!session_loggedin() || !forge_check_perm('project_admin', $group_id)) {
-	echo '<div class="error">'._('Permission denied').'</div>';
-	survey_footer(array());
-	exit;
-}
-
-function showResultComments($result) {
-
-	$rows  =  db_numrows($result);
-	$cols  =  db_numfields($result);
-	echo "<h3>$rows Found</h3>";
-
-	echo  "<table>\n";
-	/*  Create  the  headers  */
-	echo "<tr class=\"tableheading\">\n";
-
-	for($i  =  0;  $i  <  $cols;  $i++)  {
-		echo "<th>".db_fieldname($result,$i)."</th>\n";
-	}
-	echo "</tr>";
-
-	for($j  =  0;  $j  <  $rows;  $j++)  {
-			echo "<tr class=\"".$HTML->boxGetAltRowStyle($j)."\">\n";
-
-		for ($i = 0; $i < $cols; $i++) {
-			echo "<td>".db_result($result,$j,$i)."</td>\n";
-		}
-
-		echo "</tr>";
-	}
-	echo "</table>";
-}
-
-$result=db_query_params ('SELECT question FROM survey_questions WHERE question_id=$1',
-			 array($question_id));
-echo "<h2>Question: ".db_result($result,0,"question")."</h2>";
-echo "<p></p>";
-
-$result=db_query_params ('SELECT DISTINCT response FROM survey_responses WHERE survey_id=$1 AND question_id=$2 AND group_id=$3',
-			 array($survey_id,
-			       $question_id,
-			       $group_id));
-showResultComments($result);
-
-survey_footer(array());
-
-// Local Variables:
-// mode: php
-// c-file-style: "bsd"
-// End:
diff --git a/src/www/survey/admin/show_results_csv.php b/src/www/survey/admin/show_results_csv.php
deleted file mode 100644
index 9d488d6..0000000
--- a/src/www/survey/admin/show_results_csv.php
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-/**
- * Survey Facility
- *
- * Copyright 1999-2001 (c) VA Linux Systems
- * Copyright 2002-2004 (c) GForge Team
- * http://fusionforge.org/
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once $gfwww.'include/HTML_Graphs.php';
-
-$group_id = getIntFromRequest('group_id');
-$survey_id = getIntFromRequest('survey_id');
-
-if (!session_loggedin() || !forge_check_perm('project_admin', $group_id)) {
-        echo '<div class="error">'._('Permission denied').'</div>';
-	exit;
-}
-
-function strip_commas($string) {
-	return preg_replace("/,/","",$string);
-}
-
-/*
-	Select this survey from the database
-*/
-
-
-
-$result = db_query_params ('SELECT * FROM surveys WHERE survey_id=$1',
-			   array ($survey_id));
-
-/*
-	Select the questions for this survey and show as top row
-*/
-
-$questions=db_result($result, 0, "survey_questions");
-$questions=str_replace(" ", "", $questions);
-$quest_array=explode(',', $questions);
-$count=count($quest_array);
-
-echo "<html><pre>";
-/*
-#
-#
-#
-#
-#                  clean up later
-#
-#
-#
-#
-*/
-
-echo "cust_id,first_name,field_1,email,field2,phone,field3,field4,field5,year,month,day,";
-
-for ($i=0; $i<$count; $i++) {
-	$result = db_query_params ('SELECT question FROM questions WHERE question_id=$1 AND question_type <> 4',
-				   array($quest_array[$i]));
-	if ($result && db_numrows($result) > 0) {
-		echo strip_commas(db_result($result, 0, 0)).",";
-	}
-}
-
-echo "\n";
-
-/*
-	Now show the customer rows
-*/
-
-$result = db_query_params ('SELECT DISTINCT customer_id FROM responses WHERE survey_id=$1',
-			   array ($survey_id));
-
-$rows=db_numrows($result);
-
-for ($i=0; $i<$rows; $i++) {
-
-	/*
-		Get this customer's info
-	*/
-
-
-	$result2 = db_query_params ('SELECT DISTINCT cust_id,first_name,people.last_name,people.email,people.email2,people.phone,people.beeper,people.cell,people.yes_interested,responses.response_year,responses.response_month,responses.response_day FROM people,responses WHERE cust_id=$1 AND cust_id=responses.customer_id',
-				    array (db_result($result, $i, "customer_id")));
-
-	if (db_numrows($result2) > 0) {
-
-		$cols=db_numfields($result2);
-
-		for ($i2=0; $i2<$cols; $i2++) {
-			echo strip_commas(db_result($result2, 0, $i2)).",";
-		}
-
-		/*
-			Get this customer's responses. may have to be ordered by original question order
-		*/
-
-
-		$result3 = db_query_params ('SELECT response FROM responses WHERE customer_id=$1 AND survey_id=$2',
-					    array (db_result($result, $i, "customer_id"),
-						   $survey_id));
-
-		$rows3=db_numrows($result3);
-
-		for ($i3=0; $i3<$rows3; $i3++) {
-			echo strip_commas(db_result($result3, $i3, "response")).",";
-		}
-
-		/*
-			End of this customer
-		*/
-		echo "\n";
-
-	}
-
-}

commit edd13b7c1ab61cf39454f5e87f3e4d0aa371c075
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 7 17:19:23 2013 +0200

    survey: delete orphan page

diff --git a/src/www/survey/admin/show_results_aggregate.php b/src/www/survey/admin/show_results_aggregate.php
deleted file mode 100644
index 4a24403..0000000
--- a/src/www/survey/admin/show_results_aggregate.php
+++ /dev/null
@@ -1,242 +0,0 @@
-<?php
-/**
- * Survey Facility
- *
- * Copyright 1999-2001 (c) VA Linux Systems
- * Copyright 2002-2004 (c) GForge Team
- * http://fusionforge.org/
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once $gfwww.'include/HTML_Graphs.php';
-
-$is_admin_page='y';
-$group_id = getIntFromRequest('group_id');
-$survey_id = getIntFromRequest('survey_id');
-survey_header(array('title'=>_('Survey Aggregate Results')));
-
-if (!session_loggedin() || !forge_check_perm('project_admin', $group_id)) {
-	echo '<div class="error">'._('Permission denied').'</div>';
-	survey_footer(array());
-	exit;
-}
-
-/*
-	Select this survey from the database
-*/
-
-$result = db_query_params ('SELECT * FROM surveys WHERE survey_id=$1 AND group_id=$2',
-			   array ($survey_id,
-				  $group_id));
-
-echo "<h2>".db_result($result, 0, "survey_title")."</h2><p> </p>";
-
-/*
-echo "<h3><a href=\"show_results_csv.php?survey_id=$survey_id&group_id=$group_id\">.CSV File</a></h3><p>";
-*/
-
-/*
-	Select the questions for this survey
-*/
-
-$questions=db_result($result, 0, "survey_questions");
-$questions=str_replace(" ", "", $questions);
-$quest_array=explode(',', $questions);
-$count=count($quest_array);
-
-echo "\n\n<table>";
-
-$q_num=1;
-
-for ($i=0; $i<$count; $i++) {
-
-	/*
-		Build the questions on the HTML form
-	*/
-
-	$result = db_query_params ('SELECT question_type,question,question_id FROM survey_questions WHERE question_id=$1 AND group_id=$2',
-				   array ($quest_array[$i],
-					  $group_id));
-
-	$question_type=db_result($result, 0, "question_type");
-
-	if ($question_type == "4") {
-		/*
-			Don't show question number if it's just a comment
-		*/
-
-		echo "\n<tr><td class=\"top\"> </td>\n<td>";
-
-	} else {
-
-		echo "\n<tr><td class=\"top\"><strong>";
-
-		/*
-			If it's a 1-5 question box and first in series, move Quest
-			number down a bit
-		*/
-
-		if (($question_type != $last_question_type) && (($question_type == "1") || ($question_type == "3"))) {
-			echo " <p> </p>";
-		}
-
-		echo $q_num."    <br /></td>\n<td>";
-		$q_num++;
-
-	}
-
-	if ($question_type == "1") { // This is a radio-button question. Values 1-5.
-		// Show the 1-5 markers only if this is the first in a series
-
-		if ($question_type != $last_question_type) {
-			echo "\n<strong>1                   5</strong>\n";
-			echo "<br />";
-
-		}
-
-		// Select the number of responses to this question
-
-		$result2 = db_query_params ('SELECT count(*) AS count FROM survey_responses WHERE survey_id=$1 AND question_id=$2 AND response IN (1,2,3,4,5) AND group_id=$3',
-			array ($survey_id,
-				$quest_array[$i],
-				$group_id));
-		if (!$result2 || db_numrows($result2) < 1) {
-			echo _('error');
-			echo db_error();
-		} else {
-			$response_count = db_result($result2, 0, 'count');
-			echo "<strong>" . $response_count . "</strong>" ._('Responses')."<br />";
-		}
-
-		//	average
-		if ($response_count > 0){
-			$result2 = db_query_params ('SELECT avg(response::int) AS avg FROM survey_responses WHERE survey_id=$1 AND question_id=$2 AND group_id=$3 AND response IN (1,2,3,4,5)',
-						    array ($survey_id,
-							   $quest_array[$i],
-							   $group_id));
-			if (!$result2 || db_numrows($result2) < 1) {
-				echo _('error');
-				echo db_error();
-			} else {
-				echo "<strong>". number_format(db_result($result2, 0, 'avg'),2) ."</strong>"._('Average');
-			}
-
-			$result2 = db_query_params ('SELECT response,count(*) AS count FROM survey_responses WHERE survey_id=$1 AND question_id=$2 AND group_id=$3 AND response IN (1,2,3,4,5) GROUP BY response',
-						    array ($survey_id,
-							   $quest_array[$i],
-							   $group_id));
-			if (!$result2 || db_numrows($result2) < 1) {
-				echo _('error');
-				echo db_error();
-			} else {
-				GraphResult($result2,stripslashes(db_result($result, 0, "question")));
-			}
-		}// end if (responses to survey question present)
-	} elseif ($question_type == "2") { // This is a text-area question.
-		echo db_result($result, 0, "question")."<br />\n";
-		echo "<a href=\"show_results_comments.php?survey_id=$survey_id&question_id=$quest_array[$i]&group_id=$group_id\">"._('View All Comments')."</a>";
-
-	} elseif ($question_type == "3") { // 	This is a Yes/No question.
-	  //	Show the Yes/No only if this is the first in a series
-		if ($question_type != $last_question_type) {
-			echo "<strong>"._('Yes / No')."</strong><br />\n";
-		}
-
-		// Select the count and average of responses to this question
-		$result2 = db_query_params ('SELECT count(*) AS count FROM survey_responses WHERE survey_id=$1 AND question_id=$2 AND group_id=$3 AND response IN (1,5)',
-					    array ($survey_id,
-						   $quest_array[$i],
-						   $group_id));
-		if (!$result2 || db_numrows($result2) < 1) {
-			echo _('error');
-			echo db_error();
-		} else {
-			echo "<strong>".db_result($result2, 0, 0)."</strong> "._('Responses')."<br />";
-		}
-
-		// average
-		$result2 = db_query_params ('SELECT avg(response::int) AS avg FROM survey_responses WHERE survey_id=$1 AND question_id=$2 AND group_id=$3  and response != $4',
-					    array ($survey_id,
-						   $quest_array[$i],
-						   $group_id,
-						   ''));
-
-		if (!$result2 || db_numrows($result2) < 1) {
-			echo _('error');
-			echo db_error();
-		} else {
-			echo "<strong>".number_format(db_result($result2, 0, 0),2)."</strong>"._('Average');
-		}
-
-		// Get the YES responses
-		$result2 = db_query_params ('SELECT count(*) AS count FROM survey_responses WHERE survey_id=$1 AND question_id=$2 AND group_id=$3 AND response=1',
-					    array ($survey_id,
-						   $quest_array[$i],
-						   $group_id));
-
-		$name_array[0]=_('Yes');
-
-		if (!$result2 || db_numrows($result2) < 1) {
-			$value_array[0]=0;
-		} else {
-			$value_array[0]=db_result($result2, 0, "count");
-		}
-
-		// Get the NO responses
-		$result2 = db_query_params ('SELECT count(*) AS count FROM survey_responses WHERE survey_id=$1 AND question_id=$2 AND group_id=$3 AND response=5',
-					    array ($survey_id,
-						   $quest_array[$i],
-						   $group_id));
-
-		$name_array[1]=_('No');
-
-		if (!$result2 || db_numrows($result2) < 1) {
-			$value_array[1]=0;
-		} else {
-			$value_array[1]=db_result($result2, 0, "count");
-		}
-
-		GraphIt($name_array,$value_array,stripslashes(db_result($result, 0, "question")));
-
-	} elseif ($question_type == "4") {
-
-		echo " <p><strong>".db_result($result, 0, "question")."</strong></p>\n";
-		echo "<input type=\"hidden\" name=\"_".$quest_array[$i]."\" value=\"-666\" />";
-
-	} elseif ($question_type == "5") { // This is a text-field question.
-		echo db_result($result, 0, "question")."<br />\n";
-
-		echo "<a href=\"show_results_comments.php?survey_id=$survey_id&question_id=$quest_array[$i]&group_id=$group_id\">"._('View All Comments')."</a>";
-
-	}
-
-	echo "</td></tr>";
-
-	$last_question_type=$question_type;
-
-}
-
-echo "\n\n</table>";
-
-survey_footer(array());
-
-// Local Variables:
-// mode: php
-// c-file-style: "bsd"
-// End:

commit de8333953d9657372d63552c55f4dc28db7d163f
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 7 16:56:03 2013 +0200

    jqplot: pm implement quick report

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 99cc7dd..eb7a0d7 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -1152,7 +1152,7 @@ function report_sitetimebargraph($start, $end) {
 	return true;
 }
 
-function report_pm_hbar($id, $values, $ticks, $labels) {
+function report_pm_hbar($id, $values, $ticks, $labels, $stackSeries = false) {
 	$yMax = 0;
 	echo '<script type="text/javascript">//<![CDATA['."\n";
 	echo 'var plot'.$id.';';
@@ -1176,12 +1176,15 @@ function report_pm_hbar($id, $values, $ticks, $labels) {
 	for ($z = 0; $z < count($values); $z++) {
 		echo 'series'.$id.'.push(values'.$id.'['.$z.']);';
 	}
-	$height = 40+50*count($ticks);
+	$height = 40 + 50 * count($ticks);
 	
 	echo 'jQuery(document).ready(function(){
 			plot'.$id.' = jQuery.jqplot (\'chart'.$id.'\', series'.$id.', {
-				height: '.$height.',
-				axesDefaults: {
+				height: '.$height.',';
+	if ($stackSeries) {
+		echo '		stackSeries: '.$stackSeries.',';
+	}
+	echo '			axesDefaults: {
 					tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
 					tickOptions: {
 						angle: 0,
@@ -1196,6 +1199,10 @@ function report_pm_hbar($id, $values, $ticks, $labels) {
 					lineWidth: 1,
 					fill: true,
 					renderer:jQuery.jqplot.BarRenderer,
+					pointLabels: {
+						show:true,
+						stackedValue: true
+					},
 					rendererOptions: {
 						barDirection: \'horizontal\',
 						fillToZero: true
@@ -1208,9 +1215,11 @@ function report_pm_hbar($id, $values, $ticks, $labels) {
 					labels'.$id.'
 				,
 				axes: {
-					xaxis: {
-						max: '.++$yMax.',
-						min: 0,
+					xaxis: {';
+	if (!$stackSeries) {
+		echo '				max: '.++$yMax.',';
+	}
+	echo '					min: 0,
 						tickOptions: {
 							angle: 0,
 							showMark: true,
@@ -1222,13 +1231,6 @@ function report_pm_hbar($id, $values, $ticks, $labels) {
 						ticks: ticks'.$id.'
 					},
 				},
-				highlighter: {
-					show: true,
-					sizeAdjust: 2.5,
-					showTooltip: true,
-					tooltipAxes: \'x\',
-					tooltipLocation: \'ne\'
-				},
 			});
 		});';
 	echo 'jQuery(window).resize(function() {
diff --git a/src/www/include/tool_reports.php b/src/www/include/tool_reports.php
index 78a9c66..df2259d 100644
--- a/src/www/include/tool_reports.php
+++ b/src/www/include/tool_reports.php
@@ -4,6 +4,7 @@
  * Copyright 1999-2001 (c) VA Linux Systems
  * Copyright 2010, FusionForge Team
  * Copyright (C) 2010-2012 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -31,41 +32,28 @@
  * @param		string	The bar colors
  */
 function reports_quick_graph($title,$qpa1,$qpa2,$bar_colors) {
-	$result1=db_query_qpa($qpa1);
-	$result2=db_query_qpa($qpa2);
+	$result1 = db_query_qpa($qpa1);
+	$result2 = db_query_qpa($qpa2);
 	if ($result1 && $result2 && db_numrows($result2) > 0) {
 
-		$assoc_open=util_result_columns_to_assoc($result1);
-		$assoc_all=util_result_columns_to_assoc($result2);
-		while (list($key,$val)=each($assoc_all)) {
+		$assoc_open = util_result_columns_to_assoc($result1);
+		$assoc_all = util_result_columns_to_assoc($result2);
+		while (list($key, $val) = each($assoc_all)) {
 			$titles[]=$key;
-			$all[]=$val;
-			if ($assoc_open[$key])	$open[]=$assoc_open[$key];
-			else $open[]=0;
+			if ($assoc_open[$key]) {
+				$open[] = $assoc_open[$key];
+				$diff[] = $val - $assoc_open[$key];
+			} else {
+				$open[] = 0;
+				$diff[] = $val;
+			}
 		}
 
-/*	       	for ($i=0; $i<db_numrows($result1); $i++) {
-			echo "$titles[$i]=>$opened[$i]/$all[$i]<br />";
-		}
-*/
-		$scale=graph_calculate_scale(array($open,$all),400);
-		$props["scale"]=$scale;
-		$props["cellspacing"]=5;
-		$props = hv_graph_defaults($props);
-		start_graph($props, $titles);
-
-		horizontal_multisection_graph(
-			$titles,
-			array($open,$all),
-			$bar_colors,
-			$props
-		);
-		end_graph();
-		print '<p /><br />';
-		print '<table><tr class="align-center"><td style="width:15%">'._('Key').':</td><td style="width:5%">(</td><td style="width:35%; background-color:'.$bar_colors[0].'">'._('Open').'</td>'.
-		      '<td style="width:5%">/</td><td style="width:35%; background-color:'.$bar_colors[1].'">'._('All').' </td><td style="width:5%">)</td></tr></table>';
-		print '<p />';
-//      		GraphResult($result,$title);
+		$labels[] = _('Open');
+		$labels[] = _('All');
+		$values[] = $open;
+		$values[] = $diff;
+		report_pm_hbar(1, $values, $titles, $labels, true);
 	} else {
 		echo "<p class='information'>"._('No data found to report')."</p>";
 	}
diff --git a/src/www/pm/reporting/index.php b/src/www/pm/reporting/index.php
index a16972f..84d7bc2 100644
--- a/src/www/pm/reporting/index.php
+++ b/src/www/pm/reporting/index.php
@@ -79,7 +79,6 @@ function pm_quick_report($group_id,$title,$subtitle1,$qpa1,$subtitle2,$qpa2,$com
 }
 
 html_use_jqueryjqplotpluginCanvas();
-html_use_jqueryjqplotpluginhighlighter();
 html_use_jqueryjqplotplugindateAxisRenderer();
 html_use_jqueryjqplotpluginBar();
 
@@ -120,8 +119,8 @@ if ($what) {
 		
 		for ($counter=1; $counter<=$span; $counter++) {
 
-			$start=($time_now-($counter*$sub_duration));
-			$end=($time_now-(($counter-1)*$sub_duration));
+			$start = ($time_now-($counter*$sub_duration));
+			$end = ($time_now-(($counter-1)*$sub_duration));
 
 			if ($end < $g->getStartDate()) {
 				break;
@@ -154,10 +153,10 @@ if ($what) {
 		$values = array();
 		$labels = array();
 		$ticks = array();
-		for ($counter=1; $counter<=$span; $counter++) {
+		for ($counter = 1; $counter <= $span; $counter++) {
 
-			$start=($time_now-($counter*$sub_duration));
-			$end=($time_now-(($counter-1)*$sub_duration));
+			$start = ($time_now - ($counter * $sub_duration));
+			$end = ($time_now - (($counter - 1 ) * $sub_duration));
 
 			if ($end < $g->getStartDate()) {
 				break;
@@ -171,8 +170,8 @@ if ($what) {
 								AND project_group_list.group_id=$3 ',
 								array($end, $end, $group_id));
 
-			$ticks[$counter-1]=date("Y-m-d",($end));
-			$values[0][$counter-1]=db_result($resNotCompleted, 0,0);
+			$ticks[$counter-1] = date("Y-m-d", ($end));
+			$values[0][$counter-1] = db_result($resNotCompleted, 0, 0);
 		}
 
 		$labels[] = _('Number of tasks still not completed');

commit d025ef41db220441ad6f52b1718efc69630dc672
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jul 7 15:59:09 2013 +0200

    jqplot: fix toolpie, implement pm reporting aging

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 6031f32..99cc7dd 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -953,7 +953,7 @@ function report_toolspiegraph($datatype = 0, $start, $end) {
 		echo '<script type="text/javascript">//<![CDATA['."\n";
 		echo 'var data'.$chartid.' = new Array();';
 		while ($row = db_fetch_array($res)) {
-			echo 'data'.$chartid.'.push([\''.htmlentities($row[0]).'\',\''.$row[1].'\']);';
+			echo 'data'.$chartid.'.push([\''.htmlentities($row[0]).'\','.$row[1].']);';
 		}
 		echo 'var plot'.$chartid.';';
 		echo 'jQuery(document).ready(function(){
@@ -1152,6 +1152,92 @@ function report_sitetimebargraph($start, $end) {
 	return true;
 }
 
+function report_pm_hbar($id, $values, $ticks, $labels) {
+	$yMax = 0;
+	echo '<script type="text/javascript">//<![CDATA['."\n";
+	echo 'var plot'.$id.';';
+	echo 'var values'.$id.' = new Array();';
+	echo 'var ticks'.$id.' = new Array();';
+	echo 'var labels'.$id.' = new Array();';
+	echo 'var series'.$id.' = new Array();';
+	for ($z = 0; $z < count($values); $z++) {
+		echo 'values'.$id.'['.$z.'] = new Array();';
+		echo 'labels'.$id.'.push({label:\''.$labels[$z].'\'});';
+	}
+	for ($j = 0; $j < count($ticks); $j++) {
+		for ($z = 0; $z < count($values); $z++) {
+			if ($values[$z][$j] > $yMax) {
+				$yMax = $values[$z][$j];
+			}
+			echo 'values'.$id.'['.$z.'].push('.$values[$z][$j].');';
+		}
+		echo 'ticks'.$id.'.push(\''.$ticks[$j].'\');';
+	}
+	for ($z = 0; $z < count($values); $z++) {
+		echo 'series'.$id.'.push(values'.$id.'['.$z.']);';
+	}
+	$height = 40+50*count($ticks);
+	
+	echo 'jQuery(document).ready(function(){
+			plot'.$id.' = jQuery.jqplot (\'chart'.$id.'\', series'.$id.', {
+				height: '.$height.',
+				axesDefaults: {
+					tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
+					tickOptions: {
+						angle: 0,
+						fontSize: \'8px\',
+						showGridline: false,
+						showMark: false,
+					},
+					pad: 0
+				},
+				seriesDefaults: {
+					showMarker: false,
+					lineWidth: 1,
+					fill: true,
+					renderer:jQuery.jqplot.BarRenderer,
+					rendererOptions: {
+						barDirection: \'horizontal\',
+						fillToZero: true
+					}
+				},
+				legend: {
+					show:true, location: \'ne\'
+				},
+				series:
+					labels'.$id.'
+				,
+				axes: {
+					xaxis: {
+						max: '.++$yMax.',
+						min: 0,
+						tickOptions: {
+							angle: 0,
+							showMark: true,
+							formatString: \'%d\'
+						}
+					},
+					yaxis: {
+						renderer: jQuery.jqplot.CategoryAxisRenderer,
+						ticks: ticks'.$id.'
+					},
+				},
+				highlighter: {
+					show: true,
+					sizeAdjust: 2.5,
+					showTooltip: true,
+					tooltipAxes: \'x\',
+					tooltipLocation: \'ne\'
+				},
+			});
+		});';
+	echo 'jQuery(window).resize(function() {
+		plot'.$id.'.replot();
+	});'."\n";
+	echo '//]]></script>';
+	echo '<div id="chart'.$id.'"></div>';
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/pm/reporting/index.php b/src/www/pm/reporting/index.php
index 4d1d035..a16972f 100644
--- a/src/www/pm/reporting/index.php
+++ b/src/www/pm/reporting/index.php
@@ -32,6 +32,7 @@ require_once $gfcommon.'pm/ProjectCategory.class.php';
 require_once $gfwww.'project/stats/project_stats_utils.php';
 require_once $gfwww.'include/tool_reports.php';
 require_once $gfwww.'include/HTML_Graphs.php';
+require_once $gfcommon.'reporting/report_utils.php';
 
 
 if (!session_loggedin()) {
@@ -77,6 +78,10 @@ function pm_quick_report($group_id,$title,$subtitle1,$qpa1,$subtitle2,$qpa2,$com
 	pm_footer(array());
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
 
 $what = getStringFromRequest('what');
 if ($what) {
@@ -97,7 +102,6 @@ if ($what) {
 		pm_reporting_header($group_id);
 
 		$time_now=time();
-//		echo $time_now."<p>";
 
 		if (!$period || $period=="lifespan") {
 			$period="month";
@@ -108,8 +112,12 @@ if ($what) {
 			$span=1;
 		}
 		$sub_duration=period2seconds($period,1);
-//		echo $sub_duration,"<br />";
 
+		$values = array();
+		$labels = array();
+		$labels[0] = _('Average duration for closed tasks (days)');
+		$labels[1] = _('Number of started tasks');
+		
 		for ($counter=1; $counter<=$span; $counter++) {
 
 			$start=($time_now-($counter*$sub_duration));
@@ -119,23 +127,33 @@ if ($what) {
 				break;
 			}
 
-			$result = db_query_params ('SELECT avg((end_date-start_date)/(24*60*60))
-FROM project_task,project_group_list
-WHERE end_date > 0
-AND (start_date >= $1 AND start_date <= $2)
-AND project_task.status_id=2
-AND project_group_list.group_project_id=project_task.group_project_id
-AND project_group_list.group_id=$3 ',
-			array($start,
-				$end,
-				$group_id));
-
-			$names[$counter-1]=date("Y-m-d",($start))." to ".date("Y-m-d",($end));
-			$values[$counter-1]=((int)(db_result($result, 0,0)*1000))/1000;
+			$resAvgClosedTask = db_query_params ('SELECT avg((end_date-start_date)/(24*60*60))
+								FROM project_task,project_group_list
+								WHERE end_date > 0
+								AND (start_date >= $1 AND start_date <= $2)
+								AND project_task.status_id=2
+								AND project_group_list.group_project_id=project_task.group_project_id
+								AND project_group_list.group_id=$3 ',
+								array($start, $end, $group_id));
+				
+			$resStartTasks = db_query_params ('SELECT count(*)
+								FROM project_task,project_group_list
+								WHERE start_date >= $1
+								AND start_date <= $2
+								AND project_group_list.group_project_id=project_task.group_project_id
+								AND project_group_list.group_id=$3 ',
+								array($start, $end, $group_id));
+
+			$ticks[$counter-1] = date("Y-m-d", ($start))." to ".date("Y-m-d",($end));
+			$values[0][$counter-1] = ((int)(db_result($resAvgClosedTask, 0, 0)*1000))/1000;
+			$values[1][$counter-1] = (int)db_result($resStartTasks, 0, 0);
 		}
 
-		GraphIt($names, $values, _('Average duration for closed tasks (days)'));
+		report_pm_hbar(1, $values, $ticks, $labels);
 
+		$values = array();
+		$labels = array();
+		$ticks = array();
 		for ($counter=1; $counter<=$span; $counter++) {
 
 			$start=($time_now-($counter*$sub_duration));
@@ -144,47 +162,21 @@ AND project_group_list.group_id=$3 ',
 			if ($end < $g->getStartDate()) {
 				break;
 			}
-			
-			$result = db_query_params ('SELECT count(*)
-FROM project_task,project_group_list
-WHERE start_date >= $1
-AND start_date <= $2
-AND project_group_list.group_project_id=project_task.group_project_id
-AND project_group_list.group_id=$3 ',
-			array($start,
-				$end,
-				$group_id));
-
-			$names[$counter-1]=date("Y-m-d",($start))." to ".date("Y-m-d",($end));
-			$values[$counter-1]=db_result($result, 0,0);
-		}
-
-		GraphIt($names, $values, _('Number of started tasks'));
-
-		for ($counter=1; $counter<=$span; $counter++) {
-
-			$start=($time_now-($counter*$sub_duration));
-			$end=($time_now-(($counter-1)*$sub_duration));
 
-			if ($end < $g->getStartDate()) {
-				break;
-			}
+			$resNotCompleted = db_query_params ('SELECT count(*)
+								FROM project_task,project_group_list
+								WHERE start_date <= $1
+								AND (end_date >= $2 OR end_date < 1 OR end_date is null)
+								AND project_group_list.group_project_id=project_task.group_project_id
+								AND project_group_list.group_id=$3 ',
+								array($end, $end, $group_id));
 
-			$result = db_query_params ('SELECT count(*)
-FROM project_task,project_group_list
-WHERE start_date <= $1
-AND (end_date >= $2 OR end_date < 1 OR end_date is null)
-AND project_group_list.group_project_id=project_task.group_project_id
-AND project_group_list.group_id=$3 ',
-			array($end,
-				$end,
-				$group_id));
-
-			$names[$counter-1]=date("Y-m-d",($end));
-			$values[$counter-1]=db_result($result, 0,0);
+			$ticks[$counter-1]=date("Y-m-d",($end));
+			$values[0][$counter-1]=db_result($resNotCompleted, 0,0);
 		}
 
-		GraphIt($names, $values, _('Number of tasks still not completed'));
+		$labels[] = _('Number of tasks still not completed');
+		report_pm_hbar(2, $values, $ticks, $labels);
 
 		pm_footer(array());
 

commit 1530ea3da8fb72ca16c174889c442147d86dcb47
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 5 16:08:03 2013 +0200

    jqplot: implement survey graphs

diff --git a/src/www/survey/admin/graphs.php b/src/www/survey/admin/graphs.php
deleted file mode 100644
index fbf3b09..0000000
--- a/src/www/survey/admin/graphs.php
+++ /dev/null
@@ -1,128 +0,0 @@
-<?php
-/**
- * FusionForge Survey HTML Facility
- * General Graph showing module for Survey
- *
- * Copyright 2010 (c) FusionForge Team
- * http://fusionforge.org/
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/*
- * This script produces PNG image which shows graph of SCM metrics
- */
-
-/**
- * Expecting data
- *  @ legend[] - array of legends
- *  @ value[]  - array of values
- *  @ type - grap type. We support pie and vertical bar graph (pie, vbar)
- *  @ width
- *  @ hight
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-
-// Check if we have jpgraph
-if (!file_exists(forge_get_config('jpgraph_path').'/jpgraph.php')) {
-    //# TODO: Need to show the message as a image file
-    exit_error(_('Package JPGraph not installed'),'surveys');
-}
-
-// Read jPGraph libraries.
-require_once forge_get_config('jpgraph_path').'/jpgraph.php';
-require_once forge_get_config('jpgraph_path').'/jpgraph_line.php';
-require_once forge_get_config('jpgraph_path').'/jpgraph_bar.php';
-require_once forge_get_config('jpgraph_path').'/jpgraph_pie.php';
-require_once forge_get_config('jpgraph_path').'/jpgraph_pie3d.php';
-
-$type = getStringFromRequest('type');
-$legend = getStringFromRequest('legend');
-$value = getStringFromRequest('value');
-
-if ($type=='pie') {
-    ShowPie($legend, $value);
-} else {
-    ShowHBar($legend, $value);
-}
-
-/**
- * Show 3D Pie graph
- */
-function ShowPie(&$legend, &$value) {
-
-    $graph = new PieGraph(330,200,"auto");
-    $graph->SetFrame(false);
-    //$graph->title->Set("A simple 3D Pie plot");
-    //$graph->title->SetFont(FF_FONT1,FS_BOLD);
-
-    $p1 = new PiePlot3D($value);
-    $p1->ExplodeSlice(1);
-    $p1->SetCenter(0.45);
-    $p1->SetLegends($legend);
-    $graph->legend->SetPos(0.01,0.01,'right','top');
-
-    $graph->Add($p1);
-    $graph->Stroke();
-}
-
-
-/**
- * Show Horizontal Bar graph
- */
-function ShowHBar(&$legend, &$value) {
-
-    $height=50+count($value)*18;
-    $width=500;
-
-    // Set the basic parameters of the graph
-    $graph = new Graph($width,$height,'auto');
-
-    $graph->SetScale("textlin");
-    $top = 30;
-    $bottom = 20;
-    $left = 100;
-    $right = 50;
-    $graph->Set90AndMargin($left,$right,$top,$bottom);
-    $graph->xaxis->SetTickLabels($legend);
-    $graph->SetFrame(false);
-
-    // Label align for X-axis
-    $graph->xaxis->SetLabelAlign('right','center','right');
-
-    // Label align for Y-axis
-    $graph->yaxis->SetLabelAlign('center','bottom');
-
-    // Create a bar pot
-    $bplot = new BarPlot($value);
-    $bplot->SetFillColor("orange");
-    $bplot->SetWidth(0.5);
-    // We want to display the value of each bar at the top
-    $graph->yaxis->scale->SetGrace(10);
-    $graph->yaxis->SetLabelAlign('center','bottom');
-    $graph->yaxis->SetLabelFormat('%d');
-
-    $bplot->value->Show();
-    $bplot->value->SetFormat('%.d votes');
-    // Setup color for gradient fill style
-    $bplot->SetFillGradient("navy","lightsteelblue",GRAD_MIDVER);
-
-    $graph->Add($bplot);
-
-    $graph->Stroke();
-}
diff --git a/src/www/survey/admin/show_results.php b/src/www/survey/admin/show_results.php
index c0ca08c..be4020d 100644
--- a/src/www/survey/admin/show_results.php
+++ b/src/www/survey/admin/show_results.php
@@ -5,6 +5,7 @@
  * Copyright 1999-2001 (c) VA Linux Systems
  * Copyright 2002-2004 (c) GForge Team
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -52,6 +53,12 @@ if (!$g || !is_object($g) || $g->isError()) {
 $is_admin_page='y';
 $sh = new  SurveyHtml();
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginPie();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
+
 $title = _('Survey Results');
 $sh->header(array('title' => $title, 'modal' => 1));
 
diff --git a/src/www/survey/include/SurveyHTML.class.php b/src/www/survey/include/SurveyHTML.class.php
index c1917d6..8178e3d 100644
--- a/src/www/survey/include/SurveyHTML.class.php
+++ b/src/www/survey/include/SurveyHTML.class.php
@@ -6,6 +6,7 @@
  * The rest Copyright 2002-2004 (c) GForge Team - Sung Kim
  * Copyright 2008-2010 (c) FusionForge Team
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -597,14 +598,12 @@ class SurveyHTML extends Error {
 			$results[0] =  $votes - $results[1] - $results[2] - $results[3] - $results[4] - $results[5];
 
 			if ($show_graph) {
-				$url ='graphs.php?type=vbar';
 				for ($j=5; $j>=0; $j--) {
 					$percent = sprintf("%02.1f%%", (float)$results[$j]*100/$votes);
-
-					$url.='&legend[]='.urlencode($arr_name[$j].' ('. $percent.')');
-					$url.='&value[]='.urlencode($results[$j]);
+					$legendArr[] = $arr_name[$j].' ('. $percent.')';
+					$valuesArr[] = $results[$j];
 				}
-				$ret.= '<img src="'.$url.'" alt="Graph of '.$Question->getQuestion().'"></img>';
+				$ret.= $this->drawGraph($Question->getID(), 'hbar', $legendArr, $valuesArr);
 			} else {
 				$ret.= '<table style="padding-left: 3em" width="100%">';
 
@@ -627,12 +626,11 @@ class SurveyHTML extends Error {
 			$res[3] =  $votes - $res[1] -$res[2];
 
 			if ($show_graph) {
-				$url ='graphs.php?type=pie';
 				for ($j=1; $j<=3; $j++) {
-					$url.='&legend[]='.urlencode($arr_name[$j].'('.$res[$j].')');
-					$url.='&value[]='.urlencode($res[$j]);
+					$legendArr[] = $arr_name[$j].'('.$res[$j].')';
+					$valuesArr[] = $res[$j];
 				}
-				$ret.= '<img src="'.$url.'" alt="Graph of '.$Question->getQuestion().'"></img>';
+				$ret.= $this->drawGraph($Question->getID(), 'pie', $legendArr, $valuesArr);
 			} else {
 				$ret.= '<table style="padding-left: 3em" width="100%">';
 				for ($j=1; $j<=3; $j++) {
@@ -727,6 +725,105 @@ class SurveyHTML extends Error {
 
 		return $ret;
 	}
+	
+	function drawGraph($id, $graphType, $legend, $values) {
+		switch($graphType) {
+			case 'pie': {
+				$ret = '<script type="text/javascript">//<![CDATA['."\n";
+				$ret .= 'var data'.$id.' = new Array();';
+				$ret .= 'var plot'.$id.';';
+				for ($i = 0; $i < count($values); $i++) {
+					$ret .= 'data'.$id.'.push([\''.htmlentities($legend[$i]).'\','.$values[$i].']);';
+				}
+				$ret .= 'jQuery(document).ready(function(){
+						plot'.$id.' = jQuery.jqplot (\'chart'.$id.'\', [data'.$id.'],
+						{
+							seriesDefaults: {
+								renderer: jQuery.jqplot.PieRenderer,
+								rendererOptions: {
+									showDataLabels: true,
+									dataLabels: \'percent\',
+								}
+							},
+							legend: {
+								show:true, location: \'e\',
+							},
+						});
+					});';
+				$ret .= 'jQuery(window).resize(function() {
+						plot'.$id.'.replot( { resetAxes: true } );
+					});'."\n";
+				$ret .= '//]]></script>';
+				$ret .= '<div id="chart'.$id.'"></div>';
+				break;
+			}
+			default: {
+				$ret = '<script type="text/javascript">//<![CDATA['."\n";
+				$ret .= 'var data'.$id.' = new Array();';
+				$ret .= 'var ticks'.$id.' = new Array();';
+				$ret .= 'var plot'.$id.';';
+				$yMax = 0;
+				for ($i = 0; $i < count($values); $i++) {
+					$ret .= 'data'.$id.'.push(['.$values[$i].']);';
+					if ($yMax < $values[$i]) {
+						$yMax = $values[$i];
+					}
+					$ret .= 'ticks'.$id.'.push([\''.htmlentities($legend[$i]).'\']);';
+				}
+				$ret .= 'jQuery(document).ready(function(){
+						plot'.$id.' = jQuery.jqplot (\'chart'.$id.'\', data'.$id.', 
+						{
+							axesDefaults: {
+								tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
+								tickOptions: {
+									angle: 90,
+									fontSize: \'8px\',
+									showGridline: false,
+									showMark: false,
+								},
+								pad: 0,
+							},
+							seriesDefaults: {
+								showMarker: false,
+								lineWidth: 1,
+								fill: true,
+								renderer:jQuery.jqplot.BarRenderer,
+								rendererOptions: {
+									fillToZero: true,
+								},
+							},
+							axes: {
+								xaxis: {
+									renderer: jQuery.jqplot.CategoryAxisRenderer,
+									ticks: ticks'.$id.',
+								},
+								yaxis: {
+									max: '.++$yMax.',
+									min: 0,
+									tickOptions: {
+										angle: 0,
+										showMark: true,
+										formatString: \'%d\'
+									}
+								},
+							},
+							highlighter: {
+								show: true,
+								sizeAdjust: 2.5,
+								showTooltip: true,
+								tooltipAxes: \'y\',
+							},
+						});
+					});';
+				$ret .= 'jQuery(window).resize(function() {
+						plot'.$id.'.replot( { resetAxes: true } );
+					});'."\n";
+				$ret .= '//]]></script>';
+				$ret .= '<div id="chart'.$id.'"></div>';
+			}
+		}
+		return $ret;
+	}
 }
 
 // Local Variables:

commit fb3c4b0962dcabc8b2abcf254e3e2d92cd3d7f3c
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 5 15:02:05 2013 +0200

    jqplot: same display for pie graph

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 50ee637..6031f32 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -965,6 +965,7 @@ function report_toolspiegraph($datatype = 0, $start, $end) {
 						rendererOptions: {
 							showDataLabels: true,
 							dataLabels: \'percent\',
+							sliceMargin: 5
 						}
 					},
 					legend: {

commit 19fadcfcc299eefb6469da253cb27beab5f45c91
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 5 14:20:30 2013 +0200

    Revert "survey: delete unused file"
    
    This reverts commit 88a442c1a65f7a36374ce6fcd0b365228d392418.

diff --git a/src/www/survey/admin/graphs.php b/src/www/survey/admin/graphs.php
new file mode 100644
index 0000000..fbf3b09
--- /dev/null
+++ b/src/www/survey/admin/graphs.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * FusionForge Survey HTML Facility
+ * General Graph showing module for Survey
+ *
+ * Copyright 2010 (c) FusionForge Team
+ * http://fusionforge.org/
+ *
+ * This file is part of FusionForge. FusionForge is free software;
+ * you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or (at your option)
+ * any later version.
+ *
+ * FusionForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FusionForge; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * This script produces PNG image which shows graph of SCM metrics
+ */
+
+/**
+ * Expecting data
+ *  @ legend[] - array of legends
+ *  @ value[]  - array of values
+ *  @ type - grap type. We support pie and vertical bar graph (pie, vbar)
+ *  @ width
+ *  @ hight
+ */
+
+require_once '../../env.inc.php';
+require_once $gfcommon.'include/pre.php';
+
+// Check if we have jpgraph
+if (!file_exists(forge_get_config('jpgraph_path').'/jpgraph.php')) {
+    //# TODO: Need to show the message as a image file
+    exit_error(_('Package JPGraph not installed'),'surveys');
+}
+
+// Read jPGraph libraries.
+require_once forge_get_config('jpgraph_path').'/jpgraph.php';
+require_once forge_get_config('jpgraph_path').'/jpgraph_line.php';
+require_once forge_get_config('jpgraph_path').'/jpgraph_bar.php';
+require_once forge_get_config('jpgraph_path').'/jpgraph_pie.php';
+require_once forge_get_config('jpgraph_path').'/jpgraph_pie3d.php';
+
+$type = getStringFromRequest('type');
+$legend = getStringFromRequest('legend');
+$value = getStringFromRequest('value');
+
+if ($type=='pie') {
+    ShowPie($legend, $value);
+} else {
+    ShowHBar($legend, $value);
+}
+
+/**
+ * Show 3D Pie graph
+ */
+function ShowPie(&$legend, &$value) {
+
+    $graph = new PieGraph(330,200,"auto");
+    $graph->SetFrame(false);
+    //$graph->title->Set("A simple 3D Pie plot");
+    //$graph->title->SetFont(FF_FONT1,FS_BOLD);
+
+    $p1 = new PiePlot3D($value);
+    $p1->ExplodeSlice(1);
+    $p1->SetCenter(0.45);
+    $p1->SetLegends($legend);
+    $graph->legend->SetPos(0.01,0.01,'right','top');
+
+    $graph->Add($p1);
+    $graph->Stroke();
+}
+
+
+/**
+ * Show Horizontal Bar graph
+ */
+function ShowHBar(&$legend, &$value) {
+
+    $height=50+count($value)*18;
+    $width=500;
+
+    // Set the basic parameters of the graph
+    $graph = new Graph($width,$height,'auto');
+
+    $graph->SetScale("textlin");
+    $top = 30;
+    $bottom = 20;
+    $left = 100;
+    $right = 50;
+    $graph->Set90AndMargin($left,$right,$top,$bottom);
+    $graph->xaxis->SetTickLabels($legend);
+    $graph->SetFrame(false);
+
+    // Label align for X-axis
+    $graph->xaxis->SetLabelAlign('right','center','right');
+
+    // Label align for Y-axis
+    $graph->yaxis->SetLabelAlign('center','bottom');
+
+    // Create a bar pot
+    $bplot = new BarPlot($value);
+    $bplot->SetFillColor("orange");
+    $bplot->SetWidth(0.5);
+    // We want to display the value of each bar at the top
+    $graph->yaxis->scale->SetGrace(10);
+    $graph->yaxis->SetLabelAlign('center','bottom');
+    $graph->yaxis->SetLabelFormat('%d');
+
+    $bplot->value->Show();
+    $bplot->value->SetFormat('%.d votes');
+    // Setup color for gradient fill style
+    $bplot->SetFillGradient("navy","lightsteelblue",GRAD_MIDVER);
+
+    $graph->Add($bplot);
+
+    $graph->Stroke();
+}

commit fc21f7406c94eae0000c1dd4ff7ee9d9dfb840d5
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 5 14:14:22 2013 +0200

    survey: delete unused file

diff --git a/src/www/survey/admin/graphs.php b/src/www/survey/admin/graphs.php
deleted file mode 100644
index fbf3b09..0000000
--- a/src/www/survey/admin/graphs.php
+++ /dev/null
@@ -1,128 +0,0 @@
-<?php
-/**
- * FusionForge Survey HTML Facility
- * General Graph showing module for Survey
- *
- * Copyright 2010 (c) FusionForge Team
- * http://fusionforge.org/
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/*
- * This script produces PNG image which shows graph of SCM metrics
- */
-
-/**
- * Expecting data
- *  @ legend[] - array of legends
- *  @ value[]  - array of values
- *  @ type - grap type. We support pie and vertical bar graph (pie, vbar)
- *  @ width
- *  @ hight
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-
-// Check if we have jpgraph
-if (!file_exists(forge_get_config('jpgraph_path').'/jpgraph.php')) {
-    //# TODO: Need to show the message as a image file
-    exit_error(_('Package JPGraph not installed'),'surveys');
-}
-
-// Read jPGraph libraries.
-require_once forge_get_config('jpgraph_path').'/jpgraph.php';
-require_once forge_get_config('jpgraph_path').'/jpgraph_line.php';
-require_once forge_get_config('jpgraph_path').'/jpgraph_bar.php';
-require_once forge_get_config('jpgraph_path').'/jpgraph_pie.php';
-require_once forge_get_config('jpgraph_path').'/jpgraph_pie3d.php';
-
-$type = getStringFromRequest('type');
-$legend = getStringFromRequest('legend');
-$value = getStringFromRequest('value');
-
-if ($type=='pie') {
-    ShowPie($legend, $value);
-} else {
-    ShowHBar($legend, $value);
-}
-
-/**
- * Show 3D Pie graph
- */
-function ShowPie(&$legend, &$value) {
-
-    $graph = new PieGraph(330,200,"auto");
-    $graph->SetFrame(false);
-    //$graph->title->Set("A simple 3D Pie plot");
-    //$graph->title->SetFont(FF_FONT1,FS_BOLD);
-
-    $p1 = new PiePlot3D($value);
-    $p1->ExplodeSlice(1);
-    $p1->SetCenter(0.45);
-    $p1->SetLegends($legend);
-    $graph->legend->SetPos(0.01,0.01,'right','top');
-
-    $graph->Add($p1);
-    $graph->Stroke();
-}
-
-
-/**
- * Show Horizontal Bar graph
- */
-function ShowHBar(&$legend, &$value) {
-
-    $height=50+count($value)*18;
-    $width=500;
-
-    // Set the basic parameters of the graph
-    $graph = new Graph($width,$height,'auto');
-
-    $graph->SetScale("textlin");
-    $top = 30;
-    $bottom = 20;
-    $left = 100;
-    $right = 50;
-    $graph->Set90AndMargin($left,$right,$top,$bottom);
-    $graph->xaxis->SetTickLabels($legend);
-    $graph->SetFrame(false);
-
-    // Label align for X-axis
-    $graph->xaxis->SetLabelAlign('right','center','right');
-
-    // Label align for Y-axis
-    $graph->yaxis->SetLabelAlign('center','bottom');
-
-    // Create a bar pot
-    $bplot = new BarPlot($value);
-    $bplot->SetFillColor("orange");
-    $bplot->SetWidth(0.5);
-    // We want to display the value of each bar at the top
-    $graph->yaxis->scale->SetGrace(10);
-    $graph->yaxis->SetLabelAlign('center','bottom');
-    $graph->yaxis->SetLabelFormat('%d');
-
-    $bplot->value->Show();
-    $bplot->value->SetFormat('%.d votes');
-    // Setup color for gradient fill style
-    $bplot->SetFillGradient("navy","lightsteelblue",GRAD_MIDVER);
-
-    $graph->Add($bplot);
-
-    $graph->Stroke();
-}

commit f51ecfec852ab36ef8608515b2bcef0b5d707ebb
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jul 5 10:57:38 2013 +0200

    jqplot: fix scm history. use startdate or first data in db

diff --git a/src/www/scm/include/scm_utils.php b/src/www/scm/include/scm_utils.php
index 8dd5802..2bfe2b6 100644
--- a/src/www/scm/include/scm_utils.php
+++ b/src/www/scm/include/scm_utils.php
@@ -76,21 +76,6 @@ function scm_footer() {
 function commitstime_graph($group_id, $chartid) {
 	$g = group_get_object($group_id);
 	$end = time();
-	$start = $g->getStartDate();
-	$monthsArr[] = date('Ym', $start);
-	$timeStampArr[] = mktime(0, 0, 0, substr($monthsArr[0], 4, 2) , 1, substr($monthsArr[0], 0, 4));
-	$i = 0;
-	while($start < $end) {
-		$start = strtotime(date('Y-m-d', $start).' +1 month');
-		$i++;
-		$monthsArr[$i] = date('Ym', $start);
-		$timeStampArr[$i] = mktime(0, 0, 0, substr($monthsArr[$i], 4, 2) , 1, substr($monthsArr[$i], 0, 4));
-		if ($monthsArr[$i] == date('Ym', strtotime(date('Y-m-d', $end).' +1 month'))) {
-			array_pop($monthsArr);
-			array_pop($timeStampArr);
-			$i--;
-		}
-	}
 	$res = db_query_params ('SELECT month, sum(commits) AS count
 				FROM stats_cvs_group
 				WHERE group_id = $1
@@ -104,9 +89,32 @@ function commitstime_graph($group_id, $chartid) {
 	echo '<script type="text/javascript">//<![CDATA['."\n";
 	echo 'var values = new Array();';
 
+	$firstDateInDB = 0;
 	$data = array();
 	while ($row = db_fetch_array($res)) {
 		$data[$row[0]] = $row[1];
+		if (!$firstDateInDB)
+			$firstDateInDB = $row[0];
+	}
+	
+	$start = $g->getStartDate();
+	$monthsArr[] = date('Ym', $start);
+	if ( $firstDateInDB < $monthsArr[0] ) {
+		$monthsArr[0] = $firstDateInDB;
+		$start = mktime(0, 0, 0, substr($monthsArr[0], 4, 2) , 1, substr($monthsArr[0], 0, 4));
+	}
+	$timeStampArr[] = mktime(0, 0, 0, substr($monthsArr[0], 4, 2) , 1, substr($monthsArr[0], 0, 4));
+	$i = 0;
+	while($start < $end) {
+		$start = strtotime(date('Y-m-d', $start).' +1 month');
+		$i++;
+		$monthsArr[$i] = date('Ym', $start);
+		$timeStampArr[$i] = mktime(0, 0, 0, substr($monthsArr[$i], 4, 2) , 1, substr($monthsArr[$i], 0, 4));
+		if ($monthsArr[$i] == date('Ym', strtotime(date('Y-m-d', $end).' +1 month'))) {
+			array_pop($monthsArr);
+			array_pop($timeStampArr);
+			$i--;
+		}
 	}
 
 	$yMax = 0;

commit 513794c52889d407676df3dd5536e3eec300b082
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jun 30 13:05:16 2013 +0200

    report: fix gmt as default tz

diff --git a/src/common/reporting/Report.class.php b/src/common/reporting/Report.class.php
index 87e958a..fa98264 100644
--- a/src/common/reporting/Report.class.php
+++ b/src/common/reporting/Report.class.php
@@ -57,6 +57,7 @@ function Report() {
 	//	All reporting action will be done in GMT timezone
 	//
 	putenv('TZ=GMT');
+	date_default_timezone_set('GMT');
 }
 
 /**

commit 001a3f5a442d4acf5b1bb7385906fa95568d93b5
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jun 30 12:59:24 2013 +0200

    project stat: fix permission check

diff --git a/src/www/project/stats/index.php b/src/www/project/stats/index.php
index 923e6ee..27150d9 100644
--- a/src/www/project/stats/index.php
+++ b/src/www/project/stats/index.php
@@ -37,6 +37,8 @@ if ( !$group_id ) {
 	exit_no_group();
 }
 
+session_require_perm('project_admin', $group_id);
+
 $group = group_get_object($group_id);
 if (!$group || !is_object($group)) {
     exit_no_group();
@@ -57,8 +59,8 @@ $end = getIntFromRequest('end');
 /*
  * Set the start date to birth of the project.
  */
-$res=db_query_params('SELECT register_time FROM groups WHERE group_id=$1', array($group_id));
-$report->site_start_date=db_result($res,0,'register_time');
+$res = db_query_params('SELECT register_time FROM groups WHERE group_id=$1', array($group_id));
+$report->site_start_date = db_result($res,0,'register_time');
 
 if (!$start || !$end) $z =& $report->getMonthStartArr();
 

commit 00d70bdcf746e995c04a3ba7890a573e05282d8f
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sat Jun 29 23:47:20 2013 +0200

    jqplot: wrap legend option, fix legend data

diff --git a/src/www/scm/include/scm_utils.php b/src/www/scm/include/scm_utils.php
index b8b0531..8dd5802 100644
--- a/src/www/scm/include/scm_utils.php
+++ b/src/www/scm/include/scm_utils.php
@@ -205,7 +205,7 @@ function commits_graph($group_id, $days, $chartid) {
 		echo '<script type="text/javascript">//<![CDATA['."\n";
 		echo 'var data'.$chartid.' = new Array();';
 		while ($row = db_fetch_array($res)) {
-			echo 'data'.$chartid.'.push([\''.htmlentities($row[0]).'\','.$row[1].']);';
+			echo 'data'.$chartid.'.push([\''.htmlentities($row[0]).' ('.$row[1].')\','.$row[1].']);';
 		}
 		echo 'var plot'.$chartid.';';
 		echo 'jQuery(document).ready(function(){
@@ -217,10 +217,12 @@ function commits_graph($group_id, $days, $chartid) {
 						rendererOptions: {
 							showDataLabels: true,
 							dataLabels: \'percent\',
+							sliceMargin: 5
 						}
 					},
 					legend: {
-						show:true, location: \'e\',
+						show:true,
+						location: \'e\'
 					},
 				}
 				);

commit 66c818698b777685adcb8c91d595671f2768aafe
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sat Jun 29 18:39:55 2013 +0200

    jqplot: fix scm pie, tooltip and y axe format

diff --git a/src/www/scm/include/scm_utils.php b/src/www/scm/include/scm_utils.php
index f0cbc21..b8b0531 100644
--- a/src/www/scm/include/scm_utils.php
+++ b/src/www/scm/include/scm_utils.php
@@ -162,6 +162,7 @@ function commitstime_graph($group_id, $chartid) {
 						tickOptions: {
 							angle: 0,
 							showMark: true,
+							formatString: \'%d\'
 						}
 					}
 				},
@@ -169,7 +170,7 @@ function commitstime_graph($group_id, $chartid) {
 					show: true,
 					sizeAdjust: 2.5,
 					showTooltip: true,
-					tooltipAxes: \'y\',
+					tooltipAxes: \'y\'
 				},
 			});
 		});';
@@ -204,7 +205,7 @@ function commits_graph($group_id, $days, $chartid) {
 		echo '<script type="text/javascript">//<![CDATA['."\n";
 		echo 'var data'.$chartid.' = new Array();';
 		while ($row = db_fetch_array($res)) {
-			echo 'data'.$chartid.'.push([\''.htmlentities($row[0]).'\',\''.$row[1].'\']);';
+			echo 'data'.$chartid.'.push([\''.htmlentities($row[0]).'\','.$row[1].']);';
 		}
 		echo 'var plot'.$chartid.';';
 		echo 'jQuery(document).ready(function(){

commit b921895f4b8276776ba1ced08943ec7e9bb80ac2
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sat Jun 29 18:27:36 2013 +0200

    jqplot: fix highlighter

diff --git a/src/www/stats/site_stats_utils.php b/src/www/stats/site_stats_utils.php
index 11d8ec8..764d5f3 100644
--- a/src/www/stats/site_stats_utils.php
+++ b/src/www/stats/site_stats_utils.php
@@ -519,6 +519,7 @@ function views_graph($monthly = 0) {
 		$ydata[$i] = $row['site_views'] + $row['subdomain_views'];
 		++$i;
 	}
+
 	$monthStartArr = $report->getMonthStartArr();
 	$monthStartArrFormat = $report->getMonthStartArrFormat();
 	if (count($ydata)) {
@@ -561,6 +562,8 @@ function views_graph($monthly = 0) {
 					highlighter: {
 						show: true,
 						sizeAdjust: 2.5,
+						showTooltip: true,
+						tooltipAxes: \'y\',
 					},
 				});
 			});';

commit 3f6109b8b2fc08c7ebd02809f44a3da20d7e06fd
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sat Jun 29 18:11:28 2013 +0200

    jqplot: fix y value, fix highlight, fix loop on date

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 0450c67..50ee637 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -350,6 +350,7 @@ function trackeract_graph($group_id, $area, $SPAN, $start, $end, $atid) {
 					tickOptions: {
 						angle: 0,
 						showMark: true,
+						formatString: \'%d\'
 					}
 				},
 			},
@@ -573,12 +574,15 @@ function report_graph($type, $SPAN, $start, $end) {
 					min: 0,
 					tickOptions: {
 						angle: 0,
+						formatString: \'%d\'
 					},
 				}
 			},
 			highlighter: {
 				show: true,
 				sizeAdjust: 2.5,
+				showTooltip: true,
+				tooltipAxes: \'y\',
 			},
 		});
 	});';
@@ -648,12 +652,14 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 		$timeStampArr = $report->getMonthStartArr();
 		$formatDate = 'Y/m';
 	}
-	
-	for ($j = 0; $j < count($timeStampArr); $j++) {
+
+	$initialSizeOfTimeStampArr = count($timeStampArr);
+	for ($j = 0; $j < $initialSizeOfTimeStampArr; $j++) {
 		if ($timeStampArr[$j] < $start || $timeStampArr[$j] >= $end) {
 			unset($timeStampArr[$j]);
 		}
 	}
+
 	$timeStampArr = array_values($timeStampArr);
 	for ($j = 0; $j < count($timeStampArr); $j++) {
 		$tickArr[] = date($formatDate, $timeStampArr[$j]);
@@ -820,8 +826,9 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', series, {
 				title : \''.utf8_decode($areaname).' ( '.strftime('%x', $start).' - '.strftime('%x', $end).') \',
 				axesDefaults: {
+					tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
 					tickOptions: {
-						angle: -90,
+						angle: 90,
 						fontSize: \'8px\',
 						showGridline: false,
 						showMark: false,
@@ -854,12 +861,15 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 						tickOptions: {
 							angle: 0,
 							showMark: true,
+							formatString: \'%d\'
 						}
 					},
 				},
 				highlighter: {
 					show: true,
 					sizeAdjust: 2.5,
+					showTooltip: true,
+					tooltipAxes: \'y\',
 				},
 			});
 		});';
@@ -951,11 +961,8 @@ function report_toolspiegraph($datatype = 0, $start, $end) {
 				{
 					title : \''.$arr[$datatype].' ('.strftime('%x', $start) .' - '. strftime('%x', $end) .')\',
 					seriesDefaults: {
-						// Make this a pie chart.
 						renderer: jQuery.jqplot.PieRenderer,
 						rendererOptions: {
-							// Put data labels on the pie slices.
-							// By default, labels show the percentage of the slice.
 							showDataLabels: true,
 							dataLabels: \'percent\',
 						}
@@ -1018,11 +1025,8 @@ function report_timegraph($type = 'site', $area = 'tasks', $start, $end, $id = 0
 				{
 					title : \''.$arr[$area].' ('.strftime('%x', $start) .' - '. strftime('%x', $end) .')\',
 					seriesDefaults: {
-						// Make this a pie chart.
 						renderer: jQuery.jqplot.PieRenderer,
 						rendererOptions: {
-							// Put data labels on the pie slices.
-							// By default, labels show the percentage of the slice.
 							showDataLabels: true,
 							dataLabels: \'percent\',
 						}
@@ -1089,8 +1093,9 @@ function report_sitetimebargraph($start, $end) {
 				plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', series, {
 					title : \''.utf8_decode($areaname).' ( '.strftime('%x', $start).' - '.strftime('%x', $end).') \',
 					axesDefaults: {
+						tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
 						tickOptions: {
-							angle: -90,
+							angle: 90,
 							fontSize: \'8px\',
 							showGridline: false,
 							showMark: false,
@@ -1123,12 +1128,15 @@ function report_sitetimebargraph($start, $end) {
 							tickOptions: {
 								angle: 0,
 								showMark: true,
+								formatString: \'%d\'
 							}
 						},
 					},
 					highlighter: {
 						show: true,
 						sizeAdjust: 2.5,
+						showTooltip: true,
+						tooltipAxes: \'y\',
 					},
 				});
 			});';
diff --git a/src/www/scm/include/scm_utils.php b/src/www/scm/include/scm_utils.php
index c835366..f0cbc21 100644
--- a/src/www/scm/include/scm_utils.php
+++ b/src/www/scm/include/scm_utils.php
@@ -132,7 +132,7 @@ function commitstime_graph($group_id, $chartid) {
 				axesDefaults: {
 					tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
 					tickOptions: {
-						angle: -90,
+						angle: 90,
 						fontSize: \'8px\',
 						showGridline: false,
 						showMark: false,
@@ -168,6 +168,8 @@ function commitstime_graph($group_id, $chartid) {
 				highlighter: {
 					show: true,
 					sizeAdjust: 2.5,
+					showTooltip: true,
+					tooltipAxes: \'y\',
 				},
 			});
 		});';
@@ -210,11 +212,8 @@ function commits_graph($group_id, $days, $chartid) {
 				{
 					title : \''.utf8_decode(_("Commits By User")." (".strftime('%x',$start) ." - ". strftime('%x',$end) .")").'\',
 					seriesDefaults: {
-						// Make this a pie chart.
 						renderer: jQuery.jqplot.PieRenderer,
 						rendererOptions: {
-							// Put data labels on the pie slices.
-							// By default, labels show the percentage of the slice.
 							showDataLabels: true,
 							dataLabels: \'percent\',
 						}

commit 96a4b875c0e1852bed04445a887c5b959d4e446d
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 28 15:27:06 2013 +0200

    jqplot: missing dot

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index d3ff9b0..0450c67 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -457,7 +457,7 @@ function report_graph($type, $SPAN, $start, $end) {
 	}
 	$rdates = $report->getRawDates();
 	if (!$rdates) {
-		echo '<p class="error">'._('No data to display').'</p>';
+		echo '<p class="error">'._('No data to display.').'</p>';
 		return false;
 	}
 	$ydata[0]  = $report->getData();
@@ -626,7 +626,7 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 	}
 	$rdates = $report->getRawDates();
 	if (!$rdates) {
-		echo '<p class="error">'._('No data to display').'</p>';
+		echo '<p class="error">'._('No data to display.').'</p>';
 		return false;
 	}
 	if (!$SPAN)

commit b09d0bfc0df81d1909e5bb78ee4c14591b147164
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 28 15:05:58 2013 +0200

    stats_function.php: remove unused file

diff --git a/src/www/include/stats_function.php b/src/www/include/stats_function.php
deleted file mode 100644
index d212ab6..0000000
--- a/src/www/include/stats_function.php
+++ /dev/null
@@ -1,185 +0,0 @@
-<?php
-/**
- *
- * Copyright 1999-2001 (c) VA Linux Systems
- * Copyright 2010, FusionForge Team
- * Copyright (C) 2010 Alain Peyrat - Alcatel-Lucent
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once $gfwww.'include/HTML_Graphs.php';
-
-/**
- * stats_sf_stats() - Get SourceForge stats
- */
-function stats_sf_stats() {
-/*
-	pages/day
-*/
-	$result = db_query_params ('SELECT * FROM stats_agg_pages_by_day',
-				   array ());
-	$rows = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		echo '<p class="error">Stats Problem'.db_error().'</p>';
-	} else {
-		$j=0;
-		for ($i=0; $i<$rows; $i++) {
-			//echo $i." - ".($i%7)."<br />";
-			if ($i % 7 == 0) {
-				//echo $i."<br />";
-				//increment the new weekly array
-				//and set the beginning date for this week
-				$j++;
-				$name_string[$j]=db_result($result,$i,'day');
-				$vals[$j]=0;
-			}
-			//add today to the week
-                        $vals[$j] += db_result($result,$i,'count');
-		}
-		$j++;
-		$vals[$j]='';
-		$name_string[$j]='';
-		GraphIt($name_string,$vals,'Page Views By Week');
-	}
-
-/*
-	Projects added by week
-*/
-	$result = db_query_params ('select (round((register_time/604800),0)*604800) AS time ,count(*) from groups group by time',
-				   array ());
-	$rows = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		echo '<p class="error">Stats Problem'.db_error().'</p>';
-	} else {
-		$count=array();
-		$dates=array();
-		$count=util_result_column_to_array($result,1);
-
-		for ($i=0;$i<$rows;$i++) {
-			//convert the dates and add to an array
-			$dates[$i]=date(_('Y-m-d H:i'),db_result($result,$i,0));
-		}
-		GraphIt($dates,$count,'New Projects Added Each Week');
-	}
-
-/*
-	Users added by week
-*/
-	$result = db_query_params ('select (round((add_date/604800),0)*604800) AS time ,count(*) from users group by time',
-				   array ());
-	$rows = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		echo '<p class="error">Stats Problem'.db_error().'</p>';
-	} else {
-		$count=array();
-		$dates=array();
-		$count=util_result_column_to_array($result,1);
-
-		for ($i=0;$i<$rows;$i++) {
-			//convert the dates and add to an array
-			$dates[$i]=date(_('Y-m-d H:i'),db_result($result,$i,0));
-		}
-		GraphIt($dates,$count,'New Users Added Each Week');
-	}
-
-}
-
-
-/**
- * stats_project_stats() - Get project stats
- */
-function stats_project_stats() {
-/*
-	logo impressions/day
-*/
-
-	$result = db_query_params ('SELECT * FROM stats_agg_logo_by_day',
-				   array ());
-	$rows = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		echo '<p class="error">Stats Problem'.db_error().'</p>';
-	} else {
-		GraphResult($result,'Logo Showings By Day');
-	}
-
-/*
-	logo impressions/group
-*/
-
-	$result = db_query_params ('SELECT group_id,sum(count) as count FROM stats_agg_logo_by_group GROUP BY group_id',
-				   array ());
-	$rows = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		echo '<p class="error">Stats Problem'.db_error().'</p>';
-	} else {
-		GraphResult($result,'Logo Showings By Project');
-	}
-}
-
-
-/**
- * stats_browser_stats() - Get browser stats
- */
-function stats_browser_stats() {
-/*
-	Browser
-*/
-
-	$result = db_query_params ('SELECT * FROM stats_agg_pages_by_browser',
-				   array ());
-	$rows = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		echo '<p class="error">Stats Problem'.db_error().'</p>';
-	} else {
-		GraphResult($result,'Page Views By Browser');
-	}
-
-/*
-	Platform
-*/
-
-	$result = db_query_params ('SELECT * FROM stats_agg_pages_by_platform',
-				   array ());
-	$rows = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		echo '<p class="error">Stats Problem'.db_error().'</p>';
-	} else {
-		GraphResult($result,'Page Views By Platform');
-	}
-
-/*
-	Browser/ver
-*/
-
-	$result = db_query_params ('SELECT * FROM stats_agg_pages_by_plat_brow_ver',
-				   array ());
-	$rows = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		echo '<p class="error">Stats Problem'.db_error().'</p>';
-	} else {
-		ShowResultSet($result,'Page Views By Platform/Browser Version');
-	}
-}

commit 27ff0144e8322f5190d62da70184bc6170443a8d
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 28 15:00:40 2013 +0200

    graph_lib.php remove unused file

diff --git a/src/www/include/graph_lib.php b/src/www/include/graph_lib.php
deleted file mode 100644
index 4ab5a6e..0000000
--- a/src/www/include/graph_lib.php
+++ /dev/null
@@ -1,679 +0,0 @@
-<?php
-/**
- * Graphing class
- *
- * Copyright 1999-2001 (c) VA Linux Systems
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-class Graph {
-	/**
-	 * x coordinate title
-	 *
-	 * @var		string		$xtitle
-	 */
-	var $xtitle;
-
-	/**
-	 * y coordinate title
-	 *
-	 * @var		string	$ytitle
-	 */
-	var $ytitle;
-
-	/**
-	 * @var		?	$im
-	 */
-	var $im;
-
-	/**
-	 * @var		string	$color
-	 */
-	var $color;
-
-	/**
-	 * x coordinate minimum
-	 *
-	 * @var		int		$xmin
-	 */
-	var $xmin;
-
-	/**
-	 * x coordinate maximum
-	 *
-	 * @var		int		$xmax
-	 */
-	var $xmax;
-
-	/**
-	 * y coordinate minimum
-	 *
-	 * @var		int		$ymin
-	 */
-	var $ymin;
-
-	/**
-	 * y coordinate maximum
-	 *
-	 * @var		int		$ymax
-	 */
-	var $ymax;
-
-	/**
-	 * x coordinate data diff
-	 *
-	 * @var		?		$xdata_diff
-	 */
-	var $xdata_diff;
-
-	/**
-	 * y coordinate data diff
-	 *
-	 * @var		?		$ydata_diff
-	 */
-	var $ydata_diff;
-
-	/**
-	 * Overall graph height
-	 *
-	 * @var		int		$graph_height
-	 */
-	var $graph_height;
-
-	/**
-	 * Overall graph width
-	 *
-	 * @var		int		$graph_width
-	 */
-	var $graph_width;
-
-	/**
-	 * x coordinate pad
-	 *
-	 * @var		?		$xpad
-	 */
-	var $xpad;
-
-	/**
-	 * y coordinate pad
-	 *
-	 * @var		?		$ypad
-	 */
-	var $ypad;
-
-	/**
-	 * Image height
-	 *
-	 * @var		int		$image_height
-	 */
-	var $image_height;
-
-	/**
-	 * Image width
-	 *
-	 * @var		int		$image_width
-	 */
-	var $image_width;
-
-	/**
-	 * Data set
-	 *
-	 * @var		?		$data_set
-	 */
-	var $data_set;
-
-	/**
-	 *  Number of data sets
-	 *
-	 * @var		int		$num_data_sets
-	 */
-	var $num_data_sets;
-
-	/**
-	 * Number of points
-	 *
-	 * @var		int		$num_points
-	 */
-	var $num_points;
-
-	/**
-	 * Debug string
-	 *
-	 * @var		string $strDebug
-	 */
-	var $strDebug;
-
-	/**
-	 * Graph() - Constructor
-	 *
-	 * The function constructor sets up the basic vars needed to draw a graph.
-	 * It sets up the geometry for the graph
-	 * as well as any data extents that need to be set.
-	 *
-	 * @param	int		Width of the graph
-	 * @param	int		Height of the graph
-	 */
-	function Graph( $width = 640, $height = 480 ) {
-
-		$this->xpad = 50;
-		$this->ypad = 40;
-
-		$this->graph_height = $height - (2 * $this->ypad);
-		$this->graph_width  = $width  - (2 * $this->xpad);
-
-		$this->image_height = $height;
-		$this->image_width  = $width;
-
-		$this->im    = ImageCreate($this->image_width, $this->image_height);
-		$this->color = array();
-
-		$this->color['white']		= ImageColorAllocate($this->im,255,255,255);
-		$this->color['black']		= ImageColorAllocate($this->im,0,0,0);
-		$this->color['red']		= ImageColorAllocate($this->im,180,0,0);
-		$this->color['darkred']		= ImageColorAllocate($this->im,120,0,0);
-		$this->color['green']		= ImageColorAllocate($this->im,0,180,0);
-		$this->color['darkgreen']	= ImageColorAllocate($this->im,0,120,0);
-		$this->color['blue']		= ImageColorAllocate($this->im,0,0,180);
-		$this->color['darkblue']	= ImageColorAllocate($this->im,0,0,120);
-		$this->color['gray']		= ImageColorAllocate($this->im,180,180,180);
-		$this->color['darkgray']	= ImageColorAllocate($this->im,64,64,64);
-		$this->color['magenta']		= ImageColorAllocate($this->im,240,0,240);
-		$this->color['darkmagenta']	= ImageColorAllocate($this->im,180,0,180);
-
-	} // function Graph Constructor
-
-
-	/**
-	 * SetPad() - Redefines the x and y padding distances on the object.
-	 *
-	 * @param	int		The x distance on either side reserved for markings.
-	 * @param	int		The y distance on the top and bottom reserved for markings.
-	 */
-	function SetPads( $xpad = 50, $ypad = 40 ) {
-		$this->xpad = $xpad;
-		$this->ypad = $ypad;
-
-		$this->graph_height = $this->image_height - (2 * $this->ypad);
-		$this->graph_width  = $this->image_width  - (2 * $this->xpad);
-	}
-
-	/**
-	 * AddData() - Adds an array of prefetched data to this object.
-	 *
-	 * @param	string	The x data to add
-	 * @param	string	The y data to add
-	 * @param	string	The x label to add
-	 */
-	function AddData( $xdata, $ydata, $xlabel = 0 ) {
-		$this->num_data_sets++;
-		//asort( $xdata );
-		$i = 0;
-
-		$this->strDebug[] = "Adding dataset " . $this->num_data_sets . " "
-					. ($xlabel ? "with a label" : "without a label") . " to the datasets.";
-
-		while (list($index,$val) = each($xdata)) {
-			$this->data_set[$this->num_data_sets]['x'][$i] = $xdata[$index];
-			$this->data_set[$this->num_data_sets]['y'][$i] = $ydata[$index];
-
-			if ( $xlabel ) {
-				$this->data_set[$this->num_data_sets]['xlabel'][$i] = $xlabel[$index];
-			} else {
-				$this->data_set[$this->num_data_sets]['xlabel'][$i] = $xdata[$index];
-			}
-			++$i;
-		}
-
-		$this->num_points[$this->num_data_sets] = min(sizeof($xdata),sizeof($ydata));
-
-		if ($this->num_data_sets == 1) {
-			$this->xmax = max($xdata);
-			$this->xmin = min($xdata);
-			$this->ymax = max($ydata);
-			$this->ymin = (min($ydata) < 0) ? min($ydata) : 0;
-		} else {
-			$tmp_xmax = max($xdata);
-			$tmp_xmin = min($xdata);
-			$tmp_ymax = max($ydata);
-			$tmp_ymin = min($ydata);
-
-			$this->xmax = max($this->xmax,$tmp_xmax);
-			$this->xmin = min($this->xmin,$tmp_xmin);
-			$this->ymax = max($this->ymax,$tmp_ymax);
-			$this->ymin = (min($this->ymin,$tmp_ymin) < 0 ) ? min($this->ymin,$tmp_ymin) : 0;
-		}
-
-		$this->xdata_diff = (($this->xmax) - ($this->xmin));
-		$this->ydata_diff = (($this->ymax) - ($this->ymin));
-
-		return $this->num_data_sets;
-
-	} // function AddData
-
-
-	/**
-	 * translate() - Translate shifts the $x and $y arguments from points in the world space to
-	 * pixels in graph plane space.
-	 *
-	 * @param	int		The x position in world coordinates
-	 * @param	int		The y position in world coordinates
-	 * @param	int		The x position in screen pixels
-	 * @param	int		The y position in screen pixels
-	 */
-	function translate( &$x, &$y, &$xpos, &$ypos ) {
-		$xpos = $this->xdata_diff ? ($this->graph_width / $this->xdata_diff) * ($x - $this->xmin) + $this->xpad : 0 + $this->xpad;
-		$ypos = $this->ydata_diff ? ((($this->ymax - $y) / $this->ydata_diff) * $this->graph_height) + $this->ypad : 0 + $this->ypad;
-	}
-
-
-	/**
-	 * adjustNum() - Makes a number better for axis spacing.
-	 * Instead of having something like .12452314 it should be closer to .12 for presentability
-	 *
-	 * @param	int		This is the number you want to adjust
-	 * @param	int		This is the total range of values that are spanned by this axis
-	 * @param	int		How many divisions will there be?
-	 */
-	function adjustNum ( $num, $data_diff, $num_divisions ) {
-
-		$data_diff = abs($data_diff);
-		$adjusted  = $data_diff / $num_divisions;
-
-		if ( $num == 0 ) {
-
-			return $num;
-
-		} elseif ($adjusted >= 1) {
-
-			$decimals = strlen(floor($adjusted)."") - 1;
-			$divisor  = pow(10,$decimals);
-			$num      = floor($num / $divisor) * $divisor;
-
-		} else {
-
-			list($zero,$adjusted) = explode(".",$adjusted);
-			$decimals = strlen(floor(1/$num) . "") + 1;
-			$divisor  = pow(10,$decimals);
-			$num      = round($num * $divisor) / $divisor;
-
-		}
-
-		return $num;
-
-	} // function adjustNum
-
-
-	/**
-	 * DrawLine() - Draws a line with point value inputs.
-	 * This translates the input coordinates into screen space and draws a line
-	 *
-	 * @param	int		The first point's x coordinate (in the world coordinate view)
-	 * @param	int		The first point's y coordinate (in the world coordinate view)
-	 * @param	int		The second point's x coordinate (in the world coordinate view)
-	 * @param	int		The second point's y coordinate (in the world coordinate view)
-	 * @param	string	The color to draw the line
-	 */
-	function DrawLine ( $x1, $y1, $x2, $y2, $color ) {
-
-		$this->translate( $x1, $y1, $x1pos, $y1pos );
-		$this->translate( $x2, $y2, $x2pos, $y2pos );
-
-		ImageLine( $this->im, $x1pos, $y1pos, $x2pos, $y2pos, $color );
-	}
-
-
-
-
-	/**
-	 * DrawFilledPolygon() - Is a wrapper to the imageFilledPolygon GD function.
-	 *
-	 * @param	array	The vertices for the polygon
-	 * @param	string	The color you want the polygon to be
-	 */
-	function DrawFilledPolygon ( $verts, $color ) {
-
-		for ( $i = 0; $i < sizeof($verts); $i++ ) {
-			$this->translate( $verts[$i], $verts[$i+1], $verts[$i], $verts[++$i] );
-		}
-
-		imageFilledPolygon( $this->im, $verts, (sizeof($verts) / 2), $color );
-	}
-
-
-	/**
-	 * DrawShadowedPolygon() - Is a wrapper to the imageFilledPolygon GD function that
-	 * first creates a drop shadow.
-	 *
-	 * @param	array	The vertices for the polygon
-	 * @param	string	The color you want the polygon to be
-	 */
-	function DrawShadowedPolygon ( $verts, $color, $color ) {
-
-		for ( $i = 0; $i < sizeof($verts); $i++ ) {
-			$this->translate( $verts[$i], $verts[$i+1], $verts[$i], $verts[++$i] );
-		}
-
-		imageFilledPolygon( $this->im, $verts, (sizeof($verts) / 2), $color );
-	}
-
-
-	/**
-	 * DrawDashedLine() - Draws a dashed line from the start coordinate to the end coordinate
-	 *
-	 * @param	int		The first point's x coordinate (in the world coordinate view)
-	 * @param	int		The first point's y coordinate (in the world coordinate view)
-	 * @param	int		The second point's x coordinate (in the world coordinate view)
-	 * @param	int		The second point's y coordinate (in the world coordinate view)
-	 * @param	int		The length of a dash on the dashed line
-	 * @param	int		The length of a space in the dashed line
-	 * @param	string	The line color
-	 */
-	function DrawDashedLine ($x1,$y1,$x2,$y2,$dash_length,$dash_space,$color) {
-
-		$this->translate($x1,$y1,$x1pos,$y1pos);
-		$this->translate($x2,$y2,$x2pos,$y2pos);
-
-		// Get the length of the line in pixels
-		$line_length = ceil( sqrt( pow(($x2pos - $x1pos),2) + pow(($y2pos - $y1pos),2) ) );
-
-		$cosTheta = $line_length ? ($x2pos - $x1pos) / $line_length : 0;
-		$sinTheta = $line_length ? ($y2pos - $y1pos) / $line_length : 0;
-		$lastx    = $x1pos;
-		$lasty    = $y1pos;
-
-		   // Let's draw the dashed line
-		   // for as we go along the length of the line
-		for ( $i = 0; $i < $line_length; $i += ($dash_length + $dash_space) ) {
-			$xpos = ($dash_length * $cosTheta) + $lastx;
-			$ypos = ($dash_length * $sinTheta) + $lasty;
-
-			ImageLine( $this->im, $lastx, $lasty, $xpos, $ypos, $color );
-			$lastx = $xpos + ($dash_space * $cosTheta);
-			$lasty = $ypos + ($dash_space * $sinTheta);
-		}
-	}
-
-	/**
-	 * DrawGrid() - Draws the grid lines for the graph
-	 *
-	 * @param	string	The color to draw the grid lines in.
-	 */
-	function DrawGrid( $color ) {
-
-		$color    = $this->color[$color];
-		$numGrid  = 10;
-		$xNum     = $this->graph_width  / 30;
-		$yNum     = $this->graph_height / 30;
-
-
-		   // If we have a NULL data set, assume some sane defaults.
-		if ( $this->ydata_diff == 0 ) {
-			$this->ydata_diff = 10;
-			$this->ymax = $this->ymin + 10;
-		}
-
-		$numxGrid = min($numGrid, $xNum);
-		$xTick    = $this->adjustNum( ($this->xdata_diff / $numxGrid), $this->xdata_diff, $numxGrid );
-		$xStart = floor($this->xmin / $xTick);
-		$xEnd   = ceil(($this->xmax ? $this->xmax : 0) / $xTick);
-
-		$numyGrid = min($numGrid, $yNum);
-		$yTick    = $this->adjustNum( ($this->ydata_diff / $numyGrid), $this->ydata_diff, $numyGrid );
-		$yStart = floor($this->ymin / $yTick);
-		$yEnd   = ceil(($this->ymax ? $this->ymax : 0) / $yTick);
-
-		$this->strDebug[] = "";
-		$this->strDebug[] = "xNum = $xNum  numxGrid = $numxGrid  xTick = $xTick xStart = $xStart xEnd = $xEnd ";
-		$this->strDebug[] = "yNum = $yNum  numyGrid = $numyGrid  yTick = $yTick yStart = $yStart yEnd = $yEnd ";
-		$this->strDebug[] = "xdata_diff = $this->xdata_diff  ydata_diff = $this->ydata_diff";
-
-		  // make sure that our scale always fits nicely.
-		$this->ymin = ( $yStart * $yTick );
-		$this->ymax = ( $yEnd * $yTick );
-		$this->ydata_diff = ( $this->ymax - $this->ymin );
-
-		   // Draw the vertical grid lines
-		for ( $gridCount = $xStart; $gridCount <= $xEnd; $gridCount++ ) {
-			$gridx = $gridCount * $xTick;
-
-			$this->DrawDashedLine($gridx, $this->ymin, $gridx, $this->ymax, 2, 3, $color);
-
-			   // world $gridx,$ymin  -> graph $x0 $y0
-			$this->translate($gridx,$this->ymin,$x0,$y0);
-			ImageLine  ($this->im,$x0,$y0 + 3,$x0,$y0 - 3,$this->color['black']);
-			$gridx = $this->data_set[1]['xlabel'][$gridx];
-			ImageString($this->im,1,$x0 - 2.5 * strlen($gridx),$y0 + 6,$gridx,$this->color['black']);
-		}
-
-		   // Draw the horizontal grid lines
-		for ( $gridCount = $yStart; $gridCount <= $yEnd; $gridCount++ ) {
-			$gridy = $gridCount * $yTick;
-
-			if ( $gridy == 0 ) {
-				$this->DrawLine( $this->xmin, $gridy, $this->xmax, $gridy, $color );
-			} else {
-				$this->DrawDashedLine( $this->xmin, $gridy, $this->xmax, $gridy, 2, 3, $color );
-			}
-
-			$this->translate($this->xmin,$gridy,$x0,$y0);
-			ImageLine( $this->im, $x0 - 3, $y0, $x0 + 3, $y0, $this->color['black'] );
-			ImageString( $this->im, 1, $x0 - 5 * strlen($gridy) - 3, $y0 - 4, $gridy, $this->color['black'] );
-		}
-	} // function DrawGrid
-
-
-	/**
-	 * DrawAxis() - Draws the x-axis and the y-axis for the graph
-	 */
-	function DrawAxis() {
-		$this->DrawLine($this->xmin,$this->ymin,$this->xmax,$this->ymin,$this->color['black']);
-		$this->DrawLine($this->xmin,$this->ymin,$this->xmin,$this->ymax,$this->color['black']);
-	} // function DrawAxis
-
-
-	/**
-	 * LineGraph() - Draws a line graph from the data set that gets passed in.
-	 * This takes in 2 arrays and loops until the end of the smallest one.
-	 *
-	 * @param	string	The dataset
-	 * @param	string	The line color
-	 */
-	function LineGraph ($dataset,$color) {
-
-		$color = $this->color[$color];
-
-		$lastx = $this->data_set[$dataset]['x'][0];
-		$lasty = $this->data_set[$dataset]['y'][0];
-
-		for ($i = 1; $i < $this->num_points[$dataset]; ++$i) {
-			$this->DrawLine($lastx, $lasty, $this->data_set[$dataset]['x'][$i], $this->data_set[$dataset]['y'][$i], $color);
-			$lastx = $this->data_set[$dataset]['x'][$i];
-			$lasty = $this->data_set[$dataset]['y'][$i];
-		}
-
-	} // function LineGraph
-
-
-	/**
-	 * FilledLineGraph() - Draws a filled line graph for the data.
-	 *
-	 * @param	array	The array of x-data.
-	 * @param	array	The array of y-data.
-	 * @param	string	The color you want the graph drawn.
-	 */
-	function FilledLineGraph( $dataset, $color, $colortwo = 0 ) {
-
-		$color = $this->color[$color];
-		$lastx = $this->data_set[$dataset]['x'][0];
-		$lasty = $this->data_set[$dataset]['y'][0];
-
-		// $this->strDebug[] = "lastx: $lastx, lasty: $lasty";
-
-		for ($i = 1; $i < $this->num_points[$dataset]; ++$i) {
-			$verts[0] = $lastx;
-			$verts[1] = $lasty;
-			$verts[2] = $this->data_set[$dataset]['x'][$i];
-			$verts[3] = $this->data_set[$dataset]['y'][$i];
-			$verts[4] = $this->data_set[$dataset]['x'][$i];
-			$verts[5] = $this->ymin;
-			$verts[6] = $lastx;
-			$verts[7] = $this->ymin;
-
-			$lastx = $this->data_set[$dataset]['x'][$i];
-			$lasty = $this->data_set[$dataset]['y'][$i];
-
-			if ( $colortwo ) {
-				$this->DrawShadowedPolygon( $verts, $color, $colortwo);
-			} else {
-				$this->DrawFilledPolygon( $verts, $color );
-			}
-		}
-
-	} // function FilledLineGraph
-
-
-	/**
-	 * addDebug() - Allows the appending of debug information to the graph from the calling script
-	 */
-	function addDebug( $message ) {
-		$this->strDebug[] = $message;
-	}
-
-
-	/**
-	 * showDebug() - Shows debugging text on the graph in case you want to show data on the graph that never usually gets output.
-	 */
-	function showDebug() {
-		$lines = 0;
-
-		while ( list($key,$str) = each($this->strDebug) ) {
-			$lpad = $span = 0;
-			for ( $i = 0; $i < strlen($str); $i += $span )  {
-				$span = ($this->image_width - (($this->xpad * 2) + 5 + ($lpad ? 20 : 0))) / 5;
-				ImageString( $this->im, 1,
-					$this->xpad + 5 + ($lpad++ ? 20 : 0),
-					$this->ypad + 5 + ($lines++ * 13),
-					substr( $str, $i, $span ),
-					$this->color['red'] );
-			}
-		}
-
-	}
-
-
-	/**
-	 * SetTitle() - Draws a title on the graph.
-	 *
-	 * @param	string	The title of the graph.
-	 */
-	function SetTitle($title) {
-
-		$text_left = ($this->image_width / 2) - (strlen($title) * 2.7);
-		ImageString($this->im,2,$text_left,5,$title,$this->color['black']);
-
-	}
-
-
-	/**
-	 * SetSubTitle() - Draws a sub title on the graph in smaller text below the main title.
-	 *
-	 * @param	string	The title of the graph.
-	 */
-	function SetSubTitle($subtitle) {
-		$text_left = ($this->image_width / 2) - (strlen($subtitle) * 2.4);
-		ImageString($this->im,1,$text_left,25,$subtitle,$this->color['black']);
-	}
-
-
-	/**
-	 * SetxTitle() - Sets a title below the x-axis.
-	 */
-	function SetxTitle($xtitle) {
-		$text_left = ($this->image_width / 2) - (strlen($xtitle) * 2.4);
-		ImageString($this->im,1,$text_left,($this->image_height - $this->ypad + 20),$xtitle,$this->color['black']);
-	}
-
-
-	/**
-	 * SetyTitle() - Sets a title to the left of the y-axis.
-	 */
-	function SetyTitle($ytitle) {
-		$text_left = 10;
-		$text_top  = ($this->image_height / 2) + (strlen($ytitle) * 2.4);
-		ImageStringUp($this->im,1,$text_left,$text_top,$ytitle,$this->color['black']);
-	}
-
-
-	/**
-	 * ShowGraph() - Sets the header type and displays the graph.
-	 */
-	function ShowGraph( $type = "png" ) {
-
-		if ( $type == "gif" ) {
-
-			header("Content-Type:image/gif");
-			ImageGIF($this->im);
-
-		} elseif ( $type == "jpeg" ) {
-
-			header("Content-Type:image/jpeg");
-			ImageJPEG($this->im);
-
-		} else {
-
-			header("Content-Type:image/png");
-			ImagePNG($this->im);
-		}
-
-		ImageDestroy($this->im);
-	}
-
-} // class Graph
-
-
-//
-//  EXAMPLE CODE;
-//
-/*
-for ($i = 0; $i <= 100; ++$i) {
-	$x[] = $i;
-	$xlabel[] = "Value $i";
-	$y[] = (pow($i,3) - (170 * sin($i / 15)) * pow($i,2) - 5 * $i + 40000) / 43247823 ;
-	$y2[] = (sin($i/10) / 100) - .007;
-}
-
-$graph = new Graph;
-$graph->InitGraph(500,500);
-
-$data1 = $graph->AddData($x,$y, $xlabel );
-$data2 = $graph->AddData($x,$y2, $xlabel );
-
-$graph->SetTitle('Sweet Ass Graphs');
-$graph->SetSubTitle('A selection of mathematical functiond for your pleasure.');
-$graph->SetxTitle('Counted data');
-$graph->SetyTitle('Some foo data');
-$graph->DrawGrid('gray');
-
-$graph->FilledLineGraph($data1,'red');
-$graph->LineGraph($data2,'magenta');
-
-$graph->DrawAxis();
-$graph->showDebug();
-$graph->ShowGraph();
-
-*/

commit d1377a369d4821f061f1d55aa5d29faf03903086
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 28 14:47:59 2013 +0200

    pm: fix warning

diff --git a/src/common/pm/ProjectTask.class.php b/src/common/pm/ProjectTask.class.php
index 9d356da..b02a727 100644
--- a/src/common/pm/ProjectTask.class.php
+++ b/src/common/pm/ProjectTask.class.php
@@ -7,6 +7,7 @@
  * Copyright 2009, Roland Mas
  * Copyright 2010, Alain Peyrat - Alcatel-Lucent
  * Copyright 2011, Thorsten Glaser <t.glaser at tarent.de>
+ * Copyright 2013, Franck Villaume - TrivialDev
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -807,7 +808,7 @@ class ProjectTask extends Error {
 	function &convertDependentOn($arr) {
 		$deps = $this->getDependentOn();
 		for ($i=0; $i<count($arr); $i++) {
-			if ($deps[$arr[$i]]) {
+			if (isset($deps[$arr[$i]])) {
 				//use existing link_type if it exists
 				$new[$arr[$i]]=$deps[$arr[$i]];
 			} else {

commit 2e4e74bbb4a06f14955d8a3e7d18b974aa439f32
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 28 14:37:59 2013 +0200

    jqplot: delete jpgraph code

diff --git a/src/www/project/stats/index.php b/src/www/project/stats/index.php
index 6d06096..923e6ee 100644
--- a/src/www/project/stats/index.php
+++ b/src/www/project/stats/index.php
@@ -115,9 +115,6 @@ if ($start == $end) {
 	}
 }
 ?>
-<noscript>
-<img src="/reporting/projectact_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&g_id=$group_id&area=$area"; ?>" width="640" height="480" alt="stats graph" />
-</noscript>
 </p>
 </div>
 <?php
diff --git a/src/www/reporting/groupadded.php b/src/www/reporting/groupadded.php
index 37459f4..a28e2eb 100644
--- a/src/www/reporting/groupadded.php
+++ b/src/www/reporting/groupadded.php
@@ -70,12 +70,7 @@ report_header(_('Projects Added'));
 </form>
 <?php if ($start != $end) { ?>
 	<p>
-	<?php
-		report_graph('groupadded', $SPAN, $start, $end);
-	?>
-	<noscript>
-	<img src="groupadded_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
-	</noscript>
+	<?php report_graph('groupadded', $SPAN, $start, $end); ?>
 	</p>
 <?php }
 
diff --git a/src/www/reporting/groupadded_graph.php b/src/www/reporting/groupadded_graph.php
deleted file mode 100644
index 75fb0c8..0000000
--- a/src/www/reporting/groupadded_graph.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportGroupAdded.class.php';
-
-session_require_global_perm ('forge_stats','read') ;
-
-$SPAN = getIntFromRequest('SPAN');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-//
-//	Create Report
-//
-$report=new ReportGroupAdded($SPAN,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage(),'');
-}
-
-// Some data
-$ydata  = $report->getData();
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-$graph->SetScale( "textlin");
-
-// Create the linear plot
-$lineplot =new LinePlot($ydata);
-$lineplot ->SetColor("black");
-$lineplot->SetFillColor("orange");
-
-// Add the plot to the graph
-$graph->Add( $lineplot);
-
-//$graph->SetMargin(10,10,25,10);
-$graph->title->Set("Projects Added ".$report->getSpanName()
-	." (".date('m/d/Y',$report->getStartDate()) ."-". date('m/d/Y',$report->getEndDate()) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval($report->getGraphInterval());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/groupcum.php b/src/www/reporting/groupcum.php
index 7ff4156..d735341 100644
--- a/src/www/reporting/groupcum.php
+++ b/src/www/reporting/groupcum.php
@@ -69,13 +69,8 @@ report_header(_('Cumulative Projects'));
 </tr></table>
 </form>
 <?php if ($start != $end) { ?>
-		<p>
-	<?php
-		report_graph('groupcumul', $SPAN, $start, $end);
-	?>
-	<noscript>
-	<img src="groupcum_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
-	</noscript>
+	<p>
+	<?php report_graph('groupcumul', $SPAN, $start, $end); ?>
 	</p>
 <?php }
 
diff --git a/src/www/reporting/groupcum_graph.php b/src/www/reporting/groupcum_graph.php
deleted file mode 100644
index 50dad51..0000000
--- a/src/www/reporting/groupcum_graph.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportGroupCum.class.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$SPAN = getIntFromRequest('SPAN');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-//
-//	Create Report
-//
-$report=new ReportGroupCum($SPAN,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-// Some data
-$ydata  = $report->getData();
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-$graph->SetScale( "textlin");
-
-// Create the linear plot
-$lineplot =new LinePlot($ydata);
-$lineplot ->SetColor("black");
-$lineplot->SetFillColor("orange");
-
-// Add the plot to the graph
-$graph->Add( $lineplot);
-
-//$graph->SetMargin(10,10,25,10);
-$graph->title->Set("Cumulative Projects ".$report->getSpanName()
-	." (".date('m/d/Y',$report->getStartDate()) ."-". date('m/d/Y',$report->getEndDate()) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval($report->getGraphInterval());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/projectact.php b/src/www/reporting/projectact.php
index 85986a2..acc0933 100644
--- a/src/www/reporting/projectact.php
+++ b/src/www/reporting/projectact.php
@@ -76,12 +76,7 @@ report_header(_('Project Activity'));
 </form>
 <?php if ($g_id && $start != $end) { ?>
 	<p>
-	<?php
-		report_actgraph('project', $SPAN, $start, $end, $g_id, $area);
-	?>
-	<noscript>
-	<img src="projectact_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&g_id=$g_id&area=$area"; ?>" alt="" />
-	</noscript>
+	<?php report_actgraph('project', $SPAN, $start, $end, $g_id, $area); ?>
 	</p>
 	<?php
 
diff --git a/src/www/reporting/projectact_graph.php b/src/www/reporting/projectact_graph.php
deleted file mode 100644
index 141d174..0000000
--- a/src/www/reporting/projectact_graph.php
+++ /dev/null
@@ -1,225 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportProjectAct.class.php';
-require_once $gfwww.'include/unicode.php';
-
-$area = getStringFromRequest('area');
-$SPAN = getIntFromRequest('SPAN', 1);
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-$g_id = getIntFromRequest('g_id');
-
-$area = util_ensure_value_in_set ($area, array ('tracker','forum','docman','taskman','downloads','pageviews')) ;
-
-//
-//	Create Report
-//
-$report=new ReportProjectAct($SPAN,$g_id,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-//
-// Get Project Object
-//
-$g = group_get_object($g_id);
-if (!$g || !is_object($g)) {
-	exit_no_group();
-} elseif ($g->isError()) {
-	exit_error($g->getErrorMessage(),'');
-}
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-$graph->SetScale( "textlin");
-//$graph->SetScale( "linlog");
-//$graph ->SetYScale("log");
-
-if ($area=='tracker') {
-
-	// Create the tracker open plot
-	$ydata  =& $report->getTrackerOpened();
-	$lineplot =new LinePlot($ydata);
-	$lineplot ->SetColor("black");
-	$graph->Add( $lineplot);
-
-	// Create the tracker close plot
-	$ydata2  =& $report->getTrackerClosed();
-	$lineplot2 =new LinePlot($ydata2);
-	$lineplot2 ->SetColor("blue");
-	$graph->Add( $lineplot2 );
-
-	//	Legends
-	$lineplot->SetLegend (convert_unicode(_('Tracker Items Opened')));
-	$lineplot2 ->SetLegend(convert_unicode(_('Tracker Items Closed')));
-
-} elseif ($area=='forum') {
-
-	// Create the forum plot
-	$ydata3  =& $report->getForum();
-	$lineplot3 =new LinePlot($ydata3);
-	$lineplot3 ->SetColor("orange");
-	$graph->Add( $lineplot3 );
-
-	//	Legends
-	$lineplot3 ->SetLegend("Forum");
-
-} elseif ($area=='docman') {
-
-	// Create the Docman plot
-	$ydata4  =& $report->getDocs();
-	$lineplot4 =new LinePlot($ydata4);
-	$lineplot4 ->SetColor("red");
-	$graph->Add( $lineplot4 );
-
-	//	Legends
-	$lineplot4 ->SetLegend(convert_unicode(_('Docs')));
-
-} elseif ($area=='downloads') {
-
-	// Create the Docman plot
-	$ydata4  =& $report->getDownloads();
-	$lineplot4 =new LinePlot($ydata4);
-	$lineplot4 ->SetColor("red");
-	$graph->Add( $lineplot4 );
-
-	//	Legends
-	$lineplot4 ->SetLegend(convert_unicode(_('Downloads')));
-
-} elseif ($area=='taskman') {
-
-	// Create the Tasks Opened plot
-	$ydata5  =& $report->getTaskOpened();
-	$lineplot5 =new LinePlot($ydata5);
-	$lineplot5 ->SetColor("purple");
-	$graph->Add( $lineplot5 );
-
-	// Create the Tasks Closed plot
-	$ydata6  =& $report->getTaskClosed();
-	$lineplot6 =new LinePlot($ydata6);
-	$lineplot6 ->SetColor("yellow");
-	$graph->Add( $lineplot6 );
-
-	//	Legends
-	$lineplot5 ->SetLegend(convert_unicode(_('Task Open')));
-	$lineplot6 ->SetLegend(convert_unicode(_('Task Close')));
-
-} elseif ($area=='pageviews') {
-
-	// Create the PageViews plot
-	$ydata4  =& $report->getPageViews();
-	$lineplot4 =new LinePlot($ydata4);
-	$lineplot4 ->SetColor("blue");
-	$graph->Add( $lineplot4 );
-
-	//	Legends
-	$lineplot4 ->SetLegend(convert_unicode(_('Page Views')));
-
-} else {
-	/*
- 	* The goal of this code is to get values from the activity hook to compute stats without the
- 	* need of another specific hook or another dedicated tables.
- 	*
- 	* So, values are requested to the hook and stored in $results array.
- 	* After, the sum is made according to the chosen interval
- 	* And then, the sum is stored in the ydata array.
-	*/
-
-	$results = array();
-	$ids = array();
-	$texts = array();
-
-	$hookParams['group'] = $g_id ;
-	$hookParams['results'] = &$results;
-	$hookParams['show'] = array();
-	$hookParams['begin'] = $start;
-	$hookParams['end'] = $end;
-	$hookParams['ids'] = &$ids;
-	$hookParams['texts'] = &$texts;
-	plugin_hook ("activity", $hookParams) ;
-
-	if ($SPAN == REPORT_TYPE_DAILY) {
-		$interval = REPORT_DAY_SPAN;
-	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
-		$interval = REPORT_WEEK_SPAN;
-	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
-		$interval = REPORT_MONTH_SPAN;
-	}
-
-//	print "start: $start ".date('r',$start)."<br>";
-//	print "  end: $end ".date('r', $end)."<br>";
-
-	$sum = array();
-	$starting_date = $start;
-	foreach ($results as $arr) {
-		$d = $arr['activity_date'];
-		$col = intval(($d - $starting_date)/$interval);
-		$col_date = $starting_date+$col*$interval;
-		$sum[$col_date]++;
-	}
-
-	// Now, stores the values in the ydata array for the graph.
-	$ydata = array();
-	$i = 0;
-	foreach ($report->getDates() as $d) {
-		$ydata[$i++] = isset($sum[strtotime($d)]) ? $sum[strtotime($d)] : 0;
-	}
-
-	$lineplot =new LinePlot($ydata);
-	$lineplot->SetColor("violet");
-	$graph->Add( $lineplot );
-
-	//	Legends
-	$lineplot->SetLegend($area);
-
-//	var_dump($report->getDates());
-//	var_dump($ydata);
-// 	exit;
-}
-
-
-//
-//	Titles
-//
-$graph->title->Set("Project Activity For: ".util_unconvert_htmlspecialchars($g->getPublicName()).
-	" (".date('Y-m-d',$report->getStartDate()) ." to ". date('Y-m-d',$report->getEndDate()) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval($report->getGraphInterval());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/projecttime.php b/src/www/reporting/projecttime.php
index 8acad6d..90500a0 100644
--- a/src/www/reporting/projecttime.php
+++ b/src/www/reporting/projecttime.php
@@ -3,6 +3,8 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
+ * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -101,12 +103,7 @@ $a2[]='user';
 
 	} elseif ($g_id && $start != $end) { ?>
 	<p>
-	<?php
-		report_timegraph('project', $type, $start, $end, $g_id);
-	?>
-	<noscript>
-	<img src="projecttime_graph.php?<?php echo "start=$start&end=$end&g_id=$g_id&type=$type"; ?>" alt="" />
-	</noscript>
+	<?php report_timegraph('project', $type, $start, $end, $g_id); ?>
 	</p>
 	<?php
 
diff --git a/src/www/reporting/projecttime_graph.php b/src/www/reporting/projecttime_graph.php
deleted file mode 100644
index c9626f2..0000000
--- a/src/www/reporting/projecttime_graph.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie3d.php');
-require_once $gfcommon.'reporting/ReportProjectTime.class.php';
-require_once $gfcommon.'reporting/report_utils.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$g_id = getIntFromRequest('g_id');
-$type = getStringFromRequest('type');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-//
-//	Create Report
-//
-$report=new ReportProjectTime($g_id,$type,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-// XXX ogi: Isn't it $type?
-if (!isset($datatype)) {
-	$datatype=1;
-}
-
-if (!$start) {
-	$start=mktime(0,0,0,date('m'),1,date('Y'));;
-}
-if (!$end) {
-	$end=time();
-} else {
-	$end--;
-}
-
-// Create the graph. These two calls are always required
-$graph  = new PieGraph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-
-$arr['tasks']='By Task';
-$arr['category']='By Category';
-$arr['subproject']='By Subproject';
-$arr['user']='By User';
-
-$graph->title->Set("Time Report ".$arr[$type]." (".date('m/d/Y',$start) ."-". date('m/d/Y',$end) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-
-report_pie_arr($report->labels,$report->getData());
-
-$p1  = new PiePlot3D( $pie_vals );
-$p1->ExplodeSlice (0);
-$p1->SetLegends( $pie_labels );
-$graph->Add( $p1);
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/siteact.php b/src/www/reporting/siteact.php
index 0b41395..e6068bd 100644
--- a/src/www/reporting/siteact.php
+++ b/src/www/reporting/siteact.php
@@ -76,12 +76,7 @@ report_header(_('Site-Wide Activity'));
 </form>
 <?php if ($area && $start != $end) { ?>
 	<p>
-	<?php
-		report_actgraph('sitewide', $SPAN, $start, $end, 0, $area);
-	?>
-	<noscript>
-	<img src="siteact_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&area=$area"; ?>" alt="" />
-	</noscript>
+	<?php report_actgraph('sitewide', $SPAN, $start, $end, 0, $area); ?>
 	</p>
 	<?php
 
diff --git a/src/www/reporting/siteact_graph.php b/src/www/reporting/siteact_graph.php
deleted file mode 100644
index 22172b4..0000000
--- a/src/www/reporting/siteact_graph.php
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportSiteAct.class.php';
-require_once $gfwww.'include/unicode.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$area = getFilteredStringFromRequest('area', '/^[a-z]+$/');
-$SPAN = getIntFromRequest('SPAN');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-//
-//	Create Report
-//
-$report=new ReportSiteAct($SPAN,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-$graph->SetScale( "textlin");
-//$graph->SetScale( "linlog");
-//$graph ->SetYScale("log");
-
-if ($area=='tracker') {
-
-	// Create the tracker open plot
-	$ydata  =& $report->getTrackerOpened();
-	$lineplot =new LinePlot($ydata);
-	$lineplot ->SetColor("black");
-	$graph->Add( $lineplot);
-
-	// Create the tracker close plot
-	$ydata2  =& $report->getTrackerClosed();
-	$lineplot2 =new LinePlot($ydata2);
-	$lineplot2 ->SetColor("blue");
-	$graph->Add( $lineplot2 );
-
-	//	Legends
-	$lineplot->SetLegend (convert_unicode(_('Tracker Items Opened')));
-	$lineplot2 ->SetLegend(convert_unicode(_('Tracker Items Closed')));
-
-} elseif ($area=='forum') {
-
-	// Create the forum plot
-	$ydata3  =& $report->getForum();
-	$lineplot3 =new LinePlot($ydata3);
-	$lineplot3 ->SetColor("orange");
-	$graph->Add( $lineplot3 );
-
-	//	Legends
-	$lineplot3 ->SetLegend("Forum");
-
-} elseif ($area=='docman') {
-
-	// Create the Docman plot
-	$ydata4  =& $report->getDocs();
-	$lineplot4 =new LinePlot($ydata4);
-	$lineplot4 ->SetColor("red");
-	$graph->Add( $lineplot4 );
-
-	//	Legends
-	$lineplot4 ->SetLegend("Docs");
-
-} elseif ($area=='taskman') {
-
-	// Create the Tasks Opened plot
-	$ydata5  =& $report->getTaskOpened();
-	$lineplot5 =new LinePlot($ydata5);
-	$lineplot5 ->SetColor("purple");
-	$graph->Add( $lineplot5 );
-
-	// Create the Tasks Closed plot
-	$ydata6  =& $report->getTaskClosed();
-	$lineplot6 =new LinePlot($ydata6);
-	$lineplot6 ->SetColor("yellow");
-	$graph->Add( $lineplot6 );
-
-	//	Legends
-	$lineplot5 ->SetLegend("Task Open");
-	$lineplot6 ->SetLegend("Task Close");
-
-} elseif ($area=='downloads') {
-
-	// Create the Downloads plot
-	$ydata5  =& $report->getDownloads();
-	$lineplot5 =new LinePlot($ydata5);
-	$lineplot5 ->SetColor("purple");
-	$graph->Add( $lineplot5 );
-
-	//	Legends
-	$lineplot5 ->SetLegend("Downloads");
-
-}
-
-
-//
-//	Titles
-//
-$graph->title->Set("Site-Wide Activity (".date('m/d/Y',$report->getStartDate()) ."-". date('m/d/Y',$report->getEndDate()) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval($report->getGraphInterval());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/sitetime.php b/src/www/reporting/sitetime.php
index 119c172..f925fa0 100644
--- a/src/www/reporting/sitetime.php
+++ b/src/www/reporting/sitetime.php
@@ -101,12 +101,7 @@ if ($typ =='r') {
 	echo $HTML->listTableBottom ();
 } elseif ($start != $end) { ?>
 <p>
-<?php
-	report_timegraph('site', $type, $start, $end);
-?>
-<noscript>
-<img src="sitetime_graph.php?<?php echo "start=$start&end=$end&type=$type"; ?>" alt="" />
-</noscript>
+<?php report_timegraph('site', $type, $start, $end); ?>
 </p>
 <?php
 }
diff --git a/src/www/reporting/sitetime_graph.php b/src/www/reporting/sitetime_graph.php
deleted file mode 100644
index 5c9bcab..0000000
--- a/src/www/reporting/sitetime_graph.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie3d.php');
-require_once $gfcommon.'reporting/ReportSiteTime.class.php';
-require_once $gfcommon.'reporting/report_utils.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-$type = getStringFromRequest('type');
-
-//
-//	Create Report
-//
-$report=new ReportSiteTime($type,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-// XXX ogi: Isn't it $type?
-if (!isset($datatype)) {
-	$datatype=1;
-}
-
-if (!$start) {
-	$start=mktime(0,0,0,date('m'),1,date('Y'));;
-}
-if (!$end) {
-	$end=time();
-} else {
-	$end--;
-}
-
-// Create the graph. These two calls are always required
-$graph  = new PieGraph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-
-$arr['tasks']='By Task';
-$arr['category']='By Category';
-$arr['subproject']='By Subproject';
-$arr['user']='By User';
-
-$graph->title->Set("Time Report ".$arr[$type]." (".date('m/d/Y',$start) ."-". date('m/d/Y',$end) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-
-report_pie_arr($report->labels,$report->getData());
-
-$p1  = new PiePlot3D( $pie_vals );
-$p1->ExplodeSlice (0);
-$p1->SetLegends( $pie_labels );
-$graph->Add( $p1);
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/sitetimebar_graph.php b/src/www/reporting/sitetimebar_graph.php
deleted file mode 100644
index 77e7368..0000000
--- a/src/www/reporting/sitetimebar_graph.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_bar.php');
-require_once $gfcommon.'reporting/Report.class.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-//
-//	Create Report
-//
-$report=new Report();
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-if (!$start) {
-	$start=mktime(0,0,0,date('m'),1,date('Y'));;
-}
-if (!$end) {
-	$end=time();
-} else {
-	$end--;
-}
-
-$res=db_query_params ('SELECT week,sum(hours)
-	FROM rep_time_tracking
-	WHERE week
-	BETWEEN $1 AND $2 GROUP BY week',
-			array($start,
-				$end));
-
-$report->setDates($res,0);
-$report->setData($res,1);
-
-//////
-// Create the graph. These two calls are always required
-$graph = new Graph(640,480,"auto");
-$graph->SetScale("textlin");
-$graph->yaxis->scale->SetGrace(20);
-
-// Add a drop shadow
-//$graph->SetShadow();
-
-// Adjust the margin a bit to make more room for titles
-$graph->img->SetMargin(40,20,35,40);
-
-// Create a bar pot
-$bplot = new BarPlot($report->getData());
-
-// Adjust fill color
-$bplot->SetFillColor('orange');
-$bplot->SetShadow();
-$bplot->value->Show();
-//$bplot->value->SetAngle(90);
-//$bplot->value->SetFormat('%0.1f');
-$graph->Add($bplot);
-
-// Setup the titles
-$graph->title->Set("Hours Recorded (".date('m/d/Y',$start) ."-". date('m/d/Y',$end) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-$graph->xaxis->title->Set("Date");
-$graph->yaxis->title->Set("Hours");
-
-// Setup X-axis
-$graph->xaxis->SetTickLabels($report->getDates());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/toolspie.php b/src/www/reporting/toolspie.php
index dff54ae..8515be4 100644
--- a/src/www/reporting/toolspie.php
+++ b/src/www/reporting/toolspie.php
@@ -70,12 +70,7 @@ report_header(_('Tool Pie Graphs'));
 </form>
 <?php if ($start != $end) { ?>
 <p>
-<?php
-	report_toolspiegraph($datatype, $start, $end);
-?>
-<noscript>
-<img src="toolspie_graph.php?<?php echo "datatype=$datatype&start=$start&end=$end"; ?>" alt="" />
-</noscript>
+<?php report_toolspiegraph($datatype, $start, $end); ?>
 </p>
 <?php }
 
diff --git a/src/www/reporting/toolspie_graph.php b/src/www/reporting/toolspie_graph.php
deleted file mode 100644
index 2a507cf..0000000
--- a/src/www/reporting/toolspie_graph.php
+++ /dev/null
@@ -1,149 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie3d.php');
-require_once $gfcommon.'reporting/Report.class.php';
-require_once $gfcommon.'reporting/report_utils.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-//
-//	Create Report
-//
-$report=new Report();
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-$datatype = getIntFromRequest('datatype');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-if (!isset($datatype)) {
-	$datatype=1;
-}
-
-if (!$start) {
-	$start=mktime(0,0,0,date('m'),1,date('Y'));;
-}
-if (!$end) {
-	$end=time();
-} else {
-	$end--;
-}
-
-
-if ($datatype < 5) {
-	$res = db_query_params ('SELECT g.group_name,count(*) AS count
-	FROM groups g, artifact_group_list agl, artifact a
-	WHERE g.group_id=agl.group_id
-	AND agl.group_artifact_id=a.group_artifact_id
-	AND a.open_date BETWEEN $1 AND $2
-	AND agl.datatype=$3
-	GROUP BY group_name
-	ORDER BY count DESC',
-				array ($start,
-				       $end,
-				       $datatype));
-} elseif ($datatype == 5) {
-	$res = db_query_params ('SELECT g.group_name,count(*) AS count
-	FROM groups g, forum_group_list fgl, forum f
-	WHERE g.group_id=fgl.group_id
-	AND fgl.group_forum_id=f.group_forum_id
-	AND f.post_date BETWEEN $1 AND $2
-	GROUP BY group_name
-	ORDER BY count DESC',
-				array ($start,
-				       $end));
-} elseif ($datatype == 6) {
-	$res = db_query_params ('SELECT g.group_name,count(*) AS count
-	FROM groups g, project_group_list pgl, project_task pt
-	WHERE g.group_id=pgl.group_id
-	AND pgl.group_project_id=pt.group_project_id
-	AND pt.start_date BETWEEN $1 AND $2
-	GROUP BY group_name
-	ORDER BY count DESC',
-				array ($start,
-				       $end));
-} else {
-	$res = db_query_params ('SELECT g.group_name,count(*) AS count
-	FROM groups g, frs_package fp, frs_release fr, frs_file ff, frs_dlstats_file fdf
-	WHERE g.group_id=fp.group_id
-	AND fp.package_id=fr.package_id
-	AND fr.release_id=ff.release_id
-	AND ff.file_id=fdf.file_id
-	AND (((fdf.month > $1) OR (fdf.month = $1 AND fdf.day >= $2))
-	AND ((fdf.month < $3) OR (fdf.month = $3 AND fdf.day < $4)))
-	GROUP BY group_name
-	ORDER BY count DESC',
-				array (date('Ym',$start),
-				       date('d',$start),
-				       date('Ym',$end),
-				       date('d',$end)));
-}
-
-//echo $sql;
-//exit;
-
-
-if (db_error()) {
-	exit_error(db_error());
-}
-
-// Create the graph. These two calls are always required
-$graph  = new PieGraph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-
-$arr[1]='Bugs';
-$arr[2]='Support Requests';
-$arr[3]='Patches';
-$arr[4]='Feature Requests';
-$arr[0]='Other Trackers';
-$arr[5]='Forum Messages';
-$arr[6]='Tasks';
-$arr[7]='Downloads';
-$graph->title->Set($arr[$datatype]." By Project (".date('m/d/Y',$start) ."-". date('m/d/Y',$end) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-
-// Create the tracker open plot
-report_pie_arr(util_result_column_to_array($res,0), util_result_column_to_array($res,1));
-
-$p1  = new PiePlot3D($pie_vals);
-$p1->ExplodeSlice (0);
-$p1->SetLegends($pie_labels);
-$graph->Add( $p1);
-
-// Display the graph
-$graph->Stroke();
-
-// Local Variables:
-// mode: php
-// c-file-style: "bsd"
-// End:
diff --git a/src/www/reporting/trackerpie_graph.php b/src/www/reporting/trackerpie_graph.php
deleted file mode 100644
index fecbac6..0000000
--- a/src/www/reporting/trackerpie_graph.php
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie3d.php');
-require_once $gfcommon.'reporting/Report.class.php';
-require_once $gfcommon.'reporting/report_utils.php';
-require_once $gfcommon.'tracker/include/ArtifactTypeHtml.class.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-//
-//	Create Report
-//
-$report=new Report();
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-$area = getStringFromRequest('area');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-if (!isset($area)) {
-	$area='category';
-}
-
-if (!$start) {
-	$start=mktime(0,0,0,date('m'),1,date('Y'));;
-}
-if (!$end) {
-	$end=time();
-} else {
-	$end--;
-}
-
-
-if ($area == 'category') {
-	$res = db_query_params ('SELECT ac.category_name,count(*)
-	FROM artifact a, artifact_category ac
-	WHERE a.group_artifact_id=$1
-	AND a.category_id=ac.id
-	AND a.open_date BETWEEN $2 AND $3
-	GROUP BY category_name',
-				array($atid,
-				      $start,
-				      $end));
-} elseif ($area == 'group') {
-	$res = db_query_params ('SELECT ag.group_name,count(*)
-	FROM artifact a, artifact_group ag
-	WHERE a.group_artifact_id=$1
-	AND a.artifact_group_id=ag.id
-	AND a.open_date BETWEEN $2 AND $3
-	GROUP BY group_name',
-				array($atid,
-				      $start,
-				      $end));
-} elseif ($area == 'resolution') {
-	$res = db_query_params ('SELECT ar.resolution_name,count(*)
-	FROM artifact a, artifact_resolution ar
-	WHERE a.group_artifact_id=$1
-	AND a.resolution_id=ar.id
-	AND a.open_date BETWEEN $2 AND $3
-	GROUP BY resolution_name',
-				array($atid,
-				      $start,
-				      $end));
-} else {
-	$area = 'assignee';
-	$res = db_query_params ('SELECT u.realname,count(*)
-	FROM artifact a, users u
-	WHERE a.group_artifact_id=$1
-	AND a.assigned_to=u.user_id
-	AND a.open_date BETWEEN $2 AND $3
-	GROUP BY realname',
-				array($atid,
-				      $start,
-				      $end));
-}
-
-if (db_error()) {
-	exit_error(db_error());
-}
-
-// Create the graph. These two calls are always required
-$graph  = new PieGraph(640, 480,"auto");
-//$graph->SetMargin(50,10,35,50);
-
-$arr = array();
-$arr['category']='By Category';
-$arr['group']='By Group';
-$arr['resolution']='By Resolution';
-$arr['assignee']='By Assignee';
-$graph->title->Set($arr[$area]." (".date('m/d/Y',$start) ."-". date('m/d/Y',$end) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-
-// Create the tracker open plot
-report_pie_arr(util_result_column_to_array($res,0), util_result_column_to_array($res,1));
-
-$p1  = new PiePlot3D($pie_vals);
-$p1->ExplodeSlice (0);
-$p1->SetLegends($pie_labels);
-$graph->Add( $p1);
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/useract.php b/src/www/reporting/useract.php
index ae76cbf..e97145f 100644
--- a/src/www/reporting/useract.php
+++ b/src/www/reporting/useract.php
@@ -91,12 +91,7 @@ if ($sw) {
 	</form>
 	<?php if ($dev_id && $start != $end) { ?>
 		<p>
-		<?php
-			report_actgraph('user', $SPAN, $start, $end, $dev_id, $area);
-		?>
-		<noscript>
-		<img src="useract_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&dev_id=$dev_id&area=$area"; ?>" alt="" />
-		</noscript>
+		<?php report_actgraph('user', $SPAN, $start, $end, $dev_id, $area); ?>
 		</p>
 		<?php
 
diff --git a/src/www/reporting/useract_graph.php b/src/www/reporting/useract_graph.php
deleted file mode 100644
index f4485d8..0000000
--- a/src/www/reporting/useract_graph.php
+++ /dev/null
@@ -1,140 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportUserAct.class.php';
-require_once $gfwww.'include/unicode.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$dev_id = getIntFromRequest('dev_id');
-$SPAN = getIntFromRequest('SPAN');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-$area = getFilteredStringFromRequest('area', '/^[a-z]+$/');
-
-//
-//	Create Report
-//
-$report=new ReportUserAct($SPAN,$dev_id,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-//
-// Get User Object
-//
-$u =& user_get_object($dev_id);
-if (!$u || $u->isError()) {
-	exit_error(_("Could Not Get User"));
-}
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-$graph->SetScale( "textlin");
-//$graph->SetScale( "linlog");
-//$graph ->SetYScale("log");
-
-if ($area=='tracker') {
-
-	// Create the tracker open plot
-	$ydata  =& $report->getTrackerOpened();
-	$lineplot =new LinePlot($ydata);
-	$lineplot ->SetColor("black");
-	$graph->Add( $lineplot);
-
-	// Create the tracker close plot
-	$ydata2  =& $report->getTrackerClosed();
-	$lineplot2 =new LinePlot($ydata2);
-	$lineplot2 ->SetColor("blue");
-	$graph->Add( $lineplot2 );
-
-	//	Legends
-	$lineplot->SetLegend (convert_unicode(_('Tracker Items Opened')));
-	$lineplot2 ->SetLegend(convert_unicode(_('Tracker Items Closed')));
-
-} elseif ($area=='forum') {
-
-	// Create the forum plot
-	$ydata3  =& $report->getForum();
-	$lineplot3 =new LinePlot($ydata3);
-	$lineplot3 ->SetColor("orange");
-	$graph->Add( $lineplot3 );
-
-	//	Legends
-	$lineplot3 ->SetLegend("Forum");
-
-} elseif ($area=='docman') {
-
-	// Create the Docman plot
-	$ydata4  =& $report->getDocs();
-	$lineplot4 =new LinePlot($ydata4);
-	$lineplot4 ->SetColor("red");
-	$graph->Add( $lineplot4 );
-
-	//	Legends
-	$lineplot4 ->SetLegend("Docs");
-
-} elseif ($area=='taskman') {
-
-	// Create the Tasks Opened plot
-	$ydata5  =& $report->getTaskOpened();
-	$lineplot5 =new LinePlot($ydata5);
-	$lineplot5 ->SetColor("purple");
-	$graph->Add( $lineplot5 );
-
-	// Create the Tasks Closed plot
-	$ydata6  =& $report->getTaskClosed();
-	$lineplot6 =new LinePlot($ydata6);
-	$lineplot6 ->SetColor("yellow");
-	$graph->Add( $lineplot6 );
-
-	//	Legends
-	$lineplot5 ->SetLegend("Task Open");
-	$lineplot6 ->SetLegend("Task Close");
-}
-
-
-//
-//	Titles
-//
-$graph->title->Set("User Activity For: ".$u->getRealName()
-	." (".date('m/d/Y',$report->getStartDate()) ."-". date('m/d/Y',$report->getEndDate()) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval($report->getGraphInterval());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/useradded.php b/src/www/reporting/useradded.php
index f4ca44c..c8b7457 100644
--- a/src/www/reporting/useradded.php
+++ b/src/www/reporting/useradded.php
@@ -69,12 +69,7 @@ report_header(_('Users Added'));
 </form>
 <?php if ($start != $end) { ?>
 	<p>
-	<?php
-		report_graph('useradded', $SPAN, $start, $end);
-	?>
-	<noscript>
-	<img src="useradded_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
-	</noscript>
+	<?php report_graph('useradded', $SPAN, $start, $end); ?>
 	</p>
 <?php }
 
diff --git a/src/www/reporting/useradded_graph.php b/src/www/reporting/useradded_graph.php
deleted file mode 100644
index f2dffe8..0000000
--- a/src/www/reporting/useradded_graph.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportUserAdded.class.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$SPAN = getIntFromRequest('SPAN');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-//
-//	Create Report
-//
-$report=new ReportUserAdded($SPAN,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-// Some data
-$ydata  = $report->getData();
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-$graph->SetScale( "textlin");
-
-// Create the linear plot
-$lineplot =new LinePlot($ydata);
-$lineplot ->SetColor("black");
-$lineplot->SetFillColor("orange");
-
-// Add the plot to the graph
-$graph->Add( $lineplot);
-
-//$graph->SetMargin(10,10,25,10);
-$graph->title->Set("Users Added ".$report->getSpanName()
-	." (".date('m/d/Y',$report->getStartDate()) ."-". date('m/d/Y',$report->getEndDate()) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval($report->getGraphInterval());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/usercum.php b/src/www/reporting/usercum.php
index 989b4c7..ea6b4e7 100644
--- a/src/www/reporting/usercum.php
+++ b/src/www/reporting/usercum.php
@@ -69,12 +69,7 @@ report_header(_('Cumulative Users'));
 </form>
 <?php if ($start != $end) { ?>
 	<p>
-	<?php
-		report_graph('usercumul', $SPAN, $start, $end);
-	?>
-	<noscript>
-	<img src="usercum_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
-	</noscript>
+	<?php report_graph('usercumul', $SPAN, $start, $end); ?>
 	</p>
 <?php }
 
diff --git a/src/www/reporting/usercum_graph.php b/src/www/reporting/usercum_graph.php
deleted file mode 100644
index 0fa3f1b..0000000
--- a/src/www/reporting/usercum_graph.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportUserCum.class.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$SPAN = getIntFromRequest('SPAN');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-//
-//	Create Report
-//
-$report=new ReportUserCum($SPAN,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-// Some data
-$ydata  = $report->getData();
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-$graph->SetScale( "textlin");
-
-// Create the linear plot
-$lineplot =new LinePlot($ydata);
-$lineplot ->SetColor("black");
-$lineplot->SetFillColor("orange");
-
-// Add the plot to the graph
-$graph->Add( $lineplot);
-
-//$graph->SetMargin(10,10,25,10);
-$graph->title->Set("Cumulative Users ".$report->getSpanName()
-	." (".date('m/d/Y',$report->getStartDate()) ."-". date('m/d/Y',$report->getEndDate()) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval($report->getGraphInterval());
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/reporting/usertime.php b/src/www/reporting/usertime.php
index a3b6783..7dd9a79 100644
--- a/src/www/reporting/usertime.php
+++ b/src/www/reporting/usertime.php
@@ -116,12 +116,7 @@ if ($sw) {
 
 		} elseif ($dev_id && $start != $end) { ?>
 		<p>
-		<?php
-			report_timegraph('user', $type, $start, $end, $dev_id);
-		?>
-		<noscript>
-		<img src="usertime_graph.php?<?php echo "start=$start&end=$end&dev_id=$dev_id&type=$type"; ?>" alt="" />
-		</noscript>
+		<?php report_timegraph('user', $type, $start, $end, $dev_id); ?>
 		</p>
 		<?php
 		}
diff --git a/src/www/reporting/usertime_graph.php b/src/www/reporting/usertime_graph.php
deleted file mode 100644
index 84d973a..0000000
--- a/src/www/reporting/usertime_graph.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie3d.php');
-require_once $gfcommon.'reporting/ReportUserTime.class.php';
-require_once $gfcommon.'reporting/report_utils.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$dev_id = getIntFromRequest('dev_id');
-$type = getStringFromRequest('type');
-$start = getIntFromRequest('start');
-$end = getIntFromRequest('end');
-
-//
-//	Create Report
-//
-$report=new ReportUserTime($dev_id,$type,$start,$end);
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage());
-}
-
-// XXX ogi: Isn't it $type?
-if (!isset($datatype)) {
-	$datatype=1;
-}
-
-if (!$start) {
-	$start=mktime(0,0,0,date('m'),1,date('Y'));;
-}
-if (!$end) {
-	$end=time();
-} else {
-	$end--;
-}
-
-// Create the graph. These two calls are always required
-$graph  = new PieGraph(640, 480,"auto");
-$graph->SetMargin(50,10,35,80);
-
-$arr['tasks']='By Task';
-$arr['category']='By Category';
-$arr['subproject']='By Subproject';
-
-$graph->title->Set("Time Report ".$arr[$type]." (".date('m/d/Y',$start) ."-". date('m/d/Y',$end) .")");
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-
-// Create the tracker open plot
-//$data  =& $report->getData();
-//$labels =& $report->labels;
-report_pie_arr($report->labels,$report->getData());
-
-$p1  = new PiePlot3D( $pie_vals );
-$p1->ExplodeSlice (0);
-$p1->SetLegends( $pie_labels );
-$graph->Add( $p1);
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/scm/reporting/commits_graph.php b/src/www/scm/reporting/commits_graph.php
deleted file mode 100644
index 3a4d129..0000000
--- a/src/www/scm/reporting/commits_graph.php
+++ /dev/null
@@ -1,96 +0,0 @@
-<?php
-/**
- * FusionForge Reporting System
- *
- * Copyright 2003-2004 (c) GForge LLC, Tim Perdue
- * Copyright 2010 (c) Franck Villaume
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_pie3d.php');
-require_once $gfcommon.'reporting/Report.class.php';
-require_once $gfcommon.'reporting/report_utils.php';
-
-//
-//	Create Report
-//
-$report=new Report();
-
-//
-//	Check for error, such as license key problem
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage(),'scm');
-}
-
-$group_id = getIntFromRequest('group_id');
-$g = group_get_object($group_id);
-if (!$g || !is_object($g)) {
-	exit_no_group();
-}
-
-$days = getIntFromRequest('days');
-if (!$days || $days < 1) {
-	$days=30;
-}
-
-$start = getIntFromRequest('start');
-if (!$start) {
-	$start=time() - ($days * 60 * 60 * 24);
-	$formattedmonth = date('Ym',$start);
-}
-
-$end = getIntFromRequest('end');
-if (!$end) {
-	$end=time();
-} else {
-	$end--;
-}
-
-$res = db_query_params ('SELECT u.realname,sum(commits) AS count
-		FROM stats_cvs_user scu, users u
-		WHERE u.user_id = scu.user_id
-		AND scu.month >= $1
-		AND group_id=$2
-		GROUP BY realname ORDER BY count DESC',
-			array ($formattedmonth,
-			       $group_id));
-
-if (db_error()) {
-	exit_error(db_error(),'scm');
-}
-
-// Create the graph. These two calls are always required
-$graph  = new PieGraph(640, 480,"auto");
-//$graph->SetMargin(50,10,35,50);
-
-$graph->title->Set(utf8_decode(_("Commits By User")." (".strftime('%x',$start) ." - ". strftime('%x',$end) .")"));
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-
-// Create the tracker open plot
-report_pie_arr(util_result_column_to_array($res,0), util_result_column_to_array($res,1), 0);
-
-$p1  = new PiePlot3D($pie_vals);
-$p1->SetLegends($pie_labels);
-$graph->Add( $p1);
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/scm/reporting/commitstime_graph.php b/src/www/scm/reporting/commitstime_graph.php
deleted file mode 100644
index 92a5f84..0000000
--- a/src/www/scm/reporting/commitstime_graph.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * Reporting System
- *
- * Copyright 2003-2004 (c) Tim Perdue - GForge LLC
- * Copyright 2012, Franck Villaume - TrivialDev
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once(forge_get_config('jpgraph_path').'/jpgraph.php');
-require_once(forge_get_config('jpgraph_path').'/jpgraph_line.php');
-require_once $gfcommon.'reporting/ReportUserAdded.class.php';
-
-//
-//      Create Report
-//
-$report=new Report();
-
-//
-//      Check for error
-//
-if ($report->isError()) {
-	exit_error($report->getErrorMessage(),'scm');
-}
-
-$group_id = getIntFromRequest('group_id');
-$g = group_get_object($group_id);
-if (!$g || !is_object($g)) {
-	exit_no_group();
-}
-
-$res = db_query_params ('SELECT month,sum(commits) AS count
-	FROM stats_cvs_group
-	WHERE group_id=$1
-	GROUP BY month ORDER BY month ASC',
-			array ($group_id));
-if (db_error()) {
-	exit_error(db_error(), 'scm');
-}
-
-$report->labels=util_result_column_to_array($res,0);
-$report->setData($res,1);
-$report->start_date=$report->labels[0];
-$report->end_date=$report->labels[count($report->labels)-1];
-
-// Some data
-
-// Create the graph. These two calls are always required
-$graph  = new Graph(640, 480,"auto");
-$graph->SetMargin(50,10,35,50);
-$graph->SetScale( "textlin");
-
-// Create the linear plot
-$lineplot =new LinePlot($report->getData());
-$lineplot ->SetColor("black");
-$lineplot->SetFillColor("orange");
-
-// Add the plot to the graph
-$graph->Add( $lineplot);
-
-//$graph->SetMargin(10,10,25,10);
-$graph->title->Set($g->getPublicName()." Commits Over Time: ".$report->start_date." - ".$report->end_date);
-$graph->subtitle->Set(forge_get_config ('forge_name'));
-//$graph->xaxis-> title->Set("Date" );
-//$graph->yaxis-> title->Set("Number" );
-
-$a=$report->getDates();
-$graph->xaxis->SetTickLabels($a);
-$graph->xaxis->SetLabelAngle(90);
-$graph->xaxis->SetTextLabelInterval(3);
-
-// Display the graph
-$graph->Stroke();
diff --git a/src/www/scm/reporting/index.php b/src/www/scm/reporting/index.php
index 10587a2..f6b274b 100644
--- a/src/www/scm/reporting/index.php
+++ b/src/www/scm/reporting/index.php
@@ -3,7 +3,7 @@
  * SCM Reporting
  *
  * Copyright 2004-2005 (c) Tim Perdue - GForge LLC
- * Copyright 2012, Franck Villaume - TrivialDev
+ * Copyright 2012-2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -35,51 +35,22 @@ $group_id = getIntFromRequest("group_id");
 scm_header(array('title'=>_('SCM Repository Reporting'), 'group'=>$group_id));
 
 ?>
-
 <h2>Commits Over Time</h2>
 <p>
-<?php
-commitstime_graph($group_id, 1);
-?>
-<noscript>
-<img src="commitstime_graph.php?group_id=<?php echo $group_id; ?>"
-     alt="Commits Over Time" />
-</noscript>
+<?php commitstime_graph($group_id, 1); ?>
 </p>
-
 <h2>Commits Last 30 Days</h2>
 <p>
-<?php
-commits_graph($group_id, 30, 2);
-?>
-<noscript>
-<img src="commits_graph.php?group_id=<?php echo $group_id; ?>&days=30"
-     alt="Commits Last 30 Days" />
-</noscript>
+<?php commits_graph($group_id, 30, 2); ?>
 </p>
-
 <h2>Commits Last 90 Days</h2>
 <p>
-<?php
-commits_graph($group_id, 90, 3);
-?>
-<noscript>
-<img src="commits_graph.php?group_id=<?php echo $group_id; ?>&days=90"
-     alt="Commits Last 90 Days" />
-</noscript>
+<?php commits_graph($group_id, 90, 3); ?>
 </p>
-
 <h2>Commits Last 365 Days</h2>
 <p>
-<?php
-commits_graph($group_id, 365, 4);
-?>
-<noscript>
-<img src="commits_graph.php?group_id=<?php echo $group_id; ?>&days=365"
-     alt="Commits Last 365 Days" />
-</noscript>
+<?php commits_graph($group_id, 365, 4); ?>
 </p>
-
 <?php
 
 scm_footer();
diff --git a/src/www/stats/graphs.php b/src/www/stats/graphs.php
index d96e728..fa1a548 100644
--- a/src/www/stats/graphs.php
+++ b/src/www/stats/graphs.php
@@ -49,20 +49,10 @@ $HTML->header(array('title'=>sprintf(_('%1$s Sitewide Statistics Graphs'), forge
 <hr />
 <p class="information" ><?php echo _('Displayed data: only last 24 months.'); ?></p>
 <p class="align-center">
-<?php 
-views_graph(1);
-?>
-<noscript>
-<img src="views_graph.php?monthly=1" alt="" />
-</noscript>
+<?php views_graph(1); ?>
 </p>
 <p class="align-center">
-<?php
-users_graph();
-?>
-<noscript>
-<img src="users_graph.php" alt="" />
-</noscript>
+<?php users_graph(); ?>
 </p>
 
 <?php
diff --git a/src/www/stats/users_graph.php b/src/www/stats/users_graph.php
deleted file mode 100644
index 5c99234..0000000
--- a/src/www/stats/users_graph.php
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-/**
- * Sitewide Statistics
- *
- * Copyright 1999-2001 (c) VA Linux Systems
- * Copyright 2010 (c) FusionForge Team
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once $gfwww.'include/graph_lib.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$group_id = getIntFromRequest('group_id');
-$year = getIntFromRequest('year');
-
-if ( ! $group_id ) {
-	$group_id = 0;
-}
-
-if ( ! $year ) {
-	$year = gmstrftime("%Y", time() );
-}
-
-$res = db_query_params ('SELECT month,day,new_users,new_projects FROM stats_site ORDER BY month ASC, day ASC',
-			array ());
-
-$i = 0;
-while ( $row = db_fetch_array($res) ) {
-        $xdata[$i]          = $i;
-	$xlabel[$i]         = (substr($row['month'],4) + 1 - 1) . "/" . $row['day'];
-        $ydata1[$i]         = $row["new_users"];
-        $ydata2[$i]         = $row["new_projects"];
-        ++$i;
-}
-//
-// Need at least 2 data points
-//
-if ($i == 0) {
-    $xdata[0] = 0;
-    $xlabel[0] = "";
-    $ydata1[0] = 0;
-    $ydata2[0] = 0;
-
-    $xdata[1] = 1;
-    $xlabel[1] = "";
-    $ydata1[1] = 0;
-    $ydata2[1] = 0;
-}
-if ($i == 1) {
-    $xdata[1] = 1;
-    $xlabel[1] = $xlabel[0];
-    $ydata1[1] = $ydata1[0];
-    $ydata2[1] = $ydata2[0];
-}
-
-
-$graph = new Graph( 750, 550 );
-
-$data1 = $graph->AddData( $xdata, $ydata1, $xlabel );
-$data2 = $graph->AddData( $xdata, $ydata2, $xlabel );
-
-$graph->DrawGrid('gray');
-$graph->LineGraph($data1,'red');
-$graph->LineGraph($data2,'blue');
-$graph->SetTitle(_('New Additions, by Day') );
-$graph->SetSubTitle(_('New Users (RED), New Projects (BLUE)'));
-$graph->SetxTitle(_('Date'));
-$graph->SetyTitle(_('Users (RED) / Projects (BLUE)'));
-$graph->DrawAxis();
-//$graph->showDebug();
-$graph->ShowGraph('png');
diff --git a/src/www/stats/views_graph.php b/src/www/stats/views_graph.php
deleted file mode 100644
index d37dfae..0000000
--- a/src/www/stats/views_graph.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-/**
- * Sitewide Statistics
- *
- * Copyright 1999-2001 (c) VA Linux Systems
- * Copyright 2010 (c) FusionForge Team
- * http://fusionforge.org
- *
- * This file is part of FusionForge. FusionForge is free software;
- * you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the Licence, or (at your option)
- * any later version.
- *
- * FusionForge is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with FusionForge; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-require_once '../env.inc.php';
-require_once $gfcommon.'include/pre.php';
-require_once $gfwww.'include/graph_lib.php';
-
-session_require_global_perm ('forge_stats', 'read') ;
-
-$group_id = getIntFromRequest('group_id');
-$year = getIntFromRequest('year');
-$monthly = getIntFromRequest('monthly');
-
-if ( ! $group_id ) {
-	$group_id = 0;
-}
-
-if ( ! $year ) {
-	$year = gmstrftime("%Y", time() );
-}
-
-if ($monthly) {
-
-
-$res = db_query_params ('SELECT month,site_page_views AS site_views,subdomain_views
-		FROM stats_site_months ORDER BY month ASC',
-			array ());
-	$grouping='Months';
-
-} else {
-
-	$beg_year=date('Y',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
-	$beg_month=date('m',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
-	$beg_day=date('d',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
-
-
-$res = db_query_params ('SELECT month,day,site_page_views AS site_views,subdomain_views
-		FROM stats_site_vw
-		( month = $1 AND day >= $2 ) OR ( month > $3 )
-		ORDER BY month ASC, day ASC',
-			array ("$beg_year$beg_month",
-				$beg_day,
-				"$beg_year$beg_month"));
-	$grouping='Days';
-
-}
-
-
-$i = 0;
-$xdata = array();
-$ydata = array();
-while ( $row = db_fetch_array($res) ) {
-		$xdata[$i]		  = $i;
-	$xlabel[$i]		 = $row['month'] . (($row['day']) ? "/" . $row['day'] : '');
-		$ydata1[$i]		 = $row["site_views"] + $row["subdomain_views"];
-		++$i;
-}
-
-$graph = new Graph( 750, 550 );
-//
-// Need at least 2 data points
-//
-if ($i == 0) {
-	$xdata[0] = 0;
-	$xlabel[0] = "";
-	$ydata1[1] = 0;
-	$xdata[1] = 1;
-	$xlabel[1] = "";
-	$ydata1[1] = 0;
-}
-
-if ($i == 1) {
-	$xdata[1] = 1;
-	$xlabel[1] = $xlabel[0];
-	$ydata1[1] = $ydata1[0];
-}
-$graph->SetTitle( _('Forge Page Views') );
-$graph->SetSubTitle(sprintf(_('Total Page Views (RED) (%1$s days)'),  $i));
-
-$data1 = $graph->AddData( $xdata, $ydata1, $xlabel );
-$graph->LineGraph($data1,'red');
-
-$graph->DrawGrid('gray');
-$graph->SetxTitle(_('Date'));
-$graph->SetyTitle(_('Views (RED)'));
-$graph->DrawAxis();
-//$graph->showDebug();
-$graph->ShowGraph('png');

commit 948aa59b5096eef132ceb909de4a0d6a9e55472b
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 28 11:02:11 2013 +0200

    jqplot: update to 1.0.8r1250

diff --git a/src/vendor/jquery-jqplot/jquery.jqplot.css b/src/vendor/jquery-jqplot/jquery.jqplot.css
index d30bafb..f6768a6 100644
--- a/src/vendor/jquery-jqplot/jquery.jqplot.css
+++ b/src/vendor/jquery-jqplot/jquery.jqplot.css
@@ -62,12 +62,12 @@
 }
 
 .jqplot-yaxis-tick.jqplot-breakTick {
-	right: -20px;
-	margin-right: 0px;
-	padding:1px 5px 1px 5px;
-/*	background-color: white;*/
-	z-index: 2;
-	font-size: 1.5em;
+    right: -20px;
+    margin-right: 0px;
+    padding:1px 5px 1px 5px;
+    /*background-color: white;*/
+    z-index: 2;
+    font-size: 1.5em;
 }
 
 .jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick {
@@ -254,6 +254,6 @@ div.jqplot-bubble-label.jqplot-bubble-label-highlight {
 }
 
 div.jqplot-noData-container {
-	text-align: center;
-	background-color: rgba(96%, 96%, 96%, 0.3);
+    text-align: center;
+    background-color: rgba(96%, 96%, 96%, 0.3);
 }
diff --git a/src/vendor/jquery-jqplot/jquery.jqplot.js b/src/vendor/jquery-jqplot/jquery.jqplot.js
index 1f45250..49812b7 100644
--- a/src/vendor/jquery-jqplot/jquery.jqplot.js
+++ b/src/vendor/jquery-jqplot/jquery.jqplot.js
@@ -5,12 +5,12 @@
  * 
  * About: Version
  * 
- * version: 1.0.4 
- * revision: 1120
+ * version: 1.0.8 
+ * revision: 1250
  * 
  * About: Copyright & License
  * 
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT and GPL version 2.0 licenses. This means that you can 
  * choose the license that best suits your project and use it accordingly.
@@ -48,19 +48,19 @@
  * jqPlot can be customized by overriding the defaults of any of the objects which make
  * up the plot. The general usage of jqplot is:
  * 
- * > chart = jQuery.jqplot('targetElemId', [dataArray,...], {optionsObject});
+ * > chart = $.jqplot('targetElemId', [dataArray,...], {optionsObject});
  * 
  * The options available to jqplot are detailed in <jqPlot Options> in the jqPlotOptions.txt file.
  * 
- * An actual call to jQuery.jqplot() may look like the 
+ * An actual call to $.jqplot() may look like the 
  * examples below:
  * 
- * > chart = jQuery.jqplot('chartdiv',  [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]]);
+ * > chart = $.jqplot('chartdiv',  [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]]);
  * 
  * or
  * 
  * > dataArray = [34,12,43,55,77];
- * > chart = jQuery.jqplot('targetElemId', [dataArray, ...], {title:'My Plot', axes:{yaxis:{min:20, max:100}}});
+ * > chart = $.jqplot('targetElemId', [dataArray, ...], {title:'My Plot', axes:{yaxis:{min:20, max:100}}});
  * 
  * For more inforrmation, see <jqPlot Usage>.
  * 
@@ -86,15 +86,15 @@
     // make sure undefined is undefined
     var undefined;
     
-    jQuery.fn.emptyForce = function() {
+    $.fn.emptyForce = function() {
       for ( var i = 0, elem; (elem = $(this)[i]) != null; i++ ) {
         // Remove element nodes and prevent memory leaks
         if ( elem.nodeType === 1 ) {
-          jQuery.cleanData( elem.getElementsByTagName("*") );
+          $.cleanData( elem.getElementsByTagName("*") );
         }
   
         // Remove any remaining nodes
-        if (jQuery.jqplot.use_excanvas) {
+        if ($.jqplot.use_excanvas) {
           elem.outerHTML = "";
         }
         else {
@@ -109,22 +109,22 @@
       return $(this);
     };
   
-    jQuery.fn.removeChildForce = function(parent) {
+    $.fn.removeChildForce = function(parent) {
       while ( parent.firstChild ) {
         this.removeChildForce( parent.firstChild );
         parent.removeChild( parent.firstChild );
       }
     };
 
-    jQuery.fn.jqplot = function() {
+    $.fn.jqplot = function() {
         var datas = [];
         var options = [];
         // see how many data arrays we have
         for (var i=0, l=arguments.length; i<l; i++) {
-            if (jQuery.isArray(arguments[i])) {
+            if ($.isArray(arguments[i])) {
                 datas.push(arguments[i]);
             }
-            else if (jQuery.isPlainObject(arguments[i])) {
+            else if ($.isPlainObject(arguments[i])) {
                 options.push(arguments[i]);
             }
         }
@@ -156,11 +156,11 @@
             // if not assign it one.
             tid = $this.attr('id');
             if (tid === undefined) {
-                tid = 'jqplot_target_' + jQuery.jqplot.targetCounter++;
+                tid = 'jqplot_target_' + $.jqplot.targetCounter++;
                 $this.attr('id', tid);
             }
 
-            plot = jQuery.jqplot(tid, data, opts);
+            plot = $.jqplot(tid, data, opts);
 
             $this.data('jqplot', plot);
         });
@@ -168,7 +168,7 @@
 
 
     /**
-     * Namespace: jQuery.jqplot
+     * Namespace: $.jqplot
      * jQuery function called by the user to create a plot.
      *  
      * Parameters:
@@ -191,7 +191,7 @@
      *   is a jqplot wide default.
      */
 
-    jQuery.jqplot = function(target, data, options) {
+    $.jqplot = function(target, data, options) {
         var _data = null, _options = null;
 
         if (arguments.length === 3) {
@@ -200,11 +200,11 @@
         }
 
         else if (arguments.length === 2) {
-            if (jQuery.isArray(data)) {
+            if ($.isArray(data)) {
                 _data = data;
             }
 
-            else if (jQuery.isPlainObject(data)) {
+            else if ($.isPlainObject(data)) {
                 _options = data;
             }
         }
@@ -217,7 +217,7 @@
         // remove any error class that may be stuck on target.
         $('#'+target).removeClass('jqplot-error');
         
-        if (jQuery.jqplot.config.catchErrors) {
+        if ($.jqplot.config.catchErrors) {
             try {
                 plot.init(target, _data, _options);
                 plot.draw();
@@ -225,15 +225,15 @@
                 return plot;
             }
             catch(e) {
-                var msg = jQuery.jqplot.config.errorMessage || e.message;
+                var msg = $.jqplot.config.errorMessage || e.message;
                 $('#'+target).append('<div class="jqplot-error-message">'+msg+'</div>');
                 $('#'+target).addClass('jqplot-error');
-                document.getElementById(target).style.background = jQuery.jqplot.config.errorBackground;
-                document.getElementById(target).style.border = jQuery.jqplot.config.errorBorder;
-                document.getElementById(target).style.fontFamily = jQuery.jqplot.config.errorFontFamily;
-                document.getElementById(target).style.fontSize = jQuery.jqplot.config.errorFontSize;
-                document.getElementById(target).style.fontStyle = jQuery.jqplot.config.errorFontStyle;
-                document.getElementById(target).style.fontWeight = jQuery.jqplot.config.errorFontWeight;
+                document.getElementById(target).style.background = $.jqplot.config.errorBackground;
+                document.getElementById(target).style.border = $.jqplot.config.errorBorder;
+                document.getElementById(target).style.fontFamily = $.jqplot.config.errorFontFamily;
+                document.getElementById(target).style.fontSize = $.jqplot.config.errorFontSize;
+                document.getElementById(target).style.fontStyle = $.jqplot.config.errorFontStyle;
+                document.getElementById(target).style.fontWeight = $.jqplot.config.errorFontWeight;
             }
         }
         else {        
@@ -244,20 +244,20 @@
         }
     };
 
-    jQuery.jqplot.version = "1.0.4";
-    jQuery.jqplot.revision = "1120";
+    $.jqplot.version = "1.0.8";
+    $.jqplot.revision = "1250";
 
-    jQuery.jqplot.targetCounter = 1;
+    $.jqplot.targetCounter = 1;
 
     // canvas manager to reuse canvases on the plot.
     // Should help solve problem of canvases not being freed and
     // problem of waiting forever for firefox to decide to free memory.
-    jQuery.jqplot.CanvasManager = function() {
+    $.jqplot.CanvasManager = function() {
         // canvases are managed globally so that they can be reused
         // across plots after they have been freed
-        if (typeof jQuery.jqplot.CanvasManager.canvases == 'undefined') {
-            jQuery.jqplot.CanvasManager.canvases = [];
-            jQuery.jqplot.CanvasManager.free = [];
+        if (typeof $.jqplot.CanvasManager.canvases == 'undefined') {
+            $.jqplot.CanvasManager.canvases = [];
+            $.jqplot.CanvasManager.free = [];
         }
         
         var myCanvases = [];
@@ -266,13 +266,13 @@
             var canvas;
             var makeNew = true;
             
-            if (!jQuery.jqplot.use_excanvas) {
-                for (var i = 0, l = jQuery.jqplot.CanvasManager.canvases.length; i < l; i++) {
-                    if (jQuery.jqplot.CanvasManager.free[i] === true) {
+            if (!$.jqplot.use_excanvas) {
+                for (var i = 0, l = $.jqplot.CanvasManager.canvases.length; i < l; i++) {
+                    if ($.jqplot.CanvasManager.free[i] === true) {
                         makeNew = false;
-                        canvas = jQuery.jqplot.CanvasManager.canvases[i];
+                        canvas = $.jqplot.CanvasManager.canvases[i];
                         // $(canvas).removeClass('jqplot-canvasManager-free').addClass('jqplot-canvasManager-inuse');
-                        jQuery.jqplot.CanvasManager.free[i] = false;
+                        $.jqplot.CanvasManager.free[i] = false;
                         myCanvases.push(i);
                         break;
                     }
@@ -281,9 +281,9 @@
 
             if (makeNew) {
                 canvas = document.createElement('canvas');
-                myCanvases.push(jQuery.jqplot.CanvasManager.canvases.length);
-                jQuery.jqplot.CanvasManager.canvases.push(canvas);
-                jQuery.jqplot.CanvasManager.free.push(false);
+                myCanvases.push($.jqplot.CanvasManager.canvases.length);
+                $.jqplot.CanvasManager.canvases.push(canvas);
+                $.jqplot.CanvasManager.free.push(false);
             }   
             
             return canvas;
@@ -292,7 +292,7 @@
         // this method has to be used after settings the dimesions
         // on the element returned by getCanvas()
         this.initCanvas = function(canvas) {
-            if (jQuery.jqplot.use_excanvas) {
+            if ($.jqplot.use_excanvas) {
                 return window.G_vmlCanvasManager.initElement(canvas);
             }
             return canvas;
@@ -306,13 +306,13 @@
         };
 
         this.freeCanvas = function(idx) {
-            if (jQuery.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
+            if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
                 // excanvas can't be reused, but properly unset
-                window.G_vmlCanvasManager.uninitElement(jQuery.jqplot.CanvasManager.canvases[idx]);
-                jQuery.jqplot.CanvasManager.canvases[idx] = null;
+                window.G_vmlCanvasManager.uninitElement($.jqplot.CanvasManager.canvases[idx]);
+                $.jqplot.CanvasManager.canvases[idx] = null;
             } 
             else {
-                var canvas = jQuery.jqplot.CanvasManager.canvases[idx];
+                var canvas = $.jqplot.CanvasManager.canvases[idx];
                 canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
                 $(canvas).unbind().removeAttr('class').removeAttr('style');
                 // Style attributes seemed to be still hanging around.  wierd.  Some ticks
@@ -321,7 +321,7 @@
                 // setting size to 0 may save memory of unused canvases?
                 canvas.width = 0;
                 canvas.height = 0;
-                jQuery.jqplot.CanvasManager.free[idx] = true;
+                $.jqplot.CanvasManager.free[idx] = true;
             }
         };
         
@@ -329,13 +329,13 @@
 
             
     // Convienence function that won't hang IE or FF without FireBug.
-    jQuery.jqplot.log = function() {
+    $.jqplot.log = function() {
         if (window.console) {
             window.console.log.apply(window.console, arguments);
         }
     };
         
-    jQuery.jqplot.config = {
+    $.jqplot.config = {
         addDomReference: false,
         enablePlugins:false,
         defaultHeight:300,
@@ -361,97 +361,97 @@
     };
     
     
-    jQuery.jqplot.arrayMax = function( array ){
+    $.jqplot.arrayMax = function( array ){
         return Math.max.apply( Math, array );
     };
     
-    jQuery.jqplot.arrayMin = function( array ){
+    $.jqplot.arrayMin = function( array ){
         return Math.min.apply( Math, array );
     };
     
-    jQuery.jqplot.enablePlugins = jQuery.jqplot.config.enablePlugins;
+    $.jqplot.enablePlugins = $.jqplot.config.enablePlugins;
     
     // canvas related tests taken from modernizer:
     // Copyright (c) 2009 - 2010 Faruk Ates.
     // http://www.modernizr.com
     
-    jQuery.jqplot.support_canvas = function() {
-        if (typeof jQuery.jqplot.support_canvas.result == 'undefined') {
-            jQuery.jqplot.support_canvas.result = !!document.createElement('canvas').getContext; 
+    $.jqplot.support_canvas = function() {
+        if (typeof $.jqplot.support_canvas.result == 'undefined') {
+            $.jqplot.support_canvas.result = !!document.createElement('canvas').getContext; 
         }
-        return jQuery.jqplot.support_canvas.result;
+        return $.jqplot.support_canvas.result;
     };
             
-    jQuery.jqplot.support_canvas_text = function() {
-        if (typeof jQuery.jqplot.support_canvas_text.result == 'undefined') {
+    $.jqplot.support_canvas_text = function() {
+        if (typeof $.jqplot.support_canvas_text.result == 'undefined') {
             if (window.G_vmlCanvasManager !== undefined && window.G_vmlCanvasManager._version > 887) {
-                jQuery.jqplot.support_canvas_text.result = true;
+                $.jqplot.support_canvas_text.result = true;
             }
             else {
-                jQuery.jqplot.support_canvas_text.result = !!(document.createElement('canvas').getContext && typeof document.createElement('canvas').getContext('2d').fillText == 'function');
+                $.jqplot.support_canvas_text.result = !!(document.createElement('canvas').getContext && typeof document.createElement('canvas').getContext('2d').fillText == 'function');
             }
              
         }
-        return jQuery.jqplot.support_canvas_text.result;
+        return $.jqplot.support_canvas_text.result;
     };
     
-    jQuery.jqplot.use_excanvas = (jQuery.browser.msie && !jQuery.jqplot.support_canvas()) ? true : false;
+    $.jqplot.use_excanvas = ((!$.support.boxModel || !$.support.objectAll || !$support.leadingWhitespace) && !$.jqplot.support_canvas()) ? true : false;
     
     /**
      * 
      * Hooks: jqPlot Pugin Hooks
      * 
-     * jQuery.jqplot.preInitHooks - called before initialization.
-     * jQuery.jqplot.postInitHooks - called after initialization.
-     * jQuery.jqplot.preParseOptionsHooks - called before user options are parsed.
-     * jQuery.jqplot.postParseOptionsHooks - called after user options are parsed.
-     * jQuery.jqplot.preDrawHooks - called before plot draw.
-     * jQuery.jqplot.postDrawHooks - called after plot draw.
-     * jQuery.jqplot.preDrawSeriesHooks - called before each series is drawn.
-     * jQuery.jqplot.postDrawSeriesHooks - called after each series is drawn.
-     * jQuery.jqplot.preDrawLegendHooks - called before the legend is drawn.
-     * jQuery.jqplot.addLegendRowHooks - called at the end of legend draw, so plugins
+     * $.jqplot.preInitHooks - called before initialization.
+     * $.jqplot.postInitHooks - called after initialization.
+     * $.jqplot.preParseOptionsHooks - called before user options are parsed.
+     * $.jqplot.postParseOptionsHooks - called after user options are parsed.
+     * $.jqplot.preDrawHooks - called before plot draw.
+     * $.jqplot.postDrawHooks - called after plot draw.
+     * $.jqplot.preDrawSeriesHooks - called before each series is drawn.
+     * $.jqplot.postDrawSeriesHooks - called after each series is drawn.
+     * $.jqplot.preDrawLegendHooks - called before the legend is drawn.
+     * $.jqplot.addLegendRowHooks - called at the end of legend draw, so plugins
      *     can add rows to the legend table.
-     * jQuery.jqplot.preSeriesInitHooks - called before series is initialized.
-     * jQuery.jqplot.postSeriesInitHooks - called after series is initialized.
-     * jQuery.jqplot.preParseSeriesOptionsHooks - called before series related options
+     * $.jqplot.preSeriesInitHooks - called before series is initialized.
+     * $.jqplot.postSeriesInitHooks - called after series is initialized.
+     * $.jqplot.preParseSeriesOptionsHooks - called before series related options
      *     are parsed.
-     * jQuery.jqplot.postParseSeriesOptionsHooks - called after series related options
+     * $.jqplot.postParseSeriesOptionsHooks - called after series related options
      *     are parsed.
-     * jQuery.jqplot.eventListenerHooks - called at the end of plot drawing, binds
+     * $.jqplot.eventListenerHooks - called at the end of plot drawing, binds
      *     listeners to the event canvas which lays on top of the grid area.
-     * jQuery.jqplot.preDrawSeriesShadowHooks - called before series shadows are drawn.
-     * jQuery.jqplot.postDrawSeriesShadowHooks - called after series shadows are drawn.
+     * $.jqplot.preDrawSeriesShadowHooks - called before series shadows are drawn.
+     * $.jqplot.postDrawSeriesShadowHooks - called after series shadows are drawn.
      * 
      */
     
-    jQuery.jqplot.preInitHooks = [];
-    jQuery.jqplot.postInitHooks = [];
-    jQuery.jqplot.preParseOptionsHooks = [];
-    jQuery.jqplot.postParseOptionsHooks = [];
-    jQuery.jqplot.preDrawHooks = [];
-    jQuery.jqplot.postDrawHooks = [];
-    jQuery.jqplot.preDrawSeriesHooks = [];
-    jQuery.jqplot.postDrawSeriesHooks = [];
-    jQuery.jqplot.preDrawLegendHooks = [];
-    jQuery.jqplot.addLegendRowHooks = [];
-    jQuery.jqplot.preSeriesInitHooks = [];
-    jQuery.jqplot.postSeriesInitHooks = [];
-    jQuery.jqplot.preParseSeriesOptionsHooks = [];
-    jQuery.jqplot.postParseSeriesOptionsHooks = [];
-    jQuery.jqplot.eventListenerHooks = [];
-    jQuery.jqplot.preDrawSeriesShadowHooks = [];
-    jQuery.jqplot.postDrawSeriesShadowHooks = [];
+    $.jqplot.preInitHooks = [];
+    $.jqplot.postInitHooks = [];
+    $.jqplot.preParseOptionsHooks = [];
+    $.jqplot.postParseOptionsHooks = [];
+    $.jqplot.preDrawHooks = [];
+    $.jqplot.postDrawHooks = [];
+    $.jqplot.preDrawSeriesHooks = [];
+    $.jqplot.postDrawSeriesHooks = [];
+    $.jqplot.preDrawLegendHooks = [];
+    $.jqplot.addLegendRowHooks = [];
+    $.jqplot.preSeriesInitHooks = [];
+    $.jqplot.postSeriesInitHooks = [];
+    $.jqplot.preParseSeriesOptionsHooks = [];
+    $.jqplot.postParseSeriesOptionsHooks = [];
+    $.jqplot.eventListenerHooks = [];
+    $.jqplot.preDrawSeriesShadowHooks = [];
+    $.jqplot.postDrawSeriesShadowHooks = [];
 
     // A superclass holding some common properties and methods.
-    jQuery.jqplot.ElemContainer = function() {
+    $.jqplot.ElemContainer = function() {
         this._elem;
         this._plotWidth;
         this._plotHeight;
         this._plotDimensions = {height:null, width:null};
     };
     
-    jQuery.jqplot.ElemContainer.prototype.createElement = function(el, offsets, clss, cssopts, attrib) {
+    $.jqplot.ElemContainer.prototype.createElement = function(el, offsets, clss, cssopts, attrib) {
         this._offsets = offsets;
         var klass = clss || 'jqplot';
         var elem = document.createElement(el);
@@ -464,7 +464,7 @@
         return this._elem;
     };
     
-    jQuery.jqplot.ElemContainer.prototype.getWidth = function() {
+    $.jqplot.ElemContainer.prototype.getWidth = function() {
         if (this._elem) {
             return this._elem.outerWidth(true);
         }
@@ -473,7 +473,7 @@
         }
     };
     
-    jQuery.jqplot.ElemContainer.prototype.getHeight = function() {
+    $.jqplot.ElemContainer.prototype.getHeight = function() {
         if (this._elem) {
             return this._elem.outerHeight(true);
         }
@@ -482,7 +482,7 @@
         }
     };
     
-    jQuery.jqplot.ElemContainer.prototype.getPosition = function() {
+    $.jqplot.ElemContainer.prototype.getPosition = function() {
         if (this._elem) {
             return this._elem.position();
         }
@@ -491,19 +491,19 @@
         }
     };
     
-    jQuery.jqplot.ElemContainer.prototype.getTop = function() {
+    $.jqplot.ElemContainer.prototype.getTop = function() {
         return this.getPosition().top;
     };
     
-    jQuery.jqplot.ElemContainer.prototype.getLeft = function() {
+    $.jqplot.ElemContainer.prototype.getLeft = function() {
         return this.getPosition().left;
     };
     
-    jQuery.jqplot.ElemContainer.prototype.getBottom = function() {
+    $.jqplot.ElemContainer.prototype.getBottom = function() {
         return this._elem.css('bottom');
     };
     
-    jQuery.jqplot.ElemContainer.prototype.getRight = function() {
+    $.jqplot.ElemContainer.prototype.getRight = function() {
         return this._elem.css('right');
     };
     
@@ -511,12 +511,12 @@
     /**
      * Class: Axis
      * An individual axis object.  Cannot be instantiated directly, but created
-     * by the Plot oject.  Axis properties can be set or overriden by the 
+     * by the Plot object.  Axis properties can be set or overridden by the 
      * options passed in from the user.
      * 
      */
     function Axis(name) {
-        jQuery.jqplot.ElemContainer.call(this);
+        $.jqplot.ElemContainer.call(this);
         // Group: Properties
         //
         // Axes options are specified within an axes object at the top level of the 
@@ -538,14 +538,14 @@
         this.show = false;
         // prop: tickRenderer
         // A class of a rendering engine for creating the ticks labels displayed on the plot, 
-        // See <jQuery.jqplot.AxisTickRenderer>.
-        this.tickRenderer = jQuery.jqplot.AxisTickRenderer;
+        // See <$.jqplot.AxisTickRenderer>.
+        this.tickRenderer = $.jqplot.AxisTickRenderer;
         // prop: tickOptions
-        // Options that will be passed to the tickRenderer, see <jQuery.jqplot.AxisTickRenderer> options.
+        // Options that will be passed to the tickRenderer, see <$.jqplot.AxisTickRenderer> options.
         this.tickOptions = {};
         // prop: labelRenderer
         // A class of a rendering engine for creating an axis label.
-        this.labelRenderer = jQuery.jqplot.AxisLabelRenderer;
+        this.labelRenderer = $.jqplot.AxisLabelRenderer;
         // prop: labelOptions
         // Options passed to the label renderer.
         this.labelOptions = {};
@@ -593,9 +593,9 @@
         // prop: renderer
         // A class of a rendering engine that handles tick generation, 
         // scaling input data to pixel grid units and drawing the axis element.
-        this.renderer = jQuery.jqplot.LinearAxisRenderer;
+        this.renderer = $.jqplot.LinearAxisRenderer;
         // prop: rendererOptions
-        // renderer specific options.  See <jQuery.jqplot.LinearAxisRenderer> for options.
+        // renderer specific options.  See <$.jqplot.LinearAxisRenderer> for options.
         this.rendererOptions = {};
         // prop: showTicks
         // Wether to show the ticks (both marks and labels) or not.
@@ -664,11 +664,11 @@
         this._options = {};
     }
     
-    Axis.prototype = new jQuery.jqplot.ElemContainer();
+    Axis.prototype = new $.jqplot.ElemContainer();
     Axis.prototype.constructor = Axis;
     
     Axis.prototype.init = function() {
-        if (jQuery.isFunction(this.renderer)) {
+        if ($.isFunction(this.renderer)) {
             this.renderer = new this.renderer();  
         }
         // set the axis name
@@ -763,7 +763,7 @@
     };
     
     Axis.prototype.resetScale = function(opts) {
-        jQuery.extend(true, this, {min: null, max: null, numberTicks: null, tickInterval: null, _ticks: [], ticks: []}, opts);
+        $.extend(true, this, {min: null, max: null, numberTicks: null, tickInterval: null, _ticks: [], ticks: []}, opts);
         this.resetDataBounds();
     };
     
@@ -814,7 +814,7 @@
                 // every series will have a chance to set doforce to false.  once it is set to 
                 // false, it cannot be reset to true.
                 // If any series attached to axis is not a bar, wont force 0.
-                if (doforce && s.renderer.constructor !== jQuery.jqplot.BarRenderer) {
+                if (doforce && s.renderer.constructor !== $.jqplot.BarRenderer) {
                     doforce = false;
                 }
 
@@ -822,7 +822,7 @@
                     doforce = false;
                 }
 
-                else if (doforce && s.renderer.constructor === jQuery.jqplot.BarRenderer) {
+                else if (doforce && s.renderer.constructor === $.jqplot.BarRenderer) {
                     if (s.barDirection == 'vertical' && this.name != 'xaxis' && this.name != 'x2axis') { 
                         if (this._options.pad != null || this._options.padMin != null) {
                             doforce = false;
@@ -839,7 +839,7 @@
             }
         }
 
-        if (doforce && this.renderer.constructor === jQuery.jqplot.LinearAxisRenderer && db.min >= 0) {
+        if (doforce && this.renderer.constructor === $.jqplot.LinearAxisRenderer && db.min >= 0) {
             this.padMin = 1.0;
             this.forceTickAt0 = true;
         }
@@ -848,11 +848,11 @@
     /**
      * Class: Legend
      * Legend object.  Cannot be instantiated directly, but created
-     * by the Plot oject.  Legend properties can be set or overriden by the 
+     * by the Plot object.  Legend properties can be set or overridden by the 
      * options passed in from the user.
      */
     function Legend(options) {
-        jQuery.jqplot.ElemContainer.call(this);
+        $.jqplot.ElemContainer.call(this);
         // Group: Properties
         
         // prop: show
@@ -907,8 +907,8 @@
         this.rowSpacing = '0.5em';
         // renderer
         // A class that will create a DOM object for the legend,
-        // see <jQuery.jqplot.TableLegendRenderer>.
-        this.renderer = jQuery.jqplot.TableLegendRenderer;
+        // see <$.jqplot.TableLegendRenderer>.
+        this.renderer = $.jqplot.TableLegendRenderer;
         // prop: rendererOptions
         // renderer specific options passed to the renderer.
         this.rendererOptions = {};
@@ -942,14 +942,14 @@
         this.escapeHtml = false;
         this._series = [];
         
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
     }
     
-    Legend.prototype = new jQuery.jqplot.ElemContainer();
+    Legend.prototype = new $.jqplot.ElemContainer();
     Legend.prototype.constructor = Legend;
     
     Legend.prototype.setOptions = function(options) {
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
         
         // Try to emulate deprecated behaviour
         // if user has specified xoffset or yoffset, copy these to
@@ -1064,8 +1064,8 @@
     };
     
     Legend.prototype.draw = function(offsets, plot) {
-        for (var i=0; i<jQuery.jqplot.preDrawLegendHooks.length; i++){
-            jQuery.jqplot.preDrawLegendHooks[i].call(this, offsets);
+        for (var i=0; i<$.jqplot.preDrawLegendHooks.length; i++){
+            $.jqplot.preDrawLegendHooks[i].call(this, offsets);
         }
         return this.renderer.draw.call(this, offsets, plot);
     };
@@ -1077,21 +1077,21 @@
     /**
      * Class: Title
      * Plot Title object.  Cannot be instantiated directly, but created
-     * by the Plot oject.  Title properties can be set or overriden by the 
+     * by the Plot object.  Title properties can be set or overridden by the 
      * options passed in from the user.
      * 
      * Parameters:
      * text - text of the title.
      */
     function Title(text) {
-        jQuery.jqplot.ElemContainer.call(this);
+        $.jqplot.ElemContainer.call(this);
         // Group: Properties
         
         // prop: text
         // text of the title;
         this.text = text;
         // prop: show
-        // wether or not to show the title
+        // whether or not to show the title
         this.show = true;
         // prop: fontFamily
         // css font-family spec for the text.
@@ -1107,8 +1107,8 @@
         this.textColor;
         // prop: renderer
         // A class for creating a DOM element for the title,
-        // see <jQuery.jqplot.DivTitleRenderer>.
-        this.renderer = jQuery.jqplot.DivTitleRenderer;
+        // see <$.jqplot.DivTitleRenderer>.
+        this.renderer = $.jqplot.DivTitleRenderer;
         // prop: rendererOptions
         // renderer specific options passed to the renderer.
         this.rendererOptions = {};   
@@ -1118,7 +1118,7 @@
         this.escapeHtml = false;
     }
     
-    Title.prototype = new jQuery.jqplot.ElemContainer();
+    Title.prototype = new $.jqplot.ElemContainer();
     Title.prototype.constructor = Title;
     
     Title.prototype.init = function() {
@@ -1140,12 +1140,12 @@
     /**
      * Class: Series
      * An individual data series object.  Cannot be instantiated directly, but created
-     * by the Plot oject.  Series properties can be set or overriden by the 
+     * by the Plot object.  Series properties can be set or overridden by the 
      * options passed in from the user.
      */
     function Series(options) {
         options = options || {};
-        jQuery.jqplot.ElemContainer.call(this);
+        $.jqplot.ElemContainer.call(this);
         // Group: Properties
         // Properties will be assigned from a series array at the top level of the
         // options.  If you had two series and wanted to change the color and line
@@ -1159,7 +1159,7 @@
         // > }
 
         // prop: show
-        // wether or not to draw the series.
+        // whether or not to draw the series.
         this.show = true;
         // prop: xaxis
         // which x axis to use with this series, either 'xaxis' or 'x2axis'.
@@ -1172,8 +1172,8 @@
         this.gridBorderWidth = 2.0;
         // prop: renderer
         // A class of a renderer which will draw the series, 
-        // see <jQuery.jqplot.LineRenderer>.
-        this.renderer = jQuery.jqplot.LineRenderer;
+        // see <$.jqplot.LineRenderer>.
+        this.renderer = $.jqplot.LineRenderer;
         // prop: rendererOptions
         // Options to pass on to the renderer.
         this.rendererOptions = {};
@@ -1226,23 +1226,23 @@
         this.breakOnNull = false;
         // prop: markerRenderer
         // A class of a renderer which will draw marker (e.g. circle, square, ...) at the data points,
-        // see <jQuery.jqplot.MarkerRenderer>.
-        this.markerRenderer = jQuery.jqplot.MarkerRenderer;
+        // see <$.jqplot.MarkerRenderer>.
+        this.markerRenderer = $.jqplot.MarkerRenderer;
         // prop: markerOptions
         // renderer specific options to pass to the markerRenderer,
-        // see <jQuery.jqplot.MarkerRenderer>.
+        // see <$.jqplot.MarkerRenderer>.
         this.markerOptions = {};
         // prop: showLine
-        // wether to actually draw the line or not.  Series will still be renderered, even if no line is drawn.
+        // whether to actually draw the line or not.  Series will still be renderered, even if no line is drawn.
         this.showLine = true;
         // prop: showMarker
-        // wether or not to show the markers at the data points.
+        // whether or not to show the markers at the data points.
         this.showMarker = true;
         // prop: index
         // 0 based index of this series in the plot series array.
         this.index;
         // prop: fill
-        // true or false, wether to fill under lines or in bars.
+        // true or false, whether to fill under lines or in bars.
         // May not be implemented in all renderers.
         this.fill = false;
         // prop: fillColor
@@ -1300,8 +1300,8 @@
         this._stackAxis = 'y';
         this._primaryAxis = '_xaxis';
         // give each series a canvas to draw on.  This should allow for redrawing speedups.
-        this.canvas = new jQuery.jqplot.GenericCanvas();
-        this.shadowCanvas = new jQuery.jqplot.GenericCanvas();
+        this.canvas = new $.jqplot.GenericCanvas();
+        this.shadowCanvas = new $.jqplot.GenericCanvas();
         this.plugins = {};
         // sum of y values in this series.
         this._sumy = 0;
@@ -1309,7 +1309,7 @@
         this._type = '';
     }
     
-    Series.prototype = new jQuery.jqplot.ElemContainer();
+    Series.prototype = new $.jqplot.ElemContainer();
     Series.prototype.constructor = Series;
     
     Series.prototype.init = function(index, gridbw, plot) {
@@ -1353,8 +1353,8 @@
             this.fillColor = this.color;
         }
         if (this.fillAlpha) {
-            var comp = jQuery.jqplot.normalize2rgb(this.fillColor);
-            var comp = jQuery.jqplot.getColorComponents(comp);
+            var comp = $.jqplot.normalize2rgb(this.fillColor);
+            var comp = $.jqplot.getColorComponents(comp);
             this.fillColor = 'rgba('+comp[0]+','+comp[1]+','+comp[2]+','+this.fillAlpha+')';
         }
         if ($.isFunction(this.renderer)) {
@@ -1369,7 +1369,7 @@
             this.markerOptions.show = this.showMarker;
         }
         this.showMarker = this.markerOptions.show;
-        // the markerRenderer is called within it's own scaope, don't want to overwrite series options!!
+        // the markerRenderer is called within its own scope, don't want to overwrite series options!!
         this.markerRenderer.init(this.markerOptions);
     };
     
@@ -1384,8 +1384,8 @@
         
         // hooks get called even if series not shown
         // we don't clear canvas here, it would wipe out all other series as well.
-        for (j=0; j<jQuery.jqplot.preDrawSeriesHooks.length; j++) {
-            jQuery.jqplot.preDrawSeriesHooks[j].call(this, sctx, options);
+        for (j=0; j<$.jqplot.preDrawSeriesHooks.length; j++) {
+            $.jqplot.preDrawSeriesHooks[j].call(this, sctx, options);
         }
         if (this.show) {
             this.renderer.setGridData.call(this, plot);
@@ -1411,8 +1411,8 @@
             this.renderer.draw.call(this, sctx, gridData, options, plot);
         }
         
-        for (j=0; j<jQuery.jqplot.postDrawSeriesHooks.length; j++) {
-            jQuery.jqplot.postDrawSeriesHooks[j].call(this, sctx, options, plot);
+        for (j=0; j<$.jqplot.postDrawSeriesHooks.length; j++) {
+            $.jqplot.postDrawSeriesHooks[j].call(this, sctx, options, plot);
         }
         
         sctx = opts = plot = j = data = gridData = null;
@@ -1426,8 +1426,8 @@
         
         // hooks get called even if series not shown
         // we don't clear canvas here, it would wipe out all other series as well.
-        for (j=0; j<jQuery.jqplot.preDrawSeriesShadowHooks.length; j++) {
-            jQuery.jqplot.preDrawSeriesShadowHooks[j].call(this, sctx, options);
+        for (j=0; j<$.jqplot.preDrawSeriesShadowHooks.length; j++) {
+            $.jqplot.preDrawSeriesShadowHooks[j].call(this, sctx, options);
         }
         if (this.shadow) {
             this.renderer.setGridData.call(this, plot);
@@ -1447,8 +1447,8 @@
             this.renderer.drawShadow.call(this, sctx, gridData, options, plot);
         }
         
-        for (j=0; j<jQuery.jqplot.postDrawSeriesShadowHooks.length; j++) {
-            jQuery.jqplot.postDrawSeriesShadowHooks[j].call(this, sctx, options);
+        for (j=0; j<$.jqplot.postDrawSeriesShadowHooks.length; j++) {
+            $.jqplot.postDrawSeriesShadowHooks[j].call(this, sctx, options);
         }
         
         sctx = opts = plot = j = data = gridData = null;
@@ -1524,15 +1524,15 @@
      * Object representing the grid on which the plot is drawn.  The grid in this
      * context is the area bounded by the axes, the area which will contain the series.
      * Note, the series are drawn on their own canvas.
-     * The Grid object cannot be instantiated directly, but is created by the Plot oject.  
-     * Grid properties can be set or overriden by the options passed in from the user.
+     * The Grid object cannot be instantiated directly, but is created by the Plot object.  
+     * Grid properties can be set or overridden by the options passed in from the user.
      */
     function Grid() {
-        jQuery.jqplot.ElemContainer.call(this);
+        $.jqplot.ElemContainer.call(this);
         // Group: Properties
         
         // prop: drawGridlines
-        // wether to draw the gridlines on the plot.
+        // whether to draw the gridlines on the plot.
         this.drawGridlines = true;
         // prop: gridLineColor
         // color of the grid lines.
@@ -1553,7 +1553,7 @@
         // True to draw border around grid.
         this.drawBorder = true;
         // prop: shadow
-        // wether to show a shadow behind the grid.
+        // whether to show a shadow behind the grid.
         this.shadow = true;
         // prop: shadowAngle
         // shadow angle in degrees
@@ -1582,16 +1582,16 @@
         this._axes = [];
         // prop: renderer
         // Instance of a renderer which will actually render the grid,
-        // see <jQuery.jqplot.CanvasGridRenderer>.
-        this.renderer = jQuery.jqplot.CanvasGridRenderer;
+        // see <$.jqplot.CanvasGridRenderer>.
+        this.renderer = $.jqplot.CanvasGridRenderer;
         // prop: rendererOptions
         // Options to pass on to the renderer,
-        // see <jQuery.jqplot.CanvasGridRenderer>.
+        // see <$.jqplot.CanvasGridRenderer>.
         this.rendererOptions = {};
         this._offsets = {top:null, bottom:null, left:null, right:null};
     }
     
-    Grid.prototype = new jQuery.jqplot.ElemContainer();
+    Grid.prototype = new $.jqplot.ElemContainer();
     Grid.prototype.constructor = Grid;
     
     Grid.prototype.init = function() {
@@ -1610,15 +1610,15 @@
         this.renderer.draw.call(this);
     };
     
-    jQuery.jqplot.GenericCanvas = function() {
-        jQuery.jqplot.ElemContainer.call(this);
+    $.jqplot.GenericCanvas = function() {
+        $.jqplot.ElemContainer.call(this);
         this._ctx;  
     };
     
-    jQuery.jqplot.GenericCanvas.prototype = new jQuery.jqplot.ElemContainer();
-    jQuery.jqplot.GenericCanvas.prototype.constructor = jQuery.jqplot.GenericCanvas;
+    $.jqplot.GenericCanvas.prototype = new $.jqplot.ElemContainer();
+    $.jqplot.GenericCanvas.prototype.constructor = $.jqplot.GenericCanvas;
     
-    jQuery.jqplot.GenericCanvas.prototype.createElement = function(offsets, clss, plotDimensions, plot) {
+    $.jqplot.GenericCanvas.prototype.createElement = function(offsets, clss, plotDimensions, plot) {
         this._offsets = offsets;
         var klass = 'jqplot';
         if (clss != undefined) {
@@ -1646,15 +1646,15 @@
         return this._elem;
     };
     
-    jQuery.jqplot.GenericCanvas.prototype.setContext = function() {
+    $.jqplot.GenericCanvas.prototype.setContext = function() {
         this._ctx = this._elem.get(0).getContext("2d");
         return this._ctx;
     };
     
     // Memory Leaks patch
-    jQuery.jqplot.GenericCanvas.prototype.resetCanvas = function() {
+    $.jqplot.GenericCanvas.prototype.resetCanvas = function() {
       if (this._elem) {
-        if (jQuery.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
+        if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
            window.G_vmlCanvasManager.uninitElement(this._elem.get(0));
         }
         
@@ -1665,12 +1665,12 @@
       this._ctx = null;
     };
     
-    jQuery.jqplot.HooksManager = function () {
+    $.jqplot.HooksManager = function () {
         this.hooks =[];
         this.args = [];
     };
     
-    jQuery.jqplot.HooksManager.prototype.addOnce = function(fn, args) {
+    $.jqplot.HooksManager.prototype.addOnce = function(fn, args) {
         args = args || [];
         var havehook = false;
         for (var i=0, l=this.hooks.length; i<l; i++) {
@@ -1684,17 +1684,17 @@
         }
     };
     
-    jQuery.jqplot.HooksManager.prototype.add = function(fn, args) {
+    $.jqplot.HooksManager.prototype.add = function(fn, args) {
         args = args || [];
         this.hooks.push(fn);
         this.args.push(args);
     };
     
-    jQuery.jqplot.EventListenerManager = function () {
+    $.jqplot.EventListenerManager = function () {
         this.hooks =[];
     };
     
-    jQuery.jqplot.EventListenerManager.prototype.addOnce = function(ev, fn) {
+    $.jqplot.EventListenerManager.prototype.addOnce = function(ev, fn) {
         var havehook = false, h, i;
         for (var i=0, l=this.hooks.length; i<l; i++) {
             h = this.hooks[i];
@@ -1707,7 +1707,7 @@
         }
     };
     
-    jQuery.jqplot.EventListenerManager.prototype.add = function(ev, fn) {
+    $.jqplot.EventListenerManager.prototype.add = function(ev, fn) {
         this.hooks.push([ev, fn]);
     };
 
@@ -1716,7 +1716,7 @@
 
     /**
      * Class: jqPlot
-     * Plot object returned by call to jQuery.jqplot.  Handles parsing user options,
+     * Plot object returned by call to $.jqplot.  Handles parsing user options,
      * creating sub objects (Axes, legend, title, series) and rendering the plot.
      */
     function jqPlot() {
@@ -1741,23 +1741,24 @@
         // animation in these situations can cause problems.
         this.animateReplot = false;
         // prop: axes
-        // up to 4 axes are supported, each with it's own options, 
+        // up to 4 axes are supported, each with its own options, 
         // See <Axis> for axis specific options.
         this.axes = {xaxis: new Axis('xaxis'), yaxis: new Axis('yaxis'), x2axis: new Axis('x2axis'), y2axis: new Axis('y2axis'), y3axis: new Axis('y3axis'), y4axis: new Axis('y4axis'), y5axis: new Axis('y5axis'), y6axis: new Axis('y6axis'), y7axis: new Axis('y7axis'), y8axis: new Axis('y8axis'), y9axis: new Axis('y9axis'), yMidAxis: new Axis('yMidAxis')};
-        this.baseCanvas = new jQuery.jqplot.GenericCanvas();
+        this.baseCanvas = new $.jqplot.GenericCanvas();
         // true to intercept right click events and fire a 'jqplotRightClick' event.
         // this will also block the context menu.
         this.captureRightClick = false;
         // prop: data
         // user's data.  Data should *NOT* be specified in the options object,
-        // but be passed in as the second argument to the jQuery.jqplot() function.
+        // but be passed in as the second argument to the $.jqplot() function.
         // The data property is described here soley for reference. 
         // The data should be in the form of an array of 2D or 1D arrays like
         // > [ [[x1, y1], [x2, y2],...], [y1, y2, ...] ].
         this.data = [];
         // prop: dataRenderer
         // A callable which can be used to preprocess data passed into the plot.
-        // Will be called with 2 arguments, the plot data and a reference to the plot.
+        // Will be called with 3 arguments: the plot data, a reference to the plot,
+        // and the value of dataRendererOptions.
         this.dataRenderer;
         // prop: dataRendererOptions
         // Options that will be passed to the dataRenderer.
@@ -1788,7 +1789,7 @@
         // positioned correclty if renderered into a hidden container.  To render into
         // a hidden container, call the replot method when the container is shown.
         this.drawIfHidden = false;
-        this.eventCanvas = new jQuery.jqplot.GenericCanvas();
+        this.eventCanvas = new $.jqplot.GenericCanvas();
         // prop: fillBetween
         // Fill between 2 line series in a plot.
         // Options object:
@@ -1816,11 +1817,10 @@
         // See <Grid> for grid specific options.
         this.grid = new Grid();
         // prop: legend
-        // see <jQuery.jqplot.TableLegendRenderer>
+        // see <$.jqplot.TableLegendRenderer>
         this.legend = new Legend();
         // prop: noDataIndicator
         // Options to set up a mock plot with a data loading indicator if no data is specified.
-        this.negativeSeriesColors = jQuery.jqplot.config.defaultNegativeColors;
         this.noDataIndicator = {    
             show: false,
             indicator: 'Loading Data...',
@@ -1839,16 +1839,19 @@
                 }
             }
         };
+        // prop: negativeSeriesColors 
+        // colors to use for portions of the line below zero.
+        this.negativeSeriesColors = $.jqplot.config.defaultNegativeColors;
         // container to hold all of the merged options.  Convienence for plugins.
         this.options = {};
         this.previousSeriesStack = [];
-        // Namespece to hold plugins.  Generally non-renderer plugins add themselves to here.
+        // Namespace to hold plugins.  Generally non-renderer plugins add themselves to here.
         this.plugins = {};
         // prop: series
         // Array of series object options.
         // see <Series> for series specific options.
         this.series = [];
-        // array of series indicies. Keep track of order
+        // array of series indices. Keep track of order
         // which series canvases are displayed, lowest
         // to highest, back to front.
         this.seriesStack = [];
@@ -1857,10 +1860,10 @@
         // to the series in the plot.  Colors will wrap around so, if their
         // are more series than colors, colors will be reused starting at the
         // beginning.  For pie charts, this specifies the colors of the slices.
-        this.seriesColors = jQuery.jqplot.config.defaultColors;
+        this.seriesColors = $.jqplot.config.defaultColors;
         // prop: sortData
         // false to not sort the data passed in by the user.
-        // Many bar, stakced and other graphs as well as many plugins depend on
+        // Many bar, stacked and other graphs as well as many plugins depend on
         // having sorted data.
         this.sortData = true;
         // prop: stackSeries
@@ -1887,7 +1890,7 @@
         // Mostly used to test if plot has never been dran (=0), has been successfully drawn
         // into a visible container once (=1) or draw more than once into a visible container.
         // Can use this in tests to see if plot has been visibly drawn at least one time.
-        // After plot has been visibly drawn once, it generally doesn't need redrawn if its
+        // After plot has been visibly drawn once, it generally doesn't need redrawing if its
         // container is hidden and shown.
         this._drawCount = 0;
         // sum of y values for all series in plot.
@@ -1907,32 +1910,32 @@
         this._gridPadding = {top:null, right:null, bottom:null, left:null};
         this._defaultGridPadding = {top:10, right:10, bottom:23, left:10};
 
-        this._addDomReference = jQuery.jqplot.config.addDomReference;
-
-        this.preInitHooks = new jQuery.jqplot.HooksManager();
-        this.postInitHooks = new jQuery.jqplot.HooksManager();
-        this.preParseOptionsHooks = new jQuery.jqplot.HooksManager();
-        this.postParseOptionsHooks = new jQuery.jqplot.HooksManager();
-        this.preDrawHooks = new jQuery.jqplot.HooksManager();
-        this.postDrawHooks = new jQuery.jqplot.HooksManager();
-        this.preDrawSeriesHooks = new jQuery.jqplot.HooksManager();
-        this.postDrawSeriesHooks = new jQuery.jqplot.HooksManager();
-        this.preDrawLegendHooks = new jQuery.jqplot.HooksManager();
-        this.addLegendRowHooks = new jQuery.jqplot.HooksManager();
-        this.preSeriesInitHooks = new jQuery.jqplot.HooksManager();
-        this.postSeriesInitHooks = new jQuery.jqplot.HooksManager();
-        this.preParseSeriesOptionsHooks = new jQuery.jqplot.HooksManager();
-        this.postParseSeriesOptionsHooks = new jQuery.jqplot.HooksManager();
-        this.eventListenerHooks = new jQuery.jqplot.EventListenerManager();
-        this.preDrawSeriesShadowHooks = new jQuery.jqplot.HooksManager();
-        this.postDrawSeriesShadowHooks = new jQuery.jqplot.HooksManager();
-        
-        this.colorGenerator = new jQuery.jqplot.ColorGenerator();
-        this.negativeColorGenerator = new jQuery.jqplot.ColorGenerator();
-
-        this.canvasManager = new jQuery.jqplot.CanvasManager();
-
-        this.themeEngine = new jQuery.jqplot.ThemeEngine();
+        this._addDomReference = $.jqplot.config.addDomReference;
+
+        this.preInitHooks = new $.jqplot.HooksManager();
+        this.postInitHooks = new $.jqplot.HooksManager();
+        this.preParseOptionsHooks = new $.jqplot.HooksManager();
+        this.postParseOptionsHooks = new $.jqplot.HooksManager();
+        this.preDrawHooks = new $.jqplot.HooksManager();
+        this.postDrawHooks = new $.jqplot.HooksManager();
+        this.preDrawSeriesHooks = new $.jqplot.HooksManager();
+        this.postDrawSeriesHooks = new $.jqplot.HooksManager();
+        this.preDrawLegendHooks = new $.jqplot.HooksManager();
+        this.addLegendRowHooks = new $.jqplot.HooksManager();
+        this.preSeriesInitHooks = new $.jqplot.HooksManager();
+        this.postSeriesInitHooks = new $.jqplot.HooksManager();
+        this.preParseSeriesOptionsHooks = new $.jqplot.HooksManager();
+        this.postParseSeriesOptionsHooks = new $.jqplot.HooksManager();
+        this.eventListenerHooks = new $.jqplot.EventListenerManager();
+        this.preDrawSeriesShadowHooks = new $.jqplot.HooksManager();
+        this.postDrawSeriesShadowHooks = new $.jqplot.HooksManager();
+        
+        this.colorGenerator = new $.jqplot.ColorGenerator();
+        this.negativeColorGenerator = new $.jqplot.ColorGenerator();
+
+        this.canvasManager = new $.jqplot.CanvasManager();
+
+        this.themeEngine = new $.jqplot.ThemeEngine();
         
         var seriesColorsIndex = 0;
 
@@ -1943,8 +1946,8 @@
         // options to plot.
         this.init = function(target, data, options) {
             options = options || {};
-            for (var i=0; i<jQuery.jqplot.preInitHooks.length; i++) {
-                jQuery.jqplot.preInitHooks[i].call(this, target, data, options);
+            for (var i=0; i<$.jqplot.preInitHooks.length; i++) {
+                $.jqplot.preInitHooks[i].call(this, target, data, options);
             }
 
             for (var i=0; i<this.preInitHooks.hooks.length; i++) {
@@ -1963,7 +1966,7 @@
             // remove any error class that may be stuck on target.
             this.target.removeClass('jqplot-error');
             if (!this.target.get(0)) {
-                throw "No plot target specified";
+                throw new Error("No plot target specified");
             }
             
             // make sure the target is positioned by some means and set css
@@ -1984,7 +1987,7 @@
                     h = parseInt(this.target.attr('data-height'), 10);
                 }
                 else {
-                    h = parseInt(jQuery.jqplot.config.defaultHeight, 10);
+                    h = parseInt($.jqplot.config.defaultHeight, 10);
                 }
                 this._height = h;
                 this.target.css('height', h+'px');
@@ -2001,7 +2004,7 @@
                     w = parseInt(this.target.attr('data-width'), 10);
                 }
                 else {
-                    w = parseInt(jQuery.jqplot.config.defaultWidth, 10);
+                    w = parseInt($.jqplot.config.defaultWidth, 10);
                 }
                 this._width = w;
                 this.target.css('width', w+'px');
@@ -2022,7 +2025,7 @@
             this.eventCanvas._plotDimensions = this._plotDimensions;
             this.legend._plotDimensions = this._plotDimensions;
             if (this._height <=0 || this._width <=0 || !this._height || !this._width) {
-                throw "Canvas dimension not set";
+                throw new Error("Canvas dimension not set");
             }
             
             if (options.dataRenderer && $.isFunction(options.dataRenderer)) {
@@ -2034,18 +2037,18 @@
             }
             
             if (options.noDataIndicator && $.isPlainObject(options.noDataIndicator)) {
-                jQuery.extend(true, this.noDataIndicator, options.noDataIndicator);
+                $.extend(true, this.noDataIndicator, options.noDataIndicator);
             }
             
             if (data == null || $.isArray(data) == false || data.length == 0 || $.isArray(data[0]) == false || data[0].length == 0) {
                 
                 if (this.noDataIndicator.show == false) {
-                    throw "No Data";
+                    throw new Error("No data specified");
                 }
                 
                 else {
                     // have to be descructive here in order for plot to not try and render series.
-                    // This means that jQuery.jqplot() will have to be called again when there is data.
+                    // This means that $.jqplot() will have to be called again when there is data.
                     //delete options.series;
                     
                     for (var ax in this.noDataIndicator.axes) {
@@ -2078,7 +2081,7 @@
             }
             
             // make a copy of the data
-            this.data = jQuery.extend(true, [], data);
+            this.data = $.extend(true, [], data);
             
             this.parseOptions(options);
             
@@ -2103,8 +2106,8 @@
                 this.previousSeriesStack.push(i);
                 this.series[i].shadowCanvas._plotDimensions = this._plotDimensions;
                 this.series[i].canvas._plotDimensions = this._plotDimensions;
-                for (var j=0; j<jQuery.jqplot.preSeriesInitHooks.length; j++) {
-                    jQuery.jqplot.preSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
+                for (var j=0; j<$.jqplot.preSeriesInitHooks.length; j++) {
+                    $.jqplot.preSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
                 }
                 for (var j=0; j<this.preSeriesInitHooks.hooks.length; j++) {
                     this.preSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
@@ -2112,8 +2115,8 @@
                 // this.populatePlotData(this.series[i], i);
                 this.series[i]._plotDimensions = this._plotDimensions;
                 this.series[i].init(i, this.grid.borderWidth, this);
-                for (var j=0; j<jQuery.jqplot.postSeriesInitHooks.length; j++) {
-                    jQuery.jqplot.postSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
+                for (var j=0; j<$.jqplot.postSeriesInitHooks.length; j++) {
+                    $.jqplot.postSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
                 }
                 for (var j=0; j<this.postSeriesInitHooks.hooks.length; j++) {
                     this.postSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
@@ -2147,8 +2150,8 @@
             
             this.legend._series = this.series;
 
-            for (var i=0; i<jQuery.jqplot.postInitHooks.length; i++) {
-                jQuery.jqplot.postInitHooks[i].call(this, target, this.data, options);
+            for (var i=0; i<$.jqplot.postInitHooks.length; i++) {
+                $.jqplot.postInitHooks[i].call(this, target, this.data, options);
             }
 
             for (var i=0; i<this.postInitHooks.hooks.length; i++) {
@@ -2188,13 +2191,13 @@
             // reason, set it by other means.  Plot must not have
             // a display:none attribute, however.
 
-            var options = jQuery.extend(true, {}, this.options, opts);
+            var options = $.extend(true, {}, this.options, opts);
 
             var target = this.targetId.substr(1);
             var tdata = (data == null) ? this.data : data;
 
-            for (var i=0; i<jQuery.jqplot.preInitHooks.length; i++) {
-                jQuery.jqplot.preInitHooks[i].call(this, target, tdata, options);
+            for (var i=0; i<$.jqplot.preInitHooks.length; i++) {
+                $.jqplot.preInitHooks[i].call(this, target, tdata, options);
             }
 
             for (var i=0; i<this.preInitHooks.hooks.length; i++) {
@@ -2205,7 +2208,7 @@
             this._width = this.target.width();
             
             if (this._height <=0 || this._width <=0 || !this._height || !this._width) {
-                throw "Target dimension not set";
+                throw new Error("Target dimension not set");
             }
             
             this._plotDimensions.height = this._height;
@@ -2231,7 +2234,7 @@
                   var el = t[j]._elem;
                   if (el) {
                     // if canvas renderer
-                    if (jQuery.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
+                    if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
                       window.G_vmlCanvasManager.uninitElement(el.get(0));
                     }
                     el.emptyForce();
@@ -2258,7 +2261,7 @@
                 }
                 
                 // make a copy of the data
-                this.data = jQuery.extend(true, [], data);
+                this.data = $.extend(true, [], data);
             }
 
             if (opts) {
@@ -2292,8 +2295,8 @@
                 this.previousSeriesStack.push(i);
                 this.series[i].shadowCanvas._plotDimensions = this._plotDimensions;
                 this.series[i].canvas._plotDimensions = this._plotDimensions;
-                for (var j=0; j<jQuery.jqplot.preSeriesInitHooks.length; j++) {
-                    jQuery.jqplot.preSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
+                for (var j=0; j<$.jqplot.preSeriesInitHooks.length; j++) {
+                    $.jqplot.preSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
                 }
                 for (var j=0; j<this.preSeriesInitHooks.hooks.length; j++) {
                     this.preSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
@@ -2301,8 +2304,8 @@
                 // this.populatePlotData(this.series[i], i);
                 this.series[i]._plotDimensions = this._plotDimensions;
                 this.series[i].init(i, this.grid.borderWidth, this);
-                for (var j=0; j<jQuery.jqplot.postSeriesInitHooks.length; j++) {
-                    jQuery.jqplot.postSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
+                for (var j=0; j<$.jqplot.postSeriesInitHooks.length; j++) {
+                    $.jqplot.postSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
                 }
                 for (var j=0; j<this.postSeriesInitHooks.hooks.length; j++) {
                     this.postSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);
@@ -2335,8 +2338,8 @@
             
             this.legend._series = this.series;
 
-            for (var i=0, l=jQuery.jqplot.postInitHooks.length; i<l; i++) {
-                jQuery.jqplot.postInitHooks[i].call(this, target, this.data, options);
+            for (var i=0, l=$.jqplot.postInitHooks.length; i<l; i++) {
+                $.jqplot.postInitHooks[i].call(this, target, this.data, options);
             }
 
             for (var i=0, l=this.postInitHooks.hooks.length; i<l; i++) {
@@ -2361,7 +2364,7 @@
             this._width = this.target.width();
             
             if (this._height <=0 || this._width <=0 || !this._height || !this._width) {
-                throw "Target dimension not set";
+                throw new Error("Target dimension not set");
             }
             
             this._plotDimensions.height = this._height;
@@ -2414,7 +2417,7 @@
                   var el = t[i]._elem;
                   if (el) {
                     // if canvas renderer
-                    if (jQuery.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
+                    if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
                       window.G_vmlCanvasManager.uninitElement(el.get(0));
                     }
                     el.emptyForce();
@@ -2487,8 +2490,8 @@
                 this._plotData.push([]);
                 this._stackData.push([]);
                 var cd = series.data;
-                this._plotData[index] = jQuery.extend(true, [], cd);
-                this._stackData[index] = jQuery.extend(true, [], cd);
+                this._plotData[index] = $.extend(true, [], cd);
+                this._stackData[index] = $.extend(true, [], cd);
                 series._plotData = this._plotData[index];
                 series._stackData = this._stackData[index];
                 var plotValues = {x:[], y:[]};
@@ -2563,9 +2566,9 @@
                 // var idx = sidx ? 0 : 1;
                 // push the current data into stackData
                 //this._stackData.push(this.series[i].data);
-                var temp = jQuery.extend(true, [], series.data);
+                var temp = $.extend(true, [], series.data);
                 // create the data that will be plotted for this series
-                var plotdata = jQuery.extend(true, [], series.data);
+                var plotdata = $.extend(true, [], series.data);
                 var tempx, tempy, dval, stackval, comparator;
                 // for first series, nothing to add to stackData.
                 for (var j=0; j<index; j++) {
@@ -2636,10 +2639,10 @@
             for (var i=0; i<this.preParseOptionsHooks.hooks.length; i++) {
                 this.preParseOptionsHooks.hooks[i].call(this, options);
             }
-            for (var i=0; i<jQuery.jqplot.preParseOptionsHooks.length; i++) {
-                jQuery.jqplot.preParseOptionsHooks[i].call(this, options);
+            for (var i=0; i<$.jqplot.preParseOptionsHooks.length; i++) {
+                $.jqplot.preParseOptionsHooks[i].call(this, options);
             }
-            this.options = jQuery.extend(true, {}, this.defaults, options);
+            this.options = $.extend(true, {}, this.defaults, options);
             var opts = this.options;
             this.animate = opts.animate;
             this.animateReplot = opts.animateReplot;
@@ -2672,13 +2675,13 @@
             // var cg = new this.colorGenerator(this.seriesColors);
             // var ncg = new this.colorGenerator(this.negativeSeriesColors);
             // this._gridPadding = this.options.gridPadding;
-            jQuery.extend(true, this._gridPadding, opts.gridPadding);
+            $.extend(true, this._gridPadding, opts.gridPadding);
             this.sortData = (opts.sortData != null) ? opts.sortData : this.sortData;
             for (var i=0; i<12; i++) {
                 var n = _axisNames[i];
                 var axis = this.axes[n];
-                axis._options = jQuery.extend(true, {}, opts.axesDefaults, opts.axes[n]);
-                jQuery.extend(true, axis, opts.axesDefaults, opts.axes[n]);
+                axis._options = $.extend(true, {}, opts.axesDefaults, opts.axes[n]);
+                $.extend(true, axis, opts.axesDefaults, opts.axes[n]);
                 axis._plotWidth = this._width;
                 axis._plotHeight = this._height;
             }
@@ -2710,7 +2713,7 @@
                 }            
                 else {
                     // we have a properly formatted data series, copy it.
-                    jQuery.extend(true, temp, data);
+                    $.extend(true, temp, data);
                 }
                 return temp;
             };
@@ -2718,20 +2721,20 @@
             var colorIndex = 0;
             this.series = [];
             for (var i=0; i<this.data.length; i++) {
-                var sopts = jQuery.extend(true, {index: i}, {seriesColors:this.seriesColors, negativeSeriesColors:this.negativeSeriesColors}, this.options.seriesDefaults, this.options.series[i], {rendererOptions:{animation:{show: this.animate}}});
+                var sopts = $.extend(true, {index: i}, {seriesColors:this.seriesColors, negativeSeriesColors:this.negativeSeriesColors}, this.options.seriesDefaults, this.options.series[i], {rendererOptions:{animation:{show: this.animate}}});
                 // pass in options in case something needs set prior to initialization.
                 var temp = new Series(sopts);
-                for (var j=0; j<jQuery.jqplot.preParseSeriesOptionsHooks.length; j++) {
-                    jQuery.jqplot.preParseSeriesOptionsHooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]);
+                for (var j=0; j<$.jqplot.preParseSeriesOptionsHooks.length; j++) {
+                    $.jqplot.preParseSeriesOptionsHooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]);
                 }
                 for (var j=0; j<this.preParseSeriesOptionsHooks.hooks.length; j++) {
                     this.preParseSeriesOptionsHooks.hooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]);
                 }
                 // Now go back and apply the options to the series.  Really should just do this during initializaiton, but don't want to
                 // mess up preParseSeriesOptionsHooks at this point.
-                jQuery.extend(true, temp, sopts);
+                $.extend(true, temp, sopts);
                 var dir = 'vertical';
-                if (temp.renderer === jQuery.jqplot.BarRenderer && temp.rendererOptions && temp.rendererOptions.barDirection == 'horizontal') {
+                if (temp.renderer === $.jqplot.BarRenderer && temp.rendererOptions && temp.rendererOptions.barDirection == 'horizontal') {
                     dir = 'horizontal';
                     temp._stackAxis = 'x';
                     temp._primaryAxis = '_yaxis';
@@ -2776,10 +2779,10 @@
                     temp.label = 'Series '+ (i+1).toString();
                 }
                 // temp.rendererOptions.show = temp.show;
-                // jQuery.extend(true, temp.renderer, {color:this.seriesColors[i]}, this.rendererOptions);
+                // $.extend(true, temp.renderer, {color:this.seriesColors[i]}, this.rendererOptions);
                 this.series.push(temp);  
-                for (var j=0; j<jQuery.jqplot.postParseSeriesOptionsHooks.length; j++) {
-                    jQuery.jqplot.postParseSeriesOptionsHooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]);
+                for (var j=0; j<$.jqplot.postParseSeriesOptionsHooks.length; j++) {
+                    $.jqplot.postParseSeriesOptionsHooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]);
                 }
                 for (var j=0; j<this.postParseSeriesOptionsHooks.hooks.length; j++) {
                     this.postParseSeriesOptionsHooks.hooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]);
@@ -2787,7 +2790,7 @@
             }
             
             // copy the grid and title options into this object.
-            jQuery.extend(true, this.grid, this.options.grid);
+            $.extend(true, this.grid, this.options.grid);
             // if axis border properties aren't set, set default.
             for (var i=0, l=_axisNames.length; i<l; i++) {
                 var n = _axisNames[i];
@@ -2801,13 +2804,13 @@
                 this.title.text = this.options.title;
             }
             else if (typeof this.options.title == 'object') {
-                jQuery.extend(true, this.title, this.options.title);
+                $.extend(true, this.title, this.options.title);
             }
             this.title._plotWidth = this._width;
             this.legend.setOptions(this.options.legend);
             
-            for (var i=0; i<jQuery.jqplot.postParseOptionsHooks.length; i++) {
-                jQuery.jqplot.postParseOptionsHooks[i].call(this, options);
+            for (var i=0; i<$.jqplot.postParseOptionsHooks.length; i++) {
+                $.jqplot.postParseOptionsHooks[i].call(this, options);
             }
             for (var i=0; i<this.postParseOptionsHooks.hooks.length; i++) {
                 this.postParseOptionsHooks.hooks[i].call(this, options);
@@ -2921,10 +2924,10 @@
                     j,
                     l,
                     tempseries;
-                for (i=0, l=jQuery.jqplot.preDrawHooks.length; i<l; i++) {
-                    jQuery.jqplot.preDrawHooks[i].call(this);
+                for (i=0, l=$.jqplot.preDrawHooks.length; i<l; i++) {
+                    $.jqplot.preDrawHooks[i].call(this);
                 }
-                for (i=0, l=this.preDrawHooks.length; i<l; i++) {
+                for (i=0, l=this.preDrawHooks.hooks.length; i<l; i++) {
                     this.preDrawHooks.hooks[i].apply(this, this.preDrawSeriesHooks.args[i]);
                 }
                 // create an underlying canvas to be used for special features.
@@ -3096,10 +3099,10 @@
                 }
             
                 // register event listeners on the overlay canvas
-                for (var i=0, l=jQuery.jqplot.eventListenerHooks.length; i<l; i++) {
+                for (var i=0, l=$.jqplot.eventListenerHooks.length; i<l; i++) {
                     // in the handler, this will refer to the eventCanvas dom element.
                     // make sure there are references back into plot objects.
-                    this.eventCanvas._elem.bind(jQuery.jqplot.eventListenerHooks[i][0], {plot:this}, jQuery.jqplot.eventListenerHooks[i][1]);
+                    this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]);
                 }
             
                 // register event listeners on the overlay canvas
@@ -3114,8 +3117,8 @@
                     this.doFillBetweenLines();
                 }
 
-                for (var i=0, l=jQuery.jqplot.postDrawHooks.length; i<l; i++) {
-                    jQuery.jqplot.postDrawHooks[i].call(this);
+                for (var i=0, l=$.jqplot.postDrawHooks.length; i<l; i++) {
+                    $.jqplot.postDrawHooks[i].call(this);
                 }
 
                 for (var i=0, l=this.postDrawHooks.hooks.length; i<l; i++) {
@@ -3234,7 +3237,7 @@
                 s = series[i];
                 hp = s._highlightThreshold;
                 switch (s.renderer.constructor) {
-                    case jQuery.jqplot.BarRenderer:
+                    case $.jqplot.BarRenderer:
                         x = gridpos.x;
                         y = gridpos.y;
                         for (j=0; j<s._barPoints.length; j++) {
@@ -3245,7 +3248,7 @@
                             }
                         }
                         break;
-                    case jQuery.jqplot.PyramidRenderer:
+                    case $.jqplot.PyramidRenderer:
                         x = gridpos.x;
                         y = gridpos.y;
                         for (j=0; j<s._barPoints.length; j++) {
@@ -3257,7 +3260,7 @@
                         }
                         break;
                     
-                    case jQuery.jqplot.DonutRenderer:
+                    case $.jqplot.DonutRenderer:
                         sa = s.startAngle/180*Math.PI;
                         x = gridpos.x - s._center[0];
                         y = gridpos.y - s._center[1];
@@ -3296,13 +3299,13 @@
                                 minang = (j>0) ? s.gridData[j-1][1]+sm : sm;
                                 maxang = s.gridData[j][1];
                                 if (theta > minang && theta < maxang) {
-                                    return {seriesIndex:s.index, pointIndex:j, gridData:s.gridData[j], data:s.data[j]};
+                                    return {seriesIndex:s.index, pointIndex:j, gridData:[gridpos.x,gridpos.y], data:s.data[j]};
                                 }
                             }
                         }
                         break;
                         
-                    case jQuery.jqplot.PieRenderer:
+                    case $.jqplot.PieRenderer:
                         sa = s.startAngle/180*Math.PI;
                         x = gridpos.x - s._center[0];
                         y = gridpos.y - s._center[1];
@@ -3341,13 +3344,13 @@
                                 minang = (j>0) ? s.gridData[j-1][1]+sm : sm;
                                 maxang = s.gridData[j][1];
                                 if (theta > minang && theta < maxang) {
-                                    return {seriesIndex:s.index, pointIndex:j, gridData:s.gridData[j], data:s.data[j]};
+                                    return {seriesIndex:s.index, pointIndex:j, gridData:[gridpos.x,gridpos.y], data:s.data[j]};
                                 }
                             }
                         }
                         break;
                         
-                    case jQuery.jqplot.BubbleRenderer:
+                    case $.jqplot.BubbleRenderer:
                         x = gridpos.x;
                         y = gridpos.y;
                         var ret = null;
@@ -3367,7 +3370,7 @@
                         }
                         break;
                         
-                    case jQuery.jqplot.FunnelRenderer:
+                    case $.jqplot.FunnelRenderer:
                         x = gridpos.x;
                         y = gridpos.y;
                         var v = s._vertices,
@@ -3398,7 +3401,7 @@
                         }         
                         break;           
                     
-                    case jQuery.jqplot.LineRenderer:
+                    case $.jqplot.LineRenderer:
                         x = gridpos.x;
                         y = gridpos.y;
                         r = s.renderer;
@@ -3439,7 +3442,7 @@
                                 for (var j=0; j<s.gridData.length; j++) {
                                     p = s.gridData[j];
                                     // neighbor looks different to OHLC chart.
-                                    if (r.constructor == jQuery.jqplot.OHLCRenderer) {
+                                    if (r.constructor == $.jqplot.OHLCRenderer) {
                                         if (r.candleStick) {
                                             var yp = s._yaxis.series_u2p;
                                             if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {
@@ -3484,7 +3487,7 @@
                             for (var j=0; j<s.gridData.length; j++) {
                                 p = s.gridData[j];
                                 // neighbor looks different to OHLC chart.
-                                if (r.constructor == jQuery.jqplot.OHLCRenderer) {
+                                if (r.constructor == $.jqplot.OHLCRenderer) {
                                     if (r.candleStick) {
                                         var yp = s._yaxis.series_u2p;
                                         if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {
@@ -3637,7 +3640,7 @@
                 ctx = series.canvas._ctx;
                 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
                 series.draw(ctx, options, this);
-                if (series.renderer.constructor == jQuery.jqplot.BezierCurveRenderer) {
+                if (series.renderer.constructor == $.jqplot.BezierCurveRenderer) {
                     if (idx < this.series.length - 1) {
                         this.drawSeries(idx+1); 
                     }
@@ -3769,12 +3772,12 @@
     
     
     // conpute a highlight color or array of highlight colors from given colors.
-    jQuery.jqplot.computeHighlightColors  = function(colors) {
+    $.jqplot.computeHighlightColors  = function(colors) {
         var ret;
         if ($.isArray(colors)) {
             ret = [];
             for (var i=0; i<colors.length; i++){
-                var rgba = jQuery.jqplot.getColorComponents(colors[i]);
+                var rgba = $.jqplot.getColorComponents(colors[i]);
                 var newrgb = [rgba[0], rgba[1], rgba[2]];
                 var sum = newrgb[0] + newrgb[1] + newrgb[2];
                 for (var j=0; j<3; j++) {
@@ -3790,7 +3793,7 @@
             }
         }
         else {
-            var rgba = jQuery.jqplot.getColorComponents(colors);
+            var rgba = $.jqplot.getColorComponents(colors);
             var newrgb = [rgba[0], rgba[1], rgba[2]];
             var sum = newrgb[0] + newrgb[1] + newrgb[2];
             for (var j=0; j<3; j++) {
@@ -3809,8 +3812,8 @@
         return ret;
     };
         
-   jQuery.jqplot.ColorGenerator = function(colors) {
-        colors = colors || jQuery.jqplot.config.defaultColors;
+   $.jqplot.ColorGenerator = function(colors) {
+        colors = colors || $.jqplot.config.defaultColors;
         var idx = 0;
         
         this.next = function () { 
@@ -3859,7 +3862,7 @@
     // convert a hex color string to rgb string.
     // h - 3 or 6 character hex string, with or without leading #
     // a - optional alpha
-    jQuery.jqplot.hex2rgb = function(h, a) {
+    $.jqplot.hex2rgb = function(h, a) {
         h = h.replace('#', '');
         if (h.length == 3) {
             h = h.charAt(0)+h.charAt(0)+h.charAt(1)+h.charAt(1)+h.charAt(2)+h.charAt(2);
@@ -3874,7 +3877,7 @@
     };
     
     // convert an rgb color spec to a hex spec.  ignore any alpha specification.
-    jQuery.jqplot.rgb2hex = function(s) {
+    $.jqplot.rgb2hex = function(s) {
         var pat = /rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/;
         var m = s.match(pat);
         var h = '#';
@@ -3898,23 +3901,23 @@
     };
     
     // given a css color spec, return an rgb css color spec
-    jQuery.jqplot.normalize2rgb = function(s, a) {
+    $.jqplot.normalize2rgb = function(s, a) {
         if (s.search(/^ *rgba?\(/) != -1) {
             return s; 
         }
         else if (s.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/) != -1) {
-            return jQuery.jqplot.hex2rgb(s, a);
+            return $.jqplot.hex2rgb(s, a);
         }
         else {
-            throw 'invalid color spec';
+            throw new Error('Invalid color spec');
         }
     };
     
     // extract the r, g, b, a color components out of a css color spec.
-    jQuery.jqplot.getColorComponents = function(s) {
+    $.jqplot.getColorComponents = function(s) {
         // check to see if a color keyword.
-        s = jQuery.jqplot.colorKeywordMap[s] || s;
-        var rgb = jQuery.jqplot.normalize2rgb(s);
+        s = $.jqplot.colorKeywordMap[s] || s;
+        var rgb = $.jqplot.normalize2rgb(s);
         var pat = /rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/;
         var m = rgb.match(pat);
         var ret = [];
@@ -3930,7 +3933,7 @@
         return ret;
     };
     
-    jQuery.jqplot.colorKeywordMap = {
+    $.jqplot.colorKeywordMap = {
         aliceblue: 'rgb(240, 248, 255)',
         antiquewhite: 'rgb(250, 235, 215)',
         aqua: 'rgb( 0, 255, 255)',
@@ -4082,15 +4085,16 @@
 
     
 
-    // class: jQuery.jqplot.AxisLabelRenderer
+
+    // class: $.jqplot.AxisLabelRenderer
     // Renderer to place labels on the axes.
-    jQuery.jqplot.AxisLabelRenderer = function(options) {
+    $.jqplot.AxisLabelRenderer = function(options) {
         // Group: Properties
-        jQuery.jqplot.ElemContainer.call(this);
+        $.jqplot.ElemContainer.call(this);
         // name of the axis associated with this tick
         this.axis;
         // prop: show
-        // wether or not to show the tick (mark and label).
+        // whether or not to show the tick (mark and label).
         this.show = true;
         // prop: label
         // The text or html for the label.
@@ -4103,17 +4107,17 @@
         // true to escape HTML entities in the label.
         this.escapeHTML = false;
         
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
     };
     
-    jQuery.jqplot.AxisLabelRenderer.prototype = new jQuery.jqplot.ElemContainer();
-    jQuery.jqplot.AxisLabelRenderer.prototype.constructor = jQuery.jqplot.AxisLabelRenderer;
+    $.jqplot.AxisLabelRenderer.prototype = new $.jqplot.ElemContainer();
+    $.jqplot.AxisLabelRenderer.prototype.constructor = $.jqplot.AxisLabelRenderer;
     
-    jQuery.jqplot.AxisLabelRenderer.prototype.init = function(options) {
-        jQuery.extend(true, this, options);
+    $.jqplot.AxisLabelRenderer.prototype.init = function(options) {
+        $.extend(true, this, options);
     };
     
-    jQuery.jqplot.AxisLabelRenderer.prototype.draw = function(ctx, plot) {
+    $.jqplot.AxisLabelRenderer.prototype.draw = function(ctx, plot) {
         // Memory Leaks patch
         if (this._elem) {
             this._elem.emptyForce();
@@ -4145,24 +4149,24 @@
         return this._elem;
     };
     
-    jQuery.jqplot.AxisLabelRenderer.prototype.pack = function() {
+    $.jqplot.AxisLabelRenderer.prototype.pack = function() {
     };
 
-    // class: jQuery.jqplot.AxisTickRenderer
+    // class: $.jqplot.AxisTickRenderer
     // A "tick" object showing the value of a tick/gridline on the plot.
-    jQuery.jqplot.AxisTickRenderer = function(options) {
+    $.jqplot.AxisTickRenderer = function(options) {
         // Group: Properties
-        jQuery.jqplot.ElemContainer.call(this);
+        $.jqplot.ElemContainer.call(this);
         // prop: mark
         // tick mark on the axis.  One of 'inside', 'outside', 'cross', '' or null.
         this.mark = 'outside';
         // name of the axis associated with this tick
         this.axis;
         // prop: showMark
-        // wether or not to show the mark on the axis.
+        // whether or not to show the mark on the axis.
         this.showMark = true;
         // prop: showGridline
-        // wether or not to draw the gridline on the grid at this tick.
+        // whether or not to draw the gridline on the grid at this tick.
         this.showGridline = true;
         // prop: isMinorTick
         // if this is a minor tick.
@@ -4176,19 +4180,19 @@
         // will be stoked above and below axis, so total length will be twice this.
         this.markSize = 6;
         // prop: show
-        // wether or not to show the tick (mark and label).
+        // whether or not to show the tick (mark and label).
         // Setting this to false requires more testing.  It is recommended
         // to set showLabel and showMark to false instead.
         this.show = true;
         // prop: showLabel
-        // wether or not to show the label.
+        // whether or not to show the label.
         this.showLabel = true;
         this.label = null;
         this.value = null;
         this._styles = {};
         // prop: formatter
         // A class of a formatter for the tick text.  sprintf by default.
-        this.formatter = jQuery.jqplot.DefaultTickFormatter;
+        this.formatter = $.jqplot.DefaultTickFormatter;
         // prop: prefix
         // String to prepend to the tick label.
         // Prefix is prepended to the formatted tick label.
@@ -4213,19 +4217,19 @@
         // true to escape HTML entities in the label.
         this.escapeHTML = false;
         this._elem;
-		this._breakTick = false;
+        this._breakTick = false;
         
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
     };
     
-    jQuery.jqplot.AxisTickRenderer.prototype.init = function(options) {
-        jQuery.extend(true, this, options);
+    $.jqplot.AxisTickRenderer.prototype.init = function(options) {
+        $.extend(true, this, options);
     };
     
-    jQuery.jqplot.AxisTickRenderer.prototype = new jQuery.jqplot.ElemContainer();
-    jQuery.jqplot.AxisTickRenderer.prototype.constructor = jQuery.jqplot.AxisTickRenderer;
+    $.jqplot.AxisTickRenderer.prototype = new $.jqplot.ElemContainer();
+    $.jqplot.AxisTickRenderer.prototype.constructor = $.jqplot.AxisTickRenderer;
     
-    jQuery.jqplot.AxisTickRenderer.prototype.setTick = function(value, axisName, isMinor) {
+    $.jqplot.AxisTickRenderer.prototype.setTick = function(value, axisName, isMinor) {
         this.value = value;
         this.axis = axisName;
         if (isMinor) {
@@ -4234,7 +4238,7 @@
         return this;
     };
     
-    jQuery.jqplot.AxisTickRenderer.prototype.draw = function() {
+    $.jqplot.AxisTickRenderer.prototype.draw = function() {
         if (this.label === null) {
             this.label = this.prefix + this.formatter(this.formatString, this.value) + this.suffix;
         }
@@ -4273,63 +4277,63 @@
         if (this.textColor) {
             this._elem.css('color', this.textColor);
         }
-		if (this._breakTick) {
-			this._elem.addClass('jqplot-breakTick');
-		}
+        if (this._breakTick) {
+          this._elem.addClass('jqplot-breakTick');
+        }
         
         return this._elem;
     };
         
-    jQuery.jqplot.DefaultTickFormatter = function (format, val) {
+    $.jqplot.DefaultTickFormatter = function (format, val) {
         if (typeof val == 'number') {
             if (!format) {
-                format = jQuery.jqplot.config.defaultTickFormatString;
+                format = $.jqplot.config.defaultTickFormatString;
             }
-            return jQuery.jqplot.sprintf(format, val);
+            return $.jqplot.sprintf(format, val);
         }
         else {
             return String(val);
         }
     };
         
-    jQuery.jqplot.PercentTickFormatter = function (format, val) {
+    $.jqplot.PercentTickFormatter = function (format, val) {
         if (typeof val == 'number') {
             val = 100 * val;
             if (!format) {
-                format = jQuery.jqplot.config.defaultTickFormatString;
+                format = $.jqplot.config.defaultTickFormatString;
             }
-            return jQuery.jqplot.sprintf(format, val);
+            return $.jqplot.sprintf(format, val);
         }
         else {
             return String(val);
         }
     };
     
-    jQuery.jqplot.AxisTickRenderer.prototype.pack = function() {
+    $.jqplot.AxisTickRenderer.prototype.pack = function() {
     };
      
-    // Class: jQuery.jqplot.CanvasGridRenderer
+    // Class: $.jqplot.CanvasGridRenderer
     // The default jqPlot grid renderer, creating a grid on a canvas element.
     // The renderer has no additional options beyond the <Grid> class.
-    jQuery.jqplot.CanvasGridRenderer = function(){
-        this.shadowRenderer = new jQuery.jqplot.ShadowRenderer();
+    $.jqplot.CanvasGridRenderer = function(){
+        this.shadowRenderer = new $.jqplot.ShadowRenderer();
     };
     
     // called with context of Grid object
-    jQuery.jqplot.CanvasGridRenderer.prototype.init = function(options) {
+    $.jqplot.CanvasGridRenderer.prototype.init = function(options) {
         this._ctx;
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
         // set the shadow renderer options
         var sopts = {lineJoin:'miter', lineCap:'round', fill:false, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, lineWidth:this.shadowWidth, closePath:false, strokeStyle:this.shadowColor};
         this.renderer.shadowRenderer.init(sopts);
     };
     
     // called with context of Grid.
-    jQuery.jqplot.CanvasGridRenderer.prototype.createElement = function(plot) {
+    $.jqplot.CanvasGridRenderer.prototype.createElement = function(plot) {
         var elem;
         // Memory Leaks patch
         if (this._elem) {
-          if (jQuery.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
+          if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
             elem = this._elem.get(0);
             window.G_vmlCanvasManager.uninitElement(elem);
             elem = null;
@@ -4349,8 +4353,8 @@
         this._elem.addClass('jqplot-grid-canvas');
         this._elem.css({ position: 'absolute', left: 0, top: 0 });
         
-		elem = plot.canvasManager.initCanvas(elem);
-		
+        elem = plot.canvasManager.initCanvas(elem);
+
         this._top = this._offsets.top;
         this._bottom = h - this._offsets.bottom;
         this._left = this._offsets.left;
@@ -4362,7 +4366,7 @@
         return this._elem;
     };
     
-    jQuery.jqplot.CanvasGridRenderer.prototype.draw = function() {
+    $.jqplot.CanvasGridRenderer.prototype.draw = function() {
         this._ctx = this._elem.get(0).getContext("2d");
         var ctx = this._ctx;
         var axes = this._axes;
@@ -4630,7 +4634,7 @@
             ctx.save();
             opts = opts || {};
             if (opts.lineWidth == null || opts.lineWidth != 0){
-                jQuery.extend(true, ctx, opts);
+                $.extend(true, ctx, opts);
                 ctx.beginPath();
                 ctx.moveTo(bx, by);
                 ctx.lineTo(ex, ey);
@@ -4660,16 +4664,16 @@
         axes = null;
     };
  
-    // Class: jQuery.jqplot.DivTitleRenderer
+    // Class: $.jqplot.DivTitleRenderer
     // The default title renderer for jqPlot.  This class has no options beyond the <Title> class. 
-    jQuery.jqplot.DivTitleRenderer = function() {
+    $.jqplot.DivTitleRenderer = function() {
     };
     
-    jQuery.jqplot.DivTitleRenderer.prototype.init = function(options) {
-        jQuery.extend(true, this, options);
+    $.jqplot.DivTitleRenderer.prototype.init = function(options) {
+        $.extend(true, this, options);
     };
     
-    jQuery.jqplot.DivTitleRenderer.prototype.draw = function() {
+    $.jqplot.DivTitleRenderer.prototype.draw = function() {
         // Memory Leaks patch
         if (this._elem) {
             this._elem.emptyForce();
@@ -4745,20 +4749,20 @@
         return this._elem;
     };
     
-    jQuery.jqplot.DivTitleRenderer.prototype.pack = function() {
+    $.jqplot.DivTitleRenderer.prototype.pack = function() {
         // nothing to do here
     };
   
 
     var dotlen = 0.1;
 
-    jQuery.jqplot.LinePattern = function (ctx, pattern) {
+    $.jqplot.LinePattern = function (ctx, pattern) {
 
-		var defaultLinePatterns = {
-			dotted: [ dotlen, jQuery.jqplot.config.dotGapLength ],
-			dashed: [ jQuery.jqplot.config.dashLength, jQuery.jqplot.config.gapLength ],
-			solid: null
-		};   	
+        var defaultLinePatterns = {
+            dotted: [ dotlen, $.jqplot.config.dotGapLength ],
+            dashed: [ $.jqplot.config.dashLength, $.jqplot.config.gapLength ],
+            solid: null
+        };
 
         if (typeof pattern === 'string') {
             if (pattern[0] === '.' || pattern[0] === '-') {
@@ -4769,12 +4773,12 @@
                         pattern.push( dotlen );
                     }
                     else if (s[i] === '-') {
-                        pattern.push( jQuery.jqplot.config.dashLength );
+                        pattern.push( $.jqplot.config.dashLength );
                     }
                     else {
                         continue;
                     }
-                    pattern.push( jQuery.jqplot.config.gapLength );
+                    pattern.push( $.jqplot.config.gapLength );
                 }
             }
             else {
@@ -4859,16 +4863,16 @@
         };
     };
 
-    // Class: jQuery.jqplot.LineRenderer
+    // Class: $.jqplot.LineRenderer
     // The default line renderer for jqPlot, this class has no options beyond the <Series> class.
     // Draws series as a line.
-    jQuery.jqplot.LineRenderer = function(){
-        this.shapeRenderer = new jQuery.jqplot.ShapeRenderer();
-        this.shadowRenderer = new jQuery.jqplot.ShadowRenderer();
+    $.jqplot.LineRenderer = function(){
+        this.shapeRenderer = new $.jqplot.ShapeRenderer();
+        this.shadowRenderer = new $.jqplot.ShadowRenderer();
     };
     
     // called with scope of series.
-    jQuery.jqplot.LineRenderer.prototype.init = function(options, plot) {
+    $.jqplot.LineRenderer.prototype.init = function(options, plot) {
         // Group: Properties
         //
         options = options || {};
@@ -4963,7 +4967,7 @@
         delete (options.highlightMouseDown);
         delete (options.highlightColor);
         
-        jQuery.extend(true, this.renderer, options);
+        $.extend(true, this.renderer, options);
 
         this.renderer.options = options;
 
@@ -5034,11 +5038,11 @@
                 lopts.highlightMouseOver = false;
             }
         
-            jQuery.extend(true, this, {highlightMouseOver: lopts.highlightMouseOver, highlightMouseDown: lopts.highlightMouseDown, highlightColor: lopts.highlightColor});
+            $.extend(true, this, {highlightMouseOver: lopts.highlightMouseOver, highlightMouseDown: lopts.highlightMouseDown, highlightColor: lopts.highlightColor});
             
             if (!this.highlightColor) {
                 var fc = (this.renderer.bands.show) ? this.renderer.bands.fillColor : this.fillColor;
-                this.highlightColor = jQuery.jqplot.computeHighlightColors(fc);
+                this.highlightColor = $.jqplot.computeHighlightColors(fc);
             }
             // turn off (disable) the highlighter plugin
             if (this.highlighter) {
@@ -5059,7 +5063,7 @@
 
     };
 
-    jQuery.jqplot.LineRenderer.prototype.initBands = function(options, plot) {
+    $.jqplot.LineRenderer.prototype.initBands = function(options, plot) {
         // use bandData if no data specified in bands option
         //var bd = this.renderer.bandData;
         var bd = options.bandData || [];
@@ -5246,7 +5250,7 @@
         // }
 
         if (bands.fillColor === null) {
-            var c = jQuery.jqplot.getColorComponents(bands.color);
+            var c = $.jqplot.getColorComponents(bands.color);
             // now adjust alpha to differentiate fill
             c[3] = c[3] * 0.5;
             bands.fillColor = 'rgba(' + c[0] +', '+ c[1] +', '+ c[2] +', '+ c[3] + ')';
@@ -5503,7 +5507,7 @@
     // converts the user data values to grid coordinates and stores them
     // in the gridData array.
     // Called with scope of a series.
-    jQuery.jqplot.LineRenderer.prototype.setGridData = function(plot) {
+    $.jqplot.LineRenderer.prototype.setGridData = function(plot) {
         // recalculate the grid data
         var xp = this._xaxis.series_u2p;
         var yp = this._yaxis.series_u2p;
@@ -5603,7 +5607,7 @@
     // linerenderer to generate grid data points without overwriting the
     // grid data associated with that series.
     // Called with scope of a series.
-    jQuery.jqplot.LineRenderer.prototype.makeGridData = function(data, plot) {
+    $.jqplot.LineRenderer.prototype.makeGridData = function(data, plot) {
         // recalculate the grid data
         var xp = this._xaxis.series_u2p;
         var yp = this._yaxis.series_u2p;
@@ -5686,10 +5690,10 @@
     
 
     // called within scope of series.
-    jQuery.jqplot.LineRenderer.prototype.draw = function(ctx, gd, options, plot) {
+    $.jqplot.LineRenderer.prototype.draw = function(ctx, gd, options, plot) {
         var i;
         // get a copy of the options, so we don't modify the original object.
-        var opts = jQuery.extend(true, {}, options);
+        var opts = $.extend(true, {}, options);
         var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
         var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;
         var fill = (opts.fill != undefined) ? opts.fill : this.fill;
@@ -5732,7 +5736,7 @@
                                     tempgd.push(gd[i]);
                                     this._areaPoints.push(gd[i]);
                                     // do we have an axis crossing?
-                                    if (pd[i][1] * pd[i+1][1] < 0) {
+                                    if (pd[i][1] * pd[i+1][1] <= 0) {
                                         if (pd[i][1] < 0) {
                                             isnegative = true;
                                             opts.fillStyle = negativeColor;
@@ -5828,7 +5832,7 @@
                         this.renderer.shapeRenderer.draw(ctx, gd, opts);                        
                     }
                     if (fillAndStroke) {
-                        var fasopts = jQuery.extend(true, {}, opts, {fill:false, closePath:false});
+                        var fasopts = $.extend(true, {}, opts, {fill:false, closePath:false});
                         this.renderer.shapeRenderer.draw(ctx, fasgd, fasopts);
                         //////////
                         // TODO: figure out some way to do shadows nicely
@@ -5850,7 +5854,7 @@
 
                     if (this.renderer.bands.show) {
                         var bdat;
-                        var bopts = jQuery.extend(true, {}, opts);
+                        var bopts = $.extend(true, {}, opts);
                         if (this.renderer.bands.showLines) {
                             bdat = (this.renderer.smooth) ? this.renderer._hiBandSmoothedData : this.renderer._hiBandGridData;
                             this.renderer.shapeRenderer.draw(ctx, bdat, opts);
@@ -5921,7 +5925,7 @@
         ctx.restore();
     };  
     
-    jQuery.jqplot.LineRenderer.prototype.drawShadow = function(ctx, gd, options) {
+    $.jqplot.LineRenderer.prototype.drawShadow = function(ctx, gd, options) {
         // This is a no-op, shadows drawn with lines.
     };
     
@@ -5929,7 +5933,7 @@
     // make sure to not leave anything highlighted.
     function postInit(target, data, options) {
         for (var i=0; i<this.series.length; i++) {
-            if (this.series[i].renderer.constructor == jQuery.jqplot.LineRenderer) {
+            if (this.series[i].renderer.constructor == $.jqplot.LineRenderer) {
                 // don't allow mouseover and mousedown at same time.
                 if (this.series[i].highlightMouseOver) {
                     this.series[i].highlightMouseDown = false;
@@ -5949,7 +5953,7 @@
         }
         
         this.plugins.lineRenderer.highlightedSeriesIndex = null;
-        this.plugins.lineRenderer.highlightCanvas = new jQuery.jqplot.GenericCanvas();
+        this.plugins.lineRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
         
         this.eventCanvas._elem.before(this.plugins.lineRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-lineRenderer-highlight-canvas', this._plotDimensions, this));
         this.plugins.lineRenderer.highlightCanvas.setContext();
@@ -5992,7 +5996,7 @@
             plot.target.trigger(evt1, ins);
             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.lineRenderer.highlightedSeriesIndex)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -6009,7 +6013,7 @@
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.lineRenderer.highlightedSeriesIndex)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -6032,7 +6036,7 @@
         if (neighbor) {
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             var evt = jQuery.Event('jqplotDataClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
@@ -6047,7 +6051,7 @@
                 unhighlight(plot);
             }
             var evt = jQuery.Event('jqplotDataRightClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
@@ -6055,13 +6059,13 @@
     }
     
     
-    // class: jQuery.jqplot.LinearAxisRenderer
+    // class: $.jqplot.LinearAxisRenderer
     // The default jqPlot axis renderer, creating a numeric axis.
-    jQuery.jqplot.LinearAxisRenderer = function() {
+    $.jqplot.LinearAxisRenderer = function() {
     };
     
     // called with scope of axis object.
-    jQuery.jqplot.LinearAxisRenderer.prototype.init = function(options){
+    $.jqplot.LinearAxisRenderer.prototype.init = function(options){
         // prop: breakPoints
         // EXPERIMENTAL!! Use at your own risk!
         // Works only with linear axes and the default tick renderer.
@@ -6119,7 +6123,7 @@
         this._autoFormatString = '';
         this._overrideFormatString = false;
         this._scalefact = 1.0;
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
         if (this.breakPoints) {
             if (!$.isArray(this.breakPoints)) {
                 this.breakPoints = null;
@@ -6135,14 +6139,14 @@
     };
     
     // called with scope of axis
-    jQuery.jqplot.LinearAxisRenderer.prototype.draw = function(ctx, plot) {
+    $.jqplot.LinearAxisRenderer.prototype.draw = function(ctx, plot) {
         if (this.show) {
             // populate the axis label and value properties.
             // createTicks is a method on the renderer, but
             // call it within the scope of the axis.
             this.renderer.createTicks.call(this, plot);
             // fill a div with axes labels in the right direction.
-            // Need to pregenerate each axis to get it's bounds and
+            // Need to pregenerate each axis to get its bounds and
             // position it and the labels correctly on the plot.
             var dim=0;
             var temp;
@@ -6190,7 +6194,7 @@
     };
     
     // called with scope of an axis
-    jQuery.jqplot.LinearAxisRenderer.prototype.reset = function() {
+    $.jqplot.LinearAxisRenderer.prototype.reset = function() {
         this.min = this._options.min;
         this.max = this._options.max;
         this.tickInterval = this._options.tickInterval;
@@ -6204,7 +6208,7 @@
     };
     
     // called with scope of axis
-    jQuery.jqplot.LinearAxisRenderer.prototype.set = function() { 
+    $.jqplot.LinearAxisRenderer.prototype.set = function() { 
         var dim = 0;
         var temp;
         var w = 0;
@@ -6245,14 +6249,14 @@
             else if (this.name == 'yaxis') {
                 dim = dim + w;
                 this._elem.css({'width':dim+'px', left:'0px', top:'0px'});
-                if (lshow && this._label.constructor == jQuery.jqplot.AxisLabelRenderer) {
+                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {
                     this._label._elem.css('width', w+'px');
                 }
             }
             else {
                 dim = dim + w;
                 this._elem.css({'width':dim+'px', right:'0px', top:'0px'});
-                if (lshow && this._label.constructor == jQuery.jqplot.AxisLabelRenderer) {
+                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {
                     this._label._elem.css('width', w+'px');
                 }
             }
@@ -6260,7 +6264,7 @@
     };    
     
     // called with scope of axis
-    jQuery.jqplot.LinearAxisRenderer.prototype.createTicks = function(plot) {
+    $.jqplot.LinearAxisRenderer.prototype.createTicks = function(plot) {
         // we're are operating on an axis here
         var ticks = this._ticks;
         var userTicks = this.ticks;
@@ -6315,7 +6319,7 @@
                 }
 
                 else if ($.isPlainObject(ut)) {
-                    jQuery.extend(true, t, ut);
+                    $.extend(true, t, ut);
                     t.axis = this.name;
                     this._ticks.push(t);
                 }
@@ -6413,7 +6417,7 @@
                 // var threshold = 30;
                 // var tdim = Math.max(dim, threshold+1);
                 // this._scalefact =  (tdim-threshold)/300.0;
-                var ret = jQuery.jqplot.LinearTickGenerator(min, max, this._scalefact, _numberTicks, keepMin, keepMax); 
+                var ret = $.jqplot.LinearTickGenerator(min, max, this._scalefact, _numberTicks, keepMin, keepMax); 
                 // calculate a padded max and min, points should be less than these
                 // so that they aren't too close to the edges of the plot.
                 // User can adjust how much padding is allowed with pad, padMin and PadMax options. 
@@ -6426,7 +6430,7 @@
                 if (min <tumin || max > tumax) {
                     tumin = (this.min != null) ? min : min - range*(this.padMin - 1);
                     tumax = (this.max != null) ? max : max + range*(this.padMax - 1);
-                    ret = jQuery.jqplot.LinearTickGenerator(tumin, tumax, this._scalefact, _numberTicks, keepMin, keepMax);
+                    ret = $.jqplot.LinearTickGenerator(tumin, tumax, this._scalefact, _numberTicks, keepMin, keepMax);
                 }
 
                 this.min = ret[0];
@@ -6479,7 +6483,7 @@
                             }
                             var dp = (vmax - vmin) / vmax;
                             // is this sries a bar?
-                            if (s.renderer.constructor == jQuery.jqplot.BarRenderer) {
+                            if (s.renderer.constructor == $.jqplot.BarRenderer) {
                                 // if no negative values and could also check range.
                                 if (vmin >= 0 && (s.fillToZero || dp > 0.1)) {
                                     forceMinZero = true;
@@ -6591,7 +6595,7 @@
 
                     // Compute a somewhat decent format string if it is needed.
                     // get precision of interval and determine a format string.
-                    var sf = jQuery.jqplot.getSignificantFigures(this.tickInterval);
+                    var sf = $.jqplot.getSignificantFigures(this.tickInterval);
 
                     var fstr;
 
@@ -6643,7 +6647,7 @@
                     }
 
                     // get precision of interval and determine a format string.
-                    var sf = jQuery.jqplot.getSignificantFigures(this.tickInterval);
+                    var sf = $.jqplot.getSignificantFigures(this.tickInterval);
 
                     var fstr;
 
@@ -6665,14 +6669,14 @@
                     this.max = rmax;
                 }
                 
-                if (this.renderer.constructor == jQuery.jqplot.LinearAxisRenderer && this._autoFormatString == '') {
+                if (this.renderer.constructor == $.jqplot.LinearAxisRenderer && this._autoFormatString == '') {
                     // fix for misleading tick display with small range and low precision.
                     range = this.max - this.min;
                     // figure out precision
                     var temptick = new this.tickRenderer(this.tickOptions);
                     // use the tick formatString or, the default.
-                    var fs = temptick.formatString || jQuery.jqplot.config.defaultTickFormatString; 
-                    var fs = fs.match(jQuery.jqplot.sprintf.regex)[0];
+                    var fs = temptick.formatString || $.jqplot.config.defaultTickFormatString; 
+                    var fs = fs.match($.jqplot.sprintf.regex)[0];
                     var precision = 0;
                     if (fs) {
                         if (fs.search(/[fFeEgGpP]/) > -1) {
@@ -6750,7 +6754,7 @@
             for (var i=0; i<this.numberTicks; i++){
                 tt = this.min + i * this.tickInterval;
                 t = new this.tickRenderer(this.tickOptions);
-                // var t = new jQuery.jqplot.AxisTickRenderer(this.tickOptions);
+                // var t = new $.jqplot.AxisTickRenderer(this.tickOptions);
 
                 t.setTick(tt, this.name);
                 this._ticks.push(t);
@@ -6758,7 +6762,7 @@
                 if (i < this.numberTicks - 1) {
                     for (var j=0; j<this.minorTicks; j++) {
                         tt += this.tickInterval/(this.minorTicks+1);
-                        to = jQuery.extend(true, {}, this.tickOptions, {name:this.name, value:tt, label:'', isMinorTick:true});
+                        to = $.extend(true, {}, this.tickOptions, {name:this.name, value:tt, label:'', isMinorTick:true});
                         t = new this.tickRenderer(to);
                         this._ticks.push(t);
                     }
@@ -6783,7 +6787,7 @@
     //
     // > plot.axes.yaxis.renderer.resetTickValues.call(plot.axes.yaxis, yarr);
     //
-    jQuery.jqplot.LinearAxisRenderer.prototype.resetTickValues = function(opts) {
+    $.jqplot.LinearAxisRenderer.prototype.resetTickValues = function(opts) {
         if ($.isArray(opts) && opts.length == this._ticks.length) {
             var t;
             for (var i=0; i<opts.length; i++) {
@@ -6794,8 +6798,8 @@
                 t._elem.html(t.label);
             }
             t = null;
-            this.min = jQuery.jqplot.arrayMin(opts);
-            this.max = jQuery.jqplot.arrayMax(opts);
+            this.min = $.jqplot.arrayMin(opts);
+            this.max = $.jqplot.arrayMax(opts);
             this.pack();
         }
         // Not implemented yet.
@@ -6805,7 +6809,7 @@
     };
     
     // called with scope of axis
-    jQuery.jqplot.LinearAxisRenderer.prototype.pack = function(pos, offsets) {
+    $.jqplot.LinearAxisRenderer.prototype.pack = function(pos, offsets) {
         // Add defaults for repacking from resetTickValues function.
         pos = pos || {};
         offsets = offsets || this._offsets;
@@ -6915,7 +6919,7 @@
                     if (t.show && t.showLabel) {
                         var shim;
                         
-                        if (t.constructor == jQuery.jqplot.CanvasAxisTickRenderer && t.angle) {
+                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {
                             // will need to adjust auto positioning based on which axis this is.
                             var temp = (this.name == 'xaxis') ? 1 : -1;
                             switch (t.labelPosition) {
@@ -6968,7 +6972,7 @@
                     var t = ticks[i];
                     if (t.show && t.showLabel) {                        
                         var shim;
-                        if (t.constructor == jQuery.jqplot.CanvasAxisTickRenderer && t.angle) {
+                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {
                             // will need to adjust auto positioning based on which axis this is.
                             var temp = (this.name == 'yaxis') ? 1 : -1;
                             switch (t.labelPosition) {
@@ -7111,7 +7115,7 @@
         var temp;
         var sd;
         var bestNT;
-        var gsf = jQuery.jqplot.getSignificantFigures;
+        var gsf = $.jqplot.getSignificantFigures;
         var fsd;
         var fs;
         var currentNT;
@@ -7285,7 +7289,7 @@
     // for the graphing, a good number for the number of ticks, and a
     // format string so that extraneous digits are not displayed.
     // returned is an array containing [min, max, nTicks, format]
-    jQuery.jqplot.LinearTickGenerator = function(axis_min, axis_max, scalefact, numberTicks, keepMin, keepMax) {
+    $.jqplot.LinearTickGenerator = function(axis_min, axis_max, scalefact, numberTicks, keepMin, keepMax) {
         // Set to preserve EITHER min OR max.
         // If min is preserved, max must be free.
         keepMin = (keepMin === null) ? false : keepMin;
@@ -7307,7 +7311,7 @@
         var r = [];
         var ss = bestLinearInterval(axis_max - axis_min, scalefact);
 
-        var gsf = jQuery.jqplot.getSignificantFigures;
+        var gsf = $.jqplot.getSignificantFigures;
         
         if (numberTicks == null) {
 
@@ -7387,19 +7391,19 @@
         return r;
     };
 
-    jQuery.jqplot.LinearTickGenerator.bestLinearInterval = bestLinearInterval;
-    jQuery.jqplot.LinearTickGenerator.bestInterval = bestInterval;
-    jQuery.jqplot.LinearTickGenerator.bestLinearComponents = bestLinearComponents;
-    jQuery.jqplot.LinearTickGenerator.bestConstrainedInterval = bestConstrainedInterval;
+    $.jqplot.LinearTickGenerator.bestLinearInterval = bestLinearInterval;
+    $.jqplot.LinearTickGenerator.bestInterval = bestInterval;
+    $.jqplot.LinearTickGenerator.bestLinearComponents = bestLinearComponents;
+    $.jqplot.LinearTickGenerator.bestConstrainedInterval = bestConstrainedInterval;
 
 
-    // class: jQuery.jqplot.MarkerRenderer
+    // class: $.jqplot.MarkerRenderer
     // The default jqPlot marker renderer, rendering the points on the line.
-    jQuery.jqplot.MarkerRenderer = function(options){
+    $.jqplot.MarkerRenderer = function(options){
         // Group: Properties
         
         // prop: show
-        // wether or not to show the marker.
+        // whether or not to show the marker.
         this.show = true;
         // prop: style
         // One of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare
@@ -7414,7 +7418,7 @@
         // color of marker.  Will be set to color of series by default on init.
         this.color = '#666666';
         // prop: shadow
-        // wether or not to draw a shadow on the line
+        // whether or not to draw a shadow on the line
         this.shadow = true;
         // prop: shadowAngle
         // Shadow angle in degrees
@@ -7430,16 +7434,16 @@
         this.shadowAlpha = '0.07';
         // prop: shadowRenderer
         // Renderer that will draws the shadows on the marker.
-        this.shadowRenderer = new jQuery.jqplot.ShadowRenderer();
+        this.shadowRenderer = new $.jqplot.ShadowRenderer();
         // prop: shapeRenderer
         // Renderer that will draw the marker.
-        this.shapeRenderer = new jQuery.jqplot.ShapeRenderer();
+        this.shapeRenderer = new $.jqplot.ShapeRenderer();
         
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.init = function(options) {
-        jQuery.extend(true, this, options);
+    $.jqplot.MarkerRenderer.prototype.init = function(options) {
+        $.extend(true, this, options);
         var sdopt = {angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, lineWidth:this.lineWidth, depth:this.shadowDepth, closePath:true};
         if (this.style.indexOf('filled') != -1) {
             sdopt.fill = true;
@@ -7461,7 +7465,7 @@
         this.shapeRenderer.init(shopt);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.drawDiamond = function(x, y, ctx, fill, options) {
+    $.jqplot.MarkerRenderer.prototype.drawDiamond = function(x, y, ctx, fill, options) {
         var stretch = 1.2;
         var dx = this.size/2/stretch;
         var dy = this.size/2*stretch;
@@ -7472,13 +7476,13 @@
         this.shapeRenderer.draw(ctx, points, options);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.drawPlus = function(x, y, ctx, fill, options) {
+    $.jqplot.MarkerRenderer.prototype.drawPlus = function(x, y, ctx, fill, options) {
         var stretch = 1.0;
         var dx = this.size/2*stretch;
         var dy = this.size/2*stretch;
         var points1 = [[x, y-dy], [x, y+dy]];
         var points2 = [[x+dx, y], [x-dx, y]];
-        var opts = jQuery.extend(true, {}, this.options, {closePath:false});
+        var opts = $.extend(true, {}, this.options, {closePath:false});
         if (this.shadow) {
             this.shadowRenderer.draw(ctx, points1, {closePath:false});
             this.shadowRenderer.draw(ctx, points2, {closePath:false});
@@ -7487,11 +7491,11 @@
         this.shapeRenderer.draw(ctx, points2, opts);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.drawX = function(x, y, ctx, fill, options) {
+    $.jqplot.MarkerRenderer.prototype.drawX = function(x, y, ctx, fill, options) {
         var stretch = 1.0;
         var dx = this.size/2*stretch;
         var dy = this.size/2*stretch;
-        var opts = jQuery.extend(true, {}, this.options, {closePath:false});
+        var opts = $.extend(true, {}, this.options, {closePath:false});
         var points1 = [[x-dx, y-dy], [x+dx, y+dy]];
         var points2 = [[x-dx, y+dy], [x+dx, y-dy]];
         if (this.shadow) {
@@ -7502,7 +7506,7 @@
         this.shapeRenderer.draw(ctx, points2, opts);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.drawDash = function(x, y, ctx, fill, options) {
+    $.jqplot.MarkerRenderer.prototype.drawDash = function(x, y, ctx, fill, options) {
         var stretch = 1.0;
         var dx = this.size/2*stretch;
         var dy = this.size/2*stretch;
@@ -7513,7 +7517,7 @@
         this.shapeRenderer.draw(ctx, points, options);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.drawLine = function(p1, p2, ctx, fill, options) {
+    $.jqplot.MarkerRenderer.prototype.drawLine = function(p1, p2, ctx, fill, options) {
         var points = [p1, p2];
         if (this.shadow) {
             this.shadowRenderer.draw(ctx, points);
@@ -7521,7 +7525,7 @@
         this.shapeRenderer.draw(ctx, points, options);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.drawSquare = function(x, y, ctx, fill, options) {
+    $.jqplot.MarkerRenderer.prototype.drawSquare = function(x, y, ctx, fill, options) {
         var stretch = 1.0;
         var dx = this.size/2/stretch;
         var dy = this.size/2*stretch;
@@ -7532,7 +7536,7 @@
         this.shapeRenderer.draw(ctx, points, options);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.drawCircle = function(x, y, ctx, fill, options) {
+    $.jqplot.MarkerRenderer.prototype.drawCircle = function(x, y, ctx, fill, options) {
         var radius = this.size/2;
         var end = 2*Math.PI;
         var points = [x, y, radius, 0, end, true];
@@ -7542,7 +7546,7 @@
         this.shapeRenderer.draw(ctx, points, options);
     };
     
-    jQuery.jqplot.MarkerRenderer.prototype.draw = function(x, y, ctx, options) {
+    $.jqplot.MarkerRenderer.prototype.draw = function(x, y, ctx, options) {
         options = options || {};
         // hack here b/c shape renderer uses canvas based color style options
         // and marker uses css style names.
@@ -7591,9 +7595,9 @@
         }
     };
     
-    // class: jQuery.jqplot.shadowRenderer
+    // class: $.jqplot.shadowRenderer
     // The default jqPlot shadow renderer, rendering shadows behind shapes.
-    jQuery.jqplot.ShadowRenderer = function(options){ 
+    $.jqplot.ShadowRenderer = function(options){ 
         // Group: Properties
         
         // prop: angle
@@ -7625,14 +7629,14 @@
         this.depth = 3;
         this.strokeStyle = 'rgba(0,0,0,0.1)';
         // prop: isarc
-        // wether the shadow is an arc or not.
+        // whether the shadow is an arc or not.
         this.isarc = false;
         
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
     };
     
-    jQuery.jqplot.ShadowRenderer.prototype.init = function(options) {
-        jQuery.extend(true, this, options);
+    $.jqplot.ShadowRenderer.prototype.init = function(options) {
+        $.extend(true, this, options);
     };
     
     // function: draw
@@ -7640,7 +7644,7 @@
     //
     // ctx - canvas drawing context
     // points - array of points or [x, y, radius, start angle (rad), end angle (rad)]
-    jQuery.jqplot.ShadowRenderer.prototype.draw = function(ctx, points, options) {
+    $.jqplot.ShadowRenderer.prototype.draw = function(ctx, points, options) {
         ctx.save();
         var opts = (options != null) ? options : {};
         var fill = (opts.fill != null) ? opts.fill : this.fill;
@@ -7657,7 +7661,7 @@
         ctx.strokeStyle = opts.strokeStyle || this.strokeStyle || 'rgba(0,0,0,'+alpha+')';
         ctx.fillStyle = opts.fillStyle || this.fillStyle || 'rgba(0,0,0,'+alpha+')';
         for (var j=0; j<depth; j++) {
-            var ctxPattern = jQuery.jqplot.LinePattern(ctx, linePattern);
+            var ctxPattern = $.jqplot.LinePattern(ctx, linePattern);
             ctx.translate(Math.cos(this.angle*Math.PI/180)*offset, Math.sin(this.angle*Math.PI/180)*offset);
             ctxPattern.beginPath();
             if (isarc) {
@@ -7700,12 +7704,12 @@
         ctx.restore();
     };
     
-    // class: jQuery.jqplot.shapeRenderer
+    // class: $.jqplot.shapeRenderer
     // The default jqPlot shape renderer.  Given a set of points will
     // plot them and either stroke a line (fill = false) or fill them (fill = true).
     // If a filled shape is desired, closePath = true must also be set to close
     // the shape.
-    jQuery.jqplot.ShapeRenderer = function(options){
+    $.jqplot.ShapeRenderer = function(options){
         
         this.lineWidth = 1.5;
         // prop: linePattern
@@ -7727,7 +7731,7 @@
         // whether to fill the shape.
         this.fill = false;
         // prop: isarc
-        // wether the shadow is an arc or not.
+        // whether the shadow is an arc or not.
         this.isarc = false;
         // prop: fillRect
         // true to draw shape as a filled rectangle.
@@ -7745,11 +7749,11 @@
         // css color spec for the fill style.
         this.fillStyle = '#999999'; 
         
-        jQuery.extend(true, this, options);
+        $.extend(true, this, options);
     };
     
-    jQuery.jqplot.ShapeRenderer.prototype.init = function(options) {
-        jQuery.extend(true, this, options);
+    $.jqplot.ShapeRenderer.prototype.init = function(options) {
+        $.extend(true, this, options);
     };
     
     // function: draw
@@ -7759,7 +7763,7 @@
     // points - array of points for shapes or 
     // [x, y, width, height] for rectangles or
     // [x, y, radius, start angle (rad), end angle (rad)] for circles and arcs.
-    jQuery.jqplot.ShapeRenderer.prototype.draw = function(ctx, points, options) {
+    $.jqplot.ShapeRenderer.prototype.draw = function(ctx, points, options) {
         ctx.save();
         var opts = (options != null) ? options : {};
         var fill = (opts.fill != null) ? opts.fill : this.fill;
@@ -7769,7 +7773,7 @@
         var clearRect = (opts.clearRect != null) ? opts.clearRect : this.clearRect;
         var isarc = (opts.isarc != null) ? opts.isarc : this.isarc;
         var linePattern = (opts.linePattern != null) ? opts.linePattern : this.linePattern;
-        var ctxPattern = jQuery.jqplot.LinePattern(ctx, linePattern);
+        var ctxPattern = $.jqplot.LinePattern(ctx, linePattern);
         ctx.lineWidth = opts.lineWidth || this.lineWidth;
         ctx.lineJoin = opts.lineJoin || this.lineJoin;
         ctx.lineCap = opts.lineCap || this.lineCap;
@@ -7835,17 +7839,17 @@
         ctx.restore();
     };
     
-    // class jQuery.jqplot.TableLegendRenderer
+    // class $.jqplot.TableLegendRenderer
     // The default legend renderer for jqPlot.
-    jQuery.jqplot.TableLegendRenderer = function(){
+    $.jqplot.TableLegendRenderer = function(){
         //
     };
     
-    jQuery.jqplot.TableLegendRenderer.prototype.init = function(options) {
-        jQuery.extend(true, this, options);
+    $.jqplot.TableLegendRenderer.prototype.init = function(options) {
+        $.extend(true, this, options);
     };
         
-    jQuery.jqplot.TableLegendRenderer.prototype.addrow = function (label, color, pad, reverse) {
+    $.jqplot.TableLegendRenderer.prototype.addrow = function (label, color, pad, reverse) {
         var rs = (pad) ? this.rowSpacing+'px' : '0px';
         var tr;
         var td;
@@ -7905,7 +7909,7 @@
     };
     
     // called with scope of legend
-    jQuery.jqplot.TableLegendRenderer.prototype.draw = function() {
+    $.jqplot.TableLegendRenderer.prototype.draw = function() {
         if (this._elem) {
             this._elem.emptyForce();
             this._elem = null;
@@ -7950,10 +7954,10 @@
         
             var pad = false, 
                 reverse = false,
-				s;
+                s;
             for (var i = 0; i< series.length; i++) {
                 s = series[i];
-                if (s._stack || s.renderer.constructor == jQuery.jqplot.BezierCurveRenderer){
+                if (s._stack || s.renderer.constructor == $.jqplot.BezierCurveRenderer){
                     reverse = true;
                 }
                 if (s.show && s.showLabel) {
@@ -7970,8 +7974,8 @@
                         pad = true;
                     }
                     // let plugins add more rows to legend.  Used by trend line plugin.
-                    for (var j=0; j<jQuery.jqplot.addLegendRowHooks.length; j++) {
-                        var item = jQuery.jqplot.addLegendRowHooks[j].call(this, s);
+                    for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) {
+                        var item = $.jqplot.addLegendRowHooks[j].call(this, s);
                         if (item) {
                             this.renderer.addrow.call(this, item.label, item.color, pad);
                             pad = true;
@@ -7984,7 +7988,7 @@
         return this._elem;
     };
     
-    jQuery.jqplot.TableLegendRenderer.prototype.pack = function(offsets) {
+    $.jqplot.TableLegendRenderer.prototype.pack = function(offsets) {
         if (this.show) {       
             if (this.placement == 'insideGrid') {
                 switch (this.location) {
@@ -8128,7 +8132,7 @@
     };
 
     /**
-     * Class: jQuery.jqplot.ThemeEngine
+     * Class: $.jqplot.ThemeEngine
      * Theme Engine provides a programatic way to change some of the  more
      * common jqplot styling options such as fonts, colors and grid options.
      * A theme engine instance is created with each plot.  The theme engine
@@ -8298,7 +8302,7 @@
      * > }
      * 
      */
-    jQuery.jqplot.ThemeEngine = function(){
+    $.jqplot.ThemeEngine = function(){
         // Group: Properties
         //
         // prop: themes
@@ -8312,9 +8316,9 @@
     };
     
     // called with scope of plot
-    jQuery.jqplot.ThemeEngine.prototype.init = function() {
+    $.jqplot.ThemeEngine.prototype.init = function() {
         // get the Default theme from the current plot settings.
-        var th = new jQuery.jqplot.Theme({_name:'Default'});
+        var th = new $.jqplot.Theme({_name:'Default'});
         var n, i, nn;
         
         for (n in th.target) {
@@ -8357,22 +8361,22 @@
         
         for (i=0; i<this.series.length; i++) {
             s = this.series[i];
-            if (s.renderer.constructor == jQuery.jqplot.LineRenderer) {
+            if (s.renderer.constructor == $.jqplot.LineRenderer) {
                 th.series.push(new LineSeriesProperties());
             }
-            else if (s.renderer.constructor == jQuery.jqplot.BarRenderer) {
+            else if (s.renderer.constructor == $.jqplot.BarRenderer) {
                 th.series.push(new BarSeriesProperties());
             }
-            else if (s.renderer.constructor == jQuery.jqplot.PieRenderer) {
+            else if (s.renderer.constructor == $.jqplot.PieRenderer) {
                 th.series.push(new PieSeriesProperties());
             }
-            else if (s.renderer.constructor == jQuery.jqplot.DonutRenderer) {
+            else if (s.renderer.constructor == $.jqplot.DonutRenderer) {
                 th.series.push(new DonutSeriesProperties());
             }
-            else if (s.renderer.constructor == jQuery.jqplot.FunnelRenderer) {
+            else if (s.renderer.constructor == $.jqplot.FunnelRenderer) {
                 th.series.push(new FunnelSeriesProperties());
             }
-            else if (s.renderer.constructor == jQuery.jqplot.MeterGaugeRenderer) {
+            else if (s.renderer.constructor == $.jqplot.MeterGaugeRenderer) {
                 th.series.push(new MeterSeriesProperties());
             }
             else {
@@ -8433,7 +8437,7 @@
      * 
      * Theme instance of given name.
      */   
-    jQuery.jqplot.ThemeEngine.prototype.get = function(name) {
+    $.jqplot.ThemeEngine.prototype.get = function(name) {
         if (!name) {
             // return the active theme
             return this.activeTheme;
@@ -8458,7 +8462,7 @@
      * 
      * A the list of theme names in this manager in alpha-numerical order.
      */       
-    jQuery.jqplot.ThemeEngine.prototype.getThemeNames = function() {
+    $.jqplot.ThemeEngine.prototype.getThemeNames = function() {
         var tn = [];
         for (var n in this.themes) {
             tn.push(n);
@@ -8479,7 +8483,7 @@
      * 
      * A list of themes in alpha-numerical order by name.
      */ 
-    jQuery.jqplot.ThemeEngine.prototype.getThemes = function() {
+    $.jqplot.ThemeEngine.prototype.getThemes = function() {
         var tn = [];
         var themes = [];
         for (var n in this.themes) {
@@ -8492,7 +8496,7 @@
         return themes;
     };
     
-    jQuery.jqplot.ThemeEngine.prototype.activate = function(plot, name) {
+    $.jqplot.ThemeEngine.prototype.activate = function(plot, name) {
         // sometimes need to redraw whole plot.
         var redrawPlot = false;
         if (!name && this.activeTheme && this.activeTheme._name) {
@@ -8522,7 +8526,7 @@
                 if (axis.show) {
                     var thaxis = th.axes[axname] || {};
                     var thaxstyle = th.axesStyles;
-                    var thax = jQuery.jqplot.extend(true, {}, thaxis, thaxstyle);
+                    var thax = $.jqplot.extend(true, {}, thaxis, thaxstyle);
                     val = (th.axesStyles.borderColor != null) ? th.axesStyles.borderColor : thax.borderColor;
                     if (thax.borderColor != null) {
                         axis.borderColor = thax.borderColor;
@@ -8637,7 +8641,7 @@
         
     };
     
-    jQuery.jqplot.ThemeEngine.prototype._add = function(theme, name) {
+    $.jqplot.ThemeEngine.prototype._add = function(theme, name) {
         if (name) {
             theme._name = name;
         }
@@ -8669,7 +8673,7 @@
      * 
      * true on success, false on failure.
      */
-    jQuery.jqplot.ThemeEngine.prototype.remove = function(name) {
+    $.jqplot.ThemeEngine.prototype.remove = function(name) {
         if (name == 'Default') {
             return false;
         }
@@ -8690,7 +8694,7 @@
      * 
      * new Theme object.
      */
-    jQuery.jqplot.ThemeEngine.prototype.newTheme = function(name, obj) {
+    $.jqplot.ThemeEngine.prototype.newTheme = function(name, obj) {
         if (typeof(name) == 'object') {
             obj = obj || name;
             name = null;
@@ -8701,9 +8705,9 @@
         else {
             name = name || Date.parse(new Date());
         }
-        // var th = new jQuery.jqplot.Theme(name);
+        // var th = new $.jqplot.Theme(name);
         var th = this.copy(this.themes['Default']._name, name);
-        jQuery.jqplot.extend(th, obj);
+        $.jqplot.extend(th, obj);
         return th;
     };
     
@@ -8723,7 +8727,7 @@
         return temp;
     }
     
-    jQuery.jqplot.clone = clone;
+    $.jqplot.clone = clone;
     
     function merge(obj1, obj2) {
         if (obj2 ==  null || typeof(obj2) != 'object') {
@@ -8745,10 +8749,10 @@
         }
     }
     
-    jQuery.jqplot.merge = merge;
+    $.jqplot.merge = merge;
     
         // Use the jQuery 1.3.2 extend function since behaviour in jQuery 1.4 seems problematic
-    jQuery.jqplot.extend = function() {
+    $.jqplot.extend = function() {
         // copy reference to target object
         var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
 
@@ -8779,7 +8783,7 @@
 
                     // Recurse if we're merging object values
                     if ( deep && copy && typeof copy === "object" && !copy.nodeType ) {
-                        target[ name ] = jQuery.jqplot.extend( deep, 
+                        target[ name ] = $.jqplot.extend( deep, 
                             // Never move original objects, clone them
                             src || ( copy.length != null ? [ ] : { } )
                         , copy );
@@ -8809,7 +8813,7 @@
      * 
      * new Theme object.
      */
-    jQuery.jqplot.ThemeEngine.prototype.rename = function (oldName, newName) {
+    $.jqplot.ThemeEngine.prototype.rename = function (oldName, newName) {
         if (oldName == 'Default' || newName == 'Default') {
             throw new Error ("jqplot.ThemeEngine Error: Cannot rename from/to Default");
         }
@@ -8839,7 +8843,7 @@
      * 
      * new Theme object.
      */
-    jQuery.jqplot.ThemeEngine.prototype.copy = function (sourceName, targetName, obj) {
+    $.jqplot.ThemeEngine.prototype.copy = function (sourceName, targetName, obj) {
         if (targetName == 'Default') {
             throw new Error ("jqplot.ThemeEngine Error: Cannot copy over Default theme");
         }
@@ -8854,14 +8858,14 @@
         else {
             var th = clone(this.themes[sourceName]);
             th._name = targetName;
-            jQuery.jqplot.extend(true, th, obj);
+            $.jqplot.extend(true, th, obj);
             this._add(th);
             return th;
         }
     };
     
     
-    jQuery.jqplot.Theme = function(name, obj) {
+    $.jqplot.Theme = function(name, obj) {
         if (typeof(name) == 'object') {
             obj = obj || name;
             name = null;
@@ -8901,7 +8905,7 @@
             this._name = obj;
         }
         else if(typeof(obj) == 'object') {
-            jQuery.jqplot.extend(true, this, obj);
+            $.jqplot.extend(true, this, obj);
         }
     };
     
@@ -9014,14 +9018,14 @@
 
 
 
-    jQuery.fn.jqplotChildText = function() {
+    $.fn.jqplotChildText = function() {
         return $(this).contents().filter(function() {
             return this.nodeType == 3;  // Node.TEXT_NODE not defined in I7
         }).text();
     };
 
     // Returns font style as abbreviation for "font" property.
-    jQuery.fn.jqplotGetComputedFontStyle = function() {
+    $.fn.jqplotGetComputedFontStyle = function() {
         var css = window.getComputedStyle ?  window.getComputedStyle(this[0], "") : this[0].currentStyle;
         var attrs = css['font-style'] ? ['font-style', 'font-weight', 'font-size', 'font-family'] : ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily'];
         var style = [];
@@ -9037,12 +9041,12 @@
     };
 
     /**
-     * Namespace: jQuery.fn
+     * Namespace: $.fn
      * jQuery namespace to attach functions to jQuery elements.
      *  
      */
 
-    jQuery.fn.jqplotToImageCanvas = function(options) {
+    $.fn.jqplotToImageCanvas = function(options) {
 
         options = options || {};
         var x_offset = (options.x_offset == null) ? 0 : options.x_offset;
@@ -9054,7 +9058,7 @@
         }
 
         // excanvas and hence IE < 9 do not support toDataURL and cannot export images.
-        if (jQuery.jqplot.use_excanvas) {
+        if ($.jqplot.use_excanvas) {
             return null;
         }
         
@@ -9257,7 +9261,7 @@
 
     // return the raw image data string.
     // Should work on canvas supporting browsers.
-    jQuery.fn.jqplotToImageStr = function(options) {
+    $.fn.jqplotToImageStr = function(options) {
         var imgCanvas = $(this).jqplotToImageCanvas(options);
         if (imgCanvas) {
             return imgCanvas.toDataURL("image/png");
@@ -9269,7 +9273,7 @@
 
     // return a DOM <img> element and return it.
     // Should work on canvas supporting browsers.
-    jQuery.fn.jqplotToImageElem = function(options) {
+    $.fn.jqplotToImageElem = function(options) {
         var elem = document.createElement("img");
         var str = $(this).jqplotToImageStr(options);
         elem.src = str;
@@ -9278,14 +9282,14 @@
 
     // return a string for an <img> element and return it.
     // Should work on canvas supporting browsers.
-    jQuery.fn.jqplotToImageElemStr = function(options) {
+    $.fn.jqplotToImageElemStr = function(options) {
         var str = '<img src='+$(this).jqplotToImageStr(options)+' />';
         return str;
     };
 
-    // Not gauranteed to work, even on canvas supporting browsers due to 
+    // Not guaranteed to work, even on canvas supporting browsers due to 
     // limitations with location.href and browser support.
-    jQuery.fn.jqplotSaveImage = function() {
+    $.fn.jqplotSaveImage = function() {
         var imgData = $(this).jqplotToImageStr({});
         if (imgData) {
             window.location.href = imgData.replace("image/png", "image/octet-stream");
@@ -9293,9 +9297,9 @@
 
     };
 
-    // Not gauranteed to work, even on canvas supporting browsers due to
+    // Not guaranteed to work, even on canvas supporting browsers due to
     // limitations with window.open and arbitrary data.
-    jQuery.fn.jqplotViewImage = function() {
+    $.fn.jqplotViewImage = function() {
         var imgStr = $(this).jqplotToImageElemStr({});
         var imgData = $(this).jqplotToImageStr({});
         if (imgStr) {
@@ -9323,12 +9327,12 @@
      * @author Chris Leonello
      * @date #date#
      * @version #VERSION#
-     * @copyright (c) 2010 Chris Leonello
+     * @copyright (c) 2010-2013 Chris Leonello
      * jsDate is currently available for use in all personal or commercial projects 
      * under both the MIT and GPL version 2.0 licenses. This means that you can 
      * choose the license that best suits your project and use it accordingly.
      * 
-     * <p>Ken's origianl Date Instance Methods and copyright notice:</p>
+     * <p>Ken's original Date Instance Methods and copyright notice:</p>
      * <pre>
      * Ken Snyder (ken d snyder at gmail dot com)
      * 2008-09-10
@@ -9616,7 +9620,7 @@
     
     jsDate.prototype.getIsoWeek = function() {
         var d = this.proxy;
-        var woy = d.getWeekOfYear();
+        var woy = this.getWeekOfYear();
         var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay();
         // First week is 01 and not 00 as in the case of %U and %W,
         // so we add 1 to the final result except if day 1 of the year
@@ -10010,8 +10014,31 @@
             dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'],
             dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
             formatString: '%Y-%m-%d %H:%M:%S'
-        }
+        },
         
+        'pl': {
+            monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec','Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
+            monthNamesShort: ['Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze','Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'],
+            dayNames: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'],
+            dayNamesShort: ['Ni', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'Sb'],
+            formatString: '%Y-%m-%d %H:%M:%S'
+        },
+
+        'nl': {
+            monthNames: ['Januari','Februari','Maart','April','Mei','Juni','July','Augustus','September','Oktober','November','December'],
+            monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Aug','Sep','Okt','Nov','Dec'],
+            dayNames:','['Zondag','Maandag','Dinsdag','Woensdag','Donderdag','Vrijdag','Zaterdag'],
+            dayNamesShort: ['Zo','Ma','Di','Wo','Do','Vr','Za'],
+            formatString: '%Y-%m-%d %H:%M:%S'
+        },
+
+        'sv': {
+            monthNames: ['januari','februari','mars','april','maj','juni','juli','augusti','september','oktober','november','december'],
+          monthNamesShort: ['jan','feb','mar','apr','maj','jun','jul','aug','sep','okt','nov','dec'],
+            dayNames: ['söndag','måndag','tisdag','onsdag','torsdag','fredag','lördag'],
+            dayNamesShort: ['sön','mån','tis','ons','tor','fre','lör'],
+            formatString: '%Y-%m-%d %H:%M:%S'
+        }
     
     };
     
@@ -10819,12 +10846,12 @@
       * Format: '%.4g', Input: 4.321e-5, Output: 4.3210e-5
       * 
       * Example:
-      * >>> jQuery.jqplot.sprintf('%.2f, %d', 23.3452, 43.23)
+      * >>> $.jqplot.sprintf('%.2f, %d', 23.3452, 43.23)
       * "23.35, 43"
-      * >>> jQuery.jqplot.sprintf("no value: %n, decimal with thousands separator: %'d", 23.3452, 433524)
+      * >>> $.jqplot.sprintf("no value: %n, decimal with thousands separator: %'d", 23.3452, 433524)
       * "no value: , decimal with thousands separator: 433,524"
       */
-    jQuery.jqplot.sprintf = function() {
+    $.jqplot.sprintf = function() {
         function pad(str, len, chr, leftJustify) {
             var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
             return leftJustify ? str + padding : padding + str;
@@ -10834,7 +10861,7 @@
         function thousand_separate(value) {
             var value_str = new String(value);
             for (var i=10; i>0; i--) {
-                if (value_str == (value_str = value_str.replace(/^(\d+)(\d{3})/, "$1"+jQuery.jqplot.sprintf.thousandsSeparator+"$2"))) break;
+                if (value_str == (value_str = value_str.replace(/^(\d+)(\d{3})/, "$1"+$.jqplot.sprintf.thousandsSeparator+"$2"))) break;
             }
             return value_str; 
         }
@@ -10870,7 +10897,7 @@
 
         var a = arguments, i = 0, format = a[i++];
 
-        return format.replace(jQuery.jqplot.sprintf.regex, function(substring, valueIndex, flags, minWidth, _, precision, type) {
+        return format.replace($.jqplot.sprintf.regex, function(substring, valueIndex, flags, minWidth, _, precision, type) {
             if (substring == '%%') { return '%'; }
 
             // parse flags
@@ -10908,7 +10935,7 @@
             }
 
             if (!isFinite(minWidth)) {
-                throw new Error('jQuery.jqplot.sprintf: (minimum-)width must be finite');
+                throw new Error('$.jqplot.sprintf: (minimum-)width must be finite');
             }
 
             if (!precision) {
@@ -10976,15 +11003,18 @@
                       var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
                       var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
                       var number_str = Math.abs(number)[method](precision);
-                      number_str = thousandSeparation ? thousand_separate(number_str): number_str;
+                      
+                      // Apply the decimal mark properly by splitting the number by the
+                      //   decimalMark, applying thousands separator, and then placing it
+                      //   back in.
+                      var parts = number_str.toString().split('.');
+                      parts[0] = thousandSeparation ? thousand_separate(parts[0]) : parts[0];
+                      number_str = parts.join($.jqplot.sprintf.decimalMark);
+                      
                       value = prefix + number_str;
                       var justified = justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform]();
-
-                      if (jQuery.jqplot.sprintf.decimalMark !== '.' && jQuery.jqplot.sprintf.decimalMark !== jQuery.jqplot.sprintf.thousandsSeparator) {
-                          return justified.replace(/\./, jQuery.jqplot.sprintf.decimalMark);
-                      } else {
-                          return justified;
-                      }
+                      
+                      return justified;
                   }
             case 'p':
             case 'P':
@@ -10997,7 +11027,7 @@
                 var prefix = number < 0 ? '-' : positivePrefix;
 
                 var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/);
-                var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : parts[0].length;
+                var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : String(number).length;
                 var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0;
                 
                 if (Math.abs(number) < 1) {
@@ -11026,16 +11056,16 @@
         });
     };
 
-    jQuery.jqplot.sprintf.thousandsSeparator = ',';
+    $.jqplot.sprintf.thousandsSeparator = ',';
     // Specifies the decimal mark for floating point values. By default a period '.'
     // is used. If you change this value to for example a comma be sure to also
     // change the thousands separator or else this won't work since a simple String
     // replace is used (replacing all periods with the mark specified here).
-    jQuery.jqplot.sprintf.decimalMark = '.';
+    $.jqplot.sprintf.decimalMark = '.';
     
-    jQuery.jqplot.sprintf.regex = /%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g;
+    $.jqplot.sprintf.regex = /%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g;
 
-    jQuery.jqplot.getSignificantFigures = function(number) {
+    $.jqplot.getSignificantFigures = function(number) {
         var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/);
         // total significant digits
         var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : parts[0].length;
@@ -11049,16 +11079,16 @@
         return {significantDigits: sd, digitsLeft: dleft, digitsRight: dright, zeros: zeros, exponent: expn} ;
     };
 
-    jQuery.jqplot.getPrecision = function(number) {
-        return jQuery.jqplot.getSignificantFigures(number).digitsRight;
+    $.jqplot.getPrecision = function(number) {
+        return $.jqplot.getSignificantFigures(number).digitsRight;
     };
 
-})(jQuery);  
+  
 
 
     var backCompat = $.uiBackCompat !== false;
 
-    jQuery.jqplot.effects = {
+    $.jqplot.effects = {
         effect: {}
     };
 
@@ -11069,7 +11099,7 @@
     /*********************************** EFFECTS **********************************/
     /******************************************************************************/
 
-    jQuery.extend( jQuery.jqplot.effects, {
+    $.extend( $.jqplot.effects, {
         version: "1.9pre",
 
         // Saves a set of properties in a data storage
@@ -11141,7 +11171,7 @@
                 wrapper.css({ position: "relative" });
                 element.css({ position: "relative" });
             } else {
-                jQuery.extend( props, {
+                $.extend( props, {
                     position: element.css( "position" ),
                     zIndex: element.css( "z-index" )
                 });
@@ -11219,7 +11249,7 @@
 
         // add options to effect
         if ( options ) {
-            jQuery.extend( effect, options );
+            $.extend( effect, options );
         }
 
         speed = speed || options.duration;
@@ -11238,9 +11268,9 @@
         }
 
         // invalid strings - treat as "normal" speed
-        if ( typeof speed === "string" && !jQuery.jqplot.effects.effect[ speed ] ) {
+        if ( typeof speed === "string" && !$.jqplot.effects.effect[ speed ] ) {
             // TODO: remove in 2.0 (#7115)
-            if ( backCompat && jQuery.jqplot.effects[ speed ] ) {
+            if ( backCompat && $.jqplot.effects[ speed ] ) {
                 return false;
             }
             return true;
@@ -11249,15 +11279,15 @@
         return false;
     }
 
-    jQuery.fn.extend({
+    $.fn.extend({
         jqplotEffect: function( effect, options, speed, callback ) {
             var args = _normalizeArguments.apply( this, arguments ),
                 mode = args.mode,
                 queue = args.queue,
-                effectMethod = jQuery.jqplot.effects.effect[ args.effect ],
+                effectMethod = $.jqplot.effects.effect[ args.effect ],
 
                 // DEPRECATED: remove in 2.0 (#7115)
-                oldEffectMethod = !effectMethod && backCompat && jQuery.jqplot.effects[ args.effect ];
+                oldEffectMethod = !effectMethod && backCompat && $.jqplot.effects[ args.effect ];
 
             if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) {
                 // delegate to the original method (e.g., .show()) if possible
@@ -11316,11 +11346,11 @@
     var rvertical = /up|down|vertical/,
         rpositivemotion = /up|left|vertical|horizontal/;
 
-    jQuery.jqplot.effects.effect.blind = function( o, done ) {
+    $.jqplot.effects.effect.blind = function( o, done ) {
         // Create element
         var el = $( this ),
             props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-            mode = jQuery.jqplot.effects.setMode( el, o.mode || "hide" ),
+            mode = $.jqplot.effects.setMode( el, o.mode || "hide" ),
             direction = o.direction || "up",
             vertical = rvertical.test( direction ),
             ref = vertical ? "height" : "width",
@@ -11332,13 +11362,13 @@
 
         // // if already wrapped, the wrapper's properties are my property. #6245
         if ( el.parent().is( ".ui-effects-wrapper" ) ) {
-            jQuery.jqplot.effects.save( el.parent(), props );
+            $.jqplot.effects.save( el.parent(), props );
         } else {
-            jQuery.jqplot.effects.save( el, props );
+            $.jqplot.effects.save( el, props );
         }
         el.show();
         top = parseInt(el.css('top'), 10);
-        wrapper = jQuery.jqplot.effects.createWrapper( el ).css({
+        wrapper = $.jqplot.effects.createWrapper( el ).css({
             overflow: "hidden"
         });
 
@@ -11370,12 +11400,12 @@
                 if ( mode === "hide" ) {
                     el.hide();
                 }
-                jQuery.jqplot.effects.restore( el, props );
-                jQuery.jqplot.effects.removeWrapper( el );
+                $.jqplot.effects.restore( el, props );
+                $.jqplot.effects.removeWrapper( el );
                 done();
             }
         });
 
     };
 
-
+})(jQuery);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.BezierCurveRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.BezierCurveRenderer.js
index ecb3fc2..1c7b031 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.BezierCurveRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.BezierCurveRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -289,6 +289,7 @@
     function preInit(target, data, options) {
         options = options || {};
         options.axesDefaults = $.extend(true, {pad:0}, options.axesDefaults);
+        options.seriesDefaults = options.seriesDefaults || {};
         options.legend = $.extend(true, {placement:'outside'}, options.legend);
         // only set these if there is a pie series
         var setopts = false;
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.barRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.barRenderer.js
index 920c16b..9b714e9 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.barRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.barRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -115,7 +115,7 @@
         
         //////
         // This is probably wrong here.
-        // After going back and forth on wether renderer should be the thing
+        // After going back and forth on whether renderer should be the thing
         // or extend the thing, it seems that it it best if it is a property
         // on the thing.  This should be something that is commonized 
         // among series renderers in the future.
@@ -198,14 +198,20 @@
             var count = 0;
             for (var i=skip; i<l; i+=skip) {
                 this.data.splice(i+count, 0, [null, null]);
+                this._plotData.splice(i+count, 0, [null, null]);
+                this._stackData.splice(i+count, 0, [null, null]);
                 count++;
             }
             for (i=0; i<this.data.length; i++) {
                 if (this._primaryAxis == '_xaxis') {
                     this.data[i][0] = i+1;
+                    this._plotData[i][0] = i+1;
+                    this._stackData[i][0] = i+1;
                 }
                 else {
                     this.data[i][1] = i+1;
+                    this._plotData[i][1] = i+1;
+                    this._stackData[i][1] = i+1;
                 }
             }
         }
@@ -344,7 +350,7 @@
         var nvals = temp[0];
         var nseries = temp[1];
         var pos = temp[2];
-		var points = [];
+        var points = [];
         
         if (this._stack) {
             this._barNudge = 0;
@@ -360,9 +366,9 @@
                 negativeColor = opts.fillStyle;
             }
             var positiveColor = opts.fillStyle;
-			var base;
-			var xstart; 
-			var ystart;
+            var base;
+            var xstart; 
+            var ystart;
             
             if (this.barDirection == 'vertical') {
                 for (var i=0; i<gridData.length; i++) {
@@ -432,20 +438,20 @@
                             opts.fillStyle = positiveColor;
                         }
                     }
-					
-					if (!this.fillToZero || this._plotData[i][1] >= 0) { 
-						points.push([base-this.barWidth/2, ystart]);
-						points.push([base-this.barWidth/2, gridData[i][1]]);
-						points.push([base+this.barWidth/2, gridData[i][1]]);
-						points.push([base+this.barWidth/2, ystart]);
-					}
-					// for negative bars make sure points are always ordered clockwise
-					else {              
-						points.push([base-this.barWidth/2, gridData[i][1]]);
-						points.push([base-this.barWidth/2, ystart]);
-						points.push([base+this.barWidth/2, ystart]);
-						points.push([base+this.barWidth/2, gridData[i][1]]);
-					}
+                    
+                    if (!this.fillToZero || this._plotData[i][1] >= 0) { 
+                        points.push([base-this.barWidth/2, ystart]);
+                        points.push([base-this.barWidth/2, gridData[i][1]]);
+                        points.push([base+this.barWidth/2, gridData[i][1]]);
+                        points.push([base+this.barWidth/2, ystart]);
+                    }
+                    // for negative bars make sure points are always ordered clockwise
+                    else {              
+                        points.push([base-this.barWidth/2, gridData[i][1]]);
+                        points.push([base-this.barWidth/2, ystart]);
+                        points.push([base+this.barWidth/2, ystart]);
+                        points.push([base+this.barWidth/2, gridData[i][1]]);
+                    }
                     this._barPoints.push(points);
                     // now draw the shadows if not stacked.
                     // for stacked plots, they are predrawn by drawShadow
@@ -507,7 +513,7 @@
                             xstart = 0;
                         }
                     }
-                    if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) {
+                    if ((this.fillToZero && this._plotData[i][0] < 0) || (this.waterfall && this._data[i][0] < 0)) {
                         if (this.varyBarColor && !this._stack) {
                             if (this.useNegativeColors) {
                                 opts.fillStyle = negativeColors.next();
@@ -516,6 +522,9 @@
                                 opts.fillStyle = positiveColors.next();
                             }
                         }
+                        else {
+                            opts.fillStyle = negativeColor;
+                        }
                     }
                     else {
                         if (this.varyBarColor && !this._stack) {
@@ -723,9 +732,10 @@
             evt1.pageX = ev.pageX;
             evt1.pageY = ev.pageY;
             plot.target.trigger(evt1, ins);
-            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
+            if (plot.series[ins[0]].show && plot.series[ins[0]].highlightMouseOver &&
+                !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -742,7 +752,7 @@
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -765,7 +775,7 @@
         if (neighbor) {
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             var evt = jQuery.Event('jqplotDataClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
@@ -780,7 +790,7 @@
                 unhighlight(plot);
             }
             var evt = jQuery.Event('jqplotDataRightClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
@@ -788,4 +798,4 @@
     }
     
     
-})(jQuery);    
\ No newline at end of file
+})(jQuery);
\ No newline at end of file
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.blockRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.blockRenderer.js
index 4467d0b..e7c782c 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.blockRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.blockRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.bubbleRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.bubbleRenderer.js
index e45ebe2..1629d85 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.bubbleRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.bubbleRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -632,7 +632,7 @@
             plot.target.trigger(evt1, ins);
             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -651,7 +651,7 @@
             var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
             if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -676,7 +676,7 @@
             var pi = neighbor.pointIndex;
             var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
             var evt = jQuery.Event('jqplotDataClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
@@ -693,7 +693,7 @@
                 unhighlight(plot);
             }
             var evt = jQuery.Event('jqplotDataRightClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.canvasAxisLabelRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.canvasAxisLabelRenderer.js
index 1385089..6313dc1 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.canvasAxisLabelRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.canvasAxisLabelRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -52,10 +52,10 @@
         // name of the axis associated with this tick
         this.axis;
         // prop: show
-        // wether or not to show the tick (mark and label).
+        // whether or not to show the tick (mark and label).
         this.show = true;
         // prop: showLabel
-        // wether or not to show the label.
+        // whether or not to show the label.
         this.showLabel = true;
         // prop: label
         // label for the axis.
@@ -186,8 +186,8 @@
         elem.style.width = w;
         elem.style.height = h;
         
-		elem = plot.canvasManager.initCanvas(elem);
-		
+        elem = plot.canvasManager.initCanvas(elem);
+
         this._elem = $(elem);
         this._elem.css({ position: 'absolute'});
         this._elem.addClass('jqplot-'+this.axis+'-label');
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.canvasAxisTickRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.canvasAxisTickRenderer.js
index 36cb7f0..b6120d0 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.canvasAxisTickRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.canvasAxisTickRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -49,10 +49,10 @@
         // tick mark on the axis.  One of 'inside', 'outside', 'cross', '' or null.
         this.mark = 'outside';
         // prop: showMark
-        // wether or not to show the mark on the axis.
+        // whether or not to show the mark on the axis.
         this.showMark = true;
         // prop: showGridline
-        // wether or not to draw the gridline on the grid at this tick.
+        // whether or not to draw the gridline on the grid at this tick.
         this.showGridline = true;
         // prop: isMinorTick
         // if this is a minor tick.
@@ -65,10 +65,10 @@
         // will be stoked above and below axis, so total length will be twice this.
         this.markSize = 4;
         // prop: show
-        // wether or not to show the tick (mark and label).
+        // whether or not to show the tick (mark and label).
         this.show = true;
         // prop: showLabel
-        // wether or not to show the label.
+        // whether or not to show the label.
         this.showLabel = true;
         // prop: labelPosition
         // 'auto', 'start', 'middle' or 'end'.
@@ -180,6 +180,16 @@
             return w;
         }
     };
+
+    // return top.
+    $.jqplot.CanvasAxisTickRenderer.prototype.getTop = function(ctx) {
+        if (this._elem) {
+         return this._elem.position().top;
+        }
+        else {
+            return null;
+        }
+    };
     
     $.jqplot.CanvasAxisTickRenderer.prototype.getAngleRad = function() {
         var a = this.angle * Math.PI/180;
@@ -225,13 +235,13 @@
         elem.style.height = h;
         elem.style.textAlign = 'left';
         elem.style.position = 'absolute';
-		
-		elem = plot.canvasManager.initCanvas(elem);
-		
+
+        elem = plot.canvasManager.initCanvas(elem);
+
         this._elem = $(elem);
         this._elem.css(this._styles);
         this._elem.addClass('jqplot-'+this.axis+'-tick');
-		
+
         elem = null;
         return this._elem;
     };
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.canvasOverlay.js b/src/vendor/jquery-jqplot/plugins/jqplot.canvasOverlay.js
index b9ddaf5..4094413 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.canvasOverlay.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.canvasOverlay.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -66,6 +66,9 @@
                         case 'dashedVerticalLine':
                             this.addDashedVerticalLine(obj[n]);
                             break;
+                        case 'rectangle':
+                            this.addRectangle(obj[n]);
+                            break;
                         default:
                             break;
                     }
@@ -107,7 +110,7 @@
             // color of the line
             color: '#666666',
             // prop: shadow
-            // wether or not to draw a shadow on the line
+            // whether or not to draw a shadow on the line
             shadow: true,
             // prop: shadowAngle
             // Shadow angle in degrees
@@ -153,7 +156,41 @@
             tooltipFormatString: '%d, %d'
         };
     }
+    
+    
+    function Rectangle(options) {
+        LineBase.call(this);
+        this.type = 'rectangle';
+        var opts = {
+         // prop: xmin
+                // x value for the start of the line, null to scale to axis min.
+                xmin: null,
+                // prop: xmax
+                // x value for the end of the line, null to scale to axis max.
+                xmax: null,
+                // prop xOffset
+                // offset ends of the line inside the grid. Number
+                xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
+                xminOffset: null,
+                xmaxOffset: null,
+                
+                ymin: null,
+                ymax: null,
+                yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
+                yminOffset: null,
+                ymaxOffset: null
+        };
+        $.extend(true, this.options, opts, options);
 
+        if (this.options.showTooltipPrecision < 0.01) {
+            this.options.showTooltipPrecision = 0.01;
+        }
+    }
+
+    Rectangle.prototype = new LineBase();
+    Rectangle.prototype.constructor = Rectangle;
+
+    
     /**
      * Class: Line
      * A straight line.
@@ -338,6 +375,13 @@
         this.objectNames.push(line.options.name);
     };
     
+    $.jqplot.CanvasOverlay.prototype.addRectangle = function(opts) {
+        var line = new Rectangle(opts);
+        line.uid = objCounter++;
+        this.objects.push(line);
+        this.objectNames.push(line.options.name);
+    };
+    
     $.jqplot.CanvasOverlay.prototype.removeObject = function(idx) {
         // check if integer, remove by index
         if ($.type(idx) == 'number') {
@@ -621,6 +665,80 @@
                                 }
                             }
                             break;
+                            
+                        case 'rectangle':
+                            // style and shadow properties should be set before
+                            // every draw of marker renderer.
+                            mr.style = 'line';
+                            opts.closePath = true;
+                            
+                            var xaxis = plot.axes[obj.options.xaxis],
+                                    xstart,
+                                    xstop,
+                                    y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
+                                    xminoff = obj.options.xminOffset || obj.options.xOffset,
+                                    xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
+                            if (obj.options.xmin != null) {
+                                xstart = xaxis.series_u2p(obj.options.xmin);
+                            }
+                            else if (xminoff != null) {
+                                if ($.type(xminoff) == "number") {
+                                    xstart = xaxis.series_u2p(xaxis.min + xminoff);
+                                }
+                                else if ($.type(xminoff) == "string") {
+                                    xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
+                                }
+                            }
+                            if (obj.options.xmax != null) {
+                                xstop = xaxis.series_u2p(obj.options.xmax);
+                            }
+                            else if (xmaxoff != null) {
+                                if ($.type(xmaxoff) == "number") {
+                                    xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
+                                }
+                                else if ($.type(xmaxoff) == "string") {
+                                    xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
+                                }
+                            }
+                            
+                            var yaxis = plot.axes[obj.options.yaxis],
+                                ystart,
+                                ystop,
+                                x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
+                                yminoff = obj.options.yminOffset || obj.options.yOffset,
+                                ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
+                            if (obj.options.ymin != null) {
+                                ystart = yaxis.series_u2p(obj.options.ymin);
+                            }
+                            else if (yminoff != null) {
+                                if ($.type(yminoff) == "number") {
+                                    ystart = yaxis.series_u2p(yaxis.min - yminoff);
+                                }
+                                else if ($.type(yminoff) == "string") {
+                                    ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
+                                }
+                            }
+                            if (obj.options.ymax != null) {
+                                ystop = yaxis.series_u2p(obj.options.ymax);
+                            }
+                            else if (ymaxoff != null) {
+                                if ($.type(ymaxoff) == "number") {
+                                    ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
+                                }
+                                else if ($.type(ymaxoff) == "string") {
+                                    ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
+                                }
+                            }
+                            
+
+                            if (xstop != null && xstart != null && ystop != null && ystart != null) {
+                                obj.gridStart = [xstart, ystart];
+                                obj.gridStop = [xstop, ystop];
+                                
+                                this.canvas._ctx.fillStyle = obj.options.color;
+                                this.canvas._ctx.fillRect(xstart, ystart, xstop - xstart, ystop - ystart);
+                            }
+                            break;
 
                         default:
                             break;
@@ -738,6 +856,24 @@
         var ret = (res < eps) ? true : false;
         return ret;
     }
+    
+    function isNearRectangle(point, lstart, lstop, width) {
+        // r is point to test, p and q are end points.
+        var rx = point[0];
+        var ry = point[1];
+        var px = Math.round(lstop[0]);
+        var py = Math.round(lstop[1]);
+        var qx = Math.round(lstart[0]);
+        var qy = Math.round(lstart[1]);
+        
+        var temp;
+        if (px > qx) { temp = px; px = qx; qx = temp; }
+        if (py > qy) { temp = py; py = qy; qy = temp; }
+        
+        var ret = (rx >= px && rx <= qx && ry >= py && ry <= qy);
+        
+        return ret;
+    }
 
 
     function handleMove(ev, gridpos, datapos, neighbor, plot) {
@@ -749,7 +885,12 @@
         for (var i=0; i<l; i++) {
             obj = objs[i];
             if (obj.options.showTooltip) {
-                var n = isNearLine([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);
+            	var n;
+                if (obj.type === 'rectangle') {
+                 n = isNearRectangle([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);
+                } else {
+                 n = isNearLine([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);
+                }
                 datapos = [plot.axes[obj.options.xaxis].series_p2u(gridpos.x), plot.axes[obj.options.yaxis].series_p2u(gridpos.y)];
 
                 // cases:
@@ -775,6 +916,11 @@
                         case 'dashedVerticalLine':
                             showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
                             break;
+                            
+                        case 'rectangle':
+                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
+                            break;
+                            
                         default:
                             break;
                     } 
@@ -809,6 +955,11 @@
                         case 'dashedVerticalLine':
                             showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
                             break;
+                            
+                        case 'rectangle':
+                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
+                            break;
+                            
                         default:
                             break;
                     }
@@ -834,6 +985,11 @@
                         case 'dashedVerticalLine':
                             showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
                             break;
+                            
+                        case 'rectangle':
+                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
+                            break;
+                            
                         default:
                             break;
                     }
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.canvasTextRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.canvasTextRenderer.js
index 447b4d5..dc8434e 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.canvasTextRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.canvasTextRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -29,7 +29,7 @@
  *
  * included jsDate library by Chris Leonello:
  *
- * Copyright (c) 2010-2012 Chris Leonello
+ * Copyright (c) 2010-2013 Chris Leonello
  *
  * jsDate is currently available for use in all personal or commercial projects 
  * under both the MIT and GPL version 2.0 licenses. This means that you can 
@@ -38,7 +38,7 @@
  * jsDate borrows many concepts and ideas from the Date Instance 
  * Methods by Ken Snyder along with some parts of Ken's actual code.
  * 
- * Ken's origianl Date Instance Methods and copyright notice:
+ * Ken's original Date Instance Methods and copyright notice:
  * 
  * Ken Snyder (ken d snyder at gmail dot com)
  * 2008-09-10
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.categoryAxisRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.categoryAxisRenderer.js
index bc9ac39..aa77120 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.categoryAxisRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.categoryAxisRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -211,7 +211,11 @@
             }
             
             if (isMerged && this.sortMergedLabels) {
-                labels.sort(function(a,b) { return a - b; });
+                if (typeof labels[0] == "string") {
+                    labels.sort();
+                } else {
+                    labels.sort(function(a,b) { return a - b; });
+                }
             }
             
             // keep a reference to these tick labels to use for redrawing plot (see bug #57)
@@ -306,7 +310,7 @@
             // call it within the scope of the axis.
             this.renderer.createTicks.call(this);
             // fill a div with axes labels in the right direction.
-            // Need to pregenerate each axis to get it's bounds and
+            // Need to pregenerate each axis to get its bounds and
             // position it and the labels correctly on the plot.
             var dim=0;
             var temp;
@@ -432,7 +436,7 @@
         var offmin = offsets.min;
         var lshow = (this._label == null) ? false : this._label.show;
         var i;
-		
+
         for (var p in pos) {
             this._elem.css(p, pos[p]);
         }
@@ -564,11 +568,12 @@
                 }
                 
                 // draw the group labels
-                var step = parseInt(this._ticks.length/this.groups, 10);
+                var step = parseInt(this._ticks.length/this.groups, 10) + 1;
                 for (i=0; i<this._groupLabels.length; i++) {
                     var mid = 0;
                     var count = 0;
-                    for (var j=i*step; j<=(i+1)*step; j++) {
+                    for (var j=i*step; j<(i+1)*step; j++) {
+                        if (j >= this._ticks.length-1) continue; // the last tick does not exist as there is no other group in order to have an empty one.
                         if (this._ticks[j]._elem && this._ticks[j].label != " ") {
                             var t = this._ticks[j]._elem;
                             var p = t.position();
@@ -648,11 +653,12 @@
                 }
                 
                 // draw the group labels, position top here, do left after label position.
-                var step = parseInt(this._ticks.length/this.groups, 10);
+                var step = parseInt(this._ticks.length/this.groups, 10) + 1; // step is one more than before as we don't want to have overlaps in loops
                 for (i=0; i<this._groupLabels.length; i++) {
                     var mid = 0;
                     var count = 0;
-                    for (var j=i*step; j<=(i+1)*step; j++) {
+                    for (var j=i*step; j<(i+1)*step; j++) { // j must never reach (i+1)*step as we don't want to have overlap between loops
+                        if (j >= this._ticks.length-1) continue; // the last tick does not exist as there is no other group in order to have an empty one.
                         if (this._ticks[j]._elem && this._ticks[j].label != " ") {
                             var t = this._ticks[j]._elem;
                             var p = t.position();
@@ -670,4 +676,4 @@
     };    
     
     
-})(jQuery);
\ No newline at end of file
+})(jQuery);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.ciParser.js b/src/vendor/jquery-jqplot/plugins/jqplot.ciParser.js
index d51036d..2f094fc 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.ciParser.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.ciParser.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -54,7 +54,7 @@
     $.jqplot.ciParser = function (data, plot) {
         var ret = [],
             line,
-			temp,
+            temp,
             i, j, k, kk;
     
          if (typeof(data) == "string") {
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.cursor.js b/src/vendor/jquery-jqplot/plugins/jqplot.cursor.js
index 0e2f786..bf1c36f 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.cursor.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.cursor.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -42,7 +42,7 @@
         this.style = 'crosshair';
         this.previousCursor = 'auto';
         // prop: show
-        // wether to show the cursor or not.
+        // whether to show the cursor or not.
         this.show = $.jqplot.config.enablePlugins;
         // prop: showTooltip
         // show a cursor position tooltip.  Location of the tooltip
@@ -654,7 +654,7 @@
             
         elem.css('left', x);
         elem.css('top', y);
-	    elem = null;
+        elem = null;
     }
     
     function positionTooltip(plot) { 
@@ -1048,7 +1048,7 @@
         if (this.show) {
             var series = this._series, s;
             // make a table.  one line label per row.
-            var elem = document.createElement('div');
+            var elem = document.createElement('table');
             this._elem = $(elem);
             elem = null;
             this._elem.addClass('jqplot-legend jqplot-cursor-legend');
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.dateAxisRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.dateAxisRenderer.js
index 0a210bf..e371a28 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.dateAxisRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.dateAxisRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -33,7 +33,7 @@
      * Class: $.jqplot.DateAxisRenderer
      * A plugin for a jqPlot to render an axis as a series of date values.
      * This renderer has no options beyond those supplied by the <Axis> class.
-     * It supplies it's own tick formatter, so the tickOptions.formatter option
+     * It supplies its own tick formatter, so the tickOptions.formatter option
      * should not be overridden.
      * 
      * Thanks to Ken Synder for his enhanced Date instance methods which are
@@ -334,14 +334,35 @@
         var tt, i;
         var threshold = 30;
         var insetMult = 1;
+        var daTickInterval = null;
+        
+        // if user specified a tick interval, convert to usable.
+        if (this.tickInterval != null)
+        {
+            // if interval is a number or can be converted to one, use it.
+            // Assume it is in SECONDS!!!
+            if (Number(this.tickInterval)) {
+                daTickInterval = [Number(this.tickInterval), 'seconds'];
+            }
+            // else, parse out something we can build from.
+            else if (typeof this.tickInterval == "string") {
+                var parts = this.tickInterval.split(' ');
+                if (parts.length == 1) {
+                    daTickInterval = [1, parts[0]];
+                }
+                else if (parts.length == 2) {
+                    daTickInterval = [parts[0], parts[1]];
+                }
+            }
+        }
 
         var tickInterval = this.tickInterval;
         
         // if we already have ticks, use them.
         // ticks must be in order of increasing value.
         
-        min = ((this.min != null) ? new $.jsDate(this.min).getTime() : db.min);
-        max = ((this.max != null) ? new $.jsDate(this.max).getTime() : db.max);
+        min = new $.jsDate((this.min != null) ? this.min : db.min).getTime();
+        max = new $.jsDate((this.max != null) ? this.max : db.max).getTime();
 
         // see if we're zooming.  if we are, don't use the min and max we're given,
         // but compute some nice ones.  They will be reset later.
@@ -459,16 +480,16 @@
             }
 
             // If tickInterval is specified, we'll try to honor it.
-            // Not gauranteed to get this interval, but we'll get as close as
+            // Not guaranteed to get this interval, but we'll get as close as
             // we can.
             // tickInterval will be used before numberTicks, that is if
             // both are specified, numberTicks will be ignored.
             else if (this.tickInterval) {
-                titarget = this.tickInterval;
+                titarget = new $.jsDate(0).add(daTickInterval[0], daTickInterval[1]).getTime();
             }
 
             // if numberTicks specified, try to honor it.
-            // Not gauranteed, but will try to get close.
+            // Not guaranteed, but will try to get close.
             else if (this.numberTicks) {
                 nttarget = this.numberTicks;
                 titarget = (max - min) / (nttarget - 1);
@@ -480,9 +501,8 @@
                 var tempti = ret[0];
                 this._autoFormatString = ret[1];
 
-                min = Math.floor(min/tempti) * tempti;
                 min = new $.jsDate(min);
-                min = min.getTime() + min.getUtcOffset();
+                min = Math.floor((min.getTime() - min.getUtcOffset())/tempti) * tempti + min.getUtcOffset();
 
                 nttarget = Math.ceil((max - min) / tempti) + 1;
                 this.min = min;
@@ -640,24 +660,8 @@
                 this.tickInterval = null;
             }
             
-            // if user specified a tick interval, convert to usable.
-            if (this.tickInterval != null)
-            {
-                // if interval is a number or can be converted to one, use it.
-                // Assume it is in SECONDS!!!
-                if (Number(this.tickInterval)) {
-                    this.daTickInterval = [Number(this.tickInterval), 'seconds'];
-                }
-                // else, parse out something we can build from.
-                else if (typeof this.tickInterval == "string") {
-                    var parts = this.tickInterval.split(' ');
-                    if (parts.length == 1) {
-                        this.daTickInterval = [1, parts[0]];
-                    }
-                    else if (parts.length == 2) {
-                        this.daTickInterval = [parts[0], parts[1]];
-                    }
-                }
+            if (this.tickInterval != null && daTickInterval != null) {
+                this.daTickInterval = daTickInterval;
             }
             
             // if min and max are same, space them out a bit
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.donutRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.donutRenderer.js
index 9cdf4fb..9684812 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.donutRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.donutRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -101,7 +101,7 @@
         // null will compute ringMargin based on sliceMargin.
         this.ringMargin = null;
         // prop: fill
-        // true or false, wether to fil the slices.
+        // true or false, whether to fil the slices.
         this.fill = true;
         // prop: shadowOffset
         // offset of the shadow from the slice and offset of 
@@ -703,7 +703,7 @@
             plot.target.trigger(evt1, ins);
             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -720,7 +720,7 @@
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -743,7 +743,7 @@
         if (neighbor) {
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             var evt = jQuery.Event('jqplotDataClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
@@ -758,7 +758,7 @@
                 unhighlight(plot);
             }
             var evt = jQuery.Event('jqplotDataRightClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.dragable.js b/src/vendor/jquery-jqplot/plugins/jqplot.dragable.js
index a5e6eec..a9639bf 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.dragable.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.dragable.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.enhancedLegendRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.enhancedLegendRenderer.js
index 292ada3..5a2cbc6 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.enhancedLegendRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.enhancedLegendRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -73,7 +73,7 @@
         var legend = this;
         if (this.show) {
             var series = this._series;
-			var s;
+            var s;
             var ss = 'position:absolute;';
             ss += (this.background) ? 'background:'+this.background+';' : '';
             ss += (this.border) ? 'border:'+this.border+';' : '';
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.funnelRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.funnelRenderer.js
index 357457a..2cbc9c2 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.funnelRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.funnelRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -102,7 +102,7 @@
         // spacing between funnel sections in pixels.
         this.sectionMargin = 6;
         // prop: fill
-        // true or false, wether to fill the areas.
+        // true or false, whether to fill the areas.
         this.fill = true;
         // prop: shadowOffset
         // offset of the shadow from the area and offset of 
@@ -841,7 +841,7 @@
             plot.target.trigger(evt1, ins);
             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -858,7 +858,7 @@
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -881,7 +881,7 @@
         if (neighbor) {
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             var evt = jQuery.Event('jqplotDataClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
@@ -896,7 +896,7 @@
                 unhighlight(plot);
             }
             var evt = jQuery.Event('jqplotDataRightClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.highlighter.js b/src/vendor/jquery-jqplot/plugins/jqplot.highlighter.js
index ce1573b..3105c85 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.highlighter.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.highlighter.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -44,7 +44,7 @@
      * To disable the tooltip, set "showTooltip" to false.
      * 
      * You can control what data is displayed in the tooltip with various
-     * options.  The "tooltipAxes" option controls wether the x, y or both
+     * options.  The "tooltipAxes" option controls whether the x, y or both
      * data values are displayed.
      * 
      * Some chart types (e.g. hi-low-close) have more than one y value per
@@ -339,12 +339,12 @@
         if (series.markerRenderer.show == true) { 
             ms = (series.markerRenderer.size + opts.sizeAdjust)/2;
         }
-		
-		var loc = locations;
-		if (series.fillToZero && series.fill && neighbor.data[1] < 0) {
-			loc = oppositeLocations;
-		}
-		
+
+        var loc = locations;
+        if (series.fillToZero && series.fill && neighbor.data[1] < 0) {
+          loc = oppositeLocations;
+        }
+
         switch (loc[locationIndicies[opts.tooltipLocation]]) {
             case 'nw':
                 var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - fact * ms;
@@ -432,7 +432,7 @@
                 if (hl.showMarker) {
                     draw(plot, neighbor);
                 }
-                if (hl.showTooltip && (!c || !c._zoom.started)) {
+                if (plot.series[neighbor.seriesIndex].show && hl.showTooltip && (!c || !c._zoom.started)) {
                     showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor);
                 }
                 if (hl.bringSeriesToFront) {
@@ -452,7 +452,7 @@
                     if (hl.showMarker) {
                         draw(plot, neighbor);
                     }
-                    if (hl.showTooltip && (!c || !c._zoom.started)) {
+                    if (plot.series[neighbor.seriesIndex].show && hl.showTooltip && (!c || !c._zoom.started)) {
                         showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor);
                     }
                     if (hl.bringSeriesToFront) {
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.logAxisRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.logAxisRenderer.js
index 376f7d4..3bd3e2a 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.logAxisRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.logAxisRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -161,10 +161,10 @@
             
             // perform some checks
             if (this.min != null && this.min <= 0) {
-                throw('log axis minimum must be greater than 0');
+                throw new Error("Log axis minimum must be greater than 0");
             }
             if (this.max != null && this.max <= 0) {
-                throw('log axis maximum must be greater than 0');
+                throw new Error("Log axis maximum must be greater than 0");
             }
 
             function findCeil (val) {
@@ -192,6 +192,11 @@
             //     rmax = rmax*(1+adj);
             // }
 
+            // Handle case where a data value was zero
+            if (rmin === 0) {
+              rmin = 1;
+            }
+
             var order = Math.round(Math.log(rmin)/Math.LN10);
 
             if (this.tickOptions == null || !this.tickOptions.formatString) {
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.mekkoAxisRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.mekkoAxisRenderer.js
index 9af6a29..b90c5bc 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.mekkoAxisRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.mekkoAxisRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -91,7 +91,7 @@
             // call it within the scope of the axis.
             this.renderer.createTicks.call(this);
             // fill a div with axes labels in the right direction.
-            // Need to pregenerate each axis to get it's bounds and
+            // Need to pregenerate each axis to get its bounds and
             // position it and the labels correctly on the plot.
             var dim=0;
             var temp;
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.mekkoRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.mekkoRenderer.js
index 953ee1b..05f495f 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.mekkoRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.mekkoRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -33,7 +33,7 @@
      * Class: $.jqplot.MekkoRenderer
      * Draws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph.
      * the <$.jqplot.MekkoAxisRenderer> should be used with mekko charts.  The mekko renderer
-     * overrides the default legend renderer with it's own $.jqplot.MekkoLegendRenderer
+     * overrides the default legend renderer with its own $.jqplot.MekkoLegendRenderer
      * which allows more flexibility to specify number of rows and columns in the legend.
      * 
      * Data is specified per bar in the chart.  You can specify data as an array of y values, or as 
@@ -434,4 +434,4 @@
     
     $.jqplot.preInitHooks.push(preInit);
     
-})(jQuery);    
\ No newline at end of file
+})(jQuery);    
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.meterGaugeRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.meterGaugeRenderer.js
index b1b1b56..8bd899d 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.meterGaugeRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.meterGaugeRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -94,7 +94,7 @@
         this.needleColor = "#C3D3E5";
         // prop: tickColor
         // color of the tick marks around the gauge.
-        this.tickColor = "989898";
+        this.tickColor = "#989898";
         // prop: ringWidth
         // width of the ring around the gauge.  Auto computed by default.
         this.ringWidth = null;
@@ -358,7 +358,7 @@
         
         
             
-        // pre-draw so can get it's dimensions.
+        // pre-draw so can get its dimensions.
         if (this.label) {
             this._labelElem = $('<div class="jqplot-meterGauge-label" style="position:absolute;">'+this.label+'</div>');
             this.canvas._elem.after(this._labelElem);
@@ -413,13 +413,12 @@
                 // will be center of hub.
                 this._center = [(cw-trans*offx)/2 + trans * offx, (ch-trans*offy)/2 + trans * offy];
             }
+            if (this._labelElem && this.labelPosition == 'bottom') {
+                this._center[1] -= this._labelElem.outerHeight(true);
+            }
+            
         }
 
-        
-        if (this._labelElem && this.labelPosition == 'bottom') {
-            this._center[1] -= this._labelElem.outerHeight(true);
-        }
-        
         this._radius = this.diameter/2;
         
         this.tickSpacing = 6000/this.diameter;
@@ -719,7 +718,7 @@
                     l = this._tickPoints[i][0] - ew * (this._tickPoints[i][2]-Math.PI)/Math.PI - tp * Math.cos(this._tickPoints[i][2]);
                     t = this._tickPoints[i][1] - eh/2 + eh/2 * Math.pow(Math.abs((Math.sin(this._tickPoints[i][2]))), 0.5) + tp/3 * Math.pow(Math.abs((Math.sin(this._tickPoints[i][2]))), 0.5) ;
                     // t = this._tickPoints[i][1] - eh/2 - eh/2 * Math.sin(this._tickPoints[i][2]) - tp/2 * Math.sin(this._tickPoints[i][2]);
-                    elem.css({left:l, top:t});
+                    elem.css({left:l, top:t, color: this.tickColor});
                     dim  = ew*Math.cos(this._tickPoints[i][2]) + eh*Math.sin(Math.PI/2+this._tickPoints[i][2]/2);
                     maxdim = (dim > maxdim) ? dim : maxdim;
                 }
@@ -739,7 +738,7 @@
             
             else if (this.label && this.labelPosition == 'bottom') {
                 var l = this._center[0] + this.canvas._offsets.left - this._labelElem.outerWidth(true)/2;
-                var t = this._center[1] + this.canvas._offsets.top + this.innerPad + + this.ringWidth + this.padding + this.labelHeightAdjust;
+                var t = this._center[1] + this.canvas._offsets.top + this.innerPad + this.ringWidth + this.padding + this.labelHeightAdjust;
                 this._labelElem.css({left:l, top:t});
                 
             }
@@ -1027,4 +1026,4 @@
     
 })(jQuery);
     
-    
\ No newline at end of file
+    
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.mobile.js b/src/vendor/jquery-jqplot/plugins/jqplot.mobile.js
index 585a42f..fa68a5f 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.mobile.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.mobile.js
@@ -2,8 +2,8 @@
  * jqplot.jquerymobile plugin
  * jQuery Mobile virtual event support.
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
  * Copyright (c) 2011 Takashi Okamoto
  * jqPlot is currently available for use in all personal or commercial projects 
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.ohlcRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.ohlcRenderer.js
index a9c31eb..3cffbfb 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.ohlcRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.ohlcRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -65,7 +65,7 @@
      * 
      */
     $.jqplot.OHLCRenderer = function(){
-        // subclass line renderer to make use of some of it's methods.
+        // subclass line renderer to make use of some of its methods.
         $.jqplot.LineRenderer.call(this);
         // prop: candleStick
         // true to render chart as candleStick.
@@ -370,4 +370,4 @@
     
     //$.jqplot.preInitHooks.push($.jqplot.OHLCRenderer.checkOptions);
     
-})(jQuery);    
\ No newline at end of file
+})(jQuery);    
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.pieRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.pieRenderer.js
index 75db1a4..1d508bd 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.pieRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.pieRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -88,7 +88,7 @@
         // angular spacing between pie slices in degrees.
         this.sliceMargin = 0;
         // prop: fill
-        // true or false, wether to fil the slices.
+        // true or false, whether to fil the slices.
         this.fill = true;
         // prop: shadowOffset
         // offset of the shadow from the slice and offset of 
@@ -801,7 +801,7 @@
             plot.target.trigger(evt1, ins);
             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -818,7 +818,7 @@
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
@@ -841,7 +841,7 @@
         if (neighbor) {
             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             var evt = jQuery.Event('jqplotDataClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
@@ -856,7 +856,7 @@
                 unhighlight(plot);
             }
             var evt = jQuery.Event('jqplotDataRightClick');
-	    evt.which = ev.which;
+            evt.which = ev.which;
             evt.pageX = ev.pageX;
             evt.pageY = ev.pageY;
             plot.target.trigger(evt, ins);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.pointLabels.js b/src/vendor/jquery-jqplot/plugins/jqplot.pointLabels.js
index 082b233..4edc69e 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.pointLabels.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.pointLabels.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -155,7 +155,7 @@
             labelIdx = p.seriesLabelIndex;
         }
         else if (this.renderer.constructor === $.jqplot.BarRenderer && this.barDirection === 'horizontal') {
-            labelIdx = 0;
+           labelIdx = (this._plotData[0].length < 3) ? 0 : this._plotData[0].length -1;
         }
         else {
             labelIdx = (this._plotData.length === 0) ? 0 : this._plotData[0].length -1;
@@ -294,13 +294,11 @@
             for (var i=0, l=p._labels.length; i < l; i++) {
                 var label = p._labels[i];
                 
-                if (p.hideZeros && parseInt(p._labels[i], 10) == 0) {
-                    label = '';
+                if (label == null || (p.hideZeros && parseInt(label, 10) == 0)) {
+                    continue;
                 }
                 
-                if (label != null) {
-                    label = p.formatter(p.formatString, label);
-                } 
+                label = p.formatter(p.formatString, label);
 
                 helem = document.createElement('div');
                 p._elems[i] = $(helem);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.pyramidAxisRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.pyramidAxisRenderer.js
index 884b793..7650e30 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.pyramidAxisRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.pyramidAxisRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -111,7 +111,7 @@
             // call it within the scope of the axis.
             this.renderer.createTicks.call(this, plot);
             // fill a div with axes labels in the right direction.
-            // Need to pregenerate each axis to get it's bounds and
+            // Need to pregenerate each axis to get its bounds and
             // position it and the labels correctly on the plot.
             var dim=0;
             var temp;
@@ -725,4 +725,4 @@
 
         ticks = null;
     };
-})(jQuery);
\ No newline at end of file
+})(jQuery);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.pyramidGridRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.pyramidGridRenderer.js
index 26d05c6..aeea423 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.pyramidGridRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.pyramidGridRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.pyramidRenderer.js b/src/vendor/jquery-jqplot/plugins/jqplot.pyramidRenderer.js
index 6ffeb04..f230d9f 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.pyramidRenderer.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.pyramidRenderer.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -495,7 +495,7 @@
             plot.target.trigger(evt1, ins);
             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pyramidRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 var evt = jQuery.Event('jqplotDataHighlight');
-		evt.which = ev.which;
+                evt.which = ev.which;
                 evt.pageX = ev.pageX;
                 evt.pageY = ev.pageY;
                 plot.target.trigger(evt, ins);
diff --git a/src/vendor/jquery-jqplot/plugins/jqplot.trendline.js b/src/vendor/jquery-jqplot/plugins/jqplot.trendline.js
index b65db71..666498a 100644
--- a/src/vendor/jquery-jqplot/plugins/jqplot.trendline.js
+++ b/src/vendor/jquery-jqplot/plugins/jqplot.trendline.js
@@ -2,10 +2,10 @@
  * jqPlot
  * Pure JavaScript plotting plugin using jQuery
  *
- * Version: 1.0.4
- * Revision: 1120
+ * Version: 1.0.8
+ * Revision: 1250
  *
- * Copyright (c) 2009-2012 Chris Leonello
+ * Copyright (c) 2009-2013 Chris Leonello
  * jqPlot is currently available for use in all personal or commercial projects 
  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
@@ -60,7 +60,7 @@
         // Either 'exponential', 'exp', or 'linear'.
         this.type = 'linear';
         // prop: shadow
-        // true or false, wether or not to show the shadow.
+        // true or false, whether or not to show the shadow.
         this.shadow = true;
         // prop: markerRenderer
         // Renderer to use to draw markers on the line.

commit 8211a9b38d8157179e9b1668db9d752326375286
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon Jun 24 23:41:10 2013 +0200

    jqplot: implement generic sitetime, projecttime and usertime graphs

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index a6755ff..d3ff9b0 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -976,14 +976,28 @@ function report_toolspiegraph($datatype = 0, $start, $end) {
 	}
 }
 
-function report_sitetimegraph($type = 'tasks', $start, $end) {
-	global $pie_labels,$pie_vals;
+function report_timegraph($type = 'site', $area = 'tasks', $start, $end, $id = 0) {
+	global $pie_labels, $pie_vals;
 
 	$now = time() - 60*24*24;
 	if ($now < $end) {
 		$end = $now;
 	}
-	$report = new ReportSiteTime($type, $start, $end);
+	switch($type) {
+		case 'site': {
+			$report = new ReportSiteTime($area, $start, $end);
+			break;
+		}
+		case 'project': {
+			$report = new ReportProjectTime($id, $area, $start, $end);
+			break;
+		}
+		case 'user': {
+			$report = new ReportUserTime($id, $area, $start, $end);
+			break;
+		}
+	}
+
 	$arr['tasks']='By Task';
 	$arr['category']='By Category';
 	$arr['subproject']='By Subproject';
@@ -991,7 +1005,7 @@ function report_sitetimegraph($type = 'tasks', $start, $end) {
 
 	report_pie_arr($report->labels, $report->getData());
 	
-	$chartid = 'sitetimegraph';
+	$chartid = 'timegraph';
 	if (count($pie_vals)) {
 		echo '<script type="text/javascript">//<![CDATA['."\n";
 		echo 'var data'.$chartid.' = new Array();';
@@ -1002,7 +1016,7 @@ function report_sitetimegraph($type = 'tasks', $start, $end) {
 		echo 'jQuery(document).ready(function(){
 			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [data'.$chartid.'],
 				{
-					title : \''.$arr[$type].' ('.strftime('%x', $start) .' - '. strftime('%x', $end) .')\',
+					title : \''.$arr[$area].' ('.strftime('%x', $start) .' - '. strftime('%x', $end) .')\',
 					seriesDefaults: {
 						// Make this a pie chart.
 						renderer: jQuery.jqplot.PieRenderer,
diff --git a/src/www/reporting/projecttime.php b/src/www/reporting/projecttime.php
index 3bf78a9..8acad6d 100644
--- a/src/www/reporting/projecttime.php
+++ b/src/www/reporting/projecttime.php
@@ -52,6 +52,11 @@ if ($typ != 'r' && $start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginPie();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+
 report_header(_('Time Tracking By Project'));
 
 $a[]=_('By Task');
@@ -96,7 +101,12 @@ $a2[]='user';
 
 	} elseif ($g_id && $start != $end) { ?>
 	<p>
+	<?php
+		report_timegraph('project', $type, $start, $end, $g_id);
+	?>
+	<noscript>
 	<img src="projecttime_graph.php?<?php echo "start=$start&end=$end&g_id=$g_id&type=$type"; ?>" alt="" />
+	</noscript>
 	</p>
 	<?php
 
diff --git a/src/www/reporting/sitetime.php b/src/www/reporting/sitetime.php
index 0f9c8ca..119c172 100644
--- a/src/www/reporting/sitetime.php
+++ b/src/www/reporting/sitetime.php
@@ -102,7 +102,7 @@ if ($typ =='r') {
 } elseif ($start != $end) { ?>
 <p>
 <?php
-	report_sitetimegraph($type, $start, $end);
+	report_timegraph('site', $type, $start, $end);
 ?>
 <noscript>
 <img src="sitetime_graph.php?<?php echo "start=$start&end=$end&type=$type"; ?>" alt="" />
diff --git a/src/www/reporting/usertime.php b/src/www/reporting/usertime.php
index a3ca637..a3b6783 100644
--- a/src/www/reporting/usertime.php
+++ b/src/www/reporting/usertime.php
@@ -54,6 +54,11 @@ if ($typ != 'r' && $start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginPie();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+
 report_header(_('User Time Reporting'));
 
 $abc_array = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
@@ -111,12 +116,15 @@ if ($sw) {
 
 		} elseif ($dev_id && $start != $end) { ?>
 		<p>
+		<?php
+			report_timegraph('user', $type, $start, $end, $dev_id);
+		?>
+		<noscript>
 		<img src="usertime_graph.php?<?php echo "start=$start&end=$end&dev_id=$dev_id&type=$type"; ?>" alt="" />
+		</noscript>
 		</p>
 		<?php
-
-	}
-
+		}
 }
 
 report_footer();

commit 56c1e6fec238466523b119721a1a42e707589365
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon Jun 24 21:27:05 2013 +0200

    jqplot: fix toolspie report

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index bdd08f7..a6755ff 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -871,7 +871,7 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 	return true;
 }
 
-function report_toolspiegraph($datatype = 1, $start, $end) {
+function report_toolspiegraph($datatype = 0, $start, $end) {
 	$now = time() - 60*24*24;
 	if ($now < $end) {
 		$end = $now;
diff --git a/src/www/reporting/toolspie.php b/src/www/reporting/toolspie.php
index 4efd9a5..dff54ae 100644
--- a/src/www/reporting/toolspie.php
+++ b/src/www/reporting/toolspie.php
@@ -34,7 +34,7 @@ if ($report->isError()) {
 	exit_error($report->getErrorMessage());
 }
 
-$datatype = getStringFromRequest('datatype');
+$datatype = getIntFromRequest('datatype');
 $start = getIntFromRequest('start');
 $end = getIntFromRequest('end');
 
@@ -59,10 +59,6 @@ html_use_jqueryjqplotplugindateAxisRenderer();
 
 report_header(_('Tool Pie Graphs'));
 
-if (!isset($datatype)) {
-	$datatype = 1;
-}
-
 ?>
 <form action="<?php echo getStringFromServer('PHP_SELF'); ?>" method="get">
 <table><tr>

commit 04349af545f045b474a48307dc724a18ec667c6e
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon Jun 24 19:18:17 2013 +0200

    jqplot: header

diff --git a/src/www/reporting/groupcum.php b/src/www/reporting/groupcum.php
index 44776fe..7ff4156 100644
--- a/src/www/reporting/groupcum.php
+++ b/src/www/reporting/groupcum.php
@@ -3,6 +3,8 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
+ * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
diff --git a/src/www/reporting/sitetimebar.php b/src/www/reporting/sitetimebar.php
index 7e440c9..95ea7b0 100644
--- a/src/www/reporting/sitetimebar.php
+++ b/src/www/reporting/sitetimebar.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
diff --git a/src/www/reporting/useradded.php b/src/www/reporting/useradded.php
index 3f71be7..f4ca44c 100644
--- a/src/www/reporting/useradded.php
+++ b/src/www/reporting/useradded.php
@@ -4,6 +4,7 @@
  *
  * Copyright 2003-2004 (c) GForge LLC
  * Copyright 2013, Franck Villaume - TrivialDev
+ * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
diff --git a/src/www/reporting/usersummary.php b/src/www/reporting/usersummary.php
index 4d48c72..061de87 100644
--- a/src/www/reporting/usersummary.php
+++ b/src/www/reporting/usersummary.php
@@ -5,6 +5,7 @@
  * Copyright 2003-2004 (c) GForge LLC, Tim Perdue
  * Copyright 2010 (c), FusionForge Team
  * Copyright 2013, Franck Villaume - TrivialDev
+ * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the

commit ebfd63e4880878c9f18a2e816233f7cd8ad983be
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon Jun 24 00:03:06 2013 +0200

    jqplot: implement report time tracking

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 2ef1a62..bdd08f7 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -619,9 +619,14 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 			break;
 		}
 	}
-	
+
+	if ($report->isError()) {
+		echo '<p class="error">'.$report->getErrorMessage().'</p>';
+		return false;
+	}
 	$rdates = $report->getRawDates();
 	if (!$rdates) {
+		echo '<p class="error">'._('No data to display').'</p>';
 		return false;
 	}
 	if (!$SPAN)
@@ -813,7 +818,7 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 	}
 	echo 'jQuery(document).ready(function(){
 			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', series, {
-				title : \''.utf8_decode($areaname).' ( '.strftime('%x',$start).' - '.strftime('%x',$end).') \',
+				title : \''.utf8_decode($areaname).' ( '.strftime('%x', $start).' - '.strftime('%x', $end).') \',
 				axesDefaults: {
 					tickOptions: {
 						angle: -90,
@@ -864,7 +869,6 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 	echo '//]]></script>';
 	echo '<div id="chart'.$chartid.'"></div>';
 	return true;
-	echo 'joli graph';
 }
 
 function report_toolspiegraph($datatype = 1, $start, $end) {
@@ -945,7 +949,7 @@ function report_toolspiegraph($datatype = 1, $start, $end) {
 		echo 'jQuery(document).ready(function(){
 			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [data'.$chartid.'],
 				{
-					title : \''.$arr[$datatype].' ('.strftime('%x',$start) .' - '. strftime('%x',$end) .')\',
+					title : \''.$arr[$datatype].' ('.strftime('%x', $start) .' - '. strftime('%x', $end) .')\',
 					seriesDefaults: {
 						// Make this a pie chart.
 						renderer: jQuery.jqplot.PieRenderer,
@@ -972,6 +976,159 @@ function report_toolspiegraph($datatype = 1, $start, $end) {
 	}
 }
 
+function report_sitetimegraph($type = 'tasks', $start, $end) {
+	global $pie_labels,$pie_vals;
+
+	$now = time() - 60*24*24;
+	if ($now < $end) {
+		$end = $now;
+	}
+	$report = new ReportSiteTime($type, $start, $end);
+	$arr['tasks']='By Task';
+	$arr['category']='By Category';
+	$arr['subproject']='By Subproject';
+	$arr['user']='By User';
+
+	report_pie_arr($report->labels, $report->getData());
+	
+	$chartid = 'sitetimegraph';
+	if (count($pie_vals)) {
+		echo '<script type="text/javascript">//<![CDATA['."\n";
+		echo 'var data'.$chartid.' = new Array();';
+		for ($i = 0; $i < count($pie_vals); $i++) {
+			echo 'data'.$chartid.'.push([\''.htmlentities($pie_labels[0]).'\',\''.$pie_vals[1].'\']);';
+		}
+		echo 'var plot'.$chartid.';';
+		echo 'jQuery(document).ready(function(){
+			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [data'.$chartid.'],
+				{
+					title : \''.$arr[$type].' ('.strftime('%x', $start) .' - '. strftime('%x', $end) .')\',
+					seriesDefaults: {
+						// Make this a pie chart.
+						renderer: jQuery.jqplot.PieRenderer,
+						rendererOptions: {
+							// Put data labels on the pie slices.
+							// By default, labels show the percentage of the slice.
+							showDataLabels: true,
+							dataLabels: \'percent\',
+						}
+					},
+					legend: {
+						show:true, location: \'e\',
+					},
+				}
+				);
+			});';
+		echo 'jQuery(window).resize(function() {
+				plot'.$chartid.'.replot( { resetAxes: true } );
+			});'."\n";
+		echo '//]]></script>';
+		echo '<div id="chart'.$chartid.'"></div>';
+	} else {
+		echo '<p class="information" >'._('No data to display.').'</p>';
+	}
+}
+
+function report_sitetimebargraph($start, $end) {
+	$now = time() - 60*24*24;
+	if ($now < $end) {
+		$end = $now;
+	}
+	
+	$res = db_query_params('SELECT week,sum(hours)
+		FROM rep_time_tracking
+		WHERE week
+		BETWEEN $1 AND $2 GROUP BY week',
+				array($start, $end));
+
+	$report = new Report();
+	if ($report->isError()) {
+		exit_error($report->getErrorMessage());
+	}
+	$report->setDates($res,0);
+	$report->setData($res,1);
+	$chartid = 'sitetimebargraph';
+	$areaname = _('Hours Recorded');
+	$yMax = 0;
+	$dates[0] = $report->getDates();
+	$ydata[0] = $report->getData();
+	$label[0] = _(' Hours');
+	if (count($ydata[0])) {
+		echo '<script type="text/javascript">//<![CDATA['."\n";
+		echo 'var plot'.$chartid.';';
+		echo 'var values = new Array();';
+		echo 'var ticks = new Array();';
+		echo 'var labels = new Array();';
+		echo 'var series = new Array();';
+		for ($z = 0; $z < count($ydata); $z++) {
+			echo 'values['.$z.'] = new Array();';
+			echo 'labels.push({label:\''.$label[$z].'\'});';
+			for ($j = 0; $j < count($ydata[$z]); $j++) {
+				echo 'values['.$z.'].push('.$ydata[$z][$j].')';
+				echo 'ticks.push('.$dates[$z][$j].')';
+			}
+		}
+		for ($z = 0; $z < count($ydata); $z++) {
+			echo 'series.push(values['.$z.']);';
+		}
+		echo 'jQuery(document).ready(function(){
+				plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', series, {
+					title : \''.utf8_decode($areaname).' ( '.strftime('%x', $start).' - '.strftime('%x', $end).') \',
+					axesDefaults: {
+						tickOptions: {
+							angle: -90,
+							fontSize: \'8px\',
+							showGridline: false,
+							showMark: false,
+						},
+						pad: 0,
+					},
+					seriesDefaults: {
+						showMarker: false,
+						lineWidth: 1,
+						fill: true,
+						renderer:jQuery.jqplot.BarRenderer,
+						rendererOptions: {
+							fillToZero: true,
+						},
+					},
+					legend: {
+						show:true, location: \'ne\',
+					},
+					series:
+						labels
+					,
+					axes: {
+						xaxis: {
+							renderer: jQuery.jqplot.CategoryAxisRenderer,
+							ticks: ticks,
+						},
+						yaxis: {
+							max: '.++$yMax.',
+							min: 0,
+							tickOptions: {
+								angle: 0,
+								showMark: true,
+							}
+						},
+					},
+					highlighter: {
+						show: true,
+						sizeAdjust: 2.5,
+					},
+				});
+			});';
+		echo 'jQuery(window).resize(function() {
+			plot'.$chartid.'.replot();
+		});'."\n";
+		echo '//]]></script>';
+		echo '<div id="chart'.$chartid.'"></div>';
+	} else {
+		echo '<p class="information">'._('No data to display').'</p>';
+	}
+	return true;
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/reporting/sitetime.php b/src/www/reporting/sitetime.php
index e599621..0f9c8ca 100644
--- a/src/www/reporting/sitetime.php
+++ b/src/www/reporting/sitetime.php
@@ -4,6 +4,7 @@
  *
  * Copyright 2003-2004 (c) GForge LLC
  * Copyright (C) 2010 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -53,6 +54,11 @@ if ($typ != 'r' && $start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginPie();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+
 report_header(_('Site-Wide Time Tracking'));
 
 $a[]=_('By Task');
@@ -95,7 +101,12 @@ if ($typ =='r') {
 	echo $HTML->listTableBottom ();
 } elseif ($start != $end) { ?>
 <p>
+<?php
+	report_sitetimegraph($type, $start, $end);
+?>
+<noscript>
 <img src="sitetime_graph.php?<?php echo "start=$start&end=$end&type=$type"; ?>" alt="" />
+</noscript>
 </p>
 <?php
 }
diff --git a/src/www/reporting/sitetimebar.php b/src/www/reporting/sitetimebar.php
index 844368d..7e440c9 100644
--- a/src/www/reporting/sitetimebar.php
+++ b/src/www/reporting/sitetimebar.php
@@ -51,6 +51,11 @@ if ($typ != 'r' && $start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
+
 report_header(_('Site-Wide Time Tracking'));
 
 ?>
@@ -100,7 +105,12 @@ if ($typ=='r') {
 
 } elseif ($start != $end) { ?>
 	<p>
+	<?php
+		report_sitetimebargraph($start, $end);
+	?>
+	<noscript>
 	<img src="sitetimebar_graph.php?<?php echo "start=$start&end=$end"; ?>"  alt="" />
+	</noscript>
 	</p>
 	<?php
 }
diff --git a/src/www/reporting/usersummary.php b/src/www/reporting/usersummary.php
index 25bb87e..4d48c72 100644
--- a/src/www/reporting/usersummary.php
+++ b/src/www/reporting/usersummary.php
@@ -4,6 +4,7 @@
  *
  * Copyright 2003-2004 (c) GForge LLC, Tim Perdue
  * Copyright 2010 (c), FusionForge Team
+ * Copyright 2013, Franck Villaume - TrivialDev
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -95,7 +96,7 @@ GROUP BY realname, users.user_id, user_name, status_name, pgl.group_id, pt.group
 				       $end,
 				       db_int_array_to_any_clause (explode(',',$tstat))));
 if (!$res || db_numrows($res) < 1) {
-	echo '<p class="feedback">' . _('No matches found').db_error() . '</p>';
+	echo '<p class="information">' . _('No matches found').db_error() . '</p>';
 } else {
 	$tableHeaders = array(
 		_('Name'),

commit 734c08356d8a020bd25cb68a156b53fe3bad417e
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 21 18:08:49 2013 +0200

    jqplot: implement toolspie graph

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 893cd4d..2ef1a62 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -867,6 +867,111 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 	echo 'joli graph';
 }
 
+function report_toolspiegraph($datatype = 1, $start, $end) {
+	$now = time() - 60*24*24;
+	if ($now < $end) {
+		$end = $now;
+	}
+	if ($datatype < 5) {
+		$res = db_query_params ('SELECT g.group_name,count(*) AS count
+		FROM groups g, artifact_group_list agl, artifact a
+		WHERE g.group_id=agl.group_id
+		AND agl.group_artifact_id=a.group_artifact_id
+		AND a.open_date BETWEEN $1 AND $2
+		AND agl.datatype=$3
+		GROUP BY group_name
+		ORDER BY count DESC',
+					array ($start,
+					$end,
+					$datatype));
+	} elseif ($datatype == 5) {
+		$res = db_query_params ('SELECT g.group_name,count(*) AS count
+		FROM groups g, forum_group_list fgl, forum f
+		WHERE g.group_id=fgl.group_id
+		AND fgl.group_forum_id=f.group_forum_id
+		AND f.post_date BETWEEN $1 AND $2
+		GROUP BY group_name
+		ORDER BY count DESC',
+					array ($start,
+					$end));
+	} elseif ($datatype == 6) {
+		$res = db_query_params ('SELECT g.group_name,count(*) AS count
+		FROM groups g, project_group_list pgl, project_task pt
+		WHERE g.group_id=pgl.group_id
+		AND pgl.group_project_id=pt.group_project_id
+		AND pt.start_date BETWEEN $1 AND $2
+		GROUP BY group_name
+		ORDER BY count DESC',
+					array ($start,
+					$end));
+	} else {
+		$res = db_query_params ('SELECT g.group_name,count(*) AS count
+		FROM groups g, frs_package fp, frs_release fr, frs_file ff, frs_dlstats_file fdf
+		WHERE g.group_id=fp.group_id
+		AND fp.package_id=fr.package_id
+		AND fr.release_id=ff.release_id
+		AND ff.file_id=fdf.file_id
+		AND (((fdf.month > $1) OR (fdf.month = $1 AND fdf.day >= $2))
+		AND ((fdf.month < $3) OR (fdf.month = $3 AND fdf.day < $4)))
+		GROUP BY group_name
+		ORDER BY count DESC',
+					array (date('Ym',$start),
+					date('d',$start),
+					date('Ym',$end),
+					date('d',$end)));
+	}
+
+	if (db_error()) {
+		exit_error(db_error(), '');
+	}
+	
+	$arr[1] = 'Bugs';
+	$arr[2] = 'Support Requests';
+	$arr[3] = 'Patches';
+	$arr[4] = 'Feature Requests';
+	$arr[0] = 'Other Trackers';
+	$arr[5] = 'Forum Messages';
+	$arr[6] = 'Tasks';
+	$arr[7] = 'Downloads';
+	
+	$chartid = 'toolspie';
+	if (db_numrows($res)) {
+		echo '<script type="text/javascript">//<![CDATA['."\n";
+		echo 'var data'.$chartid.' = new Array();';
+		while ($row = db_fetch_array($res)) {
+			echo 'data'.$chartid.'.push([\''.htmlentities($row[0]).'\',\''.$row[1].'\']);';
+		}
+		echo 'var plot'.$chartid.';';
+		echo 'jQuery(document).ready(function(){
+			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [data'.$chartid.'],
+				{
+					title : \''.$arr[$datatype].' ('.strftime('%x',$start) .' - '. strftime('%x',$end) .')\',
+					seriesDefaults: {
+						// Make this a pie chart.
+						renderer: jQuery.jqplot.PieRenderer,
+						rendererOptions: {
+							// Put data labels on the pie slices.
+							// By default, labels show the percentage of the slice.
+							showDataLabels: true,
+							dataLabels: \'percent\',
+						}
+					},
+					legend: {
+						show:true, location: \'e\',
+					},
+				}
+				);
+			});';
+		echo 'jQuery(window).resize(function() {
+				plot'.$chartid.'.replot( { resetAxes: true } );
+			});'."\n";
+		echo '//]]></script>';
+		echo '<div id="chart'.$chartid.'"></div>';
+	} else {
+		echo '<p class="information" >'._('No data to display.').'</p>';
+	}
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/reporting/toolspie.php b/src/www/reporting/toolspie.php
index b23e522..4efd9a5 100644
--- a/src/www/reporting/toolspie.php
+++ b/src/www/reporting/toolspie.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -51,10 +52,15 @@ if ($start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginPie();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+
 report_header(_('Tool Pie Graphs'));
 
-if (!$datatype) {
-	$datatype=1;
+if (!isset($datatype)) {
+	$datatype = 1;
 }
 
 ?>
@@ -68,7 +74,12 @@ if (!$datatype) {
 </form>
 <?php if ($start != $end) { ?>
 <p>
+<?php
+	report_toolspiegraph($datatype, $start, $end);
+?>
+<noscript>
 <img src="toolspie_graph.php?<?php echo "datatype=$datatype&start=$start&end=$end"; ?>" alt="" />
+</noscript>
 </p>
 <?php }
 

commit 528128d402c46e3977b0ecdad81089f93ea0fbdf
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 21 17:01:48 2013 +0200

    jqplot: sitewide line reporting

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 50ac150..893cd4d 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -614,12 +614,19 @@ function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
 			}
 			break;
 		}
+		case 'sitewide': {
+			$report = new ReportSiteAct($SPAN, $start, $end);
+			break;
+		}
 	}
 	
 	$rdates = $report->getRawDates();
 	if (!$rdates) {
 		return false;
 	}
+	if (!$SPAN)
+		$SPAN = 1;
+
 	if ($SPAN == REPORT_TYPE_DAILY) {
 		$i = 0;
 		$looptime = $start;
diff --git a/src/www/reporting/siteact.php b/src/www/reporting/siteact.php
index 253ad45..0b41395 100644
--- a/src/www/reporting/siteact.php
+++ b/src/www/reporting/siteact.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -25,6 +26,7 @@ require_once '../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportSiteAct.class.php';
 
 session_require_global_perm ('forge_stats', 'read') ;
 
@@ -54,6 +56,11 @@ if ($start == $end) {
 
 $area = util_ensure_value_in_set ($area, array ('tracker','forum','docman','taskman','downloads', 'pageviews')) ;
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
+
 report_header(_('Site-Wide Activity'));
 
 ?>
@@ -69,7 +76,12 @@ report_header(_('Site-Wide Activity'));
 </form>
 <?php if ($area && $start != $end) { ?>
 	<p>
+	<?php
+		report_actgraph('sitewide', $SPAN, $start, $end, 0, $area);
+	?>
+	<noscript>
 	<img src="siteact_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&area=$area"; ?>" alt="" />
+	</noscript>
 	</p>
 	<?php
 

commit af1dd4ca91a999a2368c4aeb1d69572795cb66d2
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 21 14:48:50 2013 +0200

    jqplot: implement project activity at forge level, merge code with project stat view

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 1c60824..50ac150 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -590,6 +590,276 @@ function report_graph($type, $SPAN, $start, $end) {
 	return true;
 }
 
+function report_actgraph($type, $SPAN, $start, $end, $id, $area) {
+	$now = time() - 60*24*24;
+	if ($now < $end) {
+		$end = $now;
+	}
+	switch ($type) {
+		case 'user': {
+			$report = new ReportUserAct($SPAN, $id, $start, $end);
+			$u =& user_get_object($id);
+			if (!$u || $u->isError()) {
+				exit_error(_("Could Not Get User"));
+			}
+			break;
+		}
+		case 'project': {
+			$report = new ReportProjectAct($SPAN, $id, $start, $end);
+			$g = group_get_object($id);
+			if (!$g || !is_object($g)) {
+				exit_no_group();
+			} elseif ($g->isError()) {
+				exit_error($g->getErrorMessage(), '');
+			}
+			break;
+		}
+	}
+	
+	$rdates = $report->getRawDates();
+	if (!$rdates) {
+		return false;
+	}
+	if ($SPAN == REPORT_TYPE_DAILY) {
+		$i = 0;
+		$looptime = $start;
+		while ($looptime < $end) {
+			$timeStampArr[$i] = $looptime;
+			$looptime += REPORT_DAY_SPAN;
+			$i++;
+		}
+		$formatDate = 'Y/m/d';
+	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
+		$timeStampArr = $report->getWeekStartArr();
+		$formatDate = 'Y/W';
+	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
+		$timeStampArr = $report->getMonthStartArr();
+		$formatDate = 'Y/m';
+	}
+	
+	for ($j = 0; $j < count($timeStampArr); $j++) {
+		if ($timeStampArr[$j] < $start || $timeStampArr[$j] >= $end) {
+			unset($timeStampArr[$j]);
+		}
+	}
+	$timeStampArr = array_values($timeStampArr);
+	for ($j = 0; $j < count($timeStampArr); $j++) {
+		$tickArr[] = date($formatDate, $timeStampArr[$j]);
+	}
+	
+	switch ($area) {
+		case 'docman': {
+			$ydata[] =& $report->getDocs();
+			$areaname = _('Docs');
+			$label[] = _('Documents');
+			break;
+		}
+		case 'downloads': {
+			$ydata[] =& $report->getDownloads();
+			$areaname = _('Downloads');
+			$label[] = _('Downloads');
+			break;
+		}
+		case 'forum' : {
+			$ydata[] =& $report->getForum();
+			$areaname = _('Forums');
+			$label[] = _('Forums');
+			break;
+		}
+		case 'pageviews': {
+			$ydata[] =& $report->getPageViews();
+			$areaname = _('Page views');
+			$label[] = _('Page views');
+			break;
+		}
+		case 'taskman': {
+			$ydata[] =& $report->getTaskOpened();
+			$ydata[] =& $report->getTaskClosed();
+			$areaname = _('Tasks');
+			$label[] = _('Task open');
+			$label[] = _('Task close');
+			break;
+		}
+		case 'tracker': {
+			$ydata[] =& $report->getTrackerOpened();
+			$ydata[] =& $report->getTrackerClosed();
+			$areaname = _('Trackers');
+			$label[] = _('Tracker items opened');
+			$label[] = _('Tracker items closed');
+			break;
+		}
+		default: {
+			$results = array();
+			$ids = array();
+			$texts = array();
+			$show[] = $area;
+
+			$hookParams['group'] = $id;
+			$hookParams['results'] = &$results;
+			$hookParams['show'] = &$show;
+			$hookParams['begin'] = $start;
+			$hookParams['end'] = $end;
+			$hookParams['ids'] = &$ids;
+			$hookParams['texts'] = &$texts;
+			plugin_hook("activity", $hookParams);
+
+			$areaname = $texts[0];
+			$label[] = $texts[0];
+			$sum = array();
+			foreach ($results as $arr) {
+				$dd = date($formatDate, $arr['activity_date']);
+				switch ($SPAN) {
+					case REPORT_TYPE_MONTHLY : {
+						$d = mktime(0, 0, 0, substr($dd, 5, 2) , 1, substr($dd, 0, 4));
+						break;
+					}
+					case REPORT_TYPE_WEEKLY: {
+						$d = strtotime(substr($dd, 0, 4).'-W'.substr($dd, 5, 2));
+						break;
+					}
+					case REPORT_TYPE_DAILY: {
+						$d = mktime(0, 0, 0, substr($dd, 5, 2) , substr($dd, 8, 2), substr($dd, 0, 4));
+						break;
+					}
+				}
+				@$sum[$d]++;
+			}
+
+			// Now, stores the values in the ydata array for the graph.
+			$ydata[] = array();
+			$i = 0;
+			foreach ($rdates as $d) {
+				$ydata[0][$i++] = isset($sum[$d]) ? $sum[$d] : 0;
+			}
+			break;
+		}
+	}
+
+	$chartid = 'report_actgraph_'.$id;
+	$yMax = 0;
+	echo '<script type="text/javascript">//<![CDATA['."\n";
+	echo 'var plot'.$chartid.';';
+	echo 'var values = new Array();';
+	echo 'var ticks = new Array();';
+	echo 'var labels = new Array();';
+	echo 'var series = new Array();';
+	for ($z = 0; $z < count($ydata); $z++) {
+		echo 'values['.$z.'] = new Array();';
+		echo 'labels.push({label:\''.$label[$z].'\'});';
+	}
+	switch ($SPAN) {
+		case REPORT_TYPE_DAILY :
+		case REPORT_TYPE_MONTHLY : {
+			for ($j = 0; $j < count($timeStampArr); $j++) {
+				for ($z = 0; $z < count($ydata); $z++) {
+					if (in_array($timeStampArr[$j], $rdates)) {
+						$thekey = array_search($timeStampArr[$j], $rdates);
+						if (isset($ydata[$z][$thekey])) {
+							if ($ydata[$z][$thekey] === false) {
+								$ydata[$z][$thekey] = 0;
+							}
+							if ($ydata[$z][$thekey] > $yMax) {
+								$yMax = $ydata[$z][$thekey];
+							}
+							echo 'values['.$z.'].push('.$ydata[$z][$thekey].');';
+						} else {
+							echo 'values['.$z.'].push(0);';
+						}
+					} else {
+						echo 'values['.$z.'].push(0);';
+					}
+				}
+				echo 'ticks.push(\''.$tickArr[$j].'\');';
+			}
+			break;
+		}
+		case REPORT_TYPE_WEEKLY : {
+			for ($j = 0; $j < count($rdates); $j++) {
+				$wrdates[$j] = date($formatDate, $rdates[$j]);
+			}
+			for ($j = 0; $j < count($tickArr); $j++) {
+				for ($z = 0; $z < count($ydata); $z++) {
+					if (in_array($tickArr[$j], $wrdates)) {
+						$thekey = array_search($tickArr[$j], $wrdates);
+						if (isset($ydata[$z][$thekey])) {
+							if ($ydata[$z][$thekey] === false) {
+								$ydata[$z][$thekey] = 0;
+							}
+							if ($ydata[$z][$thekey] > $yMax) {
+								$yMax = $ydata[$z][$thekey];
+							}
+							echo 'values['.$z.'].push('.$ydata[$z][$thekey].');';
+						} else {
+							echo 'values['.$z.'].push(0);';
+						}
+					} else {
+						echo 'values['.$z.'].push(0);';
+					}
+				}
+				echo 'ticks.push(\''.$tickArr[$j].'\');';
+			}
+			break;
+		}
+	}
+	for ($z = 0; $z < count($ydata); $z++) {
+		echo 'series.push(values['.$z.']);';
+	}
+	echo 'jQuery(document).ready(function(){
+			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', series, {
+				title : \''.utf8_decode($areaname).' ( '.strftime('%x',$start).' - '.strftime('%x',$end).') \',
+				axesDefaults: {
+					tickOptions: {
+						angle: -90,
+						fontSize: \'8px\',
+						showGridline: false,
+						showMark: false,
+					},
+					pad: 0,
+				},
+				seriesDefaults: {
+					showMarker: false,
+					lineWidth: 1,
+					fill: true,
+					renderer:jQuery.jqplot.BarRenderer,
+					rendererOptions: {
+						fillToZero: true,
+					},
+				},
+				legend: {
+					show:true, location: \'ne\',
+				},
+				series:
+					labels
+				,
+				axes: {
+					xaxis: {
+						renderer: jQuery.jqplot.CategoryAxisRenderer,
+						ticks: ticks,
+					},
+					yaxis: {
+						max: '.++$yMax.',
+						min: 0,
+						tickOptions: {
+							angle: 0,
+							showMark: true,
+						}
+					},
+				},
+				highlighter: {
+					show: true,
+					sizeAdjust: 2.5,
+				},
+			});
+		});';
+	echo 'jQuery(window).resize(function() {
+		plot'.$chartid.'.replot();
+	});'."\n";
+	echo '//]]></script>';
+	echo '<div id="chart'.$chartid.'"></div>';
+	return true;
+	echo 'joli graph';
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index e2314b1..90af1bc 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -6,7 +6,6 @@
  * Copyright 2002-2004 (c) GForge Team
  * Copyright 2011, Franck Villaume - Capgemini
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
- * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -233,269 +232,6 @@ function permissions_blurb() {
 	return _('<strong>NOTE:</strong><dl><dt><strong>Project Admins (bold)</strong></dt><dd>can access this page and other project administration pages</dd><dt><strong>Release Technicians</strong></dt><dd>can make the file releases (any project admin also a release technician)</dd><dt><strong>Tool Technicians (T)</strong></dt><dd>can be assigned Bugs/Tasks/Patches</dd><dt><strong>Tool Admins (A)</strong></dt><dd>can make changes to Bugs/Tasks/Patches as well as use the /toolname/admin/ pages</dd><dt><strong>Tool No Permission (N/A)</strong></dt><dd>Developer doesn\'t have specific permission (currently equivalent to \'-\')</dd><dt><strong>Moderators</strong> (forums)</dt><dd>can delete messages from the project forums</dd><dt><strong>Editors</strong> (doc. manager)</dt><dd>can update/edit/remove documentation from the project.</dd></dl>');
 }
 
-/**
- * projectact_graph - draw jqplot report stats
- *
- * @param	int	group_id, the project id
- * @param	string	area, the stats zone (documents, trackers, ...)
- * @param	int	SPAN, is it a daily, weekly, monthly report ?
- * @param	int	start, date
- * @param	int	end, date
- * @return	string	the JS code
- */
-function projectact_graph($group_id, $area, $SPAN, $start, $end) {
-	if (!strlen($area)) {
-		echo '<p class="information">'._('No selected area.').'</p>';
-		return true;
-	}
-	$report = new ReportProjectAct($SPAN, $group_id, $start, $end);
-	if ($report->isError()) {
-		echo '<p class="error">'.$report->getErrorMessage().'</p>';
-		return false;
-	}
-	$rdates = $report->getRawDates();
-	if (!$rdates) {
-		return false;
-	}
-	if ($SPAN == REPORT_TYPE_DAILY) {
-		$i = 0;
-		$looptime = $start;
-		while ($looptime < $end) {
-			$timeStampArr[$i] = $looptime;
-			$looptime += REPORT_DAY_SPAN;
-			$i++;
-		}
-		$formatDate = 'Y/m/d';
-	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
-		$timeStampArr = $report->getWeekStartArr();
-		$formatDate = 'Y/W';
-	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
-		$timeStampArr = $report->getMonthStartArr();
-		$formatDate = 'Y/m';
-	}
-	
-	for ($j = 0; $j < count($timeStampArr); $j++) {
-		if ($timeStampArr[$j] < $start || $timeStampArr[$j] >= $end) {
-			unset($timeStampArr[$j]);
-		}
-	}
-	$timeStampArr = array_values($timeStampArr);
-	for ($j = 0; $j < count($timeStampArr); $j++) {
-		$tickArr[] = date($formatDate, $timeStampArr[$j]);
-	}
-
-	switch ($area) {
-		case 'docman': {
-			$ydata[] =& $report->getDocs();
-			$areaname = _('Docs');
-			$label[] = _('Documents');
-			break;
-		}
-		case 'downloads': {
-			$ydata[] =& $report->getDownloads();
-			$areaname = _('Downloads');
-			$label[] = _('Downloads');
-			break;
-		}
-		case 'forum' : {
-			$ydata[] =& $report->getForum();
-			$areaname = _('Forums');
-			$label[] = _('Forums');
-			break;
-		}
-		case 'pageviews': {
-			$ydata[] =& $report->getPageViews();
-			$areaname = _('Page views');
-			$label[] = _('Page views');
-			break;
-		}
-		case 'taskman': {
-			$ydata[] =& $report->getTaskOpened();
-			$ydata[] =& $report->getTaskClosed();
-			$areaname = _('Tasks');
-			$label[] = _('Task open');
-			$label[] = _('Task close');
-			break;
-		}
-		case 'tracker': {
-			$ydata[] =& $report->getTrackerOpened();
-			$ydata[] =& $report->getTrackerClosed();
-			$areaname = _('Trackers');
-			$label[] = _('Tracker items opened');
-			$label[] = _('Tracker items closed');
-			break;
-		}
-		default: {
-			$results = array();
-			$ids = array();
-			$texts = array();
-			$show[] = $area;
-
-			$hookParams['group'] = $group_id;
-			$hookParams['results'] = &$results;
-			$hookParams['show'] = &$show;
-			$hookParams['begin'] = $start;
-			$hookParams['end'] = $end;
-			$hookParams['ids'] = &$ids;
-			$hookParams['texts'] = &$texts;
-			plugin_hook("activity", $hookParams);
-
-			$areaname = $texts[0];
-			$label[] = $texts[0];
-			$sum = array();
-			foreach ($results as $arr) {
-				$dd = date($formatDate, $arr['activity_date']);
-				switch ($SPAN) {
-					case REPORT_TYPE_MONTHLY : {
-						$d = mktime(0, 0, 0, substr($dd, 5, 2) , 1, substr($dd, 0, 4));
-						break;
-					}
-					case REPORT_TYPE_WEEKLY: {
-						$d = strtotime(substr($dd, 0, 4).'-W'.substr($dd, 5, 2));
-						break;
-					}
-					case REPORT_TYPE_DAILY: {
-						$d = mktime(0, 0, 0, substr($dd, 5, 2) , substr($dd, 8, 2), substr($dd, 0, 4));
-						break;
-					}
-				}
-				@$sum[$d]++;
-			}
-
-			// Now, stores the values in the ydata array for the graph.
-			$ydata[] = array();
-			$i = 0;
-			foreach ($rdates as $d) {
-				$ydata[0][$i++] = isset($sum[$d]) ? $sum[$d] : 0;
-			}
-			break;
-		}
-	}
-
-	$chartid = 'projectgraph_'.$group_id;
-	$yMax = 0;
-	echo '<script type="text/javascript">//<![CDATA['."\n";
-	echo 'var plot'.$chartid.';';
-	echo 'var values = new Array();';
-	echo 'var ticks = new Array();';
-	echo 'var labels = new Array();';
-	echo 'var series = new Array();';
-	for ($z = 0; $z < count($ydata); $z++) {
-		echo 'values['.$z.'] = new Array();';
-		echo 'labels.push({label:\''.$label[$z].'\'});';
-	}
-	switch ($SPAN) {
-		case REPORT_TYPE_DAILY :
-		case REPORT_TYPE_MONTHLY : {
-			for ($j = 0; $j < count($timeStampArr); $j++) {
-				for ($z = 0; $z < count($ydata); $z++) {
-					if (in_array($timeStampArr[$j], $rdates)) {
-						$thekey = array_search($timeStampArr[$j], $rdates);
-						if (isset($ydata[$z][$thekey])) {
-							if ($ydata[$z][$thekey] === false) {
-								$ydata[$z][$thekey] = 0;
-							}
-							if ($ydata[$z][$thekey] > $yMax) {
-								$yMax = $ydata[$z][$thekey];
-							}
-							echo 'values['.$z.'].push('.$ydata[$z][$thekey].');';
-						} else {
-							echo 'values['.$z.'].push(0);';
-						}
-					} else {
-						echo 'values['.$z.'].push(0);';
-					}
-				}
-				echo 'ticks.push(\''.$tickArr[$j].'\');';
-			}
-			break;
-		}
-		case REPORT_TYPE_WEEKLY : {
-			for ($j = 0; $j < count($rdates); $j++) {
-				$wrdates[$j] = date($formatDate, $rdates[$j]);
-			}
-			for ($j = 0; $j < count($tickArr); $j++) {
-				for ($z = 0; $z < count($ydata); $z++) {
-					if (in_array($tickArr[$j], $wrdates)) {
-						$thekey = array_search($tickArr[$j], $wrdates);
-						if (isset($ydata[$z][$thekey])) {
-							if ($ydata[$z][$thekey] === false) {
-								$ydata[$z][$thekey] = 0;
-							}
-							if ($ydata[$z][$thekey] > $yMax) {
-								$yMax = $ydata[$z][$thekey];
-							}
-							echo 'values['.$z.'].push('.$ydata[$z][$thekey].');';
-						} else {
-							echo 'values['.$z.'].push(0);';
-						}
-					} else {
-						echo 'values['.$z.'].push(0);';
-					}
-				}
-				echo 'ticks.push(\''.$tickArr[$j].'\');';
-			}
-			break;
-		}
-	}
-	for ($z = 0; $z < count($ydata); $z++) {
-		echo 'series.push(values['.$z.']);';
-	}
-	echo 'jQuery(document).ready(function(){
-			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', series, {
-				title : \''.utf8_decode($areaname).' ( '.strftime('%x',$start).' - '.strftime('%x',$end).') \',
-				axesDefaults: {
-					tickOptions: {
-						angle: -90,
-						fontSize: \'8px\',
-						showGridline: false,
-						showMark: false,
-					},
-					pad: 0,
-				},
-				seriesDefaults: {
-					showMarker: false,
-					lineWidth: 1,
-					fill: true,
-					renderer:jQuery.jqplot.BarRenderer,
-					rendererOptions: {
-						fillToZero: true,
-					},
-				},
-				legend: {
-					show:true, location: \'ne\',
-				},
-				series:
-					labels
-				,
-				axes: {
-					xaxis: {
-						renderer: jQuery.jqplot.CategoryAxisRenderer,
-						ticks: ticks,
-					},
-					yaxis: {
-						max: '.++$yMax.',
-						min: 0,
-						tickOptions: {
-							angle: 0,
-							showMark: true,
-						}
-					},
-				},
-				highlighter: {
-					show: true,
-					sizeAdjust: 2.5,
-				},
-			});
-		});';
-	echo 'jQuery(window).resize(function() {
-		plot'.$chartid.'.replot();
-	});'."\n";
-	echo '//]]></script>';
-	echo '<div id="chart'.$chartid.'"></div>';
-	return true;
-}
-
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/project/stats/index.php b/src/www/project/stats/index.php
index 02b0fd8..6d06096 100644
--- a/src/www/project/stats/index.php
+++ b/src/www/project/stats/index.php
@@ -110,7 +110,7 @@ project_admin_header(array('title'=>_('Project Statistics').'','group'=>$group_i
 if ($start == $end) {
 	echo '<p class="warning">'._('Cannot proceed the request. Start date is equal to end date.').'</p>';
 } else {
-	if (!projectact_graph($group_id, $area, $SPAN, $start, $end)) {
+	if (!report_actgraph('project', $SPAN, $start, $end, $group_id, $area)) {
 		echo '<p class="error">'._('Error during graphic computation.');
 	}
 }
diff --git a/src/www/reporting/projectact.php b/src/www/reporting/projectact.php
index 8729272..85986a2 100644
--- a/src/www/reporting/projectact.php
+++ b/src/www/reporting/projectact.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -25,6 +26,7 @@ require_once '../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportProjectAct.class.php';
 
 session_require_global_perm ('forge_stats', 'read') ;
 
@@ -53,6 +55,11 @@ if ($start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
+
 report_header(_('Project Activity'));
 
 ?>
@@ -69,7 +76,12 @@ report_header(_('Project Activity'));
 </form>
 <?php if ($g_id && $start != $end) { ?>
 	<p>
+	<?php
+		report_actgraph('project', $SPAN, $start, $end, $g_id, $area);
+	?>
+	<noscript>
 	<img src="projectact_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&g_id=$g_id&area=$area"; ?>" alt="" />
+	</noscript>
 	</p>
 	<?php
 
diff --git a/src/www/reporting/useract.php b/src/www/reporting/useract.php
index 4a585b1..ae76cbf 100644
--- a/src/www/reporting/useract.php
+++ b/src/www/reporting/useract.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -25,6 +26,7 @@ require_once '../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportUserAct.class.php';
 
 session_require_global_perm ('forge_stats', 'read') ;
 
@@ -54,6 +56,11 @@ if ($start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
+
 report_header(_('User Activity'));
 
 $abc_array = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
@@ -84,7 +91,12 @@ if ($sw) {
 	</form>
 	<?php if ($dev_id && $start != $end) { ?>
 		<p>
+		<?php
+			report_actgraph('user', $SPAN, $start, $end, $dev_id, $area);
+		?>
+		<noscript>
 		<img src="useract_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&dev_id=$dev_id&area=$area"; ?>" alt="" />
+		</noscript>
 		</p>
 		<?php
 

commit e39d6b3aa88d3f7519c6391addd562f8a5cb32a0
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jun 16 18:14:58 2013 +0200

    jqplot: implement groups added and cumul graphs

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 3b28e35..1c60824 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -423,22 +423,32 @@ function trackerpie_graph($group_id, $area, $SPAN, $start, $end, $atid) {
 	return true;
 }
 
-function userreport_graph($type, $SPAN, $start, $end) {
-	$now = time();
+function report_graph($type, $SPAN, $start, $end) {
+	$now = time() - 60*24*24;
 	if ($now < $end) {
 		$end = $now;
 	}
 	switch ($type) {
-		case 'cumul': {
+		case 'usercumul': {
 			$report = new ReportUserCum($SPAN, $start, $end);
 			$label[0] = _('Cumulative users.');
 			break;
 		}
-		case 'added': {
+		case 'useradded': {
 			$report = new ReportUserAdded($SPAN, $start, $end);
 			$label[0] = _('Users added.');
 			break;
 		}
+		case 'groupadded': {
+			$report = new ReportGroupAdded($SPAN, $start, $end);
+			$label[0] = _('Projects added.');
+			break;
+		}
+		case 'groupcumul': {
+			$report = new ReportGroupCum($SPAN, $start, $end);
+			$label[0] = _('Cumulative Projects.');
+			break;
+		}
 	}
 	
 	if ($report->isError()) {
diff --git a/src/www/reporting/groupadded.php b/src/www/reporting/groupadded.php
index d12d9ae..37459f4 100644
--- a/src/www/reporting/groupadded.php
+++ b/src/www/reporting/groupadded.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -25,6 +26,7 @@ require_once '../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportGroupAdded.class.php';
 
 session_require_global_perm ('forge_stats', 'read') ;
 
@@ -51,6 +53,9 @@ if ($start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+
 report_header(_('Projects Added'));
 
 ?>
@@ -64,7 +69,14 @@ report_header(_('Projects Added'));
 </tr></table>
 </form>
 <?php if ($start != $end) { ?>
-	<p><img src="groupadded_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" /></p>
+	<p>
+	<?php
+		report_graph('groupadded', $SPAN, $start, $end);
+	?>
+	<noscript>
+	<img src="groupadded_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
+	</noscript>
+	</p>
 <?php }
 
 report_footer();
diff --git a/src/www/reporting/groupcum.php b/src/www/reporting/groupcum.php
index 28bcfe9..44776fe 100644
--- a/src/www/reporting/groupcum.php
+++ b/src/www/reporting/groupcum.php
@@ -24,6 +24,7 @@ require_once '../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportGroupCum.class.php';
 
 session_require_global_perm ('forge_stats', 'read') ;
 
@@ -50,6 +51,9 @@ if ($start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+
 report_header(_('Cumulative Projects'));
 
 ?>
@@ -63,7 +67,14 @@ report_header(_('Cumulative Projects'));
 </tr></table>
 </form>
 <?php if ($start != $end) { ?>
-	<p><img src="groupcum_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" /></p>
+		<p>
+	<?php
+		report_graph('groupcumul', $SPAN, $start, $end);
+	?>
+	<noscript>
+	<img src="groupcum_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
+	</noscript>
+	</p>
 <?php }
 
 report_footer();
diff --git a/src/www/reporting/useradded.php b/src/www/reporting/useradded.php
index 6bab0d1..3f71be7 100644
--- a/src/www/reporting/useradded.php
+++ b/src/www/reporting/useradded.php
@@ -69,7 +69,7 @@ report_header(_('Users Added'));
 <?php if ($start != $end) { ?>
 	<p>
 	<?php
-		userreport_graph('added', $SPAN, $start, $end);
+		report_graph('useradded', $SPAN, $start, $end);
 	?>
 	<noscript>
 	<img src="useradded_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
diff --git a/src/www/reporting/usercum.php b/src/www/reporting/usercum.php
index 68a67b1..989b4c7 100644
--- a/src/www/reporting/usercum.php
+++ b/src/www/reporting/usercum.php
@@ -70,7 +70,7 @@ report_header(_('Cumulative Users'));
 <?php if ($start != $end) { ?>
 	<p>
 	<?php
-		userreport_graph('cumul', $SPAN, $start, $end);
+		report_graph('usercumul', $SPAN, $start, $end);
 	?>
 	<noscript>
 	<img src="usercum_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />

commit 44d5d37cffba4f4d79c0ae341473883fddff2c34
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jun 16 15:56:56 2013 +0200

    jqplot: implement user added, user cumul

diff --git a/src/common/reporting/Report.class.php b/src/common/reporting/Report.class.php
index 371f73b..87e958a 100644
--- a/src/common/reporting/Report.class.php
+++ b/src/common/reporting/Report.class.php
@@ -34,18 +34,19 @@ DEFINE('REPORT_TYPE_OA',4);
 class Report extends Error {
 
 //var $adjust_days=array('Sun'=>0, 'Sat'=>6, 'Fri'=>5, 'Thu'=>4, 'Wed'=>3, 'Tue'=>2, 'Mon'=>1);
-var $adjust_days=array('Sun'=>'0.0', 'Sat'=>1, 'Fri'=>2, 'Thu'=>3, 'Wed'=>4, 'Tue'=>5, 'Mon'=>6);
-var $month_start_arr=array();
+var $adjust_days = array('Sun'=>'0.0', 'Sat'=>1, 'Fri'=>2, 'Thu'=>3, 'Wed'=>4, 'Tue'=>5, 'Mon'=>6);
+var $month_start_arr = array();
 var $month_start_arr_format = array();
-var $week_start_arr=array();
+var $week_start_arr = array();
+var $week_start_arr_format = array();
 var $site_start_date;
 var $data;
 var $labels;
 var $span;
 var $start_date;
 var $end_date;
-var $span_name=array(1=>'Daily',2=>'Weekly',3=>'Monthly',4=>'OverAll');
-var $graph_interval=array(1=>7,2=>1,3=>1,4=>1);
+var $span_name = array(1=>'Daily',2=>'Weekly',3=>'Monthly',4=>'OverAll');
+var $graph_interval = array(1=>7,2=>1,3=>1,4=>1);
 var $max_weeks = 104;
 var $max_month = 24;
 var $rawdates = array();
@@ -92,11 +93,13 @@ function &getWeekStartArr() {
 		$start=mktime(0,0,0,date('m'),(date('d')+$this->adjust_days[date('D')]),date('Y'));
 		for ($i=0; $i<$this->max_weeks; $i++) {
 			$this->week_start_arr[]=($start-REPORT_WEEK_SPAN*$i);
+			$this->week_start_arr_format[] = date('Y/W', $this->week_start_arr[$i]);
 			if ($this->week_start_arr[$i] < $min_date) {
 				break;
 			}
 		}
 		sort($this->week_start_arr);
+		sort($this->week_start_arr_format);
 	}
 	return $this->week_start_arr;
 }
@@ -160,6 +163,9 @@ function getMonthStartArrFormat() {
 	return $this->month_start_arr_format;
 }
 
+function getWeekStartArrFormat() {
+	return $this->week_start_arr_format;
+}
 }
 
 // Local Variables:
diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 723a939..3b28e35 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -246,6 +246,10 @@ function report_package_box($group_id, $name='dev_id', $selected='') {
 }
 
 function trackeract_graph($group_id, $area, $SPAN, $start, $end, $atid) {
+	$now = time();
+	if ($now < $end) {
+		$end = $now;
+	}
 	if (!strlen($area)) {
 		echo '<p class="information">'._('No selected area.').'</p>';
 		return true;
@@ -364,6 +368,10 @@ function trackeract_graph($group_id, $area, $SPAN, $start, $end, $atid) {
 }
 
 function trackerpie_graph($group_id, $area, $SPAN, $start, $end, $atid) {
+	$now = time();
+	if ($now < $end) {
+		$end = $now;
+	}
 	if (!strlen($area)) {
 		echo '<p class="information">'._('No selected area.').'</p>';
 		return true;
@@ -415,6 +423,163 @@ function trackerpie_graph($group_id, $area, $SPAN, $start, $end, $atid) {
 	return true;
 }
 
+function userreport_graph($type, $SPAN, $start, $end) {
+	$now = time();
+	if ($now < $end) {
+		$end = $now;
+	}
+	switch ($type) {
+		case 'cumul': {
+			$report = new ReportUserCum($SPAN, $start, $end);
+			$label[0] = _('Cumulative users.');
+			break;
+		}
+		case 'added': {
+			$report = new ReportUserAdded($SPAN, $start, $end);
+			$label[0] = _('Users added.');
+			break;
+		}
+	}
+	
+	if ($report->isError()) {
+		echo '<p class="error">'.$report->getErrorMessage().'</p>';
+		return false;
+	}
+	$rdates = $report->getRawDates();
+	if (!$rdates) {
+		echo '<p class="error">'._('No data to display').'</p>';
+		return false;
+	}
+	$ydata[0]  = $report->getData();
+	
+	if ($SPAN == REPORT_TYPE_DAILY) {
+		$i = 0;
+		$formatDate = 'Y/m/d';
+		$looptime = $start;
+		while ($looptime < $end) {
+			$timeStampArr[$i] = $looptime;
+			$timeStampArrFormat[$i] = date($formatDate, $looptime);
+			$looptime += REPORT_DAY_SPAN;
+			$i++;
+		}
+	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
+		$timeStampArr = $report->getWeekStartArr();
+		$timeStampArrFormat = $report->getWeekStartArrFormat();
+		$formatDate = 'Y/W';
+	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
+		$timeStampArr = $report->getMonthStartArr();
+		$timeStampArrFormat = $report->getMonthStartArrFormat();
+		$formatDate = 'Y/m';
+	}
+
+	$chartid = '_useradded';
+	$yMax = 0;
+	echo '<script type="text/javascript">//<![CDATA['."\n";
+	echo 'var plot'.$chartid.';';
+	echo 'var '.$chartid.'values = new Array();';
+	echo 'var '.$chartid.'labels = new Array();';
+	echo 'var '.$chartid.'series = new Array();';
+	for ($z = 0; $z < count($ydata); $z++) {
+		echo $chartid.'values['.$z.'] = new Array();';
+		echo $chartid.'labels.push({label:\''.$label[$z].'\'});';
+		switch ($SPAN) {
+			case REPORT_TYPE_DAILY :
+			case REPORT_TYPE_MONTHLY : {
+				for ($j = 0; $j < count($timeStampArr); $j++) {
+					if (in_array($timeStampArr[$j], $rdates)) {
+						$thekey = array_search($timeStampArr[$j], $rdates);
+						if (isset($ydata[$z][$thekey])) {
+							if ($ydata[$z][$thekey] === false) {
+								$ydata[$z][$thekey] = 0;
+							}
+							if ($ydata[$z][$thekey] > $yMax) {
+								$yMax = $ydata[$z][$thekey];
+							}
+							echo 'var '.$chartid.'datevalues = '.$ydata[$z][$thekey].';';
+						} else {
+							echo 'var '.$chartid.'datevalues = 0;';
+						}
+					} else {
+						echo 'var '.$chartid.'datevalues = 0;';
+					}
+					echo 'var '.$chartid.'date = \''.$timeStampArrFormat[$j].'\';';
+					echo $chartid.'values['.$z.'].push(['.$chartid.'date, '.$chartid.'datevalues]);';
+				}
+				break;
+			}
+			case REPORT_TYPE_WEEKLY : {
+				for ($j = 0; $j < count($rdates); $j++) {
+					$wrdates[$j] = date($formatDate, $rdates[$j]);
+				}
+				for ($j = 0; $j < count($timeStampArr); $j++) {
+					if (in_array($timeStampArrFormat[$j], $wrdates)) {
+						$thekey = array_search($timeStampArr[$j], $wrdates);
+						if (isset($ydata[$z][$thekey])) {
+							if ($ydata[$z][$thekey] === false) {
+								$ydata[$z][$thekey] = 0;
+							}
+							if ($ydata[$z][$thekey] > $yMax) {
+								$yMax = $ydata[$z][$thekey];
+							}
+							echo 'var '.$chartid.'datevalues = '.$ydata[$z][$thekey].';';
+						} else {
+							echo 'var '.$chartid.'datevalues = 0;';
+						}
+					} else {
+						echo 'var '.$chartid.'datevalues = 0;';
+					}
+					echo 'var '.$chartid.'date = \''.$timeStampArrFormat[$j].'\';';
+					echo $chartid.'values['.$z.'].push(['.$chartid.'date, '.$chartid.'datevalues]);';
+				}
+				break;
+			}
+		}
+	}
+	for ($z = 0; $z < count($ydata); $z++) {
+		echo $chartid.'series.push('.$chartid.'values['.$z.']);';
+	}
+	echo 'jQuery(document).ready(function(){
+		plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', '.$chartid.'series, {
+			axesDefaults: {
+				tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
+				tickOptions: {
+					angle: 60,
+					showGridline: false,
+				}
+			},
+			legend: {
+				show:true, location: \'ne\',
+			},
+			series:
+				'.$chartid.'labels
+			,
+			axes: {
+				xaxis: {
+					renderer: jQuery.jqplot.CategoryAxisRenderer,
+					label: \''.$label[0].'\',
+				},
+				yaxis: {
+					max: '.++$yMax.',
+					min: 0,
+					tickOptions: {
+						angle: 0,
+					},
+				}
+			},
+			highlighter: {
+				show: true,
+				sizeAdjust: 2.5,
+			},
+		});
+	});';
+	echo 'jQuery(window).resize(function() {
+			plot'.$chartid.'.replot( { resetAxes: true } );
+		});'."\n";
+	echo '//]]></script>';
+	echo '<div id="chart'.$chartid.'"></div>';
+	return true;
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/reporting/useradded.php b/src/www/reporting/useradded.php
index bfddb13..6bab0d1 100644
--- a/src/www/reporting/useradded.php
+++ b/src/www/reporting/useradded.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -24,6 +25,7 @@ require_once '../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportUserAdded.class.php';
 
 session_require_global_perm ('forge_stats', 'read') ;
 
@@ -50,6 +52,9 @@ if ($start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+
 report_header(_('Users Added'));
 
 ?>
@@ -62,7 +67,14 @@ report_header(_('Users Added'));
 </tr></table>
 </form>
 <?php if ($start != $end) { ?>
-	<p><img src="useradded_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" /></p>
+	<p>
+	<?php
+		userreport_graph('added', $SPAN, $start, $end);
+	?>
+	<noscript>
+	<img src="useradded_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
+	</noscript>
+	</p>
 <?php }
 
 report_footer();
diff --git a/src/www/reporting/usercum.php b/src/www/reporting/usercum.php
index 0b089e3..68a67b1 100644
--- a/src/www/reporting/usercum.php
+++ b/src/www/reporting/usercum.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) GForge LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -25,6 +26,7 @@ require_once '../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportUserCum.class.php';
 
 session_require_global_perm ('forge_stats', 'read') ;
 
@@ -51,6 +53,9 @@ if ($start == $end) {
 	$error_msg .= _('Start and end dates must be different');
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+
 report_header(_('Cumulative Users'));
 ?>
 
@@ -63,9 +68,14 @@ report_header(_('Cumulative Users'));
 </tr></table>
 </form>
 <?php if ($start != $end) { ?>
-<p>
-<img src="usercum_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
-</p>
+	<p>
+	<?php
+		userreport_graph('cumul', $SPAN, $start, $end);
+	?>
+	<noscript>
+	<img src="usercum_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end"; ?>" alt="" />
+	</noscript>
+	</p>
 <?php }
 
 report_footer();

commit 486bdf382926cb00275fe24851d24321634094fc
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jun 16 15:56:18 2013 +0200

    jpqlot: project stats: cleanup

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index d273c63..e2314b1 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -258,21 +258,18 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 		return false;
 	}
 	if ($SPAN == REPORT_TYPE_DAILY) {
-		$interval = REPORT_DAY_SPAN;
 		$i = 0;
 		$looptime = $start;
 		while ($looptime < $end) {
 			$timeStampArr[$i] = $looptime;
-			$looptime += $interval;
+			$looptime += REPORT_DAY_SPAN;
 			$i++;
 		}
 		$formatDate = 'Y/m/d';
 	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
-		$interval = REPORT_WEEK_SPAN;
 		$timeStampArr = $report->getWeekStartArr();
 		$formatDate = 'Y/W';
 	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
-		$interval = REPORT_MONTH_SPAN;
 		$timeStampArr = $report->getMonthStartArr();
 		$formatDate = 'Y/m';
 	}

commit 46af446c40b197f640baaba4e7d9db0ae2cff541
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jun 16 15:55:40 2013 +0200

    Report: add informations label

diff --git a/src/www/reporting/index.php b/src/www/reporting/index.php
index ca8ca93..a3b1ed4 100644
--- a/src/www/reporting/index.php
+++ b/src/www/reporting/index.php
@@ -37,6 +37,7 @@ report_header('Main Page');
 <p>
 <a href="useradded.php?SPAN=1"><?php echo _('Users Added (graph)'); ?></a><br />
 <a href="usercum.php?SPAN=1"><?php echo _('Cumulative Users (graph)'); ?></a><br />
+<?php echo _('User-specific reports: Tracker, Task Mgr, Forums, Doc Mgr, Downloads'); ?><br />
 <a href="useract.php"><?php echo _('Activity (graph)'); ?></a></p>
 <h2><?php echo _('Projects'); ?></h2>
 <p>

commit 13287103254e334532c5c85b9bdd9340e7bc5a14
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sun Jun 16 15:55:12 2013 +0200

    jpqlot: site wide stats: cleanup, set yMax when needed, use pad

diff --git a/src/www/stats/site_stats_utils.php b/src/www/stats/site_stats_utils.php
index 07bfccb..11d8ec8 100644
--- a/src/www/stats/site_stats_utils.php
+++ b/src/www/stats/site_stats_utils.php
@@ -525,16 +525,11 @@ function views_graph($monthly = 0) {
 		$chartid = '_views_graph';
 		echo '<script type="text/javascript">//<![CDATA['."\n";
 		echo 'var '.$chartid.'values = new Array();';
-		echo 'var '.$chartid.'ticks = new Array();';
 		echo 'var plot'.$chartid.';';
-		$yMax = 0;
 		for ($j = 0; $j < count($monthStartArrFormat); $j++) {
 			$key = array_search($monthStartArrFormat[$j], $xlabel);
 			if ($key !== FALSE) {
 				echo 'var '.$chartid.'datevalues = '.$ydata[$key].';';
-				if ($ydata[$key] > $yMax) {
-					$yMax = $ydata[$key];
-				}
 			} else {
 				echo 'var '.$chartid.'datevalues = 0;';
 			}
@@ -547,7 +542,9 @@ function views_graph($monthly = 0) {
 						tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
 						tickOptions: {
 							angle: 30,
-						}
+							showGridline: false,
+						},
+						pad: 0,
 					},
 					axes: {
 						xaxis: {
@@ -585,6 +582,7 @@ function users_graph() {
 			array ());
 
 	$i = 0;
+	$yMax = 0;
 	$xlabel = array();
 	$ydata = array();
 	$ydata[0] = array();
@@ -603,7 +601,6 @@ function users_graph() {
 		$chartid = '_newprojectuser';
 		echo '<script type="text/javascript">//<![CDATA['."\n";
 		echo 'var '.$chartid.'values = new Array();';
-		echo 'var '.$chartid.'ticks = new Array();';
 		echo 'var '.$chartid.'labels = new Array();';
 		echo 'var '.$chartid.'series = new Array();';
 		echo 'var plot'.$chartid.';';
@@ -614,8 +611,8 @@ function users_graph() {
 				$key = array_search($monthStartArrFormat[$j], $xlabel);
 				if ($key !== FALSE) {
 					echo 'var '.$chartid.'datevalues = '.$ydata[$z][$key].';';
-					if ($ydata[$z][$key] > $yMax) {
-						$yMax = $ydata[$z][$key];
+					if ($ydata[$z][$thekey] > $yMax) {
+						$yMax = $ydata[$z][$thekey];
 					}
 				} else {
 					echo 'var '.$chartid.'datevalues = 0;';
@@ -633,7 +630,9 @@ function users_graph() {
 						tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
 						tickOptions: {
 							angle: 30,
-						}
+							showGridline: false,
+						},
+						pad: 0,
 					},
 					legend: {
 						show:true, location: \'ne\',
@@ -647,6 +646,7 @@ function users_graph() {
 							label: \''.('New Users and new projects per month').'\',
 						},
 						yaxis: {
+							max: '.++$yMax.',
 							min: 0,
 							tickOptions: {
 								angle: 0,

commit 046e007c1d2fb9902ade8a0fa06865286bfc3977
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 14 19:47:52 2013 +0200

    jqplot: sitewide stats, add informations about displayed data

diff --git a/src/www/stats/graphs.php b/src/www/stats/graphs.php
index dc60432..d96e728 100644
--- a/src/www/stats/graphs.php
+++ b/src/www/stats/graphs.php
@@ -47,7 +47,7 @@ $HTML->header(array('title'=>sprintf(_('%1$s Sitewide Statistics Graphs'), forge
 </table>
 
 <hr />
-
+<p class="information" ><?php echo _('Displayed data: only last 24 months.'); ?></p>
 <p class="align-center">
 <?php 
 views_graph(1);

commit 5e0ec9dfea7b49a3f6ede40db23bcc7c199aac80
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri Jun 14 18:35:59 2013 +0200

    jqplot: implement Site-wide Stats

diff --git a/src/common/reporting/Report.class.php b/src/common/reporting/Report.class.php
index 332e2d1..371f73b 100644
--- a/src/common/reporting/Report.class.php
+++ b/src/common/reporting/Report.class.php
@@ -36,6 +36,7 @@ class Report extends Error {
 //var $adjust_days=array('Sun'=>0, 'Sat'=>6, 'Fri'=>5, 'Thu'=>4, 'Wed'=>3, 'Tue'=>2, 'Mon'=>1);
 var $adjust_days=array('Sun'=>'0.0', 'Sat'=>1, 'Fri'=>2, 'Thu'=>3, 'Wed'=>4, 'Tue'=>5, 'Mon'=>6);
 var $month_start_arr=array();
+var $month_start_arr_format = array();
 var $week_start_arr=array();
 var $site_start_date;
 var $data;
@@ -47,7 +48,7 @@ var $span_name=array(1=>'Daily',2=>'Weekly',3=>'Monthly',4=>'OverAll');
 var $graph_interval=array(1=>7,2=>1,3=>1,4=>1);
 var $max_weeks = 104;
 var $max_month = 24;
-var $rawdates;
+var $rawdates = array();
 
 function Report() {
 	$this->Error();
@@ -73,12 +74,14 @@ function &getMonthStartArr() {
 	if (count($this->month_start_arr) < 1) {
 		$min_date=$this->getMinDate();
 		for ($i=0; $i<$this->max_month; $i++) {
-			$this->month_start_arr[]=mktime(0,0,0,date('m')+1-$i,1,date('Y'));
+			$this->month_start_arr[] = mktime(0,0,0,date('m')+1-$i,1,date('Y'));
+			$this->month_start_arr_format[] = date('Ym', $this->month_start_arr[$i]);
 			if ($this->month_start_arr[$i] < $min_date) {
 				break;
 			}
 		}
 		sort($this->month_start_arr);
+		sort($this->month_start_arr_format);
 	}
 	return $this->month_start_arr;
 }
@@ -153,6 +156,10 @@ function getEndDate() {
 	return $this->end_date;
 }
 
+function getMonthStartArrFormat() {
+	return $this->month_start_arr_format;
+}
+
 }
 
 // Local Variables:
diff --git a/src/www/stats/site_stats_utils.php b/src/www/stats/site_stats_utils.php
index e2010c5..07bfccb 100644
--- a/src/www/stats/site_stats_utils.php
+++ b/src/www/stats/site_stats_utils.php
@@ -491,15 +491,17 @@ function stats_site_aggregate( ) {
 }
 
 function views_graph($monthly = 0) {
-	$year = gmstrftime("%Y", time() );
+	global $gfcommon;
+	require_once $gfcommon.'reporting/Report.class.php';
+	$report = new Report();
 	if ($monthly) {
 		$res = db_query_params('SELECT month,site_page_views AS site_views,subdomain_views
 					FROM stats_site_months ORDER BY month ASC',
 					array());
 	} else {
-		$beg_year=date('Y',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
-		$beg_month=date('m',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
-		$beg_day=date('d',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
+		$beg_year = date('Y',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
+		$beg_month = date('m',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
+		$beg_day = date('d',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
 		$res = db_query_params ('SELECT month,day,site_page_views AS site_views,subdomain_views
 			FROM stats_site_vw
 			( month = $1 AND day >= $2 ) OR ( month > $3 )
@@ -514,34 +516,49 @@ function views_graph($monthly = 0) {
 	$ydata = array();
 	while ( $row = db_fetch_array($res) ) {
 		$xlabel[$i] = $row['month'] . ((isset($row['day'])) ? "/" . $row['day'] : '');
-		$ydata[$i] = $row["site_views"] + $row["subdomain_views"];
+		$ydata[$i] = $row['site_views'] + $row['subdomain_views'];
 		++$i;
 	}
+	$monthStartArr = $report->getMonthStartArr();
+	$monthStartArrFormat = $report->getMonthStartArrFormat();
 	if (count($ydata)) {
 		$chartid = '_views_graph';
 		echo '<script type="text/javascript">//<![CDATA['."\n";
-		echo 'var values = new Array();';
+		echo 'var '.$chartid.'values = new Array();';
+		echo 'var '.$chartid.'ticks = new Array();';
 		echo 'var plot'.$chartid.';';
 		$yMax = 0;
-		for ($j = 0; $j < count($ydata); $j++) {
-			$timeStamp = mktime(0, 0, 0, substr($xlabel[$j], 4, 2) , 1, substr($xlabel[$j], 0, 4));
-			echo 'var date = new Date(0);';
-			echo 'date.setUTCSeconds('.$timeStamp.');';
-			echo 'date = '.$xlabel[$j].';';
-			echo 'var datevalues = '.$ydata[$j].';';
-			echo 'values.push([date, datevalues]);';
-			if ($ydata[$j] > $yMax) {
-				$yMax = $ydata[$j];
+		for ($j = 0; $j < count($monthStartArrFormat); $j++) {
+			$key = array_search($monthStartArrFormat[$j], $xlabel);
+			if ($key !== FALSE) {
+				echo 'var '.$chartid.'datevalues = '.$ydata[$key].';';
+				if ($ydata[$key] > $yMax) {
+					$yMax = $ydata[$key];
+				}
+			} else {
+				echo 'var '.$chartid.'datevalues = 0;';
 			}
+			echo 'var '.$chartid.'date = '.$monthStartArrFormat[$j].';';
+			echo $chartid.'values.push(['.$chartid.'date, '.$chartid.'datevalues]);';
 		}
 		echo 'jQuery(document).ready(function(){
-				plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
+				plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', ['.$chartid.'values], {
+					axesDefaults: {
+						tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
+						tickOptions: {
+							angle: 30,
+						}
+					},
 					axes: {
 						xaxis: {
-							label: \''.('Month').'\',
+							renderer: jQuery.jqplot.CategoryAxisRenderer,
+							label: \''.('Pages view per month').'\',
 						},
 						yaxis: {
-							label: \''._('Pages view').'\',
+							min: 0,
+							tickOptions: {
+								angle: 0,
+							}
 						}
 					},
 					highlighter: {
@@ -561,7 +578,95 @@ function views_graph($monthly = 0) {
 }
 
 function users_graph() {
-	echo 'autre joli graph';
+	global $gfcommon;
+	require_once $gfcommon.'reporting/Report.class.php';
+	$report = new Report();
+	$res = db_query_params ('SELECT month,day,new_users,new_projects FROM stats_site ORDER BY month ASC, day ASC',
+			array ());
+
+	$i = 0;
+	$xlabel = array();
+	$ydata = array();
+	$ydata[0] = array();
+	$ydata[1] = array();
+	$label[0] = _('New users');
+	$label[1] = _('New projects');
+	$monthStartArr = $report->getMonthStartArr();
+	$monthStartArrFormat = $report->getMonthStartArrFormat();
+	while ( $row = db_fetch_array($res) ) {
+		$xlabel[$i] = $row['month'] . ((isset($row['day'])) ? "/" . $row['day'] : '');
+		$ydata[0][$i] = $row['new_users'];
+		$ydata[1][$i] = $row['new_projects'];
+		++$i;
+	}
+	if (count($ydata[0])) {
+		$chartid = '_newprojectuser';
+		echo '<script type="text/javascript">//<![CDATA['."\n";
+		echo 'var '.$chartid.'values = new Array();';
+		echo 'var '.$chartid.'ticks = new Array();';
+		echo 'var '.$chartid.'labels = new Array();';
+		echo 'var '.$chartid.'series = new Array();';
+		echo 'var plot'.$chartid.';';
+		for ($z = 0; $z < count($ydata); $z++) {
+			echo $chartid.'values['.$z.'] = new Array();';
+			echo $chartid.'labels.push({label:\''.$label[$z].'\'});';
+			for ($j = 0; $j < count($monthStartArrFormat); $j++) {
+				$key = array_search($monthStartArrFormat[$j], $xlabel);
+				if ($key !== FALSE) {
+					echo 'var '.$chartid.'datevalues = '.$ydata[$z][$key].';';
+					if ($ydata[$z][$key] > $yMax) {
+						$yMax = $ydata[$z][$key];
+					}
+				} else {
+					echo 'var '.$chartid.'datevalues = 0;';
+				}
+				echo 'var '.$chartid.'date = '.$monthStartArrFormat[$j].';';
+				echo $chartid.'values['.$z.'].push(['.$chartid.'date, '.$chartid.'datevalues]);';
+			}
+		}
+		for ($z = 0; $z < count($ydata); $z++) {
+			echo $chartid.'series.push('.$chartid.'values['.$z.']);';
+		}
+		echo 'jQuery(document).ready(function(){
+				plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', '.$chartid.'series, {
+					axesDefaults: {
+						tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
+						tickOptions: {
+							angle: 30,
+						}
+					},
+					legend: {
+						show:true, location: \'ne\',
+					},
+					series:
+						'.$chartid.'labels
+					,
+					axes: {
+						xaxis: {
+							renderer: jQuery.jqplot.CategoryAxisRenderer,
+							label: \''.('New Users and new projects per month').'\',
+						},
+						yaxis: {
+							min: 0,
+							tickOptions: {
+								angle: 0,
+							}
+						}
+					},
+					highlighter: {
+						show: true,
+						sizeAdjust: 2.5,
+					},
+				});
+			});';
+		echo 'jQuery(window).resize(function() {
+			plot'.$chartid.'.replot();
+			});'."\n";
+		echo '//]]></script>';
+		echo '<div id="chart'.$chartid.'"></div>';
+	} else {
+		echo '<p class="information">'._('New users, new projects: no graph to display.').'</p>';
+	}
 }
 
 // Local Variables:

commit f78927fcc564107261595de6b5cda0ed88ccb05d
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Tue Jun 4 00:21:36 2013 +0200

    jqplot: site stats, implement pages view graph

diff --git a/src/www/stats/graphs.php b/src/www/stats/graphs.php
index f743dc4..dc60432 100644
--- a/src/www/stats/graphs.php
+++ b/src/www/stats/graphs.php
@@ -5,6 +5,7 @@
  * Copyright 1999-2001 (c) VA Linux Systems
  * Copyright 2010 (c) FusionForge Team
  * Copyright (C) 2010 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -29,6 +30,9 @@ require_once $gfwww.'stats/site_stats_utils.php';
 
 session_require_global_perm ('forge_stats', 'read') ;
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+
 $HTML->header(array('title'=>sprintf(_('%1$s Sitewide Statistics Graphs'), forge_get_config ('forge_name'))));
 ?>
 
@@ -45,10 +49,20 @@ $HTML->header(array('title'=>sprintf(_('%1$s Sitewide Statistics Graphs'), forge
 <hr />
 
 <p class="align-center">
+<?php 
+views_graph(1);
+?>
+<noscript>
 <img src="views_graph.php?monthly=1" alt="" />
+</noscript>
 </p>
 <p class="align-center">
+<?php
+users_graph();
+?>
+<noscript>
 <img src="users_graph.php" alt="" />
+</noscript>
 </p>
 
 <?php
diff --git a/src/www/stats/site_stats_utils.php b/src/www/stats/site_stats_utils.php
index 0863dbc..e2010c5 100644
--- a/src/www/stats/site_stats_utils.php
+++ b/src/www/stats/site_stats_utils.php
@@ -490,6 +490,80 @@ function stats_site_aggregate( ) {
 	<?php
 }
 
+function views_graph($monthly = 0) {
+	$year = gmstrftime("%Y", time() );
+	if ($monthly) {
+		$res = db_query_params('SELECT month,site_page_views AS site_views,subdomain_views
+					FROM stats_site_months ORDER BY month ASC',
+					array());
+	} else {
+		$beg_year=date('Y',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
+		$beg_month=date('m',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
+		$beg_day=date('d',mktime(0,0,0,(date('m')-1),date('d'),date('Y')));
+		$res = db_query_params ('SELECT month,day,site_page_views AS site_views,subdomain_views
+			FROM stats_site_vw
+			( month = $1 AND day >= $2 ) OR ( month > $3 )
+			ORDER BY month ASC, day ASC',
+			array ("$beg_year$beg_month",
+				$beg_day,
+				"$beg_year$beg_month"));
+	}
+
+	$i = 0;
+	$xlabel = array();
+	$ydata = array();
+	while ( $row = db_fetch_array($res) ) {
+		$xlabel[$i] = $row['month'] . ((isset($row['day'])) ? "/" . $row['day'] : '');
+		$ydata[$i] = $row["site_views"] + $row["subdomain_views"];
+		++$i;
+	}
+	if (count($ydata)) {
+		$chartid = '_views_graph';
+		echo '<script type="text/javascript">//<![CDATA['."\n";
+		echo 'var values = new Array();';
+		echo 'var plot'.$chartid.';';
+		$yMax = 0;
+		for ($j = 0; $j < count($ydata); $j++) {
+			$timeStamp = mktime(0, 0, 0, substr($xlabel[$j], 4, 2) , 1, substr($xlabel[$j], 0, 4));
+			echo 'var date = new Date(0);';
+			echo 'date.setUTCSeconds('.$timeStamp.');';
+			echo 'date = '.$xlabel[$j].';';
+			echo 'var datevalues = '.$ydata[$j].';';
+			echo 'values.push([date, datevalues]);';
+			if ($ydata[$j] > $yMax) {
+				$yMax = $ydata[$j];
+			}
+		}
+		echo 'jQuery(document).ready(function(){
+				plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
+					axes: {
+						xaxis: {
+							label: \''.('Month').'\',
+						},
+						yaxis: {
+							label: \''._('Pages view').'\',
+						}
+					},
+					highlighter: {
+						show: true,
+						sizeAdjust: 2.5,
+					},
+				});
+			});';
+		echo 'jQuery(window).resize(function() {
+			plot'.$chartid.'.replot();
+			});'."\n";
+		echo '//]]></script>';
+		echo '<div id="chart'.$chartid.'"></div>';
+	} else {
+		echo '<p class="information">'._('Page view: no graph to display.').'</p>';
+	}
+}
+
+function users_graph() {
+	echo 'autre joli graph';
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"

commit 473fc58811178fd54e1fdaa9da096f831de3831b
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Sat May 25 16:37:01 2013 +0200

    Forge Reporting: fix label

diff --git a/src/www/reporting/index.php b/src/www/reporting/index.php
index db532b8..ca8ca93 100644
--- a/src/www/reporting/index.php
+++ b/src/www/reporting/index.php
@@ -3,9 +3,8 @@
  * Reporting System
  *
  * Copyright 2004 (c) GForge LLC
- *
- * @author Tim Perdue tim at gforge.org
- * @date 2003-03-16
+ * Copyright 2006, Tim Perdue - gforge.org
+ * Copyright 2013, Franck Villaume - TrivialDev
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -36,13 +35,13 @@ report_header('Main Page');
 ?>
 <h2><?php echo _('Users'); ?></h2>
 <p>
-<a href="useradded.php?SPAN=1"><?php echo _('Users Added Weekly (graph)'); ?></a><br />
-<a href="usercum.php?SPAN=1"><?php echo _('Cumulative Users Weekly (graph)'); ?></a><br />
+<a href="useradded.php?SPAN=1"><?php echo _('Users Added (graph)'); ?></a><br />
+<a href="usercum.php?SPAN=1"><?php echo _('Cumulative Users (graph)'); ?></a><br />
 <a href="useract.php"><?php echo _('Activity (graph)'); ?></a></p>
 <h2><?php echo _('Projects'); ?></h2>
 <p>
-<a href="groupadded.php?SPAN=1"><?php echo _('Projects Added Weekly (graph)'); ?></a><br />
-<a href="groupcum.php?SPAN=1"><?php echo _('Cumulative Projects Weekly (graph)'); ?></a><br />
+<a href="groupadded.php?SPAN=1"><?php echo _('Projects Added (graph)'); ?></a><br />
+<a href="groupcum.php?SPAN=1"><?php echo _('Cumulative Projects (graph)'); ?></a><br />
 <?php echo _('Project-specific reports: Tracker, Task Mgr, Forums, Doc Mgr, Downloads'); ?><br />
 <a href="projectact.php"><?php echo _('Activity (graph)'); ?></a></p>
 <h2><?php echo _('Site-Wide'); ?></h2>

commit 7ca249869e53d45d59662ce65d57d3145d3dfe10
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 16:54:26 2013 +0200

    jqplot: fix javascript warning

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index e71f243..d273c63 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -378,6 +378,7 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	$chartid = 'projectgraph_'.$group_id;
 	$yMax = 0;
 	echo '<script type="text/javascript">//<![CDATA['."\n";
+	echo 'var plot'.$chartid.';';
 	echo 'var values = new Array();';
 	echo 'var ticks = new Array();';
 	echo 'var labels = new Array();';

commit 5bdd518d0eecc689587bc4397fa395bf74908134
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 16:54:06 2013 +0200

    jqplot: enable pie

diff --git a/src/www/tracker/reporting/index.php b/src/www/tracker/reporting/index.php
index 241776d..125ff99 100644
--- a/src/www/tracker/reporting/index.php
+++ b/src/www/tracker/reporting/index.php
@@ -110,6 +110,7 @@ if ($atid) {
 }
 
 html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginPie();
 html_use_jqueryjqplotpluginhighlighter();
 html_use_jqueryjqplotplugindateAxisRenderer();
 html_use_jqueryjqplotpluginBar();

commit 9fe97dbe37d305c3cfc78963600a89cfe67b9014
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 16:46:27 2013 +0200

    jqplot: implement tracker report per assignee

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index 5791c6e..723a939 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -272,6 +272,7 @@ function trackeract_graph($group_id, $area, $SPAN, $start, $end, $atid) {
 	echo 'var ticks = new Array();';
 	echo 'var labels = new Array();';
 	echo 'var series = new Array();';
+	echo 'var plot'.$chartid.';';
 	for ($z = 0; $z < count($ydata); $z++) {
 		echo 'values['.$z.'] = new Array();';
 		echo 'labels.push({label:\''.$label[$z].'\'});';
@@ -367,7 +368,50 @@ function trackerpie_graph($group_id, $area, $SPAN, $start, $end, $atid) {
 		echo '<p class="information">'._('No selected area.').'</p>';
 		return true;
 	}
-	echo 'joli graph';
+	$report = new ReportTrackerAct($SPAN, $group_id, $atid, $start, $end);
+	if ($report->isError()) {
+		echo '<p class="error">'.$report->getErrorMessage().'</p>';
+		return false;
+	}
+	switch ($area) {
+		default: {
+			$dbres = $report->getPerAssignee($atid, $start, $end);
+			$areaname = _('Per assignee');
+			break;
+		}
+	}
+	$chartid = 'projecttrackerpie_'.$group_id;
+	echo '<script type="text/javascript">//<![CDATA['."\n";
+	echo 'var plot'.$chartid.';';
+	echo 'var data = new Array();';
+	while ($row = db_fetch_array($dbres)) {
+		echo 'data.push([\''.htmlentities($row[0]).'\',\''.$row[1].'\']);';
+	}
+	echo 'jQuery(document).ready(function(){
+		plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [data],
+			{
+				title : \''.utf8_decode($areaname." (".strftime('%x',$start) ." - ". strftime('%x',$end) .")").'\',
+				seriesDefaults: {
+					// Make this a pie chart.
+					renderer: jQuery.jqplot.PieRenderer,
+					rendererOptions: {
+						// Put data labels on the pie slices.
+						// By default, labels show the percentage of the slice.
+						showDataLabels: true,
+						dataLabels: \'percent\',
+					}
+				},
+				legend: {
+					show:true, location: \'e\',
+				},
+			}
+			);
+		});';
+	echo 'jQuery(window).resize(function() {
+			plot'.$chartid.'.replot( { resetAxes: true } );
+		});'."\n";
+	echo '//]]></script>';
+	echo '<div id="chart'.$chartid.'"></div>';
 	return true;
 }
 

commit 6751bc261c6162a61a3dab874a9fe4e954eae184
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 16:45:25 2013 +0200

    Report Tracker: add getPerAssignee method, factorize code

diff --git a/src/common/reporting/ReportTrackerAct.class.php b/src/common/reporting/ReportTrackerAct.class.php
index 98ffefe..ecee14d 100644
--- a/src/common/reporting/ReportTrackerAct.class.php
+++ b/src/common/reporting/ReportTrackerAct.class.php
@@ -59,42 +59,28 @@ function ReportTrackerAct($span,$group_id,$atid,$start=0,$end=0) {
 		$this->setError('No group_id');
 		return false;
 	}
-	if (!$span || $span == REPORT_TYPE_MONTHLY) {
-
-		$arr =& $this->getMonthStartArr();
-
-		for ($i=0; $i<count($arr); $i++) {
-			if ($arr[$i]<$start || $arr[$i]>$end) {
-				//skip this month as it's not in the range
-				unset($arr[$i]);
-			} else {
-
-				$this->labels[]=date('M d',($arr[$i-1]-1)).' <-> '.date('M d',$arr[$i]);
-				$this->avgtime[]=$this->getAverageTime($atid,($arr[$i-1]-1),$arr[$i]);
-				$this->opencount[]=$this->getOpenCount($atid,($arr[$i-1]-1),$arr[$i]);
-				$this->stillopencount[]=$this->getStillOpenCount($atid,$arr[$i]);
-
-			}
+	
+	switch ($span) {
+		case REPORT_TYPE_WEEKLY: {
+			$arr =& $this->getWeekStartArr();
+			break;
 		}
-
-	} elseif ($span == REPORT_TYPE_WEEKLY) {
-
-		$arr =& $this->getWeekStartArr();
-
-		for ($i=0; $i<count($arr); $i++) {
-			if ($arr[$i]<$start || $arr[$i]>$end) {
-				//skip this week as it's not in the range
-				unset($arr[$i]);
-			} else {
-
-				$this->labels[]=date('M d',($arr[$i-1]-1)).' <-> '.date('M d',$arr[$i]);
-				$this->avgtime[]=$this->getAverageTime($atid,($arr[$i-1]-1),$arr[$i]);
-				$this->opencount[]=$this->getOpenCount($atid,($arr[$i-1]-1),$arr[$i]);
-				$this->stillopencount[]=$this->getStillOpenCount($atid,$arr[$i]);
-
-			}
+		default: {
+			$arr =& $this->getMonthStartArr();
+			break;
 		}
+	}
 
+	for ($i=0; $i<count($arr); $i++) {
+		if ($arr[$i]<$start || $arr[$i]>$end) {
+			//skip this month as it's not in the range
+			unset($arr[$i]);
+		} else {
+			$this->labels[]=date('M d',($arr[$i-1]-1)).' <-> '.date('M d',$arr[$i]);
+			$this->avgtime[]=$this->getAverageTime($atid,($arr[$i-1]-1),$arr[$i]);
+			$this->opencount[]=$this->getOpenCount($atid,($arr[$i-1]-1),$arr[$i]);
+			$this->stillopencount[]=$this->getStillOpenCount($atid,$arr[$i]);
+		}
 	}
 
 	$this->start_date=$start;
@@ -144,6 +130,19 @@ function getStillOpenCount($atid,$end) {
 	return db_result($res,0,0);
 }
 
+function getPerAssignee($atid, $start, $end) {
+	$res = db_query_params('SELECT u.realname,count(*)
+		FROM artifact a, users u
+		WHERE a.group_artifact_id=$1
+		AND a.assigned_to=u.user_id
+		AND a.open_date BETWEEN $2 AND $3
+		GROUP BY realname',
+				array($atid,
+				      $start,
+				      $end));
+	return $res;
+}
+
 function &getAverageTimeData() {
 	return $this->avgtime;
 }

commit 250e8bef175b62dfff44cfb605f8d4a3127c1f71
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 13:28:53 2013 +0200

    jqplot: implement tracker report activity

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index c6f9966..5791c6e 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -250,9 +250,115 @@ function trackeract_graph($group_id, $area, $SPAN, $start, $end, $atid) {
 		echo '<p class="information">'._('No selected area.').'</p>';
 		return true;
 	}
-	$report=new ReportTrackerAct($SPAN, $group_id, $atid, $start, $end);
-	var_dump($report);
-	echo 'joli graph';
+	$report = new ReportTrackerAct($SPAN, $group_id, $atid, $start, $end);
+	if ($report->isError()) {
+		echo '<p class="error">'.$report->getErrorMessage().'</p>';
+		return false;
+	}
+	$rdates = $report->getRawDates();
+	if (!$rdates) {
+		return false;
+	}
+	$ydata[] =& $report->getAverageTimeData();
+	$label[] = _('Avg Time Open (in days)');
+	$ydata[] =& $report->getOpenCountData();
+	$label[] = _('Total Opened');
+	$ydata[] =& $report->getStillOpenCountData();
+	$label[] = _('Total Still Open');
+	$chartid = 'projecttrackergraph_'.$group_id;
+	$yMax = 0;
+	echo '<script type="text/javascript">//<![CDATA['."\n";
+	echo 'var values = new Array();';
+	echo 'var ticks = new Array();';
+	echo 'var labels = new Array();';
+	echo 'var series = new Array();';
+	for ($z = 0; $z < count($ydata); $z++) {
+		echo 'values['.$z.'] = new Array();';
+		echo 'labels.push({label:\''.$label[$z].'\'});';
+	}
+	$tickArr = array();
+	switch ($SPAN) {
+		case REPORT_TYPE_MONTHLY : {
+			$formatDate = 'Y/m';
+			break;
+		}
+		case REPORT_TYPE_WEEKLY : {
+			$formatDate = 'Y/W';
+			break;
+		}
+	}
+	for ($j = 0; $j < count($rdates); $j++) {
+		for ($z = 0; $z < count($ydata); $z++) {
+			if (isset($ydata[$z][$j])) {
+				if ($ydata[$z][$j] === false || $ydata[$z][$j] === NULL) {
+					$ydata[$z][$j] = 0;
+				}
+				if ($ydata[$z][$j] > $yMax) {
+					$yMax = $ydata[$z][$j];
+				}
+				echo 'values['.$z.'].push('.$ydata[$z][$j].');';
+			} else {
+				echo 'values['.$z.'].push(0);';
+			}
+		}
+		$tickArr[] = date($formatDate, $rdates[$j]);
+		echo 'ticks.push(\''.$tickArr[$j].'\');';
+	}
+	for ($z = 0; $z < count($ydata); $z++) {
+		echo 'series.push(values['.$z.']);';
+	}
+	echo 'jQuery(document).ready(function(){
+		plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', series, {
+			title : \''.utf8_decode(_('Tracker Activity')).' ( '.strftime('%x',$start).' - '.strftime('%x',$end).') \',
+			axesDefaults: {
+				tickOptions: {
+					angle: -90,
+					fontSize: \'8px\',
+					showGridline: false,
+					showMark: false,
+				},
+				pad: 0,
+			},
+			seriesDefaults: {
+				showMarker: false,
+				lineWidth: 1,
+				fill: true,
+				renderer:jQuery.jqplot.BarRenderer,
+				rendererOptions: {
+					fillToZero: true,
+				},
+			},
+			legend: {
+				show:true, location: \'ne\',
+			},
+			series:
+				labels
+			,
+			axes: {
+				xaxis: {
+					renderer: jQuery.jqplot.CategoryAxisRenderer,
+					ticks: ticks,
+				},
+				yaxis: {
+					max: '.++$yMax.',
+					min: 0,
+					tickOptions: {
+						angle: 0,
+						showMark: true,
+					}
+				},
+			},
+			highlighter: {
+				show: true,
+				sizeAdjust: 2.5,
+			},
+		});
+	});';
+	echo 'jQuery(window).resize(function() {
+		plot'.$chartid.'.replot();
+		});'."\n";
+	echo '//]]></script>';
+	echo '<div id="chart'.$chartid.'"></div>';
 	return true;
 }
 

commit dfc238b49a84498b6aa372d2b85ce8f595637a4e
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 13:28:17 2013 +0200

    jqplot: enable jqplot in tracker reporting

diff --git a/src/www/tracker/reporting/index.php b/src/www/tracker/reporting/index.php
index 11e6b21..241776d 100644
--- a/src/www/tracker/reporting/index.php
+++ b/src/www/tracker/reporting/index.php
@@ -109,6 +109,11 @@ if ($atid) {
 	$h = new ArtifactTypeFactoryHtml($group);
 }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
+
 $h->header(array('title' => _('Tracker Activity Reporting')));
 
 ?>

commit cd41873a8a437246f84242d4bca4afdd331d0438
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 12:06:18 2013 +0200

    Report tracker: remove debug string

diff --git a/src/common/reporting/ReportTrackerAct.class.php b/src/common/reporting/ReportTrackerAct.class.php
index ae2f207..98ffefe 100644
--- a/src/common/reporting/ReportTrackerAct.class.php
+++ b/src/common/reporting/ReportTrackerAct.class.php
@@ -120,7 +120,6 @@ function getAverageTime($atid,$start,$end) {
 }
 
 function getOpenCount($atid,$start,$end) {
-	echo $start.'|'.$end."\n";
 	$res = db_query_params ('SELECT count(*)
 		FROM artifact
 		WHERE

commit 411455f403a404eed0dfe84f89dfd4c3d730eb48
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 11:47:16 2013 +0200

    Report Tracker: fix logic

diff --git a/src/common/reporting/ReportTrackerAct.class.php b/src/common/reporting/ReportTrackerAct.class.php
index 072bd6c..ae2f207 100644
--- a/src/common/reporting/ReportTrackerAct.class.php
+++ b/src/common/reporting/ReportTrackerAct.class.php
@@ -69,10 +69,10 @@ function ReportTrackerAct($span,$group_id,$atid,$start=0,$end=0) {
 				unset($arr[$i]);
 			} else {
 
-				$this->labels[]=date('M d',$arr[$i]).' <-> '.date('M d',($arr[$i-1]-1));
-				$this->avgtime[]=$this->getAverageTime($atid,$arr[$i],($arr[$i-1]-1));
-				$this->opencount[]=$this->getOpenCount($atid,$arr[$i],($arr[$i-1]-1));
-				$this->stillopencount[]=$this->getStillOpenCount($atid,$arr[$i],($arr[$i-1]-1));
+				$this->labels[]=date('M d',($arr[$i-1]-1)).' <-> '.date('M d',$arr[$i]);
+				$this->avgtime[]=$this->getAverageTime($atid,($arr[$i-1]-1),$arr[$i]);
+				$this->opencount[]=$this->getOpenCount($atid,($arr[$i-1]-1),$arr[$i]);
+				$this->stillopencount[]=$this->getStillOpenCount($atid,$arr[$i]);
 
 			}
 		}
@@ -87,10 +87,10 @@ function ReportTrackerAct($span,$group_id,$atid,$start=0,$end=0) {
 				unset($arr[$i]);
 			} else {
 
-				$this->labels[]=date('M d',$arr[$i]).' <-> '.date('M d',($arr[$i-1]-1));
-				$this->avgtime[]=$this->getAverageTime($atid,$arr[$i],($arr[$i-1]-1));
-				$this->opencount[]=$this->getOpenCount($atid,$arr[$i],($arr[$i-1]-1));
-				$this->stillopencount[]=$this->getStillOpenCount($atid,$arr[$i],($arr[$i-1]-1));
+				$this->labels[]=date('M d',($arr[$i-1]-1)).' <-> '.date('M d',$arr[$i]);
+				$this->avgtime[]=$this->getAverageTime($atid,($arr[$i-1]-1),$arr[$i]);
+				$this->opencount[]=$this->getOpenCount($atid,($arr[$i-1]-1),$arr[$i]);
+				$this->stillopencount[]=$this->getStillOpenCount($atid,$arr[$i]);
 
 			}
 		}
@@ -120,6 +120,7 @@ function getAverageTime($atid,$start,$end) {
 }
 
 function getOpenCount($atid,$start,$end) {
+	echo $start.'|'.$end."\n";
 	$res = db_query_params ('SELECT count(*)
 		FROM artifact
 		WHERE
@@ -131,7 +132,7 @@ function getOpenCount($atid,$start,$end) {
 	return db_result($res,0,0);
 }
 
-function getStillOpenCount($atid,$start,$end) {
+function getStillOpenCount($atid,$end) {
 	$res = db_query_params ('SELECT count(*)
 		FROM artifact
 		WHERE

commit 5ed9a1b7d32e8a3b8de53e1b3fdf386e899c6560
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 24 10:59:56 2013 +0200

    Report Tracker: fix setDates

diff --git a/src/common/reporting/ReportTrackerAct.class.php b/src/common/reporting/ReportTrackerAct.class.php
index ab67d4d..072bd6c 100644
--- a/src/common/reporting/ReportTrackerAct.class.php
+++ b/src/common/reporting/ReportTrackerAct.class.php
@@ -66,6 +66,7 @@ function ReportTrackerAct($span,$group_id,$atid,$start=0,$end=0) {
 		for ($i=0; $i<count($arr); $i++) {
 			if ($arr[$i]<$start || $arr[$i]>$end) {
 				//skip this month as it's not in the range
+				unset($arr[$i]);
 			} else {
 
 				$this->labels[]=date('M d',$arr[$i]).' <-> '.date('M d',($arr[$i-1]-1));
@@ -82,7 +83,8 @@ function ReportTrackerAct($span,$group_id,$atid,$start=0,$end=0) {
 
 		for ($i=0; $i<count($arr); $i++) {
 			if ($arr[$i]<$start || $arr[$i]>$end) {
-				//skip this month as it's not in the range
+				//skip this week as it's not in the range
+				unset($arr[$i]);
 			} else {
 
 				$this->labels[]=date('M d',$arr[$i]).' <-> '.date('M d',($arr[$i-1]-1));
@@ -99,6 +101,7 @@ function ReportTrackerAct($span,$group_id,$atid,$start=0,$end=0) {
 	$this->end_date=$end;
 
 	$this->setSpan($span);
+	$arr = array_values($arr);
 	$this->setDates($arr, 1);
 	$this->res = $arr;
 	return true;

commit 0deca794e8ff3b584f4e7c4d70fee75251ea9169
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon May 20 19:00:16 2013 +0200

    jqplot: tracker fix behavior, stick to current

diff --git a/src/www/tracker/reporting/index.php b/src/www/tracker/reporting/index.php
index e62a164..11e6b21 100644
--- a/src/www/tracker/reporting/index.php
+++ b/src/www/tracker/reporting/index.php
@@ -155,8 +155,6 @@ if ($start == $end) {
 	</noscript>
 	<?php
 		}
-	} else {
-		echo '<p class="warning">'._('Missing tracker. Please select one tracker').'</p>';
 	}
 }
 ?>

commit 3946310ee35d6b60d75a1b22b5210babeb61f5bd
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon May 20 18:59:43 2013 +0200

    jqplot: fix error message

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index bfb74bf..e71f243 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -250,7 +250,8 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	}
 	$report = new ReportProjectAct($SPAN, $group_id, $start, $end);
 	if ($report->isError()) {
-		exit_error($report->getErrorMessage());
+		echo '<p class="error">'.$report->getErrorMessage().'</p>';
+		return false;
 	}
 	$rdates = $report->getRawDates();
 	if (!$rdates) {

commit 7e9d99587154f0e585ca4c594762273084029bac
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon May 20 18:58:58 2013 +0200

    Report: fix setDates when result is an array. case: ReportProjectAct

diff --git a/src/common/reporting/Report.class.php b/src/common/reporting/Report.class.php
index 0afb643..332e2d1 100644
--- a/src/common/reporting/Report.class.php
+++ b/src/common/reporting/Report.class.php
@@ -111,7 +111,12 @@ function setData($result,$column) {
 }
 
 function setDates($result,$column) {
-	$arr =& util_result_column_to_array($result,$column);
+	$arr = NULL;
+	if (!is_array($result)) {
+		$arr =& util_result_column_to_array($result,$column);
+	} elseif (is_array($result)) {
+		$arr = $result;
+	}
 	if(isset($this->span) && $this->span == REPORT_TYPE_MONTHLY) {
 		$format = 'M Y';
 	} else {

commit 0f71be117facb4c4a63c4d14793dbdb9979c0198
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon May 20 17:20:30 2013 +0200

    jqplot: fix rebase

diff --git a/src/www/project/stats/index.php b/src/www/project/stats/index.php
index b5a119e..02b0fd8 100644
--- a/src/www/project/stats/index.php
+++ b/src/www/project/stats/index.php
@@ -85,6 +85,7 @@ if ($end && !is_numeric($end)) { $end = false; }
 html_use_jqueryjqplotpluginCanvas();
 html_use_jqueryjqplotpluginhighlighter();
 html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
 
 project_admin_header(array('title'=>_('Project Statistics').'','group'=>$group_id));
 

commit 3eeb1824e364559e7299b1b13dae0eda81869852
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 10 17:32:22 2013 +0200

    jqplot: add support for multiples series

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index a515dff..bfb74bf 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -409,7 +409,6 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 				}
 				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
-			echo 'labels.push({label:\''.$label[0].'\'});';
 			break;
 		}
 		case REPORT_TYPE_WEEKLY : {
@@ -437,7 +436,6 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 				}
 				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
-			echo 'labels.push({label:\''.$label[0].'\'});';
 			break;
 		}
 	}

commit 06b0a17ce20af6b1f45f3ee14912726c59646c96
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 10 17:08:43 2013 +0200

    jqplot: support labels, fix plugin handling

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index bfb74bf..a515dff 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -409,6 +409,7 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 				}
 				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
+			echo 'labels.push({label:\''.$label[0].'\'});';
 			break;
 		}
 		case REPORT_TYPE_WEEKLY : {
@@ -436,6 +437,7 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 				}
 				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
+			echo 'labels.push({label:\''.$label[0].'\'});';
 			break;
 		}
 	}

commit 040b44a71f36c76ceb02e4d0912fe03e82d68fa9
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Thu May 9 19:45:19 2013 +0200

    jqplot: add min value in scm stats

diff --git a/src/www/scm/include/scm_utils.php b/src/www/scm/include/scm_utils.php
index 3323c1a..c835366 100644
--- a/src/www/scm/include/scm_utils.php
+++ b/src/www/scm/include/scm_utils.php
@@ -158,6 +158,7 @@ function commitstime_graph($group_id, $chartid) {
 					},
 					yaxis: {
 						max: '.++$yMax.',
+						min: 0,
 						tickOptions: {
 							angle: 0,
 							showMark: true,

commit 8c4f50bf598319ea0b7e31d0838a1a297e5f8309
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon May 6 21:20:48 2013 +0200

    jqplot: support scm stats, initiale project stats

diff --git a/src/www/project/stats/index.php b/src/www/project/stats/index.php
index 02b0fd8..b5a119e 100644
--- a/src/www/project/stats/index.php
+++ b/src/www/project/stats/index.php
@@ -85,7 +85,6 @@ if ($end && !is_numeric($end)) { $end = false; }
 html_use_jqueryjqplotpluginCanvas();
 html_use_jqueryjqplotpluginhighlighter();
 html_use_jqueryjqplotplugindateAxisRenderer();
-html_use_jqueryjqplotpluginBar();
 
 project_admin_header(array('title'=>_('Project Statistics').'','group'=>$group_id));
 
diff --git a/src/www/scm/include/scm_utils.php b/src/www/scm/include/scm_utils.php
index c835366..3323c1a 100644
--- a/src/www/scm/include/scm_utils.php
+++ b/src/www/scm/include/scm_utils.php
@@ -158,7 +158,6 @@ function commitstime_graph($group_id, $chartid) {
 					},
 					yaxis: {
 						max: '.++$yMax.',
-						min: 0,
 						tickOptions: {
 							angle: 0,
 							showMark: true,

commit 256b9c50708fa9460fd51f9d06d2d807a5de6e6c
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 10 18:56:28 2013 +0200

    jqplot: start implement tracker report graph

diff --git a/src/common/reporting/report_utils.php b/src/common/reporting/report_utils.php
index e1ce264..c6f9966 100644
--- a/src/common/reporting/report_utils.php
+++ b/src/common/reporting/report_utils.php
@@ -5,7 +5,7 @@
  * Copyright 2003-2004, Tim Perdue/GForge, LLC
  * Copyright 2009, Roland Mas
  * Copyright (C) 2010 Alain Peyrat - Alcatel-Lucent
- * Copyright (C) 2010 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -245,6 +245,26 @@ function report_package_box($group_id, $name='dev_id', $selected='') {
 	return html_build_select_box($res, $name, $selected, false);
 }
 
+function trackeract_graph($group_id, $area, $SPAN, $start, $end, $atid) {
+	if (!strlen($area)) {
+		echo '<p class="information">'._('No selected area.').'</p>';
+		return true;
+	}
+	$report=new ReportTrackerAct($SPAN, $group_id, $atid, $start, $end);
+	var_dump($report);
+	echo 'joli graph';
+	return true;
+}
+
+function trackerpie_graph($group_id, $area, $SPAN, $start, $end, $atid) {
+	if (!strlen($area)) {
+		echo '<p class="information">'._('No selected area.').'</p>';
+		return true;
+	}
+	echo 'joli graph';
+	return true;
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/tracker/reporting/index.php b/src/www/tracker/reporting/index.php
index 86e0f58..e62a164 100644
--- a/src/www/tracker/reporting/index.php
+++ b/src/www/tracker/reporting/index.php
@@ -5,6 +5,7 @@
  * Copyright 2003, Tim Perdue, tim at gforge.org
  * Copyright 2004 (c) GForge LLC
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -27,6 +28,7 @@ require_once '../../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportTrackerAct.class.php';
 require_once $gfcommon.'tracker/include/ArtifactTypeHtml.class.php';
 require_once $gfcommon.'tracker/include/ArtifactTypeFactoryHtml.class.php';
 
@@ -129,19 +131,33 @@ $h->header(array('title' => _('Tracker Activity Reporting')));
 </tr>
 </table>
 </form>
-<p class="align-center">
-<?php if ($atid) {
+<?php
+if ($start == $end) {
+	echo '<p class="warning">'._('Cannot proceed the request. Start date is equal to end date.').'</p>';
+} else {
+	if ($atid) {
 		if (!$area || $area == 'activity') {
+			if (!trackeract_graph($group_id, 'activity', $SPAN, $start, $end, $atid)) {
+				echo '<p class="error">'._('Error during graphic computation.');
+			}
 	?>
+	<noscript>
 	<img src="trackeract_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&group_id=$group_id&atid=$atid"; ?>" width="640" height="480" alt="" />
+	</noscript>
 	<?php
 		} else {
+			if (!trackerpie_graph($group_id, $area, $SPAN, $start, $end, $atid)) {
+				echo '<p class="error">'._('Error during graphic computation.');
+			}
 	?>
+	<noscript>
 	<img src="trackerpie_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&group_id=$group_id&atid=$atid&area=$area"; ?>" width="640" height="480" alt="" />
+	</noscript>
 	<?php
-
 		}
-
+	} else {
+		echo '<p class="warning">'._('Missing tracker. Please select one tracker').'</p>';
+	}
 }
 ?>
 </p>

commit 03ee3a2a8eaf883021f2f18a33f302ed25e9ad47
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 10 18:55:48 2013 +0200

    jqplot: same options for any graph

diff --git a/src/common/docman/views/reporting.php b/src/common/docman/views/reporting.php
index b5f31df..33c82e3 100644
--- a/src/common/docman/views/reporting.php
+++ b/src/common/docman/views/reporting.php
@@ -74,6 +74,7 @@ if (!$end) {
 if ($end < $start) list($start, $end) = array($end, $start);
 
 html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
 echo $HTML->getJavascripts();
 echo $HTML->getStylesheets();
 
@@ -131,6 +132,14 @@ if (count($data) == 0) {
 	echo 'var plot1;';
 	echo 'jQuery(document).ready(function(){
 			plot1 = jQuery.jqplot (\'chart1\', [values], {
+					axesDefaults: {
+						tickOptions: {
+							angle: -90,
+							fontSize: \'8px\',
+							showGridline: false,
+							showMark: false,
+						},
+					},
 					axes: {
 						xaxis: {
 							label: "'._('Month').'",
@@ -141,8 +150,16 @@ if (count($data) == 0) {
 						yaxis: {
 							label: "'._('Downloads').'",
 							padMin: 0,
+							tickOptions: {
+								angle: 0,
+								showMark: true,
+							}
 						}
-					}
+					},
+					highlighter: {
+						show: true,
+						sizeAdjust: 2.5,
+					},
 				});
 		});';
 	echo 'jQuery(window).resize(function() {
diff --git a/src/www/frs/reporting/downloads.php b/src/www/frs/reporting/downloads.php
index 889dace..007d00d 100644
--- a/src/www/frs/reporting/downloads.php
+++ b/src/www/frs/reporting/downloads.php
@@ -83,6 +83,7 @@ if (!$end) {
 if ($end < $start) list($start, $end) = array($end, $start);
 
 html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
 
 frs_header(array('title' => _('File Release Reporting'),
 		 'group' => $group_id,
@@ -147,6 +148,14 @@ if (count($data) == 0) {
 	echo 'var plot1;';
 	echo 'jQuery(document).ready(function(){
 			plot1 = jQuery.jqplot (\'chart1\', [values], {
+					axesDefaults: {
+						tickOptions: {
+							angle: -90,
+							fontSize: \'8px\',
+							showGridline: false,
+							showMark: false,
+						},
+					},
 					legend: {
 						show: true,
 						placement: \'insideGrid\',
@@ -165,8 +174,16 @@ if (count($data) == 0) {
 						yaxis: {
 							label: "'._('Downloads').'",
 							padMin: 0,
+							tickOptions: {
+								angle: 0,
+								showMark: true,
+							}
 						}
-					}
+					},
+					highlighter: {
+						show: true,
+						sizeAdjust: 2.5,
+					},
 				});
 		});';
 	echo 'jQuery(window).resize(function() {

commit 91666e96c66a54d32b962ea24c6d0024b6c9fd9f
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 10 17:32:22 2013 +0200

    jqplot: add support for multiples series

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index 07c89a9..bfb74bf 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -288,40 +288,40 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 
 	switch ($area) {
 		case 'docman': {
-			$ydata =& $report->getDocs();
+			$ydata[] =& $report->getDocs();
 			$areaname = _('Docs');
 			$label[] = _('Documents');
 			break;
 		}
 		case 'downloads': {
-			$ydata =& $report->getDownloads();
+			$ydata[] =& $report->getDownloads();
 			$areaname = _('Downloads');
 			$label[] = _('Downloads');
 			break;
 		}
 		case 'forum' : {
-			$ydata =& $report->getForum();
+			$ydata[] =& $report->getForum();
 			$areaname = _('Forums');
 			$label[] = _('Forums');
 			break;
 		}
 		case 'pageviews': {
-			$ydata =& $report->getPageViews();
+			$ydata[] =& $report->getPageViews();
 			$areaname = _('Page views');
 			$label[] = _('Page views');
 			break;
 		}
 		case 'taskman': {
-			$ydata =& $report->getTaskOpened();
-			$ydata2 =& $report->getTaskClosed();
+			$ydata[] =& $report->getTaskOpened();
+			$ydata[] =& $report->getTaskClosed();
 			$areaname = _('Tasks');
 			$label[] = _('Task open');
 			$label[] = _('Task close');
 			break;
 		}
 		case 'tracker': {
-			$ydata =& $report->getTrackerOpened();
-			$ydata2 =& $report->getTrackerClosed();
+			$ydata[] =& $report->getTrackerOpened();
+			$ydata[] =& $report->getTrackerClosed();
 			$areaname = _('Trackers');
 			$label[] = _('Tracker items opened');
 			$label[] = _('Tracker items closed');
@@ -365,10 +365,10 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 			}
 
 			// Now, stores the values in the ydata array for the graph.
-			$ydata = array();
+			$ydata[] = array();
 			$i = 0;
 			foreach ($rdates as $d) {
-				$ydata[$i++] = isset($sum[$d]) ? $sum[$d] : 0;
+				$ydata[0][$i++] = isset($sum[$d]) ? $sum[$d] : 0;
 			}
 			break;
 		}
@@ -380,29 +380,35 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	echo 'var values = new Array();';
 	echo 'var ticks = new Array();';
 	echo 'var labels = new Array();';
+	echo 'var series = new Array();';
+	for ($z = 0; $z < count($ydata); $z++) {
+		echo 'values['.$z.'] = new Array();';
+		echo 'labels.push({label:\''.$label[$z].'\'});';
+	}
 	switch ($SPAN) {
 		case REPORT_TYPE_DAILY :
 		case REPORT_TYPE_MONTHLY : {
 			for ($j = 0; $j < count($timeStampArr); $j++) {
-				if (in_array($timeStampArr[$j], $rdates)) {
-					$thekey = array_search($timeStampArr[$j], $rdates);
-					if (isset($ydata[$thekey])) {
-						if ($ydata[$thekey] === false) {
-							$ydata[$thekey] = 0;
-						}
-						if ($ydata[$thekey] > $yMax) {
-							$yMax = $ydata[$thekey];
+				for ($z = 0; $z < count($ydata); $z++) {
+					if (in_array($timeStampArr[$j], $rdates)) {
+						$thekey = array_search($timeStampArr[$j], $rdates);
+						if (isset($ydata[$z][$thekey])) {
+							if ($ydata[$z][$thekey] === false) {
+								$ydata[$z][$thekey] = 0;
+							}
+							if ($ydata[$z][$thekey] > $yMax) {
+								$yMax = $ydata[$z][$thekey];
+							}
+							echo 'values['.$z.'].push('.$ydata[$z][$thekey].');';
+						} else {
+							echo 'values['.$z.'].push(0);';
 						}
-						echo 'values.push('.$ydata[$thekey].');';
 					} else {
-						echo 'values.push(0);';
+						echo 'values['.$z.'].push(0);';
 					}
-				} else {
-					echo 'values.push(0);';
 				}
 				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
-			echo 'labels.push({label:\''.$label[0].'\'});';
 			break;
 		}
 		case REPORT_TYPE_WEEKLY : {
@@ -410,32 +416,38 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 				$wrdates[$j] = date($formatDate, $rdates[$j]);
 			}
 			for ($j = 0; $j < count($tickArr); $j++) {
-				if (in_array($tickArr[$j], $wrdates)) {
-					$thekey = array_search($tickArr[$j], $wrdates);
-					if (isset($ydata[$thekey])) {
-						if ($ydata[$thekey] === false) {
-							$ydata[$thekey] = 0;
-						}
-						if ($ydata[$thekey] > $yMax) {
-							$yMax = $ydata[$thekey];
+				for ($z = 0; $z < count($ydata); $z++) {
+					if (in_array($tickArr[$j], $wrdates)) {
+						$thekey = array_search($tickArr[$j], $wrdates);
+						if (isset($ydata[$z][$thekey])) {
+							if ($ydata[$z][$thekey] === false) {
+								$ydata[$z][$thekey] = 0;
+							}
+							if ($ydata[$z][$thekey] > $yMax) {
+								$yMax = $ydata[$z][$thekey];
+							}
+							echo 'values['.$z.'].push('.$ydata[$z][$thekey].');';
+						} else {
+							echo 'values['.$z.'].push(0);';
 						}
-						echo 'values.push('.$ydata[$thekey].');';
+					} else {
+						echo 'values['.$z.'].push(0);';
 					}
-				} else {
-					echo 'values.push(0);';
 				}
 				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
-			echo 'labels.push({label:\''.$label[0].'\'});';
 			break;
 		}
 	}
+	for ($z = 0; $z < count($ydata); $z++) {
+		echo 'series.push(values['.$z.']);';
+	}
 	echo 'jQuery(document).ready(function(){
-			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
+			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', series, {
 				title : \''.utf8_decode($areaname).' ( '.strftime('%x',$start).' - '.strftime('%x',$end).') \',
 				axesDefaults: {
 					tickOptions: {
-						angle: -30,
+						angle: -90,
 						fontSize: \'8px\',
 						showGridline: false,
 						showMark: false,

commit 8b20750e417986388a17b6193f1db71bd25e4cb9
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 10 17:08:43 2013 +0200

    jqplot: support labels, fix plugin handling

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index 0613041..07c89a9 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -244,6 +244,10 @@ function permissions_blurb() {
  * @return	string	the JS code
  */
 function projectact_graph($group_id, $area, $SPAN, $start, $end) {
+	if (!strlen($area)) {
+		echo '<p class="information">'._('No selected area.').'</p>';
+		return true;
+	}
 	$report = new ReportProjectAct($SPAN, $group_id, $start, $end);
 	if ($report->isError()) {
 		exit_error($report->getErrorMessage());
@@ -285,27 +289,61 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	switch ($area) {
 		case 'docman': {
 			$ydata =& $report->getDocs();
+			$areaname = _('Docs');
+			$label[] = _('Documents');
+			break;
+		}
+		case 'downloads': {
+			$ydata =& $report->getDownloads();
+			$areaname = _('Downloads');
+			$label[] = _('Downloads');
+			break;
+		}
+		case 'forum' : {
+			$ydata =& $report->getForum();
+			$areaname = _('Forums');
+			$label[] = _('Forums');
+			break;
+		}
+		case 'pageviews': {
+			$ydata =& $report->getPageViews();
+			$areaname = _('Page views');
+			$label[] = _('Page views');
+			break;
+		}
+		case 'taskman': {
+			$ydata =& $report->getTaskOpened();
+			$ydata2 =& $report->getTaskClosed();
+			$areaname = _('Tasks');
+			$label[] = _('Task open');
+			$label[] = _('Task close');
 			break;
 		}
 		case 'tracker': {
 			$ydata =& $report->getTrackerOpened();
 			$ydata2 =& $report->getTrackerClosed();
+			$areaname = _('Trackers');
+			$label[] = _('Tracker items opened');
+			$label[] = _('Tracker items closed');
 			break;
 		}
 		default: {
 			$results = array();
 			$ids = array();
 			$texts = array();
+			$show[] = $area;
 
 			$hookParams['group'] = $group_id;
 			$hookParams['results'] = &$results;
-			$hookParams['show'] = array();
+			$hookParams['show'] = &$show;
 			$hookParams['begin'] = $start;
 			$hookParams['end'] = $end;
 			$hookParams['ids'] = &$ids;
 			$hookParams['texts'] = &$texts;
 			plugin_hook("activity", $hookParams);
 
+			$areaname = $texts[0];
+			$label[] = $texts[0];
 			$sum = array();
 			foreach ($results as $arr) {
 				$dd = date($formatDate, $arr['activity_date']);
@@ -341,21 +379,30 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	echo '<script type="text/javascript">//<![CDATA['."\n";
 	echo 'var values = new Array();';
 	echo 'var ticks = new Array();';
+	echo 'var labels = new Array();';
 	switch ($SPAN) {
 		case REPORT_TYPE_DAILY :
 		case REPORT_TYPE_MONTHLY : {
 			for ($j = 0; $j < count($timeStampArr); $j++) {
 				if (in_array($timeStampArr[$j], $rdates)) {
 					$thekey = array_search($timeStampArr[$j], $rdates);
-					if ($ydata[$thekey] > $yMax) {
-						$yMax = $ydata[$thekey];
+					if (isset($ydata[$thekey])) {
+						if ($ydata[$thekey] === false) {
+							$ydata[$thekey] = 0;
+						}
+						if ($ydata[$thekey] > $yMax) {
+							$yMax = $ydata[$thekey];
+						}
+						echo 'values.push('.$ydata[$thekey].');';
+					} else {
+						echo 'values.push(0);';
 					}
-					echo 'values.push('.$ydata[$thekey].');';
 				} else {
 					echo 'values.push(0);';
 				}
 				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
+			echo 'labels.push({label:\''.$label[0].'\'});';
 			break;
 		}
 		case REPORT_TYPE_WEEKLY : {
@@ -365,23 +412,30 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 			for ($j = 0; $j < count($tickArr); $j++) {
 				if (in_array($tickArr[$j], $wrdates)) {
 					$thekey = array_search($tickArr[$j], $wrdates);
-					if ($ydata[$thekey] > $yMax) {
-						$yMax = $ydata[$thekey];
+					if (isset($ydata[$thekey])) {
+						if ($ydata[$thekey] === false) {
+							$ydata[$thekey] = 0;
+						}
+						if ($ydata[$thekey] > $yMax) {
+							$yMax = $ydata[$thekey];
+						}
+						echo 'values.push('.$ydata[$thekey].');';
 					}
-					echo 'values.push('.$ydata[$thekey].');';
 				} else {
 					echo 'values.push(0);';
 				}
 				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
+			echo 'labels.push({label:\''.$label[0].'\'});';
 			break;
 		}
 	}
 	echo 'jQuery(document).ready(function(){
-			var plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
+			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
+				title : \''.utf8_decode($areaname).' ( '.strftime('%x',$start).' - '.strftime('%x',$end).') \',
 				axesDefaults: {
 					tickOptions: {
-						angle: 30,
+						angle: -30,
 						fontSize: \'8px\',
 						showGridline: false,
 						showMark: false,
@@ -398,8 +452,11 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 					},
 				},
 				legend: {
-					show: false,
+					show:true, location: \'ne\',
 				},
+				series:
+					labels
+				,
 				axes: {
 					xaxis: {
 						renderer: jQuery.jqplot.CategoryAxisRenderer,

commit 17875240c62ea91cb9490363bc290dca2f6de7ea
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Fri May 10 13:10:28 2013 +0200

    jqplot: fix project stats for plugin

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index b354365..0613041 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -261,15 +261,15 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 			$looptime += $interval;
 			$i++;
 		}
-		$formatDate = _('Y/m/d');
+		$formatDate = 'Y/m/d';
 	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
 		$interval = REPORT_WEEK_SPAN;
 		$timeStampArr = $report->getWeekStartArr();
-		$formatDate = _('W');
+		$formatDate = 'Y/W';
 	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
 		$interval = REPORT_MONTH_SPAN;
 		$timeStampArr = $report->getMonthStartArr();
-		$formatDate = _('Y/m');
+		$formatDate = 'Y/m';
 	}
 	
 	for ($j = 0; $j < count($timeStampArr); $j++) {
@@ -307,18 +307,29 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 			plugin_hook("activity", $hookParams);
 
 			$sum = array();
-			$starting_date = $start;
 			foreach ($results as $arr) {
-				$d = $arr['activity_date'];
-				$col = intval(($d - $starting_date)/$interval);
-				$col_date = $starting_date+$col*$interval;
-				@$sum[$col_date]++;
+				$dd = date($formatDate, $arr['activity_date']);
+				switch ($SPAN) {
+					case REPORT_TYPE_MONTHLY : {
+						$d = mktime(0, 0, 0, substr($dd, 5, 2) , 1, substr($dd, 0, 4));
+						break;
+					}
+					case REPORT_TYPE_WEEKLY: {
+						$d = strtotime(substr($dd, 0, 4).'-W'.substr($dd, 5, 2));
+						break;
+					}
+					case REPORT_TYPE_DAILY: {
+						$d = mktime(0, 0, 0, substr($dd, 5, 2) , substr($dd, 8, 2), substr($dd, 0, 4));
+						break;
+					}
+				}
+				@$sum[$d]++;
 			}
 
 			// Now, stores the values in the ydata array for the graph.
 			$ydata = array();
 			$i = 0;
-			foreach ($report->getRawDates() as $d) {
+			foreach ($rdates as $d) {
 				$ydata[$i++] = isset($sum[$d]) ? $sum[$d] : 0;
 			}
 			break;

commit 3d93e7a79b55174436f768f32ac32dc4adf09b5f
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Thu May 9 19:46:06 2013 +0200

    jqplot: implement v1 project stats

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index dbb5cc8..b354365 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -249,6 +249,9 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 		exit_error($report->getErrorMessage());
 	}
 	$rdates = $report->getRawDates();
+	if (!$rdates) {
+		return false;
+	}
 	if ($SPAN == REPORT_TYPE_DAILY) {
 		$interval = REPORT_DAY_SPAN;
 		$i = 0;
@@ -258,19 +261,27 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 			$looptime += $interval;
 			$i++;
 		}
+		$formatDate = _('Y/m/d');
 	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
 		$interval = REPORT_WEEK_SPAN;
 		$timeStampArr = $report->getWeekStartArr();
+		$formatDate = _('W');
 	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
 		$interval = REPORT_MONTH_SPAN;
 		$timeStampArr = $report->getMonthStartArr();
+		$formatDate = _('Y/m');
 	}
+	
 	for ($j = 0; $j < count($timeStampArr); $j++) {
 		if ($timeStampArr[$j] < $start || $timeStampArr[$j] >= $end) {
 			unset($timeStampArr[$j]);
 		}
 	}
 	$timeStampArr = array_values($timeStampArr);
+	for ($j = 0; $j < count($timeStampArr); $j++) {
+		$tickArr[] = date($formatDate, $timeStampArr[$j]);
+	}
+
 	switch ($area) {
 		case 'docman': {
 			$ydata =& $report->getDocs();
@@ -307,8 +318,8 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 			// Now, stores the values in the ydata array for the graph.
 			$ydata = array();
 			$i = 0;
-			foreach ($report->getDates() as $d) {
-				$ydata[$i++] = isset($sum[strtotime($d)]) ? $sum[strtotime($d)] : 0;
+			foreach ($report->getRawDates() as $d) {
+				$ydata[$i++] = isset($sum[$d]) ? $sum[$d] : 0;
 			}
 			break;
 		}
@@ -318,28 +329,48 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	$yMax = 0;
 	echo '<script type="text/javascript">//<![CDATA['."\n";
 	echo 'var values = new Array();';
-	echo 'var minDate = new Date(0);';
-	$z = 0;
-	for ($j = 0; $j < count($timeStampArr); $j++) {
-		echo 'var date = new Date(0);';
-		echo 'date.setUTCSeconds('.$timeStampArr[$j].');';
-		if (in_array($timeStampArr[$j], $rdates)) {
-			if ($ydata[$z] > $yMax) {
-				$yMax = $ydata[$z];
+	echo 'var ticks = new Array();';
+	switch ($SPAN) {
+		case REPORT_TYPE_DAILY :
+		case REPORT_TYPE_MONTHLY : {
+			for ($j = 0; $j < count($timeStampArr); $j++) {
+				if (in_array($timeStampArr[$j], $rdates)) {
+					$thekey = array_search($timeStampArr[$j], $rdates);
+					if ($ydata[$thekey] > $yMax) {
+						$yMax = $ydata[$thekey];
+					}
+					echo 'values.push('.$ydata[$thekey].');';
+				} else {
+					echo 'values.push(0);';
+				}
+				echo 'ticks.push(\''.$tickArr[$j].'\');';
 			}
-			echo 'values.push([date, '.$ydata[$z].']);';
-			$z++;
-		} else {
-			echo 'values.push([date, 0]);';
+			break;
+		}
+		case REPORT_TYPE_WEEKLY : {
+			for ($j = 0; $j < count($rdates); $j++) {
+				$wrdates[$j] = date($formatDate, $rdates[$j]);
+			}
+			for ($j = 0; $j < count($tickArr); $j++) {
+				if (in_array($tickArr[$j], $wrdates)) {
+					$thekey = array_search($tickArr[$j], $wrdates);
+					if ($ydata[$thekey] > $yMax) {
+						$yMax = $ydata[$thekey];
+					}
+					echo 'values.push('.$ydata[$thekey].');';
+				} else {
+					echo 'values.push(0);';
+				}
+				echo 'ticks.push(\''.$tickArr[$j].'\');';
+			}
+			break;
 		}
 	}
-	echo 'minDate.setUTCSeconds('.$timeStampArr[0].');';
 	echo 'jQuery(document).ready(function(){
-			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
+			var plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
 				axesDefaults: {
-					tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
 					tickOptions: {
-						angle: -90,
+						angle: 30,
 						fontSize: \'8px\',
 						showGridline: false,
 						showMark: false,
@@ -350,22 +381,22 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 					showMarker: false,
 					lineWidth: 1,
 					fill: true,
+					renderer:jQuery.jqplot.BarRenderer,
+					rendererOptions: {
+						fillToZero: true,
+					},
 				},
 				legend: {
 					show: false,
 				},
 				axes: {
 					xaxis: {
-						renderer: jQuery.jqplot.DateAxisRenderer,
-						min: minDate,';
-	if ($SPAN == REPORT_TYPE_MONTHLY) {
-		echo '				tickInterval: '.$interval.',';
-	}
-	echo '
-
+						renderer: jQuery.jqplot.CategoryAxisRenderer,
+						ticks: ticks,
 					},
 					yaxis: {
 						max: '.++$yMax.',
+						min: 0,
 						tickOptions: {
 							angle: 0,
 							showMark: true,
@@ -383,6 +414,7 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	});'."\n";
 	echo '//]]></script>';
 	echo '<div id="chart'.$chartid.'"></div>';
+	return true;
 }
 
 // Local Variables:
diff --git a/src/www/project/stats/index.php b/src/www/project/stats/index.php
index 62a362d..02b0fd8 100644
--- a/src/www/project/stats/index.php
+++ b/src/www/project/stats/index.php
@@ -85,6 +85,7 @@ if ($end && !is_numeric($end)) { $end = false; }
 html_use_jqueryjqplotpluginCanvas();
 html_use_jqueryjqplotpluginhighlighter();
 html_use_jqueryjqplotplugindateAxisRenderer();
+html_use_jqueryjqplotpluginBar();
 
 project_admin_header(array('title'=>_('Project Statistics').'','group'=>$group_id));
 
@@ -109,7 +110,9 @@ project_admin_header(array('title'=>_('Project Statistics').'','group'=>$group_i
 if ($start == $end) {
 	echo '<p class="warning">'._('Cannot proceed the request. Start date is equal to end date.').'</p>';
 } else {
-	projectact_graph($group_id, $area, $SPAN, $start, $end);
+	if (!projectact_graph($group_id, $area, $SPAN, $start, $end)) {
+		echo '<p class="error">'._('Error during graphic computation.');
+	}
 }
 ?>
 <noscript>

commit 63f9a40464ebaa0694b3f73eafd852455250fd55
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Thu May 9 19:45:19 2013 +0200

    jqplot: add min value in scm stats

diff --git a/src/www/scm/include/scm_utils.php b/src/www/scm/include/scm_utils.php
index 3323c1a..c835366 100644
--- a/src/www/scm/include/scm_utils.php
+++ b/src/www/scm/include/scm_utils.php
@@ -158,6 +158,7 @@ function commitstime_graph($group_id, $chartid) {
 					},
 					yaxis: {
 						max: '.++$yMax.',
+						min: 0,
 						tickOptions: {
 							angle: 0,
 							showMark: true,

commit 471e4d9d918542e54fe95d292d5e1f1272ab8aad
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Wed May 8 20:05:24 2013 +0200

    jqplot: work on project statistics

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index dc91690..dbb5cc8 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -248,13 +248,29 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	if ($report->isError()) {
 		exit_error($report->getErrorMessage());
 	}
+	$rdates = $report->getRawDates();
 	if ($SPAN == REPORT_TYPE_DAILY) {
 		$interval = REPORT_DAY_SPAN;
+		$i = 0;
+		$looptime = $start;
+		while ($looptime < $end) {
+			$timeStampArr[$i] = $looptime;
+			$looptime += $interval;
+			$i++;
+		}
 	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
 		$interval = REPORT_WEEK_SPAN;
+		$timeStampArr = $report->getWeekStartArr();
 	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
 		$interval = REPORT_MONTH_SPAN;
+		$timeStampArr = $report->getMonthStartArr();
+	}
+	for ($j = 0; $j < count($timeStampArr); $j++) {
+		if ($timeStampArr[$j] < $start || $timeStampArr[$j] >= $end) {
+			unset($timeStampArr[$j]);
+		}
 	}
+	$timeStampArr = array_values($timeStampArr);
 	switch ($area) {
 		case 'docman': {
 			$ydata =& $report->getDocs();
@@ -298,27 +314,23 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 		}
 	}
 
-	$i = 0;
-	$timeStampArr[] = $start;
-	while($start < $end) {
-		$start += $interval;
-		$i++;
-		$timeStampArr[$i] = $start;
-		if ($timeStampArr[$i] > $end) {
-			array_pop($timeStampArr);
-		}
-	}
 	$chartid = 'projectgraph_'.$group_id;
 	$yMax = 0;
 	echo '<script type="text/javascript">//<![CDATA['."\n";
 	echo 'var values = new Array();';
-	echo 'var minDate = new Date('.$timeStampArr[0].');';
-	for ($j = 1; $j < count($timeStampArr) -1; $j++) {
+	echo 'var minDate = new Date(0);';
+	$z = 0;
+	for ($j = 0; $j < count($timeStampArr); $j++) {
 		echo 'var date = new Date(0);';
 		echo 'date.setUTCSeconds('.$timeStampArr[$j].');';
-		echo 'values.push([date, '.$ydata[$j].']);';
-		if ($ydata[$j] > $yMax) {
-			$yMax = $ydata[$j];
+		if (in_array($timeStampArr[$j], $rdates)) {
+			if ($ydata[$z] > $yMax) {
+				$yMax = $ydata[$z];
+			}
+			echo 'values.push([date, '.$ydata[$z].']);';
+			$z++;
+		} else {
+			echo 'values.push([date, 0]);';
 		}
 	}
 	echo 'minDate.setUTCSeconds('.$timeStampArr[0].');';
@@ -345,11 +357,12 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 				axes: {
 					xaxis: {
 						renderer: jQuery.jqplot.DateAxisRenderer,
-						min: minDate,
-						tickInterval: \'1 month\',
-						tickOptions: {
-							formatString: \'%Y/%m\'
-						}
+						min: minDate,';
+	if ($SPAN == REPORT_TYPE_MONTHLY) {
+		echo '				tickInterval: '.$interval.',';
+	}
+	echo '
+
 					},
 					yaxis: {
 						max: '.++$yMax.',
@@ -357,7 +370,7 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 							angle: 0,
 							showMark: true,
 						}
-					}
+					},
 				},
 				highlighter: {
 					show: true,

commit 0aff02f150c6c0df841e7234d9f445abbc445762
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Wed May 8 20:03:17 2013 +0200

    project stats: protect when start = end

diff --git a/src/www/project/stats/index.php b/src/www/project/stats/index.php
index 533b869..62a362d 100644
--- a/src/www/project/stats/index.php
+++ b/src/www/project/stats/index.php
@@ -106,7 +106,11 @@ project_admin_header(array('title'=>_('Project Statistics').'','group'=>$group_i
 </form>
 <p>
 <?php
-projectact_graph($group_id, $area, $SPAN, $start, $end);
+if ($start == $end) {
+	echo '<p class="warning">'._('Cannot proceed the request. Start date is equal to end date.').'</p>';
+} else {
+	projectact_graph($group_id, $area, $SPAN, $start, $end);
+}
 ?>
 <noscript>
 <img src="/reporting/projectact_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&g_id=$group_id&area=$area"; ?>" width="640" height="480" alt="stats graph" />

commit 801e5d60ff032787fd6ac8156061429ca4a8e536
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Wed May 8 20:02:44 2013 +0200

    report class: getRawDates return epoch

diff --git a/src/common/reporting/Report.class.php b/src/common/reporting/Report.class.php
index 8a9907a..0afb643 100644
--- a/src/common/reporting/Report.class.php
+++ b/src/common/reporting/Report.class.php
@@ -4,6 +4,7 @@
  *
  * Copyright 2003-2004, Tim Perdue/GForge, LLC
  * Copyright 2009, Roland Mas
+ * Copyright 2013, Franck Villaume - TrivialDev
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -46,6 +47,7 @@ var $span_name=array(1=>'Daily',2=>'Weekly',3=>'Monthly',4=>'OverAll');
 var $graph_interval=array(1=>7,2=>1,3=>1,4=>1);
 var $max_weeks = 104;
 var $max_month = 24;
+var $rawdates;
 
 function Report() {
 	$this->Error();
@@ -118,6 +120,7 @@ function setDates($result,$column) {
 
 	for ($i=0; $i<count($arr); $i++) {
 		$this->labels[$i] = date($format,$arr[$i]);
+		$this->rawdates[$i] = $arr[$i];
 	}
 }
 
@@ -133,6 +136,10 @@ function &getDates() {
 	return $this->labels;
 }
 
+function &getRawDates() {
+	return $this->rawdates;
+}
+
 function getStartDate() {
 	return $this->start_date;
 }

commit d058c513025bf1e558273a5e4f62bff0b3fc7941
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon May 6 23:20:19 2013 +0200

    jqplot: improve project stats

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index 2d45dab..dc91690 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -248,9 +248,21 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 	if ($report->isError()) {
 		exit_error($report->getErrorMessage());
 	}
+	if ($SPAN == REPORT_TYPE_DAILY) {
+		$interval = REPORT_DAY_SPAN;
+	} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
+		$interval = REPORT_WEEK_SPAN;
+	} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
+		$interval = REPORT_MONTH_SPAN;
+	}
 	switch ($area) {
 		case 'docman': {
-			$ydata  =& $report->getDocs();
+			$ydata =& $report->getDocs();
+			break;
+		}
+		case 'tracker': {
+			$ydata =& $report->getTrackerOpened();
+			$ydata2 =& $report->getTrackerClosed();
 			break;
 		}
 		default: {
@@ -266,14 +278,6 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 			$hookParams['ids'] = &$ids;
 			$hookParams['texts'] = &$texts;
 			plugin_hook("activity", $hookParams);
-			
-			if ($SPAN == REPORT_TYPE_DAILY) {
-				$interval = REPORT_DAY_SPAN;
-			} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
-				$interval = REPORT_WEEK_SPAN;
-			} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
-				$interval = REPORT_MONTH_SPAN;
-			}
 
 			$sum = array();
 			$starting_date = $start;
@@ -293,8 +297,79 @@ function projectact_graph($group_id, $area, $SPAN, $start, $end) {
 			break;
 		}
 	}
-	var_dump($ydata);
-	echo 'joli graph';
+
+	$i = 0;
+	$timeStampArr[] = $start;
+	while($start < $end) {
+		$start += $interval;
+		$i++;
+		$timeStampArr[$i] = $start;
+		if ($timeStampArr[$i] > $end) {
+			array_pop($timeStampArr);
+		}
+	}
+	$chartid = 'projectgraph_'.$group_id;
+	$yMax = 0;
+	echo '<script type="text/javascript">//<![CDATA['."\n";
+	echo 'var values = new Array();';
+	echo 'var minDate = new Date('.$timeStampArr[0].');';
+	for ($j = 1; $j < count($timeStampArr) -1; $j++) {
+		echo 'var date = new Date(0);';
+		echo 'date.setUTCSeconds('.$timeStampArr[$j].');';
+		echo 'values.push([date, '.$ydata[$j].']);';
+		if ($ydata[$j] > $yMax) {
+			$yMax = $ydata[$j];
+		}
+	}
+	echo 'minDate.setUTCSeconds('.$timeStampArr[0].');';
+	echo 'jQuery(document).ready(function(){
+			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
+				axesDefaults: {
+					tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
+					tickOptions: {
+						angle: -90,
+						fontSize: \'8px\',
+						showGridline: false,
+						showMark: false,
+					},
+					pad: 0,
+				},
+				seriesDefaults: {
+					showMarker: false,
+					lineWidth: 1,
+					fill: true,
+				},
+				legend: {
+					show: false,
+				},
+				axes: {
+					xaxis: {
+						renderer: jQuery.jqplot.DateAxisRenderer,
+						min: minDate,
+						tickInterval: \'1 month\',
+						tickOptions: {
+							formatString: \'%Y/%m\'
+						}
+					},
+					yaxis: {
+						max: '.++$yMax.',
+						tickOptions: {
+							angle: 0,
+							showMark: true,
+						}
+					}
+				},
+				highlighter: {
+					show: true,
+					sizeAdjust: 2.5,
+				},
+			});
+		});';
+	echo 'jQuery(window).resize(function() {
+		plot'.$chartid.'.replot();
+	});'."\n";
+	echo '//]]></script>';
+	echo '<div id="chart'.$chartid.'"></div>';
 }
 
 // Local Variables:

commit 6cee093606b1e385fba5878bd82f67b8c5451693
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Mon May 6 21:20:48 2013 +0200

    jqplot: support scm stats, initiale project stats

diff --git a/src/www/project/admin/project_admin_utils.php b/src/www/project/admin/project_admin_utils.php
index 90af1bc..2d45dab 100644
--- a/src/www/project/admin/project_admin_utils.php
+++ b/src/www/project/admin/project_admin_utils.php
@@ -6,6 +6,7 @@
  * Copyright 2002-2004 (c) GForge Team
  * Copyright 2011, Franck Villaume - Capgemini
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2013, Franck Villaume - TrivialDev
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -232,6 +233,70 @@ function permissions_blurb() {
 	return _('<strong>NOTE:</strong><dl><dt><strong>Project Admins (bold)</strong></dt><dd>can access this page and other project administration pages</dd><dt><strong>Release Technicians</strong></dt><dd>can make the file releases (any project admin also a release technician)</dd><dt><strong>Tool Technicians (T)</strong></dt><dd>can be assigned Bugs/Tasks/Patches</dd><dt><strong>Tool Admins (A)</strong></dt><dd>can make changes to Bugs/Tasks/Patches as well as use the /toolname/admin/ pages</dd><dt><strong>Tool No Permission (N/A)</strong></dt><dd>Developer doesn\'t have specific permission (currently equivalent to \'-\')</dd><dt><strong>Moderators</strong> (forums)</dt><dd>can delete messages from the project forums</dd><dt><strong>Editors</strong> (doc. manager)</dt><dd>can update/edit/remove documentation from the project.</dd></dl>');
 }
 
+/**
+ * projectact_graph - draw jqplot report stats
+ *
+ * @param	int	group_id, the project id
+ * @param	string	area, the stats zone (documents, trackers, ...)
+ * @param	int	SPAN, is it a daily, weekly, monthly report ?
+ * @param	int	start, date
+ * @param	int	end, date
+ * @return	string	the JS code
+ */
+function projectact_graph($group_id, $area, $SPAN, $start, $end) {
+	$report = new ReportProjectAct($SPAN, $group_id, $start, $end);
+	if ($report->isError()) {
+		exit_error($report->getErrorMessage());
+	}
+	switch ($area) {
+		case 'docman': {
+			$ydata  =& $report->getDocs();
+			break;
+		}
+		default: {
+			$results = array();
+			$ids = array();
+			$texts = array();
+
+			$hookParams['group'] = $group_id;
+			$hookParams['results'] = &$results;
+			$hookParams['show'] = array();
+			$hookParams['begin'] = $start;
+			$hookParams['end'] = $end;
+			$hookParams['ids'] = &$ids;
+			$hookParams['texts'] = &$texts;
+			plugin_hook("activity", $hookParams);
+			
+			if ($SPAN == REPORT_TYPE_DAILY) {
+				$interval = REPORT_DAY_SPAN;
+			} elseif ($SPAN == REPORT_TYPE_WEEKLY) {
+				$interval = REPORT_WEEK_SPAN;
+			} elseif ($SPAN == REPORT_TYPE_MONTHLY) {
+				$interval = REPORT_MONTH_SPAN;
+			}
+
+			$sum = array();
+			$starting_date = $start;
+			foreach ($results as $arr) {
+				$d = $arr['activity_date'];
+				$col = intval(($d - $starting_date)/$interval);
+				$col_date = $starting_date+$col*$interval;
+				@$sum[$col_date]++;
+			}
+
+			// Now, stores the values in the ydata array for the graph.
+			$ydata = array();
+			$i = 0;
+			foreach ($report->getDates() as $d) {
+				$ydata[$i++] = isset($sum[strtotime($d)]) ? $sum[strtotime($d)] : 0;
+			}
+			break;
+		}
+	}
+	var_dump($ydata);
+	echo 'joli graph';
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/project/stats/index.php b/src/www/project/stats/index.php
index 3af9b17..533b869 100644
--- a/src/www/project/stats/index.php
+++ b/src/www/project/stats/index.php
@@ -5,7 +5,7 @@
  * Copyright 2003 GForge, LLC
  * Copyright 2010 (c) Franck Villaume - Capgemini
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
- * Copyright 2012, Franck Villaume - TrivialDev
+ * Copyright 2012-2013, Franck Villaume - TrivialDev
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -28,8 +28,10 @@ require_once '../../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfcommon.'reporting/report_utils.php';
 require_once $gfcommon.'reporting/Report.class.php';
+require_once $gfcommon.'reporting/ReportProjectAct.class.php';
 require_once $gfwww.'project/admin/project_admin_utils.php';
 
+
 $group_id = getIntFromRequest('group_id');
 if ( !$group_id ) {
 	exit_no_group();
@@ -80,6 +82,10 @@ if ($SPAN && !is_numeric($SPAN)) { $SPAN = 1; }
 if ($start && !is_numeric($start)) { $start = false; }
 if ($end && !is_numeric($end)) { $end = false; }
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+
 project_admin_header(array('title'=>_('Project Statistics').'','group'=>$group_id));
 
 //
@@ -99,7 +105,12 @@ project_admin_header(array('title'=>_('Project Statistics').'','group'=>$group_i
 </tr></table>
 </form>
 <p>
+<?php
+projectact_graph($group_id, $area, $SPAN, $start, $end);
+?>
+<noscript>
 <img src="/reporting/projectact_graph.php?<?php echo "SPAN=$SPAN&start=$start&end=$end&g_id=$group_id&area=$area"; ?>" width="640" height="480" alt="stats graph" />
+</noscript>
 </p>
 </div>
 <?php
diff --git a/src/www/scm/include/scm_utils.php b/src/www/scm/include/scm_utils.php
index 6322988..3323c1a 100644
--- a/src/www/scm/include/scm_utils.php
+++ b/src/www/scm/include/scm_utils.php
@@ -5,7 +5,7 @@
  * Copyright 2004-2005 (c) GForge LLC, Tim Perdue
  * Copyright 2010 (c), Franck Villaume - Capgemini
  * Copyright (C) 2010-2011 Alain Peyrat - Alcatel-Lucent
- * Copyright 2012, Franck Villaume - TrivialDev
+ * Copyright 2012-2013, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -73,6 +73,167 @@ function scm_footer() {
 	site_project_footer(array());
 }
 
+function commitstime_graph($group_id, $chartid) {
+	$g = group_get_object($group_id);
+	$end = time();
+	$start = $g->getStartDate();
+	$monthsArr[] = date('Ym', $start);
+	$timeStampArr[] = mktime(0, 0, 0, substr($monthsArr[0], 4, 2) , 1, substr($monthsArr[0], 0, 4));
+	$i = 0;
+	while($start < $end) {
+		$start = strtotime(date('Y-m-d', $start).' +1 month');
+		$i++;
+		$monthsArr[$i] = date('Ym', $start);
+		$timeStampArr[$i] = mktime(0, 0, 0, substr($monthsArr[$i], 4, 2) , 1, substr($monthsArr[$i], 0, 4));
+		if ($monthsArr[$i] == date('Ym', strtotime(date('Y-m-d', $end).' +1 month'))) {
+			array_pop($monthsArr);
+			array_pop($timeStampArr);
+			$i--;
+		}
+	}
+	$res = db_query_params ('SELECT month, sum(commits) AS count
+				FROM stats_cvs_group
+				WHERE group_id = $1
+				GROUP BY month ORDER BY month ASC',
+				array($group_id));
+
+	if (db_error()) {
+		exit_error(db_error(),'scm');
+	}
+
+	echo '<script type="text/javascript">//<![CDATA['."\n";
+	echo 'var values = new Array();';
+
+	$data = array();
+	while ($row = db_fetch_array($res)) {
+		$data[$row[0]] = $row[1];
+	}
+
+	$yMax = 0;
+	for ($j = 0; $j < count($monthsArr); $j++) {
+		echo 'var date = new Date(0);';
+		echo 'date.setUTCSeconds('.$timeStampArr[$j].');';
+		$indexkey = array_key_exists($monthsArr[$j], $data);
+		if ($indexkey !== false) {
+			echo 'var datevalues = '.$data[$monthsArr[$j]].';';
+			if ($data[$monthsArr[$j]] > $yMax) {
+				$yMax = $data[$monthsArr[$j]];
+			}
+		} else {
+			echo 'var datevalues = 0;';
+		}
+		echo 'values.push([date, datevalues]);';
+	}
+	echo 'var plot'.$chartid.';';
+	echo 'var minDate = new Date(0);';
+	echo 'minDate.setUTCSeconds('.$timeStampArr[0].');';
+	echo 'jQuery(document).ready(function(){
+			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [values], {
+				axesDefaults: {
+					tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer,
+					tickOptions: {
+						angle: -90,
+						fontSize: \'8px\',
+						showGridline: false,
+						showMark: false,
+					},
+					pad: 0,
+				},
+				seriesDefaults: {
+					showMarker: false,
+					lineWidth: 1,
+					fill: true,
+				},
+				legend: {
+					show: false,
+				},
+				axes: {
+					xaxis: {
+						renderer: jQuery.jqplot.DateAxisRenderer,
+						min: minDate,
+						tickInterval: \'1 month\',
+						tickOptions: {
+							formatString: \'%Y/%m\'
+						}
+					},
+					yaxis: {
+						max: '.++$yMax.',
+						tickOptions: {
+							angle: 0,
+							showMark: true,
+						}
+					}
+				},
+				highlighter: {
+					show: true,
+					sizeAdjust: 2.5,
+				},
+			});
+		});';
+	echo 'jQuery(window).resize(function() {
+			plot'.$chartid.'.replot();
+		});'."\n";
+	echo '//]]></script>';
+	echo '<div id="chart'.$chartid.'"></div>';
+}
+
+function commits_graph($group_id, $days, $chartid) {
+	$start = time() - ($days * 60 * 60 * 24);
+	$g = group_get_object($group_id);
+	$end=time();
+	if ( $start < $g->getStartDate()) {
+		$start = $g->getStartDate();
+	}
+	$formattedmonth = date('Ym', $start);
+	$res = db_query_params('SELECT u.realname,sum(commits) AS count
+			FROM stats_cvs_user scu, users u
+			WHERE u.user_id = scu.user_id
+			AND scu.month >= $1
+			AND group_id = $2
+			GROUP BY realname ORDER BY count DESC',
+			array($formattedmonth, $group_id));
+
+	if (db_error()) {
+		exit_error(db_error(), 'scm');
+	}
+
+	if (db_numrows($res)) {
+		echo '<script type="text/javascript">//<![CDATA['."\n";
+		echo 'var data'.$chartid.' = new Array();';
+		while ($row = db_fetch_array($res)) {
+			echo 'data'.$chartid.'.push([\''.htmlentities($row[0]).'\',\''.$row[1].'\']);';
+		}
+		echo 'var plot'.$chartid.';';
+		echo 'jQuery(document).ready(function(){
+			plot'.$chartid.' = jQuery.jqplot (\'chart'.$chartid.'\', [data'.$chartid.'],
+				{
+					title : \''.utf8_decode(_("Commits By User")." (".strftime('%x',$start) ." - ". strftime('%x',$end) .")").'\',
+					seriesDefaults: {
+						// Make this a pie chart.
+						renderer: jQuery.jqplot.PieRenderer,
+						rendererOptions: {
+							// Put data labels on the pie slices.
+							// By default, labels show the percentage of the slice.
+							showDataLabels: true,
+							dataLabels: \'percent\',
+						}
+					},
+					legend: {
+						show:true, location: \'e\',
+					},
+				}
+				);
+			});';
+		echo 'jQuery(window).resize(function() {
+				plot'.$chartid.'.replot( { resetAxes: true } );
+			});'."\n";
+		echo '//]]></script>';
+		echo '<div id="chart'.$chartid.'"></div>';
+	} else {
+		echo '<p class="information">'._('No commits during this period.').'</p>';
+	}
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/www/scm/reporting/commitstime_graph.php b/src/www/scm/reporting/commitstime_graph.php
index db2bc39..92a5f84 100644
--- a/src/www/scm/reporting/commitstime_graph.php
+++ b/src/www/scm/reporting/commitstime_graph.php
@@ -3,6 +3,7 @@
  * Reporting System
  *
  * Copyright 2003-2004 (c) Tim Perdue - GForge LLC
+ * Copyright 2012, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -50,7 +51,9 @@ $res = db_query_params ('SELECT month,sum(commits) AS count
 	WHERE group_id=$1
 	GROUP BY month ORDER BY month ASC',
 			array ($group_id));
-echo db_error();
+if (db_error()) {
+	exit_error(db_error(), 'scm');
+}
 
 $report->labels=util_result_column_to_array($res,0);
 $report->setData($res,1);
diff --git a/src/www/scm/reporting/index.php b/src/www/scm/reporting/index.php
index 59979d8..10587a2 100644
--- a/src/www/scm/reporting/index.php
+++ b/src/www/scm/reporting/index.php
@@ -3,6 +3,7 @@
  * SCM Reporting
  *
  * Copyright 2004-2005 (c) Tim Perdue - GForge LLC
+ * Copyright 2012, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -25,33 +26,58 @@ require_once '../../env.inc.php';
 require_once $gfcommon.'include/pre.php';
 require_once $gfwww.'scm/include/scm_utils.php';
 
+html_use_jqueryjqplotpluginCanvas();
+html_use_jqueryjqplotpluginPie();
+html_use_jqueryjqplotpluginhighlighter();
+html_use_jqueryjqplotplugindateAxisRenderer();
+
 $group_id = getIntFromRequest("group_id");
-scm_header(array('title'=>_('SCM Repository Reporting'),'group'=>$group_id));
+scm_header(array('title'=>_('SCM Repository Reporting'), 'group'=>$group_id));
 
 ?>
 
 <h2>Commits Over Time</h2>
 <p>
+<?php
+commitstime_graph($group_id, 1);
+?>
+<noscript>
 <img src="commitstime_graph.php?group_id=<?php echo $group_id; ?>"
      alt="Commits Over Time" />
+</noscript>
 </p>
 
 <h2>Commits Last 30 Days</h2>
 <p>
+<?php
+commits_graph($group_id, 30, 2);
+?>
+<noscript>
 <img src="commits_graph.php?group_id=<?php echo $group_id; ?>&days=30"
      alt="Commits Last 30 Days" />
+</noscript>
 </p>
 
 <h2>Commits Last 90 Days</h2>
 <p>
+<?php
+commits_graph($group_id, 90, 3);
+?>
+<noscript>
 <img src="commits_graph.php?group_id=<?php echo $group_id; ?>&days=90"
      alt="Commits Last 90 Days" />
+</noscript>
 </p>
 
 <h2>Commits Last 365 Days</h2>
 <p>
+<?php
+commits_graph($group_id, 365, 4);
+?>
+<noscript>
 <img src="commits_graph.php?group_id=<?php echo $group_id; ?>&days=365"
      alt="Commits Last 365 Days" />
+</noscript>
 </p>
 
 <?php

-----------------------------------------------------------------------

Summary of changes:
 src/common/docman/views/reporting.php              |   19 +-
 src/common/pm/ProjectTask.class.php                |    3 +-
 src/common/reporting/Report.class.php              |   40 +-
 src/common/reporting/ReportTrackerAct.class.php    |   66 +-
 src/common/reporting/report_utils.php              |  997 ++++++++++++++++-
 src/etc/httpd.conf.d/vhost-main.inc                |    1 +
 src/vendor/jquery-jqplot/jquery.jqplot.css         |   16 +-
 src/vendor/jquery-jqplot/jquery.jqplot.js          | 1148 ++++++++++----------
 .../plugins/jqplot.BezierCurveRenderer.js          |    7 +-
 .../jquery-jqplot/plugins/jqplot.barRenderer.js    |   68 +-
 .../jquery-jqplot/plugins/jqplot.blockRenderer.js  |    6 +-
 .../jquery-jqplot/plugins/jqplot.bubbleRenderer.js |   14 +-
 .../plugins/jqplot.canvasAxisLabelRenderer.js      |   14 +-
 .../plugins/jqplot.canvasAxisTickRenderer.js       |   32 +-
 .../jquery-jqplot/plugins/jqplot.canvasOverlay.js  |  166 ++-
 .../plugins/jqplot.canvasTextRenderer.js           |   10 +-
 .../plugins/jqplot.categoryAxisRenderer.js         |   28 +-
 .../jquery-jqplot/plugins/jqplot.ciParser.js       |    8 +-
 src/vendor/jquery-jqplot/plugins/jqplot.cursor.js  |   12 +-
 .../plugins/jqplot.dateAxisRenderer.js             |   62 +-
 .../jquery-jqplot/plugins/jqplot.donutRenderer.js  |   16 +-
 .../jquery-jqplot/plugins/jqplot.dragable.js       |    6 +-
 .../plugins/jqplot.enhancedLegendRenderer.js       |    8 +-
 .../jquery-jqplot/plugins/jqplot.funnelRenderer.js |   16 +-
 .../jquery-jqplot/plugins/jqplot.highlighter.js    |   24 +-
 .../plugins/jqplot.logAxisRenderer.js              |   15 +-
 .../plugins/jqplot.mekkoAxisRenderer.js            |    8 +-
 .../jquery-jqplot/plugins/jqplot.mekkoRenderer.js  |   10 +-
 .../plugins/jqplot.meterGaugeRenderer.js           |   25 +-
 src/vendor/jquery-jqplot/plugins/jqplot.mobile.js  |    4 +-
 .../jquery-jqplot/plugins/jqplot.ohlcRenderer.js   |   10 +-
 .../jquery-jqplot/plugins/jqplot.pieRenderer.js    |   16 +-
 .../jquery-jqplot/plugins/jqplot.pointLabels.js    |   16 +-
 .../plugins/jqplot.pyramidAxisRenderer.js          |   10 +-
 .../plugins/jqplot.pyramidGridRenderer.js          |    6 +-
 .../plugins/jqplot.pyramidRenderer.js              |    8 +-
 .../jquery-jqplot/plugins/jqplot.trendline.js      |    8 +-
 src/vendor/jquery-teamwork-gantt/add.gif           |  Bin 0 -> 332 bytes
 src/vendor/jquery-teamwork-gantt/alert.gif         |  Bin 0 -> 397 bytes
 src/vendor/jquery-teamwork-gantt/closeBig.png      |  Bin 0 -> 904 bytes
 src/vendor/jquery-teamwork-gantt/del.gif           |  Bin 0 -> 338 bytes
 src/vendor/jquery-teamwork-gantt/edit.gif          |  Bin 0 -> 355 bytes
 src/vendor/jquery-teamwork-gantt/gantt.css         |  323 ++++++
 src/vendor/jquery-teamwork-gantt/ganttDrawer.js    |  752 +++++++++++++
 .../jquery-teamwork-gantt/ganttGridEditor.js       |  518 +++++++++
 src/vendor/jquery-teamwork-gantt/ganttMaster.js    |  705 ++++++++++++
 src/vendor/jquery-teamwork-gantt/ganttTask.js      |  947 ++++++++++++++++
 src/vendor/jquery-teamwork-gantt/ganttUtilities.js |  240 ++++
 src/vendor/jquery-teamwork-gantt/gantt_compact.css |  323 ++++++
 .../jquery-teamwork-gantt/hasExternalDeps.png      |  Bin 0 -> 3976 bytes
 .../jquery-teamwork-gantt/libs/JST/jquery.JST.js   |  167 +++
 src/vendor/jquery-teamwork-gantt/libs/date.js      |  584 ++++++++++
 .../libs/dateField/images/next.png                 |  Bin 0 -> 148 bytes
 .../libs/dateField/images/prev.png                 |  Bin 0 -> 146 bytes
 .../libs/dateField/jquery.dateField.css            |   88 ++
 .../libs/dateField/jquery.dateField.js             |  212 ++++
 src/vendor/jquery-teamwork-gantt/libs/i18nJs.js    |  140 +++
 .../libs/jquery.livequery.min.js                   |   11 +
 .../jquery-teamwork-gantt/libs/jquery.timers.js    |  142 +++
 src/vendor/jquery-teamwork-gantt/libs/platform.js  |  954 ++++++++++++++++
 src/vendor/jquery-teamwork-gantt/linkArrow.png     |  Bin 0 -> 210 bytes
 src/vendor/jquery-teamwork-gantt/milestone.png     |  Bin 0 -> 1136 bytes
 src/vendor/jquery-teamwork-gantt/platform.css      |  347 ++++++
 .../jquery-teamwork-gantt/res/img/black_70.png     |  Bin 0 -> 166 bytes
 .../teamwork-regular-webfont.eot                   |  Bin 0 -> 23827 bytes
 .../teamwork-regular-webfont.otf                   |  Bin 0 -> 18260 bytes
 .../teamwork-regular-webfont.svg                   |  152 +++
 .../teamwork-regular-webfont.ttf                   |  Bin 0 -> 37208 bytes
 .../teamwork-regular-webfont.woff                  |  Bin 0 -> 26948 bytes
 src/vendor/jquery-teamwork-gantt/teamworkFont.css  |   16 +
 src/www/frs/reporting/downloads.php                |   19 +-
 src/www/images/closeBig.png                        |  Bin 0 -> 904 bytes
 src/www/images/linkArrow.png                       |  Bin 0 -> 210 bytes
 src/www/include/HTML_Graphs.php                    |  845 --------------
 src/www/include/graph_lib.php                      |  679 ------------
 src/www/include/html.php                           |   22 +-
 src/www/include/stats_function.php                 |  185 ----
 src/www/include/tool_reports.php                   |   51 +-
 src/www/pm/detail_task.php                         |    3 +
 src/www/pm/gantt.php                               |  135 ---
 src/www/pm/ganttofuser.php                         |  132 ---
 src/www/pm/ganttpage.php                           |  401 +++++--
 src/www/pm/reporting/index.php                     |  108 +-
 src/www/pm/task.php                                |    9 +-
 src/www/project/stats/index.php                    |   25 +-
 src/www/reporting/groupadded.php                   |    9 +-
 src/www/reporting/groupadded_graph.php             |   77 --
 src/www/reporting/groupcum.php                     |   10 +-
 src/www/reporting/groupcum_graph.php               |   76 --
 src/www/reporting/index.php                        |   14 +-
 src/www/reporting/projectact.php                   |    9 +-
 src/www/reporting/projectact_graph.php             |  225 ----
 src/www/reporting/projecttime.php                  |    9 +-
 src/www/reporting/projecttime_graph.php            |   84 --
 src/www/reporting/siteact.php                      |    9 +-
 src/www/reporting/siteact_graph.php                |  142 ---
 src/www/reporting/sitetime.php                     |    8 +-
 src/www/reporting/sitetime_graph.php               |   83 --
 src/www/reporting/sitetimebar.php                  |   11 +
 src/www/reporting/sitetimebar_graph.php            |   99 --
 src/www/reporting/toolspie.php                     |   14 +-
 src/www/reporting/toolspie_graph.php               |  149 ---
 src/www/reporting/trackerpie_graph.php             |  133 ---
 src/www/reporting/useract.php                      |    9 +-
 src/www/reporting/useract_graph.php                |  140 ---
 src/www/reporting/useradded.php                    |   10 +-
 src/www/reporting/useradded_graph.php              |   77 --
 src/www/reporting/usercum.php                      |   11 +-
 src/www/reporting/usercum_graph.php                |   77 --
 src/www/reporting/usersummary.php                  |    4 +-
 src/www/reporting/usertime.php                     |   11 +-
 src/www/reporting/usertime_graph.php               |   87 --
 src/www/scm/include/scm_utils.php                  |  174 ++-
 src/www/scm/reporting/commits_graph.php            |   96 --
 src/www/scm/reporting/commitstime_graph.php        |   87 --
 src/www/scm/reporting/index.php                    |   25 +-
 src/www/stats/graphs.php                           |   10 +-
 src/www/stats/site_stats_utils.php                 |  182 ++++
 src/www/stats/users_graph.php                      |   89 --
 src/www/stats/views_graph.php                      |  109 --
 src/www/survey/admin/graphs.php                    |  128 ---
 src/www/survey/admin/show_results.php              |    7 +
 src/www/survey/admin/show_results_aggregate.php    |  242 -----
 src/www/survey/admin/show_results_comments.php     |   84 --
 src/www/survey/admin/show_results_csv.php          |  133 ---
 src/www/survey/include/SurveyHTML.class.php        |  115 +-
 src/www/tracker/reporting/index.php                |   34 +-
 src/www/tracker/reporting/trackeract_graph.php     |  115 --
 src/www/tracker/reporting/trackerpie_graph.php     |  154 ---
 129 files changed, 9743 insertions(+), 5786 deletions(-)
 create mode 100644 src/vendor/jquery-teamwork-gantt/add.gif
 create mode 100644 src/vendor/jquery-teamwork-gantt/alert.gif
 create mode 100644 src/vendor/jquery-teamwork-gantt/closeBig.png
 create mode 100644 src/vendor/jquery-teamwork-gantt/del.gif
 create mode 100644 src/vendor/jquery-teamwork-gantt/edit.gif
 create mode 100644 src/vendor/jquery-teamwork-gantt/gantt.css
 create mode 100644 src/vendor/jquery-teamwork-gantt/ganttDrawer.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/ganttGridEditor.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/ganttMaster.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/ganttTask.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/ganttUtilities.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/gantt_compact.css
 create mode 100644 src/vendor/jquery-teamwork-gantt/hasExternalDeps.png
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/JST/jquery.JST.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/date.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/dateField/images/next.png
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/dateField/images/prev.png
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/dateField/jquery.dateField.css
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/dateField/jquery.dateField.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/i18nJs.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/jquery.livequery.min.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/jquery.timers.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/libs/platform.js
 create mode 100644 src/vendor/jquery-teamwork-gantt/linkArrow.png
 create mode 100644 src/vendor/jquery-teamwork-gantt/milestone.png
 create mode 100644 src/vendor/jquery-teamwork-gantt/platform.css
 create mode 100644 src/vendor/jquery-teamwork-gantt/res/img/black_70.png
 create mode 100644 src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.eot
 create mode 100644 src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.otf
 create mode 100644 src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.svg
 create mode 100644 src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.ttf
 create mode 100644 src/vendor/jquery-teamwork-gantt/teamwork-regular-webfont.woff
 create mode 100644 src/vendor/jquery-teamwork-gantt/teamworkFont.css
 create mode 100644 src/www/images/closeBig.png
 create mode 100644 src/www/images/linkArrow.png
 delete mode 100644 src/www/include/HTML_Graphs.php
 delete mode 100644 src/www/include/graph_lib.php
 delete mode 100644 src/www/include/stats_function.php
 delete mode 100644 src/www/pm/gantt.php
 delete mode 100644 src/www/pm/ganttofuser.php
 delete mode 100644 src/www/reporting/groupadded_graph.php
 delete mode 100644 src/www/reporting/groupcum_graph.php
 delete mode 100644 src/www/reporting/projectact_graph.php
 delete mode 100644 src/www/reporting/projecttime_graph.php
 delete mode 100644 src/www/reporting/siteact_graph.php
 delete mode 100644 src/www/reporting/sitetime_graph.php
 delete mode 100644 src/www/reporting/sitetimebar_graph.php
 delete mode 100644 src/www/reporting/toolspie_graph.php
 delete mode 100644 src/www/reporting/trackerpie_graph.php
 delete mode 100644 src/www/reporting/useract_graph.php
 delete mode 100644 src/www/reporting/useradded_graph.php
 delete mode 100644 src/www/reporting/usercum_graph.php
 delete mode 100644 src/www/reporting/usertime_graph.php
 delete mode 100644 src/www/scm/reporting/commits_graph.php
 delete mode 100644 src/www/scm/reporting/commitstime_graph.php
 delete mode 100644 src/www/stats/users_graph.php
 delete mode 100644 src/www/stats/views_graph.php
 delete mode 100644 src/www/survey/admin/graphs.php
 delete mode 100644 src/www/survey/admin/show_results_aggregate.php
 delete mode 100644 src/www/survey/admin/show_results_comments.php
 delete mode 100644 src/www/survey/admin/show_results_csv.php
 delete mode 100644 src/www/tracker/reporting/trackeract_graph.php
 delete mode 100644 src/www/tracker/reporting/trackerpie_graph.php


hooks/post-receive
-- 
FusionForge



More information about the Fusionforge-commits mailing list