diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 79c1167..4b47047 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -12,6 +12,6 @@ Just a few guidelines before submitting issues and pull requests:
- Ensure the code passes [JSHint](http://jshint.com) completely
- Always strive to write code that meets [best practices](http://taitems.github.com/Front-End-Development-Guidelines/)
- If you're attempting to solve a very unique bug, a test case is preferred
-- Please target all pull requests to the [develop](/../../tree/develop) branch
+- Please target all pull requests to the [master](/../../tree/master) branch
And thanks once again!
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d8c2dc9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Marek Bielańczuk, Tait Brown, Leo Pfeifenberger, Grzegorz Russek and Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 6052e12..d7e52a9 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,13 @@
-[Demo and Documentation](http://taitems.github.com/jQuery.Gantt/)
-==============
+
+## [Demo and Documentation](http://taitems.github.com/jQuery.Gantt/)
+
+## Installation
+
+- Git clone
+- `yarn add @taitems/jquery-gantt`, or
+- `npm install @taitems/jquery-gantt`
+
+## About
jQuery Gantt Chart is a simple chart that implements gantt functionality as
a jQuery component.
diff --git a/css/style.css b/css/style.css
index 4980b9d..1d6d46c 100644
--- a/css/style.css
+++ b/css/style.css
@@ -1,14 +1,14 @@
-.gantt, .gantt2 {
+.gantt {
width: 100%;
margin: 20px auto;
border: 14px solid #ddd;
position: relative;
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
+-webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
border-radius: 6px;
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
+-webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
}
.gantt:after {
@@ -23,13 +23,26 @@
width: 100%;
}
+.fn-gantt *,
+.fn-gantt *:after,
+.fn-gantt *:before {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
.fn-gantt .fn-content {
overflow: hidden;
position: relative;
width: 100%;
}
-
+.fn-gantt .row {
+ float: left;
+ height: 24px;
+ line-height: 24px;
+ margin: 0;
+}
/* === LEFT PANEL === */
@@ -43,13 +56,6 @@
z-index: 20;
}
-.fn-gantt .row {
- float: left;
- height: 24px;
- line-height: 24px;
- margin-left: -1px;
-}
-
.fn-gantt .leftPanel .fn-label {
display: inline-block;
margin: 0 0 0 5px;
@@ -60,34 +66,27 @@
overflow: hidden;
}
-.fn-gantt .leftPanel .row0 {
- border-top: 1px solid #DDD;
+.fn-gantt .leftPanel .row {
+ border-bottom: 1px solid #DDD;
}
.fn-gantt .leftPanel .name, .fn-gantt .leftPanel .desc {
float: left;
- height: 23px;
- margin: 0;
- border-bottom: 1px solid #DDD;
+ height: 24px;
+ width: 50%;
background-color: #f6f6f6;
}
.fn-gantt .leftPanel .name {
- width: 110px;
font-weight: bold;
}
-.fn-gantt .leftPanel .desc {
- width: 115px;
-}
-
.fn-gantt .leftPanel .fn-wide, .fn-gantt .leftPanel .fn-wide .fn-label {
- width: 225px;
+ width: 100%;
}
-.fn-gantt .spacer {
- margin: -2px 0 1px 0;
- border-bottom: none;
+.fn-gantt .leftPanel .spacer {
background-color: #f6f6f6;
+ width: 100%;
}
@@ -100,44 +99,37 @@
}
.fn-gantt .dataPanel {
- margin-left: 0px;
- border-right: 1px solid #DDD;
+ margin-left: 0;
+ outline: 1px solid #DDD;
+ /* TODO: Replace image with gradient?
+ background-size: 24px 24px;
+ background-image: linear-gradient(to left, rgba(221, 221, 221, 0.7) 1px, transparent 1px), linear-gradient(to top, rgba(221, 221, 221, 0.7) 1px, transparent 1px);
+ */
background-image: url(../img/grid.png);
background-repeat: repeat;
- background-position: 24px 24px;
position: relative;
}
+
+.fn-gantt .row.header {
+ margin-right: -1px;
+ width: 100%;
+}
+
.fn-gantt .day, .fn-gantt .date {
overflow: visible;
width: 24px;
line-height: 24px;
text-align: center;
- border-left: 1px solid #DDD;
+ border-right: 1px solid #DDD;
border-bottom: 1px solid #DDD;
- margin: -1px 0 0 -1px;
font-size: 11px;
color: #484a4d;
text-shadow: 0 1px 0 rgba(255,255,255,0.75);
text-align: center;
}
-.fn-gantt .holiday {
- background-color: #ffd263;
- height: 23px;
- margin: 0 0 -1px -1px;
-}
-
-.fn-gantt .today {
- background-color: #fff8da;
- height: 23px;
- margin: 0 0 -1px -1px;
- font-weight: bold;
- text-align: center;
-}
-
.fn-gantt .sa, .fn-gantt .sn, .fn-gantt .wd {
- height: 23px;
- margin: 0 0 0 -1px;
+ height: 24px;
text-align: center;
}
@@ -152,13 +144,24 @@
text-align: center;
}
+.fn-gantt .holiday {
+ background-color: #ffd263;
+ height: 24px;
+}
+
+.fn-gantt .today {
+ background-color: #fff8da;
+ height: 24px;
+ font-weight: bold;
+ text-align: center;
+}
+
.fn-gantt .rightPanel .month, .fn-gantt .rightPanel .year {
float: left;
overflow: hidden;
- border-left: 1px solid #DDD;
+ border-right: 1px solid #DDD;
border-bottom: 1px solid #DDD;
- height: 23px;
- margin: 0 0 0 -1px;
+ height: 24px;
background-color: #f6f6f6;
font-weight: bold;
font-size: 11px;
@@ -174,24 +177,24 @@
position: absolute;
display: none;
z-index: 11;
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
+-webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
border-radius: 4px;
}
.fn-gantt .bar {
background-color: #D0E4FD;
height: 18px;
- margin: 0px 3px 3px 0px;
+ margin: 0 3px 3px 0;
position: absolute;
z-index: 10;
text-align: center;
- -webkit-box-shadow: 0 0 1px rgba(0,0,0,0.25) inset;
- -moz-box-shadow: 0 0 1px rgba(0,0,0,0.25) inset;
+-webkit-box-shadow: 0 0 1px rgba(0,0,0,0.25) inset;
+ -moz-box-shadow: 0 0 1px rgba(0,0,0,0.25) inset;
box-shadow: 0 0 1px rgba(0,0,0,0.25) inset;
- -webkit-border-radius: 3px;
- -moz-border-radius: 3px;
- border-radius: 3px;
+-webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
}
.fn-gantt .bar .fn-label {
@@ -278,20 +281,20 @@
height: 6px;
background-color: #838688;
margin: 8px 0 0 0;
- -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;
- -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;
+-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;
+ -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;
box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;
- -webkit-border-radius: 3px;
- -moz-border-radius: 3px;
- border-radius: 3px;
+-webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
}
.fn-gantt .navigate .nav-slider-button {
width: 17px;
height: 60px;
background: url(../img/slider_handle.png) center center no-repeat;
- left: 0px;
- top: 0px;
+ left: 0;
+ top: 0;
margin: -26px 0 0 0;
cursor: pointer;
}
@@ -319,25 +322,25 @@
display: inline-block;
width: 20px;
height: 20px;
- font-size: 0px;
+ font-size: 0;
background: #595959 url(../img/icon_sprite.png) !important;
border: 1px solid #454546;
cursor: pointer;
vertical-align: top;
- -webkit-border-radius: 2px;
- -moz-border-radius: 2px;
+-webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
border-radius: 2px;
- -webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
- -moz-box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
- box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
+-webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
+ -moz-box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
+ box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
+-webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
}
.fn-gantt .nav-link:active {
- -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
- -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
- box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
+-webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
+ -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
+ box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
}
.fn-gantt .navigate .nav-page-back {
diff --git a/index.html b/index.html
index f8434c6..8ba3d3d 100644
--- a/index.html
+++ b/index.html
@@ -2,558 +2,626 @@
jQuery.Gantt
-
-
+
+
+
+
-
-
-
+
+
-
+
-
- jQuery.Gantt
- — Draw Gantt charts with the famous jQuery ease of development
-
+
+ jQuery.Gantt
+ — Draw Gantt charts with the famous jQuery ease of development
+
-
Contributors
-
-
- Marek Bielańczuk wrote the original jQuery.Gantt plugin that this version is based off of.
-
-
- Tait Brown enforced stricter code guidelines by validating the code, updating it to support HTML5 and tweaking the design.
-
-
- Leo Pfeifenberger made major performance updates as well as adding requested features such as click events, state persisting via cookies and scrollToToday on load functionality.
-
-
- Grzegorz Russek helped fix the White Whale of a bug that prevented the hour view rendering correctly. Nice one.
-
-
+
Contributors
+
+
+ Marek Bielańczuk wrote the original jQuery.Gantt plugin that this version is based off of.
+
+
+ Tait Brown enforced stricter code guidelines by validating the code, updating it to support HTML5 and tweaking the design.
+
+
+ Leo Pfeifenberger made major performance updates as well as adding requested features such as click events, state persisting via cookies and scrollToToday on load functionality.
+
+
+ Grzegorz Russek helped fix the White Whale of a bug that prevented the hour view rendering correctly. Nice one.
+
+
+ Many more from the GitHub community
+
+
-
- Example
-
+
+ Example
+
-
+
-
- Gantt Configuration
-
+
+ Gantt Configuration
+
-
+
$(".selector").gantt({
- source: "ajax/data.json",
- scale: "weeks",
- minScale: "weeks",
- maxScale: "months",
- onItemClick: function(data) {
- alert("Item clicked - show some details");
- },
- onAddClick: function(dt, rowId) {
- alert("Empty space clicked - add an item!");
- },
- onRender: function() {
- console.log("chart rendered");
- }
+ source: "ajax/data.json",
+ scale: "weeks",
+ minScale: "weeks",
+ maxScale: "months",
+ onItemClick: function(data) {
+ alert("Item clicked - show some details");
+ },
+ onAddClick: function(dt, rowId) {
+ alert("Empty space clicked - add an item!");
+ },
+ onRender: function() {
+ console.log("chart rendered");
+ }
});
-
-
-
-
- Parameter
-
-
- Default
-
-
- Accepts Type
-
-
-
-
-
-
- source
-
-
- []
-
-
- Array, String (url)
-
-
-
-
- itemsPerPage
-
-
- 7
-
-
- Number
-
-
-
-
- months
-
-
- ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
-
-
- Array
-
-
-
-
- dow
-
-
- ["S", "M", "T", "W", "T", "F", "S"]
-
-
- Array
-
-
-
-
- navigate
-
-
- "buttons"
-
-
- String ("buttons","scroll")
-
-
-
-
- scale
-
-
- "days"
-
-
- String
-
-
-
-
- maxScale
-
-
- "months"
-
-
- String
-
-
-
-
- minScale
-
-
- "hours"
-
-
- String
-
-
-
-
- waitText
-
-
- "Please Wait..."
-
-
- String
-
-
-
-
- onItemClick
-
-
- function (data) { return; }
-
- a JS Function that gets called when clicking on a Gantt-Item. The parameter passed to the function is the dataObj of the item
-
-
-
- onAddClick
-
- function (dt, rowId) { return; }
-
- a JS Function that gets called when clicking on a Gantt-Item. The parameter passed to the function is the DateTime in ms for the clicked Cell, and the ID if the source object (row)
-
-
-
- onRender
-
- function () { return; }
-
- a JS Function called whenever the chart is (re)rendered
-
+
+
-
- useCookie
-
- false
-
- indicates if cookies should be used to track the chart's state (scale, scrollposition) between postpacks
- jquery.cookie.js needs to be referenced for this to work
-
-
-
- scrollToToday
-
- true
-
- Boolean
-
-
-
+
+ Name
+
+
+ Default
+
+
+ Type
+
+
+
+
+
+
+ source
+
+
+ []
+
+
+ Array, string (url)
+
+
+
+
+ itemsPerPage
+
+
+ 7
+
+
+ number
+
+
+
+
+ months
+
+
+ ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
+
+
+ Array (12 strings representing the months of the year)
+
+
+
+
+ dow
+
+
+ ["S", "M", "T", "W", "T", "F", "S"]
+
+
+ Array (7 strings representing the days of the week)
+
+
+
+
+ holidays
+
+
+ undefined
+
+
+ Array of numbers (ms), date strings (see formats ), or Date objects
+
+
+
+
+ navigate
+
+
+ "buttons"
+
+
+ string ("buttons", "scroll")
+
+
+
+
+ scale
+
+
+ "days"
+
+
+ string ("months", "weeks", "days", "hours")
+
+
+
+
+ maxScale
+
+
+ "months"
+
+
+ string ("months", "weeks", "days", "hours")
+
+
+
+
+ minScale
+
+
+ "hours"
+
+
+ string ("months", "weeks", "days", "hours")
+
+
+
+
+ waitText
+
+
+ "Please wait..."
+
+
+ string
+
+
+
+
+ onItemClick
+
+
+ function (data) { return; }
+
+ Function called when clicking on a Gantt item. The parameter passed to the function is the dataObj of the source item, if one was provided.
+
+
+
+ onAddClick
+
+ function (dt, rowId) { return; }
+
+ Function called when clicking on empty space inside the Gantt data panel. The parameter passed to the function is the date/time in milliseconds for the clicked cell, and the ID of the source object (row), if one was provided.
+
+
+
+ onRender
+
+ $.noop
+
+ Function called whenever the chart is (re)rendered
+
+
+
+ useCookie
+
+ false
+
+ indicates whether or not cookies should be used to save and restore the chart's view state (scale, scroll position) between page loads;
+ jquery.cookie needs to be referenced for this to work
+
+
+
+ cookieKey
+
+ "jquery.fn.gantt"
+
+ The prefix used when storing cookies (depends on useCookie being set to true)
+
+
+
+ scrollToToday
+
+ true
+
+ Boolean
+
+
+
-
- Source Configuration
-
+
+ Source Configuration
+
-
-source: [{
- name: "Example",
- desc: "Lorem ipsum dolor sit amet.",
- values: [ ... ]
-}]
+
+source: [
+ {
+ name: "Example",
+ desc: "Lorem ipsum dolor sit amet.",
+ values: [ ... ]
+ id: 1,
+ cssClass: "redLabel"
+ },
+ ... // more rows
+]
-
-
-
-
- Parameter
-
-
- Default
-
-
- Accepts Type
-
-
- Meaning
-
-
-
-
-
-
- name
-
-
- null
-
-
- String
-
-
- Bold value in the left-most column of the gantt row.
-
-
-
-
- desc
-
-
- null
-
-
- String
-
-
- Secondary value in the gantt row.
-
-
-
-
- values
-
-
- null
-
-
- Array
-
-
- Collection of date ranges for gantt items. See next table.
-
-
-
-
+
+
+
+
+ Name
+
+
+ Type
+
+
+ Description
+
+
+
+
+
+
+ name
+
+
+ string
+
+
+ Optional primary label for this row of values; appears in the leftmost column of the row.
+
+
+
+
+ desc
+
+
+ string
+
+
+ Optional secondary label for this row of the Gantt.
+
+
+
+
+ values
+
+
+ Array
+
+
+ Sequence of date ranges for each row of the Gantt. See table below .
+
+
+
+
+ id
+
+
+ string or number
+
+
+ Optional value to be passed as second parameter to onAddClick() callback when triggered.
+
+
+
+
+ cssClass
+
+
+ string
+
+
+ Optional space-separated class names to be applied to this row's labels.
+
+
+
+
-
- Value Configuration
-
+
+ Value Configuration
+
-
-values: [{
- to: "/Date(1328832000000)/",
- from: "/Date(1333411200000)/",
- desc: "Something",
- label: "Example Value",
- customClass: "ganttRed",
- dataObj: foo.bar[i]
-}]
+
+values: [
+ {
+ from: '2012-02-10',
+ to: '2012-04-03',
+ label: "Example Value",
+ desc: "Something",
+ customClass: "ganttRed",
+ dataObj: foo.bar[i]
+ },
+ ... // more items for the row (though Gantt charts traditionally have only one item per row)
+]
-
-
-
-
- Parameter
-
-
- Accepts Type
-
-
- Meaning
-
-
-
-
-
-
- to
-
-
- String (Date)
-
-
- -
-
-
-
-
- from
-
-
- String (Date)
-
-
- -
-
-
-
-
- desc
-
-
- String
-
-
- Text that appears on hover, I think?
-
-
-
-
- label
-
-
- String
-
-
- Appears on the gantt item.
-
-
-
-
- customClass
-
-
- String
-
-
- Custom class to be applied to the gantt item.
-
-
-
-
- dataObj
-
-
- All
-
-
- A data object that is applied directly to the gantt item.
-
-
-
-
+
+
+
+
+ Name
+
+
+ Type
+
+
+ Description
+
+
+
+
+
+
+ from
+
+
+ number (ms), string (see formats )
+
+
+ Start date/time of the Gantt item.
+
+
+
+
+ to
+
+
+ number (ms), string (see formats )
+
+
+ End date/time of the Gantt item.
+
+
+
+
+ label
+
+
+ string
+
+
+ Optional label/name of the Gantt item.
+
+
+
+
+ desc
+
+
+ string
+
+
+ Optional description of the Gantt item, used as HTML content of hover "hint").
+
+
+
+
+ customClass
+
+
+ string
+
+
+ Optional space-separated class names to be applied to the Gantt item.
+
+
+
+
+ dataObj
+
+
+ Any
+
+
+ Optional data object that is stored directly on the Gantt item.
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+ });
+
diff --git a/js/jquery.cookie.js b/js/jquery.cookie.js
deleted file mode 100644
index f8f852c..0000000
--- a/js/jquery.cookie.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/*!
- * jQuery Cookie Plugin v1.3.1
- * https://github.com/carhartl/jquery-cookie
- *
- * Copyright 2013 Klaus Hartl
- * Released under the MIT license
- */
-(function (factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as anonymous module.
- define(['jquery'], factory);
- } else {
- // Browser globals.
- factory(jQuery);
- }
-}(function ($) {
-
- var pluses = /\+/g;
-
- function decode(s) {
- if (config.raw) {
- return s;
- }
- return decodeURIComponent(s.replace(pluses, ' '));
- }
-
- function decodeAndParse(s) {
- if (s.indexOf('"') === 0) {
- // This is a quoted cookie as according to RFC2068, unescape...
- s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
- }
-
- s = decode(s);
-
- try {
- return config.json ? JSON.parse(s) : s;
- } catch(e) {}
- }
-
- var config = $.cookie = function (key, value, options) {
-
- // Write
- if (value !== undefined) {
- options = $.extend({}, config.defaults, options);
-
- if (typeof options.expires === 'number') {
- var days = options.expires, t = options.expires = new Date();
- t.setDate(t.getDate() + days);
- }
-
- value = config.json ? JSON.stringify(value) : String(value);
-
- return (document.cookie = [
- config.raw ? key : encodeURIComponent(key),
- '=',
- config.raw ? value : encodeURIComponent(value),
- options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
- options.path ? '; path=' + options.path : '',
- options.domain ? '; domain=' + options.domain : '',
- options.secure ? '; secure' : ''
- ].join(''));
- }
-
- // Read
- var cookies = document.cookie.split('; ');
- var result = key ? undefined : {};
- for (var i = 0, l = cookies.length; i < l; i++) {
- var parts = cookies[i].split('=');
- var name = decode(parts.shift());
- var cookie = parts.join('=');
-
- if (key && key === name) {
- result = decodeAndParse(cookie);
- break;
- }
-
- if (!key) {
- result[name] = decodeAndParse(cookie);
- }
- }
-
- return result;
- };
-
- config.defaults = {};
-
- $.removeCookie = function (key, options) {
- if ($.cookie(key) !== undefined) {
- // Must not alter options, thus extending a fresh object...
- $.cookie(key, '', $.extend({}, options, { expires: -1 }));
- return true;
- }
- return false;
- };
-
-}));
diff --git a/js/jquery.fn.gantt.js b/js/jquery.fn.gantt.js
index 4629ffc..fcb582f 100644
--- a/js/jquery.fn.gantt.js
+++ b/js/jquery.fn.gantt.js
@@ -1,210 +1,200 @@
-// jQuery Gantt Chart
-// ==================
-
-// Basic usage:
-
-// $(".selector").gantt({
-// source: "ajax/data.json",
-// scale: "weeks",
-// minScale: "weeks",
-// maxScale: "months",
-// onItemClick: function(data) {
-// alert("Item clicked - show some details");
-// },
-// onAddClick: function(dt, rowId) {
-// alert("Empty space clicked - add an item!");
-// },
-// onRender: function() {
-// console.log("chart rendered");
-// }
-// });
-
-//
-/*jshint shadow:true, laxbreak:true, jquery:true, strict:true, trailing:true */
+/**
+ * jQuery Gantt Chart
+ *
+ * @see http://taitems.github.io/jQuery.Gantt/
+ * @license MIT
+ */
+/*jshint camelcase:true, freeze:true, jquery:true */
(function ($, undefined) {
-
"use strict";
+ var UTC_DAY_IN_MS = 24 * 60 * 60 * 1000;
+
+ // custom selector `:findday` used to match on specified day in ms.
+ //
+ // The selector is passed a date in ms and elements are added to the
+ // selection filter if the element date matches, as determined by the
+ // id attribute containing a parsable date in ms.
+ function findDay(elt, text) {
+ var cd = new Date(parseInt(text, 10));
+ cd.setHours(0, 0, 0, 0);
+ var id = $(elt).attr("id") || "";
+ var si = id.indexOf("-") + 1;
+ var ed = new Date(parseInt(id.substring(si, id.length), 10));
+ ed.setHours(0, 0, 0, 0);
+ return cd.getTime() === ed.getTime();
+ }
+ $.expr.pseudos.findday = $.expr.createPseudo ?
+ $.expr.createPseudo(function(text) {
+ return function(elt) {
+ return findDay(elt, text);
+ };
+ }) :
+ function(elt, i, match) {
+ return findDay(elt, match[3]);
+ };
+
+ // custom selector `:findweek` used to match on specified week in ms.
+ function findWeek(elt, text) {
+ var cd = new Date(parseInt(text, 10));
+ var y = cd.getFullYear();
+ var w = cd.getWeekOfYear();
+ var m = cd.getMonth();
+ if (m === 11 && w === 1) {
+ y++;
+ } else if (!m && w > 51) {
+ y--;
+ }
+ cd = y + "-" + w;
+ var id = $(elt).attr("id") || "";
+ var si = id.indexOf("-") + 1;
+ var ed = id.substring(si, id.length);
+ return cd === ed;
+ }
+ $.expr.pseudos.findweek = $.expr.createPseudo ?
+ $.expr.createPseudo(function(text) {
+ return function(elt) {
+ return findWeek(elt, text);
+ };
+ }) :
+ function(elt, i, match) {
+ return findWeek(elt, match[3]);
+ };
+
+ // custom selector `:findmonth` used to match on specified month in ms.
+ function findMonth(elt, text) {
+ var cd = new Date(parseInt(text, 10));
+ cd = cd.getFullYear() + "-" + cd.getMonth();
+ var id = $(elt).attr("id") || "";
+ var si = id.indexOf("-") + 1;
+ var ed = id.substring(si, id.length);
+ return cd === ed;
+ }
+ $.expr[':'].findmonth = $.expr.createPseudo ?
+ $.expr.createPseudo(function(text) {
+ return function(elt) {
+ return findMonth(elt, text);
+ };
+ }) :
+ function(elt, i, match) {
+ return findMonth(elt, match[3]);
+ };
+
+ // Date prototype helpers
+ // ======================
+
+ // `getWeekId` returns a string in the form of 'dh-YYYY-WW', where WW is
+ // the week # for the year.
+ // It is used to add an id to the week divs
+ Date.prototype.getWeekId = function () {
+ var y = this.getFullYear();
+ var w = this.getWeekOfYear();
+ var m = this.getMonth();
+ if (m === 11 && w === 1) {
+ y++;
+ } else if (!m && w > 51) {
+ y--;
+ }
+ return 'dh-' + y + "-" + w;
+ };
+
+ // `getRepDate` returns the milliseconds since the epoch for a given date
+ // depending on the active scale
+ Date.prototype.getRepDate = function (scale) {
+ switch (scale) {
+ case "hours":
+ return this.getTime();
+ case "weeks":
+ return this.getDayForWeek().getTime();
+ case "months":
+ return new Date(this.getFullYear(), this.getMonth(), 1).getTime();
+ case "days":
+ /* falls through */
+ default:
+ return this.getTime();
+ }
+ };
+
+ // `getDayOfYear` returns the day number for the year
+ Date.prototype.getDayOfYear = function () {
+ var year = this.getFullYear();
+ return (Date.UTC(year, this.getMonth(), this.getDate()) -
+ Date.UTC(year, 0, 0)) / UTC_DAY_IN_MS;
+ };
+
+ // Use ISO week by default
+ //TODO: make these options.
+ var firstDay = 1; // ISO week starts with Monday (1); use Sunday (0) for, e.g., North America
+ var weekOneDate = 4; // ISO week one always contains 4 Jan; use 1 Jan for, e.g., North America
+
+ // `getWeekOfYear` returns the week number for the year
+ //TODO: fix bug when firstDay=6/weekOneDate=1 : https://github.com/moment/moment/issues/2115
+ Date.prototype.getWeekOfYear = function () {
+ var year = this.getFullYear(),
+ month = this.getMonth(),
+ date = this.getDate(),
+ day = this.getDay();
+ //var diff = weekOneDate - day + 7 * (day < firstDay ? -1 : 1);
+ var diff = weekOneDate - day;
+ if (day < firstDay) {
+ diff -= 7;
+ }
+ if (diff + 7 < weekOneDate - firstDay) {
+ diff += 7;
+ }
+ return Math.ceil(new Date(year, month, date + diff).getDayOfYear() / 7);
+ };
+
+ // `getDayForWeek` returns the first day of this Date's week
+ Date.prototype.getDayForWeek = function () {
+ var day = this.getDay();
+ var diff = (day < firstDay ? -7 : 0) + firstDay - day;
+ return new Date( this.getFullYear(), this.getMonth(), this.getDate() + diff );
+ };
+
$.fn.gantt = function (options) {
- var cookieKey = "jquery.fn.gantt";
var scales = ["hours", "days", "weeks", "months"];
//Default settings
var settings = {
source: [],
+ holidays: [],
+ // paging
itemsPerPage: 7,
- months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ // localisation
dow: ["S", "M", "T", "W", "T", "F", "S"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ waitText: "Please wait...",
+ // navigation
navigate: "buttons",
- scale: "days",
+ scrollToToday: true,
+ // cookie options
useCookie: false,
+ cookieKey: "jquery.fn.gantt",
+ // scale parameters
+ scale: "days",
maxScale: "months",
minScale: "hours",
- waitText: "Please wait...",
+ // callbacks
onItemClick: function (data) { return; },
- onAddClick: function (data) { return; },
- onRender: function() { return; },
- scrollToToday: true
+ onAddClick: function (dt, rowId) { return; },
+ onRender: $.noop
};
- /**
- * Extend options with default values
- */
- if (options) {
- $.extend(settings, options);
- }
+ // read options
+ $.extend(settings, options);
// can't use cookie if don't have `$.cookie`
settings.useCookie = settings.useCookie && $.isFunction($.cookie);
- // custom selector `:findday` used to match on specified day in ms.
- //
- // The selector is passed a date in ms and elements are added to the
- // selection filter if the element date matches, as determined by the
- // id attribute containing a parsable date in ms.
- $.extend($.expr[":"], {
- findday: function (a, i, m) {
- var cd = new Date(parseInt(m[3], 10));
- var id = $(a).attr("id");
- id = id ? id : "";
- var si = id.indexOf("-") + 1;
- var ed = new Date(parseInt(id.substring(si, id.length), 10));
- cd = new Date(cd.getFullYear(), cd.getMonth(), cd.getDate());
- ed = new Date(ed.getFullYear(), ed.getMonth(), ed.getDate());
- return cd.getTime() === ed.getTime();
- }
- });
- // custom selector `:findweek` used to match on specified week in ms.
- $.extend($.expr[":"], {
- findweek: function (a, i, m) {
- var cd = new Date(parseInt(m[3], 10));
- var id = $(a).attr("id");
- id = id ? id : "";
- var si = id.indexOf("-") + 1;
- cd = cd.getFullYear() + "-" + cd.getDayForWeek().getWeekOfYear();
- var ed = id.substring(si, id.length);
- return cd === ed;
- }
- });
- // custom selector `:findmonth` used to match on specified month in ms.
- $.extend($.expr[":"], {
- findmonth: function (a, i, m) {
- var cd = new Date(parseInt(m[3], 10));
- cd = cd.getFullYear() + "-" + cd.getMonth();
- var id = $(a).attr("id");
- id = id ? id : "";
- var si = id.indexOf("-") + 1;
- var ed = id.substring(si, id.length);
- return cd === ed;
- }
- });
-
- // Date prototype helpers
- // ======================
-
- // `getWeekId` returns a string in the form of 'dh-YYYY-WW', where WW is
- // the week # for the year.
- // It is used to add an id to the week divs
- Date.prototype.getWeekId = function () {
- var y = this.getFullYear();
- var w = this.getDayForWeek().getWeekOfYear();
- var m = this.getMonth();
- if (m === 11 && w === 1) {
- y++;
- }
- return 'dh-' + y + "-" + w;
- };
-
- // `getRepDate` returns the seconds since the epoch for a given date
- // depending on the active scale
- Date.prototype.getRepDate = function () {
- switch (settings.scale) {
- case "hours":
- return this.getTime();
- case "weeks":
- return this.getDayForWeek().getTime();
- case "months":
- return new Date(this.getFullYear(), this.getMonth(), 1).getTime();
- default:
- return this.getTime();
- }
- };
-
- // `getDayOfYear` returns the day number for the year
- Date.prototype.getDayOfYear = function () {
- var fd = new Date(this.getFullYear(), 0, 0);
- var sd = new Date(this.getFullYear(), this.getMonth(), this.getDate());
- return Math.ceil((sd - fd) / 86400000);
- };
-
- // `getWeekOfYear` returns the week number for the year
- Date.prototype.getWeekOfYear = function () {
- var ys = new Date(this.getFullYear(), 0, 1);
- var sd = new Date(this.getFullYear(), this.getMonth(), this.getDate());
- if (ys.getDay() > 3) {
- ys = new Date(sd.getFullYear(), 0, (7 - ys.getDay()));
- }
- var daysCount = sd.getDayOfYear() - ys.getDayOfYear();
- return Math.ceil(daysCount / 7);
-
- };
-
- // `getDaysInMonth` returns the number of days in a month
- Date.prototype.getDaysInMonth = function () {
- return 32 - new Date(this.getFullYear(), this.getMonth(), 32).getDate();
- };
-
- // `hasWeek` returns `true` if the date resides on a week boundary
- // **????????????????? Don't know if this is true**
- Date.prototype.hasWeek = function () {
- var df = new Date(this.valueOf());
- df.setDate(df.getDate() - df.getDay());
- var dt = new Date(this.valueOf());
- dt.setDate(dt.getDate() + (6 - dt.getDay()));
-
- if (df.getMonth() === dt.getMonth()) {
- return true;
- } else {
- return (df.getMonth() === this.getMonth() && dt.getDate() < 4) || (df.getMonth() !== this.getMonth() && dt.getDate() >= 4);
- }
- };
-
- // `getDayForWeek` returns the Date object for the starting date of
- // the week # for the year
- Date.prototype.getDayForWeek = function () {
- var df = new Date(this.valueOf());
- df.setDate(df.getDate() - df.getDay());
- var dt = new Date(this.valueOf());
- dt.setDate(dt.getDate() + (6 - dt.getDay()));
- if ((df.getMonth() === dt.getMonth()) || (df.getMonth() !== dt.getMonth() && dt.getDate() >= 4)) {
- return new Date(dt.setDate(dt.getDate() - 3));
- } else {
- return new Date(df.setDate(df.getDate() + 3));
- }
- };
-
- // fixes https://github.com/taitems/jQuery.Gantt/issues/62
- function ktkGetNextDate(currentDate, scaleStep) {
- for(var minIncrements = 1;; minIncrements++) {
- var nextDate = new Date(currentDate);
- nextDate.setHours(currentDate.getHours() + scaleStep * minIncrements);
-
- if (nextDate.getTime() !== currentDate.getTime()) {
- return nextDate;
- }
-
- // If code reaches here, it's because current didn't really increment (invalid local time) because of daylight-saving adjustments
- // => retry adding 2, 3, 4 hours, and so on (until nextDate > current)
- }
- }
-
// Grid management
// ===============
// Core object is responsible for navigation and rendering
var core = {
// Return the element whose topmost point lies under the given point
- // Normalizes for old browsers
+ // Normalizes for old browsers (NOTE: doesn't work when element is outside viewport)
+ //TODO: https://github.com/taitems/jQuery.Gantt/issues/137
elementFromPoint: (function(){ // IIFE
// version for normal browsers
if (document.compatMode === "CSS1Compat") {
@@ -240,7 +230,7 @@
// **Setup the initial view**
// Here we calculate the number of rows, pages and visible start
- // and end dates once the data is ready
+ // and end dates once the data are ready
init: function (element) {
element.rowsNum = element.data.length;
element.pageCount = Math.ceil(element.rowsNum / settings.itemsPerPage);
@@ -251,7 +241,7 @@
/* core.render(element); */
- core.waitToggle(element, true, function () { core.render(element); });
+ core.waitToggle(element, function () { core.render(element); });
},
// **Render the grid**
@@ -260,7 +250,7 @@
var $leftPanel = core.leftPanel(element);
content.append($leftPanel);
var $rightPanel = core.rightPanel(element, $leftPanel);
- var mLeft, hPos;
+ var pLeft, hPos;
content.append($rightPanel);
content.append(core.navigation(element));
@@ -271,7 +261,7 @@
$(element).empty().append(element.gantt);
- element.scrollNavigation.panelMargin = parseInt($dataPanel.css("margin-left").replace("px", ""), 10);
+ element.scrollNavigation.panelMargin = parseInt($dataPanel.css("left").replace("px", ""), 10);
element.scrollNavigation.panelMaxPos = ($dataPanel.width() - $rightPanel.width());
element.scrollNavigation.canScroll = ($dataPanel.width() > $rightPanel.width());
@@ -281,7 +271,7 @@
// Set a cookie to record current position in the view
if (settings.useCookie) {
- var sc = $.cookie(this.cookieKey + "ScrollPos");
+ var sc = $.cookie(settings.cookieKey + "ScrollPos");
if (sc) {
element.hPosition = sc;
}
@@ -295,23 +285,19 @@
} else {
if (element.hPosition !== 0) {
if (element.scaleOldWidth) {
- mLeft = ($dataPanel.width() - $rightPanel.width());
- hPos = mLeft * element.hPosition / element.scaleOldWidth;
- hPos = hPos > 0 ? 0 : hPos;
- $dataPanel.css({ "margin-left": hPos + "px" });
- element.scrollNavigation.panelMargin = hPos;
- element.hPosition = hPos;
+ pLeft = ($dataPanel.width() - $rightPanel.width());
+ hPos = pLeft * element.hPosition / element.scaleOldWidth;
+ element.hPosition = hPos > 0 ? 0 : hPos;
element.scaleOldWidth = null;
- } else {
- $dataPanel.css({ "margin-left": element.hPosition + "px" });
- element.scrollNavigation.panelMargin = element.hPosition;
}
+ $dataPanel.css({ "left": element.hPosition });
+ element.scrollNavigation.panelMargin = element.hPosition;
}
core.repositionLabel(element);
}
$dataPanel.css({ height: $leftPanel.height() });
- core.waitToggle(element, false);
+ core.waitToggle(element);
settings.onRender();
},
@@ -320,26 +306,38 @@
/* Left panel */
var ganttLeftPanel = $('
')
.append($('
')
- .css("height", tools.getCellSize() * element.headerRows + "px")
- .css("width", "100%"));
+ .css("height", tools.getCellSize() * element.headerRows));
var entries = [];
$.each(element.data, function (i, entry) {
- if (i >= element.pageNum * settings.itemsPerPage && i < (element.pageNum * settings.itemsPerPage + settings.itemsPerPage)) {
- entries.push('');
+ if (i >= element.pageNum * settings.itemsPerPage &&
+ i < (element.pageNum * settings.itemsPerPage + settings.itemsPerPage)) {
+ var dataId = ('id' in entry) ? '" data-id="' + entry.id : '';
+ entries.push(
+ '');
if (entry.desc) {
- entries.push('');
- entries.push('' + entry.desc + ' ');
- entries.push('
');
+ entries.push(
+ '' +
+ '' +
+ entry.desc +
+ ' ' +
+ '
');
}
}
});
- ganttLeftPanel.append(entries.join(""));
- return ganttLeftPanel;
+ return ganttLeftPanel.append(entries.join(""));
},
// Create and return the data panel element
@@ -347,11 +345,12 @@
var dataPanel = $('
');
// Handle mousewheel events for scrolling the data panel
- var wheel = 'onwheel' in element ? 'wheel' : document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll';
+ var wheel = 'onwheel' in element ?
+ 'wheel' : document.onmousewheel !== undefined ?
+ 'mousewheel' : 'DOMMouseScroll';
$(element).on(wheel, function (e) { core.wheelScroll(element, e); });
- // Handle click events and dispatch to registered `onAddClick`
- // function
+ // Handle click events and dispatch to registered `onAddClick` function
dataPanel.click(function (e) {
e.stopPropagation();
@@ -359,21 +358,19 @@
var leftpanel = $(element).find(".fn-gantt .leftPanel");
var datapanel = $(element).find(".fn-gantt .dataPanel");
switch (settings.scale) {
- case "weeks":
- corrY = tools.getCellSize() * 2;
- break;
- case "months":
- corrY = tools.getCellSize();
- break;
- case "hours":
- corrY = tools.getCellSize() * 4;
- break;
- case "days":
- corrY = tools.getCellSize() * 3;
- break;
- default:
- corrY = tools.getCellSize() * 2;
- break;
+ case "months":
+ corrY = tools.getCellSize();
+ break;
+ case "hours":
+ corrY = tools.getCellSize() * 4;
+ break;
+ case "days":
+ corrY = tools.getCellSize() * 3;
+ break;
+ case "weeks":
+ /* falls through */
+ default:
+ corrY = tools.getCellSize() * 2;
}
/* Adjust, so get middle of elm
@@ -389,16 +386,16 @@
col = $(col);
}
- var dt = col.attr("repdate");
+ var dt = col.data("repdate");
// Find row where click occurred
var row = core.elementFromPoint(leftpanel.offset().left + leftpanel.width() - 10, e.pageY);
- // Was the lable clicked directly?
+ // Was the label clicked directly?
if (row.className.indexOf("fn-label") === 0) {
row = $(row.parentNode);
} else {
row = $(row);
}
- var rowId = row.data().id;
+ var rowId = row.data('id');
// Dispatch user registered function with the DateTime in ms
// and the id if the clicked object is a row
@@ -407,346 +404,368 @@
return dataPanel;
},
- // Creates and return the right panel containing the year/week/day
- // header
+ // Creates and return the right panel containing the year/week/day header
rightPanel: function (element, leftPanel /* <- never used? */) {
-
var range = null;
// Days of the week have a class of one of
// `sn` (Sunday), `sa` (Saturday), or `wd` (Weekday)
var dowClass = ["sn", "wd", "wd", "wd", "wd", "wd", "sa"];
- //TODO: was someone planning to allow styles to stretch to the bottom of the chart?
+ //unused: was someone planning to allow styles to stretch to the bottom of the chart?
//var gridDowClass = [" sn", "", "", "", "", "", " sa"];
- var yearArr = ['
'];
- var daysInYear = 0;
+ var yearArr = [];
+ var scaleUnitsThisYear = 0;
- var monthArr = ['
'];
- var daysInMonth = 0;
+ var monthArr = [];
+ var scaleUnitsThisMonth = 0;
var dayArr = [];
-
var hoursInDay = 0;
var dowArr = [];
-
var horArr = [];
-
var today = new Date();
- today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
+ today.setHours(0, 0, 0, 0);
+
+ // reused variables
+ var $row = $('');
+ var i, len;
+ var year, month, week, day;
+ var rday, dayClass;
+ var dataPanel, dataPanelWidth;
// Setup the headings based on the chosen `settings.scale`
switch (settings.scale) {
- // **Hours**
- case "hours":
-
- range = tools.parseTimeRange(element.dateStart, element.dateEnd, element.scaleStep);
-
- var year = range[0].getFullYear();
- var month = range[0].getMonth();
- var day = range[0];
-
- for (var i = 0, len = range.length; i < len; i++) {
- var rday = range[i];
-
- // Fill years
- var rfy = rday.getFullYear();
- if (rfy !== year) {
- yearArr.push(
- (''));
-
- year = rfy;
- daysInYear = 0;
- }
- daysInYear++;
-
-
- // Fill months
- var rm = rday.getMonth();
- if (rm !== month) {
- monthArr.push(
- (''));
-
- month = rm;
- daysInMonth = 0;
- }
- daysInMonth++;
-
-
- // Fill days & hours
-
- var rgetDay = rday.getDay();
- var getDay = day.getDay();
- var day_class = dowClass[rgetDay];
- if (tools.isHoliday(rday)) {
- day_class = "holiday";
- }
- if (rgetDay !== getDay) {
- var day_class2 = (today - day === 0) ? "today" : tools.isHoliday( day.getTime() ) ? "holiday" : dowClass[getDay];
-
- dayArr.push(' '
- + '
' + day.getDate() + '
');
- dowArr.push(' '
- + '
' + settings.dow[getDay] + '
');
-
- day = rday;
- hoursInDay = 0;
- }
- hoursInDay++;
-
- horArr.push(''
- + rday.getHours()
- + '
');
+ // **Hours**
+ case "hours":
+ range = tools.parseTimeRange(element.dateStart, element.dateEnd, element.scaleStep);
+ dataPanelWidth = range.length * tools.getCellSize();
+
+ year = range[0].getFullYear();
+ month = range[0].getMonth();
+ day = range[0];
+
+ for (i = 0, len = range.length; i < len; i++) {
+ rday = range[i];
+
+ // Fill years
+ var rfy = rday.getFullYear();
+ if (rfy !== year) {
+ yearArr.push(
+ '');
+
+ year = rfy;
+ scaleUnitsThisYear = 0;
}
+ scaleUnitsThisYear++;
- // Last year
- yearArr.push(
- '');
-
- // Last month
- monthArr.push(
- '');
-
- var day_class = dowClass[day.getDay()];
+ // Fill months
+ var rm = rday.getMonth();
+ if (rm !== month) {
+ monthArr.push(
+ '' +
+ settings.months[month] +
+ '
');
- if ( tools.isHoliday(day) ) {
- day_class = "holiday";
+ month = rm;
+ scaleUnitsThisMonth = 0;
}
-
- dayArr.push(' '
- + '
' + day.getDate() + '
');
-
- dowArr.push(' '
- + '
' + settings.dow[day.getDay()] + '
');
-
- var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());
-
-
- // Append panel elements
- dataPanel.append(yearArr.join(""));
- dataPanel.append(monthArr.join(""));
- dataPanel.append($('
').html(dayArr.join("")));
- dataPanel.append($('
').html(dowArr.join("")));
- dataPanel.append($('
').html(horArr.join("")));
-
- break;
-
- // **Weeks**
- case "weeks":
- range = tools.parseWeeksRange(element.dateStart, element.dateEnd);
- yearArr = ['
'];
- monthArr = ['
'];
- var year = range[0].getFullYear();
- var month = range[0].getMonth();
- var day = range[0];
-
- for (var i = 0, len = range.length; i < len; i++) {
- var rday = range[i];
-
- // Fill years
- if (rday.getFullYear() !== year) {
- yearArr.push(
- (''));
- year = rday.getFullYear();
- daysInYear = 0;
- }
- daysInYear++;
-
- // Fill months
- if (rday.getMonth() !== month) {
- monthArr.push(
- (''));
- month = rday.getMonth();
- daysInMonth = 0;
- }
- daysInMonth++;
-
- // Fill weeks
- dayArr.push(' '
- + '
' + rday.getWeekOfYear() + '
');
+ scaleUnitsThisMonth++;
+
+ // Fill days & hours
+ var rgetDay = rday.getDay();
+ var getDay = day.getDay();
+ if (rgetDay !== getDay) {
+ dayClass = (today - day === 0) ?
+ "today" : tools.isHoliday( day.getTime() ) ?
+ "holiday" : dowClass[getDay];
+
+ dayArr.push(
+ '' +
+ '
' + day.getDate() + '
');
+ dowArr.push(
+ '' +
+ '
' + settings.dow[getDay] + '
');
+
+ day = rday;
+ hoursInDay = 0;
}
+ hoursInDay++;
+ dayClass = dowClass[rgetDay];
+ if (tools.isHoliday(rday)) {
+ dayClass = "holiday";
+ }
+ horArr.push(
+ '' +
+ rday.getHours() +
+ '
');
+ }
- // Last year
- yearArr.push(
- '');
+ // Last year
+ yearArr.push(
+ '');
- // Last month
- monthArr.push(
- '');
+ // Last month
+ monthArr.push(
+ '' +
+ settings.months[month] +
+ '
');
- var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());
+ dayClass = dowClass[day.getDay()];
- dataPanel.append(yearArr.join("") + monthArr.join("") + dayArr.join("") + (dowArr.join("")));
+ if ( tools.isHoliday(day) ) {
+ dayClass = "holiday";
+ }
- break;
+ dayArr.push(
+ '' +
+ '
' + day.getDate() + '
');
+
+ dowArr.push(
+ '' +
+ '
' + settings.dow[day.getDay()] + '
');
+
+ dataPanel = core.dataPanel(element, dataPanelWidth);
+
+ // Append panel elements
+ dataPanel.append(
+ $row.clone().html(yearArr.join("")),
+ $row.clone().html(monthArr.join("")),
+ $row.clone().html(dayArr.join("")),
+ $row.clone().html(dowArr.join("")),
+ $row.clone().html(horArr.join(""))
+ );
+ break;
- // **Months**
- case 'months':
- range = tools.parseMonthsRange(element.dateStart, element.dateEnd);
-
- var year = range[0].getFullYear();
- var month = range[0].getMonth();
- var day = range[0];
-
- for (var i = 0, len = range.length; i < len; i++) {
- var rday = range[i];
-
- // Fill years
- if (rday.getFullYear() !== year) {
- yearArr.push(
- (''));
- year = rday.getFullYear();
- daysInYear = 0;
- }
- daysInYear++;
- monthArr.push('' + (1 + rday.getMonth()) + '
');
+ // **Weeks**
+ case "weeks":
+ range = tools.parseWeeksRange(element.dateStart, element.dateEnd);
+ dataPanelWidth = range.length * tools.getCellSize();
+
+ year = range[0].getFullYear();
+ month = range[0].getMonth();
+ week = range[0].getWeekOfYear();
+ var diff;
+
+ for (i = 0, len = range.length; i < len; i++) {
+ rday = range[i];
+
+ // Fill years
+ if (week > (week = rday.getWeekOfYear())) {
+ // partial weeks to subtract from year header
+ diff = rday.getDate() - 1;
+ // offset one month (December) if week starts in last year
+ diff -= !rday.getMonth() ? 0 : 31;
+ diff /= 7;
+ yearArr.push(
+ '');
+ year++;
+ scaleUnitsThisYear = diff;
}
+ scaleUnitsThisYear++;
+
+ // Fill months
+ if (rday.getMonth() !== month) {
+ // partial weeks to subtract from month header
+ diff = rday.getDate() - 1;
+ // offset one week if week starts in last month
+ //diff -= (diff <= 6) ? 0 : 7;
+ diff /= 7;
+ monthArr.push(
+ '' +
+ settings.months[month] +
+ '
');
+ month = rday.getMonth();
+ scaleUnitsThisMonth = diff;
+ }
+ scaleUnitsThisMonth++;
+
+ // Fill weeks
+ dayArr.push(
+ '');
+ }
-
- // Last year
- yearArr.push(
- '');
-
- // Last month
+ // Last year
+ yearArr.push(
+ '');
+
+ // Last month
+ monthArr.push(
+ '' +
+ settings.months[month] +
+ '
');
+
+ dataPanel = core.dataPanel(element, dataPanelWidth);
+
+ // Append panel elements
+ dataPanel.append(
+ $row.clone().html(yearArr.join("")),
+ $row.clone().html(monthArr.join("")),
+ $row.clone().html(dayArr.join(""))
+ );
+ break;
+
+ // **Months**
+ case 'months':
+ range = tools.parseMonthsRange(element.dateStart, element.dateEnd);
+ dataPanelWidth = range.length * tools.getCellSize();
+
+ year = range[0].getFullYear();
+ month = range[0].getMonth();
+
+ for (i = 0, len = range.length; i < len; i++) {
+ rday = range[i];
+
+ // Fill years
+ if (rday.getFullYear() !== year) {
+ yearArr.push(
+ '');
+ year = rday.getFullYear();
+ scaleUnitsThisYear = 0;
+ }
+ scaleUnitsThisYear++;
monthArr.push(
- '');
-
- var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());
-
- // Append panel elements
- dataPanel.append(yearArr.join(""));
- dataPanel.append(monthArr.join(""));
- dataPanel.append($('
').html(dayArr.join("")));
- dataPanel.append($('
').html(dowArr.join("")));
-
- break;
-
- // **Days (default)**
- default:
- range = tools.parseDateRange(element.dateStart, element.dateEnd);
-
- var dateBefore = ktkGetNextDate(range[0], -1);
- var year = dateBefore.getFullYear();
- var month = dateBefore.getMonth();
- var day = dateBefore; // <- never used?
-
- for (var i = 0, len = range.length; i < len; i++) {
- var rday = range[i];
-
- // Fill years
- if (rday.getFullYear() !== year) {
- yearArr.push(
- (''));
- year = rday.getFullYear();
- daysInYear = 0;
- }
- daysInYear++;
-
- // Fill months
- if (rday.getMonth() !== month) {
- monthArr.push(
- (''));
- month = rday.getMonth();
- daysInMonth = 0;
- }
- daysInMonth++;
+ '' +
+ (1 + rday.getMonth()) + '
');
+ }
- var getDay = rday.getDay();
- var day_class = dowClass[getDay];
- if ( tools.isHoliday(rday) ) {
- day_class = "holiday";
- }
+ // Last year
+ yearArr.push(
+ '');
- dayArr.push('');
- dowArr.push('');
- } //for
-
- // Last year
- yearArr.push(
- '');
-
- // Last month
- monthArr.push(
- '');
-
- var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());
+ dataPanel = core.dataPanel(element, dataPanelWidth);
+ // Append panel elements
+ dataPanel.append(
+ $row.clone().html(yearArr.join("")),
+ $row.clone().html(monthArr.join(""))
+ );
+ break;
- // Append panel elements
+ // **Days (default)**
+ default:
+ range = tools.parseDateRange(element.dateStart, element.dateEnd);
+ dataPanelWidth = range.length * tools.getCellSize();
+
+ year = range[0].getFullYear();
+ month = range[0].getMonth();
+
+ for (i = 0, len = range.length; i < len; i++) {
+ rday = range[i];
+
+ // Fill years
+ if (rday.getFullYear() !== year) {
+ yearArr.push(
+ '');
+ year = rday.getFullYear();
+ scaleUnitsThisYear = 0;
+ }
+ scaleUnitsThisYear++;
+
+ // Fill months
+ if (rday.getMonth() !== month) {
+ monthArr.push(
+ '' +
+ settings.months[month] +
+ '
');
+ month = rday.getMonth();
+ scaleUnitsThisMonth = 0;
+ }
+ scaleUnitsThisMonth++;
- dataPanel.append(yearArr.join(""));
- dataPanel.append(monthArr.join(""));
- dataPanel.append($('
').html(dayArr.join("")));
- dataPanel.append($('
').html(dowArr.join("")));
+ day = rday.getDay();
+ dayClass = dowClass[day];
+ if ( tools.isHoliday(rday) ) {
+ dayClass = "holiday";
+ }
- break;
+ dayArr.push(
+ '');
+ dowArr.push(
+ '');
+ } //for
+
+ // Last year
+ yearArr.push(
+ '');
+
+ // Last month
+ monthArr.push(
+ '' +
+ settings.months[month] +
+ '
');
+
+ dataPanel = core.dataPanel(element, dataPanelWidth);
+
+ // Append panel elements
+ dataPanel.append(
+ $row.clone().html(yearArr.join("")),
+ $row.clone().html(monthArr.join("")),
+ $row.clone().html(dayArr.join("")),
+ $row.clone().html(dowArr.join(""))
+ );
}
return $('
').append(dataPanel);
@@ -762,7 +781,7 @@
.append($('
')
.append($('
')
.append($(' ')
- .html('<')
+ .html('↑')
.click(function () {
core.navigatePage(element, -1);
}))
@@ -770,7 +789,7 @@
.append($(' ')
.html(element.pageNum + 1 + ' / ' + element.pageCount)))
.append($(' ')
- .html('>')
+ .html('↓')
.click(function () {
core.navigatePage(element, 1);
}))
@@ -867,15 +886,15 @@
} else {
ganttNavigate = $('
')
.append($(' ')
- .html('<')
+ .html('↑')
.click(function () {
core.navigatePage(element, -1);
}))
.append($('
')
.append($(' ')
- .html(element.pageNum + 1 + ' of ' + element.pageCount)))
+ .html(element.pageNum + 1 + ' / ' + element.pageCount)))
.append($(' ')
- .html('>')
+ .html('↓')
.click(function () {
core.navigatePage(element, 1);
}))
@@ -925,32 +944,25 @@
core.zoomInOut(element, 1);
}));
}
- return $('
').append(ganttNavigate);
+ return $('
').append(ganttNavigate);
},
// **Progress Bar**
- // Return an element representing a progress of position within
- // the entire chart
- createProgressBar: function (days, cls, desc, label, dataObj) {
- var cellWidth = tools.getCellSize();
- var barMarg = tools.getProgressBarMargin() || 0;
+ // Return an element representing a progress of position within the entire chart
+ createProgressBar: function (label, desc, classNames, dataObj) {
+ label = label || "";
var bar = $('')
- .addClass(cls)
- .css({
- width: ((cellWidth * days) - barMarg) + 2
- })
.data("dataObj", dataObj);
-
if (desc) {
bar
- .mouseover(function (e) {
+ .mouseenter(function (e) {
var hint = $('
').html(desc);
$("body").append(hint);
hint.css("left", e.pageX);
hint.css("top", e.pageY);
hint.show();
})
- .mouseout(function () {
+ .mouseleave(function () {
$(".fn-gantt-hint").remove();
})
.mousemove(function (e) {
@@ -958,6 +970,9 @@
$(".fn-gantt-hint").css("top", e.pageY + 15);
});
}
+ if (classNames) {
+ bar.addClass(classNames);
+ }
bar.click(function (e) {
e.stopPropagation();
settings.onItemClick($(this).data("dataObj"));
@@ -968,26 +983,29 @@
// Remove the `wd` (weekday) class and add `today` class to the
// current day/week/month (depending on the current scale)
markNow: function (element) {
+ var cd = new Date().setHours(0, 0, 0, 0);
switch (settings.scale) {
- case "weeks":
- var cd = Date.parse(new Date());
- cd = (Math.floor(cd / 36400000) * 36400000);
- $(element).find(':findweek("' + cd + '")').removeClass('wd').addClass('today');
- break;
- case "months":
- $(element).find(':findmonth("' + new Date().getTime() + '")').removeClass('wd').addClass('today');
- break;
- default:
- var cd = Date.parse(new Date());
- cd = (Math.floor(cd / 36400000) * 36400000);
- $(element).find(':findday("' + cd + '")').removeClass('wd').addClass('today');
- break;
+ case "weeks":
+ $(element).find(':findweek("' + cd + '")').removeClass('wd').addClass('today');
+ break;
+ case "months":
+ $(element).find(':findmonth("' + cd + '")').removeClass('wd').addClass('today');
+ break;
+ case "days":
+ /* falls through */
+ case "hours":
+ /* falls through */
+ default:
+ $(element).find(':findday("' + cd + '")').removeClass('wd').addClass('today');
}
},
// **Fill the Chart**
// Parse the data and fill the data panel
fillData: function (element, datapanel, leftpanel /* <- never used? */) {
+ var cellWidth = tools.getCellSize();
+ var barOffset = (cellWidth - 18) / 2;
+ var dataPanelWidth = datapanel.width();
var invertColor = function (colStr) {
try {
colStr = colStr.replace("rgb(", "").replace(")", "");
@@ -1003,157 +1021,132 @@
};
// Loop through the values of each data element and set a row
$.each(element.data, function (i, entry) {
- if (i >= element.pageNum * settings.itemsPerPage && i < (element.pageNum * settings.itemsPerPage + settings.itemsPerPage)) {
+ if (i >= element.pageNum * settings.itemsPerPage &&
+ i < (element.pageNum * settings.itemsPerPage + settings.itemsPerPage)) {
$.each(entry.values, function (j, day) {
- var _bar = null;
-
+ var _bar;
+ var from, to, cFrom, cTo, dFrom, dTo, dl, dp;
+ var topEl, top;
switch (settings.scale) {
- // **Hourly data**
- case "hours":
- var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime(), element.scaleStep);
- var from = $(element).find('#dh-' + dFrom);
-
- var dTo = tools.genId(tools.dateDeserialize(day.to).getTime(), element.scaleStep);
- var to = $(element).find('#dh-' + dTo);
-
- var cFrom = from.attr("offset");
- var cTo = to.attr("offset");
- var dl = Math.floor((cTo - cFrom) / tools.getCellSize()) + 1;
-
- _bar = core.createProgressBar(
- dl,
- day.customClass ? day.customClass : "",
- day.desc ? day.desc : "",
- day.label ? day.label : "",
- day.dataObj ? day.dataObj : null
- );
-
- // find row
- var topEl = $(element).find("#rowheader" + i);
-
- var top = tools.getCellSize() * 5 + 2 + parseInt(topEl.attr("offset"), 10);
- _bar.css({ 'top': top, 'left': Math.floor(cFrom) });
-
- datapanel.append(_bar);
- break;
-
- // **Weekly data**
- case "weeks":
- var dtFrom = tools.dateDeserialize(day.from);
- var dtTo = tools.dateDeserialize(day.to);
-
- if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
- dtFrom.setDate(dtFrom.getDate() + 4);
- }
-
- if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
- dtFrom.setDate(dtFrom.getDate() + 4);
- }
-
- if (dtTo.getDate() <= 3 && dtTo.getMonth() === 0) {
- dtTo.setDate(dtTo.getDate() + 4);
- }
-
- var from = $(element).find("#" + dtFrom.getWeekId());
-
- var cFrom = from.attr("offset");
-
- var to = $(element).find("#" + dtTo.getWeekId());
- var cTo = to.attr("offset");
-
- var dl = Math.round((cTo - cFrom) / tools.getCellSize()) + 1;
-
- _bar = core.createProgressBar(
- dl,
- day.customClass ? day.customClass : "",
- day.desc ? day.desc : "",
- day.label ? day.label : "",
- day.dataObj ? day.dataObj : null
- );
-
- // find row
- var topEl = $(element).find("#rowheader" + i);
-
- var top = tools.getCellSize() * 3 + 2 + parseInt(topEl.attr("offset"), 10);
- _bar.css({ 'top': top, 'left': Math.floor(cFrom) });
-
- datapanel.append(_bar);
- break;
-
- // **Monthly data**
- case "months":
- var dtFrom = tools.dateDeserialize(day.from);
- var dtTo = tools.dateDeserialize(day.to);
-
- if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
- dtFrom.setDate(dtFrom.getDate() + 4);
- }
-
- if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
- dtFrom.setDate(dtFrom.getDate() + 4);
- }
-
- if (dtTo.getDate() <= 3 && dtTo.getMonth() === 0) {
- dtTo.setDate(dtTo.getDate() + 4);
- }
-
- var from = $(element).find("#dh-" + tools.genId(dtFrom.getTime()));
- var cFrom = from.attr("offset");
- var to = $(element).find("#dh-" + tools.genId(dtTo.getTime()));
- var cTo = to.attr("offset");
- var dl = Math.round((cTo - cFrom) / tools.getCellSize()) + 1;
-
- _bar = core.createProgressBar(
- dl,
- day.customClass ? day.customClass : "",
- day.desc ? day.desc : "",
- day.label ? day.label : "",
- day.dataObj ? day.dataObj : null
- );
-
- // find row
- var topEl = $(element).find("#rowheader" + i);
-
- var top = tools.getCellSize() * 2 + 2 + parseInt(topEl.attr("offset"), 10);
- _bar.css({ 'top': top, 'left': Math.floor(cFrom) });
-
- datapanel.append(_bar);
- break;
-
- // **Days**
- default:
- var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime());
- var dTo = tools.genId(tools.dateDeserialize(day.to).getTime());
-
- var from = $(element).find("#dh-" + dFrom);
- var cFrom = from.attr("offset");
-
- var dl = Math.floor(((dTo / 1000) - (dFrom / 1000)) / 86400) + 1;
- _bar = core.createProgressBar(
- dl,
- day.customClass ? day.customClass : "",
- day.desc ? day.desc : "",
- day.label ? day.label : "",
- day.dataObj ? day.dataObj : null
- );
-
- // find row
- var topEl = $(element).find("#rowheader" + i);
-
- var top = tools.getCellSize() * 4 + 2 + parseInt(topEl.attr("offset"), 10);
- _bar.css({ 'top': top, 'left': Math.floor(cFrom) });
-
- datapanel.append(_bar);
-
- break;
+ // **Hourly data**
+ case "hours":
+ dFrom = tools.genId(tools.dateDeserialize(day.from), element.scaleStep);
+ from = $(element).find('#dh-' + dFrom);
+ dTo = tools.genId(tools.dateDeserialize(day.to), element.scaleStep);
+ to = $(element).find('#dh-' + dTo);
+ cFrom = from.data("offset");
+ cTo = to.data("offset");
+ dl = Math.floor((cTo - cFrom) / cellWidth) + 1;
+ dp = 100 * (cellWidth * dl - 1) / dataPanelWidth;
+
+ _bar = core.createProgressBar(day.label, day.desc, day.customClass, day.dataObj);
+
+ // find row
+ topEl = $(element).find("#rowheader" + i);
+ top = cellWidth * 5 + barOffset + topEl.data("offset");
+ _bar.css({
+ top: top,
+ left: Math.floor(cFrom),
+ width: dp + '%'
+ });
+
+ datapanel.append(_bar);
+ break;
+
+ // **Weekly data**
+ case "weeks":
+ dFrom = tools.dateDeserialize(day.from);
+ dTo = tools.dateDeserialize(day.to);
+
+ from = $(element).find("#" + dFrom.getWeekId());
+ cFrom = from.data("offset");
+ to = $(element).find("#" + dTo.getWeekId());
+ cTo = to.data("offset");
+ dl = Math.round((cTo - cFrom) / cellWidth) + 1;
+ dp = 100 * (cellWidth * dl - 1) / dataPanelWidth;
+
+ _bar = core.createProgressBar(day.label, day.desc, day.customClass, day.dataObj);
+
+ // find row
+ topEl = $(element).find("#rowheader" + i);
+ top = cellWidth * 3 + barOffset + topEl.data("offset");
+ _bar.css({
+ top: top,
+ left: Math.floor(cFrom),
+ width: dp + '%'
+ });
+
+ datapanel.append(_bar);
+ break;
+
+ // **Monthly data**
+ case "months":
+ dFrom = tools.dateDeserialize(day.from);
+ dTo = tools.dateDeserialize(day.to);
+
+ if (dFrom.getDate() <= 3 && dFrom.getMonth() === 0) {
+ dFrom.setDate(dFrom.getDate() + 4);
+ }
+
+ if (dFrom.getDate() <= 3 && dFrom.getMonth() === 0) {
+ dFrom.setDate(dFrom.getDate() + 4);
+ }
+
+ if (dTo.getDate() <= 3 && dTo.getMonth() === 0) {
+ dTo.setDate(dTo.getDate() + 4);
+ }
+
+ from = $(element).find("#dh-" + tools.genId(dFrom));
+ cFrom = from.data("offset");
+ to = $(element).find("#dh-" + tools.genId(dTo));
+ cTo = to.data("offset");
+ dl = Math.round((cTo - cFrom) / cellWidth) + 1;
+ dp = 100 * (cellWidth * dl - 1) / dataPanelWidth;
+
+ _bar = core.createProgressBar(day.label, day.desc, day.customClass, day.dataObj);
+
+ // find row
+ topEl = $(element).find("#rowheader" + i);
+ top = cellWidth * 2 + barOffset + topEl.data("offset");
+ _bar.css({
+ top: top,
+ left: Math.floor(cFrom),
+ width: dp + '%'
+ });
+
+ datapanel.append(_bar);
+ break;
+
+ // **Days**
+ case "days":
+ /* falls through */
+ default:
+ dFrom = tools.genId(tools.dateDeserialize(day.from));
+ dTo = tools.genId(tools.dateDeserialize(day.to));
+ from = $(element).find("#dh-" + dFrom);
+ cFrom = from.data("offset");
+ dl = Math.round((dTo - dFrom) / UTC_DAY_IN_MS) + 1;
+ dp = 100 * (cellWidth * dl - 1) / dataPanelWidth;
+
+ _bar = core.createProgressBar(day.label, day.desc, day.customClass, day.dataObj);
+
+ // find row
+ topEl = $(element).find("#rowheader" + i);
+ top = cellWidth * 4 + barOffset + topEl.data("offset");
+ _bar.css({
+ top: top,
+ left: Math.floor(cFrom),
+ width: dp + '%'
+ });
+
+ datapanel.append(_bar);
}
+
var $l = _bar.find(".fn-label");
- if ($l && _bar.length) {
- var gray = invertColor(_bar[0].style.backgroundColor);
+ if ($l.length) {
+ var gray = invertColor(_bar.css('backgroundColor'));
$l.css("color", gray);
- } else if ($l) {
- $l.css("color", "");
}
});
@@ -1169,51 +1162,52 @@
var shift = function () {
core.repositionLabel(element);
};
+ var maxLeft, curLeft;
switch (val) {
- case "begin":
- $dataPanel.animate({ "margin-left": "0px" }, "fast", shift);
- element.scrollNavigation.panelMargin = 0;
- break;
- case "end":
- var mLeft = dataPanelWidth - rightPanelWidth;
- element.scrollNavigation.panelMargin = mLeft * -1;
- $dataPanel.animate({ "margin-left": "-" + mLeft + "px" }, "fast", shift);
- break;
- case "now":
- if (!element.scrollNavigation.canScroll || !$dataPanel.find(".today").length) {
- return false;
- }
- var max_left = (dataPanelWidth - rightPanelWidth) * -1;
- var cur_marg = $dataPanel.css("margin-left").replace("px", "");
- var val = $dataPanel.find(".today").offset().left - $dataPanel.offset().left;
- val *= -1;
- if (val > 0) {
- val = 0;
- } else if (val < max_left) {
- val = max_left;
- }
- $dataPanel.animate({ "margin-left": val + "px" }, "fast", shift);
- element.scrollNavigation.panelMargin = val;
- break;
- default:
- var max_left = (dataPanelWidth - rightPanelWidth) * -1;
- var cur_marg = $dataPanel.css("margin-left").replace("px", "");
- var val = parseInt(cur_marg, 10) + val;
- if (val <= 0 && val >= max_left) {
- $dataPanel.animate({ "margin-left": val + "px" }, "fast", shift);
- }
- element.scrollNavigation.panelMargin = val;
- break;
+ case "begin":
+ $dataPanel.animate({ "left": "0" }, "fast", shift);
+ element.scrollNavigation.panelMargin = 0;
+ break;
+ case "end":
+ var pLeft = dataPanelWidth - rightPanelWidth;
+ element.scrollNavigation.panelMargin = pLeft * -1;
+ $dataPanel.animate({ "left": "-" + pLeft }, "fast", shift);
+ break;
+ case "now":
+ if (!element.scrollNavigation.canScroll || !$dataPanel.find(".today").length) {
+ return false;
+ }
+ maxLeft = (dataPanelWidth - rightPanelWidth) * -1;
+ curLeft = $dataPanel.css("left").replace("px", "");
+ val = $dataPanel.find(".today").offset().left - $dataPanel.offset().left;
+ val *= -1;
+ if (val > 0) {
+ val = 0;
+ } else if (val < maxLeft) {
+ val = maxLeft;
+ }
+ $dataPanel.animate({ "left": val }, "fast", shift);
+ element.scrollNavigation.panelMargin = val;
+ break;
+ default:
+ maxLeft = (dataPanelWidth - rightPanelWidth) * -1;
+ curLeft = $dataPanel.css("left").replace("px", "");
+ val = parseInt(curLeft, 10) + val;
+ if (val <= 0 && val >= maxLeft) {
+ $dataPanel.animate({ "left": val }, "fast", shift);
+ }
+ element.scrollNavigation.panelMargin = val;
}
core.synchronizeScroller(element);
},
// Navigate to a specific page
navigatePage: function (element, val) {
- if ((element.pageNum + val) >= 0 && (element.pageNum + val) < Math.ceil(element.rowsNum / settings.itemsPerPage)) {
- core.waitToggle(element, true, function () {
+ if ((element.pageNum + val) >= 0 &&
+ (element.pageNum + val) < Math.ceil(element.rowsNum / settings.itemsPerPage)) {
+ core.waitToggle(element, function () {
element.pageNum += val;
- element.hPosition = $(".fn-gantt .dataPanel").css("margin-left").replace("px", "");
+ element.hPosition = $(".fn-gantt .dataPanel").css("left").replace("px", "");
element.scaleOldWidth = false;
core.init(element);
});
@@ -1222,12 +1216,12 @@
// Change zoom level
zoomInOut: function (element, val) {
- core.waitToggle(element, true, function () {
+ core.waitToggle(element, function () {
var zoomIn = (val < 0);
-
var scaleSt = element.scaleStep + val * 3;
- scaleSt = scaleSt <= 1 ? 1 : scaleSt === 4 ? 3 : scaleSt;
+ // adjust hour scale to desired factors of 24
+ scaleSt = {4:3, 5:6, 9:8, 11:12}[scaleSt] || (scaleSt < 1 ? 1 : scaleSt);
var scale = settings.scale;
var headerRows = element.headerRows;
if (settings.scale === "hours" && scaleSt >= 13) {
@@ -1256,23 +1250,25 @@
scaleSt = 13;
}
- if ((zoomIn && $.inArray(scale, scales) < $.inArray(settings.minScale, scales))
- || (!zoomIn && $.inArray(scale, scales) > $.inArray(settings.maxScale, scales))) {
+ // do nothing if attempting to zoom past max/min
+ if ((zoomIn && $.inArray(scale, scales) < $.inArray(settings.minScale, scales)) ||
+ (!zoomIn && $.inArray(scale, scales) > $.inArray(settings.maxScale, scales))) {
core.init(element);
return;
}
+
element.scaleStep = scaleSt;
settings.scale = scale;
element.headerRows = headerRows;
var $rightPanel = $(element).find(".fn-gantt .rightPanel");
var $dataPanel = $rightPanel.find(".dataPanel");
- element.hPosition = $dataPanel.css("margin-left").replace("px", "");
+ element.hPosition = $dataPanel.css("left").replace("px", "");
element.scaleOldWidth = ($dataPanel.width() - $rightPanel.width());
if (settings.useCookie) {
- $.cookie(this.cookieKey + "CurrentScale", settings.scale);
+ $.cookie(settings.cookieKey + "CurrentScale", settings.scale);
// reset scrollPos
- $.cookie(this.cookieKey + "ScrollPos", null);
+ $.cookie(settings.cookieKey + "ScrollPos", null);
}
core.init(element);
});
@@ -1324,24 +1320,24 @@
var bWidth = $sliderBar.width();
var wButton = $sliderBarBtn.width();
- var pos, mLeft;
+ var pos, pLeft;
if ((e.pageX >= bPos.left) && (e.pageX <= bPos.left + bWidth)) {
pos = e.pageX - bPos.left;
pos = pos - wButton / 2;
$sliderBarBtn.css("left", pos);
- mLeft = $dataPanel.width() - $rightPanel.width();
+ pLeft = $dataPanel.width() - $rightPanel.width();
- var pPos = pos * mLeft / bWidth * -1;
+ var pPos = pos * pLeft / bWidth * -1;
if (pPos >= 0) {
- $dataPanel.css("margin-left", "0px");
+ $dataPanel.css("left", "0");
element.scrollNavigation.panelMargin = 0;
} else if (pos >= bWidth - (wButton * 1)) {
- $dataPanel.css("margin-left", mLeft * -1 + "px");
- element.scrollNavigation.panelMargin = mLeft * -1;
+ $dataPanel.css("left", pLeft * -1);
+ element.scrollNavigation.panelMargin = pLeft * -1;
} else {
- $dataPanel.css("margin-left", pPos + "px");
+ $dataPanel.css("left", pPos);
element.scrollNavigation.panelMargin = pPos;
}
clearTimeout(element.scrollNavigation.repositionDelay);
@@ -1357,37 +1353,36 @@
var _panelMargin = parseInt(element.scrollNavigation.panelMargin, 10) + delta;
if (_panelMargin > 0) {
element.scrollNavigation.panelMargin = 0;
- $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
+ $(element).find(".fn-gantt .dataPanel").css("left", element.scrollNavigation.panelMargin);
} else if (_panelMargin < element.scrollNavigation.panelMaxPos * -1) {
element.scrollNavigation.panelMargin = element.scrollNavigation.panelMaxPos * -1;
- $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
+ $(element).find(".fn-gantt .dataPanel").css("left", element.scrollNavigation.panelMargin);
} else {
element.scrollNavigation.panelMargin = _panelMargin;
- $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
+ $(element).find(".fn-gantt .dataPanel").css("left", element.scrollNavigation.panelMargin);
}
core.synchronizeScroller(element);
},
// Synchronize scroller
synchronizeScroller: function (element) {
- if (settings.navigate === "scroll") {
- var $rightPanel = $(element).find(".fn-gantt .rightPanel");
- var $dataPanel = $rightPanel.find(".dataPanel");
- var $sliderBar = $(element).find(".nav-slider-bar");
- var $sliderBtn = $sliderBar.find(".nav-slider-button");
+ if (settings.navigate !== "scroll") { return; }
+ var $rightPanel = $(element).find(".fn-gantt .rightPanel");
+ var $dataPanel = $rightPanel.find(".dataPanel");
+ var $sliderBar = $(element).find(".nav-slider-bar");
+ var $sliderBtn = $sliderBar.find(".nav-slider-button");
- var bWidth = $sliderBar.width();
- var wButton = $sliderBtn.width();
+ var bWidth = $sliderBar.width();
+ var wButton = $sliderBtn.width();
- var mLeft = $dataPanel.width() - $rightPanel.width();
- var hPos = 0;
- if ($dataPanel.css("margin-left")) {
- hPos = $dataPanel.css("margin-left").replace("px", "");
- }
- var pos = hPos * bWidth / mLeft - $sliderBtn.width() * 0.25;
- pos = pos > 0 ? 0 : (pos * -1 >= bWidth - (wButton * 0.75)) ? (bWidth - (wButton * 1.25)) * -1 : pos;
- $sliderBtn.css("left", pos * -1);
+ var pLeft = $dataPanel.width() - $rightPanel.width();
+ var hPos = $dataPanel.css("left") || 0;
+ if (hPos) {
+ hPos = hPos.replace("px", "");
}
+ var pos = hPos * bWidth / pLeft - $sliderBtn.width() * 0.25;
+ pos = pos > 0 ? 0 : (pos * -1 >= bWidth - (wButton * 0.75)) ? (bWidth - (wButton * 1.25)) * -1 : pos;
+ $sliderBtn.css("left", pos * -1);
},
// Reposition data labels
@@ -1402,24 +1397,25 @@
}
if (settings.useCookie) {
- $.cookie(this.cookieKey + "ScrollPos", $dataPanel.css("margin-left").replace("px", ""));
+ $.cookie(settings.cookieKey + "ScrollPos", $dataPanel.css("left").replace("px", ""));
}
}, 500);
},
// waitToggle
- waitToggle: function (element, show, fn) {
- if (show) {
- var eo = $(element).offset();
- var ew = $(element).outerWidth();
- var eh = $(element).outerHeight();
+ waitToggle: function (element, showCallback) {
+ if ( $.isFunction(showCallback) ) {
+ var $elt = $(element);
+ var eo = $elt.offset();
+ var ew = $elt.outerWidth();
+ var eh = $elt.outerHeight();
if (!element.loader) {
- element.loader = $(''
- + '
' + settings.waitText + '
');
+ element.loader = $('' +
+ '
' + settings.waitText + '
');
}
- $(element).append(element.loader);
- setTimeout(fn, 500);
+ $elt.append(element.loader);
+ setTimeout(showCallback, 500);
} else if (element.loader) {
element.loader.detach();
@@ -1436,30 +1432,35 @@
var maxDate = null;
$.each(element.data, function (i, entry) {
$.each(entry.values, function (i, date) {
- maxDate = maxDate < tools.dateDeserialize(date.to) ? tools.dateDeserialize(date.to) : maxDate;
+ var toDate = tools.dateDeserialize(date.to);
+ if (isNaN(toDate)) { return; }
+ maxDate = maxDate < toDate ? toDate : maxDate;
});
});
maxDate = maxDate || new Date();
+ var bd;
switch (settings.scale) {
- case "hours":
- maxDate.setHours(Math.ceil((maxDate.getHours()) / element.scaleStep) * element.scaleStep);
- maxDate.setHours(maxDate.getHours() + element.scaleStep * 3);
- break;
- case "weeks":
- var bd = new Date(maxDate.getTime());
- var bd = new Date(bd.setDate(bd.getDate() + 3 * 7));
- var md = Math.floor(bd.getDate() / 7) * 7;
- maxDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
- break;
- case "months":
- var bd = new Date(maxDate.getFullYear(), maxDate.getMonth(), 1);
- bd.setMonth(bd.getMonth() + 2);
- maxDate = new Date(bd.getFullYear(), bd.getMonth(), 1);
- break;
- default:
- maxDate.setHours(0);
- maxDate.setDate(maxDate.getDate() + 3);
- break;
+ case "hours":
+ maxDate.setHours(Math.ceil((maxDate.getHours()) / element.scaleStep) * element.scaleStep);
+ maxDate.setHours(maxDate.getHours() + element.scaleStep * 3);
+ break;
+ case "weeks":
+ // wtf is happening here?
+ bd = new Date(maxDate.getTime());
+ bd = new Date(bd.setDate(bd.getDate() + 3 * 7));
+ var md = Math.floor(bd.getDate() / 7) * 7;
+ maxDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
+ break;
+ case "months":
+ bd = new Date(maxDate.getFullYear(), maxDate.getMonth(), 1);
+ bd.setMonth(bd.getMonth() + 2);
+ maxDate = new Date(bd.getFullYear(), bd.getMonth(), 1);
+ break;
+ case "days":
+ /* falls through */
+ default:
+ maxDate.setHours(0);
+ maxDate.setDate(maxDate.getDate() + 3);
}
return maxDate;
},
@@ -1469,116 +1470,80 @@
var minDate = null;
$.each(element.data, function (i, entry) {
$.each(entry.values, function (i, date) {
- minDate = minDate > tools.dateDeserialize(date.from) || minDate === null ? tools.dateDeserialize(date.from) : minDate;
+ var fromDate = tools.dateDeserialize(date.from);
+ if (isNaN(fromDate)) { return; }
+ minDate = minDate > fromDate || minDate === null ? fromDate : minDate;
});
});
minDate = minDate || new Date();
switch (settings.scale) {
- case "hours":
- minDate.setHours(Math.floor((minDate.getHours()) / element.scaleStep) * element.scaleStep);
- minDate.setHours(minDate.getHours() - element.scaleStep * 3);
- break;
- case "weeks":
- var bd = new Date(minDate.getTime());
- var bd = new Date(bd.setDate(bd.getDate() - 3 * 7));
- var md = Math.floor(bd.getDate() / 7) * 7;
- minDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
- break;
- case "months":
- var bd = new Date(minDate.getFullYear(), minDate.getMonth(), 1);
- bd.setMonth(bd.getMonth() - 3);
- minDate = new Date(bd.getFullYear(), bd.getMonth(), 1);
- break;
- default:
- minDate.setHours(0);
- minDate.setDate(minDate.getDate() - 3);
- break;
+ case "hours":
+ minDate.setHours(Math.floor((minDate.getHours()) / element.scaleStep) * element.scaleStep);
+ minDate.setHours(minDate.getHours() - element.scaleStep * 3);
+ break;
+ case "weeks":
+ // wtf is happening here?
+ var bd = new Date(minDate.getTime());
+ bd = new Date(bd.setDate(bd.getDate() - 3 * 7));
+ var md = Math.floor(bd.getDate() / 7) * 7;
+ minDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
+ break;
+ case "months":
+ minDate.setHours(0, 0, 0, 0);
+ minDate.setDate(1);
+ minDate.setMonth(minDate.getMonth() - 3);
+ break;
+ case "days":
+ /* falls through */
+ default:
+ minDate.setHours(0, 0, 0, 0);
+ minDate.setDate(minDate.getDate() - 3);
}
return minDate;
},
// Return an array of Date objects between `from` and `to`
parseDateRange: function (from, to) {
- var current = new Date(from.getTime());
- var end = new Date(to.getTime()); // <- never used?
- var ret = [];
- var i = 0;
+ var year = from.getFullYear();
+ var month = from.getMonth();
+ var date = from.getDate();
+ var range = [], i = 0;
do {
- ret[i++] = new Date(current.getTime());
- current.setDate(current.getDate() + 1);
- } while (current.getTime() <= to.getTime());
- return ret;
-
+ range[i] = new Date(year, month, date + i);
+ } while (range[i++] < to);
+ return range;
},
// Return an array of Date objects between `from` and `to`,
// scaled hourly
parseTimeRange: function (from, to, scaleStep) {
- var current = new Date(from);
- var end = new Date(to);
-
- // GR: Fix begin
- current.setMilliseconds(0);
- current.setSeconds(0);
- current.setMinutes(0);
- current.setHours(0);
-
- end.setMilliseconds(0);
- end.setSeconds(0);
- if (end.getMinutes() > 0 || end.getHours() > 0) {
- end.setMinutes(0);
- end.setHours(0);
- end.setTime(end.getTime() + (86400000)); // Add day
- }
- // GR: Fix end
-
- var ret = [];
- var i = 0;
- for(;;) {
- var dayStartTime = new Date(current);
- dayStartTime.setHours(Math.floor((current.getHours()) / scaleStep) * scaleStep);
-
- if (ret[i] && dayStartTime.getDay() !== ret[i].getDay()) {
- // If mark-cursor jumped to next day, make sure it starts at 0 hours
- dayStartTime.setHours(0);
- }
- ret[i] = dayStartTime;
-
- // Note that we use ">" because we want to include the end-time point.
- if (current.getTime() > to.getTime()) break;
-
- /* BUG-2: current is moved backwards producing a dead-lock! (crashes chrome/IE/firefox)
- * SEE: https://github.com/taitems/jQuery.Gantt/issues/62
- if (current.getDay() !== ret[i].getDay()) {
- current.setHours(0);
+ var year = from.getFullYear();
+ var month = from.getMonth();
+ var date = from.getDate();
+ var hour = from.getHours();
+ hour -= hour % scaleStep;
+ var range = [], h = 0, i = 0;
+ do {
+ range[i] = new Date(year, month, date, hour + h++ * scaleStep);
+ // overwrite any hours repeated due to DST changes
+ if (i > 0 && range[i].getHours() === range[i-1].getHours()) {
+ i--;
}
- */
-
- // GR Fix Begin
- current = ktkGetNextDate(dayStartTime, scaleStep);
- // GR Fix End
-
- i++;
- }
-
- return ret;
+ } while (range[i++] < to);
+ return range;
},
// Return an array of Date objects between a range of weeks
// between `from` and `to`
parseWeeksRange: function (from, to) {
-
- var current = new Date(from);
- var end = new Date(to); // <- never used?
+ var current = from.getDayForWeek();
var ret = [];
var i = 0;
do {
- if (current.getDay() === 0) {
- ret[i++] = current.getDayForWeek();
- }
- current.setDate(current.getDate() + 1);
- } while (current.getTime() <= to.getTime());
+ ret[i++] = current.getDayForWeek();
+ current.setDate(current.getDate() + 7);
+ } while (current <= to);
return ret;
},
@@ -1587,7 +1552,6 @@
// Return an array of Date objects between a range of months
// between `from` and `to`
parseMonthsRange: function (from, to) {
-
var current = new Date(from);
var end = new Date(to); // <- never used?
@@ -1596,7 +1560,7 @@
do {
ret[i++] = new Date(current.getFullYear(), current.getMonth(), 1);
current.setMonth(current.getMonth() + 1);
- } while (current.getTime() <= to.getTime());
+ } while (current <= to);
return ret;
},
@@ -1611,27 +1575,33 @@
},
// Generate an id for a date
- genId: function (ticks) {
- var t = new Date(ticks);
+ genId: function (t) { // varargs
+ if ( $.isNumeric(t) ) {
+ t = new Date(t);
+ }
switch (settings.scale) {
- case "hours":
- var hour = t.getHours();
- if (arguments.length >= 2) {
- hour = (Math.floor((t.getHours()) / arguments[1]) * arguments[1]);
- }
- return (new Date(t.getFullYear(), t.getMonth(), t.getDate(), hour)).getTime();
- case "weeks":
- var y = t.getFullYear();
- var w = t.getDayForWeek().getWeekOfYear();
- var m = t.getMonth();
- if (m === 11 && w === 1) {
- y++;
- }
- return y + "-" + w;
- case "months":
- return t.getFullYear() + "-" + t.getMonth();
- default:
- return (new Date(t.getFullYear(), t.getMonth(), t.getDate())).getTime();
+ case "hours":
+ var hour = t.getHours();
+ if (arguments.length >= 2) {
+ hour = (Math.floor(t.getHours() / arguments[1]) * arguments[1]);
+ }
+ return (new Date(t.getFullYear(), t.getMonth(), t.getDate(), hour)).getTime();
+ case "weeks":
+ var y = t.getFullYear();
+ var w = t.getWeekOfYear();
+ var m = t.getMonth();
+ if (m === 11 && w === 1) {
+ y++;
+ } else if (!m && w > 51) {
+ y--;
+ }
+ return y + "-" + w;
+ case "months":
+ return t.getFullYear() + "-" + t.getMonth();
+ case "days":
+ /* falls through */
+ default:
+ return (new Date(t.getFullYear(), t.getMonth(), t.getDate())).getTime();
}
},
@@ -1647,7 +1617,7 @@
// Returns true when the given date appears in the array of holidays, if provided
isHoliday: (function() { // IIFE
// short-circuits the function if no holidays option was passed
- if (!settings.holidays) {
+ if (!settings.holidays || !settings.holidays.length) {
return function () { return false; };
}
var holidays = false;
@@ -1665,46 +1635,20 @@
};
})(),
- // Get the current cell size
- _getCellSize: null,
+ // Get the current cell height
getCellSize: function () {
- if (!tools._getCellSize) {
- $("body").append(
- $('')
- );
- tools._getCellSize = $("#measureCellWidth .row").height();
- $("#measureCellWidth").empty().remove();
+ if (typeof tools._getCellSize === "undefined") {
+ var measure = $('');
+ $("body").append(measure);
+ tools._getCellSize = measure.find(".row").height();
+ measure.empty().remove();
}
return tools._getCellSize;
},
- // Get the current size of the right panel
- getRightPanelSize: function () {
- $("body").append(
- $('')
- );
- var ret = $("#measureCellWidth .rightPanel").height();
- $("#measureCellWidth").empty().remove();
- return ret;
- },
-
// Get the current page height
getPageHeight: function (element) {
return element.pageNum + 1 === element.pageCount ? element.rowsOnLastPage * tools.getCellSize() : settings.itemsPerPage * tools.getCellSize();
- },
-
- // Get the current margin size of the progress bar
- _getProgressBarMargin: null,
- getProgressBarMargin: function () {
- if (!tools._getProgressBarMargin && tools._getProgressBarMargin !== 0) {
- $("body").append(
- $('')
- );
- tools._getProgressBarMargin = parseInt($("#measureBarWidth .fn-gantt .rightPanel .day .bar").css("margin-left").replace("px", ""), 10);
- tools._getProgressBarMargin += parseInt($("#measureBarWidth .fn-gantt .rightPanel .day .bar").css("margin-right").replace("px", ""), 10);
- $("#measureBarWidth").empty().remove();
- }
- return tools._getProgressBarMargin;
}
};
@@ -1724,20 +1668,36 @@
// Update cookie with current scale
if (settings.useCookie) {
- var sc = $.cookie(this.cookieKey + "CurrentScale");
+ var sc = $.cookie(settings.cookieKey + "CurrentScale");
if (sc) {
- settings.scale = $.cookie(this.cookieKey + "CurrentScale");
+ settings.scale = sc;
} else {
- $.cookie(this.cookieKey + "CurrentScale", settings.scale);
+ $.cookie(settings.cookieKey + "CurrentScale", settings.scale);
}
}
switch (settings.scale) {
- //case "hours": this.headerRows = 5; this.scaleStep = 8; break;
- case "hours": this.headerRows = 5; this.scaleStep = 1; break;
- case "weeks": this.headerRows = 3; this.scaleStep = 13; break;
- case "months": this.headerRows = 2; this.scaleStep = 14; break;
- default: this.headerRows = 4; this.scaleStep = 13; break;
+ //case "hours":
+ // this.headerRows = 5;
+ // this.scaleStep = 8;
+ // break;
+ case "hours":
+ this.headerRows = 5;
+ this.scaleStep = 1;
+ break;
+ case "weeks":
+ this.headerRows = 3;
+ this.scaleStep = 13;
+ break;
+ case "months":
+ this.headerRows = 2;
+ this.scaleStep = 14;
+ break;
+ case "days":
+ /* falls through */
+ default:
+ this.headerRows = 4;
+ this.scaleStep = 13;
}
this.scrollNavigation = {
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..734e14e
--- /dev/null
+++ b/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "@taitems/jquery-gantt",
+ "version": "1.1.2",
+ "description": "jQuery Gantt Chart is a simple chart that implements gantt functionality as a jQuery component.",
+ "main": "index.js",
+ "directories": {
+ "test": "tests"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/taitems/jQuery.Gantt.git"
+ },
+ "keywords": [
+ "Gantt",
+ "jQuery",
+ "ecosystem:jquery",
+ "jquery-plugin"
+ ],
+ "author": "Tait Brown ",
+ "contributors": [
+ "Usman (https://github.com/usmonster)"
+ ],
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/taitems/jQuery.Gantt/issues"
+ },
+ "homepage": "https://github.com/taitems/jQuery.Gantt#readme"
+}
diff --git a/tests/moment.min.js b/tests/moment.min.js
deleted file mode 100644
index f56b370..0000000
--- a/tests/moment.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-//! moment.js
-//! version : 2.2.1
-//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
-//! license : MIT
-//! momentjs.com
-(function(a){function b(a,b){return function(c){return i(a.call(this,c),b)}}function c(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function d(){}function e(a){g(this,a)}function f(a){var b=a.years||a.year||a.y||0,c=a.months||a.month||a.M||0,d=a.weeks||a.week||a.w||0,e=a.days||a.day||a.d||0,f=a.hours||a.hour||a.h||0,g=a.minutes||a.minute||a.m||0,h=a.seconds||a.second||a.s||0,i=a.milliseconds||a.millisecond||a.ms||0;this._input=a,this._milliseconds=+i+1e3*h+6e4*g+36e5*f,this._days=+e+7*d,this._months=+c+12*b,this._data={},this._bubble()}function g(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function h(a){return 0>a?Math.ceil(a):Math.floor(a)}function i(a,b){for(var c=a+"";c.lengthc;c++)~~a[c]!==~~b[c]&&f++;return f+e}function m(a){return a?ib[a]||a.toLowerCase().replace(/(.)s$/,"$1"):a}function n(a,b){return b.abbr=a,P[a]||(P[a]=new d),P[a].set(b),P[a]}function o(a){delete P[a]}function p(a){if(!a)return L.fn._lang;if(!P[a]&&Q)try{require("./lang/"+a)}catch(b){return L.fn._lang}return P[a]||L.fn._lang}function q(a){return a.match(/\[.*\]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function r(a){var b,c,d=a.match(T);for(b=0,c=d.length;c>b;b++)d[b]=mb[d[b]]?mb[d[b]]:q(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function s(a,b){return b=t(b,a.lang()),jb[b]||(jb[b]=r(b)),jb[b](a)}function t(a,b){function c(a){return b.longDateFormat(a)||a}for(var d=5;d--&&(U.lastIndex=0,U.test(a));)a=a.replace(U,c);return a}function u(a,b){switch(a){case"DDDD":return X;case"YYYY":return Y;case"YYYYY":return Z;case"S":case"SS":case"SSS":case"DDD":return W;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return $;case"a":case"A":return p(b._l)._meridiemParse;case"X":return bb;case"Z":case"ZZ":return _;case"T":return ab;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return V;default:return new RegExp(a.replace("\\",""))}}function v(a){var b=(_.exec(a)||[])[0],c=(b+"").match(fb)||["-",0,0],d=+(60*c[1])+~~c[2];return"+"===c[0]?-d:d}function w(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[1]=~~b-1);break;case"MMM":case"MMMM":d=p(c._l).monthsParse(b),null!=d?e[1]=d:c._isValid=!1;break;case"D":case"DD":null!=b&&(e[2]=~~b);break;case"DDD":case"DDDD":null!=b&&(e[1]=0,e[2]=~~b);break;case"YY":e[0]=~~b+(~~b>68?1900:2e3);break;case"YYYY":case"YYYYY":e[0]=~~b;break;case"a":case"A":c._isPm=p(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[3]=~~b;break;case"m":case"mm":e[4]=~~b;break;case"s":case"ss":e[5]=~~b;break;case"S":case"SS":case"SSS":e[6]=~~(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=v(b)}null==b&&(c._isValid=!1)}function x(a){var b,c,d,e=[];if(!a._d){for(d=z(a),b=0;3>b&&null==a._a[b];++b)a._a[b]=e[b]=d[b];for(;7>b;b++)a._a[b]=e[b]=null==a._a[b]?2===b?1:0:a._a[b];e[3]+=~~((a._tzm||0)/60),e[4]+=~~((a._tzm||0)%60),c=new Date(0),a._useUTC?(c.setUTCFullYear(e[0],e[1],e[2]),c.setUTCHours(e[3],e[4],e[5],e[6])):(c.setFullYear(e[0],e[1],e[2]),c.setHours(e[3],e[4],e[5],e[6])),a._d=c}}function y(a){var b=a._i;a._d||(a._a=[b.years||b.year||b.y,b.months||b.month||b.M,b.days||b.day||b.d,b.hours||b.hour||b.h,b.minutes||b.minute||b.m,b.seconds||b.second||b.s,b.milliseconds||b.millisecond||b.ms],x(a))}function z(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function A(a){var b,c,d,e=p(a._l),f=""+a._i;for(d=t(a._f,e).match(T),a._a=[],b=0;bh&&(i=h,d=c);g(a,d)}function C(a){var b,c=a._i,d=cb.exec(c);if(d){for(a._f="YYYY-MM-DD"+(d[2]||" "),b=0;4>b;b++)if(eb[b][1].exec(c)){a._f+=eb[b][0];break}_.exec(c)&&(a._f+=" Z"),A(a)}else a._d=new Date(c)}function D(b){var c=b._i,d=R.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?C(b):k(c)?(b._a=c.slice(0),x(b)):c instanceof Date?b._d=new Date(+c):"object"==typeof c?y(b):b._d=new Date(c)}function E(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function F(a,b,c){var d=O(Math.abs(a)/1e3),e=O(d/60),f=O(e/60),g=O(f/24),h=O(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",O(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,E.apply({},i)}function G(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=L(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function H(a){var b=a._i,c=a._f;return null===b||""===b?null:("string"==typeof b&&(a._i=b=p().preparse(b)),L.isMoment(b)?(a=g({},b),a._d=new Date(+b._d)):c?k(c)?B(a):A(a):D(a),new e(a))}function I(a,b){L.fn[a]=L.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),L.updateOffset(this),this):this._d["get"+c+b]()}}function J(a){L.duration.fn[a]=function(){return this._data[a]}}function K(a,b){L.duration.fn["as"+a]=function(){return+this/b}}for(var L,M,N="2.2.1",O=Math.round,P={},Q="undefined"!=typeof module&&module.exports,R=/^\/?Date\((\-?\d+)/i,S=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/,T=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,U=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,V=/\d\d?/,W=/\d{1,3}/,X=/\d{3}/,Y=/\d{1,4}/,Z=/[+\-]?\d{1,6}/,$=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,_=/Z|[\+\-]\d\d:?\d\d/i,ab=/T/i,bb=/[\+\-]?\d+(\.\d{1,3})?/,cb=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,db="YYYY-MM-DDTHH:mm:ssZ",eb=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],fb=/([\+\-]|\d\d)/gi,gb="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),hb={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ib={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",w:"week",W:"isoweek",M:"month",y:"year"},jb={},kb="DDD w W M D d".split(" "),lb="M D H h m s w W".split(" "),mb={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return i(this.year()%100,2)},YYYY:function(){return i(this.year(),4)},YYYYY:function(){return i(this.year(),5)},gg:function(){return i(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return i(this.weekYear(),5)},GG:function(){return i(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return i(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return i(~~(this.milliseconds()/10),2)},SSS:function(){return i(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(~~(a/60),2)+":"+i(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(~~(10*a/6),4)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()}};kb.length;)M=kb.pop(),mb[M+"o"]=c(mb[M],M);for(;lb.length;)M=lb.pop(),mb[M+M]=b(mb[M],2);for(mb.DDDD=b(mb.DDD,3),g(d.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=L.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=L([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return G(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6}}),L=function(a,b,c){return H({_i:a,_f:b,_l:c,_isUTC:!1})},L.utc=function(a,b,c){return H({_useUTC:!0,_isUTC:!0,_l:c,_i:a,_f:b}).utc()},L.unix=function(a){return L(1e3*a)},L.duration=function(a,b){var c,d,e=L.isDuration(a),g="number"==typeof a,h=e?a._input:g?{}:a,i=S.exec(a);return g?b?h[b]=a:h.milliseconds=a:i&&(c="-"===i[1]?-1:1,h={y:0,d:~~i[2]*c,h:~~i[3]*c,m:~~i[4]*c,s:~~i[5]*c,ms:~~i[6]*c}),d=new f(h),e&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},L.version=N,L.defaultFormat=db,L.updateOffset=function(){},L.lang=function(a,b){return a?(a=a.toLowerCase(),a=a.replace("_","-"),b?n(a,b):null===b?(o(a),a="en"):P[a]||p(a),L.duration.fn._lang=L.fn._lang=p(a),void 0):L.fn._lang._abbr},L.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),p(a)},L.isMoment=function(a){return a instanceof e},L.isDuration=function(a){return a instanceof f},g(L.fn=e.prototype,{clone:function(){return L(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){return s(L(this).utc(),"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!l(this._a,(this._isUTC?L.utc(this._a):L(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},invalidAt:function(){var a,b=this._a,c=(this._isUTC?L.utc(this._a):L(this._a)).toArray();for(a=6;a>=0&&b[a]===c[a];--a);return a},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=s(this,a||L.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?L.duration(+b,a):L.duration(a,b),j(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?L.duration(+b,a):L.duration(a,b),j(this,c,-1),this},diff:function(a,b,c){var d,e,f=this._isUTC?L(a).zone(this._offset||0):L(a).local(),g=6e4*(this.zone()-f.zone());return b=m(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-L(this).startOf("month")-(f-L(f).startOf("month")))/d,e-=6e4*(this.zone()-L(this).startOf("month").zone()-(f.zone()-L(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:h(e)},from:function(a,b){return L.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(L(),a)},calendar:function(){var a=this.diff(L().zone(this.zone()).startOf("day"),"days",!0),b=-6>a?"sameElse":-1>a?"lastWeek":0>a?"lastDay":1>a?"sameDay":2>a?"nextDay":7>a?"nextWeek":"sameElse";return this.format(this.lang().calendar(b,this))},isLeapYear:function(){var a=this.year();return 0===a%4&&0!==a%100||0===a%400},isDST:function(){return this.zone()+L(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+L(a).startOf(b)},isSame:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)===+L(a).startOf(b)},min:function(a){return a=L.apply(null,arguments),this>a?this:a},max:function(a){return a=L.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=v(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&j(this,L.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},hasAlignedHourOffset:function(a){return a=a?L(a).zone():0,0===(this.zone()-a)%60},daysInMonth:function(){return L.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(a){var b=O((L(this).startOf("day")-L(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},weekYear:function(a){var b=G(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=G(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=G(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this._d.getDay()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=m(a),this[a.toLowerCase()]()},set:function(a,b){a=m(a),this[a.toLowerCase()](b)},lang:function(b){return b===a?this._lang:(this._lang=p(b),this)}}),M=0;M
-
+
+
jQuery.Gantt - Test Suite 01
-
-
-
-
-
-
+
+
+
+
-
+
-
- jQuery.Gantt
- — Test Suite 01
-
+
+ jQuery.Gantt
+ — Test Suite 01
+
-
- Expected behaviour: Gantt bar should run from "now" until 2 hours from now. It fails when all the bars are docked left at the hour view.
-
+
+ Expected behaviour: Gantt bar should run from "now" until 2 hours from now. It fails when all the bars are docked left at the hour view.
+
-
- Manual validation:
-
-
-
-
+
+ Manual validation:
+
+
+
-
-
-
-
-
-
-
+
+
+
-
\ No newline at end of file
+
+
+