File: 0.00.1a/js/freedesk.js (View as Code)

1: /* ------------------------------------------------------------- 2: This file is part of FreeDESK 3: 4: FreeDESK is (C) Copyright 2012 David Cutting 5: 6: FreeDESK is free software: you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation, either version 3 of the License, or 9: (at your option) any later version. 10: 11: FreeDESK is distributed in the hope that it will be useful, 12: but WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14: GNU General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with FreeDESK. If not, see www.gnu.org/licenses 18: 19: For more information see www.purplepixie.org/freedesk/ 20: -------------------------------------------------------------- */ 21: 22: /** 23: * The main FreeDESK JavaScript client-side code 24: **/ 25: 26: function FreeDESK() 27: { 28: this.sid = ""; // Session ID 29: 30: // Statuses of requests (text) 31: this.requestStatus = new Array(); 32: // Priorities of requests (text) 33: this.requestPriority = new Array(); 34: // List of display fields for request list 35: this.fieldList = new Array(); 36: 37: // XML of last request list fetched (for redisplay) 38: this.lastListXML = null; 39: 40: // Last Request Details 41: this.lastTeam = 0; 42: this.lastUser = ""; 43: 44: // Last subpage 45: this.lastSubpage = ""; 46: this.lastSubpageOpts = ""; 47: 48: // Sort Criteria 49: this.sortField = "requestid"; 50: this.sortOrder = "D"; 51: 52: // Refresh Event 53: this.refreshEvent = null; 54: 55: // Login Support 56: this.login_action = function(responseXML) 57: { 58: //alert(responseXML); 59: //var txt = document.createTextNode(responseXML); 60: //document.getElementById("login_content").appendChild(txt); 61: if (DESK.isError(responseXML)) 62: { 63: DESK.show_login(DESK.getError(responseXML)); 64: } 65: else 66: { 67: var newsid = responseXML.getElementsByTagName("sid")[0].childNodes[0].nodeValue; 68: if (DESK.sid == "") // no current session so reload to index 69: { 70: //var loc = "./?sid="+newsid; 71: //window.location.href = loc; 72: document.forms['login_sid_form'].elements['sid'].value = newsid; 73: document.forms['login_sid_form'].submit(); 74: } 75: else 76: { 77: DESK.sid = newsid; 78: DESK.hide_login(); 79: // Any other actions? 80: } 81: } 82: } 83: 84: this.login_click=function() 85: { 86: var req = new ServerRequest(); 87: req.url = "api.php?mode=login&type=user&username=" 88: +document.getElementById("login_username").value 89: +"&password=" 90: +document.getElementById("login_password").value; 91: req.callback = DESK.login_action; 92: req.Get(); 93: } 94: 95: this.show_login=function(errormsg) 96: { 97: this.backdrop(true); 98: var txt = ""; 99: if (errormsg !== undefined) 100: txt=errormsg; 101: document.getElementById("login_message").innerHTML = txt; 102: document.getElementById("login_form").style.display = "block"; 103: } 104: 105: this.hide_login=function() 106: { 107: document.getElementById("login_form").style.display = "none"; 108: document.getElementById("login_message").style.display = "none"; 109: this.backdrop(false); 110: } 111: 112: // Logout 113: this.logout_click=function() 114: { 115: var req = new ServerRequest(); 116: req.url="api.php?mode=logout&sid="+this.sid; 117: req.callback = DESK.logout_action; 118: req.Get(); 119: } 120: 121: this.logout_action=function() 122: { 123: window.location.href="./"; 124: } 125: 126: // Show/Hide Backdrop 127: this.backdrop = function(set) 128: { 129: var bd = document.getElementById("screen_backdrop"); 130: if (set === undefined) // toggle 131: { 132: if (bd.style.display == "block") 133: set = false; 134: else 135: set = true; 136: } 137: 138: if (set) 139: bd.style.display = "block"; 140: else 141: bd.style.display = "none"; 142: } 143: 144: // Check for errors 145: this.isError = function(xml) 146: { 147: //alert(xml); 148: //alert(xml.documentElement); 149: //alert(xml.documentElement.tagName); 150: //alert(xml.getElementsByTagName("error")[0].childNodes[0].nodeValue); 151: if (xml.documentElement.tagName == "error") 152: //if (xml.getElementsByTagName("error").length > 0) 153: return true; 154: return false; 155: } 156: 157: this.getError = function(xml) 158: { 159: var out = xml.getElementsByTagName("code")[0].childNodes[0].nodeValue; 160: out += ": "; 161: out += xml.getElementsByTagName("text")[0].childNodes[0].nodeValue; 162: return out; 163: } 164: 165: this.getErrorCode = function(xml) 166: { 167: return xml.getElementsByTagName("code")[0].childNodes[0].nodeValue; 168: } 169: 170: // Display main or sub page (true for main, false for sub) 171: this.displayMain = function(disp) 172: { 173: if (disp) 174: { 175: document.getElementById("subpage").style.display="none"; 176: document.getElementById("mainpage").style.display="block"; 177: } 178: else 179: { 180: document.getElementById("mainpage").style.display="none"; 181: document.getElementById("subpage").style.display="block"; 182: } 183: } 184: 185: // Load sub-pages 186: this.displaySubpage = function(text) 187: { 188: document.getElementById("subpage").innerHTML = text; 189: DESK.displayMain(false); 190: } 191: 192: this.loadSubpage = function(page, opts) 193: { 194: if (opts == undefined) 195: var opts = ""; 196: this.lastSubpage = page; 197: this.lastSubpageOpts = opts; 198: var sr = new ServerRequest(); 199: sr.xmlrequest=false; 200: sr.url = "page.php?page="+page; 201: if (opts != "") 202: sr.url += "&"+opts; 203: sr.url += "&sid="+this.sid; 204: 205: sr.callback = DESK.displaySubpage; 206: sr.Get(); 207: } 208: 209: // Refresh the subpage 210: this.refreshSubpage = function() 211: { 212: DESK.loadSubpage(DESK.lastSubpage, DESK.lastSubpageOpts); 213: } 214: 215: // Load a Request List to the Main Pane 216: this.mainPane = function(teamid, username) 217: { 218: if (teamid == undefined) 219: var teamid = 0; 220: if (username == undefined) 221: var username=""; 222: //alert(teamid+" "+username); 223: var sr = new ServerRequest(); 224: this.lastTeam = teamid; 225: this.lastUser = username; 226: 227: sr.url = "api.php?mode=requests_assigned&teamid="+teamid+"&username="+username; 228: if (this.sortField != "") 229: { 230: sr.url += "&sort="+this.sortField; 231: sr.url += "&order="+this.sortOrder; 232: } 233: sr.url += "&sid="+this.sid; 234: sr.callback = DESK.mainPaneDisplay; 235: sr.Get(); 236: } 237: 238: // Refresh the Main Pane 239: this.mainPaneRefresh = function() 240: { 241: DESK.mainPane(DESK.lastTeam, DESK.lastUser); 242: } 243: 244: // Display a request list in the main pane 245: this.mainPaneDisplay = function(xml) 246: { 247: DESK.lastListXML = xml; 248: var table = document.createElement("table"); // table for results 249: table.border=0; 250: table.width="100%"; 251: table.className="requestList"; 252: 253: var container = document.getElementById('mainright'); 254: 255: if (container.hasChildNodes()) 256: { 257: while(container.childNodes.length >= 1) 258: container.removeChild(container.firstChild); 259: } 260: 261: var requests = xml.getElementsByTagName("request"); 262: 263: if (requests.length <= 0) 264: { 265: container.innerHTML = "

No Requests Found

";
266: return; 267: } 268: 269: container.appendChild(table); 270: 271: var title = table.insertRow(0); 272: title.className = "requestListTitle"; 273: for (var i=0; i274: { 275: if (DESK.fieldList[i][1] == 1) // displayed field 276: { 277: var cell = title.insertCell(-1); 278: 279: var fieldTitle = DESK.fieldList[i][0]; 280: 281: var link = ""; 282: link += fieldTitle; 283: 284: if (DESK.sortField == DESK.fieldList[i][2]) 285: if (DESK.sortOrder == "D") 286: link+=" >"; 287: else 288: link+=" <"; 289: 290: link+""; 291: 292: cell.innerHTML = link; 293: } 294: } 295: 296: for (var req=0; req297: { 298: var request = requests[req]; 299: var row = table.insertRow(table.getElementsByTagName("tr").length); 300: row.className="requestList"; 301: 302: for (var fc=0; fc303: { 304: var field = DESK.fieldList[fc]; 305: if (field[1] == 1) // display this field 306: { 307: var contents = ""; 308: var data = request.getElementsByTagName(field[2])[0]; 309: if (!data) // no field data of this form returned 310: { 311: contents=" -"; 312: } 313: else 314: { 315: contents = (data.textContent == undefined) ? data.firstChild.nodeValue : data.textContent; 316: if (field[2]=="status") 317: contents = DESK.requestStatus[contents]; 318: else if (field[2]=="priority") 319: contents = DESK.requestPriority[contents]; 320: else if (field[2]=="requestid") 321: { 322: var id = contents; 323: contents = ""+contents+""; 324: // row.onclick = function(){ return DESK.displayRequest(id); }; // Always uses last - TODO fix it 325: } 326: } 327: 328: var cell = row.insertCell(-1); 329: cell.innerHTML = contents; 330: } 331: } 332: } 333: } 334: 335: // Set main pane sort 336: this.mainPaneSort = function(field) 337: { 338: if (DESK.sortField == field) 339: { 340: if (DESK.sortOrder == "D") 341: DESK.sortOrder = "A"; 342: else 343: DESK.sortOrder = "D"; 344: } 345: else 346: { 347: DESK.sortField = field; 348: DESK.sortOrder = "D"; 349: } 350: DESK.mainPane(DESK.lastTeam, DESK.lastUser); 351: } 352: 353: // Option Displays for Main Page 354: this.optionDisplay = function(opt) 355: { 356: if (opt == 1) 357: { 358: document.getElementById('option_select').style.display = "none"; 359: 360: var container = document.getElementById('option_dialog'); 361: 362: if (container.hasChildNodes()) 363: { 364: while(container.childNodes.length >= 1) 365: container.removeChild(container.firstChild); 366: } 367: 368: for (var i=0; i369: { 370: var displayed = false; 371: if (this.fieldList[i][1]==1) 372: displayed=true; 373: var a = ""; 374: if (displayed) 375: a += ""; 376: a += "377: if (displayed) 378: a+="0"; 379: else 380: a+="1"; 381: a+="); DESK.optionDisplay(1);\">"; 382: //container.innerHTML += a; 383: a += this.fieldList[i][0]; 384: a += ""; 385: if (displayed) 386: a += ""; 387: container.innerHTML += a; 388: container.innerHTML += "
";
389: } 390: 391: 392: container.innerHTML += "
Close and Apply";
393: 394: container.style.display = "block"; 395: } 396: else 397: { 398: document.getElementById('option_dialog').style.display = "none"; 399: document.getElementById('option_select').style.display = "block"; 400: } 401: } 402: 403: // Set a fieldDisplay property 404: this.setFieldDisplay = function(index, setting) 405: { 406: this.fieldList[index][1]=setting; 407: } 408: 409: // Display a Request 410: this.displayRequest = function(id) 411: { 412: var url = "request.php?id="+id+"&sid="+DESK.sid; 413: DESK.openWindow("FreeDESK Request", url); 414: } 415: 416: // Open a Window 417: this.openWindow = function(windowname, url, xsize, ysize, resizeable) 418: { 419: if (xsize == undefined) 420: var xsize = 700; 421: if (ysize == undefined) 422: var ysize = 500; 423: 424: if (resizeable == undefined) 425: var resizeable = 1; 426: else if(resizeable) 427: resizeable=1; 428: else if(!resizeable) 429: resizable=0; 430: 431: var windowopts = "location=0,status=0,scrollbars=1,toolbar=0,width="+xsize+",height="+ysize+",resizeable="+resizeable; 432: 433: window.open(url, '', windowopts); 434: } 435: 436: // Perform an entity search 437: this.entitySearch = function(entity, callback, fields) 438: { 439: var url = "entity.php?mode=search&entity="+entity; 440: 441: if (callback != undefined) 442: url += "&callback="+callback; 443: if (fields != undefined) 444: { 445: for (var i=0; i446: { 447: url += "&" + fields[i][0] + "=" + fields[i][1]; // escape? 448: } 449: } 450: url += "&sid=" + this.sid; 451: 452: this.openWindow("Search "+entity, url); 453: } 454: 455: // Open Edit Entity 456: this.editEntity = function(entity, keyfield, keyfieldValue) 457: { 458: var url = "entity.php?mode=edit&entity="+entity+"&keyfield="+keyfield+"&value="+keyfieldValue; 459: url += "&sid=" + this.sid; 460: 461: this.openWindow("Edit "+entity, url); 462: } 463: 464: // Perform an entity creation 465: this.entityCreate = function(entity, callback) 466: { 467: var url = "entity.php?mode=create&entity="+entity; 468: 469: if (callback != undefined) 470: url += "&callback="+callback; 471: 472: url += "&sid=" + this.sid; 473: 474: this.openWindow("Create "+entity, url); 475: } 476: 477: // Convert form to query string 478: this.formToQuery = function(formid) 479: { 480: var data = ""; 481: 482: function add(name, value) 483: { 484: if (value == undefined) 485: var value = ""; 486: 487: data += (data.length > 0 ? "&" : ""); // add & if required 488: 489: data += escape(name).replace(/\+/g, "%2B") + "="; 490: 491: data += escape(value).replace(/\+/g, "%2B"); 492: } 493: 494: var form = document.forms[formid]; 495: if (!form) 496: return ""; 497: var elements = form.elements; 498: 499: for (var i=0; i500: { 501: var element = elements[i]; 502: var type = element.type.toLowerCase(); 503: var name = element.name; 504: 505: if (name) 506: { 507: if ( type == "text" || type == "password" || 508: type == "button" || type == "reset" || 509: type == "file" || type == "submit" || 510: type == "image" || type == "hidden" || 511: type == "textarea" ) 512: add(name, element.value); 513: 514: else if ( type == "checkbox" && element.checked ) 515: add(name, element.value ? element.value : "On"); 516: 517: else if ( type == "radio" && element.checked) 518: add(name, element.value); 519: 520: else if ( type.indexOf("select") != -1 ) 521: { 522: for (var x=0; x523: { 524: var opt = element.options[x]; 525: if (opt.selected) 526: add(name, opt.value ? opt.value : opt.text); 527: } 528: } 529: } 530: } 531: 532: return data; 533: } 534: 535: // API Form Action e.g. save entity 536: this.formAPI = function(formid, closeOnComplete, reloadOnComplete, callbackOnComplete) 537: { 538: if (closeOnComplete == undefined) 539: var closeOnComplete = false; 540: if (reloadOnComplete == undefined) 541: var reloadOnComplete = false; 542: if (callbackOnComplete == undefined) 543: var callbackOnComplete = false; 544: 545: 546: var q = DESK.formToQuery(formid); 547: 548: q += "&sid=" + DESK.sid; 549: 550: var sr = new ServerRequest(); 551: sr.url = "api.php"; 552: sr.callback = DESK.formAPIcallback; 553: sr.additional = new Array(); 554: sr.additional[0] = closeOnComplete; 555: sr.additional[1] = reloadOnComplete; 556: sr.additional[2] = callbackOnComplete; 557: sr.Post(q); 558: } 559: 560: this.formAPIcallback = function(xml, additional) 561: { 562: if (DESK.isError(xml)) 563: { 564: Alerts.add(DESK.getError(xml), 2, 10); 565: } 566: else 567: { 568: // We got this far - no DESK error or XML error so we can say success! 569: Alerts.add("Operation Successful", 0); 570: 571: if (additional[2]) // do the javascript first if there is any 572: { 573: additional[2](xml); 574: } 575: 576: if (additional[0]) 577: window.close(); 578: else if (additional[1]) 579: window.location.reload(); 580: } 581: } 582: 583: // Switch a pane 584: this.paneSwitch = function(pid, oid) 585: { 586: var pane = document.getElementById("pane_"+pid); 587: var header = document.getElementById("pane_"+pid+"_header"); 588: 589: var child = header.firstChild; 590: 591: var spans = header.getElementsByTagName("SPAN"); 592: 593: for (var i=0; i594: { 595: var arr = spans[i].id.split("_"); 596: var opt = arr[arr.length-1]; 597: 598: var contentid = "pane_"+pid+"_"+opt+"_content"; 599: 600: if (oid == opt) 601: spans[i].className = "pane_option_selected"; 602: else 603: spans[i].className = "pane_option"; 604: // Always hide the divs to avoid duplicate display 605: document.getElementById(contentid).className = "pane_content_hidden"; 606: } 607: 608: var contentid = "pane_"+pid+"_"+oid+"_content"; 609: document.getElementById(contentid).className = "pane_content"; 610: 611: } 612: 613: // Open new create request window 614: this.createRequest = function(reqclass) 615: { 616: if (reqclass == undefined) 617: var reqclass = ""; 618: 619: var url = "request.php?"; 620: if (reqclass != "") 621: url += "class="+reqclass+"&"; 622: url += "sid="+DESK.sid; 623: 624: DESK.openWindow("FreeDESK Request", url); 625: } 626: 627: // Debug data output 628: this.debugData = function(container, session) 629: { 630: var out = "Client-Side JavaScript Debug

