Rev 1408 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4 | daniel-mar | 1 | /* |
2 | * OIDplus 2.0 |
||
781 | daniel-mar | 3 | * Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft |
4 | daniel-mar | 4 | * |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
||
6 | * you may not use this file except in compliance with the License. |
||
7 | * You may obtain a copy of the License at |
||
8 | * |
||
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
||
10 | * |
||
11 | * Unless required by applicable law or agreed to in writing, software |
||
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
||
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
14 | * See the License for the specific language governing permissions and |
||
15 | * limitations under the License. |
||
16 | */ |
||
17 | |||
9 | daniel-mar | 18 | /*jshint esversion: 6 */ |
19 | |||
219 | daniel-mar | 20 | // $('#html').jstree(); |
21 | |||
833 | daniel-mar | 22 | var bs5Utils = undefined; |
23 | |||
219 | daniel-mar | 24 | var current_node = ""; |
25 | var popstate_running = false; |
||
362 | daniel-mar | 26 | // DEFAULT_LANGUAGE will be set by oidplus.min.js.php |
360 | daniel-mar | 27 | // language_messages will be set by oidplus.min.js.php |
28 | // language_tblprefix will be set by oidplus.min.js.php |
||
424 | daniel-mar | 29 | // csrf_token will be set by oidplus.min.js.php |
561 | daniel-mar | 30 | // samesite_policy will bet set by oidplus.min.js.php |
219 | daniel-mar | 31 | |
399 | daniel-mar | 32 | var pageChangeCallbacks = []; |
33 | var pageChangeRequestCallbacks = []; |
||
34 | |||
839 | daniel-mar | 35 | var pageLoadedCallbacks= { |
876 | daniel-mar | 36 | "anyPageLoad": [], // this is processed inside both AJAX successful reload and document.ready (at the very end) |
839 | daniel-mar | 37 | "ajaxPageLoad": [], // inside AJAX successful reload only |
38 | "documentReadyBefore": [], // inside document.ready, in the very beginning of the function |
||
39 | "documentReadyAfter": [] // inside document.ready, in the very end of the function |
||
40 | }; |
||
833 | daniel-mar | 41 | |
819 | daniel-mar | 42 | var oidplus_menu_width = 450; // In pixels. You can change this at runtime because of the glayoutWorkaroundB() workaround |
818 | daniel-mar | 43 | |
839 | daniel-mar | 44 | function executeAllCallbacks(functionsArray) { |
45 | functionsArray.forEach( |
||
46 | function(fel) { |
||
47 | if (typeof fel == 'function') fel(); |
||
48 | } |
||
49 | ); |
||
50 | } |
||
51 | |||
112 | daniel-mar | 52 | function getOidPlusSystemTitle() { |
360 | daniel-mar | 53 | return getMeta('OIDplus-SystemTitle'); // do not translate |
112 | daniel-mar | 54 | } |
55 | |||
5 | daniel-mar | 56 | function combine_systemtitle_and_pagetitle(systemtitle, pagetitle) { |
309 | daniel-mar | 57 | // Please also change the function in index.php |
5 | daniel-mar | 58 | if (systemtitle == pagetitle) { |
59 | return systemtitle; |
||
60 | } else { |
||
309 | daniel-mar | 61 | return pagetitle + ' - ' + systemtitle; |
5 | daniel-mar | 62 | } |
63 | } |
||
64 | |||
385 | daniel-mar | 65 | function getSystemUrl(relative) { |
1287 | daniel-mar | 66 | relative = (typeof relative === 'undefined') ? false : relative; // do not translate |
385 | daniel-mar | 67 | var url = new URL(window.location.href); |
1287 | daniel-mar | 68 | var res = relative ? url.pathname : url.href.substr(0, url.href.length-url.search.length); |
69 | if (res.endsWith("index.php")) res = res.substring(0, res.lastIndexOf('/')) + "/"; |
||
70 | return res; |
||
385 | daniel-mar | 71 | } |
72 | |||
2 | daniel-mar | 73 | function getTreeLoadURL() { |
74 | var url = new URL(window.location.href); |
||
75 | var goto = url.searchParams.get("goto"); |
||
641 | daniel-mar | 76 | return (goto != null) ? "ajax.php?csrf_token="+encodeURIComponent(csrf_token)+"&action=tree_load&anticache="+Date.now()+"&goto="+encodeURIComponent(goto) |
77 | : "ajax.php?csrf_token="+encodeURIComponent(csrf_token)+"&action=tree_load&anticache="+Date.now(); |
||
2 | daniel-mar | 78 | } |
79 | |||
80 | function reloadContent() { |
||
154 | daniel-mar | 81 | // window.location.href = "?goto="+encodeURIComponent(current_node); |
399 | daniel-mar | 82 | if (openOidInPanel(current_node, false)) { |
450 | daniel-mar | 83 | if(!$('#oidtree').jstree(true).get_node(current_node)) { |
84 | // Avoid that a language change at "oidplus:srvreg_status" won't redirect the user to "oidplus:srv_registration" because of the reselection during refresh |
||
85 | $('#oidtree').jstree("deselect_all"); |
||
86 | } |
||
87 | |||
399 | daniel-mar | 88 | $('#oidtree').jstree("refresh"); |
89 | } |
||
2 | daniel-mar | 90 | } |
91 | |||
107 | daniel-mar | 92 | function x_rec(x_data, i) { |
93 | $('#oidtree').jstree('open_node', x_data[i], function(e, data) { |
||
94 | if (i+1 < x_data.length) { |
||
95 | x_rec(x_data, i+1); |
||
96 | } else { |
||
114 | daniel-mar | 97 | popstate_running = true; // don't call openOidInPanel again |
98 | try { |
||
99 | $('#oidtree').jstree('select_node', x_data[i]); |
||
100 | } catch (err) { |
||
101 | popstate_running = false; |
||
102 | } finally { |
||
103 | popstate_running = false; |
||
104 | } |
||
107 | daniel-mar | 105 | } |
106 | }); |
||
107 | } |
||
2 | daniel-mar | 108 | |
399 | daniel-mar | 109 | function performCloseQueryCB() { |
110 | for (var i=0; i<pageChangeRequestCallbacks.length; i++) { |
||
111 | if (!pageChangeRequestCallbacks[i][0](pageChangeRequestCallbacks[i][1])) return false; |
||
112 | } |
||
113 | pageChangeRequestCallbacks = []; |
||
114 | return true; // may close |
||
115 | } |
||
116 | |||
117 | function performCloseCB() { |
||
118 | for (var i=0; i<pageChangeCallbacks.length; i++) { |
||
119 | pageChangeCallbacks[i][0](pageChangeCallbacks[i][1]); |
||
120 | } |
||
121 | pageChangeCallbacks = []; |
||
122 | } |
||
123 | |||
124 | function openOidInPanel(id, reselect/*=false*/, anchor/*=''*/, force/*=false*/) { |
||
699 | daniel-mar | 125 | reselect = (typeof reselect === 'undefined') ? false : reselect; // do not translate |
126 | anchor = (typeof anchor === 'undefined') ? '' : anchor; // do not translate |
||
127 | force = (typeof force === 'undefined') ? false : force; // do not translate |
||
150 | daniel-mar | 128 | |
399 | daniel-mar | 129 | var mayClose = performCloseQueryCB(); |
130 | if (!force && !mayClose) return false; |
||
131 | |||
132 | performCloseCB(); |
||
405 | daniel-mar | 133 | |
704 | daniel-mar | 134 | $.xhrPool.abortAll(); |
135 | |||
107 | daniel-mar | 136 | if (reselect) { |
2 | daniel-mar | 137 | $('#oidtree').jstree('deselect_all'); |
107 | daniel-mar | 138 | |
114 | daniel-mar | 139 | popstate_running = true; // don't call openOidInPanel during tree selection |
140 | try { |
||
141 | // If the node is already loaded in the tree, select it |
||
142 | if (!$('#oidtree').jstree('select_node', id)) { |
||
143 | // If the node is not loaded, then we try to search it. |
||
144 | // If it can be found, then open all parent nodes and select the node |
||
145 | $.ajax({ |
||
146 | url:"ajax.php", |
||
147 | method:"POST", |
||
544 | daniel-mar | 148 | beforeSend: function(jqXHR, settings) { |
704 | daniel-mar | 149 | //$.xhrPool.abortAll(); |
544 | daniel-mar | 150 | $.xhrPool.add(jqXHR); |
151 | }, |
||
152 | complete: function(jqXHR, text) { |
||
153 | $.xhrPool.remove(jqXHR); |
||
154 | }, |
||
114 | daniel-mar | 155 | data:{ |
424 | daniel-mar | 156 | csrf_token:csrf_token, |
114 | daniel-mar | 157 | action:"tree_search", |
641 | daniel-mar | 158 | search:id, |
159 | anticache:Date.now() |
||
114 | daniel-mar | 160 | }, |
161 | error:function(jqXHR, textStatus, errorThrown) { |
||
544 | daniel-mar | 162 | if (errorThrown == "abort") return; |
797 | daniel-mar | 163 | console.error("Tree search failed"); |
360 | daniel-mar | 164 | console.error(_L("Error: %1",errorThrown)); |
114 | daniel-mar | 165 | }, |
166 | success:function(data) { |
||
1447 | daniel-mar | 167 | if (typeof data === "object" && "error" in data) { |
797 | daniel-mar | 168 | console.error("Tree search failed"); |
114 | daniel-mar | 169 | console.error(data); |
170 | } else if ((data instanceof Array) && (data.length > 0)) { |
||
171 | x_rec(data, 0); |
||
172 | } else { |
||
797 | daniel-mar | 173 | console.error("Tree search failed"); |
114 | daniel-mar | 174 | console.error(data); |
175 | } |
||
176 | } |
||
177 | }); |
||
107 | daniel-mar | 178 | } |
114 | daniel-mar | 179 | } catch (err) { |
180 | popstate_running = false; |
||
181 | } finally { |
||
182 | popstate_running = false; |
||
183 | } |
||
2 | daniel-mar | 184 | } |
185 | |||
114 | daniel-mar | 186 | // This loads the actual content |
187 | |||
405 | daniel-mar | 188 | // document.title = ""; // <-- we may not do this, otherwise Firefox won't |
189 | // show titles in the browser history (right-click |
||
190 | // on back-button), although document.title() is |
||
499 | daniel-mar | 191 | // set inside the AJAX-callback [Firefox bug?!] |
405 | daniel-mar | 192 | |
2 | daniel-mar | 193 | $('#real_title').html(" "); |
355 | daniel-mar | 194 | $('#real_content').html(_L("Loading...")); |
1289 | daniel-mar | 195 | $('#static_link').attr("href", oidplus_webpath_absolute_canonical+"?goto="+encodeURIComponent(id)); |
183 | daniel-mar | 196 | $("#gotoedit").val(id); |
2 | daniel-mar | 197 | |
198 | // Normal opening of a description |
||
560 | daniel-mar | 199 | $.ajax({ |
200 | url:"ajax.php", |
||
201 | method:"GET", |
||
202 | beforeSend: function(jqXHR, settings) { |
||
704 | daniel-mar | 203 | //$.xhrPool.abortAll(); |
560 | daniel-mar | 204 | $.xhrPool.add(jqXHR); |
205 | }, |
||
206 | complete: function(jqXHR, text) { |
||
207 | $.xhrPool.remove(jqXHR); |
||
208 | }, |
||
209 | data:{ |
||
210 | csrf_token:csrf_token, |
||
211 | action:"get_description", |
||
641 | daniel-mar | 212 | id:id, |
213 | anticache:Date.now() |
||
560 | daniel-mar | 214 | }, |
215 | error:function(jqXHR, textStatus, errorThrown) { |
||
216 | if (errorThrown == "abort") return; |
||
833 | daniel-mar | 217 | alertError(_L("Failed to load content: %1",errorThrown)); |
560 | daniel-mar | 218 | console.error(_L("Error: %1",errorThrown)); |
219 | }, |
||
220 | success:function(data) { |
||
1292 | daniel-mar | 221 | // TODO: Use oidplus_ajax_success(), since this checks the existance of "error" in data, and checks if status>=0 |
1447 | daniel-mar | 222 | if (typeof data === "object" && "error" in data) { |
223 | console.error(data.error); |
||
833 | daniel-mar | 224 | alertError(_L("Failed to load content: %1",data.error)); |
1447 | daniel-mar | 225 | } else if (typeof data === "object" && "status" in data && data.status >= 0) { |
1400 | daniel-mar | 226 | if (!("id" in data)) data.id = id; |
107 | daniel-mar | 227 | |
560 | daniel-mar | 228 | var state = { |
1400 | daniel-mar | 229 | "node_id":data.id, |
560 | daniel-mar | 230 | "titleHTML":(data.icon ? '<img src="'+data.icon+'" width="48" height="48" alt="'+data.title.htmlentities()+'"> ' : '') + data.title.htmlentities(), |
231 | "textHTML":data.text, |
||
1400 | daniel-mar | 232 | "staticlinkHREF":oidplus_webpath_absolute_canonical+"?goto="+encodeURIComponent(data.id), |
560 | daniel-mar | 233 | }; |
1400 | daniel-mar | 234 | if (current_node != data.id) { |
235 | window.history.pushState(state, data.title, "?goto="+encodeURIComponent(data.id)); |
||
560 | daniel-mar | 236 | } else { |
1400 | daniel-mar | 237 | window.history.replaceState(state, data.title, "?goto="+encodeURIComponent(data.id)); |
560 | daniel-mar | 238 | } |
2 | daniel-mar | 239 | |
560 | daniel-mar | 240 | document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.title); |
2 | daniel-mar | 241 | |
560 | daniel-mar | 242 | if (data.icon) { |
243 | $('#real_title').html('<img src="'+data.icon+'" width="48" height="48" alt="'+data.title.htmlentities()+'"> ' + data.title.htmlentities()); |
||
244 | } else { |
||
245 | $('#real_title').html(data.title.htmlentities()); |
||
246 | } |
||
247 | $('#real_content').html(data.text); |
||
248 | document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.title); |
||
1400 | daniel-mar | 249 | current_node = data.id; |
405 | daniel-mar | 250 | |
839 | daniel-mar | 251 | executeAllCallbacks(pageLoadedCallbacks.anyPageLoad); |
252 | executeAllCallbacks(pageLoadedCallbacks.ajaxPageLoad); |
||
833 | daniel-mar | 253 | |
560 | daniel-mar | 254 | if (anchor != '') { |
255 | jumpToAnchor(anchor); |
||
256 | } |
||
1447 | daniel-mar | 257 | } else if (typeof data === "object" && "status" in data && data.status < 0) { |
258 | console.error(data); |
||
259 | alertError(_L("Failed to load content: %1",data.status)); |
||
32 | daniel-mar | 260 | } else { |
560 | daniel-mar | 261 | console.error(data); |
1447 | daniel-mar | 262 | alertError(_L("Failed to load content: %1",data)); |
32 | daniel-mar | 263 | } |
560 | daniel-mar | 264 | } |
2 | daniel-mar | 265 | }); |
399 | daniel-mar | 266 | |
267 | return true; |
||
2 | daniel-mar | 268 | } |
269 | |||
107 | daniel-mar | 270 | // This function opens the "parentID" node, and then selects the "childID" node (which should be beneath the parent node) |
2 | daniel-mar | 271 | function openAndSelectNode(childID, parentID) { |
272 | if ($('#oidtree').jstree(true).get_node(parentID)) { |
||
107 | daniel-mar | 273 | $('#oidtree').jstree('open_node', parentID, function(e, data) { // open parent node |
2 | daniel-mar | 274 | if ($('#oidtree').jstree(true).get_node(childID)) { // is the child there? |
107 | daniel-mar | 275 | $('#oidtree').jstree('deselect_all').jstree('select_node', childID); // select it |
2 | daniel-mar | 276 | } else { |
277 | // This can happen if the content page contains brand new items which are not in the treeview yet |
||
183 | daniel-mar | 278 | $("#gotoedit").val(childID); |
154 | daniel-mar | 279 | window.location.href = "?goto="+encodeURIComponent(childID); |
2 | daniel-mar | 280 | } |
281 | }, true); |
||
282 | } else { |
||
283 | // This should usually not happen |
||
183 | daniel-mar | 284 | $("#gotoedit").val(childID); |
154 | daniel-mar | 285 | window.location.href = "?goto="+encodeURIComponent(childID); |
2 | daniel-mar | 286 | } |
287 | } |
||
288 | |||
289 | $(window).on("popstate", function(e) { |
||
399 | daniel-mar | 290 | if (!performCloseQueryCB()) { |
291 | // TODO: does not work!!! The "back/forward" action will be cancelled, but the browser still thinks it was successful, |
||
292 | // so if you do it again, you will then jump 2 pages back, etc! |
||
293 | // This does also not help: |
||
294 | //window.history.pushState(e.originalEvent.state, e.originalEvent.title, e.originalEvent.url); |
||
295 | //window.history.forward(); |
||
296 | return; |
||
297 | } |
||
298 | |||
2 | daniel-mar | 299 | popstate_running = true; |
300 | try { |
||
301 | var data = e.originalEvent.state; |
||
302 | |||
303 | current_node = data.node_id; |
||
327 | daniel-mar | 304 | $("#gotoedit").val(current_node); |
107 | daniel-mar | 305 | $('#oidtree').jstree('deselect_all').jstree('select_node', data.node_id); |
2 | daniel-mar | 306 | $('#real_title').html(data.titleHTML); |
307 | $('#real_content').html(data.textHTML); |
||
308 | $('#static_link').attr("href", data.staticlinkHREF); |
||
112 | daniel-mar | 309 | document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.titleHTML.html_entity_decode()); |
2 | daniel-mar | 310 | } catch (err) { |
311 | popstate_running = false; |
||
312 | } finally { |
||
313 | popstate_running = false; |
||
314 | } |
||
315 | }); |
||
316 | |||
317 | $(document).ready(function () { |
||
876 | daniel-mar | 318 | |
839 | daniel-mar | 319 | executeAllCallbacks(pageLoadedCallbacks.documentReadyBefore); |
876 | daniel-mar | 320 | |
399 | daniel-mar | 321 | /* |
322 | window.onbeforeunload = function(e) { |
||
323 | // TODO: This won't be called because TinyMCE overrides it?? |
||
324 | // TODO: when the user accepted the query in performCloseQueryCB(), then the message will be shown again by the browser! |
||
325 | if (!performCloseQueryCB()) { |
||
326 | // Cancel the event |
||
327 | e.preventDefault(); // If you prevent default behavior in Mozilla Firefox prompt will always be shown |
||
328 | // Chrome requires returnValue to be set |
||
329 | e.returnValue = ''; |
||
330 | } else { |
||
331 | // the absence of a returnValue property on the event will guarantee the browser unload happens |
||
332 | delete e['returnValue']; |
||
333 | } |
||
334 | }; |
||
335 | */ |
||
214 | daniel-mar | 336 | |
829 | daniel-mar | 337 | if (typeof oidplus_menu_width_uservalue !== 'undefined') { |
338 | oidplus_menu_width = oidplus_menu_width_uservalue; |
||
339 | } |
||
340 | |||
2 | daniel-mar | 341 | // --- JsTree |
342 | |||
1055 | daniel-mar | 343 | if ($('#oidtree').length > 0) $('#oidtree') |
2 | daniel-mar | 344 | .jstree({ |
345 | plugins: ['massload','search','conditionalselect'], |
||
346 | 'core' : { |
||
347 | 'data' : { |
||
348 | "url" : getTreeLoadURL(), |
||
349 | "data" : function (node) { |
||
350 | return { "id" : node.id }; |
||
351 | } |
||
352 | }, |
||
353 | "multiple": false |
||
354 | }, |
||
355 | 'conditionalselect' : function (node) { |
||
68 | daniel-mar | 356 | if (node.original.conditionalselect !== undefined) { |
357 | return eval(node.original.conditionalselect); |
||
2 | daniel-mar | 358 | } else { |
399 | daniel-mar | 359 | return performCloseQueryCB(); |
2 | daniel-mar | 360 | } |
361 | }, |
||
362 | }) |
||
363 | .on('ready.jstree', function (e, data) { |
||
364 | var url = new URL(window.location.href); |
||
365 | var goto = url.searchParams.get("goto"); |
||
366 | if (goto == null) goto = "oidplus:system"; // the page was not called with ?goto=... |
||
1055 | daniel-mar | 367 | if ($('#gotoedit').length > 0) $("#gotoedit").val(goto); |
2 | daniel-mar | 368 | |
107 | daniel-mar | 369 | // By setting current_node, select_node() will not cause ajax.php?action=get_description to load (since we already loaded the first static content via PHP, for search engines mainly) |
2 | daniel-mar | 370 | // But then we need to set the history state manually |
371 | current_node = goto; |
||
100 | daniel-mar | 372 | window.history.replaceState({ |
107 | daniel-mar | 373 | "node_id":goto, |
100 | daniel-mar | 374 | "titleHTML":$('#real_title').html(), |
375 | "textHTML":$('#real_content').html(), |
||
1289 | daniel-mar | 376 | "staticlinkHREF":oidplus_webpath_absolute_canonical+"?goto="+encodeURIComponent(goto), |
113 | daniel-mar | 377 | }, $('#real_title').html(), "?goto="+encodeURIComponent(goto)); |
2 | daniel-mar | 378 | |
379 | if (goto != null) data.instance.select_node([goto]); |
||
128 | daniel-mar | 380 | |
643 | daniel-mar | 381 | setTimeout(glayoutWorkaroundAC, 100); |
137 | daniel-mar | 382 | setTimeout(glayoutWorkaroundB, 100); |
2 | daniel-mar | 383 | }) |
384 | .on('select_node.jstree', function (node, selected, event) { |
||
120 | daniel-mar | 385 | mobileNavClose(); |
95 | daniel-mar | 386 | |
9 | daniel-mar | 387 | var id = selected.node.id; |
114 | daniel-mar | 388 | if ((!popstate_running) && (current_node != id)) { |
399 | daniel-mar | 389 | // 4th argument: we force the reload (because in the |
390 | // conditional select above, we already asked if |
||
391 | // tinyMCE needs to be saved) |
||
392 | openOidInPanel(id, false, '', true); |
||
2 | daniel-mar | 393 | } |
394 | }); |
||
395 | |||
396 | // --- Layout |
||
397 | |||
1055 | daniel-mar | 398 | if ($('#system_title_menu').length > 0) $("#system_title_menu")[0].style.display = "block"; |
120 | daniel-mar | 399 | |
355 | daniel-mar | 400 | var tmpObjectTree = _L("OBJECT TREE").replace(/(.{1})/g,"$1<br>"); |
401 | tmpObjectTree = tmpObjectTree.substring(0, tmpObjectTree.length-"<br>".length); |
||
402 | |||
1055 | daniel-mar | 403 | if ($('#oidtree').length > 0) $('#oidtree').addClass('ui-layout-west'); |
404 | if ($('#content_window').length > 0) $('#content_window').addClass('ui-layout-center'); |
||
405 | if ($('#system_title_bar').length > 0) $('#system_title_bar').addClass('ui-layout-north'); |
||
406 | if ($('#frames').length > 0) glayout = $('#frames').layout({ |
||
120 | daniel-mar | 407 | north__size: 40, |
408 | north__slidable: false, |
||
409 | north__closable: false, |
||
410 | north__resizable: false, |
||
818 | daniel-mar | 411 | west__size: oidplus_menu_width, |
120 | daniel-mar | 412 | west__spacing_closed: 20, |
413 | west__togglerLength_closed: 230, |
||
829 | daniel-mar | 414 | west__togglerAlign_closed: "center", |
355 | daniel-mar | 415 | west__togglerContent_closed: tmpObjectTree, |
416 | west__togglerTip_closed: _L("Open & Pin Menu"), |
||
417 | west__sliderTip: _L("Slide Open Menu"), |
||
120 | daniel-mar | 418 | west__slideTrigger_open: "mouseover", |
1408 | daniel-mar | 419 | west__enableCursorHotkey: false, // disable Ctrl+Shift+LeftArrow hotkey ( see https://github.com/danielmarschall/oidplus/issues/28 ) |
829 | daniel-mar | 420 | center__maskContents: true, // IMPORTANT - enable iframe masking |
1055 | daniel-mar | 421 | onresize_start: function() { if (typeof handle_glayout_onresize_start == 'function') handle_glayout_onresize_start(); } |
120 | daniel-mar | 422 | }); |
183 | daniel-mar | 423 | |
1055 | daniel-mar | 424 | if ($('#gotobox').length == 0) $("#languageBox").css('right', '20px'); // Language Box to the right if there is no goto-box |
425 | |||
426 | if ($('#gotobox').length > 0) $("#gotobox").addClass("mobilehidden"); |
||
427 | if ($('#languageBox').length > 0) $("#languageBox").addClass("mobilehidden"); |
||
428 | if ($('#gotobox').length > 0) $("#gotobox")[0].style.display = "block"; |
||
429 | if ($('#gotoedit').length > 0) $('#gotoedit').keypress(function(event) { |
||
183 | daniel-mar | 430 | var keycode = (event.keyCode ? event.keyCode : event.which); |
431 | if (keycode == '13') { |
||
432 | gotoButtonClicked(); |
||
433 | } |
||
434 | }); |
||
833 | daniel-mar | 435 | |
436 | if (typeof Bs5Utils !== "undefined") { |
||
437 | Bs5Utils.defaults.toasts.position = 'top-center'; |
||
438 | Bs5Utils.defaults.toasts.stacking = true; |
||
439 | bs5Utils = new Bs5Utils(); |
||
440 | } |
||
876 | daniel-mar | 441 | |
839 | daniel-mar | 442 | executeAllCallbacks(pageLoadedCallbacks.anyPageLoad); |
443 | executeAllCallbacks(pageLoadedCallbacks.documentReadyAfter); |
||
376 | daniel-mar | 444 | }); |
2 | daniel-mar | 445 | |
829 | daniel-mar | 446 | // can be overridden if necessary |
447 | var handle_glayout_onresize_start = undefined; |
||
448 | |||
643 | daniel-mar | 449 | function glayoutWorkaroundAC() { |
211 | daniel-mar | 450 | // "Bug A": Sometimes, the design is completely destroyed after reloading the page. It does not help when glayout.resizeAll() |
137 | daniel-mar | 451 | // is called at the beginning (e.g. during the ready function), and it does not help if we wait 500ms. |
452 | // So we do it all the time. It has probably something to do with slow loading times, since the error |
||
453 | // does only appear when the page is "blank" for a short while while it is loading. |
||
454 | glayout.resizeAll(); |
||
287 | daniel-mar | 455 | |
456 | // "Bug C": With Firefox (And sometimes with Chrome), there is a gap between the content-window (including scroll bars) |
||
457 | // and the right corner of the screen. Removing the explicit width solves this problem. |
||
561 | daniel-mar | 458 | $("#content_window")[0].style.removeProperty("width"); |
643 | daniel-mar | 459 | |
460 | setTimeout(glayoutWorkaroundAC, 100); |
||
137 | daniel-mar | 461 | } |
462 | |||
463 | function glayoutWorkaroundB() { |
||
464 | // "Bug B": Sometimes, after reload, weird space between oidtree and content window, because oidtree has size of 438px |
||
818 | daniel-mar | 465 | $("#oidtree")[0].style.width = oidplus_menu_width + "px"; |
137 | daniel-mar | 466 | } |
467 | |||
120 | daniel-mar | 468 | function mobileNavClose() { |
469 | if ($("#system_title_menu").is(":hidden")) { |
||
470 | return; |
||
471 | } |
||
472 | |||
473 | $("#oidtree").slideUp("medium").promise().done(function() { |
||
474 | $("#oidtree").addClass("ui-layout-west"); |
||
475 | $("#oidtree").show(); |
||
185 | daniel-mar | 476 | // $("#gotobox").hide(); |
355 | daniel-mar | 477 | // $("#languageBox").hide(); |
185 | daniel-mar | 478 | $("#gotobox").addClass("mobilehidden"); |
355 | daniel-mar | 479 | $("#languageBox").addClass("mobilehidden"); |
120 | daniel-mar | 480 | }); |
481 | $("#system_title_menu").removeClass("active"); |
||
95 | daniel-mar | 482 | } |
483 | |||
120 | daniel-mar | 484 | function mobileNavOpen() { |
485 | $("#oidtree").hide(); |
||
486 | $("#oidtree").removeClass("ui-layout-west"); |
||
487 | $("#oidtree").slideDown("medium"); |
||
185 | daniel-mar | 488 | // $("#gotobox").show(); |
355 | daniel-mar | 489 | // $("#languageBox").show(); |
185 | daniel-mar | 490 | $("#gotobox").removeClass("mobilehidden"); |
355 | daniel-mar | 491 | $("#languageBox").removeClass("mobilehidden"); |
120 | daniel-mar | 492 | $("#system_title_menu").addClass("active"); |
493 | } |
||
494 | |||
105 | daniel-mar | 495 | function mobileNavButtonClick(sender) { |
120 | daniel-mar | 496 | if ($("#oidtree").hasClass("ui-layout-west")) { |
497 | mobileNavOpen(); |
||
103 | daniel-mar | 498 | } else { |
120 | daniel-mar | 499 | mobileNavClose(); |
103 | daniel-mar | 500 | } |
501 | } |
||
105 | daniel-mar | 502 | |
503 | function mobileNavButtonHover(sender) { |
||
504 | sender.classList.toggle("hover"); |
||
505 | } |
||
183 | daniel-mar | 506 | |
507 | function gotoButtonClicked() { |
||
704 | daniel-mar | 508 | openOidInPanel($("#gotoedit").val(), true); |
183 | daniel-mar | 509 | } |
199 | daniel-mar | 510 | |
355 | daniel-mar | 511 | function setLanguage(lngid) { |
1289 | daniel-mar | 512 | setCookie('LANGUAGE', lngid, 0/*Until browser closes*/, oidplus_webpath_relative); |
356 | daniel-mar | 513 | |
1060 | daniel-mar | 514 | if (current_node == "") return false; // Happens for Setup. Open URL instead. |
515 | |||
356 | daniel-mar | 516 | $(".lng_flag").each(function(){ |
517 | $(this).addClass("picture_ghost"); |
||
355 | daniel-mar | 518 | }); |
675 | daniel-mar | 519 | $("#lng_flag_"+$.escapeSelector(lngid)).removeClass("picture_ghost"); |
356 | daniel-mar | 520 | |
1349 | daniel-mar | 521 | // TODO: Small detail: The "Go" button also needs to be re-translated |
522 | reloadContent(); |
||
523 | mobileNavClose(); |
||
524 | |||
1060 | daniel-mar | 525 | return true; // we have handled it. Do not follow href="" |
355 | daniel-mar | 526 | } |
527 | |||
532 | daniel-mar | 528 | function show_waiting_anim() { |
529 | $("#loading").show(); |
||
530 | } |
||
531 | |||
532 | function hide_waiting_anim() { |
||
533 | $("#loading").hide(); |
||
534 | } |
||
544 | daniel-mar | 535 | |
536 | /* Mini-framework to abort all AJAX requests if a new request is made */ |
||
537 | |||
538 | $.xhrPool = []; |
||
539 | $.xhrPool.add = function(jqXHR) { |
||
540 | $.xhrPool.push(jqXHR); |
||
541 | } |
||
542 | $.xhrPool.remove = function(jqXHR) { |
||
543 | var index = $.xhrPool.indexOf(jqXHR); |
||
544 | if (index > -1) { |
||
545 | $.xhrPool.splice(index, 1); |
||
546 | } |
||
547 | }; |
||
548 | $.xhrPool.abortAll = function() { |
||
549 | var calls = Array.from($.xhrPool); |
||
550 | $.each(calls, function(key, value) { |
||
551 | value.abort(); |
||
552 | }); |
||
553 | } |
||
829 | daniel-mar | 554 | |
833 | daniel-mar | 555 | /* Individual alert types */ |
556 | /* TODO: alert() blocks program flow, but alertSuccess() not! Will the mass change have negative effects (e.g. a redirect without the user seeing the toast)? */ |
||
557 | |||
558 | function alertSuccess(txt) { |
||
559 | if (typeof bs5Utils !== "undefined") { |
||
560 | bs5Utils.Snack.show('success', _L(txt), delay = 5000, dismissible = true); |
||
561 | } else { |
||
562 | alert(txt); |
||
563 | } |
||
564 | } |
||
565 | |||
566 | function alertWarning(txt) { |
||
567 | // TODO: as toast? |
||
568 | alert(txt); |
||
569 | } |
||
570 | |||
571 | function alertError(txt) { |
||
572 | // TODO: as toast? |
||
573 | alert(txt); |
||
574 | } |
||
1036 | daniel-mar | 575 | |
576 | /* AJAX success/error-handling */ |
||
577 | |||
578 | function oidplus_ajax_error(jqXHR, textStatus, errorThrown) { |
||
579 | if (errorThrown == "abort") return; |
||
580 | console.error(errorThrown, jqXHR); |
||
581 | alertError(_L("Error: %1", errorThrown)); |
||
582 | } |
||
583 | |||
584 | function oidplus_ajax_success(data, cb) { |
||
585 | if (typeof data === "object" && "error" in data) { |
||
1447 | daniel-mar | 586 | console.error(data); |
1036 | daniel-mar | 587 | alertError(_L("Error: %1", data.error)); |
1447 | daniel-mar | 588 | } else if (typeof data === "object" && "status" in data && data.status >= 0) { |
1036 | daniel-mar | 589 | cb(data); |
1447 | daniel-mar | 590 | } else if (typeof data === "object" && "status" in data && data.status < 0) { |
591 | console.error(data); |
||
592 | alertError(_L("Error: %1", data.status)); |
||
1036 | daniel-mar | 593 | } else { |
1447 | daniel-mar | 594 | console.error(data); |
1036 | daniel-mar | 595 | alertError(_L("Error: %1", data)); |
596 | } |
||
597 | } |