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
114
115
116
117
118
119
120
121
122
123
124
// 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 == 'b_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('#b_fontSize_css'));
} else {
newSt.insertBefore(jQuery('#b_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));
}
}
function b_initEmPxFactor() {
// read px value for 1 em from hidden div
o_info.emPxFactor = jQuery('#b_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
if (window.opener && window.opener.OPOL) {
// use the opener when opener window is an OpenOLAT window
return window.opener;
} else if (window.OPOL) {
// other cases the current window is the main window
return window;

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

gnaegi
committed
//mal versuche mit jQuery().ready.. erst dann wieder clicks erlauben...
showAjaxBusy();
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
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
// 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;
}
}
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)));
}
}
}
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
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
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)
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) {
// commands
if(r == undefined) {
return;
}
o_info.inainvoke = true;
var cmdcnt = r["cmdcnt"];
if (cmdcnt > 0) {
//fxdiff FXOLAT-310
b_changedDomEl = new Array();
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
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 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 newc = jQuery("#o_c"+ciid);
if (newc == null || (newc.length == 0)) {
//not a container, perhaps an element
newc = jQuery("#o_fi"+ciid);
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";
}
// do dom replacement
// remove listeners !! ext overwrite or prototype replace does NOT remove listeners !!
// newc.descendants().each(function(el){if (el.stopObserving) el.stopObserving()});
if(replaceElement) {
newc.replaceWith(hdrco);
} else {
newc.empty();
try{
newc.html(hdrco);//Ext.DomHelper.overwrite(newc, hdrco, false);
} catch(e) {

srosse
committed
if(console) console.log(e);
if(console) console.log('Fragment',hdrco);
}
b_changedDomEl.push('o_c'+ciid);
newc = null;
// exeucte inline scripts
if (inscripts != "") {
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"];
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
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");
}
}
// 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");
// all rendering finished, adjust height on menu and content
OPOL.adjustHeight();
}
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('#b_ajax_busy').each(function(index, el) {
jQuery(el).addClass('b_ajax_busy');
jQuery('#b_body').addClass('b_ajax_busy');
});
} catch (e) {
if(console) console.log(e);
}
}
}, 500);
}
function removeAjaxBusy() {
// try/catch because can fail in full page refresh situation when called before page DOM is ready
try {
jQuery('#b_ajax_busy').each(function(index, el) {
jQuery(el).removeClass('b_ajax_busy');
jQuery('#b_body').removeClass('b_ajax_busy');
});
} 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 ="b_button b_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();
}
//TODO: for 5.3 add popup capability to link and table
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();
}
function b_togglebox(domid, toggler) {
// toggle the domid element and switch the toggler classes
jQuery('#'+domid).slideToggle(400, function() {
var togglerEl = jQuery(toggler);
togglerEl.toggleClass('b_togglebox_closed');
togglerEl.toggleClass('b_togglebox_opened');
});
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
}
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) {
saveButton.className='b_button b_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.");
}

strentini
committed
function b_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.
* @dependencies: prototype library, ExtJS
* @author: Florian Gnaegi
*/
OPOL.getMainColumnsMaxHeight = function(){
var col1Height = 0,
col2Height = 0,
col3Height = 0,
mainInnerHeight = 0,
mainHeight = 0,
mainDomElement,
col1DomElement = jQuery('#b_col1_content'),
col2DomElement = jQuery('#b_col2_content'),
col3DomElement = jQuery('#b_col3_content');

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

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

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

strentini
committed
}

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

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

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

strentini
committed
}
if (mainDomElement > 0) {
return mainDomElement;
}
// fallback to viewport height
return b_viewportHeight();

