comparison genajax.js @ 1069:5f92fa5e683a

Refactor how the "AJAX" stuff works.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 24 Jan 2017 17:25:48 +0200
parents ajax.js@82ecea33c477
children 7da8bde9b7be
comparison
equal deleted inserted replaced
1068:50d005dd22d8 1069:5f92fa5e683a
1 //
2 // FAPWeb - Simple Web-based Demoparty Management System
3 // Common JavaScript / AJAX code
4 // (C) Copyright 2012-2015 Tecnic Software productions (TNSP)
5 //
6 var jsMessageBoxCBCancel = null, jsMessageBoxCBData = null, jsMessageBoxCBOK = null;
7 var jsUploadCBS = [];
8
9
10 function jsHandleMessageBoxKeys(ev)
11 {
12 ev = ev || window.event;
13 var key = ev.keyCode ? ev.keyCode : ev.which;
14 if (key == 27)
15 {
16 jsCloseMessageBox(jsMessageBoxCBCancel, jsMessageBoxCBData);
17 return false;
18 }
19 else
20 return true;
21 }
22
23
24 function jsSetMessageBoxCBs(cb_ok, cb_cancel, cb_data)
25 {
26 jsMessageBoxCBOK = cb_ok;
27 jsMessageBoxCBCancel = cb_cancel;
28 jsMessageBoxCBData = cb_data;
29 }
30
31
32 function jsCloseMessageBox(callback, cb_data)
33 {
34 var nitem = document.getElementById("messageBox");
35 if (nitem)
36 {
37 document.onkeydown = null;
38 jsSetMessageBoxCBs(null, null, null);
39
40 if (nitem.style.display != "none")
41 {
42 nitem.style.display = "none";
43
44 if (callback && typeof(callback) === "function")
45 callback(cb_data);
46 }
47 }
48 }
49
50
51 function jsMessageBox(msg)
52 {
53 var nitem = document.getElementById("messageBox");
54 if (nitem)
55 {
56 nitem.innerHTML = "<div class='messageBoxInner'>"+ msg +
57 "<div class='messageBoxControls'>"+
58 "<input id='msgBoxConfirmClose' type='button' value=' OK '>"+
59 "</div></div>";
60
61 document.onkeydown = jsHandleMessageBoxKeys;
62 jsSetMessageBoxCBs(null, null, null);
63
64 var elem = document.getElementById("msgBoxConfirmClose");
65 elem.onclick = function () { jsCloseMessageBox(0, 0); }
66
67 nitem.style.display = "block";
68 }
69 }
70
71
72 function jsErrorMessageBox(msg)
73 {
74 jsMessageBox("<h1>Error!</h1><div>"+msg+"</div>");
75 }
76
77
78 function jsTitleMessageBox(title, msg)
79 {
80 jsMessageBox("<h1>"+title+"</h1><div>"+msg+"</div>");
81 }
82
83
84 function jsConfirmBox(msg, cb_ok, cb_cancel, cb_data)
85 {
86 var nitem = document.getElementById("messageBox");
87 if (nitem)
88 {
89 nitem.innerHTML = "<div class='messageBoxInner'><h1>Confirmation</h1><p>"+ msg +"</p>"+
90 "<div class='messageBoxControls'>"+
91 "<input id='msgBoxConfirmCancel' type='button' value=' Cancel '>"+
92 "<input id='msgBoxConfirmOK' type='button' value=' OK '>"+
93 "</div></div>";
94
95 document.onkeydown = jsHandleMessageBoxKeys;
96 jsSetMessageBoxCBs(cb_ok, cb_cancel, cb_data);
97
98 var elem = document.getElementById("msgBoxConfirmCancel");
99 elem.onclick = function () { jsCloseMessageBox(cb_cancel, cb_data); }
100
101 elem = document.getElementById("msgBoxConfirmOK");
102 elem.onclick = function () { jsCloseMessageBox(cb_ok, cb_data); }
103
104 nitem.style.display = "block";
105 }
106 }
107
108
109 function jsStatusMsg(msg)
110 {
111 var nitem = document.getElementById("nstatus");
112 if (nitem) nstatus.innerHTML = msg;
113 }
114
115
116 function strtrim(str)
117 {
118 if (!str || str == null)
119 return "";
120 return str.replace(/^\s+|\s+$/g,'')
121 }
122
123
124 function strencode(str)
125 {
126 return encodeURIComponent(str);
127 }
128
129
130 function jsCreateXMLRequest()
131 {
132 var req;
133 if (window.XMLHttpRequest)
134 {
135 // Modern browsers
136 req = new XMLHttpRequest();
137 }
138 else
139 {
140 // Old IE versions
141 req = new ActiveXObject("Microsoft.XMLHTTP");
142 }
143 return req;
144 }
145
146
147 //
148 // Function for creating AJAX POST request arguments list based
149 // on fields and giving them specified types. Also basic check
150 // for validity can be performed (e.g. field empty or not)
151 //
152 var lastPostArgs = Object();
153 function jsMakePostArgs(fields, fprefix, fsuffix, nofail)
154 {
155 var res = [];
156 lastPostArgs = Object();
157
158 for (var id in fields)
159 {
160 var elname = fprefix + id + fsuffix;
161 switch (fields[id])
162 {
163 case 4:
164 elname += "Sel";
165 break;
166 }
167
168 var elem = document.getElementById(elname);
169 if (!elem && !nofail)
170 {
171 jsErrorMessageBox("No such DOM element '"+ elname +"'.");
172 return "";
173 }
174
175 if (elem)
176 {
177 switch (fields[id])
178 {
179 case 1:
180 var vstr = strtrim(elem.value);
181 res.push(id+"="+strencode(vstr));
182 lastPostArgs[id] = vstr;
183 break;
184
185 case 2:
186 var vint = parseInt(strtrim(elem.value));
187 res.push(id+"="+vint);
188 lastPostArgs[id] = vint;
189 break;
190
191 case 3:
192 res.push(id+"="+(elem.checked ? "1" : "0"));
193 lastPostArgs[id] = elem.checked;
194 break;
195
196 case 4:
197 var vval = (elem.selectedIndex != -1) ? elem.options[elem.selectedIndex].value : -1;
198 res.push(id+"="+vval);
199 lastPostArgs[id] = vval;
200 break;
201
202 default:
203 jsErrorMessageBox("Unsupported field type in "+ elname);
204 return "";
205 }
206 }
207 }
208 return res.join("&");
209 }
210
211
212 function jsGetValue(elname, eltype)
213 {
214 var elem = document.getElementById(elname);
215 if (!elem)
216 {
217 jsErrorMessageBox("No such DOM element '"+ elname +"'.");
218 return "";
219 }
220
221 switch (eltype)
222 {
223 case 1:
224 var vstr = strtrim(elem.value);
225 return strencode(vstr);
226
227 case 2:
228 var vint = parseInt(strtrim(elem.value));
229 return vint;
230
231 case 3:
232 return elem.checked ? "1" : "0";
233
234 case 4:
235 if (elem.selectedIndex != -1)
236 return elem.options[elem.selectedIndex].value;
237 else
238 return null;
239
240 default:
241 jsErrorMessageBox("Unsupported field type in "+ elname);
242 return "";
243 }
244 }
245
246
247 function jsShowPreviewImage(file)
248 {
249 var nitem = document.getElementById("messageBox");
250 if (nitem)
251 {
252 nitem.innerHTML = "<div class='imageBoxInner'>"+
253 "<img src='"+file+"' alt='"+file+"' />"+
254 "</div>";
255
256 var elem = document.getElementById("messageBox");
257 elem.onclick = function () { jsCloseMessageBox(0, 0); }
258
259 nitem.style.display = "block";
260
261 return false;
262 }
263
264 return true;
265 }
266
267
268 function jsFormatSize(bytes)
269 {
270 var suffixes = ["Bytes", "KiB", "MiB"];
271 var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
272 return (bytes / Math.pow(1024, i)).toFixed(1) +' '+ suffixes[i];
273 }
274
275
276 function jsStartFileUpload(formID, formTarget, fileSelID, fileMaxSize, fileCallback)
277 {
278 var formFile = document.getElementById(fileSelID).files[0];
279 if (!formFile || typeof(formFile) !== "object")
280 {
281 jsErrorMessageBox("No file selected to be uploaded.");
282 return;
283 }
284
285 if (formFile.size > fileMaxSize)
286 {
287 jsErrorMessageBox("File size exceeds "+ jsFormatSize(fileMaxSize) +".");
288 return;
289 }
290
291 var filename = formFile.name;
292 var formElem = document.getElementById(formID);
293 if (!formElem)
294 {
295 jsErrorMessageBox("File upload form '"+ formID +"' element not found!");
296 return;
297 }
298
299 var formData = new FormData(formElem);
300 var req = jsCreateXMLRequest();
301 req.upload.addEventListener("progress", function(e)
302 {
303 if (e.lengthComputable)
304 {
305 var complete = Math.round(e.loaded * 100 / e.total);
306 if (complete < 100)
307 jsStatusMsg("Uploaded ["+filename+"] "+ complete.toString() +'%, '+ jsFormatSize(e.loaded));
308 else
309 jsStatusMsg("Upload ["+filename+"] finished ...");
310 }
311 }, false);
312 req.addEventListener("error", function(e)
313 {
314 jsErrorMessageBox("Error occured while uploading "+filename);
315 }, false);
316 req.addEventListener("abort", function(e)
317 {
318 jsStatusMsg("Upload of '"+filename+"' aborted.");
319 }, false);
320
321 req.onreadystatechange = function()
322 {
323 if (req.readyState == 4)
324 {
325 switch (req.status)
326 {
327 case 902:
328 jsStatusMsg(req.statusText);
329 jsMessageBox(req.responseText);
330 break;
331
332 case 903:
333 {
334 var nitem = document.getElementById("messageBox");
335 if (nitem)
336 {
337 nitem.innerHTML = "<div class='messageBoxInner'>"+ req.responseText +
338 "<div class='messageBoxControls'>"+
339 "</div></div>";
340 nitem.style.display = "block";
341 }
342 }
343 break;
344
345 case 200:
346 if (fileCallback)
347 {
348 var tid = setTimeout(function(qtid)
349 {
350 jsRemoveUploadCB(qtid);
351 setTimeout(fileCallback, 10);
352 //jsTitleMessageBox("File upload", req.responseText);
353 }, 10, qtid);
354 jsUploadCBS.push(tid);
355 }
356 break;
357
358 default:
359 jsStatusMsg("["+req.status+" - "+req.statusText+"] "+ req.responseText);
360 break;
361 }
362 }
363 }
364
365 req.open("POST", formTarget);
366 req.send(formData);
367 }
368
369
370 function jsCancelUploadCBS()
371 {
372 if (jsUploadCBS.length > 0)
373 {
374 for (var tid in jsUploadCBS)
375 clearTimeout(tid);
376 }
377 }
378
379
380 function jsRemoveUploadCB(tid)
381 {
382 var index = jsUploadCBS.indexOf(tid);
383 if (index >= 0)
384 jsUploadCBS.splice(index, 1);
385 }