فهرست منبع

Update jsGant lib to 2.7.3

Laurent Destailleur 4 سال پیش
والد
کامیت
506659a9d2

+ 1 - 1
COPYRIGHT

@@ -52,7 +52,7 @@ jQuery jqueryFileTree  1.0.1         GPL and MIT License         Yes
 jQuery jquerytreeview  1.4.1         MIT License                 Yes             JS library for filetree
 jQuery TableDnD        0.6           GPL and MIT License         Yes             JS library plugin TableDnD (to reorder table rows)
 jQuery Timepicker      1.1.0         GPL and MIT License         Yes             JS library Timepicker addon for Datepicker
-jsGanttImproved        1.7.5.4       BSD License                 Yes             JS library (to build Gantt reports)
+jsGanttImproved        2.7.3         BSD License                 Yes             JS library (to build Gantt reports)
 JsTimezoneDetect       1.0.6         MIT License                 Yes             JS library to detect user timezone
 SwaggerUI			   2.0.24		 GPL-2+                      Yes             JS library to offer the REST API explorer
 

+ 1 - 1
htdocs/includes/jsgantt/CONTRIBUTING.md

@@ -177,4 +177,4 @@ You can find out more detailed information about contributing in the [Documentat
 [github]: https://github.com/jsGanttImproved/jsgantt-improved
 [js-style-guide]: https://google.github.io/styleguide/jsguide.html
 [closing-issues]: https://help.github.com/articles/closing-issues-via-commit-messages/
-[docs]: https://github.com/jsGanttImproved/jsgantt-improved/wiki/Documentation
+[docs]: https://github.com/jsGanttImproved/jsgantt-improved/wiki/Documentation

+ 2 - 4
htdocs/includes/jsgantt/LICENSE

@@ -1,5 +1,4 @@
-* Copyright (c) 2013-2017, Paul Geldart, Eduardo Rodrigues and Ricardo Cardoso.
-* All rights reserved.
+* Copyright (c) 2013-2018, Paul Geldart, Eduardo Rodrigues and Ricardo Cardoso.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
@@ -26,7 +25,6 @@
 This project is based on jsGantt 1.2, the original project license follows:
 
 * Copyright (c) 2008, Shlomy Gantz/BlueBrick Inc.
-* All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
@@ -48,4 +46,4 @@ This project is based on jsGantt 1.2, the original project license follows:
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 139 - 9
htdocs/includes/jsgantt/README.md

@@ -1,21 +1,151 @@
-A fully featured gantt chart component built entirely in Javascript, CSS and AJAX. It is lightweight and there is no need of external libraries or additional images.
+[![Build Status](https://travis-ci.com/jsGanttImproved/jsgantt-improved.svg?branch=master)](https://travis-ci.com/jsGanttImproved/jsgantt-improved)
 
-You can view a live example at https://jsGanttImproved.github.io/jsgantt-improved
 
-Features include:
+A fully featured gantt chart component built entirely in Javascript, CSS and AJAX. It is lightweight and there is no need of external libraries or additional images. 
+
+
+![Demo Image](/docs/demo.gif)
+
+
+Start using with including the files `jsgantt.js` and `jsgantt.css` that are inside `docs/` folder.
+
+Or install and use in JS 
+
+`npm install jsgantt-improved`
+
+Import in your JS `import {JSGantt} from 'jsgantt-improved';`
+
+See the [FULL DOCUMENTATION](./Documentation.md) for more details in all features.
+
+For **Angular** use the component [ng-gantt](https://github.com/jsGanttImproved/ng-gantt) 
+
+For **React** use the component [react-jsgantt](https://github.com/jsGanttImproved/react-jsgantt) 
+
+
+For **Vue** , see this example: https://stackblitz.com/edit/vue-jsgantt
+
+
+For **.NET** , see this example: [.NET Documentation](./docs/DotNet.md)
+
+
+## Example
+
+
+You can view a Solo live example at:
+
+* https://jsganttimproved.github.io/jsgantt-improved/docs/demo.html
+
+Or use a live coding example at Codenpen:
+
+* https://codepen.io/mariomol/pen/mQzBPV
+
+
+## Easy to Use
+
+```html
+<link href="jsgantt.css" rel="stylesheet" type="text/css"/>
+<script src="jsgantt.js" type="text/javascript"></script>
+
+<div style="position:relative" class="gantt" id="GanttChartDIV"></div>
+
+<script>
+
+var g = new JSGantt.GanttChart(document.getElementById('GanttChartDIV'), 'day');
+
+g.setOptions({
+  vCaptionType: 'Complete',  // Set to Show Caption : None,Caption,Resource,Duration,Complete,     
+  vQuarterColWidth: 36,
+  vDateTaskDisplayFormat: 'day dd month yyyy', // Shown in tool tip box
+  vDayMajorDateDisplayFormat: 'mon yyyy - Week ww',// Set format to dates in the "Major" header of the "Day" view
+  vWeekMinorDateDisplayFormat: 'dd mon', // Set format to display dates in the "Minor" header of the "Week" view
+  vLang: 'en',
+  vShowTaskInfoLink: 1, // Show link in tool tip (0/1)
+  vShowEndWeekDate: 0,  // Show/Hide the date for the last day of the week in header for daily
+  vAdditionalHeaders: { // Add data columns to your table
+      category: {
+        title: 'Category'
+      },
+      sector: {
+        title: 'Sector'
+      }
+    },
+  vUseSingleCell: 10000, // Set the threshold cell per table row (Helps performance for large data.
+  vFormatArr: ['Day', 'Week', 'Month', 'Quarter'], // Even with setUseSingleCell using Hour format on such a large chart can cause issues in some browsers,
+  
+});
+
+// Load from a Json url
+JSGantt.parseJSON('./fixes/data.json', g);
+
+// Or Adding  Manually
+g.AddTaskItemObject({
+  pID: 1,
+  pName: "Define Chart <strong>API</strong>",
+  pStart: "2017-02-25",
+  pEnd: "2017-03-17",
+  pPlanStart: "2017-04-01",
+  pPlanEnd: "2017-04-15 12:00",
+  pClass: "ggroupblack",
+  pLink: "",
+  pMile: 0,
+  pRes: "Brian",
+  pComp: 0,
+  pGroup: 0,
+  pParent: 0,
+  pOpen: 1,
+  pDepend: "",
+  pCaption: "",
+  pCost: 1000,
+  pNotes: "Some Notes text",
+  category: "My Category",
+  sector: "Finance"
+});
+
+g.Draw();
+
+</script>
+```
+
+## Features
+
   * Tasks & Collapsible Task Groups
-  * Dependencies
+  * Dependencies and Highlight when hover a task
+  * Edit data in gantt table with list of responsible
   * Task Completion
-  * Task Styling
+  * Table with Additional Columns
+  * Task Styling or as HTML tags
   * Milestones
   * Resources
+  * Costs
+  * Plan Start and End Dates
+  * Gantt with Planned vs Executed
   * Dynamic Loading of Tasks
   * Dynamic change of format: Hour, Day, Week, Month, Quarter
-  * Load Gantt from XML
+  * Load Gantt from JSON and XML
     * From external files (including experimental support for MS Project XML files)
     * From JavaScript Strings
-  * Support for Internationalization (all hard coded strings can be overridden)
+  * Support for Internationalization 
+
+## Documentation
+
+See the [Documentation](./Documentation.md) wiki page or the included ``docs/index.html`` file for instructions on use.
+
+Project based on https://code.google.com/p/jsgantt/.
+
+
+## Want to Collaborate?
+
+Its easy to get it set:
+
+* Clone this repo
+* Install lib dependencies: `npm i` 
+* Install global dependencies: `npm i -g browserify nodemon onchange` 
+* Run the demo, This will start a `localhost:8080` with a live  example:  `npm start`. 
+* Use `npm run watch` or do your change in `src` and restart this command refresh the changes.
+
+For testing use `npm run test` with e2e tests.
+
+Or help us donating...
 
-Project forked as I was unable to contact the original maintainers. This work was done to support a personal project that didn't warrant a more heavyweight system (e.g. the dojo toolkit gantt chart features).
+[![](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=S7B43P63C5QEN)
 
-See the [Documentation](https://github.com/jsGanttImproved/jsgantt-improved/wiki/Documentation) wiki page or the included ``index.html`` file for instructions on use.

BIN
htdocs/includes/jsgantt/home-bg.jpg


+ 0 - 1167
htdocs/includes/jsgantt/index.html

@@ -1,1167 +0,0 @@
-<!DOCTYPE html>
-<html lang="en" class="no-js">
-
-<!-- Head -->
-  <head>
-  <!-- Meta data -->
-    <meta charset="utf-8">
-    <title>jsGantt Improved</title>
-    <meta name="description" content="FREE javascript gantt - jsGantt Improved HTML, CSS and AJAX only">
-    <meta name="keywords" content="jsgantt-improved free javascript gantt-chart html css ajax">
-    <meta name="viewport" content="width=device-width,initial-scale=1">
-
-  <!-- External resources -->
-    <!-- jQuery + Ajax [required by Bootstrap] -->
-      <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
-      <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
-      <!-- Required by smooth scrolling -->
-        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
-    <!-- Bootstrap v4.0.0 Alpha -->
-      <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous" />
-      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
-    <!-- Font Awesome -->
-      <script src="https://use.fontawesome.com/78d1e57168.js"></script>
-    <!-- Google's Code Prettify -->
-      <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?lang=css&amp;skin=sunburst"></script>
-    <!-- Google Fonts -->
-      <link href="https://fonts.googleapis.com/css?family=Cookie|Satisfy|Kelly+Slab|Overlock" rel="stylesheet">
-
-  <!-- Internal resources -->
-    <!-- Webpage -->
-      <link href="main.css" rel="stylesheet" type="text/css" />
-      <script src="main.js" type="text/javascript"></script>
-    <!-- jsGanttImproved App -->
-      <link href="jsgantt.css" rel="stylesheet" type="text/css"/>
-      <script src="jsgantt.js" type="text/javascript"></script>
-  </head>
-
-<!-- Content -->
-  <body data-spy="scroll" data-target="#my-navbar-nav">
-  <!-- Navigation bar -->
-    <nav class="navbar navbar-toggleable-md navbar-inverse bg-inverse fixed-top">
-      <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#my-navbar-nav" aria-controls="my-navbar-nav" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
-      </button>
-      <a class="navbar-brand product-name" id="my-nav-brand" href="#home">jsGanttImproved</a>
-
-      <div class="collapse navbar-collapse" id="my-navbar-nav">
-        <ul class="navbar-nav mr-auto" role="tablist">
-          <li class="nav-item">
-            <a class="nav-link" href="#home">Home <span class="sr-only">(current)</span></a>
-          </li>
-          <li class="nav-item">
-            <a class="nav-link" href="#demo">Demo</a>
-          </li>
-          <li class="nav-item">
-            <a class="nav-link" href="#features">Features</a>
-          </li>
-          <li class="nav-item">
-            <a class="nav-link" href="#usage">Usage</a>
-          </li>
-          <li class="nav-item">
-            <a class="nav-link" href="#credits">Credits</a>
-          </li>
-        </ul>
-        <form class="form-inline my-2 my-lg-0">
-          <a class="btn btn-outline-danger my-2 my-sm-0 mx-1" href="https://api.github.com/repos/jsGanttImproved/jsgantt-improved/zipball">Download</a>
-          <a class="btn btn-outline-primary my-2 my-sm-0 mx-1" href="https://github.com/jsGanttImproved/jsgantt-improved" target="_blank">View on GitHub</a>
-        </form>
-      </div>
-    </nav>
-
-  <!-- Content -->
-    <!-- Home -->
-      <div class="container-fluid" id="home">
-        <div class="row"> 
-          <div class="col-lg-6 text-center">
-            <h1 class="display-1 product-name" id="home-title">jsGanttImproved</h1>
-            <h2 class="display-2" id="home-subtitle">latest v1.7.5.4</h2>
-            <a class="btn btn-danger my-2 my-sm-0 mx-1" href="https://api.github.com/repos/jsGanttImproved/jsgantt-improved/zipball">Download</a>
-            <a class="btn btn-primary my-2 my-sm-0 mx-1" href="https://github.com/jsGanttImproved/jsgantt-improved" target="_blank">View on GitHub</a>
-          </div>
-          <div class="col-lg-6">
-            <div class="card text-center" id="slide-card">
-              <div class="card-block">
-                <span class="card-text slide">
-                  <p><i class="fa fa-code slide-icon"></i></p>
-                  <p>100% HTML + CSS + JavaScript Gantt Chart</p>
-                </span>
-                <span class="card-text slide">
-                  <p><i class="fa fa-usd slide-icon"></i></p>
-                  <p>Completely FREE</p>
-                </span>
-                <span class="card-text slide">
-                  <p><i class="fa fa-github slide-icon"></i></p>
-                  <p>Open source</p>
-                </span>
-              </div>
-              <div class="card-footer text-muted" id="slide-dots">
-                <span class="dot"></span>
-                <span class="dot"></span>
-                <span class="dot"></span>
-              </div>
-            </div>
-          </div>
-        </div>
-        <div class="row">
-          <div class="col text-center">
-            <a class="btn btn-outline-info" href="#demo" id="learn-more"><i class="fa fa-chevron-down"></i></a>
-          </div>
-        </div>
-      </div>
-    <!-- Demo -->
-      <div class="container-fluid section" id="demo">
-        <h1>Demo</h1>
-        <div class="btn-group" data-toggle="buttons">
-          <label class="btn btn-primary btn-demo">
-            <input type="checkbox" autocomplete="off"><i class="fa fa-code"></i> Embedded Code
-          </label>
-          <label class="btn btn-primary btn-demo">
-            <input type="checkbox" autocomplete="off"><i class="fa fa-file-code-o"></i> External XML File
-          </label>
-        </div>
-        <div id="embedded-Gantt">
-          <script type="text/javascript">
-var g = new JSGantt.GanttChart(document.getElementById('embedded-Gantt'), 'week');
-if (g.getDivId() != null) {
-  g.setCaptionType('Complete');  // Set to Show Caption (None,Caption,Resource,Duration,Complete)
-  g.setQuarterColWidth(36);
-  g.setDateTaskDisplayFormat('day dd month yyyy'); // Shown in tool tip box
-  g.setDayMajorDateDisplayFormat('mon yyyy - Week ww') // Set format to display dates in the "Major" header of the "Day" view
-  g.setWeekMinorDateDisplayFormat('dd mon') // Set format to display dates in the "Minor" header of the "Week" view
-  g.setShowTaskInfoLink(1); // Show link in tool tip (0/1)
-  g.setShowEndWeekDate(0); // Show/Hide the date for the last day of the week in header for daily view (1/0)
-  g.setUseSingleCell(10000); // Set the threshold at which we will only use one cell per table row (0 disables).  Helps with rendering performance for large charts.
-  g.setFormatArr('Day', 'Week', 'Month', 'Quarter'); // Even with setUseSingleCell using Hour format on such a large chart can cause issues in some browsers
-  // Parameters                     (pID, pName,                  pStart,       pEnd,        pStyle,         pLink (unused)  pMile, pRes,       pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGantt)
-  g.AddTaskItem(new JSGantt.TaskItem(1,   'Define Chart API',     '',           '',          'ggroupblack',  '',                 0, 'Brian',    0,     1,      0,       1,     '',      '',      'Some Notes text', g ));
-  g.AddTaskItem(new JSGantt.TaskItem(11,  'Chart Object',         '2017-02-20','2017-02-20', 'gmilestone',   '',                 1, 'Shlomy',   100,   0,      1,       1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(12,  'Task Objects',         '',           '',          'ggroupblack',  '',                 0, 'Shlomy',   40,    1,      1,       1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(121, 'Constructor Proc',     '2017-02-21','2017-03-09', 'gtaskblue',    '',                 0, 'Brian T.', 60,    0,      12,      1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(122, 'Task Variables',       '2017-03-06','2017-03-11', 'gtaskred',     '',                 0, 'Brian',    60,    0,      12,      1,     121,     '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(123, 'Task by Minute/Hour',  '2017-03-09','2017-03-14 12:00', 'gtaskyellow', '',            0, 'Ilan',     60,    0,      12,      1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(124, 'Task Functions',       '2017-03-09','2017-03-29', 'gtaskred',     '',                 0, 'Anyone',   60,    0,      12,      1,     '123SS', 'This is a caption', null, g));
-  g.AddTaskItem(new JSGantt.TaskItem(2,   'Create HTML Shell',    '2017-03-24','2017-03-24', 'gtaskyellow',  '',                 0, 'Brian',    20,    0,      0,       1,     122,     '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(3,   'Code Javascript',      '',           '',          'ggroupblack',  '',                 0, 'Brian',    0,     1,      0,       1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(31,  'Define Variables',     '2017-02-25','2017-03-17', 'gtaskpurple',  '',                 0, 'Brian',    30,    0,      3,       1,     '',      'Caption 1','',   g));
-  g.AddTaskItem(new JSGantt.TaskItem(32,  'Calculate Chart Size', '2017-03-15','2017-03-24', 'gtaskgreen',   '',                 0, 'Shlomy',   40,    0,      3,       1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(33,  'Draw Task Items',      '',           '',          'ggroupblack',  '',                 0, 'Someone',  40,    2,      3,       1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(332, 'Task Label Table',     '2017-03-06','2017-03-09', 'gtaskblue',    '',                 0, 'Brian',    60,    0,      33,      1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(333, 'Task Scrolling Grid',  '2017-03-11','2017-03-20', 'gtaskblue',    '',                 0, 'Brian',    0,     0,      33,      1,     '332',   '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(34,  'Draw Task Bars',       '',           '',          'ggroupblack',  '',                 0, 'Anybody',  60,    1,      3,       0,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(341, 'Loop each Task',       '2017-03-26','2017-04-11', 'gtaskred',     '',                 0, 'Brian',    60,    0,      34,      1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(342, 'Calculate Start/Stop', '2017-04-12','2017-05-18', 'gtaskpink',    '',                 0, 'Brian',    60,    0,      34,      1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(343, 'Draw Task Div',        '2017-05-13','2017-05-17', 'gtaskred',     '',                 0, 'Brian',    60,    0,      34,      1,     '',      '',      '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(344, 'Draw Completion Div',  '2017-05-17','2017-06-04', 'gtaskred',     '',                 0, 'Brian',    60,    0,      34,      1,     "342,343",'',     '',      g));
-  g.AddTaskItem(new JSGantt.TaskItem(35,  'Make Updates',         '2017-07-17','2017-09-04', 'gtaskpurple',  '',                 0, 'Brian',    30,    0,      3,       1,     '333',   '',      '',      g));
-
-  g.Draw();
-} else {
-  alert("Error, unable to create Gantt Chart");
-}
-          </script>
-        </div>
-        <div id="external-Gantt">
-          <script type="text/javascript">
-var g = new JSGantt.GanttChart(document.getElementById('external-Gantt'), 'day');
-
-if (g.getDivId() != null) {
-  g.setCaptionType('Resource');  // Set to Show Caption (None,Caption,Resource,Duration,Complete)
-  g.setShowTaskInfoLink(1); // Show link in tool tip (0/1)
-  g.setDayMajorDateDisplayFormat('dd mon');
-  g.setDateTaskDisplayFormat('dd month yyyy HH:MI');
-  // Use the XML file parser
-  JSGantt.parseXML('project.xml', g)
-
-  g.Draw();
-} else {
-  alert("Error, unable to create Gantt Chart");
-}
-          </script>
-        </div>
-      </div>
-    <!-- Features -->
-      <div class="container-fluid section" id="features">
-        <h1>Features</h1>
-        <p>jsGanttImproved is a fully featured gantt chart component built entirely in Javascript, CSS and AJAX. It is lightweight and there is no need of external libraries or additional images.</p>
-        <div class="row">
-          <div class="col-lg">
-            <h2>Basic Features</h2>
-            <ul>
-              <li>Tasks &amp; Collapsible Task Groups</li>
-              <li>Multiple Dependencies</li>
-              <li>Task Completion</li>
-              <li>Task Style</li>
-              <li>Milestones</li>
-              <li>Resources</li>
-            </ul>
-          </div>
-          <div class="col-lg">
-            <h2>Advanced Features</h3>
-            <ul>
-              <li>Dynamic Loading of Tasks</li>
-              <li>Dynamic change of format: Hour, Day, Week, Month, Quarter</li>
-              <li>
-                Load Gantt from:
-                <ul>
-                  <li>External XML files (including experimental support for Microsoft Project XML files)</li>
-                  <li>JavaScript strings</li>
-                </ul>
-              </li>
-              <li>Export Gantt as XML string</li>
-              <li>Support for internationalization</li>
-            </ul>
-          </div>
-        </div>
-        <h2>Current Known Issues:</h3>
-        <ul>
-          <li>If the browser is viewing the page at anything other than 100% zoom then bars may not be sized or positioned correctly.</li>
-        </ul>
-        <h2>Changelog:</h3>
-        <p>Check the full list of changes on <a href="https://github.com/jsGanttImproved/jsgantt-improved/releases">GitHub releases page</a>.</p>
-        <h3>v1.7.5.4:</h3>
-        <ul>
-          <li>Left part of the chart is now created first on JavaScript and establishes the left floating reference</li>
-          <li>Minimum width updated to 632px so that the left part of the chart has a fixed width of 532px and the right part fills out the rest with a minimum of 100px</li>
-        </ul>
-        <h3>v1.7.5.3:</h3>
-        <ul>
-          <li>Fixed group completion percentage that now is a weighted average</li>
-          <li>Start and end dates specified on standard group tasks will now be respected if they fall outside of the calculated group date range</li>
-          <li>Fixed problem that would occur if Tool Tips were disabled</li>
-          <li>Moved example dates forward so the current date marker is visible</li>
-        </ul>
-        <h3>v1.7.5:</h3>
-        <ul>
-          <li>Project Migrated to GitHub</li>
-          <li>Instantiating a new JSGantt.TaskItem will now also accept Date objects for start and end dates</li>
-          <li>Fixed old Internet Explorer compatibilty broken by v1.7</li>
-          <li>Fixed bug in Iso week date format</li>
-          <li>Changed to solid arrows on dependency lines to be more printer friendly</li>
-          <li>Code refactoring and clean up</li>
-        </ul>
-        <h3>v1.7:</h3>
-        <ul>
-          <li>
-            Fixed nasty long-standing bug where the first Gantt chart created must be stored in a javascript variable named &quot;g&quot;
-            <ul>
-              <li>NOTE: This required a change in the method to instatiate a JSGantt.TaskItem object to pass the related chart.</li>
-              <li>A temporary fix is included that still assumes the use of "g" for the chart if the chart object is not passed, this will be removed in v1.8</li>
-            </ul>
-          </li>
-          <li>Altered XML export functionality so that dates are output in the specified input format for the chart</li>
-          <li>Added method to read XML directly from an input string</li>
-          <li>Prevented creation of a task with a duplicate &quot;unique&quot; ID</li>
-          <li>Fixed bug where attempting to remove the first task defined would prevent the chart from redrawing</li>
-          <li>Some general code clean up</li>
-        </ul>
-      </div>
-    <!-- Usage -->
-      <div class="container-fluid section" id="usage">
-        <h1>Usage</h1>
-        <p>Following the steps below you will be able to get create a basic Gantt Chart. If you notice any bugs, please post them to <a href="https://github.com/jsGanttImproved/jsgantt-improved/issues">GitHub&nbsp;issues</a>.</p>
-        <ol>
-          <li>
-            Include JSGantt CSS and Javascript
-            <pre class="prettyprint lang-html code-block"><code>&lt;link rel="stylesheet" type="text/css" href="jsgantt.css" /&gt;
-&lt;script language="javascript" src="jsgantt.js"&gt;&lt;/script&gt;</code></pre>
-          </li>
-          <li>
-            Create a div element to hold the gantt chart
-            <pre class="prettyprint lang-html"><code>&lt;div style="position:relative" class="gantt" id="GanttChartDIV"&gt;&lt;/div&gt;</code></pre>
-          </li>
-          <li>
-            Start a &lt;script&gt; block
-            <pre class="prettyprint lang-html"><code>&lt;script type="text/javascript"&gt;</code></pre>
-          </li>
-          <li>
-            Instantiate JSGantt using GanttChart()
-            <pre class="prettyprint lang-js"><code>var g = new JSGantt.GanttChart(document.getElementById('GanttChartDIV'), 'day');</code></pre>
-            <p>Method definition:
-              <strong>GanttChart(<em>pDiv, pFormat</em>)</strong>
-            </p>
-            <p><table>
-              <tr>
-                <th>pDiv:</th>
-                <td>(required) this is a DIV object created in HTML</td>
-              </tr>
-              <tr>
-                <th>pFormat:</th>
-                <td>(required) - used to indicate whether chart should be drawn in "hour", "day", "week", "month", or "quarter" format</td>
-              </tr>
-            </table></p>
-          </li>
-          <li>
-            <p>Customize the look and feel using configuration methods (see <a href="#options">Configuration Options</a>)</p>
-          </li>
-          <li>
-            Add Tasks
-            <ul>
-              <li>
-                using AddTaskItem()
-                <pre class="prettyprint lang-js"><code>g.AddTaskItem(new JSGantt.TaskItem(1, 'Define Chart API','',          '',          'ggroupblack','', 0, 'Brian', 0,  1,0,1,'','','Some Notes text',g));
-g.AddTaskItem(new JSGantt.TaskItem(11,'Chart Object',    '2016-02-20','2016-02-20','gmilestone', '', 1, 'Shlomy',100,0,1,1,'','','',g));
-                </code></pre>
-                <p>Method definition:
-                  <strong>TaskItem(<em>pID, pName, pStart, pEnd, pColor, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGantt</em>)</strong>
-                </p>
-                <table>
-                  <tr>
-                    <th>pID:</th>
-                    <td>(required) a unique numeric ID used to identify each row</td>
-                  </tr>
-                  <tr>
-                    <th>pName:</th>
-                    <td>(required) the task Label</td>
-                  </tr>
-                  <tr>
-                    <th>pStart:</th>
-                    <td>(required) the task start date, can enter empty date ('') for groups. You can also enter specific time (2016-02-20 12:00) for additional precision.</td>
-                  </tr>
-                  <tr>
-                    <th>pEnd:</th>
-                    <td>(required) the task end date, can enter empty date ('') for groups</td>
-                  </tr>
-                  <tr>
-                    <th>pClass:</th>
-                    <td>(required) the css class for this task</td>
-                  </tr>
-                  <tr>
-                    <th>pLink:</th>
-                    <td>(optional) any http link to be displayed in tool tip as the "More information" link.</td>
-                  </tr>
-                  <tr>
-                    <th>pMile:</th>
-                    <td>(optional) indicates whether this is a milestone task - Numeric; 1 = milestone, 0 = not milestone</td>
-                  </tr>
-                  <tr>
-                    <th>pRes:</th>
-                    <td>(optional) resource name</td>
-                  </tr>
-                  <tr>
-                    <th>pComp:</th>
-                    <td>(required) completion percent, numeric</td>
-                  </tr>
-                  <tr>
-                    <th>pGroup:</th>
-                    <td>(optional) indicates whether this is a group task (parent) - Numeric; 0 = normal task, 1 = standard group task, 2 = combined group task<a href='#combinedtasks' class="footnote">*</a></td>
-                  </tr>
-                  <tr>
-                    <th>pParent:</th>
-                    <td>(required) identifies a parent pID, this causes this task to be a child of identified task. Numeric, top level tasks should have pParent set to 0</td>
-                  </tr>
-                  <tr>
-                    <th>pOpen:</th>
-                    <td>(required) indicates whether a standard group task is open when chart is first drawn. Value must be set for all items but is only used by standard group tasks.  Numeric, 1 = open, 0 = closed</td>
-                  </tr>
-                  <tr>
-                    <th>pDepend:</th>
-                    <td>
-                      (optional) comma separated list of id&#39;s this task is dependent on. A line will be drawn from each listed task to this item<br />Each id can optionally be followed by a dependency type suffix. Valid values are:
-                      <blockquote>'FS' - Finish to Start (default if suffix is omitted)<br />'SF' - Start to Finish<br />'SS' - Start to Start<br />'FF' - Finish to Finish</blockquote>
-                      If present the suffix must be added directly to the id e.g. '123SS'
-                    </td>
-                  </tr>
-                  <tr>
-                    <th>pCaption:</th>
-                    <td>(optional) caption that will be added after task bar if CaptionType set to "Caption"</td>
-                  </tr>
-                  <tr>
-                    <th>pNotes:</th>
-                    <td>(optional) Detailed task information that will be displayed in tool tip for this task</td>
-                  </tr>
-                  <tr>
-                    <th>pGantt:</th>
-                    <td>(required) javascript JSGantt.GanttChart object from which to take settings.  Defaults to &quot;g&quot; for backwards compatibility</td>
-                  </tr>
-                </table>
-                <p id='combinedtasks'><span style="color: red;">*</span> Combined group tasks show all sub-tasks on one row. The information displayed in the task list and row caption are taken from the parent task.  Tool tips are generated individually for each sub-task from its own information.  Milestones are not valid as sub-tasks of a combined group task and will not be displayed. No bounds checking of start and end dates of sub-tasks is performed therefore it is possible for these task bars to overlap. Dependencies can be set to and from sub-tasks only.</p>
-              </li>
-              <li>
-                using parseXML() with an external XML file
-                <pre class="prettyprint lang-js"><code>JSGantt.parseXML("project.xml",g);</code></pre>
-                <p>Method definition:
-                  <strong>JSGantt.parseXML(<em>pFile, pGanttObj</em>)</strong>
-                </p>
-                <table>
-                  <tr>
-                    <th>pFile:</th>
-                    <td>(required) this is the filename of the XML</td>
-                  </tr>
-                  <tr>
-                    <th>pGanttObj:</th>
-                    <td>(required) a GanttChart object returned by a call to JSGantt.GanttChart()</td>
-                  </tr>
-                </table>
-                <p>The structure of the native XML file:</p>
-                <pre class="prettyprint lang-ml"><code>&lt;project&gt;
-  &lt;task&gt;
-    &lt;pID&gt;25&lt;/pID&gt;
-    &lt;pName&gt;WCF Changes&lt;/pName&gt;
-    &lt;pStart&gt;&lt;/pStart&gt;
-    &lt;pEnd&gt;&lt;/pEnd&gt;
-    &lt;pClass&gt;gtaskred&lt;/pClass&gt;
-    &lt;pLink&gt;&lt;/pLink&gt;
-    &lt;pMile&gt;0&lt;/pMile&gt;
-    &lt;pRes&gt;&lt;/pRes&gt;
-    &lt;pComp&gt;0&lt;/pComp&gt;
-    &lt;pGroup&gt;1&lt;/pGroup&gt;
-    &lt;pParent&gt;2&lt;/pParent&gt;
-    &lt;pOpen&gt;1&lt;/pOpen&gt;
-    &lt;pDepend&gt;2,24&lt;/pDepend&gt;
-    &lt;pCaption&gt;A caption&lt;/pCaption&gt;
-    &lt;pNotes&gt;Text - can include limited HTML&lt;/pNotes&gt;
-  &lt;/task&gt;
-&lt;/project&gt;</code></pre>
-                <p>Field definitions are as described for the parameters to TaskItem above. The pClass element is optional in XML files and will default to "ggroupblack" for group tasks, "gtaskblue" for normal tasks and "gmilestone" for milestones. The pGantt element is not required for XML import.</p>
-                <p>JSGannt Improved will also test the provided XML file to see if it appears to be in Microsoft Project XML format. If so an attempt will be made to load up the project. This feature is experimental, the import is best effort and not guaranteed. Once loaded the project as interpreted by JSGantt Improved can be extracted using the <a href="#xmlExport">XML Export methods</a> provided.</p>
-              </li>
-              <li>
-                using parseXMLString() with XML held in a javascript string object
-                <pre class="prettyprint lang-js"><code>JSGantt.parseXMLString("&lt;project&gt;&lt;task&gt;...&lt;/task&gt;&lt;/project&gt;",g);</code></pre>
-                <p>Method definition:
-                  <strong>JSGantt.parseXMLString(<em>pStr, pGanttObj</em>)</strong>
-                </p>
-                <table>
-                  <tr>
-                    <th>pStr:</th>
-                    <td>(required) this is a javascript String containing XML</td>
-                  </tr>
-                  <tr>
-                    <th>pGanttObj:</th>
-                    <td>(required) a GanttChart object returned by a call to JSGantt.GanttChart()</td>
-                  </tr>
-                </table>
-                <p>The XML provided will be parsed in exactly the same way as the contents of an external XML file and hence must match the format as described for JSGantt.parseXML() above</p>
-              </li>
-            </ul>
-          </li>
-          <li>
-            <p>Call Draw()</p>
-            <pre class="prettyprint lang-js"><code>g.Draw();</code></pre>
-          </li>
-          <li>
-            <p>Close the &lt;script&gt; block</p>
-            <pre class="prettyprint lang-html"><code>&lt;/script&gt;</code></pre>
-          </li>
-        </ol>
-        <p>It is possible to add items to the chart in realtime via javascript using either direct method calls or additional XML files.
-          It is also possible to delete tasks using RemoveTaskItem() method.
-        </p>
-        <pre class="prettyprint lang-js"><code>g.RemoveTaskItem(11);</code></pre>
-        <p>Method definition:
-          <strong>RemoveTaskItem(<em>pID</em>)</strong>
-        </p>
-        <table>
-          <tr>
-            <th>pID:</th>
-            <td>(required) the unique numeric ID of the item to be removed</td>
-          </tr>
-        </table>
-        <p>If the task removed is a group item, all child tasks will also be removed. </p>
-        <p>After adding or removing tasks a call to "g.Draw()" must be made to redraw the chart.</p>
-        <h2 id="options">Configuration Options</h2>
-        <h3>Switches</h3>
-        <p>Many of the features of jsGanttImproved can be customised through the use of setter methods available on the GanttChart object returned by a call to JSGantt.GanttChart()</p>
-        <p>The following options take a single numeric parameter; a value of 1 will enable the describe functionality, 0 will disable it</p>
-        <table class="configlist">
-          <tr>
-            <th id="setUseToolTip">setUseToolTip():</th>
-            <td>Controls the display of tool tip boxes, defaults to 1 (enabled)</td>
-          </tr>
-          <tr>
-            <th id="setUseFade">setUseFade():</th>
-            <td>Controls use of the fade effect when showing/hiding tool tips, defaults to 1 (enabled)</td>
-          </tr>
-          <tr>
-            <th id="setUseMove">setUseMove():</th>
-            <td>Controls use of the sliding effect when changing between different task tool tips, defaults to 1 (enabled)</td>
-          </tr>
-          <tr>
-            <th id="setUseRowHlt">setUseRowHlt():</th>
-            <td>Controls the use of row mouseover highlighting, defaults to 1 (enabled)</td>
-          </tr>
-          <tr>
-            <th id="setUseSort">setUseSort():</th>
-            <td>Controls whether the task list is sorted into parent task / start time order or is simply displayed in the order created, defaults to 1 (sort enabled)</td>
-          </tr>
-          <tr>
-            <th id="setShowRes">setShowRes():</th>
-            <td>Controls whether the Resource column is displayed in the task list, defaults to 1 (show column)</td>
-          </tr>
-          <tr>
-            <th id="setShowDur">setShowDur():</th>
-            <td>Controls whether the Task Duration column is displayed in the task list, defaults to 1 (show column)</td>
-          </tr>
-          <tr>
-            <th id="setShowComp">setShowComp():</th>
-            <td>Controls whether the Percentage Complete column is displayed in the task list, defaults to 1 (show column)</td>
-          </tr>
-          <tr>
-            <th id="setShowStartDate">setShowStartDate():</th>
-            <td>Controls whether the Task Start Date column is displayed in the task list, defaults to 1 (show column)</td>
-          </tr>
-          <tr>
-            <th id="setShowEndDate">setShowEndDate():</th>
-            <td>Controls whether the Task End Date column is displayed in the task list, defaults to 1 (show column)</td>
-          </tr>
-          <tr>
-            <th id="setShowTaskInfoRes">setShowTaskInfoRes():</th>
-            <td>Controls whether the Resource information is displayed in the task tool tip, defaults to 1 (show information)</td>
-          </tr>
-          <tr>
-            <th id="setShowTaskInfoDur">setShowTaskInfoDur():</th>
-            <td>Controls whether the Task Duration information is displayed in the task tool tip, defaults to 1 (show information)</td>
-          </tr>
-          <tr>
-            <th id="setShowTaskInfoComp">setShowTaskInfoComp():</th>
-            <td>Controls whether the Percentage Complete information is displayed in the task tool tip, defaults to 1 (show information)</td>
-          </tr>
-          <tr>
-            <th id="setShowTaskInfoStartDate">setShowTaskInfoStartDate():</th>
-            <td>Controls whether the Task Start Date information is displayed in the task tool tip, defaults to 1 (show information)</td>
-          </tr>
-          <tr>
-            <th id="setShowTaskInfoEndDate">setShowTaskInfoEndDate():</th>
-            <td>Controls whether the Task End Date information is displayed in the task tool tip, defaults to 1 (show information)</td>
-          </tr>
-          <tr>
-            <th id="setShowTaskInfoLink">setShowTaskInfoLink():</th>
-            <td>Controls whether the More Information link is displayed in the task tool tip, defaults to 0 (do NOT show link)</td>
-          </tr>
-          <tr>
-            <th id="setShowTaskInfoNotes">setShowTaskInfoNotes():</th>
-            <td>Controls whether the Additional Notes data is displayed in the task tool tip, defaults to 1 (show notes)</td>
-          </tr>
-          <tr>
-            <th id="setShowEndWeekDate">setShowEndWeekDate():</th>
-            <td>Controls whether the major heading in "Day" view displays the week end-date in the appropriate format (see <a href="#setDayMajorDateDisplayFormat">below</a>), defaults to 1 (show date)</td>
-          </tr>
-          <tr>
-            <th id="setShowDeps">setShowDeps():</th>
-            <td>Controls display of dependancy lines, defaults to 1 (show dependencies)</td>
-          </tr>
-        </table>
-        <h3>Key Values</h3>
-        <p>The following options enable functionality using a set of specific key values</p>
-        <table class="configlist">
-          <tr>
-            <th id="setShowSelector">setShowSelector():</th>
-            <td>Controls where the format selector is displayed, accepts multiple parameters.<br/>Valid parameter values are &quot;Top&quot;, &quot;Bottom&quot;.<br/>Defaults to "Top".</td>
-          </tr>
-          <tr>
-            <th id="setFormatArr">setFormatArr():</th>
-            <td>Controls which format options are shown in the format selector, accepts multiple parameters.<br/>Valid parameter values are &quot;Hour&quot;, &quot;Day&quot;, &quot;Week&quot;, &quot;Month&quot;, &quot;Quarter&quot;.<br/>Defaults to all valid values.</td>
-          </tr>
-          <tr>
-            <th id="setCaptionType">setCaptionType():</th>
-            <td>Controls which task field to use as a caption on the Gantt Chart task bar, accepts a single parameter.<br/>Valid parameter values are &quot;None&quot;, &quot;Caption&quot;, &quot;Resource&quot;, &quot;Duration&quot;, &quot;Complete&quot;.<br/>Defaults to &quot;None&quot;</td>
-          </tr>
-          <tr>
-            <th id="setDateInputFormat">setDateInputFormat():</th>
-            <td>Defines the input format used for dates in task creation, accepts a single parameter.<br/>Valid parameter values are &quot;yyyy-mm-dd&quot;, &quot;dd/mm/yyyy&quot;, &quot;mm/dd/yyyy&quot;.<br/>Defaults to &quot;yyyy-mm-dd&quot;</td>
-          </tr>
-          <tr>
-            <th id="setScrollTo">setScrollTo():</th>
-            <td>Sets the date the Gantt Chart will be scrolled to, specified in the date input format set by setDateInputFormat() above. Also accepts the special value &quot;today&quot;<br/>Defaults to minimum display date</td>
-          </tr>
-          <tr>
-            <th id="setUseSingleCell">setUseSingleCell():</th>
-            <td>Sets the threshold total number of cells at which the task list will use a single table cell for each row rather than one cell per period.  Useful to improve performance on large charts.  A value of 0 disables this functionality (always use multiple cells), defaults to 25000</td>
-          </tr>
-          <tr>
-            <th id="setLang">setLang():</th>
-            <td>Sets translation to use when drawing the chart.  Defaults to "en" as this is the only language provided in the base installation (see <a href="#optionsLanguage">internationalization</a> below for details on how to add more translations.)</td>
-          </tr>
-        </table>
-        <h3>Layout</h3>
-        <p>Most of the look and feel of the Gantt Chart can be controlled using CSS however, as the length of a task bar is determined by column width, the following methods take a single numeric parameter that defines the appropriate column width in pixels.</p>
-        <p>Note that the task bar sizing code assumes the use of collapsed table borders 1px wide.</p>
-        <table class="configlist">
-          <tr>
-            <th id="setHourColWidth">setHourColWidth():</th>
-            <td>Width of Gantt Chart columns in pixels when drawn in "Hour" format. Defaults to 18.</td>
-          </tr>
-          <tr>
-            <th id="setDayColWidth">setDayColWidth():</th>
-            <td>Width of Gantt Chart columns in pixels when drawn in "Day" format. Defaults to 18.</td>
-          </tr>
-          <tr>
-            <th id="setWeekColWidth">setWeekColWidth():</th>
-            <td>Width of Gantt Chart columns in pixels when drawn in "Week" format. Defaults to 36.</td>
-          </tr>
-          <tr>
-            <th id="setMonthColWidth">setMonthColWidth():</th>
-            <td>Width of Gantt Chart columns in pixels when drawn in "Month" format. Defaults to 36.</td>
-          </tr>
-          <tr>
-            <th id="setQuarterColWidth">setQuarterColWidth():</th>
-            <td>Width of Gantt Chart columns in pixels when drawn in "Quarter" format, although not mandatory it is recommended that this be set to a value divisible by 3. Defaults to 18.</td>
-          </tr>
-          <tr>
-            <th id="setRowHeight">setRowHeight():</th>
-            <td>Height of Gantt Chart rows in pixels. Used to route dependency lines near end points. Defaults to 20.</td>
-          </tr>
-          <tr>
-            <th id="setMinGpLen">setMinGpLen():</th>
-            <td>Group tasks have their task bars embellished with end points, this value specifies the width of one of these end points in pixels.  A short task bar&#39;s length will be rounded up to display either a single or both endpoints correctly. Defaults to 8.</td>
-          </tr>
-        </table>
-        <h3>Display Date Formats</h3>
-        <p>Date display formats can be individually controlled. The methods used to set these display formats each take a single format string parameter.  The format string can be made up of the following components (case sensitive)</p>
-        <blockquote>
-          <table>
-            <tr>
-              <th>h:</th>
-              <td>Hour (1-12)</td>
-            </tr>
-            <tr>
-              <th>hh:</th>
-              <td>Hour (01-12)</td>
-            </tr>
-            <tr>
-              <th>pm:</th>
-              <td>am/pm indicator</td>
-            </tr>
-            <tr>
-              <th>PM:</th>
-              <td>AM/PM indicator</td>
-            </tr>
-            <tr>
-              <th>H:</th>
-              <td>Hour (0-23)</td>
-            </tr>
-            <tr>
-              <th>HH:</th>
-              <td>Hour (01-23)</td>
-            </tr>
-            <tr>
-              <th>mi:</th>
-              <td>Minutes (1-59)</td>
-            </tr>
-            <tr>
-              <th>MI:</th>
-              <td>Minutes (01-59)</td>
-            </tr>
-            <tr>
-              <th>d:</th>
-              <td>Day (1-31)</td>
-            </tr>
-            <tr>
-              <th>dd:</th>
-              <td>Day (01-31)</td>
-            </tr>
-            <tr>
-              <th>day:</th>
-              <td>Abbreviated day of week</td>
-            </tr>
-            <tr>
-              <th>DAY:</th>
-              <td>Day of week</td>
-            </tr>
-            <tr>
-              <th>m:</th>
-              <td>Month (1-12)</td>
-            </tr>
-            <tr>
-              <th>mm:</th>
-              <td>Month (01-12)</td>
-            </tr>
-            <tr>
-              <th>mon:</th>
-              <td>Abbreviated month text</td>
-            </tr>
-            <tr>
-              <th>month:</th>
-              <td>Full month text</td>
-            </tr>
-            <tr>
-              <th>yy:</th>
-              <td>Year, excluding century</td>
-            </tr>
-            <tr>
-              <th>yyyy:</th>
-              <td>Year</td>
-            </tr>
-            <tr>
-              <th>q:</th>
-              <td>Quarter (1-4)</td>
-            </tr>
-            <tr>
-              <th>qq:</th>
-              <td>Quarter (Q1-Q4)</td>
-            </tr>
-            <tr>
-              <th>w:</th>
-              <td>ISO Week number (1-53)</td>
-            </tr>
-            <tr>
-              <th>ww:</th>
-              <td>ISO Week number (01-53)</td>
-            </tr>
-            <tr>
-              <th>week:</th>
-              <td>Full ISO Week date format</td>
-            </tr>
-          </table>
-          <p>separated by one of the following characters: <strong>&quot;/\-.,&#39;&lt;space&gt;:</strong></p>
-          <p>Any text between separators that does not match one of the components above will be checked using a case insensitive match for a valid internationalized string (see <a href="#optionsLanguage">internationalization</a> below).  If the value is still not found the text will be output unchanged.</p>
-        </blockquote>
-        <p>The available date display methods are</p>
-        <table class="dateconfiglist">
-          <tr>
-            <th id="setDateTaskTableDisplayFormat">setDateTaskTableDisplayFormat():</th>
-            <td>Date format used for start and end dates in the main task list. Defaults to 'dd/mm/yyyy'.</td>
-          </tr>
-          <tr>
-            <th id="setDateTaskDisplayFormat">setDateTaskDisplayFormat():</th>
-            <td>Date format used for start and end dates in task tool tips. Defaults to 'dd month yyyy'.</td>
-          </tr>
-          <tr>
-            <th id="setHourMajorDateDisplayFormat">setHourMajorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart major date headings displayed in "Hour" format. Defaults to 'day dd month yyyy'.</td>
-          </tr>
-          <tr>
-            <th id="setDayMajorDateDisplayFormat">setDayMajorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart major date headings displayed in "Day" format. Defaults to 'dd/mm/yyyy'.</td>
-          </tr>
-          <tr>
-            <th id="setWeekMajorDateDisplayFormat">setWeekMajorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart major date headings displayed in "Week" format. Defaults to 'yyyy'.</td>
-          </tr>
-          <tr>
-            <th id="setMonthMajorDateDisplayFormat">setMonthMajorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart major date headings displayed in "Month" format. Defaults to 'yyyy'.</td>
-          </tr>
-          <tr>
-            <th id="setQuarterMajorDateDisplayFormat">setQuarterMajorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart major date headings displayed in "Year" format. Defaults to 'yyyy'.</td>
-          </tr>
-          <tr>
-            <th id="setHourMinorDateDisplayFormat">setHourMinorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart minor date headings displayed in "Hour" format. Defaults to 'HH'.</td>
-          </tr>
-          <tr>
-            <th id="setDayMinorDateDisplayFormat">setDayMinorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart minor date headings displayed in "Day" format. Defaults to 'dd'.</td>
-          </tr>
-          <tr>
-            <th id="setWeekMinjorDateDisplayFormat">setWeekMinjorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart minor date headings displayed in "Week" format. Defaults to 'dd/mm'.</td>
-          </tr>
-          <tr>
-            <th id="setMonthMinorDateDisplayFormat">setMonthMinorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart minor date headings displayed in "Month" format. Defaults to 'mon'.</td>
-          </tr>
-          <tr>
-            <th id="setQuarterMinorDateDisplayFormat">setQuarterMinorDateDisplayFormat():</th>
-            <td>Date format used for Gantt Chart minor date headings displayed in "Year" format. Defaults to 'qq'.</td>
-          </tr>
-        </table>
-        <h3 id="optionsLanguage">Internationalization</h3>
-        <p>jsGanttImproved only provides English text however all hard coded strings can be replaced by calling the addLang() method available on the GanttChart object returned by a call to JSGantt.GanttChart()</p>
-        <p>The addLang() method takes two parameters.  The first is a string identifier for the language, the second is a javascript object containing all the replacement text pairs, the default English settings are:</p>
-        <blockquote>
-          <table class="multipleColumns">
-            <tbody>
-              <tr>
-                <td class="lang">
-                  <table>
-                    <tr>
-                      <th>january:</th>
-                      <td>January</td>
-                    </tr>
-                    <tr>
-                      <th>february:</th>
-                      <td>February</td>
-                    </tr>
-                    <tr>
-                      <th>march:</th>
-                      <td>March</td>
-                    </tr>
-                    <tr>
-                      <th>april:</th>
-                      <td>April</td>
-                    </tr>
-                    <tr>
-                      <th>maylong:</th>
-                      <td>May</td>
-                    </tr>
-                    <tr>
-                      <th>june:</th>
-                      <td>June</td>
-                    </tr>
-                    <tr>
-                      <th>july:</th>
-                      <td>July</td>
-                    </tr>
-                    <tr>
-                      <th>august:</th>
-                      <td>August</td>
-                    </tr>
-                    <tr>
-                      <th>september:</th>
-                      <td>September</td>
-                    </tr>
-                    <tr>
-                      <th>october:</th>
-                      <td>October</td>
-                    </tr>
-                    <tr>
-                      <th>november:</th>
-                      <td>November</td>
-                    </tr>
-                    <tr>
-                      <th>december:</th>
-                      <td>December</td>
-                    </tr>
-                    <tr>
-                      <th>jan:</th>
-                      <td>Jan</td>
-                    </tr>
-                    <tr>
-                      <th>feb:</th>
-                      <td>Feb</td>
-                    </tr>
-                    <tr>
-                      <th>mar:</th>
-                      <td>Mar</td>
-                    </tr>
-                    <tr>
-                      <th>apr:</th>
-                      <td>Apr</td>
-                    </tr>
-                    <tr>
-                      <th>may:</th>
-                      <td>May</td>
-                    </tr>
-                    <tr>
-                      <th>jun:</th>
-                      <td>Jun</td>
-                    </tr>
-                    <tr>
-                      <th>jul:</th>
-                      <td>Jul</td>
-                    </tr>
-                    <tr>
-                      <th>aug:</th>
-                      <td>Aug</td>
-                    </tr>
-                    <tr>
-                      <th>sep:</th>
-                      <td>Sep</td>
-                    </tr>
-                    <tr>
-                      <th>oct:</th>
-                      <td>Oct</td>
-                    </tr>
-                    <tr>
-                      <th>nov:</th>
-                      <td>Nov</td>
-                    </tr>
-                    <tr>
-                      <th>dec:</th>
-                      <td>Dec</td>
-                    </tr>
-                  </table>
-                </td>
-                <td class="lang">
-                  <table>
-                    <tr>
-                      <th>sunday:</th>
-                      <td>Sunday</td>
-                    </tr>
-                    <tr>
-                      <th>monday:</th>
-                      <td>Monday</td>
-                    </tr>
-                    <tr>
-                      <th>tuesday:</th>
-                      <td>Tuesday</td>
-                    </tr>
-                    <tr>
-                      <th>wednesday:</th>
-                      <td>Wednesday</td>
-                    </tr>
-                    <tr>
-                      <th>thursday:</th>
-                      <td>Thursday</td>
-                    </tr>
-                    <tr>
-                      <th>friday:</th>
-                      <td>Friday</td>
-                    </tr>
-                    <tr>
-                      <th>saturday:</th>
-                      <td>Saturday</td>
-                    </tr>
-                    <tr>
-                      <th>sun:</th>
-                      <td>Sun</td>
-                    </tr>
-                    <tr>
-                      <th>mon:</th>
-                      <td>Mon</td>
-                    </tr>
-                    <tr>
-                      <th>tue:</th>
-                      <td>Tue</td>
-                    </tr>
-                    <tr>
-                      <th>wed:</th>
-                      <td>Wed</td>
-                    </tr>
-                    <tr>
-                      <th>thu:</th>
-                      <td>Thu</td>
-                    </tr>
-                    <tr>
-                      <th>fri:</th>
-                      <td>Fri</td>
-                    </tr>
-                    <tr>
-                      <th>sat:</th>
-                      <td>Sat</td>
-                    </tr>
-                    <tr>
-                      <th>resource:</th>
-                      <td>Resource</td>
-                    </tr>
-                    <tr>
-                      <th>duration:</th>
-                      <td>Duration</td>
-                    </tr>
-                    <tr>
-                      <th>comp:</th>
-                      <td>% Comp.</td>
-                    </tr>
-                    <tr>
-                      <th>completion:</th>
-                      <td>Completion</td>
-                    </tr>
-                    <tr>
-                      <th>startdate:</th>
-                      <td>Start Date</td>
-                    </tr>
-                    <tr>
-                      <th>enddate:</th>
-                      <td>End Date</td>
-                    </tr>
-                    <tr>
-                      <th>moreinfo:</th>
-                      <td>More Information</td>
-                    </tr>
-                    <tr>
-                      <th>notes:</th>
-                      <td>Notes</td>
-                    </tr>
-                  </table>
-                </td>
-                <td class="lang">
-                  <table>
-                    <tr>
-                      <th>format:</th>
-                      <td>Format</td>
-                    </tr>
-                    <tr>
-                      <th>hour:</th>
-                      <td>Hour</td>
-                    </tr>
-                    <tr>
-                      <th>day:</th>
-                      <td>Day</td>
-                    </tr>
-                    <tr>
-                      <th>week:</th>
-                      <td>Week</td>
-                    </tr>
-                    <tr>
-                      <th>month:</th>
-                      <td>Month</td>
-                    </tr>
-                    <tr>
-                      <th>quarter:</th>
-                      <td>Quarter</td>
-                    </tr>
-                    <tr>
-                      <th>hours:</th>
-                      <td>Hours</td>
-                    </tr>
-                    <tr>
-                      <th>days:</th>
-                      <td>Days</td>
-                    </tr>
-                    <tr>
-                      <th>weeks:</th>
-                      <td>Weeks</td>
-                    </tr>
-                    <tr>
-                      <th>months:</th>
-                      <td>Months</td>
-                    </tr>
-                    <tr>
-                      <th>quarters:</th>
-                      <td>Quarters</td>
-                    </tr>
-                    <tr>
-                      <th>hr:</th>
-                      <td>Hr</td>
-                    </tr>
-                    <tr>
-                      <th>dy:</th>
-                      <td>Day</td>
-                    </tr>
-                    <tr>
-                      <th>wk:</th>
-                      <td>Wk</td>
-                    </tr>
-                    <tr>
-                      <th>mth:</th>
-                      <td>Mth</td>
-                    </tr>
-                    <tr>
-                      <th>qtr:</th>
-                      <td>Qtr</td>
-                    </tr>
-                    <tr>
-                      <th>hrs:</th>
-                      <td>Hrs</td>
-                    </tr>
-                    <tr>
-                      <th>dys:</th>
-                      <td>Days</td>
-                    </tr>
-                    <tr>
-                      <th>wks:</th>
-                      <td>Wks</td>
-                    </tr>
-                    <tr>
-                      <th>mths:</th>
-                      <td>Mths</td>
-                    </tr>
-                    <tr>
-                      <th>qtrs:</th>
-                      <td>Qtrs</td>
-                    </tr>
-                  </table>
-                </td>
-            </tbody>
-          </table>
-        </blockquote>
-        <p>When adding a language any translations that are not provided will use the default English language value.  This provides a simple way to override default strings e.g.</p>
-        <pre class="prettyprint lang-js"><code>g.addLang('en2', {'format':'Select', 'comp':'Complete'});</code></pre>
-        <p>would create a language called 'en2' where the text in the format selector was "Select" rather than "Format" and the header for the Percentage Complete column in the task list is "Complete" rather than "% Comp."</p>
-        <p>Once a translation has been added a call must be made to <a href="#setLang">setLang()</a> with the appropriate langage identifier before calling Draw().</p>
-        <h3 id="tOptionsExamples">Example Options</h3>
-        <p>The configuration options used in the example chart above are:</p>
-        <pre class="prettyprint lang-js"><code>g.setCaptionType('Complete');  // Set to Show Caption (None,Caption,Resource,Duration,Complete)
-g.setQuarterColWidth(36);
-g.setDateTaskDisplayFormat('day dd month yyyy'); // Shown in tool tip box
-g.setDayMajorDateDisplayFormat('mon yyyy - Week ww'); // Set format to display dates in the "Major" header of the "Day" view
-g.setWeekMinorDateDisplayFormat('dd mon'); // Set format to display dates in the "Minor" header of the "Week" view
-g.setShowTaskInfoLink(1); //Show link in tool tip (0/1)
-g.setShowEndWeekDate(0); // Show/Hide the date for the last day of the week in header for daily view (1/0)
-g.setUseSingleCell(10000); // Set the threshold at which we will only use one cell per table row (0 disables).  Helps with rendering performance for large charts.
-g.setFormatArr('Day', 'Week', 'Month', 'Quarter'); // Even with setUseSingleCell using Hour format on such a large chart can cause issues in some browsers
-        </code></pre>
-        <p>Putting all this information together the final code to produce the chart above is as follows:</p>
-        <pre class="prettyprint lang-html"><code>&lt;link rel="stylesheet" type="text/css" href="jsgantt.css" /&gt;
-&lt;script language="javascript" src="jsgantt.js"&gt;&lt;/script&gt;
-&lt;div style="position:relative" class="gantt" id="GanttChartDIV"&gt;&lt;/div&gt;
-&lt;script&gt;
-
-var g = new JSGantt.GanttChart('g',document.getElementById('GanttChartDIV'), 'day');
-
-if( g.getDivId() != null ) {
-g.setCaptionType('Complete');
-g.setQuarterColWidth(36);
-g.setDateTaskDisplayFormat('day dd month yyyy');
-g.setDayMajorDateDisplayFormat('mon yyyy - Week ww');
-g.setWeekMinorDateDisplayFormat('dd mon');
-g.setShowTaskInfoLink(1);
-g.setShowEndWeekDate(0);
-g.setUseSingleCell(10000);
-g.setFormatArr('Day', 'Week', 'Month', 'Quarter');
-
-g.AddTaskItem(new JSGantt.TaskItem(1,   'Define Chart API',     '',           '',          'ggroupblack',  '',       0, 'Brian',    0,   1, 0,  1, '',      '',      'Some Notes text', g ));
-g.AddTaskItem(new JSGantt.TaskItem(11,  'Chart Object',         '2016-02-20','2016-02-20', 'gmilestone',   '',       1, 'Shlomy',   100, 0, 1,  1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(12,  'Task Objects',         '',           '',          'ggroupblack',  '',       0, 'Shlomy',   40,  1, 1,  1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(121, 'Constructor Proc',     '2016-02-21','2016-03-09', 'gtaskblue',    '',       0, 'Brian T.', 60,  0, 12, 1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(122, 'Task Variables',       '2016-03-06','2016-03-11', 'gtaskred',     '',       0, 'Brian',    60,  0, 12, 1, 121,     '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(123, 'Task by Minute/Hour',  '2016-03-09','2016-03-14 12:00', 'gtaskyellow', '',  0, 'Ilan',     60,  0, 12, 1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(124, 'Task Functions',       '2016-03-09','2016-03-29', 'gtaskred',     '',       0, 'Anyone',   60,  0, 12, 1, '123SS', 'This is a caption', null, g));
-g.AddTaskItem(new JSGantt.TaskItem(2,   'Create HTML Shell',    '2016-03-24','2016-03-24', 'gtaskyellow',  '',       0, 'Brian',    20,  0, 0,  1, 122,     '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(3,   'Code Javascript',      '',           '',          'ggroupblack',  '',       0, 'Brian',    0,   1, 0,  1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(31,  'Define Variables',     '2016-02-25','2016-03-17', 'gtaskpurple',  '',       0, 'Brian',    30,  0, 3,  1, '',      'Caption 1','',   g));
-g.AddTaskItem(new JSGantt.TaskItem(32,  'Calculate Chart Size', '2016-03-15','2016-03-24', 'gtaskgreen',   '',       0, 'Shlomy',   40,  0, 3,  1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(33,  'Draw Task Items',      '',           '',          'ggroupblack',  '',       0, 'Someone',  40,  2, 3,  1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(332, 'Task Label Table',     '2016-03-06','2016-03-09', 'gtaskblue',    '',       0, 'Brian',    60,  0, 33, 1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(333, 'Task Scrolling Grid',  '2016-03-11','2016-03-20', 'gtaskblue',    '',       0, 'Brian',    0,   0, 33, 1, '332',   '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(34,  'Draw Task Bars',       '',           '',          'ggroupblack',  '',       0, 'Anybody',  60,  1, 3,  0, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(341, 'Loop each Task',       '2016-03-26','2016-04-11', 'gtaskred',     '',       0, 'Brian',    60,  0, 34, 1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(342, 'Calculate Start/Stop', '2016-04-12','2016-05-18', 'gtaskpink',    '',       0, 'Brian',    60,  0, 34, 1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(343, 'Draw Task Div',        '2016-05-13','2016-05-17', 'gtaskred',     '',       0, 'Brian',    60,  0, 34, 1, '',      '',      '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(344, 'Draw Completion Div',  '2016-05-17','2016-06-04', 'gtaskred',     '',       0, 'Brian',    60,  0, 34, 1, "342,343",'',     '',      g));
-g.AddTaskItem(new JSGantt.TaskItem(35,  'Make Updates',         '2016-07-17','2017-09-04', 'gtaskpurple',  '',       0, 'Brian',    30,  0, 3,  1, '333',   '',      '',      g));
-
-g.Draw();
-}
-else
-{
-alert("Error, unable to create Gantt Chart");
-}
-
-&lt;/script&gt;</code></pre>
-        <h2 id="xmlExport">XML Export</h2>
-        <p>The following methods can be used to extract details of tasks in the project in XML format</p>
-        <p>Method definition: <strong>getXMLProject()</strong></p>
-        <p>Returns a string containing the entire project in JSGantt Improved XML format. Dates will be exported in the currently defined input format as set by setDateInputFormat()</p>
-        <p>Method definition: <strong>getXMLTask(<em>pID, pIdx</em>)</strong></p>
-        <table>
-          <tr>
-            <th>pID:</th>
-            <td>(required) the numeric ID that identifies the task to extract</td>
-          </tr>
-          <tr>
-            <th>pIdx:</th>
-            <td>(optional) Boolean - if present and set to "true" the number passed in the pID parameter is treated as an array index for the task list rather than an ID</td>
-          </tr>
-        </table>
-        <p>Returns a string containing the specified task item in JSGantt Improved XML format. Dates will be exported in the currently defined input format as set by setDateInputFormat()</p>
-      </div>
-    <!-- Credits -->
-      <div class="container-fluid section" id="credits">
-        <h1>Credits</h1>
-        <div class="card-group">
-          <div class="card contact-card">
-            <img class="img-fluid" src="https://avatars.githubusercontent.com/eduardomourar" alt="Eduardo Rodrigues">
-            <div class="card-block">
-              <h4 class="card-title">Eduardo Rodrigues</h4>
-              <p class="card-text">Developer</p>
-              <div class="text-right">
-                <a href="https://github.com/eduardomourar" class="card-link contact-link"><i class="fa fa-github"></i></a>
-              </div>
-            </div>
-          </div>
-          <div class="card contact-card">
-            <img class="img-fluid" src="https://avatars.githubusercontent.com/RickCardoso" alt="Ricardo Cardoso">
-            <div class="card-block">
-              <h4 class="card-title">Ricardo Cardoso</h4>
-              <p class="card-text">Developer</p>
-              <div class="text-right">
-                <a href="https://github.com/RickCardoso" class="card-link contact-link"><i class="fa fa-github"></i></a>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-    <!-- Footer -->
-      <div class="footer text-center">
-        <p>© Copyright 2013-2017 jsGanttImproved<br />
-        Designed with <a href="https://v4-alpha.getbootstrap.com" target="_blank">Bootstrap</a> and <a href="http://fontawesome.io" target="_blank">Font Awesome</a></p>
-      </div>
-
-  </body>
-
-</html>

+ 867 - 128
htdocs/includes/jsgantt/jsgantt.css

@@ -1,228 +1,793 @@
-/* Sample CSS for jsGanttImproved v1.7.5.4 */
-div.gantt		{ font-family:tahoma, arial, verdana, Sans-serif; font-size:10px; color: #656565; }
+/* Sample CSS for jsGanttImproved v1.8.0 */
 
-.gantt table	{ border-collapse: collapse; }
-.gantt td { padding: 0px; }
+div.gantt {
+  font-family: tahoma, arial, verdana, Sans-serif;
+  font-size: 10px;
+  color: #656565;
+}
+
+.gantt table {
+  border-collapse: collapse;
+}
+
+.gantt td {
+  padding: 0px;
+}
 
 /* cell defaults */
+.headweekends div {
+  font-size: 8px;
+  width: 100% !important;
+  margin: 0;
+}
+
 .gmajorheading,
 .gminorheading,
 .gminorheadingwkend,
 .gtaskcell,
-.gtaskcellwkend				{ height: 19px; font-size: 12px; border: #efefef 1px solid; text-align: center; cursor: default }
-.gtasklist					{ height: 19px; min-width: 5px; max-width: 5px; width: 5px; border: #efefef 1px solid; border-right: none; } /* all three width values set just to make sure - helps resizing code */
+.gtaskcellcurrent,
+.gtaskcellwkend {
+  height: 19px;
+  font-size: 12px;
+  border: #efefef 1px solid;
+  text-align: center;
+  cursor: default
+}
+
+
+.gtasklist {
+  height: 19px;
+  min-width: 5px;
+  max-width: 5px;
+  width: 5px;
+  border: #efefef 1px solid;
+  border-right: none;
+}
+
+.gtasknolist-label{
+  padding: 10px 50px;
+}
+/* all three width values set just to make sure - helps resizing code */
 
 /* Additional values for some cell elements */
+
 .gtaskheading,
 .gmajorheading,
-.gminorheading				{ background-color: #ffffff; font-weight: bold; font-size: 9px; white-space: nowrap; }
+.gminorheading {
+  background-color: #ffffff;
+  font-weight: bold;
+  font-size: 9px;
+  white-space: nowrap;
+}
+
 .gtaskcellwkend,
-.gminorheadingwkend			{ background-color: #f7f7f7; font-weight: bold; font-size: 9px; white-space: nowrap; }
-td.gtaskcell				{ text-align: left }
-td.gspanning				{ border-left: none; border-right: none; }
-.gtaskcelldiv				{ position: relative; }
+.gtaskcellcurrent,
+.gminorheadingwkend {
+  background-color: #f7f7f7;
+  font-weight: bold;
+  font-size: 9px;
+  white-space: nowrap;
+}
+
+.gtaskcellcurrent {
+  background-color: #e1e0f7;
+}
+
+td.gtaskcell {
+  text-align: left;
+}
+
+td.gspanning {
+  border-left: none;
+  border-right: none;
+}
+
+.gtaskcelldiv {
+  position: relative;
+}
 
 /* Task list defaults */
+
 .gtaskheading,
 .gname,
 .gtaskname,
-.gresource,
-.gduration,
-.gpccomplete,
+.gres,
+.gdur,
+.gcomp,
 .gstartdate,
-.genddate					{ height: 18px; white-space: nowrap; border: #efefef 1px solid; }
+.gplanstartdate,
+.gplanenddate,
+.gcost,
+.genddate {
+  height: 18px;
+  white-space: nowrap;
+  border: #efefef 1px solid;
+}
+
+.gtaskheading div,
+.gname div,
+.gtaskname div,
+.gres div,
+.gdur div,
+.gcomp div,
+.gstartdate div,
+.gplanstartdate div,
+.gplanenddate div,
+.gcost div,
+.genddate div {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.gtaskbarcontainer.gplan {
+  position: absolute !important;
+  top: 0px;
+  opacity: 0.3;
+  background: white;
+  z-index: 10000;
+  border: 1px solid black;
+}
 
 /* Additional values for some task list elements */
-.gresource,
-.gduration,
-.gpccomplete,
-.gstartdate div, /* needed for IE8 */
-.gstartdate					{ text-align: center; min-width: 70px; max-width: 70px; width: 70px; font-size: 10px; }
-.genddate div, /* needed for IE8 */
-.genddate					{ text-align: center; min-width: 70px; max-width: 70px; width: 70px; font-size: 10px; }
-.gtaskheading				{ text-align: center; }
-.gtaskname div, /* needed for IE8 */
-.gtaskname					{ min-width: 170px; max-width: 170px; width: 170px; font-size: 9px; border-left: none; }
-
-.gselector					{ text-align: left; white-space: nowrap; min-width: 170px; max-width: 170px; width: 170px; }
-
-.gformlabel					{ position:relative; top:0px; cursor:pointer; border: #ffffff 1px solid; margin-left: 2px; padding-left: 2px; padding-right: 2px; }
+
+/* needed for IE8 */
+
+.gstartdate div,
+.gplanstartdate,
+.gplanenddate,
+.gstartdate,
+.genddate {
+  text-align: center;
+  min-width: 105px;
+  width: 105px;
+  max-width: 105px;
+  font-size: 10px;
+}
+
+.gtaskheading {
+  text-align: center;
+}
+
+.gtaskname div,
+/* needed for IE8 */
+
+.gtaskname {
+  min-width: 170px;
+  max-width: 170px;
+  width: 170px;
+  font-size: 9px;
+  border-left: none;
+}
+
+.gtaskheading,
+.gtaskname {
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+
+.gtaskname.gtaskeditable div,
+.gtaskname.gtaskeditable {
+  overflow: unset;
+}
+
+.gselector {
+  text-align: left;
+  white-space: nowrap;
+  min-width: 170px;
+  max-width: 170px;
+  width: 170px;
+}
+
+.gformlabel {
+  position: relative;
+  top: 0px;
+  cursor: pointer;
+  border: #ffffff 1px solid;
+  margin-left: 2px;
+  padding-left: 2px;
+  padding-right: 2px;
+}
+
 span.gformlabel:hover,
-span.gselected				{ background-color: #dbecff; border: #cccccc 1px solid;}
+span.gselected {
+  background-color: #dbecff;
+  border: #cccccc 1px solid;
+}
 
-span.gfoldercollapse		{ color:#000000; cursor:pointer; font-weight:bold; font-size: 12px; font-family: Courier, "Courier New", monospace; }
+span.gfoldercollapse {
+  color: #000000;
+  cursor: pointer;
+  font-weight: bold;
+  font-size: 12px;
+  font-family: Courier, "Courier New", monospace;
+}
 
 .gtasktableh,
-.gtasktable					{ border-right: #efefef 1px solid; }
-.gcharttable				{ border: #efefef 1px solid; }  /* for some reason firefox needs this */
+.gtasktable {
+  border-right: #efefef 1px solid;
+  width: 100%;
+}
+
+.gcharttableh,
+.gtasktableh,
+.gtasktable,
+.gcharttable {
+  border-collapse: collapse;
+}
+
+.gcharttable,
+.gcharttableh {
+  table-layout: fixed;
+}
+
+.gcharttable {
+  border: #efefef 1px solid;
+}
+
+/* for some reason firefox needs this */
 
 /* Differentiate Group, Milestone and Ordinary task items (applied to row) */
-.ggroupitem					{ background-color: #fbfbfb; font-weight: bold; }
+
+.ggroupitem {
+  background-color: #fbfbfb;
+  font-weight: bold;
+}
+
 .gmileitem,
-.glineitem					{ background-color: #ffffff; }
+.glineitem {
+  background-color: #ffffff;
+}
 
 /* highlight row (applied to row) */
-.gitemhighlight	td			{ background-image: none; background-color: #fffde5;}
+
+.gitemhighlight td {
+  background-image: none;
+  background-color: #fffde5;
+}
 
 /* task bar caption text styles */
+
 .gmilecaption,
 .ggroupcaption,
-.gcaption					{ font-weight: normal; font-size: 9px; text-align: left; white-space: nowrap; top:1px; position: absolute; top:2px; }
+.gcaption {
+  font-weight: normal;
+  font-size: 9px;
+  text-align: left;
+  white-space: nowrap;
+  top: 1px;
+  position: absolute;
+  top: 2px;
+}
 
 .ggroupcaption,
-.gcaption					{ right: -126px; }
+.gcaption {
+  right: -126px;
+}
 
 /* Task complete %age bar shared attributes */
-.gtaskcomplete				{ float:left; overflow: hidden; }
+
+.gtaskcomplete {
+  float: left;
+  overflow: hidden;
+}
 
 /* Task complete %age bar */
-.gtaskcomplete				{ height:5px; background-color:#000000; margin-top:4px; opacity:0.4; filter: alpha(opacity=40); }
+
+.gtaskcomplete {
+  height: 5px;
+  background-color: #000000;
+  margin-top: 4px;
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
 
 /* Milestones */
-.gmilestone					{ font-size: 14px; position: absolute; top: -2px; }
-.gmdtop						{ top: 2px; overflow: hidden; width:0px; height:0px; border-bottom: 5px solid black; border-left: 5px solid transparent; border-top: 5px solid transparent; border-right: 5px solid transparent;}
-.gmdbottom					{ top: 2px; overflow: hidden; width:0px; height:0px; border-top: 5px solid black; border-left: 5px solid transparent; border-bottom: 5px solid transparent; border-right: 5px solid transparent;}
+
+.gmilestone {
+  font-size: 14px;
+  position: absolute;
+  top: -2px;
+}
+
+.gmdtop {
+  top: 2px;
+  overflow: hidden;
+  width: 0px;
+  height: 0px;
+  border-bottom: 5px solid black;
+  border-left: 5px solid transparent;
+  border-top: 5px solid transparent;
+  border-right: 5px solid transparent;
+}
+
+.gmdbottom {
+  top: 2px;
+  overflow: hidden;
+  width: 0px;
+  height: 0px;
+  border-top: 5px solid black;
+  border-left: 5px solid transparent;
+  border-bottom: 5px solid transparent;
+  border-right: 5px solid transparent;
+}
 
 /* Task bar shared attributes */
+
 .ggroupblack,
 .gtaskblue,
 .gtaskred,
 .gtaskgreen,
 .gtaskyellow,
 .gtaskpurple,
-.gtaskpink					{ height: 13px; filter: alpha(opacity=90); opacity:0.9; margin-top: 1px; }
+.gtaskpink {
+  height: 13px;
+  filter: alpha(opacity=90);
+  opacity: 0.9;
+  margin-top: 1px;
+}
 
 /* Task bars - ggroupblack is set as the default class on the task if it is undefined */
-.ggroupblack { height: 7px; background: #000000; margin-top: 2px; }
-.ggroupblackendpointleft	{ overflow: hidden; width:0px; height:0px; top: 2px; border-top: 4px solid black; border-left: 4px solid transparent; border-bottom: 4px solid transparent; border-right: 4px solid transparent; float: left; }
-.ggroupblackendpointright	{ overflow: hidden; width:0px; height:0px; top: 2px; border-top: 4px solid black; border-left: 4px solid transparent; border-bottom: 4px solid transparent; border-right: 4px solid transparent; float: right; }
-.ggroupblackcomplete		{ float:left; overflow: hidden; height:3px; filter: alpha(opacity=80); opacity:0.8; background-color:#777777; margin-top:2px; margin-bottom: 2px; }
+
+.ggroupblack {
+  height: 7px;
+  background: #000000;
+  margin-top: 2px;
+}
+
+.ggroupblackendpointleft {
+  overflow: hidden;
+  width: 0px;
+  height: 0px;
+  top: 2px;
+  border-top: 4px solid black;
+  border-left: 4px solid transparent;
+  border-bottom: 4px solid transparent;
+  border-right: 4px solid transparent;
+  float: left;
+}
+
+.ggroupblackendpointright {
+  overflow: hidden;
+  width: 0px;
+  height: 0px;
+  top: 2px;
+  border-top: 4px solid black;
+  border-left: 4px solid transparent;
+  border-bottom: 4px solid transparent;
+  border-right: 4px solid transparent;
+  float: right;
+}
+
+.ggroupblackcomplete {
+  float: left;
+  overflow: hidden;
+  height: 3px;
+  filter: alpha(opacity=80);
+  opacity: 0.8;
+  background-color: #777777;
+  margin-top: 2px;
+  margin-bottom: 2px;
+}
+
 .gtaskblue {
-	background: rgb(58,132,195); /* Old browsers */
-	background: linear-gradient(to bottom,  rgba(58,132,195,1) 0%,rgba(65,154,214,1) 20%,rgba(75,184,240,1) 40%,rgba(58,139,194,1) 70%,rgba(38,85,139,1) 100%); /* W3C */
-	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4bb8f0', endColorstr='#3a84c3',GradientType=0 ); /* IE6-9 */
+  background: rgb(58, 132, 195);
+  /* Old browsers */
+  background: linear-gradient(to bottom, rgba(58, 132, 195, 1) 0%, rgba(65, 154, 214, 1) 20%, rgba(75, 184, 240, 1) 40%, rgba(58, 139, 194, 1) 70%, rgba(38, 85, 139, 1) 100%);
+  /* W3C */
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4bb8f0', endColorstr='#3a84c3', GradientType=0);
+  /* IE6-9 */
 }
+
 .gtaskred {
-	background: rgb(196,58,58); /* Old browsers */
-	background: linear-gradient(to bottom,  rgba(196,58,58,1) 0%,rgba(211,65,65,1) 20%,rgba(239,76,76,1) 40%,rgba(196,58,58,1) 70%,rgba(135,37,37,1) 100%); /* W3C */
-	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ef4c4c', endColorstr='#c43a3a',GradientType=0 ); /* IE6-9 */
+  background: rgb(196, 58, 58);
+  /* Old browsers */
+  background: linear-gradient(to bottom, rgba(196, 58, 58, 1) 0%, rgba(211, 65, 65, 1) 20%, rgba(239, 76, 76, 1) 40%, rgba(196, 58, 58, 1) 70%, rgba(135, 37, 37, 1) 100%);
+  /* W3C */
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ef4c4c', endColorstr='#c43a3a', GradientType=0);
+  /* IE6-9 */
 }
+
 .gtaskgreen {
-	background: rgb(80,193,58); /* Old browsers */
-	background: linear-gradient(to bottom,  rgba(80,193,58,1) 0%,rgba(88,209,64,1) 20%,rgba(102,237,75,1) 40%,rgba(80,193,58,1) 70%,rgba(53,132,37,1) 100%); /* W3C */
-	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#66ED4B', endColorstr='#50c13a',GradientType=0 ); /* IE6-9 */
+  background: rgb(80, 193, 58);
+  /* Old browsers */
+  background: linear-gradient(to bottom, rgba(80, 193, 58, 1) 0%, rgba(88, 209, 64, 1) 20%, rgba(102, 237, 75, 1) 40%, rgba(80, 193, 58, 1) 70%, rgba(53, 132, 37, 1) 100%);
+  /* W3C */
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#66ED4B', endColorstr='#50c13a', GradientType=0);
+  /* IE6-9 */
 }
+
 .gtaskyellow {
-	background: rgb(247,228,56); /* Old browsers */
-	background: linear-gradient(to bottom,  rgba(247,228,56,1) 0%,rgba(239,239,55,1) 20%,rgba(255,255,58,1) 40%,rgba(242,236,55,1) 70%,rgba(241,218,54,1) 100%); /* W3C */
-	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffff3a', endColorstr='#f7e438',GradientType=0 ); /* IE6-9 */
+  background: rgb(247, 228, 56);
+  /* Old browsers */
+  background: linear-gradient(to bottom, rgba(247, 228, 56, 1) 0%, rgba(239, 239, 55, 1) 20%, rgba(255, 255, 58, 1) 40%, rgba(242, 236, 55, 1) 70%, rgba(241, 218, 54, 1) 100%);
+  /* W3C */
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff3a', endColorstr='#f7e438', GradientType=0);
+  /* IE6-9 */
 }
+
 .gtaskpurple {
-	background: rgb(193,58,193); /* Old browsers */
-	background: linear-gradient(to bottom,  rgba(193,58,193,1) 0%,rgba(211,65,211,1) 20%,rgba(239,76,239,1) 40%,rgba(193,58,193,1) 70%,rgba(137,38,137,1) 100%); /* W3C */
-	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ef4cef', endColorstr='#892689',GradientType=0 ); /* IE6-9 */
+  background: rgb(193, 58, 193);
+  /* Old browsers */
+  background: linear-gradient(to bottom, rgba(193, 58, 193, 1) 0%, rgba(211, 65, 211, 1) 20%, rgba(239, 76, 239, 1) 40%, rgba(193, 58, 193, 1) 70%, rgba(137, 38, 137, 1) 100%);
+  /* W3C */
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ef4cef', endColorstr='#892689', GradientType=0);
+  /* IE6-9 */
 }
+
 .gtaskpink {
-	background: rgb(249,177,245); /* Old browsers */
-	background: linear-gradient(to bottom,  rgba(249,177,245,1) 0%,rgba(247,192,243,1) 20%,rgba(247,202,244,1) 40%,rgba(249,192,246,1) 70%,rgba(252,174,247,1) 100%); /* W3C */
-	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7caf4', endColorstr='#fcaef7',GradientType=0 ); /* IE6-9 */
+  background: rgb(249, 177, 245);
+  /* Old browsers */
+  background: linear-gradient(to bottom, rgba(249, 177, 245, 1) 0%, rgba(247, 192, 243, 1) 20%, rgba(247, 202, 244, 1) 40%, rgba(249, 192, 246, 1) 70%, rgba(252, 174, 247, 1) 100%);
+  /* W3C */
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7caf4', endColorstr='#fcaef7', GradientType=0);
+  /* IE6-9 */
 }
+
 .gtaskbluecomplete,
 .gtaskredcomplete,
 .gtaskgreencomplete,
 .gtaskyellowcomplete,
 .gtaskpurplecomplete,
-.gtaskpinkcomplete			{ float:left; overflow: hidden; height:5px; filter: alpha(opacity=40); opacity:0.4; background-color: #000000; margin-top:4px; }
-
-/* Printer friendly styles - we could use these all the time but they are not as pretty! */
-/* note that "@media print" is not supported in IE6 or 7.  Fully patched IE8 should be OK */
-@media print {
-	.ggroupblack { height:0px; border-top: 7px solid; border-color: #000000; }
-	.gtaskblue { height:0px; border-top: 13px solid; border-color: rgb(58,132,195); }
-	.gtaskred { height:0px; border-top: 13px solid; border-color: rgb(196,58,58); }
-	.gtaskgreen { height:0px; border-top: 13px solid; border-color: rgb(80,193,58); }
-	.gtaskyellow { height:0px; border-top: 13px solid; border-color: rgb(247,228,56); }
-	.gtaskpurple { height:0px; border-top: 13px solid; border-color: rgb(193,58,193); }
-	.gtaskpink { height:0px; border-top: 13px solid; border-color: rgb(249,177,245); }
-
-	.gtaskbluecomplete,
-	.gtaskredcomplete,
-	.gtaskgreencomplete,
-	.gtaskyellowcomplete,
-	.gtaskpurplecomplete,
-	.gtaskpinkcomplete { height:0px; filter: alpha(opacity=40); opacity:0.4; margin-top: -9px; border-top: 5px solid; border-color: #000000; }
-	.ggroupblackcomplete { height: 0px; filter: alpha(opacity=80); opacity:0.8; margin-top:-5px; border-top:3px solid; border-color:#777777; }
+.gtaskpinkcomplete {
+  float: left;
+  overflow: hidden;
+  height: 5px;
+  filter: alpha(opacity=40);
+  opacity: 0.4;
+  background-color: #000000;
+  margin-top: 4px;
 }
 
 /*  END Task bar styles */
-.glinev { border-left: 1px solid; width: 0px; }
-.glineh { border-top: 1px solid; height: 0px; }
+
+.glinev {
+  border-left: 1px solid;
+  width: 0px;
+}
+
+.glineh {
+  border-top: 1px solid;
+  height: 0px;
+}
 
 .gDepFS,
 .gDepSS,
 .gDepSF,
-.gDepFF				{ border-color: #ff0000; }
+.gDepFF {
+  border-color: #ff0000;
+}
+
 .gDepFSArw,
-.gDepSSArw			{ overflow: hidden; width:0px; height:0px; border-bottom: 4px solid transparent; border-left: 4px solid #ff0000; border-top: 4px solid transparent; border-right: 4px solid transparent;}
+.gDepSSArw {
+  overflow: hidden;
+  width: 0px;
+  height: 0px;
+  border-bottom: 4px solid transparent;
+  border-left: 4px solid #ff0000;
+  border-top: 4px solid transparent;
+  border-right: 4px solid transparent;
+}
+
 .gDepFFArw,
-.gDepSFArw			{ overflow: hidden; width:0px; height:0px; border-bottom: 4px solid transparent; border-left: 4px solid transparent; border-top: 4px solid transparent; border-right: 4px solid #ff0000;}
-.gCurDate			{ border-color: #0000ff; }
+.gDepSFArw {
+  overflow: hidden;
+  width: 0px;
+  height: 0px;
+  border-bottom: 4px solid transparent;
+  border-left: 4px solid transparent;
+  border-top: 4px solid transparent;
+  border-right: 4px solid #ff0000;
+}
+
+.gCurDate {
+  border-color: #0000ff;
+}
+
+div.gtaskbarcontainer {
+  z-index: 1;
+  position: absolute;
+  top: 0px
+}
+
+.textbar {
+  word-break: break-all;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  width: 40%;
+  display: inline-block;
+}
+
+.JSGanttToolTip {
+  position: absolute;
+  display: block;
+  z-index: 10000;
+}
+
+.JSGanttToolTipcont {
+  font-family: tahoma, arial, verdana;
+  font-size: 10px;
+  display: block;
+  background: #ffffff;
+  color: #656565
+}
+
+.gTaskInfo {
+  background: #dbecff;
+  width: 400px;
+  border: #656565 1px solid;
+  border-radius: 10px;
+  padding: 4px 6px 4px 6px;
+  float: left;
+}
+
+.gTtTitle {
+  display: block;
+  font-size: 12px;
+  font-weight: bold;
+  color: #404040;
+  margin-left: 4px;
+  margin-bottom: 1em;
+}
+
+.gTaskLabel {
+  font-size: 11px;
+  font-weight: bold;
+  color: #656565;
+  margin-left: 4px;
+}
+
+.gTaskText {
+  position: absolute;
+  left: 90px;
+  padding-top: 1px;
+  font-size: 10px;
+  font-weight: normal;
+  color: #656565;
+}
+
+.gTaskNotes {
+  font-size: 11px;
+  font-weight: normal;
+  color: #323232;
+  padding: 0 15px;
+  display: block;
+}
+
+.gTIn {
+  padding-top: 10px;
+}
+
+.gantt {
+  min-width: 632px;
+  /* 2x LC width */
+}
+
+.gchartcontainer {
+  /* padding-left: 532px; LC width */
+  line-height: 1;
+  /* Overrides inherited CSS (e.g. from Bootstrap) */
+  display: flex;
+}
+
+.gcontainercol {
+  position: relative;
+}
+
+/* Add a max-height value here if wanted */
+
+.glistgrid {
+  min-width: 132px;
+  /* LC width */
+  float: left;
+  /* LC width */
+  padding-right: 0px;
+  padding-left: 0px;
+  padding-bottom: 0px;
+  padding-top: 0px;
+  background-color: #ffffff;
+  overflow: hidden;
+}
 
+.glistlbl {
+  min-width: 132px;
+  /* LC width */
+  float: left;
+  /* LC width */
+  padding-right: 0px;
+  padding-left: 0px;
+  padding-bottom: 0px;
+  padding-top: 0px;
+  background-color: #ffffff;
+  overflow: hidden;
+  flex: none;
+}
 
-div.gtaskbarcontainer		{ z-index: 1; position: absolute; top: 0px }
+.glistlbl,
+.gchartgrid {
+  display: flex;
+  flex-direction: column;
+}
 
-.JSGanttToolTip		{position: absolute; display: block; z-index: 2;}
-.JSGanttToolTipcont	{font-family: tahoma, arial, verdana; font-size: 10px; display: block; background: #ffffff; color: #656565}
-.gTaskInfo			{background: #dbecff; width: 400px; border: #656565 1px solid; border-radius: 10px; padding: 4px 6px 4px 6px; float: left;}
-.gTtTitle			{display: block; font-size: 12px; font-weight: bold; color: #404040; margin-left: 4px; margin-bottom: 1em;}
-.gTaskLabel 		{font-size: 11px; font-weight: bold; color: #656565; margin-left: 4px;}
-.gTaskText	 		{position:absolute; left: 90px; padding-top: 1px; font-size: 10px; font-weight: normal; color: #656565;}
-.gTaskNotes 		{font-size: 11px; font-weight: normal; color: #323232; padding: 0 15px; display: block;}
-.gTIn	 			{padding-top: 10px;}
+.glabelfooter {
+  clear: both;
+}
 
-.gantt				{ min-width: 632px;	/* 2x LC width */ }
-.gchartcontainer	{ /* padding-left: 532px; LC width */ line-height: 1; /* Overrides inherited CSS (e.g. from Bootstrap) */ }
-.gcontainercol		{ position: relative; } /* Add a max-height value here if wanted */
-.glistgrid			{ width: 532px; /* LC width */ float: left; /* LC width */ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; overflow: hidden; }
-.glistlbl			{ width: 532px; /* LC width */ float: left; /* LC width */ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; overflow: hidden; }
-.glabelfooter		{ clear: both; }
-.ggridfooter		{ clear: both; }
+.ggridfooter {
+  clear: both;
+}
+
+.rhscrpad {
+  width: 150px;
+  position: absolute;
+  top: 0px;
+  height: 1px;
+}
 
-.rhscrpad			{ width: 150px; position: absolute; top: 0px; height: 1px; }
+.gchartgrid {
+  padding-right: 0px;
+  padding-left: 0px;
+  padding-bottom: 0px;
+  padding-top: 0px;
+  background-color: #ffffff;
+  position: relative;
+  /* overflow: auto; */
+  overflow: unset;
+  overflow-y: auto;
+  min-height: 0%;
+}
 
-.gchartgrid			{ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; position: relative; overflow: auto; min-height: 0%; }
-.gchartlbl			{ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; position: relative; overflow: hidden; }
+.gchartlbl {
+  padding-right: 0px;
+  padding-left: 0px;
+  padding-bottom: 0px;
+  padding-top: 0px;
+  background-color: #ffffff;
+  position: relative;
+  overflow: hidden;
+  flex: none;
+}
 
 /* Old Internet Explorer version hacks */
-.gantt						{ _height: 100% }	/* otherwise the chart disappears! */
-div .gantt					{ /* _width: 1064px; ie6 fixed width */ }
+
+.gantt {
+  _height: 100%
+}
+
+/* otherwise the chart disappears! */
+
+div .gantt {
+  /* _width: 1064px; ie6 fixed width */
+}
+
 div.gchartlbl,
-div.gchartgrid				{/* _width: 532px; */}	/* ie6 fixed width */
+div.gchartgrid {
+  /* _width: 532px; */
+}
+
+/* ie6 fixed width */
+
 div.glistlbl,
 div.glistgrid {
-	*right: 0px;			/* ie7 pulls the content too far left with the negative margin */
-	_right: 532px;			/* but ie6 fixed width needs this */
-	_margin-left: -532px;	/* ie6 fixed width */
-	float: left;
+  *right: 0px;
+  /* ie7 pulls the content too far left with the negative margin */
+  _right: 532px;
+  /* but ie6 fixed width needs this */
+  _margin-left: -532px;
+  /* ie6 fixed width */
+  float: left;
+}
+
+div.gchartgrid {
+  *padding-bottom: 20px;
+  *overflow-y: hidden;
+}
+
+/* variable height design, no need for vertical scroll */
+
+td.gmajorheading div {
+  *overflow: hidden;
 }
-div.gchartgrid { *padding-bottom: 20px; *overflow-y: hidden; } /* variable height design, no need for vertical scroll */
-td.gmajorheading div { *overflow: hidden; } /* stops resizing fixed width columns if the text is too wide */
-td.gspanning div { *overflow: hidden; } /* stops resizing fixed width columns if the text is too wide */
+
+/* stops resizing fixed width columns if the text is too wide */
+
+td.gspanning div {
+  *overflow: hidden;
+}
+
+/* stops resizing fixed width columns if the text is too wide */
 
 /* border transparency tricks */
-.ggroupblackendpointleft { _border-top: 4px solid black; _border-left: 4px solid pink; _border-bottom: 4px solid pink; _border-right: 4px solid pink; _filter: chroma(color=pink); }
-.ggroupblackendpointright { _border-top: 4px solid black; _border-left: 4px solid pink; _border-bottom: 4px solid pink; _border-right: 4px solid pink;_filter: chroma(color=pink); }
 
-.gmdtop { _border-left: 5px solid pink; _border-top: 5px solid pink; _border-right: 5px solid pink; _filter: chroma(color=pink);}
-.gmdbottom { _border-left: 5px solid pink; _border-bottom: 5px solid pink; _border-right: 5px solid pink; _filter: chroma(color=pink);}
+.ggroupblackendpointleft {
+  _border-top: 4px solid black;
+  _border-left: 4px solid pink;
+  _border-bottom: 4px solid pink;
+  _border-right: 4px solid pink;
+  _filter: chroma(color=pink);
+}
+
+.ggroupblackendpointright {
+  _border-top: 4px solid black;
+  _border-left: 4px solid pink;
+  _border-bottom: 4px solid pink;
+  _border-right: 4px solid pink;
+  _filter: chroma(color=pink);
+}
+
+.gmdtop {
+  _border-left: 5px solid pink;
+  _border-top: 5px solid pink;
+  _border-right: 5px solid pink;
+  _filter: chroma(color=pink);
+}
+
+.gmdbottom {
+  _border-left: 5px solid pink;
+  _border-bottom: 5px solid pink;
+  _border-right: 5px solid pink;
+  _filter: chroma(color=pink);
+}
 
 .gDepFSArw,
-.gDepSSArw { _border-bottom: 4px solid pink; _border-top: 4px solid pink; _border-right: 4px solid pink; _filter: chroma(color=pink);}
+.gDepSSArw {
+  _border-bottom: 4px solid pink;
+  _border-top: 4px solid pink;
+  _border-right: 4px solid pink;
+  _filter: chroma(color=pink);
+}
+
 .gDepFFArw,
-.gDepSFArw { _border-bottom: 4px solid pink; _border-left: 4px solid pink; _border-top: 4px solid pink; _filter: chroma(color=pink);}
+.gDepSFArw {
+  _border-bottom: 4px solid pink;
+  _border-left: 4px solid pink;
+  _border-top: 4px solid pink;
+  _filter: chroma(color=pink);
+}
 
 /* Workaround for odd bug in old versions of Opera - no other browser needs this */
-.glinediv {position: absolute; top: 0px; left: 0px;}
+
+.glinediv {
+  position: absolute;
+  top: 0px;
+  left: 0px;
+  z-index: 1px;
+}
+
+.gantt-inputtable {
+  max-width: 100%;
+  max-height: 16px;
+}
+
+.gadditional {
+  border: #efefef 1px solid;
+}
+
+.gadditional,
+.gres,
+.gdur,
+.gcomp,
+.gcost {
+  text-align: center;
+  width: 70px;
+  max-width: 70px;
+  min-width: 70px;
+  font-size: 10px;
+}
+
+@media print {
+
+  /* All your print styles go here */
+  html,
+  .gchartgrid {
+    overflow: unset !important;
+  }
+
+  .glistgrid {
+    float: none !important;
+  }
+}
 
 /* if using setUseSingleCell(1) the following is a suggested set of CSS3 styles to recreate the table grid - won't work on old browsers
 .ggrouphour td,
@@ -241,3 +806,177 @@ td.gspanning div { *overflow: hidden; } /* stops resizing fixed width columns if
 .gmilequarter td,
 .gitemquarter td		{ background-size: 19px 1px; background-image: linear-gradient(to left, #efefef, transparent 1px, transparent 18px); width: 100%; height: 19px; }
 */
+
+.gmain {
+  height: 100%;
+
+  display: flex;
+  flex-direction: column;
+}
+
+.gmainright {
+  overflow: hidden;
+  flex: auto;
+}
+
+.gmainleft {
+  overflow: hidden;
+  flex: 0 0 50%;
+}
+
+.gtasktableh tr,
+.gcharttable tr,
+.gcharttableh tr,
+.gtasktable tr {
+  height: 22px !important;
+}
+
+.gtasktableouterwrapper {
+  overflow: hidden;
+}
+
+.gtasktablewrapper {
+  overflow-y: scroll;
+  flex: auto;
+  height: 100%;
+}
+
+.chartgrid {
+  overflow: auto;
+  flex: auto;
+}
+
+/* .gtasktable {
+  margin-bottom: 14px;
+} */
+
+/* Printer friendly styles - we could use these all the time but they are not as pretty! */
+
+/* note that "@media print" is not supported in IE6 or 7.  Fully patched IE8 should be OK */
+
+@media print {
+  .ggroupblack {
+    height: 0px;
+    border-top: 7px solid;
+    border-color: #000000;
+  }
+
+  .gtaskblue {
+    height: 0px;
+    border-top: 13px solid;
+    border-color: rgb(58, 132, 195);
+  }
+
+  .gtaskred {
+    height: 0px;
+    border-top: 13px solid;
+    border-color: rgb(196, 58, 58);
+  }
+
+  .gtaskgreen {
+    height: 0px;
+    border-top: 13px solid;
+    border-color: rgb(80, 193, 58);
+  }
+
+  .gtaskyellow {
+    height: 0px;
+    border-top: 13px solid;
+    border-color: rgb(247, 228, 56);
+  }
+
+  .gtaskpurple {
+    height: 0px;
+    border-top: 13px solid;
+    border-color: rgb(193, 58, 193);
+  }
+
+  .gtaskpink {
+    height: 0px;
+    border-top: 13px solid;
+    border-color: rgb(249, 177, 245);
+  }
+
+  .gtaskbluecomplete,
+  .gtaskredcomplete,
+  .gtaskgreencomplete,
+  .gtaskyellowcomplete,
+  .gtaskpurplecomplete,
+  .gtaskpinkcomplete {
+    height: 0px;
+    filter: alpha(opacity=40);
+    opacity: 0.4;
+    margin-top: -9px;
+    border-top: 5px solid;
+    border-color: #000000;
+  }
+
+  .ggroupblackcomplete {
+    height: 0px;
+    filter: alpha(opacity=80);
+    opacity: 0.8;
+    margin-top: -5px;
+    border-top: 3px solid;
+    border-color: #777777;
+  }
+
+  .gmainright,
+  .gmainleft {
+    overflow: hidden;
+    width: auto;
+  }
+
+  table {
+    page-break-after: auto
+  }
+
+  tr {
+    page-break-inside: avoid;
+    page-break-after: auto
+  }
+
+  td {
+    page-break-inside: avoid;
+    page-break-after: auto
+  }
+
+  thead {
+    display: table-header-group
+  }
+
+  tfoot {
+    display: table-footer-group
+  }
+}
+
+/* Fix for OSx trackpad hiding the scroll bars*/
+.frame::-webkit-scrollbar {
+  -webkit-appearance: none;
+}
+
+.frame::-webkit-scrollbar:vertical {
+  width: 11px;
+}
+
+.frame::-webkit-scrollbar:horizontal {
+  height: 11px;
+}
+
+.frame::-webkit-scrollbar-thumb {
+  border-radius: 8px;
+  border: 2px solid white;
+  /* should match background, can't be transparent */
+  background-color: rgba(0, 0, 0, .5);
+}
+
+.frame::-webkit-scrollbar-track {
+  background-color: #fff;
+  border-radius: 8px;
+}
+
+.gscrollbar-calculation-container {
+  visibility: hidden;
+  overflow: scroll;
+  -ms-overflow-style: scrollbar;
+  display: block;
+}

+ 5013 - 2526
htdocs/includes/jsgantt/jsgantt.js

@@ -1,2577 +1,5064 @@
-/*
-	   _        ___            _   _    _____                                        _
-	  (_)___   / _ \__ _ _ __ | |_| |_  \_   \_ __ ___  _ __  _ __ _____   _____  __| |
-	  | / __| / /_\/ _` | '_ \| __| __|  / /\/ '_ ` _ \| '_ \| '__/ _ \ \ / / _ \/ _` |
-	  | \__ \/ /_\\ (_| | | | | |_| |_/\/ /_ | | | | | | |_) | | | (_) \ V /  __/ (_| |
-	 _/ |___/\____/\__,_|_| |_|\__|\__\____/ |_| |_| |_| .__/|_|  \___/ \_/ \___|\__,_|
-	|__/                                               |_|
-	jsGanttImproved 1.7.5.4
-
-	The current version of this code can be found at https://github.com/jsGanttImproved/jsgantt-improved/
-
-	* Copyright (c) 2013-2017, Paul Geldart, Eduardo Rodrigues and Ricardo Cardoso.
-	* All rights reserved.
-	*
-	* Redistribution and use in source and binary forms, with or without
-	* modification, are permitted provided that the following conditions are met:
-	*     * Redistributions of source code must retain the above copyright
-	*       notice, this list of conditions and the following disclaimer.
-	*     * Redistributions in binary form must reproduce the above copyright
-	*       notice, this list of conditions and the following disclaimer in the
-	*       documentation and/or other materials provided with the distribution.
-	*     * Neither the name of Paul Geldart, Eduardo Rodrigues and Ricardo Cardoso nor the names of its contributors
-	*       may be used to endorse or promote products derived from this software
-	*       without specific prior written permission.
-	*
-	* THIS SOFTWARE IS PROVIDED BY PAUL GELDART, EDUARDO RODRIGUES AND RICARDO CARDOSO ''AS IS'' AND ANY EXPRESS OR
-	* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-	* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-	* IN NO EVENT SHALL PAUL GELDART, EDUARDO RODRIGUES AND RICARDO CARDOSO BE LIABLE FOR ANY DIRECT,
-	* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-	* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-	* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-	* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-	* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-	This project is based on jsGantt 1.2, (which can be obtained from
-	https://code.google.com/p/jsgantt/) and remains under the original BSD license.
-	The original project license follows:
-
-	Copyright (c) 2009, Shlomy Gantz BlueBrick Inc. All rights reserved.
-
-	* Redistribution and use in source and binary forms, with or without
-	* modification, are permitted provided that the following conditions are met:
-	*     * Redistributions of source code must retain the above copyright
-	*       notice, this list of conditions and the following disclaimer.
-	*     * Redistributions in binary form must reproduce the above copyright
-	*       notice, this list of conditions and the following disclaimer in the
-	*       documentation and/or other materials provided with the distribution.
-	*     * Neither the name of Shlomy Gantz or BlueBrick Inc. nor the
-	*       names of its contributors may be used to endorse or promote products
-	*       derived from this software without specific prior written permission.
-	*
-	* THIS SOFTWARE IS PROVIDED BY SHLOMY GANTZ/BLUEBRICK INC. ''AS IS'' AND ANY
-	* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-	* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-	* DISCLAIMED. IN NO EVENT SHALL SHLOMY GANTZ/BLUEBRICK INC. BE LIABLE FOR ANY
-	* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-	* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-	* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-	* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-	* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-var JSGantt; if (!JSGantt) JSGantt={};
-
-var vBenchTime=new Date().getTime();
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSGantt = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var jsGantt = require("./src/jsgantt");
+module.exports = jsGantt.JSGantt;
+exports.JSGantt = jsGantt.JSGantt;
+
+},{"./src/jsgantt":6}],2:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var lang = require("./lang");
+var events_1 = require("./events");
+var general_utils_1 = require("./utils/general_utils");
+var task_1 = require("./task");
+var xml_1 = require("./xml");
+var draw_columns_1 = require("./draw_columns");
+var draw_utils_1 = require("./utils/draw_utils");
+var draw_dependencies_1 = require("./draw_dependencies");
+var options_1 = require("./options");
+var date_utils_1 = require("./utils/date_utils");
+/**
+ * function that loads the main gantt chart properties and functions
+ * @param pDiv (required) this is a div object created in HTML
+ * @param pFormat (required) - used to indicate whether chart should be drawn in "hour", "day", "week", "month", or "quarter" format
+ */
+exports.GanttChart = function (pDiv, pFormat) {
+    this.vDiv = pDiv;
+    this.vFormat = pFormat;
+    this.vDivId = null;
+    this.vUseFade = 1;
+    this.vUseMove = 1;
+    this.vUseRowHlt = 1;
+    this.vUseToolTip = 1;
+    this.vUseSort = 1;
+    this.vUseSingleCell = 25000;
+    this.vShowRes = 1;
+    this.vShowDur = 1;
+    this.vShowComp = 1;
+    this.vShowStartDate = 1;
+    this.vShowEndDate = 1;
+    this.vShowPlanStartDate = 0;
+    this.vShowPlanEndDate = 0;
+    this.vShowCost = 0;
+    this.vShowAddEntries = 0;
+    this.vShowEndWeekDate = 1;
+    this.vShowWeekends = 1;
+    this.vShowTaskInfoRes = 1;
+    this.vShowTaskInfoDur = 1;
+    this.vShowTaskInfoComp = 1;
+    this.vShowTaskInfoStartDate = 1;
+    this.vShowTaskInfoEndDate = 1;
+    this.vShowTaskInfoNotes = 1;
+    this.vShowTaskInfoLink = 0;
+    this.vShowDeps = 1;
+    this.vTotalHeight = undefined;
+    this.vWorkingDays = {
+        0: true,
+        1: true,
+        2: true,
+        3: true,
+        4: true,
+        5: true,
+        6: true
+    };
+    this.vEventClickCollapse = null;
+    this.vEventClickRow = null;
+    this.vEvents = {
+        taskname: null,
+        res: null,
+        dur: null,
+        comp: null,
+        startdate: null,
+        enddate: null,
+        planstartdate: null,
+        planenddate: null,
+        cost: null,
+        beforeDraw: null,
+        afterDraw: null,
+        beforeLineDraw: null,
+        afterLineDraw: null,
+        onLineDraw: null,
+        onLineContainerHover: null
+    };
+    this.vEventsChange = {
+        taskname: null,
+        res: null,
+        dur: null,
+        comp: null,
+        startdate: null,
+        enddate: null,
+        planstartdate: null,
+        planenddate: null,
+        cost: null,
+        line: null
+    };
+    this.vResources = null;
+    this.vAdditionalHeaders = {};
+    this.vColumnOrder = draw_columns_1.COLUMN_ORDER;
+    this.vEditable = false;
+    this.vDebug = false;
+    this.vShowSelector = new Array('top');
+    this.vDateInputFormat = 'yyyy-mm-dd';
+    this.vDateTaskTableDisplayFormat = date_utils_1.parseDateFormatStr('dd/mm/yyyy');
+    this.vDateTaskDisplayFormat = date_utils_1.parseDateFormatStr('dd month yyyy');
+    this.vHourMajorDateDisplayFormat = date_utils_1.parseDateFormatStr('day dd month yyyy');
+    this.vHourMinorDateDisplayFormat = date_utils_1.parseDateFormatStr('HH');
+    this.vDayMajorDateDisplayFormat = date_utils_1.parseDateFormatStr('dd/mm/yyyy');
+    this.vDayMinorDateDisplayFormat = date_utils_1.parseDateFormatStr('dd');
+    this.vWeekMajorDateDisplayFormat = date_utils_1.parseDateFormatStr('yyyy');
+    this.vWeekMinorDateDisplayFormat = date_utils_1.parseDateFormatStr('dd/mm');
+    this.vMonthMajorDateDisplayFormat = date_utils_1.parseDateFormatStr('yyyy');
+    this.vMonthMinorDateDisplayFormat = date_utils_1.parseDateFormatStr('mon');
+    this.vQuarterMajorDateDisplayFormat = date_utils_1.parseDateFormatStr('yyyy');
+    this.vQuarterMinorDateDisplayFormat = date_utils_1.parseDateFormatStr('qq');
+    this.vUseFullYear = date_utils_1.parseDateFormatStr('dd/mm/yyyy');
+    this.vCaptionType;
+    this.vDepId = 1;
+    this.vTaskList = new Array();
+    this.vFormatArr = new Array('hour', 'day', 'week', 'month', 'quarter');
+    this.vMonthDaysArr = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
+    this.vProcessNeeded = true;
+    this.vMinGpLen = 8;
+    this.vScrollTo = '';
+    this.vHourColWidth = 18;
+    this.vDayColWidth = 18;
+    this.vWeekColWidth = 36;
+    this.vMonthColWidth = 36;
+    this.vQuarterColWidth = 18;
+    this.vRowHeight = 20;
+    this.vTodayPx = -1;
+    this.vLangs = lang;
+    this.vLang = navigator.language && navigator.language in lang ? navigator.language : 'en';
+    this.vChartBody = null;
+    this.vChartHead = null;
+    this.vListBody = null;
+    this.vChartTable = null;
+    this.vLines = null;
+    this.vTimer = 20;
+    this.vTooltipDelay = 1500;
+    this.vTooltipTemplate = null;
+    this.vMinDate = null;
+    this.vMaxDate = null;
+    this.includeGetSet = options_1.includeGetSet.bind(this);
+    this.includeGetSet();
+    this.mouseOver = events_1.mouseOver;
+    this.mouseOut = events_1.mouseOut;
+    this.addListener = events_1.addListener.bind(this);
+    this.removeListener = events_1.removeListener.bind(this);
+    this.createTaskInfo = task_1.createTaskInfo;
+    this.AddTaskItem = task_1.AddTaskItem;
+    this.AddTaskItemObject = task_1.AddTaskItemObject;
+    this.RemoveTaskItem = task_1.RemoveTaskItem;
+    this.ClearTasks = task_1.ClearTasks;
+    this.getXMLProject = xml_1.getXMLProject;
+    this.getXMLTask = xml_1.getXMLTask;
+    this.CalcTaskXY = draw_utils_1.CalcTaskXY.bind(this);
+    // sLine: Draw a straight line (colored one-pixel wide div)
+    this.sLine = draw_utils_1.sLine.bind(this);
+    this.drawDependency = draw_dependencies_1.drawDependency.bind(this);
+    this.DrawDependencies = draw_dependencies_1.DrawDependencies.bind(this);
+    this.getArrayLocationByID = draw_utils_1.getArrayLocationByID.bind(this);
+    this.drawSelector = draw_utils_1.drawSelector.bind(this);
+    this.clearDependencies = function () {
+        var parent = this.getLines();
+        if (this.vEventsChange.line &&
+            typeof this.vEventsChange.line === 'function') {
+            this.removeListener('click', this.vEventsChange.line, parent);
+            this.addListener('click', this.vEventsChange.line, parent);
+        }
+        while (parent.hasChildNodes())
+            parent.removeChild(parent.firstChild);
+        this.vDepId = 1;
+    };
+    this.drawListHead = function (vLeftHeader) {
+        var _this = this;
+        var vTmpDiv = draw_utils_1.newNode(vLeftHeader, 'div', this.vDivId + 'glisthead', 'glistlbl gcontainercol');
+        var gListLbl = vTmpDiv;
+        this.setListBody(vTmpDiv);
+        var vTmpTab = draw_utils_1.newNode(vTmpDiv, 'table', null, 'gtasktableh');
+        var vTmpTBody = draw_utils_1.newNode(vTmpTab, 'tbody');
+        var vTmpRow = draw_utils_1.newNode(vTmpTBody, 'tr');
+        draw_utils_1.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0');
+        var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gspanning gtaskname', null, null, null, null, this.getColumnOrder().length + 1);
+        vTmpCell.appendChild(this.drawSelector('top'));
+        vTmpRow = draw_utils_1.newNode(vTmpTBody, 'tr');
+        draw_utils_1.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0');
+        draw_utils_1.newNode(vTmpRow, 'td', null, 'gtaskname', '\u00A0');
+        this.getColumnOrder().forEach(function (column) {
+            if (_this[column] == 1 || column === 'vAdditionalHeaders') {
+                draw_columns_1.draw_task_headings(column, vTmpRow, _this.vLangs, _this.vLang, _this.vAdditionalHeaders, _this.vEvents);
+            }
+        });
+        return gListLbl;
+    };
+    this.drawListBody = function (vLeftHeader) {
+        var _this = this;
+        var vTmpContentTabOuterWrapper = draw_utils_1.newNode(vLeftHeader, 'div', null, 'gtasktableouterwrapper');
+        var vTmpContentTabWrapper = draw_utils_1.newNode(vTmpContentTabOuterWrapper, 'div', null, 'gtasktablewrapper');
+        vTmpContentTabWrapper.style.width = "calc(100% + " + general_utils_1.getScrollbarWidth() + "px)";
+        var vTmpContentTab = draw_utils_1.newNode(vTmpContentTabWrapper, 'table', null, 'gtasktable');
+        var vTmpContentTBody = draw_utils_1.newNode(vTmpContentTab, 'tbody');
+        var vNumRows = 0;
+        var _loop_1 = function (i) {
+            var vBGColor = void 0;
+            if (this_1.vTaskList[i].getGroup() == 1)
+                vBGColor = 'ggroupitem';
+            else
+                vBGColor = 'glineitem';
+            var vID = this_1.vTaskList[i].getID();
+            var vTmpRow_1, vTmpCell_1 = void 0;
+            if ((!(this_1.vTaskList[i].getParItem() && this_1.vTaskList[i].getParItem().getGroup() == 2)) || this_1.vTaskList[i].getGroup() == 2) {
+                if (this_1.vTaskList[i].getVisible() == 0)
+                    vTmpRow_1 = draw_utils_1.newNode(vTmpContentTBody, 'tr', this_1.vDivId + 'child_' + vID, 'gname ' + vBGColor, null, null, null, 'none');
+                else
+                    vTmpRow_1 = draw_utils_1.newNode(vTmpContentTBody, 'tr', this_1.vDivId + 'child_' + vID, 'gname ' + vBGColor);
+                this_1.vTaskList[i].setListChildRow(vTmpRow_1);
+                draw_utils_1.newNode(vTmpRow_1, 'td', null, 'gtasklist', '\u00A0');
+                var editableClass = this_1.vEditable ? 'gtaskname gtaskeditable' : 'gtaskname';
+                vTmpCell_1 = draw_utils_1.newNode(vTmpRow_1, 'td', null, editableClass);
+                var vCellContents = '';
+                for (var j = 1; j < this_1.vTaskList[i].getLevel(); j++) {
+                    vCellContents += '\u00A0\u00A0\u00A0\u00A0';
+                }
+                var task_2 = this_1.vTaskList[i];
+                var vEventClickRow_1 = this_1.vEventClickRow;
+                var vEventClickCollapse_1 = this_1.vEventClickCollapse;
+                events_1.addListener('click', function (e) {
+                    if (e.target.classList.contains('gfoldercollapse') === false) {
+                        if (vEventClickRow_1 && typeof vEventClickRow_1 === "function") {
+                            vEventClickRow_1(task_2);
+                        }
+                    }
+                    else {
+                        if (vEventClickCollapse_1 && typeof vEventClickCollapse_1 === "function") {
+                            vEventClickCollapse_1(task_2);
+                        }
+                    }
+                }, vTmpRow_1);
+                if (this_1.vTaskList[i].getGroup() == 1) {
+                    var vTmpDiv = draw_utils_1.newNode(vTmpCell_1, 'div', null, null, vCellContents);
+                    var vTmpSpan = draw_utils_1.newNode(vTmpDiv, 'span', this_1.vDivId + 'group_' + vID, 'gfoldercollapse', (this_1.vTaskList[i].getOpen() == 1) ? '-' : '+');
+                    this_1.vTaskList[i].setGroupSpan(vTmpSpan);
+                    events_1.addFolderListeners(this_1, vTmpSpan, vID);
+                    var divTask = document.createElement('span');
+                    divTask.innerHTML = '\u00A0' + this_1.vTaskList[i].getName();
+                    vTmpDiv.appendChild(divTask);
+                    // const text = makeInput(this.vTaskList[i].getName(), this.vEditable, 'text');
+                    // vTmpDiv.appendChild(document.createNode(text));
+                    var callback = function (task, e) { return task.setName(e.target.value); };
+                    events_1.addListenerInputCell(vTmpCell_1, this_1.vEventsChange, callback, this_1.vTaskList, i, 'taskname', this_1.Draw.bind(this_1));
+                    events_1.addListenerClickCell(vTmpDiv, this_1.vEvents, this_1.vTaskList[i], 'taskname');
+                }
+                else {
+                    vCellContents += '\u00A0\u00A0\u00A0\u00A0';
+                    var text = draw_utils_1.makeInput(this_1.vTaskList[i].getName(), this_1.vEditable, 'text');
+                    var vTmpDiv = draw_utils_1.newNode(vTmpCell_1, 'div', null, null, vCellContents + text);
+                    var callback = function (task, e) { return task.setName(e.target.value); };
+                    events_1.addListenerInputCell(vTmpCell_1, this_1.vEventsChange, callback, this_1.vTaskList, i, 'taskname', this_1.Draw.bind(this_1));
+                    events_1.addListenerClickCell(vTmpCell_1, this_1.vEvents, this_1.vTaskList[i], 'taskname');
+                }
+                this_1.getColumnOrder().forEach(function (column) {
+                    if (_this[column] == 1 || column === 'vAdditionalHeaders') {
+                        draw_columns_1.draw_header(column, i, vTmpRow_1, _this.vTaskList, _this.vEditable, _this.vEventsChange, _this.vEvents, _this.vDateTaskTableDisplayFormat, _this.vAdditionalHeaders, _this.vFormat, _this.vLangs, _this.vLang, _this.vResources, _this.Draw.bind(_this));
+                    }
+                });
+                vNumRows++;
+            }
+        };
+        var this_1 = this;
+        for (var i = 0; i < this.vTaskList.length; i++) {
+            _loop_1(i);
+        }
+        // Render no daa in the chart
+        if (this.vTaskList.length == 0) {
+            var totalColumns = this.getColumnOrder()
+                .filter(function (column) { return _this[column] == 1 || column === 'vAdditionalHeaders'; })
+                .length;
+            var vTmpRow_2 = draw_utils_1.newNode(vTmpContentTBody, 'tr', this.vDivId + 'child_', 'gname ');
+            // this.vTaskList[i].setListChildRow(vTmpRow);
+            var vTmpCell_2 = draw_utils_1.newNode(vTmpRow_2, 'td', null, 'gtasknolist', '', null, null, null, totalColumns);
+            var vOutput = document.createDocumentFragment();
+            draw_utils_1.newNode(vOutput, 'div', null, 'gtasknolist-label', this.vLangs[this.vLang]['nodata'] + '.');
+            vTmpCell_2.appendChild(vOutput);
+        }
+        // DRAW the date format selector at bottom left.
+        var vTmpRow = draw_utils_1.newNode(vTmpContentTBody, 'tr');
+        draw_utils_1.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0');
+        var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gspanning gtaskname');
+        vTmpCell.appendChild(this.drawSelector('bottom'));
+        this.getColumnOrder().forEach(function (column) {
+            if (_this[column] == 1 || column === 'vAdditionalHeaders') {
+                draw_columns_1.draw_bottom(column, vTmpRow, _this.vAdditionalHeaders);
+            }
+        });
+        // Add some white space so the vertical scroll distance should always be greater
+        // than for the right pane (keep to a minimum as it is seen in unconstrained height designs)
+        // newNode(vTmpDiv2, 'br');
+        // newNode(vTmpDiv2, 'br');
+        return {
+            vNumRows: vNumRows,
+            vTmpContentTabWrapper: vTmpContentTabWrapper
+        };
+    };
+    /**
+     *
+     * DRAW CHAR HEAD
+     *
+     */
+    this.drawChartHead = function (vMinDate, vMaxDate, vColWidth, vNumRows) {
+        var vRightHeader = document.createDocumentFragment();
+        var vTmpDiv = draw_utils_1.newNode(vRightHeader, 'div', this.vDivId + 'gcharthead', 'gchartlbl gcontainercol');
+        var gChartLbl = vTmpDiv;
+        this.setChartHead(vTmpDiv);
+        var vTmpTab = draw_utils_1.newNode(vTmpDiv, 'table', this.vDivId + 'chartTableh', 'gcharttableh');
+        var vTmpTBody = draw_utils_1.newNode(vTmpTab, 'tbody');
+        var vTmpRow = draw_utils_1.newNode(vTmpTBody, 'tr');
+        var vTmpDate = new Date();
+        vTmpDate.setFullYear(vMinDate.getFullYear(), vMinDate.getMonth(), vMinDate.getDate());
+        if (this.vFormat == 'hour')
+            vTmpDate.setHours(vMinDate.getHours());
+        else
+            vTmpDate.setHours(0);
+        vTmpDate.setMinutes(0);
+        vTmpDate.setSeconds(0);
+        vTmpDate.setMilliseconds(0);
+        var vColSpan = 1;
+        // Major Date Header
+        while (vTmpDate.getTime() <= vMaxDate.getTime()) {
+            var vHeaderCellClass = 'gmajorheading';
+            var vCellContents = '';
+            if (this.vFormat == 'day') {
+                var colspan = 7;
+                if (!this.vShowWeekends) {
+                    vHeaderCellClass += ' headweekends';
+                    colspan = 5;
+                }
+                var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, null, null, null, colspan);
+                vCellContents += date_utils_1.formatDateStr(vTmpDate, this.vDayMajorDateDisplayFormat, this.vLangs[this.vLang]);
+                vTmpDate.setDate(vTmpDate.getDate() + 6);
+                if (this.vShowEndWeekDate == 1)
+                    vCellContents += ' - ' + date_utils_1.formatDateStr(vTmpDate, this.vDayMajorDateDisplayFormat, this.vLangs[this.vLang]);
+                draw_utils_1.newNode(vTmpCell, 'div', null, null, vCellContents, vColWidth * colspan);
+                vTmpDate.setDate(vTmpDate.getDate() + 1);
+            }
+            else if (this.vFormat == 'week') {
+                var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, vColWidth);
+                draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vWeekMajorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth);
+                vTmpDate.setDate(vTmpDate.getDate() + 7);
+            }
+            else if (this.vFormat == 'month') {
+                vColSpan = (12 - vTmpDate.getMonth());
+                if (vTmpDate.getFullYear() == vMaxDate.getFullYear())
+                    vColSpan -= (11 - vMaxDate.getMonth());
+                var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, null, null, null, vColSpan);
+                draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vMonthMajorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth * vColSpan);
+                vTmpDate.setFullYear(vTmpDate.getFullYear() + 1, 0, 1);
+            }
+            else if (this.vFormat == 'quarter') {
+                vColSpan = (4 - Math.floor(vTmpDate.getMonth() / 3));
+                if (vTmpDate.getFullYear() == vMaxDate.getFullYear())
+                    vColSpan -= (3 - Math.floor(vMaxDate.getMonth() / 3));
+                var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, null, null, null, vColSpan);
+                draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vQuarterMajorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth * vColSpan);
+                vTmpDate.setFullYear(vTmpDate.getFullYear() + 1, 0, 1);
+            }
+            else if (this.vFormat == 'hour') {
+                vColSpan = (24 - vTmpDate.getHours());
+                if (vTmpDate.getFullYear() == vMaxDate.getFullYear() &&
+                    vTmpDate.getMonth() == vMaxDate.getMonth() &&
+                    vTmpDate.getDate() == vMaxDate.getDate())
+                    vColSpan -= (23 - vMaxDate.getHours());
+                var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, null, null, null, vColSpan);
+                draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vHourMajorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth * vColSpan);
+                vTmpDate.setHours(0);
+                vTmpDate.setDate(vTmpDate.getDate() + 1);
+            }
+        }
+        vTmpRow = draw_utils_1.newNode(vTmpTBody, 'tr', null, 'footerdays');
+        // Minor Date header and Cell Rows
+        vTmpDate.setFullYear(vMinDate.getFullYear(), vMinDate.getMonth(), vMinDate.getDate()); // , vMinDate.getHours()
+        if (this.vFormat == 'hour')
+            vTmpDate.setHours(vMinDate.getHours());
+        var vNumCols = 0;
+        while (vTmpDate.getTime() <= vMaxDate.getTime()) {
+            var vMinorHeaderCellClass = 'gminorheading';
+            if (this.vFormat == 'day') {
+                if (vTmpDate.getDay() % 6 == 0) {
+                    if (!this.vShowWeekends) {
+                        vTmpDate.setDate(vTmpDate.getDate() + 1);
+                        continue;
+                    }
+                    vMinorHeaderCellClass += 'wkend';
+                }
+                if (vTmpDate <= vMaxDate) {
+                    var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vMinorHeaderCellClass);
+                    draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vDayMinorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth);
+                    vNumCols++;
+                }
+                vTmpDate.setDate(vTmpDate.getDate() + 1);
+            }
+            else if (this.vFormat == 'week') {
+                if (vTmpDate <= vMaxDate) {
+                    var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vMinorHeaderCellClass);
+                    draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vWeekMinorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth);
+                    vNumCols++;
+                }
+                vTmpDate.setDate(vTmpDate.getDate() + 7);
+            }
+            else if (this.vFormat == 'month') {
+                if (vTmpDate <= vMaxDate) {
+                    var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vMinorHeaderCellClass);
+                    draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vMonthMinorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth);
+                    vNumCols++;
+                }
+                vTmpDate.setDate(vTmpDate.getDate() + 1);
+                while (vTmpDate.getDate() > 1) {
+                    vTmpDate.setDate(vTmpDate.getDate() + 1);
+                }
+            }
+            else if (this.vFormat == 'quarter') {
+                if (vTmpDate <= vMaxDate) {
+                    var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vMinorHeaderCellClass);
+                    draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vQuarterMinorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth);
+                    vNumCols++;
+                }
+                vTmpDate.setDate(vTmpDate.getDate() + 81);
+                while (vTmpDate.getDate() > 1)
+                    vTmpDate.setDate(vTmpDate.getDate() + 1);
+            }
+            else if (this.vFormat == 'hour') {
+                for (var i = vTmpDate.getHours(); i < 24; i++) {
+                    vTmpDate.setHours(i); //works around daylight savings but may look a little odd on days where the clock goes forward
+                    if (vTmpDate <= vMaxDate) {
+                        var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, vMinorHeaderCellClass);
+                        draw_utils_1.newNode(vTmpCell, 'div', null, null, date_utils_1.formatDateStr(vTmpDate, this.vHourMinorDateDisplayFormat, this.vLangs[this.vLang]), vColWidth);
+                        vNumCols++;
+                    }
+                }
+                vTmpDate.setHours(0);
+                vTmpDate.setDate(vTmpDate.getDate() + 1);
+            }
+        }
+        var vDateRow = vTmpRow;
+        // Calculate size of grids  : Plus 3 because 1 border left + 2 of paddings
+        var vTaskLeftPx = (vNumCols * (vColWidth + 3)) + 1;
+        // Fix a small space at the end for day
+        if (this.vFormat === 'day') {
+            vTaskLeftPx += 2;
+        }
+        vTmpTab.style.width = vTaskLeftPx + 'px'; // Ensure that the headings has exactly the same width as the chart grid
+        // const vTaskPlanLeftPx = (vNumCols * (vColWidth + 3)) + 1;
+        var vSingleCell = false;
+        if (this.vUseSingleCell !== 0 && this.vUseSingleCell < (vNumCols * vNumRows))
+            vSingleCell = true;
+        draw_utils_1.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx + 1);
+        vTmpDiv = draw_utils_1.newNode(vRightHeader, 'div', null, 'glabelfooter');
+        return { gChartLbl: gChartLbl, vTaskLeftPx: vTaskLeftPx, vSingleCell: vSingleCell, vDateRow: vDateRow, vRightHeader: vRightHeader, vNumCols: vNumCols };
+    };
+    /**
+     *
+     * DRAW CHART BODY
+     *
+     */
+    this.drawCharBody = function (vTaskLeftPx, vTmpContentTabWrapper, gChartLbl, gListLbl, vMinDate, vMaxDate, vSingleCell, vNumCols, vColWidth, vDateRow) {
+        var vRightTable = document.createDocumentFragment();
+        var vTmpDiv = draw_utils_1.newNode(vRightTable, 'div', this.vDivId + 'gchartbody', 'gchartgrid gcontainercol');
+        this.setChartBody(vTmpDiv);
+        var vTmpTab = draw_utils_1.newNode(vTmpDiv, 'table', this.vDivId + 'chartTable', 'gcharttable', null, vTaskLeftPx);
+        this.setChartTable(vTmpTab);
+        draw_utils_1.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx + 1);
+        var vTmpTBody = draw_utils_1.newNode(vTmpTab, 'tbody');
+        var vTmpTFoot = draw_utils_1.newNode(vTmpTab, 'tfoot');
+        events_1.syncScroll([vTmpContentTabWrapper, vTmpDiv], 'scrollTop');
+        events_1.syncScroll([gChartLbl, vTmpDiv], 'scrollLeft');
+        events_1.syncScroll([vTmpContentTabWrapper, gListLbl], 'scrollLeft');
+        // Draw each row
+        var i = 0;
+        var j = 0;
+        var bd;
+        if (this.vDebug) {
+            bd = new Date();
+            console.info('before tasks loop', bd);
+        }
+        for (i = 0; i < this.vTaskList.length; i++) {
+            var curTaskStart = this.vTaskList[i].getStart() ? this.vTaskList[i].getStart() : this.vTaskList[i].getPlanStart();
+            var curTaskEnd = this.vTaskList[i].getEnd() ? this.vTaskList[i].getEnd() : this.vTaskList[i].getPlanEnd();
+            var vTaskLeftPx_1 = general_utils_1.getOffset(vMinDate, curTaskStart, vColWidth, this.vFormat, this.vShowWeekends);
+            var vTaskRightPx = general_utils_1.getOffset(curTaskStart, curTaskEnd, vColWidth, this.vFormat, this.vShowWeekends);
+            var curTaskPlanStart = void 0, curTaskPlanEnd = void 0;
+            curTaskPlanStart = this.vTaskList[i].getPlanStart();
+            curTaskPlanEnd = this.vTaskList[i].getPlanEnd();
+            var vTaskPlanLeftPx = 0;
+            var vTaskPlanRightPx = 0;
+            if (curTaskPlanStart && curTaskPlanEnd) {
+                vTaskPlanLeftPx = general_utils_1.getOffset(vMinDate, curTaskPlanStart, vColWidth, this.vFormat, this.vShowWeekends);
+                vTaskPlanRightPx = general_utils_1.getOffset(curTaskPlanStart, curTaskPlanEnd, vColWidth, this.vFormat, this.vShowWeekends);
+            }
+            var vID = this.vTaskList[i].getID();
+            var vComb = (this.vTaskList[i].getParItem() && this.vTaskList[i].getParItem().getGroup() == 2);
+            var vCellFormat = '';
+            var vTmpDiv_1 = null;
+            var vTmpItem = this.vTaskList[i];
+            var vCaptClass = null;
+            // set cell width only for first row because of table-layout:fixed
+            var taskCellWidth = i === 0 ? vColWidth : null;
+            if (this.vTaskList[i].getMile() && !vComb) {
+                var vTmpRow = draw_utils_1.newNode(vTmpTBody, 'tr', this.vDivId + 'childrow_' + vID, 'gmileitem gmile' + this.vFormat, null, null, null, ((this.vTaskList[i].getVisible() == 0) ? 'none' : null));
+                this.vTaskList[i].setChildRow(vTmpRow);
+                events_1.addThisRowListeners(this, this.vTaskList[i].getListChildRow(), vTmpRow);
+                var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gtaskcell gtaskcellmile', null, vColWidth, null, null, null);
+                vTmpDiv_1 = draw_utils_1.newNode(vTmpCell, 'div', null, 'gtaskcelldiv', '\u00A0\u00A0');
+                vTmpDiv_1 = draw_utils_1.newNode(vTmpDiv_1, 'div', this.vDivId + 'bardiv_' + vID, 'gtaskbarcontainer', null, 12, vTaskLeftPx_1 + vTaskRightPx - 6);
+                this.vTaskList[i].setBarDiv(vTmpDiv_1);
+                var vTmpDiv2 = draw_utils_1.newNode(vTmpDiv_1, 'div', this.vDivId + 'taskbar_' + vID, this.vTaskList[i].getClass(), null, 12);
+                this.vTaskList[i].setTaskDiv(vTmpDiv2);
+                if (this.vTaskList[i].getCompVal() < 100)
+                    vTmpDiv2.appendChild(document.createTextNode('\u25CA'));
+                else {
+                    vTmpDiv2 = draw_utils_1.newNode(vTmpDiv2, 'div', null, 'gmilediamond');
+                    draw_utils_1.newNode(vTmpDiv2, 'div', null, 'gmdtop');
+                    draw_utils_1.newNode(vTmpDiv2, 'div', null, 'gmdbottom');
+                }
+                vCaptClass = 'gmilecaption';
+                if (!vSingleCell && !vComb) {
+                    this.drawColsChart(vNumCols, vTmpRow, taskCellWidth, vMinDate, vMaxDate);
+                }
+            }
+            else {
+                var vTaskWidth = vTaskRightPx;
+                // Draw Group Bar which has outer div with inner group div
+                // and several small divs to left and right to create angled-end indicators
+                if (this.vTaskList[i].getGroup()) {
+                    vTaskWidth = (vTaskWidth > this.vMinGpLen && vTaskWidth < this.vMinGpLen * 2) ? this.vMinGpLen * 2 : vTaskWidth; // Expand to show two end points
+                    vTaskWidth = (vTaskWidth < this.vMinGpLen) ? this.vMinGpLen : vTaskWidth; // expand to show one end point
+                    var vTmpRow = draw_utils_1.newNode(vTmpTBody, 'tr', this.vDivId + 'childrow_' + vID, ((this.vTaskList[i].getGroup() == 2) ? 'glineitem gitem' : 'ggroupitem ggroup') + this.vFormat, null, null, null, ((this.vTaskList[i].getVisible() == 0) ? 'none' : null));
+                    this.vTaskList[i].setChildRow(vTmpRow);
+                    events_1.addThisRowListeners(this, this.vTaskList[i].getListChildRow(), vTmpRow);
+                    var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gtaskcell gtaskcellbar', null, vColWidth, null, null);
+                    vTmpDiv_1 = draw_utils_1.newNode(vTmpCell, 'div', null, 'gtaskcelldiv', '\u00A0\u00A0');
+                    this.vTaskList[i].setCellDiv(vTmpDiv_1);
+                    if (this.vTaskList[i].getGroup() == 1) {
+                        vTmpDiv_1 = draw_utils_1.newNode(vTmpDiv_1, 'div', this.vDivId + 'bardiv_' + vID, 'gtaskbarcontainer', null, vTaskWidth, vTaskLeftPx_1);
+                        this.vTaskList[i].setBarDiv(vTmpDiv_1);
+                        var vTmpDiv2 = draw_utils_1.newNode(vTmpDiv_1, 'div', this.vDivId + 'taskbar_' + vID, this.vTaskList[i].getClass(), null, vTaskWidth);
+                        this.vTaskList[i].setTaskDiv(vTmpDiv2);
+                        draw_utils_1.newNode(vTmpDiv2, 'div', this.vDivId + 'complete_' + vID, this.vTaskList[i].getClass() + 'complete', null, this.vTaskList[i].getCompStr());
+                        draw_utils_1.newNode(vTmpDiv_1, 'div', null, this.vTaskList[i].getClass() + 'endpointleft');
+                        if (vTaskWidth >= this.vMinGpLen * 2)
+                            draw_utils_1.newNode(vTmpDiv_1, 'div', null, this.vTaskList[i].getClass() + 'endpointright');
+                        vCaptClass = 'ggroupcaption';
+                    }
+                    if (!vSingleCell && !vComb) {
+                        this.drawColsChart(vNumCols, vTmpRow, taskCellWidth, vMinDate, vMaxDate);
+                    }
+                }
+                else {
+                    vTaskWidth = (vTaskWidth <= 0) ? 1 : vTaskWidth;
+                    /**
+                     * DRAW THE BOXES FOR GANTT
+                     */
+                    var vTmpDivCell = void 0, vTmpRow = void 0;
+                    if (vComb) {
+                        vTmpDivCell = vTmpDiv_1 = this.vTaskList[i].getParItem().getCellDiv();
+                    }
+                    else {
+                        // Draw Task Bar which has colored bar div
+                        vTmpRow = draw_utils_1.newNode(vTmpTBody, 'tr', this.vDivId + 'childrow_' + vID, 'glineitem gitem' + this.vFormat, null, null, null, ((this.vTaskList[i].getVisible() == 0) ? 'none' : null));
+                        this.vTaskList[i].setChildRow(vTmpRow);
+                        events_1.addThisRowListeners(this, this.vTaskList[i].getListChildRow(), vTmpRow);
+                        var vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gtaskcell gtaskcellcolorbar', null, taskCellWidth, null, null);
+                        vTmpDivCell = vTmpDiv_1 = draw_utils_1.newNode(vTmpCell, 'div', null, 'gtaskcelldiv', '\u00A0\u00A0');
+                    }
+                    // DRAW TASK BAR
+                    vTmpDiv_1 = draw_utils_1.newNode(vTmpDiv_1, 'div', this.vDivId + 'bardiv_' + vID, 'gtaskbarcontainer', null, vTaskWidth, vTaskLeftPx_1);
+                    this.vTaskList[i].setBarDiv(vTmpDiv_1);
+                    var vTmpDiv2 = void 0;
+                    if (this.vTaskList[i].getStartVar()) {
+                        // textbar
+                        vTmpDiv2 = draw_utils_1.newNode(vTmpDiv_1, 'div', this.vDivId + 'taskbar_' + vID, this.vTaskList[i].getClass(), null, vTaskWidth);
+                        if (this.vTaskList[i].getBarText()) {
+                            draw_utils_1.newNode(vTmpDiv2, 'span', this.vDivId + 'tasktextbar_' + vID, 'textbar', this.vTaskList[i].getBarText(), this.vTaskList[i].getCompRestStr());
+                        }
+                        this.vTaskList[i].setTaskDiv(vTmpDiv2);
+                    }
+                    // PLANNED
+                    // If exist and one of them are different, show plan bar... show if there is no real vStart as well (just plan dates)
+                    if (vTaskPlanLeftPx && ((vTaskPlanLeftPx != vTaskLeftPx_1 || vTaskPlanRightPx != vTaskRightPx) || !this.vTaskList[i].getStartVar())) {
+                        var vTmpPlanDiv = draw_utils_1.newNode(vTmpDivCell, 'div', this.vDivId + 'bardiv_' + vID, 'gtaskbarcontainer gplan', null, vTaskPlanRightPx, vTaskPlanLeftPx);
+                        var vTmpPlanDiv2 = draw_utils_1.newNode(vTmpPlanDiv, 'div', this.vDivId + 'taskbar_' + vID, this.vTaskList[i].getClass() + ' gplan', null, vTaskPlanRightPx);
+                        this.vTaskList[i].setPlanTaskDiv(vTmpPlanDiv2);
+                    }
+                    // and opaque completion div
+                    if (vTmpDiv2) {
+                        draw_utils_1.newNode(vTmpDiv2, 'div', this.vDivId + 'complete_' + vID, this.vTaskList[i].getClass() + 'complete', null, this.vTaskList[i].getCompStr());
+                    }
+                    // caption
+                    if (vComb)
+                        vTmpItem = this.vTaskList[i].getParItem();
+                    if (!vComb || (vComb && this.vTaskList[i].getParItem().getEnd() == this.vTaskList[i].getEnd()))
+                        vCaptClass = 'gcaption';
+                    // Background cells
+                    if (!vSingleCell && !vComb && vTmpRow) {
+                        this.drawColsChart(vNumCols, vTmpRow, taskCellWidth, vMinDate, vMaxDate);
+                    }
+                }
+            }
+            if (this.getCaptionType() && vCaptClass !== null) {
+                var vCaptionStr = void 0;
+                switch (this.getCaptionType()) {
+                    case 'Caption':
+                        vCaptionStr = vTmpItem.getCaption();
+                        break;
+                    case 'Resource':
+                        vCaptionStr = vTmpItem.getResource();
+                        break;
+                    case 'Duration':
+                        vCaptionStr = vTmpItem.getDuration(this.vFormat, this.vLangs[this.vLang]);
+                        break;
+                    case 'Complete':
+                        vCaptionStr = vTmpItem.getCompStr();
+                        break;
+                }
+                draw_utils_1.newNode(vTmpDiv_1, 'div', null, vCaptClass, vCaptionStr, 120, (vCaptClass == 'gmilecaption') ? 12 : 0);
+            }
+            // Add Task Info div for tooltip
+            if (this.vTaskList[i].getTaskDiv() && vTmpDiv_1) {
+                var vTmpDiv2 = draw_utils_1.newNode(vTmpDiv_1, 'div', this.vDivId + 'tt' + vID, null, null, null, null, 'none');
+                var _a = this.createTaskInfo(this.vTaskList[i], this.vTooltipTemplate), component = _a.component, callback = _a.callback;
+                vTmpDiv2.appendChild(component);
+                events_1.addTooltipListeners(this, this.vTaskList[i].getTaskDiv(), vTmpDiv2, callback);
+            }
+            // Add Plan Task Info div for tooltip
+            if (this.vTaskList[i].getPlanTaskDiv() && vTmpDiv_1) {
+                var vTmpDiv2 = draw_utils_1.newNode(vTmpDiv_1, 'div', this.vDivId + 'tt' + vID, null, null, null, null, 'none');
+                var _b = this.createTaskInfo(this.vTaskList[i], this.vTooltipTemplate), component = _b.component, callback = _b.callback;
+                vTmpDiv2.appendChild(component);
+                events_1.addTooltipListeners(this, this.vTaskList[i].getPlanTaskDiv(), vTmpDiv2, callback);
+            }
+        }
+        // Include the footer with the days/week/month...
+        if (vSingleCell) {
+            var vTmpTFootTRow = draw_utils_1.newNode(vTmpTFoot, 'tr');
+            var vTmpTFootTCell = draw_utils_1.newNode(vTmpTFootTRow, 'td', null, null, null, '100%');
+            var vTmpTFootTCellTable = draw_utils_1.newNode(vTmpTFootTCell, 'table', null, 'gcharttableh', null, '100%');
+            var vTmpTFootTCellTableTBody = draw_utils_1.newNode(vTmpTFootTCellTable, 'tbody');
+            vTmpTFootTCellTableTBody.appendChild(vDateRow.cloneNode(true));
+        }
+        else {
+            vTmpTFoot.appendChild(vDateRow.cloneNode(true));
+        }
+        return { vRightTable: vRightTable };
+    };
+    this.drawColsChart = function (vNumCols, vTmpRow, taskCellWidth, pStartDate, pEndDate) {
+        if (pStartDate === void 0) { pStartDate = null; }
+        if (pEndDate === void 0) { pEndDate = null; }
+        var columnCurrentDay = null;
+        // Find the Current day cell to put a different class
+        if (this.vShowWeekends !== false && pStartDate && pEndDate && (this.vFormat == 'day' || this.vFormat == 'week')) {
+            var curTaskStart = new Date(pStartDate.getTime());
+            var curTaskEnd = new Date();
+            var onePeriod = 3600000;
+            if (this.vFormat == 'day') {
+                onePeriod *= 24;
+            }
+            else if (this.vFormat == 'week') {
+                onePeriod *= 24 * 7;
+            }
+            columnCurrentDay = Math.floor(general_utils_1.calculateCurrentDateOffset(curTaskStart, curTaskEnd) / onePeriod) - 1;
+        }
+        for (var j = 0; j < vNumCols - 1; j++) {
+            var vCellFormat = 'gtaskcell gtaskcellcols';
+            if (this.vShowWeekends !== false && this.vFormat == 'day' && ((j % 7 == 4) || (j % 7 == 5))) {
+                vCellFormat = 'gtaskcellwkend';
+            }
+            //When is the column is the current day/week,give a different class
+            else if ((this.vFormat == 'week' || this.vFormat == 'day') && j === columnCurrentDay) {
+                vCellFormat = 'gtaskcellcurrent';
+            }
+            draw_utils_1.newNode(vTmpRow, 'td', null, vCellFormat, '\u00A0\u00A0', taskCellWidth);
+        }
+    };
+    /**
+     *
+     *
+     * DRAWING PROCESS
+     *
+     *  vTaskRightPx,vTaskWidth,vTaskPlanLeftPx,vTaskPlanRightPx,vID
+     */
+    this.Draw = function () {
+        var vMaxDate = new Date();
+        var vMinDate = new Date();
+        var vColWidth = 0;
+        var bd;
+        if (this.vEvents && this.vEvents.beforeDraw) {
+            this.vEvents.beforeDraw();
+        }
+        if (this.vDebug) {
+            bd = new Date();
+            console.info('before draw', bd);
+        }
+        // Process all tasks, reset parent date and completion % if task list has altered
+        if (this.vProcessNeeded)
+            task_1.processRows(this.vTaskList, 0, -1, 1, 1, this.getUseSort(), this.vDebug);
+        this.vProcessNeeded = false;
+        // get overall min/max dates plus padding
+        vMinDate = date_utils_1.getMinDate(this.vTaskList, this.vFormat, this.getMinDate() && date_utils_1.coerceDate(this.getMinDate()));
+        vMaxDate = date_utils_1.getMaxDate(this.vTaskList, this.vFormat, this.getMaxDate() && date_utils_1.coerceDate(this.getMaxDate()));
+        // Calculate chart width variables.
+        if (this.vFormat == 'day')
+            vColWidth = this.vDayColWidth;
+        else if (this.vFormat == 'week')
+            vColWidth = this.vWeekColWidth;
+        else if (this.vFormat == 'month')
+            vColWidth = this.vMonthColWidth;
+        else if (this.vFormat == 'quarter')
+            vColWidth = this.vQuarterColWidth;
+        else if (this.vFormat == 'hour')
+            vColWidth = this.vHourColWidth;
+        // DRAW the Left-side of the chart (names, resources, comp%)
+        var vLeftHeader = document.createDocumentFragment();
+        /**
+         * LIST HEAD
+        */
+        var gListLbl = this.drawListHead(vLeftHeader);
+        /**
+         * LIST BODY
+        */
+        var _a = this.drawListBody(vLeftHeader), vNumRows = _a.vNumRows, vTmpContentTabWrapper = _a.vTmpContentTabWrapper;
+        /**
+         * CHART HEAD
+         */
+        var _b = this.drawChartHead(vMinDate, vMaxDate, vColWidth, vNumRows), gChartLbl = _b.gChartLbl, vTaskLeftPx = _b.vTaskLeftPx, vSingleCell = _b.vSingleCell, vRightHeader = _b.vRightHeader, vDateRow = _b.vDateRow, vNumCols = _b.vNumCols;
+        /**
+         * CHART GRID
+         */
+        var vRightTable = this.drawCharBody(vTaskLeftPx, vTmpContentTabWrapper, gChartLbl, gListLbl, vMinDate, vMaxDate, vSingleCell, vNumCols, vColWidth, vDateRow).vRightTable;
+        if (this.vDebug) {
+            var ad = new Date();
+            console.info('after tasks loop', ad, (ad.getTime() - bd.getTime()));
+        }
+        // MAIN VIEW: Appending all generated components to main view
+        while (this.vDiv.hasChildNodes())
+            this.vDiv.removeChild(this.vDiv.firstChild);
+        var vTmpDiv = draw_utils_1.newNode(this.vDiv, 'div', null, 'gchartcontainer');
+        vTmpDiv.style.height = this.vTotalHeight;
+        var leftvTmpDiv = draw_utils_1.newNode(vTmpDiv, 'div', null, 'gmain gmainleft');
+        leftvTmpDiv.appendChild(vLeftHeader);
+        // leftvTmpDiv.appendChild(vLeftTable);
+        var rightvTmpDiv = draw_utils_1.newNode(vTmpDiv, 'div', null, 'gmain gmainright');
+        rightvTmpDiv.appendChild(vRightHeader);
+        rightvTmpDiv.appendChild(vRightTable);
+        vTmpDiv.appendChild(leftvTmpDiv);
+        vTmpDiv.appendChild(rightvTmpDiv);
+        draw_utils_1.newNode(vTmpDiv, 'div', null, 'ggridfooter');
+        var vTmpDiv2 = draw_utils_1.newNode(this.getChartBody(), 'div', this.vDivId + 'Lines', 'glinediv');
+        if (this.vEvents.onLineContainerHover && typeof this.vEvents.onLineContainerHover === 'function') {
+            events_1.addListener('mouseover', this.vEvents.onLineContainerHover, vTmpDiv2);
+            events_1.addListener('mouseout', this.vEvents.onLineContainerHover, vTmpDiv2);
+        }
+        vTmpDiv2.style.visibility = 'hidden';
+        this.setLines(vTmpDiv2);
+        /* Quick hack to show the generated HTML on older browsers
+              let tmpGenSrc=document.createElement('textarea');
+              tmpGenSrc.appendChild(document.createTextNode(vTmpDiv.innerHTML));
+              vDiv.appendChild(tmpGenSrc);
+        //*/
+        // LISTENERS: Now all the content exists, register scroll listeners
+        events_1.addScrollListeners(this);
+        // SCROLL: now check if we are actually scrolling the pane
+        if (this.vScrollTo != '') {
+            var vScrollDate = new Date(vMinDate.getTime());
+            var vScrollPx = 0;
+            if (this.vScrollTo.substr && this.vScrollTo.substr(0, 2) == 'px') {
+                vScrollPx = parseInt(this.vScrollTo.substr(2));
+            }
+            else {
+                if (this.vScrollTo === 'today') {
+                    vScrollDate = new Date();
+                }
+                else if (this.vScrollTo instanceof Date) {
+                    vScrollDate = this.vScrollTo;
+                }
+                else {
+                    vScrollDate = date_utils_1.parseDateStr(this.vScrollTo, this.getDateInputFormat());
+                }
+                if (this.vFormat == 'hour')
+                    vScrollDate.setMinutes(0, 0, 0);
+                else
+                    vScrollDate.setHours(0, 0, 0, 0);
+                vScrollPx = general_utils_1.getOffset(vMinDate, vScrollDate, vColWidth, this.vFormat, this.vShowWeekends) - 30;
+            }
+            this.getChartBody().scrollLeft = vScrollPx;
+        }
+        if (vMinDate.getTime() <= (new Date()).getTime() && vMaxDate.getTime() >= (new Date()).getTime()) {
+            this.vTodayPx = general_utils_1.getOffset(vMinDate, new Date(), vColWidth, this.vFormat, this.vShowWeekends);
+        }
+        else
+            this.vTodayPx = -1;
+        // DEPENDENCIES: Draw lines of Dependencies
+        var bdd;
+        if (this.vDebug) {
+            bdd = new Date();
+            console.info('before DrawDependencies', bdd);
+        }
+        if (this.vEvents && typeof this.vEvents.beforeLineDraw === 'function') {
+            this.vEvents.beforeLineDraw();
+        }
+        this.DrawDependencies(this.vDebug);
+        events_1.addListenerDependencies(this.vLineOptions);
+        // EVENTS
+        if (this.vEvents && typeof this.vEvents.afterLineDraw === 'function') {
+            this.vEvents.afterLineDraw();
+        }
+        if (this.vDebug) {
+            var ad = new Date();
+            console.info('after DrawDependencies', ad, (ad.getTime() - bdd.getTime()));
+        }
+        this.drawComplete(vMinDate, vColWidth, bd);
+    };
+    /**
+     * Actions after all the render process
+     */
+    this.drawComplete = function (vMinDate, vColWidth, bd) {
+        if (this.vDebug) {
+            var ad = new Date();
+            console.info('after draw', ad, (ad.getTime() - bd.getTime()));
+        }
+        events_1.updateGridHeaderWidth(this);
+        this.chartRowDateToX = function (date) {
+            return general_utils_1.getOffset(vMinDate, date, vColWidth, this.vFormat, this.vShowWeekends);
+        };
+        if (this.vEvents && this.vEvents.afterDraw) {
+            this.vEvents.afterDraw();
+        }
+    };
+    if (this.vDiv && this.vDiv.nodeName && this.vDiv.nodeName.toLowerCase() == 'div')
+        this.vDivId = this.vDiv.id;
+}; //GanttChart
 
-JSGantt.isIE=function ()
-{
-	if(typeof document.all!='undefined')
-	{
-		if ('pageXOffset' in window) return false;	// give IE9 and above the benefit of the doubt!
-		else return true;
-	}
-	else return false;
+},{"./draw_columns":3,"./draw_dependencies":4,"./events":5,"./lang":8,"./options":9,"./task":10,"./utils/date_utils":11,"./utils/draw_utils":12,"./utils/general_utils":13,"./xml":14}],3:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var date_utils_1 = require("./utils/date_utils");
+var task_1 = require("./task");
+var events_1 = require("./events");
+var draw_utils_1 = require("./utils/draw_utils");
+exports.COLUMN_ORDER = [
+    'vShowRes',
+    'vShowDur',
+    'vShowComp',
+    'vShowStartDate',
+    'vShowEndDate',
+    'vShowPlanStartDate',
+    'vShowPlanEndDate',
+    'vShowCost',
+    'vAdditionalHeaders',
+    'vShowAddEntries'
+];
+var COLUMNS_TYPES = {
+    'vShowRes': 'res',
+    'vShowDur': 'dur',
+    'vShowComp': 'comp',
+    'vShowStartDate': 'startdate',
+    'vShowEndDate': 'enddate',
+    'vShowPlanStartDate': 'planstartdate',
+    'vShowPlanEndDate': 'planenddate',
+    'vShowCost': 'cost',
+    'vShowAddEntries': 'addentries'
 };
-
-JSGantt.TaskItem=function(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGantt)
-{
-
-	var vID=parseInt(document.createTextNode(pID).data);
-	var vName=document.createTextNode(pName).data;
-	var vStart=new Date(0);
-	var vEnd=new Date(0);
-	var vGroupMinStart=null;
-	var vGroupMinEnd=null;
-	var vClass=document.createTextNode(pClass).data;
-	var vLink=document.createTextNode(pLink).data;
-	var vMile=parseInt(document.createTextNode(pMile).data);
-	var vRes=document.createTextNode(pRes).data;
-	var vComp=parseFloat(document.createTextNode(pComp).data);
-	var vGroup=parseInt(document.createTextNode(pGroup).data);
-	var vParent=document.createTextNode(pParent).data;
-	var vOpen=(vGroup==2)?1:parseInt(document.createTextNode(pOpen).data);
-	var vDepend=new Array();
-	var vDependType=new Array();
-	var vCaption=document.createTextNode(pCaption).data;
-	var vDuration='';
-	var vLevel=0;
-	var vNumKid=0;
-	var vWeight=0;
-	var vVisible=1;
-	var vSortIdx=0;
-	var vToDelete=false;
-	var x1, y1, x2, y2;
-	var vNotes;
-	var vParItem=null;
-	var vCellDiv=null;
-	var vGantt=(pGantt instanceof JSGantt.GanttChart)? pGantt : g; //hack for backwards compatibility
-	var vBarDiv=null;
-	var vTaskDiv=null;
-	var vListChildRow=null;
-	var vChildRow=null;
-	var vGroupSpan=null;
-
-	vNotes=document.createElement('span');
-	vNotes.className='gTaskNotes';
-	if (pNotes!=null)
-	{
-		vNotes.innerHTML=pNotes;
-		JSGantt.stripUnwanted(vNotes);
-	}
-
-	if (pStart!=null && pStart!='')
-	{
-		vStart=(pStart instanceof Date)?pStart:JSGantt.parseDateStr(document.createTextNode(pStart).data,vGantt.getDateInputFormat());
-		vGroupMinStart=vStart;
-	}
-
-	if (pEnd!=null && pEnd!='')
-	{
-		vEnd  =(pEnd instanceof Date)?pEnd:JSGantt.parseDateStr(document.createTextNode(pEnd).data,vGantt.getDateInputFormat());
-		vGroupMinEnd=vEnd;
-	}
-
-	if (pDepend!=null)
-	{
-		var vDependStr=pDepend+'';
-		var vDepList=vDependStr.split(',');
-		var n=vDepList.length;
-
-		for(var k=0;k<n;k++)
-		{
-			if(vDepList[k].toUpperCase().indexOf('SS')!=-1)
-			{
-				vDepend[k]=vDepList[k].substring(0,vDepList[k].toUpperCase().indexOf('SS'));
-				vDependType[k]='SS';
-			}
-			else if(vDepList[k].toUpperCase().indexOf('FF')!=-1)
-			{
-				vDepend[k]=vDepList[k].substring(0,vDepList[k].toUpperCase().indexOf('FF'));
-				vDependType[k]='FF';
-			}
-			else if(vDepList[k].toUpperCase().indexOf('SF')!=-1)
-			{
-				vDepend[k]=vDepList[k].substring(0,vDepList[k].toUpperCase().indexOf('SF'));
-				vDependType[k]='SF';
-			}
-			else if(vDepList[k].toUpperCase().indexOf('FS')!=-1)
-			{
-				vDepend[k]=vDepList[k].substring(0,vDepList[k].toUpperCase().indexOf('FS'));
-				vDependType[k]='FS';
-			}
-			else
-			{
-				vDepend[k]=vDepList[k];
-				vDependType[k]='FS';
-			}
-		}
-	}
-
-	this.getID=function(){return vID;};
-	this.getName=function(){return vName;};
-	this.getStart=function(){return vStart;};
-	this.getEnd=function(){return vEnd;};
-	this.getGroupMinStart=function(){return vGroupMinStart;};
-	this.getGroupMinEnd=function(){return vGroupMinEnd;};
-	this.getClass=function(){return vClass;};
-	this.getLink=function(){return vLink;};
-	this.getMile=function(){return vMile;};
-	this.getDepend=function(){if(vDepend) return vDepend; else return null;};
-	this.getDepType=function(){if(vDependType) return vDependType; else return null;};
-	this.getCaption=function(){if(vCaption) return vCaption; else return '';};
-	this.getResource=function(){if(vRes) return vRes; else return '\u00A0';};
-	this.getCompVal=function(){if(vComp) return vComp; else return 0;};
-	this.getCompStr=function(){if(vComp) return vComp+'%'; else return '';};
-	this.getNotes=function(){return vNotes;};
-	this.getSortIdx=function(){return vSortIdx;};
-	this.getToDelete=function(){return vToDelete;};
-
-	this.getDuration=function(pFormat, pLang)
-	{
-		if (vMile)
-		{
-			vDuration='-';
-		}
-		else
-		{
-			var vTaskEnd=new Date(this.getEnd().getTime());
-			var vUnits=null;
-			switch(pFormat)
-			{
-				case 'week':  vUnits='day'; break;
-				case 'month':  vUnits='week'; break;
-				case 'quarter': vUnits='month'; break;
-				default: vUnits=pFormat; break;
-			}
-
-			if ((vTaskEnd.getTime()-(vTaskEnd.getTimezoneOffset()*60000))%(86400000)==0)
-			{
-				vTaskEnd=new Date(vTaskEnd.getFullYear(), vTaskEnd.getMonth(), vTaskEnd.getDate()+1, vTaskEnd.getHours(), vTaskEnd.getMinutes(), vTaskEnd.getSeconds());
-			}
-			var tmpPer=(JSGantt.getOffset(this.getStart(), vTaskEnd, 999, vUnits))/1000;
-			if(Math.floor(tmpPer)!=tmpPer) tmpPer=Math.round(tmpPer*10)/10;
-			switch(vUnits)
-			{
-				case 'hour': vDuration=tmpPer+' '+((tmpPer!=1)?pLang['hrs']:pLang['hr']); break;
-				case 'day': vDuration=tmpPer+' '+((tmpPer!=1)?pLang['dys']:pLang['dy']); break;
-				case 'week': vDuration=tmpPer+' '+((tmpPer!=1)?pLang['wks']:pLang['wk']); break;
-				case 'month': vDuration=tmpPer+' '+((tmpPer!=1)?pLang['mths']:pLang['mth']); break;
-				case 'quarter': vDuration=tmpPer+' '+((tmpPer!=1)?pLang['qtrs']:pLang['qtr']); break;
-			}
-		}
-		return vDuration;
-	};
-
-	this.getParent=function(){return vParent;};
-	this.getGroup=function(){return vGroup;};
-	this.getOpen=function(){return vOpen;};
-	this.getLevel=function(){return vLevel;};
-	this.getNumKids=function(){return vNumKid;};
-	this.getWeight=function(){return vWeight;};
-	this.getStartX=function(){return x1;};
-	this.getStartY=function(){return y1;};
-	this.getEndX=function(){return x2;};
-	this.getEndY=function(){return y2;};
-	this.getVisible=function(){return vVisible;};
-	this.getParItem=function(){return vParItem;};
-	this.getCellDiv=function(){return vCellDiv;};
-	this.getBarDiv=function(){return vBarDiv;};
-	this.getTaskDiv=function(){return vTaskDiv;};
-	this.getChildRow=function(){return vChildRow;};
-	this.getListChildRow=function(){return vListChildRow;};
-	this.getGroupSpan=function(){return vGroupSpan;};
-	this.setStart=function(pStart){if(pStart instanceof Date)vStart=pStart;};
-	this.setEnd=function(pEnd){if(pEnd instanceof Date)vEnd=pEnd;};
-	this.setGroupMinStart=function(pStart){if(pStart instanceof Date)vGroupMinStart=pStart;};
-	this.setGroupMinEnd=function(pEnd){if(pEnd instanceof Date)vGroupMinEnd=pEnd;};
-	this.setLevel=function(pLevel){vLevel=parseInt(document.createTextNode(pLevel).data);};
-	this.setNumKid=function(pNumKid){vNumKid=parseInt(document.createTextNode(pNumKid).data);};
-	this.setWeight=function(pWeight){vWeight=parseInt(document.createTextNode(pWeight).data);};
-	this.setCompVal=function(pCompVal){vComp=parseFloat(document.createTextNode(pCompVal).data);};
-	this.setStartX=function(pX){x1=parseInt(document.createTextNode(pX).data);};
-	this.setStartY=function(pY){y1=parseInt(document.createTextNode(pY).data);};
-	this.setEndX=function(pX){x2=parseInt(document.createTextNode(pX).data);};
-	this.setEndY=function(pY){y2=parseInt(document.createTextNode(pY).data);};
-	this.setOpen=function(pOpen){vOpen=parseInt(document.createTextNode(pOpen).data);};
-	this.setVisible=function(pVisible){vVisible=parseInt(document.createTextNode(pVisible).data);};
-	this.setSortIdx=function(pSortIdx){vSortIdx=parseInt(document.createTextNode(pSortIdx).data);};
-	this.setToDelete=function(pToDelete){if (pToDelete) vToDelete=true; else vToDelete=false;};
-	this.setParItem=function(pParItem){if(pParItem instanceof JSGantt.TaskItem) vParItem=pParItem;};
-	this.setCellDiv=function(pCellDiv){if(typeof HTMLDivElement !== 'function' || pCellDiv instanceof HTMLDivElement) vCellDiv=pCellDiv;}; //"typeof HTMLDivElement !== 'function'" to play nice with ie6 and 7
-	this.setGroup=function(pGroup){vGroup=parseInt(document.createTextNode(pGroup).data);};
-	this.setBarDiv=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vBarDiv=pDiv;};
-	this.setTaskDiv=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vTaskDiv=pDiv;};
-	this.setChildRow=function(pRow){if(typeof HTMLTableRowElement !== 'function' || pRow instanceof HTMLTableRowElement)vChildRow=pRow;};
-	this.setListChildRow=function(pRow){if(typeof HTMLTableRowElement !== 'function' || pRow instanceof HTMLTableRowElement)vListChildRow=pRow;};
-	this.setGroupSpan=function(pSpan){if(typeof HTMLSpanElement !== 'function' || pSpan instanceof HTMLSpanElement)vGroupSpan=pSpan;};
+exports.draw_header = function (column, i, vTmpRow, vTaskList, vEditable, vEventsChange, vEvents, vDateTaskTableDisplayFormat, vAdditionalHeaders, vFormat, vLangs, vLang, vResources, Draw) {
+    var vTmpCell, vTmpDiv;
+    if ('vShowRes' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gres');
+        var text = draw_utils_1.makeInput(vTaskList[i].getResource(), vEditable, 'resource', vTaskList[i].getResource(), vResources);
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, text);
+        var callback = function (task, e) { return task.setResource(e.target.value); };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'res', Draw, 'change');
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'res');
+    }
+    if ('vShowDur' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gdur');
+        var text = draw_utils_1.makeInput(vTaskList[i].getDuration(vFormat, vLangs[vLang]), vEditable, 'text', vTaskList[i].getDuration());
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, text);
+        var callback = function (task, e) { return task.setDuration(e.target.value); };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'dur', Draw);
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'dur');
+    }
+    if ('vShowComp' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gcomp');
+        var text = draw_utils_1.makeInput(vTaskList[i].getCompStr(), vEditable, 'percentage', vTaskList[i].getCompVal());
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, text);
+        var callback = function (task, e) { task.setComp(e.target.value); task.setCompVal(e.target.value); };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'comp', Draw);
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'comp');
+    }
+    if ('vShowStartDate' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gstartdate');
+        var v = date_utils_1.formatDateStr(vTaskList[i].getStartVar(), vDateTaskTableDisplayFormat, vLangs[vLang]);
+        var text = draw_utils_1.makeInput(v, vEditable, 'date', vTaskList[i].getStartVar());
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, text);
+        var callback = function (task, e) { return task.setStart(e.target.value); };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'start', Draw);
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'start');
+    }
+    if ('vShowEndDate' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'genddate');
+        var v = date_utils_1.formatDateStr(vTaskList[i].getEndVar(), vDateTaskTableDisplayFormat, vLangs[vLang]);
+        var text = draw_utils_1.makeInput(v, vEditable, 'date', vTaskList[i].getEndVar());
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, text);
+        var callback = function (task, e) { return task.setEnd(e.target.value); };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'end', Draw);
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'end');
+    }
+    if ('vShowPlanStartDate' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gplanstartdate');
+        var v = vTaskList[i].getPlanStart() ? date_utils_1.formatDateStr(vTaskList[i].getPlanStart(), vDateTaskTableDisplayFormat, vLangs[vLang]) : '';
+        var text = draw_utils_1.makeInput(v, vEditable, 'date', vTaskList[i].getPlanStart());
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, text);
+        var callback = function (task, e) { return task.setPlanStart(e.target.value); };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'planstart', Draw);
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'planstart');
+    }
+    if ('vShowPlanEndDate' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gplanenddate');
+        var v = vTaskList[i].getPlanEnd() ? date_utils_1.formatDateStr(vTaskList[i].getPlanEnd(), vDateTaskTableDisplayFormat, vLangs[vLang]) : '';
+        var text = draw_utils_1.makeInput(v, vEditable, 'date', vTaskList[i].getPlanEnd());
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, text);
+        var callback = function (task, e) { return task.setPlanEnd(e.target.value); };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'planend', Draw);
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'planend');
+    }
+    if ('vShowCost' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gcost');
+        var text = draw_utils_1.makeInput(vTaskList[i].getCost(), vEditable, 'cost');
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, text);
+        var callback = function (task, e) { return task.setCost(e.target.value); };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'cost', Draw);
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'cost');
+    }
+    if ('vAdditionalHeaders' === column && vAdditionalHeaders) {
+        for (var key in vAdditionalHeaders) {
+            var header = vAdditionalHeaders[key];
+            var css = header.class ? header.class : "gadditional-" + key;
+            var data = vTaskList[i].getDataObject();
+            vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, "gadditional " + css);
+            vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, data ? data[key] : '');
+            events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], "additional_" + key);
+            // const callback = (task, e) => task.setCost(e.target.value);
+            // addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'costdate');
+        }
+    }
+    if ('vShowAddEntries' === column) {
+        vTmpCell = draw_utils_1.newNode(vTmpRow, 'td', null, 'gaddentries');
+        var button = "<button>+</button>";
+        vTmpDiv = draw_utils_1.newNode(vTmpCell, 'div', null, null, button);
+        var callback = function (task, e) {
+            task_1.AddTaskItemObject({
+                vParent: task.getParent()
+            });
+        };
+        events_1.addListenerInputCell(vTmpCell, vEventsChange, callback, vTaskList, i, 'addentries', Draw.bind(this));
+        events_1.addListenerClickCell(vTmpCell, vEvents, vTaskList[i], 'addentries');
+    }
 };
-
-// function that loads the main gantt chart properties and functions
-// pDiv: (required) this is a div object created in HTML
-// pFormat: (required) - used to indicate whether chart should be drawn in "hour", "day", "week", "month", or "quarter" format
-JSGantt.GanttChart=function(pDiv, pFormat)
-{
-	var vDiv=pDiv;
-	var vFormat=pFormat;
-	var vDivId=null;
-	var vUseFade=1;
-	var vUseMove=1;
-	var vUseRowHlt=1;
-	var vUseToolTip=1;
-	var vUseSort=1;
-	var vUseSingleCell=25000;
-	var vShowRes=1;
-	var vShowDur=1;
-	var vShowComp=1;
-	var vShowStartDate=1;
-	var vShowEndDate=1;
-	var vShowEndWeekDate=1;
-	var vShowTaskInfoRes=1;
-	var vShowTaskInfoDur=1;
-	var vShowTaskInfoComp=1;
-	var vShowTaskInfoStartDate=1;
-	var vShowTaskInfoEndDate=1;
-	var vShowTaskInfoNotes=1;
-	var vShowTaskInfoLink=0;
-	var vShowDeps=1;
-	var vShowSelector=new Array('top');
-	var vDateInputFormat='yyyy-mm-dd';
-	var vDateTaskTableDisplayFormat=JSGantt.parseDateFormatStr('dd/mm/yyyy');
-	var vDateTaskDisplayFormat=JSGantt.parseDateFormatStr('dd month yyyy');
-	var vHourMajorDateDisplayFormat=JSGantt.parseDateFormatStr('day dd month yyyy');
-	var vHourMinorDateDisplayFormat=JSGantt.parseDateFormatStr('HH');
-	var vDayMajorDateDisplayFormat=JSGantt.parseDateFormatStr('dd/mm/yyyy');
-	var vDayMinorDateDisplayFormat=JSGantt.parseDateFormatStr('dd');
-	var vWeekMajorDateDisplayFormat=JSGantt.parseDateFormatStr('yyyy');
-	var vWeekMinorDateDisplayFormat=JSGantt.parseDateFormatStr('dd/mm');
-	var vMonthMajorDateDisplayFormat=JSGantt.parseDateFormatStr('yyyy');
-	var vMonthMinorDateDisplayFormat=JSGantt.parseDateFormatStr('mon');
-	var vQuarterMajorDateDisplayFormat=JSGantt.parseDateFormatStr('yyyy');
-	var vQuarterMinorDateDisplayFormat=JSGantt.parseDateFormatStr('qq');
-	var vUseFullYear=JSGantt.parseDateFormatStr('dd/mm/yyyy');
-	var vCaptionType;
-	var vDepId=1;
-	var vTaskList=new Array();
-	var vFormatArr=new Array('hour','day','week','month','quarter');
-	var vMonthDaysArr=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
-	var vProcessNeeded=true;
-	var vMinGpLen=8;
-	var vScrollTo='';
-	var vHourColWidth=18;
-	var vDayColWidth=18;
-	var vWeekColWidth=36;
-	var vMonthColWidth=36;
-	var vQuarterColWidth=18;
-	var vRowHeight=20;
-	var vTodayPx=-1;
-	var vLangs={'en':
-			{'format':'Format','hour':'Hour','day':'Day','week':'Week','month':'Month','quarter':'Quarter','hours':'Hours','days':'Days',
-			 'weeks':'Weeks','months':'Months','quarters':'Quarters','hr':'Hr','dy':'Day','wk':'Wk','mth':'Mth','qtr':'Qtr','hrs':'Hrs',
-			 'dys':'Days','wks':'Wks','mths':'Mths','qtrs':'Qtrs','resource':'Resource','duration':'Duration','comp':'%',
-			 'completion':'Completion','startdate':'Start Date','enddate':'End Date','moreinfo':'More Information','notes':'Notes',
-			 'january':'January','february':'February','march':'March','april':'April','maylong':'May','june':'June','july':'July',
-			 'august':'August','september':'September','october':'October','november':'November','december':'December','jan':'Jan',
-			 'feb':'Feb','mar':'Mar','apr':'Apr','may':'May','jun':'Jun','jul':'Jul','aug':'Aug','sep':'Sep','oct':'Oct','nov':'Nov',
-			 'dec':'Dec','sunday':'Sunday','monday':'Monday','tuesday':'Tuesday','wednesday':'Wednesday','thursday':'Thursday',
-			 'friday':'Friday','saturday':'Saturday','sun':'Sun','mon':'Mon','tue':'Tue','wed':'Wed','thu':'Thu','fri':'Fri','sat':'Sat'}
-		};
-	var vLang='en';
-	var vChartBody=null;
-	var vChartHead=null;
-	var vListBody=null;
-	var vChartTable=null;
-	var vLines=null;
-	var vTimer=20;
-
-	this.setUseFade=function(pVal){vUseFade=pVal;};
-	this.setUseMove=function(pVal){vUseMove=pVal;};
-	this.setUseRowHlt=function(pVal){vUseRowHlt=pVal;};
-	this.setUseToolTip=function(pVal){vUseToolTip=pVal;};
-	this.setUseSort=function(pVal){vUseSort=pVal;};
-	this.setUseSingleCell=function(pVal){vUseSingleCell=pVal*1;};
-	this.setFormatArr=function()
-	{
-		var vValidFormats='hour day week month quarter';
-		vFormatArr=new Array();
-		for(var i=0, j=0; i<arguments.length; i++)
-		{
-			if (vValidFormats.indexOf(arguments[i].toLowerCase())!=-1 && arguments[i].length>1)
-			{
-				vFormatArr[j++]=arguments[i].toLowerCase();
-				var vRegExp=new RegExp('(?:^|\s)'+arguments[i]+'(?!\S)', 'g');
-				vValidFormats=vValidFormats.replace(vRegExp, '');
-			}
-		}
-	};
-	this.setShowRes=function(pVal){vShowRes=pVal;};
-	this.setShowDur=function(pVal){vShowDur=pVal;};
-	this.setShowComp=function(pVal){vShowComp=pVal;};
-	this.setShowStartDate=function(pVal){vShowStartDate=pVal;};
-	this.setShowEndDate=function(pVal){vShowEndDate=pVal;};
-	this.setShowTaskInfoRes=function(pVal){vShowTaskInfoRes=pVal;};
-	this.setShowTaskInfoDur=function(pVal){vShowTaskInfoDur=pVal;};
-	this.setShowTaskInfoComp=function(pVal){vShowTaskInfoComp=pVal;};
-	this.setShowTaskInfoStartDate=function(pVal){vShowTaskInfoStartDate=pVal;};
-	this.setShowTaskInfoEndDate=function(pVal){vShowTaskInfoEndDate=pVal;};
-	this.setShowTaskInfoNotes=function(pVal){vShowTaskInfoNotes=pVal;};
-	this.setShowTaskInfoLink=function(pVal){vShowTaskInfoLink=pVal;};
-	this.setShowEndWeekDate=function(pVal){vShowEndWeekDate=pVal;};
-	this.setShowSelector=function()
-	{
-		var vValidSelectors='top bottom';
-		vShowSelector=new Array();
-		for(var i=0, j=0; i<arguments.length; i++)
-		{
-			if (vValidSelectors.indexOf(arguments[i].toLowerCase())!=-1 && arguments[i].length>1)
-			{
-				vShowSelector[j++]=arguments[i].toLowerCase();
-				var vRegExp=new RegExp('(?:^|\s)'+arguments[i]+'(?!\S)', 'g');
-				vValidSelectors=vValidSelectors.replace(vRegExp, '');
-			}
-		}
-	};
-	this.setShowDeps=function(pVal){vShowDeps=pVal;};
-	this.setDateInputFormat=function(pVal){vDateInputFormat=pVal;};
-	this.setDateTaskTableDisplayFormat=function(pVal){vDateTaskTableDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setDateTaskDisplayFormat=function(pVal){vDateTaskDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setHourMajorDateDisplayFormat=function(pVal){vHourMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setHourMinorDateDisplayFormat=function(pVal){vHourMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setDayMajorDateDisplayFormat=function(pVal){vDayMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setDayMinorDateDisplayFormat=function(pVal){vDayMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setWeekMajorDateDisplayFormat=function(pVal){vWeekMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setWeekMinorDateDisplayFormat=function(pVal){vWeekMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setMonthMajorDateDisplayFormat=function(pVal){vMonthMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setMonthMinorDateDisplayFormat=function(pVal){vMonthMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setQuarterMajorDateDisplayFormat=function(pVal){vQuarterMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setQuarterMinorDateDisplayFormat=function(pVal){vQuarterMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);};
-	this.setCaptionType=function(pType){vCaptionType=pType;};
-	this.setFormat=function(pFormat)
-	{
-		vFormat=pFormat;
-		this.Draw();
-	};
-	this.setMinGpLen=function(pMinGpLen){vMinGpLen=pMinGpLen;};
-	this.setScrollTo=function(pDate){vScrollTo=pDate;};
-	this.setHourColWidth=function(pWidth){vHourColWidth=pWidth;};
-	this.setDayColWidth=function(pWidth){vDayColWidth=pWidth;};
-	this.setWeekColWidth=function(pWidth){vWeekColWidth=pWidth;};
-	this.setMonthColWidth=function(pWidth){vMonthColWidth=pWidth;};
-	this.setQuarterColWidth=function(pWidth){vQuarterColWidth=pWidth;};
-	this.setRowHeight=function(pHeight){vRowHeight=pHeight;};
-	this.setLang=function(pLang){if(vLangs[pLang])vLang=pLang;};
-	this.setChartBody=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vChartBody=pDiv;};
-	this.setChartHead=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vChartHead=pDiv;};
-	this.setListBody=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vListBody=pDiv;};
-	this.setChartTable=function(pTable){if(typeof HTMLTableElement !== 'function' || pTable instanceof HTMLTableElement)vChartTable=pTable;};
-	this.setLines=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vLines=pDiv;};
-	this.setTimer=function(pVal){vTimer=pVal*1;};
-	this.addLang=function(pLang, pVals){
-		if(!vLangs[pLang])
-		{
-			vLangs[pLang]=new Object();
-			for(var vKey in vLangs['en'])vLangs[pLang][vKey]=(pVals[vKey])?document.createTextNode(pVals[vKey]).data:vLangs['en'][vKey];
-		}
-	};
-
-	this.getDivId=function(){return vDivId;};
-	this.getUseFade=function(){return vUseFade;};
-	this.getUseMove=function(){return vUseMove;};
-	this.getUseRowHlt=function(){return vUseRowHlt;};
-	this.getUseToolTip=function(){return vUseToolTip;};
-	this.getUseSort=function(){return vUseSort;};
-	this.getUseSingleCell=function(){return vUseSingleCell;};
-	this.getFormatArr=function(){return vFormatArr;};
-	this.getShowRes=function(){return vShowRes;};
-	this.getShowDur=function(){return vShowDur;};
-	this.getShowComp=function(){return vShowComp;};
-	this.getShowStartDate=function(){return vShowStartDate;};
-	this.getShowEndDate=function(){return vShowEndDate;};
-	this.getShowTaskInfoRes=function(){return vShowTaskInfoRes;};
-	this.getShowTaskInfoDur=function(){return vShowTaskInfoDur;};
-	this.getShowTaskInfoComp=function(){return vShowTaskInfoComp;};
-	this.getShowTaskInfoStartDate=function(){return vShowTaskInfoStartDate;};
-	this.getShowTaskInfoEndDate=function(){return vShowTaskInfoEndDate;};
-	this.getShowTaskInfoNotes=function(){return vShowTaskInfoNotes;};
-	this.getShowTaskInfoLink=function(){return vShowTaskInfoLink;};
-	this.getShowEndWeekDate=function(){return vShowEndWeekDate;};
-	this.getShowSelector=function(){return vShowSelector;};
-	this.getShowDeps=function(){return vShowDeps;};
-	this.getDateInputFormat=function(){return vDateInputFormat;};
-	this.getDateTaskTableDisplayFormat=function(){return vDateTaskTableDisplayFormat;};
-	this.getDateTaskDisplayFormat=function(){return vDateTaskDisplayFormat;};
-	this.getHourMajorDateDisplayFormat=function(){return vHourMajorDateDisplayFormat;};
-	this.getHourMinorDateDisplayFormat=function(){return vHourMinorDateDisplayFormat;};
-	this.getDayMajorDateDisplayFormat=function(){return vDayMajorDateDisplayFormat;};
-	this.getDayMinorDateDisplayFormat=function(){return vDayMinorDateDisplayFormat;};
-	this.getWeekMajorDateDisplayFormat=function(){return vWeekMajorDateDisplayFormat;};
-	this.getWeekMinorDateDisplayFormat=function(){return vWeekMinorDateDisplayFormat;};
-	this.getMonthMajorDateDisplayFormat=function(){return vMonthMajorDateDisplayFormat;};
-	this.getMonthMinorDateDisplayFormat=function(){return vMonthMinorDateDisplayFormat;};
-	this.getQuarterMajorDateDisplayFormat=function(){return vQuarterMajorDateDisplayFormat;};
-	this.getQuarterMinorDateDisplayFormat=function(){return vQuarterMinorDateDisplayFormat;};
-	this.getCaptionType=function(){return vCaptionType;};
-	this.getMinGpLen=function(){return vMinGpLen;};
-	this.getScrollTo=function(){return vScrollTo;};
-	this.getHourColWidth=function(){return vHourColWidth;};
-	this.getDayColWidth=function(){return vDayColWidth;};
-	this.getWeekColWidth=function(){return vWeekColWidth;};
-	this.getMonthColWidth=function(){return vMonthColWidth;};
-	this.getQuarterColWidth=function(){return vQuarterColWidth;};
-	this.getRowHeight=function(){return vRowHeight;};
-	this.getChartBody=function(){return vChartBody;};
-	this.getChartHead=function(){return vChartHead;};
-	this.getListBody=function(){return vListBody;};
-	this.getChartTable=function(){return vChartTable;};
-	this.getLines=function(){return vLines;};
-	this.getTimer=function(){return vTimer;};
-
-	this.CalcTaskXY=function()
-	{
-		var vID;
-		var vList=this.getList();
-		var vBarDiv;
-		var vTaskDiv;
-		var vParDiv;
-		var vLeft, vTop, vWidth;
-		var vHeight=Math.floor((this.getRowHeight()/2));
-
-		for(var i=0; i<vList.length; i++)
-		{
-			vID=vList[i].getID();
-			vBarDiv=vList[i].getBarDiv();
-			vTaskDiv=vList[i].getTaskDiv();
-			if((vList[i].getParItem() && vList[i].getParItem().getGroup()==2))
-			{
-				vParDiv=vList[i].getParItem().getChildRow();
-			}
-			else vParDiv=vList[i].getChildRow();
-
-			if(vBarDiv)
-			{
-				vList[i].setStartX(vBarDiv.offsetLeft+1);
-				vList[i].setStartY(vParDiv.offsetTop+vBarDiv.offsetTop+vHeight-1);
-				vList[i].setEndX(vBarDiv.offsetLeft+vBarDiv.offsetWidth+1);
-				vList[i].setEndY(vParDiv.offsetTop+vBarDiv.offsetTop+vHeight-1);
-			}
-		}
-	};
-
-	this.AddTaskItem=function(value)
-	{
-		var vExists=false;
-		for (var i=0; i<vTaskList.length; i++)
-		{
-			if (vTaskList[i].getID()==value.getID())
-			{
-				i=vTaskList.length;
-				vExists=true;
-			}
-		}
-		if(!vExists)
-		{
-			vTaskList.push(value);
-			vProcessNeeded=true;
-		}
-	};
-
-	this.RemoveTaskItem=function(pID)
-	{
-		// simply mark the task for removal at this point - actually remove it next time we re-draw the chart
-		for (var i=0; i<vTaskList.length; i++)
-		{
-			if (vTaskList[i].getID()==pID) vTaskList[i].setToDelete(true);
-			else if (vTaskList[i].getParent()==pID) this.RemoveTaskItem(vTaskList[i].getID());
-		}
-		vProcessNeeded=true;
-	};
-
-	this.getList=function(){return vTaskList;};
-
-	this.clearDependencies=function()
-	{
-		var parent=this.getLines();
-		while(parent.hasChildNodes())parent.removeChild(parent.firstChild);
-		vDepId=1;
-	};
-
-
-	// sLine: Draw a straight line (colored one-pixel wide div)
-	this.sLine=function(x1,y1,x2,y2,pClass)
-	{
-		var vLeft=Math.min(x1,x2);
-		var vTop=Math.min(y1,y2);
-		var vWid=Math.abs(x2-x1)+1;
-		var vHgt=Math.abs(y2-y1)+1;
-
-		var vTmpDiv=document.createElement('div');
-		vTmpDiv.id=vDivId+'line'+vDepId++;
-		vTmpDiv.style.position='absolute';
-		vTmpDiv.style.overflow='hidden';
-		vTmpDiv.style.zIndex=0;
-		vTmpDiv.style.left=vLeft+'px';
-		vTmpDiv.style.top=vTop+'px';
-		vTmpDiv.style.width=vWid+'px';
-		vTmpDiv.style.height=vHgt+'px';
-
-		vTmpDiv.style.visibility='visible';
-
-		if (vWid==1) vTmpDiv.className='glinev';
-		else vTmpDiv.className='glineh';
-
-		if (pClass) vTmpDiv.className+=' '+pClass;
-
-		this.getLines().appendChild(vTmpDiv);
-
-		return vTmpDiv;
-	};
-
-	this.drawDependency =function(x1,y1,x2,y2,pType,pClass)
-	{
-		var vDir=1;
-		var vBend=false;
-		var vShort=4;
-		var vRow=Math.floor(this.getRowHeight()/2);
-
-		if(y2<y1) vRow*=-1;
-
-		switch(pType)
-		{
-			case 'SF':
-				vShort*=-1;
-				if(x1-10<=x2 && y1!=y2) vBend=true;
-				vDir=-1;
-				break;
-			case 'SS':
-				if (x1<x2) vShort*=-1;
-				else vShort=x2-x1-(2*vShort);
-				break;
-			case 'FF':
-				if (x1<=x2) vShort=x2-x1+(2*vShort);
-				vDir=-1;
-				break;
-			default:
-				if(x1+10>=x2 && y1!=y2) vBend=true;
-				break;
-		}
-
-		if (vBend)
-		{
-			this.sLine(x1,y1,x1+vShort,y1,pClass);
-			this.sLine(x1+vShort,y1,x1+vShort,y2-vRow,pClass);
-			this.sLine(x1+vShort,y2-vRow,x2-(vShort*2),y2-vRow,pClass);
-			this.sLine(x2-(vShort*2),y2-vRow,x2-(vShort*2),y2,pClass);
-			this.sLine(x2-(vShort*2),y2,x2-(1*vDir),y2,pClass);
-		}
-		else if (y1!=y2)
-		{
-			this.sLine(x1,y1,x1+vShort,y1,pClass);
-			this.sLine(x1+vShort,y1,x1+vShort,y2,pClass);
-			this.sLine(x1+vShort,y2,x2-(1*vDir),y2,pClass);
-		}
-		else this.sLine(x1,y1,x2-(1*vDir),y2,pClass);
-
-		var vTmpDiv=this.sLine(x2,y2,x2-3-((vDir<0)?1:0),y2-3-((vDir<0)?1:0),pClass+"Arw");
-		vTmpDiv.style.width='0px';
-		vTmpDiv.style.height='0px';
-	};
-
-	this.DrawDependencies=function()
-	{
-		if (this.getShowDeps()==1)
-		{
-			//First recalculate the x,y
-			this.CalcTaskXY();
-			this.clearDependencies();
-
-			var vList=this.getList();
-			for(var i=0; i<vList.length; i++)
-			{
-				var vDepend=vList[i].getDepend();
-				var vDependType=vList[i].getDepType();
-				var n=vDepend.length;
-
-				if(n>0 && vList[i].getVisible()==1)
-				{
-					for(var k=0;k<n;k++)
-					{
-						var vTask=this.getArrayLocationByID(vDepend[k]);
-						if (vTask>=0 && vList[vTask].getGroup()!=2)
-						{
-							if(vList[vTask].getVisible()==1)
-							{
-								if(vDependType[k]=='SS')this.drawDependency(vList[vTask].getStartX()-1,vList[vTask].getStartY(),vList[i].getStartX()-1,vList[i].getStartY(),'SS','gDepSS');
-								else if(vDependType[k]=='FF')this.drawDependency(vList[vTask].getEndX(),vList[vTask].getEndY(),vList[i].getEndX(),vList[i].getEndY(),'FF','gDepFF');
-								else if(vDependType[k]=='SF')this.drawDependency(vList[vTask].getStartX()-1,vList[vTask].getStartY(),vList[i].getEndX(),vList[i].getEndY(),'SF','gDepSF');
-								else if(vDependType[k]=='FS')this.drawDependency(vList[vTask].getEndX(),vList[vTask].getEndY(),vList[i].getStartX()-1,vList[i].getStartY(),'FS','gDepFS');
-							}
-						}
-					}
-				}
-			}
-		}
-		// draw the current date line
-		if (vTodayPx>=0) this.sLine(vTodayPx, 0, vTodayPx, this.getChartTable().offsetHeight-1, 'gCurDate');
-	};
-
-	this.getArrayLocationByID=function(pId)
-	{
-		var vList=this.getList();
-		for(var i=0; i<vList.length; i++)
-		{
-			if(vList[i].getID()==pId)
-			return i;
-		}
-		return -1;
-	};
-
-	this.newNode=function(pParent, pNodeType, pId, pClass, pText, pWidth, pLeft, pDisplay, pColspan, pAttribs)
-	{
-		var vNewNode=pParent.appendChild(document.createElement(pNodeType));
-		if (pAttribs)
-		{
-			for (var i=0; i+1<pAttribs.length; i+=2)
-			{
-				vNewNode.setAttribute(pAttribs[i],pAttribs[i+1]);
-			}
-		}
-		// I wish I could do this with setAttribute but older IEs don't play nice
-		if (pId)vNewNode.id=pId;
-		if (pClass)vNewNode.className=pClass;
-		if (pWidth)vNewNode.style.width=(isNaN(pWidth*1))?pWidth:pWidth+'px';
-		if (pLeft)vNewNode.style.left=(isNaN(pLeft*1))?pLeft:pLeft+'px';
-		if (pText)vNewNode.appendChild(document.createTextNode(pText));
-		if (pDisplay)vNewNode.style.display=pDisplay;
-		if (pColspan)vNewNode.colSpan=pColspan;
-		return vNewNode;
-	};
-
-	this.Draw=function()
-	{
-		var vMaxDate=new Date();
-		var vMinDate=new Date();
-		var vTmpDate=new Date();
-		var vTaskLeftPx=0;
-		var vTaskRightPx=0;
-		var vTaskWidth=1;
-		var vNumCols=0;
-		var vNumRows=0;
-		var vSingleCell=false;
-		var vID=0;
-		var vMainTable='';
-		var vDateRow=null;
-		var vFirstCellItemRowStr='';
-		var vItemRowStr='';
-		var vColWidth=0;
-		var vColUnit=0;
-		var vChild;
-		var vGroup;
-		var vTaskDiv;
-		var vParDiv;
-
-		if(vTaskList.length>0)
-		{
-			// Process all tasks, reset parent date and completion % if task list has altered
-			if (vProcessNeeded)	JSGantt.processRows(vTaskList, 0, -1, 1, 1, this.getUseSort());
-			vProcessNeeded=false;
-
-			// get overall min/max dates plus padding
-			vMinDate=JSGantt.getMinDate(vTaskList, vFormat);
-			vMaxDate=JSGantt.getMaxDate(vTaskList, vFormat);
-
-			// Calculate chart width variables.
-			if(vFormat=='day') vColWidth=vDayColWidth;
-			else if(vFormat=='week') vColWidth=vWeekColWidth;
-			else if(vFormat=='month') vColWidth=vMonthColWidth;
-			else if(vFormat=='quarter') vColWidth=vQuarterColWidth;
-			else if(vFormat=='hour') vColWidth=vHourColWidth;
-
-			// DRAW the Left-side of the chart (names, resources, comp%)
-			var vLeftHeader=document.createDocumentFragment();
-
-			var vTmpDiv=this.newNode(vLeftHeader, 'div', vDivId+'glisthead', 'glistlbl gcontainercol');
-			var vTmpTab=this.newNode(vTmpDiv, 'table', null, 'gtasktableh');
-			var vTmpTBody=this.newNode(vTmpTab, 'tbody');
-			var vTmpRow=this.newNode(vTmpTBody, 'tr');
-			this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0');
-			var vTmpCell=this.newNode(vTmpRow, 'td', null, 'gspanning gtaskname');
-			vTmpCell.appendChild(this.drawSelector('top'));
-			if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gspanning gresource', '\u00A0');
-			if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gspanning gduration', '\u00A0');
-			if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gspanning gpccomplete', '\u00A0');
-			if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning gstartdate', '\u00A0');
-			if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning genddate', '\u00A0');
-
-			vTmpRow=this.newNode(vTmpTBody, 'tr');
-			this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0');
-			this.newNode(vTmpRow, 'td', null, 'gtaskname', '\u00A0');
-			if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gresource', vLangs[vLang]['resource']);
-			if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gduration', vLangs[vLang]['duration']);
-			if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gpccomplete', vLangs[vLang]['comp']);
-			if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gstartdate', vLangs[vLang]['startdate']);
-			if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading genddate', vLangs[vLang]['enddate']);
-
-			var vLeftTable=document.createDocumentFragment();
-			var vTmpDiv2=this.newNode(vLeftTable, 'div', vDivId+'glistbody', 'glistgrid gcontainercol');
-			this.setListBody(vTmpDiv2);
-			vTmpTab=this.newNode(vTmpDiv2, 'table', null, 'gtasktable');
-			vTmpTBody=this.newNode(vTmpTab, 'tbody');
-
-			for(i=0; i<vTaskList.length; i++)
-			{
-				if(vTaskList[i].getGroup()==1) var vBGColor='ggroupitem';
-				else vBGColor='glineitem';
-
-				vID=vTaskList[i].getID();
-
-				if((!(vTaskList[i].getParItem() && vTaskList[i].getParItem().getGroup()==2)) || vTaskList[i].getGroup()==2)
-				{
-					if(vTaskList[i].getVisible()==0) vTmpRow=this.newNode(vTmpTBody, 'tr', vDivId+'child_'+vID, 'gname '+vBGColor, null, null, null, 'none');
-					else vTmpRow=this.newNode(vTmpTBody, 'tr', vDivId+'child_'+vID, 'gname '+vBGColor);
-					vTaskList[i].setListChildRow(vTmpRow);
-					this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0');
-					vTmpCell=this.newNode(vTmpRow, 'td', null, 'gtaskname');
-
-					var vCellContents ='';
-					for(j=1; j<vTaskList[i].getLevel(); j++)
-					{
-						vCellContents+='\u00A0\u00A0\u00A0\u00A0';
-					}
-
-					if(vTaskList[i].getGroup()==1)
-					{
-						vTmpDiv=this.newNode(vTmpCell, 'div', null, null, vCellContents);
-						var vTmpSpan=this.newNode(vTmpDiv, 'span', vDivId+'group_'+vID, 'gfoldercollapse', (vTaskList[i].getOpen()==1)?'-':'+');
-						vTaskList[i].setGroupSpan(vTmpSpan);
-						JSGantt.addFolderListeners(this, vTmpSpan, vID);
-						vTmpDiv.appendChild(document.createTextNode('\u00A0'+vTaskList[i].getName()));
-					}
-					else
-					{
-						vCellContents+='\u00A0\u00A0\u00A0\u00A0';
-						vTmpDiv=this.newNode(vTmpCell, 'div', null, null, vCellContents+vTaskList[i].getName());
-					}
-
-					if(vShowRes==1)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, 'gresource');
-						/*vTmpDiv=this.newNode(vTmpCell, 'div', null, null, vTaskList[i].getResource());*/
-                        var vTmpNode=this.newNode(vTmpCell, 'div', null, '');
-                        vTmpNode=this.newNode(vTmpNode, 'a', null, '', (vTaskList[i].getLink() != '' ? vLangs[vLang]['moreinfo'] : ''));
-                        vTmpNode.setAttribute('href',vTaskList[i].getLink());
- 						
-					}
-					if(vShowDur==1)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, 'gduration');
-						vTmpDiv=this.newNode(vTmpCell, 'div', null, null, vTaskList[i].getDuration(vFormat, vLangs[vLang]));
-					}
-					if(vShowComp==1)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, 'gpccomplete');
-						vTmpDiv=this.newNode(vTmpCell, 'div', null, null, vTaskList[i].getCompStr());
-					}
-					if(vShowStartDate==1)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, 'gstartdate');
-						vTmpDiv=this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTaskList[i].getStart(), vDateTaskTableDisplayFormat, vLangs[vLang]));
-					}
-					if(vShowEndDate==1)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, 'genddate');
-						vTmpDiv=this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTaskList[i].getEnd(), vDateTaskTableDisplayFormat, vLangs[vLang]));
-					}
-					vNumRows++;
-				}
-			}
-
-			// DRAW the date format selector at bottom left.
-			vTmpRow=this.newNode(vTmpTBody, 'tr');
-			this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0');
-			vTmpCell=this.newNode(vTmpRow, 'td', null, 'gspanning gtaskname');
-			vTmpCell.appendChild(this.drawSelector('bottom'));
-			if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gspanning gresource', '\u00A0');
-			if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gspanning gduration', '\u00A0');
-			if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gspanning gpccomplete', '\u00A0');
-			if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning gstartdate', '\u00A0');
-			if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning genddate', '\u00A0');
-			// Add some white space so the vertical scroll distance should always be greater
-			// than for the right pane (keep to a minimum as it is seen in unconstrained height designs)
-			this.newNode(vTmpDiv2, 'br');
-			this.newNode(vTmpDiv2, 'br');
-
-			// Draw the Chart Rows
-			var vRightHeader=document.createDocumentFragment();
-			vTmpDiv=this.newNode(vRightHeader, 'div', vDivId+'gcharthead', 'gchartlbl gcontainercol');
-			this.setChartHead(vTmpDiv);
-			vTmpTab=this.newNode(vTmpDiv, 'table', vDivId+'chartTableh', 'gcharttableh');
-			vTmpTBody=this.newNode(vTmpTab, 'tbody');
-			vTmpRow=this.newNode(vTmpTBody, 'tr');
-
-			vTmpDate.setFullYear(vMinDate.getFullYear(), vMinDate.getMonth(), vMinDate.getDate());
-			if(vFormat=='hour')vTmpDate.setHours(vMinDate.getHours());
-			else vTmpDate.setHours(0);
-			vTmpDate.setMinutes(0);
-			vTmpDate.setSeconds(0);
-			vTmpDate.setMilliseconds(0);
-
-			var vColSpan=1;
-			// Major Date Header
-			while(vTmpDate.getTime()<=vMaxDate.getTime())
-			{
-				var vHeaderCellClass='gmajorheading';
-				vCellContents='';
-
-				if(vFormat=='day')
-				{
-					vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, null, null, null, 7);
-					vCellContents+=JSGantt.formatDateStr(vTmpDate,vDayMajorDateDisplayFormat,vLangs[vLang]);
-					vTmpDate.setDate(vTmpDate.getDate()+6);
-
-					if (vShowEndWeekDate==1) vCellContents+=' - ' +JSGantt.formatDateStr(vTmpDate, vDayMajorDateDisplayFormat,vLangs[vLang]);
-
-					this.newNode(vTmpCell, 'div', null, null, vCellContents, vColWidth*7);
-					vTmpDate.setDate(vTmpDate.getDate()+1);
-				}
-				else if(vFormat=='week')
-				{
-					vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, vColWidth);
-					this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vWeekMajorDateDisplayFormat,vLangs[vLang]), vColWidth);
-					vTmpDate.setDate(vTmpDate.getDate()+7);
-				}
-				else if(vFormat=='month')
-				{
-					vColSpan=(12-vTmpDate.getMonth());
-					if (vTmpDate.getFullYear()==vMaxDate.getFullYear()) vColSpan-=(11-vMaxDate.getMonth());
-					vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, null, null, null, vColSpan);
-					this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vMonthMajorDateDisplayFormat,vLangs[vLang]), vColWidth*vColSpan);
-					vTmpDate.setFullYear(vTmpDate.getFullYear()+1,0,1);
-				}
-				else if(vFormat=='quarter')
-				{
-					vColSpan=(4-Math.floor(vTmpDate.getMonth()/3));
-					if (vTmpDate.getFullYear()==vMaxDate.getFullYear()) vColSpan-=(3-Math.floor(vMaxDate.getMonth()/3));
-					vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, null, null, null, vColSpan);
-					this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vQuarterMajorDateDisplayFormat,vLangs[vLang]), vColWidth*vColSpan);
-					vTmpDate.setFullYear(vTmpDate.getFullYear()+1,0,1);
-				}
-				else if(vFormat=='hour')
-				{
-					vColSpan=(24-vTmpDate.getHours());
-					if (vTmpDate.getFullYear()==vMaxDate.getFullYear() &&
-						vTmpDate.getMonth()==vMaxDate.getMonth() &&
-						vTmpDate.getDate()==vMaxDate.getDate()) vColSpan-=(23-vMaxDate.getHours());
-					vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass, null, null, null, null, vColSpan);
-					this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vHourMajorDateDisplayFormat,vLangs[vLang]), vColWidth*vColSpan);
-					vTmpDate.setHours(0);
-					vTmpDate.setDate(vTmpDate.getDate()+1);
-				}
-			}
-
-			vTmpRow=this.newNode(vTmpTBody, 'tr');
-
-			// Minor Date header and Cell Rows
-			vTmpDate.setFullYear(vMinDate.getFullYear(), vMinDate.getMonth(), vMinDate.getDate(), vMinDate.getHours());
-			if(vFormat=='hour')vTmpDate.setHours(vMinDate.getHours());
-			vNumCols=0;
-
-			while(vTmpDate.getTime()<=vMaxDate.getTime())
-			{
-				vHeaderCellClass='gminorheading';
-				var vCellClass='gtaskcell';
-
-				if(vFormat=='day')
-				{
-					if(vTmpDate.getDay()%6==0)
-					{
-						vHeaderCellClass+='wkend';
-						vCellClass+='wkend';
-					}
-
-					if(vTmpDate<=vMaxDate)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass);
-						this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vDayMinorDateDisplayFormat,vLangs[vLang]), vColWidth);
-						vNumCols++;
-					}
-
-					vTmpDate.setDate(vTmpDate.getDate()+1);
-				}
-				else if(vFormat=='week')
-				{
-					if(vTmpDate<=vMaxDate)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass);
-						this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vWeekMinorDateDisplayFormat,vLangs[vLang]), vColWidth);
-						vNumCols++;
-					}
-
-					vTmpDate.setDate(vTmpDate.getDate()+7);
-				}
-				else if(vFormat=='month')
-				{
-					if(vTmpDate<=vMaxDate)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass);
-						this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vMonthMinorDateDisplayFormat,vLangs[vLang]), vColWidth);
-						vNumCols++;
-					}
-
-					vTmpDate.setDate(vTmpDate.getDate()+1);
-
-					while(vTmpDate.getDate()>1)
-					{
-						vTmpDate.setDate(vTmpDate.getDate()+1);
-					}
-				}
-				else if(vFormat=='quarter')
-				{
-					if(vTmpDate<=vMaxDate)
-					{
-						vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass);
-						this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vQuarterMinorDateDisplayFormat,vLangs[vLang]), vColWidth);
-						vNumCols++;
-					}
-
-					vTmpDate.setDate(vTmpDate.getDate()+81);
-
-					while(vTmpDate.getDate()>1) vTmpDate.setDate(vTmpDate.getDate()+1);
-				}
-				else if(vFormat=='hour')
-				{
-					for(i=vTmpDate.getHours();i<24;i++)
-					{
-						vTmpDate.setHours(i);//works around daylight savings but may look a little odd on days where the clock goes forward
-						if(vTmpDate<=vMaxDate)
-						{
-							vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass);
-							this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vHourMinorDateDisplayFormat,vLangs[vLang]), vColWidth);
-							vNumCols++;
-						}
-					}
-					vTmpDate.setHours(0);
-					vTmpDate.setDate(vTmpDate.getDate()+1);
-				}
-			}
-			vDateRow=vTmpRow;
-
-			vTaskLeftPx=(vNumCols *(vColWidth+1))+1;
-
-			if(vUseSingleCell!=0 && vUseSingleCell<(vNumCols*vNumRows))vSingleCell=true;
-
-			this.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx+1);
-
-			vTmpDiv=this.newNode(vRightHeader, 'div', null, 'glabelfooter');
-
-			var vRightTable=document.createDocumentFragment();
-			vTmpDiv=this.newNode(vRightTable, 'div', vDivId+'gchartbody', 'gchartgrid gcontainercol');
-			this.setChartBody(vTmpDiv);
-			vTmpTab=this.newNode(vTmpDiv, 'table', vDivId+'chartTable', 'gcharttable', null, vTaskLeftPx);
-			this.setChartTable(vTmpTab);
-			this.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx+1);
-			vTmpTBody=this.newNode(vTmpTab, 'tbody');
-
-			// Draw each row
-
-			var i=0;
-			var j=0;
-			for(i=0; i<vTaskList.length; i++)
-			{
-				var curTaskStart=vTaskList[i].getStart();
-				var curTaskEnd=vTaskList[i].getEnd();
-				if ((curTaskEnd.getTime()-(curTaskEnd.getTimezoneOffset()*60000))%(86400000)==0) curTaskEnd=new Date(curTaskEnd.getFullYear(), curTaskEnd.getMonth(), curTaskEnd.getDate()+1, curTaskEnd.getHours(), curTaskEnd.getMinutes(), curTaskEnd.getSeconds()); // add 1 day here to simplify calculations below
-
-				vTaskLeftPx=JSGantt.getOffset(vMinDate, curTaskStart, vColWidth, vFormat);
-				vTaskRightPx=JSGantt.getOffset(curTaskStart, curTaskEnd, vColWidth, vFormat);
-
-				vID=vTaskList[i].getID();
-				var vComb=(vTaskList[i].getParItem() && vTaskList[i].getParItem().getGroup()==2);
-				var vCellFormat='';
-
-				var vTmpItem=vTaskList[i];
-				var vCaptionStr='';
-				var vCaptClass=null;
-				if(vTaskList[i].getMile() && !vComb)
-				{
-					vTmpRow=this.newNode(vTmpTBody, 'tr', vDivId+'childrow_'+vID, 'gmileitem gmile'+vFormat, null, null, null, ((vTaskList[i].getVisible()==0)? 'none' : null));
-					vTaskList[i].setChildRow(vTmpRow);
-					JSGantt.addThisRowListeners(this, vTaskList[i].getListChildRow(), vTmpRow);
-					vTmpCell=this.newNode(vTmpRow, 'td', null, 'gtaskcell');
-					vTmpDiv=this.newNode(vTmpCell, 'div', null, 'gtaskcelldiv', '\u00A0\u00A0');
-					vTmpDiv=this.newNode(vTmpDiv, 'div', vDivId+'bardiv_'+vID, 'gtaskbarcontainer', null, 12, vTaskLeftPx-6);
-					vTaskList[i].setBarDiv(vTmpDiv);
-					vTmpDiv2=this.newNode(vTmpDiv, 'div', vDivId+'taskbar_'+vID, vTaskList[i].getClass(), null, 12);
-					vTaskList[i].setTaskDiv(vTmpDiv2);
-
-					if(vTaskList[i].getCompVal()<100)
-						vTmpDiv2.appendChild(document.createTextNode('\u25CA'));
-					else
-					{
-						vTmpDiv2=this.newNode(vTmpDiv2, 'div', null, 'gmilediamond');
-						this.newNode(vTmpDiv2, 'div', null, 'gmdtop');
-						this.newNode(vTmpDiv2, 'div', null, 'gmdbottom');
-					}
-
-					vCaptClass='gmilecaption';
-
-					if(!vSingleCell && !vComb)
-					{
-						vCellFormat='';
-						for(j=0; j<vNumCols-1; j++)
-						{
-							if(vFormat=='day'&&((j%7==4)||(j%7==5))) vCellFormat='gtaskcellwkend';
-							else vCellFormat='gtaskcell';
-							this.newNode(vTmpRow, 'td', null, vCellFormat, '\u00A0\u00A0');
-						}
-					}
-				}
-				else
-				{
-					vTaskWidth=vTaskRightPx-1;
-
-					// Draw Group Bar which has outer div with inner group div and several small divs to left and right to create angled-end indicators
-					if(vTaskList[i].getGroup())
-					{
-						vTaskWidth=(vTaskWidth>vMinGpLen && vTaskWidth<vMinGpLen*2)? vMinGpLen*2 : vTaskWidth; // Expand to show two end points
-						vTaskWidth=(vTaskWidth<vMinGpLen)? vMinGpLen : vTaskWidth; // expand to show one end point
-
-						vTmpRow=this.newNode(vTmpTBody, 'tr', vDivId+'childrow_'+vID, ((vTaskList[i].getGroup()==2)?'glineitem gitem':'ggroupitem ggroup')+vFormat, null, null, null, ((vTaskList[i].getVisible()==0)? 'none' : null));
-						vTaskList[i].setChildRow(vTmpRow);
-						JSGantt.addThisRowListeners(this, vTaskList[i].getListChildRow(), vTmpRow);
-						vTmpCell=this.newNode(vTmpRow, 'td', null, 'gtaskcell');
-						vTmpDiv=this.newNode(vTmpCell, 'div', null, 'gtaskcelldiv', '\u00A0\u00A0');
-						vTaskList[i].setCellDiv(vTmpDiv);
-						if(vTaskList[i].getGroup()==1)
-						{
-							vTmpDiv=this.newNode(vTmpDiv, 'div', vDivId+'bardiv_'+vID, 'gtaskbarcontainer', null, vTaskWidth, vTaskLeftPx);
-							vTaskList[i].setBarDiv(vTmpDiv);
-							vTmpDiv2=this.newNode(vTmpDiv, 'div', vDivId+'taskbar_'+vID, vTaskList[i].getClass(), null, vTaskWidth);
-							vTaskList[i].setTaskDiv(vTmpDiv2);
-
-							this.newNode(vTmpDiv2, 'div', vDivId+'complete_'+vID, vTaskList[i].getClass() +'complete', null, vTaskList[i].getCompStr());
-
-							this.newNode(vTmpDiv, 'div', null, vTaskList[i].getClass() +'endpointleft');
-							if (vTaskWidth>=vMinGpLen*2) this.newNode(vTmpDiv, 'div', null, vTaskList[i].getClass() +'endpointright');
-
-							vCaptClass='ggroupcaption';
-						}
-
-						if(!vSingleCell && !vComb)
-						{
-							vCellFormat='';
-							for(j=0; j<vNumCols-1; j++)
-							{
-								if(vFormat=='day'&&((j%7==4)||(j%7==5))) vCellFormat='gtaskcellwkend';
-								else vCellFormat='gtaskcell';
-								this.newNode(vTmpRow, 'td', null, vCellFormat, '\u00A0\u00A0');
-							}
-						}
-					}
-					else
-					{
-						vTaskWidth=(vTaskWidth<=0)? 1 : vTaskWidth;
-
-						if(vComb)
-						{
-							vTmpDiv=vTaskList[i].getParItem().getCellDiv();
-						}
-						else
-						{
-							vTmpRow=this.newNode(vTmpTBody, 'tr', vDivId+'childrow_'+vID, 'glineitem gitem'+vFormat, null, null, null, ((vTaskList[i].getVisible()==0)? 'none' : null));
-							vTaskList[i].setChildRow(vTmpRow);
-							JSGantt.addThisRowListeners(this, vTaskList[i].getListChildRow(), vTmpRow);
-							vTmpCell=this.newNode(vTmpRow, 'td', null, 'gtaskcell');
-							vTmpDiv=this.newNode(vTmpCell, 'div', null, 'gtaskcelldiv', '\u00A0\u00A0');
-						}
-						// Draw Task Bar which has colored bar div, and opaque completion div
-						vTmpDiv=this.newNode(vTmpDiv, 'div', vDivId+'bardiv_'+vID, 'gtaskbarcontainer', null, vTaskWidth, vTaskLeftPx);
-						vTaskList[i].setBarDiv(vTmpDiv);
-						vTmpDiv2=this.newNode(vTmpDiv, 'div', vDivId+'taskbar_'+vID, vTaskList[i].getClass(), null, vTaskWidth);
-						vTaskList[i].setTaskDiv(vTmpDiv2);
-						this.newNode(vTmpDiv2, 'div', vDivId+'complete_'+vID, vTaskList[i].getClass() +'complete', null, vTaskList[i].getCompStr());
-
-						if(vComb)vTmpItem=vTaskList[i].getParItem();
-						if(!vComb || (vComb && vTaskList[i].getParItem().getEnd()==vTaskList[i].getEnd())) vCaptClass='gcaption';
-
-						if(!vSingleCell && !vComb)
-						{
-							vCellFormat='';
-							for(j=0; j<vNumCols-1; j++)
-							{
-								if(vFormat=='day'&&((j%7==4)||(j%7==5))) vCellFormat='gtaskcellwkend';
-								else vCellFormat='gtaskcell';
-								this.newNode(vTmpRow, 'td', null, vCellFormat, '\u00A0\u00A0');
-							}
-						}
-					}
-				}
-
-				if(this.getCaptionType() && vCaptClass!==null)
-				{
-					switch(this.getCaptionType())
-					{
-						case 'Caption': var vCaptionStr=vTmpItem.getCaption(); break;
-						case 'Resource': vCaptionStr=vTmpItem.getResource(); break;
-						case 'Duration': vCaptionStr=vTmpItem.getDuration(vFormat, vLangs[vLang]); break;
-						case 'Complete': vCaptionStr=vTmpItem.getCompStr(); break;
-					}
-					this.newNode(vTmpDiv, 'div', null, vCaptClass, vCaptionStr, 120, (vCaptClass=='gmilecaption')?12:0);
-				}
-
-				if (vTaskList[i].getTaskDiv() && vTmpDiv)
-				{
-					// Add Task Info div for tooltip
-					vTmpDiv2=this.newNode(vTmpDiv, 'div', vDivId+'tt'+vID, null, null, null, null, 'none');
-					vTmpDiv2.appendChild(this.createTaskInfo(vTaskList[i]));
-					JSGantt.addTooltipListeners(this, vTaskList[i].getTaskDiv(), vTmpDiv2);
-				}
-			}
-
-			if(!vSingleCell) vTmpTBody.appendChild(vDateRow.cloneNode(true));
-
-			while(vDiv.hasChildNodes())vDiv.removeChild(vDiv.firstChild);
-			vTmpDiv=this.newNode(vDiv, 'div', null, 'gchartcontainer');
-			vTmpDiv.appendChild(vLeftHeader);
-			vTmpDiv.appendChild(vRightHeader);
-			vTmpDiv.appendChild(vLeftTable);
-			vTmpDiv.appendChild(vRightTable);
-			this.newNode(vTmpDiv, 'div', null, 'ggridfooter');
-			vTmpDiv2=this.newNode(this.getChartBody(), 'div', vDivId+'Lines', 'glinediv');
-			vTmpDiv2.style.visibility='hidden';
-			this.setLines(vTmpDiv2);
-
-/* Quick hack to show the generated HTML on older browsers - add a '/' to the begining of this line to activate
-			var tmpGenSrc=document.createElement('textarea');
-			tmpGenSrc.appendChild(document.createTextNode(vTmpDiv.innerHTML));
-			vDiv.appendChild(tmpGenSrc);
-//*/
-			// Now all the content exists, register scroll listeners
-			JSGantt.addScrollListeners(this);
-
-			// now check if we are actually scrolling the pane
-			if (vScrollTo!='')
-			{
-				var vScrollDate=new Date(vMinDate.getTime());
-				var vScrollPx=0;
-
-				if(vScrollTo.substr(0,2)=='px')
-				{
-					vScrollPx=parseInt(vScrollTo.substr(2));
-				}
-				else
-				{
-					vScrollDate=JSGantt.parseDateStr(vScrollTo, this.getDateInputFormat());
-					if(vFormat=='hour')vScrollDate.setMinutes(0,0,0);
-					else vScrollDate.setHours(0,0,0,0);
-					vScrollPx=JSGantt.getOffset(vMinDate, vScrollDate, vColWidth, vFormat);
-				}
-				this.getChartBody().scrollLeft=vScrollPx;
-			}
-
-			if (vMinDate.getTime()<=(new Date()).getTime() && vMaxDate.getTime()>=(new Date()).getTime()) vTodayPx=JSGantt.getOffset(vMinDate, new Date(), vColWidth, vFormat);
-			else vTodayPx=-1;
-			this.DrawDependencies();
-		}
-	}; //this.draw
-
-	this.mouseOver=function(pObj1, pObj2)
-	{
-		if (this.getUseRowHlt())
-		{
-			pObj1.className+=' gitemhighlight';
-			pObj2.className+=' gitemhighlight';
-		}
-	};
-
-	this.mouseOut=function(pObj1, pObj2)
-	{
-		if (this.getUseRowHlt())
-		{
-			pObj1.className=pObj1.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, '');
-			pObj2.className=pObj2.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, '');
-		}
-	};
-
-	this.drawSelector=function(pPos)
-	{
-		var vOutput=document.createDocumentFragment();
-		var vDisplay=false;
-
-		for (var i=0; i<vShowSelector.length && !vDisplay; i++)
-		{
-			if (vShowSelector[i].toLowerCase()==pPos.toLowerCase()) vDisplay=true;
-		}
-
-		if (vDisplay)
-		{
-			var vTmpDiv=this.newNode(vOutput, 'div', null, 'gselector', vLangs[vLang]['format']+':');
-
-			if (vFormatArr.join().toLowerCase().indexOf('hour')!=-1)
-				JSGantt.addFormatListeners(this, 'hour', this.newNode(vTmpDiv, 'span', vDivId+'formathour'+pPos, 'gformlabel'+((vFormat=='hour')?' gselected':''), vLangs[vLang]['hour']));
-
-			if (vFormatArr.join().toLowerCase().indexOf('day')!=-1)
-				JSGantt.addFormatListeners(this, 'day', this.newNode(vTmpDiv, 'span', vDivId+'formatday'+pPos, 'gformlabel'+((vFormat=='day')?' gselected':''), vLangs[vLang]['day']));
-
-			if (vFormatArr.join().toLowerCase().indexOf('week')!=-1)
-				JSGantt.addFormatListeners(this, 'week', this.newNode(vTmpDiv, 'span', vDivId+'formatweek'+pPos, 'gformlabel'+((vFormat=='week')?' gselected':''), vLangs[vLang]['week']));
-
-			if (vFormatArr.join().toLowerCase().indexOf('month')!=-1)
-				JSGantt.addFormatListeners(this, 'month', this.newNode(vTmpDiv, 'span', vDivId+'formatmonth'+pPos, 'gformlabel'+((vFormat=='month')?' gselected':''), vLangs[vLang]['month']));
-
-			if (vFormatArr.join().toLowerCase().indexOf('quarter')!=-1)
-				JSGantt.addFormatListeners(this, 'quarter', this.newNode(vTmpDiv, 'span', vDivId+'formatquarter'+pPos, 'gformlabel'+((vFormat=='quarter')?' gselected':''), vLangs[vLang]['quarter']));
-		}
-		else
-		{
-			this.newNode(vOutput, 'div', null, 'gselector');
-		}
-		return vOutput;
-	};
-
-	this.createTaskInfo=function(pTask)
-	{
-		var vTmpDiv;
-		var vTaskInfoBox=document.createDocumentFragment();
-		var vTaskInfo=this.newNode(vTaskInfoBox, 'div', null, 'gTaskInfo');
-		this.newNode(vTaskInfo, 'span', null, 'gTtTitle', pTask.getName());
-		if(vShowTaskInfoStartDate==1){
-			vTmpDiv=this.newNode(vTaskInfo, 'div', null, 'gTILine gTIsd');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskLabel', vLangs[vLang]['startdate']+': ');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskText', JSGantt.formatDateStr(pTask.getStart(), vDateTaskDisplayFormat,vLangs[vLang]));
-		}
-		if(vShowTaskInfoEndDate==1){
-			vTmpDiv=this.newNode(vTaskInfo, 'div', null, 'gTILine gTIed');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskLabel', vLangs[vLang]['enddate']+': ');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskText', JSGantt.formatDateStr(pTask.getEnd(), vDateTaskDisplayFormat,vLangs[vLang]));
-		}
-		if(vShowTaskInfoDur==1 && !pTask.getMile()){
-			vTmpDiv=this.newNode(vTaskInfo, 'div', null, 'gTILine gTId');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskLabel', vLangs[vLang]['duration']+': ');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskText', pTask.getDuration(vFormat, vLangs[vLang]));
-		}
-		if(vShowTaskInfoComp==1){
-			vTmpDiv=this.newNode(vTaskInfo, 'div', null, 'gTILine gTIc');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskLabel', vLangs[vLang]['completion']+': ');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskText', pTask.getCompStr());
-		}
-		if(vShowTaskInfoRes==1){
-			vTmpDiv=this.newNode(vTaskInfo, 'div', null, 'gTILine gTIr');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskLabel', vLangs[vLang]['resource']+': ');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskText', pTask.getResource());
-		}
-		if(vShowTaskInfoLink==1 && pTask.getLink()!=''){
-			vTmpDiv=this.newNode(vTaskInfo, 'div', null, 'gTILine gTIl');
-			var vTmpNode=this.newNode(vTmpDiv, 'span', null, 'gTaskLabel');
-			vTmpNode=this.newNode(vTmpNode, 'a', null, 'gTaskText', vLangs[vLang]['moreinfo']);
-			vTmpNode.setAttribute('href',pTask.getLink());
-		}
-		if(vShowTaskInfoNotes==1){
-			vTmpDiv=this.newNode(vTaskInfo, 'div', null, 'gTILine gTIn');
-			this.newNode(vTmpDiv, 'span', null, 'gTaskLabel', vLangs[vLang]['notes']+': ');
-			if(pTask.getNotes())vTmpDiv.appendChild(pTask.getNotes());
-		}
-		return vTaskInfoBox;
-	};
-
-	this.getXMLProject=function()
-	{
-		var vProject='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
-		for (var i=0; i<vTaskList.length; i++)
-		{
-			vProject+=this.getXMLTask(i,true);
-		}
-		vProject+='</project>';
-		return vProject;
-	};
-
-	this.getXMLTask=function(pID,pIdx)
-	{
-		var i=0;
-		var vIdx=-1;
-		var vTask='';
-		var vOutFrmt=JSGantt.parseDateFormatStr(this.getDateInputFormat()+' HH:MI');
-		if (pIdx===true)vIdx=pID;
-		else
-		{
-			for (i=0; i<vTaskList.length; i++)
-			{
-				if (vTaskList[i].getID()==pID) {vIdx=i; break;}
-			}
-		}
-		if (vIdx>=0 && vIdx<vTaskList.length)
-		{
-			/* Simplest way to return case sensitive node names is to just build a string */
-			vTask='<task>';
-			vTask+='<pID>'+vTaskList[vIdx].getID()+'</pID>';
-			vTask+='<pName>'+vTaskList[vIdx].getName()+'</pName>';
-			vTask+='<pStart>'+JSGantt.formatDateStr(vTaskList[vIdx].getStart(),vOutFrmt,vLangs[vLang])+'</pStart>';
-			vTask+='<pEnd>'+JSGantt.formatDateStr(vTaskList[vIdx].getEnd(),vOutFrmt,vLangs[vLang])+'</pEnd>';
-			vTask+='<pClass>'+vTaskList[vIdx].getClass()+'</pClass>';
-			vTask+='<pLink>'+vTaskList[vIdx].getLink()+'</pLink>';
-			vTask+='<pMile>'+vTaskList[vIdx].getMile()+'</pMile>';
-			if(vTaskList[vIdx].getResource()!='\u00A0') vTask+='<pRes>'+vTaskList[vIdx].getResource()+'</pRes>';
-			vTask+='<pComp>'+vTaskList[vIdx].getCompVal()+'</pComp>';
-			vTask+='<pGroup>'+vTaskList[vIdx].getGroup()+'</pGroup>';
-			vTask+='<pParent>'+vTaskList[vIdx].getParent()+'</pParent>';
-			vTask+='<pOpen>'+vTaskList[vIdx].getOpen()+'</pOpen>';
-			vTask+='<pDepend>';
-			var vDepList=vTaskList[vIdx].getDepend();
-			for (i=0;i<vDepList.length;i++)
-			{
-				if(i>0)vTask+=',';
-				if(vDepList[i]>0)vTask+=vDepList[i]+vTaskList[vIdx].getDepType()[i];
-			}
-			vTask+='</pDepend>';
-			vTask+='<pCaption>'+vTaskList[vIdx].getCaption()+'</pCaption>';
-
-			var vTmpFrag=document.createDocumentFragment();
-			var vTmpDiv=this.newNode(vTmpFrag, 'div', null, null,vTaskList[vIdx].getNotes().innerHTML);
-			vTask+='<pNotes>'+vTmpDiv.innerHTML+'</pNotes>';
-			vTask+='</task>';
-		}
-		return vTask;
-	};
-	if (vDiv && vDiv.nodeName.toLowerCase()=='div') vDivId=vDiv.id;
-}; //GanttChart
-
-JSGantt.updateFlyingObj=function (e, pGanttChartObj, pTimer) {
-	var vCurTopBuf=3;
-	var vCurLeftBuf=5;
-	var vCurBotBuf=3;
-	var vCurRightBuf=15;
-	var vMouseX=(e)?e.clientX:window.event.clientX;
-	var vMouseY=(e)?e.clientY:window.event.clientY;
-	var vViewportX=document.documentElement.clientWidth||document.getElementsByTagName('body')[0].clientWidth;
-	var vViewportY=document.documentElement.clientHeight||document.getElementsByTagName('body')[0].clientHeight;
-	var vNewX=vMouseX;
-	var vNewY=vMouseY;
-
-	if (navigator.appName.toLowerCase ()=='microsoft internet explorer') {
-		// the clientX and clientY properties include the left and top borders of the client area
-		vMouseX-=document.documentElement.clientLeft;
-		vMouseY-=document.documentElement.clientTop;
-
-		var vZoomFactor=JSGantt.getZoomFactor ();
-		if (vZoomFactor!=1) {// IE 7 at non-default zoom level
-			vMouseX=Math.round (vMouseX / vZoomFactor);
-			vMouseY=Math.round (vMouseY / vZoomFactor);
-		}
-	}
-
-	var vScrollPos=JSGantt.getScrollPositions();
-
-	/* Code for positioned right of the mouse by default*/
-	/*
-	if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX)
-	{
-		if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0) vNewX=vScrollPos.x;
-		else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth;
-	}
-	else vNewX=vMouseX+vScrollPos.x+vCurRightBuf;
-	*/
-
-	/* Code for positioned left of the mouse by default */
-	if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0)
-	{
-		if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX) vNewX=vScrollPos.x;
-		else vNewX=vMouseX+vScrollPos.x+vCurRightBuf;
-	}
-	else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth;
-
-	/* Code for positioned below the mouse by default */
-	if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY)
-	{
-		if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0) vNewY=vScrollPos.y;
-		else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight;
-	}
-	else vNewY=vMouseY+vScrollPos.y+vCurBotBuf;
-
-	/* Code for positioned above the mouse by default */
-	/*
-	if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0)
-	{
-		if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY) vNewY=vScrollPos.y;
-		else vNewY=vMouseY+vScrollPos.y+vCurBotBuf;
-	}
-	else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight;
-	*/
-
-	if (pGanttChartObj.getUseMove())
-	{
-		clearInterval(pGanttChartObj.vTool.moveInterval);
-		pGanttChartObj.vTool.moveInterval=setInterval(function(){JSGantt.moveToolTip(vNewX, vNewY, pGanttChartObj.vTool, pTimer);},pTimer);
-	}
-	else
-	{
-		pGanttChartObj.vTool.style.left=vNewX +'px';
-		pGanttChartObj.vTool.style.top=vNewY +'px';
-	}
+exports.draw_bottom = function (column, vTmpRow, vAdditionalHeaders) {
+    if ('vAdditionalHeaders' === column && vAdditionalHeaders) {
+        for (var key in vAdditionalHeaders) {
+            var header = vAdditionalHeaders[key];
+            var css = header.class ? header.class : "gadditional-" + key;
+            draw_utils_1.newNode(vTmpRow, 'td', null, "gspanning gadditional " + css, '\u00A0');
+        }
+    }
+    else {
+        var type = COLUMNS_TYPES[column];
+        draw_utils_1.newNode(vTmpRow, 'td', null, "gspanning g" + type, '\u00A0');
+    }
 };
-
-JSGantt.showToolTip=function(pGanttChartObj, e, pContents, pWidth, pTimer){
-	var vTtDivId=pGanttChartObj.getDivId()+'JSGanttToolTip';
-	var vMaxW=500;
-	var vMaxAlpha=100;
-	var vShowing=pContents.id;
-
-	if(pGanttChartObj.getUseToolTip())
-	{
-		if(pGanttChartObj.vTool==null){
-			pGanttChartObj.vTool=document.createElement('div');
-			pGanttChartObj.vTool.id=vTtDivId;
-			pGanttChartObj.vTool.className='JSGanttToolTip';
-			pGanttChartObj.vTool.vToolCont=document.createElement('div');
-			pGanttChartObj.vTool.vToolCont.id=vTtDivId+'cont';
-			pGanttChartObj.vTool.vToolCont.className='JSGanttToolTipcont';
-			pGanttChartObj.vTool.vToolCont.setAttribute('showing','');
-			pGanttChartObj.vTool.appendChild(pGanttChartObj.vTool.vToolCont);
-			document.body.appendChild(pGanttChartObj.vTool);
-			pGanttChartObj.vTool.style.opacity=0;
-			pGanttChartObj.vTool.setAttribute('currentOpacity',0);
-			pGanttChartObj.vTool.setAttribute('fadeIncrement',10);
-			pGanttChartObj.vTool.setAttribute('moveSpeed',10);
-			pGanttChartObj.vTool.style.filter='alpha(opacity=0)';
-			pGanttChartObj.vTool.style.visibility='hidden';
-			pGanttChartObj.vTool.style.left=Math.floor(((e)?e.clientX:window.event.clientX)/2)+'px';
-			pGanttChartObj.vTool.style.top=Math.floor(((e)?e.clientY:window.event.clientY)/2)+'px';
-			JSGantt.addListener('mouseover', function () {clearTimeout(pGanttChartObj.vTool.delayTimeout);}, pGanttChartObj.vTool);
-			JSGantt.addListener('mouseout', function () {JSGantt.delayedHide(pGanttChartObj, pGanttChartObj.vTool, pTimer);}, pGanttChartObj.vTool);
-		}
-		clearTimeout(pGanttChartObj.vTool.delayTimeout);
-		if(pGanttChartObj.vTool.vToolCont.getAttribute('showing')!=vShowing || pGanttChartObj.vTool.style.visibility!='visible')
-		{
-			if (pGanttChartObj.vTool.vToolCont.getAttribute('showing')!=vShowing)
-			{
-				pGanttChartObj.vTool.vToolCont.setAttribute('showing',vShowing);
-
-				pGanttChartObj.vTool.vToolCont.innerHTML=pContents.innerHTML;
-				// as we are allowing arbitrary HTML we should remove any tag ids to prevent duplication
-				JSGantt.stripIds(pGanttChartObj.vTool.vToolCont);
-			}
-
-			pGanttChartObj.vTool.style.visibility='visible';
-			// Rather than follow the mouse just have it stay put
-			JSGantt.updateFlyingObj(e, pGanttChartObj, pTimer);
-			pGanttChartObj.vTool.style.width=(pWidth)? pWidth+'px' : 'auto';
-			if(!pWidth && JSGantt.isIE()){
-				pGanttChartObj.vTool.style.width=pGanttChartObj.vTool.offsetWidth;
-			}
-			if(pGanttChartObj.vTool.offsetWidth>vMaxW){pGanttChartObj.vTool.style.width=vMaxW+'px';}
-		}
-
-		if (pGanttChartObj.getUseFade())
-		{
-			clearInterval(pGanttChartObj.vTool.fadeInterval);
-			pGanttChartObj.vTool.fadeInterval=setInterval(function(){JSGantt.fadeToolTip(1, pGanttChartObj.vTool, vMaxAlpha);},pTimer);
-		}
-		else
-		{
-			pGanttChartObj.vTool.style.opacity=vMaxAlpha * 0.01;
-			pGanttChartObj.vTool.style.filter='alpha(opacity='+vMaxAlpha+')';
-		}
-	}
+// export const draw_list_headings = function (column, vTmpRow, vAdditionalHeaders, vEvents) {
+//   let nodeCreated;
+//   if ('vAdditionalHeaders' === column && vAdditionalHeaders) {
+//     for (const key in vAdditionalHeaders) {
+//       const header = vAdditionalHeaders[key];
+//       const css = header.class ? header.class : `gadditional-${key}`;
+//       newNode(vTmpRow, 'td', null, `gspanning gadditional ${css}`, '\u00A0');
+//     }
+//   } else {
+//     const type = COLUMNS_TYPES[column];
+//     nodeCreated = newNode(vTmpRow, 'td', null, `gspanning g${type}`, '\u00A0');
+//     addListenerClickCell(nodeCreated, vEvents, { hader: true, column }, type);
+//   }
+// }
+exports.draw_task_headings = function (column, vTmpRow, vLangs, vLang, vAdditionalHeaders, vEvents) {
+    var nodeCreated;
+    if ('vAdditionalHeaders' === column && vAdditionalHeaders) {
+        for (var key in vAdditionalHeaders) {
+            var header = vAdditionalHeaders[key];
+            var text = header.translate ? vLangs[vLang][header.translate] : header.title;
+            var css = header.class ? header.class : "gadditional-" + key;
+            nodeCreated = draw_utils_1.newNode(vTmpRow, 'td', null, "gtaskheading gadditional " + css, text);
+        }
+    }
+    else {
+        var type = COLUMNS_TYPES[column];
+        nodeCreated = draw_utils_1.newNode(vTmpRow, 'td', null, "gtaskheading g" + type, vLangs[vLang][type]);
+        events_1.addListenerClickCell(nodeCreated, vEvents, { hader: true, column: column }, type);
+    }
 };
 
-JSGantt.stripIds=function(pNode){
-	for(var i=0; i<pNode.childNodes.length; i++)
-	{
-		if ('removeAttribute' in pNode.childNodes[i]) pNode.childNodes[i].removeAttribute('id');
-		if (pNode.childNodes[i].hasChildNodes()) JSGantt.stripIds(pNode.childNodes[i]);
-	}
+},{"./events":5,"./task":10,"./utils/date_utils":11,"./utils/draw_utils":12}],4:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.drawDependency = function (x1, y1, x2, y2, pType, pClass) {
+    var vDir = 1;
+    var vBend = false;
+    var vShort = 4;
+    var vRow = Math.floor(this.getRowHeight() / 2);
+    if (y2 < y1)
+        vRow *= -1;
+    switch (pType) {
+        case 'SF':
+            vShort *= -1;
+            if (x1 - 10 <= x2 && y1 != y2)
+                vBend = true;
+            vDir = -1;
+            break;
+        case 'SS':
+            if (x1 < x2)
+                vShort *= -1;
+            else
+                vShort = x2 - x1 - (2 * vShort);
+            break;
+        case 'FF':
+            if (x1 <= x2)
+                vShort = x2 - x1 + (2 * vShort);
+            vDir = -1;
+            break;
+        default:
+            if (x1 + 10 >= x2 && y1 != y2)
+                vBend = true;
+            break;
+    }
+    if (vBend) {
+        this.sLine(x1, y1, x1 + vShort, y1, pClass);
+        this.sLine(x1 + vShort, y1, x1 + vShort, y2 - vRow, pClass);
+        this.sLine(x1 + vShort, y2 - vRow, x2 - (vShort * 2), y2 - vRow, pClass);
+        this.sLine(x2 - (vShort * 2), y2 - vRow, x2 - (vShort * 2), y2, pClass);
+        this.sLine(x2 - (vShort * 2), y2, x2 - (1 * vDir), y2, pClass);
+    }
+    else if (y1 != y2) {
+        this.sLine(x1, y1, x1 + vShort, y1, pClass);
+        this.sLine(x1 + vShort, y1, x1 + vShort, y2, pClass);
+        this.sLine(x1 + vShort, y2, x2 - (1 * vDir), y2, pClass);
+    }
+    else
+        this.sLine(x1, y1, x2 - (1 * vDir), y2, pClass);
+    var vTmpDiv = this.sLine(x2, y2, x2 - 3 - ((vDir < 0) ? 1 : 0), y2 - 3 - ((vDir < 0) ? 1 : 0), pClass + "Arw");
+    vTmpDiv.style.width = '0px';
+    vTmpDiv.style.height = '0px';
 };
-
-JSGantt.stripUnwanted=function(pNode){
-	var vAllowedTags=new Array('#text','p','br','ul','ol','li','div','span','img');
-	for(var i=0; i<pNode.childNodes.length; i++)
-	{
-		/* versions of IE<9 don't support indexOf on arrays so add trailing comma to the joined array and lookup value to stop substring matches */
-		if ((vAllowedTags.join().toLowerCase()+',').indexOf(pNode.childNodes[i].nodeName.toLowerCase()+',')==-1)
-		{
-			pNode.replaceChild(document.createTextNode(pNode.childNodes[i].outerHTML), pNode.childNodes[i]);
-		}
-		if (pNode.childNodes[i].hasChildNodes()) JSGantt.stripUnwanted(pNode.childNodes[i]);
-	}
+exports.DrawDependencies = function (vDebug) {
+    if (vDebug === void 0) { vDebug = false; }
+    if (this.getShowDeps() == 1) {
+        this.CalcTaskXY(); //First recalculate the x,y
+        this.clearDependencies();
+        var vList = this.getList();
+        for (var i = 0; i < vList.length; i++) {
+            var vDepend = vList[i].getDepend();
+            var vDependType = vList[i].getDepType();
+            var n = vDepend.length;
+            if (n > 0 && vList[i].getVisible() == 1) {
+                for (var k = 0; k < n; k++) {
+                    var vTask = this.getArrayLocationByID(vDepend[k]);
+                    if (vTask >= 0 && vList[vTask].getGroup() != 2) {
+                        if (vList[vTask].getVisible() == 1) {
+                            if (vDebug) {
+                                console.info("init drawDependency ", vList[vTask].getID(), new Date());
+                            }
+                            var cssClass = 'gDepId' + vList[vTask].getID() +
+                                ' ' + 'gDepNextId' + vList[i].getID();
+                            var dependedData = vList[vTask].getDataObject();
+                            var nextDependedData = vList[i].getDataObject();
+                            if (dependedData && dependedData.pID && nextDependedData && nextDependedData.pID) {
+                                cssClass += ' gDepDataId' + dependedData.pID + ' ' + 'gDepNextDataId' + nextDependedData.pID;
+                            }
+                            if (vDependType[k] == 'SS')
+                                this.drawDependency(vList[vTask].getStartX() - 1, vList[vTask].getStartY(), vList[i].getStartX() - 1, vList[i].getStartY(), 'SS', cssClass + ' gDepSS');
+                            else if (vDependType[k] == 'FF')
+                                this.drawDependency(vList[vTask].getEndX(), vList[vTask].getEndY(), vList[i].getEndX(), vList[i].getEndY(), 'FF', cssClass + ' gDepFF');
+                            else if (vDependType[k] == 'SF')
+                                this.drawDependency(vList[vTask].getStartX() - 1, vList[vTask].getStartY(), vList[i].getEndX(), vList[i].getEndY(), 'SF', cssClass + ' gDepSF');
+                            else if (vDependType[k] == 'FS')
+                                this.drawDependency(vList[vTask].getEndX(), vList[vTask].getEndY(), vList[i].getStartX() - 1, vList[i].getStartY(), 'FS', cssClass + ' gDepFS');
+                        }
+                    }
+                }
+            }
+        }
+    }
+    // draw the current date line
+    if (this.vTodayPx >= 0) {
+        this.sLine(this.vTodayPx, 0, this.vTodayPx, this.getChartTable().offsetHeight - 1, 'gCurDate');
+    }
 };
 
-JSGantt.delayedHide=function(pGanttChartObj, pTool, pTimer){
-	var vDelay=1500;
-	if(pTool) pTool.delayTimeout=setTimeout(function(){JSGantt.hideToolTip(pGanttChartObj, pTool, pTimer);}, vDelay);
+},{}],5:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var general_utils_1 = require("./utils/general_utils");
+// Function to open/close and hide/show children of specified task
+exports.folder = function (pID, ganttObj) {
+    var vList = ganttObj.getList();
+    ganttObj.clearDependencies(); // clear these first so slow rendering doesn't look odd
+    for (var i = 0; i < vList.length; i++) {
+        if (vList[i].getID() == pID) {
+            if (vList[i].getOpen() == 1) {
+                vList[i].setOpen(0);
+                exports.hide(pID, ganttObj);
+                if (general_utils_1.isIE())
+                    vList[i].getGroupSpan().innerText = '+';
+                else
+                    vList[i].getGroupSpan().textContent = '+';
+            }
+            else {
+                vList[i].setOpen(1);
+                exports.show(pID, 1, ganttObj);
+                if (general_utils_1.isIE())
+                    vList[i].getGroupSpan().innerText = '-';
+                else
+                    vList[i].getGroupSpan().textContent = '-';
+            }
+        }
+    }
+    var bd;
+    if (this.vDebug) {
+        bd = new Date();
+        console.info('after drawDependency', bd);
+    }
+    ganttObj.DrawDependencies(this.vDebug);
+    if (this.vDebug) {
+        var ad = new Date();
+        console.info('after drawDependency', ad, (ad.getTime() - bd.getTime()));
+    }
 };
-
-JSGantt.hideToolTip=function(pGanttChartObj, pTool, pTimer){
-	if (pGanttChartObj.getUseFade())
-	{
-		clearInterval(pTool.fadeInterval);
-		pTool.fadeInterval=setInterval(function(){JSGantt.fadeToolTip(-1, pTool, 0);}, pTimer);
-	}
-	else
-	{
-		pTool.style.opacity=0;
-		pTool.style.filter='alpha(opacity=0)';
-		pTool.style.visibility='hidden';
-	}
+exports.hide = function (pID, ganttObj) {
+    var vList = ganttObj.getList();
+    var vID = 0;
+    for (var i = 0; i < vList.length; i++) {
+        if (vList[i].getParent() == pID) {
+            vID = vList[i].getID();
+            // it's unlikely but if the task list has been updated since
+            // the chart was drawn some of the rows may not exist
+            if (vList[i].getListChildRow())
+                vList[i].getListChildRow().style.display = 'none';
+            if (vList[i].getChildRow())
+                vList[i].getChildRow().style.display = 'none';
+            vList[i].setVisible(0);
+            if (vList[i].getGroup())
+                exports.hide(vID, ganttObj);
+        }
+    }
 };
-
-JSGantt.fadeToolTip=function(pDirection, pTool, pMaxAlpha){
-	var vIncrement=parseInt(pTool.getAttribute('fadeIncrement'));
-	var vAlpha=pTool.getAttribute('currentOpacity');
-	var vCurAlpha=parseInt(vAlpha);
-	if((vCurAlpha!=pMaxAlpha && pDirection==1) || (vCurAlpha!=0 && pDirection==-1)){
-		var i=vIncrement;
-		if(pMaxAlpha-vCurAlpha<vIncrement && pDirection==1){
-			i=pMaxAlpha-vCurAlpha;
-		}else if(vAlpha<vIncrement && pDirection==-1){
-			i=vCurAlpha;
-		}
-		vAlpha=vCurAlpha+(i * pDirection);
-		pTool.style.opacity=vAlpha * 0.01;
-		pTool.style.filter='alpha(opacity='+vAlpha+')';
-		pTool.setAttribute('currentOpacity', vAlpha);
-	}else{
-		clearInterval(pTool.fadeInterval);
-		if(pDirection==-1){
-			pTool.style.opacity=0;
-			pTool.style.filter='alpha(opacity=0)';
-			pTool.style.visibility='hidden';
-		}
-	}
+// Function to show children of specified task
+exports.show = function (pID, pTop, ganttObj) {
+    var vList = ganttObj.getList();
+    var vID = 0;
+    var vState = '';
+    for (var i = 0; i < vList.length; i++) {
+        if (vList[i].getParent() == pID) {
+            if (!vList[i].getParItem()) {
+                console.error("Cant find parent on who event (maybe problems with Task ID and Parent Id mixes?)");
+            }
+            if (vList[i].getParItem().getGroupSpan()) {
+                if (general_utils_1.isIE())
+                    vState = vList[i].getParItem().getGroupSpan().innerText;
+                else
+                    vState = vList[i].getParItem().getGroupSpan().textContent;
+            }
+            i = vList.length;
+        }
+    }
+    for (var i = 0; i < vList.length; i++) {
+        if (vList[i].getParent() == pID) {
+            var vChgState = false;
+            vID = vList[i].getID();
+            if (pTop == 1 && vState == '+')
+                vChgState = true;
+            else if (vState == '-')
+                vChgState = true;
+            else if (vList[i].getParItem() && vList[i].getParItem().getGroup() == 2)
+                vList[i].setVisible(1);
+            if (vChgState) {
+                if (vList[i].getListChildRow())
+                    vList[i].getListChildRow().style.display = '';
+                if (vList[i].getChildRow())
+                    vList[i].getChildRow().style.display = '';
+                vList[i].setVisible(1);
+            }
+            if (vList[i].getGroup())
+                exports.show(vID, 0, ganttObj);
+        }
+    }
 };
-
-JSGantt.moveToolTip=function(pNewX, pNewY, pTool){
-	var vSpeed=parseInt(pTool.getAttribute('moveSpeed'));
-	var vOldX=parseInt(pTool.style.left);
-	var vOldY=parseInt(pTool.style.top);
-
-	if (pTool.style.visibility!='visible')
-	{
-		pTool.style.left=pNewX +'px';
-		pTool.style.top=pNewY +'px';
-		clearInterval(pTool.moveInterval);
-	}
-	else
-	{
-		if(pNewX!=vOldX && pNewY!=vOldY)
-		{
-			vOldX+=Math.ceil((pNewX-vOldX)/vSpeed);
-			vOldY+=Math.ceil((pNewY-vOldY)/vSpeed);
-			pTool.style.left=vOldX +'px';
-			pTool.style.top=vOldY +'px';
-		}
-		else
-		{
-			clearInterval(pTool.moveInterval);
-		}
-	}
+exports.mouseOver = function (pObj1, pObj2) {
+    if (this.getUseRowHlt()) {
+        pObj1.className += ' gitemhighlight';
+        pObj2.className += ' gitemhighlight';
+    }
 };
-
-JSGantt.getZoomFactor=function() {
-	var vFactor=1;
-	if (document.body.getBoundingClientRect)
-	{
-		// rect is only in physical pixel size in IE before version 8
-		var vRect=document.body.getBoundingClientRect ();
-		var vPhysicalW=vRect.right-vRect.left;
-		var vLogicalW=document.body.offsetWidth;
-
-		// the zoom level is always an integer percent value
-		vFactor=Math.round ((vPhysicalW / vLogicalW) * 100) / 100;
-	}
-	return vFactor;
+exports.mouseOut = function (pObj1, pObj2) {
+    if (this.getUseRowHlt()) {
+        pObj1.className = pObj1.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, '');
+        pObj2.className = pObj2.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, '');
+    }
 };
-
-JSGantt.getScrollPositions=function() {
-	var vScrollLeft=window.pageXOffset;
-	var vScrollTop=window.pageYOffset;
-	if (!('pageXOffset' in window))	// Internet Explorer before version 9
-	{
-		var vZoomFactor=JSGantt.getZoomFactor ();
-		vScrollLeft=Math.round (document.documentElement.scrollLeft / vZoomFactor);
-		vScrollTop=Math.round (document.documentElement.scrollTop / vZoomFactor);
-	}
-	return {x : vScrollLeft, y : vScrollTop};
+exports.showToolTip = function (pGanttChartObj, e, pContents, pWidth, pTimer) {
+    var vTtDivId = pGanttChartObj.getDivId() + 'JSGanttToolTip';
+    var vMaxW = 500;
+    var vMaxAlpha = 100;
+    var vShowing = pContents.id;
+    if (pGanttChartObj.getUseToolTip()) {
+        if (pGanttChartObj.vTool == null) {
+            pGanttChartObj.vTool = document.createElement('div');
+            pGanttChartObj.vTool.id = vTtDivId;
+            pGanttChartObj.vTool.className = 'JSGanttToolTip';
+            pGanttChartObj.vTool.vToolCont = document.createElement('div');
+            pGanttChartObj.vTool.vToolCont.id = vTtDivId + 'cont';
+            pGanttChartObj.vTool.vToolCont.className = 'JSGanttToolTipcont';
+            pGanttChartObj.vTool.vToolCont.setAttribute('showing', '');
+            pGanttChartObj.vTool.appendChild(pGanttChartObj.vTool.vToolCont);
+            document.body.appendChild(pGanttChartObj.vTool);
+            pGanttChartObj.vTool.style.opacity = 0;
+            pGanttChartObj.vTool.setAttribute('currentOpacity', 0);
+            pGanttChartObj.vTool.setAttribute('fadeIncrement', 10);
+            pGanttChartObj.vTool.setAttribute('moveSpeed', 10);
+            pGanttChartObj.vTool.style.filter = 'alpha(opacity=0)';
+            pGanttChartObj.vTool.style.visibility = 'hidden';
+            pGanttChartObj.vTool.style.left = Math.floor(((e) ? e.clientX : window.event.clientX) / 2) + 'px';
+            pGanttChartObj.vTool.style.top = Math.floor(((e) ? e.clientY : window.event.clientY) / 2) + 'px';
+            this.addListener('mouseover', function () { clearTimeout(pGanttChartObj.vTool.delayTimeout); }, pGanttChartObj.vTool);
+            this.addListener('mouseout', function () { general_utils_1.delayedHide(pGanttChartObj, pGanttChartObj.vTool, pTimer); }, pGanttChartObj.vTool);
+        }
+        clearTimeout(pGanttChartObj.vTool.delayTimeout);
+        var newHTML = pContents.innerHTML;
+        if (pGanttChartObj.vTool.vToolCont.getAttribute("content") !== newHTML) {
+            pGanttChartObj.vTool.vToolCont.innerHTML = pContents.innerHTML;
+            // as we are allowing arbitrary HTML we should remove any tag ids to prevent duplication
+            general_utils_1.stripIds(pGanttChartObj.vTool.vToolCont);
+            pGanttChartObj.vTool.vToolCont.setAttribute("content", newHTML);
+        }
+        if (pGanttChartObj.vTool.vToolCont.getAttribute('showing') != vShowing || pGanttChartObj.vTool.style.visibility != 'visible') {
+            if (pGanttChartObj.vTool.vToolCont.getAttribute('showing') != vShowing) {
+                pGanttChartObj.vTool.vToolCont.setAttribute('showing', vShowing);
+            }
+            pGanttChartObj.vTool.style.visibility = 'visible';
+            // Rather than follow the mouse just have it stay put
+            general_utils_1.updateFlyingObj(e, pGanttChartObj, pTimer);
+            pGanttChartObj.vTool.style.width = (pWidth) ? pWidth + 'px' : 'auto';
+            if (!pWidth && general_utils_1.isIE()) {
+                pGanttChartObj.vTool.style.width = pGanttChartObj.vTool.offsetWidth;
+            }
+            if (pGanttChartObj.vTool.offsetWidth > vMaxW) {
+                pGanttChartObj.vTool.style.width = vMaxW + 'px';
+            }
+        }
+        if (pGanttChartObj.getUseFade()) {
+            clearInterval(pGanttChartObj.vTool.fadeInterval);
+            pGanttChartObj.vTool.fadeInterval = setInterval(function () { general_utils_1.fadeToolTip(1, pGanttChartObj.vTool, vMaxAlpha); }, pTimer);
+        }
+        else {
+            pGanttChartObj.vTool.style.opacity = vMaxAlpha * 0.01;
+            pGanttChartObj.vTool.style.filter = 'alpha(opacity=' + vMaxAlpha + ')';
+        }
+    }
 };
-
-JSGantt.getOffset=function(pStartDate, pEndDate, pColWidth, pFormat)
-{
-	var vMonthDaysArr=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
-	var curTaskStart=new Date(pStartDate.getTime());
-	var curTaskEnd=new Date(pEndDate.getTime());
-	var vTaskRightPx=0;
-	var tmpTaskStart=Date.UTC(curTaskStart.getFullYear(), curTaskStart.getMonth(), curTaskStart.getDate(), curTaskStart.getHours(), 0, 0);
-	var tmpTaskEnd=Date.UTC(curTaskEnd.getFullYear(), curTaskEnd.getMonth(), curTaskEnd.getDate(), curTaskEnd.getHours(), 0, 0);
-
-	var vTaskRight=(tmpTaskEnd-tmpTaskStart)/3600000; // Length of task in hours
-
-	if(pFormat=='day')
-	{
-		vTaskRightPx=Math.ceil((vTaskRight/24) * (pColWidth+1));
-	}
-	else if(pFormat=='week')
-	{
-		vTaskRightPx=Math.ceil(((vTaskRight/24) * (pColWidth+1))/7);
-	}
-	else if(pFormat=='month')
-	{
-		var vMonthsDiff=(12 * (curTaskEnd.getFullYear()-curTaskStart.getFullYear()))+(curTaskEnd.getMonth()-curTaskStart.getMonth());
-		var vPosTmpDate=new Date(curTaskEnd.getTime());
-		vPosTmpDate.setDate(curTaskStart.getDate());
-		var vDaysCrctn=(curTaskEnd.getTime()-vPosTmpDate.getTime())/ (86400000);
-
-		vTaskRightPx=Math.ceil((vMonthsDiff * (pColWidth+1))+(vDaysCrctn * (pColWidth/vMonthDaysArr[curTaskEnd.getMonth()])));
-	}
-	else if(pFormat=='quarter')
-	{
-		vMonthsDiff=(12 * (curTaskEnd.getFullYear()-curTaskStart.getFullYear()))+(curTaskEnd.getMonth()-curTaskStart.getMonth());
-		vPosTmpDate=new Date(curTaskEnd.getTime());
-		vPosTmpDate.setDate(curTaskStart.getDate());
-		vDaysCrctn=(curTaskEnd.getTime()-vPosTmpDate.getTime())/ (86400000);
-
-		vTaskRightPx=Math.ceil((vMonthsDiff * ((pColWidth+1)/3))+(vDaysCrctn * (pColWidth/90)));
-	}
-	else if(pFormat=='hour')
-	{
-		// can't just calculate sum because of daylight savings changes
-		vPosTmpDate=new Date(curTaskEnd.getTime());
-		vPosTmpDate.setMinutes(curTaskStart.getMinutes(), 0);
-		var vMinsCrctn=(curTaskEnd.getTime()-vPosTmpDate.getTime())/(3600000);
-
-		vTaskRightPx=Math.ceil((vTaskRight * (pColWidth+1))+(vMinsCrctn * (pColWidth)));
-	}
-	return vTaskRightPx;
+exports.addListener = function (eventName, handler, control) {
+    // Check if control is a string
+    if (control === String(control))
+        control = general_utils_1.findObj(control);
+    if (control.addEventListener) //Standard W3C
+     {
+        return control.addEventListener(eventName, handler, false);
+    }
+    else if (control.attachEvent) //IExplore
+     {
+        return control.attachEvent('on' + eventName, handler);
+    }
+    else {
+        return false;
+    }
 };
-
-// Recursively process task tree ... set min, max dates of parent tasks and identfy task level.
-JSGantt.processRows=function(pList, pID, pRow, pLevel, pOpen, pUseSort)
-{
-	var vMinDate=new Date();
-	var vMaxDate=new Date();
-	var vVisible=pOpen;
-	var vCurItem=null;
-	var vCompSum=0;
-	var vMinSet=0;
-	var vMaxSet=0;
-	var vNumKid=0;
-	var vWeight=0;
-	var vLevel=pLevel;
-	var vList=pList;
-	var vComb=false;
-	var i=0;
-
-	for(i=0; i<pList.length; i++)
-	{
-		if (pList[i].getToDelete())
-		{
-			pList.splice(i,1);
-			i--;
-		}
-		if (i>=0 && pList[i].getID()==pID)vCurItem=pList[i];
-	}
-
-	for(i=0; i<pList.length; i++)
-	{
-		if(pList[i].getParent()==pID)
-		{
-			vVisible=pOpen;
-			pList[i].setParItem(vCurItem);
-			pList[i].setVisible(vVisible);
-			if(vVisible==1 && pList[i].getOpen()==0) vVisible=0;
-
-			if(pList[i].getMile() && pList[i].getParItem() && pList[i].getParItem().getGroup()==2)
-			{//remove milestones owned by combined groups
-				pList.splice(i,1);
-				i--;
-				continue;
-			}
-
-			pList[i].setLevel(vLevel);
-
-			if(pList[i].getGroup())
-			{
-				if(pList[i].getParItem() && pList[i].getParItem().getGroup()==2)pList[i].setGroup(2);
-				JSGantt.processRows(vList, pList[i].getID(), i, vLevel+1, vVisible, 0);
-			}
-
-			if(vMinSet==0 || pList[i].getStart()<vMinDate)
-			{
-				vMinDate=pList[i].getStart();
-				vMinSet=1;
-			}
-
-			if(vMaxSet==0 || pList[i].getEnd()>vMaxDate)
-			{
-				vMaxDate=pList[i].getEnd();
-				vMaxSet=1;
-			}
-
-			vNumKid++;
-			vWeight+=pList[i].getEnd()-pList[i].getStart()+1;
-			vCompSum+=pList[i].getCompVal()*(pList[i].getEnd()-pList[i].getStart()+1);
-			pList[i].setSortIdx(i*pList.length);
-		}
-	}
-
-	if(pRow>=0)
-	{
-		if(pList[pRow].getGroupMinStart()!=null && pList[pRow].getGroupMinStart()<vMinDate)
-		{
-			vMinDate=pList[pRow].getGroupMinStart();
-		}
-
-		if(pList[pRow].getGroupMinEnd()!=null && pList[pRow].getGroupMinEnd()>vMaxDate)
-		{
-			vMaxDate=pList[pRow].getGroupMinEnd();
-		}
-		pList[pRow].setStart(vMinDate);
-		pList[pRow].setEnd(vMaxDate);
-		pList[pRow].setNumKid(vNumKid);
-		pList[pRow].setWeight(vWeight);
-		pList[pRow].setCompVal(Math.ceil(vCompSum/vWeight));
-	}
-
-	if (pID==0 && pUseSort==1)
-	{
-		JSGantt.sortTasks(pList, 0, 0);
-		pList.sort(function(a,b){return a.getSortIdx()-b.getSortIdx();});
-	}
-	if (pID==0 && pUseSort!=1) // Need to sort combined tasks regardless
-	{
-		for(i=0; i<pList.length; i++)
-		{
-			if (pList[i].getGroup()==2)
-			{
-				vComb=true;
-				JSGantt.sortTasks(pList, pList[i].getID(), pList[i].getSortIdx()+1);
-			}
-		}
-		if(vComb==true) pList.sort(function(a,b){return a.getSortIdx()-b.getSortIdx();});
-	}
+exports.removeListener = function (eventName, handler, control) {
+    // Check if control is a string
+    if (control === String(control))
+        control = general_utils_1.findObj(control);
+    if (control.removeEventListener) {
+        //Standard W3C
+        return control.removeEventListener(eventName, handler, false);
+    }
+    else if (control.detachEvent) {
+        //IExplore
+        return control.attachEvent('on' + eventName, handler);
+    }
+    else {
+        return false;
+    }
 };
-
-JSGantt.sortTasks=function (pList, pID, pIdx)
-{
-	var sortIdx=pIdx;
-	var sortArr=new Array();
-
-	for(var i=0; i<pList.length; i++)
-	{
-		if(pList[i].getParent()==pID)sortArr.push(pList[i]);
-	}
-
-	if (sortArr.length>0)
-	{
-		sortArr.sort(function(a,b){ var i=a.getStart().getTime()-b.getStart().getTime();
-									if (i==0) i=a.getEnd().getTime()-b.getEnd().getTime();
-									if (i==0) return a.getID()-b.getID();
-									else return i; });
-	}
-
-	for (var j=0; j<sortArr.length; j++)
-	{
-		for(i=0; i<pList.length; i++)
-		{
-			if(pList[i].getID()==sortArr[j].getID())
-			{
-				pList[i].setSortIdx(sortIdx++);
-				sortIdx=JSGantt.sortTasks(pList, pList[i].getID(), sortIdx);
-			}
-		}
-	}
-	return sortIdx;
+exports.syncScroll = function (elements, attrName) {
+    var syncFlags = new Map(elements.map(function (e) { return [e, false]; }));
+    function scrollEvent(e) {
+        if (!syncFlags.get(e.target)) {
+            for (var _i = 0, elements_2 = elements; _i < elements_2.length; _i++) {
+                var el = elements_2[_i];
+                if (el !== e.target) {
+                    syncFlags.set(el, true);
+                    el[attrName] = e.target[attrName];
+                }
+            }
+        }
+        syncFlags.set(e.target, false);
+    }
+    for (var _i = 0, elements_1 = elements; _i < elements_1.length; _i++) {
+        var el = elements_1[_i];
+        el.addEventListener('scroll', scrollEvent);
+    }
 };
-
-// Used to determine the minimum date of all tasks and set lower bound based on format
-JSGantt.getMinDate=function getMinDate(pList, pFormat)
-{
-	var vDate=new Date();
-	vDate.setTime(pList[0].getStart().getTime());
-
-	// Parse all Task End dates to find min
-	for(var i=0; i<pList.length; i++)
-	{
-		if(pList[i].getStart().getTime()<vDate.getTime()) vDate.setTime(pList[i].getStart().getTime());
-	}
-
-	// Adjust min date to specific format boundaries (first of week or first of month)
-	if (pFormat=='day')
-	{
-		vDate.setDate(vDate.getDate()-1);
-		while(vDate.getDay()%7!=1) vDate.setDate(vDate.getDate()-1);
-	}
-	else if (pFormat=='week')
-	{
-		vDate.setDate(vDate.getDate()-1);
-		while(vDate.getDay()%7!=1) vDate.setDate(vDate.getDate()-1);
-	}
-	else if (pFormat=='month')
-	{
-		vDate.setDate(vDate.getDate()-15);
-		while(vDate.getDate()>1) vDate.setDate(vDate.getDate()-1);
-	}
-	else if (pFormat=='quarter')
-	{
-		vDate.setDate(vDate.getDate()-31);
-		if(vDate.getMonth()==0 || vDate.getMonth()==1 || vDate.getMonth()==2)
-			vDate.setFullYear(vDate.getFullYear(), 0, 1);
-		else if(vDate.getMonth()==3 || vDate.getMonth()==4 || vDate.getMonth()==5)
-			vDate.setFullYear(vDate.getFullYear(), 3, 1);
-		else if(vDate.getMonth()==6 || vDate.getMonth()==7 || vDate.getMonth()==8)
-			vDate.setFullYear(vDate.getFullYear(), 6, 1);
-		else if(vDate.getMonth()==9 || vDate.getMonth()==10 || vDate.getMonth()==11)
-			vDate.setFullYear(vDate.getFullYear(), 9, 1);
-	}
-	else if (pFormat=='hour')
-	{
-		vDate.setHours(vDate.getHours()-1);
-		while(vDate.getHours()%6!=0) vDate.setHours(vDate.getHours()-1);
-	}
-
-	if(pFormat=='hour')vDate.setMinutes(0,0);
-	else vDate.setHours(0,0,0);
-	return(vDate);
+exports.addTooltipListeners = function (pGanttChart, pObj1, pObj2, callback) {
+    var isShowingTooltip = false;
+    exports.addListener('mouseover', function (e) {
+        if (isShowingTooltip || !callback) {
+            exports.showToolTip(pGanttChart, e, pObj2, null, pGanttChart.getTimer());
+        }
+        else if (callback) {
+            isShowingTooltip = true;
+            var promise = callback();
+            exports.showToolTip(pGanttChart, e, pObj2, null, pGanttChart.getTimer());
+            if (promise && promise.then) {
+                promise.then(function () {
+                    if (pGanttChart.vTool.vToolCont.getAttribute('showing') === pObj2.id &&
+                        pGanttChart.vTool.style.visibility === 'visible') {
+                        exports.showToolTip(pGanttChart, e, pObj2, null, pGanttChart.getTimer());
+                    }
+                });
+            }
+        }
+    }, pObj1);
+    exports.addListener('mouseout', function (e) {
+        var outTo = e.relatedTarget;
+        if (general_utils_1.isParentElementOrSelf(outTo, pObj1) || (pGanttChart.vTool && general_utils_1.isParentElementOrSelf(outTo, pGanttChart.vTool))) {
+            // not actually out
+        }
+        else {
+            isShowingTooltip = false;
+        }
+        general_utils_1.delayedHide(pGanttChart, pGanttChart.vTool, pGanttChart.getTimer());
+    }, pObj1);
 };
-
-// Used to determine the maximum date of all tasks and set upper bound based on format
-JSGantt.getMaxDate=function (pList, pFormat)
-{
-	var vDate=new Date();
-
-	vDate.setTime(pList[0].getEnd().getTime());
-
-	// Parse all Task End dates to find max
-	for(var i=0; i<pList.length; i++)
-	{
-		if(pList[i].getEnd().getTime()>vDate.getTime()) vDate.setTime(pList[i].getEnd().getTime());
-	}
-
-	// Adjust max date to specific format boundaries (end of week or end of month)
-	if (pFormat=='day')
-	{
-		vDate.setDate(vDate.getDate()+1);
-
-		while(vDate.getDay()%7!=0) vDate.setDate(vDate.getDate()+1);
-	}
-	else if (pFormat=='week')
-	{
-		//For weeks, what is the last logical boundary?
-		vDate.setDate(vDate.getDate()+1);
-
-		while(vDate.getDay()%7!=0) vDate.setDate(vDate.getDate()+1);
-	}
-	else if (pFormat=='month')
-	{
-		// Set to last day of current Month
-		while(vDate.getDate()>1) vDate.setDate(vDate.getDate()+1);
-		vDate.setDate(vDate.getDate()-1);
-	}
-	else if (pFormat=='quarter')
-	{
-		// Set to last day of current Quarter
-		if(vDate.getMonth()==0 || vDate.getMonth()==1 || vDate.getMonth()==2)
-			vDate.setFullYear(vDate.getFullYear(), 2, 31);
-		else if(vDate.getMonth()==3 || vDate.getMonth()==4 || vDate.getMonth()==5)
-			vDate.setFullYear(vDate.getFullYear(), 5, 30);
-		else if(vDate.getMonth()==6 || vDate.getMonth()==7 || vDate.getMonth()==8)
-			vDate.setFullYear(vDate.getFullYear(), 8, 30);
-		else if(vDate.getMonth()==9 || vDate.getMonth()==10 || vDate.getMonth()==11)
-			vDate.setFullYear(vDate.getFullYear(), 11, 31);
-	}
-	else if (pFormat=='hour')
-	{
-		if(vDate.getHours()==0)vDate.setDate(vDate.getDate()+1);
-		vDate.setHours(vDate.getHours()+1);
-
-		while(vDate.getHours()%6!=5) vDate.setHours(vDate.getHours()+1);
-	}
-	return(vDate);
+exports.addThisRowListeners = function (pGanttChart, pObj1, pObj2) {
+    exports.addListener('mouseover', function () { pGanttChart.mouseOver(pObj1, pObj2); }, pObj1);
+    exports.addListener('mouseover', function () { pGanttChart.mouseOver(pObj1, pObj2); }, pObj2);
+    exports.addListener('mouseout', function () { pGanttChart.mouseOut(pObj1, pObj2); }, pObj1);
+    exports.addListener('mouseout', function () { pGanttChart.mouseOut(pObj1, pObj2); }, pObj2);
+};
+exports.updateGridHeaderWidth = function (pGanttChart) {
+    var head = pGanttChart.getChartHead();
+    var body = pGanttChart.getChartBody();
+    if (!head || !body)
+        return;
+    var isScrollVisible = body.scrollHeight > body.clientHeight;
+    if (isScrollVisible) {
+        head.style.width = "calc(100% - " + general_utils_1.getScrollbarWidth() + "px)";
+    }
+    else {
+        head.style.width = '100%';
+    }
+};
+exports.addFolderListeners = function (pGanttChart, pObj, pID) {
+    exports.addListener('click', function () {
+        exports.folder(pID, pGanttChart);
+        exports.updateGridHeaderWidth(pGanttChart);
+    }, pObj);
+};
+exports.addFormatListeners = function (pGanttChart, pFormat, pObj) {
+    exports.addListener('click', function () { general_utils_1.changeFormat(pFormat, pGanttChart); }, pObj);
+};
+exports.addScrollListeners = function (pGanttChart) {
+    exports.addListener('resize', function () { pGanttChart.getChartHead().scrollLeft = pGanttChart.getChartBody().scrollLeft; }, window);
+    exports.addListener('resize', function () {
+        pGanttChart.getListBody().scrollTop = pGanttChart.getChartBody().scrollTop;
+    }, window);
+};
+exports.addListenerClickCell = function (vTmpCell, vEvents, task, column) {
+    exports.addListener('click', function (e) {
+        if (e.target.classList.contains('gfoldercollapse') === false &&
+            vEvents[column] && typeof vEvents[column] === 'function') {
+            vEvents[column](task, e, vTmpCell, column);
+        }
+    }, vTmpCell);
+};
+exports.addListenerInputCell = function (vTmpCell, vEventsChange, callback, tasks, index, column, draw, event) {
+    if (draw === void 0) { draw = null; }
+    if (event === void 0) { event = 'blur'; }
+    var task = tasks[index];
+    if (vTmpCell.children[0] && vTmpCell.children[0].children && vTmpCell.children[0].children[0]) {
+        var tagName = vTmpCell.children[0].children[0].tagName;
+        var selectInputOrButton = tagName === 'SELECT' || tagName === 'INPUT' || tagName === 'BUTTON';
+        if (selectInputOrButton) {
+            exports.addListener(event, function (e) {
+                if (callback) {
+                    callback(task, e);
+                }
+                if (vEventsChange[column] && typeof vEventsChange[column] === 'function') {
+                    var q = vEventsChange[column](tasks, task, e, vTmpCell, vColumnsNames[column]);
+                    if (q && q.then) {
+                        q.then(function (e) { return draw(); });
+                    }
+                    else {
+                        draw();
+                    }
+                }
+                else {
+                    draw();
+                }
+            }, vTmpCell.children[0].children[0]);
+        }
+    }
+};
+exports.addListenerDependencies = function (vLineOptions) {
+    var elements = document.querySelectorAll('.gtaskbarcontainer');
+    for (var i = 0; i < elements.length; i++) {
+        var taskDiv = elements[i];
+        taskDiv.addEventListener('mouseover', function (e) {
+            toggleDependencies(e, vLineOptions);
+        });
+        taskDiv.addEventListener('mouseout', function (e) {
+            toggleDependencies(e, vLineOptions);
+        });
+    }
+};
+var toggleDependencies = function (e, vLineOptions) {
+    var target = e.currentTarget;
+    var ids = target.getAttribute('id').split('_');
+    var style = vLineOptions && vLineOptions.borderStyleHover !== undefined ? vLineOptions.hoverStyle : 'groove';
+    if (e.type === 'mouseout') {
+        style = '';
+    }
+    if (ids.length > 1) {
+        var frameZones = Array.from(document.querySelectorAll(".gDepId" + ids[1]));
+        frameZones.forEach(function (c) {
+            c.style.borderStyle = style;
+        });
+        // document.querySelectorAll(`.gDepId${ids[1]}`).forEach((c: any) => {
+        // c.style.borderStyle = style;
+        // });
+    }
+};
+var vColumnsNames = {
+    taskname: 'pName',
+    res: 'pRes',
+    dur: '',
+    comp: 'pComp',
+    start: 'pStart',
+    end: 'pEnd',
+    planstart: 'pPlanStart',
+    planend: 'pPlanEnd',
+    link: 'pLink',
+    cost: 'pCost',
+    mile: 'pMile',
+    group: 'pGroup',
+    parent: 'pParent',
+    open: 'pOpen',
+    depend: 'pDepend',
+    caption: 'pCaption',
+    note: 'pNotes'
 };
 
+},{"./utils/general_utils":13}],6:[function(require,module,exports){
+"use strict";
+/*
+    * Copyright (c) 2013-2018, Paul Geldart, Eduardo Rodrigues, Ricardo Cardoso and Mario Mol.
+    *
+    * Redistribution and use in source and binary forms, with or without
+    * modification, are permitted provided that the following conditions are met:
+    *     * Redistributions of source code must retain the above copyright
+    *       notice, this list of conditions and the following disclaimer.
+    *     * Redistributions in binary form must reproduce the above copyright
+    *       notice, this list of conditions and the following disclaimer in the
+    *       documentation and/or other materials provided with the distribution.
+    *     * Neither the name of AUTHORS nor the names of its contributors
+    *       may be used to endorse or promote products derived from this software
+    *       without specific prior written permission.
+    *
+    * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR
+    * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    * IN NO EVENT SHALL AUTHORS BE LIABLE FOR ANY DIRECT,
+    * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    This project is based on jsGantt 1.2, (which can be obtained from
+    https://code.google.com/p/jsgantt/) and remains under the original BSD license.
+    Copyright (c) 2009, Shlomy Gantz BlueBrick Inc.
+*/
+Object.defineProperty(exports, "__esModule", { value: true });
+var events_1 = require("./events");
+var general_utils_1 = require("./utils/general_utils");
+var xml_1 = require("./xml");
+var task_1 = require("./task");
+var draw_1 = require("./draw");
+var json_1 = require("./json");
+var date_utils_1 = require("./utils/date_utils");
+if (!exports.JSGantt)
+    exports.JSGantt = {};
+exports.JSGantt.isIE = general_utils_1.isIE;
+exports.JSGantt.TaskItem = task_1.TaskItem;
+exports.JSGantt.GanttChart = draw_1.GanttChart;
+exports.JSGantt.updateFlyingObj = general_utils_1.updateFlyingObj;
+exports.JSGantt.showToolTip = events_1.showToolTip;
+exports.JSGantt.stripIds = general_utils_1.stripIds;
+exports.JSGantt.stripUnwanted = general_utils_1.stripUnwanted;
+exports.JSGantt.delayedHide = general_utils_1.delayedHide;
+exports.JSGantt.hideToolTip = general_utils_1.hideToolTip;
+exports.JSGantt.fadeToolTip = general_utils_1.fadeToolTip;
+exports.JSGantt.moveToolTip = general_utils_1.moveToolTip;
+exports.JSGantt.getZoomFactor = general_utils_1.getZoomFactor;
+exports.JSGantt.getOffset = general_utils_1.getOffset;
+exports.JSGantt.getScrollPositions = general_utils_1.getScrollPositions;
+exports.JSGantt.processRows = task_1.processRows;
+exports.JSGantt.sortTasks = task_1.sortTasks;
+// Used to determine the minimum date of all tasks and set lower bound based on format
+exports.JSGantt.getMinDate = date_utils_1.getMinDate;
+// Used to determine the maximum date of all tasks and set upper bound based on format
+exports.JSGantt.getMaxDate = date_utils_1.getMaxDate;
 // This function finds the document id of the specified object
-JSGantt.findObj=function (theObj, theDoc)
-{
-	var p, i, foundObj;
-	if(!theDoc) theDoc=document;
-	if(document.getElementById) foundObj=document.getElementById(theObj);
-	return foundObj;
+exports.JSGantt.findObj = general_utils_1.findObj;
+exports.JSGantt.changeFormat = general_utils_1.changeFormat;
+// Tasks
+exports.JSGantt.folder = events_1.folder;
+exports.JSGantt.hide = events_1.hide;
+exports.JSGantt.show = events_1.show;
+exports.JSGantt.taskLink = task_1.taskLink;
+exports.JSGantt.parseDateStr = date_utils_1.parseDateStr;
+exports.JSGantt.formatDateStr = date_utils_1.formatDateStr;
+exports.JSGantt.parseDateFormatStr = date_utils_1.parseDateFormatStr;
+// XML 
+exports.JSGantt.parseXML = xml_1.parseXML;
+exports.JSGantt.parseXMLString = xml_1.parseXMLString;
+exports.JSGantt.findXMLNode = xml_1.findXMLNode;
+exports.JSGantt.getXMLNodeValue = xml_1.getXMLNodeValue;
+exports.JSGantt.AddXMLTask = xml_1.AddXMLTask;
+// JSON
+exports.JSGantt.parseJSON = json_1.parseJSON;
+exports.JSGantt.parseJSONString = json_1.parseJSONString;
+exports.JSGantt.addJSONTask = json_1.addJSONTask;
+exports.JSGantt.benchMark = general_utils_1.benchMark;
+exports.JSGantt.getIsoWeek = date_utils_1.getIsoWeek;
+exports.JSGantt.addListener = events_1.addListener;
+exports.JSGantt.addTooltipListeners = events_1.addTooltipListeners;
+exports.JSGantt.addThisRowListeners = events_1.addThisRowListeners;
+exports.JSGantt.addFolderListeners = events_1.addFolderListeners;
+exports.JSGantt.addFormatListeners = events_1.addFormatListeners;
+exports.JSGantt.addScrollListeners = events_1.addScrollListeners;
+exports.JSGantt.criticalPath = general_utils_1.criticalPath;
+
+},{"./draw":2,"./events":5,"./json":7,"./task":10,"./utils/date_utils":11,"./utils/general_utils":13,"./xml":14}],7:[function(require,module,exports){
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
+    });
 };
-
-JSGantt.changeFormat=function(pFormat,ganttObj)
-{
-	if(ganttObj) ganttObj.setFormat(pFormat);
-	else alert('Chart undefined');
+var __generator = (this && this.__generator) || function (thisArg, body) {
+    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+    function verb(n) { return function (v) { return step([n, v]); }; }
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (_) try {
+            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+            if (y = 0, t) op = [op[0] & 2, t.value];
+            switch (op[0]) {
+                case 0: case 1: t = op; break;
+                case 4: _.label++; return { value: op[1], done: false };
+                case 5: _.label++; y = op[1]; op = [0]; continue;
+                case 7: op = _.ops.pop(); _.trys.pop(); continue;
+                default:
+                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+                    if (t[2]) _.ops.pop();
+                    _.trys.pop(); continue;
+            }
+            op = body.call(thisArg, _);
+        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+    }
 };
-
-// Function to open/close and hide/show children of specified task
-JSGantt.folder=function (pID,ganttObj)
-{
-	var vList=ganttObj.getList();
-	var vDivId=ganttObj.getDivId();
-
-	ganttObj.clearDependencies(); // clear these first so slow rendering doesn't look odd
-
-	for(var i=0; i<vList.length; i++)
-	{
-		if(vList[i].getID()==pID)
-		{
-			if(vList[i].getOpen()==1)
-			{
-				vList[i].setOpen(0);
-				JSGantt.hide(pID,ganttObj);
-
-				if (JSGantt.isIE())
-					vList[i].getGroupSpan().innerText='+';
-				else
-					vList[i].getGroupSpan().textContent='+';
-			}
-			else
-			{
-				vList[i].setOpen(1);
-				JSGantt.show(pID, 1, ganttObj);
-
-				if (JSGantt.isIE())
-					vList[i].getGroupSpan().innerText='-';
-				else
-					vList[i].getGroupSpan().textContent='-';
-			}
-		}
-	}
-	ganttObj.DrawDependencies();
+Object.defineProperty(exports, "__esModule", { value: true });
+var task_1 = require("./task");
+var general_utils_1 = require("./utils/general_utils");
+/**
+ *
+ * @param pFile
+ * @param pGanttlet
+ */
+exports.parseJSON = function (pFile, pGanttVar, vDebug, redrawAfter) {
+    if (vDebug === void 0) { vDebug = false; }
+    if (redrawAfter === void 0) { redrawAfter = true; }
+    return __awaiter(this, void 0, void 0, function () {
+        var jsonObj, bd, ad;
+        return __generator(this, function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, general_utils_1.makeRequest(pFile, true, true)];
+                case 1:
+                    jsonObj = _a.sent();
+                    if (vDebug) {
+                        bd = new Date();
+                        console.info('before jsonparse', bd);
+                    }
+                    exports.addJSONTask(pGanttVar, jsonObj);
+                    if (this.vDebug) {
+                        ad = new Date();
+                        console.info('after addJSONTask', ad, (ad.getTime() - bd.getTime()));
+                    }
+                    if (redrawAfter) {
+                        pGanttVar.Draw();
+                    }
+                    return [2 /*return*/, jsonObj];
+            }
+        });
+    });
 };
-
-JSGantt.hide=function (pID,ganttObj)
-{
-	var vList=ganttObj.getList();
-	var vID=0;
-	var vDivId=ganttObj.getDivId();
-
-	for(var i=0; i<vList.length; i++)
-	{
-		if(vList[i].getParent()==pID)
-		{
-			vID=vList[i].getID();
-			// it's unlikely but if the task list has been updated since
-			// the chart was drawn some of the rows may not exist
-			if (vList[i].getListChildRow()) vList[i].getListChildRow().style.display='none';
-			if (vList[i].getChildRow()) vList[i].getChildRow().style.display='none';
-			vList[i].setVisible(0);
-			if(vList[i].getGroup()) JSGantt.hide(vID,ganttObj);
-		}
-	}
+exports.parseJSONString = function (pStr, pGanttVar) {
+    exports.addJSONTask(pGanttVar, JSON.parse(pStr));
+};
+exports.addJSONTask = function (pGanttVar, pJsonObj) {
+    for (var index = 0; index < pJsonObj.length; index++) {
+        var id = void 0;
+        var name_1 = void 0;
+        var start = void 0;
+        var end = void 0;
+        var planstart = void 0;
+        var planend = void 0;
+        var itemClass = void 0;
+        var link = '';
+        var milestone = 0;
+        var resourceName = '';
+        var completion = void 0;
+        var group = 0;
+        var parent_1 = void 0;
+        var open_1 = void 0;
+        var dependsOn = '';
+        var caption = '';
+        var notes = '';
+        var cost = void 0;
+        var duration = '';
+        var bartext = '';
+        var additionalObject = {};
+        for (var prop in pJsonObj[index]) {
+            var property = prop;
+            var value = pJsonObj[index][property];
+            switch (property.toLowerCase()) {
+                case 'pid':
+                case 'id':
+                    id = value;
+                    break;
+                case 'pname':
+                case 'name':
+                    name_1 = value;
+                    break;
+                case 'pstart':
+                case 'start':
+                    start = value;
+                    break;
+                case 'pend':
+                case 'end':
+                    end = value;
+                    break;
+                case 'pplanstart':
+                case 'planstart':
+                    planstart = value;
+                    break;
+                case 'pplanend':
+                case 'planend':
+                    planend = value;
+                    break;
+                case 'pclass':
+                case 'class':
+                    itemClass = value;
+                    break;
+                case 'plink':
+                case 'link':
+                    link = value;
+                    break;
+                case 'pmile':
+                case 'mile':
+                    milestone = value;
+                    break;
+                case 'pres':
+                case 'res':
+                    resourceName = value;
+                    break;
+                case 'pcomp':
+                case 'comp':
+                    completion = value;
+                    break;
+                case 'pgroup':
+                case 'group':
+                    group = value;
+                    break;
+                case 'pparent':
+                case 'parent':
+                    parent_1 = value;
+                    break;
+                case 'popen':
+                case 'open':
+                    open_1 = value;
+                    break;
+                case 'pdepend':
+                case 'depend':
+                    dependsOn = value;
+                    break;
+                case 'pcaption':
+                case 'caption':
+                    caption = value;
+                    break;
+                case 'pnotes':
+                case 'notes':
+                    notes = value;
+                    break;
+                case 'pcost':
+                case 'cost':
+                    cost = value;
+                    break;
+                case 'duration':
+                case 'pduration':
+                    duration = value;
+                    break;
+                case 'bartext':
+                case 'pbartext':
+                    bartext = value;
+                    break;
+                default:
+                    additionalObject[property.toLowerCase()] = value;
+            }
+        }
+        //if (id != undefined && !isNaN(parseInt(id)) && isFinite(id) && name && start && end && itemClass && completion != undefined && !isNaN(parseFloat(completion)) && isFinite(completion) && !isNaN(parseInt(parent)) && isFinite(parent)) {
+        pGanttVar.AddTaskItem(new task_1.TaskItem(id, name_1, start, end, itemClass, link, milestone, resourceName, completion, group, parent_1, open_1, dependsOn, caption, notes, pGanttVar, cost, planstart, planend, duration, bartext, additionalObject));
+        //}
+    }
 };
 
-// Function to show children of specified task
-JSGantt.show=function (pID, pTop, ganttObj)
-{
-	var vList=ganttObj.getList();
-	var vID=0;
-	var vDivId=ganttObj.getDivId();
-	var vState='';
-
-	for(var i=0; i<vList.length; i++)
-	{
-		if(vList[i].getParent()==pID)
-		{
-			if (vList[i].getParItem().getGroupSpan())
-			{
-				if (JSGantt.isIE()) vState=vList[i].getParItem().getGroupSpan().innerText;
-				else vState=vList[i].getParItem().getGroupSpan().textContent;
-			}
-			i=vList.length;
-		}
-	}
-
-	for(i=0; i<vList.length; i++)
-	{
-		if(vList[i].getParent()==pID)
-		{
-			var vChgState=false;
-			vID=vList[i].getID();
-
-			if(pTop==1 && vState=='+')vChgState=true;
-			else if(vState=='-')vChgState=true;
-			else if(vList[i].getParItem() && vList[i].getParItem().getGroup()==2)vList[i].setVisible(1);
-
-			if(vChgState)
-			{
-				if (vList[i].getListChildRow()) vList[i].getListChildRow().style.display='';
-				if (vList[i].getChildRow()) vList[i].getChildRow().style.display='';
-				vList[i].setVisible(1);
-			}
-			if(vList[i].getGroup()) JSGantt.show(vID, 0,ganttObj);
-		}
-	}
+},{"./task":10,"./utils/general_utils":13}],8:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var es = {
+    'january': 'Enero',
+    'february': 'Febrero',
+    'march': 'Marzo',
+    'april': 'Abril',
+    'maylong': 'Mayo',
+    'june': 'Junio',
+    'july': 'Julio',
+    'august': 'Agosto',
+    'september': 'Septiembre',
+    'october': 'Octubre',
+    'november': 'Noviembre',
+    'december': 'Diciembre',
+    'jan': 'Ene',
+    'feb': 'Feb',
+    'mar': 'Mar',
+    'apr': 'Abr',
+    'may': 'May',
+    'jun': 'Jun',
+    'jul': 'Jul',
+    'aug': 'Ago',
+    'sep': 'Sep',
+    'oct': 'Oct',
+    'nov': 'Nov',
+    'dec': 'Dic',
+    'sunday': 'Domingo',
+    'monday': 'Lunes',
+    'tuesday': 'Martes',
+    'wednesday': 'Miércoles',
+    'thursday': 'Jueves',
+    'friday': 'Viernes',
+    'saturday': 'Sábado',
+    'sun': '	Dom',
+    'mon': '	Lun',
+    'tue': '	Mar',
+    'wed': '	Mie',
+    'thu': '	Jue',
+    'fri': '	Vie',
+    'sat': '	Sab',
+    'res': 'Recurso',
+    'dur': 'Duración',
+    'comp': '% Compl.',
+    'completion': 'Completado',
+    'startdate': 'Inicio',
+    'planstartdate': 'Inicio Planificado',
+    'cost': 'Coste',
+    'enddate': 'Fin',
+    'planenddate': 'Fin Planificado',
+    'moreinfo': 'Más Información',
+    'nodata': 'No tasks found',
+    'notes': 'Notas',
+    'format': 'Formato',
+    'hour': 'Hora',
+    'day': 'Día',
+    'week': 'Semana',
+    'month': 'Mes',
+    'quarter': 'Trimestre',
+    'hours': 'Horas',
+    'days': 'Días',
+    'weeks': 'Semanas',
+    'months': 'Meses',
+    'quarters': 'Trimestres',
+    'hr': 'h',
+    'dy': 'Día',
+    'wk': 'Sem.',
+    'mth': 'Mes',
+    'qtr': 'Trim.',
+    'hrs': 'h',
+    'dys': 'Días',
+    'wks': 'Sem.',
+    'mths': 'Meses',
+    'qtrs': 'Trim.',
+    'tooltipLoading': 'Cargando...'
+};
+exports.es = es;
+var en = {
+    'format': 'Format',
+    'hour': 'Hour',
+    'day': 'Day',
+    'week': 'Week',
+    'month': 'Month',
+    'quarter': 'Quarter',
+    'hours': 'Hours',
+    'days': 'Days',
+    'weeks': 'Weeks',
+    'months': 'Months',
+    'quarters': 'Quarters',
+    'hr': 'Hr',
+    'dy': 'Day',
+    'wk': 'Wk',
+    'mth': 'Mth',
+    'qtr': 'Qtr',
+    'hrs': 'Hrs',
+    'dys': 'Days',
+    'wks': 'Wks',
+    'mths': 'Mths',
+    'qtrs': 'Qtrs',
+    'res': 'Resource',
+    'dur': 'Duration',
+    'comp': '% Comp.',
+    'completion': 'Completion',
+    'startdate': 'Start Date',
+    'planstartdate': 'Plan Start Date',
+    'enddate': 'End Date',
+    'planenddate': 'Plan End Date',
+    'cost': 'Cost',
+    'moreinfo': 'More Information',
+    'nodata': 'No tasks found',
+    'notes': 'Notes',
+    'january': 'January',
+    'february': 'February',
+    'march': 'March',
+    'april': 'April',
+    'maylong': 'May',
+    'june': 'June',
+    'july': 'July',
+    'august': 'August',
+    'september': 'September',
+    'october': 'October',
+    'november': 'November',
+    'december': 'December',
+    'jan': 'Jan',
+    'feb': 'Feb',
+    'mar': 'Mar',
+    'apr': 'Apr',
+    'may': 'May',
+    'jun': 'Jun',
+    'jul': 'Jul',
+    'aug': 'Aug',
+    'sep': 'Sep',
+    'oct': 'Oct',
+    'nov': 'Nov',
+    'dec': 'Dec',
+    'sunday': 'Sunday',
+    'monday': 'Monday',
+    'tuesday': 'Tuesday',
+    'wednesday': 'Wednesday',
+    'thursday': 'Thursday',
+    'friday': 'Friday',
+    'saturday': 'Saturday',
+    'sun': 'Sun',
+    'mon': 'Mon',
+    'tue': 'Tue',
+    'wed': 'Wed',
+    'thu': 'Thu',
+    'fri': 'Fri',
+    'sat': 'Sat',
+    'tooltipLoading': 'Loading...'
+};
+exports.en = en;
+var de = {
+    'format': 'Ansicht',
+    'hour': 'Stunde',
+    'day': 'Tag',
+    'week': 'Woche',
+    'month': 'Monat',
+    'quarter': 'Quartal',
+    'hours': 'Stunden',
+    'days': 'Tage',
+    'weeks': 'Wochen',
+    'months': 'Monate',
+    'quarters': 'Quartale',
+    'hr': 'h',
+    'dy': 'T',
+    'wk': 'W',
+    'mth': 'M',
+    'qtr': 'Q',
+    'hrs': 'Std',
+    'dys': 'Tage',
+    'wks': 'Wochen',
+    'mths': 'Monate',
+    'qtrs': 'Quartal',
+    'res': 'Resource',
+    'dur': 'Dauer',
+    'comp': '%Fertig',
+    'completion': 'Fertigstellung',
+    'startdate': 'Erste Buchu',
+    'planstartdate': 'Erste Buchu Plan',
+    'enddate': 'Letzte Buchung',
+    'planenddate': 'Plan Letzte Buchung',
+    'cost': 'Cost',
+    'moreinfo': 'Weitere Infos',
+    'nodata': 'No tasks found',
+    'notes': 'Anmerkung',
+    'january': 'Jänner',
+    'february': 'Februar',
+    'march': 'März',
+    'april': 'April',
+    'maylong': 'Mai',
+    'june': 'Juni',
+    'july': 'Juli',
+    'august': 'August',
+    'september': 'September',
+    'october': 'Oktober',
+    'november': 'November',
+    'december': 'Dezember',
+    'jan': 'Jan',
+    'feb': 'Feb',
+    'mar': 'Mar',
+    'apr': 'Apr',
+    'may': 'Mai',
+    'jun': 'Jun',
+    'jul': 'Jul',
+    'aug': 'Aug',
+    'sep': 'Sep',
+    'oct': 'Okt',
+    'nov': 'Nov',
+    'dec': 'Dez',
+    'sunday': 'Sonntag',
+    'monday': 'Montag',
+    'tuesday': 'Dienstag',
+    'wednesday': 'Mittwoch',
+    'thursday': 'Donnerstag',
+    'friday': 'Freitag',
+    'saturday': 'Samstag',
+    'sun': 'So',
+    'mon': 'Mo', 'tue': 'Di', 'wed': 'Mi', 'thu': 'Do', 'fri': 'Fr', 'sat': 'Sa'
+};
+exports.de = de;
+var pt = {
+    'hours': 'Horas',
+    'days': 'Dias',
+    'weeks': 'Weeks',
+    'months': 'Months',
+    'quarters': 'Quarters',
+    'format': 'Formato',
+    'hour': 'Hora',
+    'day': 'Dia',
+    'week': 'Semana',
+    'month': 'Mês',
+    'quarter': 'Trimestre',
+    'hr': 'hr',
+    'dy': 'dia',
+    'wk': 'sem.',
+    'mth': 'mês',
+    'qtr': 'qtr',
+    'hrs': 'hrs',
+    'dys': 'dias',
+    'wks': 'sem.',
+    'mths': 'meses',
+    'qtrs': 'qtrs',
+    'completion': 'Terminado',
+    'comp': '% Completado',
+    'moreinfo': 'Mais informações',
+    'nodata': 'Sem atividades',
+    'notes': 'Notas',
+    'res': 'Responsável',
+    'dur': 'Duração',
+    'startdate': 'Data inicial',
+    'planstartdate': 'Plan Data inicial',
+    'enddate': 'Data final',
+    'planenddate': 'Plan Data final',
+    'cost': 'Custo',
+    'jan': 'Jan',
+    'feb': 'Fev',
+    'mar': 'Mar',
+    'apr': 'Abr',
+    'may': 'Mai',
+    'jun': 'Jun',
+    'jul': 'Jul',
+    'aug': 'Ago',
+    'sep': 'Set',
+    'oct': 'Out',
+    'nov': 'Nov',
+    'dec': 'Dez',
+    'january': 'Janeiro',
+    'february': 'Fevereiro',
+    'march': 'Março',
+    'april': 'Abril',
+    'maylong': 'Maio',
+    'june': 'Junho',
+    'july': 'Julho',
+    'august': 'Agosto',
+    'september': 'Setembro',
+    'october': 'Outubro',
+    'november': 'Novembro',
+    'december': 'Dezembro',
+    'sun': 'Dom',
+    'mon': 'Seg',
+    'tue': 'Ter',
+    'wed': 'Qua',
+    'thu': 'Qui',
+    'fri': 'Sex',
+    'sat': 'Sab'
+};
+exports.pt = pt;
+var ru = {
+    'january': 'Январь',
+    'february': 'Февраль',
+    'march': 'Март',
+    'april': 'Апрель',
+    'maylong': 'Май',
+    'june': 'Июнь',
+    'july': 'Июль',
+    'august': 'Август', 'september': 'Сентябрь',
+    'october': 'Октябрь',
+    'november': 'Ноябрь',
+    'december': 'Декабрь',
+    'jan': 'Янв',
+    'feb': 'Фев',
+    'mar': 'Мар',
+    'apr': 'Апр',
+    'may': 'Май',
+    'jun': 'Июн',
+    'jul': 'Июл',
+    'aug': 'Авг',
+    'sep': 'Сен',
+    'oct': 'Окт',
+    'nov': 'Ноя',
+    'dec': 'Дек',
+    'sunday': 'Воскресенье',
+    'monday': 'Понедельник',
+    'tuesday': 'Вторник',
+    'wednesday': 'Среда',
+    'thursday': 'Четверг',
+    'friday': 'Пятница',
+    'saturday': 'Суббота',
+    'sun': '	Вс',
+    'mon': '	Пн',
+    'tue': '	Вт',
+    'wed': '	Ср',
+    'thu': '	Чт',
+    'fri': '	Пт',
+    'sat': '	Сб',
+    'res': 'Ресурс',
+    'dur': 'Длительность',
+    'comp': '% выполнения',
+    'completion': 'Выполнено',
+    'startdate': 'Нач. дата',
+    'planstartdate': 'Plan Нач. дата',
+    'enddate': 'Кон. дата',
+    'planenddate': 'Plan Кон. дата',
+    'cost': 'Cost',
+    'moreinfo': 'Детали',
+    'nodata': 'No tasks found',
+    'notes': 'Заметки',
+    'format': 'Формат',
+    'hour': 'Час',
+    'day': 'День',
+    'week': 'Неделя',
+    'month': 'Месяц',
+    'quarter': 'Кварт',
+    'hours': 'Часов',
+    'days': 'Дней',
+    'weeks': 'Недель',
+    'months': 'Месяцев',
+    'quarters': 'Кварталов',
+    'hr': 'ч.',
+    'dy': 'дн.',
+    'wk': 'нед.',
+    'mth': 'мес.',
+    'qtr': 'кв.',
+    'hrs': 'ч.',
+    'dys': 'дн.',
+    'wks': 'нед.',
+    'mths': 'мес.',
+    'qtrs': 'кв.',
+    'tooltipLoading': 'Загрузка...'
+};
+exports.ru = ru;
+/**
+ * Mois : http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=3619
+   Jours : http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=3617
+ */
+var fr = {
+    'january': 'Janvier',
+    'february': 'Février',
+    'march': 'Mars',
+    'april': 'Avril',
+    'maylong': 'Mai',
+    'june': 'Juin',
+    'july': 'Juillet',
+    'august': 'Août',
+    'september': 'Septembre',
+    'october': 'Octobre',
+    'november': 'Novembre',
+    'december': 'Décembre',
+    'jan': 'Janv',
+    'feb': 'Févr',
+    'mar': 'Mars',
+    'apr': 'Avr',
+    'may': 'Mai',
+    'jun': 'Juin',
+    'jul': 'Juil',
+    'aug': 'Août',
+    'sep': 'Sept',
+    'oct': 'Oct',
+    'nov': 'Nov',
+    'dec': 'Déc',
+    'sunday': 'Dimanche',
+    'monday': 'Lundi',
+    'tuesday': 'Mardi',
+    'wednesday': 'Mercredi',
+    'thursday': 'Jeudi',
+    'friday': 'Vendredi',
+    'saturday': 'Samedi',
+    'sun': 'Dim',
+    'mon': 'Lun',
+    'tue': 'Mar',
+    'wed': 'Mer',
+    'thu': 'Jeu',
+    'fri': 'Ven',
+    'sat': 'Sam',
+    'res': 'Ressource',
+    'dur': 'Durée',
+    'comp': '% Term.',
+    'completion': 'Terminé',
+    'startdate': 'Début',
+    'planstartdate': 'Plan Début',
+    'enddate': 'Fin',
+    'planenddate': 'Plan Fin',
+    'cost': 'Cost',
+    'moreinfo': "Plus d'informations",
+    'nodata': 'No tasks found',
+    'notes': 'Notes',
+    'format': 'Format',
+    'hour': 'Heure',
+    'day': 'Jour',
+    'week': 'Semaine',
+    'month': 'Mois',
+    'quarter': 'Trimestre',
+    'hours': 'Heures',
+    'days': 'Jours',
+    'weeks': 'Semaines',
+    'months': 'Mois',
+    'quarters': 'Trimestres',
+    'hr': 'h',
+    'dy': 'j',
+    'wk': 'sem',
+    'mth': 'mois',
+    'qtr': 'tri',
+    'hrs': 'h',
+    'dys': 'j',
+    'wks': 'sem',
+    'mths': 'mois',
+    'qtrs': 'tri'
+};
+exports.fr = fr;
+var cn = {
+    'january': '一月',
+    'february': '二月',
+    'march': '三月',
+    'april': '四月',
+    'maylong': '五月',
+    'june': '六月',
+    'july': '七月',
+    'august': '八月',
+    'september': '九月',
+    'october': '十月',
+    'november': '十一月',
+    'december': '十二月',
+    'jan': '一月',
+    'feb': '二月',
+    'mar': '三月',
+    'apr': '四月',
+    'may': '五月',
+    'jun': '六月',
+    'jul': '七月',
+    'aug': '八月',
+    'sep': '九月',
+    'oct': '十月',
+    'nov': '十一月',
+    'dec': '十二月',
+    'sunday': '星期日',
+    'monday': '星期一',
+    'tuesday': '星期二',
+    'wednesday': '星期三',
+    'thursday': '星期四',
+    'friday': '星期五',
+    'saturday': '星期六',
+    'sun': '星期日',
+    'mon': '星期一',
+    'tue': '星期二',
+    'wed': '星期三',
+    'thu': '星期四',
+    'fri': '星期五',
+    'sat': '星期六',
+    'res': '資源',
+    'dur': '時程',
+    'comp': '達成率',
+    'completion': '達成',
+    'startdate': '起始日期',
+    'planstartdate': '計劃起始日期',
+    'enddate': '截止日期',
+    'planenddate': '計劃截止日期',
+    'cost': '成本',
+    'moreinfo': "更多資訊",
+    'nodata': 'No tasks found',
+    'notes': '備註',
+    'format': '格式',
+    'hour': '時',
+    'day': '日',
+    'week': '星期',
+    'month': '月',
+    'quarter': '季',
+    'hours': '小時',
+    'days': '天',
+    'weeks': '週',
+    'months': '月',
+    'quarters': '季',
+    'hr': '小時',
+    'dy': '天',
+    'wk': '週',
+    'mth': '月',
+    'qtr': '季',
+    'hrs': '小時',
+    'dys': '天',
+    'wks': '週',
+    'mths': '月',
+    'qtrs': '季'
+};
+exports.cn = cn;
+var sv = {
+    'format': 'Filter',
+    'hour': 'Timme',
+    'day': 'Dag',
+    'week': 'Vecka',
+    'month': 'Månad',
+    'quarter': 'Kvartal',
+    'hours': 'Timmar',
+    'days': 'Dagar',
+    'weeks': 'Veckor',
+    'months': 'Månader',
+    'quarters': 'Kvartal',
+    'hr': 'Timme',
+    'dy': 'Dag',
+    'wk': 'Vecka',
+    'mth': 'Månad',
+    'qtr': 'Q',
+    'hrs': 'Timmar',
+    'dys': 'Dagar',
+    'wks': 'Veckor',
+    'mths': 'Månader',
+    'qtrs': 'Q',
+    'res': 'Resurs',
+    'dur': 'Tidsåtgång',
+    'comp': '% klart',
+    'completion': 'Klart',
+    'startdate': 'Startdatum',
+    'planstartdate': 'Planerad startdatum',
+    'enddate': 'Slutdatum',
+    'planenddate': 'Planerad slutdatum',
+    'cost': 'Kostnad',
+    'moreinfo': 'Mer Information',
+    'nodata': 'No tasks found',
+    'notes': 'Notes',
+    'january': 'januari',
+    'february': 'februari',
+    'march': 'mars',
+    'april': 'april',
+    'maylong': 'maj',
+    'june': 'juni',
+    'july': 'juli',
+    'august': 'augusti',
+    'september': 'september',
+    'october': 'oktober',
+    'november': 'november',
+    'december': 'december',
+    'jan': 'jan',
+    'feb': 'feb',
+    'mar': 'mar',
+    'apr': 'apr',
+    'may': 'maj',
+    'jun': 'jun',
+    'jul': 'jul',
+    'aug': 'aug',
+    'sep': 'sep',
+    'oct': 'okt',
+    'nov': 'nov',
+    'dec': 'dec',
+    'sunday': 'söndag',
+    'monday': 'måndag',
+    'tuesday': 'tisdag',
+    'wednesday': 'onsdag',
+    'thursday': 'torsdag',
+    'friday': 'fredag',
+    'saturday': 'lördag',
+    'sun': 'sön',
+    'mon': 'mån',
+    'tue': 'tis',
+    'wed': 'ons',
+    'thu': 'tor',
+    'fri': 'fre',
+    'sat': 'lör'
+};
+exports.sv = sv;
+var nl = {
+    'format': 'Format',
+    'hour': 'Uur',
+    'day': 'Dag',
+    'week': 'Week',
+    'month': 'Maand',
+    'quarter': 'Kwartaal',
+    'hours': 'Uren',
+    'days': 'Dagen',
+    'weeks': 'Weken',
+    'months': 'Maanden',
+    'quarters': 'Kwartalen',
+    'hr': 'uur',
+    'dy': 'dag',
+    'wk': 'wk',
+    'mth': 'mnd',
+    'qtr': 'kw',
+    'hrs': 'uren',
+    'dys': 'dagen',
+    'wks': 'weken',
+    'mths': 'maanden',
+    'qtrs': 'kwartalen',
+    'res': 'Resource',
+    'dur': 'Doorlooptijd',
+    'comp': '% gereed',
+    'completion': 'Gereed',
+    'startdate': 'Startdatum',
+    'planstartdate': 'Geplande startdatum',
+    'enddate': 'Einddatum',
+    'planenddate': 'Geplande einddatum',
+    'cost': 'Kosten',
+    'moreinfo': 'Meer informatie',
+    'nodata': 'No tasks found',
+    'notes': 'Notities',
+    'january': 'januari',
+    'february': 'februari',
+    'march': 'maart',
+    'april': 'april',
+    'maylong': 'mei',
+    'june': 'juni',
+    'july': 'juli',
+    'august': 'augustus',
+    'september': 'september',
+    'october': 'oktober',
+    'november': 'november',
+    'december': 'december',
+    'jan': 'jan',
+    'feb': 'feb',
+    'mar': 'mrt',
+    'apr': 'apr',
+    'may': 'mei',
+    'jun': 'jun',
+    'jul': 'jul',
+    'aug': 'aug',
+    'sep': 'sep',
+    'oct': 'okt',
+    'nov': 'nov',
+    'dec': 'dec',
+    'sunday': 'zondag',
+    'monday': 'maandag',
+    'tuesday': 'dinsdag',
+    'wednesday': 'woensdag',
+    'thursday': 'donderdag',
+    'friday': 'vrijdag',
+    'saturday': 'zaterdag',
+    'sun': 'zo',
+    'mon': 'ma',
+    'tue': 'di',
+    'wed': 'wo',
+    'thu': 'do',
+    'fri': 'vr',
+    'sat': 'za'
+};
+exports.nl = nl;
+var id = {
+    'format': 'Format',
+    'hour': 'Jam',
+    'day': 'Hari',
+    'week': 'Minggu',
+    'month': 'Bulan',
+    'quarter': 'Kuartal',
+    'hours': 'Jam',
+    'days': 'Hari',
+    'weeks': 'Minggu',
+    'months': 'Bulan',
+    'quarters': 'Kuartal',
+    'hr': 'Jam',
+    'dy': 'Hari',
+    'wk': 'Min',
+    'mth': 'Bln',
+    'qtr': 'Krtl',
+    'hrs': 'Jam',
+    'dys': 'Hari',
+    'wks': 'Min',
+    'mths': 'Bln',
+    'qtrs': 'Krtl',
+    'res': 'Sumber Daya',
+    'dur': 'Durasi',
+    'comp': '% Penyelesaian',
+    'completion': 'Penyelesaian',
+    'startdate': 'Tanggal Mulai',
+    'planstartdate': 'Perencanaan Tanggal Mulai',
+    'enddate': 'Tanggal Akhir',
+    'planenddate': 'Perencanaan Tanggal Akhir',
+    'cost': 'Biaya',
+    'moreinfo': 'Informasi Lebih Lanjut',
+    'nodata': 'No tasks found',
+    'notes': 'Catatan',
+    'january': 'Januari',
+    'february': 'Februari',
+    'march': 'Maret',
+    'april': 'April',
+    'maylong': 'Mei',
+    'june': 'Juni',
+    'july': 'Juli',
+    'august': 'Agustus',
+    'september': 'September',
+    'october': 'Oktober',
+    'november': 'November',
+    'december': 'Desember',
+    'jan': 'Jan',
+    'feb': 'Feb',
+    'mar': 'Mar',
+    'apr': 'Apr',
+    'may': 'Mei',
+    'jun': 'Jun',
+    'jul': 'Jul',
+    'aug': 'Agu',
+    'sep': 'Sep',
+    'oct': 'Okt',
+    'nov': 'Nov',
+    'dec': 'Des',
+    'sunday': 'Minggu',
+    'monday': 'Senin',
+    'tuesday': 'Selasa',
+    'wednesday': 'Rabu',
+    'thursday': 'Kamis',
+    'friday': 'Jumat',
+    'saturday': 'Sabtu',
+    'sun': 'Min',
+    'mon': 'Sen',
+    'tue': 'Sel',
+    'wed': 'Rab',
+    'thu': 'Kam',
+    'fri': 'Jum',
+    'sat': 'Sab'
+};
+exports.id = id;
+var tr = {
+    'format': 'Biçim',
+    'hour': 'Saat',
+    'day': 'Gün',
+    'week': 'Hafta',
+    'month': 'Ay',
+    'quarter': 'Çeyrek Yıl',
+    'hours': 'Saat',
+    'days': 'Gün',
+    'weeks': 'Hafta',
+    'months': 'Ay',
+    'quarters': 'Çeyrek Yıl',
+    'hr': 'Saat',
+    'dy': 'Gün',
+    'wk': 'Hft',
+    'mth': 'Ay',
+    'qtr': 'Çyrk',
+    'hrs': 'Saat',
+    'dys': 'Gün',
+    'wks': 'Hft',
+    'mths': 'Ay',
+    'qtrs': 'Çyrk',
+    'res': 'Kaynak',
+    'dur': 'Süre',
+    'comp': '% Tamamlanma.',
+    'completion': 'Tamamlanma',
+    'startdate': 'Başlangıç Tarihi',
+    'planstartdate': 'Plan Başlama Tarihi',
+    'enddate': 'Bitiş Tarihi',
+    'planenddate': 'Plan Bitiş Tarihi',
+    'cost': 'Tutar',
+    'moreinfo': 'Daha Fazla Bilgi',
+    'nodata': 'No tasks found',
+    'notes': 'Notlar',
+    'january': 'Ocak',
+    'february': 'Şubat',
+    'march': 'Mart',
+    'april': 'Nisan',
+    'maylong': 'Mayıs',
+    'june': 'Haziran',
+    'july': 'Temmuz',
+    'august': 'Ağustos',
+    'september': 'Eylül',
+    'october': 'Ekim',
+    'november': 'Kasım',
+    'december': 'Aralık',
+    'jan': 'Oca',
+    'feb': 'Şub',
+    'mar': 'Mar',
+    'apr': 'Nis',
+    'may': 'May',
+    'jun': 'Haz',
+    'jul': 'Tem',
+    'aug': 'Ağu',
+    'sep': 'Eyl',
+    'oct': 'Eki',
+    'nov': 'Kas',
+    'dec': 'Ara',
+    'sunday': 'Pazar',
+    'monday': 'Pazartesi',
+    'tuesday': 'Salı',
+    'wednesday': 'Çarşamba',
+    'thursday': 'Perşembe',
+    'friday': 'Cuma',
+    'saturday': 'Cumartesi',
+    'sun': 'Paz',
+    'mon': 'Pzt',
+    'tue': 'Sal',
+    'wed': 'Çrş',
+    'thu': 'Prş',
+    'fri': 'Cum',
+    'sat': 'Cmt'
+};
+exports.tr = tr;
+var ja = {
+    'format': 'タイムライン表示',
+    'hour': '時',
+    'day': '日',
+    'week': '週',
+    'month': '月',
+    'quarter': '四半期',
+    'hours': '時間',
+    'days': '日間',
+    'weeks': '週間',
+    'months': '月間',
+    'quarters': '四半期',
+    'hr': '時',
+    'dy': '日',
+    'wk': '週',
+    'mth': '月',
+    'qtr': '四',
+    'hrs': '時間',
+    'dys': '日間',
+    'wks': '週間',
+    'mths': '月間',
+    'qtrs': '四半期',
+    'res': 'リソース',
+    'dur': '期間',
+    'comp': '進捗率',
+    'completion': '進捗率',
+    'startdate': '開始日',
+    'planstartdate': '予定開始日',
+    'enddate': '期日',
+    'planenddate': '予定期日',
+    'cost': 'コスト',
+    'moreinfo': '詳細',
+    'nodata': 'No tasks found',
+    'notes': 'ノート',
+    'january': '1月',
+    'february': '2月',
+    'march': '3月',
+    'april': '4月',
+    'maylong': '5月',
+    'june': '6月',
+    'july': '7月',
+    'august': '8月',
+    'september': '9月',
+    'october': '10月',
+    'november': '11月',
+    'december': '12月',
+    'jan': '1月',
+    'feb': '2月',
+    'mar': '3月',
+    'apr': '4月',
+    'may': '5月',
+    'jun': '6月',
+    'jul': '7月',
+    'aug': '8月',
+    'sep': '9月',
+    'oct': '10月',
+    'nov': '11月',
+    'dec': '12月',
+    'sunday': '日曜日',
+    'monday': '月曜日',
+    'tuesday': '火曜日',
+    'wednesday': '水曜日',
+    'thursday': '木曜日',
+    'friday': '金曜日',
+    'saturday': '土曜日',
+    'sun': '日',
+    'mon': '月',
+    'tue': '火',
+    'wed': '水',
+    'thu': '木',
+    'fri': '金',
+    'sat': '土',
+    'tooltipLoading': 'ローディング中...'
+};
+exports.ja = ja;
+var cs = {
+    'format': 'Zobrazení',
+    'hour': 'Hodina',
+    'day': 'Den',
+    'week': 'Týden',
+    'month': 'Měsíc',
+    'quarter': 'Kvartál',
+    'hours': 'Hodiny',
+    'days': 'Dni',
+    'weeks': 'Týdny',
+    'months': 'Měsíce',
+    'quarters': 'Kvartály',
+    'hr': 'Ho',
+    'dy': 'Den',
+    'wk': 'Tyd',
+    'mth': 'Měs',
+    'qtr': 'Kvar',
+    'hrs': 'Ho',
+    'dys': 'Dni',
+    'wks': 'Tyd',
+    'mths': 'Měs',
+    'qtrs': 'Kvar',
+    'res': 'Přiřazeno',
+    'dur': 'Trvání',
+    'comp': '% Hotovo',
+    'completion': 'Hotovo',
+    'startdate': 'Start',
+    'planstartdate': 'Plánovaný start',
+    'enddate': 'Konec',
+    'planenddate': 'Plánovaný konec',
+    'cost': 'Náklady',
+    'moreinfo': 'Více informací',
+    'nodata': 'No tasks found',
+    'notes': 'Poznámky',
+    'january': 'Leden',
+    'february': 'Únor',
+    'march': 'Březen',
+    'april': 'Duben',
+    'maylong': 'Květen',
+    'june': 'Červen',
+    'july': 'Červenec',
+    'august': 'Srpen',
+    'september': 'Září',
+    'october': 'Říjen',
+    'november': 'Listopad',
+    'december': 'Prosinec',
+    'jan': 'Led',
+    'feb': 'Úno',
+    'mar': 'Bře',
+    'apr': 'Dub',
+    'may': 'Kvě',
+    'jun': 'Čer',
+    'jul': 'Čvc',
+    'aug': 'Srp',
+    'sep': 'Zář',
+    'oct': 'Říj',
+    'nov': 'Lis',
+    'dec': 'Pro',
+    'sunday': 'Neděle',
+    'monday': 'Pondělí',
+    'tuesday': 'Úterý',
+    'wednesday': 'Středa',
+    'thursday': 'Čtvrtek',
+    'friday': 'Pátek',
+    'saturday': 'Sobota',
+    'sun': 'Ne',
+    'mon': 'Po',
+    'tue': 'Út',
+    'wed': 'St',
+    'thu': 'Čt',
+    'fri': 'Pa',
+    'sat': 'So',
+    'tooltipLoading': 'Nahrávám...'
+};
+exports.cs = cs;
+var hu = {
+    'format': 'Formátum',
+    'hour': 'Óra',
+    'day': 'Nap',
+    'week': 'Hét',
+    'month': 'Hónap',
+    'quarter': 'Negyedév ',
+    'hours': 'Órák',
+    'days': 'Nap',
+    'weeks': 'Hét',
+    'months': 'Hónap',
+    'quarters': 'Negyedév',
+    'hr': 'Ó',
+    'dy': 'Nap',
+    'wk': 'Hét',
+    'mth': 'Hó',
+    'qtr': 'NÉ',
+    'hrs': 'Óra',
+    'dys': 'Nap',
+    'wks': 'Hét',
+    'mths': 'Hó',
+    'qtrs': 'NÉ',
+    'res': 'Erőforrás',
+    'dur': 'Időtartam',
+    'comp': '% Kész',
+    'completion': 'Elkészült',
+    'startdate': 'Kezdés',
+    'planstartdate': 'Tervezett kezdés',
+    'enddate': 'Befejezés',
+    'planenddate': 'Tervezett befejezés',
+    'cost': 'Költség',
+    'moreinfo': 'További információ',
+    'nodata': 'No tasks found',
+    'notes': 'Jegyzetek',
+    'january': 'Január',
+    'february': 'Február',
+    'march': 'Március',
+    'april': 'Április',
+    'maylong': 'Május',
+    'june': 'Június',
+    'july': 'Július',
+    'august': 'Augusztus',
+    'september': 'Szeptember',
+    'october': 'Október',
+    'november': 'November',
+    'december': 'December',
+    'jan': 'Jan',
+    'feb': 'Feb',
+    'mar': 'Már',
+    'apr': 'Ápr',
+    'may': 'Máj',
+    'jun': 'Jún',
+    'jul': 'Júl',
+    'aug': 'Aug',
+    'sep': 'Szep',
+    'oct': 'Okt',
+    'nov': 'Nov',
+    'dec': 'Dec',
+    'sunday': 'Vasárnap',
+    'monday': 'Hétfő',
+    'tuesday': 'Kedd',
+    'wednesday': 'Szerda',
+    'thursday': 'Csütörtök',
+    'friday': 'Péntek',
+    'saturday': 'Szombat',
+    'sun': 'Vas',
+    'mon': 'Hé',
+    'tue': 'Ke',
+    'wed': 'Sze',
+    'thu': 'Csü',
+    'fri': 'Pén',
+    'sat': 'Szo',
+    'tooltipLoading': 'Belöltés...'
+};
+exports.hu = hu;
+var ko = {
+    'format': '구분',
+    'hour': '시',
+    'day': '일',
+    'week': '주',
+    'month': '월',
+    'quarter': '분기',
+    'hours': '시',
+    'days': '일',
+    'weeks': '주',
+    'months': '월',
+    'quarters': '분기',
+    'hr': '시',
+    'dy': '일',
+    'wk': '주',
+    'mth': '월',
+    'qtr': '분기',
+    'hrs': '시',
+    'dys': '일',
+    'wks': '주',
+    'mths': '월',
+    'qtrs': '분기',
+    'res': '이름',
+    'dur': '기간',
+    'comp': '% ',
+    'completion': '완료',
+    'startdate': '시작일자',
+    'planstartdate': '계획 시작일자',
+    'enddate': '종료일자',
+    'planenddate': '계획 종료일자',
+    'cost': '비용',
+    'moreinfo': '더 많은 정보',
+    'nodata': 'No tasks found',
+    'notes': '비고',
+    'january': '1월',
+    'february': '2월',
+    'march': '3월',
+    'april': '4월',
+    'maylong': '5월',
+    'june': '6월',
+    'july': '7월',
+    'august': '8월',
+    'september': '9월',
+    'october': '10월',
+    'november': '11월',
+    'december': '12월',
+    'jan': '1',
+    'feb': '2',
+    'mar': '3',
+    'apr': '4',
+    'may': '5',
+    'jun': '6',
+    'jul': '7',
+    'aug': '8',
+    'sep': '9',
+    'oct': '10',
+    'nov': '11',
+    'dec': '12',
+    'sunday': '일요일',
+    'monday': '월요일',
+    'tuesday': '화요일',
+    'wednesday': '수요일',
+    'thursday': '목요일',
+    'friday': '금요일',
+    'saturday': '토요일',
+    'sun': '일',
+    'mon': '월',
+    'tue': '화',
+    'wed': '수',
+    'thu': '목',
+    'fri': '금',
+    'sat': '토',
+    'tooltipLoading': '로딩중...'
+};
+exports.ko = ko;
+
+},{}],9:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var date_utils_1 = require("./utils/date_utils");
+var draw_columns_1 = require("./draw_columns");
+exports.includeGetSet = function () {
+    /**
+     * SETTERS
+     */
+    this.setOptions = function (options) {
+        var keys = Object.keys(options);
+        for (var i = 0; i < keys.length; i++) {
+            var key = keys[i];
+            var val = options[key];
+            if (key === 'vResources' || key === 'vColumnOrder') {
+                // ev = `this.set${key.substr(1)}(val)`;
+                this['set' + key.substr(1)](val);
+            }
+            else if (val instanceof Array) {
+                // ev = `this.set${key.substr(1)}(...val)`;
+                this['set' + key.substr(1)].apply(this, val);
+            }
+            else {
+                // ev = `this.set${key.substr(1)}(val)`;
+                this['set' + key.substr(1)](val);
+            }
+        }
+    };
+    this.setUseFade = function (pVal) { this.vUseFade = pVal; };
+    this.setUseMove = function (pVal) { this.vUseMove = pVal; };
+    this.setUseRowHlt = function (pVal) { this.vUseRowHlt = pVal; };
+    this.setUseToolTip = function (pVal) { this.vUseToolTip = pVal; };
+    this.setUseSort = function (pVal) { this.vUseSort = pVal; };
+    this.setUseSingleCell = function (pVal) { this.vUseSingleCell = pVal * 1; };
+    this.setFormatArr = function () {
+        var vValidFormats = 'hour day week month quarter';
+        this.vFormatArr = new Array();
+        for (var i = 0, j = 0; i < arguments.length; i++) {
+            if (vValidFormats.indexOf(arguments[i].toLowerCase()) != -1 && arguments[i].length > 1) {
+                this.vFormatArr[j++] = arguments[i].toLowerCase();
+                var vRegExp = new RegExp('(?:^|\s)' + arguments[i] + '(?!\S)', 'g');
+                vValidFormats = vValidFormats.replace(vRegExp, '');
+            }
+        }
+    };
+    this.setShowRes = function (pVal) { this.vShowRes = pVal; };
+    this.setShowDur = function (pVal) { this.vShowDur = pVal; };
+    this.setShowComp = function (pVal) { this.vShowComp = pVal; };
+    this.setShowStartDate = function (pVal) { this.vShowStartDate = pVal; };
+    this.setShowEndDate = function (pVal) { this.vShowEndDate = pVal; };
+    this.setShowPlanStartDate = function (pVal) { this.vShowPlanStartDate = pVal; };
+    this.setShowPlanEndDate = function (pVal) { this.vShowPlanEndDate = pVal; };
+    this.setShowCost = function (pVal) { this.vShowCost = pVal; };
+    this.setShowAddEntries = function (pVal) { this.vShowAddEntries = pVal; };
+    this.setShowTaskInfoRes = function (pVal) { this.vShowTaskInfoRes = pVal; };
+    this.setShowTaskInfoDur = function (pVal) { this.vShowTaskInfoDur = pVal; };
+    this.setShowTaskInfoComp = function (pVal) { this.vShowTaskInfoComp = pVal; };
+    this.setShowTaskInfoStartDate = function (pVal) { this.vShowTaskInfoStartDate = pVal; };
+    this.setShowTaskInfoEndDate = function (pVal) { this.vShowTaskInfoEndDate = pVal; };
+    this.setShowTaskInfoNotes = function (pVal) { this.vShowTaskInfoNotes = pVal; };
+    this.setShowTaskInfoLink = function (pVal) { this.vShowTaskInfoLink = pVal; };
+    this.setShowEndWeekDate = function (pVal) { this.vShowEndWeekDate = pVal; };
+    this.setShowWeekends = function (pVal) { this.vShowWeekends = pVal; };
+    this.setShowSelector = function () {
+        var vValidSelectors = 'top bottom';
+        this.vShowSelector = new Array();
+        for (var i = 0, j = 0; i < arguments.length; i++) {
+            if (vValidSelectors.indexOf(arguments[i].toLowerCase()) != -1 && arguments[i].length > 1) {
+                this.vShowSelector[j++] = arguments[i].toLowerCase();
+                var vRegExp = new RegExp('(?:^|\s)' + arguments[i] + '(?!\S)', 'g');
+                vValidSelectors = vValidSelectors.replace(vRegExp, '');
+            }
+        }
+    };
+    this.setShowDeps = function (pVal) { this.vShowDeps = pVal; };
+    this.setDateInputFormat = function (pVal) { this.vDateInputFormat = pVal; };
+    this.setDateTaskTableDisplayFormat = function (pVal) { this.vDateTaskTableDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setDateTaskDisplayFormat = function (pVal) { this.vDateTaskDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setHourMajorDateDisplayFormat = function (pVal) { this.vHourMajorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setHourMinorDateDisplayFormat = function (pVal) { this.vHourMinorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setDayMajorDateDisplayFormat = function (pVal) { this.vDayMajorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setDayMinorDateDisplayFormat = function (pVal) { this.vDayMinorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setWeekMajorDateDisplayFormat = function (pVal) { this.vWeekMajorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setWeekMinorDateDisplayFormat = function (pVal) { this.vWeekMinorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setMonthMajorDateDisplayFormat = function (pVal) { this.vMonthMajorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setMonthMinorDateDisplayFormat = function (pVal) { this.vMonthMinorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setQuarterMajorDateDisplayFormat = function (pVal) { this.vQuarterMajorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setQuarterMinorDateDisplayFormat = function (pVal) { this.vQuarterMinorDateDisplayFormat = date_utils_1.parseDateFormatStr(pVal); };
+    this.setCaptionType = function (pType) { this.vCaptionType = pType; };
+    this.setFormat = function (pFormat) {
+        this.vFormat = pFormat;
+        this.Draw();
+    };
+    this.setWorkingDays = function (workingDays) { this.vWorkingDays = workingDays; };
+    this.setMinGpLen = function (pMinGpLen) { this.vMinGpLen = pMinGpLen; };
+    this.setScrollTo = function (pDate) { this.vScrollTo = pDate; };
+    this.setHourColWidth = function (pWidth) { this.vHourColWidth = pWidth; };
+    this.setDayColWidth = function (pWidth) { this.vDayColWidth = pWidth; };
+    this.setWeekColWidth = function (pWidth) { this.vWeekColWidth = pWidth; };
+    this.setMonthColWidth = function (pWidth) { this.vMonthColWidth = pWidth; };
+    this.setQuarterColWidth = function (pWidth) { this.vQuarterColWidth = pWidth; };
+    this.setRowHeight = function (pHeight) { this.vRowHeight = pHeight; };
+    this.setLang = function (pLang) { if (this.vLangs[pLang])
+        this.vLang = pLang; };
+    this.setChartBody = function (pDiv) { if (typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)
+        this.vChartBody = pDiv; };
+    this.setChartHead = function (pDiv) { if (typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)
+        this.vChartHead = pDiv; };
+    this.setListBody = function (pDiv) { if (typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)
+        this.vListBody = pDiv; };
+    this.setChartTable = function (pTable) { if (typeof HTMLTableElement !== 'function' || pTable instanceof HTMLTableElement)
+        this.vChartTable = pTable; };
+    this.setLines = function (pDiv) { if (typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)
+        this.vLines = pDiv; };
+    this.setLineOptions = function (lineOptions) { this.vLineOptions = lineOptions; };
+    this.setTimer = function (pVal) { this.vTimer = pVal * 1; };
+    this.setTooltipDelay = function (pVal) { this.vTooltipDelay = pVal * 1; };
+    this.setTooltipTemplate = function (pVal) { this.vTooltipTemplate = pVal; };
+    this.setMinDate = function (pVal) { this.vMinDate = pVal; };
+    this.setMaxDate = function (pVal) { this.vMaxDate = pVal; };
+    this.addLang = function (pLang, pVals) {
+        if (!this.vLangs[pLang]) {
+            this.vLangs[pLang] = new Object();
+            for (var vKey in this.vLangs['en'])
+                this.vLangs[pLang][vKey] = (pVals[vKey]) ? document.createTextNode(pVals[vKey]).data : this.vLangs['en'][vKey];
+        }
+    };
+    this.setTotalHeight = function (pVal) { this.vTotalHeight = pVal; };
+    // EVENTS
+    this.setEvents = function (pEvents) { this.vEvents = pEvents; };
+    this.setEventsChange = function (pEventsChange) { this.vEventsChange = pEventsChange; };
+    this.setEventClickRow = function (fn) { this.vEventClickRow = fn; };
+    this.setEventClickCollapse = function (fn) { this.vEventClickCollapse = fn; };
+    this.setResources = function (resources) { this.vResources = resources; };
+    this.setAdditionalHeaders = function (headers) { this.vAdditionalHeaders = headers; };
+    this.setColumnOrder = function (order) { this.vColumnOrder = order; };
+    this.setEditable = function (editable) { this.vEditable = editable; };
+    this.setDebug = function (debug) { this.vDebug = debug; };
+    /**
+     * GETTERS
+     */
+    this.getDivId = function () { return this.vDivId; };
+    this.getUseFade = function () { return this.vUseFade; };
+    this.getUseMove = function () { return this.vUseMove; };
+    this.getUseRowHlt = function () { return this.vUseRowHlt; };
+    this.getUseToolTip = function () { return this.vUseToolTip; };
+    this.getUseSort = function () { return this.vUseSort; };
+    this.getUseSingleCell = function () { return this.vUseSingleCell; };
+    this.getFormatArr = function () { return this.vFormatArr; };
+    this.getShowRes = function () { return this.vShowRes; };
+    this.getShowDur = function () { return this.vShowDur; };
+    this.getShowComp = function () { return this.vShowComp; };
+    this.getShowStartDate = function () { return this.vShowStartDate; };
+    this.getShowEndDate = function () { return this.vShowEndDate; };
+    this.getShowPlanStartDate = function () { return this.vShowPlanStartDate; };
+    this.getShowPlanEndDate = function () { return this.vShowPlanEndDate; };
+    this.getShowCost = function () { return this.vShowCost; };
+    this.getShowAddEntries = function () { return this.vShowAddEntries; };
+    this.getShowTaskInfoRes = function () { return this.vShowTaskInfoRes; };
+    this.getShowTaskInfoDur = function () { return this.vShowTaskInfoDur; };
+    this.getShowTaskInfoComp = function () { return this.vShowTaskInfoComp; };
+    this.getShowTaskInfoStartDate = function () { return this.vShowTaskInfoStartDate; };
+    this.getShowTaskInfoEndDate = function () { return this.vShowTaskInfoEndDate; };
+    this.getShowTaskInfoNotes = function () { return this.vShowTaskInfoNotes; };
+    this.getShowTaskInfoLink = function () { return this.vShowTaskInfoLink; };
+    this.getShowEndWeekDate = function () { return this.vShowEndWeekDate; };
+    this.getShowWeekends = function () { return this.vShowWeekends; };
+    this.getShowSelector = function () { return this.vShowSelector; };
+    this.getShowDeps = function () { return this.vShowDeps; };
+    this.getDateInputFormat = function () { return this.vDateInputFormat; };
+    this.getDateTaskTableDisplayFormat = function () { return this.vDateTaskTableDisplayFormat; };
+    this.getDateTaskDisplayFormat = function () { return this.vDateTaskDisplayFormat; };
+    this.getHourMajorDateDisplayFormat = function () { return this.vHourMajorDateDisplayFormat; };
+    this.getHourMinorDateDisplayFormat = function () { return this.vHourMinorDateDisplayFormat; };
+    this.getDayMajorDateDisplayFormat = function () { return this.vDayMajorDateDisplayFormat; };
+    this.getDayMinorDateDisplayFormat = function () { return this.vDayMinorDateDisplayFormat; };
+    this.getWeekMajorDateDisplayFormat = function () { return this.vWeekMajorDateDisplayFormat; };
+    this.getWeekMinorDateDisplayFormat = function () { return this.vWeekMinorDateDisplayFormat; };
+    this.getMonthMajorDateDisplayFormat = function () { return this.vMonthMajorDateDisplayFormat; };
+    this.getMonthMinorDateDisplayFormat = function () { return this.vMonthMinorDateDisplayFormat; };
+    this.getQuarterMajorDateDisplayFormat = function () { return this.vQuarterMajorDateDisplayFormat; };
+    this.getQuarterMinorDateDisplayFormat = function () { return this.vQuarterMinorDateDisplayFormat; };
+    this.getCaptionType = function () { return this.vCaptionType; };
+    this.getMinGpLen = function () { return this.vMinGpLen; };
+    this.getScrollTo = function () { return this.vScrollTo; };
+    this.getHourColWidth = function () { return this.vHourColWidth; };
+    this.getDayColWidth = function () { return this.vDayColWidth; };
+    this.getWeekColWidth = function () { return this.vWeekColWidth; };
+    this.getMonthColWidth = function () { return this.vMonthColWidth; };
+    this.getQuarterColWidth = function () { return this.vQuarterColWidth; };
+    this.getRowHeight = function () { return this.vRowHeight; };
+    this.getChartBody = function () { return this.vChartBody; };
+    this.getChartHead = function () { return this.vChartHead; };
+    this.getListBody = function () { return this.vListBody; };
+    this.getChartTable = function () { return this.vChartTable; };
+    this.getLines = function () { return this.vLines; };
+    this.getTimer = function () { return this.vTimer; };
+    this.getMinDate = function () { return this.vMinDate; };
+    this.getMaxDate = function () { return this.vMaxDate; };
+    this.getTooltipDelay = function () { return this.vTooltipDelay; };
+    this.getList = function () { return this.vTaskList; };
+    //EVENTS
+    this.getEventsClickCell = function () { return this.vEvents; };
+    this.getEventsChange = function () { return this.vEventsChange; };
+    this.getEventClickRow = function () { return this.vEventClickRow; };
+    this.getEventClickCollapse = function () { return this.vEventClickCollapse; };
+    this.getResources = function () { return this.vResources; };
+    this.getAdditionalHeaders = function () { return this.vAdditionalHeaders; };
+    this.getColumnOrder = function () { return this.vColumnOrder || draw_columns_1.COLUMN_ORDER; };
 };
 
+},{"./draw_columns":3,"./utils/date_utils":11}],10:[function(require,module,exports){
+"use strict";
+var __assign = (this && this.__assign) || function () {
+    __assign = Object.assign || function(t) {
+        for (var s, i = 1, n = arguments.length; i < n; i++) {
+            s = arguments[i];
+            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
+                t[p] = s[p];
+        }
+        return t;
+    };
+    return __assign.apply(this, arguments);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var general_utils_1 = require("./utils/general_utils");
+var draw_utils_1 = require("./utils/draw_utils");
+var date_utils_1 = require("./utils/date_utils");
 // function to open window to display task link
-JSGantt.taskLink=function(pRef,pWidth,pHeight)
-{
-
-	if(pWidth) var vWidth =pWidth; else vWidth =400;
-	if(pHeight) var vHeight=pHeight; else vHeight=400;
-
-	var OpenWindow=window.open(pRef, 'newwin', 'height='+vHeight+',width='+vWidth);
+exports.taskLink = function (pRef, pWidth, pHeight) {
+    var vWidth, vHeight;
+    if (pWidth)
+        vWidth = pWidth;
+    else
+        vWidth = 400;
+    if (pHeight)
+        vHeight = pHeight;
+    else
+        vHeight = 400;
+    window.open(pRef, 'newwin', 'height=' + vHeight + ',width=' + vWidth); // let OpenWindow = 
 };
-
-JSGantt.parseDateStr=function(pDateStr,pFormatStr)
-{
-	var vDate=new Date();
-	var vDateParts=pDateStr.split(/[^0-9]/);
-	if (pDateStr.length>=10 && vDateParts.length>=3)
-	{
-		while(vDateParts.length<5)vDateParts.push(0);
-
-		switch(pFormatStr)
-		{
-			case 'mm/dd/yyyy':
-			vDate=new Date(vDateParts[2], vDateParts[0]-1, vDateParts[1], vDateParts[3], vDateParts[4]);
-			break;
-			case 'dd/mm/yyyy':
-			vDate=new Date(vDateParts[2], vDateParts[1]-1, vDateParts[0], vDateParts[3], vDateParts[4]);
-			break;
-			case 'yyyy-mm-dd':
-			vDate=new Date(vDateParts[0], vDateParts[1]-1, vDateParts[2], vDateParts[3], vDateParts[4]);
-			break;
-		}
-	}
-	return(vDate);
+exports.sortTasks = function (pList, pID, pIdx) {
+    if (pList.length < 2) {
+        return pIdx;
+    }
+    var sortIdx = pIdx;
+    var sortArr = new Array();
+    for (var i = 0; i < pList.length; i++) {
+        if (pList[i].getParent() == pID)
+            sortArr.push(pList[i]);
+    }
+    if (sortArr.length > 0) {
+        sortArr.sort(function (a, b) {
+            var i = a.getStart().getTime() - b.getStart().getTime();
+            if (i == 0)
+                i = a.getEnd().getTime() - b.getEnd().getTime();
+            if (i == 0)
+                return a.getID() - b.getID();
+            else
+                return i;
+        });
+    }
+    for (var j = 0; j < sortArr.length; j++) {
+        for (var i = 0; i < pList.length; i++) {
+            if (pList[i].getID() == sortArr[j].getID()) {
+                pList[i].setSortIdx(sortIdx++);
+                sortIdx = exports.sortTasks(pList, pList[i].getID(), sortIdx);
+            }
+        }
+    }
+    return sortIdx;
 };
-
-JSGantt.formatDateStr=function(pDate, pDateFormatArr, pL)
-{
-	var vDateStr='';
-
-	var vYear2Str=pDate.getFullYear().toString().substring(2,4);
-	var vMonthStr=(pDate.getMonth()+1)+'';
-	var vMonthArr=new Array(pL['january'],pL['february'],pL['march'],pL['april'],pL['maylong'],pL['june'],pL['july'],pL['august'],pL['september'],pL['october'],pL['november'],pL['december']);
-	var vDayArr=new Array(pL['sunday'],pL['monday'],pL['tuesday'],pL['wednesday'],pL['thursday'],pL['friday'],pL['saturday']);
-	var vMthArr=new Array(pL['jan'],pL['feb'],pL['mar'],pL['apr'],pL['may'],pL['jun'],pL['jul'],pL['aug'],pL['sep'],pL['oct'],pL['nov'],pL['dec']);
-	var vDyArr=new Array(pL['sun'],pL['mon'],pL['tue'],pL['wed'],pL['thu'],pL['fri'],pL['sat']);
-
-	for (var i=0; i<pDateFormatArr.length; i++)
-	{
-		switch(pDateFormatArr[i])
-		{
-			case 'dd':
-				if (pDate.getDate()<10) vDateStr+='0'; // now fall through
-			case 'd':
-				vDateStr+=pDate.getDate();
-				break;
-			case 'day':
-				vDateStr+=vDyArr[pDate.getDay()];
-				break;
-			case 'DAY':
-				vDateStr+=vDayArr[pDate.getDay()];
-				break;
-			case 'mm':
-				if (vMonthStr<10) vDateStr+='0'; // now fall through
-			case 'm':
-				vDateStr+=vMonthStr;
-				break;
-			case 'mon':
-				vDateStr+=vMthArr[pDate.getMonth()];
-				break;
-			case 'month':
-				vDateStr+=vMonthArr[pDate.getMonth()];
-				break;
-			case 'yyyy':
-				vDateStr+=pDate.getFullYear();
-				break;
-			case 'yy':
-				vDateStr+=vYear2Str;
-				break;
-			case 'qq':
-				vDateStr+='Q'; // now fall through
-			case 'q':
-				vDateStr+=Math.floor(pDate.getMonth()/3)+1;
-				break;
-			case 'hh':
-				if ((((pDate.getHours()%12)==0)?12:pDate.getHours()%12)<10) vDateStr+='0'; // now fall through
-			case 'h':
-				vDateStr+=((pDate.getHours()%12)==0)?12:pDate.getHours()%12;
-				break;
-			case 'HH':
-				if ((pDate.getHours())<10) vDateStr+='0'; // now fall through
-			case 'H':
-				vDateStr+=(pDate.getHours());
-				break;
-			case 'MI':
-				if (pDate.getMinutes()<10) vDateStr+='0'; // now fall through
-			case 'mi':
-				vDateStr+=pDate.getMinutes();
-				break;
-			case 'pm':
-				vDateStr+=((pDate.getHours())<12)?'am':'pm';
-				break;
-			case 'PM':
-				vDateStr+=((pDate.getHours())<12)?'AM':'PM';
-				break;
-			case 'ww':
-				if (JSGantt.getIsoWeek(pDate)<10) vDateStr+='0'; // now fall through
-			case 'w':
-				vDateStr+=JSGantt.getIsoWeek(pDate);
-				break;
-			case 'week':
-				var vWeekNum=JSGantt.getIsoWeek(pDate);
-				var vYear=pDate.getFullYear();
-				var vDayOfWeek=(pDate.getDay()==0)? 7 : pDate.getDay();
-				if (vWeekNum>=52 && vMonthStr==1) vYear--;
-				if (vWeekNum==1 && vMonthStr==12) vYear++;
-				if (vWeekNum<10) vWeekNum='0'+vWeekNum;
-
-				vDateStr+=vYear+'-W'+vWeekNum+'-'+vDayOfWeek;
-				break;
-			default:
-				if (pL[pDateFormatArr[i].toLowerCase()]) vDateStr+=pL[pDateFormatArr[i].toLowerCase()];
-				else vDateStr+=pDateFormatArr[i];
-				break;
-		}
-	}
-	return vDateStr;
+exports.TaskItemObject = function (object) {
+    var pDataObject = __assign({}, object);
+    general_utils_1.internalProperties.forEach(function (property) {
+        delete pDataObject[property];
+    });
+    return new exports.TaskItem(object.pID, object.pName, object.pStart, object.pEnd, object.pClass, object.pLink, object.pMile, object.pRes, object.pComp, object.pGroup, object.pParent, object.pOpen, object.pDepend, object.pCaption, object.pNotes, object.pGantt, object.pCost, object.pPlanStart, object.pPlanEnd, object.pDuration, object.pBarText, object);
 };
-
-JSGantt.parseDateFormatStr=function(pFormatStr)
-{
-	var vDateStr='';
-	var vComponantStr='';
-	var vCurrChar='';
-	var vSeparators=new RegExp('[\/\\ -.,\'":]');
-	var vDateFormatArray=new Array();
-
-	for (var i=0; i<pFormatStr.length; i++)
-	{
-		vCurrChar=pFormatStr.charAt(i);
-		if ((vCurrChar.match(vSeparators)) || (i+1==pFormatStr.length)) // separator or end of string
-		{
-			if ((i+1==pFormatStr.length) && (!(vCurrChar.match(vSeparators)))) // at end of string add any non-separator chars to the current component
-			{
-				vComponantStr+=vCurrChar;
-			}
-			vDateFormatArray.push(vComponantStr);
-			if (vCurrChar.match(vSeparators)) vDateFormatArray.push(vCurrChar);
-			vComponantStr='';
-		}
-		else
-		{
-			vComponantStr+=vCurrChar;
-		}
-
-	}
-	return vDateFormatArray;
+exports.TaskItem = function (pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGantt, pCost, pPlanStart, pPlanEnd, pDuration, pBarText, pDataObject) {
+    if (pCost === void 0) { pCost = null; }
+    if (pPlanStart === void 0) { pPlanStart = null; }
+    if (pPlanEnd === void 0) { pPlanEnd = null; }
+    if (pDuration === void 0) { pDuration = null; }
+    if (pBarText === void 0) { pBarText = null; }
+    if (pDataObject === void 0) { pDataObject = null; }
+    var vGantt = pGantt ? pGantt : this;
+    var _id = document.createTextNode(pID).data;
+    var vID = general_utils_1.hashKey(document.createTextNode(pID).data);
+    var vName = document.createTextNode(pName).data;
+    var vStart = null;
+    var vEnd = null;
+    var vPlanStart = null;
+    var vPlanEnd = null;
+    var vGroupMinStart = null;
+    var vGroupMinEnd = null;
+    var vGroupMinPlanStart = null;
+    var vGroupMinPlanEnd = null;
+    var vClass = document.createTextNode(pClass).data;
+    var vLink = document.createTextNode(pLink).data;
+    var vMile = parseInt(document.createTextNode(pMile).data);
+    var vRes = document.createTextNode(pRes).data;
+    var vComp = parseFloat(document.createTextNode(pComp).data);
+    var vCost = parseInt(document.createTextNode(pCost).data);
+    var vGroup = parseInt(document.createTextNode(pGroup).data);
+    var vDataObject = pDataObject;
+    var vCompVal;
+    var parent = document.createTextNode(pParent).data;
+    if (parent && parent !== '0') {
+        parent = general_utils_1.hashKey(parent).toString();
+    }
+    var vParent = parent;
+    var vOpen = (vGroup == 2) ? 1 : parseInt(document.createTextNode(pOpen).data);
+    var vDepend = new Array();
+    var vDependType = new Array();
+    var vCaption = document.createTextNode(pCaption).data;
+    var vDuration = pDuration || '';
+    var vBarText = pBarText || '';
+    var vLevel = 0;
+    var vNumKid = 0;
+    var vWeight = 0;
+    var vVisible = 1;
+    var vSortIdx = 0;
+    var vToDelete = false;
+    var x1, y1, x2, y2;
+    var vNotes;
+    var vParItem = null;
+    var vCellDiv = null;
+    var vBarDiv = null;
+    var vTaskDiv = null;
+    var vPlanTaskDiv = null;
+    var vListChildRow = null;
+    var vChildRow = null;
+    var vGroupSpan = null;
+    vNotes = document.createElement('span');
+    vNotes.className = 'gTaskNotes';
+    if (pNotes != null) {
+        vNotes.innerHTML = pNotes;
+        general_utils_1.stripUnwanted(vNotes);
+    }
+    if (pStart != null && pStart != '') {
+        vStart = (pStart instanceof Date) ? pStart : date_utils_1.parseDateStr(document.createTextNode(pStart).data, vGantt.getDateInputFormat());
+        vGroupMinStart = vStart;
+    }
+    if (pEnd != null && pEnd != '') {
+        vEnd = (pEnd instanceof Date) ? pEnd : date_utils_1.parseDateStr(document.createTextNode(pEnd).data, vGantt.getDateInputFormat());
+        vGroupMinEnd = vEnd;
+    }
+    if (pPlanStart != null && pPlanStart != '') {
+        vPlanStart = (pPlanStart instanceof Date) ? pPlanStart : date_utils_1.parseDateStr(document.createTextNode(pPlanStart).data, vGantt.getDateInputFormat());
+        vGroupMinPlanStart = vPlanStart;
+    }
+    if (pPlanEnd != null && pPlanEnd != '') {
+        vPlanEnd = (pPlanEnd instanceof Date) ? pPlanEnd : date_utils_1.parseDateStr(document.createTextNode(pPlanEnd).data, vGantt.getDateInputFormat());
+        vGroupMinPlanEnd = vPlanEnd;
+    }
+    if (pDepend != null) {
+        var vDependStr = pDepend + '';
+        var vDepList = vDependStr.split(',');
+        var n = vDepList.length;
+        for (var k = 0; k < n; k++) {
+            if (vDepList[k].toUpperCase().endsWith('SS')) {
+                vDepend[k] = vDepList[k].substring(0, vDepList[k].length - 2);
+                vDependType[k] = 'SS';
+            }
+            else if (vDepList[k].toUpperCase().endsWith('FF')) {
+                vDepend[k] = vDepList[k].substring(0, vDepList[k].length - 2);
+                vDependType[k] = 'FF';
+            }
+            else if (vDepList[k].toUpperCase().endsWith('SF')) {
+                vDepend[k] = vDepList[k].substring(0, vDepList[k].length - 2);
+                vDependType[k] = 'SF';
+            }
+            else if (vDepList[k].toUpperCase().endsWith('FS')) {
+                vDepend[k] = vDepList[k].substring(0, vDepList[k].length - 2);
+                vDependType[k] = 'FS';
+            }
+            else {
+                vDepend[k] = vDepList[k];
+                vDependType[k] = 'FS';
+            }
+            if (vDepend[k]) {
+                vDepend[k] = general_utils_1.hashKey(vDepend[k]).toString();
+            }
+        }
+    }
+    this.getID = function () { return vID; };
+    this.getOriginalID = function () { return _id; };
+    this.getGantt = function () { return vGantt; };
+    this.getName = function () { return vName; };
+    this.getStart = function () {
+        if (vStart)
+            return vStart;
+        else if (vPlanStart)
+            return vPlanStart;
+        else
+            return new Date();
+    };
+    this.getStartVar = function () {
+        return vStart;
+    };
+    this.getEnd = function () {
+        if (vEnd)
+            return vEnd;
+        else if (vPlanEnd)
+            return vPlanEnd;
+        else if (vStart && vDuration) {
+            var date = new Date(vStart);
+            var vUnits = vDuration.split(' ');
+            var value = parseInt(vUnits[0]);
+            switch (vUnits[1]) {
+                case 'hour':
+                    date.setMinutes(date.getMinutes() + (value * 60));
+                    break;
+                case 'day':
+                    date.setMinutes(date.getMinutes() + (value * 60 * 24));
+                    break;
+                case 'week':
+                    date.setMinutes(date.getMinutes() + (value * 60 * 24 * 7));
+                    break;
+                case 'month':
+                    date.setMonth(date.getMonth() + (value));
+                    break;
+                case 'quarter':
+                    date.setMonth(date.getMonth() + (value * 3));
+                    break;
+            }
+            return date;
+        }
+        else
+            return new Date();
+    };
+    this.getEndVar = function () {
+        return vEnd;
+    };
+    this.getPlanStart = function () { return vPlanStart ? vPlanStart : vStart; };
+    this.getPlanEnd = function () { return vPlanEnd ? vPlanEnd : vEnd; };
+    this.getCost = function () { return vCost; };
+    this.getGroupMinStart = function () { return vGroupMinStart; };
+    this.getGroupMinEnd = function () { return vGroupMinEnd; };
+    this.getGroupMinPlanStart = function () { return vGroupMinPlanStart; };
+    this.getGroupMinPlanEnd = function () { return vGroupMinPlanEnd; };
+    this.getClass = function () { return vClass; };
+    this.getLink = function () { return vLink; };
+    this.getMile = function () { return vMile; };
+    this.getDepend = function () {
+        if (vDepend)
+            return vDepend;
+        else
+            return null;
+    };
+    this.getDataObject = function () { return vDataObject; };
+    this.getDepType = function () { if (vDependType)
+        return vDependType;
+    else
+        return null; };
+    this.getCaption = function () { if (vCaption)
+        return vCaption;
+    else
+        return ''; };
+    this.getResource = function () { if (vRes)
+        return vRes;
+    else
+        return '\u00A0'; };
+    this.getCompVal = function () { if (vComp)
+        return vComp;
+    else if (vCompVal)
+        return vCompVal;
+    else
+        return 0; };
+    this.getCompStr = function () { if (vComp)
+        return vComp + '%';
+    else if (vCompVal)
+        return vCompVal + '%';
+    else
+        return ''; };
+    this.getCompRestStr = function () { if (vComp)
+        return (100 - vComp) + '%';
+    else if (vCompVal)
+        return (100 - vCompVal) + '%';
+    else
+        return ''; };
+    this.getNotes = function () { return vNotes; };
+    this.getSortIdx = function () { return vSortIdx; };
+    this.getToDelete = function () { return vToDelete; };
+    this.getDuration = function (pFormat, pLang) {
+        if (vMile) {
+            vDuration = '-';
+        }
+        else if (!vEnd && !vStart && vPlanStart && vPlanEnd) {
+            return calculateVDuration(pFormat, pLang, this.getPlanStart(), this.getPlanEnd());
+        }
+        else if (!vEnd && vDuration) {
+            return vDuration;
+        }
+        else {
+            vDuration = calculateVDuration(pFormat, pLang, this.getStart(), this.getEnd());
+        }
+        return vDuration;
+    };
+    function calculateVDuration(pFormat, pLang, start, end) {
+        var vDuration;
+        var vUnits = null;
+        switch (pFormat) {
+            case 'week':
+                vUnits = 'day';
+                break;
+            case 'month':
+                vUnits = 'week';
+                break;
+            case 'quarter':
+                vUnits = 'month';
+                break;
+            default:
+                vUnits = pFormat;
+                break;
+        }
+        // let vTaskEnd = new Date(this.getEnd().getTime());
+        // if ((vTaskEnd.getTime() - (vTaskEnd.getTimezoneOffset() * 60000)) % (86400000) == 0) {
+        //   vTaskEnd = new Date(vTaskEnd.getFullYear(), vTaskEnd.getMonth(), vTaskEnd.getDate() + 1, vTaskEnd.getHours(), vTaskEnd.getMinutes(), vTaskEnd.getSeconds());
+        // }
+        // let tmpPer = (getOffset(this.getStart(), vTaskEnd, 999, vUnits)) / 1000;
+        var hours = (end.getTime() - start.getTime()) / 1000 / 60 / 60;
+        var tmpPer;
+        switch (vUnits) {
+            case 'hour':
+                tmpPer = Math.round(hours);
+                vDuration = tmpPer + ' ' + ((tmpPer != 1) ? pLang['hrs'] : pLang['hr']);
+                break;
+            case 'day':
+                tmpPer = Math.round(hours / 24);
+                vDuration = tmpPer + ' ' + ((tmpPer != 1) ? pLang['dys'] : pLang['dy']);
+                break;
+            case 'week':
+                tmpPer = Math.round(hours / 24 / 7);
+                vDuration = tmpPer + ' ' + ((tmpPer != 1) ? pLang['wks'] : pLang['wk']);
+                break;
+            case 'month':
+                tmpPer = Math.round(hours / 24 / 7 / 30);
+                vDuration = tmpPer + ' ' + ((tmpPer != 1) ? pLang['mths'] : pLang['mth']);
+                break;
+            case 'quarter':
+                tmpPer = Math.round(hours / 24 / 7 / 30 / 3);
+                vDuration = tmpPer + ' ' + ((tmpPer != 1) ? pLang['qtrs'] : pLang['qtr']);
+                break;
+        }
+        return vDuration;
+    }
+    this.getBarText = function () { return vBarText; };
+    this.getParent = function () { return vParent; };
+    this.getGroup = function () { return vGroup; };
+    this.getOpen = function () { return vOpen; };
+    this.getLevel = function () { return vLevel; };
+    this.getNumKids = function () { return vNumKid; };
+    this.getWeight = function () { return vWeight; };
+    this.getStartX = function () { return x1; };
+    this.getStartY = function () { return y1; };
+    this.getEndX = function () { return x2; };
+    this.getEndY = function () { return y2; };
+    this.getVisible = function () { return vVisible; };
+    this.getParItem = function () { return vParItem; };
+    this.getCellDiv = function () { return vCellDiv; };
+    this.getBarDiv = function () { return vBarDiv; };
+    this.getTaskDiv = function () { return vTaskDiv; };
+    this.getPlanTaskDiv = function () { return vPlanTaskDiv; };
+    this.getChildRow = function () { return vChildRow; };
+    this.getListChildRow = function () { return vListChildRow; };
+    this.getGroupSpan = function () { return vGroupSpan; };
+    this.setName = function (pName) { vName = pName; };
+    this.setNotes = function (pNotes) { vNotes = pNotes; };
+    this.setClass = function (pClass) { vClass = pClass; };
+    this.setCost = function (pCost) { vCost = pCost; };
+    this.setResource = function (pRes) { vRes = pRes; };
+    this.setDuration = function (pDuration) { vDuration = pDuration; };
+    this.setDataObject = function (pDataObject) { vDataObject = pDataObject; };
+    this.setStart = function (pStart) {
+        if (pStart instanceof Date) {
+            vStart = pStart;
+        }
+        else {
+            var temp = new Date(pStart);
+            if (temp instanceof Date && !isNaN(temp.valueOf())) {
+                vStart = temp;
+            }
+        }
+    };
+    this.setEnd = function (pEnd) {
+        if (pEnd instanceof Date) {
+            vEnd = pEnd;
+        }
+        else {
+            var temp = new Date(pEnd);
+            if (temp instanceof Date && !isNaN(temp.valueOf())) {
+                vEnd = temp;
+            }
+        }
+    };
+    this.setPlanStart = function (pPlanStart) {
+        if (pPlanStart instanceof Date)
+            vPlanStart = pPlanStart;
+        else
+            vPlanStart = new Date(pPlanStart);
+    };
+    this.setPlanEnd = function (pPlanEnd) {
+        if (pPlanEnd instanceof Date)
+            vPlanEnd = pPlanEnd;
+        else
+            vPlanEnd = new Date(pPlanEnd);
+    };
+    this.setGroupMinStart = function (pStart) { if (pStart instanceof Date)
+        vGroupMinStart = pStart; };
+    this.setGroupMinEnd = function (pEnd) { if (pEnd instanceof Date)
+        vGroupMinEnd = pEnd; };
+    this.setLevel = function (pLevel) { vLevel = parseInt(document.createTextNode(pLevel).data); };
+    this.setNumKid = function (pNumKid) { vNumKid = parseInt(document.createTextNode(pNumKid).data); };
+    this.setWeight = function (pWeight) { vWeight = parseInt(document.createTextNode(pWeight).data); };
+    this.setCompVal = function (pCompVal) { vCompVal = parseFloat(document.createTextNode(pCompVal).data); };
+    this.setComp = function (pComp) {
+        vComp = parseInt(document.createTextNode(pComp).data);
+    };
+    this.setStartX = function (pX) { x1 = parseInt(document.createTextNode(pX).data); };
+    this.setStartY = function (pY) { y1 = parseInt(document.createTextNode(pY).data); };
+    this.setEndX = function (pX) { x2 = parseInt(document.createTextNode(pX).data); };
+    this.setEndY = function (pY) { y2 = parseInt(document.createTextNode(pY).data); };
+    this.setOpen = function (pOpen) { vOpen = parseInt(document.createTextNode(pOpen).data); };
+    this.setVisible = function (pVisible) { vVisible = parseInt(document.createTextNode(pVisible).data); };
+    this.setSortIdx = function (pSortIdx) { vSortIdx = parseInt(document.createTextNode(pSortIdx).data); };
+    this.setToDelete = function (pToDelete) { if (pToDelete)
+        vToDelete = true;
+    else
+        vToDelete = false; };
+    this.setParItem = function (pParItem) { if (pParItem)
+        vParItem = pParItem; };
+    this.setCellDiv = function (pCellDiv) { if (typeof HTMLDivElement !== 'function' || pCellDiv instanceof HTMLDivElement)
+        vCellDiv = pCellDiv; }; //"typeof HTMLDivElement !== 'function'" to play nice with ie6 and 7
+    this.setGroup = function (pGroup) {
+        if (pGroup === true || pGroup === 'true') {
+            vGroup = 1;
+        }
+        else if (pGroup === false || pGroup === 'false') {
+            vGroup = 0;
+        }
+        else {
+            vGroup = parseInt(document.createTextNode(pGroup).data);
+        }
+    };
+    this.setBarText = function (pBarText) { if (pBarText)
+        vBarText = pBarText; };
+    this.setBarDiv = function (pDiv) { if (typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)
+        vBarDiv = pDiv; };
+    this.setTaskDiv = function (pDiv) { if (typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)
+        vTaskDiv = pDiv; };
+    this.setPlanTaskDiv = function (pDiv) { if (typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)
+        vPlanTaskDiv = pDiv; };
+    this.setChildRow = function (pRow) { if (typeof HTMLTableRowElement !== 'function' || pRow instanceof HTMLTableRowElement)
+        vChildRow = pRow; };
+    this.setListChildRow = function (pRow) { if (typeof HTMLTableRowElement !== 'function' || pRow instanceof HTMLTableRowElement)
+        vListChildRow = pRow; };
+    this.setGroupSpan = function (pSpan) { if (typeof HTMLSpanElement !== 'function' || pSpan instanceof HTMLSpanElement)
+        vGroupSpan = pSpan; };
+    this.getAllData = function () {
+        return {
+            pID: vID,
+            pName: vName,
+            pStart: vStart,
+            pEnd: vEnd,
+            pPlanStart: vPlanStart,
+            pPlanEnd: vPlanEnd,
+            pGroupMinStart: vGroupMinStart,
+            pGroupMinEnd: vGroupMinEnd,
+            pClass: vClass,
+            pLink: vLink,
+            pMile: vMile,
+            pRes: vRes,
+            pComp: vComp,
+            pCost: vCost,
+            pGroup: vGroup,
+            pDataObjec: vDataObject
+        };
+    };
 };
-
-JSGantt.parseXML=function(pFile,pGanttVar)
-{
-	if (window.XMLHttpRequest) {
-		var xhttp=new XMLHttpRequest();
-	} else {	// IE 5/6
-		xhttp=new ActiveXObject('Microsoft.XMLHTTP');
-	}
-
-	xhttp.open('GET', pFile, false);
-	xhttp.send(null);
-	var xmlDoc=xhttp.responseXML;
-
-	JSGantt.AddXMLTask(pGanttVar, xmlDoc);
+/**
+ * @param pTask
+ * @param templateStrOrFn template string or function(task). In any case parameters in template string are substituted.
+ *        If string - just a static template.
+ *        If function(task): string - per task template. Can return null|undefined to fallback to default template.
+ *        If function(task): Promise<string>) - async per task template. Tooltip will show 'Loading...' if promise is not yet complete.
+ *          Otherwise returned template will be handled in the same manner as in other cases.
+ */
+exports.createTaskInfo = function (pTask, templateStrOrFn) {
+    var _this = this;
+    if (templateStrOrFn === void 0) { templateStrOrFn = null; }
+    var vTmpDiv;
+    var vTaskInfoBox = document.createDocumentFragment();
+    var vTaskInfo = draw_utils_1.newNode(vTaskInfoBox, 'div', null, 'gTaskInfo');
+    var setupTemplate = function (template) {
+        vTaskInfo.innerHTML = "";
+        if (template) {
+            var allData_1 = pTask.getAllData();
+            general_utils_1.internalProperties.forEach(function (key) {
+                var lang;
+                if (general_utils_1.internalPropertiesLang[key]) {
+                    lang = _this.vLangs[_this.vLang][general_utils_1.internalPropertiesLang[key]];
+                }
+                if (!lang) {
+                    lang = key;
+                }
+                var val = allData_1[key];
+                template = template.replace("{{" + key + "}}", val);
+                if (lang) {
+                    template = template.replace("{{Lang:" + key + "}}", lang);
+                }
+                else {
+                    template = template.replace("{{Lang:" + key + "}}", key);
+                }
+            });
+            draw_utils_1.newNode(vTaskInfo, 'span', null, 'gTtTemplate', template);
+        }
+        else {
+            draw_utils_1.newNode(vTaskInfo, 'span', null, 'gTtTitle', pTask.getName());
+            if (_this.vShowTaskInfoStartDate == 1) {
+                vTmpDiv = draw_utils_1.newNode(vTaskInfo, 'div', null, 'gTILine gTIsd');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskLabel', _this.vLangs[_this.vLang]['startdate'] + ': ');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskText', date_utils_1.formatDateStr(pTask.getStart(), _this.vDateTaskDisplayFormat, _this.vLangs[_this.vLang]));
+            }
+            if (_this.vShowTaskInfoEndDate == 1) {
+                vTmpDiv = draw_utils_1.newNode(vTaskInfo, 'div', null, 'gTILine gTIed');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskLabel', _this.vLangs[_this.vLang]['enddate'] + ': ');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskText', date_utils_1.formatDateStr(pTask.getEnd(), _this.vDateTaskDisplayFormat, _this.vLangs[_this.vLang]));
+            }
+            if (_this.vShowTaskInfoDur == 1 && !pTask.getMile()) {
+                vTmpDiv = draw_utils_1.newNode(vTaskInfo, 'div', null, 'gTILine gTId');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskLabel', _this.vLangs[_this.vLang]['duration'] + ': ');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskText', pTask.getDuration(_this.vFormat, _this.vLangs[_this.vLang]));
+            }
+            if (_this.vShowTaskInfoComp == 1) {
+                vTmpDiv = draw_utils_1.newNode(vTaskInfo, 'div', null, 'gTILine gTIc');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskLabel', _this.vLangs[_this.vLang]['completion'] + ': ');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskText', pTask.getCompStr());
+            }
+            if (_this.vShowTaskInfoRes == 1) {
+                vTmpDiv = draw_utils_1.newNode(vTaskInfo, 'div', null, 'gTILine gTIr');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskLabel', _this.vLangs[_this.vLang]['resource'] + ': ');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskText', pTask.getResource());
+            }
+            if (_this.vShowTaskInfoLink == 1 && pTask.getLink() != '') {
+                vTmpDiv = draw_utils_1.newNode(vTaskInfo, 'div', null, 'gTILine gTIl');
+                var vTmpNode = draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskLabel');
+                vTmpNode = draw_utils_1.newNode(vTmpNode, 'a', null, 'gTaskText', _this.vLangs[_this.vLang]['moreinfo']);
+                vTmpNode.setAttribute('href', pTask.getLink());
+            }
+            if (_this.vShowTaskInfoNotes == 1) {
+                vTmpDiv = draw_utils_1.newNode(vTaskInfo, 'div', null, 'gTILine gTIn');
+                draw_utils_1.newNode(vTmpDiv, 'span', null, 'gTaskLabel', _this.vLangs[_this.vLang]['notes'] + ': ');
+                if (pTask.getNotes())
+                    vTmpDiv.appendChild(pTask.getNotes());
+            }
+        }
+    };
+    var callback;
+    if (typeof templateStrOrFn === 'function') {
+        callback = function () {
+            var strOrPromise = templateStrOrFn(pTask);
+            if (!strOrPromise || typeof strOrPromise === 'string') {
+                setupTemplate(strOrPromise);
+            }
+            else if (strOrPromise.then) {
+                setupTemplate(_this.vLangs[_this.vLang]['tooltipLoading'] || _this.vLangs['en']['tooltipLoading']);
+                return strOrPromise.then(setupTemplate);
+            }
+        };
+    }
+    else {
+        setupTemplate(templateStrOrFn);
+    }
+    return { component: vTaskInfoBox, callback: callback };
 };
-
-JSGantt.parseXMLString=function(pStr,pGanttVar)
-{
-	if (typeof window.DOMParser!='undefined') {
-		var xmlDoc =(new window.DOMParser()).parseFromString(pStr, 'text/xml');
-	} else if (typeof window.ActiveXObject!='undefined' &&
-		   new window.ActiveXObject('Microsoft.XMLDOM')) {
-		xmlDoc=new window.ActiveXObject('Microsoft.XMLDOM');
-		xmlDoc.async='false';
-		xmlDoc.loadXML(pStr);
-	}
-
-	JSGantt.AddXMLTask(pGanttVar, xmlDoc);
+exports.AddTaskItem = function (value) {
+    var vExists = false;
+    for (var i = 0; i < this.vTaskList.length; i++) {
+        if (this.vTaskList[i].getID() == value.getID()) {
+            i = this.vTaskList.length;
+            vExists = true;
+        }
+    }
+    if (!vExists) {
+        this.vTaskList.push(value);
+        this.vProcessNeeded = true;
+    }
 };
-
-
-JSGantt.findXMLNode=function(pRoot,pNodeName)
-{
-	var vRetValue;
-
-	try {vRetValue=pRoot.getElementsByTagName(pNodeName);
-	} catch (error)	{ ; } // do nothing, we'll return undefined
-
-	return vRetValue;
+exports.AddTaskItemObject = function (object) {
+    if (!object.pGantt) {
+        object.pGantt = this;
+    }
+    return this.AddTaskItem(exports.TaskItemObject(object));
 };
-
-// pType can be 1=numeric, 2=String, all other values just return raw data
-JSGantt.getXMLNodeValue=function(pRoot,pNodeName,pType,pDefault)
-{
-	var vRetValue;
-
-	try {vRetValue=pRoot.getElementsByTagName(pNodeName)[0].childNodes[0].nodeValue;
-	} catch (error)
-	{
-		if (typeof pDefault!='undefined')vRetValue=pDefault;
-	}
-
-	if (typeof vRetValue!='undefined' && vRetValue!=null)
-	{
-		if (pType==1)vRetValue*=1;
-		else if (pType==2)vRetValue=vRetValue.toString();
-	}
-	return vRetValue;
+exports.RemoveTaskItem = function (pID) {
+    // simply mark the task for removal at this point - actually remove it next time we re-draw the chart
+    for (var i = 0; i < this.vTaskList.length; i++) {
+        if (this.vTaskList[i].getID() == pID)
+            this.vTaskList[i].setToDelete(true);
+        else if (this.vTaskList[i].getParent() == pID)
+            this.RemoveTaskItem(this.vTaskList[i].getID());
+    }
+    this.vProcessNeeded = true;
 };
-
-JSGantt.AddXMLTask=function(pGanttVar, pXmlDoc)
-{
-	var project='';
-	var vMSP=false;
-	var Task;
-	var n=0;
-	var m=0;
-	var i=0;
-	var j=0;
-	var k=0;
-	var maxPID=0;
-	var ass=new Array();
-	var assRes=new Array();
-	var res=new Array();
-	var pars=new Array();
-
-	var projNode=JSGantt.findXMLNode(pXmlDoc,'Project');
-	if (typeof projNode!='undefined' && projNode.length>0) project=projNode[0].getAttribute('xmlns');
-
-	if(project=='http://schemas.microsoft.com/project')
-	{
-		vMSP=true;
-		pGanttVar.setDateInputFormat('yyyy-mm-dd');
-		Task=JSGantt.findXMLNode(pXmlDoc,'Task');
-		if (typeof Task=='undefined')n=0;
-		else n=Task.length;
-
-		var resources=JSGantt.findXMLNode(pXmlDoc,'Resource');
-		if (typeof resources=='undefined'){n=0; m=0;}
-		else m=resources.length;
-
-		for(i=0;i<m;i++)
-		{
-			var resname=JSGantt.getXMLNodeValue(resources[i],'Name',2,'');
-			var uid=JSGantt.getXMLNodeValue(resources[i],'UID',1,-1);
-
-			if (resname.length>0 && uid>0) res[uid]=resname;
-		}
-
-		var assignments=JSGantt.findXMLNode(pXmlDoc,'Assignment');
-		if (typeof assignments=='undefined') j=0;
-		else j=assignments.length;
-
-		for(i=0;i<j;i++)
-		{
-			var resUID=JSGantt.getXMLNodeValue(assignments[i],'ResourceUID',1,-1);
-			uid=JSGantt.getXMLNodeValue(assignments[i],'TaskUID',1,-1);
-
-			if (uid>0)
-			{
-				if (resUID>0) assRes[uid]=res[resUID];
-				ass[uid]=assignments[i];
-			}
-		}
-
-		// Store information about parent UIDs in an easily searchable form
-		for(i=0;i<n;i++)
-		{
-			uid=JSGantt.getXMLNodeValue(Task[i],'UID',1,0);
-
-			if(uid!=0) var vOutlineNumber=JSGantt.getXMLNodeValue(Task[i],'OutlineNumber',2,'0');
-			if (uid>0) pars[vOutlineNumber]=uid;
-			if (uid>maxPID)maxPID=uid;
-		}
-
-		for(i=0;i<n;i++)
-		{
-			// optional parameters may not have an entry
-			// Task ID must NOT be zero otherwise it will be skipped
-			var pID=JSGantt.getXMLNodeValue(Task[i],'UID',1,0);
-
-			if(pID!=0)
-			{
-				var pName=JSGantt.getXMLNodeValue(Task[i],'Name',2,'No Task Name');
-				var pStart=JSGantt.getXMLNodeValue(Task[i],'Start',2,'');
-				var pEnd=JSGantt.getXMLNodeValue(Task[i],'Finish',2,'');
-				var pLink=JSGantt.getXMLNodeValue(Task[i],'HyperlinkAddress',2,'');
-				var pMile=JSGantt.getXMLNodeValue(Task[i],'Milestone',1,0);
-				var pComp=JSGantt.getXMLNodeValue(Task[i],'PercentWorkComplete',1,0);
-				var pGroup=JSGantt.getXMLNodeValue(Task[i],'Summary',1,0);
-
-				var pParent=0;
-
-				var vOutlineLevel=JSGantt.getXMLNodeValue(Task[i],'OutlineLevel',1,0);
-				if (vOutlineLevel>1)
-				{
-					vOutlineNumber=JSGantt.getXMLNodeValue(Task[i],'OutlineNumber',2,'0');
-					pParent=pars[vOutlineNumber.substr(0, vOutlineNumber.lastIndexOf('.'))];
-				}
-
-				try {var pNotes=Task[i].getElementsByTagName('Notes')[0].childNodes[1].nodeValue; //this should be a CDATA node
-				} catch (error)
-				{pNotes ='';}
-
-				if(typeof assRes[pID]!='undefined') var pRes=assRes[pID];
-				else pRes='';
-
-				var predecessors=JSGantt.findXMLNode(Task[i],'PredecessorLink');
-				if (typeof predecessors=='undefined') j=0;
-				else j=predecessors.length;
-				var pDepend='';
-
-				for(k=0;k<j;k++)
-				{
-					var depUID=JSGantt.getXMLNodeValue(predecessors[k],'PredecessorUID',1,-1);
-					var depType=JSGantt.getXMLNodeValue(predecessors[k],'Type',1,1);
-
-					if (depUID>0)
-					{
-						if (pDepend.length>0)pDepend+=',';
-						switch(depType)
-						{
-							case 0:  pDepend+=depUID+'FF'; break;
-							case 1:  pDepend+=depUID+'FS'; break;
-							case 2:  pDepend+=depUID+'SF'; break;
-							case 3:  pDepend+=depUID+'SS'; break;
-							default: pDepend+=depUID+'FS'; break;
-						}
-					}
-				}
-
-				var pOpen=1;
-				var pCaption='';
-
-				if(pGroup>0) var pClass ='ggroupblack';
-				else if(pMile>0) pClass ='gmilestone';
-				else pClass ='gtaskblue';
-
-				// check for split tasks
-
-				var splits=JSGantt.findXMLNode(ass[pID],'TimephasedData');
-				if (typeof splits=='undefined') j=0;
-				else j=splits.length;
-
-				var vSplitStart=pStart;
-				var vSplitEnd=pEnd;
-				var vSubCreated=false;
-				var vDepend=pDepend.replace(/,*[0-9]+[FS]F/g,'');
-
-				for(k=0;k<j;k++)
-				{
-					var vDuration=JSGantt.getXMLNodeValue(splits[k],'Value',2,'0');
-					//remove all text
-					vDuration='0'+vDuration.replace(/\D/g,'');
-					vDuration*=1;
-					if ((vDuration==0 && !vSubCreated)|| (k+1==j && pGroup==2))
-					{
-						// No time booked in the given period (or last entry)
-						// Make sure the parent task is set as a combined group
-						pGroup=2;
-						// Handle last loop
-						if (k+1==j)vDepend=pDepend.replace(/,*[0-9]+[FS]S/g,'');
-						// Now create a subtask
-						maxPID++;
-						vSplitEnd=JSGantt.getXMLNodeValue(splits[k],(k+1==j)?'Finish':'Start',2,'');
-						pGanttVar.AddTaskItem(new JSGantt.TaskItem(maxPID, pName, vSplitStart, vSplitEnd, 'gtaskblue', pLink, pMile, pRes, pComp, 0, pID, pOpen, vDepend, pCaption, pNotes, pGanttVar));
-						vSubCreated=true;
-						vDepend='';
-					}
-					else if (vDuration!=0 && vSubCreated)
-					{
-						vSplitStart=JSGantt.getXMLNodeValue(splits[k],'Start',2,'');
-						vSubCreated=false;
-					}
-				}
-				if (vSubCreated)pDepend='';
-
-				// Finally add the task
-				pGanttVar.AddTaskItem(new JSGantt.TaskItem(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGanttVar));
-			}
-		}
-	}
-	else
-	{
-		Task=pXmlDoc.getElementsByTagName('task');
-		n=Task.length;
-
-		for(i=0;i<n;i++)
-		{
-			// optional parameters may not have an entry
-			// Task ID must NOT be zero otherwise it will be skipped
-			pID=JSGantt.getXMLNodeValue(Task[i],'pID',1,0);
-
-			if(pID!=0)
-			{
-				pName=JSGantt.getXMLNodeValue(Task[i],'pName',2,'No Task Name');
-				pStart=JSGantt.getXMLNodeValue(Task[i],'pStart',2,'');
-				pEnd=JSGantt.getXMLNodeValue(Task[i],'pEnd',2,'');
-				pLink=JSGantt.getXMLNodeValue(Task[i],'pLink',2,'');
-				pMile=JSGantt.getXMLNodeValue(Task[i],'pMile',1,0);
-				pComp=JSGantt.getXMLNodeValue(Task[i],'pComp',1,0);
-				pGroup=JSGantt.getXMLNodeValue(Task[i],'pGroup',1,0);
-				pParent=JSGantt.getXMLNodeValue(Task[i],'pParent',1,0);
-				pRes=JSGantt.getXMLNodeValue(Task[i],'pRes',2,'');
-				pOpen=JSGantt.getXMLNodeValue(Task[i],'pOpen',1,1);
-				pDepend=JSGantt.getXMLNodeValue(Task[i],'pDepend',2,'');
-				pCaption=JSGantt.getXMLNodeValue(Task[i],'pCaption',2,'');
-				pNotes=JSGantt.getXMLNodeValue(Task[i],'pNotes',2,'');
-				pClass=JSGantt.getXMLNodeValue(Task[i],'pClass',2);
-				if (typeof pClass=='undefined')
-				{
-					if(pGroup>0) pClass ='ggroupblack';
-					else if(pMile>0) pClass ='gmilestone';
-					else pClass ='gtaskblue';
-				}
-
-				// Finally add the task
-				pGanttVar.AddTaskItem(new JSGantt.TaskItem(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGanttVar));
-			}
-		}
-	}
+exports.ClearTasks = function () {
+    var _this = this;
+    this.vTaskList.map(function (task) { return _this.RemoveTaskItem(task.getID()); });
+    this.vProcessNeeded = true;
 };
-
-
-JSGantt.benchMark=function(pItem)
-{
-	var vEndTime=new Date().getTime();
-	alert(pItem+': Elapsed time: '+((vEndTime-vBenchTime)/1000)+' seconds.');
-	vBenchTime=new Date().getTime();
+// Recursively process task tree ... set min, max dates of parent tasks and identfy task level.
+exports.processRows = function (pList, pID, pRow, pLevel, pOpen, pUseSort, vDebug) {
+    if (vDebug === void 0) { vDebug = false; }
+    var vMinDate = null;
+    var vMaxDate = null;
+    var vMinPlanDate = null;
+    var vMaxPlanDate = null;
+    var vVisible = pOpen;
+    var vCurItem = null;
+    var vCompSum = 0;
+    var vMinSet = 0;
+    var vMaxSet = 0;
+    var vMinPlanSet = 0;
+    var vMaxPlanSet = 0;
+    var vNumKid = 0;
+    var vWeight = 0;
+    var vLevel = pLevel;
+    var vList = pList;
+    var vComb = false;
+    var i = 0;
+    for (i = 0; i < pList.length; i++) {
+        if (pList[i].getToDelete()) {
+            pList.splice(i, 1);
+            i--;
+        }
+        if (i >= 0 && pList[i].getID() == pID)
+            vCurItem = pList[i];
+    }
+    for (i = 0; i < pList.length; i++) {
+        if (pList[i].getParent() == pID) {
+            vVisible = pOpen;
+            pList[i].setParItem(vCurItem);
+            pList[i].setVisible(vVisible);
+            if (vVisible == 1 && pList[i].getOpen() == 0)
+                vVisible = 0;
+            if (pList[i].getMile() && pList[i].getParItem() && pList[i].getParItem().getGroup() == 2) { //remove milestones owned by combined groups
+                pList.splice(i, 1);
+                i--;
+                continue;
+            }
+            pList[i].setLevel(vLevel);
+            if (pList[i].getGroup()) {
+                if (pList[i].getParItem() && pList[i].getParItem().getGroup() == 2)
+                    pList[i].setGroup(2);
+                exports.processRows(vList, pList[i].getID(), i, vLevel + 1, vVisible, 0);
+            }
+            if (pList[i].getStartVar() && (vMinSet == 0 || pList[i].getStartVar() < vMinDate)) {
+                vMinDate = pList[i].getStartVar();
+                vMinSet = 1;
+            }
+            if (pList[i].getEndVar() && (vMaxSet == 0 || pList[i].getEndVar() > vMaxDate)) {
+                vMaxDate = pList[i].getEndVar();
+                vMaxSet = 1;
+            }
+            if (vMinPlanSet == 0 || pList[i].getPlanStart() < vMinPlanDate) {
+                vMinPlanDate = pList[i].getPlanStart();
+                vMinPlanSet = 1;
+            }
+            if (vMaxPlanSet == 0 || pList[i].getPlanEnd() > vMaxPlanDate) {
+                vMaxPlanDate = pList[i].getPlanEnd();
+                vMaxPlanSet = 1;
+            }
+            vNumKid++;
+            vWeight += pList[i].getEnd() - pList[i].getStart() + 1;
+            vCompSum += pList[i].getCompVal() * (pList[i].getEnd() - pList[i].getStart() + 1);
+            pList[i].setSortIdx(i * pList.length);
+        }
+    }
+    if (pRow >= 0) {
+        if (pList[pRow].getGroupMinStart() != null && pList[pRow].getGroupMinStart() < vMinDate) {
+            vMinDate = pList[pRow].getGroupMinStart();
+        }
+        if (pList[pRow].getGroupMinEnd() != null && pList[pRow].getGroupMinEnd() > vMaxDate) {
+            vMaxDate = pList[pRow].getGroupMinEnd();
+        }
+        if (vMinDate) {
+            pList[pRow].setStart(vMinDate);
+        }
+        if (vMaxDate) {
+            pList[pRow].setEnd(vMaxDate);
+        }
+        if (pList[pRow].getGroupMinPlanStart() != null && pList[pRow].getGroupMinPlanStart() < vMinPlanDate) {
+            vMinPlanDate = pList[pRow].getGroupMinPlanStart();
+        }
+        if (pList[pRow].getGroupMinPlanEnd() != null && pList[pRow].getGroupMinPlanEnd() > vMaxPlanDate) {
+            vMaxPlanDate = pList[pRow].getGroupMinPlanEnd();
+        }
+        if (vMinPlanDate) {
+            pList[pRow].setPlanStart(vMinPlanDate);
+        }
+        if (vMaxPlanDate) {
+            pList[pRow].setPlanEnd(vMaxPlanDate);
+        }
+        pList[pRow].setNumKid(vNumKid);
+        pList[pRow].setWeight(vWeight);
+        pList[pRow].setCompVal(Math.ceil(vCompSum / vWeight));
+    }
+    if (pID == 0 && pUseSort == 1) {
+        var bd = void 0;
+        if (vDebug) {
+            bd = new Date();
+            console.info('before afterTasks', bd);
+        }
+        exports.sortTasks(pList, 0, 0);
+        if (vDebug) {
+            var ad = new Date();
+            console.info('after afterTasks', ad, (ad.getTime() - bd.getTime()));
+        }
+        pList.sort(function (a, b) { return a.getSortIdx() - b.getSortIdx(); });
+    }
+    if (pID == 0 && pUseSort != 1) // Need to sort combined tasks regardless
+     {
+        for (i = 0; i < pList.length; i++) {
+            if (pList[i].getGroup() == 2) {
+                vComb = true;
+                var bd = void 0;
+                if (vDebug) {
+                    bd = new Date();
+                    console.info('before sortTasks', bd);
+                }
+                exports.sortTasks(pList, pList[i].getID(), pList[i].getSortIdx() + 1);
+                if (vDebug) {
+                    var ad = new Date();
+                    console.info('after sortTasks', ad, (ad.getTime() - bd.getTime()));
+                }
+            }
+        }
+        if (vComb == true)
+            pList.sort(function (a, b) { return a.getSortIdx() - b.getSortIdx(); });
+    }
 };
 
-JSGantt.getIsoWeek=function(pDate){
-	// We have to compare against the monday of the first week of the year containing 04 jan *not* 01/01
-	// 60*60*24*1000=86400000
-	var dayMiliseconds=86400000;
-	var keyDay=new Date(pDate.getFullYear(),0,4,0,0,0);
-	var keyDayOfWeek=(keyDay.getDay()==0) ? 6 : keyDay.getDay()-1; // define monday as 0
-	var firstMondayYearTime=keyDay.getTime()-(keyDayOfWeek * dayMiliseconds);
-	var thisDate=new Date(pDate.getFullYear(), pDate.getMonth(),pDate.getDate(),0,0,0); // This at 00:00:00
-	var thisTime=thisDate.getTime();
-	var daysFromFirstMonday=Math.round(((thisTime-firstMondayYearTime) / dayMiliseconds));
-	var lastWeek=99;
-	var thisWeek=99;
-
-	var firstMondayYear=new Date(firstMondayYearTime);
-
-	thisWeek=Math.ceil((daysFromFirstMonday+1)/7);
-
-	if (thisWeek<=0) thisWeek=JSGantt.getIsoWeek(new Date(pDate.getFullYear()-1,11,31,0,0,0));
-	else if (thisWeek==53 && (new Date(pDate.getFullYear(),0,1,0,0,0)).getDay()!=4 && (new Date(pDate.getFullYear(),11,31,0,0,0)).getDay()!=4) thisWeek=1;
-	return thisWeek;
+},{"./utils/date_utils":11,"./utils/draw_utils":12,"./utils/general_utils":13}],11:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+/**
+ * DATES
+ */
+exports.getMinDate = function (pList, pFormat, pMinDate) {
+    var vDate = new Date();
+    if (pList.length <= 0)
+        return pMinDate || vDate;
+    vDate.setTime((pMinDate && pMinDate.getTime()) || pList[0].getStart().getTime());
+    // Parse all Task Start dates to find min
+    for (var i = 0; i < pList.length; i++) {
+        if (pList[i].getStart().getTime() < vDate.getTime())
+            vDate.setTime(pList[i].getStart().getTime());
+        if (pList[i].getPlanStart() && pList[i].getPlanStart().getTime() < vDate.getTime())
+            vDate.setTime(pList[i].getPlanStart().getTime());
+    }
+    // Adjust min date to specific format boundaries (first of week or first of month)
+    if (pFormat == 'day') {
+        vDate.setDate(vDate.getDate() - 1);
+        while (vDate.getDay() % 7 != 1)
+            vDate.setDate(vDate.getDate() - 1);
+    }
+    else if (pFormat == 'week') {
+        vDate.setDate(vDate.getDate() - 1);
+        while (vDate.getDay() % 7 != 1)
+            vDate.setDate(vDate.getDate() - 1);
+    }
+    else if (pFormat == 'month') {
+        vDate.setDate(vDate.getDate() - 15);
+        while (vDate.getDate() > 1)
+            vDate.setDate(vDate.getDate() - 1);
+    }
+    else if (pFormat == 'quarter') {
+        vDate.setDate(vDate.getDate() - 31);
+        if (vDate.getMonth() == 0 || vDate.getMonth() == 1 || vDate.getMonth() == 2)
+            vDate.setFullYear(vDate.getFullYear(), 0, 1);
+        else if (vDate.getMonth() == 3 || vDate.getMonth() == 4 || vDate.getMonth() == 5)
+            vDate.setFullYear(vDate.getFullYear(), 3, 1);
+        else if (vDate.getMonth() == 6 || vDate.getMonth() == 7 || vDate.getMonth() == 8)
+            vDate.setFullYear(vDate.getFullYear(), 6, 1);
+        else if (vDate.getMonth() == 9 || vDate.getMonth() == 10 || vDate.getMonth() == 11)
+            vDate.setFullYear(vDate.getFullYear(), 9, 1);
+    }
+    else if (pFormat == 'hour') {
+        vDate.setHours(vDate.getHours() - 1);
+        while (vDate.getHours() % 6 != 0)
+            vDate.setHours(vDate.getHours() - 1);
+    }
+    if (pFormat == 'hour')
+        vDate.setMinutes(0, 0);
+    else
+        vDate.setHours(0, 0, 0);
+    return (vDate);
 };
-
-JSGantt.addListener=function (eventName, handler, control)
-{
-	// Check if control is a string
-	if (control===String(control)) control=JSGantt.findObj(control);
-
-	if(control.addEventListener) //Standard W3C
-	{
-		return control.addEventListener(eventName, handler, false);
-	}
-	else if (control.attachEvent) //IExplore
-	{
-		return control.attachEvent('on'+eventName, handler);
-	}
-	else
-	{
-		return false;
-	}
+exports.getMaxDate = function (pList, pFormat, pMaxDate) {
+    var vDate = new Date();
+    if (pList.length <= 0)
+        return pMaxDate || vDate;
+    vDate.setTime((pMaxDate && pMaxDate.getTime()) || pList[0].getEnd().getTime());
+    // Parse all Task End dates to find max
+    for (var i = 0; i < pList.length; i++) {
+        if (pList[i].getEnd().getTime() > vDate.getTime())
+            vDate.setTime(pList[i].getEnd().getTime());
+        if (pList[i].getPlanEnd() && pList[i].getPlanEnd().getTime() > vDate.getTime())
+            vDate.setTime(pList[i].getPlanEnd().getTime());
+    }
+    // Adjust max date to specific format boundaries (end of week or end of month)
+    if (pFormat == 'day') {
+        vDate.setDate(vDate.getDate() + 1);
+        while (vDate.getDay() % 7 != 0)
+            vDate.setDate(vDate.getDate() + 1);
+    }
+    else if (pFormat == 'week') {
+        //For weeks, what is the last logical boundary?
+        vDate.setDate(vDate.getDate() + 1);
+        while (vDate.getDay() % 7 != 0)
+            vDate.setDate(vDate.getDate() + 1);
+    }
+    else if (pFormat == 'month') {
+        // Set to last day of current Month
+        while (vDate.getDate() > 1)
+            vDate.setDate(vDate.getDate() + 1);
+        vDate.setDate(vDate.getDate() - 1);
+    }
+    else if (pFormat == 'quarter') {
+        // Set to last day of current Quarter
+        if (vDate.getMonth() == 0 || vDate.getMonth() == 1 || vDate.getMonth() == 2)
+            vDate.setFullYear(vDate.getFullYear(), 2, 31);
+        else if (vDate.getMonth() == 3 || vDate.getMonth() == 4 || vDate.getMonth() == 5)
+            vDate.setFullYear(vDate.getFullYear(), 5, 30);
+        else if (vDate.getMonth() == 6 || vDate.getMonth() == 7 || vDate.getMonth() == 8)
+            vDate.setFullYear(vDate.getFullYear(), 8, 30);
+        else if (vDate.getMonth() == 9 || vDate.getMonth() == 10 || vDate.getMonth() == 11)
+            vDate.setFullYear(vDate.getFullYear(), 11, 31);
+    }
+    else if (pFormat == 'hour') {
+        if (vDate.getHours() == 0)
+            vDate.setDate(vDate.getDate() + 1);
+        vDate.setHours(vDate.getHours() + 1);
+        while (vDate.getHours() % 6 != 5)
+            vDate.setHours(vDate.getHours() + 1);
+    }
+    return (vDate);
 };
-
-JSGantt.addTooltipListeners=function(pGanttChart, pObj1, pObj2)
-{
-	JSGantt.addListener('mouseover', function (e) {JSGantt.showToolTip(pGanttChart, e, pObj2, null, pGanttChart.getTimer());}, pObj1);
-	JSGantt.addListener('mouseout', function (e) {JSGantt.delayedHide(pGanttChart, pGanttChart.vTool, pGanttChart.getTimer());}, pObj1);
+exports.coerceDate = function (date) {
+    if (date instanceof Date) {
+        return date;
+    }
+    else {
+        var temp = new Date(date);
+        if (temp instanceof Date && !isNaN(temp.valueOf())) {
+            return temp;
+        }
+    }
 };
-
-JSGantt.addThisRowListeners=function(pGanttChart, pObj1, pObj2)
-{
-	JSGantt.addListener('mouseover', function () {pGanttChart.mouseOver(pObj1, pObj2);}, pObj1);
-	JSGantt.addListener('mouseover', function () {pGanttChart.mouseOver(pObj1, pObj2);}, pObj2);
-	JSGantt.addListener('mouseout', function () {pGanttChart.mouseOut(pObj1, pObj2);}, pObj1);
-	JSGantt.addListener('mouseout', function () {pGanttChart.mouseOut(pObj1, pObj2);}, pObj2);
+exports.parseDateStr = function (pDateStr, pFormatStr) {
+    var vDate = new Date();
+    var vDateParts = pDateStr.split(/[^0-9]/);
+    if (pDateStr.length >= 10 && vDateParts.length >= 3) {
+        while (vDateParts.length < 5)
+            vDateParts.push(0);
+        switch (pFormatStr) {
+            case 'mm/dd/yyyy':
+                vDate = new Date(vDateParts[2], vDateParts[0] - 1, vDateParts[1], vDateParts[3], vDateParts[4]);
+                break;
+            case 'dd/mm/yyyy':
+                vDate = new Date(vDateParts[2], vDateParts[1] - 1, vDateParts[0], vDateParts[3], vDateParts[4]);
+                break;
+            case 'yyyy-mm-dd':
+                vDate = new Date(vDateParts[0], vDateParts[1] - 1, vDateParts[2], vDateParts[3], vDateParts[4]);
+                break;
+            case 'yyyy-mm-dd HH:MI:SS':
+                vDate = new Date(vDateParts[0], vDateParts[1] - 1, vDateParts[2], vDateParts[3], vDateParts[4], vDateParts[5]);
+                break;
+        }
+    }
+    return (vDate);
+};
+exports.formatDateStr = function (pDate, pDateFormatArr, pL) {
+    // Fix on issue #303 - getXMLTask is passing null as pDates
+    if (!pDate) {
+        return;
+    }
+    var vDateStr = '';
+    var vYear2Str = pDate.getFullYear().toString().substring(2, 4);
+    var vMonthStr = (pDate.getMonth() + 1) + '';
+    var vMonthArr = new Array(pL['january'], pL['february'], pL['march'], pL['april'], pL['maylong'], pL['june'], pL['july'], pL['august'], pL['september'], pL['october'], pL['november'], pL['december']);
+    var vDayArr = new Array(pL['sunday'], pL['monday'], pL['tuesday'], pL['wednesday'], pL['thursday'], pL['friday'], pL['saturday']);
+    var vMthArr = new Array(pL['jan'], pL['feb'], pL['mar'], pL['apr'], pL['may'], pL['jun'], pL['jul'], pL['aug'], pL['sep'], pL['oct'], pL['nov'], pL['dec']);
+    var vDyArr = new Array(pL['sun'], pL['mon'], pL['tue'], pL['wed'], pL['thu'], pL['fri'], pL['sat']);
+    for (var i = 0; i < pDateFormatArr.length; i++) {
+        switch (pDateFormatArr[i]) {
+            case 'dd':
+                if (pDate.getDate() < 10)
+                    vDateStr += '0'; // now fall through
+            case 'd':
+                vDateStr += pDate.getDate();
+                break;
+            case 'day':
+                vDateStr += vDyArr[pDate.getDay()];
+                break;
+            case 'DAY':
+                vDateStr += vDayArr[pDate.getDay()];
+                break;
+            case 'mm':
+                if (parseInt(vMonthStr, 10) < 10)
+                    vDateStr += '0'; // now fall through
+            case 'm':
+                vDateStr += vMonthStr;
+                break;
+            case 'mon':
+                vDateStr += vMthArr[pDate.getMonth()];
+                break;
+            case 'month':
+                vDateStr += vMonthArr[pDate.getMonth()];
+                break;
+            case 'yyyy':
+                vDateStr += pDate.getFullYear();
+                break;
+            case 'yy':
+                vDateStr += vYear2Str;
+                break;
+            case 'qq':
+                vDateStr += pL['qtr']; // now fall through
+            case 'q':
+                vDateStr += Math.floor(pDate.getMonth() / 3) + 1;
+                break;
+            case 'hh':
+                if ((((pDate.getHours() % 12) == 0) ? 12 : pDate.getHours() % 12) < 10)
+                    vDateStr += '0'; // now fall through
+            case 'h':
+                vDateStr += ((pDate.getHours() % 12) == 0) ? 12 : pDate.getHours() % 12;
+                break;
+            case 'HH':
+                if ((pDate.getHours()) < 10)
+                    vDateStr += '0'; // now fall through
+            case 'H':
+                vDateStr += (pDate.getHours());
+                break;
+            case 'MI':
+                if (pDate.getMinutes() < 10)
+                    vDateStr += '0'; // now fall through
+            case 'mi':
+                vDateStr += pDate.getMinutes();
+                break;
+            case 'SS':
+                if (pDate.getSeconds() < 10)
+                    vDateStr += '0'; // now fall through
+            case 'ss':
+                vDateStr += pDate.getSeconds();
+                break;
+            case 'pm':
+                vDateStr += ((pDate.getHours()) < 12) ? 'am' : 'pm';
+                break;
+            case 'PM':
+                vDateStr += ((pDate.getHours()) < 12) ? 'AM' : 'PM';
+                break;
+            case 'ww':
+                if (exports.getIsoWeek(pDate) < 10)
+                    vDateStr += '0'; // now fall through
+            case 'w':
+                vDateStr += exports.getIsoWeek(pDate);
+                break;
+            case 'week':
+                var vWeekNum = exports.getIsoWeek(pDate);
+                var vYear = pDate.getFullYear();
+                var vDayOfWeek = (pDate.getDay() == 0) ? 7 : pDate.getDay();
+                if (vWeekNum >= 52 && parseInt(vMonthStr, 10) === 1)
+                    vYear--;
+                if (vWeekNum == 1 && parseInt(vMonthStr, 10) === 12)
+                    vYear++;
+                if (vWeekNum < 10)
+                    vWeekNum = parseInt('0' + vWeekNum, 10);
+                vDateStr += vYear + '-W' + vWeekNum + '-' + vDayOfWeek;
+                break;
+            default:
+                if (pL[pDateFormatArr[i].toLowerCase()])
+                    vDateStr += pL[pDateFormatArr[i].toLowerCase()];
+                else
+                    vDateStr += pDateFormatArr[i];
+                break;
+        }
+    }
+    return vDateStr;
+};
+exports.parseDateFormatStr = function (pFormatStr) {
+    var vComponantStr = '';
+    var vCurrChar = '';
+    var vSeparators = new RegExp('[\/\\ -.,\'":]');
+    var vDateFormatArray = new Array();
+    for (var i = 0; i < pFormatStr.length; i++) {
+        vCurrChar = pFormatStr.charAt(i);
+        if ((vCurrChar.match(vSeparators)) || (i + 1 == pFormatStr.length)) // separator or end of string
+         {
+            if ((i + 1 == pFormatStr.length) && (!(vCurrChar.match(vSeparators)))) // at end of string add any non-separator chars to the current component
+             {
+                vComponantStr += vCurrChar;
+            }
+            vDateFormatArray.push(vComponantStr);
+            if (vCurrChar.match(vSeparators))
+                vDateFormatArray.push(vCurrChar);
+            vComponantStr = '';
+        }
+        else {
+            vComponantStr += vCurrChar;
+        }
+    }
+    return vDateFormatArray;
+};
+/**
+ * We have to compare against the monday of the first week of the year containing 04 jan *not* 01/01
+ * 60*60*24*1000=86400000
+ * @param pDate
+ */
+exports.getIsoWeek = function (pDate) {
+    var dayMiliseconds = 86400000;
+    var keyDay = new Date(pDate.getFullYear(), 0, 4, 0, 0, 0);
+    var keyDayOfWeek = (keyDay.getDay() == 0) ? 6 : keyDay.getDay() - 1; // define monday as 0
+    var firstMondayYearTime = keyDay.getTime() - (keyDayOfWeek * dayMiliseconds);
+    var thisDate = new Date(pDate.getFullYear(), pDate.getMonth(), pDate.getDate(), 0, 0, 0); // This at 00:00:00
+    var thisTime = thisDate.getTime();
+    var daysFromFirstMonday = Math.round(((thisTime - firstMondayYearTime) / dayMiliseconds));
+    var lastWeek = 99;
+    var thisWeek = 99;
+    var firstMondayYear = new Date(firstMondayYearTime);
+    thisWeek = Math.ceil((daysFromFirstMonday + 1) / 7);
+    if (thisWeek <= 0)
+        thisWeek = exports.getIsoWeek(new Date(pDate.getFullYear() - 1, 11, 31, 0, 0, 0));
+    else if (thisWeek == 53 && (new Date(pDate.getFullYear(), 0, 1, 0, 0, 0)).getDay() != 4 && (new Date(pDate.getFullYear(), 11, 31, 0, 0, 0)).getDay() != 4)
+        thisWeek = 1;
+    return thisWeek;
 };
 
-JSGantt.addFolderListeners=function(pGanttChart, pObj, pID)
-{
-	JSGantt.addListener('click', function () {JSGantt.folder(pID, pGanttChart);}, pObj);
+},{}],12:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var events_1 = require("../events");
+exports.makeInput = function (formattedValue, editable, type, value, choices) {
+    if (type === void 0) { type = 'text'; }
+    if (value === void 0) { value = null; }
+    if (choices === void 0) { choices = null; }
+    if (!value) {
+        value = formattedValue;
+    }
+    if (editable) {
+        switch (type) {
+            case 'date':
+                // Take timezone into account before converting to ISO String
+                value = value ? new Date(value.getTime() - (value.getTimezoneOffset() * 60000)).toISOString().split('T')[0] : '';
+                return "<input class=\"gantt-inputtable\" type=\"date\" value=\"" + value + "\">";
+            case 'resource':
+                if (choices) {
+                    var found = choices.filter(function (c) { return c.id == value || c.name == value; });
+                    if (found && found.length > 0) {
+                        value = found[0].id;
+                    }
+                    else {
+                        choices.push({ id: value, name: value });
+                    }
+                    return "<select>" + choices.map(function (c) { return "<option value=\"" + c.id + "\" " + (value == c.id ? 'selected' : '') + " >" + c.name + "</option>"; }).join('') + "</select>";
+                }
+                else {
+                    return "<input class=\"gantt-inputtable\" type=\"text\" value=\"" + (value ? value : '') + "\">";
+                }
+            case 'cost':
+                return "<input class=\"gantt-inputtable\" type=\"number\" max=\"100\" min=\"0\" value=\"" + (value ? value : '') + "\">";
+            default:
+                return "<input class=\"gantt-inputtable\" value=\"" + (value ? value : '') + "\">";
+        }
+    }
+    else {
+        return formattedValue;
+    }
+};
+exports.newNode = function (pParent, pNodeType, pId, pClass, pText, pWidth, pLeft, pDisplay, pColspan, pAttribs) {
+    if (pId === void 0) { pId = null; }
+    if (pClass === void 0) { pClass = null; }
+    if (pText === void 0) { pText = null; }
+    if (pWidth === void 0) { pWidth = null; }
+    if (pLeft === void 0) { pLeft = null; }
+    if (pDisplay === void 0) { pDisplay = null; }
+    if (pColspan === void 0) { pColspan = null; }
+    if (pAttribs === void 0) { pAttribs = null; }
+    var vNewNode = pParent.appendChild(document.createElement(pNodeType));
+    if (pAttribs) {
+        for (var i = 0; i + 1 < pAttribs.length; i += 2) {
+            vNewNode.setAttribute(pAttribs[i], pAttribs[i + 1]);
+        }
+    }
+    if (pId)
+        vNewNode.id = pId; // I wish I could do this with setAttribute but older IEs don't play nice
+    if (pClass)
+        vNewNode.className = pClass;
+    if (pWidth)
+        vNewNode.style.width = (isNaN(pWidth * 1)) ? pWidth : pWidth + 'px';
+    if (pLeft)
+        vNewNode.style.left = (isNaN(pLeft * 1)) ? pLeft : pLeft + 'px';
+    if (pText) {
+        if (pText.indexOf && pText.indexOf('<') === -1) {
+            vNewNode.appendChild(document.createTextNode(pText));
+        }
+        else {
+            vNewNode.insertAdjacentHTML('beforeend', pText);
+        }
+    }
+    if (pDisplay)
+        vNewNode.style.display = pDisplay;
+    if (pColspan)
+        vNewNode.colSpan = pColspan;
+    return vNewNode;
+};
+exports.getArrayLocationByID = function (pId) {
+    var vList = this.getList();
+    for (var i = 0; i < vList.length; i++) {
+        if (vList[i].getID() == pId)
+            return i;
+    }
+    return -1;
+};
+exports.CalcTaskXY = function () {
+    var vID;
+    var vList = this.getList();
+    var vBarDiv;
+    var vTaskDiv;
+    var vParDiv;
+    var vLeft, vTop, vWidth;
+    var vHeight = Math.floor((this.getRowHeight() / 2));
+    for (var i = 0; i < vList.length; i++) {
+        vID = vList[i].getID();
+        vBarDiv = vList[i].getBarDiv();
+        vTaskDiv = vList[i].getTaskDiv();
+        if ((vList[i].getParItem() && vList[i].getParItem().getGroup() == 2)) {
+            vParDiv = vList[i].getParItem().getChildRow();
+        }
+        else
+            vParDiv = vList[i].getChildRow();
+        if (vBarDiv) {
+            vList[i].setStartX(vBarDiv.offsetLeft + 1);
+            vList[i].setStartY(vParDiv.offsetTop + vBarDiv.offsetTop + vHeight - 1);
+            vList[i].setEndX(vBarDiv.offsetLeft + vBarDiv.offsetWidth + 1);
+            vList[i].setEndY(vParDiv.offsetTop + vBarDiv.offsetTop + vHeight - 1);
+        }
+    }
+};
+exports.sLine = function (x1, y1, x2, y2, pClass) {
+    var vLeft = Math.min(x1, x2);
+    var vTop = Math.min(y1, y2);
+    var vWid = Math.abs(x2 - x1) + 1;
+    var vHgt = Math.abs(y2 - y1) + 1;
+    var vTmpDiv = document.createElement('div');
+    vTmpDiv.id = this.vDivId + 'line' + this.vDepId++;
+    vTmpDiv.style.position = 'absolute';
+    vTmpDiv.style.overflow = 'hidden';
+    vTmpDiv.style.zIndex = '0';
+    vTmpDiv.style.left = vLeft + 'px';
+    vTmpDiv.style.top = vTop + 'px';
+    vTmpDiv.style.width = vWid + 'px';
+    vTmpDiv.style.height = vHgt + 'px';
+    vTmpDiv.style.visibility = 'visible';
+    if (vWid == 1)
+        vTmpDiv.className = 'glinev';
+    else
+        vTmpDiv.className = 'glineh';
+    if (pClass)
+        vTmpDiv.className += ' ' + pClass;
+    this.getLines().appendChild(vTmpDiv);
+    if (this.vEvents.onLineDraw && typeof this.vEvents.onLineDraw === 'function') {
+        this.vEvents.onLineDraw(vTmpDiv);
+    }
+    return vTmpDiv;
+};
+exports.drawSelector = function (pPos) {
+    var vOutput = document.createDocumentFragment();
+    var vDisplay = false;
+    for (var i = 0; i < this.vShowSelector.length && !vDisplay; i++) {
+        if (this.vShowSelector[i].toLowerCase() == pPos.toLowerCase())
+            vDisplay = true;
+    }
+    if (vDisplay) {
+        var vTmpDiv = exports.newNode(vOutput, 'div', null, 'gselector', this.vLangs[this.vLang]['format'] + ':');
+        if (this.vFormatArr.join().toLowerCase().indexOf('hour') != -1)
+            events_1.addFormatListeners(this, 'hour', exports.newNode(vTmpDiv, 'span', this.vDivId + 'formathour' + pPos, 'gformlabel' + ((this.vFormat == 'hour') ? ' gselected' : ''), this.vLangs[this.vLang]['hour']));
+        if (this.vFormatArr.join().toLowerCase().indexOf('day') != -1)
+            events_1.addFormatListeners(this, 'day', exports.newNode(vTmpDiv, 'span', this.vDivId + 'formatday' + pPos, 'gformlabel' + ((this.vFormat == 'day') ? ' gselected' : ''), this.vLangs[this.vLang]['day']));
+        if (this.vFormatArr.join().toLowerCase().indexOf('week') != -1)
+            events_1.addFormatListeners(this, 'week', exports.newNode(vTmpDiv, 'span', this.vDivId + 'formatweek' + pPos, 'gformlabel' + ((this.vFormat == 'week') ? ' gselected' : ''), this.vLangs[this.vLang]['week']));
+        if (this.vFormatArr.join().toLowerCase().indexOf('month') != -1)
+            events_1.addFormatListeners(this, 'month', exports.newNode(vTmpDiv, 'span', this.vDivId + 'formatmonth' + pPos, 'gformlabel' + ((this.vFormat == 'month') ? ' gselected' : ''), this.vLangs[this.vLang]['month']));
+        if (this.vFormatArr.join().toLowerCase().indexOf('quarter') != -1)
+            events_1.addFormatListeners(this, 'quarter', exports.newNode(vTmpDiv, 'span', this.vDivId + 'formatquarter' + pPos, 'gformlabel' + ((this.vFormat == 'quarter') ? ' gselected' : ''), this.vLangs[this.vLang]['quarter']));
+    }
+    else {
+        exports.newNode(vOutput, 'div', null, 'gselector');
+    }
+    return vOutput;
 };
 
-JSGantt.addFormatListeners=function(pGanttChart, pFormat, pObj)
-{
-	JSGantt.addListener('click', function () {JSGantt.changeFormat(pFormat, pGanttChart);}, pObj);
+},{"../events":5}],13:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.internalProperties = ['pID', 'pName', 'pStart', 'pEnd', 'pClass', 'pLink', 'pMile', 'pRes', 'pComp', 'pGroup', 'pParent',
+    'pOpen', 'pDepend', 'pCaption', 'pNotes', 'pGantt', 'pCost', 'pPlanStart', 'pPlanEnd'];
+exports.internalPropertiesLang = {
+    'pID': 'id',
+    'pName': 'name',
+    'pStart': 'startdate',
+    'pEnd': 'enddate',
+    'pLink': 'link',
+    'pMile': 'mile',
+    'pRes': 'resource',
+    'pComp': 'comp',
+    'pGroup': 'group',
+    'pParent': 'parent',
+    'pOpen': 'open',
+    'pDepend': 'depend',
+    'pCaption': 'caption',
+    'pNotes': 'notes',
+    'pCost': 'cost',
+    'pPlanStart': 'planstartdate',
+    'pPlanEnd': 'planenddate'
+};
+exports.findObj = function (theObj, theDoc) {
+    if (theDoc === void 0) { theDoc = null; }
+    var p, i, foundObj;
+    if (!theDoc)
+        theDoc = document;
+    if (document.getElementById)
+        foundObj = document.getElementById(theObj);
+    return foundObj;
+};
+exports.changeFormat = function (pFormat, ganttObj) {
+    if (ganttObj)
+        ganttObj.setFormat(pFormat);
+    else
+        alert('Chart undefined');
+};
+exports.stripIds = function (pNode) {
+    for (var i = 0; i < pNode.childNodes.length; i++) {
+        if ('removeAttribute' in pNode.childNodes[i])
+            pNode.childNodes[i].removeAttribute('id');
+        if (pNode.childNodes[i].hasChildNodes())
+            exports.stripIds(pNode.childNodes[i]);
+    }
+};
+exports.stripUnwanted = function (pNode) {
+    var vAllowedTags = new Array('#text', 'p', 'br', 'ul', 'ol', 'li', 'div', 'span', 'img');
+    for (var i = 0; i < pNode.childNodes.length; i++) {
+        /* versions of IE<9 don't support indexOf on arrays so add trailing comma to the joined array and lookup value to stop substring matches */
+        if ((vAllowedTags.join().toLowerCase() + ',').indexOf(pNode.childNodes[i].nodeName.toLowerCase() + ',') == -1) {
+            pNode.replaceChild(document.createTextNode(pNode.childNodes[i].outerHTML), pNode.childNodes[i]);
+        }
+        if (pNode.childNodes[i].hasChildNodes())
+            exports.stripUnwanted(pNode.childNodes[i]);
+    }
+};
+exports.delayedHide = function (pGanttChartObj, pTool, pTimer) {
+    var vDelay = pGanttChartObj.getTooltipDelay() || 1500;
+    if (pTool)
+        pTool.delayTimeout = setTimeout(function () { exports.hideToolTip(pGanttChartObj, pTool, pTimer); }, vDelay);
+};
+exports.getZoomFactor = function () {
+    var vFactor = 1;
+    if (document.body.getBoundingClientRect) {
+        // rect is only in physical pixel size in IE before version 8
+        var vRect = document.body.getBoundingClientRect();
+        var vPhysicalW = vRect.right - vRect.left;
+        var vLogicalW = document.body.offsetWidth;
+        // the zoom level is always an integer percent value
+        vFactor = Math.round((vPhysicalW / vLogicalW) * 100) / 100;
+    }
+    return vFactor;
+};
+exports.benchMark = function (pItem) {
+    var vEndTime = new Date().getTime();
+    alert(pItem + ': Elapsed time: ' + ((vEndTime - this.vBenchTime) / 1000) + ' seconds.');
+    this.vBenchTime = new Date().getTime();
+};
+exports.getScrollPositions = function () {
+    var vScrollLeft = window.pageXOffset;
+    var vScrollTop = window.pageYOffset;
+    if (!('pageXOffset' in window)) // Internet Explorer before version 9
+     {
+        var vZoomFactor = exports.getZoomFactor();
+        vScrollLeft = Math.round(document.documentElement.scrollLeft / vZoomFactor);
+        vScrollTop = Math.round(document.documentElement.scrollTop / vZoomFactor);
+    }
+    return { x: vScrollLeft, y: vScrollTop };
+};
+var scrollbarWidth = undefined;
+exports.getScrollbarWidth = function () {
+    if (scrollbarWidth)
+        return scrollbarWidth;
+    var outer = document.createElement('div');
+    outer.className = 'gscrollbar-calculation-container';
+    document.body.appendChild(outer);
+    // Creating inner element and placing it in the container
+    var inner = document.createElement('div');
+    outer.appendChild(inner);
+    // Calculating difference between container's full width and the child width
+    scrollbarWidth = (outer.offsetWidth - inner.offsetWidth);
+    // Removing temporary elements from the DOM
+    outer.parentNode.removeChild(outer);
+    return scrollbarWidth;
+};
+exports.calculateCurrentDateOffset = function (curTaskStart, curTaskEnd) {
+    var tmpTaskStart = Date.UTC(curTaskStart.getFullYear(), curTaskStart.getMonth(), curTaskStart.getDate(), curTaskStart.getHours(), 0, 0);
+    var tmpTaskEnd = Date.UTC(curTaskEnd.getFullYear(), curTaskEnd.getMonth(), curTaskEnd.getDate(), curTaskEnd.getHours(), 0, 0);
+    return (tmpTaskEnd - tmpTaskStart);
+};
+exports.getOffset = function (pStartDate, pEndDate, pColWidth, pFormat, pShowWeekends) {
+    var DAY_CELL_MARGIN_WIDTH = 3; // Cell margin for 'day' format
+    var WEEK_CELL_MARGIN_WIDTH = 3; // Cell margin for 'week' format
+    var MONTH_CELL_MARGIN_WIDTH = 3; // Cell margin for 'month' format
+    var QUARTER_CELL_MARGIN_WIDTH = 3; // Cell margin for 'quarter' format
+    var HOUR_CELL_MARGIN_WIDTH = 3; // Cell margin for 'hour' format
+    var vMonthDaysArr = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
+    var curTaskStart = new Date(pStartDate.getTime());
+    var curTaskEnd = new Date(pEndDate.getTime());
+    var vTaskRightPx = 0;
+    // Length of task in hours
+    var oneHour = 3600000;
+    var vTaskRight = exports.calculateCurrentDateOffset(curTaskStart, curTaskEnd) / oneHour;
+    var vPosTmpDate;
+    if (pFormat == 'day') {
+        if (!pShowWeekends) {
+            var start = curTaskStart;
+            var end = curTaskEnd;
+            var countWeekends = 0;
+            while (start < end) {
+                var day = start.getDay();
+                if (day === 6 || day == 0) {
+                    countWeekends++;
+                }
+                start = new Date(start.getTime() + 24 * oneHour);
+            }
+            vTaskRight -= countWeekends * 24;
+        }
+        vTaskRightPx = Math.ceil((vTaskRight / 24) * (pColWidth + DAY_CELL_MARGIN_WIDTH) - 1);
+    }
+    else if (pFormat == 'week') {
+        vTaskRightPx = Math.ceil((vTaskRight / (24 * 7)) * (pColWidth + WEEK_CELL_MARGIN_WIDTH) - 1);
+    }
+    else if (pFormat == 'month') {
+        var vMonthsDiff = (12 * (curTaskEnd.getFullYear() - curTaskStart.getFullYear())) + (curTaskEnd.getMonth() - curTaskStart.getMonth());
+        vPosTmpDate = new Date(curTaskEnd.getTime());
+        vPosTmpDate.setDate(curTaskStart.getDate());
+        var vDaysCrctn = (curTaskEnd.getTime() - vPosTmpDate.getTime()) / (86400000);
+        vTaskRightPx = Math.ceil((vMonthsDiff * (pColWidth + MONTH_CELL_MARGIN_WIDTH)) + (vDaysCrctn * (pColWidth / vMonthDaysArr[curTaskEnd.getMonth()])) - 1);
+    }
+    else if (pFormat == 'quarter') {
+        var vMonthsDiff = (12 * (curTaskEnd.getFullYear() - curTaskStart.getFullYear())) + (curTaskEnd.getMonth() - curTaskStart.getMonth());
+        vPosTmpDate = new Date(curTaskEnd.getTime());
+        vPosTmpDate.setDate(curTaskStart.getDate());
+        var vDaysCrctn = (curTaskEnd.getTime() - vPosTmpDate.getTime()) / (86400000);
+        vTaskRightPx = Math.ceil((vMonthsDiff * ((pColWidth + QUARTER_CELL_MARGIN_WIDTH) / 3)) + (vDaysCrctn * (pColWidth / 90)) - 1);
+    }
+    else if (pFormat == 'hour') {
+        // can't just calculate sum because of daylight savings changes
+        vPosTmpDate = new Date(curTaskEnd.getTime());
+        vPosTmpDate.setMinutes(curTaskStart.getMinutes(), 0);
+        var vMinsCrctn = (curTaskEnd.getTime() - vPosTmpDate.getTime()) / (3600000);
+        vTaskRightPx = Math.ceil((vTaskRight * (pColWidth + HOUR_CELL_MARGIN_WIDTH)) + (vMinsCrctn * (pColWidth)));
+    }
+    return vTaskRightPx;
+};
+exports.isIE = function () {
+    if (typeof document.all != 'undefined') {
+        if ('pageXOffset' in window)
+            return false; // give IE9 and above the benefit of the doubt!
+        else
+            return true;
+    }
+    else
+        return false;
+};
+exports.hideToolTip = function (pGanttChartObj, pTool, pTimer) {
+    if (pGanttChartObj.getUseFade()) {
+        clearInterval(pTool.fadeInterval);
+        pTool.fadeInterval = setInterval(function () { exports.fadeToolTip(-1, pTool, 0); }, pTimer);
+    }
+    else {
+        pTool.style.opacity = 0;
+        pTool.style.filter = 'alpha(opacity=0)';
+        pTool.style.visibility = 'hidden';
+        pTool.vToolCont.setAttribute("showing", null);
+    }
+};
+exports.fadeToolTip = function (pDirection, pTool, pMaxAlpha) {
+    var vIncrement = parseInt(pTool.getAttribute('fadeIncrement'));
+    var vAlpha = pTool.getAttribute('currentOpacity');
+    var vCurAlpha = parseInt(vAlpha);
+    if ((vCurAlpha != pMaxAlpha && pDirection == 1) || (vCurAlpha != 0 && pDirection == -1)) {
+        var i = vIncrement;
+        if (pMaxAlpha - vCurAlpha < vIncrement && pDirection == 1) {
+            i = pMaxAlpha - vCurAlpha;
+        }
+        else if (vAlpha < vIncrement && pDirection == -1) {
+            i = vCurAlpha;
+        }
+        vAlpha = vCurAlpha + (i * pDirection);
+        pTool.style.opacity = vAlpha * 0.01;
+        pTool.style.filter = 'alpha(opacity=' + vAlpha + ')';
+        pTool.setAttribute('currentOpacity', vAlpha);
+    }
+    else {
+        clearInterval(pTool.fadeInterval);
+        if (pDirection == -1) {
+            pTool.style.opacity = 0;
+            pTool.style.filter = 'alpha(opacity=0)';
+            pTool.style.visibility = 'hidden';
+            pTool.vToolCont.setAttribute("showing", null);
+        }
+    }
+};
+exports.hashString = function (key) {
+    if (!key) {
+        key = 'default';
+    }
+    key += '';
+    var hash = 5381;
+    for (var i = 0; i < key.length; i++) {
+        if (key.charCodeAt) {
+            // tslint:disable-next-line:no-bitwise
+            hash = (hash << 5) + hash + key.charCodeAt(i);
+        }
+        // tslint:disable-next-line:no-bitwise
+        hash = hash & hash;
+    }
+    // tslint:disable-next-line:no-bitwise
+    return hash >>> 0;
+};
+exports.hashKey = function (key) {
+    return this.hashString(key);
+};
+exports.criticalPath = function (tasks) {
+    var path = {};
+    // calculate duration
+    tasks.forEach(function (task) {
+        task.duration = new Date(task.pEnd).getTime() - new Date(task.pStart).getTime();
+    });
+    tasks.forEach(function (task) {
+        if (!path[task.pID]) {
+            path[task.pID] = task;
+        }
+        if (!path[task.pParent]) {
+            path[task.pParent] = {
+                childrens: []
+            };
+        }
+        if (!path[task.pID].childrens) {
+            path[task.pID].childrens = [];
+        }
+        path[task.pParent].childrens.push(task);
+        var max = path[task.pParent].childrens[0].duration;
+        path[task.pParent].childrens.forEach(function (t) {
+            if (t.duration > max) {
+                max = t.duration;
+            }
+        });
+        path[task.pParent].duration = max;
+    });
+    var finalNodes = { 0: path[0] };
+    var node = path[0];
+    var _loop_1 = function () {
+        if (node.childrens.length > 0) {
+            var found_1 = node.childrens[0];
+            var max_1 = found_1.duration;
+            node.childrens.forEach(function (c) {
+                if (c.duration > max_1) {
+                    found_1 = c;
+                    max_1 = c.duration;
+                }
+            });
+            finalNodes[found_1.pID] = found_1;
+            node = found_1;
+        }
+        else {
+            node = null;
+        }
+    };
+    while (node) {
+        _loop_1();
+    }
+};
+function isParentElementOrSelf(child, parent) {
+    while (child) {
+        if (child === parent)
+            return true;
+        child = child.parentElement;
+    }
+}
+exports.isParentElementOrSelf = isParentElementOrSelf;
+exports.updateFlyingObj = function (e, pGanttChartObj, pTimer) {
+    var vCurTopBuf = 3;
+    var vCurLeftBuf = 5;
+    var vCurBotBuf = 3;
+    var vCurRightBuf = 15;
+    var vMouseX = (e) ? e.clientX : window.event.clientX;
+    var vMouseY = (e) ? e.clientY : window.event.clientY;
+    var vViewportX = document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth;
+    var vViewportY = document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight;
+    var vNewX = vMouseX;
+    var vNewY = vMouseY;
+    var screenX = screen.availWidth || window.innerWidth;
+    var screenY = screen.availHeight || window.innerHeight;
+    var vOldX = parseInt(pGanttChartObj.vTool.style.left);
+    var vOldY = parseInt(pGanttChartObj.vTool.style.top);
+    if (navigator.appName.toLowerCase() == 'microsoft internet explorer') {
+        // the clientX and clientY properties include the left and top borders of the client area
+        vMouseX -= document.documentElement.clientLeft;
+        vMouseY -= document.documentElement.clientTop;
+        var vZoomFactor = exports.getZoomFactor();
+        if (vZoomFactor != 1) { // IE 7 at non-default zoom level
+            vMouseX = Math.round(vMouseX / vZoomFactor);
+            vMouseY = Math.round(vMouseY / vZoomFactor);
+        }
+    }
+    var vScrollPos = exports.getScrollPositions();
+    /* Code for positioned right of the mouse by default*/
+    /*
+    if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX)
+    {
+        if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0) vNewX=vScrollPos.x;
+        else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth;
+    }
+    else vNewX=vMouseX+vScrollPos.x+vCurRightBuf;
+    */
+    /* Code for positioned left of the mouse by default */
+    if (vMouseX - vCurLeftBuf - pGanttChartObj.vTool.offsetWidth < 0) {
+        if (vMouseX + vCurRightBuf + pGanttChartObj.vTool.offsetWidth > vViewportX)
+            vNewX = vScrollPos.x;
+        else
+            vNewX = vMouseX + vScrollPos.x + vCurRightBuf;
+    }
+    else
+        vNewX = vMouseX + vScrollPos.x - vCurLeftBuf - pGanttChartObj.vTool.offsetWidth;
+    /* Code for positioned below the mouse by default */
+    if (vMouseY + vCurBotBuf + pGanttChartObj.vTool.offsetHeight > vViewportY) {
+        if (vMouseY - vCurTopBuf - pGanttChartObj.vTool.offsetHeight < 0)
+            vNewY = vScrollPos.y;
+        else
+            vNewY = vMouseY + vScrollPos.y - vCurTopBuf - pGanttChartObj.vTool.offsetHeight;
+    }
+    else
+        vNewY = vMouseY + vScrollPos.y + vCurBotBuf;
+    /* Code for positioned above the mouse by default */
+    /*
+    if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0)
+    {
+        if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY) vNewY=vScrollPos.y;
+        else vNewY=vMouseY+vScrollPos.y+vCurBotBuf;
+    }
+    else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight;
+    */
+    var outViewport = Math.abs(vOldX - vNewX) > screenX || Math.abs(vOldY - vNewY) > screenY;
+    if (pGanttChartObj.getUseMove() && !outViewport) {
+        clearInterval(pGanttChartObj.vTool.moveInterval);
+        pGanttChartObj.vTool.moveInterval = setInterval(function () { exports.moveToolTip(vNewX, vNewY, pGanttChartObj.vTool, pTimer); }, pTimer);
+    }
+    else {
+        pGanttChartObj.vTool.style.left = vNewX + 'px';
+        pGanttChartObj.vTool.style.top = vNewY + 'px';
+    }
+};
+exports.moveToolTip = function (pNewX, pNewY, pTool, timer) {
+    var vSpeed = parseInt(pTool.getAttribute('moveSpeed'));
+    var vOldX = parseInt(pTool.style.left);
+    var vOldY = parseInt(pTool.style.top);
+    if (pTool.style.visibility != 'visible') {
+        pTool.style.left = pNewX + 'px';
+        pTool.style.top = pNewY + 'px';
+        clearInterval(pTool.moveInterval);
+    }
+    else {
+        if (pNewX != vOldX && pNewY != vOldY) {
+            vOldX += Math.ceil((pNewX - vOldX) / vSpeed);
+            vOldY += Math.ceil((pNewY - vOldY) / vSpeed);
+            pTool.style.left = vOldX + 'px';
+            pTool.style.top = vOldY + 'px';
+        }
+        else {
+            clearInterval(pTool.moveInterval);
+        }
+    }
+};
+exports.makeRequest = function (pFile, json, vDebug) {
+    if (json === void 0) { json = true; }
+    if (vDebug === void 0) { vDebug = false; }
+    if (window.fetch) {
+        var f = fetch(pFile);
+        if (json) {
+            return f.then(function (res) { return res.json(); });
+        }
+        else {
+            return f;
+        }
+    }
+    else {
+        return exports.makeRequestOldBrowsers(pFile, vDebug)
+            .then(function (xhttp) {
+            if (json) {
+                var jsonObj = JSON.parse(xhttp.response);
+                return jsonObj;
+            }
+            else {
+                var xmlDoc = xhttp.responseXML;
+                return xmlDoc;
+            }
+        });
+    }
+};
+exports.makeRequestOldBrowsers = function (pFile, vDebug) {
+    if (vDebug === void 0) { vDebug = false; }
+    return new Promise(function (resolve, reject) {
+        var bd;
+        if (vDebug) {
+            bd = new Date();
+            console.info('before jsonparse', bd);
+        }
+        var xhttp;
+        if (window.XMLHttpRequest) {
+            xhttp = new XMLHttpRequest();
+        }
+        else { // IE 5/6
+            xhttp = new window.ActiveXObject('Microsoft.XMLHTTP');
+        }
+        xhttp.open('GET', pFile, true);
+        xhttp.send(null);
+        xhttp.onload = function (e) {
+            if (xhttp.readyState === 4) {
+                if (xhttp.status === 200) {
+                    // resolve(xhttp.responseText);
+                }
+                else {
+                    console.error(xhttp.statusText);
+                }
+                if (vDebug) {
+                    bd = new Date();
+                    console.info('before jsonparse', bd);
+                }
+                resolve(xhttp);
+            }
+        };
+        xhttp.onerror = function (e) {
+            reject(xhttp.statusText);
+        };
+    });
+};
+exports.calculateStartEndFromDepend = function (tasksList) {
 };
 
-JSGantt.addScrollListeners=function(pGanttChart)
-{
-	JSGantt.addListener('scroll', function () {pGanttChart.getChartBody().scrollTop=pGanttChart.getListBody().scrollTop;}, pGanttChart.getListBody());
-	JSGantt.addListener('scroll', function () {pGanttChart.getListBody().scrollTop=pGanttChart.getChartBody().scrollTop;}, pGanttChart.getChartBody());
-	JSGantt.addListener('scroll', function () {pGanttChart.getChartHead().scrollLeft=pGanttChart.getChartBody().scrollLeft;}, pGanttChart.getChartBody());
-	JSGantt.addListener('scroll', function () {pGanttChart.getChartBody().scrollLeft=pGanttChart.getChartHead().scrollLeft;}, pGanttChart.getChartHead());
-	JSGantt.addListener('resize', function () {pGanttChart.getChartHead().scrollLeft=pGanttChart.getChartBody().scrollLeft;}, window);
-	JSGantt.addListener('resize', function () {pGanttChart.getListBody().scrollTop=pGanttChart.getChartBody().scrollTop;}, window);
+},{}],14:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var task_1 = require("./task");
+var date_utils_1 = require("./utils/date_utils");
+var draw_utils_1 = require("./utils/draw_utils");
+var general_utils_1 = require("./utils/general_utils");
+exports.parseXML = function (pFile, pGanttVar) {
+    return general_utils_1.makeRequest(pFile, false, false)
+        .then(function (xmlDoc) {
+        exports.AddXMLTask(pGanttVar, xmlDoc);
+    });
+};
+exports.parseXMLString = function (pStr, pGanttVar) {
+    var xmlDoc;
+    if (typeof window.DOMParser != 'undefined') {
+        xmlDoc = (new window.DOMParser()).parseFromString(pStr, 'text/xml');
+    }
+    else if (typeof window.ActiveXObject != 'undefined' &&
+        new window.ActiveXObject('Microsoft.XMLDOM')) {
+        xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM');
+        xmlDoc.async = 'false';
+        xmlDoc.loadXML(pStr);
+    }
+    exports.AddXMLTask(pGanttVar, xmlDoc);
+};
+exports.findXMLNode = function (pRoot, pNodeName) {
+    var vRetValue;
+    try {
+        vRetValue = pRoot.getElementsByTagName(pNodeName);
+    }
+    catch (error) {
+        ;
+    } // do nothing, we'll return undefined
+    return vRetValue;
+};
+// pType can be 1=numeric, 2=String, all other values just return raw data
+exports.getXMLNodeValue = function (pRoot, pNodeName, pType, pDefault) {
+    var vRetValue;
+    try {
+        vRetValue = pRoot.getElementsByTagName(pNodeName)[0].childNodes[0].nodeValue;
+    }
+    catch (error) {
+        if (typeof pDefault != 'undefined')
+            vRetValue = pDefault;
+    }
+    if (typeof vRetValue != 'undefined' && vRetValue != null) {
+        if (pType == 1)
+            vRetValue *= 1;
+        else if (pType == 2)
+            vRetValue = vRetValue.toString();
+    }
+    return vRetValue;
+};
+exports.AddXMLTask = function (pGanttVar, pXmlDoc) {
+    var project = '';
+    var Task;
+    var n = 0;
+    var m = 0;
+    var i = 0;
+    var j = 0;
+    var k = 0;
+    var maxPID = 0;
+    var ass = new Array();
+    var assRes = new Array();
+    var res = new Array();
+    var pars = new Array();
+    var projNode = exports.findXMLNode(pXmlDoc, 'Project');
+    if (typeof projNode != 'undefined' && projNode.length > 0) {
+        project = projNode[0].getAttribute('xmlns');
+    }
+    if (project == 'http://schemas.microsoft.com/project') {
+        pGanttVar.setDateInputFormat('yyyy-mm-dd');
+        Task = exports.findXMLNode(pXmlDoc, 'Task');
+        if (typeof Task == 'undefined')
+            n = 0;
+        else
+            n = Task.length;
+        var resources = exports.findXMLNode(pXmlDoc, 'Resource');
+        if (typeof resources == 'undefined') {
+            n = 0;
+            m = 0;
+        }
+        else
+            m = resources.length;
+        for (i = 0; i < m; i++) {
+            var resname = exports.getXMLNodeValue(resources[i], 'Name', 2, '');
+            var uid = exports.getXMLNodeValue(resources[i], 'UID', 1, -1);
+            if (resname.length > 0 && uid > 0)
+                res[uid] = resname;
+        }
+        var assignments = exports.findXMLNode(pXmlDoc, 'Assignment');
+        if (typeof assignments == 'undefined')
+            j = 0;
+        else
+            j = assignments.length;
+        for (i = 0; i < j; i++) {
+            var uid = void 0;
+            var resUID = exports.getXMLNodeValue(assignments[i], 'ResourceUID', 1, -1);
+            uid = exports.getXMLNodeValue(assignments[i], 'TaskUID', 1, -1);
+            if (uid > 0) {
+                if (resUID > 0)
+                    assRes[uid] = res[resUID];
+                ass[uid] = assignments[i];
+            }
+        }
+        // Store information about parent UIDs in an easily searchable form
+        for (i = 0; i < n; i++) {
+            var uid = void 0;
+            uid = exports.getXMLNodeValue(Task[i], 'UID', 1, 0);
+            var vOutlineNumber = void 0;
+            if (uid != 0)
+                vOutlineNumber = exports.getXMLNodeValue(Task[i], 'OutlineNumber', 2, '0');
+            if (uid > 0)
+                pars[vOutlineNumber] = uid;
+            if (uid > maxPID)
+                maxPID = uid;
+        }
+        for (i = 0; i < n; i++) {
+            // optional parameters may not have an entry
+            // Task ID must NOT be zero otherwise it will be skipped
+            var pID = exports.getXMLNodeValue(Task[i], 'UID', 1, 0);
+            if (pID != 0) {
+                var pName = exports.getXMLNodeValue(Task[i], 'Name', 2, 'No Task Name');
+                var pStart = exports.getXMLNodeValue(Task[i], 'Start', 2, '');
+                var pEnd = exports.getXMLNodeValue(Task[i], 'Finish', 2, '');
+                var pPlanStart = exports.getXMLNodeValue(Task[i], 'PlanStart', 2, '');
+                var pPlanEnd = exports.getXMLNodeValue(Task[i], 'PlanFinish', 2, '');
+                var pDuration = exports.getXMLNodeValue(Task[i], 'Duration', 2, '');
+                var pLink = exports.getXMLNodeValue(Task[i], 'HyperlinkAddress', 2, '');
+                var pMile = exports.getXMLNodeValue(Task[i], 'Milestone', 1, 0);
+                var pComp = exports.getXMLNodeValue(Task[i], 'PercentWorkComplete', 1, 0);
+                var pCost = exports.getXMLNodeValue(Task[i], 'Cost', 2, 0);
+                var pGroup = exports.getXMLNodeValue(Task[i], 'Summary', 1, 0);
+                var pParent = 0;
+                var vOutlineLevel = exports.getXMLNodeValue(Task[i], 'OutlineLevel', 1, 0);
+                var vOutlineNumber = void 0;
+                if (vOutlineLevel > 1) {
+                    vOutlineNumber = exports.getXMLNodeValue(Task[i], 'OutlineNumber', 2, '0');
+                    pParent = pars[vOutlineNumber.substr(0, vOutlineNumber.lastIndexOf('.'))];
+                }
+                var pNotes = void 0;
+                try {
+                    pNotes = Task[i].getElementsByTagName('Notes')[0].childNodes[1].nodeValue; //this should be a CDATA node
+                }
+                catch (error) {
+                    pNotes = '';
+                }
+                var pRes = void 0;
+                if (typeof assRes[pID] != 'undefined')
+                    pRes = assRes[pID];
+                else
+                    pRes = '';
+                var predecessors = exports.findXMLNode(Task[i], 'PredecessorLink');
+                if (typeof predecessors == 'undefined')
+                    j = 0;
+                else
+                    j = predecessors.length;
+                var pDepend = '';
+                for (k = 0; k < j; k++) {
+                    var depUID = exports.getXMLNodeValue(predecessors[k], 'PredecessorUID', 1, -1);
+                    var depType = exports.getXMLNodeValue(predecessors[k], 'Type', 1, 1);
+                    if (depUID > 0) {
+                        if (pDepend.length > 0)
+                            pDepend += ',';
+                        switch (depType) {
+                            case 0:
+                                pDepend += depUID + 'FF';
+                                break;
+                            case 1:
+                                pDepend += depUID + 'FS';
+                                break;
+                            case 2:
+                                pDepend += depUID + 'SF';
+                                break;
+                            case 3:
+                                pDepend += depUID + 'SS';
+                                break;
+                            default:
+                                pDepend += depUID + 'FS';
+                                break;
+                        }
+                    }
+                }
+                var pOpen = 1;
+                var pCaption = '';
+                var pClass = void 0;
+                if (pGroup > 0)
+                    pClass = 'ggroupblack';
+                else if (pMile > 0)
+                    pClass = 'gmilestone';
+                else
+                    pClass = 'gtaskblue';
+                // check for split tasks
+                var splits = exports.findXMLNode(ass[pID], 'TimephasedData');
+                if (typeof splits == 'undefined')
+                    j = 0;
+                else
+                    j = splits.length;
+                var vSplitStart = pStart;
+                var vSplitEnd = pEnd;
+                var vSubCreated = false;
+                var vDepend = pDepend.replace(/,*[0-9]+[FS]F/g, '');
+                for (k = 0; k < j; k++) {
+                    var vDuration = exports.getXMLNodeValue(splits[k], 'Value', 2, '0');
+                    //remove all text
+                    vDuration = '0' + vDuration.replace(/\D/g, '');
+                    vDuration *= 1;
+                    if ((vDuration == 0 && !vSubCreated) || (k + 1 == j && pGroup == 2)) {
+                        // No time booked in the given period (or last entry)
+                        // Make sure the parent task is set as a combined group
+                        pGroup = 2;
+                        // Handle last loop
+                        if (k + 1 == j)
+                            vDepend = pDepend.replace(/,*[0-9]+[FS]S/g, '');
+                        // Now create a subtask
+                        maxPID++;
+                        vSplitEnd = exports.getXMLNodeValue(splits[k], (k + 1 == j) ? 'Finish' : 'Start', 2, '');
+                        pGanttVar.AddTaskItem(new task_1.TaskItem(maxPID, pName, vSplitStart, vSplitEnd, 'gtaskblue', pLink, pMile, pRes, pComp, 0, pID, pOpen, vDepend, pCaption, pNotes, pGanttVar, pCost, pPlanStart, pPlanEnd, pDuration));
+                        vSubCreated = true;
+                        vDepend = '';
+                    }
+                    else if (vDuration != 0 && vSubCreated) {
+                        vSplitStart = exports.getXMLNodeValue(splits[k], 'Start', 2, '');
+                        vSubCreated = false;
+                    }
+                }
+                if (vSubCreated)
+                    pDepend = '';
+                // Finally add the task
+                pGanttVar.AddTaskItem(new task_1.TaskItem(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGanttVar, pCost, pPlanStart, pPlanEnd, pDuration));
+            }
+        }
+    }
+    else {
+        Task = pXmlDoc.getElementsByTagName('task');
+        n = Task.length;
+        for (i = 0; i < n; i++) {
+            // optional parameters may not have an entry
+            // Task ID must NOT be zero otherwise it will be skipped
+            var pID = exports.getXMLNodeValue(Task[i], 'pID', 1, 0);
+            if (pID != 0) {
+                var pName = exports.getXMLNodeValue(Task[i], 'pName', 2, 'No Task Name');
+                var pStart = exports.getXMLNodeValue(Task[i], 'pStart', 2, '');
+                var pEnd = exports.getXMLNodeValue(Task[i], 'pEnd', 2, '');
+                var pPlanStart = exports.getXMLNodeValue(Task[i], 'pPlanStart', 2, '');
+                var pPlanEnd = exports.getXMLNodeValue(Task[i], 'pPlanEnd', 2, '');
+                var pDuration = exports.getXMLNodeValue(Task[i], 'pDuration', 2, '');
+                var pLink = exports.getXMLNodeValue(Task[i], 'pLink', 2, '');
+                var pMile = exports.getXMLNodeValue(Task[i], 'pMile', 1, 0);
+                var pComp = exports.getXMLNodeValue(Task[i], 'pComp', 1, 0);
+                var pCost = exports.getXMLNodeValue(Task[i], 'pCost', 2, 0);
+                var pGroup = exports.getXMLNodeValue(Task[i], 'pGroup', 1, 0);
+                var pParent = exports.getXMLNodeValue(Task[i], 'pParent', 1, 0);
+                var pRes = exports.getXMLNodeValue(Task[i], 'pRes', 2, '');
+                var pOpen = exports.getXMLNodeValue(Task[i], 'pOpen', 1, 1);
+                var pDepend = exports.getXMLNodeValue(Task[i], 'pDepend', 2, '');
+                var pCaption = exports.getXMLNodeValue(Task[i], 'pCaption', 2, '');
+                var pNotes = exports.getXMLNodeValue(Task[i], 'pNotes', 2, '');
+                var pClass = exports.getXMLNodeValue(Task[i], 'pClass', 2, '');
+                if (typeof pClass == 'undefined') {
+                    if (pGroup > 0)
+                        pClass = 'ggroupblack';
+                    else if (pMile > 0)
+                        pClass = 'gmilestone';
+                    else
+                        pClass = 'gtaskblue';
+                }
+                // Finally add the task
+                pGanttVar.AddTaskItem(new task_1.TaskItem(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGanttVar, pCost, pPlanStart, pPlanEnd, pDuration));
+            }
+        }
+    }
+};
+exports.getXMLProject = function () {
+    var vProject = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
+    for (var i = 0; i < this.vTaskList.length; i++) {
+        vProject += this.getXMLTask(i, true);
+    }
+    vProject += '</project>';
+    return vProject;
 };
+exports.getXMLTask = function (pID, pIdx) {
+    var i = 0;
+    var vIdx = -1;
+    var vTask = '';
+    var vOutFrmt = date_utils_1.parseDateFormatStr(this.getDateInputFormat() + ' HH:MI:SS');
+    if (pIdx === true)
+        vIdx = pID;
+    else {
+        for (i = 0; i < this.vTaskList.length; i++) {
+            if (this.vTaskList[i].getID() == pID) {
+                vIdx = i;
+                break;
+            }
+        }
+    }
+    if (vIdx >= 0 && vIdx < this.vTaskList.length) {
+        /* Simplest way to return case sensitive node names is to just build a string */
+        vTask = '<task>';
+        vTask += '<pID>' + this.vTaskList[vIdx].getID() + '</pID>';
+        vTask += '<pName>' + this.vTaskList[vIdx].getName() + '</pName>';
+        vTask += '<pStart>' + date_utils_1.formatDateStr(this.vTaskList[vIdx].getStart(), vOutFrmt, this.vLangs[this.vLang]) + '</pStart>';
+        vTask += '<pEnd>' + date_utils_1.formatDateStr(this.vTaskList[vIdx].getEnd(), vOutFrmt, this.vLangs[this.vLang]) + '</pEnd>';
+        vTask += '<pPlanStart>' + date_utils_1.formatDateStr(this.vTaskList[vIdx].getPlanStart(), vOutFrmt, this.vLangs[this.vLang]) + '</pPlanStart>';
+        vTask += '<pPlanEnd>' + date_utils_1.formatDateStr(this.vTaskList[vIdx].getPlanEnd(), vOutFrmt, this.vLangs[this.vLang]) + '</pPlanEnd>';
+        vTask += '<pDuration>' + this.vTaskList[vIdx].getDuration() + '</pDuration>';
+        vTask += '<pClass>' + this.vTaskList[vIdx].getClass() + '</pClass>';
+        vTask += '<pLink>' + this.vTaskList[vIdx].getLink() + '</pLink>';
+        vTask += '<pMile>' + this.vTaskList[vIdx].getMile() + '</pMile>';
+        if (this.vTaskList[vIdx].getResource() != '\u00A0')
+            vTask += '<pRes>' + this.vTaskList[vIdx].getResource() + '</pRes>';
+        vTask += '<pComp>' + this.vTaskList[vIdx].getCompVal() + '</pComp>';
+        vTask += '<pCost>' + this.vTaskList[vIdx].getCost() + '</pCost>';
+        vTask += '<pGroup>' + this.vTaskList[vIdx].getGroup() + '</pGroup>';
+        vTask += '<pParent>' + this.vTaskList[vIdx].getParent() + '</pParent>';
+        vTask += '<pOpen>' + this.vTaskList[vIdx].getOpen() + '</pOpen>';
+        vTask += '<pDepend>';
+        var vDepList = this.vTaskList[vIdx].getDepend();
+        for (i = 0; i < vDepList.length; i++) {
+            if (i > 0)
+                vTask += ',';
+            if (vDepList[i] > 0)
+                vTask += vDepList[i] + this.vTaskList[vIdx].getDepType()[i];
+        }
+        vTask += '</pDepend>';
+        vTask += '<pCaption>' + this.vTaskList[vIdx].getCaption() + '</pCaption>';
+        var vTmpFrag = document.createDocumentFragment();
+        var vTmpDiv = draw_utils_1.newNode(vTmpFrag, 'div', null, null, this.vTaskList[vIdx].getNotes().innerHTML);
+        vTask += '<pNotes>' + vTmpDiv.innerHTML + '</pNotes>';
+        vTask += '</task>';
+    }
+    return vTask;
+};
+
+},{"./task":10,"./utils/date_utils":11,"./utils/draw_utils":12,"./utils/general_utils":13}]},{},[1])(1)
+});

+ 0 - 126
htdocs/includes/jsgantt/main.css

@@ -1,126 +0,0 @@
-body {
-  position: relative;
-}
-
-.product-name {
-  font-family: Satisfy;
-}
-
-#my-navbar-nav {
-  font-size: 16px;
-}
-
-#my-nav-brand {
-  font-size: 24px;
-  margin: 2px 40px 0 10px;
-  color: #ffffff;
-}
-
-#home {
-  background: #323232 url(home-bg.jpg) center 0 no-repeat;
-  background-attachment: fixed;
-  background-size: cover;
-  min-height: 660px;
-  color: #ffffff;
-}
-#home-title {
-  font-size: 70px;
-  margin-top: 180px;
-}
-#home-subtitle {
-  font-size: 36px;
-  margin-top: 40px;
-  margin-bottom: 50px;
-}
-#learn-more {
-  padding: 0;
-  width: 50px;
-  height: 50px;
-  border-radius: 50%;
-  font-size: 38px;
-  margin-top: 60px;
-}
-@media screen and (max-width: 991px) {
-  #learn-more {
-    display: none;
-  }
-}
-
-.section {
-  margin: 0 15vw;
-  padding: 5px 0 0;
-}
-
-h1 {
-  font-family: Kelly Slab;
-  font-size: 56px;
-  margin: 50px 0 20px;
-}
-
-h2 {
-  font-family: Kelly Slab;
-  margin: 20px 0 10px;
-}
-
-h3 {
-  font-family: Kelly Slab;
-}
-#embedded-Gantt, #external-Gantt {
-}
-
-.code-block {
-  background-color: #222222;
-}
-
-.contact-card {
-  max-width: 200px;
-  margin: auto;
-}
-
-.contact-link {
-  font-size: 28px;
-}
-
-.footer {
-  margin-top: 10px;
-  padding-top: 10px;
-  border-top: solid #bbbbbb 1px;
-}
-
-#slide-card {
-  background: transparent;
-  border: none;
-  margin: 180px 50px 50px;
-}
-#slide-dots {
-  background: transparent;
-  border: none;
-}
-.dot {
-  cursor:pointer;
-  height: 13px;
-  width: 13px;
-  margin: 0 2px;
-  background-color: #ffffff;
-  opacity: 0.3;
-  border-radius: 50%;
-  display: inline-block;
-  -webkit-transition: all .5s; /* Safari */
-  transition: all .5s;
-}
-.dot:hover {
-  opacity: 1;
-}
-.dot.active {
-  opacity: 1;
-}
-.slide {
-  width: 100%;
-  height: 150px;
-  font-size: 20px;
-  display: none;
-  opacity: 0;
-}
-.slide-icon {
-  font-size: 60px;
-}

+ 0 - 85
htdocs/includes/jsgantt/main.js

@@ -1,85 +0,0 @@
-$(document).ready(function() {
-
-  // Scrollspy changes navbar active links
-    $("body").scrollspy({target:"#my-navbar-nav", offset:50});
-
-  // Smooth scroll
-    $("a").click(function(event) {
-      if (this.hash !== "") {
-       event.preventDefault();
-       var linkOffset = 0;
-       if ($.inArray(this.hash,["#options","#xmlExport","#optionsLanguage","#setDayMajorDateDisplayFormat"]) != -1) {
-         linkOffset = -25;
-       }
-       $("html, body").animate({
-         scrollTop: $(this.hash).offset().top - $(".navbar").height() + linkOffset
-       }, 600);
-      }
-    });
-
-  // Demo buttons
-    $("#embedded-Gantt").hide(0);
-    $("#external-Gantt").hide(0);
-
-    $(".btn-demo").click(function() {
-      if ($(this).html().indexOf("Embedded Code") != -1) {
-        if ($("#external-Gantt").is(":visible")) {
-          $("#external-Gantt").animate({
-            height: "toggle",
-            opacity: "toggle"}, 300, function () {
-              $("#embedded-Gantt").animate({
-                height: "toggle",
-                opacity: "toggle"}, 600
-              );
-            }
-          );
-          $(".btn-demo:nth-child(2)").removeClass("active");
-        } else {
-          $("#embedded-Gantt").animate({
-            height: "toggle",
-            opacity: "toggle"}, 600
-          );
-        }
-      } else {
-        if ($("#embedded-Gantt").is(":visible")) {
-          $("#embedded-Gantt").animate({
-            height: "toggle",
-            opacity: "toggle"}, 300, function() {
-              $("#external-Gantt").animate({
-                height: "toggle",
-                opacity: "toggle"}, 600
-              );
-            }
-          );
-          $(".btn-demo:nth-child(1)").removeClass("active");
-        } else {
-          $("#external-Gantt").animate({
-            height: "toggle",
-            opacity: "toggle"}, 600
-          );
-        }
-      }
-    });
-
-  // Slideshow
-    var slideIndex = 0;
-    carousel();
-
-    function carousel() {
-      var i;
-      var x = document.getElementsByClassName("slide");
-      var d = document.getElementsByClassName("dot");
-      for (i = 0; i < x.length; i++) {
-        x[i].style.display = "none";
-      }
-      slideIndex++;
-      if (slideIndex > x.length) {slideIndex = 1}
-      x[slideIndex-1].style.display = "inline-block";
-      $(".slide:nth-child(" + (slideIndex).toString() + ")").animate({
-        opacity: 1
-      }, 500);
-      $(".dot").removeClass("active");
-      $(".dot:nth-child(" + (slideIndex).toString() + ")").addClass("active");
-      setTimeout(carousel, 2000); // Change image every 2 seconds
-    }
-  });

+ 0 - 131
htdocs/includes/jsgantt/project.xml

@@ -1,131 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-	<task>
-		<pID>10</pID>
-		<pName>WCF Changes</pName>
-		<pStart></pStart>
-		<pEnd></pEnd>
-		<pClass>ggroupblack</pClass>
-		<pLink></pLink>
-		<pMile>0</pMile>
-		<pRes></pRes>
-		<pComp>0</pComp>
-		<pGroup>1</pGroup>
-		<pParent>0</pParent>
-		<pOpen>1</pOpen>
-		<pDepend />
-	</task>
-	<task>
-		<pID>20</pID>
-		<pName>Move to WCF from remoting</pName>
-		<pStart>2017-05-11 09:00</pStart>
-		<pEnd>2017-05-15</pEnd>
-		<pClass>gtaskblue</pClass>
-		<pLink></pLink>
-		<pMile>0</pMile>
-		<pRes>Paul</pRes>
-		<pComp>10</pComp>
-		<pGroup>0</pGroup>
-		<pParent>10</pParent>
-		<pOpen>1</pOpen>
-		<pDepend></pDepend>
-		<pCaption>Paul</pCaption>
-		<pNotes>This text is only available in tool tips</pNotes>
-	</task>
-	<task>
-		<pID>30</pID>
-		<pName>add Auditing</pName>
-		<pStart>2017-05-18 10:30</pStart>
-		<pEnd>2017-05-20 12:00</pEnd>
-		<pClass>gtaskblue</pClass>
-		<pLink></pLink>
-		<pMile>0</pMile>
-		<pRes>Eduardo</pRes>
-		<pComp>50</pComp>
-		<pGroup>0</pGroup>
-		<pParent>10</pParent>
-		<pOpen>1</pOpen>
-		<pDepend>20</pDepend>
-		<pCaption>Eduardo</pCaption>
-	</task>
-	<task>
-		<pID>40</pID>
-		<pName>Yet another task</pName>
-		<pStart>2017-05-24</pStart>
-		<pEnd>2017-05-25</pEnd>
-		<pClass>gtaskblue</pClass>
-		<pLink></pLink>
-		<pMile>0</pMile>
-		<pRes>Ricardo</pRes>
-		<pComp>30</pComp>
-		<pGroup>0</pGroup>
-		<pParent>0</pParent>
-		<pOpen>1</pOpen>
-		<pDepend>20,30</pDepend>
-		<pCaption>Ricardo</pCaption>
-	</task>
-	<task>
-		<pID>50</pID>
-		<pName>Another Group</pName>
-		<pStart></pStart>
-		<pEnd></pEnd>
-		<pClass>ggroupblack</pClass>
-		<pLink></pLink>
-		<pMile>0</pMile>
-		<pRes></pRes>
-		<pComp>0</pComp>
-		<pGroup>1</pGroup>
-		<pParent>0</pParent>
-		<pOpen>1</pOpen>
-		<pDepend />
-	</task>
-	<task>
-		<pID>60</pID>
-		<pName>Move to GitHub</pName>
-		<pStart>2017-05-14 09:00</pStart>
-		<pEnd>2017-05-16</pEnd>
-		<pClass>gtaskblue</pClass>
-		<pLink></pLink>
-		<pMile>0</pMile>
-		<pRes>Ricardo</pRes>
-		<pComp>10</pComp>
-		<pGroup>0</pGroup>
-		<pParent>50</pParent>
-		<pOpen>1</pOpen>
-		<pDepend></pDepend>
-		<pCaption>Ricardo</pCaption>
-		<pNotes>This text is only available in tool tips</pNotes>
-	</task>
-	<task>
-		<pID>70</pID>
-		<pName>Updating files</pName>
-		<pStart>2017-05-18 10:30</pStart>
-		<pEnd>2017-05-21 12:00</pEnd>
-		<pClass>gtaskred</pClass>
-		<pLink></pLink>
-		<pMile>0</pMile>
-		<pRes>Paul</pRes>
-		<pComp>50</pComp>
-		<pGroup>0</pGroup>
-		<pParent>50</pParent>
-		<pOpen>1</pOpen>
-		<pDepend>60</pDepend>
-		<pCaption>Paul</pCaption>
-	</task>
-	<task>
-		<pID>80</pID>
-		<pName>Yet another task</pName>
-		<pStart>2017-05-23</pStart>
-		<pEnd>2017-05-25</pEnd>
-		<pClass>gtaskyellow</pClass>
-		<pLink></pLink>
-		<pMile>0</pMile>
-		<pRes>Eduardo</pRes>
-		<pComp>30</pComp>
-		<pGroup>0</pGroup>
-		<pParent>50</pParent>
-		<pOpen>1</pOpen>
-		<pDepend>60,70</pDepend>
-		<pCaption>Eduardo</pCaption>
-	</task>
-</project>

+ 9 - 3
htdocs/projet/ganttchart.inc.php

@@ -126,9 +126,14 @@ if (g.getDivId() != null)
 			$projecttmp = new Project($db);
 			$projecttmp->fetch($t['task_project_id']);
 			$tmpt = array(
-				'task_id'=> '-'.$t['task_project_id'], 'task_alternate_id'=> '-'.$t['task_project_id'], 'task_name'=>$projecttmp->ref.' '.$projecttmp->title, 'task_resources'=>'',
-				'task_start_date'=>'', 'task_end_date'=>'',
-				'task_is_group'=>1, 'task_position'=>0, 'task_css'=>'ggroupblack', 'task_milestone'=> 0, 'task_parent'=>0, 'task_parent_alternate_id'=>0, 'task_notes'=>'',
+				'task_id'=> '-'.$t['task_project_id'],
+				'task_alternate_id'=> '-'.$t['task_project_id'],
+				'task_name'=>$projecttmp->ref.' '.$projecttmp->title,
+				'task_resources'=>'',
+				'task_start_date'=>'',
+				'task_end_date'=>'',
+				'task_is_group'=>1, 'task_position'=>0, 'task_css'=>'ggroupblack', 'task_milestone'=> 0, 'task_parent'=>0, 'task_parent_alternate_id'=>0,
+				'task_notes'=>'',
 				'task_planned_workload'=>0
 			);
 			constructGanttLine($tasks, $tmpt, array(), 0, $t['task_project_id']);
@@ -180,6 +185,7 @@ function constructGanttLine($tarr, $task, $task_dependencies, $level = 0, $proje
 	$end_date = dol_print_date($end_date, $dateformatinput2);
 	// Resources
 	$resources = $task["task_resources"];
+
 	// Define depend (ex: "", "4,13", ...)
 	$depend = '';
 	$count = 0;

+ 2 - 1
htdocs/projet/ganttview.php

@@ -334,10 +334,11 @@ if (count($tasksarray) > 0)
 				}
 			}
 		}
-		//if ($s) $tasks[$taskcursor]['task_resources']='<a href="'.DOL_URL_ROOT.'/projet/tasks/contact.php?id='.$val->id.'&withproject=1" title="'.dol_escape_htmltag($s).'">'.$langs->trans("List").'</a>';
+
 		/* For JSGanttImproved */
 		//if ($s) $tasks[$taskcursor]['task_resources']=implode(',',$idofusers);
 		$tasks[$taskcursor]['task_resources'] = $s;
+		if ($s) $tasks[$taskcursor]['task_resources'] = '<a href="'.DOL_URL_ROOT.'/projet/tasks/contact.php?id='.$val->id.'&withproject=1" title="'.dol_escape_htmltag($s).'">'.$langs->trans("List").'</a>';
 		//print "xxx".$val->id.$tasks[$taskcursor]['task_resources'];
 		$tasks[$taskcursor]['note'] = $task->note_public;
 		$taskcursor++;

+ 12 - 2
htdocs/theme/eldy/global.inc.php

@@ -5095,10 +5095,15 @@ td.gminorheading {
 .glistlbl, .glistgrid {
 	width: 582px !important;
 }
-.gtaskname div, .gtaskname {
+/*.gtaskname div, .gtaskname {
     min-width: 250px !important;
     max-width: 250px !important;
     width: 250px !important;
+}*/
+.gtaskname div, .gtaskname {
+    min-width: 250px !important;
+    max-width: unset !important;
+    width: unset !important;
 }
 .gpccomplete div, .gpccomplete {
     min-width: 40px !important;
@@ -5108,7 +5113,12 @@ td.gminorheading {
 td.gtaskheading.gstartdate, td.gtaskheading.genddate {
     white-space: break-spaces;
 }
-
+.gtasktableh tr:nth-child(2) td:nth-child(2), .gtasktableh tr:nth-child(2) td:nth-child(3), .gtasktableh tr:nth-child(2) td:nth-child(4), .gtasktableh tr:nth-child(2) td:nth-child(5), .gtasktableh tr:nth-child(2) td:nth-child(6), .gtasktableh tr:nth-child(2) td:nth-child(7) {
+    color: transparent !important;
+    border-left: none;
+    border-right: none;
+    border-top: none;
+}
 
 /* ============================================================================== */
 /*  jFileTree                                                                     */

+ 33 - 4
htdocs/theme/md/btn.inc.php

@@ -359,12 +359,41 @@ div.pagination .btnTitle:hover .btnTitle-label{
     display: block;
 }
 
-
-
-
+/* rule to reduce top menu - 2nd reduction: Reduce width of top menu icons again */
+@media only screen and (max-width: <?php echo empty($conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2) ? round($nbtopmenuentries * 69, 0) + 130 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2; ?>px)	/* reduction 2 */
+{
+	.butAction, .butActionRefused, .butActionDelete {
+		font-size: 0.95em;
+	}
+	.btnTitle, a.btnTitle {
+	    display: inline-block;
+	    padding: 4px 4px 4px 4px;
+		min-width: unset;
+	}
+}
 
 <?php if (!empty($conf->global->MAIN_BUTTON_HIDE_UNAUTHORIZED) && (!$user->admin)) { ?>
 .butActionRefused, .butActionNewRefused, .btnTitle.refused {
     display: none !important;
 }
-<?php }
+<?php } ?>
+
+
+/*
+ * BTN LINK
+ */
+
+.btn-link{
+	margin-right: 5px;
+	border: 1px solid #ddd;
+	color: #333;
+	padding: 5px 10px;
+	border-radius:1em;
+	text-decoration: none !important;
+}
+
+.btn-link:hover{
+	background-color: #ddd;
+	border: 1px solid #ddd;
+}
+

+ 14 - 6
htdocs/theme/md/style.css.php

@@ -549,8 +549,8 @@ input.removedfile {
 }
 
 input[type=file ]    { background-color: transparent; border-top: none; border-left: none; border-right: none; box-shadow: none; }
-input[type=checkbox] { background-color: transparent; border: none; box-shadow: none; }
-input[type=radio]    { background-color: transparent; border: none; box-shadow: none; }
+input[type=checkbox] { background-color: transparent; border: none; box-shadow: none; vertical-align: middle; }
+input[type=radio]    { background-color: transparent; border: none; box-shadow: none; vertical-align: middle; }
 input[type=image]    { background-color: transparent; border: none; box-shadow: none; }
 input:-webkit-autofill {
 	background-color: #FBFFEA !important;
@@ -1899,6 +1899,11 @@ img.photoref, div.photoref {
 	width: 80px;
     object-fit: contain;
 }
+
+div.photoref .fa, div.photoref .fas, div.photoref .far {
+    font-size: 2.5em;
+}
+
 img.fitcontain {
     object-fit: contain;
 }
@@ -4071,7 +4076,6 @@ div.titre {
     padding-bottom: 5px;
     text-transform: uppercase;
 	/* text-shadow: 1px 1px 2px #FFFFFF; */
-	<?php print (empty($conf->dol_optimize_smallscreen) ? '' : 'margin-top: 4px;'); ?>
 }
 div.titre {
 	color: var(--colortexttitlenotab);
@@ -5000,6 +5004,12 @@ td.gminorheading {
 td.gtaskheading.gstartdate, td.gtaskheading.genddate {
     white-space: break-spaces;
 }
+.gtasktableh tr:nth-child(2) td:nth-child(2), .gtasktableh tr:nth-child(2) td:nth-child(3), .gtasktableh tr:nth-child(2) td:nth-child(4), .gtasktableh tr:nth-child(2) td:nth-child(5), .gtasktableh tr:nth-child(2) td:nth-child(6), .gtasktableh tr:nth-child(2) td:nth-child(7) {
+    color: transparent !important;
+    border-left: none;
+    border-right: none;
+    border-top: none;
+}
 
 
 /* ============================================================================== */
@@ -6484,12 +6494,10 @@ div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link:before
 		padding-right: 5px;
 	}
     img.photoref, div.photoref {
-    	border: none;
+    	border: 1px solid rgba(0, 0, 0, 0.2);
     	-webkit-box-shadow: none;
         box-shadow: none;
         padding: 4px;
-    	height: 20px;
-    	width: 20px;
         object-fit: contain;
     }