├── res ├── alert.gif ├── icons.eot ├── icons.ttf ├── icons.woff ├── black_70.png ├── closeBig.png ├── linkArrow.png ├── milestone.png ├── twBanner.jpg ├── indentIcon.png ├── twGanttLogo.png ├── toggle-expand.png ├── hasExternalDeps.png ├── toggle_collapse.png ├── twproject-badge.png └── ganttSplitterGrip.png ├── libs ├── jquery │ ├── dateField │ │ ├── img │ │ │ ├── next.png │ │ │ ├── prev.png │ │ │ └── today.png │ │ ├── jquery.dateField.css │ │ └── jquery.dateField.js │ ├── jquery.livequery.1.1.1.min.js │ ├── jquery.timers.js │ ├── svg │ │ ├── jquery.svgdom.pack.js │ │ ├── jquery.svgdom.1.8.js │ │ └── jquery.svg.min.js │ └── JST │ │ └── jquery.JST.js ├── i18nJs.js ├── layout.js ├── dialogs.js ├── utilities.js └── forms.js ├── ganttPrint.css ├── README.md ├── platform.css ├── gantt.css ├── ganttUtilities.js └── ganttGridEditor.js /res/alert.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/alert.gif -------------------------------------------------------------------------------- /res/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/icons.eot -------------------------------------------------------------------------------- /res/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/icons.ttf -------------------------------------------------------------------------------- /res/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/icons.woff -------------------------------------------------------------------------------- /res/black_70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/black_70.png -------------------------------------------------------------------------------- /res/closeBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/closeBig.png -------------------------------------------------------------------------------- /res/linkArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/linkArrow.png -------------------------------------------------------------------------------- /res/milestone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/milestone.png -------------------------------------------------------------------------------- /res/twBanner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/twBanner.jpg -------------------------------------------------------------------------------- /res/indentIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/indentIcon.png -------------------------------------------------------------------------------- /res/twGanttLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/twGanttLogo.png -------------------------------------------------------------------------------- /res/toggle-expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/toggle-expand.png -------------------------------------------------------------------------------- /res/hasExternalDeps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/hasExternalDeps.png -------------------------------------------------------------------------------- /res/toggle_collapse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/toggle_collapse.png -------------------------------------------------------------------------------- /res/twproject-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/twproject-badge.png -------------------------------------------------------------------------------- /res/ganttSplitterGrip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/res/ganttSplitterGrip.png -------------------------------------------------------------------------------- /libs/jquery/dateField/img/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/libs/jquery/dateField/img/next.png -------------------------------------------------------------------------------- /libs/jquery/dateField/img/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/libs/jquery/dateField/img/prev.png -------------------------------------------------------------------------------- /libs/jquery/dateField/img/today.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spel/jQueryGantt/master/libs/jquery/dateField/img/today.png -------------------------------------------------------------------------------- /ganttPrint.css: -------------------------------------------------------------------------------- 1 | .noprint { 2 | display:none !important; 3 | } 4 | 5 | BODY, TBODY { 6 | font-family: arial; 7 | font-size: 12px; 8 | margin: 0; 9 | color: #000; 10 | overflow: visible!important; 11 | } 12 | 13 | .teamworkIcon{ 14 | display:none; 15 | } 16 | 17 | .mainColumn{ 18 | width:98% !important; 19 | } 20 | 21 | 22 | #TWGanttArea{ 23 | overflow-x: visible !important; 24 | overflow-y: visible !important; 25 | width: auto !important; 26 | height: auto !important; 27 | border:none !important; 28 | } 29 | 30 | .splitterContainer{ 31 | width: auto !important; 32 | height: auto !important; 33 | } 34 | .splitElement{ 35 | position: static !important; 36 | width: auto !important; 37 | height: auto !important; 38 | top:0 !important; 39 | left: 0 !important; 40 | overflow-x: visible !important; 41 | overflow-y: visible !important; 42 | } 43 | 44 | .vSplitBar,.emptyRow{ 45 | display: none !important; 46 | } 47 | 48 | .gdfTable{ 49 | width: 0 !important; 50 | } 51 | 52 | .splitBox2{ 53 | page-break-before: always !important; 54 | } 55 | 56 | 57 | .ganttFixHead{ 58 | display: none !important; 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jQueryGantt 2 | =========== 3 | jQuery Gantt editor has been written by Roberto Bicchierai and Silvia Chelazzi 4 | 5 | Twproject jQuery Gantt 6 | 7 | These are some key features: 8 | * jQuery based 3.2 9 | * MIT licensed: you can reuse everywhere 10 | * JSON import-export 11 | * internationalizable 12 | * manage task status –> project workflow 13 | * manage dependencies 14 | * manage assignments (resources, roles efforts) 15 | * server synchronization ready 16 | * full undo-redo support 17 | * cross browser (at least for recent versions) 18 | * keyboard editing support 19 | * SVG visual editor 20 | * print friendly 21 | * collapsible branches 22 | * critical path 23 | * milestones, progress etc. 24 | * zoom 25 | 26 | Try the online working demo here: https://gantt.twproject.com 27 | 28 | Read here about latest release: https://roberto.open-lab.com/2017/04/05/new-gantt-editor-release-the-best-ever/ 29 | 30 | Read the genesis of this component here: http://roberto.open-lab.com/2012/06/14/the-javascript-gantt-odyssey/ 31 | 32 | Documentation is here: http://roberto.open-lab.com/2012/08/24/jquery-gantt-editor/ 33 | 34 | jQuery Gantt editor is part of Twproject 6 project 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /libs/jquery/dateField/jquery.dateField.css: -------------------------------------------------------------------------------- 1 | .calBox { 2 | background-color: #999; 3 | text-align: center; 4 | color: white; 5 | width:200px; 6 | position:absolute; 7 | padding-bottom: 10px; 8 | } 9 | 10 | .calElement,.calDayHeader { 11 | padding: 1px; 12 | display: inline-block; 13 | overflow:hidden; 14 | } 15 | 16 | .calDayHeader { 17 | padding: 4px; 18 | display: inline-block; 19 | background-color:#55b6c7 20 | } 21 | 22 | .calNav { 23 | height: 20px; 24 | } 25 | 26 | .calNavBar { 27 | padding: 5px; 28 | background-color: rgba(0, 0, 0, 0.25) 29 | } 30 | 31 | 32 | .calDay .calElement, .calDay .calDayHeader { 33 | border: 1px solid transparent; 34 | } 35 | 36 | .calDay .calElement.holy { 37 | /*background-color: rgba(236, 195, 176, 0.40);*/ 38 | color: #81d7e2; 39 | 40 | } 41 | 42 | .calDay .calDayHeader { 43 | font-size: 8px; 44 | text-transform: uppercase; 45 | } 46 | 47 | .calElement.prev, 48 | .calElement.goToday, 49 | .calElement.next { 50 | width: 16px; 51 | height: 18px; 52 | border: none; 53 | margin-top: 0 54 | } 55 | .calElement.prev { 56 | background: transparent url(img/prev.png) no-repeat 5px center; 57 | float:left; 58 | } 59 | 60 | .calElement.goToday { 61 | background: transparent url(img/today.png) no-repeat 5px center; 62 | float:left; 63 | } 64 | 65 | .calElement.next { 66 | background: transparent url(img/next.png) no-repeat 5px center; 67 | float:right; 68 | } 69 | 70 | .calElement:hover{ 71 | background-color: transparent; 72 | border:none; 73 | cursor: pointer; 74 | opacity: 0.6 75 | } 76 | 77 | .calDay .calElement .dayNumber { 78 | font-size: 20px; 79 | } 80 | 81 | .calDay.calFullMonth .dayNumber { 82 | font-size: 14px; 83 | } 84 | .calDay .calOutOfScope{ 85 | color: #b1b0b0; 86 | } 87 | 88 | .calElement.selected { 89 | border: 1px solid #404040; 90 | } 91 | 92 | .calElement:hover { 93 | background-color: #404040; 94 | border: 1px solid #404040; 95 | cursor: pointer; 96 | } 97 | 98 | 99 | .calElement.today { 100 | border: 1px solid #c84e48; 101 | } 102 | 103 | 104 | .shortCuts { 105 | /*border-top: 1px solid rgba(0, 0, 0, 0.25);*/ 106 | padding: 3px 0 6px; 107 | background-color: rgba(97, 215, 232, 0.50) 108 | } 109 | 110 | .shortCuts span{ 111 | font-size: 11px; 112 | border: 1px dotted #617777; 113 | width: 23px; 114 | display: inline-block; 115 | cursor: pointer 116 | } 117 | 118 | .shortCuts span:hover { 119 | background-color: rgba(0, 0, 0, 0.25) 120 | } 121 | 122 | -------------------------------------------------------------------------------- /libs/jquery/jquery.livequery.1.1.1.min.js: -------------------------------------------------------------------------------- 1 | (function($){$.extend($.fn,{livequery:function(type,fn,fn2){var self=this,q;if($.isFunction(type))fn2=fn,fn=type,type=undefined;$.each($.livequery.queries,function(i,query){if(self.selector==query.selector&&self.context==query.context&&type==query.type&&(!fn||fn.$lqguid==query.fn.$lqguid)&&(!fn2||fn2.$lqguid==query.fn2.$lqguid))return(q=query)&&false});q=q||new $.livequery(this.selector,this.context,type,fn,fn2);q.stopped=false;q.run();return this},expire:function(type,fn,fn2){var self=this;if($.isFunction(type))fn2= 2 | fn,fn=type,type=undefined;$.each($.livequery.queries,function(i,query){if(self.selector==query.selector&&self.context==query.context&&(!type||type==query.type)&&(!fn||fn.$lqguid==query.fn.$lqguid)&&(!fn2||fn2.$lqguid==query.fn2.$lqguid)&&!this.stopped)$.livequery.stop(query.id)});return this}});$.livequery=function(selector,context,type,fn,fn2){this.selector=selector;this.context=context;this.type=type;this.fn=fn;this.fn2=fn2;this.elements=[];this.stopped=false;this.id=$.livequery.queries.push(this)- 3 | 1;fn.$lqguid=fn.$lqguid||$.livequery.guid++;if(fn2)fn2.$lqguid=fn2.$lqguid||$.livequery.guid++;return this};$.livequery.prototype={stop:function(){var query=this;if(this.type)this.elements.unbind(this.type,this.fn);else if(this.fn2)this.elements.each(function(i,el){query.fn2.apply(el)});this.elements=[];this.stopped=true},run:function(){if(this.stopped)return;var query=this;var oEls=this.elements,els=$(this.selector,this.context),nEls=els.not(oEls);this.elements=els;if(this.type){nEls.bind(this.type, 4 | this.fn);if(oEls.length>0)$.each(oEls,function(i,el){if($.inArray(el,els)<0)$.event.remove(el,query.type,query.fn)})}else{nEls.each(function(){query.fn.apply(this)});if(this.fn2&&oEls.length>0)$.each(oEls,function(i,el){if($.inArray(el,els)<0)query.fn2.apply(el)})}}};$.extend($.livequery,{guid:0,queries:[],queue:[],running:false,timeout:null,checkQueue:function(){if($.livequery.running&&$.livequery.queue.length){var length=$.livequery.queue.length;while(length--)$.livequery.queries[$.livequery.queue.shift()].run()}}, 5 | pause:function(){$.livequery.running=false},play:function(){$.livequery.running=true;$.livequery.run()},registerPlugin:function(){$.each(arguments,function(i,n){if(!$.fn[n])return;var old=$.fn[n];$.fn[n]=function(){var r=old.apply(this,arguments);$.livequery.run();return r}})},run:function(id){if(id!=undefined){if($.inArray(id,$.livequery.queue)<0)$.livequery.queue.push(id)}else $.each($.livequery.queries,function(id){if($.inArray(id,$.livequery.queue)<0)$.livequery.queue.push(id)});if($.livequery.timeout)clearTimeout($.livequery.timeout); 6 | $.livequery.timeout=setTimeout($.livequery.checkQueue,20)},stop:function(id){if(id!=undefined)$.livequery.queries[id].stop();else $.each($.livequery.queries,function(id){$.livequery.queries[id].stop()})}});$.livequery.registerPlugin("append","prepend","after","before","wrap","attr","removeAttr","addClass","removeClass","toggleClass","empty","remove","html");$(function(){$.livequery.play()})})(jQuery); -------------------------------------------------------------------------------- /libs/jquery/jquery.timers.js: -------------------------------------------------------------------------------- 1 | jQuery.fn.extend({ 2 | everyTime: function(interval, label, fn, times, belay) { 3 | return this.each(function() { 4 | jQuery.timer.add(this, interval, label, fn, times, belay); 5 | }); 6 | }, 7 | oneTime: function(interval, label, fn) { 8 | return this.each(function() { 9 | jQuery.timer.add(this, interval, label, fn, 1); 10 | }); 11 | }, 12 | stopTime: function(label, fn) { 13 | return this.each(function() { 14 | jQuery.timer.remove(this, label, fn); 15 | }); 16 | } 17 | }); 18 | 19 | jQuery.extend({ 20 | timer: { 21 | guid: 1, 22 | global: {}, 23 | regex: /^([0-9]+)\s*(.*s)?$/, 24 | powers: { 25 | // Yeah this is major overkill... 26 | 'ms': 1, 27 | 'cs': 10, 28 | 'ds': 100, 29 | 's': 1000, 30 | 'das': 10000, 31 | 'hs': 100000, 32 | 'ks': 1000000 33 | }, 34 | timeParse: function(value) { 35 | if (value == undefined || value == null) 36 | return null; 37 | var result = this.regex.exec(jQuery.trim(value.toString())); 38 | if (result[2]) { 39 | var num = parseInt(result[1], 10); 40 | var mult = this.powers[result[2]] || 1; 41 | return num * mult; 42 | } else { 43 | return value; 44 | } 45 | }, 46 | add: function(element, interval, label, fn, times, belay) { 47 | var counter = 0; 48 | 49 | if (jQuery.isFunction(label)) { 50 | if (!times) 51 | times = fn; 52 | fn = label; 53 | label = interval; 54 | } 55 | 56 | interval = jQuery.timer.timeParse(interval); 57 | 58 | if (typeof interval != 'number' || isNaN(interval) || interval <= 0) 59 | return; 60 | 61 | if (times && times.constructor != Number) { 62 | belay = !!times; 63 | times = 0; 64 | } 65 | 66 | times = times || 0; 67 | belay = belay || false; 68 | 69 | if (!element.$timers) 70 | element.$timers = {}; 71 | 72 | if (!element.$timers[label]) 73 | element.$timers[label] = {}; 74 | 75 | fn.$timerID = fn.$timerID || this.guid++; 76 | 77 | var handler = function() { 78 | if (belay && this.inProgress) 79 | return; 80 | this.inProgress = true; 81 | if ((++counter > times && times !== 0) || fn.call(element, counter) === false) 82 | jQuery.timer.remove(element, label, fn); 83 | this.inProgress = false; 84 | }; 85 | 86 | handler.$timerID = fn.$timerID; 87 | 88 | if (!element.$timers[label][fn.$timerID]) 89 | element.$timers[label][fn.$timerID] = window.setInterval(handler,interval); 90 | 91 | if ( !this.global[label] ) 92 | this.global[label] = []; 93 | this.global[label].push( element ); 94 | 95 | }, 96 | remove: function(element, label, fn) { 97 | var timers = element.$timers, ret; 98 | 99 | if ( timers ) { 100 | 101 | if (!label) { 102 | for ( label in timers ) 103 | this.remove(element, label, fn); 104 | } else if ( timers[label] ) { 105 | if ( fn ) { 106 | if ( fn.$timerID ) { 107 | window.clearInterval(timers[label][fn.$timerID]); 108 | delete timers[label][fn.$timerID]; 109 | } 110 | } else { 111 | for ( var fn in timers[label] ) { 112 | window.clearInterval(timers[label][fn]); 113 | delete timers[label][fn]; 114 | } 115 | } 116 | 117 | for ( ret in timers[label] ) break; 118 | if ( !ret ) { 119 | ret = null; 120 | delete timers[label]; 121 | } 122 | } 123 | 124 | for ( ret in timers ) break; 125 | if ( !ret ) 126 | element.$timers = null; 127 | } 128 | } 129 | } 130 | }); 131 | 132 | jQuery(window).one("unload", function() { 133 | var global = jQuery.timer.global; 134 | for ( var label in global ) { 135 | var els = global[label], i = els.length; 136 | while ( --i ) 137 | jQuery.timer.remove(els[i], label); 138 | } 139 | }); 140 | 141 | 142 | -------------------------------------------------------------------------------- /libs/jquery/svg/jquery.svgdom.pack.js: -------------------------------------------------------------------------------- 1 | /* http://keith-wood.name/svg.html 2 | jQuery DOM compatibility for jQuery SVG v1.4.5. 3 | Written by Keith Wood (kbwood{at}iinet.com.au) April 2009. 4 | Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 5 | MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 6 | Please attribute the author if you use it. */ 7 | eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.q.S=7(e){8 7(d){d=d||\'\';8 9.w(7(){k($.r.v(9)){l c=9;$.w(d.E(/\\s+/),7(i,a){l b=(c.o?c.o.p:c.B(\'z\'));k($.T(a,b.E(/\\s+/))==-1){b+=(b?\' \':\'\')+a;(c.o?c.o.p=b:c.H(\'z\',b))}})}x{e.A($(9),[d])}})}}($.q.S);$.q.U=7(e){8 7(d){d=d||\'\';8 9.w(7(){k($.r.v(9)){l c=9;$.w(d.E(/\\s+/),7(i,a){l b=(c.o?c.o.p:c.B(\'z\'));b=$.1d(b.E(/\\s+/),7(n,i){8 n!=a}).1e(\' \');(c.o?c.o.p=b:c.H(\'z\',b))})}x{e.A($(9),[d])}})}}($.q.U);$.q.V=7(c){8 7(a,b){8 9.w(7(){k($.r.v(9)){k(M b!==\'1f\'){b=!$(9).N(a)}$(9)[(b?\'1g\':\'1h\')+\'1i\'](a)}x{c.A($(9),[a,b])}})}}($.q.V);$.q.N=7(d){8 7(b){b=b||\'\';l c=I;9.w(7(){k($.r.v(9)){l a=(9.o?9.o.p:9.B(\'z\')).E(/\\s+/);c=($.T(b,a)>-1)}x{c=(d.A($(9),[b]))}8!c});8 c}}($.q.N);$.q.O=7(h){8 7(b,c,d){k(M b===\'W\'&&c===1j){l e=h.A(9,[b]);k(e&&e.p&&e.p.X!=J){c=\'\';e=e.p;k(b==\'1k\'){F(l i=0;i\']=7(d){8 7(a,b,c){d(a,b,c||G(a))}}($.m.y[\'>\']);$.m.y[\'\']=7(d){8 7(a,b,c){d(a,b,c||G(a))}}($.m.y[\'\']);$.m.y[\'~\']=7(d){8 7(a,b,c){d(a,b,c||G(a))}}($.m.y[\'~\']);$.m.Q.15=7(d){8 7(a,b,c){8($.r.v(b)?[b.1F.1G(a[1])]:d(a,b,c))}}($.m.Q.15);l j=16.1H(\'1I\');j.1J(16.1K(\'\'));k(j.17(\'*\').13>0){$.m.Q.1L=7(a,b){l c=b.17(a[1]);k(a[1]===\'*\'){l d=[];F(l i=0;c[i]||c.L(i);i++){k((c[i]||c.L(i)).14===1){d.18(c[i]||c.L(i))}}c=d}8 c}}$.m.1M.19=7(a,b,c,d,f,g){a=\' \'+a[1].1N(/\\\\/g,\'\')+\' \';k(g){8 a}F(l i=0,t={};t!=J;i++){t=b[i];k(!t){1O{t=b.L(i)}1P(e){}}k(t){l h=(!$.r.v(t)?t.o:(t.o?t.o.p:\'\')||t.B(\'z\'));k(f^(h&&(\' \'+h+\' \').1a(a)>-1)){k(!c)d.18(t)}x k(c){b[i]=I}}}8 I};$.m.R.19=7(a,b){l c=(!$.r.v(a)?a.o:(a.o?a.o.p:a.B(\'z\')));8(\' \'+c+\' \').1a(b)>-1};$.m.R.1b=7(g){8 7(c,d){l e=J;k($.r.v(c)){e=d[1];$.m.1c[e]=7(a){l b=a.B(e);8 b&&b.p||b}}l f=g(c,d);k(e){$.m.1c[e]=J}8 f}}($.m.R.1b)})(1Q);',62,115,'|||||||function|return|this|||||||||||if|var|expr||className|baseVal|fn|svg||elem|matrix|isSVGElem|each|else|relative|class|apply|getAttribute|case|break|split|for|anySVG|setAttribute|false|null|true|item|typeof|hasClass|attr|angle|find|filter|addClass|inArray|removeClass|toggleClass|string|numberOfItems|getItem|valueAsString|removeAttr|cssProps|css|length|nodeType|ID|document|getElementsByTagName|push|CLASS|indexOf|ATTR|attrHandle|grep|join|boolean|add|remove|Class|undefined|transform|switch|type|translate|scale|rotate|skewX|skewY|substring|in|isFunction|style|value|extend|cssNumber|stopOpacity|strokeMitrelimit|strokeOpacity|match|namespaceURI|svgNS|ownerDocument|getElementById|createElement|div|appendChild|createComment|TAG|preFilter|replace|try|catch|jQuery'.split('|'),0,{})) -------------------------------------------------------------------------------- /libs/jquery/JST/jquery.JST.js: -------------------------------------------------------------------------------- 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 | var found=false; 18 | var el=tmpl.get(0).firstChild; 19 | while (el && !found) { 20 | if (el.nodeType == 8) { // 8==comment 21 | var templateBody = el.nodeValue; // this is inside the comment 22 | found=true; 23 | break; 24 | } 25 | el=el.nextSibling; 26 | } 27 | if (!found) 28 | var templateBody = tmpl.html(); // this is the whole template 29 | 30 | if (!templateBody.match(/##\w+##/)) { // is Resig' style? e.g. (#=id#) or (# ...some javascript code 'obj' is the alias for the object #) 31 | var strFunc = 32 | "var p=[],print=function(){p.push.apply(p,arguments);};" + 33 | "with(obj){p.push('" + 34 | templateBody.replace(/[\r\t\n]/g, " ") 35 | .replace(/'(?=[^#]*#\))/g, "\t") 36 | .split("'").join("\\'") 37 | .split("\t").join("'") 38 | .replace(/\(#=(.+?)#\)/g, "',$1,'") 39 | .split("(#").join("');") 40 | .split("#)").join("p.push('") 41 | + "');}return p.join('');"; 42 | 43 | try { 44 | $.JST._templates[type] = new Function("obj", strFunc); 45 | } catch (e) { 46 | console.error("JST error: "+type, e,strFunc); 47 | } 48 | 49 | } else { //plain template e.g. ##id## 50 | try { 51 | $.JST._templates[type] = templateBody; 52 | } catch (e) { 53 | console.error("JST error: "+type, e,templateBody); 54 | } 55 | } 56 | 57 | tmpl.remove(); 58 | 59 | }); 60 | }); 61 | }, 62 | 63 | createFromTemplate: function(jsonData, template, transformToPrintable) { 64 | var templates = $.JST._templates; 65 | 66 | var jsData=new Object(); 67 | if (transformToPrintable){ 68 | for (var prop in jsonData){ 69 | var value = jsonData[prop]; 70 | if (typeof(value) == "string") 71 | value = (value + "").replace(/\n/g, "
"); 72 | jsData[prop]=value; 73 | } 74 | } else { 75 | jsData=jsonData; 76 | } 77 | 78 | function fillStripData(strip, data) { 79 | for (var prop in data) { 80 | var value = data[prop]; 81 | 82 | strip = strip.replace(new RegExp("##" + prop + "##", "gi"), value); 83 | } 84 | // then clean the remaining ##xxx## 85 | strip = strip.replace(new RegExp("##\\w+##", "gi"), ""); 86 | return strip; 87 | } 88 | 89 | var stripString = ""; 90 | if (typeof(template) == "undefined") { 91 | alert("Template is required"); 92 | stripString = "
Template is required
"; 93 | 94 | } else if (typeof(templates[template]) == "function") { // resig template 95 | try { 96 | stripString = templates[template](jsData);// create a jquery object in memory 97 | } catch (e) { 98 | console.error("JST error: "+template,e.message); 99 | stripString = "
ERROR: "+template+"
" + e.message + "
"; 100 | } 101 | 102 | } else { 103 | stripString = templates[template]; // recover strip template 104 | if (!stripString || stripString.trim() == "") { 105 | console.error("No template found for type '" + template + "'"); 106 | return $("
"); 107 | 108 | } else { 109 | stripString = fillStripData(stripString, jsData); //replace placeholders with data 110 | } 111 | } 112 | 113 | var ret = $(stripString);// create a jquery object in memory 114 | ret.attr("__template", template); // set __template attribute 115 | 116 | //decorate the strip 117 | var dec = $.JST._decorators[template]; 118 | if (typeof (dec) == "function") 119 | dec(ret, jsData); 120 | 121 | return ret; 122 | }, 123 | 124 | 125 | existsTemplate: function(template) { 126 | return $.JST._templates[template]; 127 | }, 128 | 129 | //decorate function is like function(domElement,jsonData){...} 130 | loadDecorator:function(template, decorator) { 131 | $.JST._decorators[template] = decorator; 132 | }, 133 | 134 | getDecorator:function(template) { 135 | return $.JST._decorators[template]; 136 | }, 137 | 138 | decorateTemplate:function(element) { 139 | var dec = $.JST._decorators[element.attr("__template")]; 140 | if (typeof (dec) == "function") 141 | dec(editor); 142 | }, 143 | 144 | // asynchronous 145 | ajaxLoadAsynchTemplates: function(templateUrl, callback) { 146 | 147 | $.get(templateUrl, function(data) { 148 | 149 | var div = $("
"); 150 | div.html(data); 151 | 152 | $.JST.loadTemplates(div); 153 | 154 | if (typeof(callback == "function")) 155 | callback(); 156 | },"html"); 157 | }, 158 | 159 | ajaxLoadTemplates: function(templateUrl) { 160 | $.ajax({ 161 | async:false, 162 | url: templateUrl, 163 | dataType: "html", 164 | success: function(data) { 165 | var div = $("
"); 166 | div.html(data); 167 | $.JST.loadTemplates(div); 168 | } 169 | }); 170 | 171 | } 172 | 173 | 174 | }; 175 | -------------------------------------------------------------------------------- /libs/i18nJs.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2017 Open Lab 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | function dateToRelative(localTime){ 25 | var diff=new Date().getTime()-localTime; 26 | var ret=""; 27 | 28 | var min=60000; 29 | var hour=3600000; 30 | var day=86400000; 31 | var wee=604800000; 32 | var mon=2629800000; 33 | var yea=31557600000; 34 | 35 | if (diff<-yea*2) 36 | ret ="in ## years".replace("##",(-diff/yea).toFixed(0)); 37 | 38 | else if (diff<-mon*9) 39 | ret ="in ## months".replace("##",(-diff/mon).toFixed(0)); 40 | 41 | else if (diff<-wee*5) 42 | ret ="in ## weeks".replace("##",(-diff/wee).toFixed(0)); 43 | 44 | else if (diff<-day*2) 45 | ret ="in ## days".replace("##",(-diff/day).toFixed(0)); 46 | 47 | else if (diff<-hour) 48 | ret ="in ## hours".replace("##",(-diff/hour).toFixed(0)); 49 | 50 | else if (diff<-min*35) 51 | ret ="in about one hour"; 52 | 53 | else if (diff<-min*25) 54 | ret ="in about half hour"; 55 | 56 | else if (diff<-min*10) 57 | ret ="in some minutes"; 58 | 59 | else if (diff<-min*2) 60 | ret ="in few minutes"; 61 | 62 | else if (diff<=min) 63 | ret ="just now"; 64 | 65 | else if (diff<=min*5) 66 | ret ="few minutes ago"; 67 | 68 | else if (diff<=min*15) 69 | ret ="some minutes ago"; 70 | 71 | else if (diff<=min*35) 72 | ret ="about half hour ago"; 73 | 74 | else if (diff<=min*75) 75 | ret ="about an hour ago"; 76 | 77 | else if (diff<=hour*5) 78 | ret ="few hours ago"; 79 | 80 | else if (diff<=hour*24) 81 | ret ="## hours ago".replace("##",(diff/hour).toFixed(0)); 82 | 83 | else if (diff<=day*7) 84 | ret ="## days ago".replace("##",(diff/day).toFixed(0)); 85 | 86 | else if (diff<=wee*5) 87 | ret ="## weeks ago".replace("##",(diff/wee).toFixed(0)); 88 | 89 | else if (diff<=mon*12) 90 | ret ="## months ago".replace("##",(diff/mon).toFixed(0)); 91 | 92 | else 93 | ret ="## years ago".replace("##",(diff/yea).toFixed(0)); 94 | 95 | return ret; 96 | } 97 | 98 | //override date format i18n 99 | 100 | Date.monthNames = ["January","February","March","April","May","June","July","August","September","October","November","December"]; 101 | // Month abbreviations. Change this for local month names 102 | Date.monthAbbreviations = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; 103 | // Full day names. Change this for local month names 104 | Date.dayNames =["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; 105 | // Day abbreviations. Change this for local month names 106 | Date.dayAbbreviations = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; 107 | // Used for parsing ambiguous dates like 1/2/2000 - default to preferring 'American' format meaning Jan 2. 108 | // Set to false to prefer 'European' format meaning Feb 1 109 | Date.preferAmericanFormat = false; 110 | 111 | Date.firstDayOfWeek =0; 112 | Date.defaultFormat = "M/d/yyyy"; 113 | Date.masks = { 114 | fullDate: "EEEE, MMMM d, yyyy", 115 | shortTime: "h:mm a" 116 | }; 117 | Date.today="Today"; 118 | 119 | Number.decimalSeparator = "."; 120 | Number.groupingSeparator = ","; 121 | Number.minusSign = "-"; 122 | Number.currencyFormat = "###,##0.00"; 123 | 124 | 125 | 126 | var millisInWorkingDay =28800000; 127 | var workingDaysPerWeek =5; 128 | 129 | function isHoliday(date) { 130 | var friIsHoly =false; 131 | var satIsHoly =true; 132 | var sunIsHoly =true; 133 | 134 | var pad = function (val) { 135 | val = "0" + val; 136 | return val.substr(val.length - 2); 137 | }; 138 | 139 | var holidays = "##"; 140 | 141 | var ymd = "#" + date.getFullYear() + "_" + pad(date.getMonth() + 1) + "_" + pad(date.getDate()) + "#"; 142 | var md = "#" + pad(date.getMonth() + 1) + "_" + pad(date.getDate()) + "#"; 143 | var day = date.getDay(); 144 | 145 | return (day == 5 && friIsHoly) || (day == 6 && satIsHoly) || (day == 0 && sunIsHoly) || holidays.indexOf(ymd) > -1 || holidays.indexOf(md) > -1; 146 | } 147 | 148 | 149 | 150 | var i18n = { 151 | YES: "Yes", 152 | NO: "No", 153 | FLD_CONFIRM_DELETE: "confirm the deletion?", 154 | INVALID_DATA: "The data inserted are invalid for the field format.", 155 | ERROR_ON_FIELD: "Error on field", 156 | OUT_OF_BOUDARIES: "Out of field admitted values:", 157 | CLOSE_ALL_CONTAINERS:"close all?", 158 | DO_YOU_CONFIRM: "Do you confirm?", 159 | ERR_FIELD_MAX_SIZE_EXCEEDED: "Field max size exceeded", 160 | WEEK_SHORT: "W.", 161 | 162 | FILE_TYPE_NOT_ALLOWED:"File type not allowed.", 163 | FILE_UPLOAD_COMPLETED:"File upload completed.", 164 | UPLOAD_MAX_SIZE_EXCEEDED:"Max file size exceeded", 165 | ERROR_UPLOADING:"Error uploading", 166 | UPLOAD_ABORTED:"Upload aborted", 167 | DROP_HERE:"Drop files here", 168 | 169 | FORM_IS_CHANGED: "You have some unsaved data on the page!", 170 | 171 | PIN_THIS_MENU: "PIN_THIS_MENU", 172 | UNPIN_THIS_MENU: "UNPIN_THIS_MENU", 173 | OPEN_THIS_MENU: "OPEN_THIS_MENU", 174 | CLOSE_THIS_MENU: "CLOSE_THIS_MENU", 175 | PROCEED: "Proceed?", 176 | 177 | PREV: "Previous", 178 | NEXT: "Next", 179 | HINT_SKIP: "Got it, close this hint.", 180 | 181 | WANT_TO_SAVE_FILTER: "save this filter", 182 | NEW_FILTER_NAME: "name of the new filter", 183 | SAVE: "Save", 184 | DELETE: "Delete", 185 | HINT_SKIP: "Got it, close this hint.", 186 | 187 | COMBO_NO_VALUES: "no values available...?", 188 | 189 | FILTER_UPDATED:"Filter updated.", 190 | FILTER_SAVED:"Filter correctly saved." 191 | 192 | }; 193 | 194 | 195 | -------------------------------------------------------------------------------- /libs/layout.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2017 Open Lab 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | //----------------------------------positioning----------------------------------------------- 24 | jQuery.fn.centerOnScreen = function () { 25 | return this.each(function () { 26 | var container = $(this); 27 | //console.debug($(window).height(), container.outerHeight(),(($(window).height() - container.outerHeight()) / 2)) 28 | container.css("position", "fixed"); 29 | container.css("top", (($(window).height() - container.outerHeight()) / 2) + 'px'); 30 | container.css("left", (($(window).width() - container.outerWidth()) / 2) + 'px'); 31 | }); 32 | }; 33 | 34 | 35 | function nearBestPosition(whereId, theObjId, centerOnEl) { 36 | 37 | var el = whereId; 38 | var target = theObjId; 39 | 40 | if (typeof whereId != "object") { 41 | el = $("#" + whereId); 42 | } 43 | if (typeof theObjId != "object") { 44 | target = $("#" + theObjId); 45 | } 46 | 47 | if (el) { 48 | target.css("visibility", "hidden"); 49 | var hasContainment = false; 50 | 51 | target.parents().each(function () { 52 | if ($(this).css("position") == "static") 53 | return; 54 | 55 | hasContainment = true; 56 | }); 57 | 58 | var trueX = hasContainment ? el.position().left : el.offset().left; 59 | var trueY = hasContainment ? el.position().top : el.offset().top; 60 | var h = el.outerHeight(); 61 | var elHeight = parseFloat(h); 62 | 63 | if (centerOnEl) { 64 | var elWidth = parseFloat(el.outerWidth()); 65 | var targetWidth = parseFloat(target.outerWidth()); 66 | trueX += (elWidth - targetWidth) / 2; 67 | } 68 | 69 | trueY += parseFloat(elHeight); 70 | 71 | var left = trueX; 72 | var top = trueY; 73 | var barHeight = 45 ; 74 | var barWidth = 20 ; 75 | 76 | if (trueX && trueY) { 77 | target.css("left", left); 78 | target.css("top", top); 79 | } 80 | 81 | if (target.offset().left >= ( ($(window).width() + $(window).scrollLeft()) - target.outerWidth())) { 82 | 83 | left = ( ($(window).width() + $(window).scrollLeft()) - target.outerWidth() - 10 ); 84 | target.css({left:left, marginTop: 0}); 85 | } 86 | 87 | if (target.offset().left < 0) { 88 | left = 10; 89 | target.css("left", left); 90 | } 91 | 92 | if ((target.offset().top + target.outerHeight() >= ( ($(window).height() + $(window).scrollTop()) - barHeight)) && (target.outerHeight() < $(window).height())) { 93 | var marginTop = -(target.outerHeight() + el.outerHeight()); 94 | target.css("margin-top", marginTop); 95 | } 96 | 97 | if (target.offset().top < 0) { 98 | top = 0; 99 | target.css("top", top); 100 | } 101 | 102 | 103 | target.css("visibility", "visible"); 104 | } 105 | } 106 | 107 | $.fn.keepItVisible = function (ref) { 108 | var thisTop = $(this).offset().top; 109 | var thisLeft = $(this).offset().left; 110 | var fromTop =0; 111 | var fromLeft =0; 112 | 113 | var windowH = $(window).height() + $(window).scrollTop(); 114 | var windowW = $(window).width() + $(window).scrollLeft(); 115 | 116 | if (ref){ 117 | fromTop = windowH - (ref.offset().top); 118 | fromLeft = windowW - (ref.offset().left + ref.outerWidth()); 119 | } 120 | 121 | if (thisTop + $(this).outerHeight() > windowH){ 122 | var mt = (thisTop + $(this).outerHeight()) - windowH; 123 | // $(this).css("margin-top", -$(this).outerHeight() - fromTop); 124 | $(this).css("margin-top", -mt - fromTop); 125 | } 126 | if (thisLeft + $(this).outerWidth() > windowW){ 127 | var mL = (thisLeft + $(this).outerWidth()) - windowW; 128 | // $(this).css("margin-left", -$(this).outerWidth() - fromLeft); 129 | $(this).css("margin-left", -mL - fromLeft); 130 | } 131 | $(this).css("visibility", "visible"); 132 | }; 133 | 134 | //END positioning 135 | 136 | 137 | /* Caret Functions 138 | Use setSelection with start = end to set caret 139 | */ 140 | function setSelection(input, start, end) { 141 | input.setSelectionRange(start, end); 142 | } 143 | 144 | $.fn.setCursorPosition = function(pos) { 145 | this.each(function(index, elem) { 146 | if (elem.setSelectionRange) { 147 | elem.setSelectionRange(pos, pos); 148 | } else if (elem.createTextRange) { 149 | var range = elem.createTextRange(); 150 | range.collapse(true); 151 | range.moveEnd('character', pos); 152 | range.moveStart('character', pos); 153 | range.select(); 154 | } 155 | }); 156 | return this; 157 | }; 158 | 159 | //-- Caret Functions END ---------------------------------------------------------------------------- -- 160 | 161 | 162 | 163 | /*----------------------------------------------------------------- manage bbButtons*/ 164 | $.buttonBar = { 165 | defaults: {}, 166 | 167 | init: function(){ 168 | setTimeout(function(){ 169 | $.buttonBar.manageButtonBar(); 170 | },100); 171 | 172 | $(window).on("scroll.ButtonBar",function(){ 173 | $.buttonBar.manageButtonBar(); 174 | }); 175 | $(window).on("resize.ButtonBar",function(){ 176 | $.buttonBar.manageButtonBar(); 177 | }); 178 | }, 179 | 180 | manageButtonBar: function(anim) { 181 | 182 | $(".buttonArea").not(".bbCloned").not(".notFix").each(function(){ 183 | var bb = this; 184 | 185 | //se usiamo questi si rompe la button bar flottante del save sulla issue list 186 | //bb.originalHeigh=bb.originalHeigh || $(bb).height(); 187 | //bb.originalOffsetTop=bb.originalOffsetTop||$(bb).offset().top; 188 | 189 | bb.originalHeigh= $(bb).height(); 190 | bb.originalOffsetTop=$(bb).offset().top; 191 | 192 | bb.isOut = $(window).scrollTop() + $(window).height() - bb.originalHeigh < bb.originalOffsetTop; 193 | 194 | if (bb.bbHolder) 195 | bb.bbHolder.css({width: $(bb).outerWidth(),left:$(bb).offset().left}); 196 | 197 | if (bb.isOut && !bb.isCloned){ 198 | if (bb.bbHolder) 199 | bb.bbHolder.remove(); 200 | bb.isCloned = true; 201 | bb.bbHolder = $(bb).clone().addClass("bbCloned clone bottom").css({width: $(bb).outerWidth(), marginTop:0,left:$(bb).offset().left}); 202 | bb.bbHolder.hide(); 203 | bb.bbHolder.css({position:"fixed", bottom:0, left:$(bb).offset().left}); 204 | $(bb).after(bb.bbHolder); 205 | bb.bbHolder.show(); 206 | $(bb).css("visibility","hidden"); 207 | 208 | } else if (!bb.isOut && bb.isCloned) { 209 | //} else { 210 | bb.isCloned = false; 211 | bb.bbHolder.remove(); 212 | $(bb).css("visibility","visible"); 213 | } 214 | }); 215 | }, 216 | 217 | refreshButtonBar: function() { 218 | $(".bbCloned").remove(); 219 | $(".buttonArea").not(".bbCloned").each(function(){ 220 | var bb = this; 221 | bb.isCloned = false; 222 | }); 223 | 224 | $.buttonBar.manageButtonBar(false); 225 | } 226 | }; 227 | -------------------------------------------------------------------------------- /libs/jquery/dateField/jquery.dateField.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Open Lab 3 | Written by Roberto Bicchierai 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 | jQuery.fn.dateField = function(options) { 25 | //console.debug("dateField",options); 26 | //check if the input field is passed correctly 27 | if (!options.inputField){ 28 | console.error("You must supply an input field"); 29 | return false; 30 | } 31 | 32 | // -------------------------- start default option values -------------------------- 33 | 34 | if (typeof(options.firstDayOfWeek) == "undefined") 35 | options.firstDayOfWeek=Date.firstDayOfWeek; 36 | 37 | if (typeof(options.useWheel) == "undefined") 38 | options.useWheel=true; 39 | 40 | if (typeof(options.dateFormat) == "undefined") 41 | options.dateFormat=Date.defaultFormat; 42 | 43 | if (typeof(options.todayLabel) == "undefined") 44 | options.todayLabel=Date.today; 45 | 46 | /* optional 47 | options.notBeforeMillis //disable buttons if before millis 48 | options.notAfterMillis //disable buttons if after millis 49 | options.width // imposta una larghezza al calendario 50 | options.height 51 | options.showToday // show "today" on the year or month bar 52 | options.centerOnScreen //se true centra invece che usa nearBestPosition 53 | options.useYears:0 // se >0 non disegna prev-next ma n anni prima e n anni dopo quello corrente 54 | options.useMonths:0 // se >0 non disegna prev-next ma n mesi prima e n mesi dopo quello corrente 55 | */ 56 | // -------------------------- end default option values -------------------------- 57 | 58 | 59 | 60 | // ------------------ start 61 | if(options.inputField.is("[readonly]") && !options.inputField.is(".noFocus") || options.inputField.is("[disabled]")) 62 | return; 63 | 64 | var calendar = {currentDate: new Date()}; 65 | calendar.options = options; 66 | 67 | //build the calendar on the first element in the set of matched elements. 68 | var theOpener = this.eq(0); 69 | var theDiv=$("
").addClass("calBox"); 70 | 71 | if(options.width) 72 | theDiv.css("width",options.width); 73 | 74 | if(options.height) 75 | theDiv.css("height",options.height); 76 | 77 | 78 | //create calendar elements elements 79 | var divNavBar = $("
").addClass("calNav"); 80 | var divDays = $("
").addClass("calDay"); 81 | 82 | divDays.addClass("calFullMonth"); 83 | theDiv.append(divNavBar).append(divDays); 84 | 85 | if (options.isSearchField){ 86 | var divShortcuts=$("
").addClass("shortCuts").html("LQ LM M LW W Y TTONW NM Q NQ"); 87 | divShortcuts.click(function(ev){ 88 | var el=$(ev.target); 89 | if(el.is("span")){ 90 | if (!options.isSearchField) 91 | options.inputField.val(Date.parseString(el.text().trim(),options.dateFormat,true).format(options.dateFormat)); 92 | else 93 | options.inputField.val(el.text().trim()); 94 | calendar.closeCalendar() 95 | } 96 | }); 97 | theDiv.append(divShortcuts); 98 | } 99 | 100 | //mobile management 101 | if ($("body").is(".mobile")){ 102 | enableComponentOverlay(options.inputField,theDiv); 103 | } 104 | $("body").append(theDiv); 105 | 106 | 107 | if (options.centerOnScreen){ 108 | theDiv.oneTime(10,"ce",function(){$(this).centerOnScreen()}); 109 | } else { 110 | nearBestPosition(theOpener,theDiv); 111 | } 112 | theDiv.css("z-index",10000); 113 | 114 | 115 | //register for click outside. Delayed to avoid it run immediately 116 | $("body").oneTime(100, "regclibodcal", function() { 117 | $("body").bind("click.dateField", function() { 118 | calendar.closeCalendar(); 119 | }); 120 | }); 121 | 122 | 123 | calendar.drawCalendar = function(date) { 124 | calendar.currentDate = date; 125 | //console.debug("drawCalendar",date); 126 | 127 | 128 | var fillNavBar = function(date) { 129 | //console.debug("fillNavBar",date); 130 | var today = new Date();//today 131 | divNavBar.empty(); 132 | 133 | var showToday = options.showToday; 134 | //use the classic prev next bar 135 | if (!options.useYears && !options.useMonths) { 136 | var t = new Date(date.getTime()); 137 | t.setDate(1); 138 | t.setMonth(t.getMonth() - 1); 139 | var spanPrev = $("").addClass("calElement noCallback prev").attr("millis", t.getTime()); 140 | var spanToday = $("").addClass("calElement noCallback goToday").attr("millis", new Date().getTime()).attr("title", "today"); 141 | t.setMonth(t.getMonth() + 1); 142 | var spanMonth = $("").html(t.format("MMMM yyyy")); 143 | t.setMonth(t.getMonth() + 1); 144 | var spanNext = $("").addClass("calElement noCallback next").attr("millis", t.getTime()); 145 | divNavBar.append(spanPrev, spanToday, spanMonth, spanNext); 146 | 147 | // use the year month bar 148 | } else { 149 | if (options.useYears>0){ 150 | options.useMonths=options.useMonths||1; //if shows years -> shows also months 151 | t = new Date(date.getTime()); 152 | var yB= $("
"); 153 | var w=100/(2*options.useYears+1+(showToday?1:0)); 154 | t.setFullYear(t.getFullYear()-options.useYears); 155 | if(showToday){ 156 | var s = $("").addClass("calElement noCallback goToday").attr("millis", today.getTime()).append(options.todayLabel).css("width",w+"%"); 157 | showToday=false; 158 | yB.append(s); 159 | } 160 | for (var i=-options.useYears;i<=options.useYears;i++){ 161 | var s = $("").addClass("calElement noCallback").attr("millis", t.getTime()).append(t.getFullYear()).css("width",w+"%"); 162 | if (today.getFullYear()== t.getFullYear()) //current year 163 | s.addClass("today"); 164 | if (i==0) //selected year 165 | s.addClass("selected"); 166 | 167 | yB.append(s); 168 | t.setFullYear(t.getFullYear()+1); 169 | } 170 | divNavBar.append(yB); 171 | } 172 | if (options.useMonths>0){ 173 | t = new Date(date.getTime()); 174 | t.setDate(1); 175 | var w=100/(2*options.useMonths+1+(showToday?1:0)); 176 | t.setMonth(t.getMonth()-options.useMonths); 177 | var yB= $("
"); 178 | 179 | if(showToday){ 180 | var s = $("").addClass("calElement noCallback goToday").attr("millis", today.getTime()).append(options.todayLabel).css("width",w+"%"); 181 | yB.append(s); 182 | } 183 | 184 | for (var i=-options.useMonths;i<=options.useMonths;i++){ 185 | var s = $("").addClass("calElement noCallback").attr("millis", t.getTime()).append(t.format("MMM")).css("width",w+"%"); 186 | if (today.getFullYear()== t.getFullYear() && today.getMonth()== t.getMonth()) //current year 187 | s.addClass("today"); 188 | if (i==0) //selected month 189 | s.addClass("selected"); 190 | yB.append(s); 191 | t.setMonth(t.getMonth()+1); 192 | } 193 | divNavBar.append(yB); 194 | } 195 | } 196 | 197 | }; 198 | 199 | var fillDaysFullMonth = function(date) { 200 | divDays.empty(); 201 | var today = new Date();//today 202 | var w = 100/7; 203 | // draw day headers 204 | var d = new Date(date); 205 | d.setFirstDayOfThisWeek(options.firstDayOfWeek); 206 | for (var i = 0; i < 7; i++) { 207 | var span = $("").addClass("calDayHeader").attr("day", d.getDay()); 208 | if (d.isHoliday()) 209 | span.addClass("holy"); 210 | span.css("width",w+"%"); 211 | span.html(Date.dayAbbreviations[d.getDay()]); 212 | 213 | //call the dayHeaderRenderer 214 | if (typeof(options.dayHeaderRenderer) == "function") 215 | options.dayHeaderRenderer(span,d.getDay()); 216 | 217 | divDays.append(span); 218 | d.setDate(d.getDate()+1); 219 | } 220 | 221 | //draw cells 222 | d = new Date(date); 223 | d.setDate(1); // set day to start of month 224 | d.setFirstDayOfThisWeek(options.firstDayOfWeek);//go to first day of week 225 | 226 | var i=0; 227 | 228 | while ((d.getMonth()<=date.getMonth() && d.getFullYear()<=date.getFullYear()) || d.getFullYear()").addClass("calElement day").attr("millis", d.getTime()); 230 | 231 | span.html("" + d.getDate() + "").css("width",w+"%"); 232 | if (d.getYear() == today.getYear() && d.getMonth() == today.getMonth() && d.getDate() == today.getDate()) 233 | span.addClass("today"); 234 | if (d.getYear() == date.getYear() && d.getMonth() == date.getMonth() && d.getDate() == date.getDate()) 235 | span.addClass("selected"); 236 | 237 | if (d.isHoliday()) 238 | span.addClass("holy"); 239 | 240 | if(d.getMonth()!=date.getMonth()) 241 | span.addClass("calOutOfScope"); 242 | 243 | //call the dayRenderer 244 | if (typeof(options.dayRenderer) == "function") 245 | options.dayRenderer(span,d); 246 | 247 | divDays.append(span); 248 | d.setDate(d.getDate()+1); 249 | i++; 250 | } 251 | 252 | }; 253 | 254 | fillNavBar(date); 255 | fillDaysFullMonth(date); 256 | 257 | //disable all buttons out of validity period 258 | if (options.notBeforeMillis ||options.notAfterMillis) { 259 | var notBefore = options.notBeforeMillis ? options.notBeforeMillis : Number.MIN_VALUE; 260 | var notAfter = options.notAfterMillis ? options.notAfterMillis : Number.MAX_VALUE; 261 | divDays.find(".calElement[millis]").each(function(){ 262 | var el=$(this); 263 | var m=parseInt(el.attr("millis")); 264 | if (m>notAfter || m 0) { 283 | var millis = parseInt(el.attr("millis")); 284 | var date = new Date(millis); 285 | 286 | if (el.is(".disabled")) { 287 | ev.stopPropagation(); 288 | return; 289 | } 290 | 291 | if (el.hasClass("day")) { 292 | calendar.closeCalendar(); 293 | if (!el.is(".noCallback")) { 294 | options.inputField.val(date.format(options.dateFormat)).attr("millis", date.getTime()).focus(); 295 | if (typeof(options.callback) == "function") 296 | options.callback.apply(options.inputField,[date]); // in callBack you can use "this" that refers to the input 297 | } 298 | } else { 299 | calendar.drawCalendar(date); 300 | } 301 | } 302 | ev.stopPropagation(); 303 | }); 304 | 305 | 306 | //if mousewheel 307 | if ($.event.special.mousewheel && options.useWheel) { 308 | divDays.mousewheel(function(event, delta) { 309 | var d = new Date(calendar.currentDate.getTime()); 310 | d.setMonth(d.getMonth() + delta); 311 | calendar.drawCalendar(d); 312 | return false; 313 | }); 314 | } 315 | 316 | 317 | // start calendar to the date in the input 318 | var dateStr=options.inputField.val(); 319 | 320 | if (!dateStr || !Date.isValid(dateStr,options.dateFormat,true)){ 321 | calendar.drawCalendar(new Date()); 322 | } else { 323 | var date = Date.parseString(dateStr,options.dateFormat,true); 324 | var newDateStr=date.format(options.dateFormat); 325 | //set date string formatted if not equals 326 | if (!options.isSearchField) { 327 | options.inputField.attr("millis", date.getTime()); 328 | if (dateStr != newDateStr) 329 | options.inputField.val(newDateStr); 330 | } 331 | calendar.drawCalendar(date); 332 | } 333 | 334 | return calendar; 335 | }; 336 | -------------------------------------------------------------------------------- /libs/jquery/svg/jquery.svgdom.1.8.js: -------------------------------------------------------------------------------- 1 | /* http://keith-wood.name/svg.html 2 | jQuery DOM compatibility for jQuery SVG v1.4.5. 3 | Written by Keith Wood (kbwood{at}iinet.com.au) April 2009. 4 | Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 5 | MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 6 | Please attribute the author if you use it. */ 7 | 8 | (function ($) { // Hide scope, no $ conflict 9 | 10 | var rclass = /[\t\r\n]/g, 11 | rspace = /\s+/, 12 | rwhitespace = "[\\x20\\t\\r\\n\\f]"; 13 | 14 | /* Support adding class names to SVG nodes. */ 15 | $.fn.addClass = function (origAddClass) { 16 | return function (value) { 17 | var classNames, i, l, elem, 18 | setClass, c, cl; 19 | 20 | if (jQuery.isFunction(value)) { 21 | return this.each(function (j) { 22 | jQuery(this).addClass(value.call(this, j, this.className)); 23 | }); 24 | } 25 | 26 | if (value && typeof value === "string") { 27 | classNames = value.split(rspace); 28 | 29 | for (i = 0, l = this.length; i < l; i++) { 30 | elem = this[ i ]; 31 | 32 | if (elem.nodeType === 1) { 33 | if (!(elem.className && elem.getAttribute('class')) && classNames.length === 1) { 34 | if ($.svg.isSVGElem(elem)) { 35 | (elem.className ? elem.className.baseVal = value 36 | : elem.setAttribute('class', value)); 37 | } else { 38 | elem.className = value; 39 | } 40 | } else { 41 | setClass = !$.svg.isSVGElem(elem) ? elem.className : 42 | elem.className ? elem.className.baseVal : 43 | elem.getAttribute('class'); 44 | 45 | setClass = (" " + setClass + " "); 46 | for (c = 0, cl = classNames.length; c < cl; c++) { 47 | if (setClass.indexOf(" " + classNames[ c ] + " ") < 0) { 48 | setClass += classNames[ c ] + " "; 49 | } 50 | } 51 | 52 | setClass = jQuery.trim(setClass); 53 | if ($.svg.isSVGElem(elem)) { 54 | 55 | (elem.className ? elem.className.baseVal = setClass 56 | : elem.setAttribute('class', setClass)); 57 | } else { 58 | elem.className = setClass; 59 | } 60 | } 61 | } 62 | } 63 | } 64 | 65 | return this; 66 | }; 67 | }($.fn.addClass); 68 | 69 | /* Support removing class names from SVG nodes. */ 70 | $.fn.removeClass = function (origRemoveClass) { 71 | return function (value) { 72 | var classNames, i, l, elem, className, c, cl; 73 | 74 | if (jQuery.isFunction(value)) { 75 | return this.each(function (j) { 76 | jQuery(this).removeClass(value.call(this, j, this.className)); 77 | }); 78 | } 79 | 80 | if ((value && typeof value === "string") || value === undefined) { 81 | classNames = ( value || "" ).split(rspace); 82 | 83 | for (i = 0, l = this.length; i < l; i++) { 84 | elem = this[ i ]; 85 | 86 | if (elem.nodeType === 1 && (elem.className || elem.getAttribute('class'))) { 87 | if (value) { 88 | className = !$.svg.isSVGElem(elem) ? elem.className : 89 | elem.className ? elem.className.baseVal : 90 | elem.getAttribute('class'); 91 | 92 | className = (" " + className + " ").replace(rclass, " "); 93 | 94 | for (c = 0, cl = classNames.length; c < cl; c++) { 95 | // Remove until there is nothing to remove, 96 | while (className.indexOf(" " + classNames[ c ] + " ") >= 0) { 97 | className = className.replace(" " + classNames[ c ] + " ", " "); 98 | } 99 | } 100 | 101 | className = jQuery.trim(className); 102 | } else { 103 | className = ""; 104 | } 105 | 106 | if ($.svg.isSVGElem(elem)) { 107 | (elem.className ? elem.className.baseVal = className 108 | : elem.setAttribute('class', className)); 109 | } else { 110 | elem.className = className; 111 | } 112 | } 113 | } 114 | } 115 | 116 | return this; 117 | }; 118 | }($.fn.removeClass); 119 | 120 | /* Support toggling class names on SVG nodes. */ 121 | $.fn.toggleClass = function (origToggleClass) { 122 | return function (className, state) { 123 | return this.each(function () { 124 | if ($.svg.isSVGElem(this)) { 125 | if (typeof state !== 'boolean') { 126 | state = !$(this).hasClass(className); 127 | } 128 | $(this)[(state ? 'add' : 'remove') + 'Class'](className); 129 | } 130 | else { 131 | origToggleClass.apply($(this), [className, state]); 132 | } 133 | }); 134 | }; 135 | }($.fn.toggleClass); 136 | 137 | /* Support checking class names on SVG nodes. */ 138 | $.fn.hasClass = function (origHasClass) { 139 | return function (selector) { 140 | 141 | var className = " " + selector + " ", 142 | i = 0, 143 | l = this.length, 144 | elem, classes; 145 | 146 | for (; i < l; i++) { 147 | elem = this[i]; 148 | if (elem.nodeType === 1) { 149 | classes = !$.svg.isSVGElem(elem) ? elem.className : 150 | elem.className ? elem.className.baseVal : 151 | elem.getAttribute('class'); 152 | if ((" " + classes + " ").replace(rclass, " ").indexOf(className) > -1) { 153 | return true; 154 | } 155 | } 156 | } 157 | 158 | return false; 159 | }; 160 | }($.fn.hasClass); 161 | 162 | /* Support attributes on SVG nodes. */ 163 | $.fn.attr = function (origAttr) { 164 | return function (name, value, type) { 165 | var origArgs = arguments; 166 | if (typeof name === 'string' && value === undefined) { 167 | var val = origAttr.apply(this, origArgs); 168 | if (val && val.baseVal && val.baseVal.numberOfItems != null) { // Multiple values 169 | value = ''; 170 | val = val.baseVal; 171 | if (name == 'transform') { 172 | for (var i = 0; i < val.numberOfItems; i++) { 173 | var item = val.getItem(i); 174 | switch (item.type) { 175 | case 1: 176 | value += ' matrix(' + item.matrix.a + ',' + item.matrix.b + ',' + 177 | item.matrix.c + ',' + item.matrix.d + ',' + 178 | item.matrix.e + ',' + item.matrix.f + ')'; 179 | break; 180 | case 2: 181 | value += ' translate(' + item.matrix.e + ',' + item.matrix.f + ')'; 182 | break; 183 | case 3: 184 | value += ' scale(' + item.matrix.a + ',' + item.matrix.d + ')'; 185 | break; 186 | case 4: 187 | value += ' rotate(' + item.angle + ')'; 188 | break; // Doesn't handle new origin 189 | case 5: 190 | value += ' skewX(' + item.angle + ')'; 191 | break; 192 | case 6: 193 | value += ' skewY(' + item.angle + ')'; 194 | break; 195 | } 196 | } 197 | val = value.substring(1); 198 | } 199 | else { 200 | val = val.getItem(0).valueAsString; 201 | } 202 | } 203 | return (val && val.baseVal ? val.baseVal.valueAsString : val); 204 | } 205 | 206 | var options = name; 207 | if (typeof name === 'string') { 208 | options = {}; 209 | options[name] = value; 210 | } 211 | return $(this).each(function () { 212 | if ($.svg.isSVGElem(this)) { 213 | for (var n in options) { 214 | var val = ($.isFunction(options[n]) ? options[n]() : options[n]); 215 | (type ? this.style[n] = val : this.setAttribute(n, val)); 216 | } 217 | } 218 | else { 219 | origAttr.apply($(this), origArgs); 220 | } 221 | }); 222 | }; 223 | }($.fn.attr); 224 | 225 | /* Support removing attributes on SVG nodes. */ 226 | $.fn.removeAttr = function (origRemoveAttr) { 227 | return function (name) { 228 | return this.each(function () { 229 | if ($.svg.isSVGElem(this)) { 230 | (this[name] && this[name].baseVal ? this[name].baseVal.value = '' : 231 | this.setAttribute(name, '')); 232 | } 233 | else { 234 | origRemoveAttr.apply($(this), [name]); 235 | } 236 | }); 237 | }; 238 | }($.fn.removeAttr); 239 | 240 | /* Add numeric only properties. */ 241 | $.extend($.cssNumber, { 242 | 'stopOpacity': true, 243 | 'strokeMitrelimit':true, 244 | 'strokeOpacity': true 245 | }); 246 | 247 | /* Support retrieving CSS/attribute values on SVG nodes. */ 248 | if ($.cssProps) { 249 | $.css = function (origCSS) { 250 | return function (elem, name, numeric, extra) { 251 | var value = (name.match(/^svg.*/) ? $(elem).attr($.cssProps[name] || name) : ''); 252 | return value || origCSS(elem, name, numeric, extra); 253 | }; 254 | }($.css); 255 | } 256 | 257 | $.find.isXML = function (origIsXml) { 258 | return function (elem) { 259 | return $.svg.isSVGElem(elem) || origIsXml(elem); 260 | } 261 | }($.find.isXML) 262 | 263 | var div = document.createElement('div'); 264 | div.appendChild(document.createComment('')); 265 | if (div.getElementsByTagName('*').length > 0) { // Make sure no comments are found 266 | $.expr.find.TAG = function (match, context) { 267 | var results = context.getElementsByTagName(match[1]); 268 | if (match[1] === '*') { // Filter out possible comments 269 | var tmp = []; 270 | for (var i = 0; results[i] || results.item(i); i++) { 271 | if ((results[i] || results.item(i)).nodeType === 1) { 272 | tmp.push(results[i] || results.item(i)); 273 | } 274 | } 275 | results = tmp; 276 | } 277 | return results; 278 | }; 279 | } 280 | 281 | $.expr.filter.CLASS = function (className) { 282 | var pattern = new RegExp("(^|" + rwhitespace + ")" + className + "(" + rwhitespace + "|$)"); 283 | return function (elem) { 284 | var elemClass = (!$.svg.isSVGElem(elem) ? elem.className || (typeof elem.getAttribute !== "undefined" && elem.getAttribute("class")) || "" : 285 | (elem.className ? elem.className.baseVal : elem.getAttribute('class'))); 286 | 287 | return pattern.test(elemClass); 288 | }; 289 | }; 290 | 291 | /* 292 | In the removeData function (line 1881, v1.7.2): 293 | 294 | if ( jQuery.support.deleteExpando ) { 295 | delete elem[ internalKey ]; 296 | } else { 297 | try { // SVG 298 | elem.removeAttribute( internalKey ); 299 | } catch (e) { 300 | elem[ internalKey ] = null; 301 | } 302 | } 303 | 304 | In the event.add function (line 2985, v1.7.2): 305 | 306 | if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 307 | // Bind the global event handler to the element 308 | try { // SVG 309 | elem.addEventListener( type, eventHandle, false ); 310 | } catch(e) { 311 | if ( elem.attachEvent ) { 312 | elem.attachEvent( "on" + type, eventHandle ); 313 | } 314 | } 315 | } 316 | 317 | In the event.remove function (line 3074, v1.7.2): 318 | 319 | if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { 320 | try { // SVG 321 | elem.removeEventListener(type, elemData.handle, false); 322 | } 323 | catch (e) { 324 | if (elem.detachEvent) { 325 | elem.detachEvent("on" + type, elemData.handle); 326 | } 327 | } 328 | } 329 | 330 | In the event.fix function (line 3394, v1.7.2): 331 | 332 | if (event.target.namespaceURI == 'http://www.w3.org/2000/svg') { // SVG 333 | event.button = [1, 4, 2][event.button]; 334 | } 335 | 336 | // Add which for click: 1 === left; 2 === middle; 3 === right 337 | // Note: button is not normalized, so don't use it 338 | if ( !event.which && button !== undefined ) { 339 | event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); 340 | } 341 | 342 | In the Sizzle function (line 4083, v1.7.2): 343 | 344 | if ( toString.call(checkSet) === "[object Array]" ) { 345 | if ( !prune ) { 346 | results.push.apply( results, checkSet ); 347 | 348 | } else if ( context && context.nodeType === 1 ) { 349 | for ( i = 0; checkSet[i] != null; i++ ) { 350 | if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { 351 | results.push( set[i] || set.item(i) ); // SVG 352 | } 353 | } 354 | 355 | } else { 356 | for ( i = 0; checkSet[i] != null; i++ ) { 357 | if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 358 | results.push( set[i] || set.item(i) ); // SVG 359 | } 360 | } 361 | } 362 | } else {... 363 | 364 | In the fallback for the Sizzle makeArray function (line 4877, v1.7.2): 365 | 366 | if ( toString.call(array) === "[object Array]" ) { 367 | Array.prototype.push.apply( ret, array ); 368 | 369 | } else { 370 | if ( typeof array.length === "number" ) { 371 | for ( var l = array.length; i < l; i++ ) { 372 | ret.push( array[i] || array.item(i) ); // SVG 373 | } 374 | 375 | } else { 376 | for ( ; array[i]; i++ ) { 377 | ret.push( array[i] ); 378 | } 379 | } 380 | } 381 | 382 | In the jQuery.cleandata function (line 6538, v1.7.2): 383 | 384 | if ( deleteExpando ) { 385 | delete elem[ jQuery.expando ]; 386 | 387 | } else { 388 | try { // SVG 389 | elem.removeAttribute( jQuery.expando ); 390 | } catch (e) { 391 | // Ignore 392 | } 393 | } 394 | 395 | In the fallback getComputedStyle function (line 6727, v1.7.2): 396 | 397 | defaultView = (elem.ownerDocument ? elem.ownerDocument.defaultView : elem.defaultView); // SVG 398 | if ( defaultView && 399 | (computedStyle = defaultView.getComputedStyle( elem, null )) ) { 400 | 401 | ret = computedStyle.getPropertyValue( name ); 402 | ... 403 | 404 | */ 405 | 406 | })(jQuery); -------------------------------------------------------------------------------- /libs/dialogs.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2017 Open Lab 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | function centerPopup(url, target, w, h, scroll, resiz) { 24 | var winl = (screen.width - w) / 2; 25 | var wint = (screen.height - h) / 2; 26 | var winprops = 'height=' + h + ',width=' + w + ',top=' + wint + ',left=' + winl + ',scrollbars=' + scroll + ',resizable=' + resiz + ', toolbars=false, status=false, menubar=false'; 27 | var win = window.open(url, target, winprops); 28 | if (!win) 29 | alert("A popup blocker was detected: please allow them for this application (check out the upper part of the browser window)."); 30 | if (parseInt(navigator.appVersion) >= 4) { 31 | win.window.focus(); 32 | } 33 | } 34 | 35 | function openCenteredWindow(url, target, winprops) { 36 | var prop_array = winprops.split(","); 37 | var i = 0; 38 | var w = 800; 39 | var h = 600; 40 | if (winprops && winprops != '') { 41 | while (i < prop_array.length) { 42 | if (prop_array[i].indexOf('width') > -1) { 43 | s = prop_array[i].substring(prop_array[i].indexOf('=') + 1); 44 | w = parseInt(s); 45 | } else if (prop_array[i].indexOf('height') > -1) { 46 | s = prop_array[i].substring(prop_array[i].indexOf('=') + 1); 47 | h = parseInt(s); 48 | } 49 | i += 1; 50 | } 51 | var winl = (screen.width - w) / 2; 52 | var wint = (screen.height - h) / 2; 53 | winprops = winprops + ",top=" + wint + ",left=" + winl; 54 | } 55 | win = window.open(url, target, winprops); 56 | if (!win) 57 | alert("A popup blocker was detected: please allow them for this application (check out the upper part of the browser window)."); 58 | if (parseInt(navigator.appVersion) >= 4) { 59 | win.window.focus(); 60 | } 61 | } 62 | 63 | function showFeedbackMessage(typeOrObject, message, title, autoCloseTime) { 64 | 65 | if(!autoCloseTime) 66 | autoCloseTime = 0; 67 | 68 | //console.debug("showFeedbackMessage",typeOrObject, message, title); 69 | var place = $("#__FEEDBACKMESSAGEPLACE"); 70 | var mess; 71 | if (typeof(typeOrObject)=="object" ) 72 | mess=typeOrObject; 73 | else 74 | mess = {type:typeOrObject, message:message,title:title}; 75 | //if exists append error message 76 | var etm = $(".FFC_"+mess.type+":visible ._errorTemplateMessage"); 77 | if(etm.length>0){ 78 | etm.append("
"+(mess.title?""+mess.title+"
":"")+mess.message+"
"); 79 | }else{ 80 | etm = $.JST.createFromTemplate(mess, "errorTemplate"); 81 | place.append(etm); 82 | place.fadeIn(); 83 | } 84 | 85 | if(autoCloseTime >0) 86 | setTimeout(function(){ 87 | etm.fadeOut(); 88 | },autoCloseTime); 89 | 90 | $(".FFC_OK").stopTime("ffchide").oneTime(1500, "ffchide",function () {$(this).fadeOut(400,function(){$(this)})}); 91 | $(".FFC_WARNING").stopTime("ffchide").oneTime(75000, "ffchide",function () {$(this).fadeOut(400,function(){$(this)})}); 92 | $(".FFC_ERROR").stopTime("ffchide").oneTime(10000, "ffchide",function () {$(this).fadeOut(400,function(){$(this)})}); 93 | } 94 | 95 | function showFeedbackMessageInDiv(type, message, divId) { 96 | var place = $("#" + divId); 97 | var mess = {type:type, message:message}; 98 | place.prepend($.JST.createFromTemplate(mess, "errorTemplate")); 99 | place.fadeIn(); 100 | $("body").oneTime(1200, function () { 101 | $(".FFC_OK").fadeOut(); 102 | }); 103 | } 104 | function hideFeedbackMessages() { 105 | $("#__FEEDBACKMESSAGEPLACE").empty(); 106 | } 107 | 108 | 109 | function submitInBlack(formId, actionHref, w, h) { 110 | 111 | if (!w) 112 | w = $(window).width() - 100; 113 | if (!h) 114 | h = $(window).height() - 50; 115 | 116 | openBlackPopup('', w + "px", h + "px", null, formId + "_ifr"); 117 | var form = $("#" + formId); 118 | var oldAction = form.prop("action"); 119 | var oldTarget = form.prop("target"); 120 | form.prop("action", actionHref); 121 | form.prop("target", formId + "_ifr"); 122 | $(window).data("openerForm", form); 123 | form.submit(); 124 | form.prop("action", oldAction); 125 | if (oldTarget) 126 | form.prop("target", oldTarget); 127 | else 128 | form.removeAttr("target"); 129 | } 130 | 131 | 132 | var __popups = []; 133 | function createModalPopup(width, height, onCloseCallBack, cssClass, element, popupOpener) { 134 | //console.debug("createModalPopup"); 135 | 136 | 137 | if (typeof(disableUploadize)=="function") 138 | disableUploadize(); 139 | 140 | // se non diversamenete specificato l'openere è la window corrente; 141 | popupOpener = popupOpener || window; 142 | 143 | if (!width) 144 | width = "80%"; 145 | 146 | if (!height) 147 | height = "80%"; 148 | 149 | var localWidth=width,localHeight=height; 150 | 151 | if (typeof (width)=="string" && width.indexOf("%")>0 ) { 152 | localWidth = function () {return ($(window).width() * parseFloat(width)) / 100}; 153 | } 154 | 155 | if (typeof (height)=="string" && height.indexOf("%")>0) 156 | localHeight = function(){return ($(window).height() * parseFloat(height)) / 100}; 157 | 158 | var popupWidth = localWidth, popupHeight = localHeight; 159 | 160 | if(typeof localWidth == "function") 161 | popupWidth = localWidth(); 162 | 163 | if(typeof localHeight == "function") 164 | popupHeight = localHeight(); 165 | 166 | popupWidth = parseFloat(popupWidth); 167 | popupHeight = parseFloat(popupHeight); 168 | 169 | if (typeof onCloseCallBack == "string") 170 | cssClass = onCloseCallBack; 171 | 172 | //$("#__popup__").remove(); 173 | 174 | var popupN = __popups.length+1; 175 | __popups.push("__popup__" + popupN); 176 | 177 | var isInIframe = isIframe(); 178 | 179 | var bg = $("
").prop("id", "__popup__" + popupN); 180 | bg.addClass("modalPopup" + (isInIframe ? " inIframe" : "")).hide(); 181 | 182 | if (cssClass) 183 | bg.addClass(cssClass); 184 | 185 | function getMarginTop(){ 186 | var mt = ($(window).height() - popupHeight)/2 - 100; 187 | return mt < 0 ? 10 : mt; 188 | } 189 | 190 | var internalDiv=$("
").addClass("bwinPopupd").css({ width:popupWidth, minHeight:popupHeight, marginTop: getMarginTop(), maxHeight:$(window).height()-20, overflow: "auto" }); 191 | 192 | $(window).off("resize.popup"+popupN).on("resize.popup"+popupN, function(){ 193 | 194 | if(typeof localWidth == "function") 195 | popupWidth = localWidth(); 196 | 197 | if(typeof localHeight == "function") 198 | popupHeight = localHeight(); 199 | 200 | internalDiv.css({ width:popupWidth, minHeight:popupHeight }); 201 | 202 | var w = internalDiv.outerWidth() > $(window).width()-20 ? $(window).width()-20 : popupWidth; 203 | var h = internalDiv.outerHeight() > $(window).height()-20 ? $(window).height()-20 : popupHeight; 204 | 205 | internalDiv.css({ marginTop: getMarginTop(), minHeight: h, maxHeight:$(window).height()-20,minWidth: w }); 206 | 207 | }); 208 | 209 | bg.append(internalDiv); 210 | 211 | var showBG = function(el, time, callback){ 212 | 213 | if (isInIframe) { 214 | internalDiv.css({marginTop: -50 }); 215 | el.show(); 216 | internalDiv.animate({marginTop: 0}, (time/2), callback); 217 | } else { 218 | internalDiv.css({opacity: 0, top: -50}).show(); 219 | el.fadeIn(time, function () { 220 | internalDiv.animate({top: 0, opacity: 1}, time/3, callback); 221 | }); 222 | } 223 | 224 | /* 225 | if(isInIframe) { 226 | internalDiv.css({marginTop: -1000 }); 227 | el.show(); 228 | internalDiv.animate({marginTop: 0}, (time * 2), callback); 229 | }else{ 230 | internalDiv.css({opacity:0, top: -500}).show(); 231 | el.fadeIn(time, function(){ 232 | internalDiv.animate({top: 0, opacity:1}, time, callback); 233 | }); 234 | } 235 | */ 236 | 237 | return this; 238 | }; 239 | 240 | if(!element) 241 | $("#twMainContainer").addClass("blur"); 242 | 243 | showBG(bg, 300, function(){}) 244 | bg.on("click",function(event){ 245 | if ($(event.target).closest(".bwinPopupd").length <= 0) 246 | bg.trigger("close"); 247 | }); 248 | 249 | var close = $("x"); 250 | internalDiv.append(close); 251 | 252 | close.click(function () { 253 | bg.trigger("close"); 254 | }); 255 | 256 | $("body").css({overflowY:"hidden"}); 257 | 258 | if(!element){ 259 | $("body").append(bg); 260 | }else{ 261 | element.after(bg); 262 | } 263 | 264 | //close call callback 265 | bg.on("close", function () { 266 | var callBackdata = $(this).data("callBackdata"); 267 | var ndo=bg; 268 | 269 | if (typeof (enableUploadize)=="function") 270 | enableUploadize(); 271 | 272 | //console.debug("ndo",ndo); 273 | 274 | var alertMsg; 275 | var ifr=bg.find("iframe"); 276 | 277 | if (ifr.length>0){ 278 | try { 279 | alertMsg = ifr.get(0).contentWindow.alertOnUnload(); 280 | }catch (e){} 281 | } else { 282 | alertMsg=alertOnUnload(ndo); 283 | } 284 | 285 | if (alertMsg){ 286 | if (!confirm(alertMsg)) 287 | return; 288 | } 289 | 290 | bg.fadeOut(100, function () { 291 | 292 | $(window).off("resize.popup"+popupN); 293 | bg.remove(); 294 | __popups.pop(); 295 | 296 | if (__popups.length == 0) 297 | $("#twMainContainer").removeClass("blur"); 298 | 299 | if (typeof(onCloseCallBack) == "function") 300 | onCloseCallBack(callBackdata); 301 | 302 | $("body").css({overflowY: "auto"}); 303 | }); 304 | 305 | }); 306 | 307 | //destroy do not call callback 308 | bg.on("destroy", function () { 309 | bg.remove(); 310 | $("body").css({overflowY: "auto"}); 311 | }); 312 | 313 | //rise resize event in order to show buttons 314 | $("body").oneTime(1000,"br",function(){$(this).resize();}); // con meno di 1000 non funziona 315 | 316 | 317 | //si deposita l'popupOpener sul bg. Per riprenderlo si usa getBlackPopupOpener() 318 | bg.data("__opener",popupOpener); 319 | 320 | return internalDiv; 321 | } 322 | 323 | function changeModalSize(w,h){ 324 | var newDim = {}; 325 | if(w) 326 | newDim.width = w; 327 | if(h) 328 | newDim.minHeight = h; 329 | 330 | var isInIframe = isIframe(); 331 | var popUp = isInIframe ? window.parent.$(".bwinPopupd") : $(".bwinPopupd"); 332 | 333 | if(popUp.length) 334 | popUp.delay(300).animate(newDim, 200); 335 | } 336 | 337 | function openBlackPopup(url, width, height, onCloseCallBack, iframeId, cssClass) { 338 | 339 | if (!iframeId) 340 | iframeId = "bwinPopupIframe"; 341 | 342 | //add black only if not already in blackpupup 343 | var color= cssClass ? cssClass + " iframe" : "iframe"; 344 | 345 | var ndo = top.createModalPopup(width, height, onCloseCallBack, color,null,window); 346 | 347 | //ndo.closest(".modalPopup ").data("__opener",window); // si deposita il vero opener 348 | 349 | var isInIframe = isIframe(); 350 | 351 | ndo.append("
"); 352 | ndo.find("iframe:first").prop("src", url).css({width:"100%", height:"100%", backgroundColor: isInIframe ? '#F9F9F9' : '#FFFFFF'}); 353 | } 354 | 355 | function getBlackPopup() { 356 | var ret=$([]); 357 | if (__popups.length>0) { 358 | var id = __popups[__popups.length - 1]; 359 | ret = $("#" + id); 360 | } 361 | if (ret.length==0 && window!=top) { 362 | ret = window.parent.getBlackPopup(); 363 | } 364 | return ret; 365 | } 366 | 367 | 368 | function getBlackPopupOpener(){ 369 | return getBlackPopup().data("__opener") 370 | } 371 | 372 | function closeBlackPopup(callBackdata) { 373 | //console.debug("closeBlackPopup ",callBackdata); 374 | var bp = getBlackPopup(); 375 | 376 | if (callBackdata) 377 | bp.data("callBackdata",callBackdata); 378 | bp.trigger("close"); 379 | } 380 | 381 | function openPopUp(el,width,height){ 382 | var popup=createModalPopup(width,height); 383 | popup.append(el.clone().show()); 384 | } 385 | 386 | //returns a jquery object where to write content 387 | 388 | function isIframe() { 389 | var isIframe = false; 390 | try{ 391 | //try to access the document object 392 | if (self.location.href != top.location.href) 393 | isIframe = true; 394 | }catch(e) { 395 | //We don't have access, it's cross-origin! 396 | isIframe = true; 397 | } 398 | return isIframe; 399 | }; 400 | 401 | 402 | function openBulkAction(bulkDivId){ 403 | var popup=createModalPopup(500,300); 404 | popup.append($("#"+bulkDivId).clone().show()); 405 | } 406 | 407 | 408 | function refreshBulk(el) { 409 | //console.debug("refreshBulk") 410 | 411 | if (el.is(":checked")) 412 | el.closest("tr").addClass("selected"); 413 | else 414 | el.closest("tr").removeClass("selected"); 415 | 416 | var table=el.closest(".dataTable"); 417 | if (table.find(".selected :checked").length > 0) { 418 | 419 | $("#bulkOp #bulkRowSel").html(table.find("tbody > tr.selected").length + "/" + table.children("tbody").children("tr").length); 420 | 421 | var bukOpt = $("#bulkOp").clone().addClass("bulkOpClone"); 422 | bukOpt.fadeIn(200, function(){ 423 | $("#bulkPlace").html(bukOpt); 424 | $.tableHF.refreshTfoot(); 425 | }); 426 | 427 | } else { 428 | $(".bulkOpClone").fadeOut(200, function(){ 429 | $.tableHF.refreshTfoot(); 430 | }); 431 | } 432 | } 433 | 434 | function selUnselAll(el){ 435 | //var bulkCheckbox = $("#multi td [type='checkbox']"); 436 | var bulkCheckbox = el.closest(".dataTable").find("[type='checkbox']"); 437 | if (el.is(":checked")){ 438 | bulkCheckbox.prop("checked", true); 439 | bulkCheckbox.closest("tr").addClass("selected"); 440 | } else { 441 | bulkCheckbox.prop("checked", false); 442 | bulkCheckbox.closest("tr").removeClass("selected"); 443 | } 444 | 445 | refreshBulk(el); 446 | } 447 | -------------------------------------------------------------------------------- /libs/utilities.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2017 Open Lab 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | 25 | // works also for IE8 beta 26 | var isExplorer = navigator.userAgent.toUpperCase().indexOf("MSIE") >= 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./); 27 | var isMozilla = navigator.userAgent.toUpperCase().indexOf("FIREFOX") >= 0; 28 | var isSafari = navigator.userAgent.toLowerCase().indexOf("safari") != -1 && navigator.userAgent.toLowerCase().indexOf('chrome') < 0; 29 | 30 | //Version detection 31 | var version = navigator.appVersion.substring(0, 1); 32 | var inProduction = false; 33 | if (inProduction) { 34 | window.console = undefined; 35 | } 36 | 37 | // deprecated use $("#domid")... 38 | function obj(element) { 39 | if (arguments.length > 1) { 40 | alert("invalid use of obj with multiple params:" + element) 41 | } 42 | var el = document.getElementById(element); 43 | if (!el) 44 | console.error("element not found: " + element); 45 | return el; 46 | } 47 | 48 | if (!window.console) { 49 | window.console = new function () { 50 | this.log = function (str) {/*alert(str)*/}; 51 | this.debug = function (str) {/*alert(str)*/}; 52 | this.error = function (str) {/*alert(str)*/}; 53 | }; 54 | } 55 | if (!window.console.debug || !window.console.error || !window.console.log) { 56 | window.console = new function () { 57 | this.log = function (str) {/*alert(str)*/}; 58 | this.debug = function (str) {/*alert(str)*/}; 59 | this.error = function (str) {/*alert(str)*/}; 60 | }; 61 | } 62 | 63 | 64 | 65 | String.prototype.trim = function () { 66 | return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1"); 67 | }; 68 | 69 | String.prototype.startsWith = function (t, i) { 70 | if (!i) { 71 | return (t == this.substring(0, t.length)); 72 | } else { 73 | return (t.toLowerCase() == this.substring(0, t.length).toLowerCase()); 74 | } 75 | }; 76 | 77 | String.prototype.endsWith = function (t, i) { 78 | if (!i) { 79 | return (t == this.substring(this.length - t.length)); 80 | } else { 81 | return (t.toLowerCase() == this.substring(this.length - t.length).toLowerCase()); 82 | } 83 | }; 84 | 85 | // leaves only char from A to Z, numbers, _ -> valid ID 86 | String.prototype.asId = function () { 87 | return this.replace(/[^a-zA-Z0-9_]+/g, ''); 88 | }; 89 | 90 | String.prototype.replaceAll = function (from, to) { 91 | return this.replace(new RegExp(RegExp.quote(from), 'g'), to); 92 | }; 93 | 94 | 95 | if (!Array.prototype.indexOf) { 96 | Array.prototype.indexOf = function (searchElement, fromIndex) { 97 | if (this == null) { 98 | throw new TypeError(); 99 | } 100 | var t = Object(this); 101 | var len = t.length >>> 0; 102 | if (len === 0) { 103 | return -1; 104 | } 105 | var n = 0; 106 | if (arguments.length > 0) { 107 | n = Number(arguments[1]); 108 | if (n != n) { // shortcut for verifying if it's NaN 109 | n = 0; 110 | } else if (n != 0 && n != Infinity && n != -Infinity) { 111 | n = (n > 0 || -1) * Math.floor(Math.abs(n)); 112 | } 113 | } 114 | if (n >= len) { 115 | return -1; 116 | } 117 | var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); 118 | for (; k < len; k++) { 119 | if (k in t && t[k] === searchElement) { 120 | return k; 121 | } 122 | } 123 | return -1; 124 | }; 125 | } 126 | 127 | 128 | Object.size = function (obj) { 129 | var size = 0, key; 130 | for (key in obj) { 131 | if (obj.hasOwnProperty(key)) size++; 132 | } 133 | return size; 134 | }; 135 | 136 | 137 | // transform string values to printable: \n in
138 | function transformToPrintable(data) { 139 | for (var prop in data) { 140 | var value = data[prop]; 141 | if (typeof(value) == "string") 142 | data[prop] = (value + "").replace(/\n/g, "
"); 143 | } 144 | return data; 145 | } 146 | 147 | 148 | RegExp.quote = function (str) { 149 | return str.replace(/([.?*+^$[\]\\(){}-])/g, "\\$1"); 150 | }; 151 | 152 | 153 | /* Object Functions */ 154 | 155 | function stopBubble(e) { 156 | e.stopPropagation(); 157 | e.preventDefault(); 158 | return false; 159 | } 160 | 161 | 162 | // ------ ------- -------- wraps http://www.mysite.com/....... with 163 | jQuery.fn.activateLinks = function (showImages) { 164 | var httpRE = /(['"]\s*)?(http[s]?:[\d]*\/\/[^"<>\s]*)/g; 165 | var wwwRE = /(['"/]\s*)?(www\.[^"<>\s]+)/g; 166 | var imgRE = /(['"]\s*)?(http[s]?:[\d]*\/\/[^"<>\s]*\.(?:gif|jpg|png|jpeg|bmp))/g; 167 | 168 | 169 | this.each(function () { 170 | var el = $(this); 171 | var html = el.html(); 172 | 173 | if (showImages) { 174 | // workaround for negative look ahead 175 | html = html.replace(imgRE, function ($0, $1) { 176 | return $1 ? $0 : "
"; 177 | }); 178 | } 179 | 180 | html = html.replace(httpRE, function ($0, $1) { 181 | return $1 ? $0 : "
" + $0 + ""; 182 | }); 183 | 184 | html = html.replace(wwwRE, function ($0, $1) { 185 | return $1 ? $0 : "" + $0 + ""; 186 | }); 187 | 188 | el.empty().append(html); 189 | 190 | if (showImages) { 191 | //inject expand capability on images 192 | el.find("div.imgWrap").each(function () { 193 | var imageDiv = $(this); 194 | 195 | 196 | imageDiv.click(function (e) { 197 | if (e.ctrlKey || e.metaKey) { 198 | window.open(imageDiv.find("img").prop("src"), "_blank"); 199 | } else { 200 | var imageClone = imageDiv.find("img").clone(); 201 | imageClone.mouseout(function () { 202 | $(this).remove(); 203 | }); 204 | imageClone.addClass("imageClone").css({"position":"absolute", "display":"none", "top":imageDiv.position().top, "left":imageDiv.position().left, "z-index":1000000}); 205 | imageDiv.after(imageClone); 206 | imageClone.fadeIn(); 207 | } 208 | }); 209 | }); 210 | } 211 | 212 | }); 213 | return this; 214 | }; 215 | 216 | jQuery.fn.emoticonize = function () { 217 | function convert(text) { 218 | var faccRE = /(:\))|(:-\))|(:-])|(:-\()|(:\()|(:-\/)|(:-\\)|(:-\|)|(;-\))|(:-D)|(:-P)|(:-p)|(:-0)|(:-o)|(:-O)|(:'-\()|(\(@\))/g; 219 | return text.replace(faccRE, function (str) { 220 | var ret = {":)":"smile", 221 | ":-)":"smile", 222 | ":-]":"polite_smile", 223 | ":-(":"frown", 224 | ":(":"frown", 225 | ":-/":"skepticism", 226 | ":-\\":"skepticism", 227 | ":-|":"sarcasm", 228 | ";-)":"wink", 229 | ":-D":"grin", 230 | ":-P":"tongue", 231 | ":-p":"tongue", 232 | ":-o":"surprise", 233 | ":-O":"surprise", 234 | ":-0":"surprise", 235 | ":'-(":"tear", 236 | "(@)":"angry"}[str]; 237 | if (ret) { 238 | ret = ""; 239 | return ret; 240 | } else 241 | return str; 242 | }); 243 | } 244 | 245 | function addBold(text) { 246 | var returnedValue; 247 | var faccRE = /\*\*[^*]*\*\*/ig; 248 | return text.replace(faccRE, function (str) { 249 | var temp = str.substr(2); 250 | var temp2 = temp.substr(0, temp.length - 2); 251 | return "" + temp2 + ""; 252 | }); 253 | } 254 | 255 | this.each(function () { 256 | var el = $(this); 257 | var html = convert(el.html()); 258 | html = addBold(html); 259 | el.html(html); 260 | }); 261 | return this; 262 | }; 263 | 264 | 265 | $.fn.unselectable = function () { 266 | this.each(function () { 267 | $(this).addClass("unselectable").attr("unselectable", "on"); 268 | }); 269 | return $(this); 270 | }; 271 | 272 | $.fn.clearUnselectable = function () { 273 | this.each(function () { 274 | $(this).removeClass("unselectable").removeAttr("unselectable"); 275 | }); 276 | return $(this); 277 | }; 278 | 279 | // ---------------------------------- initialize management 280 | var __initedComponents = new Object(); 281 | 282 | function initialize(url, type, ndo) { 283 | //console.debug("initialize before: " + url); 284 | var normUrl = url.asId(); 285 | var deferred = $.Deferred(); 286 | 287 | if (!__initedComponents[normUrl]) { 288 | __initedComponents[normUrl] = deferred; 289 | 290 | if ("CSS" == (type + "").toUpperCase()) { 291 | var link = $("").prop("href", url); 292 | $("head").append(link); 293 | deferred.resolve(); 294 | 295 | } else if ("SCRIPT" == (type + "").toUpperCase()) { 296 | $.ajax({type: "GET", 297 | url: url + "?" + buildNumber, 298 | dataType: "script", 299 | cache: true, 300 | success: function () { 301 | //console.debug("initialize loaded:" + url); 302 | deferred.resolve() 303 | }, 304 | error: function () { 305 | //console.debug("initialize failed:" + url); 306 | deferred.reject(); 307 | } 308 | }); 309 | 310 | 311 | } else { 312 | //console.debug(url+" as DOM"); 313 | //var text = getContent(url); 314 | url = url + (url.indexOf("?") > -1 ? "&" : "?") + buildNumber; 315 | var text = $.ajax({ 316 | type: "GET", 317 | url: url, 318 | dataType: "html", 319 | cache: true, 320 | success: function (text) { 321 | //console.debug("initialize loaded:" + url); 322 | ndo = ndo || $("body"); 323 | ndo.append(text); 324 | deferred.resolve() 325 | }, 326 | error: function () { 327 | //console.debug("initialize failed:" + url); 328 | deferred.reject(); 329 | } 330 | }); 331 | } 332 | } 333 | 334 | return __initedComponents[normUrl].promise(); 335 | } 336 | 337 | 338 | /** 339 | * callback receive event, data 340 | * data.response contiene la response json arrivata dal controller 341 | * E.G.: 342 | * $("body").trigger("worklogEvent",[{type:"delete",response:response}]) 343 | * 344 | * in caso di delete di solito c'è il response.deletedId 345 | */ 346 | function registerEvent(eventName,callback) { 347 | $("body").off(eventName).on(eventName, callback); 348 | } 349 | 350 | 351 | function openPersistentFile(file) { 352 | //console.debug("openPersistentFile",file); 353 | var t=window.self; 354 | try{ 355 | if(window.top != window.self) 356 | t=window.top; 357 | } catch(e) {} 358 | 359 | if (file.mime.indexOf("image") >= 0) { 360 | var img = $("").prop("src", file.url).css({position: "absolute", top: "-10000px", left: "-10000px"}).one("load", function () { 361 | //console.debug("image loaded"); 362 | var img = $(this); 363 | var w = img.width(); 364 | var h = img.height(); 365 | //console.debug("image loaded",w,h); 366 | var f=w/h; 367 | var ww = $(t).width()*.8; 368 | var wh = $(t).height()*.8; 369 | if (w>ww){ 370 | w=ww; 371 | h=w/f; 372 | } 373 | if (h>wh){ 374 | h=wh; 375 | w=h*f; 376 | } 377 | 378 | var hasTop=false; 379 | img.width(w).height(h).css({position: "static", top: 0, left: 0}); 380 | 381 | t.createModalPopup(w+100,h+100).append(img); 382 | }); 383 | t.$("body").append(img); 384 | } else if (file.mime.indexOf("pdf") >= 0) { 385 | t.openBlackPopup(file.url, $(t).width()*.8, $(t).height()*.8); 386 | } else { 387 | window.open(file.url + "&TREATASATTACH=yes"); 388 | } 389 | } 390 | 391 | 392 | function wrappedEvaluer(toEval){ 393 | eval(toEval); 394 | } 395 | 396 | function evalInContext(stringToEval,context){ 397 | wrappedEvaluer.apply(context,[stringToEval]); 398 | } 399 | 400 | 401 | Storage.prototype.setObject = function(key, value) { 402 | this.setItem(key, JSON.stringify(value)); 403 | }; 404 | 405 | Storage.prototype.getObject = function(key) { 406 | return this.getItem(key) && JSON.parse(this.getItem(key)); 407 | }; 408 | 409 | function objectSize(size) { 410 | var divisor = 1; 411 | var unit = "bytes"; 412 | if (size >= 1024 * 1024) { 413 | divisor = 1024 * 1024; 414 | unit = "MB"; 415 | } else if (size >= 1024) { 416 | divisor = 1024; 417 | unit = "KB"; 418 | } 419 | if (divisor == 1) 420 | return size + " " + unit; 421 | 422 | return (size / divisor).toFixed(2) + ' ' + unit; 423 | } 424 | 425 | 426 | function htmlEncode(value){ 427 | //create a in-memory div, set it's inner text(which jQuery automatically encodes) 428 | //then grab the encoded contents back out. The div never exists on the page. 429 | return $('
').text(value).html(); 430 | } 431 | 432 | function htmlLinearize(value, length){ 433 | value = value.replace(/(\r\n|\n|\r)/gm,"").replace(/
/g, " - "); 434 | value = value.replace(/- -/g, "-"); 435 | 436 | var ret = $('
').text(value).text(); 437 | 438 | if(length){ 439 | var ellips = ret.length > length ? "..." : ""; 440 | ret = ret.substring(0,length) + ellips; 441 | } 442 | 443 | return ret; 444 | } 445 | 446 | function htmlDecode(value){ 447 | return $('
').html(value).text(); 448 | } 449 | 450 | 451 | 452 | function createCookie(name,value,days) { 453 | if (days) { 454 | var date = new Date(); 455 | date.setTime(date.getTime()+(days*24*60*60*1000)); 456 | var expires = "; expires="+date.toGMTString(); 457 | } 458 | else var expires = ""; 459 | document.cookie = name+"="+value+expires+"; path=/"; 460 | } 461 | 462 | function readCookie(name) { 463 | var nameEQ = name + "="; 464 | var ca = document.cookie.split(';'); 465 | for(var i=0;i < ca.length;i++) { 466 | var c = ca[i]; 467 | while (c.charAt(0)==' ') c = c.substring(1,c.length); 468 | if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); 469 | } 470 | return null; 471 | } 472 | 473 | function eraseCookie(name) { 474 | createCookie(name,"",-1); 475 | } 476 | 477 | 478 | 479 | function getParameterByName(name, url) { 480 | if (!url) url = window.location.href; 481 | name = name.replace(/[\[\]]/g, "\\$&"); 482 | var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), 483 | results = regex.exec(url); 484 | if (!results) return null; 485 | if (!results[2]) return ''; 486 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 487 | } 488 | 489 | $.fn.isEmptyElement = function( ){ 490 | return !$.trim($(this).html()) 491 | }; 492 | 493 | //workaround for jquery 3.x 494 | if (typeof ($.fn.size)!="funcion") 495 | $.fn.size=function(){return this.length}; -------------------------------------------------------------------------------- /platform.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'TeamworkRegular'; 3 | src: url('res/icons.eot?5qjga5'); 4 | src: url('res/icons.eot?#iefix5qjga5') format('embedded-opentype'), 5 | url('res/icons.woff?5qjga5') format('woff'), 6 | url('res/icons.ttf?5qjga5') format('truetype'), 7 | url('res/icons.svg?5qjga5#icons') format('svg'); 8 | font-weight: normal !important; 9 | font-style: normal; 10 | } 11 | 12 | * { 13 | -webkit-box-sizing: border-box; 14 | -moz-box-sizing: border-box; 15 | -o-box-sizing: border-box; 16 | box-sizing: border-box; 17 | } 18 | 19 | /* 20 | ------------------------------------------------------- 21 | body styles 22 | ------------------------------------------------------- 23 | */ 24 | BODY, TBODY { 25 | font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 26 | /*font-family: 'Open Sans', sans-serif;*/ 27 | font-size: 14px; 28 | margin: 0; 29 | color: #1e2f41; 30 | text-decoration: none; 31 | } 32 | 33 | a { 34 | text-decoration: none; 35 | font-weight: bold; 36 | /*color: #16ABDD;*/ 37 | color: #2b9af3; 38 | text-rendering: optimizelegibility; 39 | -webkit-font-smoothing: antialiased; 40 | -moz-font-smoothing: antialiased; 41 | 42 | } 43 | 44 | a:hover, a.aHover { 45 | color: #0C85AD; 46 | color: #2575be; 47 | text-decoration: underline; 48 | } 49 | 50 | h1 { 51 | font-size: 32px; 52 | line-height: 34px; 53 | color: #91B4B7; 54 | font-weight: normal; 55 | margin: 0 0 10px 0 56 | } 57 | 58 | h2 { 59 | font-size: 28px; 60 | color: #34495e; 61 | font-weight: normal; 62 | margin: 0 0 10px 0 63 | } 64 | 65 | h3 { 66 | text-decoration: none; 67 | color: #1e2f41; 68 | font-size: 16px; 69 | margin: 0; 70 | } 71 | 72 | h4 { 73 | font-size: 16px; 74 | padding: 5px 0; 75 | color: #617777; 76 | margin: 0 77 | } 78 | 79 | #savingMessage { 80 | background-color: #E3EDED; 81 | display: none; 82 | color: #617777; 83 | font-weight: bolder; 84 | position: fixed; 85 | top: 0; 86 | left: 50%; 87 | width: 200px; 88 | text-align: center; 89 | margin-left: -100px; 90 | padding: 5px 0; 91 | z-index: 1000000; 92 | box-shadow: 0 3px 2px rgba(0, 0, 0, 0.4); 93 | -moz-box-shadow: 0 3px 2px rgba(0, 0, 0, 0.4); 94 | -webkit-box-shadow: 0 3px 2px rgba(0, 0, 0, 0.4); 95 | -o-box-shadow: 0 3px 2px rgba(0, 0, 0, 0.4); 96 | } 97 | 98 | .waiting { 99 | cursor: progress; 100 | } 101 | 102 | /* 103 | ------------------------------------------------------- 104 | teamwork icon 105 | ------------------------------------------------------- 106 | */ 107 | 108 | .teamworkIcon { 109 | font-family: 'TeamworkRegular' !important; 110 | color: #34495e; 111 | font-weight: normal; 112 | font-size: 120%; 113 | font-style: normal !important; 114 | text-rendering: optimizelegibility; 115 | -webkit-font-smoothing: antialiased; 116 | -moz-font-smoothing: antialiased; 117 | 118 | } 119 | 120 | .teamworkIcon:hover { 121 | opacity: .8 122 | } 123 | 124 | .teamworkIcon.withLabel { 125 | padding-right: 5px; 126 | } 127 | 128 | .button:hover .teamworkIcon { 129 | opacity: 0.8 130 | } 131 | 132 | .teamworkIcon.alert { 133 | color: #B61E2D; 134 | } 135 | 136 | .del { 137 | color: #ff7271 138 | } 139 | 140 | .cvcColorSquare { 141 | display: inline-block; 142 | text-align: left; 143 | border: #fff 0px solid; 144 | box-shadow: 0px 0px 5px #999; 145 | -moz-box-shadow: 2px 2px 2px #999; 146 | -webkit-box-shadow: 0px 0px 5px #999; 147 | -o-box-shadow: 0px 0px 5px #999; 148 | text-indent: 10px; 149 | border-radius: 5px; 150 | cursor: pointer; 151 | } 152 | 153 | .cvcColorSquare:hover { 154 | opacity: .7; 155 | } 156 | 157 | .unselectable { 158 | -webkit-user-select: none; 159 | -khtml-user-select: none; 160 | -moz-user-select: none; 161 | -o-user-select: none; 162 | user-select: none; 163 | } 164 | 165 | .ui-resizable { 166 | position: relative; 167 | } 168 | 169 | .ui-resizable-handle { 170 | position: absolute; 171 | font-size: 0.1px; 172 | z-index: 99999; 173 | display: block; 174 | } 175 | 176 | .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { 177 | display: none; 178 | } 179 | 180 | .ui-resizable-n { 181 | cursor: n-resize; 182 | height: 7px; 183 | width: 100%; 184 | top: -5px; 185 | left: 0; 186 | } 187 | 188 | .ui-resizable-s { 189 | cursor: s-resize; 190 | height: 7px; 191 | width: 100%; 192 | bottom: -5px; 193 | left: 0; 194 | } 195 | 196 | .ui-resizable-e { 197 | cursor: e-resize; 198 | width: 7px; 199 | right: -5px; 200 | top: 0; 201 | height: 100%; 202 | } 203 | 204 | .ui-resizable-w { 205 | cursor: w-resize; 206 | width: 7px; 207 | left: -5px; 208 | top: 0; 209 | height: 100%; 210 | } 211 | 212 | .ui-resizable-se { 213 | cursor: se-resize; 214 | width: 12px; 215 | height: 12px; 216 | right: 1px; 217 | bottom: 1px; 218 | } 219 | 220 | .ui-resizable-sw { 221 | cursor: sw-resize; 222 | width: 9px; 223 | height: 9px; 224 | left: -5px; 225 | bottom: -5px; 226 | } 227 | 228 | .ui-resizable-nw { 229 | cursor: nw-resize; 230 | width: 9px; 231 | height: 9px; 232 | left: -5px; 233 | top: -5px; 234 | } 235 | 236 | .ui-resizable-ne { 237 | cursor: ne-resize; 238 | width: 9px; 239 | height: 9px; 240 | right: -5px; 241 | top: -5px; 242 | } 243 | 244 | /* 245 | ------------------------------------------------------- 246 | table styles 247 | ------------------------------------------------------- 248 | */ 249 | 250 | .table { 251 | width: 100%; 252 | } 253 | 254 | TH, .tableHeader { 255 | font-weight: normal; 256 | color: #555; 257 | border: none; 258 | background-color: #f0f0f0; 259 | padding: 2px 260 | } 261 | 262 | .list td{ 263 | border-bottom: 1px solid #dedede; 264 | padding: 5px 0; 265 | } 266 | 267 | .list th { 268 | padding: 5px 2px 269 | } 270 | 271 | .row em {font-style: normal;color: #a2a2a2} 272 | 273 | 274 | .ganttTaskEditor h2 { 275 | text-transform: capitalize 276 | 277 | } 278 | 279 | .ganttTaskEditor .formElements, 280 | .resourceEditor .formElements { 281 | background-color: #F5F5F5; 282 | border-color: #CECECE 283 | } 284 | 285 | table .resRow td, table .assigEditRow td { 286 | border-bottom: 1px solid #cecece; 287 | padding: 5px 0 288 | } 289 | 290 | 291 | 292 | 293 | /* 294 | ------------------------------------------------------- 295 | Gantt Online 296 | ------------------------------------------------------- 297 | */ 298 | 299 | 300 | .servicesEnroll h2 { 301 | margin-bottom: 20px 302 | } 303 | 304 | .heading { 305 | text-align: center; 306 | } 307 | .heading img { 308 | display:block; 309 | margin: -20px auto 30px; 310 | } 311 | 312 | 313 | .twAds { 314 | height: 38px; 315 | background-color: #5ACADF; 316 | width: 100%; 317 | /*background-image: url("../../img/twAdBg.png");*/ 318 | text-align: center; 319 | color: #fff; 320 | z-index: 1000; 321 | } 322 | 323 | .twAds.light { 324 | padding-top: 8px 325 | } 326 | 327 | .twAds .twitterButton { 328 | vertical-align: middle; 329 | display: inline-block; 330 | margin-left: 15px 331 | } 332 | 333 | .twAds .remove { 334 | display: inline-block; 335 | line-height: 38px; 336 | color: #fff; 337 | cursor: pointer; 338 | position: absolute; 339 | top:0; 340 | right: 12px 341 | } 342 | 343 | .twAds a { 344 | color: #fff; 345 | border-bottom: 1px solid rgba(255, 255, 255, 0.40) 346 | } 347 | 348 | .twAds a:hover { 349 | text-decoration: none 350 | } 351 | 352 | .servicesEnroll .oauth { 353 | width: 90px; 354 | height: auto; 355 | } 356 | 357 | .servicesEnroll .oauth:hover { 358 | opacity: .8 359 | } 360 | 361 | .errImg img { 362 | width: 25px; 363 | height: auto; 364 | vertical-align: middle; 365 | } 366 | 367 | #__FEEDBACKMESSAGEPLACE { 368 | position: absolute; 369 | background-color: #fafad2; 370 | } 371 | 372 | .adminLogin .formElements { 373 | width: 120px; 374 | } 375 | 376 | .adminLogin { 377 | width: 350px; 378 | margin: 0 auto; 379 | position: absolute; 380 | bottom: 10px; 381 | left: 20px; 382 | } 383 | 384 | .lastMod { 385 | font-style: italic; 386 | margin-right: 10px; 387 | vertical-align: middle; 388 | display: block; 389 | color: #D37E00; 390 | font-size: 12px; 391 | position: fixed; 392 | bottom: 25px; 393 | z-index: 20; 394 | padding: 5px 10px; 395 | background-color: rgba(255, 255, 0, 0.16); 396 | } 397 | 398 | .lastMod .teamworkIcon { 399 | color: #34495e; 400 | font-size: 160%; 401 | vertical-align: middle; 402 | } 403 | 404 | .button.textual, 405 | .button.buttonImg, 406 | .ganttButtonSeparator { 407 | vertical-align: middle; 408 | } 409 | 410 | .button span.teamworkIcon { 411 | font-size: .95em; 412 | } 413 | 414 | .clearfix:after { 415 | visibility: hidden; 416 | display: block; 417 | font-size: 0; 418 | content: " "; 419 | clear: both; 420 | height: 0; 421 | } 422 | 423 | 424 | .embedCode { 425 | font-family: Consolas,monospace!important; 426 | font-size: 100%; 427 | width: 100%; 428 | color: #2792E6; 429 | padding: 10px; 430 | border: 4px solid #d0d0d0 431 | } 432 | 433 | .ruler { 434 | width: 100%; 435 | display: block; 436 | padding: 35px 0 35px; 437 | height: 1px; 438 | } 439 | 440 | .ruler.short span { 441 | width: 100px; 442 | height: 1px; 443 | display: block; 444 | margin: 0 auto; 445 | border-bottom:1px solid #ccc 446 | } 447 | 448 | 449 | .clearfix { display: inline-block; } 450 | /* start commented backslash hack \*/ 451 | * html .clearfix { height: 1%; } 452 | .clearfix { display: block; } 453 | /* close commented backslash hack */ 454 | 455 | 456 | 457 | /* 458 | ------------------------------------------------------- 459 | Buttons 460 | ------------------------------------------------------- 461 | */ 462 | 463 | .buttonBar { 464 | } 465 | 466 | .buttonBar.centered { 467 | text-align: center 468 | } 469 | 470 | .buttonBar.block .button { 471 | margin: 0 0 20px 472 | } 473 | 474 | 475 | .button { 476 | display: inline-block; 477 | font-size: 110%; 478 | color: #fff; 479 | cursor: pointer; 480 | background-color: #34495e; 481 | -moz-border-radius: 5px; 482 | -webkit-border-radius: 5px; 483 | -o-border-radius: 5px; 484 | border-radius: 5px; 485 | border: 1px solid rgba(0, 0, 0, 0.2); 486 | padding: 5px 12px 8px; 487 | margin-bottom: 10px; 488 | margin-right: 10px; 489 | text-align: center; 490 | -webkit-transition: background-color 500ms ease-out 1s; 491 | -moz-transition: background-color 500ms ease-out 1s; 492 | -o-transition: background-color 500ms ease-out 1s; 493 | transition: background-color 500ms ease-out 1s; 494 | } 495 | 496 | .button.first { 497 | background-color: #75a800; 498 | font-weight: bold; 499 | } 500 | 501 | .button.small { 502 | font-size: 100%; 503 | padding: 2px 7px 4px; 504 | margin-bottom: 0 505 | 506 | } 507 | 508 | .large { 509 | font-size: 160%; 510 | padding: 5px 14px 8px; 511 | border-radius: 6px 512 | } 513 | 514 | 515 | 516 | .button.first:hover { 517 | background-color: #2F2F2F; 518 | } 519 | 520 | .button[disabled] { 521 | cursor: default; 522 | opacity: 0.4 523 | } 524 | 525 | .button:hover[disabled] { 526 | background-color: #BABABA 527 | } 528 | 529 | .button.textual, .button.buttonImg { 530 | border: none; 531 | background-color: transparent; 532 | color: #68979B; 533 | -moz-border-radius: 0; 534 | -webkit-border-radius: 0; 535 | -o-border-radius: 0; 536 | border-radius: 0; 537 | padding: 0; 538 | margin: 0; 539 | text-align: left 540 | } 541 | 542 | .button.opt { 543 | background-color: #009E94; 544 | background-color: #2792E6; 545 | } 546 | 547 | .button.edit { 548 | color: #009E94; 549 | padding: 0; 550 | margin: 0 551 | } 552 | 553 | .button.delete { 554 | color: #B61E2D; 555 | padding: 0; 556 | margin: 0 557 | } 558 | 559 | .button:hover { 560 | background-color: #506b84; 561 | color: rgba(255, 255, 255, 0.75); 562 | } 563 | 564 | a.button:hover { 565 | text-decoration: none 566 | } 567 | 568 | .button.textual:hover, .button.buttonImg:hover { 569 | background-color: transparent; 570 | } 571 | 572 | span.separator { 573 | display: inline-block; 574 | } 575 | 576 | .button.add { 577 | color: #009E94; 578 | } 579 | 580 | .button.add .teamworkIcon { 581 | color: #009E94; 582 | } 583 | 584 | form { 585 | margin: 0; 586 | padding: 0; 587 | } 588 | 589 | select { 590 | border: 1px solid #91B4B7; 591 | padding: 4px; 592 | font-size: 16px; 593 | font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 594 | } 595 | 596 | .formElements { 597 | background-color: white; 598 | padding: 4px; 599 | font-size: 16px; 600 | border: 1px solid #91B4B7; 601 | -moz-border-radius: 3px; 602 | -webkit-border-radius: 3px; 603 | -o-border-radius: 3px; 604 | border-radius: 3px; 605 | font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 606 | } 607 | 608 | .formElementsError { 609 | border: 1px solid #ff0000; 610 | } 611 | 612 | .formElementExclamation { 613 | width: 15px; 614 | height: 25px; 615 | mmmargin-left: -20px; 616 | mmmposition: absolute; 617 | background: url("../../applications/gantt/distrib/res/alert.gif") no-repeat; 618 | } 619 | 620 | span#FLD_LOGIN_NAMEerror, span#FLD_PWDerror { 621 | margin-left: -23px; 622 | margin-top: 2px; 623 | } 624 | 625 | input { 626 | background-color: white; 627 | padding: 4px; 628 | font-size: 16px; 629 | border: 1px solid #91B4B7; 630 | -moz-border-radius: 3px; 631 | -webkit-border-radius: 3px; 632 | -o-border-radius: 3px; 633 | border-radius: 3px; 634 | font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 635 | } 636 | 637 | .confirmBox { 638 | display: inline; 639 | z-index: 10000; 640 | vertical-align: middle; 641 | text-align: center; 642 | font-style: italic; 643 | color: #777; 644 | background: #fff; 645 | position: absolute; 646 | margin: 0 auto 647 | } 648 | 649 | 650 | 651 | .confirmBox .confirmNo { 652 | color: #e06060; 653 | cursor: pointer; 654 | font-weight: bolder; 655 | } 656 | 657 | .confirmBox .confirmYes { 658 | color: #68af6c; 659 | cursor: pointer; 660 | font-weight: bolder; 661 | } 662 | 663 | .blackpopup { 664 | padding: 20px; 665 | border-radius: 10px; 666 | } 667 | 668 | .smallPopUp { 669 | top:0!important; 670 | margin-top:0!important; 671 | } 672 | 673 | iframe#bwinPopup { 674 | border-radius: 10px; 675 | } 676 | 677 | .mainWrap { 678 | padding: 20px 679 | } 680 | 681 | .mainWrap > h2:first-of-type { 682 | text-transform: capitalize 683 | } 684 | 685 | 686 | /******** SHARE BOX *********/ 687 | 688 | .shareBar { 689 | position: absolute; 690 | right: 100px; 691 | top: 0; 692 | } 693 | 694 | .shareBar img:hover { 695 | opacity: 0.8; 696 | } 697 | 698 | .shareBtn { 699 | background: none repeat scroll 0 0 #F9F7F7; 700 | border: 1px solid rgba(0, 0, 0, 0.24); 701 | border-radius: 3px; 702 | color: #878686; 703 | display: inline-block; 704 | font-family: sans-serif; 705 | font-size: 12px; 706 | padding: 4px 8px 4px 14px; 707 | text-decoration: none; 708 | } 709 | 710 | .shareBtn { 711 | cursor: pointer; 712 | } 713 | 714 | .shareBtn:hover { 715 | border: 1px solid rgba(0, 0, 0, 0.24); 716 | color: #878686; 717 | opacity: .7; 718 | } 719 | 720 | .shareBtn img { 721 | border: 0 none; 722 | padding-right: 5px; 723 | vertical-align: middle; 724 | } 725 | 726 | .shareBtn a { 727 | color: #888; 728 | text-decoration: none; 729 | } 730 | 731 | #shareBox { 732 | text-align: center 733 | } 734 | 735 | #shareBox h2 { 736 | margin-bottom: 30px; 737 | } 738 | 739 | 740 | #shareBox .shareBtn { 741 | padding: 15px 20px; 742 | font-size: 30px; 743 | } 744 | 745 | #shareBox .shareBtn.icon-facebook { 746 | background-color:#3b5998; 747 | color: #fff; 748 | } 749 | 750 | #shareBox .shareBtn.icon-twitter { 751 | background-color:#00aced; 752 | color: #fff; 753 | } 754 | 755 | #shareBox .shareBtn.icon-linkedin { 756 | background-color:#007bb6; 757 | color: #fff; 758 | } 759 | #shareBox .shareBtn.icon-gplus { 760 | background-color:#dd4b39; 761 | color: #fff; 762 | } 763 | 764 | #shareBox .shareBtn span { 765 | display: none; 766 | } 767 | 768 | 769 | /*------------------------------------------------- MODAL POPUP (ex blackPopup) ------------------------------------------------------*/ 770 | .modalPopup { 771 | position:fixed; 772 | top:0; 773 | left:0; 774 | width:100%; 775 | height:100%; 776 | background-color:rgba(255,255,255,.8); 777 | z-index: 100; 778 | } 779 | 780 | .modalPopup.upgradeMessage { 781 | top:40px; 782 | text-align: center; 783 | } 784 | 785 | .modalPopup.upgradeMessage p { 786 | margin-bottom: 20px; 787 | line-height: 1.6em; 788 | } 789 | 790 | .modalPopup.inIframe { 791 | background-color:rgba(255,255,255,0); 792 | } 793 | 794 | .modalPopup.black { 795 | background-color: rgba(75, 75, 75, 0.6); 796 | } 797 | 798 | .modalPopup .bwinPopupd{ 799 | position: relative; 800 | box-shadow: 0 0 0 4px rgba(46, 186, 255, 0.3); 801 | border: 1px solid rgba(127, 127, 127, 0.3); 802 | background-color:#fff; 803 | margin:auto; 804 | padding: 30px 30px; 805 | border-radius: 5px; 806 | } 807 | 808 | .modalPopup .popUpClose{ 809 | z-index: 9; 810 | color: #2f2f2f; 811 | width: 20px; 812 | height: 20px; 813 | text-align: center; 814 | line-height: 20px; 815 | right: 15px; 816 | top:15px; 817 | } 818 | 819 | .modalPopup.black .bwinPopupd .popUpClose{ 820 | color: #ffffff; 821 | } 822 | 823 | .modalPopup.iframe .bwinPopupd { 824 | overflow: hidden; 825 | padding: 0; 826 | } 827 | 828 | .modalPopup.iframe .bwinPopupd iframe { 829 | position: absolute; 830 | border-radius: 5px; 831 | } 832 | 833 | .modalPopup.inIframe .bwinPopupd { 834 | background-color: #f9f9f9; 835 | border-radius: 0 0 5px 5px; 836 | } 837 | 838 | .offScreen { 839 | position: absolute; 840 | left: -5000px; 841 | } 842 | 843 | -------------------------------------------------------------------------------- /gantt.css: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | /*overflow: hidden;*/ 4 | } 5 | 6 | .TWGanttWorkSpace.ganttFullScreen{ 7 | position: fixed; 8 | top:0; 9 | left:0; 10 | bottom:0; 11 | right: 0; 12 | margin: auto; 13 | z-index: 1000; 14 | background-color: #fff; 15 | } 16 | 17 | /* -------------------------------------- GRIDIFY -----------------------------------*/ 18 | .gdfTable { 19 | table-layout: fixed; 20 | border-collapse: separate; 21 | border-spacing: 0; 22 | background-color: #fff; 23 | } 24 | 25 | .gdfTable td, .gdfTable th { 26 | vertical-align: middle; 27 | overflow: hidden; 28 | text-overflow: clip; 29 | white-space: nowrap; 30 | font-size: 14px 31 | } 32 | 33 | .gdfCell { 34 | overflow: hidden; 35 | padding:4px 2px; 36 | border-bottom: 1px solid #eee; 37 | border-right: 1px solid #eee; 38 | font-family: arial, helvetica, sans-serif; 39 | } 40 | 41 | .gdfCell.noClip{ 42 | overflow: visible; 43 | } 44 | 45 | .gdfColHeader { 46 | min-width: 5px; 47 | height: 30px; 48 | background-color: #eee; 49 | border-bottom:2px solid #bbb; 50 | border-right: 1px solid #bbb; 51 | } 52 | 53 | .gdfColHeader:last-of-type { 54 | border-right: none; 55 | } 56 | 57 | .gdfCell:last-of-type { 58 | border-right: none; 59 | } 60 | 61 | 62 | .gdfCellInput { 63 | border: 0 none; 64 | font-size: 12px; 65 | height: 20px; 66 | margin: 0; 67 | padding: 0; 68 | width: 100%; 69 | background-color: #d4fbe8; 70 | } 71 | 72 | .gdfCellWrap { 73 | border: 0 none; 74 | font-size: 12px; 75 | height: 17px; 76 | margin: 0; 77 | padding: 0; 78 | width: 100%; 79 | overflow: hidden; 80 | 81 | background-color: #ffcccc; 82 | } 83 | 84 | .gdfHResizing { 85 | cursor: w-resize; 86 | } 87 | 88 | 89 | /* -------------------------------------- SPLITTER -----------------------------------*/ 90 | .splitterContainer { 91 | width: 100%; 92 | height: 100%; 93 | } 94 | 95 | .splitBox1{ 96 | overflow-x: scroll; 97 | overflow-y: hidden; 98 | } 99 | 100 | .splitBox2 { 101 | overflow-x: scroll; 102 | overflow-y: auto; 103 | } 104 | 105 | 106 | .splitElement { 107 | outline-style: none; 108 | position: absolute; 109 | height: 100%; 110 | background-color: #f3f3f3; 111 | } 112 | 113 | .vSplitBar { 114 | position: relative; 115 | width: 5px; 116 | /*background-color: rgba(170, 170, 170, .2);*/ 117 | cursor: ew-resize; 118 | text-align: center; 119 | color: white; 120 | box-shadow: 0 0 3px rgba(0, 0, 0, .4); 121 | background: rgba(170, 170, 170, .2) url("res/ganttSplitterGrip.png") no-repeat center center; 122 | z-index: 5; 123 | } 124 | 125 | .unselectable .vSplitBar, .vSplitBar:hover { 126 | background-color: rgba(170, 170, 170, .5); 127 | box-shadow: 0 0 5px rgba(0, 0, 0, .5); 128 | 129 | } 130 | 131 | .vSplitBar .toLeft,.vSplitBar .toRight,.vSplitBar .toCenter{ 132 | font-family: icons,TeamworkRegular; 133 | cursor: pointer; 134 | position: absolute; 135 | top: 0; 136 | margin-top: 0; 137 | /*background-color: rgba(170, 170, 170, .2);*/ 138 | /*background-color: rgba(0, 126, 221, 0.3);*/ 139 | background-color: rgba(47, 170, 201, 0.3); 140 | z-index: 2; 141 | font-size: 10px; 142 | width: 15px; 143 | /*box-shadow: 0 0 1px rgba(0, 0, 0, .5);*/ 144 | } 145 | 146 | .unselectable .vSplitBar .toLeft,.unselectable .vSplitBar .toCenter,.unselectable .vSplitBar .toRight, .vSplitBar:hover .toLeft, .vSplitBar:hover .toRight, .vSplitBar:hover .toCenter{ 147 | /*background-color: rgba(170, 170, 170, 1);*/ 148 | /*background-color: rgba(0, 126, 221, 1);*/ 149 | background-color: rgba(47, 170, 201, 1); 150 | 151 | box-shadow: 0 0 1px rgba(0, 0, 0, .4); 152 | } 153 | 154 | .vSplitBar .toLeft { 155 | left: -19px; 156 | text-align: left; 157 | } 158 | .vSplitBar .toCenter{ 159 | left:-4px; 160 | text-align: center; 161 | } 162 | .vSplitBar .toRight{ 163 | left:10px; 164 | text-align: right; 165 | } 166 | 167 | .ganttFixHead{ 168 | position: absolute; 169 | z-index: 2; 170 | top:0; 171 | /*background: #EEEEEE;*/ 172 | height: 42px; 173 | 174 | } 175 | 176 | /* -------------------------------------- GANTT -----------------------------------*/ 177 | 178 | .ganttTable{ 179 | table-layout:fixed; 180 | background-color: #ffffff; 181 | } 182 | 183 | .ganttTable td,.ganttTable th{ 184 | overflow: hidden; 185 | text-overflow: clip; 186 | white-space: nowrap; 187 | } 188 | 189 | .ganttHead1,.ganttHead2{ 190 | height:20px; 191 | } 192 | 193 | .ganttHead1 th{ 194 | border-left:1px solid #b0b0b0; 195 | padding: 0; 196 | margin: 0; 197 | /*border-right: 1px solid #bbb;*/ 198 | border-bottom:1px solid #bbb; 199 | background: #EEEEEE; 200 | white-space: pre-line; 201 | word-break: break-all; 202 | } 203 | 204 | .ganttHead1 th, 205 | .ganttHead2 th{ 206 | white-space: nowrap; 207 | overflow: hidden; 208 | } 209 | 210 | .ganttHead2 th{ 211 | padding: 0; 212 | margin: 0; 213 | border-left:1px solid #b0b0b0; 214 | /*border-right: 1px solid #bbb;*/ 215 | border-bottom:2px solid #bbb; 216 | background: #EEEEEE; 217 | } 218 | 219 | .ganttHead1 th.headSmall,.ganttHead2 th.headSmall{ 220 | font-size: 10px; 221 | } 222 | 223 | .ganttToday{ 224 | position:absolute; 225 | top:0; 226 | width:1px; 227 | height:100%; 228 | border-left:2px dotted #13AFA5; 229 | } 230 | 231 | .ganttTitle img { 232 | max-width: 150px; 233 | } 234 | 235 | .ganttButtonBar{ 236 | position:relative; 237 | z-index: 2; 238 | /*background-color: #fff;*/ 239 | border-bottom: 1px solid #959595; 240 | padding: 5px 0 5px 10px; 241 | } 242 | 243 | .dataTable .ganttButtonBar{ 244 | border-bottom: none; 245 | } 246 | 247 | .ganttButtonBar .buttons { 248 | position: relative; 249 | display:inline-block; 250 | width: 100%; 251 | margin-top: 0; 252 | height: 45px; 253 | } 254 | 255 | .dataTable .ganttButtonBar .buttons { 256 | display:inline-block; 257 | width: 100%; 258 | } 259 | 260 | .ganttButtonBar .buttons button{ 261 | vertical-align: middle; 262 | margin:0; 263 | outline: none; 264 | } 265 | 266 | .ganttButtonBar .buttons .button.textual.icon { 267 | height: 45px; 268 | } 269 | 270 | 271 | .button span.teamworkIcon { 272 | text-indent: -10px; 273 | } 274 | 275 | 276 | .button.textual span.teamworkIcon { 277 | font-size: 140% 278 | } 279 | 280 | #saveGanttButton { 281 | margin-left:20px; 282 | padding: 5px 12px; 283 | margin-bottom: 0; 284 | vertical-align: middle; 285 | } 286 | 287 | 288 | .ganttButtonSeparator{ 289 | border-left:1px solid #dadada; 290 | margin:0 10px; 291 | font-size: 130%; 292 | vertical-align: middle; 293 | } 294 | 295 | .ganttLines{ 296 | position:absolute; 297 | width:100%; 298 | height:1px; 299 | border-top:1px solid #eee; 300 | z-index:1; 301 | } 302 | 303 | .ganttLinks{ 304 | z-index:10; 305 | } 306 | 307 | 308 | .ganttTable td.end{ 309 | border-right: 2px dotted #ddd; 310 | } 311 | 312 | .ganttHead2 th.holyH{ 313 | background-color: rgba(236, 195, 176, 0.40); 314 | } 315 | .ganttBodyCell.holy{ 316 | background-color: rgba(255, 245, 230, 0.51); 317 | } 318 | 319 | 320 | /* -------------------------------------- TASK -----------------------------------*/ 321 | 322 | .taskBoxDiv{ 323 | position:absolute; 324 | height:25px; 325 | margin-top:3px; 326 | z-index:100; 327 | } 328 | 329 | .taskBoxDiv .layout { 330 | height:100%; 331 | color:#DB2727; 332 | border-radius:2px; 333 | background: #eee; /* Old browsers */ 334 | border:1px solid #bbb; 335 | } 336 | 337 | .taskBoxDiv .taskStatus { 338 | left:5px; 339 | top:10px; 340 | position:absolute; 341 | width:10px; 342 | height:10px; 343 | } 344 | 345 | .taskBoxDiv .layout .milestone{ 346 | top:0; 347 | position:absolute; 348 | width:18px; 349 | background: url(res/milestone.png) no-repeat; 350 | height:18px; 351 | display:none; 352 | } 353 | .taskBoxDiv .layout .milestone.end{ 354 | right:0; 355 | } 356 | .taskBoxDiv .layout .milestone.active{ 357 | display:block; 358 | } 359 | 360 | .taskBoxDiv.hasChild .layout{ 361 | border-top:2px solid black; 362 | } 363 | 364 | .taskBoxDiv .taskProgress{ 365 | height:5px; 366 | position:absolute; 367 | } 368 | 369 | .taskBoxDiv .layout.extDep{ 370 | background-image:url(res/hasExternalDeps.png); 371 | } 372 | 373 | 374 | .taskLabel{ 375 | position:absolute; 376 | height:28px; 377 | color:black; 378 | text-align:right; 379 | padding-right:5px; 380 | overflow:hidden; 381 | left:-200px; 382 | width:195px; 383 | white-space:nowrap; 384 | } 385 | 386 | 387 | .taskDepLine { 388 | border: 1px solid #9999ff; 389 | overflow: hidden; 390 | position: absolute; 391 | } 392 | 393 | 394 | .taskEditRow,.emptyRow { 395 | height:30px; 396 | } 397 | 398 | .taskEditRow input, .columnWidthTest{ 399 | border: 0 none; 400 | font-size: 14px; 401 | height: 20px; 402 | margin: 0; 403 | padding:0; 404 | outline: 0; 405 | width: 100%; 406 | border-radius: 0; 407 | vertical-align: text-bottom; 408 | } 409 | 410 | .taskEditRow input[type=checkbox]{ 411 | transform:scale(.7); 412 | width:15px; 413 | height: 15px; 414 | } 415 | 416 | .columnWidthTest{ 417 | width: auto; 418 | } 419 | 420 | .taskEditRow input:focus{ 421 | font-weight: bold; 422 | } 423 | 424 | .taskEditRow input{ 425 | background-color: transparent; 426 | } 427 | 428 | .taskEditRow.rowSelected td{ 429 | background-color:rgb(234, 248, 255); 430 | } 431 | 432 | 433 | .isGanttList .taskEditRow:nth-child(odd), .assigEditRow:nth-child(odd){ 434 | background-color: #ffffff; 435 | } 436 | .isGanttList .taskEditRow:nth-child(even), .assigEditRow:nth-child(even){ 437 | background-color: #ffffff; 438 | } 439 | 440 | input[readonly]{ 441 | color: #c0c0c0; 442 | } 443 | 444 | .taskStatusBox{ 445 | position:absolute; 446 | /*width:100px;*/ 447 | height:26px; 448 | border:1px solid #a0a0a0; 449 | background-color:#fff; 450 | margin-top:-21px; 451 | margin-left:-2px; 452 | padding: 4px; 453 | z-index: 100; 454 | } 455 | .taskStatus{ 456 | width:15px; 457 | height:15px; 458 | display:inline-block; 459 | text-indent: 0; 460 | position:relative; 461 | box-shadow: none; 462 | border-radius: 50%; 463 | border:0; 464 | cursor: pointer; 465 | } 466 | .taskStatus[status=STATUS_ACTIVE]{ 467 | background-color: #3BBF67; 468 | color: #fff; 469 | } 470 | .taskStatus[status=STATUS_DONE]{ 471 | background-color: #6EBEF4; 472 | color:#000; 473 | } 474 | .taskStatus[status=STATUS_FAILED]{ 475 | background-color: #763A96; 476 | color: #fff; 477 | } 478 | .taskStatus[status=STATUS_SUSPENDED]{ 479 | background-color: #F9C154; 480 | color:#000; 481 | } 482 | .taskStatus[status=STATUS_UNDEFINED]{ 483 | background-color: #dededf; 484 | color:#000; 485 | } 486 | .taskStatus.selected{ 487 | border:#666 2px solid; 488 | } 489 | 490 | select.taskStatus{ 491 | width: auto; 492 | height: auto; 493 | border-radius: 2px; 494 | } 495 | 496 | .assigsTableWrapper{ 497 | position: relative; 498 | height: 150px; 499 | overflow: auto; 500 | margin-top: -20px; 501 | } 502 | 503 | .unselectable { 504 | -webkit-user-select: none; 505 | -khtml-user-select: none; 506 | -moz-user-select: none; 507 | -o-user-select: none; 508 | user-select: none; 509 | } 510 | 511 | 512 | .exp-controller{ 513 | display:inline-block; 514 | width:16px; 515 | height:16px; 516 | position: relative; 517 | top: 2px; 518 | margin-left: -18px; 519 | } 520 | 521 | .isParent .exp-controller{ 522 | background-image: url(res/toggle_collapse.png); 523 | } 524 | 525 | .isParent.collapsed .exp-controller{ 526 | cursor: pointer; 527 | background-image: url(res/toggle-expand.png); 528 | } 529 | 530 | .ui-resizable-helper { border: 1px dotted #00F; } 531 | .ui-resizable-e, .ui-resizable-w {width: 5px;} 532 | .ui-draggable{ 533 | cursor:move; 534 | } 535 | 536 | /*--------------------------------------------------- SVG --------------------------------------------------*/ 537 | .ganttSVGBox{ 538 | position: absolute; 539 | top:0; 540 | left: 0; 541 | height: 100%; 542 | background-color: transparent; 543 | width: 100%; 544 | overflow-y: hidden; /*IE11 bug*/ 545 | } 546 | 547 | .taskBoxSVG{ 548 | overflow: visible; 549 | } 550 | 551 | .taskBoxSVG .taskLayout{ 552 | stroke-width:0; 553 | stroke:#999; 554 | } 555 | 556 | .taskLinkPathSVG{ 557 | stroke: rgba(47, 151, 198, 1); 558 | /*stroke:#9999ff;*/ 559 | stroke-width:2.5px; 560 | fill:none; 561 | cursor:pointer; 562 | } 563 | 564 | .ganttLinesSVG{ 565 | fill:transparent; 566 | stroke-width:1; 567 | stroke:#eee; 568 | } 569 | 570 | .isGanttList .ganttLinesSVG:nth-child(even){ 571 | fill:transparent; 572 | stroke-width:1; 573 | stroke:#fff; 574 | 575 | } 576 | .isGanttList .ganttLinesSVG:nth-child(odd){ 577 | fill:transparent; 578 | stroke-width:1; 579 | stroke:#eee; 580 | } 581 | 582 | .ganttLinesSVG.rowSelected{ 583 | fill: rgb(234, 248, 255) !important; 584 | /*fill: rgba(255, 255, 153, 0.50) !important;*/ 585 | } 586 | 587 | .ganttTodaySVG{ 588 | stroke-width:2px; 589 | stroke:#e06671; 590 | stroke-linecap:"round"; 591 | stroke-dasharray:2,2; 592 | } 593 | 594 | .colorByStatus .taskStatusSVG[status=STATUS_ACTIVE]{ 595 | fill: #3BBF67; 596 | } 597 | .colorByStatus .taskStatusSVG[status=STATUS_DONE]{ 598 | fill: #6EBEF4; 599 | } 600 | .colorByStatus .taskStatusSVG[status=STATUS_FAILED]{ 601 | fill: #763A96; 602 | } 603 | .colorByStatus .taskStatusSVG[status=STATUS_SUSPENDED]{ 604 | fill: #f9c154; 605 | } 606 | .colorByStatus .taskStatusSVG[status=STATUS_UNDEFINED]{ 607 | fill: #dededf; 608 | } 609 | .colorByStatus .taskStatusSVG[status=STATUS_UNDEFINED] .taskLayout{ 610 | stroke: #ccc; 611 | stroke-width:1; 612 | } 613 | 614 | .colorByStatus .taskStatusSVG[status=STATUS_DONE] .textPerc, 615 | .colorByStatus .taskStatusSVG[status=STATUS_ACTIVE] .textPerc, 616 | .colorByStatus .taskStatusSVG[status=STATUS_FAILED] .textPerc{ 617 | fill: #fff; 618 | } 619 | 620 | .deSVG.deSVGdrag { 621 | cursor: move; 622 | } 623 | 624 | .deSVG.deSVGhand { 625 | cursor: ew-resize; 626 | } 627 | 628 | .linkHandleSVG{ 629 | display:none; 630 | stroke:transparent; 631 | stroke-width:5; 632 | fill: rgba(47, 151, 198, 0.7); 633 | cursor: pointer; 634 | } 635 | 636 | .linkLineSVG{ 637 | stroke-width:5px; 638 | stroke: rgba(47, 151, 198, 0.7); 639 | stroke-linecap:"round"; 640 | opacity: .5; 641 | } 642 | 643 | .linkOnProgress .deSVG.taskBoxSVG { 644 | cursor:cell; 645 | } 646 | 647 | .taskBoxSVG.linkOver .taskLayout{ 648 | stroke-width:1px; 649 | stroke:rgba(47, 151, 198, 0.7); 650 | opacity: 1; 651 | } 652 | 653 | .taskLabelSVG { 654 | stroke: none; 655 | fill:#999; 656 | font-size: 12px; 657 | } 658 | 659 | .critical .taskLinkPathSVG{ 660 | stroke:red; 661 | } 662 | 663 | .taskBoxSVG.critical .taskLayout{ 664 | stroke:red; 665 | } 666 | 667 | .focused .taskLinkPathSVG{ 668 | stroke-width:5px; 669 | stroke: rgba(47, 151, 198, 0.7); 670 | } 671 | 672 | .taskBoxSVG.focused .taskLayout{ 673 | stroke-width:3px; 674 | stroke: rgba(47, 151, 198, 0.7); 675 | } 676 | 677 | .taskBoxSVG.critical .taskLayout{ 678 | stroke-width:3px; 679 | stroke: rgba(255, 0, 0, 0.7); 680 | } 681 | 682 | 683 | 684 | /*--------------------------------------------------- RESOURCE ADD --------------------------------------------------*/ 685 | .ganttAddResource{ 686 | position: absolute; 687 | width: 660px; 688 | height: 300px; 689 | border: 1px solid red; 690 | background-color: white; 691 | box-shadow: 0 0 5px rgba(0,0,0,0.3); 692 | top:120px; 693 | left:70px; 694 | z-index: 200; 695 | padding: 10px; 696 | } 697 | 698 | .ganttAddResource tr.isCompany{ 699 | display:none; 700 | } 701 | 702 | .ganttAddResource.isCompany tr.isCompany{ 703 | display:table-row; 704 | } 705 | .ganttAddResource.isCompany tr.isPerson{ 706 | display:none; 707 | } 708 | .ganttAddResourceBG { 709 | position: absolute; 710 | width: 100%; 711 | height: 100%; 712 | top: 0; 713 | left: 0; 714 | background-color: rgba(0, 0, 0, .3); 715 | z-index: 200; 716 | } 717 | 718 | 719 | /*---------------------------------#LOG_CHANGES_CONTAINER --------------------------------------------*/ 720 | #LOG_CHANGES_CONTAINER{ 721 | display: none; 722 | width: 300px; 723 | top:-130px; 724 | margin-left: -35px 725 | } 726 | 727 | 728 | .userProfile { 729 | font-size: 16px; 730 | vertical-align: middle; 731 | text-align: right; 732 | margin: 0 5px 0 0; 733 | padding: 5px; 734 | float: right; 735 | position: relative; 736 | z-index: 50; 737 | line-height: 40px; 738 | vertical-align: middle; 739 | position: absolute; 740 | right: 0; 741 | } 742 | 743 | .userLine { 744 | max-width: 150px; 745 | display: inline-block; 746 | text-overflow: ellipsis; 747 | overflow: hidden; 748 | white-space: nowrap; 749 | margin: 0;padding: 0; 750 | vertical-align: middle; 751 | } 752 | 753 | .avatar { 754 | vertical-align: middle; 755 | padding: 1px; 756 | width: 27px; 757 | height: 27px; 758 | border: 1px solid #dedede 759 | } 760 | 761 | /*--------------------------------------------------- Media queries --------------------------------------------------*/ 762 | 763 | /* Large screens */ 764 | 765 | @media only screen and (max-width : 1260px) { 766 | 767 | .ganttButtonBar .button span.teamworkIcon { 768 | font-size: 130%; 769 | } 770 | .userLine { 771 | display: none; 772 | } 773 | 774 | } 775 | 776 | @media only screen and (min-width : 1261px) and (max-width : 1320px) { 777 | 778 | .ganttButtonBar .button span.teamworkIcon { 779 | font-size: 130%; 780 | } 781 | 782 | .button { 783 | font-size: 100%; 784 | padding: 3px 9px 6px; 785 | margin-right: 5px; 786 | margin-bottom: 5px 787 | } 788 | 789 | .userLine { 790 | display: none; 791 | } 792 | 793 | } 794 | 795 | @media only screen and (max-width : 1160px) { 796 | 797 | .userProfile { 798 | float: none; 799 | position: absolute; 800 | top:0; 801 | right: 10px; 802 | } 803 | 804 | .userProfile .teamworkIcon { 805 | color: rgb(255, 255, 255); 806 | } 807 | .userProfile .ganttButtonSeparator, .userProfile .avatar { 808 | border-color: rgb(127, 154, 170); 809 | } 810 | 811 | } 812 | 813 | /* Ipad */ 814 | 815 | @media only screen and (min-width: 768px) and (max-width: 1024px){ 816 | .ganttButtonSeparator { 817 | margin-left: 2px; 818 | padding-right: 6px; 819 | font-size: 100%; 820 | } 821 | .button { 822 | padding: 5px 6px 6px; 823 | } 824 | } 825 | 826 | /* Mobile TODO */ 827 | 828 | @media only screen and (max-width: 767px) { 829 | .button { 830 | font-size: 50%; 831 | } 832 | } 833 | -------------------------------------------------------------------------------- /libs/jquery/svg/jquery.svg.min.js: -------------------------------------------------------------------------------- 1 | /* http://keith-wood.name/svg.html 2 | SVG for jQuery v1.4.5. 3 | Written by Keith Wood (kbwood{at}iinet.com.au) August 2007. 4 | Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 5 | MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 6 | Please attribute the author if you use it. */ 7 | (function($){function SVGManager(){this._settings=[];this._extensions=[];this.regional=[];this.regional['']={errorLoadingText:'Error loading',notSupportedText:'This browser does not support SVG'};this.local=this.regional[''];this._uuid=new Date().getTime();this._renesis=detectActiveX('RenesisX.RenesisCtrl')}function detectActiveX(a){try{return!!(window.ActiveXObject&&new ActiveXObject(a))}catch(e){return false}}var q='svgwrapper';$.extend(SVGManager.prototype,{markerClassName:'hasSVG',svgNS:'http://www.w3.org/2000/svg',xlinkNS:'http://www.w3.org/1999/xlink',_wrapperClass:SVGWrapper,_attrNames:{class_:'class',in_:'in',alignmentBaseline:'alignment-baseline',baselineShift:'baseline-shift',clipPath:'clip-path',clipRule:'clip-rule',colorInterpolation:'color-interpolation',colorInterpolationFilters:'color-interpolation-filters',colorRendering:'color-rendering',dominantBaseline:'dominant-baseline',enableBackground:'enable-background',fillOpacity:'fill-opacity',fillRule:'fill-rule',floodColor:'flood-color',floodOpacity:'flood-opacity',fontFamily:'font-family',fontSize:'font-size',fontSizeAdjust:'font-size-adjust',fontStretch:'font-stretch',fontStyle:'font-style',fontVariant:'font-variant',fontWeight:'font-weight',glyphOrientationHorizontal:'glyph-orientation-horizontal',glyphOrientationVertical:'glyph-orientation-vertical',horizAdvX:'horiz-adv-x',horizOriginX:'horiz-origin-x',imageRendering:'image-rendering',letterSpacing:'letter-spacing',lightingColor:'lighting-color',markerEnd:'marker-end',markerMid:'marker-mid',markerStart:'marker-start',stopColor:'stop-color',stopOpacity:'stop-opacity',strikethroughPosition:'strikethrough-position',strikethroughThickness:'strikethrough-thickness',strokeDashArray:'stroke-dasharray',strokeDashOffset:'stroke-dashoffset',strokeLineCap:'stroke-linecap',strokeLineJoin:'stroke-linejoin',strokeMiterLimit:'stroke-miterlimit',strokeOpacity:'stroke-opacity',strokeWidth:'stroke-width',textAnchor:'text-anchor',textDecoration:'text-decoration',textRendering:'text-rendering',underlinePosition:'underline-position',underlineThickness:'underline-thickness',vertAdvY:'vert-adv-y',vertOriginY:'vert-origin-y',wordSpacing:'word-spacing',writingMode:'writing-mode'},_attachSVG:function(a,b){var c=(a.namespaceURI==this.svgNS?a:null);var a=(c?null:a);if($(a||c).hasClass(this.markerClassName)){return}if(typeof b=='string'){b={loadURL:b}}else if(typeof b=='function'){b={onLoad:b}}$(a||c).addClass(this.markerClassName);try{if(!c){c=document.createElementNS(this.svgNS,'svg');c.setAttribute('version','1.1');if(a.clientWidth>0){c.setAttribute('width',a.clientWidth)}if(a.clientHeight>0){c.setAttribute('height',a.clientHeight)}a.appendChild(c)}this._afterLoad(a,c,b||{})}catch(e){if($.browser.msie){if(!a.id){a.id='svg'+(this._uuid++)}this._settings[a.id]=b;a.innerHTML=''}else{a.innerHTML='

'+this.local.notSupportedText+'

'}}},_registerSVG:function(){for(var i=0;i=0;i--){var d=a.attributes.item(i);if(!(d.nodeName=='onload'||d.nodeName=='version'||d.nodeName.substring(0,5)=='xmlns')){a.attributes.removeNamedItem(d.nodeName)}}}for(var e in b){a.setAttribute($.svg._attrNames[e]||e,b[e])}return this},getElementById:function(a){return this._svg.ownerDocument.getElementById(a)},change:function(a,b){if(a){for(var c in b){if(b[c]==null){a.removeAttribute($.svg._attrNames[c]||c)}else{a.setAttribute($.svg._attrNames[c]||c,b[c])}}}return this},_args:function(b,c,d){c.splice(0,0,'parent');c.splice(c.length,0,'settings');var e={};var f=0;if(b[0]!=null&&b[0].jquery){b[0]=b[0][0]}if(b[0]!=null&&!(typeof b[0]=='object'&&b[0].nodeName)){e['parent']=null;f=1}for(var i=0;i'+d.styles+'')}return e},script:function(a,b,c,d){var e=this._args(arguments,['script','type'],['type']);var f=this._makeNode(e.parent,'script',$.extend({type:e.type||'text/javascript'},e.settings||{}));f.appendChild(this._svg.ownerDocument.createTextNode(e.script));if(!$.browser.mozilla){$.globalEval(e.script)}return f},linearGradient:function(a,b,c,d,e,f,g,h){var i=this._args(arguments,['id','stops','x1','y1','x2','y2'],['x1']);var j=$.extend({id:i.id},(i.x1!=null?{x1:i.x1,y1:i.y1,x2:i.x2,y2:i.y2}:{}));return this._gradient(i.parent,'linearGradient',$.extend(j,i.settings||{}),i.stops)},radialGradient:function(a,b,c,d,e,r,f,g,h){var i=this._args(arguments,['id','stops','cx','cy','r','fx','fy'],['cx']);var j=$.extend({id:i.id},(i.cx!=null?{cx:i.cx,cy:i.cy,r:i.r,fx:i.fx,fy:i.fy}:{}));return this._gradient(i.parent,'radialGradient',$.extend(j,i.settings||{}),i.stops)},_gradient:function(a,b,c,d){var e=this._makeNode(a,b,c);for(var i=0;i/g,'>'))}}}return b},_checkName:function(a){a=(a.substring(0,1)>='A'&&a.substring(0,1)<='Z'?a.toLowerCase():a);return(a.substring(0,4)=='svg:'?a.substring(4):a)},load:function(j,k){k=(typeof k=='boolean'?{addTo:k}:(typeof k=='function'?{onLoad:k}:(typeof k=='string'?{parent:k}:(typeof k=='object'&&k.nodeName?{parent:k}:(typeof k=='object'&&k.jquery?{parent:k}:k||{})))));if(!k.parent&&!k.addTo){this.clear(false)}var l=[this._svg.getAttribute('width'),this._svg.getAttribute('height')];var m=this;var n=function(a){a=$.svg.local.errorLoadingText+': '+a;if(k.onLoad){k.onLoad.apply(m._container||m._svg,[m,a])}else{m.text(null,10,20,a)}};var o=function(a){var b=new ActiveXObject('Microsoft.XMLDOM');b.validateOnParse=false;b.resolveExternals=false;b.async=false;b.loadXML(a);if(b.parseError.errorCode!=0){n(b.parseError.reason);return null}return b};var p=function(a){if(!a){return}if(a.documentElement.nodeName!='svg'){var b=a.getElementsByTagName('parsererror');var c=(b.length?b[0].getElementsByTagName('div'):[]);n(!b.length?'???':(c.length?c[0]:b[0]).firstChild.nodeValue);return}var d=(k.parent?$(k.parent)[0]:m._svg);var f={};for(var i=0;i'}else{b='<'+a.nodeName;if(a.attributes){for(var i=0;i';var d=a.firstChild;while(d){b+=this._toSVG(d);d=d.nextSibling}b+=''}else{b+='/>'}}return b}});function SVGPath(){this._path=''}$.extend(SVGPath.prototype,{reset:function(){this._path='';return this},move:function(x,y,a){a=(isArray(x)?y:a);return this._coords((a?'m':'M'),x,y)},line:function(x,y,a){a=(isArray(x)?y:a);return this._coords((a?'l':'L'),x,y)},horiz:function(x,a){this._path+=(a?'h':'H')+(isArray(x)?x.join(' '):x);return this},vert:function(y,a){this._path+=(a?'v':'V')+(isArray(y)?y.join(' '):y);return this},curveC:function(a,b,c,d,x,y,e){e=(isArray(a)?b:e);return this._coords((e?'c':'C'),a,b,c,d,x,y)},smoothC:function(a,b,x,y,c){c=(isArray(a)?b:c);return this._coords((c?'s':'S'),a,b,x,y)},curveQ:function(a,b,x,y,c){c=(isArray(a)?b:c);return this._coords((c?'q':'Q'),a,b,x,y)},smoothQ:function(x,y,a){a=(isArray(x)?y:a);return this._coords((a?'t':'T'),x,y)},_coords:function(a,b,c,d,e,f,g){if(isArray(b)){for(var i=0;i").addClass("gdfWrapper"); 32 | box.append(table); 33 | 34 | var head = table.clone(); 35 | head.addClass("table ganttFixHead"); 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:not(.gdfied)").mouseover(function () { 55 | $(this).addClass("gdfColHeaderOver"); 56 | 57 | }).on("mouseout.gdf", function () { 58 | $(this).removeClass("gdfColHeaderOver"); 59 | if (!$.gridify.columInResize) { 60 | $("body").removeClass("gdfHResizing"); 61 | } 62 | 63 | }).on("mousemove.gdf", function (e) { 64 | if (!$.gridify.columInResize) { 65 | var colHeader = $(this); 66 | var nextCol = colHeader.next(); 67 | if (nextCol.length > 0 && nextCol.width() < options.resizeZoneWidth) 68 | colHeader = nextCol; 69 | 70 | if (!colHeader.is(".gdfResizable")) 71 | return; 72 | 73 | var mousePos = e.pageX - colHeader.offset().left; 74 | 75 | if (colHeader.width() - mousePos < options.resizeZoneWidth) { 76 | $("body").addClass("gdfHResizing"); 77 | } else { 78 | $("body").removeClass("gdfHResizing"); 79 | } 80 | } 81 | 82 | }).on("mousedown.gdf", function (e) { 83 | //console.debug("mousedown.gdf") 84 | var colHeader = $(this); 85 | 86 | var nextCol = colHeader.next(); 87 | if (nextCol.length > 0 && nextCol.width() < options.resizeZoneWidth) 88 | colHeader = nextCol; 89 | 90 | if (!colHeader.is(".gdfResizable")) 91 | return; 92 | 93 | var mousePos = e.pageX - colHeader.offset().left; 94 | if (colHeader.width() - mousePos < options.resizeZoneWidth) { 95 | $("body").unselectable(); 96 | $.gridify.columInResize = colHeader; 97 | //on event for start resizing 98 | //console.debug("start resizing"); 99 | $(document).on("mousemove.gdf", function (e) { 100 | 101 | e.preventDefault(); 102 | $("body").addClass("gdfHResizing"); 103 | 104 | //manage resizing 105 | var w = e.pageX - $.gridify.columInResize.offset().left; 106 | w = w <= 1 ? 1 : w; 107 | $.gridify.columInResize.width(w); 108 | $.gridify.columInResize.data("fTh").width(w); 109 | 110 | 111 | //on mouse up on body to stop resizing 112 | }).on("mouseup.gdf", function () { 113 | //console.debug("mouseup.gdf") 114 | 115 | //$("body").css({cursor: "auto"}); 116 | 117 | $(this).off("mousemove.gdf").off("mouseup.gdf").clearUnselectable(); 118 | $("body").removeClass("gdfHResizing"); 119 | delete $.gridify.columInResize; 120 | 121 | //save columns dimension 122 | storeGridState(); 123 | 124 | }); 125 | } 126 | 127 | }).on("dblclick.gdf", function () { 128 | //console.debug("dblclick.gdf") 129 | var col = $(this); 130 | 131 | if (!col.is(".gdfResizable")) 132 | return; 133 | 134 | var idx = $("th", col.parents("table")).index(col); 135 | var columnTd = $("td:nth-child(" + (idx + 1) + ")", table); 136 | var w = 0; 137 | columnTd.each(function () { 138 | var td = $(this); 139 | var content = td.children("input").length ? td.children("input").val() : td.html(); 140 | var tmp = $("
").addClass("columnWidthTest").html(content).css({position: "absolute"}); 141 | $("body").append(tmp); 142 | w = Math.max(w, tmp.width() + parseFloat(td.css("padding-left"))); 143 | tmp.remove(); 144 | }); 145 | 146 | w = w + 5; 147 | col.width(w); 148 | col.data("fTh").width(w); 149 | 150 | //save columns dimension 151 | storeGridState(); 152 | return false; 153 | 154 | }).addClass("gdfied unselectable").attr("unselectable", "true"); 155 | 156 | 157 | function storeGridState() { 158 | //console.debug("storeGridState"); 159 | if (localStorage) { 160 | var gridState = {}; 161 | 162 | var colSizes = []; 163 | $(".gdfTable .gdfColHeader").each(function () { 164 | colSizes.push($(this).outerWidth()); 165 | }); 166 | 167 | gridState.colSizes = colSizes; 168 | 169 | localStorage.setObject("TWPGanttGridState", gridState); 170 | //console.debug("gridState",localStorage.getItem("TWPGanttGridState")); 171 | } 172 | } 173 | 174 | function loadGridState() { 175 | //console.debug("loadGridState") 176 | if (localStorage) { 177 | if (localStorage.getObject("TWPGanttGridState")) { 178 | var gridState = localStorage.getObject("TWPGanttGridState"); 179 | if (gridState.colSizes) { 180 | box.find(".gdfTable .gdfColHeader").each(function (i) { 181 | $(this).width(gridState.colSizes[i]); 182 | }); 183 | } 184 | } 185 | } 186 | } 187 | 188 | loadGridState(); 189 | return box; 190 | }; 191 | 192 | 193 | 194 | 195 | $.splittify = { 196 | init: function (where, first, second, perc) { 197 | 198 | //perc = perc || 50; 199 | 200 | var element = $("
").addClass("splitterContainer"); 201 | var firstBox = $("
").addClass("splitElement splitBox1"); 202 | var splitterBar = $("
").addClass("splitElement vSplitBar").attr("unselectable", "on").css("padding-top", where.height() / 2 + "px"); 203 | var secondBox = $("
").addClass("splitElement splitBox2"); 204 | 205 | 206 | var splitter = new Splitter(element, firstBox, secondBox, splitterBar); 207 | splitter.perc = perc; 208 | 209 | //override with saved one 210 | loadPosition(); 211 | 212 | var toLeft = $("
").addClass("toLeft").html("{").click(function () {splitter.resize(0.001, 300);}); 213 | splitterBar.append(toLeft); 214 | 215 | var toCenter = $("
").addClass("toCenter").html("©").click(function () {splitter.resize(50, 300);}); 216 | splitterBar.append(toCenter); 217 | 218 | var toRight = $("
").addClass("toRight").html("}").click(function () {splitter.resize(99.9999, 300);}); 219 | splitterBar.append(toRight); 220 | 221 | 222 | firstBox.append(first); 223 | secondBox.append(second); 224 | 225 | element.append(firstBox).append(secondBox).append(splitterBar); 226 | 227 | where.append(element); 228 | 229 | var totalW = where.innerWidth(); 230 | var splW = splitterBar.width(); 231 | var fbw = totalW * perc / 100 - splW; 232 | //var realW = firstBox.get(0).scrollWidth; 233 | //fbw = fbw > realW? realW: fbw; 234 | fbw = fbw > totalW - splW - splitter.secondBoxMinWidth ? totalW - splW - splitter.secondBoxMinWidth : fbw; 235 | firstBox.width(fbw).css({left: 0}); 236 | splitterBar.css({left: firstBox.width()}); 237 | secondBox.width(totalW - fbw - splW).css({left: firstBox.width() + splW}); 238 | 239 | splitterBar.on("mousedown.gdf", function (e) { 240 | 241 | e.preventDefault(); 242 | $("body").addClass("gdfHResizing"); 243 | 244 | $.splittify.splitterBar = $(this); 245 | //on event for start resizing 246 | //console.debug("start splitting"); 247 | //var realW = firstBox.get(0).scrollWidth; 248 | $("body").unselectable().on("mousemove.gdf", function (e) { 249 | //manage resizing 250 | //console.debug(e.pageX - $.gridify.columInResize.offset().left) 251 | 252 | e.preventDefault(); 253 | 254 | var sb = $.splittify.splitterBar; 255 | var pos = e.pageX - sb.parent().offset().left; 256 | var w = sb.parent().width(); 257 | var fbw = firstBox; 258 | 259 | pos = pos > splitter.firstBoxMinWidth ? pos : splitter.firstBoxMinWidth; 260 | //pos = pos < realW - 10 ? pos : realW - 10; 261 | pos = pos > totalW - splW - splitter.secondBoxMinWidth ? totalW - splW - splitter.secondBoxMinWidth : pos; 262 | sb.css({left: pos}); 263 | firstBox.width(pos); 264 | secondBox.css({left: pos + sb.width(), width: w - pos - sb.width()}); 265 | splitter.perc = (firstBox.width() / splitter.element.width()) * 100; 266 | 267 | //on mouse up on body to stop resizing 268 | }).on("mouseup.gdf", function () { 269 | //console.debug("stop splitting"); 270 | $(this).off("mousemove.gdf").off("mouseup.gdf").clearUnselectable(); 271 | delete $.splittify.splitterBar; 272 | 273 | $("body").removeClass("gdfHResizing"); 274 | 275 | storePosition(); 276 | }); 277 | }); 278 | 279 | 280 | // keep both side in synch when scroll 281 | var stopScroll = false; 282 | var fs = firstBox.add(secondBox); 283 | fs.scroll(function (e) { 284 | var el = $(this); 285 | var top = el.scrollTop(); 286 | 287 | var firstBoxHeader = firstBox.find(".ganttFixHead"); 288 | var secondBoxHeader = secondBox.find(".ganttFixHead"); 289 | 290 | if (el.is(".splitBox1") && stopScroll != "splitBox2") { 291 | stopScroll = "splitBox1"; 292 | secondBox.scrollTop(top); 293 | } else if (el.is(".splitBox2") && stopScroll != "splitBox1") { 294 | stopScroll = "splitBox2"; 295 | firstBox.scrollTop(top); 296 | } 297 | 298 | firstBoxHeader.css('top', top).hide(); 299 | secondBoxHeader.css('top', top).hide(); 300 | 301 | where.stopTime("reset").oneTime(100, "reset", function () { 302 | 303 | stopScroll = ""; 304 | top = el.scrollTop(); 305 | 306 | firstBoxHeader.css('top', top).fadeIn(); 307 | secondBoxHeader.css('top', top).fadeIn(); 308 | 309 | }); 310 | 311 | }); 312 | 313 | 314 | firstBox.on('mousewheel MozMousePixelScroll', function (event) { 315 | 316 | event.preventDefault(); 317 | 318 | var deltaY = event.originalEvent.wheelDeltaY; 319 | if(!deltaY) 320 | deltaY=event.originalEvent.wheelDelta; 321 | 322 | var deltaX = event.originalEvent.wheelDeltaX; 323 | 324 | if (event.originalEvent.axis) { 325 | deltaY = event.originalEvent.axis == 2 ? -event.originalEvent.detail : null; 326 | deltaX = event.originalEvent.axis == 1 ? -event.originalEvent.detail : null; 327 | } 328 | 329 | deltaY = Math.abs(deltaY) < 40 ? 40 * (Math.abs(deltaY) / deltaY) : deltaY; 330 | deltaX = Math.abs(deltaX) < 40 ? 40 * (Math.abs(deltaX) / deltaX) : deltaX; 331 | 332 | var scrollToY = secondBox.scrollTop() - deltaY; 333 | var scrollToX = firstBox.scrollLeft() - deltaX; 334 | 335 | // console.debug( firstBox.scrollLeft(), Math.abs(deltaX), Math.abs(deltaY)); 336 | 337 | if (deltaY) secondBox.scrollTop(scrollToY); 338 | if (deltaX) firstBox.scrollLeft(scrollToX); 339 | 340 | return false; 341 | }); 342 | 343 | 344 | function Splitter(element, firstBox, secondBox, splitterBar) { 345 | this.element = element; 346 | this.firstBox = firstBox; 347 | this.secondBox = secondBox; 348 | this.splitterBar = splitterBar; 349 | this.perc = 0; 350 | this.firstBoxMinWidth = 0; 351 | this.secondBoxMinWidth = 30; 352 | 353 | this.resize = function (newPerc, anim) { 354 | var animTime = anim ? anim : 0; 355 | this.perc = newPerc ? newPerc : this.perc; 356 | var totalW = this.element.width(); 357 | var splW = this.splitterBar.width(); 358 | var newW = totalW * this.perc / 100; 359 | newW = newW > this.firstBoxMinWidth ? newW : this.firstBoxMinWidth; 360 | newW = newW > totalW - splW - splitter.secondBoxMinWidth ? totalW - splW - splitter.secondBoxMinWidth : newW; 361 | this.firstBox.animate({width: newW}, animTime, function () {$(this).css("overflow-x", "auto")}); 362 | this.splitterBar.animate({left: newW}, animTime); 363 | this.secondBox.animate({left: newW + this.splitterBar.width(), width: totalW - newW - splW}, animTime, function () {$(this).css("overflow", "auto")}); 364 | 365 | storePosition(); 366 | }; 367 | 368 | var self = this; 369 | this.splitterBar.on("dblclick", function () { 370 | self.resize(50, true); 371 | }) 372 | } 373 | 374 | 375 | function storePosition () { 376 | //console.debug("storePosition",splitter.perc); 377 | if (localStorage) { 378 | localStorage.setItem("TWPGanttSplitPos",splitter.perc); 379 | } 380 | } 381 | 382 | function loadPosition () { 383 | //console.debug("loadPosition"); 384 | if (localStorage) { 385 | if (localStorage.getItem("TWPGanttSplitPos")) { 386 | splitter.perc=parseFloat(localStorage.getItem("TWPGanttSplitPos")); 387 | } 388 | } 389 | } 390 | 391 | 392 | 393 | return splitter; 394 | } 395 | 396 | }; 397 | 398 | 399 | //<%------------------------------------------------------------------------ UTILITIES ---------------------------------------------------------------%> 400 | function computeStart(start) { 401 | return computeStartDate(start).getTime(); 402 | } 403 | function computeStartDate(start) { 404 | var d = new Date(start + 3600000 * 12); 405 | d.setHours(0, 0, 0, 0); 406 | //move to next working day 407 | while (isHoliday(d)) { 408 | d.setDate(d.getDate() + 1); 409 | } 410 | d.setHours(0, 0, 0, 0); 411 | return d; 412 | } 413 | 414 | function computeEnd(end) { 415 | return computeEndDate(end).getTime() 416 | } 417 | function computeEndDate(end) { 418 | var d = new Date(end - 3600000 * 12); 419 | d.setHours(23, 59, 59, 999); 420 | //move to next working day 421 | while (isHoliday(d)) { 422 | d.setDate(d.getDate() + 1); 423 | } 424 | d.setHours(23, 59, 59, 999); 425 | return d; 426 | } 427 | 428 | function computeEndByDuration(start, duration) { 429 | var d = new Date(start); 430 | //console.debug("computeEndByDuration start ",d,duration) 431 | var q = duration - 1; 432 | while (q > 0) { 433 | d.setDate(d.getDate() + 1); 434 | if (!isHoliday(d)) 435 | q--; 436 | } 437 | d.setHours(23, 59, 59, 999); 438 | return d.getTime(); 439 | } 440 | 441 | 442 | function incrementDateByWorkingDays(date, days) { 443 | var d = new Date(date); 444 | d.incrementDateByWorkingDays(days); 445 | return d.getTime(); 446 | } 447 | 448 | 449 | function recomputeDuration(start, end) { 450 | //console.debug("recomputeDuration"); 451 | return new Date(start).distanceInWorkingDays(new Date(end)) + 1; 452 | } 453 | 454 | 455 | function resynchDates(leavingField, startField, startMilesField, durationField, endField, endMilesField) { 456 | //console.debug("resynchDates",leavingField.prop("name"), startField.prop("name"), startMilesField.prop("name"), durationField.prop("name"), endField.prop("name"), endMilesField.prop("name")); 457 | function resynchDatesSetFields(command) { 458 | //console.debug("resynchDatesSetFields",command); 459 | //var duration = parseInt(durationField.val()); 460 | var duration = daysFromString(durationField.val(), true); 461 | if (!duration || duration < 1) 462 | duration = 1; 463 | 464 | var start = computeStart(Date.parseString(startField.val()).getTime()); 465 | 466 | var end = endField.val(); 467 | if (end.length > 0) { 468 | end = Date.parseString(end); 469 | end.setHours(23, 59, 59, 999); 470 | end = computeEnd(end.getTime()); 471 | } 472 | 473 | var date = new Date(); 474 | if ("CHANGE_END" == command) { 475 | date.setTime(start); 476 | var workingDays = duration - 1; 477 | date.incrementDateByWorkingDays(workingDays); 478 | date.setHours(23, 59, 59, 999); 479 | end = computeEnd(date.getTime()); 480 | } else if ("CHANGE_START" == command) { 481 | date.setTime(end); 482 | var workingDays = duration - 1; 483 | date.incrementDateByWorkingDays(-workingDays); 484 | date.setHours(0, 0, 0, 0); 485 | start = computeStart(date.getTime()); 486 | } else if ("CHANGE_DURATION" == command) { 487 | //console.debug("CHANGE_DURATION",new Date(start),new Date(end)) 488 | duration = new Date(start).distanceInWorkingDays(new Date(end)) + 1; 489 | } 490 | 491 | startField.val(new Date(start).format()); 492 | endField.val(new Date(end).format()); 493 | durationField.val(duration); 494 | 495 | return {start: start, end: end, duration: duration}; 496 | } 497 | 498 | var leavingFieldName = leavingField.prop("name"); 499 | var durIsFilled = durationField.val().length > 0; 500 | var startIsFilled = startField.val().length > 0; 501 | var endIsFilled = endField.val().length > 0; 502 | var startIsMilesAndFilled = startIsFilled && (startMilesField.prop("checked") || startField.is("[readOnly]")); 503 | var endIsMilesAndFilled = endIsFilled && (endMilesField.prop("checked") || endField.is("[readOnly]")); 504 | 505 | if (durIsFilled) { 506 | if (parseInt(durationField.val()) == NaN || parseInt(durationField.val()) < 1) 507 | durationField.val(1); 508 | } 509 | 510 | if (leavingFieldName.indexOf("Milestone") > 0) { 511 | if (startIsMilesAndFilled && endIsMilesAndFilled) { 512 | durationField.prop("readOnly", true); 513 | } else { 514 | durationField.prop("readOnly", false); 515 | } 516 | return; 517 | } 518 | 519 | //need at least two values to resynch the third 520 | if ((durIsFilled ? 1 : 0) + (startIsFilled ? 1 : 0) + (endIsFilled ? 1 : 0) < 2) 521 | return; 522 | 523 | var ret; 524 | if (leavingFieldName == 'start' && startIsFilled) { 525 | if (endIsMilesAndFilled && durIsFilled) { 526 | ret = resynchDatesSetFields("CHANGE_DURATION"); 527 | } else if (durIsFilled) { 528 | ret = resynchDatesSetFields("CHANGE_END"); 529 | } 530 | 531 | } else if (leavingFieldName == 'duration' && durIsFilled && !(endIsMilesAndFilled && startIsMilesAndFilled)) { 532 | if (endIsMilesAndFilled && !startIsMilesAndFilled) { 533 | ret = resynchDatesSetFields("CHANGE_START"); 534 | } else if (!endIsMilesAndFilled) { 535 | //document.title=('go and change end!!'); 536 | ret = resynchDatesSetFields("CHANGE_END"); 537 | } 538 | 539 | } else if (leavingFieldName == 'end' && endIsFilled) { 540 | ret = resynchDatesSetFields("CHANGE_DURATION"); 541 | } 542 | return ret; 543 | } 544 | 545 | 546 | //This prototype is provided by the Mozilla foundation and 547 | //is distributed under the MIT license. 548 | //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license 549 | 550 | if (!Array.prototype.filter) { 551 | Array.prototype.filter = function (fun) { 552 | var len = this.length; 553 | if (typeof fun != "function") 554 | throw new TypeError(); 555 | 556 | var res = new Array(); 557 | var thisp = arguments[1]; 558 | for (var i = 0; i < len; i++) { 559 | if (i in this) { 560 | var val = this[i]; // in case fun mutates this 561 | if (fun.call(thisp, val, i, this)) 562 | res.push(val); 563 | } 564 | } 565 | return res; 566 | }; 567 | } 568 | 569 | 570 | function goToPage(url) { 571 | if (!canILeave()) return; 572 | window.location.href = url; 573 | } 574 | -------------------------------------------------------------------------------- /libs/forms.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2017 Open Lab 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | var muteAlertOnChange = false; 24 | 25 | 26 | // isRequired ---------------------------------------------------------------------------- 27 | 28 | //return true if every mandatory field is filled and highlight empty ones 29 | jQuery.fn.isFullfilled = function () { 30 | var canSubmit = true; 31 | var firstErrorElement = ""; 32 | 33 | this.each(function () { 34 | var theElement = $(this); 35 | theElement.removeClass("formElementsError"); 36 | //if (theElement.val().trim().length == 0 || theElement.attr("invalid") == "true") { //robicch 13/2/15 37 | if (theElement.is("[required]") && theElement.val().trim().length == 0 || theElement.attr("invalid") == "true") { 38 | if (theElement.attr("type") == "hidden") { 39 | theElement = theElement.prevAll("#" + theElement.prop("id") + "_txt:first"); 40 | } else if (theElement.is("[withTinyMCE]")){ 41 | if (tinymce.activeEditor.getContent()=="") 42 | theElement=$("#"+theElement.attr("name")+"_tbl"); 43 | else 44 | return true;// in order to continue the loop 45 | } 46 | theElement.addClass("formElementsError"); 47 | canSubmit = false; 48 | 49 | if (firstErrorElement == "") 50 | firstErrorElement = theElement; 51 | } 52 | }); 53 | 54 | if (!canSubmit) { 55 | // get the tabdiv 56 | var theTabDiv = firstErrorElement.closest(".tabBox"); 57 | if (theTabDiv.length > 0) 58 | clickTab(theTabDiv.attr("tabId")); 59 | 60 | // highlight element 61 | firstErrorElement.effect("highlight", { color:"red" }, 1500); 62 | } 63 | return canSubmit; 64 | 65 | }; 66 | 67 | function canSubmitForm(formOrId) { 68 | //console.debug("canSubmitForm",formOrId); 69 | if (typeof formOrId != "object") 70 | formOrId=$("#" + formOrId); 71 | return formOrId.find(":input[required],:input[invalid=true]").isFullfilled(); 72 | } 73 | 74 | function showSavingMessage() { 75 | $("#savingMessage:hidden").fadeIn(); 76 | $("body").addClass("waiting"); 77 | $(window).resize(); 78 | } 79 | function hideSavingMessage() { 80 | $("#savingMessage:visible").fadeOut(); 81 | $("body").removeClass("waiting"); 82 | $(window).resize(); 83 | } 84 | 85 | 86 | 87 | /* Types Function */ 88 | 89 | function isValidURL(url) { 90 | var RegExp = /^(([\w]+:)?\/\/)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$/; 91 | return RegExp.test(url); 92 | } 93 | 94 | function isValidEmail(email) { 95 | //var RegExp = /^((([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+(\.([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+)*)@((((([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.))*([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.)[\w]{2,4}|(((([0-9]){1,3}\.){3}([0-9]){1,3}))|(\[((([0-9]){1,3}\.){3}([0-9]){1,3})\])))$/; 96 | var RegExp = /^.+@\S+\.\S+$/; 97 | return RegExp.test(email); 98 | } 99 | 100 | function isValidInteger(n) { 101 | reg = new RegExp("^[-+]{0,1}[0-9]*$"); 102 | return reg.test(n) || isNumericExpression(n); 103 | } 104 | 105 | function isValidDouble(n) { 106 | var sep = Number.decimalSeparator; 107 | reg = new RegExp("^[-+]{0,1}[0-9]*[" + sep + "]{0,1}[0-9]*$"); 108 | return reg.test(n) || isNumericExpression(n); 109 | } 110 | 111 | function isValidTime(n) { 112 | return !isNaN(millisFromHourMinute(n)); 113 | } 114 | 115 | function isValidDurationDays(n) { 116 | return !isNaN(daysFromString(n)); 117 | } 118 | 119 | function isValidDurationMillis(n) { 120 | return !isNaN(millisFromString(n)); 121 | } 122 | 123 | function isNumericExpression(expr) { 124 | try { 125 | var a = eval(expr); 126 | return typeof(a) == 'number'; 127 | } catch (t) { 128 | return false; 129 | } 130 | 131 | } 132 | 133 | function getNumericExpression(expr) { 134 | var ret; 135 | try { 136 | var a = eval(expr); 137 | if (typeof(a) == 'number') 138 | ret = a; 139 | } catch (t) { 140 | } 141 | return ret; 142 | 143 | } 144 | 145 | /* 146 | supports almost all Java currency format e.g.: ###,##0.00EUR €#,###.00 #,###.00€ -$#,###.00 $-#,###.00 147 | */ 148 | function isValidCurrency(numStr) { 149 | //first try to convert format in a regex 150 | var regex = ""; 151 | var format = Number.currencyFormat + ""; 152 | 153 | var minusFound = false; 154 | var numFound = false; 155 | var currencyString = ""; 156 | var numberRegex = "[0-9\\" + Number.groupingSeparator + "]+[\\" + Number.decimalSeparator + "]?[0-9]*"; 157 | 158 | for (var i = 0; i < format.length; i++) { 159 | var ch = format.charAt(i); 160 | 161 | if (ch == "." || ch == "," || ch == "0") { 162 | //skip it 163 | if (currencyString != "") { 164 | regex = regex + "(?:" + RegExp.quote(currencyString) + ")?"; 165 | currencyString = ""; 166 | } 167 | 168 | } else if (ch == "#") { 169 | if (currencyString != "") { 170 | regex = regex + "(?:" + RegExp.quote(currencyString) + ")?"; 171 | currencyString = ""; 172 | } 173 | 174 | if (!numFound) { 175 | numFound = true; 176 | regex = regex + numberRegex; 177 | } 178 | 179 | } else if (ch == "-") { 180 | if (currencyString != "") { 181 | regex = regex + "(?:" + RegExp.quote(currencyString) + ")?"; 182 | currencyString = ""; 183 | } 184 | if (!minusFound) { 185 | minusFound = true; 186 | regex = regex + "[-]?"; 187 | } 188 | 189 | } else { 190 | currencyString = currencyString + ch; 191 | } 192 | } 193 | if (!minusFound) 194 | regex = "[-]?" + regex; 195 | 196 | if (currencyString != "") 197 | regex = regex + "(?:" + RegExp.quote(currencyString) + ")?"; 198 | 199 | regex = "^" + regex + "$"; 200 | 201 | var rg = new RegExp(regex); 202 | return rg.test(numStr) || isNumericExpression(numStr); 203 | } 204 | 205 | function getCurrencyValue(numStr) { 206 | if (!isValidCurrency(numStr)) 207 | return NaN; 208 | 209 | var ripul = numStr.replaceAll(Number.groupingSeparator, "").replaceAll(Number.decimalSeparator, "."); 210 | return getNumericExpression(ripul) || parseFloat(ripul.replace(/[^-0123456789.]/, "")); 211 | } 212 | 213 | 214 | function formatCurrency(numberString) { 215 | return formatNumber(numberString, Number.currencyFormat); 216 | } 217 | 218 | 219 | function formatNumber(numberString, format) { 220 | if (!format) 221 | format = "##0.00"; 222 | 223 | var dec = Number.decimalSeparator; 224 | var group = Number.groupingSeparator; 225 | var neg = Number.minusSign; 226 | 227 | var round = true; 228 | 229 | var validFormat = "0#-,."; 230 | 231 | // strip all the invalid characters at the beginning and the end 232 | // of the format, and we'll stick them back on at the end 233 | // make a special case for the negative sign "-" though, so 234 | // we can have formats like -$23.32 235 | var prefix = ""; 236 | var negativeInFront = false; 237 | for (var i = 0; i < format.length; i++) { 238 | if (validFormat.indexOf(format.charAt(i)) == -1) { 239 | prefix = prefix + format.charAt(i); 240 | } else { 241 | if (i == 0 && format.charAt(i) == '-') { 242 | negativeInFront = true; 243 | } else { 244 | break; 245 | } 246 | } 247 | } 248 | var suffix = ""; 249 | for (var i = format.length - 1; i >= 0; i--) { 250 | if (validFormat.indexOf(format.charAt(i)) == -1) 251 | suffix = format.charAt(i) + suffix; 252 | else 253 | break; 254 | } 255 | 256 | format = format.substring(prefix.length); 257 | format = format.substring(0, format.length - suffix.length); 258 | 259 | // now we need to convert it into a number 260 | //while (numberString.indexOf(group) > -1) 261 | // numberString = numberString.replace(group, ''); 262 | //var number = new Number(numberString.replace(dec, ".").replace(neg, "-")); 263 | var number = new Number(numberString); 264 | 265 | 266 | var forcedToZero = false; 267 | if (isNaN(number)) { 268 | number = 0; 269 | forcedToZero = true; 270 | } 271 | 272 | // special case for percentages 273 | if (suffix == "%") 274 | number = number * 100; 275 | 276 | var returnString = ""; 277 | if (format.indexOf(".") > -1) { 278 | var decimalPortion = dec; 279 | var decimalFormat = format.substring(format.lastIndexOf(".") + 1); 280 | 281 | // round or truncate number as needed 282 | if (round) 283 | number = new Number(number.toFixed(decimalFormat.length)); 284 | else { 285 | var numStr = number.toString(); 286 | numStr = numStr.substring(0, numStr.lastIndexOf('.') + decimalFormat.length + 1); 287 | number = new Number(numStr); 288 | } 289 | 290 | var decimalValue = number % 1; 291 | var decimalString = new String(decimalValue.toFixed(decimalFormat.length)); 292 | decimalString = decimalString.substring(decimalString.lastIndexOf(".") + 1); 293 | 294 | for (var i = 0; i < decimalFormat.length; i++) { 295 | if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) != '0') { 296 | decimalPortion += decimalString.charAt(i); 297 | } else if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) == '0') { 298 | var notParsed = decimalString.substring(i); 299 | if (notParsed.match('[1-9]')) { 300 | decimalPortion += decimalString.charAt(i); 301 | } else { 302 | break; 303 | } 304 | } else if (decimalFormat.charAt(i) == "0") { 305 | decimalPortion += decimalString.charAt(i); 306 | } 307 | } 308 | returnString += decimalPortion; 309 | } else { 310 | number = Math.round(number); 311 | } 312 | var ones = Math.floor(number); 313 | if (number < 0) 314 | ones = Math.ceil(number); 315 | 316 | var onesFormat = ""; 317 | if (format.indexOf(".") == -1) 318 | onesFormat = format; 319 | else 320 | onesFormat = format.substring(0, format.indexOf(".")); 321 | 322 | var onePortion = ""; 323 | if (!(ones == 0 && onesFormat.substr(onesFormat.length - 1) == '#') || forcedToZero) { 324 | // find how many digits are in the group 325 | var oneText = new String(Math.abs(ones)); 326 | var groupLength = 9999; 327 | if (onesFormat.lastIndexOf(",") != -1) 328 | groupLength = onesFormat.length - onesFormat.lastIndexOf(",") - 1; 329 | var groupCount = 0; 330 | for (var i = oneText.length - 1; i > -1; i--) { 331 | onePortion = oneText.charAt(i) + onePortion; 332 | groupCount++; 333 | if (groupCount == groupLength && i != 0) { 334 | onePortion = group + onePortion; 335 | groupCount = 0; 336 | } 337 | } 338 | 339 | // account for any pre-data padding 340 | if (onesFormat.length > onePortion.length) { 341 | var padStart = onesFormat.indexOf('0'); 342 | if (padStart != -1) { 343 | var padLen = onesFormat.length - padStart; 344 | 345 | // pad to left with 0's or group char 346 | var pos = onesFormat.length - onePortion.length - 1; 347 | while (onePortion.length < padLen) { 348 | var padChar = onesFormat.charAt(pos); 349 | // replace with real group char if needed 350 | if (padChar == ',') 351 | padChar = group; 352 | onePortion = padChar + onePortion; 353 | pos--; 354 | } 355 | } 356 | } 357 | } 358 | 359 | if (!onePortion && onesFormat.indexOf('0', onesFormat.length - 1) !== -1) 360 | onePortion = '0'; 361 | 362 | returnString = onePortion + returnString; 363 | 364 | // handle special case where negative is in front of the invalid characters 365 | if (number < 0 && negativeInFront && prefix.length > 0) 366 | prefix = neg + prefix; 367 | else if (number < 0) 368 | returnString = neg + returnString; 369 | 370 | if (returnString.lastIndexOf(dec) == returnString.length - 1) { 371 | returnString = returnString.substring(0, returnString.length - 1); 372 | } 373 | returnString = prefix + returnString + suffix; 374 | return returnString; 375 | } 376 | 377 | 378 | //validation functions - used by textfield and datefield 379 | jQuery.fn.validateField = function () { 380 | var isValid = true; 381 | 382 | this.each(function () { 383 | var el = $(this); 384 | el.clearErrorAlert(); 385 | 386 | var value = el.val(); 387 | if (value) { 388 | var rett = true; 389 | var type = (el.attr('entryType')+"").toUpperCase(); 390 | var errParam; 391 | 392 | if (type == "INTEGER") { 393 | rett = isValidInteger(value); 394 | } else if (type == "DOUBLE") { 395 | rett = isValidDouble(value); 396 | } else if (type == "PERCENTILE") { 397 | rett = isValidDouble(value); 398 | } else if (type == "URL") { 399 | rett = isValidURL(value); 400 | } else if (type == "EMAIL") { 401 | rett = isValidEmail(value); 402 | } else if (type == "DURATIONMILLIS") { 403 | rett = isValidDurationMillis(value); 404 | } else if (type == "DURATIONDAYS") { 405 | rett = isValidDurationDays(value); 406 | } else if (type == "DATE") { 407 | rett = Date.isValid(value, el.attr("format"), true); 408 | if (!rett) 409 | errParam = el.attr("format"); 410 | } else if (type == "TIME") { 411 | rett = isValidTime(value); 412 | } else if (type == "CURRENCY") { 413 | rett = isValidCurrency(value); 414 | } 415 | 416 | if (!rett) { 417 | el.createErrorAlert(i18n.ERROR_ON_FIELD, i18n.INVALID_DATA + (errParam ? " " + errParam : "")); 418 | isValid=false; 419 | } 420 | 421 | 422 | //check limits minValue : maxValue 423 | if (rett && (el.attr("minValue") || el.attr("maxValue"))){ 424 | var val=value; 425 | var min=el.attr("minValue"); 426 | var max=el.attr("maxValue"); 427 | if (type == "INTEGER") { 428 | val=parseInt(value); 429 | min=parseInt(min); 430 | max=parseInt(max); 431 | } else if (type == "DOUBLE" || type == "PERCENTILE") { 432 | val=parseDouble(value); 433 | min=parseDouble(min); 434 | max=parseDouble(max); 435 | } else if (type == "URL") { 436 | val=value; 437 | } else if (type == "EMAIL") { 438 | val=value; 439 | } else if (type == "DURATIONMILLIS") { 440 | val=millisFromString(value); 441 | min=millisFromString(min); 442 | max=millisFromString(max); 443 | 444 | } else if (type == "DURATIONDAYS") { 445 | val=daysFromString(value); 446 | min=daysFromString(min); 447 | max=daysFromString(max); 448 | } else if (type == "DATE") { 449 | val=Date.parseString(value, el.attr("format"),true).getTime(); 450 | min=Date.parseString(min, el.attr("format"),true).getTime(); 451 | max=Date.parseString(max, el.attr("format"),true).getTime(); 452 | } else if (type == "TIME") { 453 | val = millisFromHourMinute(value); 454 | min = millisFromHourMinute(min); 455 | max = millisFromHourMinute(max); 456 | } else if (type == "CURRENCY") { 457 | val=getCurrencyValue(value); 458 | min=getCurrencyValue(min); 459 | max=getCurrencyValue(max); 460 | } 461 | 462 | if (el.attr("minValue") && valmax){ 471 | el.createErrorAlert(i18n.ERROR_ON_FIELD, i18n.OUT_OF_BOUDARIES + " ("+(el.attr("minValue")?el.attr("minValue"):"--")+" : "+el.attr("maxValue")+")"); 472 | rett=false; 473 | isValid=false; 474 | } 475 | 476 | } 477 | 478 | } 479 | 480 | }); 481 | 482 | return isValid; 483 | }; 484 | 485 | jQuery.fn.clearErrorAlert = function () { 486 | this.each(function () { 487 | var el = $(this); 488 | el.removeAttr("invalid").removeClass("formElementsError"); 489 | $("#" + el.prop("id") + "error").remove(); 490 | }); 491 | return this; 492 | }; 493 | 494 | jQuery.fn.createErrorAlert = function (errorCode, message) { 495 | this.each(function () { 496 | var el = $(this); 497 | el.attr("invalid", "true").addClass("formElementsError"); 498 | if ($("#" + el.prop("id") + "error").length <= 0) { 499 | var errMess = (errorCode ? errorCode : "") + ": " + (message ? message : ""); 500 | var err = " "; 502 | err += "\n"; 503 | err = $(err); 504 | err.prop("title", errMess); 505 | el.after(err); 506 | } 507 | }); 508 | return this; 509 | }; 510 | 511 | 512 | // button submit support BEGIN ------------------ 513 | 514 | function saveFormValues(idForm) { 515 | var formx = obj(idForm); 516 | formx.setAttribute("savedAction", formx.action); 517 | formx.setAttribute("savedTarget", formx.target); 518 | var el = formx.elements; 519 | for (i = 0; i < el.length; i++) { 520 | if (el[i].getAttribute("savedValue") != null) { 521 | el[i].setAttribute("savedValue", el[i].value); 522 | } 523 | } 524 | } 525 | 526 | function restoreFormValues(idForm) { 527 | var formx = obj(idForm); 528 | formx.action = formx.getAttribute("savedAction"); 529 | formx.target = formx.getAttribute("savedTarget"); 530 | var el = formx.elements; 531 | for (i = 0; i < el.length; i++) { 532 | if (el[i].getAttribute("savedValue") != null) { 533 | el[i].value = el[i].getAttribute("savedValue"); 534 | } 535 | } 536 | } 537 | 538 | function changeActionAndSubmit(action,command){ 539 | var f=$("form:first"); 540 | f.prop("action",action); 541 | f.find("[name=CM]").val(command); 542 | f.submit(); 543 | } 544 | 545 | 546 | 547 | // textarea limit size ------------------------------------------------- 548 | function limitSize(ob) { 549 | if (ob.getAttribute("maxlength")) { 550 | var ml =parseInt(ob.getAttribute("maxlength")); 551 | var val = ob.value;//.replace(/\r\n/g,"\n"); 552 | if (val.length > ml) { 553 | ob.value = val.substr(0, ml); 554 | $(ob).createErrorAlert("Error",i18n.ERR_FIELD_MAX_SIZE_EXCEEDED); 555 | } else { 556 | $(ob).clearErrorAlert(); 557 | } 558 | } 559 | return true; 560 | } 561 | 562 | 563 | // verify before unload BEGIN ---------------------------------------------------------------------------- 564 | 565 | function alertOnUnload(container) { 566 | //console.debug("alertOnUnload",container,muteAlertOnChange); 567 | if (!muteAlertOnChange) { 568 | 569 | //first try to call a function eventually defined on the page 570 | if (typeof(managePageUnload) == "function") 571 | managePageUnload(); 572 | 573 | container=container||$("body"); 574 | var inps= $("[alertonchange=true]",container).find("[oldValue=1]"); 575 | for (var j = 0; j < inps.length; j++) { 576 | var anInput = inps.eq(j); 577 | //console.debug(j,anInput,anInput.isValueChanged()) 578 | var oldValue = anInput.getOldValue() + ""; 579 | if (!('true' == '' + anInput.attr('excludeFromAlert'))) { 580 | if (anInput.attr("maleficoTiny")) { 581 | if (tinymce.EditorManager.get(anInput.prop("id")).isDirty()) { 582 | return i18n.FORM_IS_CHANGED + " \"" + anInput.prop("name") + "\""; 583 | } 584 | 585 | } else if (anInput.isValueChanged()) { 586 | var inputLabel = $("label[for='" + anInput.prop("id") + "']").text(); //use label element 587 | inputLabel = inputLabel ? inputLabel : anInput.prop("name"); 588 | return i18n.FORM_IS_CHANGED + " \"" + inputLabel + "\""; 589 | } 590 | } 591 | } 592 | } 593 | return undefined; 594 | } 595 | 596 | function canILeave(){ 597 | var ret = window.onbeforeunload(); 598 | if (typeof(ret)!="undefined" && !confirm(ret+" \n"+i18n.PROCEED)) 599 | return false; 600 | else 601 | return true; 602 | } 603 | 604 | // ---------------------------------- oldvalues management 605 | // update all values selected 606 | jQuery.fn.updateOldValue = function () { 607 | this.each(function () { 608 | var el = $(this); 609 | var val=(el.is(":checkbox,:radio")?el.prop("checked"):el.val())+""; 610 | el.data("_oldvalue", val); 611 | }); 612 | return this; 613 | }; 614 | 615 | // return true if at least one element has changed 616 | jQuery.fn.isValueChanged = function () { 617 | var ret = false; 618 | this.each(function () { 619 | var el = $(this); 620 | var val=(el.is(":checkbox,:radio")?el.prop("checked"):el.val())+""; 621 | if (val != el.data("_oldvalue") + "") { 622 | //console.debug("io sono diverso "+el.prop("id")+ " :"+el.val()+" != "+el.data("_oldvalue")); 623 | ret = true; 624 | return false; 625 | } 626 | }); 627 | return ret; 628 | }; 629 | 630 | jQuery.fn.getOldValue = function () { 631 | return $(this).data("_oldvalue"); 632 | }; 633 | 634 | jQuery.fn.fillJsonWithInputValues = function (jsonObject) { 635 | var inputs = this.find(":input"); 636 | $.each(inputs.serializeArray(),function(){ 637 | if (this.name) { 638 | jsonObject[this.name] = this.value; 639 | } 640 | }); 641 | 642 | inputs.filter(":checkbox[name]").each(function () { 643 | var el = $(this); 644 | jsonObject[el.attr("name")] = el.is(":checked") ? "yes" : "no"; 645 | 646 | }) 647 | 648 | return this; 649 | }; 650 | 651 | 652 | 653 | function enlargeTextArea(immediate) { 654 | //console.debug("enlargeTextArea",immediate); 655 | var el = $(this); 656 | 657 | var delay=immediate===true?1:300; 658 | el.stopTime("taResizeApply"); 659 | el.oneTime(delay,"taResizeApply",function(){ 660 | 661 | var miH = el.is("[minHeight]") ? parseInt(el.attr("minHeight")) : 30; 662 | var maH = el.is("[maxHeight]") ? parseInt(el.attr("maxHeight")) : 400; 663 | var inc = el.is("[lineHeight]") ? parseInt(el.attr("lineHeight")) : 30; 664 | 665 | //si copiano nel css per sicurezza 666 | el.css({maxHeight:maH,minHeight:miH}); 667 | 668 | var domEl = el.get(0); 669 | var pad = el.outerHeight()-el.height(); 670 | //devo allargare 671 | if (domEl.scrollHeight>el.outerHeight() && el.outerHeight()maH-pad?maH-pad:nh; 674 | el.height(nh); 675 | } else if (el.height()>miH){ 676 | //devo stringere 677 | el.height(el.height()-inc); 678 | 679 | while(el.outerHeight()-domEl.scrollHeight > 0 && el.height()>miH){ 680 | el.height(el.height()-inc); 681 | } 682 | var newH=domEl.scrollHeight-pad +inc; 683 | //newH=newH5?0:5-empty); 45 | 46 | //fill with empty lines 47 | for (var i = 0; i < rowsToAdd; i++) { 48 | var emptyRow = $.JST.createFromTemplate({}, "TASKEMPTYROW"); 49 | if (!master.permissions.canSeeDep) 50 | emptyRow.find(".requireCanSeeDep").hide(); 51 | 52 | //click on empty row create a task and fill above 53 | emptyRow.click(function (ev) { 54 | //console.debug("emptyRow.click") 55 | var emptyRow = $(this); 56 | //add on the first empty row only 57 | if (!master.permissions.canWrite || !master.permissions.canAdd || emptyRow.prevAll(".emptyRow").length > 0) 58 | return; 59 | 60 | master.beginTransaction(); 61 | var lastTask; 62 | var start = new Date().getTime(); 63 | var level = 0; 64 | if (master.tasks[0]) { 65 | start = master.tasks[0].start; 66 | level = master.tasks[0].level + 1; 67 | } 68 | 69 | //fill all empty previouses 70 | var cnt=0; 71 | emptyRow.prevAll(".emptyRow").addBack().each(function () { 72 | cnt++; 73 | var ch = factory.build("tmp_fk" + new Date().getTime()+"_"+cnt, "", "", level, start, 1); 74 | var task = master.addTask(ch); 75 | lastTask = ch; 76 | }); 77 | master.endTransaction(); 78 | if (lastTask.rowElement) { 79 | //lastTask.rowElement.click(); removed R&S 22/03/2016 il click è bindato comunque 80 | lastTask.rowElement.find("[name=name]").focus();//focus to "name" input 81 | } 82 | }); 83 | this.element.append(emptyRow); 84 | } 85 | }; 86 | 87 | 88 | GridEditor.prototype.addTask = function (task, row, hideIfParentCollapsed) { 89 | //console.debug("GridEditor.addTask",task,row); 90 | //var prof = new Profiler("editorAddTaskHtml"); 91 | 92 | //remove extisting row 93 | this.element.find("[taskId=" + task.id + "]").remove(); 94 | 95 | var taskRow = $.JST.createFromTemplate(task, "TASKROW"); 96 | 97 | if (!this.master.permissions.canSeeDep) 98 | taskRow.find(".requireCanSeeDep").hide(); 99 | 100 | if (!this.master.permissions.canSeePopEdit) 101 | taskRow.find(".edit .teamworkIcon").hide(); 102 | 103 | //save row element on task 104 | task.rowElement = taskRow; 105 | 106 | this.bindRowEvents(task, taskRow); 107 | 108 | if (typeof(row) != "number") { 109 | var emptyRow = this.element.find(".emptyRow:first"); //tries to fill an empty row 110 | if (emptyRow.length > 0) 111 | emptyRow.replaceWith(taskRow); 112 | else 113 | this.element.append(taskRow); 114 | } else { 115 | var tr = this.element.find("tr.taskEditRow").eq(row); 116 | if (tr.length > 0) { 117 | tr.before(taskRow); 118 | } else { 119 | this.element.append(taskRow); 120 | } 121 | 122 | } 123 | 124 | //[expand] 125 | if (hideIfParentCollapsed) { 126 | if (task.collapsed) taskRow.addClass('collapsed'); 127 | var collapsedDescendant = this.master.getCollapsedDescendant(); 128 | if (collapsedDescendant.indexOf(task) >= 0) taskRow.hide(); 129 | } 130 | 131 | return taskRow; 132 | }; 133 | 134 | GridEditor.prototype.refreshExpandStatus = function (task) { 135 | //console.debug("refreshExpandStatus",task); 136 | if (!task) return; 137 | if (task.isParent()) { 138 | task.rowElement.addClass("isParent"); 139 | } else { 140 | task.rowElement.removeClass("isParent"); 141 | } 142 | 143 | var par = task.getParent(); 144 | if (par && !par.rowElement.is("isParent")) { 145 | par.rowElement.addClass("isParent"); 146 | } 147 | 148 | }; 149 | 150 | GridEditor.prototype.refreshTaskRow = function (task) { 151 | //console.debug("refreshTaskRow") 152 | //var profiler = new Profiler("editorRefreshTaskRow"); 153 | 154 | var canWrite=this.master.permissions.canWrite && task.canWrite; 155 | 156 | var row = task.rowElement; 157 | 158 | row.find(".taskRowIndex").html(task.getRow() + 1); 159 | row.find(".indentCell").css("padding-left", task.level * 10 + 18); 160 | row.find("[name=name]").val(task.name); 161 | row.find("[name=code]").val(task.code); 162 | row.find("[status]").attr("status", task.status); 163 | 164 | row.find("[name=duration]").val(task.duration); 165 | row.find("[name=progress]").val(task.progress).prop("readonly",!canWrite || task.progressByWorklog==true); 166 | row.find("[name=startIsMilestone]").prop("checked", task.startIsMilestone); 167 | row.find("[name=start]").val(new Date(task.start).format()).updateOldValue().prop("readonly",!canWrite || task.depends || !task.canWrite && !this.master.permissions.canWrite ); // called on dates only because for other field is called on focus event 168 | row.find("[name=endIsMilestone]").prop("checked", task.endIsMilestone); 169 | row.find("[name=end]").val(new Date(task.end).format()).updateOldValue(); 170 | row.find("[name=depends]").val(task.depends); 171 | row.find(".taskAssigs").html(task.getAssigsString()); 172 | 173 | //manage collapsed 174 | if (task.collapsed) 175 | row.addClass("collapsed"); 176 | else 177 | row.removeClass("collapsed"); 178 | 179 | 180 | //Enhancing the function to perform own operations 181 | this.master.element.trigger('gantt.task.afterupdate.event', task); 182 | //profiler.stop(); 183 | }; 184 | 185 | GridEditor.prototype.redraw = function () { 186 | //console.debug("GridEditor.prototype.redraw") 187 | //var prof = new Profiler("ganttGridEditorRedraw"); 188 | for (var i = 0; i < this.master.tasks.length; i++) { 189 | this.refreshTaskRow(this.master.tasks[i]); 190 | } 191 | // check if new empty rows are needed 192 | if (this.master.fillWithEmptyLines) 193 | this.fillEmptyLines(); 194 | 195 | //prof.stop() 196 | 197 | }; 198 | 199 | GridEditor.prototype.reset = function () { 200 | this.element.find("[taskid]").remove(); 201 | }; 202 | 203 | 204 | GridEditor.prototype.bindRowEvents = function (task, taskRow) { 205 | var self = this; 206 | //console.debug("bindRowEvents",this,this.master,this.master.permissions.canWrite, task.canWrite); 207 | 208 | //bind row selection 209 | taskRow.click(function (event) { 210 | var row = $(this); 211 | //console.debug("taskRow.click",row.attr("taskid"),event.target) 212 | //var isSel = row.hasClass("rowSelected"); 213 | row.closest("table").find(".rowSelected").removeClass("rowSelected"); 214 | row.addClass("rowSelected"); 215 | 216 | //set current task 217 | self.master.currentTask = self.master.getTask(row.attr("taskId")); 218 | 219 | //move highlighter 220 | self.master.gantt.synchHighlight(); 221 | 222 | //if offscreen scroll to element 223 | var top = row.position().top; 224 | if (top > self.element.parent().height()) { 225 | row.offsetParent().scrollTop(top - self.element.parent().height() + 100); 226 | } else if (top <= 40) { 227 | row.offsetParent().scrollTop(row.offsetParent().scrollTop() - 40 + top); 228 | } 229 | }); 230 | 231 | 232 | if (this.master.permissions.canWrite && task.canWrite) { 233 | self.bindRowInputEvents(task, taskRow); 234 | 235 | } else { //cannot write: disable input 236 | taskRow.find("input").prop("readonly", true); 237 | taskRow.find("input:checkbox,select").prop("disabled", true); 238 | } 239 | 240 | if (!this.master.permissions.canSeeDep) 241 | taskRow.find("[name=depends]").attr("readonly", true); 242 | 243 | self.bindRowExpandEvents(task, taskRow); 244 | if (this.master.permissions.canSeePopEdit) { 245 | taskRow.find(".edit").click(function () {self.openFullEditor(task, false)}); 246 | taskRow.find(".taskAssigs").dblclick(function () {self.openFullEditor(task, true)}); 247 | } 248 | }; 249 | 250 | 251 | GridEditor.prototype.bindRowExpandEvents = function (task, taskRow) { 252 | var self = this; 253 | //expand collapse 254 | taskRow.find(".exp-controller").click(function () { 255 | var el = $(this); 256 | var taskId = el.closest("[taskid]").attr("taskid"); 257 | var task = self.master.getTask(taskId); 258 | if (task.collapsed) { 259 | self.master.expand(task,false); 260 | } else { 261 | self.master.collapse(task,false); 262 | } 263 | }); 264 | }; 265 | 266 | GridEditor.prototype.bindRowInputEvents = function (task, taskRow) { 267 | var self = this; 268 | 269 | //bind dateField on dates 270 | taskRow.find(".date").each(function () { 271 | var el = $(this); 272 | el.click(function () { 273 | var inp = $(this); 274 | inp.dateField({ 275 | inputField: el, 276 | callback: function (d) { 277 | $(this).blur(); 278 | } 279 | }); 280 | }); 281 | 282 | el.blur(function (date) { 283 | var inp = $(this); 284 | if (inp.isValueChanged()) { 285 | if (!Date.isValid(inp.val())) { 286 | alert(GanttMaster.messages["INVALID_DATE_FORMAT"]); 287 | inp.val(inp.getOldValue()); 288 | 289 | } else { 290 | var row = inp.closest("tr"); 291 | var taskId = row.attr("taskId"); 292 | var task = self.master.getTask(taskId); 293 | 294 | var leavingField = inp.prop("name"); 295 | var dates = resynchDates(inp, row.find("[name=start]"), row.find("[name=startIsMilestone]"), row.find("[name=duration]"), row.find("[name=end]"), row.find("[name=endIsMilestone]")); 296 | //console.debug("resynchDates",new Date(dates.start), new Date(dates.end),dates.duration) 297 | //update task from editor 298 | self.master.beginTransaction(); 299 | self.master.changeTaskDates(task, dates.start, dates.end); 300 | self.master.endTransaction(); 301 | inp.updateOldValue(); //in order to avoid multiple call if nothing changed 302 | } 303 | } 304 | }); 305 | }); 306 | 307 | 308 | //milestones checkbox 309 | taskRow.find(":checkbox").click(function () { 310 | var el = $(this); 311 | var row = el.closest("tr"); 312 | var taskId = row.attr("taskId"); 313 | 314 | var task = self.master.getTask(taskId); 315 | 316 | //update task from editor 317 | var field = el.prop("name"); 318 | 319 | if (field == "startIsMilestone" || field == "endIsMilestone") { 320 | self.master.beginTransaction(); 321 | //milestones 322 | task[field] = el.prop("checked"); 323 | resynchDates(el, row.find("[name=start]"), row.find("[name=startIsMilestone]"), row.find("[name=duration]"), row.find("[name=end]"), row.find("[name=endIsMilestone]")); 324 | self.master.endTransaction(); 325 | } 326 | 327 | }); 328 | 329 | 330 | //binding on blur for task update (date exluded as click on calendar blur and then focus, so will always return false, its called refreshing the task row) 331 | taskRow.find("input:text:not(.date)").focus(function () { 332 | $(this).updateOldValue(); 333 | 334 | }).blur(function (event) { 335 | var el = $(this); 336 | var row = el.closest("tr"); 337 | var taskId = row.attr("taskId"); 338 | var task = self.master.getTask(taskId); 339 | //update task from editor 340 | var field = el.prop("name"); 341 | //console.debug("blur",field) 342 | 343 | if (el.isValueChanged()) { 344 | self.master.beginTransaction(); 345 | 346 | if (field == "depends") { 347 | 348 | var oldDeps = task.depends; 349 | task.depends = el.val(); 350 | 351 | 352 | // update links 353 | var linkOK = self.master.updateLinks(task); 354 | if (linkOK) { 355 | //synchronize status from superiors states 356 | var sups = task.getSuperiors(); 357 | 358 | 359 | /* 360 | for (var i = 0; i < sups.length; i++) { 361 | if (!sups[i].from.synchronizeStatus()) 362 | break; 363 | } 364 | */ 365 | 366 | var oneFailed=false; 367 | var oneUndefined=false; 368 | var oneActive=false; 369 | var oneSuspended=false; 370 | for (var i = 0; i < sups.length; i++) { 371 | oneFailed=oneFailed|| sups[i].from.status=="STATUS_FAILED"; 372 | oneUndefined=oneUndefined|| sups[i].from.status=="STATUS_UNDEFINED"; 373 | oneActive=oneActive|| sups[i].from.status=="STATUS_ACTIVE"; 374 | oneSuspended=oneSuspended|| sups[i].from.status=="STATUS_SUSPENDED"; 375 | } 376 | 377 | if (oneFailed){ 378 | task.changeStatus("STATUS_FAILED") 379 | } else if (oneUndefined){ 380 | task.changeStatus("STATUS_UNDEFINED") 381 | } else if (oneActive){ 382 | task.changeStatus("STATUS_SUSPENDED") 383 | } else if (oneSuspended){ 384 | task.changeStatus("STATUS_SUSPENDED") 385 | } else { 386 | task.changeStatus("STATUS_ACTIVE") 387 | } 388 | 389 | 390 | self.master.changeTaskDeps(task); //dates recomputation from dependencies 391 | } 392 | 393 | } else if (field == "duration") { 394 | var dates = resynchDates(el, row.find("[name=start]"), row.find("[name=startIsMilestone]"), row.find("[name=duration]"), row.find("[name=end]"), row.find("[name=endIsMilestone]")); 395 | self.master.changeTaskDates(task, dates.start, dates.end); 396 | 397 | } else if (field == "name" && el.val() == "") { // remove unfilled task 398 | var par = task.getParent(); 399 | task.deleteTask(); 400 | self.fillEmptyLines(); 401 | 402 | if (par) self.refreshExpandStatus(par); 403 | self.master.gantt.synchHighlight(); 404 | 405 | 406 | } else if (field == "progress" ) { 407 | task[field]=parseFloat(el.val())||0; 408 | el.val(task[field]); 409 | 410 | } else { 411 | task[field] = el.val(); 412 | } 413 | self.master.endTransaction(); 414 | 415 | } else if (field == "name" && el.val() == "") { // remove unfilled task even if not changed 416 | if (task.getRow()!=0) { 417 | var par = task.getParent(); 418 | task.deleteTask(); 419 | self.fillEmptyLines(); 420 | if (par) self.refreshExpandStatus(par); 421 | self.master.gantt.synchHighlight(); 422 | }else { 423 | el.oneTime(1,"foc",function(){$(this).focus()}); // 424 | event.preventDefault(); 425 | //return false; 426 | } 427 | 428 | } 429 | }); 430 | 431 | //cursor key movement 432 | taskRow.find("input").keydown(function (event) { 433 | var theCell = $(this); 434 | var theTd = theCell.parent(); 435 | var theRow = theTd.parent(); 436 | var col = theTd.prevAll("td").length; 437 | 438 | var ret = true; 439 | if (!event.ctrlKey) { 440 | switch (event.keyCode) { 441 | 442 | case 37: //left arrow 443 | if (!theCell.is(":text") || (!this.selectionEnd || this.selectionEnd == 0)) 444 | theTd.prev().find("input").focus(); 445 | break; 446 | case 39: //right arrow 447 | if (!theCell.is(":text") || (!this.selectionEnd || this.selectionEnd == this.value.length)) 448 | theTd.next().find("input").focus(); 449 | break; 450 | 451 | case 38: //up arrow 452 | //var prevRow = theRow.prev(); 453 | var prevRow = theRow.prevAll(":visible:first"); 454 | var td = prevRow.find("td").eq(col); 455 | var inp = td.find("input"); 456 | 457 | if (inp.length > 0) 458 | inp.focus(); 459 | break; 460 | case 40: //down arrow 461 | //var nextRow = theRow.next(); 462 | var nextRow = theRow.nextAll(":visible:first"); 463 | var td = nextRow.find("td").eq(col); 464 | var inp = td.find("input"); 465 | if (inp.length > 0) 466 | inp.focus(); 467 | else 468 | nextRow.click(); //create a new row 469 | break; 470 | case 36: //home 471 | break; 472 | case 35: //end 473 | break; 474 | 475 | case 9: //tab 476 | case 13: //enter 477 | break; 478 | } 479 | } 480 | return ret; 481 | 482 | }).focus(function () { 483 | $(this).closest("tr").click(); 484 | }); 485 | 486 | 487 | //change status 488 | taskRow.find(".taskStatus").click(function () { 489 | var el = $(this); 490 | var tr = el.closest("[taskid]"); 491 | var taskId = tr.attr("taskid"); 492 | var task = self.master.getTask(taskId); 493 | 494 | var changer = $.JST.createFromTemplate({}, "CHANGE_STATUS"); 495 | changer.find("[status=" + task.status + "]").addClass("selected"); 496 | changer.find(".taskStatus").click(function (e) { 497 | e.stopPropagation(); 498 | var newStatus = $(this).attr("status"); 499 | changer.remove(); 500 | self.master.beginTransaction(); 501 | task.changeStatus(newStatus); 502 | self.master.endTransaction(); 503 | el.attr("status", task.status); 504 | }); 505 | el.oneTime(3000, "hideChanger", function () { 506 | changer.remove(); 507 | }); 508 | el.after(changer); 509 | }); 510 | 511 | }; 512 | 513 | 514 | GridEditor.prototype.openFullEditor = function (task, editOnlyAssig) { 515 | var self = this; 516 | 517 | if (!self.master.permissions.canSeePopEdit) 518 | return; 519 | 520 | var taskRow=task.rowElement; 521 | 522 | //task editor in popup 523 | var taskId = taskRow.attr("taskId"); 524 | //console.debug(task); 525 | 526 | //make task editor 527 | var taskEditor = $.JST.createFromTemplate(task, "TASK_EDITOR"); 528 | 529 | //hide task data if editing assig only 530 | if (editOnlyAssig) { 531 | taskEditor.find(".taskData").hide(); 532 | taskEditor.find(".assigsTableWrapper").height(455); 533 | taskEditor.prepend("

\""+task.name+"\"

"); 534 | } 535 | 536 | //got to extended editor 537 | if (task.isNew()|| !self.master.permissions.canSeeFullEdit){ 538 | taskEditor.find("#taskFullEditor").remove(); 539 | } else { 540 | taskEditor.bind("openFullEditor.gantt",function () { 541 | window.location.href=contextPath+"/applications/teamwork/task/taskEditor.jsp?CM=ED&OBJID="+task.id; 542 | }); 543 | } 544 | 545 | 546 | taskEditor.find("#name").val(task.name); 547 | taskEditor.find("#description").val(task.description); 548 | taskEditor.find("#code").val(task.code); 549 | taskEditor.find("#progress").val(task.progress ? parseFloat(task.progress) : 0).prop("readonly",task.progressByWorklog==true); 550 | taskEditor.find("#progressByWorklog").prop("checked",task.progressByWorklog); 551 | taskEditor.find("#status").val(task.status); 552 | taskEditor.find("#type").val(task.typeId); 553 | taskEditor.find("#type_txt").val(task.type); 554 | taskEditor.find("#relevance").val(task.relevance); 555 | //cvc_redraw(taskEditor.find(".cvcComponent")); 556 | 557 | 558 | if (task.startIsMilestone) 559 | taskEditor.find("#startIsMilestone").prop("checked", true); 560 | if (task.endIsMilestone) 561 | taskEditor.find("#endIsMilestone").prop("checked", true); 562 | 563 | taskEditor.find("#duration").val(task.duration); 564 | var startDate = taskEditor.find("#start"); 565 | startDate.val(new Date(task.start).format()); 566 | //start is readonly in case of deps 567 | if (task.depends || !this.master.permissions.canWrite && !task.canWrite) { 568 | startDate.attr("readonly", "true"); 569 | } else { 570 | startDate.removeAttr("readonly"); 571 | } 572 | 573 | taskEditor.find("#end").val(new Date(task.end).format()); 574 | 575 | //make assignments table 576 | var assigsTable = taskEditor.find("#assigsTable"); 577 | assigsTable.find("[assId]").remove(); 578 | // loop on assignments 579 | for (var i = 0; i < task.assigs.length; i++) { 580 | var assig = task.assigs[i]; 581 | var assigRow = $.JST.createFromTemplate({task: task, assig: assig}, "ASSIGNMENT_ROW"); 582 | assigsTable.append(assigRow); 583 | } 584 | 585 | if (!self.master.permissions.canWrite || !task.canWrite) { 586 | taskEditor.find("input,textarea").prop("readOnly", true); 587 | taskEditor.find("input:checkbox,select").prop("disabled", true); 588 | taskEditor.find("#saveButton").remove(); 589 | taskEditor.find(".button").addClass("disabled"); 590 | 591 | } else { 592 | 593 | //bind dateField on dates, duration 594 | taskEditor.find("#start,#end,#duration").click(function () { 595 | var input = $(this); 596 | if (input.is("[entrytype=DATE]")) { 597 | input.dateField({ 598 | inputField: input, 599 | callback: function (d) {$(this).blur();} 600 | }); 601 | } 602 | }).blur(function () { 603 | var inp = $(this); 604 | if (inp.validateField()) { 605 | resynchDates(inp, taskEditor.find("[name=start]"), taskEditor.find("[name=startIsMilestone]"), taskEditor.find("[name=duration]"), taskEditor.find("[name=end]"), taskEditor.find("[name=endIsMilestone]")); 606 | //workload computation 607 | if (typeof(workloadDatesChanged)=="function") 608 | workloadDatesChanged(); 609 | } 610 | }); 611 | 612 | taskEditor.find("#startIsMilestone,#endIsMilestone").click(function () { 613 | var inp = $(this); 614 | resynchDates(inp, taskEditor.find("[name=start]"), taskEditor.find("[name=startIsMilestone]"), taskEditor.find("[name=duration]"), taskEditor.find("[name=end]"), taskEditor.find("[name=endIsMilestone]")); 615 | }); 616 | 617 | //bind add assignment 618 | var cnt=0; 619 | taskEditor.find("#addAssig").click(function () { 620 | cnt++; 621 | var assigsTable = taskEditor.find("#assigsTable"); 622 | var assigRow = $.JST.createFromTemplate({task: task, assig: {id: "tmp_" + new Date().getTime()+"_"+cnt}}, "ASSIGNMENT_ROW"); 623 | assigsTable.append(assigRow); 624 | $("#bwinPopupd").scrollTop(10000); 625 | }).click(); 626 | 627 | //save task 628 | taskEditor.bind("saveFullEditor.gantt",function () { 629 | //console.debug("saveFullEditor"); 630 | var task = self.master.getTask(taskId); // get task again because in case of rollback old task is lost 631 | 632 | self.master.beginTransaction(); 633 | task.name = taskEditor.find("#name").val(); 634 | task.description = taskEditor.find("#description").val(); 635 | task.code = taskEditor.find("#code").val(); 636 | task.progress = parseFloat(taskEditor.find("#progress").val()); 637 | //task.duration = parseInt(taskEditor.find("#duration").val()); //bicch rimosso perchè devono essere ricalcolata dalla start end, altrimenti sbaglia 638 | task.startIsMilestone = taskEditor.find("#startIsMilestone").is(":checked"); 639 | task.endIsMilestone = taskEditor.find("#endIsMilestone").is(":checked"); 640 | 641 | task.type = taskEditor.find("#type_txt").val(); 642 | task.typeId = taskEditor.find("#type").val(); 643 | task.relevance = taskEditor.find("#relevance").val(); 644 | task.progressByWorklog= taskEditor.find("#progressByWorklog").is(":checked"); 645 | 646 | //set assignments 647 | var cnt=0; 648 | taskEditor.find("tr[assId]").each(function () { 649 | var trAss = $(this); 650 | var assId = trAss.attr("assId"); 651 | var resId = trAss.find("[name=resourceId]").val(); 652 | var resName = trAss.find("[name=resourceId_txt]").val(); // from smartcombo text input part 653 | var roleId = trAss.find("[name=roleId]").val(); 654 | var effort = millisFromString(trAss.find("[name=effort]").val(),true); 655 | 656 | //check if the selected resource exists in ganttMaster.resources 657 | var res= self.master.getOrCreateResource(resId,resName); 658 | 659 | //if resource is not found nor created 660 | if (!res) 661 | return; 662 | 663 | //check if an existing assig has been deleted and re-created with the same values 664 | var found = false; 665 | for (var i = 0; i < task.assigs.length; i++) { 666 | var ass = task.assigs[i]; 667 | 668 | if (assId == ass.id) { 669 | ass.effort = effort; 670 | ass.roleId = roleId; 671 | ass.resourceId = res.id; 672 | ass.touched = true; 673 | found = true; 674 | break; 675 | 676 | } else if (roleId == ass.roleId && res.id == ass.resourceId) { 677 | ass.effort = effort; 678 | ass.touched = true; 679 | found = true; 680 | break; 681 | 682 | } 683 | } 684 | 685 | if (!found && resId && roleId) { //insert 686 | cnt++; 687 | //console.debug("adding assig row:", assId,resId,resName,roleId,effort) 688 | var ass = task.createAssignment("tmp_" + new Date().getTime()+"_"+cnt, resId, roleId, effort); 689 | ass.touched = true; 690 | } 691 | 692 | }); 693 | 694 | //console.debug("task.assigs",task.assigs,task.assigs.length) 695 | //remove untouched assigs 696 | task.assigs = task.assigs.filter(function (ass) { 697 | var ret = ass.touched; 698 | delete ass.touched; 699 | return ret; 700 | }); 701 | //console.debug("task.assigs",task.assigs,task.assigs.length) 702 | 703 | //change dates 704 | task.setPeriod(Date.parseString(taskEditor.find("#start").val()).getTime(), Date.parseString(taskEditor.find("#end").val()).getTime() + (3600000 * 22)); 705 | 706 | //change status 707 | task.changeStatus(taskEditor.find("#status").val()); 708 | 709 | if (self.master.endTransaction()) { 710 | taskEditor.find(":input").updateOldValue(); 711 | closeBlackPopup(); 712 | } 713 | 714 | }); 715 | } 716 | 717 | taskEditor.attr("alertonchange","true"); 718 | var ndo = createModalPopup(800, 450).append(taskEditor);//.append("
") 719 | //var ndo = createModalPopup(800, 650).append("
") 720 | 721 | //workload computation 722 | if (typeof(workloadDatesChanged)=="function") 723 | workloadDatesChanged(); 724 | 725 | 726 | 727 | }; 728 | --------------------------------------------------------------------------------