";
631: if (session == DESK.sid) 632: out += "Session IDs match server and client side

";
633: else 634: out += "Session ID mis-match between client and server

";
635: 636: document.getElementById(container).innerHTML = out; 637: } 638: 639: // Relogin (use current SID and re-post login form) 640: this.relogin = function() 641: { 642: document.forms['login_sid_form'].elements['sid'].value = DESK.sid; 643: document.forms['login_sid_form'].submit(); 644: } 645: 646: // Start Auto-refreshing 647: this.startRefresh = function(interval) 648: { 649: if (interval == undefined) 650: var interval = 30; 651: interval = interval * 1000; 652: 653: DESK.refreshEvent = setInterval( 654: function(){ DESK.mainPaneRefresh(); }, 655: interval ); 656: } 657: 658: // Stop Auto-refreshing 659: this.stopRefresh = function() 660: { 661: clearInterval(DESK.refreshEvent); 662: } 663: 664: this.toSeconds = function(hours, minutes, seconds) 665: { 666: var totalSeconds = (hours * 60 * 60); 667: totalSeconds += (minutes * 60); 668: totalSeconds += (seconds); 669: return totalSeconds; 670: } 671: 672: this.toHMS = function(totalSeconds) 673: { 674: var hours = 0; 675: var minutes = 0; 676: var seconds = 0; 677: 678: if (totalSeconds >= 60*60) 679: { 680: hours = (totalSeconds/(60*60)); 681: totalSeconds -= (hours*60*60); 682: } 683: 684: if (totalSeconds >= 60) 685: { 686: minutes = (totalSeconds/60); 687: totalSeconds -= (minutes*60); 688: } 689: 690: seconds = totalSeconds; 691: 692: var out = new Array(); 693: 694: out[0] = hours; 695: out[1] = minutes; 696: out[2] = seconds; 697: 698: return out; 699: } 700: 701: 702: // Convert Form H:M:S fields to seconds field 703: this.formToSeconds = function(formid, hField, mField, sField, secondsField) 704: { 705: var hours = (document.forms[formid][hField].value == "") ? 0 : parseInt(document.forms[formid][hField].value); 706: var minutes = (document.forms[formid][mField].value == "") ? 0 : parseInt(document.forms[formid][mField].value); 707: var seconds = (document.forms[formid][sField].value == "") ? 0 : parseInt(document.forms[formid][sField].value); 708: document.forms[formid][secondsField].value = this.toSeconds(hours, minutes, seconds); 709: } 710: 711: // Convert Form Seconds to H:M:S 712: this.formToHMS = function(formid, hField, mField, sField, secondsField) 713: { 714: var hms = this.toHMS(parseInt(document.forms[formid][secondsField].value)); 715: document.forms[formid][hField].value = hms[0]; 716: document.forms[formid][mField].value = hms[1]; 717: document.forms[formid][sField].value = hms[2]; 718: } 719: 720: // Go to the mobile interface 721: this.goMobile = function() 722: { 723: window.location.href = "mobile/?sid="+DESK.sid; 724: } 725: } 726: 727: var DESK = new FreeDESK(); 728: 729: