|
- /*
- Copyright (c) 2012-2017 Open Lab
- Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
- $.gridify = function (table, opt) {
- var options = {
- resizeZoneWidth: 10
- };
-
- $.extend(options, opt);
-
- var box = $("<div>").addClass("gdfWrapper");
- box.append(table);
-
- var head = table.clone();
- head.addClass("table ganttFixHead");
- //remove non head
- head.find("tbody").remove();
- box.append(head);
-
- box.append(table);
-
- var hTh = head.find(".gdfColHeader");
- var cTh = table.find(".gdfColHeader");
- for (var i = 0; i < hTh.length; i++) {
- hTh.eq(i).data("fTh", cTh.eq(i));
- }
-
- //--------- set table to 0 to prevent a strange 100%
- table.width(0);
- head.width(0);
-
-
- //---------------------- header management start
- head.find("th.gdfColHeader:not(.gdfied)").mouseover(function () {
- $(this).addClass("gdfColHeaderOver");
-
- }).on("mouseout.gdf", function () {
- $(this).removeClass("gdfColHeaderOver");
- if (!$.gridify.columInResize) {
- $("body").removeClass("gdfHResizing");
- }
-
- }).on("mousemove.gdf", function (e) {
- if (!$.gridify.columInResize) {
- var colHeader = $(this);
- var nextCol = colHeader.next();
- if (nextCol.length > 0 && nextCol.width() < options.resizeZoneWidth)
- colHeader = nextCol;
-
- if (!colHeader.is(".gdfResizable"))
- return;
-
- var mousePos = e.pageX - colHeader.offset().left;
-
- if (colHeader.width() - mousePos < options.resizeZoneWidth) {
- $("body").addClass("gdfHResizing");
- } else {
- $("body").removeClass("gdfHResizing");
- }
- }
-
- }).on("mousedown.gdf", function (e) {
- //console.debug("mousedown.gdf")
- var colHeader = $(this);
-
- var nextCol = colHeader.next();
- if (nextCol.length > 0 && nextCol.width() < options.resizeZoneWidth)
- colHeader = nextCol;
-
- if (!colHeader.is(".gdfResizable"))
- return;
-
- var mousePos = e.pageX - colHeader.offset().left;
- if (colHeader.width() - mousePos < options.resizeZoneWidth) {
- $("body").unselectable();
- $.gridify.columInResize = colHeader;
- //on event for start resizing
- //console.debug("start resizing");
- $(document).on("mousemove.gdf", function (e) {
-
- e.preventDefault();
- $("body").addClass("gdfHResizing");
-
- //manage resizing
- var w = e.pageX - $.gridify.columInResize.offset().left;
- w = w <= 1 ? 1 : w;
- $.gridify.columInResize.width(w);
- $.gridify.columInResize.data("fTh").width(w);
-
-
- //on mouse up on body to stop resizing
- }).on("mouseup.gdf", function () {
- //console.debug("mouseup.gdf")
-
- //$("body").css({cursor: "auto"});
-
- $(this).off("mousemove.gdf").off("mouseup.gdf").clearunselectable();
- $("body").removeClass("gdfHResizing");
- delete $.gridify.columInResize;
-
- //save columns dimension
- storeGridState();
-
- });
- }
-
- }).on("dblclick.gdf", function () {
- //console.debug("dblclick.gdf")
- var col = $(this);
-
- if (!col.is(".gdfResizable"))
- return;
-
- var idx = $("th", col.parents("table")).index(col);
- var columnTd = $("td:nth-child(" + (idx + 1) + ")", table);
- var w = 0;
- columnTd.each(function () {
- var td = $(this);
- var content = td.children("input").length ? td.children("input").val() : td.html();
- var tmp = $("<div/>").addClass("columnWidthTest").html(content).css({position: "absolute"});
- $("body").append(tmp);
- w = Math.max(w, tmp.width() + parseFloat(td.css("padding-left")));
- tmp.remove();
- });
-
- w = w + 5;
- col.width(w);
- col.data("fTh").width(w);
-
- //save columns dimension
- storeGridState();
- return false;
-
- }).addClass("gdfied unselectable").attr("unselectable", "true");
-
-
- function storeGridState() {
- //console.debug("storeGridState");
- if (localStorage) {
- var gridState = {};
-
- var colSizes = [];
- $(".gdfTable .gdfColHeader").each(function () {
- colSizes.push($(this).outerWidth());
- });
-
- gridState.colSizes = colSizes;
-
- localStorage.setObject("TWPGanttGridState", gridState);
- //console.debug("gridState",localStorage.getItem("TWPGanttGridState"));
- }
- }
-
- function loadGridState() {
- //console.debug("loadGridState")
- if (localStorage) {
- if (localStorage.getObject("TWPGanttGridState")) {
- var gridState = localStorage.getObject("TWPGanttGridState");
- if (gridState.colSizes) {
- box.find(".gdfTable .gdfColHeader").each(function (i) {
- $(this).width(gridState.colSizes[i]);
- });
- }
- }
- }
- }
-
- loadGridState();
- return box;
- };
-
-
-
-
- $.splittify = {
- init: function (where, first, second, perc) {
-
- //perc = perc || 50;
-
- var element = $("<div>").addClass("splitterContainer");
- var firstBox = $("<div>").addClass("splitElement splitBox1");
- var splitterBar = $("<div>").addClass("splitElement vSplitBar").attr("unselectable", "on").css("padding-top", where.height() / 2 + "px");
- var secondBox = $("<div>").addClass("splitElement splitBox2");
-
-
- var splitter = new Splitter(element, firstBox, secondBox, splitterBar);
- splitter.perc = perc;
-
- //override with saved one
- loadPosition();
-
- var toLeft = $("<div>").addClass("toLeft").html("{").click(function () {splitter.resize(0.001, 300);});
- splitterBar.append(toLeft);
-
- var toCenter = $("<div>").addClass("toCenter").html("©").click(function () {splitter.resize(50, 300);});
- splitterBar.append(toCenter);
-
- var toRight = $("<div>").addClass("toRight").html("}").click(function () {splitter.resize(99.9999, 300);});
- splitterBar.append(toRight);
-
-
- firstBox.append(first);
- secondBox.append(second);
-
- element.append(firstBox).append(secondBox).append(splitterBar);
-
- where.append(element);
-
- var totalW = where.innerWidth();
- var splW = splitterBar.width();
- var fbw = totalW * perc / 100 - splW;
- //var realW = firstBox.get(0).scrollWidth;
- //fbw = fbw > realW? realW: fbw;
- fbw = fbw > totalW - splW - splitter.secondBoxMinWidth ? totalW - splW - splitter.secondBoxMinWidth : fbw;
- firstBox.width(fbw).css({left: 0});
- splitterBar.css({left: firstBox.width()});
- secondBox.width(totalW - fbw - splW).css({left: firstBox.width() + splW});
-
- splitterBar.on("mousedown.gdf", function (e) {
-
- e.preventDefault();
- $("body").addClass("gdfHResizing");
-
- $.splittify.splitterBar = $(this);
- //on event for start resizing
- //console.debug("start splitting");
- //var realW = firstBox.get(0).scrollWidth;
- $("body").unselectable().on("mousemove.gdf", function (e) {
- //manage resizing
- //console.debug(e.pageX - $.gridify.columInResize.offset().left)
-
- e.preventDefault();
-
- var sb = $.splittify.splitterBar;
- var pos = e.pageX - sb.parent().offset().left;
- var w = sb.parent().width();
- var fbw = firstBox;
-
- pos = pos > splitter.firstBoxMinWidth ? pos : splitter.firstBoxMinWidth;
- //pos = pos < realW - 10 ? pos : realW - 10;
- pos = pos > totalW - splW - splitter.secondBoxMinWidth ? totalW - splW - splitter.secondBoxMinWidth : pos;
- sb.css({left: pos});
- firstBox.width(pos);
- secondBox.css({left: pos + sb.width(), width: w - pos - sb.width()});
- splitter.perc = (firstBox.width() / splitter.element.width()) * 100;
-
- //on mouse up on body to stop resizing
- }).on("mouseup.gdf", function () {
- //console.debug("stop splitting");
- $(this).off("mousemove.gdf").off("mouseup.gdf").clearunselectable();
- delete $.splittify.splitterBar;
-
- $("body").removeClass("gdfHResizing");
-
- storePosition();
- });
- });
-
-
- // keep both side in synch when scroll
- var stopScroll = false;
- var fs = firstBox.add(secondBox);
- fs.scroll(function (e) {
- var el = $(this);
- var top = el.scrollTop();
- if (el.is(".splitBox1") && stopScroll != "splitBox2") {
- stopScroll = "splitBox1";
- secondBox.scrollTop(top);
- } else if (el.is(".splitBox2") && stopScroll != "splitBox1") {
- stopScroll = "splitBox2";
- firstBox.scrollTop(top);
- }
- firstBox.find(".ganttFixHead").css('top', top);
- secondBox.find(".ganttFixHead").css('top', top);
-
- where.stopTime("reset").oneTime(100, "reset", function () {stopScroll = "";})
- });
-
-
- firstBox.on('mousewheel MozMousePixelScroll', function (event) {
-
- event.preventDefault();
-
- var deltaY = event.originalEvent.wheelDeltaY;
- var deltaX = event.originalEvent.wheelDeltaX;
-
- if (event.originalEvent.axis) {
- deltaY = event.originalEvent.axis == 2 ? -event.originalEvent.detail : null;
- deltaX = event.originalEvent.axis == 1 ? -event.originalEvent.detail : null;
- }
-
- deltaY = Math.abs(deltaY) < 40 ? 40 * (Math.abs(deltaY) / deltaY) : deltaY;
- deltaX = Math.abs(deltaX) < 40 ? 40 * (Math.abs(deltaX) / deltaX) : deltaX;
-
- var scrollToY = secondBox.scrollTop() - deltaY;
- var scrollToX = firstBox.scrollLeft() - deltaX;
-
- // console.debug( firstBox.scrollLeft(), Math.abs(deltaX), Math.abs(deltaY));
-
- if (deltaY) secondBox.scrollTop(scrollToY);
- if (deltaX) firstBox.scrollLeft(scrollToX);
-
- return false;
- });
-
-
- function Splitter(element, firstBox, secondBox, splitterBar) {
- this.element = element;
- this.firstBox = firstBox;
- this.secondBox = secondBox;
- this.splitterBar = splitterBar;
- this.perc = 0;
- this.firstBoxMinWidth = 0;
- this.secondBoxMinWidth = 30;
-
- this.resize = function (newPerc, anim) {
- var animTime = anim ? anim : 0;
- this.perc = newPerc ? newPerc : this.perc;
- var totalW = this.element.width();
- var splW = this.splitterBar.width();
- var newW = totalW * this.perc / 100;
- newW = newW > this.firstBoxMinWidth ? newW : this.firstBoxMinWidth;
- newW = newW > totalW - splW - splitter.secondBoxMinWidth ? totalW - splW - splitter.secondBoxMinWidth : newW;
- this.firstBox.animate({width: newW}, animTime, function () {$(this).css("overflow-x", "auto")});
- this.splitterBar.animate({left: newW}, animTime);
- this.secondBox.animate({left: newW + this.splitterBar.width(), width: totalW - newW - splW}, animTime, function () {$(this).css("overflow", "auto")});
-
- storePosition();
- };
-
- var self = this;
- this.splitterBar.on("dblclick", function () {
- self.resize(50, true);
- })
- }
-
-
- function storePosition () {
- //console.debug("storePosition",splitter.perc);
- if (localStorage) {
- localStorage.setItem("TWPGanttSplitPos",splitter.perc);
- }
- }
-
- function loadPosition () {
- //console.debug("loadPosition");
- if (localStorage) {
- if (localStorage.getItem("TWPGanttSplitPos")) {
- splitter.perc=parseFloat(localStorage.getItem("TWPGanttSplitPos"));
- }
- }
- }
-
-
-
- return splitter;
- }
-
- };
-
-
- //<%------------------------------------------------------------------------ UTILITIES ---------------------------------------------------------------%>
- function computeStart(start) {
- return computeStartDate(start).getTime();
- }
- function computeStartDate(start) {
- var d = new Date(start + 3600000 * 12);
- d.setHours(0, 0, 0, 0);
- //move to next working day
- while (isHoliday(d)) {
- d.setDate(d.getDate() + 1);
- }
- d.setHours(0, 0, 0, 0);
- return d;
- }
-
- function computeEnd(end) {
- return computeEndDate(end).getTime()
- }
- function computeEndDate(end) {
- var d = new Date(end - 3600000 * 12);
- d.setHours(23, 59, 59, 999);
- //move to next working day
- while (isHoliday(d)) {
- d.setDate(d.getDate() + 1);
- }
- d.setHours(23, 59, 59, 999);
- return d;
- }
-
- function computeEndByDuration(start, duration) {
- var d = new Date(start);
- //console.debug("computeEndByDuration start ",d,duration)
- var q = duration - 1;
- while (q > 0) {
- d.setDate(d.getDate() + 1);
- if (!isHoliday(d))
- q--;
- }
- d.setHours(23, 59, 59, 999);
- return d.getTime();
- }
-
-
- function incrementDateByWorkingDays(date, days) {
- var d = new Date(date);
- d.incrementDateByWorkingDays(days);
- return d.getTime();
- }
-
-
- function recomputeDuration(start, end) {
- //console.debug("recomputeDuration");
- return new Date(start).distanceInWorkingDays(new Date(end)) + 1;
- }
-
-
- function resynchDates(leavingField, startField, startMilesField, durationField, endField, endMilesField) {
- //console.debug("resynchDates",leavingField.prop("name"), startField.prop("name"), startMilesField.prop("name"), durationField.prop("name"), endField.prop("name"), endMilesField.prop("name"));
- function resynchDatesSetFields(command) {
- //console.debug("resynchDatesSetFields",command);
- //var duration = parseInt(durationField.val());
- var duration = daysFromString(durationField.val(), true);
- if (!duration || duration < 1)
- duration = 1;
-
- var start = computeStart(Date.parseString(startField.val()).getTime());
-
- var end = endField.val();
- if (end.length > 0) {
- end = Date.parseString(end);
- end.setHours(23, 59, 59, 999);
- end = computeEnd(end.getTime());
- }
-
- var date = new Date();
- if ("CHANGE_END" == command) {
- date.setTime(start);
- var workingDays = duration - 1;
- date.incrementDateByWorkingDays(workingDays);
- date.setHours(23, 59, 59, 999);
- end = computeEnd(date.getTime());
- } else if ("CHANGE_START" == command) {
- date.setTime(end);
- var workingDays = duration - 1;
- date.incrementDateByWorkingDays(-workingDays);
- date.setHours(0, 0, 0, 0);
- start = computeStart(date.getTime());
- } else if ("CHANGE_DURATION" == command) {
- //console.debug("CHANGE_DURATION",new Date(start),new Date(end))
- duration = new Date(start).distanceInWorkingDays(new Date(end)) + 1;
- }
-
- startField.val(new Date(start).format());
- endField.val(new Date(end).format());
- durationField.val(duration);
-
- return {start: start, end: end, duration: duration};
- }
-
- var leavingFieldName = leavingField.prop("name");
- var durIsFilled = durationField.val().length > 0;
- var startIsFilled = startField.val().length > 0;
- var endIsFilled = endField.val().length > 0;
- var startIsMilesAndFilled = startIsFilled && (startMilesField.prop("checked") || startField.is("[readOnly]"));
- var endIsMilesAndFilled = endIsFilled && (endMilesField.prop("checked") || endField.is("[readOnly]"));
-
- if (durIsFilled) {
- if (parseInt(durationField.val()) == NaN || parseInt(durationField.val()) < 1)
- durationField.val(1);
- }
-
- if (leavingFieldName.indexOf("Milestone") > 0) {
- if (startIsMilesAndFilled && endIsMilesAndFilled) {
- durationField.prop("readOnly", true);
- } else {
- durationField.prop("readOnly", false);
- }
- return;
- }
-
- //need at least two values to resynch the third
- if ((durIsFilled ? 1 : 0) + (startIsFilled ? 1 : 0) + (endIsFilled ? 1 : 0) < 2)
- return;
-
- var ret;
- if (leavingFieldName == 'start' && startIsFilled) {
- if (endIsMilesAndFilled && durIsFilled) {
- ret = resynchDatesSetFields("CHANGE_DURATION");
- } else if (durIsFilled) {
- ret = resynchDatesSetFields("CHANGE_END");
- }
-
- } else if (leavingFieldName == 'duration' && durIsFilled && !(endIsMilesAndFilled && startIsMilesAndFilled)) {
- if (endIsMilesAndFilled && !startIsMilesAndFilled) {
- ret = resynchDatesSetFields("CHANGE_START");
- } else if (!endIsMilesAndFilled) {
- //document.title=('go and change end!!');
- ret = resynchDatesSetFields("CHANGE_END");
- }
-
- } else if (leavingFieldName == 'end' && endIsFilled) {
- ret = resynchDatesSetFields("CHANGE_DURATION");
- }
- return ret;
- }
-
-
- //This prototype is provided by the Mozilla foundation and
- //is distributed under the MIT license.
- //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
-
- if (!Array.prototype.filter) {
- Array.prototype.filter = function (fun) {
- var len = this.length;
- if (typeof fun != "function")
- throw new TypeError();
-
- var res = new Array();
- var thisp = arguments[1];
- for (var i = 0; i < len; i++) {
- if (i in this) {
- var val = this[i]; // in case fun mutates this
- if (fun.call(thisp, val, i, this))
- res.push(val);
- }
- }
- return res;
- };
- }
-
-
- function goToPage(url) {
- if (!canILeave()) return;
- window.location.href = url;
- }
|