Newer
Older
/**
* This file contains helper methods for the olatcore web app framework and the
* learning management system OLAT
*/

strentini
committed
/** OpenOLAT namespace **/
OPOL = {};
//used to mark form dirty and warn user to save first.
var o2c=0;
var o3c=new Array();//array holds flexi.form id's
// o_info is a global object that contains global variables
o_info.guibusy = false;
o_info.linkbusy = false;
//debug flag for this file, to enable debugging to the olat.log set JavaScriptTracingController to level debug
o_info.debug = true;
/**
* The BLoader object can be used to :
* - dynamically load and unload CSS files
* - dynamically load JS files
* - execute javascript code in a global context, meaning on window level
*
* 03.04.2009 gnaegi@frentix.com
*/
var BLoader = {
// List of js files loaded via AJAX call.
_ajaxLoadedJS : new Array(),
// Internal mehod to check if a JS file has already been loaded on the page
_isAlreadyLoadedJS: function(jsURL) {
var notLoaded = true;
// first check for scrips loaded via HTML head
jQuery('head script[src]').each(function(s,t) {
if (jQuery(t).attr('src').indexOf(jsURL) != -1) {
notLoaded = false;
};
});
// second check for script loaded via ajax call
if (jQuery.inArray(jsURL, this._ajaxLoadedJS) != -1) notLoaded = false;
return !notLoaded;
},
// Load a JS file from an absolute or relative URL by using the given encoding. The last flag indicates if
// the script should be loaded using an ajax call (recommended) or by adding a script tag to the document
// head. Note that by using the script tag the JS script will be loaded asynchronous
loadJS : function(jsURL, encoding, useSynchronousAjaxRequest) {
if (!this._isAlreadyLoadedJS(jsURL)) {
if (o_info.debug) o_log("BLoader::loadJS: loading ajax::" + useSynchronousAjaxRequest + " url::" + jsURL);
if (useSynchronousAjaxRequest) {
jQuery.ajax(jsURL, {
async: false,
dataType: 'script',
cache: true,
success: function(script, textStatus, jqXHR) {
//BLoader.executeGlobalJS(script, 'loadJS');
}
jQuery.getScript(jsURL);
}
if (o_info.debug) o_log("BLoader::loadJS: loading DONE url::" + jsURL);
} else {
if (o_info.debug) o_log("BLoader::loadJS: already loaded url::" + jsURL);
}
},
// Execute the given string as java script code in a global context. The contextDesc is a string that can be
// used to describe execution context verbally, this is only used to improve meaninfull logging
executeGlobalJS : function(jsString, contextDesc) {
try{
// FIXME:FG refactor as soon as global exec available in prototype
// https://prototype.lighthouseapp.com/projects/8886/tickets/433-provide-an-eval-that-works-in-global-scope
if (window.execScript) window.execScript(jsString); // IE style
else window.eval(jsString);
} catch(e){

srosse
committed
if(console) console.log(contextDesc, 'cannot execute js', jsString);
if (o_info.debug) { // add webbrowser console log
o_logerr('BLoader::executeGlobalJS: Error when executing JS code in contextDesc::' + contextDesc + ' error::"'+showerror(e)+' for: '+escape(jsString));
}
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug','BLoader::executeGlobalJS: Error when executing JS code in contextDesc::' + contextDesc + ' error::"'+showerror(e)+' for: '+escape(jsString), "functions.js::BLoader::executeGlobalJS::" + contextDesc);
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Parsing of JS script can fail in IE for unknown reasons (e.g. tinymce gets 8002010 error)
// Try to do a 'full page refresh' and load everything via page header, this normally works
if (window.location.href.indexOf('o_winrndo') != -1) window.location.reload();
else window.location.href = window.location.href + (window.location.href.indexOf('?') != -1 ? '&' : '?' ) + 'o_winrndo=1';
}
},
// Load a CSS file from the given URL. The linkid represents the DOM id that is used to identify this CSS file
loadCSS : function (cssURL, linkid, loadAfterTheme) {
var doc = window.document;
try {
if(doc.createStyleSheet) { // IE
// double check: server side should do so, but to make sure that we don't have duplicate styles
var sheets = doc.styleSheets;
var cnt = 0;
var pos = 0;
for (i = 0; i < sheets.length; i++) {
var sh = sheets[i];
var h = sh.href;
if (h == cssURL) {
cnt++;
if (sh.disabled) {
// enable a previously disabled stylesheet (ie cannot remove sheets? -> we had to disable them)
sh.disabled = false;
return;
} else {
if (o_info.debug) o_logwarn("BLoader::loadCSS: style: "+cssURL+" already in document and not disabled! (duplicate add)");
return;
}
}
// add theme position, theme has to move one down
if (sh.id == 'o_theme_css') pos = i;
}
if (cnt > 1 && o_info.debug) o_logwarn("BLoader::loadCSS: apply styles: num of stylesheets found was not 0 or 1:"+cnt);
if (loadAfterTheme) {
// add at the end
pos = sheets.length;
}
// H: stylesheet not yet inserted -> insert
var mystyle = doc.createStyleSheet(cssURL, pos);
} else { // mozilla
// double check: first try to remove the <link rel="stylesheet"...> tag, using the id.
var el = jQuery('#' +linkid);
if (el && el.size() > 0) {
if (o_info.debug) o_logwarn("BLoader::loadCSS: stylesheet already found in doc when trying to add:"+cssURL+", with id "+linkid);
return;
} else {
// create the new stylesheet and convince the browser to load the url using @import with protocol 'data'
//var styles = '@import url("'+cssURL+'");';
//var newSt = new Element('link', {rel : 'stylesheet', id : linkid, href : 'data:text/css,'+escape(styles) });
var newSt = jQuery('<link id="' + linkid + '" rel="stylesheet" type="text/css" href="' + cssURL+ '">');
if (loadAfterTheme) {
newSt.insertBefore(jQuery('#o_fontSize_css'));
newSt.insertBefore(jQuery('#o_theme_css'));

srosse
committed
if(console) console.log(e);
if (o_info.debug) { // add webbrowser console log
o_logerr('BLoader::loadCSS: Error when loading CSS from URL::' + cssURL);
}
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug','BLoader::loadCSS: Error when loading CSS from URL::' + cssURL, "functions.js::BLoader::loadCSS");
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
}
},
// Unload a CSS file from the given URL. The linkid represents the DOM id that is used to identify this CSS file
unLoadCSS : function (cssURL, linkid) {
var doc = window.document;
try {
if(doc.createStyleSheet) { // IE
var sheets = doc.styleSheets;
var cnt = 0;
// calculate relative style url because IE does keep only a
// relative URL when the stylesheet is loaded from a relative URL
var relCssURL = cssURL;
// calculate base url: protocol, domain and port https://your.domain:8080
var baseURL = window.location.href.substring(0, window.location.href.indexOf("/", 8));
if (cssURL.indexOf(baseURL) == 0) {
//remove the base url form the style url
relCssURL = cssURL.substring(baseURL.length);
}
for (i = 0; i < sheets.length; i++) {
var h = sheets[i].href;
if (h == cssURL || h == relCssURL) {
cnt++;
if (!sheets[i].disabled) {
sheets[i].disabled = true; // = null;
} else {
if (o_info.debug) o_logwarn("stylesheet: when removing: matching url, but already disabled! url:"+h);
}
}
}
if (cnt != 1 && o_info.debug) o_logwarn("stylesheet: when removeing: num of stylesheets found was not 1:"+cnt);
} else { // mozilla
var el = jQuery('#' +linkid);
if (el) {
el.href = ""; // fix unload problem in safari
el.remove();
el = null;
return;
} else {
if (o_info.debug) o_logwarn("no link with id found to remove, id:"+linkid+", url "+cssURL);
}
}
} catch(e){
if (o_info.debug) { // add webbrowser console log
o_logerr('BLoader::unLoadCSS: Error when unloading CSS from URL::' + cssURL);
}
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug','BLoader::unLoadCSS: Error when unloading CSS from URL::' + cssURL, "functions.js::BLoader::loadCSS");
}
}
};
/**
* The BFormatter object can be used to :
* - formatt latex formulas using jsMath
*
* 18.06.2009 gnaegi@frentix.com
*/
var BFormatter = {
// process element with given dom id using jsmath
formatLatexFormulas : function(domId) {
try {
if (jsMath) { // only when js math available
if (jsMath.loaded && jsMath.tex2math && jsMath.tex2math.loaded) {
jsMath.Process();
} else { // not yet loaded (autoload), load first
jsMath.Autoload.LoadJsMath();
// retry formatting when ready (recursively until loaded)

srosse
committed
setTimeout(function() {
BFormatter.formatLatexFormulas(domId);
}, 100);

srosse
committed
if (console) console.log("error in BFormatter.formatLatexFormulas: ", e);
}
}
};
function o_init() {
try {
// all init-on-new-page calls here
//return opener window

gnaegi
committed
o_getMainWin().o_afterserver();
} catch(e) {
if (o_info.debug) o_log("error in o_init: "+showerror(e));
}
}
o_info.emPxFactor = jQuery('#o_width_1em').width();
if (o_info.emPxFactor == 0 || o_info.emPxFactor == 'undefined') {
o_info.emPxFactor = 12; // default value for all strange settings
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug','Could not read with of element b_width_1em, set o_info.emPxFactor to 12', "functions.js");

gnaegi
committed
function o_getMainWin() {

gnaegi
committed
// other cases the current window is the main window
return window;
} else if (window.opener && window.opener.OPOL) {
// use the opener when opener window is an OpenOLAT window
return window.opener;
}

gnaegi
committed
} catch (e) {
if (o_info.debug) { // add webbrowser console log
o_logerr('Exception while getting main window. rror::"'+showerror(e));
}
if (console) { // add ajax logger
console.log('Exception while getting main window. rror::"'+showerror(e), "functions.js");
console.log(e);

gnaegi
committed
}
}
throw "Can not find main OpenOLAT window";

gnaegi
committed
//mal versuche mit jQuery().ready.. erst dann wieder clicks erlauben...
showAjaxBusy();
// execute iframe specific onunload code on the iframe
if (window.suppressOlatOnUnloadOnce) {
// don't call olatonunload this time, reset variable for next time
window.suppressOlatOnUnloadOnce = false;
} else if (window.olatonunload) {
olatonunload();
}
}
function o_afterserver() {
o2c = 0;
o_info.linkbusy = false;
removeAjaxBusy();
}
function o2cl() {
if (o_info.linkbusy) {
return false;
} else {
var doreq = (o2c==0 || confirm(o_info.dirty_form));
if (doreq) o_beforeserver();
return doreq;
}
}
//for tree and Firefox
function o2cl_secure() {
try {
if(o2cl()) {
return true;
} else {
return false;
}
} catch(e){
return false
}
}
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
function o3cl(formId) {
if (o_info.linkbusy) {
return false;
} else {
//detect if another flexi form on the screen is dirty too
var isRegistered = o3c1.indexOf(formId) > -1;
var flexiformdirty = (isRegistered && o3c1.length > 1) || o3c1.length > 0;
//check if no other flexi form is dirty
//otherwise ask if changes should be discarded.
var doreq = ( !flexiformdirty || confirm(o_info.dirty_form));
if (doreq) o_beforeserver();
return doreq;
}
}
// on ajax poll complete
function o_onc(response) {
var te = response.responseText;
BLoader.executeGlobalJS("o_info.last_o_onc="+te+";", 'o_onc');
//asynchronous! from polling
o_ainvoke(o_info.last_o_onc,false);
}
function o_allowNextClick() {
o_info.linkbusy = false;
removeAjaxBusy();
}
//remove busy after clicking a download link in non-ajax mode
//use LinkFactory.markDownloadLink(Link) to make a link call this method.
function removeBusyAfterDownload(e,target,options){
o2c = 0;
o_afterserver();
}
Array.prototype.search = function(s,q){
var len = this.length;
for(var i=0; i<len; i++){
if(this[i].constructor == Array){
if(this[i].search(s,q)){
return true;
break;
}
} else {
if(q){
if(this[i].indexOf(s) != -1){
return true;
break;
}
} else {
if(this[i]==s){
return true;
break;
}
}
}
}
return false;
}
if(!Function.prototype.curry) {
Function.prototype.curry = function() {
if (arguments.length<1) {
return this; //nothing to curry with - return function
}
var __method = this;
var args = Array.prototype.slice.call(arguments);
return function() {
return __method.apply(this, args.concat(Array.prototype.slice.call(arguments)));
}
}
}
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
if(!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 1) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
}
// b_AddOnDomReplacementFinishedCallback is used to add callback methods that are executed after
// the DOM replacement has occured. Note that when not in AJAX mode, those methods will not be
// executed. Use this callback to execute some JS code to cleanup eventhandlers or alike

Florian Gnaegi - frentix GmbH
committed
//DEPRECATED: listen to event "oo.dom.replacement.after"
var b_onDomReplacementFinished_callbacks=new Array();//array holding js callback methods that should be executed after the next ajax call
function b_AddOnDomReplacementFinishedCallback(funct) {
var debug = jQuery(document).ooLog().isDebugEnabled();
if(debug) jQuery(document).ooLog('debug',"callback stack size: " + b_onDomReplacementFinished_callbacks.length, "functions.js ADD");

srosse
committed
if (debug && b_onDomReplacementFinished_callbacks.toSource) {
jQuery(document).ooLog('debug',"stack content"+b_onDomReplacementFinished_callbacks.toSource(), "functions.js ADD")
};
b_onDomReplacementFinished_callbacks.push(funct);
if(debug) jQuery(document).ooLog('debug',"push to callback stack, func: " + funct, "functions.js ADD");
//fxdiff FXOLAT-310
var b_changedDomEl=new Array();
//same as above, but with a filter to prevent adding a funct. more than once
//funct then has to be an array("identifier", funct)

Florian Gnaegi - frentix GmbH
committed
// DEPRECATED: listen to event "oo.dom.replacement.after"
function b_AddOnDomReplacementFinishedUniqueCallback(funct) {
if (funct.constructor == Array){
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug',"add: its an ARRAY! ", "functions.js ADD");
//check if it has been added before
if (b_onDomReplacementFinished_callbacks.search(funct[0])){
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug',"push to callback stack, already there!!: " + funct[0], "functions.js ADD");
return;
}
}
b_AddOnDomReplacementFinishedCallback(funct);
}
// main interpreter for ajax mode
var o_debug_trid = 0;
function o_ainvoke(r) {

Florian Gnaegi - frentix GmbH
committed
if(r == undefined) {
return;
}
o_info.inainvoke = true;
var cmdcnt = r["cmdcnt"];
if (cmdcnt > 0) {

Florian Gnaegi - frentix GmbH
committed
// let everybody know dom replacement has finished
jQuery(document).trigger("oo.dom.replacement.before");
//fxdiff FXOLAT-310
b_changedDomEl = new Array();
if (o_info.debug) { o_debug_trid++; }
var cs = r["cmds"];
for (var i=0; i<cmdcnt; i++) {
var acmd = cs[i];
var co = acmd["cmd"];
var cda = acmd["cda"];
var wid = acmd["w"];
var wi = this.window; // for cross browser window: o_info.wins[wid];
var out;
if (wi) {
switch (co) {
case 1: // Excecute JavaScript Code
var jsexec = cda["e"];
BLoader.executeGlobalJS(jsexec, 'o_ainvoker::jsexec');
if (o_info.debug) o_log("c1: execute jscode: "+jsexec);
case 2: // redraw components command
var cnt = cda["cc"];
var ca = cda["cps"];
for (var j=0; j<cnt; j++) {
var c1 = ca[j];
var ciid = c1["cid"]; // component id
var civis = c1["cidvis"];// component visibility
var withWrapper = c1["cw"]; // component has a wrapper element, replace only inner content
var hfrag = c1["hfrag"]; // html fragment of component
var jsol = c1["jsol"]; // javascript on load
var hdr = c1["hdr"]; // header
if (o_info.debug) o_log("c2: redraw: "+c1["cname"]+ " ("+ciid+") "+c1["hfragsize"]+" bytes, listener(s): "+c1["clisteners"]);
//var con = jQuery(hfrag).find('script').remove(); //Strip scripts
var hdrco = hdr+"\n\n"+hfrag;
var inscripts = '';//jQuery(hfrag).find('script');//hfrag.extractScripts();
var replaceElement = false;
var newcId = "o_c"+ciid;
var newc = jQuery('#' + newcId);
if (newc == null || (newc.length == 0)) {
//not a container, perhaps an element
newcId = "o_fi"+ciid;
newc = jQuery('#' + newcId);
replaceElement = true;
if (newc != null) {
if(civis) { // needed only for ie 6/7 bug where an empty div requires space on screen
newc.css('display','');//.style.display="";//reset?
newc.css('display','none'); //newc.style.display="none";
if(replaceElement || !withWrapper) {
// replace entire DOM element
newc.replaceWith(hdrco);
} else {
try{
newc.empty().html(hdrco);
//check if the operation is a success especially for IE8
if(hdrco.length > 0 && newc.get(0).innerHTML == "") {
newc.get(0).innerHTML = hdrco;
}
} catch(e) {

srosse
committed
if(console) console.log(e);
if(console) console.log('Fragment',hdrco);
}
b_changedDomEl.push(newcId);
// execute inline scripts
inscripts.each( function(val){
BLoader.executeGlobalJS(val, 'o_ainvoker::inscripts');}
);
}
if (jsol != "") {
BLoader.executeGlobalJS(jsol, 'o_ainvoker::jsol');
}
}
}
break;
case 3: // createParentRedirectTo leads to a full page reload
wi.o2c = 0;//??
var rurl = cda["rurl"];
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
wi.document.location.replace(rurl);
break;
case 5: // create redirect for external resource mapper
wi.o2c = 0;//??
var rurl = cda["rurl"];
//in case of a mapper served media resource (xls,pdf etc.)
wi.o_afterserver();
wi.document.location.replace(rurl);//opens non-inline media resource
break;
case 6: // createPrepareClientCommand
wi.o2c = 0;
wi.o_afterserver();
break;
case 7: // JSCSS: handle dynamic insertion of js libs and dynamic insertion/deletion of css stylesheets
// css remove, add, js add order should makes no big difference? except js calling/modifying css?
var loc = wi.document.location;
var furlp = loc.protocol+"//"+loc.hostname; // e.g. http://my.server.com:8000
if (loc.port != "" ) furlp += ":"+ loc.port;
// 1. unload css file
var cssrm = cda["cssrm"];
for (j = 0; j<cssrm.length; j++) {
var ce = cssrm[j];
var id = ce["id"];
var url = furlp + ce["url"];
BLoader.unLoadCSS(url, id);
if (o_info.debug) o_log("c7: rm css: id:"+id+" ,url:'"+url+"'");
}
// 2) load css file
var cssadd = cda["cssadd"];
for (k = 0; k<cssadd.length; k++) {
var ce = cssadd[k];
var id = ce["id"];
var url = furlp + ce["url"];
var pt = ce["pt"];
BLoader.loadCSS(url,id,pt);
if (o_info.debug) o_log("c7: add css: id:"+id+" ,url:'"+url+"'");
}
// 3) js lib adds
var jsadd = cda["jsadd"];
for (l=0; l<jsadd.length; l++) {
var ce = jsadd[l];
// 3.1) execute before AJAX-code
var preJsAdd = ce["before"];
if (jQuery.type(preJsAdd) === "string") {
BLoader.executeGlobalJS(preJsAdd, 'o_ainvoker::preJsAdd');
}
// 3.2) load js file
var url = ce["url"];
var enc = ce["enc"];
if (jQuery.type(url) === "string") BLoader.loadJS(url, enc, true);
if (o_info.debug) o_log("c7: add js: "+url);
}
break;
default:
if (o_info.debug) o_log("?: unknown command "+co);
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug',"Error in o_ainvoke(), ?: unknown command "+co, "functions.js");
break;
}
} else {
if (o_info.debug) o_log ("could not find window??");
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug',"Error in o_ainvoke(), could not find window??", "functions.js");

Florian Gnaegi - frentix GmbH
committed
// BEGIN DEPRECATED DOM REPLACEMENT CALLBACK: new style below
// execute onDomReplacementFinished callback functions
var stacklength = b_onDomReplacementFinished_callbacks.length;

srosse
committed
if (b_onDomReplacementFinished_callbacks.toSource && jQuery(document).ooLog().isDebugEnabled()) {
jQuery(document).ooLog('debug',"stack content"+b_onDomReplacementFinished_callbacks.toSource(), "functions.js");

srosse
committed
for (mycounter = 0; stacklength > mycounter; mycounter++) {
if(jQuery(document).ooLog().isDebugEnabled()) {
jQuery(document).ooLog('debug',"Stopped executing DOM replacement callback functions - to many functions::" + b_onDomReplacementFinished_callbacks.length, "functions.js");
}
if(jQuery(document).ooLog().isDebugEnabled()) {
jQuery(document).ooLog('debug',"Stacksize before shift: " + b_onDomReplacementFinished_callbacks.length, "functions.js");
}
var func = b_onDomReplacementFinished_callbacks.shift();
if (typeof func.length === 'number'){
if (func[0] == "glosshighlighter") {
var tmpArr = func[1];
if(jQuery(document).ooLog().isDebugEnabled())
jQuery(document).ooLog('debug',"arr fct: "+ tmpArr, "functions.js");
if(jQuery(document).ooLog().isDebugEnabled())
jQuery(document).ooLog('debug',"Executing DOM replacement callback function #" + mycounter + " with timeout funct::" + func, "functions.js");
// don't use execScript here - must be executed outside this function scope so that dom replacement elements are available

srosse
committed
//func.delay(0.01);
func();//TODO jquery
if(jQuery(document).ooLog().isDebugEnabled())
jQuery(document).ooLog('debug',"Stacksize after timeout: " + b_onDomReplacementFinished_callbacks.length, "functions.js");

Florian Gnaegi - frentix GmbH
committed
// END DEPRECATED DOM REPLACEMENT CALLBACK: new style on next line
// let everybody know dom replacement has finished
jQuery(document).trigger("oo.dom.replacement.after");
}
o_info.inainvoke = false;
/* minimalistic debugger / profiler
BDebugger.logDOMCount();
BDebugger.logGlobalObjCount();
BDebugger.logGlobalOLATObjects();
BDebugger.logManagedOLATObjects();
*/
}
/**
* Method to remove the ajax-busy stuff and let the user click links again. This
* should only be called from the ajax iframe onload method to make sure the UI
* does not freeze when the server for whatever reason does not respond as expected.
*/
function clearAfterAjaxIframeCall() {
if (o_info.linkbusy) {
// A normal ajax call will clear the linkbusy, so something went wrong in
// the ajax channel, e.g. error message from apache or no response from server
// Call afterserver to remove busy icon clear the linkbusy flag
o_afterserver();
showMessageBox('info', o_info.i18n_noresponse_title, o_info.i18n_noresponse, undefined);
}
}
function showAjaxBusy() {
// release o_info.linkbusy only after a successful server response
// - otherwhise the response gets overriden by next request
setTimeout(function(){
if (o_info.linkbusy) {
// try/catch because can fail in full page refresh situation when called before DOM is ready
try {
jQuery('#o_body').addClass('o_ajax_busy');
jQuery('#o_ajax_busy').modal({show: true, backdrop: 'static', keyboard: 'false'});
// fix modal conflic with modal dialogs, make ajax busy appear always above modal dialogs
jQuery('body > .modal-backdrop').css({'z-index' : 1200});
} catch (e) {
if(console) console.log(e);
}
}
}
function removeAjaxBusy() {
// try/catch because can fail in full page refresh situation when called before page DOM is ready
try {
jQuery('#o_body').removeClass('o_ajax_busy');
jQuery('#o_ajax_busy').modal('hide');
} catch (e) {
if(console) console.log(e);
}
}
function setFormDirty(formId) {
// sets dirty form content flag to true and renders the submit button
// of the form with given dom id as dirty.
// (fg)
o2c=1;
// fetch the form and the forms submit button is identified via the olat
// form submit name
var myForm = document.getElementById(formId);
//TODO:gs:a why not directly accessing the submit button by an id. name="olat_fosm" send additional parameter which is unused. OLAT-1363
if (myForm != null) {
var mySubmit = myForm.olat_fosm_0;
if(mySubmit == null){
mySubmit = myForm.olat_fosm;
}
// set dirty css class
if(mySubmit) mySubmit.className ="btn o_button_dirty";
} else if(jQuery(document).ooLog().isDebugEnabled()) {
jQuery(document).ooLog('debug',"Error in setFormDirty, myForm was null for formId=" + formId, "functions.js");
}
}
//Pop-up window for context-sensitive help
function contextHelpWindow(URI) {
helpWindow = window.open(URI, "HelpWindow", "height=760, width=940, left=0, top=0, location=no, menubar=no, resizable=yes, scrollbars=yes, toolbar=no");
helpWindow.focus();
}
function o_openPopUp(url, windowname, width, height, menubar) {
// generic window popup function
attributes = "height=" + height + ", width=" + width + ", resizable=yes, scrollbars=yes, left=100, top=100, ";
if (menubar) {
attributes += "location=yes, menubar=yes, status=yes, toolbar=yes";
} else {
attributes += "location=no, menubar=no, status=no, toolbar=no";
}
var win = window.open(url, windowname, attributes);
win.focus();
if (o_info.linkbusy) {
o_afterserver();
}
}
function b_handleFileUploadFormChange(fileInputElement, fakeInputElement, saveButton) {
// file upload forms are rendered transparent and have a fake input field that is rendered.
// on change events of the real input field this method is triggered to display the file
// path in the fake input field. See the code for more info on this
var fileName = fileInputElement.value;
// remove unix path
slashPos = fileName.lastIndexOf('/');
if (slashPos != -1) {
fileName=fileName.substring(slashPos + 1);
}
// remove windows path
slashPos = fileName.lastIndexOf('\\');
if (slashPos != -1) {
fileName=fileName.substring(slashPos + 1);
}
fakeInputElement.value=fileName;
// mark save button as dirty
if (saveButton) {

Florian Gnaegi - frentix GmbH
committed
saveButton.className='o_button_dirty'
}
// set focus to next element if available
var elements = fileInputElement.form.elements;
for (i=0; i < elements.length; i++) {
var elem = elements[i];
if (elem.name == fakeInputElement.name && i+1 < elements.length) {
elements[i+1].focus();
}
}
}
// goto node must be in global scope to support content that has been opened in a new window
// with the clone controller - real implementation is moved to course run scope o_activateCourseNode()
function gotonode(nodeid) {
try {
// check if o_activateCourseNode method is available in this window
if (typeof o_activateCourseNode != 'undefined') {
o_activateCourseNode(nodeid);
} else {
// must be content opened using the clone controller - search in opener window
if (opener && typeof opener.o_activateCourseNode != 'undefined') {
opener.o_activateCourseNode(nodeid);
} else if(jQuery(document).ooLog().isDebugEnabled()) {
jQuery(document).ooLog('debug',"Error in gotonode(), could not find main window", "functions.js");
alert('Goto node error:' + e);
if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug',"Error in gotonode()::" + e.message, "functions.js");
}
}
function o_openUriInMainWindow(uri) {
// get the "olatmain" window
try {

gnaegi
committed
var w = o_getMainWin();
w.focus();
w.location.replace(uri);
} catch (e) {
showMessageBox("error", "Error", "Can not find main OpenOLAT window to open URL.");
}
function o_viewportHeight() {
var prototypeViewPortHeight = jQuery(document).height()
if (prototypeViewPortHeight > 0) {
return prototypeViewPortHeight;
} else {
return 600; // fallback
}
}

strentini
committed
/**
* calculate the height of the inner content area that can be used for
* displaying content without using scrollbars. The height includes the
* margin, border and padding of the main columns
* @dependencies: prototype library, jQuery

strentini
committed
* @author: Florian Gnaegi
*/
OPOL.getMainColumnsMaxHeight = function(){
var col1Height = 0,
col2Height = 0,
col3Height = 0,
mainInnerHeight = 0,
mainHeight = 0,
mainDomElement,
col1DomElement = jQuery('#o_main_left_content'),
col2DomElement = jQuery('#o_main_right_content'),
col3DomElement = jQuery('#o_main_center_content');

strentini
committed
if (col1DomElement != 'undefined' && col1DomElement != null) {
col1Height = col1DomElement.outerHeight(true);

strentini
committed
}
if (col2DomElement != 'undefined' && col2DomElement != null){
col2Height = col2DomElement.outerHeight(true);

strentini
committed
}
if (col3DomElement != 'undefined' && col3DomElement != null){
col3Height = col3DomElement.outerHeight(true);

strentini
committed
}

strentini
committed
mainInnerHeight = (col1Height > col2Height ? col1Height : col2Height);
mainInnerHeight = (mainInnerHeight > col3Height ? mainInnerHeight : col3Height);
if (mainInnerHeight > 0) {
return mainInnerHeight;
}

strentini
committed
mainDomElement = jQuery('#o_main');

strentini
committed
if (mainDomElement != 'undefined' && mainDomElement != null) {
mainHeight = mainDomElement.height();

strentini
committed
}
if (mainDomElement > 0) {
return mainDomElement;
return o_viewportHeight();

strentini
committed
};
OPOL.adjustHeight = function() {
// Adjust the height of col1 2 and 3 based on the max column height.
// This is necessary to implement layouts where the three columns have different
// backgounds and to enlarge the menu and content area to always show the whole
// content. It is also required by the left menu offcanvas feature.
try {
var contentHeight = 0;
col1 = jQuery('#o_main_left_content').outerHeight(true);
col2 = jQuery('#o_main_right_content').outerHeight(true);
col3 = jQuery('#o_main_center_content').outerHeight(true);
contentHeight = Math.max(col1, col2, col3);
jQuery('#o_main_left').css({'min-height' : contentHeight + "px"});
jQuery('#o_main_right').css({'min-height' : contentHeight + "px"});
jQuery('#o_main_center').css({'min-height' : contentHeight + "px"});
} catch (e) {
if(console) console.log(e);
}
};
/* Register to resize event and fire an event when the resize is finished */
jQuery(window).resize(function() {
clearTimeout(o_info.resizeId);
o_info.resizeId = setTimeout(function() {
jQuery(document).trigger("oo.window.resize.after");
}, 500);
});

Florian Gnaegi - frentix GmbH
committed
// execute after each DOM replacement cycle and on initial document load
jQuery(document).on("oo.window.resize.after", OPOL.adjustHeight);

Florian Gnaegi - frentix GmbH
committed
jQuery(document).on("oo.dom.replacement.after", OPOL.adjustHeight);
jQuery().ready(OPOL.adjustHeight);

Florian Gnaegi - frentix GmbH
committed
function o_scrollToElement(elem) {
jQuery('html, body').animate({
scrollTop: jQuery(elem).offset().top

srosse
committed
}, 333);

Florian Gnaegi - frentix GmbH
committed
}
function o_popover(id, contentId, loc) {
if(typeof(loc)==='undefined') loc = 'bottom';
jQuery('#' + id).popover({
placement : loc,
html: true,
trigger: 'click',
container: 'body',
content: function() { return jQuery('#' + contentId).clone().html(); }
}).on('shown.bs.popover', function () {
var clickListener = function (e) {
jQuery('#' + id).popover('hide');
jQuery('body').unbind('click', clickListener);
};
setTimeout(function() {
jQuery('body').on('click', clickListener);
},5);
});
}
function o_shareLinkPopup(id, text, loc) {
if(typeof(loc)==='undefined') loc = 'top';
var elem = jQuery('#' + id);
elem.popover({
placement : loc,
html: true,
trigger: 'click',
container: 'body',
content: text,
}).on('shown.bs.popover', function () {
if (jQuery(e.target).data('toggle') !== 'popover' && jQuery(e.target).parents('.popover.in').length === 0) {
jQuery('#' + id).popover('hide');
jQuery('body').unbind('click', clickListener);
}
};
setTimeout(function() {
jQuery('body').on('click', clickListener);
}, 5);
// make mouse over link text work again
elem.attr('title',elem.attr('data-original-title'));
function o_QRCodePopup(id, text, loc) {
if(typeof(loc)==='undefined') loc = 'top';
var elem = jQuery('#' + id);
elem.popover({
placement : loc,
html: true,
trigger: 'click',
content: '<div id="' + id + '_pop" class="o_qrcode"></div>'
}).on('shown.bs.popover', function () {
o_info.qr = o_QRCode(id + '_pop', (jQuery.isFunction(text) ? text() : text));
var clickListener = function (e) {
if (jQuery(e.target).data('toggle') !== 'popover' && jQuery(e.target).parents('.popover.in').length === 0) {
jQuery("#" + id).popover('hide');
jQuery('body').unbind('click', clickListener);
}
};
setTimeout(function() {
jQuery('body').on('click', clickListener);
}, 5);
}).on('hidden.bs.popover', function () {
try {
o_info.qr.clear();
delete o_info.qr;
} catch(e) {}
// make mouse over link text work again
elem.attr('title',elem.attr('data-original-title'));
}
function o_QRCode(id, text) {
// dynamically load qr code library
try {
BLoader.loadJS(o_info.o_baseURI + "/js/jquery/qrcodejs/qrcode.min.js", 'utf8', true);
return new QRCode(document.getElementById(id), text);
} catch(e) {
return null;
}

Florian Gnaegi - frentix GmbH
committed
function b_resizeIframeToMainMaxHeight(iframeId) {