strentini
committed
};
OPOL.adjustHeight = function() {
try {
// Reset col height first
jQuery('#b_col1_content').height('auto');
jQuery('#b_col2_content').height('auto');
// Calculate new col height
var contentHeight = OPOL.getMainColumnsMaxHeight();
jQuery('#b_col1_content').height(contentHeight);
jQuery('#b_col2_content').height(contentHeight);
} catch (e) {
if(console) console.log(e);
}
};
function b_resizeIframeToMainMaxHeight(iframeId) {
// adjust the given iframe to use as much height as possible
// (fg)
var theIframe = jQuery('#' + iframeId);
if (theIframe != 'undefined' && theIframe != null) {

strentini
committed
var colsHeight = OPOL.getMainColumnsMaxHeight();
var potentialHeight = b_viewportHeight() - 100;// remove some padding etc.
var elem = jQuery('#b_header');
if (elem != 'undefined' && elem != null) potentialHeight = potentialHeight - elem.height();
elem = jQuery('#b_nav');
if (elem != 'undefined' && elem != null) potentialHeight = potentialHeight - elem.height();
elem = jQuery('#b_footer');
if (elem != 'undefined' && elem != null) potentialHeight = potentialHeight - elem.height();
var height = (potentialHeight > colsHeight ? potentialHeight : colsHeight);
theIframe.height(height);
}
}
// for gui debug mode
var o_debu_oldcn, o_debu_oldtt;
function o_debu_show(cn, tt) {

srosse
committed
if (o_debu_oldcn){
o_debu_hide(o_debu_oldcn, o_debu_oldtt);
}
jQuery(cn).css('border','3px solid #00F').css('margin','0px').css('background-color','#FCFCB8');
jQuery(tt).show();
o_debu_oldtt = tt;
o_debu_oldcn = cn;
}
function o_debu_hide(cn, tt) {

srosse
committed
jQuery(tt).hide();
jQuery(cn).css('border','1px dotted black').css('margin','2px').css('background-color','');

srosse
committed
var el = jQuery('#' + elid);
if (el) {
el.css('background-color','#FCFCB8');
el.css('border','3px solid #00F');

srosse
committed
var el = jQuery('#' + elid);

srosse
committed
el.css('border','');
el.css('background-color','');
}
}
function o_clearConsole() {
o_log_all="";
o_log(null);
}
var o_log_all = "";
function o_log(str) {
if (str) {
o_log_all = "\n"+o_debug_trid+"> "+str + o_log_all;
o_log_all = o_log_all.substr(0,4000);
}
var logc = jQuery("#o_debug_cons");
if (logc) {
if (o_log_all.length == 4000) o_log_all = o_log_all +"\n... (stripped: to long)... ";
logc.value = o_log_all;
}

srosse
committed
if(!jQuery.type(window.console) === "undefined"){
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
//firebug log window
window.console.log(str);
}
}
function o_logerr(str) {
o_log("ERROR:"+str);
}
function o_logwarn(str) {
o_log("WARN:"+str);
}
function showerror(e) {
var r = "";
for (var p in e) r += p + ": " + e[p] + "\n";
return "error detail:\n"+r;
}
// Each flexible.form item with an javascript 'on...' configured calls this fn.
// It is called at least if a flexible.form is submitted.
// It submits the component id as hidden parameters. This specifies which
// form item should be dispatched by the flexible.form container. A second
// parameter submitted is the action value triggering the submit.
// A 'submit' is not the same as 'submit and validate'. if the form should validate
// is defined by the triggered component.
function o_ffEvent (formNam, dispIdField, dispId, eventIdField, eventInt){
//set hidden fields and submit form
var dispIdEl, defDispId,eventIdEl,defEventId;
dispIdEl = document.getElementById(dispIdField);
defDispId = dispIdEl.value;
eventIdEl = document.getElementById(eventIdField);
defEventId = eventIdEl.value;
eventIdEl.value=eventInt;
// manually execute onsubmit method - calling submit itself does not trigger onsubmit event!
if (document.forms[formNam].onsubmit()) {
document.forms[formNam].submit();
}
dispIdEl.value = defDispId;
eventIdEl.value = defEventId;
}
function o_ffXHREvent(formNam, dispIdField, dispId, eventIdField, eventInt) {
var data = new Object();
data['dispatchuri'] = dispId;
data['dispatchevent'] = eventInt;
if(arguments.length > 5) {
var argLength = arguments.length;
for(var i=5; i<argLength; i=i+2) {
if(argLength > i+1) {
data[arguments[i]] = arguments[i+1];
}
}
}