File:
0.00.3a/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: