File:
0.01.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: //alert(url);
420: if (xsize == undefined)
421: var xsize = 700;
422: if (ysize == undefined)
423: var ysize = 500;
424:
425: if (resizeable == undefined)
426: var resizeable = 1;
427: else if(resizeable)
428: resizeable=1;
429: else if(!resizeable)
430: resizable=0;
431:
432: var windowopts = "location=0,status=0,scrollbars=1,toolbar=0,width="+xsize+",height="+ysize+",resizeable="+resizeable;
433:
434: window.open(url, '', windowopts);
435: }
436:
437: // Perform an entity search
438: this.entitySearch = function(entity, callback, fields)
439: {
440: var url = "entity.php?mode=search&entity="+entity;
441:
442: if (callback != undefined)
443: url += "&callback="+callback;
444: if (fields != undefined)
445: {
446: for (var i=0; i447: {
448: url += "&" + fields[i][0] + "=" + fields[i][1]; // escape?
449: }
450: }
451: url += "&sid=" + this.sid;
452:
453: this.openWindow("Search "+entity, url);
454: }
455:
456: // Open Edit Entity
457: this.editEntity = function(entity, keyfield, keyfieldValue)
458: {
459: var url = "entity.php?mode=edit&entity="+entity+"&keyfield="+keyfield+"&value="+keyfieldValue;
460: url += "&sid=" + this.sid;
461:
462: this.openWindow("Edit "+entity, url);
463: }
464:
465: // Perform an entity creation
466: this.entityCreate = function(entity, callback)
467: {
468: var url = "entity.php?mode=create&entity="+entity;
469:
470: if (callback != undefined)
471: url += "&callback="+callback;
472:
473: url += "&sid=" + this.sid;
474:
475: this.openWindow("Create "+entity, url);
476: }
477:
478: // Convert form to query string
479: this.formToQuery = function(formid)
480: {
481: var data = "";
482:
483: function add(name, value)
484: {
485: if (value == undefined)
486: var value = "";
487:
488: data += (data.length > 0 ? "&" : ""); // add & if required
489:
490: data += escape(name).replace(/\+/g, "%2B") + "=";
491:
492: data += escape(value).replace(/\+/g, "%2B");
493: }
494:
495: var form = document.forms[formid];
496: if (!form)
497: return "";
498: var elements = form.elements;
499:
500: for (var i=0; i501: {
502: var element = elements[i];
503: var type = element.type.toLowerCase();
504: var name = element.name;
505:
506: if (name)
507: {
508: if ( type == "text" || type == "password" ||
509: type == "button" || type == "reset" ||
510: type == "file" || type == "submit" ||
511: type == "image" || type == "hidden" ||
512: type == "textarea" )
513: add(name, element.value);
514:
515: else if ( type == "checkbox" && element.checked )
516: add(name, element.value ? element.value : "On");
517:
518: else if ( type == "radio" && element.checked)
519: add(name, element.value);
520:
521: else if ( type.indexOf("select") != -1 )
522: {
523: for (var x=0; x524: {
525: var opt = element.options[x];
526: if (opt.selected)
527: add(name, opt.value ? opt.value : opt.text);
528: }
529: }
530: }
531: }
532:
533: return data;
534: }
535:
536: // API Form Action e.g. save entity
537: this.formAPI = function(formid, closeOnComplete, reloadOnComplete, callbackOnComplete)
538: {
539: if (closeOnComplete == undefined)
540: var closeOnComplete = false;
541: if (reloadOnComplete == undefined)
542: var reloadOnComplete = false;
543: if (callbackOnComplete == undefined)
544: var callbackOnComplete = false;
545:
546:
547: var q = DESK.formToQuery(formid);
548:
549: q += "&sid=" + DESK.sid;
550:
551: var sr = new ServerRequest();
552: sr.url = "api.php";
553: sr.callback = DESK.formAPIcallback;
554: sr.additional = new Array();
555: sr.additional[0] = closeOnComplete;
556: sr.additional[1] = reloadOnComplete;
557: sr.additional[2] = callbackOnComplete;
558: sr.Post(q);
559: }
560:
561: this.formAPIcallback = function(xml, additional)
562: {
563: if (DESK.isError(xml))
564: {
565: Alerts.add(DESK.getError(xml), 2, 10);
566: }
567: else
568: {
569: // We got this far - no DESK error or XML error so we can say success!
570: Alerts.add("Operation Successful", 0);
571:
572: if (additional[2]) // do the javascript first if there is any
573: {
574: additional[2](xml);
575: }
576:
577: if (additional[0])
578: window.close();
579: else if (additional[1])
580: window.location.reload();
581: }
582: }
583:
584: // Switch a pane
585: this.paneSwitch = function(pid, oid)
586: {
587: var pane = document.getElementById("pane_"+pid);
588: var header = document.getElementById("pane_"+pid+"_header");
589:
590: var child = header.firstChild;
591:
592: var spans = header.getElementsByTagName("SPAN");
593:
594: for (var i=0; i595: {
596: var arr = spans[i].id.split("_");
597: var opt = arr[arr.length-1];
598:
599: var contentid = "pane_"+pid+"_"+opt+"_content";
600:
601: if (oid == opt)
602: spans[i].className = "pane_option_selected";
603: else
604: spans[i].className = "pane_option";
605: // Always hide the divs to avoid duplicate display
606: document.getElementById(contentid).className = "pane_content_hidden";
607: }
608:
609: var contentid = "pane_"+pid+"_"+oid+"_content";
610: document.getElementById(contentid).className = "pane_content";
611:
612: }
613:
614: // Open new create request window
615: this.createRequest = function(reqclass)
616: {
617: if (reqclass == undefined)
618: var reqclass = "";
619:
620: var url = "request.php?";
621: if (reqclass != "")
622: url += "class="+reqclass+"&";
623: url += "sid="+DESK.sid;
624:
625: DESK.openWindow("FreeDESK Request", url);
626: }
627:
628: // Debug data output
629: this.debugData = function(container, session)
630: {
631: var out = "Client-Side JavaScript Debug
";
632: if (session == DESK.sid)
633: out += "Session IDs match server and client side
";
634: else
635: out += "Session ID mis-match between client and server
";
636:
637: document.getElementById(container).innerHTML = out;
638: }
639:
640: // Relogin (use current SID and re-post login form)
641: this.relogin = function()
642: {
643: document.forms['login_sid_form'].elements['sid'].value = DESK.sid;
644: document.forms['login_sid_form'].submit();
645: }
646:
647: // Start Auto-refreshing
648: this.startRefresh = function(interval)
649: {
650: if (interval == undefined)
651: var interval = 30;
652: interval = interval * 1000;
653:
654: DESK.refreshEvent = setInterval(
655: function(){ DESK.mainPaneRefresh(); },
656: interval );
657: }
658:
659: // Stop Auto-refreshing
660: this.stopRefresh = function()
661: {
662: clearInterval(DESK.refreshEvent);
663: }
664:
665: this.toSeconds = function(hours, minutes, seconds)
666: {
667: var totalSeconds = (hours * 60 * 60);
668: totalSeconds += (minutes * 60);
669: totalSeconds += (seconds);
670: return totalSeconds;
671: }
672:
673: this.toHMS = function(totalSeconds)
674: {
675: var hours = 0;
676: var minutes = 0;
677: var seconds = 0;
678:
679: if (totalSeconds >= 60*60)
680: {
681: hours = (totalSeconds/(60*60));
682: totalSeconds -= (hours*60*60);
683: }
684:
685: if (totalSeconds >= 60)
686: {
687: minutes = (totalSeconds/60);
688: totalSeconds -= (minutes*60);
689: }
690:
691: seconds = totalSeconds;
692:
693: var out = new Array();
694:
695: out[0] = hours;
696: out[1] = minutes;
697: out[2] = seconds;
698:
699: return out;
700: }
701:
702:
703: // Convert Form H:M:S fields to seconds field
704: this.formToSeconds = function(formid, hField, mField, sField, secondsField)
705: {
706: var hours = (document.forms[formid][hField].value == "") ? 0 : parseInt(document.forms[formid][hField].value);
707: var minutes = (document.forms[formid][mField].value == "") ? 0 : parseInt(document.forms[formid][mField].value);
708: var seconds = (document.forms[formid][sField].value == "") ? 0 : parseInt(document.forms[formid][sField].value);
709: document.forms[formid][secondsField].value = this.toSeconds(hours, minutes, seconds);
710: }
711:
712: // Convert Form Seconds to H:M:S
713: this.formToHMS = function(formid, hField, mField, sField, secondsField)
714: {
715: var hms = this.toHMS(parseInt(document.forms[formid][secondsField].value));
716: document.forms[formid][hField].value = hms[0];
717: document.forms[formid][mField].value = hms[1];
718: document.forms[formid][sField].value = hms[2];
719: }
720:
721: // Go to the mobile interface
722: this.goMobile = function()
723: {
724: window.location.href = "mobile/?sid="+DESK.sid;
725: }
726: }
727:
728: var DESK = new FreeDESK();
729:
730: