gantt_rails 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/gantt/ganttDrawerSVG.js +992 -0
- data/app/assets/gantt/ganttGridEditor.js +666 -0
- data/app/assets/gantt/ganttMaster.js +1131 -0
- data/app/assets/gantt/ganttTask.js +1034 -0
- data/app/assets/gantt/ganttUtilities.js +304 -0
- data/app/assets/gantt/libs/JST/jquery.JST.js +167 -0
- data/app/assets/gantt/libs/date.js +584 -0
- data/app/assets/gantt/libs/dateField/jquery.dateField.js +213 -0
- data/app/assets/gantt/libs/i18nJs.js +139 -0
- data/app/assets/gantt/libs/jquery.1.8.js +9472 -0
- data/app/assets/gantt/libs/jquery.livequery.min.js +11 -0
- data/app/assets/gantt/libs/jquery.svg.js +1394 -0
- data/app/assets/gantt/libs/jquery.svg.min.js +7 -0
- data/app/assets/gantt/libs/jquery.svgdom.1.8.js +406 -0
- data/app/assets/gantt/libs/jquery.svgdom.js +406 -0
- data/app/assets/gantt/libs/jquery.svgdom.pack.js +7 -0
- data/app/assets/gantt/libs/jquery.timers.js +142 -0
- data/app/assets/gantt/libs/platform.js +954 -0
- data/gantt_rails.gemspec +2 -1
- data/lib/gantt_rails/version.rb +1 -1
- metadata +34 -2
@@ -0,0 +1,304 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2012-2014 Open Lab
|
3
|
+
Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
*/
|
23
|
+
|
24
|
+
$.gridify = function (table, opt) {
|
25
|
+
var options = {
|
26
|
+
resizeZoneWidth:10
|
27
|
+
};
|
28
|
+
|
29
|
+
$.extend(options, opt);
|
30
|
+
|
31
|
+
var box = $("<div>").addClass("gdfWrapper");
|
32
|
+
box.append(table);
|
33
|
+
|
34
|
+
var head = table.clone();
|
35
|
+
head.addClass("fixHead");
|
36
|
+
//remove non head
|
37
|
+
head.find("tbody").remove();
|
38
|
+
box.append(head);
|
39
|
+
|
40
|
+
box.append(table);
|
41
|
+
|
42
|
+
var hTh=head.find(".gdfColHeader");
|
43
|
+
var cTh=table.find(".gdfColHeader");
|
44
|
+
for (var i=0; i<hTh.length;i++){
|
45
|
+
hTh.eq(i).data("fTh",cTh.eq(i));
|
46
|
+
}
|
47
|
+
|
48
|
+
//--------- set table to 0 to prevent a strange 100%
|
49
|
+
table.width(0);
|
50
|
+
head.width(0);
|
51
|
+
|
52
|
+
|
53
|
+
//---------------------- header management start
|
54
|
+
head.find("th.gdfColHeader.gdfResizable:not(.gdfied)").mouseover(function () {
|
55
|
+
$(this).addClass("gdfColHeaderOver");
|
56
|
+
|
57
|
+
}).bind("mouseout.gdf",function () {
|
58
|
+
$(this).removeClass("gdfColHeaderOver");
|
59
|
+
if (!$.gridify.columInResize) {
|
60
|
+
$("body").removeClass("gdfHResizing");
|
61
|
+
}
|
62
|
+
|
63
|
+
}).bind("mousemove.gdf",function (e) {
|
64
|
+
if (!$.gridify.columInResize) {
|
65
|
+
var colHeader = $(this);
|
66
|
+
var mousePos = e.pageX - colHeader.offset().left;
|
67
|
+
|
68
|
+
if (colHeader.width() - mousePos < options.resizeZoneWidth) {
|
69
|
+
$("body").addClass("gdfHResizing");
|
70
|
+
} else {
|
71
|
+
$("body").removeClass("gdfHResizing");
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
}).bind("mousedown.gdf",function (e) {
|
76
|
+
var colHeader = $(this);
|
77
|
+
var mousePos = e.pageX - colHeader.offset().left;
|
78
|
+
if (colHeader.width() - mousePos < options.resizeZoneWidth) {
|
79
|
+
$("body").unselectable();
|
80
|
+
$.gridify.columInResize = $(this);
|
81
|
+
//bind event for start resizing
|
82
|
+
//console.debug("start resizing");
|
83
|
+
$(document).bind("mousemove.gdf",function (e) {
|
84
|
+
//manage resizing
|
85
|
+
var w = e.pageX - $.gridify.columInResize.offset().left;
|
86
|
+
$.gridify.columInResize.width(w);
|
87
|
+
$.gridify.columInResize.data("fTh").width(w);
|
88
|
+
|
89
|
+
//bind mouse up on body to stop resizing
|
90
|
+
}).bind("mouseup.gdf", function () {
|
91
|
+
//console.debug("stop resizing");
|
92
|
+
$(this).unbind("mousemove.gdf").unbind("mouseup.gdf").clearUnselectable();
|
93
|
+
$("body").removeClass("gdfHResizing");
|
94
|
+
delete $.gridify.columInResize;
|
95
|
+
});
|
96
|
+
}
|
97
|
+
}).addClass("gdfied unselectable").attr("unselectable", "true");
|
98
|
+
|
99
|
+
|
100
|
+
//---------------------- cell management start wrapping
|
101
|
+
table.find("td.gdfCell:not(.gdfied)").each(function () {
|
102
|
+
var cell = $(this);
|
103
|
+
if (cell.is(".gdfEditable")) {
|
104
|
+
var inp = $("<input type='text'>").addClass("gdfCellInput");
|
105
|
+
inp.val(cell.text());
|
106
|
+
cell.empty().append(inp);
|
107
|
+
} else {
|
108
|
+
var wrp = $("<div>").addClass("gdfCellWrap");
|
109
|
+
wrp.html(cell.html());
|
110
|
+
cell.empty().append(wrp);
|
111
|
+
}
|
112
|
+
}).addClass("gdfied");
|
113
|
+
|
114
|
+
return box;
|
115
|
+
};
|
116
|
+
|
117
|
+
$.splittify = {
|
118
|
+
init: function(where, first, second,perc) {
|
119
|
+
|
120
|
+
perc=perc || 50;
|
121
|
+
|
122
|
+
var element = $("<div>").addClass("splitterContainer");
|
123
|
+
var firstBox = $("<div>").addClass("splitElement splitBox1");
|
124
|
+
var splitterBar = $("<div>").addClass("splitElement vSplitBar").attr("unselectable", "on").html("|").css("padding-top",where.height()/2+"px");
|
125
|
+
var secondBox = $("<div>").addClass("splitElement splitBox2");
|
126
|
+
|
127
|
+
var splitter= new Splitter(element,firstBox,secondBox,splitterBar);
|
128
|
+
splitter.perc=perc;
|
129
|
+
|
130
|
+
|
131
|
+
firstBox.append(first);
|
132
|
+
secondBox.append(second);
|
133
|
+
|
134
|
+
element.append(firstBox).append(secondBox).append(splitterBar);
|
135
|
+
|
136
|
+
where.append(element);
|
137
|
+
|
138
|
+
var w = where.innerWidth();
|
139
|
+
var fbw = w *perc/ 100 - splitterBar.width();
|
140
|
+
var realW=firstBox.get(0).scrollWidth;
|
141
|
+
fbw=fbw>realW?realW:fbw;
|
142
|
+
firstBox.width(fbw).css({left:0});
|
143
|
+
splitterBar.css({left:firstBox.width()});
|
144
|
+
secondBox.width(w -fbw-splitterBar.width() ).css({left:firstBox.width() + splitterBar.width()});
|
145
|
+
|
146
|
+
|
147
|
+
splitterBar.bind("mousedown.gdf", function(e) {
|
148
|
+
$.splittify.splitterBar = $(this);
|
149
|
+
//bind event for start resizing
|
150
|
+
//console.debug("start splitting");
|
151
|
+
var realW=firstBox.get(0).scrollWidth;
|
152
|
+
$("body").unselectable().bind("mousemove.gdf", function(e) {
|
153
|
+
//manage resizing
|
154
|
+
//console.debug(e.pageX - $.gridify.columInResize.offset().left)
|
155
|
+
var sb = $.splittify.splitterBar;
|
156
|
+
var pos = e.pageX - sb.parent().offset().left;
|
157
|
+
var w = sb.parent().width();
|
158
|
+
var fbw=firstBox;
|
159
|
+
|
160
|
+
pos=pos>splitter.firstBoxMinWidth?pos:splitter.firstBoxMinWidth;
|
161
|
+
pos=pos<realW-10?pos:realW-10;
|
162
|
+
sb.css({left:pos});
|
163
|
+
firstBox.width(pos);
|
164
|
+
secondBox.css({left:pos + sb.width(),width:w - pos - sb.width()});
|
165
|
+
splitter.perc=(firstBox.width()/splitter.element.width())*100;
|
166
|
+
|
167
|
+
//bind mouse up on body to stop resizing
|
168
|
+
}).bind("mouseup.gdf", function() {
|
169
|
+
//console.debug("stop splitting");
|
170
|
+
$(this).unbind("mousemove.gdf").unbind("mouseup.gdf").clearUnselectable();
|
171
|
+
delete $.splittify.splitterBar;
|
172
|
+
|
173
|
+
});
|
174
|
+
});
|
175
|
+
|
176
|
+
|
177
|
+
// keep both side in synch when scroll
|
178
|
+
var stopScroll=false;
|
179
|
+
var fs=firstBox.add(secondBox);
|
180
|
+
fs.scroll(function(e) {
|
181
|
+
var el = $(this);
|
182
|
+
var top = el.scrollTop();
|
183
|
+
if (el.is(".splitBox1") && stopScroll!="splitBox2"){
|
184
|
+
stopScroll="splitBox1";
|
185
|
+
secondBox.scrollTop(top);
|
186
|
+
}else if (el.is(".splitBox2") && stopScroll!="splitBox1"){
|
187
|
+
stopScroll="splitBox2";
|
188
|
+
firstBox.scrollTop(top);
|
189
|
+
}
|
190
|
+
secondBox.find(".fixHead").css('top', top);
|
191
|
+
firstBox.find(".fixHead").css('top', top);
|
192
|
+
|
193
|
+
where.stopTime("reset").oneTime(100,"reset",function(){stopScroll="";})
|
194
|
+
});
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
function Splitter(element,firstBox, secondBox, splitterBar) {
|
199
|
+
this.element=element;
|
200
|
+
this.firstBox = firstBox;
|
201
|
+
this.secondBox = secondBox;
|
202
|
+
this.splitterBar = splitterBar;
|
203
|
+
this.perc=0;
|
204
|
+
this.firstBoxMinWidth=0;
|
205
|
+
|
206
|
+
this.resize=function(newPerc){
|
207
|
+
//console.debug("resize",newPerc)
|
208
|
+
this.perc=newPerc?newPerc:this.perc;
|
209
|
+
var totW=this.element.width();
|
210
|
+
var realW=this.firstBox.get(0).scrollWidth;
|
211
|
+
var newW=totW*this.perc/100;
|
212
|
+
newW=newW>this.firstBoxMinWidth?newW:this.firstBoxMinWidth;
|
213
|
+
newW=newW<realW?newW:realW;
|
214
|
+
this.firstBox.css({width:newW});
|
215
|
+
this.splitterBar.css({left:newW});
|
216
|
+
this.secondBox.css({left:newW + this.splitterBar.width(),width:totW - newW - this.splitterBar.width()});
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
return splitter;
|
221
|
+
}
|
222
|
+
};
|
223
|
+
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
|
228
|
+
//<%------------------------------------------------------------------------ UTILITIES ---------------------------------------------------------------%>
|
229
|
+
function computeStart(start) {
|
230
|
+
return computeStartDate(start).getTime();
|
231
|
+
}
|
232
|
+
function computeStartDate(start) {
|
233
|
+
var d = new Date(start+3600000*12);
|
234
|
+
d.setHours(0, 0, 0, 0);
|
235
|
+
//move to next working day
|
236
|
+
while (isHoliday(d)) {
|
237
|
+
d.setDate(d.getDate() + 1);
|
238
|
+
}
|
239
|
+
d.setHours(0, 0, 0, 0);
|
240
|
+
return d;
|
241
|
+
}
|
242
|
+
|
243
|
+
function computeEnd(end) {
|
244
|
+
return computeEndDate(end).getTime()
|
245
|
+
}
|
246
|
+
function computeEndDate(end) {
|
247
|
+
var d = new Date(end-3600000*12);
|
248
|
+
d.setHours(23, 59, 59, 999);
|
249
|
+
//move to next working day
|
250
|
+
while (isHoliday(d)) {
|
251
|
+
d.setDate(d.getDate() + 1);
|
252
|
+
}
|
253
|
+
d.setHours(23, 59, 59, 999);
|
254
|
+
return d;
|
255
|
+
}
|
256
|
+
|
257
|
+
function computeEndByDuration(start, duration) {
|
258
|
+
var d = new Date(start);
|
259
|
+
//console.debug("computeEndByDuration start ",d,duration)
|
260
|
+
var q = duration - 1;
|
261
|
+
while (q > 0) {
|
262
|
+
d.setDate(d.getDate() + 1);
|
263
|
+
if (!isHoliday(d))
|
264
|
+
q--;
|
265
|
+
}
|
266
|
+
d.setHours(23, 59, 59, 999);
|
267
|
+
return d.getTime();
|
268
|
+
}
|
269
|
+
|
270
|
+
function incrementDateByWorkingDays(date, days) {
|
271
|
+
var d = new Date(date);
|
272
|
+
d.incrementDateByWorkingDays(days);
|
273
|
+
return d.getTime();
|
274
|
+
}
|
275
|
+
|
276
|
+
function recomputeDuration(start, end) {
|
277
|
+
//console.debug("recomputeDuration");
|
278
|
+
return new Date(start).distanceInWorkingDays(new Date(end));
|
279
|
+
}
|
280
|
+
|
281
|
+
|
282
|
+
|
283
|
+
//This prototype is provided by the Mozilla foundation and
|
284
|
+
//is distributed under the MIT license.
|
285
|
+
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
|
286
|
+
|
287
|
+
if (!Array.prototype.filter){
|
288
|
+
Array.prototype.filter = function (fun) {
|
289
|
+
var len = this.length;
|
290
|
+
if (typeof fun != "function")
|
291
|
+
throw new TypeError();
|
292
|
+
|
293
|
+
var res = new Array();
|
294
|
+
var thisp = arguments[1];
|
295
|
+
for (var i = 0; i < len; i++) {
|
296
|
+
if (i in this) {
|
297
|
+
var val = this[i]; // in case fun mutates this
|
298
|
+
if (fun.call(thisp, val, i, this))
|
299
|
+
res.push(val);
|
300
|
+
}
|
301
|
+
}
|
302
|
+
return res;
|
303
|
+
};
|
304
|
+
}
|
@@ -0,0 +1,167 @@
|
|
1
|
+
$.fn.loadTemplates = function() {
|
2
|
+
$.JST.loadTemplates($(this));
|
3
|
+
return this;
|
4
|
+
};
|
5
|
+
|
6
|
+
$.JST = {
|
7
|
+
_templates: new Object(),
|
8
|
+
_decorators:new Object(),
|
9
|
+
|
10
|
+
loadTemplates: function(elems) {
|
11
|
+
elems.each(function() {
|
12
|
+
$(this).find(".__template__").each(function() {
|
13
|
+
var tmpl = $(this);
|
14
|
+
var type = tmpl.attr("type");
|
15
|
+
|
16
|
+
//template may be inside <!-- ... --> or not in case of ajax loaded templates
|
17
|
+
if (tmpl.get(0).firstChild.nodeType == 8) // 8==comment
|
18
|
+
var templateBody = tmpl.get(0).firstChild.nodeValue; // this is inside the comment
|
19
|
+
else
|
20
|
+
var templateBody = tmpl.html(); // this is the whole template
|
21
|
+
|
22
|
+
if (!templateBody.match(/##\w+##/)) { // is Resig' style? e.g. (#=id#) or (# ...some javascript code 'obj' is the alias for the object #)
|
23
|
+
var strFunc =
|
24
|
+
"var p=[],print=function(){p.push.apply(p,arguments);};" +
|
25
|
+
"with(obj){p.push('" +
|
26
|
+
templateBody.replace(/[\r\t\n]/g, " ")
|
27
|
+
.replace(/'(?=[^#]*#\))/g, "\t")
|
28
|
+
.split("'").join("\\'")
|
29
|
+
.split("\t").join("'")
|
30
|
+
.replace(/\(#=(.+?)#\)/g, "',$1,'")
|
31
|
+
.split("(#").join("');")
|
32
|
+
.split("#)").join("p.push('")
|
33
|
+
+ "');}return p.join('');";
|
34
|
+
|
35
|
+
try {
|
36
|
+
$.JST._templates[type] = new Function("obj", strFunc);
|
37
|
+
} catch (e) {
|
38
|
+
console.error("JST error: "+type, e,strFunc);
|
39
|
+
}
|
40
|
+
|
41
|
+
} else { //plain template e.g. ##id##
|
42
|
+
try {
|
43
|
+
$.JST._templates[type] = templateBody;
|
44
|
+
} catch (e) {
|
45
|
+
console.error("JST error: "+type, e,templateBody);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
tmpl.remove();
|
50
|
+
|
51
|
+
});
|
52
|
+
});
|
53
|
+
},
|
54
|
+
|
55
|
+
createFromTemplate: function(jsonData, template, transformToPrintable) {
|
56
|
+
var templates = $.JST._templates;
|
57
|
+
|
58
|
+
var jsData=new Object();
|
59
|
+
if (transformToPrintable){
|
60
|
+
for (var prop in jsonData){
|
61
|
+
var value = jsonData[prop];
|
62
|
+
if (typeof(value) == "string")
|
63
|
+
value = (value + "").replace(/\n/g, "<br>");
|
64
|
+
jsData[prop]=value;
|
65
|
+
}
|
66
|
+
} else {
|
67
|
+
jsData=jsonData;
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
function fillStripData(strip, data) {
|
72
|
+
for (var prop in data) {
|
73
|
+
var value = data[prop];
|
74
|
+
|
75
|
+
strip = strip.replace(new RegExp("##" + prop + "##", "gi"), value);
|
76
|
+
}
|
77
|
+
// then clean the remaining ##xxx##
|
78
|
+
strip = strip.replace(new RegExp("##\\w+##", "gi"), "");
|
79
|
+
return strip;
|
80
|
+
}
|
81
|
+
|
82
|
+
var stripString = "";
|
83
|
+
if (typeof(template) == "undefined") {
|
84
|
+
alert("Template is required");
|
85
|
+
stripString = "<div>Template is required</div>";
|
86
|
+
|
87
|
+
} else if (typeof(templates[template]) == "function") { // resig template
|
88
|
+
try {
|
89
|
+
stripString = templates[template](jsData);// create a jquery object in memory
|
90
|
+
} catch (e) {
|
91
|
+
console.error("JST error: "+template,e.message);
|
92
|
+
stripString = "<div> ERROR: "+template+"<br>" + e.message + "</div>";
|
93
|
+
}
|
94
|
+
|
95
|
+
} else {
|
96
|
+
stripString = templates[template]; // recover strip template
|
97
|
+
if (!stripString || stripString.trim() == "") {
|
98
|
+
console.error("No template found for type '" + template + "'");
|
99
|
+
return $("<div>");
|
100
|
+
|
101
|
+
} else {
|
102
|
+
stripString = fillStripData(stripString, jsData); //replace placeholders with data
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
var ret = $(stripString);// create a jquery object in memory
|
107
|
+
ret.attr("__template", template); // set __template attribute
|
108
|
+
|
109
|
+
//decorate the strip
|
110
|
+
var dec = $.JST._decorators[template];
|
111
|
+
if (typeof (dec) == "function")
|
112
|
+
dec(ret, jsData);
|
113
|
+
|
114
|
+
return ret;
|
115
|
+
},
|
116
|
+
|
117
|
+
|
118
|
+
existsTemplate: function(template) {
|
119
|
+
return $.JST._templates[template];
|
120
|
+
},
|
121
|
+
|
122
|
+
//decorate function is like function(domElement,jsonData){...}
|
123
|
+
loadDecorator:function(template, decorator) {
|
124
|
+
$.JST._decorators[template] = decorator;
|
125
|
+
},
|
126
|
+
|
127
|
+
getDecorator:function(template) {
|
128
|
+
return $.JST._decorators[template];
|
129
|
+
},
|
130
|
+
|
131
|
+
decorateTemplate:function(element) {
|
132
|
+
var dec = $.JST._decorators[element.attr("__template")];
|
133
|
+
if (typeof (dec) == "function")
|
134
|
+
dec(editor);
|
135
|
+
},
|
136
|
+
|
137
|
+
// asynchronous
|
138
|
+
ajaxLoadAsynchTemplates: function(templateUrl, callback) {
|
139
|
+
|
140
|
+
$.get(templateUrl, function(data) {
|
141
|
+
|
142
|
+
var div = $("<div>");
|
143
|
+
div.html(data);
|
144
|
+
|
145
|
+
$.JST.loadTemplates(div);
|
146
|
+
|
147
|
+
if (typeof(callback == "function"))
|
148
|
+
callback();
|
149
|
+
},"html");
|
150
|
+
},
|
151
|
+
|
152
|
+
ajaxLoadTemplates: function(templateUrl) {
|
153
|
+
$.ajax({
|
154
|
+
async:false,
|
155
|
+
url: templateUrl,
|
156
|
+
dataType: "html",
|
157
|
+
success: function(data) {
|
158
|
+
var div = $("<div>");
|
159
|
+
div.html(data);
|
160
|
+
$.JST.loadTemplates(div);
|
161
|
+
}
|
162
|
+
});
|
163
|
+
|
164
|
+
}
|
165
|
+
|
166
|
+
|
167
|
+
};
|