You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

193 lines
19 KiB

  1. $.fn.loadTemplates = function() {
  2. $.JST.loadTemplates($(this));
  3. return this;
  4. };
  5. $.JST = {
  6. _templates: new Object(),
  7. _decorators:new Object(),
  8. loadTemplates: function(elems) {
  9. // var elems[0].innerHTML="↵<div class="__template__" type="GANTBUTTONS">↵ <!-- <div class="ganttButtonBar noprint">↵ <h1 class="ganttTitle" title="gantt"><img src="res/twGanttLogo.png" alt="gantt" align="absmiddle"><img src="res/twproject-badge.png" style="max-width: 120px" />↵</h1>↵ <div class="buttons">↵↵↵ <button onclick="$('#workSpace').trigger('undo.gantt');return false;" class="button textual icon requireCanWrite" title="undo"><span class="teamworkIcon">&#39;</span></button>↵ <button onclick="$('#workSpace').trigger('redo.gantt');return false;" class="button textual icon requireCanWrite" title="redo"><span class="teamworkIcon">&middot;</span></button>↵ <span class="ganttButtonSeparator requireCanWrite requireCanAdd"></span>↵ <button onclick="$('#workSpace').trigger('addAboveCurrentTask.gantt');return false;" class="button textual icon requireCanWrite requireCanAdd" title="insert above"><span class="teamworkIcon">l</span></button>↵ <button onclick="$('#workSpace').trigger('addBelowCurrentTask.gantt');return false;" class="button textual icon requireCanWrite requireCanAdd" title="insert below"><span class="teamworkIcon">X</span></button>↵ <span class="ganttButtonSeparator requireCanWrite requireCanInOutdent"></span>↵ <button onclick="$('#workSpace').trigger('outdentCurrentTask.gantt');return false;" class="button textual icon requireCanWrite requireCanInOutdent" title="un-indent task"><span class="teamworkIcon">.</span></button>↵ <button onclick="$('#workSpace').trigger('indentCurrentTask.gantt');return false;" class="button textual icon requireCanWrite requireCanInOutdent" title="indent task"><span class="teamworkIcon">:</span></button>↵ <span class="ganttButtonSeparator requireCanWrite requireCanMoveUpDown"></span>↵ <button onclick="$('#workSpace').trigger('moveUpCurrentTask.gantt');return false;" class="button textual icon requireCanWrite requireCanMoveUpDown" title="move up"><span class="teamworkIcon">k</span></button>↵ <button onclick="$('#workSpace').trigger('moveDownCurrentTask.gantt');return false;" class="button textual icon requireCanWrite requireCanMoveUpDown" title="move down"><span class="teamworkIcon">j</span></button>↵↵ <span class="ganttButtonSeparator requireCanWrite"></span>↵ <button onclick="$('#workSpace').trigger('deleteCurrentTask.gantt');return false;" class="button textual icon delete requireCanWrite" title="Delete"><span class="teamworkIcon">&cent;</span></button>↵↵ <span class="ganttButtonSeparator requireCanAddIssue"></span>↵ <button onclick="$('#workSpace').trigger('addIssue.gantt');return false;" class="button textual icon requireCanAddIssue" title="add issue / todo"><span class="teamworkIcon">i</span></button>↵↵↵ <span class="ganttButtonSeparator"></span>↵ <button onclick="$('#workSpace').trigger('expandAll.gantt');return false;" class="button textual icon " title="EXPAND_ALL"><span class="teamworkIcon">6</span></button>↵ <button onclick="$('#workSpace').trigger('collapseAll.gantt'); return false;" class="button textual icon " title="COLLAPSE_ALL"><span class="teamworkIcon">5</span></button>↵↵ <span class="ganttButtonSeparator"></span>↵ <button onclick="$('#workSpace').trigger('zoomMinus.gantt'); return false;" class="button textual icon " title="zoom out"><span class="teamworkIcon">)</span></button>↵ <button onclick="$('#workSpace').trigger('zoomPlus.gantt');return false;" class="button textual icon " title="zoom in"><span class="teamworkIcon">(</span></button>↵ <span class="ganttButtonSeparator"></span>↵ <button onclick="print();return false;" class="button textual icon " title="Print"><span class="teamworkIcon">p</span></button>↵ <span class="ganttButtonSeparator"></span>↵ <button onclick="ge.gantt.showCriticalPath=!ge.gantt.showCriticalPath; ge.redraw();return false;" class="button textual icon requireCanSeeCriticalPath" title="CRITICAL_PATH"><span class="teamworkIcon">&pound;</span></button>↵ <span class="ganttButtonSeparator requireCanSeeCriticalPath"></span>↵ <button onclick="ge.splitter.resize(.1);return false;" class="button textual icon" ><span class="teamworkIcon">F</span></button>↵ <button onclick="ge.splitter.resize(50);return false;" class="button textual icon" ><span class="teamworkIcon">O</span></button>↵ <button onclick="ge.splitter.resize(100);return false;" class="button textual icon"><span class="teamworkIcon">R</span></button>↵↵ <button onclick="editResources();" class="button textual requireWrite" title="edit resources"><span class="teamworkIcon">M</span></button>↵ &nbsp; &nbsp; &nbsp; &nbsp;↵ <button onclick="saveGanttOnServer();" class="button first big requireWrite" title="Save">Save</button>↵ <button onclick='newProject();' class='button requireWrite newproject'><em>clear project</em></button>↵ <button class="button login" title="login/enroll" onclick="loginEnroll($(this));" style="display:none;">login/enroll</butto…rt</label>&nbsp;&nbsp;&nbsp;&nbsp;↵ <input type="checkbox" id="startIsMilestone" name="startIsMilestone" value="yes"> &nbsp;<label for="startIsMilestone">is milestone</label>&nbsp;↵ <br><input type="text" name="start" id="start" size="8" class="formElements dateField validated date" autocomplete="off" maxlength="255" value="" oldvalue="1" entrytype="DATE">↵ <span title="calendar" id="starts_inputDate" class="teamworkIcon openCalendar" onclick="$(this).dateField({inputField:$(this).prevAll(':input:first'),isSearchField:false});">m</span> </div>↵ </td>↵ <td nowrap="">↵ <label for="end">End</label>&nbsp;&nbsp;&nbsp;&nbsp;↵ <input type="checkbox" id="endIsMilestone" name="endIsMilestone" value="yes"> &nbsp;<label for="endIsMilestone">is milestone</label>&nbsp;↵ <br><input type="text" name="end" id="end" size="8" class="formElements dateField validated date" autocomplete="off" maxlength="255" value="" oldvalue="1" entrytype="DATE">↵ <span title="calendar" id="ends_inputDate" class="teamworkIcon openCalendar" onclick="$(this).dateField({inputField:$(this).prevAll(':input:first'),isSearchField:false});">m</span>↵ </td>↵ <td nowrap="" >↵ <label for="duration" class=" ">Days</label><br>↵ <input type="text" name="duration" id="duration" size="4" class="formElements validated durationdays" title="Duration is in working days." autocomplete="off" maxlength="255" value="" oldvalue="1" entrytype="DURATIONDAYS">&nbsp;↵ </td>↵ </tr>↵↵ <tr>↵ <td colspan="2">↵ <label for="status" class=" ">status</label><br>↵ <select id="status" name="status" class="taskStatus" status="(#=obj.status#)" onchange="$(this).attr('STATUS',$(this).val());">↵ <option value="STATUS_ACTIVE" class="taskStatus" status="STATUS_ACTIVE" >active</option>↵ <option value="STATUS_SUSPENDED" class="taskStatus" status="STATUS_SUSPENDED" >suspended</option>↵ <option value="STATUS_DONE" class="taskStatus" status="STATUS_DONE" >completed</option>↵ <option value="STATUS_FAILED" class="taskStatus" status="STATUS_FAILED" >failed</option>↵ <option value="STATUS_UNDEFINED" class="taskStatus" status="STATUS_UNDEFINED" >undefined</option>↵ </select>↵ </td>↵↵ <td valign="top" nowrap>↵ <label>progress</label><br>↵ <input type="text" name="progress" id="progress" size="7" class="formElements validated percentile" autocomplete="off" maxlength="255" value="" oldvalue="1" entrytype="PERCENTILE">↵ </td>↵ </tr>↵↵ </tr>↵ <tr>↵ <td colspan="4">↵ <label for="description">Description</label><br>↵ <textarea rows="3" cols="30" id="description" name="description" class="formElements" style="width:100%"></textarea>↵ </td>↵ </tr>↵ </table>↵↵ <h2>Assignments</h2>↵ <table cellspacing="1" cellpadding="0" width="100%" id="assigsTable">↵ <tr>↵ <th style="width:100px;">name</th>↵ <th style="width:70px;">Role</th>↵ <th style="width:30px;">est.wklg.</th>↵ <th style="width:30px;" id="addAssig"><span class="teamworkIcon" style="cursor: pointer">+</span></th>↵ </tr>↵ </table>↵↵ <div style="text-align: right; padding-top: 20px">↵ <span id="saveButton" class="button first" onClick="$(this).trigger('saveFullEditor.gantt');">Save</span>↵ </div>↵↵ </div> -->↵ </div>↵↵↵↵<div class="__template__" type="ASSIGNMENT_ROW"><!--↵ <tr taskId="(#=obj.task.id#)" assId="(#=obj.assig.id#)" class="assigEditRow" >↵ <td ><select name="resourceId" class="formElements" (#=obj.assig.id.indexOf("tmp_")==0?"":"disabled"#) ></select></td>↵ <td ><select type="select" name="roleId" class="formElements"></select></td>↵ <td ><input type="text" name="effort" value="(#=getMillisInHoursMinutes(obj.assig.effort)#)" size="5" class="formElements"></td>↵ <td align="center"><span class="teamworkIcon delAssig del" style="cursor: pointer">d</span></td>↵ </tr>↵ --></div>↵↵↵↵<div class="__template__" type="RESOURCE_EDITOR">↵ <!-- <div class="resourceEditor" style="padding: 5px;">↵↵ <h2>Project team</h2>↵ <table cellspacing="1" cellpadding="0" width="100%" id="resourcesTable">↵ <tr>↵ <th style="width:100px;">name</th>↵ <th style="width:30px;" id="addResource"><span class="teamworkIcon" style="cursor: pointer">+</span></th>↵ </tr>↵ </table>↵↵ <div style="text-align: right; padding-top: 20px"><button id="resSaveButton" class="button big">Save</button></div>↵ </div> -->↵ </div>↵↵↵↵<div class="__template__" type="RESOURCE_ROW"><!--↵ <tr resId="(#=obj.id#)" class="resRow" >↵ <td ><input type="text" name="name" value="(#=obj.name#)" style="width:100%;" class="formElements"></td>↵ <td align="center"><span class="teamworkIcon delRes del" style="cursor: pointer">d</span></td>↵ </tr>↵ --></div>↵↵↵";
  10. elems.each(function() {
  11. $(this).find(".__template__").each(function() {
  12. var tmpl = $(this);
  13. var type = tmpl.attr("type");
  14. //template may be inside <!-- ... --> or not in case of ajax loaded templates
  15. var found=false;
  16. var el=tmpl.get(0).firstChild;
  17. while (el && !found) {
  18. if (el.nodeType == 8) { // 8==comment
  19. var templateBody = el.nodeValue; // this is inside the comment
  20. found=true;
  21. break;
  22. }
  23. el=el.nextSibling;
  24. }
  25. if (!found){
  26. var templateBody = tmpl.html(); // this is the whole template
  27. if (type=="TASKROW"){
  28. var templateBody=' <tr taskId="(#=obj.id#)" class="taskEditRow (#=obj.isParent()?'+"'isParent':''#) (#=obj.collapsed?'collapsed':''#)"+'" level="(#=level#)"> <th class="gdfCell edit" align="right" style="cursor:pointer;"><span class="taskRowIndex">(#=obj.getRow()+1#)</span> <span class="teamworkIcon" style="font-size:12px;" >e</span></th> <td class="gdfCell noClip" align="center"><div class="taskStatus cvcColorSquare" status="(#=obj.status#)"></div></td> <td class="gdfCell"><input type="text" name="code" value="(#=obj.code?obj.code:'+"''#)"+'" placeholder="编号"></td> <td class="gdfCell indentCell" style="padding-left:(#=obj.level*10+18#)px;"> <div class="exp-controller" align="center"></div> <input type="text" name="name" value="(#=obj.name#)" placeholder="名称"> </td> <td class="gdfCell" align="center"><input type="checkbox" name="startIsMilestone"></td> <td class="gdfCell"><input type="text" name="start" value="" class="date"></td> <td class="gdfCell" align="center"><input type="checkbox" name="endIsMilestone"></td> <td class="gdfCell"><input type="text" name="end" value="" class="date"></td> <td class="gdfCell"><input type="text" name="duration" autocomplete="off" value="(#=obj.duration#)"></td> <td class="gdfCell"><input type="text" name="progress" class="validated" entrytype="PERCENTILE" autocomplete="off" value="(#=obj.progress?obj.progress:'+"''#)"+'" (#=obj.progressByWorklog?"readOnly":""#)></td> <td class="gdfCell requireCanSeeDep"><input type="text" name="depends" autocomplete="off" value="(#=obj.depends#)" (#=obj.hasExternalDep?"readonly":""#)></td> <td class="gdfCell taskAssigs">(#=obj.getAssigsString()#)</td> </tr> ';
  29. }
  30. if (type=="TASKBAR"){
  31. var templateBody=' <div class="taskBox taskBoxDiv" taskId="(#=obj.id#)" > <div class="layout (#=obj.hasExternalDep?'+"'extDep':''#)"+'"> <div class="taskStatus" status="(#=obj.status#)"></div> <div class="taskProgress" style="width:(#=obj.progress>100?100:obj.progress#)%; background-color:(#=obj.progress>100?'+"'red':'rgb(153,255,51);'#);"+'"></div> <div class="milestone (#=obj.startIsMilestone?'+"'active':''#)"+'" ></div> <div class="taskLabel"></div> <div class="milestone end (#=obj.endIsMilestone?'+"'active':''#)"+'" ></div> </div> </div> ';
  32. }
  33. if (type=="ASSIGNMENT_ROW"){
  34. var templateBody=' <tr taskId="(#=obj.task.id#)" assId="(#=obj.assig.id#)" class="assigEditRow" > <td ><select name="resourceId" class="formElements" (#=obj.assig.id.indexOf("tmp_")==0?"":"disabled"#) ></select></td> <td ><select type="select" name="roleId" class="formElements"></select></td> <td ><input type="text" name="effort" value="(#=getMillisInHoursMinutes(obj.assig.effort)#)" size="5" class="formElements"></td> <td align="center"><span class="teamworkIcon delAssig del" style="cursor: pointer">d</span></td> </tr> ';
  35. }
  36. if (type=="RESOURCE_ROW"){
  37. var templateBody=' <tr resId="(#=obj.id#)" class="resRow" > <td ><input type="text" name="name" value="(#=obj.name#)" style="width:100%;" class="formElements"></td> <td align="center"><span class="teamworkIcon delRes del" style="cursor: pointer">d</span></td> </tr> ';
  38. }
  39. }
  40. if (!templateBody.match(/##\w+##/)) { // is Resig' style? e.g. (#=id#) or (# ...some javascript code 'obj' is the alias for the object #)
  41. var strFunc =
  42. "var p=[],print=function(){p.push.apply(p,arguments);};" +
  43. "with(obj){p.push('" +
  44. templateBody.replace(/[\r\t\n]/g, " ")
  45. .replace(/'(?=[^#]*#\))/g, "\t")
  46. .split("'").join("\\'")
  47. .split("\t").join("'")
  48. .replace(/\(#=(.+?)#\)/g, "',$1,'")
  49. .split("(#").join("');")
  50. .split("#)").join("p.push('")
  51. + "');}return p.join('');";
  52. try {
  53. $.JST._templates[type] = new Function("obj", strFunc);
  54. } catch (e) {
  55. console.error("JST error: "+type, e,strFunc);
  56. }
  57. } else { //plain template e.g. ##id##
  58. try {
  59. $.JST._templates[type] = templateBody;
  60. } catch (e) {
  61. console.error("JST error: "+type, e,templateBody);
  62. }
  63. }
  64. tmpl.remove();
  65. });
  66. });
  67. },
  68. createFromTemplate: function(jsonData, template, transformToPrintable) {
  69. var templates = $.JST._templates;
  70. var jsData=new Object();
  71. if (transformToPrintable){
  72. for (var prop in jsonData){
  73. var value = jsonData[prop];
  74. if (typeof(value) == "string")
  75. value = (value + "").replace(/\n/g, "<br>");
  76. jsData[prop]=value;
  77. }
  78. } else {
  79. jsData=jsonData;
  80. }
  81. function fillStripData(strip, data) {
  82. for (var prop in data) {
  83. var value = data[prop];
  84. strip = strip.replace(new RegExp("##" + prop + "##", "gi"), value);
  85. }
  86. // then clean the remaining ##xxx##
  87. strip = strip.replace(new RegExp("##\\w+##", "gi"), "");
  88. return strip;
  89. }
  90. var stripString = "";
  91. if (typeof(template) == "undefined") {
  92. alert("Template is required");
  93. stripString = "<div>Template is required</div>";
  94. } else if (typeof(templates[template]) == "function") { // resig template
  95. try {
  96. stripString = templates[template](jsData);// create a jquery object in memory
  97. if (template == "TASKEMPTYROW"){
  98. stripString =' <tr class="taskEditRow emptyRow" > <th class="gdfCell" align="right"></th> <td class="gdfCell noClip" align="center"></td> <td class="gdfCell"></td> <td class="gdfCell"></td> <td class="gdfCell"></td> <td class="gdfCell"></td> <td class="gdfCell"></td> <td class="gdfCell"></td> <td class="gdfCell"></td> <td class="gdfCell"></td> <td class="gdfCell requireCanSeeDep"></td> <td class="gdfCell"></td> </tr> '
  99. }
  100. } catch (e) {
  101. console.error("JST error: "+template,e.message);
  102. stripString = "<div> ERROR: "+template+"<br>" + e.message + "</div>";
  103. }
  104. } else {
  105. stripString = templates[template]; // recover strip template
  106. if (!stripString || stripString.trim() == "") {
  107. console.error("No template found for type '" + template + "'");
  108. return $("<div>");
  109. } else {
  110. stripString = fillStripData(stripString, jsData); //replace placeholders with data
  111. }
  112. }
  113. var ret = $(stripString);// create a jquery object in memory
  114. ret.attr("__template", template); // set __template attribute
  115. //decorate the strip
  116. var dec = $.JST._decorators[template];
  117. if (typeof (dec) == "function")
  118. dec(ret, jsData);
  119. return ret;
  120. },
  121. existsTemplate: function(template) {
  122. return $.JST._templates[template];
  123. },
  124. //decorate function is like function(domElement,jsonData){...}
  125. loadDecorator:function(template, decorator) {
  126. $.JST._decorators[template] = decorator;
  127. },
  128. getDecorator:function(template) {
  129. return $.JST._decorators[template];
  130. },
  131. decorateTemplate:function(element) {
  132. var dec = $.JST._decorators[element.attr("__template")];
  133. if (typeof (dec) == "function")
  134. dec(editor);
  135. },
  136. // asynchronous
  137. ajaxLoadAsynchTemplates: function(templateUrl, callback) {
  138. $.get(templateUrl, function(data) {
  139. var div = $("<div>");
  140. div.html(data);
  141. $.JST.loadTemplates(div);
  142. if (typeof(callback == "function"))
  143. callback();
  144. },"html");
  145. },
  146. ajaxLoadTemplates: function(templateUrl) {
  147. $.ajax({
  148. async:false,
  149. url: templateUrl,
  150. dataType: "html",
  151. success: function(data) {
  152. var div = $("<div>");
  153. div.html(data);
  154. $.JST.loadTemplates(div);
  155. }
  156. });
  157. }
  158. };