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;
o_info.scrolling = 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){
if(window.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);
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
114
// 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'));
if(window.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");
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
180
}
},
// 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(typeof MathJax === "undefined") {
o_mathjax();//will render the whole page
} else if (MathJax && MathJax.isReady) {
jQuery(function() {
MathJax.Hub.Queue(function() {
if(jQuery('#' + domId + ' .MathJax').length == 0) {
MathJax.Hub.Typeset(domId)
}
});
})
} else { // not yet loaded (autoload), load first
setTimeout(function() {
BFormatter.formatLatexFormulas(domId);
}, 100);
if (window.console) console.log("error in BFormatter.formatLatexFormulas: ", e);
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
},
// Align columns of different tables with the same column count
// Note: it is best to set the width of the fixed sized colums via css
// (e.g. to 1% to make them as small as possible). Table must set to max-size:100%
// to not overflow. New width of table can be larger than before because the largest
// width of each column is applied to all tables. With max-size the browsers magically
// fix this overflow problem.
alignTableColumns : function(tableArray) {
try {
var cellWidths = new Array();
// find all widest cells
jQuery(tableArray).each(function() {
for(j = 0; j < jQuery(this)[0].rows[0].cells.length; j++){
var cell = jQuery(this)[0].rows[0].cells[j];
if(!cellWidths[j] || cellWidths[j] < cell.clientWidth) {
cellWidths[j] = cell.clientWidth;
}
}
});
// set same width to columns of all tables
jQuery(tableArray).each(function() {
for(j = 0; j < jQuery(this)[0].rows[0].cells.length; j++){
jQuery(this)[0].rows[0].cells[j].style.width = cellWidths[j]+'px';
}
});
} catch(e) {
if (window.console) console.log("error in BFormatter.alignTableColumns: ", e);
}
}
};
function o_init() {
try {
// all init-on-new-page calls here
//return opener window

srosse
committed
o_getMainWin().o_afterserver();
// initialize the business path and social media
if(window.location.href && window.location.href != null && window.location.href.indexOf('%3A') < 0) {
var url = window.location.href;
if(url != null && !(url.lastIndexOf("http", 0) === 0) && !(url.lastIndexOf("https", 0) === 0)) {
url = o_info.serverUri + url;
}
o_info.businessPath = url;
if(!(typeof o_shareActiveSocialUrl === "undefined")) {
o_shareActiveSocialUrl();
}
}
} 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 (window.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() {
try {
if (o_info.linkbusy) {
return false;
} else {
var doreq = (o2c==0 || confirm(o_info.dirty_form));
if (doreq) o_beforeserver();
return doreq;
}
} catch(e) {
if(window.console) console.log(e);
// the method doesn't set the busy flag
function o2cl_dirtyCheckOnly() {
try {
if (o_info.linkbusy) {
return false;
} else {
return (o2c==0 || confirm(o_info.dirty_form));
}
} catch(e) {
if(window.console) console.log(e);
return false;
}
}
//for flexi tree
function o2cl_noDirtyCheck() {
if (o_info.linkbusy) {
return false;
} else {

srosse
committed
o_beforeserver();
return true;
}
}
368
369
370
371
372
373
374
375
376
377
378
379
380
381
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
416
417
418
419
420
421
422
423
424
425
426
427
428
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)));
}
}
}
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
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) {
var eds = jQuery('div.o_richtext_mce textarea', newc);
for(var t=0; t<eds.length; t++) {
try {
var edId = jQuery(eds.get(t)).attr('id');
if(typeof top.tinymce != undefined) {
top.tinymce.remove('#' + edId);
}
} catch(e) {
if(window.console) console.log(e);
}
}
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) {
if(window.console) console.log(e);
if(window.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"];
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
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();
*/
}
/**
* 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();
}
}
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 {
//don't set 2 layers
if(jQuery('#o_ajax_busy_backdrop').length == 0) {
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('#o_ajax_busy').after('<div id="o_ajax_busy_backdrop" class="modal-backdrop in"></div>');
jQuery('#o_ajax_busy>.modal-backdrop').remove();
jQuery('#o_ajax_busy_backdrop').css({'z-index' : 1200});
}
if(window.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_ajax_busy_backdrop').remove();
if(window.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;
try {
win = window.open(url, windowname, attributes);
} catch(e) {
win = window.open(url, 'OpenOLAT', attributes);
}
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_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(window.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) {
try {
o_info.scrolling = true;
jQuery('html, body').animate({
scrollTop : jQuery(elem).offset().top
}, 333, function(e, el) {
o_info.scrolling = false;
});
} catch (e) {
//console.log(e);
}

Florian Gnaegi - frentix GmbH
committed
}
function o_popover(id, contentId, loc) {
if(typeof(loc)==='undefined') loc = 'bottom';
jQuery('#' + id).popover({
placement : loc,
html: true,