Rev 448 | Rev 499 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4 | daniel-mar | 1 | /* |
2 | * OIDplus 2.0 |
||
3 | * Copyright 2019 Daniel Marschall, ViaThinkSoft |
||
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 | |||
22 | var current_node = ""; |
||
23 | var popstate_running = false; |
||
362 | daniel-mar | 24 | // DEFAULT_LANGUAGE will be set by oidplus.min.js.php |
360 | daniel-mar | 25 | // language_messages will be set by oidplus.min.js.php |
26 | // language_tblprefix will be set by oidplus.min.js.php |
||
424 | daniel-mar | 27 | // csrf_token will be set by oidplus.min.js.php |
219 | daniel-mar | 28 | |
399 | daniel-mar | 29 | var pageChangeCallbacks = []; |
30 | var pageChangeRequestCallbacks = []; |
||
31 | |||
356 | daniel-mar | 32 | function isInternetExplorer() { |
33 | var ua = window.navigator.userAgent; |
||
34 | return ((ua.indexOf("MSIE ") > 0) || (ua.indexOf("Trident/") > 0)); |
||
35 | } |
||
36 | |||
2 | daniel-mar | 37 | String.prototype.explode = function (separator, limit) { |
38 | // https://stackoverflow.com/questions/4514323/javascript-equivalent-to-php-explode |
||
39 | const array = this.split(separator); |
||
40 | if (limit !== undefined && array.length >= limit) { |
||
41 | array.push(array.splice(limit - 1).join(separator)); |
||
42 | } |
||
43 | return array; |
||
44 | }; |
||
45 | |||
46 | String.prototype.htmlentities = function () { |
||
399 | daniel-mar | 47 | return this.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');//" |
9 | daniel-mar | 48 | }; |
2 | daniel-mar | 49 | |
50 | String.prototype.html_entity_decode = function () { |
||
51 | return $('<textarea />').html(this).text(); |
||
9 | daniel-mar | 52 | }; |
2 | daniel-mar | 53 | |
112 | daniel-mar | 54 | function getMeta(metaName) { |
55 | const metas = document.getElementsByTagName('meta'); |
||
56 | |||
57 | for (let i = 0; i < metas.length; i++) { |
||
58 | if (metas[i].getAttribute('name') === metaName) { |
||
59 | return metas[i].getAttribute('content'); |
||
60 | } |
||
61 | } |
||
62 | |||
63 | return ''; |
||
64 | } |
||
65 | |||
66 | function getOidPlusSystemTitle() { |
||
360 | daniel-mar | 67 | return getMeta('OIDplus-SystemTitle'); // do not translate |
112 | daniel-mar | 68 | } |
69 | |||
5 | daniel-mar | 70 | function combine_systemtitle_and_pagetitle(systemtitle, pagetitle) { |
309 | daniel-mar | 71 | // Please also change the function in index.php |
5 | daniel-mar | 72 | if (systemtitle == pagetitle) { |
73 | return systemtitle; |
||
74 | } else { |
||
309 | daniel-mar | 75 | return pagetitle + ' - ' + systemtitle; |
5 | daniel-mar | 76 | } |
77 | } |
||
78 | |||
385 | daniel-mar | 79 | function getSystemUrl(relative) { |
80 | var url = new URL(window.location.href); |
||
81 | if (relative) { |
||
82 | return url.pathname; |
||
83 | } else { |
||
84 | return url.href.substr(0, url.href.length-url.search.length); |
||
85 | } |
||
86 | } |
||
87 | |||
2 | daniel-mar | 88 | function getTreeLoadURL() { |
89 | var url = new URL(window.location.href); |
||
90 | var goto = url.searchParams.get("goto"); |
||
424 | daniel-mar | 91 | return (goto != null) ? "ajax.php?csrf_token="+csrf_token+"&action=tree_load&goto="+encodeURIComponent(goto) |
92 | : "ajax.php?csrf_token="+csrf_token+"&action=tree_load"; |
||
2 | daniel-mar | 93 | } |
94 | |||
95 | function reloadContent() { |
||
154 | daniel-mar | 96 | // window.location.href = "?goto="+encodeURIComponent(current_node); |
399 | daniel-mar | 97 | if (openOidInPanel(current_node, false)) { |
450 | daniel-mar | 98 | if(!$('#oidtree').jstree(true).get_node(current_node)) { |
99 | // Avoid that a language change at "oidplus:srvreg_status" won't redirect the user to "oidplus:srv_registration" because of the reselection during refresh |
||
100 | $('#oidtree').jstree("deselect_all"); |
||
101 | } |
||
102 | |||
399 | daniel-mar | 103 | $('#oidtree').jstree("refresh"); |
104 | } |
||
2 | daniel-mar | 105 | } |
106 | |||
107 | daniel-mar | 107 | function x_rec(x_data, i) { |
108 | $('#oidtree').jstree('open_node', x_data[i], function(e, data) { |
||
109 | if (i+1 < x_data.length) { |
||
110 | x_rec(x_data, i+1); |
||
111 | } else { |
||
114 | daniel-mar | 112 | popstate_running = true; // don't call openOidInPanel again |
113 | try { |
||
114 | $('#oidtree').jstree('select_node', x_data[i]); |
||
115 | } catch (err) { |
||
116 | popstate_running = false; |
||
117 | } finally { |
||
118 | popstate_running = false; |
||
119 | } |
||
107 | daniel-mar | 120 | } |
121 | }); |
||
122 | } |
||
2 | daniel-mar | 123 | |
399 | daniel-mar | 124 | function performCloseQueryCB() { |
125 | for (var i=0; i<pageChangeRequestCallbacks.length; i++) { |
||
126 | if (!pageChangeRequestCallbacks[i][0](pageChangeRequestCallbacks[i][1])) return false; |
||
127 | } |
||
128 | pageChangeRequestCallbacks = []; |
||
129 | return true; // may close |
||
130 | } |
||
131 | |||
132 | function performCloseCB() { |
||
133 | for (var i=0; i<pageChangeCallbacks.length; i++) { |
||
134 | pageChangeCallbacks[i][0](pageChangeCallbacks[i][1]); |
||
135 | } |
||
136 | pageChangeCallbacks = []; |
||
137 | } |
||
138 | |||
139 | function openOidInPanel(id, reselect/*=false*/, anchor/*=''*/, force/*=false*/) { |
||
150 | daniel-mar | 140 | reselect = (typeof reselect === 'undefined') ? false : reselect; |
219 | daniel-mar | 141 | anchor = (typeof anchor === 'undefined') ? '' : anchor; |
399 | daniel-mar | 142 | force = (typeof force === 'undefined') ? false : force; |
150 | daniel-mar | 143 | |
399 | daniel-mar | 144 | var mayClose = performCloseQueryCB(); |
145 | if (!force && !mayClose) return false; |
||
146 | |||
147 | performCloseCB(); |
||
405 | daniel-mar | 148 | |
107 | daniel-mar | 149 | if (reselect) { |
2 | daniel-mar | 150 | $('#oidtree').jstree('deselect_all'); |
107 | daniel-mar | 151 | |
114 | daniel-mar | 152 | popstate_running = true; // don't call openOidInPanel during tree selection |
153 | try { |
||
154 | // If the node is already loaded in the tree, select it |
||
155 | if (!$('#oidtree').jstree('select_node', id)) { |
||
156 | // If the node is not loaded, then we try to search it. |
||
157 | // If it can be found, then open all parent nodes and select the node |
||
158 | $.ajax({ |
||
159 | url:"ajax.php", |
||
160 | method:"POST", |
||
161 | data:{ |
||
424 | daniel-mar | 162 | csrf_token:csrf_token, |
114 | daniel-mar | 163 | action:"tree_search", |
164 | search:id |
||
165 | }, |
||
166 | error:function(jqXHR, textStatus, errorThrown) { |
||
360 | daniel-mar | 167 | console.error(_L("Error: %1",errorThrown)); |
114 | daniel-mar | 168 | }, |
169 | success:function(data) { |
||
170 | if ("error" in data) { |
||
171 | console.error(data); |
||
172 | } else if ((data instanceof Array) && (data.length > 0)) { |
||
173 | x_rec(data, 0); |
||
174 | } else { |
||
175 | console.error(data); |
||
176 | } |
||
177 | } |
||
178 | }); |
||
107 | daniel-mar | 179 | } |
114 | daniel-mar | 180 | } catch (err) { |
181 | popstate_running = false; |
||
182 | } finally { |
||
183 | popstate_running = false; |
||
184 | } |
||
2 | daniel-mar | 185 | } |
186 | |||
114 | daniel-mar | 187 | // This loads the actual content |
188 | |||
405 | daniel-mar | 189 | // document.title = ""; // <-- we may not do this, otherwise Firefox won't |
190 | // show titles in the browser history (right-click |
||
191 | // on back-button), although document.title() is |
||
192 | // set inside the AJAX-callback [FirefoxBug?!] |
||
193 | |||
2 | daniel-mar | 194 | $('#real_title').html(" "); |
355 | daniel-mar | 195 | $('#real_content').html(_L("Loading...")); |
108 | daniel-mar | 196 | $('#static_link').attr("href", "index.php?goto="+encodeURIComponent(id)); |
183 | daniel-mar | 197 | $("#gotoedit").val(id); |
2 | daniel-mar | 198 | |
199 | // Normal opening of a description |
||
424 | daniel-mar | 200 | fetch("ajax.php?csrf_token="+csrf_token+"&action=get_description&id="+encodeURIComponent(id)) |
2 | daniel-mar | 201 | .then(function(response) { |
202 | response.json() |
||
203 | .then(function(data) { |
||
107 | daniel-mar | 204 | if ("error" in data) { |
360 | daniel-mar | 205 | alert(_L("Failed to load content: %1",data.error)); |
107 | daniel-mar | 206 | console.error(data.error); |
207 | return; |
||
208 | } |
||
209 | |||
2 | daniel-mar | 210 | data.id = id; |
211 | |||
212 | var state = { |
||
107 | daniel-mar | 213 | "node_id":id, |
108 | daniel-mar | 214 | "titleHTML":(data.icon ? '<img src="'+data.icon+'" width="48" height="48" alt="'+data.title.htmlentities()+'"> ' : '') + data.title.htmlentities(), |
2 | daniel-mar | 215 | "textHTML":data.text, |
108 | daniel-mar | 216 | "staticlinkHREF":"index.php?goto="+encodeURIComponent(id), |
2 | daniel-mar | 217 | }; |
218 | if (current_node != id) { |
||
104 | daniel-mar | 219 | window.history.pushState(state, data.title, "?goto="+encodeURIComponent(id)); |
2 | daniel-mar | 220 | } else { |
104 | daniel-mar | 221 | window.history.replaceState(state, data.title, "?goto="+encodeURIComponent(id)); |
2 | daniel-mar | 222 | } |
223 | |||
405 | daniel-mar | 224 | document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.title); |
225 | |||
32 | daniel-mar | 226 | if (data.icon) { |
227 | $('#real_title').html('<img src="'+data.icon+'" width="48" height="48" alt="'+data.title.htmlentities()+'"> ' + data.title.htmlentities()); |
||
228 | } else { |
||
229 | $('#real_title').html(data.title.htmlentities()); |
||
230 | } |
||
2 | daniel-mar | 231 | $('#real_content').html(data.text); |
112 | daniel-mar | 232 | document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.title); |
2 | daniel-mar | 233 | current_node = id; |
219 | daniel-mar | 234 | |
235 | if (anchor != '') { |
||
236 | jumpToAnchor(anchor); |
||
237 | } |
||
2 | daniel-mar | 238 | }) |
239 | .catch(function(error) { |
||
360 | daniel-mar | 240 | alert(_L("Failed to load content: %1",error)); |
2 | daniel-mar | 241 | console.error(error); |
242 | }); |
||
243 | }) |
||
244 | .catch(function(error) { |
||
360 | daniel-mar | 245 | alert(_L("Failed to load content: %1",error)); |
2 | daniel-mar | 246 | console.error(error); |
247 | }); |
||
399 | daniel-mar | 248 | |
249 | return true; |
||
2 | daniel-mar | 250 | } |
251 | |||
107 | daniel-mar | 252 | // This function opens the "parentID" node, and then selects the "childID" node (which should be beneath the parent node) |
2 | daniel-mar | 253 | function openAndSelectNode(childID, parentID) { |
254 | if ($('#oidtree').jstree(true).get_node(parentID)) { |
||
107 | daniel-mar | 255 | $('#oidtree').jstree('open_node', parentID, function(e, data) { // open parent node |
2 | daniel-mar | 256 | if ($('#oidtree').jstree(true).get_node(childID)) { // is the child there? |
107 | daniel-mar | 257 | $('#oidtree').jstree('deselect_all').jstree('select_node', childID); // select it |
2 | daniel-mar | 258 | } else { |
259 | // This can happen if the content page contains brand new items which are not in the treeview yet |
||
183 | daniel-mar | 260 | $("#gotoedit").val(childID); |
154 | daniel-mar | 261 | window.location.href = "?goto="+encodeURIComponent(childID); |
2 | daniel-mar | 262 | } |
263 | }, true); |
||
264 | } else { |
||
265 | // This should usually not happen |
||
183 | daniel-mar | 266 | $("#gotoedit").val(childID); |
154 | daniel-mar | 267 | window.location.href = "?goto="+encodeURIComponent(childID); |
2 | daniel-mar | 268 | } |
269 | } |
||
270 | |||
271 | $(window).on("popstate", function(e) { |
||
399 | daniel-mar | 272 | if (!performCloseQueryCB()) { |
273 | // TODO: does not work!!! The "back/forward" action will be cancelled, but the browser still thinks it was successful, |
||
274 | // so if you do it again, you will then jump 2 pages back, etc! |
||
275 | // This does also not help: |
||
276 | //window.history.pushState(e.originalEvent.state, e.originalEvent.title, e.originalEvent.url); |
||
277 | //window.history.forward(); |
||
278 | return; |
||
279 | } |
||
280 | |||
2 | daniel-mar | 281 | popstate_running = true; |
282 | try { |
||
283 | var data = e.originalEvent.state; |
||
284 | |||
285 | current_node = data.node_id; |
||
327 | daniel-mar | 286 | $("#gotoedit").val(current_node); |
107 | daniel-mar | 287 | $('#oidtree').jstree('deselect_all').jstree('select_node', data.node_id); |
2 | daniel-mar | 288 | $('#real_title').html(data.titleHTML); |
289 | $('#real_content').html(data.textHTML); |
||
290 | $('#static_link').attr("href", data.staticlinkHREF); |
||
112 | daniel-mar | 291 | document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.titleHTML.html_entity_decode()); |
2 | daniel-mar | 292 | } catch (err) { |
293 | popstate_running = false; |
||
294 | } finally { |
||
295 | popstate_running = false; |
||
296 | } |
||
297 | }); |
||
298 | |||
299 | $(document).ready(function () { |
||
399 | daniel-mar | 300 | /* |
301 | window.onbeforeunload = function(e) { |
||
302 | // TODO: This won't be called because TinyMCE overrides it?? |
||
303 | // TODO: when the user accepted the query in performCloseQueryCB(), then the message will be shown again by the browser! |
||
304 | if (!performCloseQueryCB()) { |
||
305 | // Cancel the event |
||
306 | e.preventDefault(); // If you prevent default behavior in Mozilla Firefox prompt will always be shown |
||
307 | // Chrome requires returnValue to be set |
||
308 | e.returnValue = ''; |
||
309 | } else { |
||
310 | // the absence of a returnValue property on the event will guarantee the browser unload happens |
||
311 | delete e['returnValue']; |
||
312 | } |
||
313 | }; |
||
314 | */ |
||
214 | daniel-mar | 315 | |
2 | daniel-mar | 316 | // --- JsTree |
317 | |||
318 | $('#oidtree') |
||
319 | .jstree({ |
||
320 | plugins: ['massload','search','conditionalselect'], |
||
321 | 'core' : { |
||
322 | 'data' : { |
||
323 | "url" : getTreeLoadURL(), |
||
324 | "data" : function (node) { |
||
325 | return { "id" : node.id }; |
||
326 | } |
||
327 | }, |
||
328 | "multiple": false |
||
329 | }, |
||
330 | 'conditionalselect' : function (node) { |
||
68 | daniel-mar | 331 | if (node.original.conditionalselect !== undefined) { |
332 | return eval(node.original.conditionalselect); |
||
2 | daniel-mar | 333 | } else { |
399 | daniel-mar | 334 | return performCloseQueryCB(); |
2 | daniel-mar | 335 | } |
336 | }, |
||
337 | }) |
||
338 | .on('ready.jstree', function (e, data) { |
||
339 | var url = new URL(window.location.href); |
||
340 | var goto = url.searchParams.get("goto"); |
||
341 | if (goto == null) goto = "oidplus:system"; // the page was not called with ?goto=... |
||
183 | daniel-mar | 342 | $("#gotoedit").val(goto); |
2 | daniel-mar | 343 | |
107 | daniel-mar | 344 | // 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 | 345 | // But then we need to set the history state manually |
346 | current_node = goto; |
||
100 | daniel-mar | 347 | window.history.replaceState({ |
107 | daniel-mar | 348 | "node_id":goto, |
100 | daniel-mar | 349 | "titleHTML":$('#real_title').html(), |
350 | "textHTML":$('#real_content').html(), |
||
108 | daniel-mar | 351 | "staticlinkHREF":"index.php?goto="+encodeURIComponent(goto), |
113 | daniel-mar | 352 | }, $('#real_title').html(), "?goto="+encodeURIComponent(goto)); |
2 | daniel-mar | 353 | |
354 | if (goto != null) data.instance.select_node([goto]); |
||
128 | daniel-mar | 355 | |
137 | daniel-mar | 356 | setTimeout(glayoutWorkaroundA, 100); |
357 | setTimeout(glayoutWorkaroundB, 100); |
||
2 | daniel-mar | 358 | }) |
359 | .on('select_node.jstree', function (node, selected, event) { |
||
120 | daniel-mar | 360 | mobileNavClose(); |
95 | daniel-mar | 361 | |
9 | daniel-mar | 362 | var id = selected.node.id; |
114 | daniel-mar | 363 | if ((!popstate_running) && (current_node != id)) { |
399 | daniel-mar | 364 | // 4th argument: we force the reload (because in the |
365 | // conditional select above, we already asked if |
||
366 | // tinyMCE needs to be saved) |
||
367 | openOidInPanel(id, false, '', true); |
||
2 | daniel-mar | 368 | } |
369 | }); |
||
370 | |||
371 | // --- Layout |
||
372 | |||
122 | daniel-mar | 373 | document.getElementById('system_title_menu').style.display = "block"; |
120 | daniel-mar | 374 | |
355 | daniel-mar | 375 | var tmpObjectTree = _L("OBJECT TREE").replace(/(.{1})/g,"$1<br>"); |
376 | tmpObjectTree = tmpObjectTree.substring(0, tmpObjectTree.length-"<br>".length); |
||
377 | |||
120 | daniel-mar | 378 | $('#oidtree').addClass('ui-layout-west'); |
379 | $('#content_window').addClass('ui-layout-center'); |
||
380 | $('#system_title_bar').addClass('ui-layout-north'); |
||
128 | daniel-mar | 381 | glayout = $('#frames').layout({ |
120 | daniel-mar | 382 | north__size: 40, |
383 | north__slidable: false, |
||
384 | north__closable: false, |
||
385 | north__resizable: false, |
||
386 | west__size: 450, |
||
387 | west__spacing_closed: 20, |
||
388 | west__togglerLength_closed: 230, |
||
389 | west__togglerAlign_closed: "top", |
||
355 | daniel-mar | 390 | west__togglerContent_closed: tmpObjectTree, |
391 | west__togglerTip_closed: _L("Open & Pin Menu"), |
||
392 | west__sliderTip: _L("Slide Open Menu"), |
||
120 | daniel-mar | 393 | west__slideTrigger_open: "mouseover", |
394 | center__maskContents: true // IMPORTANT - enable iframe masking |
||
395 | }); |
||
183 | daniel-mar | 396 | |
185 | daniel-mar | 397 | $("#gotobox").addClass("mobilehidden"); |
355 | daniel-mar | 398 | $("#languageBox").addClass("mobilehidden"); |
183 | daniel-mar | 399 | document.getElementById('gotobox').style.display = "block"; |
400 | $('#gotoedit').keypress(function(event) { |
||
401 | var keycode = (event.keyCode ? event.keyCode : event.which); |
||
402 | if (keycode == '13') { |
||
403 | gotoButtonClicked(); |
||
404 | } |
||
405 | }); |
||
376 | daniel-mar | 406 | }); |
2 | daniel-mar | 407 | |
137 | daniel-mar | 408 | function glayoutWorkaroundA() { |
211 | daniel-mar | 409 | // "Bug A": Sometimes, the design is completely destroyed after reloading the page. It does not help when glayout.resizeAll() |
137 | daniel-mar | 410 | // is called at the beginning (e.g. during the ready function), and it does not help if we wait 500ms. |
411 | // So we do it all the time. It has probably something to do with slow loading times, since the error |
||
412 | // does only appear when the page is "blank" for a short while while it is loading. |
||
413 | glayout.resizeAll(); |
||
414 | setTimeout(glayoutWorkaroundA, 100); |
||
287 | daniel-mar | 415 | |
416 | // "Bug C": With Firefox (And sometimes with Chrome), there is a gap between the content-window (including scroll bars) |
||
417 | // and the right corner of the screen. Removing the explicit width solves this problem. |
||
418 | document.getElementById("content_window").style.removeProperty("width"); |
||
137 | daniel-mar | 419 | } |
420 | |||
421 | function glayoutWorkaroundB() { |
||
422 | // "Bug B": Sometimes, after reload, weird space between oidtree and content window, because oidtree has size of 438px |
||
423 | document.getElementById("oidtree").style.width = "450px"; |
||
424 | } |
||
425 | |||
120 | daniel-mar | 426 | function mobileNavClose() { |
427 | if ($("#system_title_menu").is(":hidden")) { |
||
428 | return; |
||
429 | } |
||
430 | |||
431 | $("#oidtree").slideUp("medium").promise().done(function() { |
||
432 | $("#oidtree").addClass("ui-layout-west"); |
||
433 | $("#oidtree").show(); |
||
185 | daniel-mar | 434 | // $("#gotobox").hide(); |
355 | daniel-mar | 435 | // $("#languageBox").hide(); |
185 | daniel-mar | 436 | $("#gotobox").addClass("mobilehidden"); |
355 | daniel-mar | 437 | $("#languageBox").addClass("mobilehidden"); |
120 | daniel-mar | 438 | }); |
439 | $("#system_title_menu").removeClass("active"); |
||
95 | daniel-mar | 440 | } |
441 | |||
120 | daniel-mar | 442 | function mobileNavOpen() { |
443 | $("#oidtree").hide(); |
||
444 | $("#oidtree").removeClass("ui-layout-west"); |
||
445 | $("#oidtree").slideDown("medium"); |
||
185 | daniel-mar | 446 | // $("#gotobox").show(); |
355 | daniel-mar | 447 | // $("#languageBox").show(); |
185 | daniel-mar | 448 | $("#gotobox").removeClass("mobilehidden"); |
355 | daniel-mar | 449 | $("#languageBox").removeClass("mobilehidden"); |
120 | daniel-mar | 450 | $("#system_title_menu").addClass("active"); |
451 | } |
||
452 | |||
105 | daniel-mar | 453 | function mobileNavButtonClick(sender) { |
120 | daniel-mar | 454 | if ($("#oidtree").hasClass("ui-layout-west")) { |
455 | mobileNavOpen(); |
||
103 | daniel-mar | 456 | } else { |
120 | daniel-mar | 457 | mobileNavClose(); |
103 | daniel-mar | 458 | } |
459 | } |
||
105 | daniel-mar | 460 | |
461 | function mobileNavButtonHover(sender) { |
||
462 | sender.classList.toggle("hover"); |
||
463 | } |
||
183 | daniel-mar | 464 | |
465 | function gotoButtonClicked() { |
||
466 | openOidInPanel($("#gotoedit").val(), 1); |
||
467 | } |
||
199 | daniel-mar | 468 | |
219 | daniel-mar | 469 | function jumpToAnchor(anchor) { |
470 | window.location.href = "#" + anchor; |
||
471 | } |
||
472 | |||
355 | daniel-mar | 473 | function getCookie(cname) { |
474 | // Source: https://www.w3schools.com/js/js_cookies.asp |
||
475 | var name = cname + "="; |
||
476 | var decodedCookie = decodeURIComponent(document.cookie); |
||
477 | var ca = decodedCookie.split(';'); |
||
478 | for(var i = 0; i <ca.length; i++) { |
||
479 | var c = ca[i]; |
||
480 | while (c.charAt(0) == ' ') { |
||
481 | c = c.substring(1); |
||
482 | } |
||
483 | if (c.indexOf(name) == 0) { |
||
484 | return c.substring(name.length, c.length); |
||
485 | } |
||
486 | } |
||
487 | return undefined; |
||
488 | } |
||
489 | |||
356 | daniel-mar | 490 | function setCookie(cname, cvalue, exdays, path) { |
491 | var d = new Date(); |
||
492 | d.setTime(d.getTime() + (exdays*24*60*60*1000)); |
||
493 | var expires = exdays == 0 ? "" : "; expires="+d.toUTCString(); |
||
494 | document.cookie = cname + "=" + cvalue + expires + ";path=" + path; |
||
495 | } |
||
496 | |||
355 | daniel-mar | 497 | function setLanguage(lngid) { |
356 | daniel-mar | 498 | setCookie('LANGUAGE', lngid, 0/*Until browser closes*/, location.pathname); |
499 | |||
500 | $(".lng_flag").each(function(){ |
||
501 | $(this).addClass("picture_ghost"); |
||
355 | daniel-mar | 502 | }); |
356 | daniel-mar | 503 | $("#lng_flag_"+lngid).removeClass("picture_ghost"); |
504 | |||
505 | if (isInternetExplorer()) { |
||
506 | // Internet Explorer has problems with sending new cookies to new AJAX requests, so we reload the page completely |
||
507 | window.location.reload(); |
||
508 | } else { |
||
360 | daniel-mar | 509 | reloadContent(); |
356 | daniel-mar | 510 | mobileNavClose(); |
511 | } |
||
355 | daniel-mar | 512 | } |
513 | |||
514 | function getCurrentLang() { |
||
360 | daniel-mar | 515 | // Note: If the argument "?lang=" is used, PHP will automatically set a Cookie, so it is OK when we only check for the cookie |
355 | daniel-mar | 516 | var lang = getCookie('LANGUAGE'); |
517 | return (typeof lang != "undefined") ? lang : DEFAULT_LANGUAGE; |
||
518 | } |
||
519 | |||
360 | daniel-mar | 520 | function _L() { |
521 | var args = Array.prototype.slice.call(arguments); |
||
522 | var str = args.shift(); |
||
523 | |||
524 | var tmp = ""; |
||
525 | if (typeof language_messages[getCurrentLang()] == "undefined") { |
||
526 | tmp = str; |
||
527 | } else { |
||
528 | var msg = language_messages[getCurrentLang()][str]; |
||
529 | if (typeof msg != "undefined") { |
||
530 | tmp = msg; |
||
531 | } else { |
||
532 | tmp = str; |
||
533 | } |
||
534 | } |
||
535 | |||
536 | tmp = tmp.replace('###', language_tblprefix); |
||
537 | |||
538 | var n = 1; |
||
539 | while (args.length > 0) { |
||
540 | var val = args.shift(); |
||
541 | tmp = tmp.replace("%"+n, val); |
||
542 | n++; |
||
543 | } |
||
544 | |||
370 | daniel-mar | 545 | tmp = tmp.replace("%%", "%"); |
546 | |||
360 | daniel-mar | 547 | return tmp; |
355 | daniel-mar | 548 | } |