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.
@@ -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
+ };